1 /* $NetBSD: pcmcia_cis.c,v 1.17 2000/02/10 09:01:52 chopps Exp $ */
5 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Marc Horowitz.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/kernel.h>
38 #include <sys/queue.h>
39 #include <sys/types.h>
42 #include <machine/bus.h>
44 #include <machine/resource.h>
46 #include <dev/pccard/pccardreg.h>
47 #include <dev/pccard/pccardvar.h>
51 extern int pccard_cis_debug;
53 #define PCCARDCISDEBUG
55 #define DPRINTF(arg) if (pccard_cis_debug) printf arg
56 #define DEVPRINTF(arg) if (pccard_cis_debug) device_printf arg
59 #define DEVPRINTF(arg)
62 #define PCCARD_CIS_SIZE 1024
67 struct pccard_config_entry temp_cfe;
68 struct pccard_config_entry *default_cfe;
69 struct pccard_card *card;
70 struct pccard_function *pf;
73 int pccard_parse_cis_tuple(struct pccard_tuple *, void *);
74 static int decode_funce(struct pccard_tuple *, struct pccard_function *);
77 pccard_read_cis(struct pccard_softc *sc)
79 struct cis_state state;
81 bzero(&state, sizeof state);
83 state.card = &sc->card;
85 state.card->error = 0;
86 state.card->cis1_major = -1;
87 state.card->cis1_minor = -1;
88 state.card->cis1_info[0] = NULL;
89 state.card->cis1_info[1] = NULL;
90 state.card->cis1_info[2] = NULL;
91 state.card->cis1_info[3] = NULL;
92 state.card->manufacturer = PCMCIA_VENDOR_INVALID;
93 state.card->product = PCMCIA_PRODUCT_INVALID;
94 STAILQ_INIT(&state.card->pf_head);
98 if (pccard_scan_cis(sc->dev, pccard_parse_cis_tuple,
104 pccard_scan_cis(device_t dev, int (*fct)(struct pccard_tuple *, void *),
107 struct resource *res;
109 struct pccard_tuple tuple;
110 int longlink_present;
112 u_long longlink_addr;
123 /* allocate some memory */
126 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0,
127 PCCARD_CIS_SIZE, RF_ACTIVE);
129 device_printf(dev, "can't alloc memory to read attributes\n");
132 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
133 rid, PCCARD_A_MEM_ATTR);
134 tuple.memt = rman_get_bustag(res);
135 tuple.memh = rman_get_bushandle(res);
138 DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
142 longlink_present = 1;
149 DEVPRINTF((dev, "CIS tuple chain:\n"));
153 /* get the tuple code */
155 tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
157 /* two special-case tuples */
159 if (tuple.code == PCCARD_CISTPL_NULL) {
160 DPRINTF(("CISTPL_NONE\n 00\n"));
163 } else if (tuple.code == PCCARD_CISTPL_END) {
164 DPRINTF(("CISTPL_END\n ff\n"));
165 /* Call the function for the END tuple, since
166 the CIS semantics depend on it */
167 if ((*fct) (&tuple, arg)) {
174 /* now all the normal tuples */
176 tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1);
177 switch (tuple.code) {
178 case PCCARD_CISTPL_LONGLINK_A:
179 case PCCARD_CISTPL_LONGLINK_C:
180 if (tuple.length < 4) {
181 DPRINTF(("CISTPL_LONGLINK_%s too "
183 longlink_common ? "C" : "A",
187 longlink_present = 1;
188 longlink_common = (tuple.code ==
189 PCCARD_CISTPL_LONGLINK_C) ? 1 : 0;
190 longlink_addr = pccard_tuple_read_4(&tuple, 0);
191 DPRINTF(("CISTPL_LONGLINK_%s %lx\n",
192 longlink_common ? "C" : "A",
195 case PCCARD_CISTPL_NO_LINK:
196 longlink_present = 0;
197 DPRINTF(("CISTPL_NO_LINK\n"));
199 case PCCARD_CISTPL_CHECKSUM:
200 if (tuple.length < 5) {
201 DPRINTF(("CISTPL_CHECKSUM too "
202 "short %d\n", tuple.length));
211 pccard_tuple_read_2(&tuple, 0);
212 length = pccard_tuple_read_2(&tuple, 2);
213 cksum = pccard_tuple_read_1(&tuple, 4);
215 addr = tuple.ptr + offset;
217 DPRINTF(("CISTPL_CHECKSUM addr=%lx "
219 addr, length, cksum));
222 * XXX do more work to deal with
225 if ((addr >= PCCARD_CIS_SIZE) ||
228 DPRINTF((" skipped, "
233 for (i = 0; i < length; i++)
235 bus_space_read_1(tuple.memt,
237 addr + tuple.mult * i);
238 if (cksum != (sum & 0xff)) {
239 DPRINTF((" failed sum=%x\n",
242 "CIS checksum failed\n");
245 * XXX Some working cards have
246 * XXX bad checksums!!
255 case PCCARD_CISTPL_LONGLINK_MFC:
256 if (tuple.length < 1) {
257 DPRINTF(("CISTPL_LONGLINK_MFC too "
258 "short %d\n", tuple.length));
261 if (((tuple.length - 1) % 5) != 0) {
262 DPRINTF(("CISTPL_LONGLINK_MFC bogus "
263 "length %d\n", tuple.length));
267 * this is kind of ad hoc, as I don't have
268 * any real documentation
274 * put count into tmp var so that
275 * if we have to bail (because it's
276 * a bogus count) it won't be
277 * remembered for later use.
280 pccard_tuple_read_1(&tuple, 0);
282 DPRINTF(("CISTPL_LONGLINK_MFC %d",
286 * make _sure_ it's the right size;
287 * if too short, it may be a weird
288 * (unknown/undefined) format
290 if (tuple.length != (tmp_count*5 + 1)) {
291 DPRINTF((" bogus length %d\n",
296 * sanity check for a programming
297 * error which is difficult to find
301 howmany(sizeof mfc, sizeof mfc[0]))
302 panic("CISTPL_LONGLINK_MFC mfc "
303 "count would blow stack");
304 mfc_count = tmp_count;
305 for (i = 0; i < mfc_count; i++) {
307 (pccard_tuple_read_1(&tuple,
309 PCCARD_MFC_MEM_COMMON) ?
312 pccard_tuple_read_4(&tuple,
315 mfc[i].common ? "common" :
316 "attr", mfc[i].addr));
321 * for LONGLINK_MFC, fall through to the
322 * function. This tuple has structural and
327 if ((*fct) (&tuple, arg)) {
334 #ifdef PCCARDCISDEBUG
335 /* print the tuple */
339 DPRINTF((" %02x %02x", tuple.code,
342 for (i = 0; i < tuple.length; i++) {
344 pccard_tuple_read_1(&tuple, i)));
353 /* skip to the next tuple */
354 tuple.ptr += 2 + tuple.length;
358 * the chain is done. Clean up and move onto the next one,
359 * if any. The loop is here in the case that there is an MFC
360 * card with no longlink (which defaults to existing, == 0).
361 * In general, this means that if one pointer fails, it will
362 * try the next one, instead of just bailing.
366 if (longlink_present) {
367 CARD_SET_RES_FLAGS(device_get_parent(dev), dev,
368 SYS_RES_MEMORY, rid, longlink_common ?
369 PCCARD_A_MEM_COM : PCCARD_A_MEM_ATTR);
370 DPRINTF(("cis mem map %x\n",
371 (unsigned int) tuple.memh));
372 tuple.mult = longlink_common ? 1 : 2;
373 tuple.ptr = longlink_addr;
374 longlink_present = 0;
377 } else if (mfc_count && (mfc_index < mfc_count)) {
378 CARD_SET_RES_FLAGS(device_get_parent(dev), dev,
379 SYS_RES_MEMORY, rid, mfc[mfc_index].common
380 ? PCCARD_A_MEM_COM : PCCARD_A_MEM_ATTR);
381 DPRINTF(("cis mem map %x\n",
382 (unsigned int) tuple.memh));
383 /* set parse state, and point at the next one */
384 tuple.mult = mfc[mfc_index].common ? 1 : 2;
385 tuple.ptr = mfc[mfc_index].addr;
391 /* make sure that the link is valid */
392 tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
393 if (tuple.code != PCCARD_CISTPL_LINKTARGET) {
394 DPRINTF(("CISTPL_LINKTARGET expected, "
395 "code %02x observed\n", tuple.code));
398 tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1);
399 if (tuple.length < 3) {
400 DPRINTF(("CISTPL_LINKTARGET too short %d\n",
404 if ((pccard_tuple_read_1(&tuple, 0) != 'C') ||
405 (pccard_tuple_read_1(&tuple, 1) != 'I') ||
406 (pccard_tuple_read_1(&tuple, 2) != 'S')) {
407 DPRINTF(("CISTPL_LINKTARGET magic "
408 "%02x%02x%02x incorrect\n",
409 pccard_tuple_read_1(&tuple, 0),
410 pccard_tuple_read_1(&tuple, 1),
411 pccard_tuple_read_1(&tuple, 2)));
414 tuple.ptr += 2 + tuple.length;
420 bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
425 /* XXX this is incredibly verbose. Not sure what trt is */
428 pccard_print_cis(device_t dev)
430 struct pccard_softc *sc = PCCARD_SOFTC(dev);
431 struct pccard_card *card = &sc->card;
432 struct pccard_function *pf;
433 struct pccard_config_entry *cfe;
436 device_printf(dev, "CIS version ");
437 if (card->cis1_major == 4) {
438 if (card->cis1_minor == 0)
439 printf("PCCARD 1.0\n");
440 else if (card->cis1_minor == 1)
441 printf("PCCARD 2.0 or 2.1\n");
442 } else if (card->cis1_major >= 5)
443 printf("PC Card Standard %d.%d\n", card->cis1_major, card->cis1_minor);
445 printf("unknown (major=%d, minor=%d)\n",
446 card->cis1_major, card->cis1_minor);
448 device_printf(dev, "CIS info: ");
449 for (i = 0; i < 4; i++) {
450 if (card->cis1_info[i] == NULL)
454 printf("%s", card->cis1_info[i]);
458 device_printf(dev, "Manufacturer code 0x%x, product 0x%x\n",
459 card->manufacturer, card->product);
461 STAILQ_FOREACH(pf, &card->pf_head, pf_list) {
462 device_printf(dev, "function %d: ", pf->number);
464 switch (pf->function) {
465 case PCCARD_FUNCTION_UNSPEC:
466 printf("unspecified");
468 case PCCARD_FUNCTION_MULTIFUNCTION:
469 printf("multi-function");
471 case PCCARD_FUNCTION_MEMORY:
474 case PCCARD_FUNCTION_SERIAL:
475 printf("serial port");
477 case PCCARD_FUNCTION_PARALLEL:
478 printf("parallel port");
480 case PCCARD_FUNCTION_DISK:
481 printf("fixed disk");
483 case PCCARD_FUNCTION_VIDEO:
484 printf("video adapter");
486 case PCCARD_FUNCTION_NETWORK:
487 printf("network adapter");
489 case PCCARD_FUNCTION_AIMS:
490 printf("auto incrementing mass storage");
492 case PCCARD_FUNCTION_SCSI:
493 printf("SCSI bridge");
495 case PCCARD_FUNCTION_SECURITY:
496 printf("Security services");
498 case PCCARD_FUNCTION_INSTRUMENT:
499 printf("Instrument");
502 printf("unknown (%d)", pf->function);
506 printf(", ccr addr %x mask %x\n", pf->ccr_base, pf->ccr_mask);
508 STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
509 device_printf(dev, "function %d, config table entry "
510 "%d: ", pf->number, cfe->number);
512 switch (cfe->iftype) {
513 case PCCARD_IFTYPE_MEMORY:
514 printf("memory card");
516 case PCCARD_IFTYPE_IO:
520 printf("card type unknown");
524 printf("; irq mask %x", cfe->irqmask);
526 if (cfe->num_iospace) {
527 printf("; iomask %lx, iospace", cfe->iomask);
529 for (i = 0; i < cfe->num_iospace; i++) {
530 printf(" %lx", cfe->iospace[i].start);
531 if (cfe->iospace[i].length)
533 cfe->iospace[i].start +
534 cfe->iospace[i].length - 1);
537 if (cfe->num_memspace) {
538 printf("; memspace");
540 for (i = 0; i < cfe->num_memspace; i++) {
542 cfe->memspace[i].cardaddr);
543 if (cfe->memspace[i].length)
545 cfe->memspace[i].cardaddr +
546 cfe->memspace[i].length - 1);
547 if (cfe->memspace[i].hostaddr)
549 cfe->memspace[i].hostaddr);
553 printf("; maxtwins %d", cfe->maxtwins);
557 if (cfe->flags & PCCARD_CFE_MWAIT_REQUIRED)
558 printf(" mwait_required");
559 if (cfe->flags & PCCARD_CFE_RDYBSY_ACTIVE)
560 printf(" rdybsy_active");
561 if (cfe->flags & PCCARD_CFE_WP_ACTIVE)
562 printf(" wp_active");
563 if (cfe->flags & PCCARD_CFE_BVD_ACTIVE)
564 printf(" bvd_active");
565 if (cfe->flags & PCCARD_CFE_IO8)
567 if (cfe->flags & PCCARD_CFE_IO16)
569 if (cfe->flags & PCCARD_CFE_IRQSHARE)
571 if (cfe->flags & PCCARD_CFE_IRQPULSE)
573 if (cfe->flags & PCCARD_CFE_IRQLEVEL)
575 if (cfe->flags & PCCARD_CFE_POWERDOWN)
576 printf(" powerdown");
577 if (cfe->flags & PCCARD_CFE_READONLY)
579 if (cfe->flags & PCCARD_CFE_AUDIO)
587 device_printf(dev, "%d errors found while parsing CIS\n",
592 pccard_parse_cis_tuple(struct pccard_tuple *tuple, void *arg)
594 /* most of these are educated guesses */
595 static struct pccard_config_entry init_cfe = {
596 -1, PCCARD_CFE_RDYBSY_ACTIVE | PCCARD_CFE_WP_ACTIVE |
597 PCCARD_CFE_BVD_ACTIVE, PCCARD_IFTYPE_MEMORY,
600 struct cis_state *state = arg;
602 switch (tuple->code) {
603 case PCCARD_CISTPL_END:
604 /* if we've seen a LONGLINK_MFC, and this is the first
605 * END after it, reset the function list.
607 * XXX This might also be the right place to start a
608 * new function, but that assumes that a function
609 * definition never crosses any longlink, and I'm not
610 * sure about that. This is probably safe for MFC
611 * cards, but what we have now isn't broken, so I'd
612 * rather not change it.
614 if (state->gotmfc == 1) {
615 struct pccard_function *pf, *pfnext;
617 for (pf = STAILQ_FIRST(&state->card->pf_head);
618 pf != NULL; pf = pfnext) {
619 pfnext = STAILQ_NEXT(pf, pf_list);
623 STAILQ_INIT(&state->card->pf_head);
630 case PCCARD_CISTPL_LONGLINK_MFC:
632 * this tuple's structure was dealt with in scan_cis. here,
633 * record the fact that the MFC tuple was seen, so that
634 * functions declared before the MFC link can be cleaned
639 #ifdef PCCARDCISDEBUG
640 case PCCARD_CISTPL_DEVICE:
641 case PCCARD_CISTPL_DEVICE_A:
643 u_int reg, dtype, dspeed;
645 reg = pccard_tuple_read_1(tuple, 0);
646 dtype = reg & PCCARD_DTYPE_MASK;
647 dspeed = reg & PCCARD_DSPEED_MASK;
649 DPRINTF(("CISTPL_DEVICE%s type=",
650 (tuple->code == PCCARD_CISTPL_DEVICE) ? "" : "_A"));
652 case PCCARD_DTYPE_NULL:
655 case PCCARD_DTYPE_ROM:
658 case PCCARD_DTYPE_OTPROM:
661 case PCCARD_DTYPE_EPROM:
664 case PCCARD_DTYPE_EEPROM:
667 case PCCARD_DTYPE_FLASH:
670 case PCCARD_DTYPE_SRAM:
673 case PCCARD_DTYPE_DRAM:
676 case PCCARD_DTYPE_FUNCSPEC:
677 DPRINTF(("funcspec"));
679 case PCCARD_DTYPE_EXTEND:
683 DPRINTF(("reserved"));
686 DPRINTF((" speed="));
688 case PCCARD_DSPEED_NULL:
691 case PCCARD_DSPEED_250NS:
694 case PCCARD_DSPEED_200NS:
697 case PCCARD_DSPEED_150NS:
700 case PCCARD_DSPEED_100NS:
703 case PCCARD_DSPEED_EXT:
707 DPRINTF(("reserved"));
714 case PCCARD_CISTPL_VERS_1:
715 if (tuple->length < 6) {
716 DPRINTF(("CISTPL_VERS_1 too short %d\n",
720 int start, i, ch, count;
722 state->card->cis1_major = pccard_tuple_read_1(tuple, 0);
723 state->card->cis1_minor = pccard_tuple_read_1(tuple, 1);
725 for (count = 0, start = 0, i = 0;
726 (count < 4) && ((i + 4) < 256); i++) {
727 ch = pccard_tuple_read_1(tuple, 2 + i);
730 state->card->cis1_info_buf[i] = ch;
732 state->card->cis1_info[count] =
733 state->card->cis1_info_buf + start;
738 DPRINTF(("CISTPL_VERS_1\n"));
741 case PCCARD_CISTPL_MANFID:
742 if (tuple->length < 4) {
743 DPRINTF(("CISTPL_MANFID too short %d\n",
747 state->card->manufacturer = pccard_tuple_read_2(tuple, 0);
748 state->card->product = pccard_tuple_read_2(tuple, 2);
750 * This is for xe driver. But not limited to that driver.
751 * In PC Card Standard,
752 * Manufacturer ID: 2byte.
753 * Product ID: typically 2bytes, but there's no limit on its
754 * size. prodext is a two byte field, so maybe we should
755 * also handle the '6' case. So far no cards have surfaced
756 * with a length of '6'.
758 if (tuple->length == 5 ) {
759 state->card->prodext = pccard_tuple_read_1(tuple, 4);
761 DPRINTF(("CISTPL_MANFID\n"));
763 case PCCARD_CISTPL_FUNCID:
764 if (tuple->length < 1) {
765 DPRINTF(("CISTPL_FUNCID too short %d\n",
769 if ((state->pf == NULL) || (state->gotmfc == 2)) {
770 state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
772 state->pf->number = state->count++;
773 state->pf->last_config_index = -1;
774 STAILQ_INIT(&state->pf->cfe_head);
776 STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf,
779 state->pf->function = pccard_tuple_read_1(tuple, 0);
781 DPRINTF(("CISTPL_FUNCID\n"));
783 case PCCARD_CISTPL_FUNCE:
784 if (state->pf == NULL || state->pf->function <= 0) {
785 DPRINTF(("CISTPL_FUNCE is not followed by "
786 "valid CISTPL_FUNCID\n"));
789 if (tuple->length >= 2) {
790 decode_funce(tuple, state->pf);
792 DPRINTF(("CISTPL_FUNCE\n"));
794 case PCCARD_CISTPL_CONFIG:
795 if (tuple->length < 3) {
796 DPRINTF(("CISTPL_CONFIG too short %d\n",
800 u_int reg, rasz, rmsz, rfsz;
803 reg = pccard_tuple_read_1(tuple, 0);
804 rasz = 1 + ((reg & PCCARD_TPCC_RASZ_MASK) >>
805 PCCARD_TPCC_RASZ_SHIFT);
806 rmsz = 1 + ((reg & PCCARD_TPCC_RMSZ_MASK) >>
807 PCCARD_TPCC_RMSZ_SHIFT);
808 rfsz = ((reg & PCCARD_TPCC_RFSZ_MASK) >>
809 PCCARD_TPCC_RFSZ_SHIFT);
811 if (tuple->length < (rasz + rmsz + rfsz)) {
812 DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too "
813 "short %d\n", rasz, rmsz, rfsz,
817 if (state->pf == NULL) {
818 state->pf = malloc(sizeof(*state->pf),
819 M_DEVBUF, M_NOWAIT | M_ZERO);
820 state->pf->number = state->count++;
821 state->pf->last_config_index = -1;
822 STAILQ_INIT(&state->pf->cfe_head);
824 STAILQ_INSERT_TAIL(&state->card->pf_head,
827 state->pf->function = PCCARD_FUNCTION_UNSPEC;
829 state->pf->last_config_index =
830 pccard_tuple_read_1(tuple, 1);
832 state->pf->ccr_base = 0;
833 for (i = 0; i < rasz; i++)
834 state->pf->ccr_base |=
835 ((pccard_tuple_read_1(tuple, 2 + i)) <<
838 state->pf->ccr_mask = 0;
839 for (i = 0; i < rmsz; i++)
840 state->pf->ccr_mask |=
841 ((pccard_tuple_read_1(tuple,
842 2 + rasz + i)) << (i * 8));
844 /* skip the reserved area and subtuples */
846 /* reset the default cfe for each cfe list */
847 state->temp_cfe = init_cfe;
848 state->default_cfe = &state->temp_cfe;
850 DPRINTF(("CISTPL_CONFIG\n"));
852 case PCCARD_CISTPL_CFTABLE_ENTRY:
856 u_int intface, def, num;
857 u_int power, timing, iospace, irq, memspace, misc;
858 struct pccard_config_entry *cfe;
862 reg = pccard_tuple_read_1(tuple, idx);
864 intface = reg & PCCARD_TPCE_INDX_INTFACE;
865 def = reg & PCCARD_TPCE_INDX_DEFAULT;
866 num = reg & PCCARD_TPCE_INDX_NUM_MASK;
869 * this is a little messy. Some cards have only a
870 * cfentry with the default bit set. So, as we go
871 * through the list, we add new indexes to the queue,
872 * and keep a pointer to the last one with the
873 * default bit set. if we see a record with the same
874 * index, as the default, we stash the default and
875 * replace the queue entry. otherwise, we just add
876 * new entries to the queue, pointing the default ptr
877 * at them if the default bit is set. if we get to
878 * the end with the default pointer pointing at a
879 * record which hasn't had a matching index, that's
880 * ok; it just becomes a cfentry like any other.
884 * if the index in the cis differs from the default
885 * cis, create new entry in the queue and start it
886 * with the current default
888 if (num != state->default_cfe->number) {
889 cfe = (struct pccard_config_entry *)
890 malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
892 *cfe = *state->default_cfe;
894 STAILQ_INSERT_TAIL(&state->pf->cfe_head,
900 * if the default bit is set in the cis, then
901 * point the new default at whatever is being
905 state->default_cfe = cfe;
908 * the cis index matches the default index,
909 * fill in the default cfentry. It is
910 * assumed that the cfdefault index is in the
911 * queue. For it to be otherwise, the cis
912 * index would have to be -1 (initial
913 * condition) which is not possible, or there
914 * would have to be a preceding cis entry
915 * which had the same cis index and had the
916 * default bit unset. Neither condition
917 * should happen. If it does, this cfentry
918 * is lost (written into temp space), which
919 * is an acceptable failure mode.
922 cfe = state->default_cfe;
925 * if the cis entry does not have the default
926 * bit set, copy the default out of the way
930 state->temp_cfe = *state->default_cfe;
931 state->default_cfe = &state->temp_cfe;
936 reg = pccard_tuple_read_1(tuple, idx);
938 cfe->flags &= ~(PCCARD_CFE_MWAIT_REQUIRED
939 | PCCARD_CFE_RDYBSY_ACTIVE
940 | PCCARD_CFE_WP_ACTIVE
941 | PCCARD_CFE_BVD_ACTIVE);
942 if (reg & PCCARD_TPCE_IF_MWAIT)
943 cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED;
944 if (reg & PCCARD_TPCE_IF_RDYBSY)
945 cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE;
946 if (reg & PCCARD_TPCE_IF_WP)
947 cfe->flags |= PCCARD_CFE_WP_ACTIVE;
948 if (reg & PCCARD_TPCE_IF_BVD)
949 cfe->flags |= PCCARD_CFE_BVD_ACTIVE;
950 cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE;
952 reg = pccard_tuple_read_1(tuple, idx);
955 power = reg & PCCARD_TPCE_FS_POWER_MASK;
956 timing = reg & PCCARD_TPCE_FS_TIMING;
957 iospace = reg & PCCARD_TPCE_FS_IOSPACE;
958 irq = reg & PCCARD_TPCE_FS_IRQ;
959 memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK;
960 misc = reg & PCCARD_TPCE_FS_MISC;
963 /* skip over power, don't save */
964 /* for each parameter selection byte */
965 for (i = 0; i < power; i++) {
966 reg = pccard_tuple_read_1(tuple, idx);
969 for (j = 0; j < 7; j++) {
970 /* if the bit is set */
971 if ((reg >> j) & 0x01) {
972 /* skip over bytes */
974 reg2 = pccard_tuple_read_1(tuple, idx);
981 } while (reg2 & 0x80);
987 /* skip over timing, don't save */
988 reg = pccard_tuple_read_1(tuple, idx);
991 if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) !=
992 PCCARD_TPCE_TD_RESERVED_MASK)
994 if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) !=
995 PCCARD_TPCE_TD_RDYBSY_MASK)
997 if ((reg & PCCARD_TPCE_TD_WAIT_MASK) !=
998 PCCARD_TPCE_TD_WAIT_MASK)
1002 if (tuple->length <= idx) {
1003 DPRINTF(("ran out of space before TCPE_IO\n"));
1007 reg = pccard_tuple_read_1(tuple, idx);
1010 ~(PCCARD_CFE_IO8 | PCCARD_CFE_IO16);
1011 if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT)
1012 cfe->flags |= PCCARD_CFE_IO8;
1013 if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT)
1014 cfe->flags |= PCCARD_CFE_IO16;
1016 reg & PCCARD_TPCE_IO_IOADDRLINES_MASK;
1018 if (reg & PCCARD_TPCE_IO_HASRANGE) {
1019 reg = pccard_tuple_read_1(tuple, idx);
1022 cfe->num_iospace = 1 + (reg &
1023 PCCARD_TPCE_IO_RANGE_COUNT);
1025 if (cfe->num_iospace >
1026 (sizeof(cfe->iospace) /
1027 sizeof(cfe->iospace[0]))) {
1028 DPRINTF(("too many io "
1031 state->card->error++;
1034 for (i = 0; i < cfe->num_iospace; i++) {
1035 switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) {
1036 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE:
1037 cfe->iospace[i].start =
1038 pccard_tuple_read_1(tuple, idx);
1041 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO:
1042 cfe->iospace[i].start =
1043 pccard_tuple_read_2(tuple, idx);
1046 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR:
1047 cfe->iospace[i].start =
1048 pccard_tuple_read_4(tuple, idx);
1053 PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
1054 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE:
1055 cfe->iospace[i].length =
1056 pccard_tuple_read_1(tuple, idx);
1059 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO:
1060 cfe->iospace[i].length =
1061 pccard_tuple_read_2(tuple, idx);
1064 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
1065 cfe->iospace[i].length =
1066 pccard_tuple_read_4(tuple, idx);
1070 cfe->iospace[i].length++;
1073 cfe->num_iospace = 1;
1074 cfe->iospace[0].start = 0;
1075 cfe->iospace[0].length =
1080 if (tuple->length <= idx) {
1081 DPRINTF(("ran out of space before TCPE_IR\n"));
1085 reg = pccard_tuple_read_1(tuple, idx);
1087 cfe->flags &= ~(PCCARD_CFE_IRQSHARE
1088 | PCCARD_CFE_IRQPULSE
1089 | PCCARD_CFE_IRQLEVEL);
1090 if (reg & PCCARD_TPCE_IR_SHARE)
1091 cfe->flags |= PCCARD_CFE_IRQSHARE;
1092 if (reg & PCCARD_TPCE_IR_PULSE)
1093 cfe->flags |= PCCARD_CFE_IRQPULSE;
1094 if (reg & PCCARD_TPCE_IR_LEVEL)
1095 cfe->flags |= PCCARD_CFE_IRQLEVEL;
1097 if (reg & PCCARD_TPCE_IR_HASMASK) {
1099 * it's legal to ignore the
1100 * special-interrupt bits, so I will
1104 pccard_tuple_read_2(tuple, idx);
1108 (1 << (reg & PCCARD_TPCE_IR_IRQ));
1112 if (tuple->length <= idx) {
1113 DPRINTF(("ran out of space before TCPE_MS\n"));
1117 if (memspace == PCCARD_TPCE_FS_MEMSPACE_NONE) {
1118 cfe->num_memspace = 0;
1119 } else if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) {
1120 cfe->num_memspace = 1;
1121 cfe->memspace[0].length = 256 *
1122 pccard_tuple_read_2(tuple, idx);
1124 cfe->memspace[0].cardaddr = 0;
1125 cfe->memspace[0].hostaddr = 0;
1126 } else if (memspace ==
1127 PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) {
1128 cfe->num_memspace = 1;
1129 cfe->memspace[0].length = 256 *
1130 pccard_tuple_read_2(tuple, idx);
1132 cfe->memspace[0].cardaddr = 256 *
1133 pccard_tuple_read_2(tuple, idx);
1135 cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
1141 reg = pccard_tuple_read_1(tuple, idx);
1144 cfe->num_memspace = (reg &
1145 PCCARD_TPCE_MS_COUNT) + 1;
1147 if (cfe->num_memspace >
1148 (sizeof(cfe->memspace) /
1149 sizeof(cfe->memspace[0]))) {
1150 DPRINTF(("too many mem "
1152 cfe->num_memspace));
1153 state->card->error++;
1157 ((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >>
1158 PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT);
1160 ((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >>
1161 PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT);
1163 (reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
1165 if (lengthsize == 0) {
1166 DPRINTF(("cfe memspace "
1167 "lengthsize == 0"));
1168 state->card->error++;
1170 for (i = 0; i < cfe->num_memspace; i++) {
1172 cfe->memspace[i].length =
1173 256 * pccard_tuple_read_n(tuple, lengthsize,
1177 cfe->memspace[i].length = 0;
1179 if (cfe->memspace[i].length == 0) {
1180 DPRINTF(("cfe->memspace[%d].length == 0",
1182 state->card->error++;
1185 cfe->memspace[i].cardaddr =
1186 256 * pccard_tuple_read_n(tuple, cardaddrsize,
1188 idx += cardaddrsize;
1190 cfe->memspace[i].cardaddr = 0;
1193 cfe->memspace[i].hostaddr =
1194 256 * pccard_tuple_read_n(tuple, hostaddrsize,
1196 idx += hostaddrsize;
1198 cfe->memspace[i].hostaddr = 0;
1204 if (tuple->length <= idx) {
1205 DPRINTF(("ran out of space before TCPE_MI\n"));
1209 reg = pccard_tuple_read_1(tuple, idx);
1211 cfe->flags &= ~(PCCARD_CFE_POWERDOWN
1212 | PCCARD_CFE_READONLY
1213 | PCCARD_CFE_AUDIO);
1214 if (reg & PCCARD_TPCE_MI_PWRDOWN)
1215 cfe->flags |= PCCARD_CFE_POWERDOWN;
1216 if (reg & PCCARD_TPCE_MI_READONLY)
1217 cfe->flags |= PCCARD_CFE_READONLY;
1218 if (reg & PCCARD_TPCE_MI_AUDIO)
1219 cfe->flags |= PCCARD_CFE_AUDIO;
1220 cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS;
1222 while (reg & PCCARD_TPCE_MI_EXT) {
1223 reg = pccard_tuple_read_1(tuple, idx);
1227 /* skip all the subtuples */
1231 DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
1234 DPRINTF(("unhandled CISTPL %x\n", tuple->code));
1242 decode_funce(struct pccard_tuple *tuple, struct pccard_function *pf)
1244 int type = pccard_tuple_read_1(tuple, 0);
1246 switch (pf->function) {
1247 case PCCARD_FUNCTION_DISK:
1248 if (type == PCCARD_TPLFE_TYPE_DISK_DEVICE_INTERFACE) {
1249 pf->pf_funce_disk_interface
1250 = pccard_tuple_read_1(tuple, 1);
1253 case PCCARD_FUNCTION_NETWORK:
1254 if (type == PCCARD_TPLFE_TYPE_LAN_NID) {
1256 int len = pccard_tuple_read_1(tuple, 1);
1257 if (tuple->length < 2 + len || len > 8) {
1258 /* tuple length not enough or nid too long */
1261 for (i = 0; i < len; i++) {
1262 pf->pf_funce_lan_nid[i]
1263 = pccard_tuple_read_1(tuple, i + 2);
1265 pf->pf_funce_lan_nidlen = len;