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