17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
23*5f9e250aShx147065 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * This file contains the tuple handlers that are called by the CIS
317c478bd9Sstevel@tonic-gate * parser.
327c478bd9Sstevel@tonic-gate *
337c478bd9Sstevel@tonic-gate * XXX - how about a better explaination??
347c478bd9Sstevel@tonic-gate */
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate #include <sys/types.h>
377c478bd9Sstevel@tonic-gate #include <sys/systm.h>
387c478bd9Sstevel@tonic-gate #include <sys/user.h>
397c478bd9Sstevel@tonic-gate #include <sys/buf.h>
407c478bd9Sstevel@tonic-gate #include <sys/file.h>
417c478bd9Sstevel@tonic-gate #include <sys/uio.h>
427c478bd9Sstevel@tonic-gate #include <sys/conf.h>
437c478bd9Sstevel@tonic-gate #include <sys/stat.h>
447c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
457c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
467c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
477c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
487c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
497c478bd9Sstevel@tonic-gate #include <sys/debug.h>
507c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
517c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
527c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
537c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
547c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
557c478bd9Sstevel@tonic-gate #include <sys/callb.h>
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate #include <sys/pctypes.h>
587c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_types.h>
597c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis.h>
607c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis_handlers.h>
617c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs.h>
627c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_priv.h>
637c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis_protos.h>
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate * Function prototypes
677c478bd9Sstevel@tonic-gate */
687c478bd9Sstevel@tonic-gate static void cistpl_pd_parse(cistpl_t *, cistpl_cftable_entry_pwr_t *);
697c478bd9Sstevel@tonic-gate static void cis_return_name(cistpl_callout_t *, cistpl_get_tuple_name_t *);
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate /*
72*5f9e250aShx147065 * Fetch data functions.
73*5f9e250aShx147065 */
74*5f9e250aShx147065 uint16_t
cis_get_short(cistpl_t * tp)75*5f9e250aShx147065 cis_get_short(cistpl_t *tp)
76*5f9e250aShx147065 {
77*5f9e250aShx147065 uint16_t result;
78*5f9e250aShx147065
79*5f9e250aShx147065 if (tp->flags & CISTPLF_AM_SPACE) {
80*5f9e250aShx147065 result = GET_AM_BYTE(tp);
81*5f9e250aShx147065 result |= GET_AM_BYTE(tp) << 8;
82*5f9e250aShx147065 } else {
83*5f9e250aShx147065 result = GET_CM_BYTE(tp);
84*5f9e250aShx147065 result |= GET_CM_BYTE(tp) << 8;
85*5f9e250aShx147065 }
86*5f9e250aShx147065 return (result);
87*5f9e250aShx147065 }
88*5f9e250aShx147065
89*5f9e250aShx147065 uint16_t
cis_get_be_short(cistpl_t * tp)90*5f9e250aShx147065 cis_get_be_short(cistpl_t *tp)
91*5f9e250aShx147065 {
92*5f9e250aShx147065 uint16_t result;
93*5f9e250aShx147065
94*5f9e250aShx147065 if (tp->flags & CISTPLF_AM_SPACE) {
95*5f9e250aShx147065 result = GET_AM_BYTE(tp) << 8;
96*5f9e250aShx147065 result |= GET_AM_BYTE(tp);
97*5f9e250aShx147065 } else {
98*5f9e250aShx147065 result = GET_CM_BYTE(tp) << 8;
99*5f9e250aShx147065 result |= GET_CM_BYTE(tp);
100*5f9e250aShx147065 }
101*5f9e250aShx147065 return (result);
102*5f9e250aShx147065 }
103*5f9e250aShx147065
104*5f9e250aShx147065 uint32_t
cis_get_int24(cistpl_t * tp)105*5f9e250aShx147065 cis_get_int24(cistpl_t *tp)
106*5f9e250aShx147065 {
107*5f9e250aShx147065 uint32_t result = cis_get_short(tp);
108*5f9e250aShx147065
109*5f9e250aShx147065 result |= GET_BYTE(tp) << 16;
110*5f9e250aShx147065 return (result);
111*5f9e250aShx147065 }
112*5f9e250aShx147065
113*5f9e250aShx147065 uint32_t
cis_get_long(cistpl_t * tp)114*5f9e250aShx147065 cis_get_long(cistpl_t *tp)
115*5f9e250aShx147065 {
116*5f9e250aShx147065 uint32_t result = cis_get_short(tp);
117*5f9e250aShx147065
118*5f9e250aShx147065 result |= cis_get_short(tp) << 16;
119*5f9e250aShx147065 return (result);
120*5f9e250aShx147065 }
121*5f9e250aShx147065
122*5f9e250aShx147065 /*
1237c478bd9Sstevel@tonic-gate * cis_tuple_handler - call the handler for the tuple described by the
1247c478bd9Sstevel@tonic-gate * tuple pointer
1257c478bd9Sstevel@tonic-gate *
1267c478bd9Sstevel@tonic-gate * cistpl_callout_t *co - pointer to callout structure
1277c478bd9Sstevel@tonic-gate * array to use to find this tuple
1287c478bd9Sstevel@tonic-gate * cistpl_t *tp - pointer to a tuple structure
1297c478bd9Sstevel@tonic-gate * int flags - action for the handler to perform
1307c478bd9Sstevel@tonic-gate * XXX - we need a description of the flags passed to the tuple handler
1317c478bd9Sstevel@tonic-gate * void *arg - argument to pass on to tuple handler
1327c478bd9Sstevel@tonic-gate *
1337c478bd9Sstevel@tonic-gate * If the tuple is not recognized but is is a vendor-specific tuple, we
1347c478bd9Sstevel@tonic-gate * set the CISTPLF_VENDOR_SPECIFIC flag in the tuple.
1357c478bd9Sstevel@tonic-gate *
1367c478bd9Sstevel@tonic-gate * We return CISTPLF_UNKNOWN if this is an unrecognized tuple as well as
1377c478bd9Sstevel@tonic-gate * set the CISTPLF_UNKNOWN flag in the tuple list structure. Note
1387c478bd9Sstevel@tonic-gate * that encountering an unknown tuple is not necessarily an error,
1397c478bd9Sstevel@tonic-gate * so we don't set the HANDTPL_ERROR flag on the return code. It
1407c478bd9Sstevel@tonic-gate * is up to the caller to determine what an unrecognized tuple means.
1417c478bd9Sstevel@tonic-gate *
1427c478bd9Sstevel@tonic-gate * If this is a recognized tuple, the apropriate tuple handler is called and
1437c478bd9Sstevel@tonic-gate * the return value from the handler is returned directly to the caller.
1447c478bd9Sstevel@tonic-gate *
1457c478bd9Sstevel@tonic-gate * The void *arg is optional, and it's meaning is dependent on the
1467c478bd9Sstevel@tonic-gate * particular tuple handler called and the flags parameter.
1477c478bd9Sstevel@tonic-gate *
1487c478bd9Sstevel@tonic-gate * For the special case of HANDTPL_RETURN_NAME, we don't bother calling the
1497c478bd9Sstevel@tonic-gate * tuple handler and just return the tuple name to the caller.
1507c478bd9Sstevel@tonic-gate */
1517c478bd9Sstevel@tonic-gate uint32_t
cis_tuple_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg,cisdata_t subtype)1527c478bd9Sstevel@tonic-gate cis_tuple_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
1537c478bd9Sstevel@tonic-gate void *arg, cisdata_t subtype)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate /*
1567c478bd9Sstevel@tonic-gate * Check to see if this is a vendor-specific tuple.
1577c478bd9Sstevel@tonic-gate */
1587c478bd9Sstevel@tonic-gate if (CISTPL_IS_VENDOR_SPECIFIC(tp->type))
1597c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_VENDOR_SPECIFIC;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate /*
1627c478bd9Sstevel@tonic-gate * Scan the callout list until we find the tuple passed to us, or we
1637c478bd9Sstevel@tonic-gate * encounter a CISTPL_END in the callout list, which signals that
1647c478bd9Sstevel@tonic-gate * there are no more tuples in the callout list.
1657c478bd9Sstevel@tonic-gate */
1667c478bd9Sstevel@tonic-gate while (co->type != (cisdata_t)CISTPL_END) {
1677c478bd9Sstevel@tonic-gate if (co->type == tp->type &&
1687c478bd9Sstevel@tonic-gate ((tp->type != CISTPL_FUNCE) ||
1697c478bd9Sstevel@tonic-gate (tp->type == CISTPL_FUNCE && co->subtype == subtype))) {
1707c478bd9Sstevel@tonic-gate tp->flags &= ~CISTPLF_UNKNOWN;
1717c478bd9Sstevel@tonic-gate if (flags & HANDTPL_RETURN_NAME) {
1727c478bd9Sstevel@tonic-gate cis_return_name(co, (cistpl_get_tuple_name_t *)arg);
1737c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
1747c478bd9Sstevel@tonic-gate } else {
1757c478bd9Sstevel@tonic-gate return ((*co->handler) (co, tp, flags, arg));
1767c478bd9Sstevel@tonic-gate } /* HANDTPL_RETURN_NAME */
1777c478bd9Sstevel@tonic-gate } /* if */
1787c478bd9Sstevel@tonic-gate co++;
1797c478bd9Sstevel@tonic-gate } /* while */
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate * If we didn't recognize the tuple and the caller wants the tuple
1837c478bd9Sstevel@tonic-gate * name back, then return the "unknown tuple" string. At this
1847c478bd9Sstevel@tonic-gate * point, "co" will be pointing to the last entry in the
1857c478bd9Sstevel@tonic-gate * callout list. It's not an error to not recognize the tuple
1867c478bd9Sstevel@tonic-gate * when the operation is HANDTPL_RETURN_NAME.
1877c478bd9Sstevel@tonic-gate */
1887c478bd9Sstevel@tonic-gate if (flags & HANDTPL_RETURN_NAME) {
1897c478bd9Sstevel@tonic-gate cis_return_name(co, (cistpl_get_tuple_name_t *)arg);
1907c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_UNKNOWN;
1947c478bd9Sstevel@tonic-gate return (CISTPLF_UNKNOWN);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate * cis_no_tuple_handler - this generic tuple handler is used if no special
1997c478bd9Sstevel@tonic-gate * tuple processing is required for the passed
2007c478bd9Sstevel@tonic-gate * tuple
2017c478bd9Sstevel@tonic-gate *
2027c478bd9Sstevel@tonic-gate * cistpl_callout_t *co - pointer to this tuple's entry in the
2037c478bd9Sstevel@tonic-gate * tuple callout structure
2047c478bd9Sstevel@tonic-gate * cistpl_t *tp - pointer to this tuple's entry in the local linked list
2057c478bd9Sstevel@tonic-gate * int flags - action to perform
2067c478bd9Sstevel@tonic-gate *
2077c478bd9Sstevel@tonic-gate * This handler will set the CISTPLF_COPYOK flag if the tuple link is greater
2087c478bd9Sstevel@tonic-gate * than zero, indicating that it's OK to copy the tuple data body. It
2097c478bd9Sstevel@tonic-gate * will also set whatever flags are specified in the callout structure.
2107c478bd9Sstevel@tonic-gate *
2117c478bd9Sstevel@tonic-gate * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE.
2127c478bd9Sstevel@tonic-gate *
2137c478bd9Sstevel@tonic-gate * We return CISTPLF_UNKNOWN if we're being called to parse the tuple.
2147c478bd9Sstevel@tonic-gate *
2157c478bd9Sstevel@tonic-gate * We return CISTPLF_NOERROR in every other case to indicate that this is a
2167c478bd9Sstevel@tonic-gate * recognized tuple.
2177c478bd9Sstevel@tonic-gate */
2187c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2197c478bd9Sstevel@tonic-gate uint32_t
cis_no_tuple_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)2207c478bd9Sstevel@tonic-gate cis_no_tuple_handler(cistpl_callout_t *co, cistpl_t *tp,
2217c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS) {
2247c478bd9Sstevel@tonic-gate tp->flags |= co->flags; /* XXX - is = the right thing here? */
2257c478bd9Sstevel@tonic-gate if (tp->len > 0)
2267c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_COPYOK;
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
2307c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE)
2337c478bd9Sstevel@tonic-gate return (CISTPLF_UNKNOWN);
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate * cis_unknown_tuple_handler - this generic tuple handler is used if we don't
2407c478bd9Sstevel@tonic-gate * understand this tuple
2417c478bd9Sstevel@tonic-gate *
2427c478bd9Sstevel@tonic-gate * cistpl_callout_t *co - pointer to this tuple's entry in the
2437c478bd9Sstevel@tonic-gate * tuple callout structure
2447c478bd9Sstevel@tonic-gate * cistpl_t *tp - pointer to this tuple's entry in the local linked list
2457c478bd9Sstevel@tonic-gate * int flags - action to perform
2467c478bd9Sstevel@tonic-gate *
2477c478bd9Sstevel@tonic-gate * This handler will not set the CISTPLF_COPYOK flag since we don't know the
2487c478bd9Sstevel@tonic-gate * contents of a vendor-specific tuple.
2497c478bd9Sstevel@tonic-gate *
2507c478bd9Sstevel@tonic-gate * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE
2517c478bd9Sstevel@tonic-gate * to specify that we understand this tuple's code, but not it's data
2527c478bd9Sstevel@tonic-gate * body.
2537c478bd9Sstevel@tonic-gate *
2547c478bd9Sstevel@tonic-gate * We return CISTPLF_UNKNOWN if we're being called to parse the tuple or to
2557c478bd9Sstevel@tonic-gate * perform any other operation.
2567c478bd9Sstevel@tonic-gate */
2577c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2587c478bd9Sstevel@tonic-gate uint32_t
cis_unknown_tuple_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)2597c478bd9Sstevel@tonic-gate cis_unknown_tuple_handler(cistpl_callout_t *co, cistpl_t *tp,
2607c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
2617c478bd9Sstevel@tonic-gate {
2627c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS) {
2637c478bd9Sstevel@tonic-gate tp->flags |= co->flags; /* XXX - is = the right thing here? */
2647c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE) {
2687c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
2697c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate return (CISTPLF_UNKNOWN);
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate /*
2767c478bd9Sstevel@tonic-gate * cistpl_vers_1_handler - handler for the CISTPL_VERS_1 tuple
2777c478bd9Sstevel@tonic-gate *
2787c478bd9Sstevel@tonic-gate * void *arg - points to a cistpl_vers_1_t * where the
2797c478bd9Sstevel@tonic-gate * information is stuffed into
2807c478bd9Sstevel@tonic-gate */
2817c478bd9Sstevel@tonic-gate uint32_t
cistpl_vers_1_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)2827c478bd9Sstevel@tonic-gate cistpl_vers_1_handler(cistpl_callout_t *co, cistpl_t *tp,
2837c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
2847c478bd9Sstevel@tonic-gate {
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
2877c478bd9Sstevel@tonic-gate * generic handler for this
2887c478bd9Sstevel@tonic-gate */
2897c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
2907c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate /*
2937c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
2947c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
2957c478bd9Sstevel@tonic-gate */
2967c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
2977c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
3007c478bd9Sstevel@tonic-gate cistpl_vers_1_t *cs = (cistpl_vers_1_t *)arg;
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate RESET_TP(tp);
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate cs->major = GET_BYTE(tp);
3067c478bd9Sstevel@tonic-gate cs->minor = GET_BYTE(tp);
3077c478bd9Sstevel@tonic-gate for (cs->ns = 0; GET_LEN(tp) > 0 &&
3087c478bd9Sstevel@tonic-gate /* CSTYLED */
3097c478bd9Sstevel@tonic-gate cs->ns < CISTPL_VERS_1_MAX_PROD_STRINGS; ) {
3107c478bd9Sstevel@tonic-gate (void) strcpy(cs->pi[cs->ns++], cis_getstr(tp));
3117c478bd9Sstevel@tonic-gate } /* for */
3127c478bd9Sstevel@tonic-gate } /* HANDTPL_PARSE_LTUPLE */
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate /*
3187c478bd9Sstevel@tonic-gate * cistpl_config_handler - handler for the CISTPL_CONFIG tuple
3197c478bd9Sstevel@tonic-gate *
3207c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
3217c478bd9Sstevel@tonic-gate *
3227c478bd9Sstevel@tonic-gate * For the first ten config registers we set the present flags in the
3237c478bd9Sstevel@tonic-gate * cistpl_config_t if the register exists. The flags that we use
3247c478bd9Sstevel@tonic-gate * for this are the same as the flags reguired for the Card Services
3257c478bd9Sstevel@tonic-gate * RequestConfiguration function and they can be used by clients
3267c478bd9Sstevel@tonic-gate * directly without requiring any remapping of values.
3277c478bd9Sstevel@tonic-gate *
3287c478bd9Sstevel@tonic-gate * XXX we don't handle TPCC_SBTPL subtuples yet
3297c478bd9Sstevel@tonic-gate */
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate uint32_t config_regs_present_map[] = {
3327c478bd9Sstevel@tonic-gate CONFIG_OPTION_REG_PRESENT, /* COR present */
3337c478bd9Sstevel@tonic-gate CONFIG_STATUS_REG_PRESENT, /* STAT reg present */
3347c478bd9Sstevel@tonic-gate CONFIG_PINREPL_REG_PRESENT, /* PRR present */
3357c478bd9Sstevel@tonic-gate CONFIG_COPY_REG_PRESENT, /* COPY reg present */
3367c478bd9Sstevel@tonic-gate CONFIG_EXSTAT_REG_PRESENT, /* EXSTAT reg present */
3377c478bd9Sstevel@tonic-gate CONFIG_IOBASE0_REG_PRESENT, /* IOBASE0 reg present */
3387c478bd9Sstevel@tonic-gate CONFIG_IOBASE1_REG_PRESENT, /* IOBASE1 reg present */
3397c478bd9Sstevel@tonic-gate CONFIG_IOBASE2_REG_PRESENT, /* IOBASE2 reg present */
3407c478bd9Sstevel@tonic-gate CONFIG_IOBASE3_REG_PRESENT, /* IOBASE3 reg present */
3417c478bd9Sstevel@tonic-gate CONFIG_IOLIMIT_REG_PRESENT, /* IOLIMIT reg present */
3427c478bd9Sstevel@tonic-gate };
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate uint32_t
cistpl_config_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)3457c478bd9Sstevel@tonic-gate cistpl_config_handler(cistpl_callout_t *co, cistpl_t *tp,
3467c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate cisdata_t tpcc_sz;
3497c478bd9Sstevel@tonic-gate int i, n, nrb, na, hr = 0;
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate /*
3527c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
3537c478bd9Sstevel@tonic-gate * generic handler for this
3547c478bd9Sstevel@tonic-gate */
3557c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
3567c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate /*
3597c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
3607c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
3617c478bd9Sstevel@tonic-gate */
3627c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
3637c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
3667c478bd9Sstevel@tonic-gate cistpl_config_t *cr = (cistpl_config_t *)arg;
3677c478bd9Sstevel@tonic-gate int crn = 0;
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate RESET_TP(tp);
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate tpcc_sz = GET_BYTE(tp); /* config regs size fields */
3727c478bd9Sstevel@tonic-gate cr->last = GET_BYTE(tp); /* last config index */
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate na = (tpcc_sz&3)+1; /* config regs address bytes */
3757c478bd9Sstevel@tonic-gate nrb = ((tpcc_sz>>2)&0x0f)+1; /* number of bytes in config */
3767c478bd9Sstevel@tonic-gate /* regs presence mask */
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate /*
3797c478bd9Sstevel@tonic-gate * Construct the base offset address for the config registers.
3807c478bd9Sstevel@tonic-gate * We jump through these hoops because the base address
3817c478bd9Sstevel@tonic-gate * can be between one and four bytes in length.
3827c478bd9Sstevel@tonic-gate */
3837c478bd9Sstevel@tonic-gate cr->base = 0;
3847c478bd9Sstevel@tonic-gate n = na;
3857c478bd9Sstevel@tonic-gate while (n--)
3867c478bd9Sstevel@tonic-gate cr->base |= ((GET_BYTE(tp) & 0x0ff) <<
3877c478bd9Sstevel@tonic-gate (8 * (na - (n+1))));
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate /*
3907c478bd9Sstevel@tonic-gate * Go through the config register presense mask bit by bit and
3917c478bd9Sstevel@tonic-gate * figure out which config registers are present and which
3927c478bd9Sstevel@tonic-gate * aren't.
3937c478bd9Sstevel@tonic-gate * For the first ten config registers, set the appropriate
3947c478bd9Sstevel@tonic-gate * bits in the cr->present member so that the caller
3957c478bd9Sstevel@tonic-gate * doesn't have to do this.
3967c478bd9Sstevel@tonic-gate */
3977c478bd9Sstevel@tonic-gate cr->nr = 0;
3987c478bd9Sstevel@tonic-gate cr->present = 0;
3997c478bd9Sstevel@tonic-gate n = nrb;
4007c478bd9Sstevel@tonic-gate while (n--) {
4017c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++, crn++) {
4027c478bd9Sstevel@tonic-gate if (LOOK_BYTE(tp) & (1<<i)) {
4037c478bd9Sstevel@tonic-gate if (crn < (sizeof (config_regs_present_map)/
4047c478bd9Sstevel@tonic-gate sizeof (uint32_t)))
4057c478bd9Sstevel@tonic-gate cr->present |=
4067c478bd9Sstevel@tonic-gate config_regs_present_map[crn];
4077c478bd9Sstevel@tonic-gate cr->nr++;
4087c478bd9Sstevel@tonic-gate cr->hr = hr;
4097c478bd9Sstevel@tonic-gate cr->regs[hr] = MAKE_CONFIG_REG_ADDR(
4107c478bd9Sstevel@tonic-gate cr->base, hr);
4117c478bd9Sstevel@tonic-gate } /* LOOK_BYTE */
4127c478bd9Sstevel@tonic-gate hr++;
4137c478bd9Sstevel@tonic-gate } /* for */
4147c478bd9Sstevel@tonic-gate (void) GET_BYTE(tp);
4157c478bd9Sstevel@tonic-gate } /* while */
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate /*
4227c478bd9Sstevel@tonic-gate * cistpl_device_handler - handler for the CISTPL_DEVICE, CISTPL_DEVICE_A,
4237c478bd9Sstevel@tonic-gate * CISTPL_DEVICE_OC and CISTPL_DEVICE_OA tuples
4247c478bd9Sstevel@tonic-gate *
4257c478bd9Sstevel@tonic-gate * void *arg - points to a cistpl_device_t * where the
4267c478bd9Sstevel@tonic-gate * information is stuffed into
4277c478bd9Sstevel@tonic-gate *
4287c478bd9Sstevel@tonic-gate * XXX - we only handle CISTPL_DEVICE_MAX_DEVICES device descriptions
4297c478bd9Sstevel@tonic-gate * described in the tuple
4307c478bd9Sstevel@tonic-gate */
4317c478bd9Sstevel@tonic-gate uint32_t
cistpl_device_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)4327c478bd9Sstevel@tonic-gate cistpl_device_handler(cistpl_callout_t *co, cistpl_t *tp,
4337c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate cisdata_t dev_id;
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate /*
4387c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
4397c478bd9Sstevel@tonic-gate * generic handler for this
4407c478bd9Sstevel@tonic-gate */
4417c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
4427c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate /*
4457c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
4467c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
4477c478bd9Sstevel@tonic-gate */
4487c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
4497c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
4527c478bd9Sstevel@tonic-gate convert_speed_t convert_speed;
4537c478bd9Sstevel@tonic-gate cistpl_device_t *dt = (cistpl_device_t *)arg;
4547c478bd9Sstevel@tonic-gate cistpl_device_node_t *cdn;
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate /*
4577c478bd9Sstevel@tonic-gate * XXX - fix this to look for more than one device definition
4587c478bd9Sstevel@tonic-gate * XXX - fix this to handle the OC fields for
4597c478bd9Sstevel@tonic-gate * CISTPL_DEVICE_OC and CISTPL_DEVICE_OA
4607c478bd9Sstevel@tonic-gate */
4617c478bd9Sstevel@tonic-gate dt->num_devices = 1;
4627c478bd9Sstevel@tonic-gate cdn = &dt->devnode[0];
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate cdn->flags = 0;
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate RESET_TP(tp);
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate dev_id = GET_BYTE(tp);
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate /*
4717c478bd9Sstevel@tonic-gate * Get the device speed code. If it's 7, then there is an
4727c478bd9Sstevel@tonic-gate * extended speed code table in use, so parse that.
4737c478bd9Sstevel@tonic-gate * If it's anything else, get the speed information
4747c478bd9Sstevel@tonic-gate * directly from the device speed code.
4757c478bd9Sstevel@tonic-gate */
4767c478bd9Sstevel@tonic-gate if ((dev_id & 7) == 7) {
4777c478bd9Sstevel@tonic-gate cdn->nS_speed = cistpl_devspeed(tp, 0, CISTPL_DEVSPEED_EXT);
4787c478bd9Sstevel@tonic-gate } else {
4797c478bd9Sstevel@tonic-gate cdn->nS_speed = cistpl_devspeed(NULL, dev_id,
4807c478bd9Sstevel@tonic-gate CISTPL_DEVSPEED_TABLE);
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate /*
4847c478bd9Sstevel@tonic-gate * Convert the speed in nS to a device speed code.
4857c478bd9Sstevel@tonic-gate * XXX - should check return code from cis_convert_devspeed()
4867c478bd9Sstevel@tonic-gate */
4877c478bd9Sstevel@tonic-gate convert_speed.Attributes = CONVERT_NS_TO_DEVSPEED;
4887c478bd9Sstevel@tonic-gate convert_speed.nS = cdn->nS_speed;
4897c478bd9Sstevel@tonic-gate (void) cis_convert_devspeed(&convert_speed);
4907c478bd9Sstevel@tonic-gate cdn->speed = convert_speed.devspeed;
4917c478bd9Sstevel@tonic-gate
4927c478bd9Sstevel@tonic-gate if (dev_id & 8)
4937c478bd9Sstevel@tonic-gate cdn->flags |= CISTPL_DEVICE_WPS;
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate /*
4967c478bd9Sstevel@tonic-gate * Set the device type. Note that we take the raw value
4977c478bd9Sstevel@tonic-gate * from the tuple and pass it back to the caller.
4987c478bd9Sstevel@tonic-gate * If the device type codes in the standard change,
4997c478bd9Sstevel@tonic-gate * we will have to change our flags as well.
5007c478bd9Sstevel@tonic-gate */
5017c478bd9Sstevel@tonic-gate cdn->type = (dev_id>>4) & 0x0f;
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate /*
5047c478bd9Sstevel@tonic-gate * XXX - what about the device_size byte? Is the spec wrong?
5057c478bd9Sstevel@tonic-gate */
5067c478bd9Sstevel@tonic-gate cdn->size = GET_BYTE(tp);
5077c478bd9Sstevel@tonic-gate /* check for end of list */
5087c478bd9Sstevel@tonic-gate if (cdn->size != 0x0ff) {
5097c478bd9Sstevel@tonic-gate convert_size_t convert_size;
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate convert_size.devsize = cdn->size;
5127c478bd9Sstevel@tonic-gate convert_size.Attributes = CONVERT_DEVSIZE_TO_BYTES;
5137c478bd9Sstevel@tonic-gate (void) cis_convert_devsize(&convert_size);
5147c478bd9Sstevel@tonic-gate cdn->size_in_bytes = convert_size.bytes;
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate /*
5227c478bd9Sstevel@tonic-gate * cistpl_cftable_handler - handler for the CISTPL_CFTABLE_ENTRY tuple
5237c478bd9Sstevel@tonic-gate *
5247c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
5257c478bd9Sstevel@tonic-gate *
5267c478bd9Sstevel@tonic-gate * Return: CISTPLF_NOERROR - if no error parsing tuple
5277c478bd9Sstevel@tonic-gate * HANDTPL_ERROR - if error parsing tuple
5287c478bd9Sstevel@tonic-gate */
5297c478bd9Sstevel@tonic-gate extern uint32_t cistpl_cftable_io_size_table[];
5307c478bd9Sstevel@tonic-gate extern uint32_t cistpl_cftable_shift_table[];
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate uint32_t
cistpl_cftable_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)5337c478bd9Sstevel@tonic-gate cistpl_cftable_handler(cistpl_callout_t *co, cistpl_t *tp,
5347c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
5357c478bd9Sstevel@tonic-gate {
5367c478bd9Sstevel@tonic-gate cisdata_t tpce_indx, tpce_fs, tpce_td, sf, tpce_io, nr;
5377c478bd9Sstevel@tonic-gate cisdata_t ior_desc, tpce_ir, tpce_msd;
5387c478bd9Sstevel@tonic-gate int i, j;
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate /*
5417c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
5427c478bd9Sstevel@tonic-gate * generic handler for this
5437c478bd9Sstevel@tonic-gate */
5447c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
5457c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate /*
5487c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
5497c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
5507c478bd9Sstevel@tonic-gate */
5517c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
5527c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
5557c478bd9Sstevel@tonic-gate cistpl_cftable_entry_t *ce = (cistpl_cftable_entry_t *)arg;
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate RESET_TP(tp);
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate * Check to see if we have an interface description byte. If
5617c478bd9Sstevel@tonic-gate * we do, grab it and give it directly to the caller, and
5627c478bd9Sstevel@tonic-gate * set a flag so the caller knows that it's there.
5637c478bd9Sstevel@tonic-gate * We also setup the appropriate values in the ce->pin member
5647c478bd9Sstevel@tonic-gate * so that clients can feed this value directly to the
5657c478bd9Sstevel@tonic-gate * Card Services RequestConfiguration call.
5667c478bd9Sstevel@tonic-gate */
5677c478bd9Sstevel@tonic-gate if ((tpce_indx = GET_BYTE(tp)) & CISTPL_CFTABLE_TPCE_IFM) {
5687c478bd9Sstevel@tonic-gate ce->ifc = GET_BYTE(tp);
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate ce->pin = 0;
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_BVD)
5737c478bd9Sstevel@tonic-gate ce->pin |= (PRR_BVD1_STATUS | PRR_BVD2_STATUS |
5747c478bd9Sstevel@tonic-gate PRR_BVD1_EVENT | PRR_BVD2_EVENT);
5757c478bd9Sstevel@tonic-gate if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_WP)
5767c478bd9Sstevel@tonic-gate ce->pin |= (PRR_WP_STATUS | PRR_WP_EVENT);
5777c478bd9Sstevel@tonic-gate if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_RDY)
5787c478bd9Sstevel@tonic-gate ce->pin |= (PRR_READY_STATUS | PRR_READY_EVENT);
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_IF;
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate /*
5847c478bd9Sstevel@tonic-gate * Return the configuration index to the caller, and set the
5857c478bd9Sstevel@tonic-gate * default configuration flag if this is a default
5867c478bd9Sstevel@tonic-gate * configuration.
5877c478bd9Sstevel@tonic-gate */
5887c478bd9Sstevel@tonic-gate ce->index = tpce_indx & CISTPL_CFTABLE_TPCE_CFGENTRYM;
5897c478bd9Sstevel@tonic-gate if (tpce_indx & CISTPL_CFTABLE_TPCE_DEFAULTM)
5907c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_DEFAULT;
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate /*
5937c478bd9Sstevel@tonic-gate * Feature selection flags.
5947c478bd9Sstevel@tonic-gate */
5957c478bd9Sstevel@tonic-gate tpce_fs = GET_BYTE(tp);
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate /*
5987c478bd9Sstevel@tonic-gate * See what types of power information are available,
5997c478bd9Sstevel@tonic-gate * and if there is any, set the global power
6007c478bd9Sstevel@tonic-gate * information flag as well as a flag for each
6017c478bd9Sstevel@tonic-gate * power description available.
6027c478bd9Sstevel@tonic-gate */
6037c478bd9Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_PWRM) {
6047c478bd9Sstevel@tonic-gate cistpl_cftable_entry_pd_t *pd = &ce->pd;
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_PWR;
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate switch (tpce_fs & CISTPL_CFTABLE_TPCE_FS_PWRM) {
6097c478bd9Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_PWR_VPP2M:
6107c478bd9Sstevel@tonic-gate pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VPP2;
6117c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
6127c478bd9Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_PWR_VPP1M:
6137c478bd9Sstevel@tonic-gate pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VPP1;
6147c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
6157c478bd9Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_PWR_VCCM:
6167c478bd9Sstevel@tonic-gate pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VCC;
6177c478bd9Sstevel@tonic-gate } /* switch */
6187c478bd9Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_PWRM) */
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate /*
6217c478bd9Sstevel@tonic-gate * Set up the global memory information flag.
6227c478bd9Sstevel@tonic-gate */
6237c478bd9Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MEMM)
6247c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_MEM;
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate /*
6277c478bd9Sstevel@tonic-gate * Parse the various power description structures.
6287c478bd9Sstevel@tonic-gate */
6297c478bd9Sstevel@tonic-gate if (ce->flags & CISTPL_CFTABLE_TPCE_FS_PWR) {
6307c478bd9Sstevel@tonic-gate cistpl_cftable_entry_pd_t *pd = &ce->pd;
6317c478bd9Sstevel@tonic-gate cistpl_cftable_entry_pwr_t *pwr;
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate * Collect any Vcc information.
6347c478bd9Sstevel@tonic-gate */
6357c478bd9Sstevel@tonic-gate if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VCC) {
6367c478bd9Sstevel@tonic-gate pwr = &pd->pd_vcc;
6377c478bd9Sstevel@tonic-gate cistpl_pd_parse(tp, pwr);
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate /*
6407c478bd9Sstevel@tonic-gate * Collect any Vpp1 information.
6417c478bd9Sstevel@tonic-gate */
6427c478bd9Sstevel@tonic-gate if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VPP1) {
6437c478bd9Sstevel@tonic-gate pwr = &pd->pd_vpp1;
6447c478bd9Sstevel@tonic-gate cistpl_pd_parse(tp, pwr);
6457c478bd9Sstevel@tonic-gate }
6467c478bd9Sstevel@tonic-gate /*
6477c478bd9Sstevel@tonic-gate * Collect any Vpp2 information.
6487c478bd9Sstevel@tonic-gate */
6497c478bd9Sstevel@tonic-gate if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VPP2) {
6507c478bd9Sstevel@tonic-gate pwr = &pd->pd_vpp2;
6517c478bd9Sstevel@tonic-gate cistpl_pd_parse(tp, pwr);
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_PWR) */
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate /*
6567c478bd9Sstevel@tonic-gate * Check to see if there's any timing information, and if
6577c478bd9Sstevel@tonic-gate * so, parse the tuple data and store it in the
6587c478bd9Sstevel@tonic-gate * caller's structure. Set a flag in the global
6597c478bd9Sstevel@tonic-gate * flag field indicating that there is timing information.
6607c478bd9Sstevel@tonic-gate */
6617c478bd9Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_TDM) {
6627c478bd9Sstevel@tonic-gate convert_speed_t convert_speed;
6637c478bd9Sstevel@tonic-gate cistpl_cftable_entry_speed_t *sp = &ce->speed;
6647c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_TD;
6657c478bd9Sstevel@tonic-gate tpce_td = GET_BYTE(tp);
6667c478bd9Sstevel@tonic-gate /*
6677c478bd9Sstevel@tonic-gate * Parse TPCE_TD to get the various timing
6687c478bd9Sstevel@tonic-gate * scale factors. Each scale factor has
6697c478bd9Sstevel@tonic-gate * a value that indicates that the particular
6707c478bd9Sstevel@tonic-gate * timing parameter doesn't exist.
6717c478bd9Sstevel@tonic-gate */
6727c478bd9Sstevel@tonic-gate if ((sf = (tpce_td &
6737c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_WAITM)) !=
6747c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_WAITM) {
6757c478bd9Sstevel@tonic-gate sp->nS_wait = cistpl_devspeed(tp,
6767c478bd9Sstevel@tonic-gate GET_TPCE_FS_TD_WAITS(sf),
6777c478bd9Sstevel@tonic-gate CISTPL_DEVSPEED_EXT);
6787c478bd9Sstevel@tonic-gate convert_speed.Attributes =
6797c478bd9Sstevel@tonic-gate CONVERT_NS_TO_DEVSPEED;
6807c478bd9Sstevel@tonic-gate convert_speed.nS = sp->nS_wait;
6817c478bd9Sstevel@tonic-gate (void) cis_convert_devspeed(&convert_speed);
6827c478bd9Sstevel@tonic-gate sp->wait = convert_speed.devspeed;
6837c478bd9Sstevel@tonic-gate sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_WAIT;
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate if ((sf = (tpce_td & CISTPL_CFTABLE_TPCE_FS_TD_RDYM)) !=
6877c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_RDYM) {
6887c478bd9Sstevel@tonic-gate sp->nS_rdybsy = cistpl_devspeed(tp,
6897c478bd9Sstevel@tonic-gate GET_TPCE_FS_TD_RDYS(sf),
6907c478bd9Sstevel@tonic-gate CISTPL_DEVSPEED_EXT);
6917c478bd9Sstevel@tonic-gate convert_speed.Attributes =
6927c478bd9Sstevel@tonic-gate CONVERT_NS_TO_DEVSPEED;
6937c478bd9Sstevel@tonic-gate convert_speed.nS = sp->nS_rdybsy;
6947c478bd9Sstevel@tonic-gate (void) cis_convert_devspeed(&convert_speed);
6957c478bd9Sstevel@tonic-gate sp->rdybsy = convert_speed.devspeed;
6967c478bd9Sstevel@tonic-gate sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_RDY;
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate if ((sf = (tpce_td &
7007c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_RSVDM)) !=
7017c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_RSVDM) {
7027c478bd9Sstevel@tonic-gate sp->nS_rsvd = cistpl_devspeed(tp,
7037c478bd9Sstevel@tonic-gate GET_TPCE_FS_TD_RSVDS(sf),
7047c478bd9Sstevel@tonic-gate CISTPL_DEVSPEED_EXT);
7057c478bd9Sstevel@tonic-gate convert_speed.Attributes =
7067c478bd9Sstevel@tonic-gate CONVERT_NS_TO_DEVSPEED;
7077c478bd9Sstevel@tonic-gate convert_speed.nS = sp->nS_rsvd;
7087c478bd9Sstevel@tonic-gate (void) cis_convert_devspeed(&convert_speed);
7097c478bd9Sstevel@tonic-gate sp->rsvd = convert_speed.devspeed;
7107c478bd9Sstevel@tonic-gate sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_RSVD;
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_TDM) */
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate
7157c478bd9Sstevel@tonic-gate /*
7167c478bd9Sstevel@tonic-gate * Parse any I/O address information. If there is I/O
7177c478bd9Sstevel@tonic-gate * inforamtion, set a flag in the global flag field
7187c478bd9Sstevel@tonic-gate * to let the caller know.
7197c478bd9Sstevel@tonic-gate */
7207c478bd9Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_IOM) {
7217c478bd9Sstevel@tonic-gate cistpl_cftable_entry_io_t *io = &ce->io;
7227c478bd9Sstevel@tonic-gate
7237c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_IO;
7247c478bd9Sstevel@tonic-gate tpce_io = GET_BYTE(tp);
7257c478bd9Sstevel@tonic-gate /*
7267c478bd9Sstevel@tonic-gate * Pass any I/O flags that are in the tuple directly
7277c478bd9Sstevel@tonic-gate * to the caller.
7287c478bd9Sstevel@tonic-gate */
7297c478bd9Sstevel@tonic-gate io->flags = tpce_io;
7307c478bd9Sstevel@tonic-gate io->addr_lines = tpce_io &
7317c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_IO_ALM;
7327c478bd9Sstevel@tonic-gate /*
7337c478bd9Sstevel@tonic-gate * If there are any ranges, extract the number of
7347c478bd9Sstevel@tonic-gate * ranges and the range descriptions.
7357c478bd9Sstevel@tonic-gate */
7367c478bd9Sstevel@tonic-gate if (tpce_io & CISTPL_CFTABLE_TPCE_FS_IO_RANGEM) {
7377c478bd9Sstevel@tonic-gate cistpl_cftable_entry_io_range_t *ior;
7387c478bd9Sstevel@tonic-gate ior_desc = GET_BYTE(tp);
7397c478bd9Sstevel@tonic-gate /*
7407c478bd9Sstevel@tonic-gate * Number of I/O ranges is the value specified
7417c478bd9Sstevel@tonic-gate * in the tuple plus one, so there's
7427c478bd9Sstevel@tonic-gate * always at least one I/O range if the
7437c478bd9Sstevel@tonic-gate * CISTPL_CFTABLE_TPCE_FS_IO_RANGEM bit
7447c478bd9Sstevel@tonic-gate * in the I/O flags register is set.
7457c478bd9Sstevel@tonic-gate */
7467c478bd9Sstevel@tonic-gate nr = (ior_desc & 0x0f) + 1;
7477c478bd9Sstevel@tonic-gate io->ranges = nr;
7487c478bd9Sstevel@tonic-gate /*
7497c478bd9Sstevel@tonic-gate * Cycle through each I/O range.
7507c478bd9Sstevel@tonic-gate */
7517c478bd9Sstevel@tonic-gate for (i = 0; i < (int)nr; i++) {
7527c478bd9Sstevel@tonic-gate ior = &io->range[i];
7537c478bd9Sstevel@tonic-gate ior->addr = 0;
7547c478bd9Sstevel@tonic-gate ior->length = 0;
7557c478bd9Sstevel@tonic-gate /*
7567c478bd9Sstevel@tonic-gate * Gather the address information.
7577c478bd9Sstevel@tonic-gate * It's OK if there's no address
7587c478bd9Sstevel@tonic-gate * information in which case this
7597c478bd9Sstevel@tonic-gate * loop will never execute.
7607c478bd9Sstevel@tonic-gate */
7617c478bd9Sstevel@tonic-gate for (j = 0; j <
7627c478bd9Sstevel@tonic-gate cistpl_cftable_io_size_table[
7637c478bd9Sstevel@tonic-gate (ior_desc>>4)&3];
7647c478bd9Sstevel@tonic-gate j++)
7657c478bd9Sstevel@tonic-gate ior->addr |= (GET_BYTE(tp) <<
7667c478bd9Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
7677c478bd9Sstevel@tonic-gate /*
7687c478bd9Sstevel@tonic-gate * Gather the length information.
7697c478bd9Sstevel@tonic-gate * It's OK if there's no length
7707c478bd9Sstevel@tonic-gate * information in which case this
7717c478bd9Sstevel@tonic-gate * loop will never execute.
7727c478bd9Sstevel@tonic-gate */
7737c478bd9Sstevel@tonic-gate for (j = 0; j <
7747c478bd9Sstevel@tonic-gate cistpl_cftable_io_size_table[
7757c478bd9Sstevel@tonic-gate (ior_desc>>6)&3];
7767c478bd9Sstevel@tonic-gate j++)
7777c478bd9Sstevel@tonic-gate ior->length |= (GET_BYTE(tp) <<
7787c478bd9Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
7797c478bd9Sstevel@tonic-gate } /* for (nr) */
7807c478bd9Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_IO_RANGEM) */
7817c478bd9Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_IOM) */
7827c478bd9Sstevel@tonic-gate
7837c478bd9Sstevel@tonic-gate /*
7847c478bd9Sstevel@tonic-gate * Parse any IRQ information. If there is IRQ inforamtion,
7857c478bd9Sstevel@tonic-gate * set a flag in the global flag field to let the
7867c478bd9Sstevel@tonic-gate * caller know.
7877c478bd9Sstevel@tonic-gate */
7887c478bd9Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_IRQM) {
7897c478bd9Sstevel@tonic-gate cistpl_cftable_entry_irq_t *irq = &ce->irq;
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_IRQ;
7927c478bd9Sstevel@tonic-gate tpce_ir = GET_BYTE(tp);
7937c478bd9Sstevel@tonic-gate /*
7947c478bd9Sstevel@tonic-gate * Pass any IRQ flags that are in the tuple directly
7957c478bd9Sstevel@tonic-gate * to the caller.
7967c478bd9Sstevel@tonic-gate */
7977c478bd9Sstevel@tonic-gate irq->flags = tpce_ir;
7987c478bd9Sstevel@tonic-gate /*
7997c478bd9Sstevel@tonic-gate * Check for and parse the extended IRQ bitmask
8007c478bd9Sstevel@tonic-gate * if it exists.
8017c478bd9Sstevel@tonic-gate */
8027c478bd9Sstevel@tonic-gate if (tpce_ir & CISTPL_CFTABLE_TPCE_FS_IRQ_MASKM) {
8037c478bd9Sstevel@tonic-gate irq->irqs = GET_BYTE(tp) & 0x0ff;
8047c478bd9Sstevel@tonic-gate irq->irqs |= (GET_BYTE(tp) << 8)&0x0ff00;
8057c478bd9Sstevel@tonic-gate } else {
8067c478bd9Sstevel@tonic-gate irq->irqs = (1<< (tpce_ir&0x0f));
8077c478bd9Sstevel@tonic-gate }
8087c478bd9Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_IRQM) */
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate /*
8117c478bd9Sstevel@tonic-gate * Parse any memory information.
8127c478bd9Sstevel@tonic-gate *
8137c478bd9Sstevel@tonic-gate * XXX - should be a cleaner way to parse this information.
8147c478bd9Sstevel@tonic-gate */
8157c478bd9Sstevel@tonic-gate if (ce->flags & CISTPL_CFTABLE_TPCE_FS_MEM) {
8167c478bd9Sstevel@tonic-gate cistpl_cftable_entry_mem_t *mem = &ce->mem;
8177c478bd9Sstevel@tonic-gate cistpl_cftable_entry_mem_window_t *win;
8187c478bd9Sstevel@tonic-gate /*
8197c478bd9Sstevel@tonic-gate * Switch on the type of memory description
8207c478bd9Sstevel@tonic-gate * information that is available.
8217c478bd9Sstevel@tonic-gate */
8227c478bd9Sstevel@tonic-gate switch (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MEMM) {
8237c478bd9Sstevel@tonic-gate /*
8247c478bd9Sstevel@tonic-gate * variable length memory space description
8257c478bd9Sstevel@tonic-gate */
8267c478bd9Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_MEM3M:
8277c478bd9Sstevel@tonic-gate mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM3;
8287c478bd9Sstevel@tonic-gate /* memory space descriptor */
8297c478bd9Sstevel@tonic-gate tpce_msd = GET_BYTE(tp);
8307c478bd9Sstevel@tonic-gate mem->windows = ((tpce_msd &
8317c478bd9Sstevel@tonic-gate (CISTPL_CFTABLE_ENTRY_MAX_MEM_WINDOWS -
8327c478bd9Sstevel@tonic-gate 1)) + 1);
8337c478bd9Sstevel@tonic-gate /*
8347c478bd9Sstevel@tonic-gate * If there's host address information, let
8357c478bd9Sstevel@tonic-gate * the caller know.
8367c478bd9Sstevel@tonic-gate */
8377c478bd9Sstevel@tonic-gate if (tpce_msd & CISTPL_CFTABLE_TPCE_FS_MEM_HOSTM)
8387c478bd9Sstevel@tonic-gate mem->flags |=
8397c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_HOST;
8407c478bd9Sstevel@tonic-gate /*
8417c478bd9Sstevel@tonic-gate * Cycle through each window space description
8427c478bd9Sstevel@tonic-gate * and collect all the interesting bits.
8437c478bd9Sstevel@tonic-gate */
8447c478bd9Sstevel@tonic-gate for (i = 0; i < mem->windows; i++) {
8457c478bd9Sstevel@tonic-gate win = &mem->window[i];
8467c478bd9Sstevel@tonic-gate win->length = 0;
8477c478bd9Sstevel@tonic-gate win->card_addr = 0;
8487c478bd9Sstevel@tonic-gate win->host_addr = 0;
8497c478bd9Sstevel@tonic-gate /*
8507c478bd9Sstevel@tonic-gate * Gather the length information.
8517c478bd9Sstevel@tonic-gate * It's OK if there's no length
8527c478bd9Sstevel@tonic-gate * information in which case this
8537c478bd9Sstevel@tonic-gate * loop will never execute.
8547c478bd9Sstevel@tonic-gate */
8557c478bd9Sstevel@tonic-gate for (j = 0; j <
8567c478bd9Sstevel@tonic-gate (int)((tpce_msd>>3)&3); j++)
8577c478bd9Sstevel@tonic-gate win->length |= (GET_BYTE(tp) <<
8587c478bd9Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
8597c478bd9Sstevel@tonic-gate /*
8607c478bd9Sstevel@tonic-gate * Gather the card address information.
8617c478bd9Sstevel@tonic-gate * It's OK if there's no card
8627c478bd9Sstevel@tonic-gate * address information in which
8637c478bd9Sstevel@tonic-gate * case this loop will never
8647c478bd9Sstevel@tonic-gate * execute.
8657c478bd9Sstevel@tonic-gate */
8667c478bd9Sstevel@tonic-gate for (j = 0; j <
8677c478bd9Sstevel@tonic-gate (int)((tpce_msd>>5)&3); j++)
8687c478bd9Sstevel@tonic-gate win->card_addr |=
8697c478bd9Sstevel@tonic-gate (GET_BYTE(tp) <<
8707c478bd9Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
8717c478bd9Sstevel@tonic-gate /*
8727c478bd9Sstevel@tonic-gate * If there's a host address
8737c478bd9Sstevel@tonic-gate * description, grab that
8747c478bd9Sstevel@tonic-gate * as well.
8757c478bd9Sstevel@tonic-gate */
8767c478bd9Sstevel@tonic-gate if (mem->flags &
8777c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_HOST) {
8787c478bd9Sstevel@tonic-gate /*
8797c478bd9Sstevel@tonic-gate * Gather the host address
8807c478bd9Sstevel@tonic-gate * information. It's OK
8817c478bd9Sstevel@tonic-gate * if there's no host
8827c478bd9Sstevel@tonic-gate * address information in
8837c478bd9Sstevel@tonic-gate * which case this loop
8847c478bd9Sstevel@tonic-gate * will never execute.
8857c478bd9Sstevel@tonic-gate * Note that we use the card
8867c478bd9Sstevel@tonic-gate * address size to
8877c478bd9Sstevel@tonic-gate * determine how many
8887c478bd9Sstevel@tonic-gate * bytes of host address
8897c478bd9Sstevel@tonic-gate * are present.
8907c478bd9Sstevel@tonic-gate */
8917c478bd9Sstevel@tonic-gate for (j = 0; j <
8927c478bd9Sstevel@tonic-gate (int)((tpce_msd>>5)&3);
8937c478bd9Sstevel@tonic-gate j++)
8947c478bd9Sstevel@tonic-gate win->host_addr |=
8957c478bd9Sstevel@tonic-gate (GET_BYTE(tp) <<
8967c478bd9Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
8977c478bd9Sstevel@tonic-gate } else {
8987c478bd9Sstevel@tonic-gate /*
8997c478bd9Sstevel@tonic-gate * No host address information,
9007c478bd9Sstevel@tonic-gate * so the host address is
9017c478bd9Sstevel@tonic-gate * equal to the card
9027c478bd9Sstevel@tonic-gate * address.
9037c478bd9Sstevel@tonic-gate */
9047c478bd9Sstevel@tonic-gate win->host_addr = win->card_addr;
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate } /* for (i<mem->windows) */
9077c478bd9Sstevel@tonic-gate break;
9087c478bd9Sstevel@tonic-gate /*
9097c478bd9Sstevel@tonic-gate * single length and card base address specified
9107c478bd9Sstevel@tonic-gate */
9117c478bd9Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_MEM2M:
9127c478bd9Sstevel@tonic-gate mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM2;
9137c478bd9Sstevel@tonic-gate win = &mem->window[0];
9147c478bd9Sstevel@tonic-gate mem->windows = 1;
9157c478bd9Sstevel@tonic-gate /*
9167c478bd9Sstevel@tonic-gate * Construct the size of the window.
9177c478bd9Sstevel@tonic-gate */
9187c478bd9Sstevel@tonic-gate win->length = GET_BYTE(tp);
9197c478bd9Sstevel@tonic-gate win->length |= (GET_BYTE(tp)<<8);
9207c478bd9Sstevel@tonic-gate win->length *=
9217c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE;
9227c478bd9Sstevel@tonic-gate
9237c478bd9Sstevel@tonic-gate /*
9247c478bd9Sstevel@tonic-gate * Construct the card base address.
9257c478bd9Sstevel@tonic-gate */
9267c478bd9Sstevel@tonic-gate win->card_addr = GET_BYTE(tp);
9277c478bd9Sstevel@tonic-gate win->card_addr |= (GET_BYTE(tp)<<8);
9287c478bd9Sstevel@tonic-gate win->card_addr *=
9297c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE;
9307c478bd9Sstevel@tonic-gate
9317c478bd9Sstevel@tonic-gate /*
9327c478bd9Sstevel@tonic-gate * In this mode, both the host base address
9337c478bd9Sstevel@tonic-gate * and the card base address are equal.
9347c478bd9Sstevel@tonic-gate */
9357c478bd9Sstevel@tonic-gate win->host_addr = win->card_addr;
9367c478bd9Sstevel@tonic-gate break;
9377c478bd9Sstevel@tonic-gate /*
9387c478bd9Sstevel@tonic-gate * single length specified
9397c478bd9Sstevel@tonic-gate */
9407c478bd9Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_MEM1M:
9417c478bd9Sstevel@tonic-gate mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM1;
9427c478bd9Sstevel@tonic-gate win = &mem->window[0];
9437c478bd9Sstevel@tonic-gate mem->windows = 1;
9447c478bd9Sstevel@tonic-gate win->card_addr = 0;
9457c478bd9Sstevel@tonic-gate win->host_addr = 0;
9467c478bd9Sstevel@tonic-gate /*
9477c478bd9Sstevel@tonic-gate * Construct the size of the window.
9487c478bd9Sstevel@tonic-gate */
9497c478bd9Sstevel@tonic-gate win->length = GET_BYTE(tp);
9507c478bd9Sstevel@tonic-gate win->length |= (GET_BYTE(tp)<<8);
9517c478bd9Sstevel@tonic-gate win->length *=
9527c478bd9Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE;
9537c478bd9Sstevel@tonic-gate break;
9547c478bd9Sstevel@tonic-gate } /* switch (CISTPL_CFTABLE_TPCE_FS_MEMM) */
9557c478bd9Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_MEM) */
9567c478bd9Sstevel@tonic-gate
9577c478bd9Sstevel@tonic-gate /*
9587c478bd9Sstevel@tonic-gate * Check for and parse any miscellaneous information.
9597c478bd9Sstevel@tonic-gate *
9607c478bd9Sstevel@tonic-gate * We only understand how to parse the first
9617c478bd9Sstevel@tonic-gate * CISTPL_CFTABLE_TPCE_FS_MISC_MAX extension
9627c478bd9Sstevel@tonic-gate * bytes specified in the PC Card 95 standard;
9637c478bd9Sstevel@tonic-gate * we throw away any other extension bytes that
9647c478bd9Sstevel@tonic-gate * are past these bytes.
9657c478bd9Sstevel@tonic-gate * XXX Note that the assumption here is that the
9667c478bd9Sstevel@tonic-gate * size of cistpl_cftable_entry_misc_t->flags
9677c478bd9Sstevel@tonic-gate * is at least CISTPL_CFTABLE_TPCE_FS_MISC_MAX
9687c478bd9Sstevel@tonic-gate * bytes in length.
9697c478bd9Sstevel@tonic-gate */
9707c478bd9Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MISCM) {
9717c478bd9Sstevel@tonic-gate cistpl_cftable_entry_misc_t *misc = &ce->misc;
9727c478bd9Sstevel@tonic-gate int mb = CISTPL_CFTABLE_TPCE_FS_MISC_MAX;
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_MISC;
9757c478bd9Sstevel@tonic-gate misc->flags = 0;
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate do {
9787c478bd9Sstevel@tonic-gate if (mb) {
9797c478bd9Sstevel@tonic-gate misc->flags = (misc->flags << 8) | LOOK_BYTE(tp);
9807c478bd9Sstevel@tonic-gate mb--;
9817c478bd9Sstevel@tonic-gate }
9827c478bd9Sstevel@tonic-gate } while ((GET_BYTE(tp) & CISTPL_EXT_BIT) &&
9837c478bd9Sstevel@tonic-gate (!(tp->flags & CISTPLF_MEM_ERR)));
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate /*
9867c478bd9Sstevel@tonic-gate * Check to see if we tried to read past the
9877c478bd9Sstevel@tonic-gate * end of the tuple data; if we have,
9887c478bd9Sstevel@tonic-gate * there's no point in trying to parse
9897c478bd9Sstevel@tonic-gate * any more of the tuple.
9907c478bd9Sstevel@tonic-gate */
9917c478bd9Sstevel@tonic-gate if (tp->flags & CISTPLF_MEM_ERR)
9927c478bd9Sstevel@tonic-gate return (HANDTPL_ERROR);
9937c478bd9Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_MISCM) */
9947c478bd9Sstevel@tonic-gate
9957c478bd9Sstevel@tonic-gate /*
9967c478bd9Sstevel@tonic-gate * Check for and parse any additional subtuple
9977c478bd9Sstevel@tonic-gate * information. We know that there is
9987c478bd9Sstevel@tonic-gate * additional information if we haven't
9997c478bd9Sstevel@tonic-gate * reached the end of the tuple data area
10007c478bd9Sstevel@tonic-gate * and if the additional information is
10017c478bd9Sstevel@tonic-gate * in standard tuple format.
10027c478bd9Sstevel@tonic-gate * If we don't recognize the additional info,
10037c478bd9Sstevel@tonic-gate * then just silently ignore it, don't
10047c478bd9Sstevel@tonic-gate * flag it as an error.
10057c478bd9Sstevel@tonic-gate */
10067c478bd9Sstevel@tonic-gate #ifdef PARSE_STCE_TUPLES
10077c478bd9Sstevel@tonic-gate if (GET_LEN(tp) > 0) {
10087c478bd9Sstevel@tonic-gate
10097c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_STCE_EV
10107c478bd9Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_STCE_PD
10117c478bd9Sstevel@tonic-gate #endif
10127c478bd9Sstevel@tonic-gate
10137c478bd9Sstevel@tonic-gate } /* if (HANDTPL_PARSE_LTUPLE) */
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
10167c478bd9Sstevel@tonic-gate }
10177c478bd9Sstevel@tonic-gate
10187c478bd9Sstevel@tonic-gate /*
10197c478bd9Sstevel@tonic-gate * cistpl_pd_parse - read and parse a power description structure
10207c478bd9Sstevel@tonic-gate *
10217c478bd9Sstevel@tonic-gate * cisdata_t **ddp - pointer to pointer tuple data area
10227c478bd9Sstevel@tonic-gate * cistpl_cftable_entry_pwr_t *pd - pointer to local power description
10237c478bd9Sstevel@tonic-gate * structure
10247c478bd9Sstevel@tonic-gate */
10257c478bd9Sstevel@tonic-gate static void
10267c478bd9Sstevel@tonic-gate cistpl_pd_parse(cistpl_t *tp, cistpl_cftable_entry_pwr_t *pd)
10277c478bd9Sstevel@tonic-gate {
10287c478bd9Sstevel@tonic-gate cisdata_t pdesc;
10297c478bd9Sstevel@tonic-gate
10307c478bd9Sstevel@tonic-gate pdesc = GET_BYTE(tp); /* power description selector */
10317c478bd9Sstevel@tonic-gate
10327c478bd9Sstevel@tonic-gate /* nominal supply voltage */
10337c478bd9Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_NOMV) {
10347c478bd9Sstevel@tonic-gate pd->nomV = cistpl_expd_parse(tp, &pd->nomV_flags) / 100;
10357c478bd9Sstevel@tonic-gate pd->nomV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10367c478bd9Sstevel@tonic-gate }
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate /* minimum supply voltage */
10397c478bd9Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_MINV) {
10407c478bd9Sstevel@tonic-gate pd->minV = cistpl_expd_parse(tp, &pd->minV_flags) / 100;
10417c478bd9Sstevel@tonic-gate pd->minV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10427c478bd9Sstevel@tonic-gate }
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate /* maximum supply voltage */
10457c478bd9Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_MAXV) {
10467c478bd9Sstevel@tonic-gate pd->maxV = cistpl_expd_parse(tp, &pd->maxV_flags) / 100;
10477c478bd9Sstevel@tonic-gate pd->maxV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10487c478bd9Sstevel@tonic-gate }
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate /* continuous supply current */
10517c478bd9Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_STATICI) {
10527c478bd9Sstevel@tonic-gate pd->staticI_flags |= CISTPL_CFTABLE_PD_MUL10;
10537c478bd9Sstevel@tonic-gate pd->staticI = cistpl_expd_parse(tp, &pd->staticI_flags);
10547c478bd9Sstevel@tonic-gate pd->staticI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate
10577c478bd9Sstevel@tonic-gate /* maximum current required averaged over 1 second */
10587c478bd9Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_AVGI) {
10597c478bd9Sstevel@tonic-gate pd->avgI_flags |= CISTPL_CFTABLE_PD_MUL10;
10607c478bd9Sstevel@tonic-gate pd->avgI = cistpl_expd_parse(tp, &pd->avgI_flags);
10617c478bd9Sstevel@tonic-gate pd->avgI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10627c478bd9Sstevel@tonic-gate }
10637c478bd9Sstevel@tonic-gate
10647c478bd9Sstevel@tonic-gate /* maximum current required averaged over 10mS */
10657c478bd9Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_PEAKI) {
10667c478bd9Sstevel@tonic-gate pd->peakI_flags |= CISTPL_CFTABLE_PD_MUL10;
10677c478bd9Sstevel@tonic-gate pd->peakI = cistpl_expd_parse(tp, &pd->peakI_flags);
10687c478bd9Sstevel@tonic-gate pd->peakI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate
10717c478bd9Sstevel@tonic-gate /* power down supply curent required */
10727c478bd9Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_PDOWNI) {
10737c478bd9Sstevel@tonic-gate pd->pdownI_flags |= CISTPL_CFTABLE_PD_MUL10;
10747c478bd9Sstevel@tonic-gate pd->pdownI = cistpl_expd_parse(tp, &pd->pdownI_flags);
10757c478bd9Sstevel@tonic-gate pd->pdownI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10767c478bd9Sstevel@tonic-gate }
10777c478bd9Sstevel@tonic-gate }
10787c478bd9Sstevel@tonic-gate
10797c478bd9Sstevel@tonic-gate /*
10807c478bd9Sstevel@tonic-gate * cistpl_expd_parse - read and parse an extended power description structure
10817c478bd9Sstevel@tonic-gate *
10827c478bd9Sstevel@tonic-gate * cistpl_t *tp - pointer to pointer tuple data area
10837c478bd9Sstevel@tonic-gate * int *flags - flags that get for this parameter:
10847c478bd9Sstevel@tonic-gate * CISTPL_CFTABLE_PD_NC_SLEEP - no connection on
10857c478bd9Sstevel@tonic-gate * sleep/power down
10867c478bd9Sstevel@tonic-gate * CISTPL_CFTABLE_PD_ZERO - zero value required
10877c478bd9Sstevel@tonic-gate * CISTPL_CFTABLE_PD_NC - no connection ever
10887c478bd9Sstevel@tonic-gate *
10897c478bd9Sstevel@tonic-gate * The power consumption is returned in the following units:
10907c478bd9Sstevel@tonic-gate *
10917c478bd9Sstevel@tonic-gate * voltage - milliVOLTS
10927c478bd9Sstevel@tonic-gate * current - microAMPS
10937c478bd9Sstevel@tonic-gate */
10947c478bd9Sstevel@tonic-gate extern cistpl_pd_struct_t cistpl_pd_struct;
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate uint32_t
10977c478bd9Sstevel@tonic-gate cistpl_expd_parse(cistpl_t *tp, uint32_t *flags)
10987c478bd9Sstevel@tonic-gate {
10997c478bd9Sstevel@tonic-gate cisdata_t pdesc;
11007c478bd9Sstevel@tonic-gate uint32_t exponent, mantisa, val, digits = 0;
11017c478bd9Sstevel@tonic-gate
11027c478bd9Sstevel@tonic-gate /*
11037c478bd9Sstevel@tonic-gate * Get the power description parameter byte and break it up
11047c478bd9Sstevel@tonic-gate * into mantissa and exponent.
11057c478bd9Sstevel@tonic-gate */
11067c478bd9Sstevel@tonic-gate pdesc = GET_BYTE(tp);
11077c478bd9Sstevel@tonic-gate exponent = pdesc&7;
11087c478bd9Sstevel@tonic-gate mantisa = (pdesc>>3)&0x0f;
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate if (pdesc & CISTPL_EXT_BIT) {
11117c478bd9Sstevel@tonic-gate do {
11127c478bd9Sstevel@tonic-gate if (LOOK_BYTE(tp) <= 0x63)
11137c478bd9Sstevel@tonic-gate digits = LOOK_BYTE(tp);
11147c478bd9Sstevel@tonic-gate if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_NC_SLEEPM)
11157c478bd9Sstevel@tonic-gate *flags |= CISTPL_CFTABLE_PD_NC_SLEEP;
11167c478bd9Sstevel@tonic-gate if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_ZEROM)
11177c478bd9Sstevel@tonic-gate *flags |= CISTPL_CFTABLE_PD_ZERO;
11187c478bd9Sstevel@tonic-gate if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_NCM)
11197c478bd9Sstevel@tonic-gate *flags |= CISTPL_CFTABLE_PD_NC;
11207c478bd9Sstevel@tonic-gate } while (GET_BYTE(tp) & CISTPL_EXT_BIT);
11217c478bd9Sstevel@tonic-gate }
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate val = CISTPL_PD_MAN(mantisa) * CISTPL_PD_EXP(exponent);
11247c478bd9Sstevel@tonic-gate
11257c478bd9Sstevel@tonic-gate /*
11267c478bd9Sstevel@tonic-gate * If we have to multiply the power value by ten, then just
11277c478bd9Sstevel@tonic-gate * don't bother dividing.
11287c478bd9Sstevel@tonic-gate */
11297c478bd9Sstevel@tonic-gate if (! (*flags & CISTPL_CFTABLE_PD_MUL10))
11307c478bd9Sstevel@tonic-gate val = val/10; /* do this since our mantissa table is X 10 */
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate /*
11337c478bd9Sstevel@tonic-gate * If we need to add some digits to the right of the decimal, do
11347c478bd9Sstevel@tonic-gate * that here.
11357c478bd9Sstevel@tonic-gate */
11367c478bd9Sstevel@tonic-gate if (exponent)
11377c478bd9Sstevel@tonic-gate val = val + (digits * CISTPL_PD_EXP(exponent-1));
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gate val /= 1000;
11407c478bd9Sstevel@tonic-gate
11417c478bd9Sstevel@tonic-gate return (val);
11427c478bd9Sstevel@tonic-gate }
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate /*
11457c478bd9Sstevel@tonic-gate * cistpl_devspeed - returns device speed in nS
11467c478bd9Sstevel@tonic-gate *
11477c478bd9Sstevel@tonic-gate * cistpl_t *tp - tuple pointer.
11487c478bd9Sstevel@tonic-gate * cisdata_t spindex - device speed table index
11497c478bd9Sstevel@tonic-gate * int flags - operation flags
11507c478bd9Sstevel@tonic-gate * CISTPL_DEVSPEED_TABLE:
11517c478bd9Sstevel@tonic-gate * Use the spindex argument as an index into a simple
11527c478bd9Sstevel@tonic-gate * device speed table. ref: PCMCIA Release 2.01
11537c478bd9Sstevel@tonic-gate * Card Metaformat pg. 5-14 table 5-12.
11547c478bd9Sstevel@tonic-gate * When this flag is set, the spindex argument is ignored.
11557c478bd9Sstevel@tonic-gate * CISTPL_DEVSPEED_EXT:
11567c478bd9Sstevel@tonic-gate * Use the tp argument to access the
11577c478bd9Sstevel@tonic-gate * tuple data area containing an extended speed
11587c478bd9Sstevel@tonic-gate * code table. ref: PCMCIA Release 2.01 Card
11597c478bd9Sstevel@tonic-gate * Metaformat pg. 5-15 table 5-13.
11607c478bd9Sstevel@tonic-gate * The tp->read argument must point to the first byte of
11617c478bd9Sstevel@tonic-gate * an extended speed code table.
11627c478bd9Sstevel@tonic-gate * When this flag is set, the spindex argument is
11637c478bd9Sstevel@tonic-gate * used as a power-of-10 scale factor. We only allow
11647c478bd9Sstevel@tonic-gate * a maximum scale factor of 10^16.
11657c478bd9Sstevel@tonic-gate *
11667c478bd9Sstevel@tonic-gate * The device speed is returned in nS for all combinations of flags and
11677c478bd9Sstevel@tonic-gate * speed table entries.
11687c478bd9Sstevel@tonic-gate *
11697c478bd9Sstevel@tonic-gate * Note if you pass the CISTPL_DEVSPEED_TABLE with a spindex index that
11707c478bd9Sstevel@tonic-gate * refers to an extended speed table, you will get back an undefined
11717c478bd9Sstevel@tonic-gate * speed value.
11727c478bd9Sstevel@tonic-gate */
11737c478bd9Sstevel@tonic-gate extern cistpl_devspeed_struct_t cistpl_devspeed_struct;
11747c478bd9Sstevel@tonic-gate
11757c478bd9Sstevel@tonic-gate uint32_t
11767c478bd9Sstevel@tonic-gate cistpl_devspeed(cistpl_t *tp, cisdata_t spindex, uint32_t flags)
11777c478bd9Sstevel@tonic-gate {
11787c478bd9Sstevel@tonic-gate int scale = 1, first;
11797c478bd9Sstevel@tonic-gate cisdata_t exspeed;
11807c478bd9Sstevel@tonic-gate int exponent, mantisa;
11817c478bd9Sstevel@tonic-gate uint32_t speed;
11827c478bd9Sstevel@tonic-gate
11837c478bd9Sstevel@tonic-gate switch (flags) {
11847c478bd9Sstevel@tonic-gate case CISTPL_DEVSPEED_TABLE:
11857c478bd9Sstevel@tonic-gate speed = CISTPL_DEVSPEED_TBL(spindex);
11867c478bd9Sstevel@tonic-gate break;
11877c478bd9Sstevel@tonic-gate case CISTPL_DEVSPEED_EXT:
11887c478bd9Sstevel@tonic-gate do {
11897c478bd9Sstevel@tonic-gate exspeed = GET_BYTE(tp);
11907c478bd9Sstevel@tonic-gate first = 1;
11917c478bd9Sstevel@tonic-gate if (first) {
11927c478bd9Sstevel@tonic-gate /*
11937c478bd9Sstevel@tonic-gate * XXX - ugh! we don't understand additional
11947c478bd9Sstevel@tonic-gate * exspeed bytes
11957c478bd9Sstevel@tonic-gate */
11967c478bd9Sstevel@tonic-gate first = 0;
11977c478bd9Sstevel@tonic-gate exponent = (exspeed & 0x07);
11987c478bd9Sstevel@tonic-gate mantisa = (exspeed >> 3) & 0x0f;
11997c478bd9Sstevel@tonic-gate spindex &= 0x0f; /* only allow 10^16 */
12007c478bd9Sstevel@tonic-gate while (spindex--)
12017c478bd9Sstevel@tonic-gate scale *= 10;
12027c478bd9Sstevel@tonic-gate } /* if (first) */
12037c478bd9Sstevel@tonic-gate } while (exspeed & CISTPL_EXT_BIT);
12047c478bd9Sstevel@tonic-gate speed = scale * CISTPL_DEVSPEED_MAN(mantisa) *
12057c478bd9Sstevel@tonic-gate CISTPL_DEVSPEED_EXP(exponent);
12067c478bd9Sstevel@tonic-gate speed = speed/10; /* XXX - mantissa table is all X 10 */
12077c478bd9Sstevel@tonic-gate break;
12087c478bd9Sstevel@tonic-gate default:
12097c478bd9Sstevel@tonic-gate break;
12107c478bd9Sstevel@tonic-gate }
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate return (speed);
12137c478bd9Sstevel@tonic-gate }
12147c478bd9Sstevel@tonic-gate
12157c478bd9Sstevel@tonic-gate /*
12167c478bd9Sstevel@tonic-gate * cistpl_vers_2_handler - handler for the CISTPL_VERS_2 tuple
12177c478bd9Sstevel@tonic-gate *
12187c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
12197c478bd9Sstevel@tonic-gate */
12207c478bd9Sstevel@tonic-gate uint32_t
12217c478bd9Sstevel@tonic-gate cistpl_vers_2_handler(cistpl_callout_t *co, cistpl_t *tp,
12227c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
12237c478bd9Sstevel@tonic-gate {
12247c478bd9Sstevel@tonic-gate /*
12257c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
12267c478bd9Sstevel@tonic-gate * generic handler for this
12277c478bd9Sstevel@tonic-gate */
12287c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
12297c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate /*
12327c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
12337c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
12347c478bd9Sstevel@tonic-gate */
12357c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
12367c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
12397c478bd9Sstevel@tonic-gate cistpl_vers_2_t *cs = (cistpl_vers_2_t *)arg;
12407c478bd9Sstevel@tonic-gate
12417c478bd9Sstevel@tonic-gate RESET_TP(tp);
12427c478bd9Sstevel@tonic-gate
12437c478bd9Sstevel@tonic-gate cs->vers = GET_BYTE(tp);
12447c478bd9Sstevel@tonic-gate cs->comply = GET_BYTE(tp);
12457c478bd9Sstevel@tonic-gate cs->dindex = GET_SHORT(tp);
12467c478bd9Sstevel@tonic-gate
12477c478bd9Sstevel@tonic-gate cs->reserved = GET_SHORT(tp);
12487c478bd9Sstevel@tonic-gate
12497c478bd9Sstevel@tonic-gate cs->vspec8 = GET_BYTE(tp);
12507c478bd9Sstevel@tonic-gate cs->vspec9 = GET_BYTE(tp);
12517c478bd9Sstevel@tonic-gate cs->nhdr = GET_BYTE(tp);
12527c478bd9Sstevel@tonic-gate
12537c478bd9Sstevel@tonic-gate (void) strcpy(cs->oem, cis_getstr(tp));
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate if (GET_LEN(tp) > 0)
12567c478bd9Sstevel@tonic-gate (void) strcpy(cs->info, cis_getstr(tp));
12577c478bd9Sstevel@tonic-gate else
12587c478bd9Sstevel@tonic-gate (void) strcpy(cs->info, "(no info)");
12597c478bd9Sstevel@tonic-gate }
12607c478bd9Sstevel@tonic-gate
12617c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
12627c478bd9Sstevel@tonic-gate }
12637c478bd9Sstevel@tonic-gate
12647c478bd9Sstevel@tonic-gate /*
12657c478bd9Sstevel@tonic-gate * cistpl_jedec_handler - handler for JEDEC C and JEDEC A tuples
12667c478bd9Sstevel@tonic-gate *
12677c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
12687c478bd9Sstevel@tonic-gate */
12697c478bd9Sstevel@tonic-gate uint32_t
12707c478bd9Sstevel@tonic-gate cistpl_jedec_handler(cistpl_callout_t *co, cistpl_t *tp,
12717c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
12727c478bd9Sstevel@tonic-gate {
12737c478bd9Sstevel@tonic-gate /*
12747c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
12757c478bd9Sstevel@tonic-gate * generic handler for this
12767c478bd9Sstevel@tonic-gate */
12777c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
12787c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
12797c478bd9Sstevel@tonic-gate
12807c478bd9Sstevel@tonic-gate /*
12817c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
12827c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
12837c478bd9Sstevel@tonic-gate */
12847c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
12857c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
12867c478bd9Sstevel@tonic-gate
12877c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
12887c478bd9Sstevel@tonic-gate int nid;
12897c478bd9Sstevel@tonic-gate cistpl_jedec_t *cs = (cistpl_jedec_t *)arg;
12907c478bd9Sstevel@tonic-gate
12917c478bd9Sstevel@tonic-gate RESET_TP(tp);
12927c478bd9Sstevel@tonic-gate
12937c478bd9Sstevel@tonic-gate for (nid = 0; GET_LEN(tp) > 0 &&
12947c478bd9Sstevel@tonic-gate nid < CISTPL_JEDEC_MAX_IDENTIFIERS &&
12957c478bd9Sstevel@tonic-gate LOOK_BYTE(tp) != 0xFF; nid++) {
12967c478bd9Sstevel@tonic-gate cs->jid[nid].id = GET_BYTE(tp);
12977c478bd9Sstevel@tonic-gate cs->jid[nid].info = GET_BYTE(tp);
12987c478bd9Sstevel@tonic-gate }
12997c478bd9Sstevel@tonic-gate cs->nid = nid;
13007c478bd9Sstevel@tonic-gate }
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
13037c478bd9Sstevel@tonic-gate }
13047c478bd9Sstevel@tonic-gate
13057c478bd9Sstevel@tonic-gate /*
13067c478bd9Sstevel@tonic-gate * cistpl_format_handler - handler for the CISTPL_FORMAT and
13077c478bd9Sstevel@tonic-gate * CISTPL_FORMAT_A tuples
13087c478bd9Sstevel@tonic-gate */
13097c478bd9Sstevel@tonic-gate uint32_t
13107c478bd9Sstevel@tonic-gate cistpl_format_handler(cistpl_callout_t *co, cistpl_t *tp,
13117c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
13127c478bd9Sstevel@tonic-gate {
13137c478bd9Sstevel@tonic-gate /*
13147c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
13157c478bd9Sstevel@tonic-gate * generic handler for this
13167c478bd9Sstevel@tonic-gate */
13177c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
13187c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
13197c478bd9Sstevel@tonic-gate
13207c478bd9Sstevel@tonic-gate /*
13217c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
13227c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
13237c478bd9Sstevel@tonic-gate */
13247c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
13257c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
13267c478bd9Sstevel@tonic-gate
13277c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
13287c478bd9Sstevel@tonic-gate cistpl_format_t *cs = (cistpl_format_t *)arg;
13297c478bd9Sstevel@tonic-gate
13307c478bd9Sstevel@tonic-gate RESET_TP(tp);
13317c478bd9Sstevel@tonic-gate
13327c478bd9Sstevel@tonic-gate cs->type = GET_BYTE(tp);
13337c478bd9Sstevel@tonic-gate cs->edc_length = LOOK_BYTE(tp) & EDC_LENGTH_MASK;
13347c478bd9Sstevel@tonic-gate cs->edc_type = ((uint32_t)GET_BYTE(tp) >> EDC_TYPE_SHIFT) &
13357c478bd9Sstevel@tonic-gate EDC_TYPE_MASK;
13367c478bd9Sstevel@tonic-gate cs->offset = GET_LONG(tp);
13377c478bd9Sstevel@tonic-gate cs->nbytes = GET_LONG(tp);
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate switch (cs->type) {
13407c478bd9Sstevel@tonic-gate case TPLFMTTYPE_DISK:
13417c478bd9Sstevel@tonic-gate cs->dev.disk.bksize = GET_SHORT(tp);
13427c478bd9Sstevel@tonic-gate cs->dev.disk.nblocks = GET_LONG(tp);
13437c478bd9Sstevel@tonic-gate cs->dev.disk.edcloc = GET_LONG(tp);
13447c478bd9Sstevel@tonic-gate break;
13457c478bd9Sstevel@tonic-gate
13467c478bd9Sstevel@tonic-gate case TPLFMTTYPE_MEM:
13477c478bd9Sstevel@tonic-gate cs->dev.mem.flags = GET_BYTE(tp);
13487c478bd9Sstevel@tonic-gate cs->dev.mem.reserved = GET_BYTE(tp);
13497c478bd9Sstevel@tonic-gate cs->dev.mem.address = (caddr_t)(uintptr_t)GET_LONG(tp);
13507c478bd9Sstevel@tonic-gate cs->dev.disk.edcloc = GET_LONG(tp);
13517c478bd9Sstevel@tonic-gate break;
13527c478bd9Sstevel@tonic-gate default:
13537c478bd9Sstevel@tonic-gate /* don't know about any other type */
13547c478bd9Sstevel@tonic-gate break;
13557c478bd9Sstevel@tonic-gate }
13567c478bd9Sstevel@tonic-gate }
13577c478bd9Sstevel@tonic-gate
13587c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
13597c478bd9Sstevel@tonic-gate }
13607c478bd9Sstevel@tonic-gate
13617c478bd9Sstevel@tonic-gate /*
13627c478bd9Sstevel@tonic-gate * cistpl_geometry_handler - handler for the CISTPL_GEOMETRY tuple
13637c478bd9Sstevel@tonic-gate *
13647c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
13657c478bd9Sstevel@tonic-gate */
13667c478bd9Sstevel@tonic-gate uint32_t
13677c478bd9Sstevel@tonic-gate cistpl_geometry_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
13687c478bd9Sstevel@tonic-gate void *arg)
13697c478bd9Sstevel@tonic-gate {
13707c478bd9Sstevel@tonic-gate /*
13717c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
13727c478bd9Sstevel@tonic-gate * generic handler for this
13737c478bd9Sstevel@tonic-gate */
13747c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
13757c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
13767c478bd9Sstevel@tonic-gate
13777c478bd9Sstevel@tonic-gate /*
13787c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
13797c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
13807c478bd9Sstevel@tonic-gate */
13817c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
13827c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
13837c478bd9Sstevel@tonic-gate
13847c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
13857c478bd9Sstevel@tonic-gate cistpl_geometry_t *cs = (cistpl_geometry_t *)arg;
13867c478bd9Sstevel@tonic-gate
13877c478bd9Sstevel@tonic-gate RESET_TP(tp);
13887c478bd9Sstevel@tonic-gate cs->spt = GET_BYTE(tp);
13897c478bd9Sstevel@tonic-gate cs->tpc = GET_BYTE(tp);
13907c478bd9Sstevel@tonic-gate cs->ncyl = GET_SHORT(tp);
13917c478bd9Sstevel@tonic-gate }
13927c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
13937c478bd9Sstevel@tonic-gate }
13947c478bd9Sstevel@tonic-gate
13957c478bd9Sstevel@tonic-gate /*
13967c478bd9Sstevel@tonic-gate * cistpl_byteorder_handler - handler for the CISTPL_BYTEORDER tuple
13977c478bd9Sstevel@tonic-gate *
13987c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
13997c478bd9Sstevel@tonic-gate */
14007c478bd9Sstevel@tonic-gate uint32_t
14017c478bd9Sstevel@tonic-gate cistpl_byteorder_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
14027c478bd9Sstevel@tonic-gate void *arg)
14037c478bd9Sstevel@tonic-gate {
14047c478bd9Sstevel@tonic-gate /*
14057c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
14067c478bd9Sstevel@tonic-gate * generic handler for this
14077c478bd9Sstevel@tonic-gate */
14087c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
14097c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14107c478bd9Sstevel@tonic-gate
14117c478bd9Sstevel@tonic-gate /*
14127c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
14137c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
14147c478bd9Sstevel@tonic-gate */
14157c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
14167c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14177c478bd9Sstevel@tonic-gate
14187c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
14197c478bd9Sstevel@tonic-gate cistpl_byteorder_t *cs = (cistpl_byteorder_t *)arg;
14207c478bd9Sstevel@tonic-gate
14217c478bd9Sstevel@tonic-gate RESET_TP(tp);
14227c478bd9Sstevel@tonic-gate cs->order = GET_BYTE(tp);
14237c478bd9Sstevel@tonic-gate cs->map = GET_BYTE(tp);
14247c478bd9Sstevel@tonic-gate }
14257c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
14267c478bd9Sstevel@tonic-gate }
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate /*
14297c478bd9Sstevel@tonic-gate * cistpl_date_handler - handler for CISTPL_DATE card format tuple
14307c478bd9Sstevel@tonic-gate *
14317c478bd9Sstevel@tonic-gate * void *arg - points to a cistpl_date_t * where the
14327c478bd9Sstevel@tonic-gate * information is stuffed into
14337c478bd9Sstevel@tonic-gate */
14347c478bd9Sstevel@tonic-gate uint32_t
14357c478bd9Sstevel@tonic-gate cistpl_date_handler(cistpl_callout_t *co, cistpl_t *tp,
14367c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
14377c478bd9Sstevel@tonic-gate {
14387c478bd9Sstevel@tonic-gate /*
14397c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
14407c478bd9Sstevel@tonic-gate * generic handler for this
14417c478bd9Sstevel@tonic-gate */
14427c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
14437c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14447c478bd9Sstevel@tonic-gate
14457c478bd9Sstevel@tonic-gate /*
14467c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
14477c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
14487c478bd9Sstevel@tonic-gate */
14497c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
14507c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14517c478bd9Sstevel@tonic-gate
14527c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
14537c478bd9Sstevel@tonic-gate cistpl_date_t *cs = (cistpl_date_t *)arg;
14547c478bd9Sstevel@tonic-gate
14557c478bd9Sstevel@tonic-gate RESET_TP(tp);
14567c478bd9Sstevel@tonic-gate cs->time = GET_SHORT(tp);
14577c478bd9Sstevel@tonic-gate cs->day = GET_SHORT(tp);
14587c478bd9Sstevel@tonic-gate }
14597c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
14607c478bd9Sstevel@tonic-gate }
14617c478bd9Sstevel@tonic-gate
14627c478bd9Sstevel@tonic-gate /*
14637c478bd9Sstevel@tonic-gate * cistpl_battery_handler - handler for CISTPL_BATTERY battery replacement
14647c478bd9Sstevel@tonic-gate * date tuple
14657c478bd9Sstevel@tonic-gate *
14667c478bd9Sstevel@tonic-gate * void *arg - points to a cistpl_battery_t * where the
14677c478bd9Sstevel@tonic-gate * information is stuffed into
14687c478bd9Sstevel@tonic-gate */
14697c478bd9Sstevel@tonic-gate uint32_t
14707c478bd9Sstevel@tonic-gate cistpl_battery_handler(cistpl_callout_t *co, cistpl_t *tp,
14717c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
14727c478bd9Sstevel@tonic-gate {
14737c478bd9Sstevel@tonic-gate /*
14747c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
14757c478bd9Sstevel@tonic-gate * generic handler for this
14767c478bd9Sstevel@tonic-gate */
14777c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
14787c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14797c478bd9Sstevel@tonic-gate
14807c478bd9Sstevel@tonic-gate /*
14817c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
14827c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
14837c478bd9Sstevel@tonic-gate */
14847c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
14857c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14867c478bd9Sstevel@tonic-gate
14877c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
14887c478bd9Sstevel@tonic-gate cistpl_battery_t *cs = (cistpl_battery_t *)arg;
14897c478bd9Sstevel@tonic-gate
14907c478bd9Sstevel@tonic-gate RESET_TP(tp);
14917c478bd9Sstevel@tonic-gate cs->rday = GET_SHORT(tp);
14927c478bd9Sstevel@tonic-gate cs->xday = GET_SHORT(tp);
14937c478bd9Sstevel@tonic-gate }
14947c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
14957c478bd9Sstevel@tonic-gate }
14967c478bd9Sstevel@tonic-gate
14977c478bd9Sstevel@tonic-gate /*
14987c478bd9Sstevel@tonic-gate * cistpl_org_handler - handler for CISTPL_ORG data organization tuple
14997c478bd9Sstevel@tonic-gate *
15007c478bd9Sstevel@tonic-gate * void *arg - points to a cistpl_org_t * where the
15017c478bd9Sstevel@tonic-gate * information is stuffed into
15027c478bd9Sstevel@tonic-gate */
15037c478bd9Sstevel@tonic-gate uint32_t
15047c478bd9Sstevel@tonic-gate cistpl_org_handler(cistpl_callout_t *co, cistpl_t *tp,
15057c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
15067c478bd9Sstevel@tonic-gate {
15077c478bd9Sstevel@tonic-gate /*
15087c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
15097c478bd9Sstevel@tonic-gate * generic handler for this
15107c478bd9Sstevel@tonic-gate */
15117c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
15127c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15137c478bd9Sstevel@tonic-gate
15147c478bd9Sstevel@tonic-gate /*
15157c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
15167c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
15177c478bd9Sstevel@tonic-gate */
15187c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
15197c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15207c478bd9Sstevel@tonic-gate
15217c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
15227c478bd9Sstevel@tonic-gate cistpl_org_t *cs = (cistpl_org_t *)arg;
15237c478bd9Sstevel@tonic-gate
15247c478bd9Sstevel@tonic-gate RESET_TP(tp);
15257c478bd9Sstevel@tonic-gate cs->type = GET_BYTE(tp);
15267c478bd9Sstevel@tonic-gate
15277c478bd9Sstevel@tonic-gate (void) strcpy(cs->desc, cis_getstr(tp));
15287c478bd9Sstevel@tonic-gate }
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
15317c478bd9Sstevel@tonic-gate }
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate
15347c478bd9Sstevel@tonic-gate /*
15357c478bd9Sstevel@tonic-gate * cistpl_manfid_handler - handler for CISTPL_MANFID, the manufacturer ID tuple
15367c478bd9Sstevel@tonic-gate *
15377c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
15387c478bd9Sstevel@tonic-gate */
15397c478bd9Sstevel@tonic-gate uint32_t
15407c478bd9Sstevel@tonic-gate cistpl_manfid_handler(cistpl_callout_t *co, cistpl_t *tp,
15417c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
15427c478bd9Sstevel@tonic-gate {
15437c478bd9Sstevel@tonic-gate /*
15447c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
15457c478bd9Sstevel@tonic-gate * generic handler for this
15467c478bd9Sstevel@tonic-gate */
15477c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
15487c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15497c478bd9Sstevel@tonic-gate
15507c478bd9Sstevel@tonic-gate /*
15517c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
15527c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
15537c478bd9Sstevel@tonic-gate */
15547c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
15557c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15567c478bd9Sstevel@tonic-gate
15577c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
15587c478bd9Sstevel@tonic-gate cistpl_manfid_t *cs = (cistpl_manfid_t *)arg;
15597c478bd9Sstevel@tonic-gate
15607c478bd9Sstevel@tonic-gate RESET_TP(tp);
15617c478bd9Sstevel@tonic-gate cs->manf = GET_SHORT(tp);
15627c478bd9Sstevel@tonic-gate cs->card = GET_SHORT(tp);
15637c478bd9Sstevel@tonic-gate }
15647c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
15657c478bd9Sstevel@tonic-gate }
15667c478bd9Sstevel@tonic-gate
15677c478bd9Sstevel@tonic-gate /*
15687c478bd9Sstevel@tonic-gate * cistpl_funcid_handler - handler for CISTPL_FUNCID
15697c478bd9Sstevel@tonic-gate *
15707c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
15717c478bd9Sstevel@tonic-gate */
15727c478bd9Sstevel@tonic-gate uint32_t
15737c478bd9Sstevel@tonic-gate cistpl_funcid_handler(cistpl_callout_t *co, cistpl_t *tp,
15747c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
15757c478bd9Sstevel@tonic-gate {
15767c478bd9Sstevel@tonic-gate /*
15777c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
15787c478bd9Sstevel@tonic-gate * generic handler for this
15797c478bd9Sstevel@tonic-gate */
15807c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
15817c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15827c478bd9Sstevel@tonic-gate
15837c478bd9Sstevel@tonic-gate /*
15847c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
15857c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
15867c478bd9Sstevel@tonic-gate */
15877c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
15887c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15897c478bd9Sstevel@tonic-gate
15907c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
15917c478bd9Sstevel@tonic-gate cistpl_funcid_t *cs = (cistpl_funcid_t *)arg;
15927c478bd9Sstevel@tonic-gate
15937c478bd9Sstevel@tonic-gate RESET_TP(tp);
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate cs->function = GET_BYTE(tp);
15967c478bd9Sstevel@tonic-gate cs->sysinit = GET_BYTE(tp);
15977c478bd9Sstevel@tonic-gate }
15987c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
15997c478bd9Sstevel@tonic-gate }
16007c478bd9Sstevel@tonic-gate
16017c478bd9Sstevel@tonic-gate
16027c478bd9Sstevel@tonic-gate /*
16037c478bd9Sstevel@tonic-gate * cistpl_funce_serial_handler - handler for the CISTPL_FUNCE/SERIAL tuple
16047c478bd9Sstevel@tonic-gate *
16057c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
16067c478bd9Sstevel@tonic-gate */
16077c478bd9Sstevel@tonic-gate uint32_t
16087c478bd9Sstevel@tonic-gate cistpl_funce_serial_handler(cistpl_callout_t *co, cistpl_t *tp,
16097c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
16107c478bd9Sstevel@tonic-gate {
16117c478bd9Sstevel@tonic-gate int subfunction;
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate /*
16147c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
16157c478bd9Sstevel@tonic-gate * generic handler for this
16167c478bd9Sstevel@tonic-gate */
16177c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
16187c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
16197c478bd9Sstevel@tonic-gate
16207c478bd9Sstevel@tonic-gate /*
16217c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
16227c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
16237c478bd9Sstevel@tonic-gate */
16247c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
16257c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
16267c478bd9Sstevel@tonic-gate
16277c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
16287c478bd9Sstevel@tonic-gate cistpl_funce_t *cs = (cistpl_funce_t *)arg;
16297c478bd9Sstevel@tonic-gate
16307c478bd9Sstevel@tonic-gate RESET_TP(tp);
16317c478bd9Sstevel@tonic-gate
16327c478bd9Sstevel@tonic-gate cs->function = TPLFUNC_SERIAL;
16337c478bd9Sstevel@tonic-gate cs->subfunction = subfunction = GET_BYTE(tp);
16347c478bd9Sstevel@tonic-gate switch (subfunction & 0xF) {
16357c478bd9Sstevel@tonic-gate case TPLFE_SUB_SERIAL:
16367c478bd9Sstevel@tonic-gate case TPLFE_CAP_SERIAL_DATA:
16377c478bd9Sstevel@tonic-gate case TPLFE_CAP_SERIAL_FAX:
16387c478bd9Sstevel@tonic-gate case TPLFE_CAP_SERIAL_VOICE:
16397c478bd9Sstevel@tonic-gate cs->data.serial.ua = GET_BYTE(tp);
16407c478bd9Sstevel@tonic-gate cs->data.serial.uc = GET_SHORT(tp);
16417c478bd9Sstevel@tonic-gate break;
16427c478bd9Sstevel@tonic-gate case TPLFE_SUB_MODEM_COMMON:
16437c478bd9Sstevel@tonic-gate case TPLFE_CAP_MODEM_DATA:
16447c478bd9Sstevel@tonic-gate case TPLFE_CAP_MODEM_FAX:
16457c478bd9Sstevel@tonic-gate case TPLFE_CAP_MODEM_VOICE:
16467c478bd9Sstevel@tonic-gate cs->data.modem.fc = GET_BYTE(tp);
16477c478bd9Sstevel@tonic-gate cs->data.modem.cb = (GET_BYTE(tp) + 1) * 4;
16487c478bd9Sstevel@tonic-gate cs->data.modem.eb = GET_INT24(tp);
16497c478bd9Sstevel@tonic-gate cs->data.modem.tb = GET_INT24(tp);
16507c478bd9Sstevel@tonic-gate break;
16517c478bd9Sstevel@tonic-gate case TPLFE_SUB_MODEM_DATA:
16527c478bd9Sstevel@tonic-gate cs->data.data_modem.ud = GET_BE_SHORT(tp) * 75;
16537c478bd9Sstevel@tonic-gate cs->data.data_modem.ms = GET_SHORT(tp);
16547c478bd9Sstevel@tonic-gate cs->data.data_modem.em = GET_BYTE(tp);
16557c478bd9Sstevel@tonic-gate cs->data.data_modem.dc = GET_BYTE(tp);
16567c478bd9Sstevel@tonic-gate cs->data.data_modem.cm = GET_BYTE(tp);
16577c478bd9Sstevel@tonic-gate cs->data.data_modem.ex = GET_BYTE(tp);
16587c478bd9Sstevel@tonic-gate cs->data.data_modem.dy = GET_BYTE(tp);
16597c478bd9Sstevel@tonic-gate cs->data.data_modem.ef = GET_BYTE(tp);
16607c478bd9Sstevel@tonic-gate for (cs->data.data_modem.ncd = 0;
16617c478bd9Sstevel@tonic-gate GET_LEN(tp) > 0 && cs->data.data_modem.ncd < 16;
16627c478bd9Sstevel@tonic-gate cs->data.data_modem.ncd++)
16637c478bd9Sstevel@tonic-gate if (LOOK_BYTE(tp) != 255) {
16647c478bd9Sstevel@tonic-gate cs->data.data_modem.cd[
16657c478bd9Sstevel@tonic-gate cs->data.data_modem.ncd] =
16667c478bd9Sstevel@tonic-gate GET_BYTE(tp);
16677c478bd9Sstevel@tonic-gate } else {
16687c478bd9Sstevel@tonic-gate GET_BYTE(tp);
16697c478bd9Sstevel@tonic-gate break;
16707c478bd9Sstevel@tonic-gate }
16717c478bd9Sstevel@tonic-gate break;
16727c478bd9Sstevel@tonic-gate case TPLFE_SUB_MODEM_FAX:
16737c478bd9Sstevel@tonic-gate cs->data.fax.uf = GET_BE_SHORT(tp) * 75;
16747c478bd9Sstevel@tonic-gate cs->data.fax.fm = GET_BYTE(tp);
16757c478bd9Sstevel@tonic-gate cs->data.fax.fy = GET_BYTE(tp);
16767c478bd9Sstevel@tonic-gate cs->data.fax.fs = GET_SHORT(tp);
16777c478bd9Sstevel@tonic-gate for (cs->data.fax.ncf = 0;
16787c478bd9Sstevel@tonic-gate GET_LEN(tp) > 0 && cs->data.fax.ncf < 16;
16797c478bd9Sstevel@tonic-gate cs->data.fax.ncf++)
16807c478bd9Sstevel@tonic-gate if (LOOK_BYTE(tp) != 255) {
16817c478bd9Sstevel@tonic-gate cs->data.fax.cf[cs->data.fax.ncf] =
16827c478bd9Sstevel@tonic-gate GET_BYTE(tp);
16837c478bd9Sstevel@tonic-gate } else {
16847c478bd9Sstevel@tonic-gate GET_BYTE(tp);
16857c478bd9Sstevel@tonic-gate break;
16867c478bd9Sstevel@tonic-gate }
16877c478bd9Sstevel@tonic-gate break;
16887c478bd9Sstevel@tonic-gate case TPLFE_SUB_VOICE:
16897c478bd9Sstevel@tonic-gate cs->data.voice.uv = GET_BE_SHORT(tp) * 75;
16907c478bd9Sstevel@tonic-gate for (cs->data.voice.nsr = 0; LOOK_BYTE(tp) != 0 &&
16917c478bd9Sstevel@tonic-gate GET_LEN(tp) >= 2;
16927c478bd9Sstevel@tonic-gate cs->data.voice.nsr++) {
16937c478bd9Sstevel@tonic-gate cs->data.voice.sr[cs->data.voice.nsr] =
16947c478bd9Sstevel@tonic-gate GET_BYTE(tp) * 1000;
16957c478bd9Sstevel@tonic-gate cs->data.voice.sr[cs->data.voice.nsr] +=
16967c478bd9Sstevel@tonic-gate GET_BYTE(tp) * 100;
16977c478bd9Sstevel@tonic-gate }
16987c478bd9Sstevel@tonic-gate for (cs->data.voice.nss = 0; LOOK_BYTE(tp) != 0 &&
16997c478bd9Sstevel@tonic-gate GET_LEN(tp) >= 2;
17007c478bd9Sstevel@tonic-gate cs->data.voice.nss++) {
17017c478bd9Sstevel@tonic-gate cs->data.voice.ss[cs->data.voice.nss] =
17027c478bd9Sstevel@tonic-gate GET_BYTE(tp) * 10;
17037c478bd9Sstevel@tonic-gate cs->data.voice.ss[cs->data.voice.nss] +=
17047c478bd9Sstevel@tonic-gate GET_BYTE(tp);
17057c478bd9Sstevel@tonic-gate }
17067c478bd9Sstevel@tonic-gate for (cs->data.voice.nsc = 0; LOOK_BYTE(tp) != 0 &&
17077c478bd9Sstevel@tonic-gate GET_LEN(tp) >= 1;
17087c478bd9Sstevel@tonic-gate cs->data.voice.nsc++) {
17097c478bd9Sstevel@tonic-gate cs->data.voice.sc[cs->data.voice.nsc] =
17107c478bd9Sstevel@tonic-gate GET_BYTE(tp);
17117c478bd9Sstevel@tonic-gate }
17127c478bd9Sstevel@tonic-gate break;
17137c478bd9Sstevel@tonic-gate default:
17147c478bd9Sstevel@tonic-gate break;
17157c478bd9Sstevel@tonic-gate }
17167c478bd9Sstevel@tonic-gate }
17177c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
17187c478bd9Sstevel@tonic-gate }
17197c478bd9Sstevel@tonic-gate
17207c478bd9Sstevel@tonic-gate /*
17217c478bd9Sstevel@tonic-gate * cistpl_funce_lan_handler - handler for the CISTPL_FUNCE/LAN tuple
17227c478bd9Sstevel@tonic-gate *
17237c478bd9Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
17247c478bd9Sstevel@tonic-gate */
17257c478bd9Sstevel@tonic-gate uint32_t
17267c478bd9Sstevel@tonic-gate cistpl_funce_lan_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
17277c478bd9Sstevel@tonic-gate void *arg)
17287c478bd9Sstevel@tonic-gate {
17297c478bd9Sstevel@tonic-gate int subfunction;
17307c478bd9Sstevel@tonic-gate
17317c478bd9Sstevel@tonic-gate /*
17327c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
17337c478bd9Sstevel@tonic-gate * generic handler for this
17347c478bd9Sstevel@tonic-gate */
17357c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
17367c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
17377c478bd9Sstevel@tonic-gate
17387c478bd9Sstevel@tonic-gate /*
17397c478bd9Sstevel@tonic-gate * We don't currently validate this tuple. This call will
17407c478bd9Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
17417c478bd9Sstevel@tonic-gate */
17427c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
17437c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
17447c478bd9Sstevel@tonic-gate
17457c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
17467c478bd9Sstevel@tonic-gate int i;
17477c478bd9Sstevel@tonic-gate cistpl_funce_t *cs = (cistpl_funce_t *)arg;
17487c478bd9Sstevel@tonic-gate
17497c478bd9Sstevel@tonic-gate RESET_TP(tp);
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate cs->function = TPLFUNC_LAN;
17527c478bd9Sstevel@tonic-gate cs->subfunction = subfunction = GET_BYTE(tp);
17537c478bd9Sstevel@tonic-gate
17547c478bd9Sstevel@tonic-gate switch (subfunction) {
17557c478bd9Sstevel@tonic-gate case TPLFE_NETWORK_INFO:
17567c478bd9Sstevel@tonic-gate cs->data.lan.tech = GET_BYTE(tp);
17577c478bd9Sstevel@tonic-gate cs->data.lan.speed = GET_BYTE(tp);
17587c478bd9Sstevel@tonic-gate i = GET_BYTE(tp);
17597c478bd9Sstevel@tonic-gate if (i < 24) {
17607c478bd9Sstevel@tonic-gate cs->data.lan.speed <<= i;
17617c478bd9Sstevel@tonic-gate } else {
17627c478bd9Sstevel@tonic-gate /*
17637c478bd9Sstevel@tonic-gate * if speed is too large a value
17647c478bd9Sstevel@tonic-gate * to hold in a uint32 flag it and
17657c478bd9Sstevel@tonic-gate * store as [mantissa][exponent]
17667c478bd9Sstevel@tonic-gate * in least significant 16 bits
17677c478bd9Sstevel@tonic-gate */
17687c478bd9Sstevel@tonic-gate cs->data.lan.speed = 0x80000000 |
17697c478bd9Sstevel@tonic-gate (cs->data.lan.speed << 8) | i;
17707c478bd9Sstevel@tonic-gate }
17717c478bd9Sstevel@tonic-gate cs->data.lan.media = GET_BYTE(tp);
17727c478bd9Sstevel@tonic-gate cs->data.lan.con = GET_BYTE(tp);
17737c478bd9Sstevel@tonic-gate cs->data.lan.id_sz = GET_BYTE(tp);
17747c478bd9Sstevel@tonic-gate if (cs->data.lan.id_sz <= 16) {
17757c478bd9Sstevel@tonic-gate for (i = 0; i < cs->data.lan.id_sz; i++)
17767c478bd9Sstevel@tonic-gate cs->data.lan.id[i] = GET_BYTE(tp);
17777c478bd9Sstevel@tonic-gate }
17787c478bd9Sstevel@tonic-gate break;
17797c478bd9Sstevel@tonic-gate default:
17807c478bd9Sstevel@tonic-gate /* unknown LAN tuple type */
17817c478bd9Sstevel@tonic-gate return (CISTPLF_UNKNOWN);
17827c478bd9Sstevel@tonic-gate }
17837c478bd9Sstevel@tonic-gate }
17847c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
17857c478bd9Sstevel@tonic-gate }
17867c478bd9Sstevel@tonic-gate
17877c478bd9Sstevel@tonic-gate /*
17887c478bd9Sstevel@tonic-gate * cistpl_linktarget_handler - handler for CISTPL_LINKTARGET tuple
17897c478bd9Sstevel@tonic-gate *
17907c478bd9Sstevel@tonic-gate * void *arg - points to a cistpl_linktarget_t * where the
17917c478bd9Sstevel@tonic-gate * information is stuffed into
17927c478bd9Sstevel@tonic-gate *
17937c478bd9Sstevel@tonic-gate * If HANDTPL_COPY_DONE is set, we just validate the tuple but
17947c478bd9Sstevel@tonic-gate * do not return any values.
17957c478bd9Sstevel@tonic-gate * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and
17967c478bd9Sstevel@tonic-gate * return the parsed tuple data if the tuple is valid.
17977c478bd9Sstevel@tonic-gate *
17987c478bd9Sstevel@tonic-gate * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag
17997c478bd9Sstevel@tonic-gate * will be set in the tp->flags field and HANDTPL_ERROR
18007c478bd9Sstevel@tonic-gate * will be returned.
18017c478bd9Sstevel@tonic-gate *
18027c478bd9Sstevel@tonic-gate * If the tuple data body is invalid, the CISTPLF_PARAMS_INVALID flag
18037c478bd9Sstevel@tonic-gate * will be set in the tp->flags field and HANDTPL_ERROR
18047c478bd9Sstevel@tonic-gate * will be returned.
18057c478bd9Sstevel@tonic-gate *
18067c478bd9Sstevel@tonic-gate * The tuple is considered invalid if it's link field is less than
18077c478bd9Sstevel@tonic-gate * MIN_LINKTARGET_LENGTH or if the data body of the tuple
18087c478bd9Sstevel@tonic-gate * does not contain the pattern CISTPL_LINKTARGET_MAGIC.
18097c478bd9Sstevel@tonic-gate *
18107c478bd9Sstevel@tonic-gate * XXX At some point we should revisit this to see if we can call
18117c478bd9Sstevel@tonic-gate * cis_validate_longlink_acm instead of doing the validation
18127c478bd9Sstevel@tonic-gate * in both places.
18137c478bd9Sstevel@tonic-gate */
18147c478bd9Sstevel@tonic-gate uint32_t
18157c478bd9Sstevel@tonic-gate cistpl_linktarget_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
18167c478bd9Sstevel@tonic-gate void *arg)
18177c478bd9Sstevel@tonic-gate {
18187c478bd9Sstevel@tonic-gate /*
18197c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
18207c478bd9Sstevel@tonic-gate * generic handler for this
18217c478bd9Sstevel@tonic-gate */
18227c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
18237c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
18247c478bd9Sstevel@tonic-gate
18257c478bd9Sstevel@tonic-gate /*
18267c478bd9Sstevel@tonic-gate * Validate the tuple for both the HANDTPL_COPY_DONE case and
18277c478bd9Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case. Only return data in
18287c478bd9Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case.
18297c478bd9Sstevel@tonic-gate */
18307c478bd9Sstevel@tonic-gate if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) {
18317c478bd9Sstevel@tonic-gate uchar_t *cp;
18327c478bd9Sstevel@tonic-gate cisdata_t tl;
18337c478bd9Sstevel@tonic-gate
18347c478bd9Sstevel@tonic-gate if ((tl = tp->len) >= (cisdata_t)MIN_LINKTARGET_LENGTH) {
18357c478bd9Sstevel@tonic-gate cisdata_t *ltm = (cisdata_t *)CISTPL_LINKTARGET_MAGIC;
18367c478bd9Sstevel@tonic-gate int i;
18377c478bd9Sstevel@tonic-gate
18387c478bd9Sstevel@tonic-gate RESET_TP(tp);
18397c478bd9Sstevel@tonic-gate
18407c478bd9Sstevel@tonic-gate /*
18417c478bd9Sstevel@tonic-gate * Save the start address of this string in case
18427c478bd9Sstevel@tonic-gate * the tuple turns out to be OK since we
18437c478bd9Sstevel@tonic-gate * need to pass this address to the caller.
18447c478bd9Sstevel@tonic-gate */
18457c478bd9Sstevel@tonic-gate cp = GET_BYTE_ADDR(tp);
18467c478bd9Sstevel@tonic-gate
18477c478bd9Sstevel@tonic-gate /*
18487c478bd9Sstevel@tonic-gate * Check each byte of the tuple body to see if it
18497c478bd9Sstevel@tonic-gate * matches what should be in a valid tuple.
18507c478bd9Sstevel@tonic-gate * Note that we can't assume that this magic
18517c478bd9Sstevel@tonic-gate * pattern is a string and we also only need
18527c478bd9Sstevel@tonic-gate * to be sure that MIN_LINKTARGET_LENGTH bytes
18537c478bd9Sstevel@tonic-gate * match; all bytes following this magic number
18547c478bd9Sstevel@tonic-gate * in this tuple are ignored.
18557c478bd9Sstevel@tonic-gate */
18567c478bd9Sstevel@tonic-gate for (i = 0; i < MIN_LINKTARGET_LENGTH; i++) {
18577c478bd9Sstevel@tonic-gate if (GET_BYTE(tp) != *ltm++) {
18587c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_PARAMS_INVALID;
18597c478bd9Sstevel@tonic-gate return (HANDTPL_ERROR);
18607c478bd9Sstevel@tonic-gate }
18617c478bd9Sstevel@tonic-gate } /* MIN_LINKTARGET_LENGTH */
18627c478bd9Sstevel@tonic-gate
18637c478bd9Sstevel@tonic-gate /*
18647c478bd9Sstevel@tonic-gate * This tuple is valid.
18657c478bd9Sstevel@tonic-gate */
18667c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
18677c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
18687c478bd9Sstevel@tonic-gate
18697c478bd9Sstevel@tonic-gate /*
18707c478bd9Sstevel@tonic-gate * If we're also parsing this tuple, then
18717c478bd9Sstevel@tonic-gate * setup the return values.
18727c478bd9Sstevel@tonic-gate */
18737c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
18747c478bd9Sstevel@tonic-gate cistpl_linktarget_t *cs =
18757c478bd9Sstevel@tonic-gate (cistpl_linktarget_t *)arg;
18767c478bd9Sstevel@tonic-gate
18777c478bd9Sstevel@tonic-gate cs->length = tl;
18787c478bd9Sstevel@tonic-gate (void) strncpy(cs->tpltg_tag, (char *)cp,
18797c478bd9Sstevel@tonic-gate cs->length);
18807c478bd9Sstevel@tonic-gate cs->tpltg_tag[cs->length] = NULL;
18817c478bd9Sstevel@tonic-gate
18827c478bd9Sstevel@tonic-gate } /* HANDTPL_PARSE_LTUPLE */
18837c478bd9Sstevel@tonic-gate
18847c478bd9Sstevel@tonic-gate } else {
18857c478bd9Sstevel@tonic-gate
18867c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_LINK_INVALID;
18877c478bd9Sstevel@tonic-gate return (HANDTPL_ERROR);
18887c478bd9Sstevel@tonic-gate
18897c478bd9Sstevel@tonic-gate } /* CISTPL_LINKTARGET */
18907c478bd9Sstevel@tonic-gate
18917c478bd9Sstevel@tonic-gate } /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */
18927c478bd9Sstevel@tonic-gate
18937c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
18947c478bd9Sstevel@tonic-gate }
18957c478bd9Sstevel@tonic-gate
18967c478bd9Sstevel@tonic-gate /*
18977c478bd9Sstevel@tonic-gate * cistpl_longlink_ac_handler - handler for CISTPL_LONGLINK_A and
18987c478bd9Sstevel@tonic-gate * CISTPL_LONGLINK_C tuples
18997c478bd9Sstevel@tonic-gate *
19007c478bd9Sstevel@tonic-gate * void *arg - points to a cistpl_longlink_ac_t * where the
19017c478bd9Sstevel@tonic-gate * information is stuffed into
19027c478bd9Sstevel@tonic-gate *
19037c478bd9Sstevel@tonic-gate * If the passed in tuple is CISTPL_LONGLINK_A the CISTPL_LONGLINK_AC_AM
19047c478bd9Sstevel@tonic-gate * flag in cistpl_longlink_ac_t->flags is set.
19057c478bd9Sstevel@tonic-gate * If the passed in tuple is CISTPL_LONGLINK_C the CISTPL_LONGLINK_AC_CM
19067c478bd9Sstevel@tonic-gate * flag in cistpl_longlink_ac_t->flags is set.
19077c478bd9Sstevel@tonic-gate *
19087c478bd9Sstevel@tonic-gate * If HANDTPL_COPY_DONE is set, we just validate the tuple but
19097c478bd9Sstevel@tonic-gate * do not return any values.
19107c478bd9Sstevel@tonic-gate * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and
19117c478bd9Sstevel@tonic-gate * return the parsed tuple data if the tuple is valid.
19127c478bd9Sstevel@tonic-gate *
19137c478bd9Sstevel@tonic-gate * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag
19147c478bd9Sstevel@tonic-gate * will be set in the tp->flags field and HANDTPL_ERROR
19157c478bd9Sstevel@tonic-gate * will be returned.
19167c478bd9Sstevel@tonic-gate *
19177c478bd9Sstevel@tonic-gate * The tuple is considered invalid if it's link field is less than
19187c478bd9Sstevel@tonic-gate * MIN_LONGLINK_AC_LENGTH.
19197c478bd9Sstevel@tonic-gate */
19207c478bd9Sstevel@tonic-gate uint32_t
19217c478bd9Sstevel@tonic-gate cistpl_longlink_ac_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
19227c478bd9Sstevel@tonic-gate void *arg)
19237c478bd9Sstevel@tonic-gate {
19247c478bd9Sstevel@tonic-gate /*
19257c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
19267c478bd9Sstevel@tonic-gate * generic handler for this
19277c478bd9Sstevel@tonic-gate */
19287c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
19297c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
19307c478bd9Sstevel@tonic-gate
19317c478bd9Sstevel@tonic-gate /*
19327c478bd9Sstevel@tonic-gate * Validate the tuple for both the HANDTPL_COPY_DONE case and
19337c478bd9Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case. Only return data in
19347c478bd9Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case.
19357c478bd9Sstevel@tonic-gate */
19367c478bd9Sstevel@tonic-gate if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) {
19377c478bd9Sstevel@tonic-gate
19387c478bd9Sstevel@tonic-gate if (tp->len >= (cisdata_t)MIN_LONGLINK_AC_LENGTH) {
19397c478bd9Sstevel@tonic-gate
19407c478bd9Sstevel@tonic-gate /*
19417c478bd9Sstevel@tonic-gate * This tuple is valid.
19427c478bd9Sstevel@tonic-gate */
19437c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
19447c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
19457c478bd9Sstevel@tonic-gate
19467c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
19477c478bd9Sstevel@tonic-gate cistpl_longlink_ac_t *cs =
19487c478bd9Sstevel@tonic-gate (cistpl_longlink_ac_t *)arg;
19497c478bd9Sstevel@tonic-gate
19507c478bd9Sstevel@tonic-gate switch (tp->type) {
19517c478bd9Sstevel@tonic-gate case CISTPL_LONGLINK_A:
19527c478bd9Sstevel@tonic-gate cs->flags = CISTPL_LONGLINK_AC_AM;
19537c478bd9Sstevel@tonic-gate break;
19547c478bd9Sstevel@tonic-gate
19557c478bd9Sstevel@tonic-gate case CISTPL_LONGLINK_C:
19567c478bd9Sstevel@tonic-gate cs->flags = CISTPL_LONGLINK_AC_CM;
19577c478bd9Sstevel@tonic-gate break;
19587c478bd9Sstevel@tonic-gate default:
19597c478bd9Sstevel@tonic-gate break;
19607c478bd9Sstevel@tonic-gate } /* switch */
19617c478bd9Sstevel@tonic-gate
19627c478bd9Sstevel@tonic-gate RESET_TP(tp);
19637c478bd9Sstevel@tonic-gate
19647c478bd9Sstevel@tonic-gate cs->tpll_addr = GET_LONG(tp);
19657c478bd9Sstevel@tonic-gate
19667c478bd9Sstevel@tonic-gate } /* HANDTPL_PARSE_LTUPLE */
19677c478bd9Sstevel@tonic-gate
19687c478bd9Sstevel@tonic-gate } else {
19697c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_LINK_INVALID;
19707c478bd9Sstevel@tonic-gate return (HANDTPL_ERROR);
19717c478bd9Sstevel@tonic-gate } /* MIN_LONGLINK_AC_LENGTH */
19727c478bd9Sstevel@tonic-gate
19737c478bd9Sstevel@tonic-gate } /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */
19747c478bd9Sstevel@tonic-gate
19757c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
19767c478bd9Sstevel@tonic-gate }
19777c478bd9Sstevel@tonic-gate
19787c478bd9Sstevel@tonic-gate /*
19797c478bd9Sstevel@tonic-gate * cistpl_longlink_mfc_handler - handler for CISTPL_LONGLINK_MFC tuples
19807c478bd9Sstevel@tonic-gate *
19817c478bd9Sstevel@tonic-gate * void *arg - points to a cistpl_longlink_mfc_t * where the
19827c478bd9Sstevel@tonic-gate * information is stuffed into
19837c478bd9Sstevel@tonic-gate *
19847c478bd9Sstevel@tonic-gate * If HANDTPL_COPY_DONE is set, we just validate the tuple but
19857c478bd9Sstevel@tonic-gate * do not return any values.
19867c478bd9Sstevel@tonic-gate * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and
19877c478bd9Sstevel@tonic-gate * return the parsed tuple data if the tuple is valid.
19887c478bd9Sstevel@tonic-gate *
19897c478bd9Sstevel@tonic-gate * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag
19907c478bd9Sstevel@tonic-gate * will be set in the tp->flags field and HANDTPL_ERROR
19917c478bd9Sstevel@tonic-gate * will be returned.
19927c478bd9Sstevel@tonic-gate *
19937c478bd9Sstevel@tonic-gate * If the number of register sets is invalid, the CISTPLF_PARAMS_INVALID
19947c478bd9Sstevel@tonic-gate * flag be set in the tp->flags field and HANDTPL_ERROR will be
19957c478bd9Sstevel@tonic-gate * returned.
19967c478bd9Sstevel@tonic-gate *
19977c478bd9Sstevel@tonic-gate * The tuple is considered invalid if it's link field is less than
19987c478bd9Sstevel@tonic-gate * MIN_LONGLINK_MFC_LENGTH or if the number of register sets
19997c478bd9Sstevel@tonic-gate * is not in the range [MIN_LONGLINK_MFC_NREGS..CIS_MAX_FUNCTIONS]
20007c478bd9Sstevel@tonic-gate */
20017c478bd9Sstevel@tonic-gate uint32_t
20027c478bd9Sstevel@tonic-gate cistpl_longlink_mfc_handler(cistpl_callout_t *co, cistpl_t *tp,
20037c478bd9Sstevel@tonic-gate uint32_t flags, void *arg)
20047c478bd9Sstevel@tonic-gate {
20057c478bd9Sstevel@tonic-gate /*
20067c478bd9Sstevel@tonic-gate * nothing special about our flags, so just call the
20077c478bd9Sstevel@tonic-gate * generic handler for this
20087c478bd9Sstevel@tonic-gate */
20097c478bd9Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
20107c478bd9Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
20117c478bd9Sstevel@tonic-gate
20127c478bd9Sstevel@tonic-gate /*
20137c478bd9Sstevel@tonic-gate * Validate the tuple for both the HANDTPL_COPY_DONE case and
20147c478bd9Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case. Only return data in
20157c478bd9Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case.
20167c478bd9Sstevel@tonic-gate */
20177c478bd9Sstevel@tonic-gate if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) {
20187c478bd9Sstevel@tonic-gate
20197c478bd9Sstevel@tonic-gate if (tp->len >= (cisdata_t)MIN_LONGLINK_MFC_LENGTH) {
20207c478bd9Sstevel@tonic-gate
20217c478bd9Sstevel@tonic-gate /*
20227c478bd9Sstevel@tonic-gate * This tuple is valid.
20237c478bd9Sstevel@tonic-gate */
20247c478bd9Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
20257c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
20267c478bd9Sstevel@tonic-gate
20277c478bd9Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
20287c478bd9Sstevel@tonic-gate cistpl_longlink_mfc_t *cs =
20297c478bd9Sstevel@tonic-gate (cistpl_longlink_mfc_t *)arg;
20307c478bd9Sstevel@tonic-gate int fn;
20317c478bd9Sstevel@tonic-gate
20327c478bd9Sstevel@tonic-gate RESET_TP(tp);
20337c478bd9Sstevel@tonic-gate
20347c478bd9Sstevel@tonic-gate /*
20357c478bd9Sstevel@tonic-gate * Get the number of register sets described
20367c478bd9Sstevel@tonic-gate * by this tuple. The number of register
20377c478bd9Sstevel@tonic-gate * sets must be greter than or equal to
20387c478bd9Sstevel@tonic-gate * MIN_LONGLINK_MFC_NREGS and less than
20397c478bd9Sstevel@tonic-gate * CIS_MAX_FUNCTIONS.
20407c478bd9Sstevel@tonic-gate * Note that the number of functions is equal
20417c478bd9Sstevel@tonic-gate * to the number of register sets.
20427c478bd9Sstevel@tonic-gate */
20437c478bd9Sstevel@tonic-gate cs->nregs = GET_BYTE(tp);
20447c478bd9Sstevel@tonic-gate cs->nfuncs = cs->nregs;
20457c478bd9Sstevel@tonic-gate
20467c478bd9Sstevel@tonic-gate if ((cs->nregs < MIN_LONGLINK_MFC_NREGS) ||
20477c478bd9Sstevel@tonic-gate (cs->nregs > CIS_MAX_FUNCTIONS)) {
20487c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_PARAMS_INVALID;
20497c478bd9Sstevel@tonic-gate return (HANDTPL_ERROR);
20507c478bd9Sstevel@tonic-gate }
20517c478bd9Sstevel@tonic-gate
20527c478bd9Sstevel@tonic-gate /*
20537c478bd9Sstevel@tonic-gate * Cycle through each function and setup
20547c478bd9Sstevel@tonic-gate * the appropriate parameter values.
20557c478bd9Sstevel@tonic-gate */
20567c478bd9Sstevel@tonic-gate for (fn = 0; fn < cs->nregs; fn++) {
20577c478bd9Sstevel@tonic-gate cs->function[fn].tas = GET_BYTE(tp);
20587c478bd9Sstevel@tonic-gate cs->function[fn].addr = GET_LONG(tp);
20597c478bd9Sstevel@tonic-gate } /* for (fn) */
20607c478bd9Sstevel@tonic-gate
20617c478bd9Sstevel@tonic-gate } /* HANDTPL_PARSE_LTUPLE */
20627c478bd9Sstevel@tonic-gate
20637c478bd9Sstevel@tonic-gate } else {
20647c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_LINK_INVALID;
20657c478bd9Sstevel@tonic-gate return (HANDTPL_ERROR);
20667c478bd9Sstevel@tonic-gate } /* MIN_LONGLINK_MFC_LENGTH */
20677c478bd9Sstevel@tonic-gate
20687c478bd9Sstevel@tonic-gate } /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */
20697c478bd9Sstevel@tonic-gate
20707c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
20717c478bd9Sstevel@tonic-gate }
20727c478bd9Sstevel@tonic-gate
20737c478bd9Sstevel@tonic-gate /*
20747c478bd9Sstevel@tonic-gate * cis_validate_longlink_acm - Validates the secondary tuple chain pointed
20757c478bd9Sstevel@tonic-gate * to by cisptr and specified by a previous
20767c478bd9Sstevel@tonic-gate * CISTPL_LONGLINK_A, CISTPL_LONGLINK_C or
20777c478bd9Sstevel@tonic-gate * CISTPL_LONGLINK_MFC tuple.
20787c478bd9Sstevel@tonic-gate *
20797c478bd9Sstevel@tonic-gate * cisptr->offset must be the offset to the first byte in the secondary
20807c478bd9Sstevel@tonic-gate * tuple chain to validate
20817c478bd9Sstevel@tonic-gate * cisptr->flags must be setup to specify the correct address space
20827c478bd9Sstevel@tonic-gate *
20837c478bd9Sstevel@tonic-gate * The cisptr->offset member is not updated after this function returns.
20847c478bd9Sstevel@tonic-gate *
20857c478bd9Sstevel@tonic-gate * BAD_CIS_ADDR is returned is the raw CIS data cound not be read.
20867c478bd9Sstevel@tonic-gate * HANDTPL_ERROR is returned if the secondary tuple chain does not
20877c478bd9Sstevel@tonic-gate * contain a valid CISTPL_LINKTARGET tuple.
20887c478bd9Sstevel@tonic-gate */
20897c478bd9Sstevel@tonic-gate uint32_t
20907c478bd9Sstevel@tonic-gate cis_validate_longlink_acm(cisptr_t *cisptr)
20917c478bd9Sstevel@tonic-gate {
20927c478bd9Sstevel@tonic-gate uchar_t cb[MIN_LINKTARGET_LENGTH + LINKTARGET_AC_HEADER_LENGTH];
20937c478bd9Sstevel@tonic-gate cisptr_t t_cisptr, *cpt;
20947c478bd9Sstevel@tonic-gate int tl;
20957c478bd9Sstevel@tonic-gate
20967c478bd9Sstevel@tonic-gate /*
20977c478bd9Sstevel@tonic-gate * Since the NEXT_CIS_ADDR macro increments the cisptr_t->offset
20987c478bd9Sstevel@tonic-gate * member, make a local copy of the cisptr and use the local
20997c478bd9Sstevel@tonic-gate * copy to read data from the card.
21007c478bd9Sstevel@tonic-gate */
21017c478bd9Sstevel@tonic-gate cpt = &t_cisptr;
21027c478bd9Sstevel@tonic-gate bcopy((caddr_t)cisptr, (caddr_t)cpt, sizeof (cisptr_t));
21037c478bd9Sstevel@tonic-gate
21047c478bd9Sstevel@tonic-gate for (tl = 0; tl < MIN_LINKTARGET_LENGTH +
21057c478bd9Sstevel@tonic-gate LINKTARGET_AC_HEADER_LENGTH; tl++) {
21067c478bd9Sstevel@tonic-gate
21077c478bd9Sstevel@tonic-gate cb[tl] = GET_CIS_DATA(cpt);
21087c478bd9Sstevel@tonic-gate if (!NEXT_CIS_ADDR(cpt))
21097c478bd9Sstevel@tonic-gate return ((uint32_t)BAD_CIS_ADDR);
21107c478bd9Sstevel@tonic-gate
21117c478bd9Sstevel@tonic-gate } /* for */
21127c478bd9Sstevel@tonic-gate
21137c478bd9Sstevel@tonic-gate if ((cb[0] == CISTPL_LINKTARGET) && (cb[1] >= MIN_LINKTARGET_LENGTH)) {
21147c478bd9Sstevel@tonic-gate cisdata_t *ltm = (cisdata_t *)CISTPL_LINKTARGET_MAGIC;
21157c478bd9Sstevel@tonic-gate
21167c478bd9Sstevel@tonic-gate for (tl = 0; tl < MIN_LINKTARGET_LENGTH; tl++, ltm++) {
21177c478bd9Sstevel@tonic-gate if (cb[tl + LINKTARGET_AC_HEADER_LENGTH] != *ltm)
21187c478bd9Sstevel@tonic-gate return (HANDTPL_ERROR);
21197c478bd9Sstevel@tonic-gate }
21207c478bd9Sstevel@tonic-gate return (CISTPLF_NOERROR);
21217c478bd9Sstevel@tonic-gate
21227c478bd9Sstevel@tonic-gate } /* if */
21237c478bd9Sstevel@tonic-gate
21247c478bd9Sstevel@tonic-gate return (HANDTPL_ERROR);
21257c478bd9Sstevel@tonic-gate }
21267c478bd9Sstevel@tonic-gate
21277c478bd9Sstevel@tonic-gate /*
21287c478bd9Sstevel@tonic-gate * cis_getstr (tp)
21297c478bd9Sstevel@tonic-gate * we want the address of the first character returned
21307c478bd9Sstevel@tonic-gate * but need to skip past the string in the cistpl_t structure
21317c478bd9Sstevel@tonic-gate */
21327c478bd9Sstevel@tonic-gate char *
21337c478bd9Sstevel@tonic-gate cis_getstr(cistpl_t *tp)
21347c478bd9Sstevel@tonic-gate {
21357c478bd9Sstevel@tonic-gate uchar_t *cp, *cpp;
21367c478bd9Sstevel@tonic-gate uchar_t x;
21377c478bd9Sstevel@tonic-gate
21387c478bd9Sstevel@tonic-gate cp = tp->read.byte;
21397c478bd9Sstevel@tonic-gate cpp = cp;
21407c478bd9Sstevel@tonic-gate
21417c478bd9Sstevel@tonic-gate while ((x = LOOK_BYTE(tp)) != 0 && x != 0xff) {
21427c478bd9Sstevel@tonic-gate x = GET_BYTE(tp);
21437c478bd9Sstevel@tonic-gate }
21447c478bd9Sstevel@tonic-gate
21457c478bd9Sstevel@tonic-gate (void) GET_BYTE(tp); /* get past that last byte */
21467c478bd9Sstevel@tonic-gate
21477c478bd9Sstevel@tonic-gate while ((*cpp != 0) && (*cpp != 0xff))
21487c478bd9Sstevel@tonic-gate cpp++;
21497c478bd9Sstevel@tonic-gate
21507c478bd9Sstevel@tonic-gate *cpp = NULL;
21517c478bd9Sstevel@tonic-gate
21527c478bd9Sstevel@tonic-gate return ((char *)cp);
21537c478bd9Sstevel@tonic-gate }
21547c478bd9Sstevel@tonic-gate
21557c478bd9Sstevel@tonic-gate /*
21567c478bd9Sstevel@tonic-gate * cis_return_name - returns name of tuple
21577c478bd9Sstevel@tonic-gate *
21587c478bd9Sstevel@tonic-gate * calling: co - pointer to cistpl_callout_t entry that contains
21597c478bd9Sstevel@tonic-gate * tuple name to return
21607c478bd9Sstevel@tonic-gate * gtn - pointer to cistpl_get_tuple_name_t to return
21617c478bd9Sstevel@tonic-gate * name into
21627c478bd9Sstevel@tonic-gate */
21637c478bd9Sstevel@tonic-gate static void
21647c478bd9Sstevel@tonic-gate cis_return_name(cistpl_callout_t *co, cistpl_get_tuple_name_t *gtn)
21657c478bd9Sstevel@tonic-gate {
21667c478bd9Sstevel@tonic-gate (void) strncpy(gtn->name, co->text, CIS_MAX_TUPLE_NAME_LEN);
21677c478bd9Sstevel@tonic-gate gtn->name[CIS_MAX_TUPLE_NAME_LEN - 1] = NULL;
21687c478bd9Sstevel@tonic-gate }
21697c478bd9Sstevel@tonic-gate
21707c478bd9Sstevel@tonic-gate /*
21717c478bd9Sstevel@tonic-gate * cis_malloc/cis_free
21727c478bd9Sstevel@tonic-gate * wrappers around kmem_alloc()/kmem_free() that
21737c478bd9Sstevel@tonic-gate * provide malloc/free style usage
21747c478bd9Sstevel@tonic-gate */
21757c478bd9Sstevel@tonic-gate
21767c478bd9Sstevel@tonic-gate caddr_t
21777c478bd9Sstevel@tonic-gate cis_malloc(size_t len)
21787c478bd9Sstevel@tonic-gate {
21797c478bd9Sstevel@tonic-gate caddr_t addr;
21807c478bd9Sstevel@tonic-gate
21817c478bd9Sstevel@tonic-gate addr = kmem_zalloc(len + sizeof (size_t), KM_SLEEP);
21827c478bd9Sstevel@tonic-gate *(size_t *)addr = len + sizeof (size_t);
21837c478bd9Sstevel@tonic-gate addr += sizeof (size_t);
21847c478bd9Sstevel@tonic-gate return (addr);
21857c478bd9Sstevel@tonic-gate }
21867c478bd9Sstevel@tonic-gate
21877c478bd9Sstevel@tonic-gate void
21887c478bd9Sstevel@tonic-gate cis_free(caddr_t addr)
21897c478bd9Sstevel@tonic-gate {
21907c478bd9Sstevel@tonic-gate size_t len;
21917c478bd9Sstevel@tonic-gate addr -= sizeof (size_t);
21927c478bd9Sstevel@tonic-gate len = *(size_t *)addr;
21937c478bd9Sstevel@tonic-gate kmem_free(addr, len);
21947c478bd9Sstevel@tonic-gate }
2195