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