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