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