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