Initial backport of NEWCARD from FreeBSD 5.
[dragonfly.git] / sys / dev / pccard / cardbus / cardbus.c
CommitLineData
666d2603
JS
1/*
2 * Copyright (c) 2000,2001 Jonathan Chen.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: src/sys/dev/cardbus/cardbus.c,v 1.28 2002/11/27 17:30:41 imp Exp $
29 * $DragonFly: src/sys/dev/pccard/cardbus/cardbus.c,v 1.1 2004/02/10 07:55:47 joerg Exp $
30 */
31
32/*
33 * Cardbus Bus Driver
34 *
35 * much of the bus code was stolen directly from sys/pci/pci.c
36 * (Copyright (c) 1997, Stefan Esser <se@freebsd.org>)
37 *
38 * Written by Jonathan Chen <jon@freebsd.org>
39 */
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/malloc.h>
44#include <sys/kernel.h>
45#include <sys/sysctl.h>
46
47#include <sys/bus.h>
48#include <machine/bus.h>
49#include <sys/rman.h>
50#include <machine/resource.h>
51
52#include <sys/pciio.h>
53#include <bus/pci/pcivar.h>
54#include <bus/pci/pcireg.h>
55
56#include <dev/pccard/cardbus/cardbusreg.h>
57#include <dev/pccard/cardbus/cardbusvar.h>
58#include <dev/pccard/cardbus/cardbus_cis.h>
59#include <bus/pccard/pccardvar.h>
60
61#include "power_if.h"
62#include "pcib_if.h"
63
64/* sysctl vars */
65SYSCTL_NODE(_hw, OID_AUTO, cardbus, CTLFLAG_RD, 0, "CardBus parameters");
66
67int cardbus_debug = 0;
68TUNABLE_INT("hw.cardbus.debug", &cardbus_debug);
69SYSCTL_INT(_hw_cardbus, OID_AUTO, debug, CTLFLAG_RW,
70 &cardbus_debug, 0,
71 "CardBus debug");
72
73int cardbus_cis_debug = 0;
74TUNABLE_INT("hw.cardbus.cis_debug", &cardbus_cis_debug);
75SYSCTL_INT(_hw_cardbus, OID_AUTO, cis_debug, CTLFLAG_RW,
76 &cardbus_cis_debug, 0,
77 "CardBus CIS debug");
78
79#define DPRINTF(a) if (cardbus_debug) printf a
80#define DEVPRINTF(x) if (cardbus_debug) device_printf x
81
82
83static struct resource *cardbus_alloc_resource(device_t cbdev, device_t child,
84 int type, int *rid, u_long start, u_long end, u_long count,
85 u_int flags);
86static int cardbus_attach(device_t cbdev);
87static int cardbus_attach_card(device_t cbdev);
88static int cardbus_child_location_str(device_t cbdev, device_t child,
89 char *, size_t len);
90static int cardbus_child_pnpinfo_str(device_t cbdev, device_t child,
91 char *, size_t len);
92static __inline void cardbus_clear_command_bit(device_t cbdev, device_t child,
93 u_int16_t bit);
94static void cardbus_delete_resource(device_t cbdev, device_t child,
95 int type, int rid);
96static void cardbus_delete_resource_method(device_t cbdev, device_t child,
97 int type, int rid);
98static int cardbus_detach(device_t cbdev);
99static int cardbus_detach_card(device_t cbdev);
100static void cardbus_device_setup_regs(device_t brdev, int b, int s, int f,
101 pcicfgregs *cfg);
102static void cardbus_disable_busmaster_method(device_t cbdev, device_t child);
103static void cardbus_disable_io_method(device_t cbdev, device_t child,
104 int space);
105static void cardbus_driver_added(device_t cbdev, driver_t *driver);
106static void cardbus_enable_busmaster_method(device_t cbdev, device_t child);
107static void cardbus_enable_io_method(device_t cbdev, device_t child,
108 int space);
109static int cardbus_freecfg(struct cardbus_devinfo *dinfo);
110static int cardbus_get_powerstate_method(device_t cbdev, device_t child);
111static int cardbus_get_resource(device_t cbdev, device_t child, int type,
112 int rid, u_long *startp, u_long *countp);
113static int cardbus_get_resource_method(device_t cbdev, device_t child,
114 int type, int rid, u_long *startp, u_long *countp);
115static void cardbus_hdrtypedata(device_t brdev, int b, int s, int f,
116 pcicfgregs *cfg);
117static int cardbus_print_child(device_t cbdev, device_t child);
118static int cardbus_print_resources(struct resource_list *rl,
119 const char *name, int type, const char *format);
120static void cardbus_print_verbose(struct cardbus_devinfo *dinfo);
121static int cardbus_probe(device_t cbdev);
122static void cardbus_probe_nomatch(device_t cbdev, device_t child);
123static struct cardbus_devinfo *cardbus_read_device(device_t brdev, int b,
124 int s, int f);
125static void cardbus_read_extcap(device_t cbdev, pcicfgregs *cfg);
126static u_int32_t cardbus_read_config_method(device_t cbdev,
127 device_t child, int reg, int width);
128static int cardbus_read_ivar(device_t cbdev, device_t child, int which,
129 u_long *result);
130static void cardbus_release_all_resources(device_t cbdev,
131 struct cardbus_devinfo *dinfo);
132static int cardbus_release_resource(device_t cbdev, device_t child,
133 int type, int rid, struct resource *r);
134static __inline void cardbus_set_command_bit(device_t cbdev, device_t child,
135 u_int16_t bit);
136static int cardbus_set_powerstate_method(device_t cbdev, device_t child,
137 int state);
138static int cardbus_set_resource(device_t cbdev, device_t child, int type,
139 int rid, u_long start, u_long count, struct resource *res);
140static int cardbus_set_resource_method(device_t cbdev, device_t child,
141 int type, int rid, u_long start, u_long count);
142static int cardbus_setup_intr(device_t cbdev, device_t child,
143 struct resource *irq, int flags, driver_intr_t *intr,
144 void *arg, void **cookiep);
145static int cardbus_teardown_intr(device_t cbdev, device_t child,
146 struct resource *irq, void *cookie);
147static void cardbus_write_config_method(device_t cbdev, device_t child,
148 int reg, u_int32_t val, int width);
149static int cardbus_write_ivar(device_t cbdev, device_t child, int which,
150 uintptr_t value);
151
152/************************************************************************/
153/* Probe/Attach */
154/************************************************************************/
155
156static int
157cardbus_probe(device_t cbdev)
158{
159 device_set_desc(cbdev, "CardBus bus");
160 return 0;
161}
162
163static int
164cardbus_attach(device_t cbdev)
165{
166 return 0;
167}
168
169static int
170cardbus_detach(device_t cbdev)
171{
172 cardbus_detach_card(cbdev);
173 return 0;
174}
175
176static int
177cardbus_suspend(device_t self)
178{
179 cardbus_detach_card(self);
180 return (0);
181}
182
183static int
184cardbus_resume(device_t self)
185{
186 return (0);
187}
188
189/************************************************************************/
190/* Attach/Detach card */
191/************************************************************************/
192
193static void
194cardbus_device_setup_regs(device_t brdev, int b, int s, int f, pcicfgregs *cfg)
195{
196 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_INTLINE,
197 pci_get_irq(device_get_parent(brdev)), 1);
198 cfg->intline = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_INTLINE, 1);
199
200 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_CACHELNSZ, 0x08, 1);
201 cfg->cachelnsz = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_CACHELNSZ, 1);
202
203 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_LATTIMER, 0xa8, 1);
204 cfg->lattimer = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_LATTIMER, 1);
205
206 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_MINGNT, 0x14, 1);
207 cfg->mingnt = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_MINGNT, 1);
208
209 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_MAXLAT, 0x14, 1);
210 cfg->maxlat = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_MAXLAT, 1);
211}
212
213static int
214cardbus_attach_card(device_t cbdev)
215{
216 device_t brdev = device_get_parent(cbdev);
217 int cardattached = 0;
218 static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */
219 int bus, slot, func;
220
221 cardbus_detach_card(cbdev); /* detach existing cards */
222
223 POWER_ENABLE_SOCKET(brdev, cbdev);
224 bus = pcib_get_bus(cbdev);
225 if (bus == 0) {
226 /*
227 * XXX EVILE BAD XXX
228 * Not all BIOSes initialize the secondary bus number properly,
229 * so if the default is bad, we just put one in and hope it
230 * works.
231 */
232 bus = curr_bus_number;
233 pci_write_config(brdev, PCIR_SECBUS_2, curr_bus_number, 1);
234 pci_write_config(brdev, PCIR_SUBBUS_2, curr_bus_number + 2, 1);
235 curr_bus_number += 3;
236 }
237 /* For each function, set it up and try to attach a driver to it */
238 for (slot = 0; slot <= CARDBUS_SLOTMAX; slot++) {
239 int cardbusfunchigh = 0;
240 for (func = 0; func <= cardbusfunchigh; func++) {
241 struct cardbus_devinfo *dinfo =
242 cardbus_read_device(brdev, bus, slot, func);
243
244 if (dinfo == NULL)
245 continue;
246 if (dinfo->pci.cfg.mfdev)
247 cardbusfunchigh = CARDBUS_FUNCMAX;
248
249 cardbus_device_setup_regs(brdev, bus, slot, func,
250 &dinfo->pci.cfg);
251 cardbus_print_verbose(dinfo);
252 dinfo->pci.cfg.dev = device_add_child(cbdev, NULL, -1);
253 if (!dinfo->pci.cfg.dev) {
254 DEVPRINTF((cbdev, "Cannot add child!\n"));
255 cardbus_freecfg(dinfo);
256 continue;
257 }
258 resource_list_init(&dinfo->pci.resources);
259 device_set_ivars(dinfo->pci.cfg.dev, dinfo);
260 cardbus_do_cis(cbdev, dinfo->pci.cfg.dev);
261 if (device_probe_and_attach(dinfo->pci.cfg.dev) != 0)
262 cardbus_release_all_resources(cbdev, dinfo);
263 else
264 cardattached++;
265 }
266 }
267
268 if (cardattached > 0)
269 return (0);
270 POWER_DISABLE_SOCKET(brdev, cbdev);
271 return (ENOENT);
272}
273
274static int
275cardbus_detach_card(device_t cbdev)
276{
277 int numdevs;
278 device_t *devlist;
279 int tmp;
280 int err = 0;
281
282 device_get_children(cbdev, &devlist, &numdevs);
283
284 if (numdevs == 0) {
285 free(devlist, M_TEMP);
286 return (ENOENT);
287 }
288
289 for (tmp = 0; tmp < numdevs; tmp++) {
290 struct cardbus_devinfo *dinfo = device_get_ivars(devlist[tmp]);
291 int status = device_get_state(devlist[tmp]);
292
293 if (dinfo->pci.cfg.dev != devlist[tmp])
294 device_printf(cbdev, "devinfo dev mismatch\n");
295 if (status == DS_ATTACHED || status == DS_BUSY)
296 device_detach(devlist[tmp]);
297 cardbus_release_all_resources(cbdev, dinfo);
298 device_delete_child(cbdev, devlist[tmp]);
299 cardbus_freecfg(dinfo);
300 }
301 POWER_DISABLE_SOCKET(device_get_parent(cbdev), cbdev);
302 free(devlist, M_TEMP);
303 return (err);
304}
305
306static void
307cardbus_driver_added(device_t cbdev, driver_t *driver)
308{
309 int numdevs;
310 device_t *devlist;
311 int tmp;
312 struct cardbus_devinfo *dinfo;
313
314 device_get_children(cbdev, &devlist, &numdevs);
315
316 DEVICE_IDENTIFY(driver, cbdev);
317 POWER_ENABLE_SOCKET(device_get_parent(cbdev), cbdev);
318 for (tmp = 0; tmp < numdevs; tmp++) {
319 if (device_get_state(devlist[tmp]) == DS_NOTPRESENT) {
320 dinfo = device_get_ivars(devlist[tmp]);
321#ifdef notyet
322 cardbus_device_setup_regs(brdev, bus, slot, func,
323 &dinfo->pci.cfg);
324#endif
325 cardbus_print_verbose(dinfo);
326 resource_list_init(&dinfo->pci.resources);
327 cardbus_do_cis(cbdev, dinfo->pci.cfg.dev);
328 if (device_probe_and_attach(dinfo->pci.cfg.dev) != 0) {
329 cardbus_release_all_resources(cbdev, dinfo);
330 }
331 }
332 }
333
334 free(devlist, M_TEMP);
335}
336
337/************************************************************************/
338/* PCI-Like config reading (copied from pci.c */
339/************************************************************************/
340
341/* read configuration header into pcicfgrect structure */
342
343static void
344cardbus_read_extcap(device_t cbdev, pcicfgregs *cfg)
345{
346#define REG(n, w) PCIB_READ_CONFIG(cbdev, cfg->bus, cfg->slot, cfg->func, n, w)
347 int ptr, nextptr, ptrptr;
348
349 switch (cfg->hdrtype) {
350 case 0:
351 ptrptr = 0x34;
352 break;
353 case 2:
354 ptrptr = 0x14;
355 break;
356 default:
357 return; /* no extended capabilities support */
358 }
359 nextptr = REG(ptrptr, 1); /* sanity check? */
360
361 /*
362 * Read capability entries.
363 */
364 while (nextptr != 0) {
365 /* Sanity check */
366 if (nextptr > 255) {
367 printf("illegal PCI extended capability offset %d\n",
368 nextptr);
369 return;
370 }
371 /* Find the next entry */
372 ptr = nextptr;
373 nextptr = REG(ptr + 1, 1);
374
375 /* Process this entry */
376 switch (REG(ptr, 1)) {
377 case 0x01: /* PCI power management */
378 if (cfg->pp_cap == 0) {
379 cfg->pp_cap = REG(ptr + PCIR_POWER_CAP, 2);
380 cfg->pp_status = ptr + PCIR_POWER_STATUS;
381 cfg->pp_pmcsr = ptr + PCIR_POWER_PMCSR;
382 if ((nextptr - ptr) > PCIR_POWER_DATA)
383 cfg->pp_data = ptr + PCIR_POWER_DATA;
384 }
385 break;
386 default:
387 break;
388 }
389 }
390#undef REG
391}
392
393/* extract header type specific config data */
394
395static void
396cardbus_hdrtypedata(device_t brdev, int b, int s, int f, pcicfgregs *cfg)
397{
398#define REG(n, w) PCIB_READ_CONFIG(brdev, b, s, f, n, w)
399 switch (cfg->hdrtype) {
400 case 0:
401 cfg->subvendor = REG(PCIR_SUBVEND_0, 2);
402 cfg->subdevice = REG(PCIR_SUBDEV_0, 2);
403 cfg->nummaps = PCI_MAXMAPS_0;
404 break;
405 case 1:
406 cfg->subvendor = REG(PCIR_SUBVEND_1, 2);
407 cfg->subdevice = REG(PCIR_SUBDEV_1, 2);
408 cfg->nummaps = PCI_MAXMAPS_1;
409 break;
410 case 2:
411 cfg->subvendor = REG(PCIR_SUBVEND_2, 2);
412 cfg->subdevice = REG(PCIR_SUBDEV_2, 2);
413 cfg->nummaps = PCI_MAXMAPS_2;
414 break;
415 }
416#undef REG
417}
418
419static struct cardbus_devinfo *
420cardbus_read_device(device_t brdev, int b, int s, int f)
421{
422#define REG(n, w) PCIB_READ_CONFIG(brdev, b, s, f, n, w)
423 pcicfgregs *cfg = NULL;
424 struct cardbus_devinfo *devlist_entry = NULL;
425
426 if (REG(PCIR_DEVVENDOR, 4) != 0xffffffff) {
427 devlist_entry = malloc(sizeof(struct cardbus_devinfo),
428 M_DEVBUF, M_WAITOK | M_ZERO);
429 if (devlist_entry == NULL)
430 return (NULL);
431
432 cfg = &devlist_entry->pci.cfg;
433
434 cfg->bus = b;
435 cfg->slot = s;
436 cfg->func = f;
437 cfg->vendor = REG(PCIR_VENDOR, 2);
438 cfg->device = REG(PCIR_DEVICE, 2);
439 cfg->cmdreg = REG(PCIR_COMMAND, 2);
440 cfg->statreg = REG(PCIR_STATUS, 2);
441 cfg->baseclass = REG(PCIR_CLASS, 1);
442 cfg->subclass = REG(PCIR_SUBCLASS, 1);
443 cfg->progif = REG(PCIR_PROGIF, 1);
444 cfg->revid = REG(PCIR_REVID, 1);
445 cfg->hdrtype = REG(PCIR_HEADERTYPE, 1);
446 cfg->cachelnsz = REG(PCIR_CACHELNSZ, 1);
447 cfg->lattimer = REG(PCIR_LATTIMER, 1);
448 cfg->intpin = REG(PCIR_INTPIN, 1);
449 cfg->intline = REG(PCIR_INTLINE, 1);
450
451 cfg->mingnt = REG(PCIR_MINGNT, 1);
452 cfg->maxlat = REG(PCIR_MAXLAT, 1);
453
454 cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0;
455 cfg->hdrtype &= ~PCIM_MFDEV;
456
457 cardbus_hdrtypedata(brdev, b, s, f, cfg);
458
459 if (REG(PCIR_STATUS, 2) & PCIM_STATUS_CAPPRESENT)
460 cardbus_read_extcap(brdev, cfg);
461
462 devlist_entry->pci.conf.pc_sel.pc_bus = cfg->bus;
463 devlist_entry->pci.conf.pc_sel.pc_dev = cfg->slot;
464 devlist_entry->pci.conf.pc_sel.pc_func = cfg->func;
465 devlist_entry->pci.conf.pc_hdr = cfg->hdrtype;
466
467 devlist_entry->pci.conf.pc_subvendor = cfg->subvendor;
468 devlist_entry->pci.conf.pc_subdevice = cfg->subdevice;
469 devlist_entry->pci.conf.pc_vendor = cfg->vendor;
470 devlist_entry->pci.conf.pc_device = cfg->device;
471
472 devlist_entry->pci.conf.pc_class = cfg->baseclass;
473 devlist_entry->pci.conf.pc_subclass = cfg->subclass;
474 devlist_entry->pci.conf.pc_progif = cfg->progif;
475 devlist_entry->pci.conf.pc_revid = cfg->revid;
476 }
477 return (devlist_entry);
478#undef REG
479}
480
481/* free pcicfgregs structure and all depending data structures */
482
483static int
484cardbus_freecfg(struct cardbus_devinfo *dinfo)
485{
486 free(dinfo, M_DEVBUF);
487
488 return (0);
489}
490
491static void
492cardbus_print_verbose(struct cardbus_devinfo *dinfo)
493{
494 if (bootverbose || cardbus_debug > 0)
495 {
496 pcicfgregs *cfg = &dinfo->pci.cfg;
497
498 printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n",
499 cfg->vendor, cfg->device, cfg->revid);
500 printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n",
501 cfg->baseclass, cfg->subclass, cfg->progif,
502 cfg->hdrtype, cfg->mfdev);
503 printf("\tcmdreg=0x%04x, statreg=0x%04x, "
504 "cachelnsz=%d (dwords)\n",
505 cfg->cmdreg, cfg->statreg, cfg->cachelnsz);
506 printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), "
507 "maxlat=0x%02x (%d ns)\n",
508 cfg->lattimer, cfg->lattimer * 30,
509 cfg->mingnt, cfg->mingnt * 250, cfg->maxlat,
510 cfg->maxlat * 250);
511 if (cfg->intpin > 0)
512 printf("\tintpin=%c, irq=%d\n",
513 cfg->intpin + 'a' - 1, cfg->intline);
514 }
515}
516
517/************************************************************************/
518/* Resources */
519/************************************************************************/
520
521static int
522cardbus_set_resource(device_t cbdev, device_t child, int type, int rid,
523 u_long start, u_long count, struct resource *res)
524{
525 struct cardbus_devinfo *dinfo;
526 struct resource_list *rl;
527 struct resource_list_entry *rle;
528
529 if (device_get_parent(child) != cbdev)
530 return ENOENT;
531
532 dinfo = device_get_ivars(child);
533 rl = &dinfo->pci.resources;
534 rle = resource_list_find(rl, type, rid);
535 if (rle == NULL) {
536 resource_list_add(rl, type, rid, start, start + count - 1,
537 count);
538 if (res != NULL) {
539 rle = resource_list_find(rl, type, rid);
540 rle->res = res;
541 }
542 } else {
543 if (rle->res == NULL) {
544 } else if (rle->res->r_dev == cbdev &&
545 (!(rman_get_flags(rle->res) & RF_ACTIVE))) {
546 int f;
547 f = rman_get_flags(rle->res);
548 bus_release_resource(cbdev, type, rid, res);
549 rle->res = bus_alloc_resource(cbdev, type, &rid,
550 start, start + count - 1,
551 count, f);
552 } else {
553 device_printf(cbdev, "set_resource: resource busy\n");
554 return EBUSY;
555 }
556 rle->start = start;
557 rle->end = start + count - 1;
558 rle->count = count;
559 if (res != NULL)
560 rle->res = res;
561 }
562 if (device_get_parent(child) == cbdev)
563 pci_write_config(child, rid, start, 4);
564 return 0;
565}
566
567static int
568cardbus_get_resource(device_t cbdev, device_t child, int type, int rid,
569 u_long *startp, u_long *countp)
570{
571 struct cardbus_devinfo *dinfo;
572 struct resource_list *rl;
573 struct resource_list_entry *rle;
574
575 if (device_get_parent(child) != cbdev)
576 return ENOENT;
577
578 dinfo = device_get_ivars(child);
579 rl = &dinfo->pci.resources;
580 rle = resource_list_find(rl, type, rid);
581 if (!rle)
582 return ENOENT;
583 if (startp)
584 *startp = rle->start;
585 if (countp)
586 *countp = rle->count;
587 return 0;
588}
589
590static void
591cardbus_delete_resource(device_t cbdev, device_t child, int type, int rid)
592{
593 struct cardbus_devinfo *dinfo;
594 struct resource_list *rl;
595 struct resource_list_entry *rle;
596
597 if (device_get_parent(child) != cbdev)
598 return;
599
600 dinfo = device_get_ivars(child);
601 rl = &dinfo->pci.resources;
602 rle = resource_list_find(rl, type, rid);
603 if (rle) {
604 if (rle->res) {
605 if (rle->res->r_dev != cbdev ||
606 rman_get_flags(rle->res) & RF_ACTIVE) {
607 device_printf(cbdev, "delete_resource: "
608 "Resource still owned by child, oops. "
609 "(type=%d, rid=%d, addr=%lx)\n",
610 rle->type, rle->rid,
611 rman_get_start(rle->res));
612 return;
613 }
614 bus_release_resource(cbdev, type, rid, rle->res);
615 }
616 resource_list_delete(rl, type, rid);
617 }
618 if (device_get_parent(child) == cbdev)
619 pci_write_config(child, rid, 0, 4);
620}
621
622static int
623cardbus_set_resource_method(device_t cbdev, device_t child, int type, int rid,
624 u_long start, u_long count)
625{
626 int ret;
627 ret = cardbus_set_resource(cbdev, child, type, rid, start, count, NULL);
628 if (ret != 0)
629 return ret;
630 return BUS_SET_RESOURCE(device_get_parent(cbdev), child, type, rid,
631 start, count);
632}
633
634static int
635cardbus_get_resource_method(device_t cbdev, device_t child, int type, int rid,
636 u_long *startp, u_long *countp)
637{
638 int ret;
639 ret = cardbus_get_resource(cbdev, child, type, rid, startp, countp);
640 if (ret != 0)
641 return ret;
642 return BUS_GET_RESOURCE(device_get_parent(cbdev), child, type, rid,
643 startp, countp);
644}
645
646static void
647cardbus_delete_resource_method(device_t cbdev, device_t child,
648 int type, int rid)
649{
650 cardbus_delete_resource(cbdev, child, type, rid);
651 BUS_DELETE_RESOURCE(device_get_parent(cbdev), child, type, rid);
652}
653
654static void
655cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo)
656{
657 struct resource_list_entry *rle;
658
659 /* Free all allocated resources */
660 SLIST_FOREACH(rle, &dinfo->pci.resources, link) {
661 if (rle->res) {
662 if (rle->res->r_dev != cbdev)
663 device_printf(cbdev, "release_all_resource: "
664 "Resource still owned by child, oops. "
665 "(type=%d, rid=%d, addr=%lx)\n",
666 rle->type, rle->rid,
667 rman_get_start(rle->res));
668 BUS_RELEASE_RESOURCE(device_get_parent(cbdev),
669 rle->res->r_dev,
670 rle->type, rle->rid,
671 rle->res);
672 rle->res = NULL;
673 /*
674 * zero out config so the card won't acknowledge
675 * access to the space anymore
676 */
677 pci_write_config(dinfo->pci.cfg.dev, rle->rid, 0, 4);
678 }
679 }
680 resource_list_free(&dinfo->pci.resources);
681}
682
683static struct resource *
684cardbus_alloc_resource(device_t cbdev, device_t child, int type,
685 int *rid, u_long start, u_long end, u_long count, u_int flags)
686{
687 struct cardbus_devinfo *dinfo;
688 struct resource_list_entry *rle = 0;
689 int passthrough = (device_get_parent(child) != cbdev);
690
691 if (passthrough) {
692 return (BUS_ALLOC_RESOURCE(device_get_parent(cbdev), child,
693 type, rid, start, end, count, flags));
694 }
695
696 dinfo = device_get_ivars(child);
697 rle = resource_list_find(&dinfo->pci.resources, type, *rid);
698
699 if (!rle)
700 return NULL; /* no resource of that type/rid */
701
702 if (!rle->res) {
703 device_printf(cbdev, "WARNING: Resource not reserved by bus\n");
704 return NULL;
705 } else {
706 /* Release the cardbus hold on the resource */
707 if (rle->res->r_dev != cbdev)
708 return NULL;
709 bus_release_resource(cbdev, type, *rid, rle->res);
710 rle->res = NULL;
711 switch (type) {
712 case SYS_RES_IOPORT:
713 case SYS_RES_MEMORY:
714 if (!(flags & RF_ALIGNMENT_MASK))
715 flags |= rman_make_alignment_flags(rle->count);
716 break;
717 case SYS_RES_IRQ:
718 flags |= RF_SHAREABLE;
719 break;
720 }
721 /* Allocate the resource to the child */
722 return resource_list_alloc(&dinfo->pci.resources, cbdev, child,
723 type, rid, rle->start, rle->end, rle->count, flags);
724 }
725}
726
727static int
728cardbus_release_resource(device_t cbdev, device_t child, int type, int rid,
729 struct resource *r)
730{
731 struct cardbus_devinfo *dinfo;
732 int passthrough = (device_get_parent(child) != cbdev);
733 struct resource_list_entry *rle = 0;
734 int flags;
735 int ret;
736
737 if (passthrough) {
738 return BUS_RELEASE_RESOURCE(device_get_parent(cbdev), child,
739 type, rid, r);
740 }
741
742 dinfo = device_get_ivars(child);
743 /*
744 * According to the PCI 2.2 spec, devices may share an address
745 * decoder between memory mapped ROM access and memory
746 * mapped register access. To be safe, disable ROM access
747 * whenever it is released.
748 */
749 if (rid == CARDBUS_ROM_REG) {
750 uint32_t rom_reg;
751
752 rom_reg = pci_read_config(child, rid, 4);
753 rom_reg &= ~CARDBUS_ROM_ENABLE;
754 pci_write_config(child, rid, rom_reg, 4);
755 }
756
757 rle = resource_list_find(&dinfo->pci.resources, type, rid);
758
759 if (!rle) {
760 device_printf(cbdev, "Allocated resource not found\n");
761 return ENOENT;
762 }
763 if (!rle->res) {
764 device_printf(cbdev, "Allocated resource not recorded\n");
765 return ENOENT;
766 }
767
768 ret = BUS_RELEASE_RESOURCE(device_get_parent(cbdev), child,
769 type, rid, r);
770 switch (type) {
771 case SYS_RES_IOPORT:
772 case SYS_RES_MEMORY:
773 flags = rman_make_alignment_flags(rle->count);
774 break;
775 case SYS_RES_IRQ:
776 flags = RF_SHAREABLE;
777 break;
778 default:
779 flags = 0;
780 }
781 /* Restore cardbus hold on the resource */
782 rle->res = bus_alloc_resource(cbdev, type, &rid,
783 rle->start, rle->end, rle->count, flags);
784 if (rle->res == NULL)
785 device_printf(cbdev, "release_resource: "
786 "unable to reacquire resource\n");
787 return ret;
788}
789
790static int
791cardbus_setup_intr(device_t cbdev, device_t child, struct resource *irq,
792 int flags, driver_intr_t *intr, void *arg, void **cookiep)
793{
794 int ret;
795 device_t cdev;
796 struct cardbus_devinfo *dinfo;
797
798 ret = bus_generic_setup_intr(cbdev, child, irq, flags, intr, arg,
799 cookiep);
800 if (ret != 0)
801 return ret;
802
803 for (cdev = child; cbdev != device_get_parent(cdev);
804 cdev = device_get_parent(cdev))
805 /* NOTHING */;
806 dinfo = device_get_ivars(cdev);
807
808 return 0;
809}
810
811static int
812cardbus_teardown_intr(device_t cbdev, device_t child, struct resource *irq,
813 void *cookie)
814{
815 int ret;
816 device_t cdev;
817 struct cardbus_devinfo *dinfo;
818
819 ret = bus_generic_teardown_intr(cbdev, child, irq, cookie);
820 if (ret != 0)
821 return ret;
822
823 for (cdev = child; cbdev != device_get_parent(cdev);
824 cdev = device_get_parent(cdev))
825 /* NOTHING */;
826 dinfo = device_get_ivars(cdev);
827
828 return (0);
829}
830
831
832/************************************************************************/
833/* Other Bus Methods */
834/************************************************************************/
835
836static int
837cardbus_print_resources(struct resource_list *rl, const char *name,
838 int type, const char *format)
839{
840 struct resource_list_entry *rle;
841 int printed, retval;
842
843 printed = 0;
844 retval = 0;
845 /* Yes, this is kinda cheating */
846 SLIST_FOREACH(rle, rl, link) {
847 if (rle->type == type) {
848 if (printed == 0)
849 retval += printf(" %s ", name);
850 else if (printed > 0)
851 retval += printf(",");
852 printed++;
853 retval += printf(format, rle->start);
854 if (rle->count > 1) {
855 retval += printf("-");
856 retval += printf(format, rle->start +
857 rle->count - 1);
858 }
859 }
860 }
861 return retval;
862}
863
864static int
865cardbus_print_child(device_t cbdev, device_t child)
866{
867 struct cardbus_devinfo *dinfo;
868 struct resource_list *rl;
869 pcicfgregs *cfg;
870 int retval = 0;
871
872 dinfo = device_get_ivars(child);
873 cfg = &dinfo->pci.cfg;
874 rl = &dinfo->pci.resources;
875
876 retval += bus_print_child_header(cbdev, child);
877
878 retval += cardbus_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx");
879 retval += cardbus_print_resources(rl, "mem", SYS_RES_MEMORY, "%#lx");
880 retval += cardbus_print_resources(rl, "irq", SYS_RES_IRQ, "%ld");
881 if (device_get_flags(cbdev))
882 retval += printf(" flags %#x", device_get_flags(cbdev));
883
884 retval += printf(" at device %d.%d", pci_get_slot(child),
885 pci_get_function(child));
886
887 retval += bus_print_child_footer(cbdev, child);
888
889 return (retval);
890}
891
892static void
893cardbus_probe_nomatch(device_t cbdev, device_t child)
894{
895 struct cardbus_devinfo *dinfo;
896 pcicfgregs *cfg;
897
898 dinfo = device_get_ivars(child);
899 cfg = &dinfo->pci.cfg;
900 device_printf(cbdev, "<unknown card>");
901 printf(" (vendor=0x%04x, dev=0x%04x)", cfg->vendor, cfg->device);
902 printf(" at %d.%d", pci_get_slot(child), pci_get_function(child));
903 if (cfg->intpin > 0 && cfg->intline != 255) {
904 printf(" irq %d", cfg->intline);
905 }
906 printf("\n");
907
908 return;
909}
910
911static int
912cardbus_child_location_str(device_t cbdev, device_t child, char *buf,
913 size_t buflen)
914{
915 struct cardbus_devinfo *dinfo;
916 pcicfgregs *cfg;
917
918 dinfo = device_get_ivars(child);
919 cfg = &dinfo->pci.cfg;
920 snprintf(buf, buflen, "slot=%d function=%d", pci_get_slot(child),
921 pci_get_function(child));
922 return (0);
923}
924
925static int
926cardbus_child_pnpinfo_str(device_t cbdev, device_t child, char *buf,
927 size_t buflen)
928{
929 struct cardbus_devinfo *dinfo;
930 pcicfgregs *cfg;
931
932 dinfo = device_get_ivars(child);
933 cfg = &dinfo->pci.cfg;
934 snprintf(buf, buflen, "vendor=0x%04x device=0x%04x subvendor=0x%04x "
935 "subdevice=0x%04x", cfg->vendor, cfg->device, cfg->subvendor,
936 cfg->subdevice);
937 return (0);
938}
939
940static int
941cardbus_read_ivar(device_t cbdev, device_t child, int which, u_long *result)
942{
943 struct cardbus_devinfo *dinfo;
944 pcicfgregs *cfg;
945
946 dinfo = device_get_ivars(child);
947 cfg = &dinfo->pci.cfg;
948
949 switch (which) {
950 case PCI_IVAR_ETHADDR:
951 /*
952 * The generic accessor doesn't deal with failure, so
953 * we set the return value, then return an error.
954 */
955 if ((dinfo->fepresent & (1 << TPL_FUNCE_LAN_NID)) == 0) {
956 *((u_int8_t **) result) = NULL;
957 return (EINVAL);
958 }
959 *((u_int8_t **) result) = dinfo->funce.lan.nid;
960 break;
961 case PCI_IVAR_SUBVENDOR:
962 *result = cfg->subvendor;
963 break;
964 case PCI_IVAR_SUBDEVICE:
965 *result = cfg->subdevice;
966 break;
967 case PCI_IVAR_VENDOR:
968 *result = cfg->vendor;
969 break;
970 case PCI_IVAR_DEVICE:
971 *result = cfg->device;
972 break;
973 case PCI_IVAR_DEVID:
974 *result = (cfg->device << 16) | cfg->vendor;
975 break;
976 case PCI_IVAR_CLASS:
977 *result = cfg->baseclass;
978 break;
979 case PCI_IVAR_SUBCLASS:
980 *result = cfg->subclass;
981 break;
982 case PCI_IVAR_PROGIF:
983 *result = cfg->progif;
984 break;
985 case PCI_IVAR_REVID:
986 *result = cfg->revid;
987 break;
988 case PCI_IVAR_INTPIN:
989 *result = cfg->intpin;
990 break;
991 case PCI_IVAR_IRQ:
992 *result = cfg->intline;
993 break;
994 case PCI_IVAR_BUS:
995 *result = cfg->bus;
996 break;
997 case PCI_IVAR_SLOT:
998 *result = cfg->slot;
999 break;
1000 case PCI_IVAR_FUNCTION:
1001 *result = cfg->func;
1002 break;
1003 default:
1004 return ENOENT;
1005 }
1006 return 0;
1007}
1008
1009static int
1010cardbus_write_ivar(device_t cbdev, device_t child, int which, uintptr_t value)
1011{
1012 struct cardbus_devinfo *dinfo;
1013 pcicfgregs *cfg;
1014
1015 dinfo = device_get_ivars(child);
1016 cfg = &dinfo->pci.cfg;
1017
1018 switch (which) {
1019 case PCI_IVAR_ETHADDR:
1020 case PCI_IVAR_SUBVENDOR:
1021 case PCI_IVAR_SUBDEVICE:
1022 case PCI_IVAR_VENDOR:
1023 case PCI_IVAR_DEVICE:
1024 case PCI_IVAR_DEVID:
1025 case PCI_IVAR_CLASS:
1026 case PCI_IVAR_SUBCLASS:
1027 case PCI_IVAR_PROGIF:
1028 case PCI_IVAR_REVID:
1029 case PCI_IVAR_INTPIN:
1030 case PCI_IVAR_IRQ:
1031 case PCI_IVAR_BUS:
1032 case PCI_IVAR_SLOT:
1033 case PCI_IVAR_FUNCTION:
1034 return EINVAL; /* disallow for now */
1035 default:
1036 return ENOENT;
1037 }
1038 return 0;
1039}
1040
1041/************************************************************************/
1042/* Compatibility with PCI bus (XXX: Do we need this?) */
1043/************************************************************************/
1044
1045/*
1046 * PCI power manangement
1047 */
1048static int
1049cardbus_set_powerstate_method(device_t cbdev, device_t child, int state)
1050{
1051 struct cardbus_devinfo *dinfo = device_get_ivars(child);
1052 pcicfgregs *cfg = &dinfo->pci.cfg;
1053 u_int16_t status;
1054 int result;
1055
1056 if (cfg->pp_cap != 0) {
1057 status = PCI_READ_CONFIG(cbdev, child, cfg->pp_status, 2)
1058 & ~PCIM_PSTAT_DMASK;
1059 result = 0;
1060 switch (state) {
1061 case PCI_POWERSTATE_D0:
1062 status |= PCIM_PSTAT_D0;
1063 break;
1064 case PCI_POWERSTATE_D1:
1065 if (cfg->pp_cap & PCIM_PCAP_D1SUPP) {
1066 status |= PCIM_PSTAT_D1;
1067 } else {
1068 result = EOPNOTSUPP;
1069 }
1070 break;
1071 case PCI_POWERSTATE_D2:
1072 if (cfg->pp_cap & PCIM_PCAP_D2SUPP) {
1073 status |= PCIM_PSTAT_D2;
1074 } else {
1075 result = EOPNOTSUPP;
1076 }
1077 break;
1078 case PCI_POWERSTATE_D3:
1079 status |= PCIM_PSTAT_D3;
1080 break;
1081 default:
1082 result = EINVAL;
1083 }
1084 if (result == 0)
1085 PCI_WRITE_CONFIG(cbdev, child, cfg->pp_status,
1086 status, 2);
1087 } else {
1088 result = ENXIO;
1089 }
1090 return (result);
1091}
1092
1093static int
1094cardbus_get_powerstate_method(device_t cbdev, device_t child)
1095{
1096 struct cardbus_devinfo *dinfo = device_get_ivars(child);
1097 pcicfgregs *cfg = &dinfo->pci.cfg;
1098 u_int16_t status;
1099 int result;
1100
1101 if (cfg->pp_cap != 0) {
1102 status = PCI_READ_CONFIG(cbdev, child, cfg->pp_status, 2);
1103 switch (status & PCIM_PSTAT_DMASK) {
1104 case PCIM_PSTAT_D0:
1105 result = PCI_POWERSTATE_D0;
1106 break;
1107 case PCIM_PSTAT_D1:
1108 result = PCI_POWERSTATE_D1;
1109 break;
1110 case PCIM_PSTAT_D2:
1111 result = PCI_POWERSTATE_D2;
1112 break;
1113 case PCIM_PSTAT_D3:
1114 result = PCI_POWERSTATE_D3;
1115 break;
1116 default:
1117 result = PCI_POWERSTATE_UNKNOWN;
1118 break;
1119 }
1120 } else {
1121 /* No support, device is always at D0 */
1122 result = PCI_POWERSTATE_D0;
1123 }
1124 return (result);
1125}
1126
1127static u_int32_t
1128cardbus_read_config_method(device_t cbdev, device_t child, int reg, int width)
1129{
1130 struct cardbus_devinfo *dinfo = device_get_ivars(child);
1131 pcicfgregs *cfg = &dinfo->pci.cfg;
1132
1133 return PCIB_READ_CONFIG(device_get_parent(cbdev),
1134 cfg->bus, cfg->slot, cfg->func, reg, width);
1135}
1136
1137static void
1138cardbus_write_config_method(device_t cbdev, device_t child, int reg,
1139 u_int32_t val, int width)
1140{
1141 struct cardbus_devinfo *dinfo = device_get_ivars(child);
1142 pcicfgregs *cfg = &dinfo->pci.cfg;
1143
1144 PCIB_WRITE_CONFIG(device_get_parent(cbdev),
1145 cfg->bus, cfg->slot, cfg->func, reg, val, width);
1146}
1147
1148static __inline void
1149cardbus_set_command_bit(device_t cbdev, device_t child, u_int16_t bit)
1150{
1151 u_int16_t command;
1152
1153 command = PCI_READ_CONFIG(cbdev, child, PCIR_COMMAND, 2);
1154 command |= bit;
1155 PCI_WRITE_CONFIG(cbdev, child, PCIR_COMMAND, command, 2);
1156}
1157
1158static __inline void
1159cardbus_clear_command_bit(device_t cbdev, device_t child, u_int16_t bit)
1160{
1161 u_int16_t command;
1162
1163 command = PCI_READ_CONFIG(cbdev, child, PCIR_COMMAND, 2);
1164 command &= ~bit;
1165 PCI_WRITE_CONFIG(cbdev, child, PCIR_COMMAND, command, 2);
1166}
1167
1168static void
1169cardbus_enable_busmaster_method(device_t cbdev, device_t child)
1170{
1171 cardbus_set_command_bit(cbdev, child, PCIM_CMD_BUSMASTEREN);
1172}
1173
1174static void
1175cardbus_disable_busmaster_method(device_t cbdev, device_t child)
1176{
1177 cardbus_clear_command_bit(cbdev, child, PCIM_CMD_BUSMASTEREN);
1178}
1179
1180static void
1181cardbus_enable_io_method(device_t cbdev, device_t child, int space)
1182{
1183 switch (space) {
1184 case SYS_RES_IOPORT:
1185 cardbus_set_command_bit(cbdev, child, PCIM_CMD_PORTEN);
1186 break;
1187 case SYS_RES_MEMORY:
1188 cardbus_set_command_bit(cbdev, child, PCIM_CMD_MEMEN);
1189 break;
1190 }
1191}
1192
1193static void
1194cardbus_disable_io_method(device_t cbdev, device_t child, int space)
1195{
1196 switch (space) {
1197 case SYS_RES_IOPORT:
1198 cardbus_clear_command_bit(cbdev, child, PCIM_CMD_PORTEN);
1199 break;
1200 case SYS_RES_MEMORY:
1201 cardbus_clear_command_bit(cbdev, child, PCIM_CMD_MEMEN);
1202 break;
1203 }
1204}
1205
1206static device_method_t cardbus_methods[] = {
1207 /* Device interface */
1208 DEVMETHOD(device_probe, cardbus_probe),
1209 DEVMETHOD(device_attach, cardbus_attach),
1210 DEVMETHOD(device_detach, cardbus_detach),
1211 DEVMETHOD(device_shutdown, bus_generic_shutdown),
1212 DEVMETHOD(device_suspend, cardbus_suspend),
1213 DEVMETHOD(device_resume, cardbus_resume),
1214
1215 /* Bus interface */
1216 DEVMETHOD(bus_print_child, cardbus_print_child),
1217 DEVMETHOD(bus_probe_nomatch, cardbus_probe_nomatch),
1218 DEVMETHOD(bus_read_ivar, cardbus_read_ivar),
1219 DEVMETHOD(bus_write_ivar, cardbus_write_ivar),
1220 DEVMETHOD(bus_driver_added, cardbus_driver_added),
1221 DEVMETHOD(bus_alloc_resource, cardbus_alloc_resource),
1222 DEVMETHOD(bus_release_resource, cardbus_release_resource),
1223 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
1224 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
1225 DEVMETHOD(bus_setup_intr, cardbus_setup_intr),
1226 DEVMETHOD(bus_teardown_intr, cardbus_teardown_intr),
1227
1228 DEVMETHOD(bus_set_resource, cardbus_set_resource_method),
1229 DEVMETHOD(bus_get_resource, cardbus_get_resource_method),
1230 DEVMETHOD(bus_delete_resource, cardbus_delete_resource_method),
1231 DEVMETHOD(bus_child_pnpinfo_str, cardbus_child_pnpinfo_str),
1232 DEVMETHOD(bus_child_location_str, cardbus_child_location_str),
1233
1234 /* Card Interface */
1235 DEVMETHOD(card_attach_card, cardbus_attach_card),
1236 DEVMETHOD(card_detach_card, cardbus_detach_card),
1237 DEVMETHOD(card_cis_read, cardbus_cis_read),
1238 DEVMETHOD(card_cis_free, cardbus_cis_free),
1239
1240 /* Cardbus/PCI interface */
1241 DEVMETHOD(pci_read_config, cardbus_read_config_method),
1242 DEVMETHOD(pci_write_config, cardbus_write_config_method),
1243 DEVMETHOD(pci_enable_busmaster, cardbus_enable_busmaster_method),
1244 DEVMETHOD(pci_disable_busmaster, cardbus_disable_busmaster_method),
1245 DEVMETHOD(pci_enable_io, cardbus_enable_io_method),
1246 DEVMETHOD(pci_disable_io, cardbus_disable_io_method),
1247 DEVMETHOD(pci_get_powerstate, cardbus_get_powerstate_method),
1248 DEVMETHOD(pci_set_powerstate, cardbus_set_powerstate_method),
1249
1250 {0,0}
1251};
1252
1253static driver_t cardbus_driver = {
1254 "cardbus",
1255 cardbus_methods,
1256 0 /* no softc */
1257};
1258
1259static devclass_t cardbus_devclass;
1260
1261DRIVER_MODULE(cardbus, cbb, cardbus_driver, cardbus_devclass, 0, 0);
1262MODULE_VERSION(cardbus, 1);
1263MODULE_DEPEND(cardbus, exca, 1, 1, 1);
1264/*
1265MODULE_DEPEND(cardbus, pccbb, 1, 1, 1);
1266*/