pccard_cis.c revision 58581
1/*	$NetBSD: pcmcia_cis.c,v 1.10 1998/12/29 09:03:15 marc Exp $	*/
2/* $FreeBSD: head/sys/dev/pccard/pccard_cis.c 58581 2000-03-26 07:01:52Z imp $ */
3
4/*
5 * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
20 *
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.
31 */
32
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>
40
41#include <sys/bus.h>
42#include <machine/bus.h>
43#include <sys/rman.h>
44#include <machine/resource.h>
45
46#include <dev/pccard/pccardreg.h>
47#include <dev/pccard/pccardchip.h>
48#include <dev/pccard/pccardvar.h>
49
50#ifdef PCCARDCISDEBUG
51int	pccardcis_debug = 0;
52#define	DPRINTF(arg) if (pccardcis_debug) printf arg
53#define	DEVPRINTF(arg) if (pccardcis_debug) device_printf arg
54#else
55#define	DPRINTF(arg)
56#define	DEVPRINTF(arg)
57#endif
58
59#define	PCCARD_CIS_SIZE		1024
60
61struct cis_state {
62	int	count;
63	int	gotmfc;
64	struct pccard_config_entry temp_cfe;
65	struct pccard_config_entry *default_cfe;
66	struct pccard_card *card;
67	struct pccard_function *pf;
68};
69
70int	pccard_parse_cis_tuple(struct pccard_tuple *, void *);
71
72void
73pccard_read_cis(struct pccard_softc *sc)
74{
75	struct cis_state state;
76
77	state.count = 0;
78	state.gotmfc = 0;
79
80	state.card = &sc->card;
81
82	state.card->error = 0;
83	state.card->cis1_major = -1;
84	state.card->cis1_minor = -1;
85	state.card->cis1_info[0] = NULL;
86	state.card->cis1_info[1] = NULL;
87	state.card->cis1_info[2] = NULL;
88	state.card->cis1_info[3] = NULL;
89	state.card->manufacturer = PCCARD_VENDOR_INVALID;
90	state.card->product = PCCARD_PRODUCT_INVALID;
91	STAILQ_INIT(&state.card->pf_head);
92
93	state.pf = NULL;
94
95	if (pccard_scan_cis((struct device *)sc, pccard_parse_cis_tuple,
96	    &state) == -1)
97		state.card->error++;
98}
99
100int
101pccard_scan_cis(device_t dev, int (*fct)(struct pccard_tuple *, void *),
102	void *arg)
103{
104	struct resource *res;
105	int rid;
106	struct pccard_tuple tuple;
107	int longlink_present;
108	int longlink_common;
109	u_long longlink_addr;
110	int mfc_count;
111	int mfc_index;
112	struct {
113		int	common;
114		u_long	addr;
115	} mfc[256 / 5];
116	int ret;
117
118	ret = 0;
119
120	/* allocate some memory */
121
122	rid = 0;
123	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0,
124	    PCCARD_CIS_SIZE, RF_ACTIVE /* | RF_PCCARD_ATTR */);
125	if (res == NULL) {
126#ifdef DIAGNOSTIC
127		device_printf(dev, "can't alloc memory to read attributes\n");
128#endif
129		return -1;
130	}
131	tuple.memt = rman_get_bustag(res);
132	tuple.memh = rman_get_bushandle(res);
133
134	DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
135
136	tuple.mult = 2;
137
138	longlink_present = 1;
139	longlink_common = 1;
140	longlink_addr = 0;
141
142	mfc_count = 0;
143	mfc_index = 0;
144
145	DEVPRINTF((dev, "CIS tuple chain:\n"));
146
147	while (1) {
148		while (1) {
149			/* get the tuple code */
150
151			tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
152
153			/* two special-case tuples */
154
155			if (tuple.code == PCCARD_CISTPL_NULL) {
156				DPRINTF(("CISTPL_NONE\n 00\n"));
157				tuple.ptr++;
158				continue;
159			} else if (tuple.code == PCCARD_CISTPL_END) {
160				DPRINTF(("CISTPL_END\n ff\n"));
161				/* Call the function for the END tuple, since
162				   the CIS semantics depend on it */
163				if ((*fct) (&tuple, arg)) {
164					ret = 1;
165					goto done;
166				}
167				tuple.ptr++;
168				break;
169			}
170			/* now all the normal tuples */
171
172			tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1);
173			switch (tuple.code) {
174			case PCCARD_CISTPL_LONGLINK_A:
175			case PCCARD_CISTPL_LONGLINK_C:
176				if (tuple.length < 4) {
177					DPRINTF(("CISTPL_LONGLINK_%s too "
178					    "short %d\n",
179					    longlink_common ? "C" : "A",
180					    tuple.length));
181					break;
182				}
183				longlink_present = 1;
184				longlink_common = (tuple.code ==
185				    PCCARD_CISTPL_LONGLINK_C) ? 1 : 0;
186				longlink_addr = pccard_tuple_read_4(&tuple, 0);
187				DPRINTF(("CISTPL_LONGLINK_%s %lx\n",
188				    longlink_common ? "C" : "A",
189				    longlink_addr));
190				break;
191			case PCCARD_CISTPL_NO_LINK:
192				longlink_present = 0;
193				DPRINTF(("CISTPL_NO_LINK\n"));
194				break;
195			case PCCARD_CISTPL_CHECKSUM:
196				if (tuple.length < 5) {
197					DPRINTF(("CISTPL_CHECKSUM too "
198					    "short %d\n", tuple.length));
199					break;
200				} {
201					int16_t offset;
202					u_long addr, length;
203					u_int cksum, sum;
204					int i;
205
206					*((u_int16_t *) & offset) =
207					    pccard_tuple_read_2(&tuple, 0);
208					length = pccard_tuple_read_2(&tuple, 2);
209					cksum = pccard_tuple_read_1(&tuple, 4);
210
211					addr = tuple.ptr + offset;
212
213					DPRINTF(("CISTPL_CHECKSUM addr=%lx "
214					    "len=%lx cksum=%x",
215					    addr, length, cksum));
216
217					/*
218					 * XXX do more work to deal with
219					 * distant regions
220					 */
221					if ((addr >= PCCARD_CIS_SIZE) ||
222					    ((addr + length) < 0) ||
223					    ((addr + length) >=
224					      PCCARD_CIS_SIZE)) {
225						DPRINTF((" skipped, "
226						    "too distant\n"));
227						break;
228					}
229					sum = 0;
230					for (i = 0; i < length; i++)
231						sum +=
232						    bus_space_read_1(tuple.memt,
233						    tuple.memh,
234						    addr + tuple.mult * i);
235					if (cksum != (sum & 0xff)) {
236						DPRINTF((" failed sum=%x\n",
237						    sum));
238						device_printf(dev,
239						    "CIS checksum failed\n");
240#if 0
241						/*
242						 * XXX Some working cards have
243						 * XXX bad checksums!!
244						 */
245						ret = -1;
246#endif
247					} else {
248						DPRINTF((" ok\n"));
249					}
250				}
251				break;
252			case PCCARD_CISTPL_LONGLINK_MFC:
253				if (tuple.length < 1) {
254					DPRINTF(("CISTPL_LONGLINK_MFC too "
255					    "short %d\n", tuple.length));
256					break;
257				}
258				/*
259				 * this is kind of ad hoc, as I don't have
260				 * any real documentation
261				 */
262				{
263					int i;
264
265					mfc_count =
266					    pccard_tuple_read_1(&tuple, 0);
267					DPRINTF(("CISTPL_LONGLINK_MFC %d",
268					    mfc_count));
269					for (i = 0; i < mfc_count; i++) {
270						mfc[i].common =
271						    (pccard_tuple_read_1(&tuple,
272						    1 + 5 * i) ==
273						    PCCARD_MFC_MEM_COMMON) ?
274						    1 : 0;
275						mfc[i].addr =
276						    pccard_tuple_read_4(&tuple,
277						    1 + 5 * i + 1);
278						DPRINTF((" %s:%lx",
279						    mfc[i].common ? "common" :
280						    "attr", mfc[i].addr));
281					}
282					DPRINTF(("\n"));
283				}
284				/*
285				 * for LONGLINK_MFC, fall through to the
286				 * function.  This tuple has structural and
287				 * semantic content.
288				 */
289			default:
290				{
291					if ((*fct) (&tuple, arg)) {
292						ret = 1;
293						goto done;
294					}
295				}
296				break;
297			}	/* switch */
298#ifdef PCCARDCISDEBUG
299			/* print the tuple */
300			{
301				int i;
302
303				DPRINTF((" %02x %02x", tuple.code,
304				    tuple.length));
305
306				for (i = 0; i < tuple.length; i++) {
307					DPRINTF((" %02x",
308					    pccard_tuple_read_1(&tuple, i)));
309					if ((i % 16) == 13)
310						DPRINTF(("\n"));
311				}
312				if ((i % 16) != 14)
313					DPRINTF(("\n"));
314			}
315#endif
316			/* skip to the next tuple */
317			tuple.ptr += 2 + tuple.length;
318		}
319
320#ifdef XXX	/* I'm not up to this tonight, need to implement new API */
321		/* to deal with moving windows and such.  At least that's */
322		/* what it appears at this instant */
323
324		/*
325		 * the chain is done.  Clean up and move onto the next one,
326		 * if any.  The loop is here in the case that there is an MFC
327		 * card with no longlink (which defaults to existing, == 0).
328		 * In general, this means that if one pointer fails, it will
329		 * try the next one, instead of just bailing.
330		 */
331
332		while (1) {
333			pccard_chip_mem_unmap(pct, pch, window);
334
335			if (longlink_present) {
336				/*
337				 * if the longlink is to attribute memory,
338				 * then it is unindexed.  That is, if the
339				 * link value is 0x100, then the actual
340				 * memory address is 0x200.  This means that
341				 * we need to multiply by 2 before calling
342				 * mem_map, and then divide the resulting ptr
343				 * by 2 after.
344				 */
345
346				if (!longlink_common)
347					longlink_addr *= 2;
348
349				pccard_chip_mem_map(pct, pch, longlink_common ?
350				    PCCARD_MEM_COMMON : PCCARD_MEM_ATTR,
351				    longlink_addr, PCCARD_CIS_SIZE,
352				    &pcmh, &tuple.ptr, &window);
353
354				if (!longlink_common)
355					tuple.ptr /= 2;
356				DPRINTF(("cis mem map %x\n",
357				    (unsigned int) tuple.memh));
358				tuple.mult = longlink_common ? 1 : 2;
359				longlink_present = 0;
360				longlink_common = 1;
361				longlink_addr = 0;
362			} else if (mfc_count && (mfc_index < mfc_count)) {
363				if (!mfc[mfc_index].common)
364					mfc[mfc_index].addr *= 2;
365
366				pccard_chip_mem_map(pct, pch,
367				    mfc[mfc_index].common ?
368				    PCCARD_MEM_COMMON : PCCARD_MEM_ATTR,
369				    mfc[mfc_index].addr, PCCARD_CIS_SIZE,
370				    &pcmh, &tuple.ptr, &window);
371
372				if (!mfc[mfc_index].common)
373					tuple.ptr /= 2;
374				DPRINTF(("cis mem map %x\n",
375				    (unsigned int) tuple.memh));
376				/* set parse state, and point at the next one */
377
378				tuple.mult = mfc[mfc_index].common ? 1 : 2;
379
380				mfc_index++;
381			} else {
382				goto done;
383			}
384
385			/* make sure that the link is valid */
386			tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
387			if (tuple.code != PCCARD_CISTPL_LINKTARGET) {
388				DPRINTF(("CISTPL_LINKTARGET expected, "
389				    "code %02x observed\n", tuple.code));
390				continue;
391			}
392			tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1);
393			if (tuple.length < 3) {
394				DPRINTF(("CISTPL_LINKTARGET too short %d\n",
395				    tuple.length));
396				continue;
397			}
398			if ((pccard_tuple_read_1(&tuple, 0) != 'C') ||
399			    (pccard_tuple_read_1(&tuple, 1) != 'I') ||
400			    (pccard_tuple_read_1(&tuple, 2) != 'S')) {
401				DPRINTF(("CISTPL_LINKTARGET magic "
402				    "%02x%02x%02x incorrect\n",
403				    pccard_tuple_read_1(&tuple, 0),
404				    pccard_tuple_read_1(&tuple, 1),
405				    pccard_tuple_read_1(&tuple, 2)));
406				continue;
407			}
408			tuple.ptr += 2 + tuple.length;
409
410			break;
411		}
412#endif /* XXX */
413	}
414
415done:
416	bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
417
418	return (ret);
419}
420
421/* XXX this is incredibly verbose.  Not sure what trt is */
422
423void
424pccard_print_cis(device_t dev)
425{
426	struct pccard_softc *sc = (struct pccard_softc *) device_get_softc(dev);
427	struct pccard_card *card = &sc->card;
428	struct pccard_function *pf;
429	struct pccard_config_entry *cfe;
430	int i;
431
432	device_printf(dev, "CIS version ");
433	if (card->cis1_major == 4) {
434		if (card->cis1_minor == 0)
435			printf("PCCARD 1.0\n");
436		else if (card->cis1_minor == 1)
437			printf("PCCARD 2.0 or 2.1\n");
438	} else if (card->cis1_major >= 5)
439		printf("PC Card Standard %d.%d\n", card->cis1_major, card->cis1_minor);
440	else
441		printf("unknown (major=%d, minor=%d)\n",
442		    card->cis1_major, card->cis1_minor);
443
444	device_printf(dev, "CIS info: ");
445	for (i = 0; i < 4; i++) {
446		if (card->cis1_info[i] == NULL)
447			break;
448		if (i)
449			printf(", ");
450		printf("%s", card->cis1_info[i]);
451	}
452	printf("\n");
453
454	device_printf(dev, "Manufacturer code 0x%x, product 0x%x\n",
455	    card->manufacturer, card->product);
456
457	STAILQ_FOREACH(pf, &card->pf_head, pf_list) {
458		device_printf(dev, "function %d: ", pf->number);
459
460		switch (pf->function) {
461		case PCCARD_FUNCTION_UNSPEC:
462			printf("unspecified");
463			break;
464		case PCCARD_FUNCTION_MULTIFUNCTION:
465			printf("multi-function");
466			break;
467		case PCCARD_FUNCTION_MEMORY:
468			printf("memory");
469			break;
470		case PCCARD_FUNCTION_SERIAL:
471			printf("serial port");
472			break;
473		case PCCARD_FUNCTION_PARALLEL:
474			printf("parallel port");
475			break;
476		case PCCARD_FUNCTION_DISK:
477			printf("fixed disk");
478			break;
479		case PCCARD_FUNCTION_VIDEO:
480			printf("video adapter");
481			break;
482		case PCCARD_FUNCTION_NETWORK:
483			printf("network adapter");
484			break;
485		case PCCARD_FUNCTION_AIMS:
486			printf("auto incrementing mass storage");
487			break;
488		case PCCARD_FUNCTION_SCSI:
489			printf("SCSI bridge");
490			break;
491		case PCCARD_FUNCTION_SECURITY:
492			printf("Security services");
493			break;
494		case PCCARD_FUNCTION_INSTRUMENT:
495			printf("Instrument");
496			break;
497		default:
498			printf("unknown (%d)", pf->function);
499			break;
500		}
501
502		printf(", ccr addr %lx mask %lx\n", pf->ccr_base, pf->ccr_mask);
503
504		STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
505			device_printf(dev, "function %d, config table entry "
506			    "%d: ", pf->number, cfe->number);
507
508			switch (cfe->iftype) {
509			case PCCARD_IFTYPE_MEMORY:
510				printf("memory card");
511				break;
512			case PCCARD_IFTYPE_IO:
513				printf("I/O card");
514				break;
515			default:
516				printf("card type unknown");
517				break;
518			}
519
520			printf("; irq mask %x", cfe->irqmask);
521
522			if (cfe->num_iospace) {
523				printf("; iomask %lx, iospace", cfe->iomask);
524
525				for (i = 0; i < cfe->num_iospace; i++) {
526					printf(" %lx", cfe->iospace[i].start);
527					if (cfe->iospace[i].length)
528						printf("-%lx",
529						    cfe->iospace[i].start +
530						    cfe->iospace[i].length - 1);
531				}
532			}
533			if (cfe->num_memspace) {
534				printf("; memspace");
535
536				for (i = 0; i < cfe->num_memspace; i++) {
537					printf(" %lx",
538					    cfe->memspace[i].cardaddr);
539					if (cfe->memspace[i].length)
540						printf("-%lx",
541						    cfe->memspace[i].cardaddr +
542						    cfe->memspace[i].length - 1);
543					if (cfe->memspace[i].hostaddr)
544						printf("@%lx",
545						    cfe->memspace[i].hostaddr);
546				}
547			}
548			if (cfe->maxtwins)
549				printf("; maxtwins %d", cfe->maxtwins);
550
551			printf(";");
552
553			if (cfe->flags & PCCARD_CFE_MWAIT_REQUIRED)
554				printf(" mwait_required");
555			if (cfe->flags & PCCARD_CFE_RDYBSY_ACTIVE)
556				printf(" rdybsy_active");
557			if (cfe->flags & PCCARD_CFE_WP_ACTIVE)
558				printf(" wp_active");
559			if (cfe->flags & PCCARD_CFE_BVD_ACTIVE)
560				printf(" bvd_active");
561			if (cfe->flags & PCCARD_CFE_IO8)
562				printf(" io8");
563			if (cfe->flags & PCCARD_CFE_IO16)
564				printf(" io16");
565			if (cfe->flags & PCCARD_CFE_IRQSHARE)
566				printf(" irqshare");
567			if (cfe->flags & PCCARD_CFE_IRQPULSE)
568				printf(" irqpulse");
569			if (cfe->flags & PCCARD_CFE_IRQLEVEL)
570				printf(" irqlevel");
571			if (cfe->flags & PCCARD_CFE_POWERDOWN)
572				printf(" powerdown");
573			if (cfe->flags & PCCARD_CFE_READONLY)
574				printf(" readonly");
575			if (cfe->flags & PCCARD_CFE_AUDIO)
576				printf(" audio");
577
578			printf("\n");
579		}
580	}
581
582	if (card->error)
583		device_printf(dev, "%d errors found while parsing CIS\n",
584		    card->error);
585}
586
587int
588pccard_parse_cis_tuple(struct pccard_tuple *tuple, void *arg)
589{
590	/* most of these are educated guesses */
591	static struct pccard_config_entry init_cfe = {
592		-1, PCCARD_CFE_RDYBSY_ACTIVE | PCCARD_CFE_WP_ACTIVE |
593		PCCARD_CFE_BVD_ACTIVE, PCCARD_IFTYPE_MEMORY,
594	};
595
596	struct cis_state *state = arg;
597
598	switch (tuple->code) {
599	case PCCARD_CISTPL_END:
600		/* if we've seen a LONGLINK_MFC, and this is the first
601		 * END after it, reset the function list.
602		 *
603		 * XXX This might also be the right place to start a
604		 * new function, but that assumes that a function
605		 * definition never crosses any longlink, and I'm not
606		 * sure about that.  This is probably safe for MFC
607		 * cards, but what we have now isn't broken, so I'd
608		 * rather not change it.
609		 */
610		if (state->gotmfc == 1) {
611			struct pccard_function *pf, *pfnext;
612
613			for (pf = STAILQ_FIRST(&state->card->pf_head);
614			     pf != NULL; pf = pfnext) {
615				pfnext = STAILQ_NEXT(pf, pf_list);
616				free(pf, M_DEVBUF);
617			}
618
619			STAILQ_INIT(&state->card->pf_head);
620
621			state->count = 0;
622			state->gotmfc = 2;
623			state->pf = NULL;
624		}
625		break;
626	case PCCARD_CISTPL_LONGLINK_MFC:
627		/*
628		 * this tuple's structure was dealt with in scan_cis.  here,
629		 * record the fact that the MFC tuple was seen, so that
630		 * functions declared before the MFC link can be cleaned
631		 * up.
632		 */
633		state->gotmfc = 1;
634		break;
635#ifdef PCCARDCISDEBUG
636	case PCCARD_CISTPL_DEVICE:
637	case PCCARD_CISTPL_DEVICE_A:
638		{
639			u_int reg, dtype, dspeed;
640
641			reg = pccard_tuple_read_1(tuple, 0);
642			dtype = reg & PCCARD_DTYPE_MASK;
643			dspeed = reg & PCCARD_DSPEED_MASK;
644
645			DPRINTF(("CISTPL_DEVICE%s type=",
646			(tuple->code == PCCARD_CISTPL_DEVICE) ? "" : "_A"));
647			switch (dtype) {
648			case PCCARD_DTYPE_NULL:
649				DPRINTF(("null"));
650				break;
651			case PCCARD_DTYPE_ROM:
652				DPRINTF(("rom"));
653				break;
654			case PCCARD_DTYPE_OTPROM:
655				DPRINTF(("otprom"));
656				break;
657			case PCCARD_DTYPE_EPROM:
658				DPRINTF(("eprom"));
659				break;
660			case PCCARD_DTYPE_EEPROM:
661				DPRINTF(("eeprom"));
662				break;
663			case PCCARD_DTYPE_FLASH:
664				DPRINTF(("flash"));
665				break;
666			case PCCARD_DTYPE_SRAM:
667				DPRINTF(("sram"));
668				break;
669			case PCCARD_DTYPE_DRAM:
670				DPRINTF(("dram"));
671				break;
672			case PCCARD_DTYPE_FUNCSPEC:
673				DPRINTF(("funcspec"));
674				break;
675			case PCCARD_DTYPE_EXTEND:
676				DPRINTF(("extend"));
677				break;
678			default:
679				DPRINTF(("reserved"));
680				break;
681			}
682			DPRINTF((" speed="));
683			switch (dspeed) {
684			case PCCARD_DSPEED_NULL:
685				DPRINTF(("null"));
686				break;
687			case PCCARD_DSPEED_250NS:
688				DPRINTF(("250ns"));
689				break;
690			case PCCARD_DSPEED_200NS:
691				DPRINTF(("200ns"));
692				break;
693			case PCCARD_DSPEED_150NS:
694				DPRINTF(("150ns"));
695				break;
696			case PCCARD_DSPEED_100NS:
697				DPRINTF(("100ns"));
698				break;
699			case PCCARD_DSPEED_EXT:
700				DPRINTF(("ext"));
701				break;
702			default:
703				DPRINTF(("reserved"));
704				break;
705			}
706		}
707		DPRINTF(("\n"));
708		break;
709#endif
710	case PCCARD_CISTPL_VERS_1:
711		if (tuple->length < 6) {
712			DPRINTF(("CISTPL_VERS_1 too short %d\n",
713			    tuple->length));
714			break;
715		} {
716			int start, i, ch, count;
717
718			state->card->cis1_major = pccard_tuple_read_1(tuple, 0);
719			state->card->cis1_minor = pccard_tuple_read_1(tuple, 1);
720
721			for (count = 0, start = 0, i = 0;
722			    (count < 4) && ((i + 4) < 256); i++) {
723				ch = pccard_tuple_read_1(tuple, 2 + i);
724				if (ch == 0xff)
725					break;
726				state->card->cis1_info_buf[i] = ch;
727				if (ch == 0) {
728					state->card->cis1_info[count] =
729					    state->card->cis1_info_buf + start;
730					start = i + 1;
731					count++;
732				}
733			}
734			DPRINTF(("CISTPL_VERS_1\n"));
735		}
736		break;
737	case PCCARD_CISTPL_MANFID:
738		if (tuple->length < 4) {
739			DPRINTF(("CISTPL_MANFID too short %d\n",
740			    tuple->length));
741			break;
742		}
743		state->card->manufacturer = pccard_tuple_read_2(tuple, 0);
744		state->card->product = pccard_tuple_read_2(tuple, 2);
745		DPRINTF(("CISTPL_MANFID\n"));
746		break;
747	case PCCARD_CISTPL_FUNCID:
748		if (tuple->length < 1) {
749			DPRINTF(("CISTPL_FUNCID too short %d\n",
750			    tuple->length));
751			break;
752		}
753		if ((state->pf == NULL) || (state->gotmfc == 2)) {
754			state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
755			    M_NOWAIT);
756			bzero(state->pf, sizeof(*state->pf));
757			state->pf->number = state->count++;
758			state->pf->last_config_index = -1;
759			STAILQ_INIT(&state->pf->cfe_head);
760
761			STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf,
762			    pf_list);
763		}
764		state->pf->function = pccard_tuple_read_1(tuple, 0);
765
766		DPRINTF(("CISTPL_FUNCID\n"));
767		break;
768	case PCCARD_CISTPL_CONFIG:
769		if (tuple->length < 3) {
770			DPRINTF(("CISTPL_CONFIG too short %d\n",
771			    tuple->length));
772			break;
773		} {
774			u_int reg, rasz, rmsz, rfsz;
775			int i;
776
777			reg = pccard_tuple_read_1(tuple, 0);
778			rasz = 1 + ((reg & PCCARD_TPCC_RASZ_MASK) >>
779			    PCCARD_TPCC_RASZ_SHIFT);
780			rmsz = 1 + ((reg & PCCARD_TPCC_RMSZ_MASK) >>
781			    PCCARD_TPCC_RMSZ_SHIFT);
782			rfsz = ((reg & PCCARD_TPCC_RFSZ_MASK) >>
783			    PCCARD_TPCC_RFSZ_SHIFT);
784
785			if (tuple->length < (rasz + rmsz + rfsz)) {
786				DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too "
787				    "short %d\n", rasz, rmsz, rfsz,
788				    tuple->length));
789				break;
790			}
791			if (state->pf == NULL) {
792				state->pf = malloc(sizeof(*state->pf),
793				    M_DEVBUF, M_NOWAIT);
794				bzero(state->pf, sizeof(*state->pf));
795				state->pf->number = state->count++;
796				state->pf->last_config_index = -1;
797				STAILQ_INIT(&state->pf->cfe_head);
798
799				STAILQ_INSERT_TAIL(&state->card->pf_head,
800				    state->pf, pf_list);
801
802				state->pf->function = PCCARD_FUNCTION_UNSPEC;
803			}
804			state->pf->last_config_index =
805			    pccard_tuple_read_1(tuple, 1);
806
807			state->pf->ccr_base = 0;
808			for (i = 0; i < rasz; i++)
809				state->pf->ccr_base |=
810				    ((pccard_tuple_read_1(tuple, 2 + i)) <<
811				    (i * 8));
812
813			state->pf->ccr_mask = 0;
814			for (i = 0; i < rmsz; i++)
815				state->pf->ccr_mask |=
816				    ((pccard_tuple_read_1(tuple,
817				    2 + rasz + i)) << (i * 8));
818
819			/* skip the reserved area and subtuples */
820
821			/* reset the default cfe for each cfe list */
822			state->temp_cfe = init_cfe;
823			state->default_cfe = &state->temp_cfe;
824		}
825		DPRINTF(("CISTPL_CONFIG\n"));
826		break;
827	case PCCARD_CISTPL_CFTABLE_ENTRY:
828		{
829			int idx, i, j;
830			u_int reg, reg2;
831			u_int intface, def, num;
832			u_int power, timing, iospace, irq, memspace, misc;
833			struct pccard_config_entry *cfe;
834
835			idx = 0;
836
837			reg = pccard_tuple_read_1(tuple, idx);
838			idx++;
839			intface = reg & PCCARD_TPCE_INDX_INTFACE;
840			def = reg & PCCARD_TPCE_INDX_DEFAULT;
841			num = reg & PCCARD_TPCE_INDX_NUM_MASK;
842
843			/*
844			 * this is a little messy.  Some cards have only a
845			 * cfentry with the default bit set.  So, as we go
846			 * through the list, we add new indexes to the queue,
847			 * and keep a pointer to the last one with the
848			 * default bit set.  if we see a record with the same
849			 * index, as the default, we stash the default and
850			 * replace the queue entry. otherwise, we just add
851			 * new entries to the queue, pointing the default ptr
852			 * at them if the default bit is set.  if we get to
853			 * the end with the default pointer pointing at a
854			 * record which hasn't had a matching index, that's
855			 * ok; it just becomes a cfentry like any other.
856			 */
857
858			/*
859			 * if the index in the cis differs from the default
860			 * cis, create new entry in the queue and start it
861			 * with the current default
862			 */
863			if (num != state->default_cfe->number) {
864				cfe = (struct pccard_config_entry *)
865				    malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
866
867				*cfe = *state->default_cfe;
868
869				STAILQ_INSERT_TAIL(&state->pf->cfe_head,
870				    cfe, cfe_list);
871
872				cfe->number = num;
873
874				/*
875				 * if the default bit is set in the cis, then
876				 * point the new default at whatever is being
877				 * filled in
878				 */
879				if (def)
880					state->default_cfe = cfe;
881			} else {
882				/*
883				 * the cis index matches the default index,
884				 * fill in the default cfentry.  It is
885				 * assumed that the cfdefault index is in the
886				 * queue.  For it to be otherwise, the cis
887				 * index would have to be -1 (initial
888				 * condition) which is not possible, or there
889				 * would have to be a preceding cis entry
890				 * which had the same cis index and had the
891				 * default bit unset. Neither condition
892				 * should happen.  If it does, this cfentry
893				 * is lost (written into temp space), which
894				 * is an acceptable failure mode.
895				 */
896
897				cfe = state->default_cfe;
898
899				/*
900				 * if the cis entry does not have the default
901				 * bit set, copy the default out of the way
902				 * first.
903				 */
904				if (!def) {
905					state->temp_cfe = *state->default_cfe;
906					state->default_cfe = &state->temp_cfe;
907				}
908			}
909
910			if (intface) {
911				reg = pccard_tuple_read_1(tuple, idx);
912				idx++;
913				if (reg & PCCARD_TPCE_IF_MWAIT)
914					cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED;
915				if (reg & PCCARD_TPCE_IF_RDYBSY)
916					cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE;
917				if (reg & PCCARD_TPCE_IF_WP)
918					cfe->flags |= PCCARD_CFE_WP_ACTIVE;
919				if (reg & PCCARD_TPCE_IF_BVD)
920					cfe->flags |= PCCARD_CFE_BVD_ACTIVE;
921				cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE;
922			}
923			reg = pccard_tuple_read_1(tuple, idx);
924			idx++;
925
926			power = reg & PCCARD_TPCE_FS_POWER_MASK;
927			timing = reg & PCCARD_TPCE_FS_TIMING;
928			iospace = reg & PCCARD_TPCE_FS_IOSPACE;
929			irq = reg & PCCARD_TPCE_FS_IRQ;
930			memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK;
931			misc = reg & PCCARD_TPCE_FS_MISC;
932
933			if (power) {
934				/* skip over power, don't save */
935				/* for each parameter selection byte */
936				for (i = 0; i < power; i++) {
937					reg = pccard_tuple_read_1(tuple, idx);
938					idx++;
939					/* for each bit */
940					for (j = 0; j < 7; j++) {
941						/* if the bit is set */
942						if ((reg >> j) & 0x01) {
943							/* skip over bytes */
944							do {
945								reg2 = pccard_tuple_read_1(tuple, idx);
946								idx++;
947								/*
948								 * until
949								 * non-extensi
950								 * on byte
951								 */
952							} while (reg2 & 0x80);
953						}
954					}
955				}
956			}
957			if (timing) {
958				/* skip over timing, don't save */
959				reg = pccard_tuple_read_1(tuple, idx);
960				idx++;
961
962				if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) !=
963				    PCCARD_TPCE_TD_RESERVED_MASK)
964					idx++;
965				if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) !=
966				    PCCARD_TPCE_TD_RDYBSY_MASK)
967					idx++;
968				if ((reg & PCCARD_TPCE_TD_WAIT_MASK) !=
969				    PCCARD_TPCE_TD_WAIT_MASK)
970					idx++;
971			}
972			if (iospace) {
973				if (tuple->length <= idx) {
974					DPRINTF(("ran out of space before TCPE_IO\n"));
975					goto abort_cfe;
976				}
977
978				reg = pccard_tuple_read_1(tuple, idx);
979				idx++;
980
981				if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT)
982					cfe->flags |= PCCARD_CFE_IO8;
983				if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT)
984					cfe->flags |= PCCARD_CFE_IO16;
985				cfe->iomask =
986				    reg & PCCARD_TPCE_IO_IOADDRLINES_MASK;
987
988				if (reg & PCCARD_TPCE_IO_HASRANGE) {
989					reg = pccard_tuple_read_1(tuple, idx);
990					idx++;
991
992					cfe->num_iospace = 1 + (reg &
993					    PCCARD_TPCE_IO_RANGE_COUNT);
994
995					if (cfe->num_iospace >
996					    (sizeof(cfe->iospace) /
997					     sizeof(cfe->iospace[0]))) {
998						DPRINTF(("too many io "
999						    "spaces %d",
1000						    cfe->num_iospace));
1001						state->card->error++;
1002						break;
1003					}
1004					for (i = 0; i < cfe->num_iospace; i++) {
1005						switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) {
1006						case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE:
1007							cfe->iospace[i].start =
1008								pccard_tuple_read_1(tuple, idx);
1009							idx++;
1010							break;
1011						case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO:
1012							cfe->iospace[i].start =
1013								pccard_tuple_read_2(tuple, idx);
1014							idx += 2;
1015							break;
1016						case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR:
1017							cfe->iospace[i].start =
1018								pccard_tuple_read_4(tuple, idx);
1019							idx += 4;
1020							break;
1021						}
1022						switch (reg &
1023							PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
1024						case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE:
1025							cfe->iospace[i].length =
1026								pccard_tuple_read_1(tuple, idx);
1027							idx++;
1028							break;
1029						case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO:
1030							cfe->iospace[i].length =
1031								pccard_tuple_read_2(tuple, idx);
1032							idx += 2;
1033							break;
1034						case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
1035							cfe->iospace[i].length =
1036								pccard_tuple_read_4(tuple, idx);
1037							idx += 4;
1038							break;
1039						}
1040						cfe->iospace[i].length++;
1041					}
1042				} else {
1043					cfe->num_iospace = 1;
1044					cfe->iospace[0].start = 0;
1045					cfe->iospace[0].length =
1046					    (1 << cfe->iomask);
1047				}
1048			}
1049			if (irq) {
1050				if (tuple->length <= idx) {
1051					DPRINTF(("ran out of space before TCPE_IR\n"));
1052					goto abort_cfe;
1053				}
1054
1055				reg = pccard_tuple_read_1(tuple, idx);
1056				idx++;
1057
1058				if (reg & PCCARD_TPCE_IR_SHARE)
1059					cfe->flags |= PCCARD_CFE_IRQSHARE;
1060				if (reg & PCCARD_TPCE_IR_PULSE)
1061					cfe->flags |= PCCARD_CFE_IRQPULSE;
1062				if (reg & PCCARD_TPCE_IR_LEVEL)
1063					cfe->flags |= PCCARD_CFE_IRQLEVEL;
1064
1065				if (reg & PCCARD_TPCE_IR_HASMASK) {
1066					/*
1067					 * it's legal to ignore the
1068					 * special-interrupt bits, so I will
1069					 */
1070
1071					cfe->irqmask =
1072					    pccard_tuple_read_2(tuple, idx);
1073					idx += 2;
1074				} else {
1075					cfe->irqmask =
1076					    (1 << (reg & PCCARD_TPCE_IR_IRQ));
1077				}
1078			}
1079			if (memspace) {
1080				if (tuple->length <= idx) {
1081					DPRINTF(("ran out of space before TCPE_MS\n"));
1082					goto abort_cfe;
1083				}
1084
1085				if (memspace == PCCARD_TPCE_FS_MEMSPACE_NONE) {
1086					cfe->num_memspace = 0;
1087				} else if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) {
1088					cfe->num_memspace = 1;
1089					cfe->memspace[0].length = 256 *
1090					    pccard_tuple_read_2(tuple, idx);
1091					idx += 2;
1092					cfe->memspace[0].cardaddr = 0;
1093					cfe->memspace[0].hostaddr = 0;
1094				} else if (memspace ==
1095				    PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) {
1096					cfe->num_memspace = 1;
1097					cfe->memspace[0].length = 256 *
1098					    pccard_tuple_read_2(tuple, idx);
1099					idx += 2;
1100					cfe->memspace[0].cardaddr = 256 *
1101					    pccard_tuple_read_2(tuple, idx);
1102					idx += 2;
1103					cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
1104				} else {
1105					int lengthsize;
1106					int cardaddrsize;
1107					int hostaddrsize;
1108
1109					reg = pccard_tuple_read_1(tuple, idx);
1110					idx++;
1111
1112					cfe->num_memspace = (reg &
1113					    PCCARD_TPCE_MS_COUNT) + 1;
1114
1115					if (cfe->num_memspace >
1116					    (sizeof(cfe->memspace) /
1117					     sizeof(cfe->memspace[0]))) {
1118						DPRINTF(("too many mem "
1119						    "spaces %d",
1120						    cfe->num_memspace));
1121						state->card->error++;
1122						break;
1123					}
1124					lengthsize =
1125						((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >>
1126						 PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT);
1127					cardaddrsize =
1128						((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >>
1129						 PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT);
1130					hostaddrsize =
1131						(reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
1132
1133					if (lengthsize == 0) {
1134						DPRINTF(("cfe memspace "
1135						    "lengthsize == 0"));
1136						state->card->error++;
1137					}
1138					for (i = 0; i < cfe->num_memspace; i++) {
1139						if (lengthsize) {
1140							cfe->memspace[i].length =
1141								256 * pccard_tuple_read_n(tuple, lengthsize,
1142								       idx);
1143							idx += lengthsize;
1144						} else {
1145							cfe->memspace[i].length = 0;
1146						}
1147						if (cfe->memspace[i].length == 0) {
1148							DPRINTF(("cfe->memspace[%d].length == 0",
1149								 i));
1150							state->card->error++;
1151						}
1152						if (cardaddrsize) {
1153							cfe->memspace[i].cardaddr =
1154								256 * pccard_tuple_read_n(tuple, cardaddrsize,
1155								       idx);
1156							idx += cardaddrsize;
1157						} else {
1158							cfe->memspace[i].cardaddr = 0;
1159						}
1160						if (hostaddrsize) {
1161							cfe->memspace[i].hostaddr =
1162								256 * pccard_tuple_read_n(tuple, hostaddrsize,
1163								       idx);
1164							idx += hostaddrsize;
1165						} else {
1166							cfe->memspace[i].hostaddr = 0;
1167						}
1168					}
1169				}
1170			}
1171			if (misc) {
1172				if (tuple->length <= idx) {
1173					DPRINTF(("ran out of space before TCPE_MI\n"));
1174					goto abort_cfe;
1175				}
1176
1177				reg = pccard_tuple_read_1(tuple, idx);
1178				idx++;
1179
1180				if (reg & PCCARD_TPCE_MI_PWRDOWN)
1181					cfe->flags = PCCARD_CFE_POWERDOWN;
1182				if (reg & PCCARD_TPCE_MI_READONLY)
1183					cfe->flags = PCCARD_CFE_READONLY;
1184				if (reg & PCCARD_TPCE_MI_AUDIO)
1185					cfe->flags = PCCARD_CFE_AUDIO;
1186				cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS;
1187
1188				while (reg & PCCARD_TPCE_MI_EXT) {
1189					reg = pccard_tuple_read_1(tuple, idx);
1190					idx++;
1191				}
1192			}
1193			/* skip all the subtuples */
1194		}
1195
1196	abort_cfe:
1197		DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
1198		break;
1199	default:
1200		DPRINTF(("unhandled CISTPL %x\n", tuple->code));
1201		break;
1202	}
1203
1204	return (0);
1205}
1206