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