xref: /titanic_52/usr/src/uts/common/pcmcia/cis/cis_handlers.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * This file contains the tuple handlers that are called by the CIS
31  *	parser.
32  *
33  * XXX - how about a better explaination??
34  */
35 
36 #include <sys/types.h>
37 #include <sys/systm.h>
38 #include <sys/user.h>
39 #include <sys/buf.h>
40 #include <sys/file.h>
41 #include <sys/uio.h>
42 #include <sys/conf.h>
43 #include <sys/stat.h>
44 #include <sys/autoconf.h>
45 #include <sys/vtoc.h>
46 #include <sys/dkio.h>
47 #include <sys/ddi.h>
48 #include <sys/sunddi.h>
49 #include <sys/debug.h>
50 #include <sys/ddi_impldefs.h>
51 #include <sys/kstat.h>
52 #include <sys/kmem.h>
53 #include <sys/modctl.h>
54 #include <sys/kobj.h>
55 #include <sys/callb.h>
56 
57 #include <sys/pctypes.h>
58 #include <pcmcia/sys/cs_types.h>
59 #include <pcmcia/sys/cis.h>
60 #include <pcmcia/sys/cis_handlers.h>
61 #include <pcmcia/sys/cs.h>
62 #include <pcmcia/sys/cs_priv.h>
63 #include <pcmcia/sys/cis_protos.h>
64 
65 /*
66  * Function prototypes
67  */
68 static void cistpl_pd_parse(cistpl_t *, cistpl_cftable_entry_pwr_t *);
69 static void cis_return_name(cistpl_callout_t *, cistpl_get_tuple_name_t *);
70 
71 /*
72  * cis_tuple_handler - call the handler for the tuple described by the
73  *				tuple pointer
74  *
75  *	cistpl_callout_t *co - pointer to callout structure
76  *				array to use to find this tuple
77  *	cistpl_t *tp - pointer to a tuple structure
78  *	int flags - action for the handler to perform
79  * XXX - we need a description of the flags passed to the tuple handler
80  *	void *arg - argument to pass on to tuple handler
81  *
82  * If the tuple is not recognized but is is a vendor-specific tuple, we
83  *	set the CISTPLF_VENDOR_SPECIFIC flag in the tuple.
84  *
85  * We return CISTPLF_UNKNOWN if this is an unrecognized	tuple as well as
86  *	set the CISTPLF_UNKNOWN flag in the tuple list structure.  Note
87  *	that encountering an unknown tuple is not necessarily an error,
88  *	so we don't set the HANDTPL_ERROR flag on the return code.  It
89  *	is up to the caller to determine what an unrecognized tuple means.
90  *
91  * If this is a recognized tuple, the apropriate tuple handler is called and
92  *	the return value from the handler is returned directly to the caller.
93  *
94  * The void *arg is optional, and it's meaning is dependent on the
95  *	particular tuple handler called and the flags parameter.
96  *
97  * For the special case of HANDTPL_RETURN_NAME, we don't bother calling the
98  *	tuple handler and just return the tuple name to the caller.
99  */
100 uint32_t
101 cis_tuple_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
102 					void *arg, cisdata_t subtype)
103 {
104 	/*
105 	 * Check to see if this is a vendor-specific tuple.
106 	 */
107 	if (CISTPL_IS_VENDOR_SPECIFIC(tp->type))
108 	    tp->flags |= CISTPLF_VENDOR_SPECIFIC;
109 
110 	/*
111 	 * Scan the callout list until we find the tuple passed to us, or we
112 	 *	encounter a CISTPL_END in the callout list, which signals that
113 	 *	there are no more tuples in the callout list.
114 	 */
115 	while (co->type != (cisdata_t)CISTPL_END) {
116 	    if (co->type == tp->type &&
117 		((tp->type != CISTPL_FUNCE) ||
118 		    (tp->type == CISTPL_FUNCE && co->subtype == subtype))) {
119 			tp->flags &= ~CISTPLF_UNKNOWN;
120 			if (flags & HANDTPL_RETURN_NAME) {
121 			    cis_return_name(co, (cistpl_get_tuple_name_t *)arg);
122 			    return (CISTPLF_NOERROR);
123 			} else {
124 			    return ((*co->handler) (co, tp, flags, arg));
125 			} /* HANDTPL_RETURN_NAME */
126 	    } /* if */
127 	    co++;
128 	} /* while */
129 
130 	/*
131 	 * If we didn't recognize the tuple and the caller wants the tuple
132 	 *	name back, then return the "unknown tuple" string. At this
133 	 *	point, "co" will be pointing to the last entry in the
134 	 *	callout list. It's not an error to not recognize the tuple
135 	 *	when the operation is HANDTPL_RETURN_NAME.
136 	 */
137 	if (flags & HANDTPL_RETURN_NAME) {
138 	    cis_return_name(co, (cistpl_get_tuple_name_t *)arg);
139 	    return (CISTPLF_NOERROR);
140 	}
141 
142 	tp->flags |= CISTPLF_UNKNOWN;
143 	return (CISTPLF_UNKNOWN);
144 }
145 
146 /*
147  * cis_no_tuple_handler - this generic tuple handler is used if no special
148  *				tuple processing is required for the passed
149  *				tuple
150  *
151  *	cistpl_callout_t *co - pointer to this tuple's entry in the
152  *				tuple callout structure
153  *	cistpl_t *tp - pointer to this tuple's entry in the local linked list
154  *	int flags - action to perform
155  *
156  * This handler will set the CISTPLF_COPYOK flag if the tuple link is greater
157  *	than zero, indicating that it's OK to copy the tuple data body. It
158  *	will also set whatever flags are specified in the callout structure.
159  *
160  * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE.
161  *
162  * We return CISTPLF_UNKNOWN if we're being called to parse the tuple.
163  *
164  * We return CISTPLF_NOERROR in every other case to indicate that this is a
165  *	recognized tuple.
166  */
167 /*ARGSUSED*/
168 uint32_t
169 cis_no_tuple_handler(cistpl_callout_t *co, cistpl_t *tp,
170 					uint32_t flags, void *arg)
171 {
172 	if (flags & HANDTPL_SET_FLAGS) {
173 		tp->flags |= co->flags;	/* XXX - is = the right thing here? */
174 		if (tp->len > 0)
175 			tp->flags |= CISTPLF_COPYOK;
176 	}
177 
178 	if (flags & HANDTPL_COPY_DONE)
179 		tp->flags |= CISTPLF_VALID;
180 
181 	if (flags & HANDTPL_PARSE_LTUPLE)
182 	    return (CISTPLF_UNKNOWN);
183 
184 	return (CISTPLF_NOERROR);
185 }
186 
187 /*
188  * cis_unknown_tuple_handler - this generic tuple handler is used if we don't
189  *				understand this tuple
190  *
191  *	cistpl_callout_t *co - pointer to this tuple's entry in the
192  *				tuple callout structure
193  *	cistpl_t *tp - pointer to this tuple's entry in the local linked list
194  *	int flags - action to perform
195  *
196  * This handler will not set the CISTPLF_COPYOK flag since we don't know the
197  *	contents of a vendor-specific tuple.
198  *
199  * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE
200  *	to specify that we understand this tuple's code, but not it's data
201  *	body.
202  *
203  * We return CISTPLF_UNKNOWN if we're being called to parse the tuple or to
204  *	perform any other operation.
205  */
206 /*ARGSUSED*/
207 uint32_t
208 cis_unknown_tuple_handler(cistpl_callout_t *co, cistpl_t *tp,
209 					uint32_t flags, void *arg)
210 {
211 	if (flags & HANDTPL_SET_FLAGS) {
212 		tp->flags |= co->flags;	/* XXX - is = the right thing here? */
213 		return (CISTPLF_NOERROR);
214 	}
215 
216 	if (flags & HANDTPL_COPY_DONE) {
217 		tp->flags |= CISTPLF_VALID;
218 		return (CISTPLF_NOERROR);
219 	}
220 
221 	return (CISTPLF_UNKNOWN);
222 }
223 
224 /*
225  * cistpl_vers_1_handler - handler for the CISTPL_VERS_1 tuple
226  *
227  *	void *arg - points to a cistpl_vers_1_t * where the
228  *			information is stuffed into
229  */
230 uint32_t
231 cistpl_vers_1_handler(cistpl_callout_t *co, cistpl_t *tp,
232 					uint32_t flags, void *arg)
233 {
234 	/*
235 	 * nothing special about our flags, so just call the
236 	 *	generic handler for this
237 	 */
238 	if (flags & HANDTPL_SET_FLAGS)
239 		return (cis_no_tuple_handler(co, tp, flags, arg));
240 
241 	/*
242 	 * We don't currently validate this tuple. This call will
243 	 *	always set tp->flags |= CISTPLF_VALID.
244 	 */
245 	if (flags & HANDTPL_COPY_DONE)
246 		return (cis_no_tuple_handler(co, tp, flags, arg));
247 
248 	if (flags & HANDTPL_PARSE_LTUPLE) {
249 		cistpl_vers_1_t *cs = (cistpl_vers_1_t *)arg;
250 
251 
252 		RESET_TP(tp);
253 
254 		cs->major = GET_BYTE(tp);
255 		cs->minor = GET_BYTE(tp);
256 		for (cs->ns = 0; GET_LEN(tp) > 0 &&
257 				/* CSTYLED */
258 				cs->ns < CISTPL_VERS_1_MAX_PROD_STRINGS; ) {
259 			(void) strcpy(cs->pi[cs->ns++], cis_getstr(tp));
260 		} /* for */
261 	} /* HANDTPL_PARSE_LTUPLE */
262 
263 	return (CISTPLF_NOERROR);
264 }
265 
266 /*
267  * cistpl_config_handler - handler for the CISTPL_CONFIG tuple
268  *
269  *	void *arg - points to a XXX where the information is stuffed into
270  *
271  * For the first ten config registers we set the present flags in the
272  *	cistpl_config_t if the register exists.  The flags that we use
273  *	for this are the same as the flags reguired for the Card Services
274  *	RequestConfiguration function and they can be used by clients
275  *	directly without requiring any remapping of values.
276  *
277  * XXX we don't handle TPCC_SBTPL subtuples yet
278  */
279 
280 uint32_t	config_regs_present_map[] = {
281 	CONFIG_OPTION_REG_PRESENT,	/* COR present */
282 	CONFIG_STATUS_REG_PRESENT,	/* STAT reg present */
283 	CONFIG_PINREPL_REG_PRESENT,	/* PRR present */
284 	CONFIG_COPY_REG_PRESENT,	/* COPY reg present */
285 	CONFIG_EXSTAT_REG_PRESENT,	/* EXSTAT reg present */
286 	CONFIG_IOBASE0_REG_PRESENT,	/* IOBASE0 reg present */
287 	CONFIG_IOBASE1_REG_PRESENT,	/* IOBASE1 reg present */
288 	CONFIG_IOBASE2_REG_PRESENT,	/* IOBASE2 reg present */
289 	CONFIG_IOBASE3_REG_PRESENT,	/* IOBASE3 reg present */
290 	CONFIG_IOLIMIT_REG_PRESENT,	/* IOLIMIT reg present */
291 };
292 
293 uint32_t
294 cistpl_config_handler(cistpl_callout_t *co, cistpl_t *tp,
295 					uint32_t flags, void *arg)
296 {
297 	cisdata_t tpcc_sz;
298 	int i, n, nrb, na, hr = 0;
299 
300 	/*
301 	 * nothing special about our flags, so just call the
302 	 *	generic handler for this
303 	 */
304 	if (flags & HANDTPL_SET_FLAGS)
305 		return (cis_no_tuple_handler(co, tp, flags, arg));
306 
307 	/*
308 	 * We don't currently validate this tuple. This call will
309 	 *	always set tp->flags |= CISTPLF_VALID.
310 	 */
311 	if (flags & HANDTPL_COPY_DONE)
312 		return (cis_no_tuple_handler(co, tp, flags, arg));
313 
314 	if (flags & HANDTPL_PARSE_LTUPLE) {
315 		cistpl_config_t *cr = (cistpl_config_t *)arg;
316 		int crn = 0;
317 
318 		RESET_TP(tp);
319 
320 		tpcc_sz = GET_BYTE(tp);		/* config regs size fields */
321 		cr->last = GET_BYTE(tp);	/* last config index */
322 
323 		na = (tpcc_sz&3)+1;		/* config regs address bytes */
324 		nrb = ((tpcc_sz>>2)&0x0f)+1;	/* number of bytes in config */
325 						/*	regs presence mask */
326 
327 		/*
328 		 * Construct the base offset address for the config registers.
329 		 *	We jump through these hoops because the base address
330 		 *	can be between one and four bytes in length.
331 		 */
332 		cr->base = 0;
333 		n = na;
334 		while (n--)
335 			cr->base |= ((GET_BYTE(tp) & 0x0ff) <<
336 							(8 * (na - (n+1))));
337 
338 		/*
339 		 * Go through the config register presense mask bit by bit and
340 		 *	figure out which config registers are present and which
341 		 *	aren't.
342 		 * For the first ten config registers, set the appropriate
343 		 *	bits in the cr->present member so that the caller
344 		 *	doesn't have to do this.
345 		 */
346 		cr->nr = 0;
347 		cr->present = 0;
348 		n = nrb;
349 		while (n--) {
350 			for (i = 0; i < 8; i++, crn++) {
351 				if (LOOK_BYTE(tp) & (1<<i)) {
352 				    if (crn < (sizeof (config_regs_present_map)/
353 							sizeof (uint32_t)))
354 					cr->present |=
355 						config_regs_present_map[crn];
356 				    cr->nr++;
357 				    cr->hr = hr;
358 				    cr->regs[hr] = MAKE_CONFIG_REG_ADDR(
359 								cr->base, hr);
360 				} /* LOOK_BYTE */
361 				hr++;
362 			} /* for */
363 			(void) GET_BYTE(tp);
364 		} /* while */
365 	}
366 
367 	return (CISTPLF_NOERROR);
368 }
369 
370 /*
371  * cistpl_device_handler - handler for the CISTPL_DEVICE, CISTPL_DEVICE_A,
372  *				CISTPL_DEVICE_OC and CISTPL_DEVICE_OA tuples
373  *
374  *	void *arg - points to a cistpl_device_t * where the
375  *			information is stuffed into
376  *
377  * XXX - we only handle CISTPL_DEVICE_MAX_DEVICES device descriptions
378  *		described in the tuple
379  */
380 uint32_t
381 cistpl_device_handler(cistpl_callout_t *co, cistpl_t *tp,
382 					uint32_t flags, void *arg)
383 {
384 	cisdata_t dev_id;
385 
386 	/*
387 	 * nothing special about our flags, so just call the
388 	 *	generic handler for this
389 	 */
390 	if (flags & HANDTPL_SET_FLAGS)
391 		return (cis_no_tuple_handler(co, tp, flags, arg));
392 
393 	/*
394 	 * We don't currently validate this tuple. This call will
395 	 *	always set tp->flags |= CISTPLF_VALID.
396 	 */
397 	if (flags & HANDTPL_COPY_DONE)
398 		return (cis_no_tuple_handler(co, tp, flags, arg));
399 
400 	if (flags & HANDTPL_PARSE_LTUPLE) {
401 		convert_speed_t convert_speed;
402 		cistpl_device_t *dt = (cistpl_device_t *)arg;
403 		cistpl_device_node_t *cdn;
404 
405 		/*
406 		 * XXX - fix this to look for more than one device definition
407 		 * XXX - fix this to handle the OC fields for
408 		 *	CISTPL_DEVICE_OC and CISTPL_DEVICE_OA
409 		 */
410 		dt->num_devices = 1;
411 		cdn = &dt->devnode[0];
412 
413 		cdn->flags = 0;
414 
415 		RESET_TP(tp);
416 
417 		dev_id = GET_BYTE(tp);
418 
419 		/*
420 		 * Get the device speed code.  If it's 7, then there is an
421 		 *	extended speed code table in use, so parse that.
422 		 *	If it's anything else, get the speed information
423 		 *	directly from the device speed code.
424 		 */
425 		if ((dev_id & 7) == 7) {
426 		    cdn->nS_speed = cistpl_devspeed(tp, 0, CISTPL_DEVSPEED_EXT);
427 		} else {
428 		    cdn->nS_speed = cistpl_devspeed(NULL, dev_id,
429 							CISTPL_DEVSPEED_TABLE);
430 		}
431 
432 		/*
433 		 * Convert the speed in nS to a device speed code.
434 		 * XXX -  should check return code from cis_convert_devspeed()
435 		 */
436 		convert_speed.Attributes = CONVERT_NS_TO_DEVSPEED;
437 		convert_speed.nS = cdn->nS_speed;
438 		(void) cis_convert_devspeed(&convert_speed);
439 		cdn->speed = convert_speed.devspeed;
440 
441 		if (dev_id & 8)
442 			cdn->flags |= CISTPL_DEVICE_WPS;
443 
444 		/*
445 		 * Set the device type.  Note that we take the raw value
446 		 *	from the tuple and pass it back to the caller.
447 		 *	If the device type codes in the standard change,
448 		 *	we will have to change our flags as well.
449 		 */
450 		cdn->type = (dev_id>>4) & 0x0f;
451 
452 		/*
453 		 * XXX - what about the device_size byte?  Is the spec wrong?
454 		 */
455 		cdn->size = GET_BYTE(tp);
456 		/* check for end of list */
457 		if (cdn->size != 0x0ff) {
458 		    convert_size_t convert_size;
459 
460 		    convert_size.devsize = cdn->size;
461 		    convert_size.Attributes = CONVERT_DEVSIZE_TO_BYTES;
462 		    (void) cis_convert_devsize(&convert_size);
463 		    cdn->size_in_bytes = convert_size.bytes;
464 		}
465 	}
466 
467 	return (CISTPLF_NOERROR);
468 }
469 
470 /*
471  * cistpl_cftable_handler - handler for the CISTPL_CFTABLE_ENTRY tuple
472  *
473  *	void *arg - points to a XXX where the information is stuffed into
474  *
475  *    Return:	CISTPLF_NOERROR - if no error parsing tuple
476  *		HANDTPL_ERROR - if error parsing tuple
477  */
478 extern uint32_t cistpl_cftable_io_size_table[];
479 extern uint32_t cistpl_cftable_shift_table[];
480 
481 uint32_t
482 cistpl_cftable_handler(cistpl_callout_t *co, cistpl_t *tp,
483 					uint32_t flags, void *arg)
484 {
485 	cisdata_t tpce_indx, tpce_fs, tpce_td, sf, tpce_io, nr;
486 	cisdata_t ior_desc, tpce_ir, tpce_msd;
487 	int i, j;
488 
489 	/*
490 	 * nothing special about our flags, so just call the
491 	 *	generic handler for this
492 	 */
493 	if (flags & HANDTPL_SET_FLAGS)
494 		return (cis_no_tuple_handler(co, tp, flags, arg));
495 
496 	/*
497 	 * We don't currently validate this tuple. This call will
498 	 *	always set tp->flags |= CISTPLF_VALID.
499 	 */
500 	if (flags & HANDTPL_COPY_DONE)
501 		return (cis_no_tuple_handler(co, tp, flags, arg));
502 
503 	if (flags & HANDTPL_PARSE_LTUPLE) {
504 		cistpl_cftable_entry_t *ce = (cistpl_cftable_entry_t *)arg;
505 
506 		RESET_TP(tp);
507 
508 		/*
509 		 * Check to see if we have an interface description byte.  If
510 		 *	we do, grab it and give it directly to the caller, and
511 		 *	set a flag so the caller knows that it's there.
512 		 * We also setup the appropriate values in the ce->pin member
513 		 *	so that clients can feed this value directly to the
514 		 *	Card Services RequestConfiguration call.
515 		 */
516 		if ((tpce_indx = GET_BYTE(tp)) & CISTPL_CFTABLE_TPCE_IFM) {
517 			ce->ifc = GET_BYTE(tp);
518 
519 			ce->pin = 0;
520 
521 			if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_BVD)
522 			    ce->pin |= (PRR_BVD1_STATUS | PRR_BVD2_STATUS |
523 					PRR_BVD1_EVENT | PRR_BVD2_EVENT);
524 			if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_WP)
525 			    ce->pin |= (PRR_WP_STATUS | PRR_WP_EVENT);
526 			if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_RDY)
527 			    ce->pin |= (PRR_READY_STATUS | PRR_READY_EVENT);
528 
529 			ce->flags |= CISTPL_CFTABLE_TPCE_IF;
530 		}
531 
532 		/*
533 		 * Return the configuration index to the caller, and set the
534 		 *	default configuration flag if this is a default
535 		 *	configuration.
536 		 */
537 		ce->index = tpce_indx & CISTPL_CFTABLE_TPCE_CFGENTRYM;
538 		if (tpce_indx & CISTPL_CFTABLE_TPCE_DEFAULTM)
539 			ce->flags |= CISTPL_CFTABLE_TPCE_DEFAULT;
540 
541 		/*
542 		 * Feature selection flags.
543 		 */
544 		tpce_fs = GET_BYTE(tp);
545 
546 		/*
547 		 * See what types of power information are available,
548 		 *	and if there is any, set the global power
549 		 *	information flag as well as a flag for each
550 		 *	power description available.
551 		 */
552 		if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_PWRM) {
553 		    cistpl_cftable_entry_pd_t *pd = &ce->pd;
554 
555 		    ce->flags |= CISTPL_CFTABLE_TPCE_FS_PWR;
556 
557 		    switch (tpce_fs & CISTPL_CFTABLE_TPCE_FS_PWRM) {
558 			case CISTPL_CFTABLE_TPCE_FS_PWR_VPP2M:
559 				pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VPP2;
560 				/* FALLTHROUGH */
561 			case CISTPL_CFTABLE_TPCE_FS_PWR_VPP1M:
562 				pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VPP1;
563 				/* FALLTHROUGH */
564 			case CISTPL_CFTABLE_TPCE_FS_PWR_VCCM:
565 				pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VCC;
566 		    } /* switch */
567 		} /* if (CISTPL_CFTABLE_TPCE_FS_PWRM) */
568 
569 		/*
570 		 * Set up the global memory information flag.
571 		 */
572 		if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MEMM)
573 			ce->flags |= CISTPL_CFTABLE_TPCE_FS_MEM;
574 
575 		/*
576 		 * Parse the various power description structures.
577 		 */
578 		if (ce->flags & CISTPL_CFTABLE_TPCE_FS_PWR) {
579 			cistpl_cftable_entry_pd_t *pd = &ce->pd;
580 			cistpl_cftable_entry_pwr_t *pwr;
581 			/*
582 			 * Collect any Vcc information.
583 			 */
584 			if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VCC) {
585 				pwr = &pd->pd_vcc;
586 				cistpl_pd_parse(tp, pwr);
587 			}
588 			/*
589 			 * Collect any Vpp1 information.
590 			 */
591 			if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VPP1) {
592 				pwr = &pd->pd_vpp1;
593 				cistpl_pd_parse(tp, pwr);
594 			}
595 			/*
596 			 * Collect any Vpp2 information.
597 			 */
598 			if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VPP2) {
599 				pwr = &pd->pd_vpp2;
600 				cistpl_pd_parse(tp, pwr);
601 			}
602 		} /* if (CISTPL_CFTABLE_TPCE_FS_PWR) */
603 
604 		/*
605 		 * Check to see if there's any timing information, and if
606 		 *	so, parse the tuple data and store it in the
607 		 *	caller's structure.  Set a flag in the global
608 		 *	flag field indicating that there is timing information.
609 		 */
610 		if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_TDM) {
611 			convert_speed_t convert_speed;
612 			cistpl_cftable_entry_speed_t *sp = &ce->speed;
613 			ce->flags |= CISTPL_CFTABLE_TPCE_FS_TD;
614 			tpce_td = GET_BYTE(tp);
615 			/*
616 			 * Parse TPCE_TD to get the various timing
617 			 *	scale factors. Each scale factor has
618 			 *	a value that indicates that the particular
619 			 *	timing parameter doesn't exist.
620 			 */
621 			if ((sf = (tpce_td &
622 					CISTPL_CFTABLE_TPCE_FS_TD_WAITM)) !=
623 			    CISTPL_CFTABLE_TPCE_FS_TD_WAITM) {
624 				sp->nS_wait = cistpl_devspeed(tp,
625 						GET_TPCE_FS_TD_WAITS(sf),
626 						CISTPL_DEVSPEED_EXT);
627 				convert_speed.Attributes =
628 							CONVERT_NS_TO_DEVSPEED;
629 				convert_speed.nS = sp->nS_wait;
630 				(void) cis_convert_devspeed(&convert_speed);
631 				sp->wait = convert_speed.devspeed;
632 				sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_WAIT;
633 			}
634 
635 			if ((sf = (tpce_td & CISTPL_CFTABLE_TPCE_FS_TD_RDYM)) !=
636 			    CISTPL_CFTABLE_TPCE_FS_TD_RDYM) {
637 				sp->nS_rdybsy = cistpl_devspeed(tp,
638 						GET_TPCE_FS_TD_RDYS(sf),
639 						CISTPL_DEVSPEED_EXT);
640 				convert_speed.Attributes =
641 							CONVERT_NS_TO_DEVSPEED;
642 				convert_speed.nS = sp->nS_rdybsy;
643 				(void) cis_convert_devspeed(&convert_speed);
644 				sp->rdybsy = convert_speed.devspeed;
645 				sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_RDY;
646 			}
647 
648 			if ((sf = (tpce_td &
649 					CISTPL_CFTABLE_TPCE_FS_TD_RSVDM)) !=
650 			    CISTPL_CFTABLE_TPCE_FS_TD_RSVDM) {
651 				sp->nS_rsvd = cistpl_devspeed(tp,
652 						GET_TPCE_FS_TD_RSVDS(sf),
653 						CISTPL_DEVSPEED_EXT);
654 				convert_speed.Attributes =
655 							CONVERT_NS_TO_DEVSPEED;
656 				convert_speed.nS = sp->nS_rsvd;
657 				(void) cis_convert_devspeed(&convert_speed);
658 				sp->rsvd = convert_speed.devspeed;
659 				sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_RSVD;
660 			}
661 		} /* if (CISTPL_CFTABLE_TPCE_FS_TDM) */
662 
663 
664 		/*
665 		 * Parse any I/O address information.  If there is I/O
666 		 *	inforamtion, set a flag in the global flag field
667 		 *	to let the caller know.
668 		 */
669 		if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_IOM) {
670 			cistpl_cftable_entry_io_t *io = &ce->io;
671 
672 			ce->flags |= CISTPL_CFTABLE_TPCE_FS_IO;
673 			tpce_io = GET_BYTE(tp);
674 			/*
675 			 * Pass any I/O flags that are in the tuple directly
676 			 *	to the caller.
677 			 */
678 			io->flags = tpce_io;
679 			io->addr_lines = tpce_io &
680 						CISTPL_CFTABLE_TPCE_FS_IO_ALM;
681 			/*
682 			 * If there are any ranges, extract the number of
683 			 *	ranges and the range descriptions.
684 			 */
685 			if (tpce_io & CISTPL_CFTABLE_TPCE_FS_IO_RANGEM) {
686 				cistpl_cftable_entry_io_range_t *ior;
687 				ior_desc = GET_BYTE(tp);
688 				/*
689 				 * Number of I/O ranges is the value specified
690 				 *	in the tuple plus one, so there's
691 				 *	always at least one I/O range if the
692 				 *	CISTPL_CFTABLE_TPCE_FS_IO_RANGEM bit
693 				 *	in the I/O flags register is set.
694 				 */
695 				nr = (ior_desc & 0x0f) + 1;
696 				io->ranges = nr;
697 				/*
698 				 * Cycle through each I/O range.
699 				 */
700 				for (i = 0; i < (int)nr; i++) {
701 					ior = &io->range[i];
702 					ior->addr = 0;
703 					ior->length = 0;
704 					/*
705 					 * Gather the address information.
706 					 *	It's OK if there's no address
707 					 *	information in which case this
708 					 *	loop will never execute.
709 					 */
710 					for (j = 0; j <
711 						cistpl_cftable_io_size_table[
712 							(ior_desc>>4)&3];
713 									j++)
714 						ior->addr |= (GET_BYTE(tp) <<
715 						cistpl_cftable_shift_table[j]);
716 					/*
717 					 * Gather the length information.
718 					 *	It's OK if there's no length
719 					 *	information in which case this
720 					 *	loop will never execute.
721 					 */
722 					for (j = 0; j <
723 						cistpl_cftable_io_size_table[
724 							(ior_desc>>6)&3];
725 									j++)
726 						ior->length |= (GET_BYTE(tp) <<
727 						cistpl_cftable_shift_table[j]);
728 				} /* for (nr) */
729 			} /* if (CISTPL_CFTABLE_TPCE_FS_IO_RANGEM) */
730 		} /* if (CISTPL_CFTABLE_TPCE_FS_IOM) */
731 
732 		/*
733 		 * Parse any IRQ information.  If there is IRQ inforamtion,
734 		 *	set a flag in the global flag field to let the
735 		 *	caller know.
736 		 */
737 		if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_IRQM) {
738 			cistpl_cftable_entry_irq_t *irq = &ce->irq;
739 
740 			ce->flags |= CISTPL_CFTABLE_TPCE_FS_IRQ;
741 			tpce_ir = GET_BYTE(tp);
742 			/*
743 			 * Pass any IRQ flags that are in the tuple directly
744 			 *	to the caller.
745 			 */
746 			irq->flags = tpce_ir;
747 			/*
748 			 * Check for and parse the extended IRQ bitmask
749 			 *	if it exists.
750 			 */
751 			if (tpce_ir & CISTPL_CFTABLE_TPCE_FS_IRQ_MASKM) {
752 				irq->irqs = GET_BYTE(tp) & 0x0ff;
753 				irq->irqs |= (GET_BYTE(tp) << 8)&0x0ff00;
754 			} else {
755 				irq->irqs = (1<< (tpce_ir&0x0f));
756 			}
757 		} /* if (CISTPL_CFTABLE_TPCE_FS_IRQM) */
758 
759 		/*
760 		 * Parse any memory information.
761 		 *
762 		 * XXX - should be a cleaner way to parse this information.
763 		 */
764 		if (ce->flags & CISTPL_CFTABLE_TPCE_FS_MEM) {
765 			cistpl_cftable_entry_mem_t *mem = &ce->mem;
766 			cistpl_cftable_entry_mem_window_t *win;
767 			/*
768 			 * Switch on the type of memory description
769 			 *	information that is available.
770 			 */
771 			switch (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MEMM) {
772 				/*
773 				 * variable length memory space description
774 				 */
775 			case CISTPL_CFTABLE_TPCE_FS_MEM3M:
776 				mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM3;
777 				/* memory space descriptor */
778 				tpce_msd = GET_BYTE(tp);
779 				mem->windows = ((tpce_msd &
780 					(CISTPL_CFTABLE_ENTRY_MAX_MEM_WINDOWS -
781 								1)) + 1);
782 				/*
783 				 * If there's host address information, let
784 				 *	the caller know.
785 				 */
786 				if (tpce_msd & CISTPL_CFTABLE_TPCE_FS_MEM_HOSTM)
787 					mem->flags |=
788 						CISTPL_CFTABLE_TPCE_FS_MEM_HOST;
789 				/*
790 				 * Cycle through each window space description
791 				 *	and collect all the interesting bits.
792 				 */
793 				for (i = 0; i < mem->windows; i++) {
794 					win = &mem->window[i];
795 					win->length = 0;
796 					win->card_addr = 0;
797 					win->host_addr = 0;
798 					/*
799 					 * Gather the length information.
800 					 *	It's OK if there's no length
801 					 *	information in which case this
802 					 *	loop will never execute.
803 					 */
804 					for (j = 0; j <
805 						(int)((tpce_msd>>3)&3); j++)
806 						win->length |= (GET_BYTE(tp) <<
807 						cistpl_cftable_shift_table[j]);
808 					/*
809 					 * Gather the card address information.
810 					 *	It's OK if there's no card
811 					 *	address information in which
812 					 *	case this loop will never
813 					 *	execute.
814 					 */
815 					for (j = 0; j <
816 						(int)((tpce_msd>>5)&3); j++)
817 						win->card_addr |=
818 							(GET_BYTE(tp) <<
819 						cistpl_cftable_shift_table[j]);
820 					/*
821 					 * If there's a host address
822 					 *	description, grab that
823 					 *	as well.
824 					 */
825 					if (mem->flags &
826 					    CISTPL_CFTABLE_TPCE_FS_MEM_HOST) {
827 						/*
828 						 * Gather the host address
829 						 *	information.  It's OK
830 						 *	if there's no host
831 						 *	address information in
832 						 *	which case this loop
833 						 *	will never execute.
834 						 * Note that we use the card
835 						 *	address size to
836 						 *	determine how many
837 						 *	bytes of host address
838 						 *	are present.
839 						 */
840 						for (j = 0; j <
841 							(int)((tpce_msd>>5)&3);
842 									j++)
843 							win->host_addr |=
844 							(GET_BYTE(tp) <<
845 						cistpl_cftable_shift_table[j]);
846 					} else {
847 						/*
848 						 * No host address information,
849 						 *	so the host address is
850 						 *	equal to the card
851 						 *	address.
852 						 */
853 						win->host_addr = win->card_addr;
854 					}
855 				} /* for (i<mem->windows) */
856 				break;
857 				/*
858 				 * single length and card base address specified
859 				 */
860 			case CISTPL_CFTABLE_TPCE_FS_MEM2M:
861 				mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM2;
862 				win = &mem->window[0];
863 				mem->windows = 1;
864 				/*
865 				 * Construct the size of the window.
866 				 */
867 				win->length = GET_BYTE(tp);
868 				win->length |= (GET_BYTE(tp)<<8);
869 				win->length *=
870 					CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE;
871 
872 				/*
873 				 * Construct the card base address.
874 				 */
875 				win->card_addr = GET_BYTE(tp);
876 				win->card_addr |= (GET_BYTE(tp)<<8);
877 				win->card_addr *=
878 					CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE;
879 
880 				/*
881 				 * In this mode, both the host base address
882 				 *	and the card base address are equal.
883 				 */
884 				win->host_addr = win->card_addr;
885 				break;
886 				/*
887 				 * single length specified
888 				 */
889 			case CISTPL_CFTABLE_TPCE_FS_MEM1M:
890 				mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM1;
891 				win = &mem->window[0];
892 				mem->windows = 1;
893 				win->card_addr = 0;
894 				win->host_addr = 0;
895 				/*
896 				 * Construct the size of the window.
897 				 */
898 				win->length = GET_BYTE(tp);
899 				win->length |= (GET_BYTE(tp)<<8);
900 				win->length *=
901 					CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE;
902 				break;
903 			} /* switch (CISTPL_CFTABLE_TPCE_FS_MEMM) */
904 		} /* if (CISTPL_CFTABLE_TPCE_FS_MEM) */
905 
906 		/*
907 		 * Check for and parse any miscellaneous information.
908 		 *
909 		 * We only understand how to parse the first
910 		 *	CISTPL_CFTABLE_TPCE_FS_MISC_MAX extension
911 		 *	bytes specified in the PC Card 95 standard;
912 		 *	we throw away any other extension bytes that
913 		 *	are past these bytes.
914 		 * XXX Note that the assumption here is that the
915 		 *	size of cistpl_cftable_entry_misc_t->flags
916 		 *	is at least CISTPL_CFTABLE_TPCE_FS_MISC_MAX
917 		 *	bytes in length.
918 		 */
919 		if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MISCM) {
920 		    cistpl_cftable_entry_misc_t *misc = &ce->misc;
921 		    int mb = CISTPL_CFTABLE_TPCE_FS_MISC_MAX;
922 
923 		    ce->flags |= CISTPL_CFTABLE_TPCE_FS_MISC;
924 		    misc->flags = 0;
925 
926 		    do {
927 			if (mb) {
928 			    misc->flags = (misc->flags << 8) | LOOK_BYTE(tp);
929 			    mb--;
930 			}
931 		    } while ((GET_BYTE(tp) & CISTPL_EXT_BIT) &&
932 				(!(tp->flags & CISTPLF_MEM_ERR)));
933 
934 			/*
935 			 * Check to see if we tried to read past the
936 			 *	end of the tuple data; if we have,
937 			 *	there's no point in trying to parse
938 			 *	any more of the tuple.
939 			 */
940 		    if (tp->flags & CISTPLF_MEM_ERR)
941 			return (HANDTPL_ERROR);
942 		} /* if (CISTPL_CFTABLE_TPCE_FS_MISCM) */
943 
944 		/*
945 		 * Check for and parse any additional subtuple
946 		 *	information. We know that there is
947 		 *	additional information if we haven't
948 		 *	reached the end of the tuple data area
949 		 *	and if the additional information is
950 		 *	in standard tuple format.
951 		 * If we don't recognize the additional info,
952 		 *	then just silently ignore it, don't
953 		 *	flag it as an error.
954 		 */
955 #ifdef	PARSE_STCE_TUPLES
956 		if (GET_LEN(tp) > 0) {
957 
958 		ce->flags |= CISTPL_CFTABLE_TPCE_FS_STCE_EV
959 		ce->flags |= CISTPL_CFTABLE_TPCE_FS_STCE_PD
960 #endif
961 
962 	} /* if (HANDTPL_PARSE_LTUPLE) */
963 
964 	return (CISTPLF_NOERROR);
965 }
966 
967 /*
968  * cistpl_pd_parse - read and parse a power description structure
969  *
970  *	cisdata_t **ddp - pointer to pointer tuple data area
971  *	cistpl_cftable_entry_pwr_t *pd - pointer to local power description
972  *					structure
973  */
974 static void
975 cistpl_pd_parse(cistpl_t *tp, cistpl_cftable_entry_pwr_t *pd)
976 {
977 	cisdata_t pdesc;
978 
979 	pdesc = GET_BYTE(tp);	/* power description selector */
980 
981 	/* nominal supply voltage */
982 	if (pdesc & CISTPL_CFTABLE_PD_NOMV) {
983 		pd->nomV = cistpl_expd_parse(tp, &pd->nomV_flags) / 100;
984 		pd->nomV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
985 	}
986 
987 	/* minimum supply voltage */
988 	if (pdesc & CISTPL_CFTABLE_PD_MINV) {
989 		pd->minV = cistpl_expd_parse(tp, &pd->minV_flags) / 100;
990 		pd->minV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
991 	}
992 
993 	/* maximum supply voltage */
994 	if (pdesc & CISTPL_CFTABLE_PD_MAXV) {
995 		pd->maxV = cistpl_expd_parse(tp, &pd->maxV_flags) / 100;
996 		pd->maxV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
997 	}
998 
999 	/* continuous supply current */
1000 	if (pdesc & CISTPL_CFTABLE_PD_STATICI) {
1001 		pd->staticI_flags |= CISTPL_CFTABLE_PD_MUL10;
1002 		pd->staticI = cistpl_expd_parse(tp, &pd->staticI_flags);
1003 		pd->staticI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
1004 	}
1005 
1006 	/* maximum current required averaged over 1 second */
1007 	if (pdesc & CISTPL_CFTABLE_PD_AVGI) {
1008 		pd->avgI_flags |= CISTPL_CFTABLE_PD_MUL10;
1009 		pd->avgI = cistpl_expd_parse(tp, &pd->avgI_flags);
1010 		pd->avgI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
1011 	}
1012 
1013 	/* maximum current required averaged over 10mS */
1014 	if (pdesc & CISTPL_CFTABLE_PD_PEAKI) {
1015 		pd->peakI_flags |= CISTPL_CFTABLE_PD_MUL10;
1016 		pd->peakI = cistpl_expd_parse(tp, &pd->peakI_flags);
1017 		pd->peakI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
1018 	}
1019 
1020 	/* power down supply curent required */
1021 	if (pdesc & CISTPL_CFTABLE_PD_PDOWNI) {
1022 		pd->pdownI_flags |= CISTPL_CFTABLE_PD_MUL10;
1023 		pd->pdownI = cistpl_expd_parse(tp, &pd->pdownI_flags);
1024 		pd->pdownI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
1025 	}
1026 }
1027 
1028 /*
1029  * cistpl_expd_parse - read and parse an extended power description structure
1030  *
1031  *	cistpl_t *tp - pointer to pointer tuple data area
1032  *	int *flags - flags that get for this parameter:
1033  *			CISTPL_CFTABLE_PD_NC_SLEEP - no connection on
1034  *							sleep/power down
1035  *			CISTPL_CFTABLE_PD_ZERO - zero value required
1036  *			CISTPL_CFTABLE_PD_NC - no connection ever
1037  *
1038  * The power consumption is returned in the following units:
1039  *
1040  *				voltage - milliVOLTS
1041  *				current - microAMPS
1042  */
1043 extern cistpl_pd_struct_t cistpl_pd_struct;
1044 
1045 uint32_t
1046 cistpl_expd_parse(cistpl_t *tp, uint32_t *flags)
1047 {
1048 	cisdata_t pdesc;
1049 	uint32_t exponent, mantisa, val, digits = 0;
1050 
1051 	/*
1052 	 * Get the power description parameter byte and break it up
1053 	 *	into mantissa and exponent.
1054 	 */
1055 	pdesc = GET_BYTE(tp);
1056 	exponent = pdesc&7;
1057 	mantisa = (pdesc>>3)&0x0f;
1058 
1059 	if (pdesc & CISTPL_EXT_BIT) {
1060 		do {
1061 			if (LOOK_BYTE(tp) <= 0x63)
1062 				digits = LOOK_BYTE(tp);
1063 			if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_NC_SLEEPM)
1064 				*flags |= CISTPL_CFTABLE_PD_NC_SLEEP;
1065 			if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_ZEROM)
1066 				*flags |= CISTPL_CFTABLE_PD_ZERO;
1067 			if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_NCM)
1068 				*flags |= CISTPL_CFTABLE_PD_NC;
1069 		} while (GET_BYTE(tp) & CISTPL_EXT_BIT);
1070 	}
1071 
1072 	val = CISTPL_PD_MAN(mantisa) * CISTPL_PD_EXP(exponent);
1073 
1074 	/*
1075 	 * If we have to multiply the power value by ten, then just
1076 	 *	don't bother dividing.
1077 	 */
1078 	if (! (*flags & CISTPL_CFTABLE_PD_MUL10))
1079 		val = val/10;	/* do this since our mantissa table is X 10 */
1080 
1081 	/*
1082 	 * If we need to add some digits to the right of the decimal, do
1083 	 *	that here.
1084 	 */
1085 	if (exponent)
1086 		val = val + (digits * CISTPL_PD_EXP(exponent-1));
1087 
1088 	val /= 1000;
1089 
1090 	return (val);
1091 }
1092 
1093 /*
1094  * cistpl_devspeed - returns device speed in nS
1095  *
1096  *	cistpl_t *tp - tuple pointer.
1097  *	cisdata_t spindex - device speed table index
1098  *	int flags - operation flags
1099  *		CISTPL_DEVSPEED_TABLE:
1100  *		    Use the spindex argument as an index into a simple
1101  *			device speed table. ref: PCMCIA Release 2.01
1102  *			Card Metaformat pg. 5-14 table 5-12.
1103  *		    When this flag is set, the spindex argument is ignored.
1104  *		CISTPL_DEVSPEED_EXT:
1105  *		    Use the tp argument to access the
1106  *			tuple data area containing an extended speed
1107  *			code table.  ref: PCMCIA Release 2.01 Card
1108  *			Metaformat pg. 5-15 table 5-13.
1109  *		    The tp->read argument must point to the first byte of
1110  *			an extended speed code table.
1111  *		    When this flag is set, the spindex argument is
1112  *			used as a power-of-10 scale factor.  We only allow
1113  *			a maximum scale factor of 10^16.
1114  *
1115  * The device speed is returned in nS for all combinations of flags and
1116  *	speed table entries.
1117  *
1118  * Note if you pass the CISTPL_DEVSPEED_TABLE with a spindex index that
1119  *	refers to an extended speed table, you will get back an undefined
1120  *	speed value.
1121  */
1122 extern cistpl_devspeed_struct_t cistpl_devspeed_struct;
1123 
1124 uint32_t
1125 cistpl_devspeed(cistpl_t *tp, cisdata_t spindex, uint32_t flags)
1126 {
1127 	int scale = 1, first;
1128 	cisdata_t exspeed;
1129 	int exponent, mantisa;
1130 	uint32_t speed;
1131 
1132 	switch (flags) {
1133 	case CISTPL_DEVSPEED_TABLE:
1134 		speed = CISTPL_DEVSPEED_TBL(spindex);
1135 		break;
1136 	case CISTPL_DEVSPEED_EXT:
1137 		do {
1138 			exspeed = GET_BYTE(tp);
1139 			first = 1;
1140 			if (first) {
1141 				/*
1142 				 * XXX - ugh! we don't understand additional
1143 				 *	exspeed bytes
1144 				 */
1145 				first = 0;
1146 				exponent = (exspeed & 0x07);
1147 				mantisa = (exspeed >> 3) & 0x0f;
1148 				spindex &= 0x0f;	/* only allow 10^16 */
1149 				while (spindex--)
1150 					scale *= 10;
1151 			} /* if (first) */
1152 		} while (exspeed & CISTPL_EXT_BIT);
1153 		speed = scale * CISTPL_DEVSPEED_MAN(mantisa) *
1154 						CISTPL_DEVSPEED_EXP(exponent);
1155 		speed = speed/10;	/* XXX - mantissa table is all X 10 */
1156 		break;
1157 	default:
1158 		break;
1159 	}
1160 
1161 	return (speed);
1162 }
1163 
1164 /*
1165  * cistpl_vers_2_handler - handler for the CISTPL_VERS_2 tuple
1166  *
1167  *	void *arg - points to a XXX where the information is stuffed into
1168  */
1169 uint32_t
1170 cistpl_vers_2_handler(cistpl_callout_t *co, cistpl_t *tp,
1171 					uint32_t flags, void *arg)
1172 {
1173 	/*
1174 	 * nothing special about our flags, so just call the
1175 	 *	generic handler for this
1176 	 */
1177 	if (flags & HANDTPL_SET_FLAGS)
1178 		return (cis_no_tuple_handler(co, tp, flags, arg));
1179 
1180 	/*
1181 	 * We don't currently validate this tuple. This call will
1182 	 *	always set tp->flags |= CISTPLF_VALID.
1183 	 */
1184 	if (flags & HANDTPL_COPY_DONE)
1185 		return (cis_no_tuple_handler(co, tp, flags, arg));
1186 
1187 	if (flags & HANDTPL_PARSE_LTUPLE) {
1188 		cistpl_vers_2_t *cs = (cistpl_vers_2_t *)arg;
1189 
1190 		RESET_TP(tp);
1191 
1192 		cs->vers = GET_BYTE(tp);
1193 		cs->comply = GET_BYTE(tp);
1194 		cs->dindex = GET_SHORT(tp);
1195 
1196 		cs->reserved = GET_SHORT(tp);
1197 
1198 		cs->vspec8 = GET_BYTE(tp);
1199 		cs->vspec9 = GET_BYTE(tp);
1200 		cs->nhdr = GET_BYTE(tp);
1201 
1202 		(void) strcpy(cs->oem, cis_getstr(tp));
1203 
1204 		if (GET_LEN(tp) > 0)
1205 		    (void) strcpy(cs->info, cis_getstr(tp));
1206 		else
1207 		    (void) strcpy(cs->info, "(no info)");
1208 	}
1209 
1210 	return (CISTPLF_NOERROR);
1211 }
1212 
1213 /*
1214  * cistpl_jedec_handler - handler for JEDEC C and JEDEC A tuples
1215  *
1216  *	void *arg - points to a XXX where the information is stuffed into
1217  */
1218 uint32_t
1219 cistpl_jedec_handler(cistpl_callout_t *co, cistpl_t *tp,
1220 					uint32_t flags, void *arg)
1221 {
1222 	/*
1223 	 * nothing special about our flags, so just call the
1224 	 *	generic handler for this
1225 	 */
1226 	if (flags & HANDTPL_SET_FLAGS)
1227 		return (cis_no_tuple_handler(co, tp, flags, arg));
1228 
1229 	/*
1230 	 * We don't currently validate this tuple. This call will
1231 	 *	always set tp->flags |= CISTPLF_VALID.
1232 	 */
1233 	if (flags & HANDTPL_COPY_DONE)
1234 		return (cis_no_tuple_handler(co, tp, flags, arg));
1235 
1236 	if (flags & HANDTPL_PARSE_LTUPLE) {
1237 		int nid;
1238 		cistpl_jedec_t *cs = (cistpl_jedec_t *)arg;
1239 
1240 		RESET_TP(tp);
1241 
1242 		for (nid = 0; GET_LEN(tp) > 0 &&
1243 					nid < CISTPL_JEDEC_MAX_IDENTIFIERS &&
1244 					LOOK_BYTE(tp) != 0xFF; nid++) {
1245 			cs->jid[nid].id = GET_BYTE(tp);
1246 			cs->jid[nid].info = GET_BYTE(tp);
1247 		}
1248 		cs->nid = nid;
1249 	}
1250 
1251 	return (CISTPLF_NOERROR);
1252 }
1253 
1254 /*
1255  * cistpl_format_handler - handler for the CISTPL_FORMAT and
1256  *				CISTPL_FORMAT_A tuples
1257  */
1258 uint32_t
1259 cistpl_format_handler(cistpl_callout_t *co, cistpl_t *tp,
1260 					uint32_t flags, void *arg)
1261 {
1262 	/*
1263 	 * nothing special about our flags, so just call the
1264 	 *	generic handler for this
1265 	 */
1266 	if (flags & HANDTPL_SET_FLAGS)
1267 		return (cis_no_tuple_handler(co, tp, flags, arg));
1268 
1269 	/*
1270 	 * We don't currently validate this tuple. This call will
1271 	 *	always set tp->flags |= CISTPLF_VALID.
1272 	 */
1273 	if (flags & HANDTPL_COPY_DONE)
1274 		return (cis_no_tuple_handler(co, tp, flags, arg));
1275 
1276 	if (flags & HANDTPL_PARSE_LTUPLE) {
1277 		cistpl_format_t *cs = (cistpl_format_t *)arg;
1278 
1279 		RESET_TP(tp);
1280 
1281 		cs->type = GET_BYTE(tp);
1282 		cs->edc_length = LOOK_BYTE(tp) & EDC_LENGTH_MASK;
1283 		cs->edc_type = ((uint32_t)GET_BYTE(tp) >> EDC_TYPE_SHIFT) &
1284 								EDC_TYPE_MASK;
1285 		cs->offset = GET_LONG(tp);
1286 		cs->nbytes = GET_LONG(tp);
1287 
1288 		switch (cs->type) {
1289 		case TPLFMTTYPE_DISK:
1290 			cs->dev.disk.bksize = GET_SHORT(tp);
1291 			cs->dev.disk.nblocks = GET_LONG(tp);
1292 			cs->dev.disk.edcloc = GET_LONG(tp);
1293 			break;
1294 
1295 		case TPLFMTTYPE_MEM:
1296 			cs->dev.mem.flags = GET_BYTE(tp);
1297 			cs->dev.mem.reserved = GET_BYTE(tp);
1298 			cs->dev.mem.address = (caddr_t)(uintptr_t)GET_LONG(tp);
1299 			cs->dev.disk.edcloc = GET_LONG(tp);
1300 			break;
1301 		default:
1302 			/* don't know about any other type */
1303 			break;
1304 		}
1305 	}
1306 
1307 	return (CISTPLF_NOERROR);
1308 }
1309 
1310 /*
1311  * cistpl_geometry_handler - handler for the CISTPL_GEOMETRY tuple
1312  *
1313  *	void *arg - points to a XXX where the information is stuffed into
1314  */
1315 uint32_t
1316 cistpl_geometry_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
1317 								void *arg)
1318 {
1319 	/*
1320 	 * nothing special about our flags, so just call the
1321 	 *	generic handler for this
1322 	 */
1323 	if (flags & HANDTPL_SET_FLAGS)
1324 		return (cis_no_tuple_handler(co, tp, flags, arg));
1325 
1326 	/*
1327 	 * We don't currently validate this tuple. This call will
1328 	 *	always set tp->flags |= CISTPLF_VALID.
1329 	 */
1330 	if (flags & HANDTPL_COPY_DONE)
1331 		return (cis_no_tuple_handler(co, tp, flags, arg));
1332 
1333 	if (flags & HANDTPL_PARSE_LTUPLE) {
1334 		cistpl_geometry_t *cs = (cistpl_geometry_t *)arg;
1335 
1336 		RESET_TP(tp);
1337 		cs->spt = GET_BYTE(tp);
1338 		cs->tpc = GET_BYTE(tp);
1339 		cs->ncyl = GET_SHORT(tp);
1340 	}
1341 	return (CISTPLF_NOERROR);
1342 }
1343 
1344 /*
1345  * cistpl_byteorder_handler - handler for the CISTPL_BYTEORDER tuple
1346  *
1347  *	void *arg - points to a XXX where the information is stuffed into
1348  */
1349 uint32_t
1350 cistpl_byteorder_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
1351 								void *arg)
1352 {
1353 	/*
1354 	 * nothing special about our flags, so just call the
1355 	 *	generic handler for this
1356 	 */
1357 	if (flags & HANDTPL_SET_FLAGS)
1358 		return (cis_no_tuple_handler(co, tp, flags, arg));
1359 
1360 	/*
1361 	 * We don't currently validate this tuple. This call will
1362 	 *	always set tp->flags |= CISTPLF_VALID.
1363 	 */
1364 	if (flags & HANDTPL_COPY_DONE)
1365 		return (cis_no_tuple_handler(co, tp, flags, arg));
1366 
1367 	if (flags & HANDTPL_PARSE_LTUPLE) {
1368 		cistpl_byteorder_t *cs = (cistpl_byteorder_t *)arg;
1369 
1370 		RESET_TP(tp);
1371 		cs->order = GET_BYTE(tp);
1372 		cs->map = GET_BYTE(tp);
1373 	}
1374 	return (CISTPLF_NOERROR);
1375 }
1376 
1377 /*
1378  * cistpl_date_handler - handler for CISTPL_DATE card format tuple
1379  *
1380  *	void *arg - points to a cistpl_date_t * where the
1381  *			information is stuffed into
1382  */
1383 uint32_t
1384 cistpl_date_handler(cistpl_callout_t *co, cistpl_t *tp,
1385 					uint32_t flags, void *arg)
1386 {
1387 	/*
1388 	 * nothing special about our flags, so just call the
1389 	 *	generic handler for this
1390 	 */
1391 	if (flags & HANDTPL_SET_FLAGS)
1392 		return (cis_no_tuple_handler(co, tp, flags, arg));
1393 
1394 	/*
1395 	 * We don't currently validate this tuple. This call will
1396 	 *	always set tp->flags |= CISTPLF_VALID.
1397 	 */
1398 	if (flags & HANDTPL_COPY_DONE)
1399 		return (cis_no_tuple_handler(co, tp, flags, arg));
1400 
1401 	if (flags & HANDTPL_PARSE_LTUPLE) {
1402 		cistpl_date_t *cs = (cistpl_date_t *)arg;
1403 
1404 		RESET_TP(tp);
1405 		cs->time = GET_SHORT(tp);
1406 		cs->day = GET_SHORT(tp);
1407 	}
1408 	return (CISTPLF_NOERROR);
1409 }
1410 
1411 /*
1412  * cistpl_battery_handler - handler for CISTPL_BATTERY battery replacement
1413  *				date tuple
1414  *
1415  *	void *arg - points to a cistpl_battery_t * where the
1416  *			information is stuffed into
1417  */
1418 uint32_t
1419 cistpl_battery_handler(cistpl_callout_t *co, cistpl_t *tp,
1420 					uint32_t flags, void *arg)
1421 {
1422 	/*
1423 	 * nothing special about our flags, so just call the
1424 	 *	generic handler for this
1425 	 */
1426 	if (flags & HANDTPL_SET_FLAGS)
1427 		return (cis_no_tuple_handler(co, tp, flags, arg));
1428 
1429 	/*
1430 	 * We don't currently validate this tuple. This call will
1431 	 *	always set tp->flags |= CISTPLF_VALID.
1432 	 */
1433 	if (flags & HANDTPL_COPY_DONE)
1434 		return (cis_no_tuple_handler(co, tp, flags, arg));
1435 
1436 	if (flags & HANDTPL_PARSE_LTUPLE) {
1437 		cistpl_battery_t *cs = (cistpl_battery_t *)arg;
1438 
1439 		RESET_TP(tp);
1440 		cs->rday = GET_SHORT(tp);
1441 		cs->xday = GET_SHORT(tp);
1442 	}
1443 	return (CISTPLF_NOERROR);
1444 }
1445 
1446 /*
1447  * cistpl_org_handler - handler for CISTPL_ORG data organization tuple
1448  *
1449  *	void *arg - points to a cistpl_org_t * where the
1450  *			information is stuffed into
1451  */
1452 uint32_t
1453 cistpl_org_handler(cistpl_callout_t *co, cistpl_t *tp,
1454 					uint32_t flags, void *arg)
1455 {
1456 	/*
1457 	 * nothing special about our flags, so just call the
1458 	 *	generic handler for this
1459 	 */
1460 	if (flags & HANDTPL_SET_FLAGS)
1461 		return (cis_no_tuple_handler(co, tp, flags, arg));
1462 
1463 	/*
1464 	 * We don't currently validate this tuple. This call will
1465 	 *	always set tp->flags |= CISTPLF_VALID.
1466 	 */
1467 	if (flags & HANDTPL_COPY_DONE)
1468 		return (cis_no_tuple_handler(co, tp, flags, arg));
1469 
1470 	if (flags & HANDTPL_PARSE_LTUPLE) {
1471 		cistpl_org_t *cs = (cistpl_org_t *)arg;
1472 
1473 		RESET_TP(tp);
1474 		cs->type = GET_BYTE(tp);
1475 
1476 		(void) strcpy(cs->desc, cis_getstr(tp));
1477 	}
1478 
1479 	return (CISTPLF_NOERROR);
1480 }
1481 
1482 
1483 /*
1484  * cistpl_manfid_handler - handler for CISTPL_MANFID, the manufacturer ID tuple
1485  *
1486  *	void *arg - points to a XXX where the information is stuffed into
1487  */
1488 uint32_t
1489 cistpl_manfid_handler(cistpl_callout_t *co, cistpl_t *tp,
1490 					uint32_t flags, void *arg)
1491 {
1492 	/*
1493 	 * nothing special about our flags, so just call the
1494 	 *	generic handler for this
1495 	 */
1496 	if (flags & HANDTPL_SET_FLAGS)
1497 		return (cis_no_tuple_handler(co, tp, flags, arg));
1498 
1499 	/*
1500 	 * We don't currently validate this tuple. This call will
1501 	 *	always set tp->flags |= CISTPLF_VALID.
1502 	 */
1503 	if (flags & HANDTPL_COPY_DONE)
1504 		return (cis_no_tuple_handler(co, tp, flags, arg));
1505 
1506 	if (flags & HANDTPL_PARSE_LTUPLE) {
1507 		cistpl_manfid_t *cs = (cistpl_manfid_t *)arg;
1508 
1509 		RESET_TP(tp);
1510 		cs->manf = GET_SHORT(tp);
1511 		cs->card = GET_SHORT(tp);
1512 	}
1513 	return (CISTPLF_NOERROR);
1514 }
1515 
1516 /*
1517  * cistpl_funcid_handler - handler for CISTPL_FUNCID
1518  *
1519  *	void *arg - points to a XXX where the information is stuffed into
1520  */
1521 uint32_t
1522 cistpl_funcid_handler(cistpl_callout_t *co, cistpl_t *tp,
1523 					uint32_t flags, void *arg)
1524 {
1525 	/*
1526 	 * nothing special about our flags, so just call the
1527 	 *	generic handler for this
1528 	 */
1529 	if (flags & HANDTPL_SET_FLAGS)
1530 		return (cis_no_tuple_handler(co, tp, flags, arg));
1531 
1532 	/*
1533 	 * We don't currently validate this tuple. This call will
1534 	 *	always set tp->flags |= CISTPLF_VALID.
1535 	 */
1536 	if (flags & HANDTPL_COPY_DONE)
1537 		return (cis_no_tuple_handler(co, tp, flags, arg));
1538 
1539 	if (flags & HANDTPL_PARSE_LTUPLE) {
1540 		cistpl_funcid_t *cs = (cistpl_funcid_t *)arg;
1541 
1542 		RESET_TP(tp);
1543 
1544 		cs->function = GET_BYTE(tp);
1545 		cs->sysinit = GET_BYTE(tp);
1546 	}
1547 	return (CISTPLF_NOERROR);
1548 }
1549 
1550 
1551 /*
1552  * cistpl_funce_serial_handler - handler for the CISTPL_FUNCE/SERIAL tuple
1553  *
1554  *	void *arg - points to a XXX where the information is stuffed into
1555  */
1556 uint32_t
1557 cistpl_funce_serial_handler(cistpl_callout_t *co, cistpl_t *tp,
1558 						uint32_t flags, void *arg)
1559 {
1560 	int subfunction;
1561 
1562 	/*
1563 	 * nothing special about our flags, so just call the
1564 	 *	generic handler for this
1565 	 */
1566 	if (flags & HANDTPL_SET_FLAGS)
1567 		return (cis_no_tuple_handler(co, tp, flags, arg));
1568 
1569 	/*
1570 	 * We don't currently validate this tuple. This call will
1571 	 *	always set tp->flags |= CISTPLF_VALID.
1572 	 */
1573 	if (flags & HANDTPL_COPY_DONE)
1574 		return (cis_no_tuple_handler(co, tp, flags, arg));
1575 
1576 	if (flags & HANDTPL_PARSE_LTUPLE) {
1577 		cistpl_funce_t *cs = (cistpl_funce_t *)arg;
1578 
1579 		RESET_TP(tp);
1580 
1581 		cs->function = TPLFUNC_SERIAL;
1582 		cs->subfunction = subfunction = GET_BYTE(tp);
1583 		switch (subfunction & 0xF) {
1584 		case TPLFE_SUB_SERIAL:
1585 		case TPLFE_CAP_SERIAL_DATA:
1586 		case TPLFE_CAP_SERIAL_FAX:
1587 		case TPLFE_CAP_SERIAL_VOICE:
1588 			cs->data.serial.ua = GET_BYTE(tp);
1589 			cs->data.serial.uc = GET_SHORT(tp);
1590 			break;
1591 		case TPLFE_SUB_MODEM_COMMON:
1592 		case TPLFE_CAP_MODEM_DATA:
1593 		case TPLFE_CAP_MODEM_FAX:
1594 		case TPLFE_CAP_MODEM_VOICE:
1595 			cs->data.modem.fc = GET_BYTE(tp);
1596 			cs->data.modem.cb = (GET_BYTE(tp) + 1) * 4;
1597 			cs->data.modem.eb = GET_INT24(tp);
1598 			cs->data.modem.tb = GET_INT24(tp);
1599 			break;
1600 		case TPLFE_SUB_MODEM_DATA:
1601 			cs->data.data_modem.ud = GET_BE_SHORT(tp) * 75;
1602 			cs->data.data_modem.ms = GET_SHORT(tp);
1603 			cs->data.data_modem.em = GET_BYTE(tp);
1604 			cs->data.data_modem.dc = GET_BYTE(tp);
1605 			cs->data.data_modem.cm = GET_BYTE(tp);
1606 			cs->data.data_modem.ex = GET_BYTE(tp);
1607 			cs->data.data_modem.dy = GET_BYTE(tp);
1608 			cs->data.data_modem.ef = GET_BYTE(tp);
1609 			for (cs->data.data_modem.ncd = 0;
1610 				GET_LEN(tp) > 0 && cs->data.data_modem.ncd < 16;
1611 						cs->data.data_modem.ncd++)
1612 				if (LOOK_BYTE(tp) != 255) {
1613 					cs->data.data_modem.cd[
1614 						cs->data.data_modem.ncd] =
1615 								GET_BYTE(tp);
1616 				} else {
1617 					GET_BYTE(tp);
1618 					break;
1619 				}
1620 			break;
1621 		case TPLFE_SUB_MODEM_FAX:
1622 			cs->data.fax.uf = GET_BE_SHORT(tp) * 75;
1623 			cs->data.fax.fm = GET_BYTE(tp);
1624 			cs->data.fax.fy = GET_BYTE(tp);
1625 			cs->data.fax.fs = GET_SHORT(tp);
1626 			for (cs->data.fax.ncf = 0;
1627 				GET_LEN(tp) > 0 && cs->data.fax.ncf < 16;
1628 							cs->data.fax.ncf++)
1629 				if (LOOK_BYTE(tp) != 255) {
1630 					cs->data.fax.cf[cs->data.fax.ncf] =
1631 								GET_BYTE(tp);
1632 				} else {
1633 					GET_BYTE(tp);
1634 					break;
1635 				}
1636 			break;
1637 		case TPLFE_SUB_VOICE:
1638 			cs->data.voice.uv = GET_BE_SHORT(tp) * 75;
1639 			for (cs->data.voice.nsr = 0; LOOK_BYTE(tp) != 0 &&
1640 				GET_LEN(tp) >= 2;
1641 						cs->data.voice.nsr++) {
1642 				cs->data.voice.sr[cs->data.voice.nsr] =
1643 					GET_BYTE(tp) * 1000;
1644 				cs->data.voice.sr[cs->data.voice.nsr] +=
1645 					GET_BYTE(tp) * 100;
1646 			}
1647 			for (cs->data.voice.nss = 0; LOOK_BYTE(tp) != 0 &&
1648 				GET_LEN(tp) >= 2;
1649 						cs->data.voice.nss++) {
1650 				cs->data.voice.ss[cs->data.voice.nss] =
1651 					GET_BYTE(tp) * 10;
1652 				cs->data.voice.ss[cs->data.voice.nss] +=
1653 								GET_BYTE(tp);
1654 			}
1655 			for (cs->data.voice.nsc = 0; LOOK_BYTE(tp) != 0 &&
1656 				GET_LEN(tp) >= 1;
1657 						cs->data.voice.nsc++) {
1658 				cs->data.voice.sc[cs->data.voice.nsc] =
1659 								GET_BYTE(tp);
1660 			}
1661 			break;
1662 		default:
1663 			break;
1664 		}
1665 	}
1666 	return (CISTPLF_NOERROR);
1667 }
1668 
1669 /*
1670  * cistpl_funce_lan_handler - handler for the CISTPL_FUNCE/LAN tuple
1671  *
1672  *	void *arg - points to a XXX where the information is stuffed into
1673  */
1674 uint32_t
1675 cistpl_funce_lan_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
1676 								void *arg)
1677 {
1678 	int subfunction;
1679 
1680 	/*
1681 	 * nothing special about our flags, so just call the
1682 	 *	generic handler for this
1683 	 */
1684 	if (flags & HANDTPL_SET_FLAGS)
1685 		return (cis_no_tuple_handler(co, tp, flags, arg));
1686 
1687 	/*
1688 	 * We don't currently validate this tuple. This call will
1689 	 *	always set tp->flags |= CISTPLF_VALID.
1690 	 */
1691 	if (flags & HANDTPL_COPY_DONE)
1692 		return (cis_no_tuple_handler(co, tp, flags, arg));
1693 
1694 	if (flags & HANDTPL_PARSE_LTUPLE) {
1695 		int i;
1696 		cistpl_funce_t *cs = (cistpl_funce_t *)arg;
1697 
1698 		RESET_TP(tp);
1699 
1700 		cs->function = TPLFUNC_LAN;
1701 		cs->subfunction = subfunction = GET_BYTE(tp);
1702 
1703 		switch (subfunction) {
1704 		case TPLFE_NETWORK_INFO:
1705 			cs->data.lan.tech = GET_BYTE(tp);
1706 			cs->data.lan.speed = GET_BYTE(tp);
1707 			i = GET_BYTE(tp);
1708 			if (i < 24) {
1709 				cs->data.lan.speed <<= i;
1710 			} else {
1711 				/*
1712 				 * if speed is too large a value
1713 				 * to hold in a uint32 flag it and
1714 				 * store as [mantissa][exponent]
1715 				 * in least significant 16 bits
1716 				 */
1717 				cs->data.lan.speed = 0x80000000 |
1718 					(cs->data.lan.speed << 8) | i;
1719 			}
1720 			cs->data.lan.media = GET_BYTE(tp);
1721 			cs->data.lan.con = GET_BYTE(tp);
1722 			cs->data.lan.id_sz = GET_BYTE(tp);
1723 			if (cs->data.lan.id_sz <= 16) {
1724 				for (i = 0; i < cs->data.lan.id_sz; i++)
1725 					cs->data.lan.id[i] = GET_BYTE(tp);
1726 			}
1727 			break;
1728 		default:
1729 				/* unknown LAN tuple type */
1730 			return (CISTPLF_UNKNOWN);
1731 		}
1732 	}
1733 	return (CISTPLF_NOERROR);
1734 }
1735 
1736 /*
1737  * cistpl_linktarget_handler - handler for CISTPL_LINKTARGET tuple
1738  *
1739  *	void *arg - points to a cistpl_linktarget_t * where the
1740  *			information is stuffed into
1741  *
1742  *	If HANDTPL_COPY_DONE is set, we just validate the tuple but
1743  *		do not return any values.
1744  *	If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and
1745  *		return the parsed tuple data if the tuple is valid.
1746  *
1747  *	If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag
1748  *		will be set in the tp->flags field and HANDTPL_ERROR
1749  *		will be returned.
1750  *
1751  *	If the tuple data body is invalid, the CISTPLF_PARAMS_INVALID flag
1752  *		will be set in the tp->flags field and HANDTPL_ERROR
1753  *		will be returned.
1754  *
1755  *	The tuple is considered invalid if it's link field is less than
1756  *		MIN_LINKTARGET_LENGTH or if the data body of the tuple
1757  *		does not contain the pattern CISTPL_LINKTARGET_MAGIC.
1758  *
1759  * XXX At some point we should revisit this to see if we can call
1760  *	cis_validate_longlink_acm instead of doing the validation
1761  *	in both places.
1762  */
1763 uint32_t
1764 cistpl_linktarget_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
1765 								void *arg)
1766 {
1767 	/*
1768 	 * nothing special about our flags, so just call the
1769 	 *	generic handler for this
1770 	 */
1771 	if (flags & HANDTPL_SET_FLAGS)
1772 		return (cis_no_tuple_handler(co, tp, flags, arg));
1773 
1774 	/*
1775 	 * Validate the tuple for both the HANDTPL_COPY_DONE case and
1776 	 *	the HANDTPL_PARSE_LTUPLE case. Only return data in
1777 	 *	the HANDTPL_PARSE_LTUPLE case.
1778 	 */
1779 	if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) {
1780 		uchar_t *cp;
1781 		cisdata_t tl;
1782 
1783 		if ((tl = tp->len) >= (cisdata_t)MIN_LINKTARGET_LENGTH) {
1784 			cisdata_t *ltm = (cisdata_t *)CISTPL_LINKTARGET_MAGIC;
1785 			int i;
1786 
1787 			RESET_TP(tp);
1788 
1789 			/*
1790 			 * Save the start address of this string in case
1791 			 *	the tuple turns out to be OK since we
1792 			 *	need to pass this address to the caller.
1793 			 */
1794 			cp = GET_BYTE_ADDR(tp);
1795 
1796 			/*
1797 			 * Check each byte of the tuple body to see if it
1798 			 *	matches what should be in a valid tuple.
1799 			 *	Note that we can't assume that this magic
1800 			 *	pattern is a string and we also only need
1801 			 *	to be sure that MIN_LINKTARGET_LENGTH bytes
1802 			 *	match; all bytes following this magic number
1803 			 *	in this tuple are ignored.
1804 			 */
1805 			for (i = 0; i < MIN_LINKTARGET_LENGTH; i++) {
1806 				if (GET_BYTE(tp) != *ltm++) {
1807 					tp->flags |= CISTPLF_PARAMS_INVALID;
1808 					return (HANDTPL_ERROR);
1809 				}
1810 			} /* MIN_LINKTARGET_LENGTH */
1811 
1812 			/*
1813 			 * This tuple is valid.
1814 			 */
1815 			if (flags & HANDTPL_COPY_DONE)
1816 				tp->flags |= CISTPLF_VALID;
1817 
1818 			/*
1819 			 * If we're also parsing this tuple, then
1820 			 *	setup the return values.
1821 			 */
1822 			if (flags & HANDTPL_PARSE_LTUPLE) {
1823 				cistpl_linktarget_t *cs =
1824 						(cistpl_linktarget_t *)arg;
1825 
1826 				cs->length = tl;
1827 				(void) strncpy(cs->tpltg_tag, (char *)cp,
1828 								cs->length);
1829 				cs->tpltg_tag[cs->length] = NULL;
1830 
1831 			} /* HANDTPL_PARSE_LTUPLE */
1832 
1833 		} else {
1834 
1835 			tp->flags |= CISTPLF_LINK_INVALID;
1836 			return (HANDTPL_ERROR);
1837 
1838 		} /* CISTPL_LINKTARGET */
1839 
1840 	} /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */
1841 
1842 	return (CISTPLF_NOERROR);
1843 }
1844 
1845 /*
1846  * cistpl_longlink_ac_handler - handler for CISTPL_LONGLINK_A and
1847  *				CISTPL_LONGLINK_C tuples
1848  *
1849  *	void *arg - points to a cistpl_longlink_ac_t * where the
1850  *			information is stuffed into
1851  *
1852  *	If the passed in tuple is CISTPL_LONGLINK_A the CISTPL_LONGLINK_AC_AM
1853  *		flag in cistpl_longlink_ac_t->flags is set.
1854  *	If the passed in tuple is CISTPL_LONGLINK_C the CISTPL_LONGLINK_AC_CM
1855  *		flag in cistpl_longlink_ac_t->flags is set.
1856  *
1857  *	If HANDTPL_COPY_DONE is set, we just validate the tuple but
1858  *		do not return any values.
1859  *	If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and
1860  *		return the parsed tuple data if the tuple is valid.
1861  *
1862  *	If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag
1863  *		will be set in the tp->flags field and HANDTPL_ERROR
1864  *		will be returned.
1865  *
1866  *	The tuple is considered invalid if it's link field is less than
1867  *		MIN_LONGLINK_AC_LENGTH.
1868  */
1869 uint32_t
1870 cistpl_longlink_ac_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
1871 								void *arg)
1872 {
1873 	/*
1874 	 * nothing special about our flags, so just call the
1875 	 *	generic handler for this
1876 	 */
1877 	if (flags & HANDTPL_SET_FLAGS)
1878 		return (cis_no_tuple_handler(co, tp, flags, arg));
1879 
1880 	/*
1881 	 * Validate the tuple for both the HANDTPL_COPY_DONE case and
1882 	 *	the HANDTPL_PARSE_LTUPLE case. Only return data in
1883 	 *	the HANDTPL_PARSE_LTUPLE case.
1884 	 */
1885 	if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) {
1886 
1887 		if (tp->len >= (cisdata_t)MIN_LONGLINK_AC_LENGTH) {
1888 
1889 			/*
1890 			 * This tuple is valid.
1891 			 */
1892 			if (flags & HANDTPL_COPY_DONE)
1893 				tp->flags |= CISTPLF_VALID;
1894 
1895 			if (flags & HANDTPL_PARSE_LTUPLE) {
1896 				cistpl_longlink_ac_t *cs =
1897 						(cistpl_longlink_ac_t *)arg;
1898 
1899 				switch (tp->type) {
1900 				    case CISTPL_LONGLINK_A:
1901 					cs->flags = CISTPL_LONGLINK_AC_AM;
1902 					break;
1903 
1904 				    case CISTPL_LONGLINK_C:
1905 					cs->flags = CISTPL_LONGLINK_AC_CM;
1906 					break;
1907 				    default:
1908 					break;
1909 				} /* switch */
1910 
1911 				RESET_TP(tp);
1912 
1913 				cs->tpll_addr = GET_LONG(tp);
1914 
1915 			} /* HANDTPL_PARSE_LTUPLE */
1916 
1917 		} else {
1918 			tp->flags |= CISTPLF_LINK_INVALID;
1919 			return (HANDTPL_ERROR);
1920 		} /* MIN_LONGLINK_AC_LENGTH */
1921 
1922 	} /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */
1923 
1924 	return (CISTPLF_NOERROR);
1925 }
1926 
1927 /*
1928  * cistpl_longlink_mfc_handler - handler for CISTPL_LONGLINK_MFC tuples
1929  *
1930  *	void *arg - points to a cistpl_longlink_mfc_t * where the
1931  *			information is stuffed into
1932  *
1933  *	If HANDTPL_COPY_DONE is set, we just validate the tuple but
1934  *		do not return any values.
1935  *	If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and
1936  *		return the parsed tuple data if the tuple is valid.
1937  *
1938  *	If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag
1939  *		will be set in the tp->flags field and HANDTPL_ERROR
1940  *		will be returned.
1941  *
1942  *	If the number of register sets is invalid, the CISTPLF_PARAMS_INVALID
1943  *		flag be set in the tp->flags field and HANDTPL_ERROR will be
1944  *		returned.
1945  *
1946  *	The tuple is considered invalid if it's link field is less than
1947  *		MIN_LONGLINK_MFC_LENGTH or if the number of register sets
1948  *		is not in the range [MIN_LONGLINK_MFC_NREGS..CIS_MAX_FUNCTIONS]
1949  */
1950 uint32_t
1951 cistpl_longlink_mfc_handler(cistpl_callout_t *co, cistpl_t *tp,
1952 					uint32_t flags, void *arg)
1953 {
1954 	/*
1955 	 * nothing special about our flags, so just call the
1956 	 *	generic handler for this
1957 	 */
1958 	if (flags & HANDTPL_SET_FLAGS)
1959 		return (cis_no_tuple_handler(co, tp, flags, arg));
1960 
1961 	/*
1962 	 * Validate the tuple for both the HANDTPL_COPY_DONE case and
1963 	 *	the HANDTPL_PARSE_LTUPLE case. Only return data in
1964 	 *	the HANDTPL_PARSE_LTUPLE case.
1965 	 */
1966 	if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) {
1967 
1968 		if (tp->len >= (cisdata_t)MIN_LONGLINK_MFC_LENGTH) {
1969 
1970 			/*
1971 			 * This tuple is valid.
1972 			 */
1973 			if (flags & HANDTPL_COPY_DONE)
1974 				tp->flags |= CISTPLF_VALID;
1975 
1976 			if (flags & HANDTPL_PARSE_LTUPLE) {
1977 				cistpl_longlink_mfc_t *cs =
1978 						(cistpl_longlink_mfc_t *)arg;
1979 				int fn;
1980 
1981 				RESET_TP(tp);
1982 
1983 				/*
1984 				 * Get the number of register sets described
1985 				 *	by this tuple. The number of register
1986 				 *	sets must be greter than or equal to
1987 				 *	MIN_LONGLINK_MFC_NREGS and less than
1988 				 *	CIS_MAX_FUNCTIONS.
1989 				 * Note that the number of functions is equal
1990 				 *	to the number of register sets.
1991 				 */
1992 				cs->nregs = GET_BYTE(tp);
1993 				cs->nfuncs = cs->nregs;
1994 
1995 				if ((cs->nregs < MIN_LONGLINK_MFC_NREGS) ||
1996 					(cs->nregs > CIS_MAX_FUNCTIONS)) {
1997 				    tp->flags |= CISTPLF_PARAMS_INVALID;
1998 				    return (HANDTPL_ERROR);
1999 				}
2000 
2001 				/*
2002 				 * Cycle through each function and setup
2003 				 *	the appropriate parameter values.
2004 				 */
2005 				for (fn = 0; fn < cs->nregs; fn++) {
2006 				    cs->function[fn].tas = GET_BYTE(tp);
2007 				    cs->function[fn].addr = GET_LONG(tp);
2008 				} /* for (fn) */
2009 
2010 			} /* HANDTPL_PARSE_LTUPLE */
2011 
2012 		} else {
2013 			tp->flags |= CISTPLF_LINK_INVALID;
2014 			return (HANDTPL_ERROR);
2015 		} /* MIN_LONGLINK_MFC_LENGTH */
2016 
2017 	} /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */
2018 
2019 	return (CISTPLF_NOERROR);
2020 }
2021 
2022 /*
2023  * cis_validate_longlink_acm - Validates the secondary tuple chain pointed
2024  *				to by cisptr and specified by a previous
2025  *				CISTPL_LONGLINK_A, CISTPL_LONGLINK_C or
2026  *				CISTPL_LONGLINK_MFC tuple.
2027  *
2028  *	cisptr->offset must be the offset to the first byte in the secondary
2029  *		tuple chain to validate
2030  *	cisptr->flags must be setup to specify the correct address space
2031  *
2032  * The cisptr->offset member is not updated after this function returns.
2033  *
2034  *	BAD_CIS_ADDR is returned is the raw CIS data cound not be read.
2035  *	HANDTPL_ERROR is returned if the secondary tuple chain does not
2036  *		contain a valid CISTPL_LINKTARGET tuple.
2037  */
2038 uint32_t
2039 cis_validate_longlink_acm(cisptr_t *cisptr)
2040 {
2041 	uchar_t cb[MIN_LINKTARGET_LENGTH + LINKTARGET_AC_HEADER_LENGTH];
2042 	cisptr_t t_cisptr, *cpt;
2043 	int tl;
2044 
2045 	/*
2046 	 * Since the NEXT_CIS_ADDR macro increments the cisptr_t->offset
2047 	 *	member, make a local copy of the cisptr and use the local
2048 	 *	copy to read data from the card.
2049 	 */
2050 	cpt = &t_cisptr;
2051 	bcopy((caddr_t)cisptr, (caddr_t)cpt, sizeof (cisptr_t));
2052 
2053 	for (tl = 0; tl < MIN_LINKTARGET_LENGTH +
2054 					LINKTARGET_AC_HEADER_LENGTH; tl++) {
2055 
2056 		cb[tl] = GET_CIS_DATA(cpt);
2057 		if (!NEXT_CIS_ADDR(cpt))
2058 			return ((uint32_t)BAD_CIS_ADDR);
2059 
2060 	} /* for */
2061 
2062 	if ((cb[0] == CISTPL_LINKTARGET) && (cb[1] >= MIN_LINKTARGET_LENGTH)) {
2063 		cisdata_t *ltm = (cisdata_t *)CISTPL_LINKTARGET_MAGIC;
2064 
2065 		for (tl = 0; tl < MIN_LINKTARGET_LENGTH; tl++, ltm++) {
2066 			if (cb[tl + LINKTARGET_AC_HEADER_LENGTH] != *ltm)
2067 				return (HANDTPL_ERROR);
2068 		}
2069 		return (CISTPLF_NOERROR);
2070 
2071 	} /* if */
2072 
2073 	return (HANDTPL_ERROR);
2074 }
2075 
2076 /*
2077  * cis_getstr (tp)
2078  *	we want the address of the first character returned
2079  *	but need to skip past the string in the cistpl_t structure
2080  */
2081 char *
2082 cis_getstr(cistpl_t *tp)
2083 {
2084 	uchar_t *cp, *cpp;
2085 	uchar_t x;
2086 
2087 	cp = tp->read.byte;
2088 	cpp = cp;
2089 
2090 	while ((x = LOOK_BYTE(tp)) != 0 && x != 0xff) {
2091 		x = GET_BYTE(tp);
2092 	}
2093 
2094 	(void) GET_BYTE(tp);	/* get past that last byte */
2095 
2096 	while ((*cpp != 0) && (*cpp != 0xff))
2097 	    cpp++;
2098 
2099 	*cpp = NULL;
2100 
2101 	return ((char *)cp);
2102 }
2103 
2104 /*
2105  * cis_return_name - returns name of tuple
2106  *
2107  *    calling:	co - pointer to cistpl_callout_t entry that contains
2108  *			tuple name to return
2109  *		gtn - pointer to cistpl_get_tuple_name_t to return
2110  *			name into
2111  */
2112 static void
2113 cis_return_name(cistpl_callout_t *co, cistpl_get_tuple_name_t *gtn)
2114 {
2115 	(void) strncpy(gtn->name, co->text, CIS_MAX_TUPLE_NAME_LEN);
2116 	gtn->name[CIS_MAX_TUPLE_NAME_LEN - 1] = NULL;
2117 }
2118 
2119 /*
2120  * cis_malloc/cis_free
2121  *	wrappers around kmem_alloc()/kmem_free() that
2122  *	provide malloc/free style usage
2123  */
2124 
2125 caddr_t
2126 cis_malloc(size_t len)
2127 {
2128 	caddr_t addr;
2129 
2130 	addr = kmem_zalloc(len + sizeof (size_t), KM_SLEEP);
2131 	*(size_t *)addr = len + sizeof (size_t);
2132 	addr += sizeof (size_t);
2133 	return (addr);
2134 }
2135 
2136 void
2137 cis_free(caddr_t addr)
2138 {
2139 	size_t len;
2140 	addr -= sizeof (size_t);
2141 	len = *(size_t *)addr;
2142 	kmem_free(addr, len);
2143 }
2144