This source file includes following definitions.
- cardbusmatch
- cardbusattach
- cardbus_read_tuples
- parse_tuple
- cardbus_attach_card
- cardbussubmatch
- cardbusprint
- cardbus_detach_card
- cardbus_intr_establish
- cardbus_intr_disestablish
- enable_function
- disable_function
- cardbus_function_enable
- cardbus_function_disable
- cardbus_get_capability
- cardbus_matchbyid
- decode_tuples
- decode_tuple
- tuple_name
- print_tuple
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <sys/kernel.h>
41 #include <sys/syslog.h>
42 #include <sys/proc.h>
43
44 #include <machine/bus.h>
45
46 #include <dev/cardbus/cardbusvar.h>
47 #include <dev/pci/pcidevs.h>
48
49 #include <dev/cardbus/cardbus_exrom.h>
50
51 #include <dev/pci/pcivar.h>
52 #include <dev/pci/pcireg.h>
53
54 #include <dev/pcmcia/pcmciareg.h>
55
56 #if defined CARDBUS_DEBUG
57 #define STATIC
58 #define DPRINTF(a) printf a
59 #else
60 #define STATIC static
61 #define DPRINTF(a)
62 #endif
63
64 STATIC void cardbusattach(struct device *, struct device *, void *);
65
66
67 STATIC int cardbusmatch(struct device *, void *, void *);
68 static int cardbussubmatch(struct device *, void *, void *);
69 static int cardbusprint(void *, const char *);
70
71 typedef void (*tuple_decode_func)(u_int8_t *, int, void *);
72
73 static int decode_tuples(u_int8_t *, int, tuple_decode_func, void *);
74 #ifdef CARDBUS_DEBUG
75 static void print_tuple(u_int8_t *, int, void *);
76 #endif
77
78 static int cardbus_read_tuples(struct cardbus_attach_args *,
79 cardbusreg_t, u_int8_t *, size_t);
80
81 static void enable_function(struct cardbus_softc *, int, int);
82 static void disable_function(struct cardbus_softc *, int);
83
84
85 struct cfattach cardbus_ca = {
86 sizeof(struct cardbus_softc), cardbusmatch, cardbusattach
87 };
88
89 struct cfdriver cardbus_cd = {
90 NULL, "cardbus", DV_DULL
91 };
92
93 STATIC int
94 cardbusmatch(struct device *parent, void *match, void *aux)
95 {
96 struct cfdata *cf = match;
97 struct cbslot_attach_args *cba = aux;
98
99 if (strcmp(cba->cba_busname, cf->cf_driver->cd_name)) {
100 DPRINTF(("cardbusmatch: busname differs %s <=> %s\n",
101 cba->cba_busname, cf->cf_driver->cd_name));
102 return (0);
103 }
104
105 return (1);
106 }
107
108 STATIC void
109 cardbusattach(struct device *parent, struct device *self, void *aux)
110 {
111 struct cardbus_softc *sc = (void *)self;
112 struct cbslot_attach_args *cba = aux;
113 int cdstatus;
114
115 sc->sc_bus = cba->cba_bus;
116 sc->sc_device = 0;
117 sc->sc_intrline = cba->cba_intrline;
118 sc->sc_cacheline = cba->cba_cacheline;
119 sc->sc_lattimer = cba->cba_lattimer;
120
121 printf(": bus %d device %d", sc->sc_bus, sc->sc_device);
122 printf(" cacheline 0x%x, lattimer 0x%x\n",
123 sc->sc_cacheline,sc->sc_lattimer);
124
125 sc->sc_iot = cba->cba_iot;
126 sc->sc_memt = cba->cba_memt;
127 sc->sc_dmat = cba->cba_dmat;
128 sc->sc_cc = cba->cba_cc;
129 sc->sc_cf = cba->cba_cf;
130 sc->sc_rbus_iot = cba->cba_rbus_iot;
131 sc->sc_rbus_memt = cba->cba_rbus_memt;
132
133 sc->sc_funcs = NULL;
134
135 cdstatus = 0;
136 }
137
138 static int
139 cardbus_read_tuples(struct cardbus_attach_args *ca, cardbusreg_t cis_ptr,
140 u_int8_t *tuples, size_t len)
141 {
142 struct cardbus_softc *sc = ca->ca_ct->ct_sc;
143 cardbus_chipset_tag_t cc = ca->ca_ct->ct_cc;
144 cardbus_function_tag_t cf = ca->ca_ct->ct_cf;
145 cardbustag_t tag = ca->ca_tag;
146 cardbusreg_t command;
147 int found = 0;
148
149 int i, j;
150 int cardbus_space = cis_ptr & CARDBUS_CIS_ASIMASK;
151 bus_space_tag_t bar_tag;
152 bus_space_handle_t bar_memh;
153 bus_size_t bar_size;
154 bus_addr_t bar_addr;
155
156 int reg;
157
158 memset(tuples, 0, len);
159
160 cis_ptr = cis_ptr & CARDBUS_CIS_ADDRMASK;
161
162 switch (cardbus_space) {
163 case CARDBUS_CIS_ASI_TUPLE:
164 DPRINTF(("%s: reading CIS data from configuration space\n",
165 sc->sc_dev.dv_xname));
166 for (i = cis_ptr, j = 0; i < 0xff; i += 4) {
167 u_int32_t e = (cf->cardbus_conf_read)(cc, tag, i);
168 tuples[j] = 0xff & e;
169 e >>= 8;
170 tuples[j + 1] = 0xff & e;
171 e >>= 8;
172 tuples[j + 2] = 0xff & e;
173 e >>= 8;
174 tuples[j + 3] = 0xff & e;
175 j += 4;
176 }
177 found++;
178 break;
179
180 case CARDBUS_CIS_ASI_BAR0:
181 case CARDBUS_CIS_ASI_BAR1:
182 case CARDBUS_CIS_ASI_BAR2:
183 case CARDBUS_CIS_ASI_BAR3:
184 case CARDBUS_CIS_ASI_BAR4:
185 case CARDBUS_CIS_ASI_BAR5:
186 case CARDBUS_CIS_ASI_ROM:
187 if (cardbus_space == CARDBUS_CIS_ASI_ROM) {
188 reg = CARDBUS_ROM_REG;
189 DPRINTF(("%s: reading CIS data from ROM\n",
190 sc->sc_dev.dv_xname));
191 } else {
192 reg = CARDBUS_BASE0_REG + (cardbus_space - 1) * 4;
193 DPRINTF(("%s: reading CIS data from BAR%d\n",
194 sc->sc_dev.dv_xname, cardbus_space - 1));
195 }
196
197
198
199 cardbus_conf_write(cc, cf, tag, reg, 0);
200 if (Cardbus_mapreg_map(ca->ca_ct, reg,
201 CARDBUS_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
202 &bar_tag, &bar_memh, &bar_addr, &bar_size)) {
203 printf("%s: failed to map memory\n",
204 sc->sc_dev.dv_xname);
205 return (1);
206 }
207
208 if (cardbus_space == CARDBUS_CIS_ASI_ROM) {
209 cardbusreg_t exrom;
210 int save;
211 struct cardbus_rom_image_head rom_image;
212 struct cardbus_rom_image *p;
213
214 save = splhigh();
215
216 exrom = cardbus_conf_read(cc, cf, tag, reg);
217 cardbus_conf_write(cc, cf, tag, reg, exrom | 1);
218
219 command = cardbus_conf_read(cc, cf, tag,
220 CARDBUS_COMMAND_STATUS_REG);
221 cardbus_conf_write(cc, cf, tag,
222 CARDBUS_COMMAND_STATUS_REG,
223 command | CARDBUS_COMMAND_MEM_ENABLE);
224
225 if (cardbus_read_exrom(ca->ca_memt, bar_memh,
226 &rom_image))
227 goto out;
228
229 for (p = SIMPLEQ_FIRST(&rom_image); p;
230 p = SIMPLEQ_NEXT(p, next)) {
231 if (p->rom_image ==
232 CARDBUS_CIS_ASI_ROM_IMAGE(cis_ptr)) {
233 bus_space_read_region_1(p->romt,
234 p->romh, CARDBUS_CIS_ADDR(cis_ptr),
235 tuples, MIN(p->image_size, len));
236 found++;
237 break;
238 }
239 }
240
241 out:
242 while ((p = SIMPLEQ_FIRST(&rom_image)) != NULL) {
243 SIMPLEQ_REMOVE_HEAD(&rom_image, next);
244 free(p, M_DEVBUF);
245 }
246 exrom = cardbus_conf_read(cc, cf, tag, reg);
247 cardbus_conf_write(cc, cf, tag, reg, exrom & ~1);
248 splx(save);
249 } else {
250 command = cardbus_conf_read(cc, cf, tag,
251 CARDBUS_COMMAND_STATUS_REG);
252 cardbus_conf_write(cc, cf, tag,
253 CARDBUS_COMMAND_STATUS_REG,
254 command | CARDBUS_COMMAND_MEM_ENABLE);
255
256 bus_space_read_region_1(ca->ca_memt, bar_memh,
257 cis_ptr, tuples, 256);
258 found++;
259 }
260 command = cardbus_conf_read(cc, cf, tag,
261 CARDBUS_COMMAND_STATUS_REG);
262 cardbus_conf_write(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG,
263 command & ~CARDBUS_COMMAND_MEM_ENABLE);
264 cardbus_conf_write(cc, cf, tag, reg, 0);
265
266 Cardbus_mapreg_unmap(ca->ca_ct, reg, bar_tag, bar_memh,
267 bar_size);
268 break;
269
270 #ifdef DIAGNOSTIC
271 default:
272 panic("%s: bad CIS space (%d)", sc->sc_dev.dv_xname,
273 cardbus_space);
274 #endif
275 }
276 return (!found);
277 }
278
279 static void
280 parse_tuple(u_int8_t *tuple, int len, void *data)
281 {
282 struct cardbus_cis_info *cis = data;
283 int bar_index;
284 int i;
285 char *p;
286
287 switch (tuple[0]) {
288 case PCMCIA_CISTPL_MANFID:
289 if (tuple[1] < 4) {
290 DPRINTF(("%s: wrong length manufacturer id (%d)\n",
291 __func__, tuple[1]));
292 break;
293 }
294 cis->manufacturer = tuple[2] | (tuple[3] << 8);
295 cis->product = tuple[4] | (tuple[5] << 8);
296 break;
297 case PCMCIA_CISTPL_VERS_1:
298 bcopy(tuple + 2, cis->cis1_info_buf, tuple[1]);
299 i = 0;
300 p = cis->cis1_info_buf + 2;
301 while (i <
302 sizeof(cis->cis1_info) / sizeof(cis->cis1_info[0])) {
303 if (p >= cis->cis1_info_buf + tuple[1] || *p == '\xff')
304 break;
305 cis->cis1_info[i++] = p;
306 while (*p != '\0' && *p != '\xff')
307 p++;
308 if (*p == '\0')
309 p++;
310 }
311 break;
312 case PCMCIA_CISTPL_BAR:
313 if (tuple[1] != 6) {
314 DPRINTF(("%s: BAR with short length (%d)\n",
315 __func__, tuple[1]));
316 break;
317 }
318 bar_index = tuple[2] & 7;
319 if (bar_index == 0) {
320 DPRINTF(("%s: invalid ASI in BAR tuple\n",
321 __func__));
322 break;
323 }
324 bar_index--;
325 cis->bar[bar_index].flags = tuple[2];
326 cis->bar[bar_index].size = (tuple[4] << 0) |
327 (tuple[5] << 8) | (tuple[6] << 16) | (tuple[7] << 24);
328 break;
329 case PCMCIA_CISTPL_FUNCID:
330 cis->funcid = tuple[2];
331 break;
332
333 case PCMCIA_CISTPL_FUNCE:
334 switch (cis->funcid) {
335 case PCMCIA_FUNCTION_SERIAL:
336 if (tuple[1] >= 2 &&
337 tuple[2] == 0
338 ) {
339 cis->funce.serial.uart_type = tuple[3] & 0x1f;
340 cis->funce.serial.uart_present = 1;
341 }
342 break;
343 case PCMCIA_FUNCTION_NETWORK:
344 if (tuple[1] >= 8 && tuple[2] ==
345 PCMCIA_TPLFE_TYPE_LAN_NID) {
346 if (tuple[3] >
347 sizeof(cis->funce.network.netid)) {
348 DPRINTF(("%s: unknown network id type"
349 " (len = %d)\n", __func__,
350 tuple[3]));
351 } else {
352 cis->funce.network.netid_present = 1;
353 bcopy(tuple + 4,
354 cis->funce.network.netid, tuple[3]);
355 }
356 }
357 }
358 break;
359 }
360 }
361
362
363
364
365
366
367
368
369
370
371 int
372 cardbus_attach_card(struct cardbus_softc *sc)
373 {
374 cardbus_chipset_tag_t cc;
375 cardbus_function_tag_t cf;
376 int cdstatus;
377 cardbustag_t tag;
378 cardbusreg_t id, class, cis_ptr;
379 cardbusreg_t bhlc;
380 u_int8_t *tuple;
381 int function, nfunction;
382 struct cardbus_devfunc **previous_next = &(sc->sc_funcs);
383 struct device *csc;
384 int no_work_funcs = 0;
385 cardbus_devfunc_t ct;
386 int i;
387
388 cc = sc->sc_cc;
389 cf = sc->sc_cf;
390
391 DPRINTF(("cardbus_attach_card: cb%d start\n", sc->sc_dev.dv_unit));
392
393
394 if (0 == (cdstatus = (cf->cardbus_ctrl)(cc, CARDBUS_CD))) {
395 DPRINTF(("cardbusattach: no CardBus card on cb%d\n",
396 sc->sc_dev.dv_unit));
397 return (0);
398 }
399
400
401 enable_function(sc, cdstatus, 8);
402
403 function = 0;
404
405 tag = cardbus_make_tag(cc, cf, sc->sc_bus, sc->sc_device, function);
406
407
408 for (i = 0; i < 5; ++i) {
409 id = cardbus_conf_read(cc, cf, tag, CARDBUS_ID_REG);
410 if (id != 0xffffffff && id != 0)
411 break;
412 if (cold) {
413 delay(100*1000);
414 } else {
415 if (tsleep((void *)sc, PCATCH, "cardbus",
416 hz/10) != EWOULDBLOCK) {
417 break;
418 }
419 }
420 }
421 if (i == 5)
422 return (0);
423
424 bhlc = cardbus_conf_read(cc, cf, tag, CARDBUS_BHLC_REG);
425 DPRINTF(("%s bhlc 0x%08x -> ", sc->sc_dev.dv_xname, bhlc));
426 nfunction = CARDBUS_HDRTYPE_MULTIFN(bhlc) ? 8 : 1;
427
428 tuple = malloc(2048, M_TEMP, M_NOWAIT);
429 if (tuple == NULL)
430 panic("no room for cardbus tuples");
431
432 for (function = 0; function < nfunction; function++) {
433 struct cardbus_attach_args ca;
434
435 tag = cardbus_make_tag(cc, cf, sc->sc_bus, sc->sc_device,
436 function);
437
438 id = cardbus_conf_read(cc, cf, tag, CARDBUS_ID_REG);
439 class = cardbus_conf_read(cc, cf, tag, CARDBUS_CLASS_REG);
440 cis_ptr = cardbus_conf_read(cc, cf, tag, CARDBUS_CIS_REG);
441
442
443 if (CARDBUS_VENDOR(id) == PCI_VENDOR_INVALID)
444 continue;
445
446 DPRINTF(("cardbus_attach_card: Vendor 0x%x, Product 0x%x, "
447 "CIS 0x%x\n", CARDBUS_VENDOR(id), CARDBUS_PRODUCT(id),
448 cis_ptr));
449
450 enable_function(sc, cdstatus, function);
451
452
453 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE0_REG, 0);
454 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE1_REG, 0);
455 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE2_REG, 0);
456 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE3_REG, 0);
457 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE4_REG, 0);
458 cardbus_conf_write(cc, cf, tag, CARDBUS_BASE5_REG, 0);
459 cardbus_conf_write(cc, cf, tag, CARDBUS_ROM_REG, 0);
460
461
462 bhlc = cardbus_conf_read(cc, cf, tag, CARDBUS_BHLC_REG);
463 DPRINTF(("%s func%d bhlc 0x%08x -> ", sc->sc_dev.dv_xname,
464 function, bhlc));
465 bhlc &= ~((CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT) |
466 (CARDBUS_CACHELINE_MASK << CARDBUS_CACHELINE_SHIFT));
467 bhlc |= ((sc->sc_cacheline & CARDBUS_CACHELINE_MASK) <<
468 CARDBUS_CACHELINE_SHIFT);
469 bhlc |= ((sc->sc_lattimer & CARDBUS_LATTIMER_MASK) <<
470 CARDBUS_LATTIMER_SHIFT);
471
472 cardbus_conf_write(cc, cf, tag, CARDBUS_BHLC_REG, bhlc);
473 bhlc = cardbus_conf_read(cc, cf, tag, CARDBUS_BHLC_REG);
474 DPRINTF(("0x%08x\n", bhlc));
475
476 if (CARDBUS_LATTIMER(bhlc) < 0x10) {
477 bhlc &= ~(CARDBUS_LATTIMER_MASK <<
478 CARDBUS_LATTIMER_SHIFT);
479 bhlc |= (0x10 << CARDBUS_LATTIMER_SHIFT);
480 cardbus_conf_write(cc, cf, tag, CARDBUS_BHLC_REG,
481 bhlc);
482 }
483
484
485
486
487
488 if ((ct =
489 (cardbus_devfunc_t)malloc(sizeof(struct cardbus_devfunc),
490 M_DEVBUF, M_NOWAIT)) == NULL)
491 panic("no room for cardbus_tag");
492
493 ct->ct_cc = sc->sc_cc;
494 ct->ct_cf = sc->sc_cf;
495 ct->ct_bus = sc->sc_bus;
496 ct->ct_dev = sc->sc_device;
497 ct->ct_func = function;
498 ct->ct_sc = sc;
499 ct->ct_next = NULL;
500 *previous_next = ct;
501
502 memset(&ca, 0, sizeof(ca));
503
504 ca.ca_unit = sc->sc_dev.dv_unit;
505 ca.ca_ct = ct;
506
507 ca.ca_iot = sc->sc_iot;
508 ca.ca_memt = sc->sc_memt;
509 ca.ca_dmat = sc->sc_dmat;
510 ca.ca_rbus_iot = sc->sc_rbus_iot;
511 ca.ca_rbus_memt = sc->sc_rbus_memt;
512 ca.ca_tag = tag;
513 ca.ca_bus = sc->sc_bus;
514 ca.ca_device = sc->sc_device;
515 ca.ca_function = function;
516 ca.ca_id = id;
517 ca.ca_class = class;
518
519 ca.ca_intrline = sc->sc_intrline;
520
521 if (cis_ptr != 0) {
522 if (cardbus_read_tuples(&ca, cis_ptr, tuple, 2048)) {
523 printf("cardbus_attach_card: failed to "
524 "read CIS\n");
525 } else {
526 #ifdef CARDBUS_DEBUG
527 decode_tuples(tuple, 2048, print_tuple, NULL);
528 #endif
529 decode_tuples(tuple, 2048, parse_tuple,
530 &ca.ca_cis);
531 }
532 }
533
534 if ((csc = config_found_sm((void *)sc, &ca, cardbusprint,
535 cardbussubmatch)) == NULL) {
536
537 disable_function(sc, function);
538 free(ct, M_DEVBUF);
539 *previous_next = NULL;
540 } else {
541
542 previous_next = &(ct->ct_next);
543 ct->ct_device = csc;
544 ++no_work_funcs;
545 }
546 }
547
548
549
550
551 disable_function(sc, 8);
552 free(tuple, M_TEMP);
553
554 return (no_work_funcs);
555 }
556
557 static int
558 cardbussubmatch(struct device *parent, void *match, void *aux)
559 {
560 struct cfdata *cf = match;
561 struct cardbus_attach_args *ca = aux;
562
563 if (cf->cardbuscf_dev != CARDBUS_UNK_DEV &&
564 cf->cardbuscf_dev != ca->ca_unit) {
565 return (0);
566 }
567 if (cf->cardbuscf_function != CARDBUS_UNK_FUNCTION &&
568 cf->cardbuscf_function != ca->ca_function) {
569 return (0);
570 }
571
572 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
573 }
574
575 static int
576 cardbusprint(void *aux, const char *pnp)
577 {
578 struct cardbus_attach_args *ca = aux;
579 char devinfo[256];
580 int i;
581
582 if (pnp) {
583 pci_devinfo(ca->ca_id, ca->ca_class, 1, devinfo,
584 sizeof(devinfo));
585 for (i = 0; i < 4; i++) {
586 if (ca->ca_cis.cis1_info[i] == NULL)
587 break;
588 if (i)
589 printf(", ");
590 printf("%s", ca->ca_cis.cis1_info[i]);
591 }
592 if (i)
593 printf(" ");
594 if (ca->ca_cis.manufacturer)
595 printf("(manufacturer 0x%x, product 0x%x) ",
596 ca->ca_cis.manufacturer, ca->ca_cis.product);
597 printf("%s at %s", devinfo, pnp);
598 }
599 printf(" dev %d function %d", ca->ca_device, ca->ca_function);
600
601 if (!pnp) {
602 pci_devinfo(ca->ca_id, ca->ca_class, 1, devinfo,
603 sizeof(devinfo));
604 for (i = 0; i < 3 && ca->ca_cis.cis1_info[i]; i++)
605 printf("%s%s", i ? ", " : " \"",
606 ca->ca_cis.cis1_info[i]);
607 if (ca->ca_cis.cis1_info[0])
608 printf("\"");
609 }
610
611 return (UNCONF);
612 }
613
614
615
616
617
618
619
620
621
622 void
623 cardbus_detach_card(struct cardbus_softc *sc)
624 {
625 struct cardbus_devfunc *ct, *ct_next, **prev_next;
626
627 prev_next = &(sc->sc_funcs->ct_next);
628
629 for (ct = sc->sc_funcs; ct != NULL; ct = ct_next) {
630 struct device *fndev = ct->ct_device;
631 ct_next = ct->ct_next;
632
633 DPRINTF(("%s: detaching %s\n", sc->sc_dev.dv_xname,
634 fndev->dv_xname));
635
636
637 if (config_detach(fndev, 0) != 0) {
638 printf("%s: cannot detach dev %s, function %d\n",
639 sc->sc_dev.dv_xname, fndev->dv_xname, ct->ct_func);
640 prev_next = &(ct->ct_next);
641 } else {
642 sc->sc_poweron_func &= ~(1 << ct->ct_func);
643 *prev_next = ct->ct_next;
644 free(ct, M_DEVBUF);
645 }
646 }
647
648 sc->sc_poweron_func = 0;
649 sc->sc_cf->cardbus_power(sc->sc_cc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
650 }
651
652
653
654
655
656
657
658
659 void *
660 cardbus_intr_establish(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf,
661 cardbus_intr_handle_t irq, int level, int (*func)(void *), void *arg,
662 const char *name)
663 {
664 DPRINTF(("- cardbus_intr_establish: irq %d\n", irq));
665
666 return (*cf->cardbus_intr_establish)(cc, irq, level, func, arg, name);
667 }
668
669
670
671
672
673
674
675 void
676 cardbus_intr_disestablish(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf,
677 void *handler)
678 {
679 DPRINTF(("- pccard_intr_disestablish\n"));
680
681 (*cf->cardbus_intr_disestablish)(cc, handler);
682 }
683
684
685
686
687 static void
688 enable_function(struct cardbus_softc *sc, int cdstatus, int function)
689 {
690 if (sc->sc_poweron_func == 0) {
691
692 if (cdstatus & CARDBUS_3V_CARD) {
693 sc->sc_cf->cardbus_power(sc->sc_cc, CARDBUS_VCC_3V);
694 } else {
695
696 return;
697 }
698 (sc->sc_cf->cardbus_ctrl)(sc->sc_cc, CARDBUS_RESET);
699 }
700 sc->sc_poweron_func |= (1 << function);
701 }
702
703 static void
704 disable_function(struct cardbus_softc *sc, int function)
705 {
706 sc->sc_poweron_func &= ~(1 << function);
707 if (sc->sc_poweron_func == 0) {
708
709 sc->sc_cf->cardbus_power(sc->sc_cc, CARDBUS_VCC_0V);
710 }
711 }
712
713
714
715
716
717
718
719 int
720 cardbus_function_enable(struct cardbus_softc *sc, int func)
721 {
722 cardbus_chipset_tag_t cc = sc->sc_cc;
723 cardbus_function_tag_t cf = sc->sc_cf;
724 cardbusreg_t command;
725 cardbustag_t tag;
726
727 DPRINTF(("entering cardbus_function_enable... "));
728
729
730
731
732 enable_function(sc, CARDBUS_3V_CARD, func);
733
734
735
736 tag = cardbus_make_tag(cc, cf, sc->sc_bus, sc->sc_device, func);
737
738 command = cardbus_conf_read(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG);
739 command |= (CARDBUS_COMMAND_MEM_ENABLE | CARDBUS_COMMAND_IO_ENABLE |
740 CARDBUS_COMMAND_MASTER_ENABLE);
741
742 cardbus_conf_write(cc, cf, tag, CARDBUS_COMMAND_STATUS_REG, command);
743
744 cardbus_free_tag(cc, cf, tag);
745
746 DPRINTF(("%x\n", sc->sc_poweron_func));
747
748 return (0);
749 }
750
751
752
753
754
755
756
757 int
758 cardbus_function_disable(struct cardbus_softc *sc, int func)
759 {
760 DPRINTF(("entering cardbus_function_disable... "));
761
762 disable_function(sc, func);
763
764 return (0);
765 }
766
767
768
769
770
771
772
773
774 int
775 cardbus_get_capability(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf,
776 cardbustag_t tag, int capid, int *offset, cardbusreg_t *value)
777 {
778 cardbusreg_t reg;
779 unsigned int ofs;
780
781 reg = cardbus_conf_read(cc, cf, tag, PCI_COMMAND_STATUS_REG);
782 if (!(reg & PCI_STATUS_CAPLIST_SUPPORT))
783 return (0);
784
785 ofs = PCI_CAPLIST_PTR(cardbus_conf_read(cc, cf, tag,
786 PCI_CAPLISTPTR_REG));
787 while (ofs != 0) {
788 #ifdef DIAGNOSTIC
789 if ((ofs & 3) || (ofs < 0x40))
790 panic("cardbus_get_capability 0x%x", ofs);
791 #endif
792 reg = cardbus_conf_read(cc, cf, tag, ofs);
793 if (PCI_CAPLIST_CAP(reg) == capid) {
794 if (offset)
795 *offset = ofs;
796 if (value)
797 *value = reg;
798 return (1);
799 }
800 ofs = PCI_CAPLIST_NEXT(reg);
801 }
802
803 return (0);
804 }
805
806 int
807 cardbus_matchbyid(struct cardbus_attach_args *ca,
808 const struct cardbus_matchid *ids, int nent)
809 {
810 const struct cardbus_matchid *cm;
811 int i;
812
813 for (i = 0, cm = ids; i < nent; i++, cm++)
814 if (CARDBUS_VENDOR(ca->ca_id) == cm->cm_vid &&
815 CARDBUS_PRODUCT(ca->ca_id) == cm->cm_pid)
816 return (1);
817 return (0);
818 }
819
820
821
822
823
824
825 static u_int8_t *
826 decode_tuple(u_int8_t *, u_int8_t *, tuple_decode_func, void *);
827
828 static int
829 decode_tuples(u_int8_t *tuple, int buflen, tuple_decode_func func, void *data)
830 {
831 u_int8_t *tp = tuple;
832
833 if (PCMCIA_CISTPL_LINKTARGET != *tuple) {
834 DPRINTF(("WRONG TUPLE: 0x%x\n", *tuple));
835 return (0);
836 }
837
838 while ((tp = decode_tuple(tp, tuple + buflen, func, data)) != NULL)
839 ;
840
841 return (1);
842 }
843
844 static u_int8_t *
845 decode_tuple(u_int8_t *tuple, u_int8_t *end, tuple_decode_func func,
846 void *data)
847 {
848 u_int8_t type;
849 u_int8_t len;
850
851 type = tuple[0];
852 switch (type) {
853 case PCMCIA_CISTPL_NULL:
854 case PCMCIA_CISTPL_END:
855 len = 1;
856 break;
857 default:
858 if (tuple + 2 > end)
859 return (NULL);
860 len = tuple[1] + 2;
861 break;
862 }
863
864 if (tuple + len > end)
865 return (NULL);
866
867 (*func)(tuple, len, data);
868
869 if (PCMCIA_CISTPL_END == type || tuple + len == end)
870 return (NULL);
871
872 return (tuple + len);
873 }
874
875 #ifdef CARDBUS_DEBUG
876 static char *tuple_name(int type);
877
878 static char *
879 tuple_name(int type)
880 {
881 static char *tuple_name_s [] = {
882 "TPL_NULL", "TPL_DEVICE", "Reserved", "Reserved",
883 "CONFIG_CB", "CFTABLE_ENTRY_CB", "Reserved", "BAR",
884 "Reserved", "Reserved", "Reserved", "Reserved",
885 "Reserved", "Reserved", "Reserved", "Reserved",
886 "CHECKSUM", "LONGLINK_A", "LONGLINK_C", "LINKTARGET",
887 "NO_LINK", "VERS_1", "ALTSTR", "DEVICE_A",
888 "JEDEC_C", "JEDEC_A", "CONFIG", "CFTABLE_ENTRY",
889 "DEVICE_OC", "DEVICE_OA", "DEVICE_GEO",
890 "DEVICE_GEO_A", "MANFID", "FUNCID", "FUNCE", "SWIL",
891 "Reserved", "Reserved", "Reserved", "Reserved",
892 "Reserved", "Reserved", "Reserved", "Reserved",
893 "Reserved", "Reserved", "Reserved", "Reserved",
894 "Reserved", "Reserved", "Reserved", "Reserved",
895 "Reserved", "Reserved", "Reserved", "Reserved",
896 "Reserved", "Reserved", "Reserved", "Reserved",
897 "Reserved", "Reserved", "Reserved", "Reserved",
898 "VERS_2", "FORMAT", "GEOMETRY", "BYTEORDER",
899 "DATE", "BATTERY", "ORG", "FORMAT_A"
900 };
901 #define NAME_LEN(x) (sizeof(x)/sizeof(x[0]))
902
903 if (type > 0 && type < NAME_LEN(tuple_name_s))
904 return (tuple_name_s[type]);
905 else if (0xff == type)
906 return ("END");
907 else
908 return ("Reserved");
909 }
910
911 static void
912 print_tuple(u_int8_t *tuple, int len, void *data)
913 {
914 int i;
915
916 printf("tuple: %s len %d\n", tuple_name(tuple[0]), len);
917
918 for (i = 0; i < len; ++i) {
919 if (i % 16 == 0)
920 printf(" 0x%02x:", i);
921 printf(" %x",tuple[i]);
922 if (i % 16 == 15)
923 printf("\n");
924 }
925 if (i % 16 != 0)
926 printf("\n");
927 }
928 #endif