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