10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
23*1278Shx147065 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * This file contains the tuple handlers that are called by the CIS
310Sstevel@tonic-gate * parser.
320Sstevel@tonic-gate *
330Sstevel@tonic-gate * XXX - how about a better explaination??
340Sstevel@tonic-gate */
350Sstevel@tonic-gate
360Sstevel@tonic-gate #include <sys/types.h>
370Sstevel@tonic-gate #include <sys/systm.h>
380Sstevel@tonic-gate #include <sys/user.h>
390Sstevel@tonic-gate #include <sys/buf.h>
400Sstevel@tonic-gate #include <sys/file.h>
410Sstevel@tonic-gate #include <sys/uio.h>
420Sstevel@tonic-gate #include <sys/conf.h>
430Sstevel@tonic-gate #include <sys/stat.h>
440Sstevel@tonic-gate #include <sys/autoconf.h>
450Sstevel@tonic-gate #include <sys/vtoc.h>
460Sstevel@tonic-gate #include <sys/dkio.h>
470Sstevel@tonic-gate #include <sys/ddi.h>
480Sstevel@tonic-gate #include <sys/sunddi.h>
490Sstevel@tonic-gate #include <sys/debug.h>
500Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
510Sstevel@tonic-gate #include <sys/kstat.h>
520Sstevel@tonic-gate #include <sys/kmem.h>
530Sstevel@tonic-gate #include <sys/modctl.h>
540Sstevel@tonic-gate #include <sys/kobj.h>
550Sstevel@tonic-gate #include <sys/callb.h>
560Sstevel@tonic-gate
570Sstevel@tonic-gate #include <sys/pctypes.h>
580Sstevel@tonic-gate #include <pcmcia/sys/cs_types.h>
590Sstevel@tonic-gate #include <pcmcia/sys/cis.h>
600Sstevel@tonic-gate #include <pcmcia/sys/cis_handlers.h>
610Sstevel@tonic-gate #include <pcmcia/sys/cs.h>
620Sstevel@tonic-gate #include <pcmcia/sys/cs_priv.h>
630Sstevel@tonic-gate #include <pcmcia/sys/cis_protos.h>
640Sstevel@tonic-gate
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate * Function prototypes
670Sstevel@tonic-gate */
680Sstevel@tonic-gate static void cistpl_pd_parse(cistpl_t *, cistpl_cftable_entry_pwr_t *);
690Sstevel@tonic-gate static void cis_return_name(cistpl_callout_t *, cistpl_get_tuple_name_t *);
700Sstevel@tonic-gate
710Sstevel@tonic-gate /*
72*1278Shx147065 * Fetch data functions.
73*1278Shx147065 */
74*1278Shx147065 uint16_t
cis_get_short(cistpl_t * tp)75*1278Shx147065 cis_get_short(cistpl_t *tp)
76*1278Shx147065 {
77*1278Shx147065 uint16_t result;
78*1278Shx147065
79*1278Shx147065 if (tp->flags & CISTPLF_AM_SPACE) {
80*1278Shx147065 result = GET_AM_BYTE(tp);
81*1278Shx147065 result |= GET_AM_BYTE(tp) << 8;
82*1278Shx147065 } else {
83*1278Shx147065 result = GET_CM_BYTE(tp);
84*1278Shx147065 result |= GET_CM_BYTE(tp) << 8;
85*1278Shx147065 }
86*1278Shx147065 return (result);
87*1278Shx147065 }
88*1278Shx147065
89*1278Shx147065 uint16_t
cis_get_be_short(cistpl_t * tp)90*1278Shx147065 cis_get_be_short(cistpl_t *tp)
91*1278Shx147065 {
92*1278Shx147065 uint16_t result;
93*1278Shx147065
94*1278Shx147065 if (tp->flags & CISTPLF_AM_SPACE) {
95*1278Shx147065 result = GET_AM_BYTE(tp) << 8;
96*1278Shx147065 result |= GET_AM_BYTE(tp);
97*1278Shx147065 } else {
98*1278Shx147065 result = GET_CM_BYTE(tp) << 8;
99*1278Shx147065 result |= GET_CM_BYTE(tp);
100*1278Shx147065 }
101*1278Shx147065 return (result);
102*1278Shx147065 }
103*1278Shx147065
104*1278Shx147065 uint32_t
cis_get_int24(cistpl_t * tp)105*1278Shx147065 cis_get_int24(cistpl_t *tp)
106*1278Shx147065 {
107*1278Shx147065 uint32_t result = cis_get_short(tp);
108*1278Shx147065
109*1278Shx147065 result |= GET_BYTE(tp) << 16;
110*1278Shx147065 return (result);
111*1278Shx147065 }
112*1278Shx147065
113*1278Shx147065 uint32_t
cis_get_long(cistpl_t * tp)114*1278Shx147065 cis_get_long(cistpl_t *tp)
115*1278Shx147065 {
116*1278Shx147065 uint32_t result = cis_get_short(tp);
117*1278Shx147065
118*1278Shx147065 result |= cis_get_short(tp) << 16;
119*1278Shx147065 return (result);
120*1278Shx147065 }
121*1278Shx147065
122*1278Shx147065 /*
1230Sstevel@tonic-gate * cis_tuple_handler - call the handler for the tuple described by the
1240Sstevel@tonic-gate * tuple pointer
1250Sstevel@tonic-gate *
1260Sstevel@tonic-gate * cistpl_callout_t *co - pointer to callout structure
1270Sstevel@tonic-gate * array to use to find this tuple
1280Sstevel@tonic-gate * cistpl_t *tp - pointer to a tuple structure
1290Sstevel@tonic-gate * int flags - action for the handler to perform
1300Sstevel@tonic-gate * XXX - we need a description of the flags passed to the tuple handler
1310Sstevel@tonic-gate * void *arg - argument to pass on to tuple handler
1320Sstevel@tonic-gate *
1330Sstevel@tonic-gate * If the tuple is not recognized but is is a vendor-specific tuple, we
1340Sstevel@tonic-gate * set the CISTPLF_VENDOR_SPECIFIC flag in the tuple.
1350Sstevel@tonic-gate *
1360Sstevel@tonic-gate * We return CISTPLF_UNKNOWN if this is an unrecognized tuple as well as
1370Sstevel@tonic-gate * set the CISTPLF_UNKNOWN flag in the tuple list structure. Note
1380Sstevel@tonic-gate * that encountering an unknown tuple is not necessarily an error,
1390Sstevel@tonic-gate * so we don't set the HANDTPL_ERROR flag on the return code. It
1400Sstevel@tonic-gate * is up to the caller to determine what an unrecognized tuple means.
1410Sstevel@tonic-gate *
1420Sstevel@tonic-gate * If this is a recognized tuple, the apropriate tuple handler is called and
1430Sstevel@tonic-gate * the return value from the handler is returned directly to the caller.
1440Sstevel@tonic-gate *
1450Sstevel@tonic-gate * The void *arg is optional, and it's meaning is dependent on the
1460Sstevel@tonic-gate * particular tuple handler called and the flags parameter.
1470Sstevel@tonic-gate *
1480Sstevel@tonic-gate * For the special case of HANDTPL_RETURN_NAME, we don't bother calling the
1490Sstevel@tonic-gate * tuple handler and just return the tuple name to the caller.
1500Sstevel@tonic-gate */
1510Sstevel@tonic-gate uint32_t
cis_tuple_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg,cisdata_t subtype)1520Sstevel@tonic-gate cis_tuple_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
1530Sstevel@tonic-gate void *arg, cisdata_t subtype)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate /*
1560Sstevel@tonic-gate * Check to see if this is a vendor-specific tuple.
1570Sstevel@tonic-gate */
1580Sstevel@tonic-gate if (CISTPL_IS_VENDOR_SPECIFIC(tp->type))
1590Sstevel@tonic-gate tp->flags |= CISTPLF_VENDOR_SPECIFIC;
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate /*
1620Sstevel@tonic-gate * Scan the callout list until we find the tuple passed to us, or we
1630Sstevel@tonic-gate * encounter a CISTPL_END in the callout list, which signals that
1640Sstevel@tonic-gate * there are no more tuples in the callout list.
1650Sstevel@tonic-gate */
1660Sstevel@tonic-gate while (co->type != (cisdata_t)CISTPL_END) {
1670Sstevel@tonic-gate if (co->type == tp->type &&
1680Sstevel@tonic-gate ((tp->type != CISTPL_FUNCE) ||
1690Sstevel@tonic-gate (tp->type == CISTPL_FUNCE && co->subtype == subtype))) {
1700Sstevel@tonic-gate tp->flags &= ~CISTPLF_UNKNOWN;
1710Sstevel@tonic-gate if (flags & HANDTPL_RETURN_NAME) {
1720Sstevel@tonic-gate cis_return_name(co, (cistpl_get_tuple_name_t *)arg);
1730Sstevel@tonic-gate return (CISTPLF_NOERROR);
1740Sstevel@tonic-gate } else {
1750Sstevel@tonic-gate return ((*co->handler) (co, tp, flags, arg));
1760Sstevel@tonic-gate } /* HANDTPL_RETURN_NAME */
1770Sstevel@tonic-gate } /* if */
1780Sstevel@tonic-gate co++;
1790Sstevel@tonic-gate } /* while */
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate /*
1820Sstevel@tonic-gate * If we didn't recognize the tuple and the caller wants the tuple
1830Sstevel@tonic-gate * name back, then return the "unknown tuple" string. At this
1840Sstevel@tonic-gate * point, "co" will be pointing to the last entry in the
1850Sstevel@tonic-gate * callout list. It's not an error to not recognize the tuple
1860Sstevel@tonic-gate * when the operation is HANDTPL_RETURN_NAME.
1870Sstevel@tonic-gate */
1880Sstevel@tonic-gate if (flags & HANDTPL_RETURN_NAME) {
1890Sstevel@tonic-gate cis_return_name(co, (cistpl_get_tuple_name_t *)arg);
1900Sstevel@tonic-gate return (CISTPLF_NOERROR);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate tp->flags |= CISTPLF_UNKNOWN;
1940Sstevel@tonic-gate return (CISTPLF_UNKNOWN);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate /*
1980Sstevel@tonic-gate * cis_no_tuple_handler - this generic tuple handler is used if no special
1990Sstevel@tonic-gate * tuple processing is required for the passed
2000Sstevel@tonic-gate * tuple
2010Sstevel@tonic-gate *
2020Sstevel@tonic-gate * cistpl_callout_t *co - pointer to this tuple's entry in the
2030Sstevel@tonic-gate * tuple callout structure
2040Sstevel@tonic-gate * cistpl_t *tp - pointer to this tuple's entry in the local linked list
2050Sstevel@tonic-gate * int flags - action to perform
2060Sstevel@tonic-gate *
2070Sstevel@tonic-gate * This handler will set the CISTPLF_COPYOK flag if the tuple link is greater
2080Sstevel@tonic-gate * than zero, indicating that it's OK to copy the tuple data body. It
2090Sstevel@tonic-gate * will also set whatever flags are specified in the callout structure.
2100Sstevel@tonic-gate *
2110Sstevel@tonic-gate * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE.
2120Sstevel@tonic-gate *
2130Sstevel@tonic-gate * We return CISTPLF_UNKNOWN if we're being called to parse the tuple.
2140Sstevel@tonic-gate *
2150Sstevel@tonic-gate * We return CISTPLF_NOERROR in every other case to indicate that this is a
2160Sstevel@tonic-gate * recognized tuple.
2170Sstevel@tonic-gate */
2180Sstevel@tonic-gate /*ARGSUSED*/
2190Sstevel@tonic-gate uint32_t
cis_no_tuple_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)2200Sstevel@tonic-gate cis_no_tuple_handler(cistpl_callout_t *co, cistpl_t *tp,
2210Sstevel@tonic-gate uint32_t flags, void *arg)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS) {
2240Sstevel@tonic-gate tp->flags |= co->flags; /* XXX - is = the right thing here? */
2250Sstevel@tonic-gate if (tp->len > 0)
2260Sstevel@tonic-gate tp->flags |= CISTPLF_COPYOK;
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
2300Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE)
2330Sstevel@tonic-gate return (CISTPLF_UNKNOWN);
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate return (CISTPLF_NOERROR);
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate /*
2390Sstevel@tonic-gate * cis_unknown_tuple_handler - this generic tuple handler is used if we don't
2400Sstevel@tonic-gate * understand this tuple
2410Sstevel@tonic-gate *
2420Sstevel@tonic-gate * cistpl_callout_t *co - pointer to this tuple's entry in the
2430Sstevel@tonic-gate * tuple callout structure
2440Sstevel@tonic-gate * cistpl_t *tp - pointer to this tuple's entry in the local linked list
2450Sstevel@tonic-gate * int flags - action to perform
2460Sstevel@tonic-gate *
2470Sstevel@tonic-gate * This handler will not set the CISTPLF_COPYOK flag since we don't know the
2480Sstevel@tonic-gate * contents of a vendor-specific tuple.
2490Sstevel@tonic-gate *
2500Sstevel@tonic-gate * We always set the CISTPLF_VALID when we're called with HANDTPL_COPY_DONE
2510Sstevel@tonic-gate * to specify that we understand this tuple's code, but not it's data
2520Sstevel@tonic-gate * body.
2530Sstevel@tonic-gate *
2540Sstevel@tonic-gate * We return CISTPLF_UNKNOWN if we're being called to parse the tuple or to
2550Sstevel@tonic-gate * perform any other operation.
2560Sstevel@tonic-gate */
2570Sstevel@tonic-gate /*ARGSUSED*/
2580Sstevel@tonic-gate uint32_t
cis_unknown_tuple_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)2590Sstevel@tonic-gate cis_unknown_tuple_handler(cistpl_callout_t *co, cistpl_t *tp,
2600Sstevel@tonic-gate uint32_t flags, void *arg)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS) {
2630Sstevel@tonic-gate tp->flags |= co->flags; /* XXX - is = the right thing here? */
2640Sstevel@tonic-gate return (CISTPLF_NOERROR);
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE) {
2680Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
2690Sstevel@tonic-gate return (CISTPLF_NOERROR);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate return (CISTPLF_UNKNOWN);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate /*
2760Sstevel@tonic-gate * cistpl_vers_1_handler - handler for the CISTPL_VERS_1 tuple
2770Sstevel@tonic-gate *
2780Sstevel@tonic-gate * void *arg - points to a cistpl_vers_1_t * where the
2790Sstevel@tonic-gate * information is stuffed into
2800Sstevel@tonic-gate */
2810Sstevel@tonic-gate uint32_t
cistpl_vers_1_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)2820Sstevel@tonic-gate cistpl_vers_1_handler(cistpl_callout_t *co, cistpl_t *tp,
2830Sstevel@tonic-gate uint32_t flags, void *arg)
2840Sstevel@tonic-gate {
2850Sstevel@tonic-gate /*
2860Sstevel@tonic-gate * nothing special about our flags, so just call the
2870Sstevel@tonic-gate * generic handler for this
2880Sstevel@tonic-gate */
2890Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
2900Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate /*
2930Sstevel@tonic-gate * We don't currently validate this tuple. This call will
2940Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
2950Sstevel@tonic-gate */
2960Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
2970Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
3000Sstevel@tonic-gate cistpl_vers_1_t *cs = (cistpl_vers_1_t *)arg;
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate RESET_TP(tp);
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate cs->major = GET_BYTE(tp);
3060Sstevel@tonic-gate cs->minor = GET_BYTE(tp);
3070Sstevel@tonic-gate for (cs->ns = 0; GET_LEN(tp) > 0 &&
3080Sstevel@tonic-gate /* CSTYLED */
3090Sstevel@tonic-gate cs->ns < CISTPL_VERS_1_MAX_PROD_STRINGS; ) {
3100Sstevel@tonic-gate (void) strcpy(cs->pi[cs->ns++], cis_getstr(tp));
3110Sstevel@tonic-gate } /* for */
3120Sstevel@tonic-gate } /* HANDTPL_PARSE_LTUPLE */
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate return (CISTPLF_NOERROR);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate /*
3180Sstevel@tonic-gate * cistpl_config_handler - handler for the CISTPL_CONFIG tuple
3190Sstevel@tonic-gate *
3200Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
3210Sstevel@tonic-gate *
3220Sstevel@tonic-gate * For the first ten config registers we set the present flags in the
3230Sstevel@tonic-gate * cistpl_config_t if the register exists. The flags that we use
3240Sstevel@tonic-gate * for this are the same as the flags reguired for the Card Services
3250Sstevel@tonic-gate * RequestConfiguration function and they can be used by clients
3260Sstevel@tonic-gate * directly without requiring any remapping of values.
3270Sstevel@tonic-gate *
3280Sstevel@tonic-gate * XXX we don't handle TPCC_SBTPL subtuples yet
3290Sstevel@tonic-gate */
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate uint32_t config_regs_present_map[] = {
3320Sstevel@tonic-gate CONFIG_OPTION_REG_PRESENT, /* COR present */
3330Sstevel@tonic-gate CONFIG_STATUS_REG_PRESENT, /* STAT reg present */
3340Sstevel@tonic-gate CONFIG_PINREPL_REG_PRESENT, /* PRR present */
3350Sstevel@tonic-gate CONFIG_COPY_REG_PRESENT, /* COPY reg present */
3360Sstevel@tonic-gate CONFIG_EXSTAT_REG_PRESENT, /* EXSTAT reg present */
3370Sstevel@tonic-gate CONFIG_IOBASE0_REG_PRESENT, /* IOBASE0 reg present */
3380Sstevel@tonic-gate CONFIG_IOBASE1_REG_PRESENT, /* IOBASE1 reg present */
3390Sstevel@tonic-gate CONFIG_IOBASE2_REG_PRESENT, /* IOBASE2 reg present */
3400Sstevel@tonic-gate CONFIG_IOBASE3_REG_PRESENT, /* IOBASE3 reg present */
3410Sstevel@tonic-gate CONFIG_IOLIMIT_REG_PRESENT, /* IOLIMIT reg present */
3420Sstevel@tonic-gate };
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate uint32_t
cistpl_config_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)3450Sstevel@tonic-gate cistpl_config_handler(cistpl_callout_t *co, cistpl_t *tp,
3460Sstevel@tonic-gate uint32_t flags, void *arg)
3470Sstevel@tonic-gate {
3480Sstevel@tonic-gate cisdata_t tpcc_sz;
3490Sstevel@tonic-gate int i, n, nrb, na, hr = 0;
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate /*
3520Sstevel@tonic-gate * nothing special about our flags, so just call the
3530Sstevel@tonic-gate * generic handler for this
3540Sstevel@tonic-gate */
3550Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
3560Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate /*
3590Sstevel@tonic-gate * We don't currently validate this tuple. This call will
3600Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
3610Sstevel@tonic-gate */
3620Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
3630Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
3660Sstevel@tonic-gate cistpl_config_t *cr = (cistpl_config_t *)arg;
3670Sstevel@tonic-gate int crn = 0;
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate RESET_TP(tp);
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate tpcc_sz = GET_BYTE(tp); /* config regs size fields */
3720Sstevel@tonic-gate cr->last = GET_BYTE(tp); /* last config index */
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate na = (tpcc_sz&3)+1; /* config regs address bytes */
3750Sstevel@tonic-gate nrb = ((tpcc_sz>>2)&0x0f)+1; /* number of bytes in config */
3760Sstevel@tonic-gate /* regs presence mask */
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate /*
3790Sstevel@tonic-gate * Construct the base offset address for the config registers.
3800Sstevel@tonic-gate * We jump through these hoops because the base address
3810Sstevel@tonic-gate * can be between one and four bytes in length.
3820Sstevel@tonic-gate */
3830Sstevel@tonic-gate cr->base = 0;
3840Sstevel@tonic-gate n = na;
3850Sstevel@tonic-gate while (n--)
3860Sstevel@tonic-gate cr->base |= ((GET_BYTE(tp) & 0x0ff) <<
3870Sstevel@tonic-gate (8 * (na - (n+1))));
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate /*
3900Sstevel@tonic-gate * Go through the config register presense mask bit by bit and
3910Sstevel@tonic-gate * figure out which config registers are present and which
3920Sstevel@tonic-gate * aren't.
3930Sstevel@tonic-gate * For the first ten config registers, set the appropriate
3940Sstevel@tonic-gate * bits in the cr->present member so that the caller
3950Sstevel@tonic-gate * doesn't have to do this.
3960Sstevel@tonic-gate */
3970Sstevel@tonic-gate cr->nr = 0;
3980Sstevel@tonic-gate cr->present = 0;
3990Sstevel@tonic-gate n = nrb;
4000Sstevel@tonic-gate while (n--) {
4010Sstevel@tonic-gate for (i = 0; i < 8; i++, crn++) {
4020Sstevel@tonic-gate if (LOOK_BYTE(tp) & (1<<i)) {
4030Sstevel@tonic-gate if (crn < (sizeof (config_regs_present_map)/
4040Sstevel@tonic-gate sizeof (uint32_t)))
4050Sstevel@tonic-gate cr->present |=
4060Sstevel@tonic-gate config_regs_present_map[crn];
4070Sstevel@tonic-gate cr->nr++;
4080Sstevel@tonic-gate cr->hr = hr;
4090Sstevel@tonic-gate cr->regs[hr] = MAKE_CONFIG_REG_ADDR(
4100Sstevel@tonic-gate cr->base, hr);
4110Sstevel@tonic-gate } /* LOOK_BYTE */
4120Sstevel@tonic-gate hr++;
4130Sstevel@tonic-gate } /* for */
4140Sstevel@tonic-gate (void) GET_BYTE(tp);
4150Sstevel@tonic-gate } /* while */
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate return (CISTPLF_NOERROR);
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate /*
4220Sstevel@tonic-gate * cistpl_device_handler - handler for the CISTPL_DEVICE, CISTPL_DEVICE_A,
4230Sstevel@tonic-gate * CISTPL_DEVICE_OC and CISTPL_DEVICE_OA tuples
4240Sstevel@tonic-gate *
4250Sstevel@tonic-gate * void *arg - points to a cistpl_device_t * where the
4260Sstevel@tonic-gate * information is stuffed into
4270Sstevel@tonic-gate *
4280Sstevel@tonic-gate * XXX - we only handle CISTPL_DEVICE_MAX_DEVICES device descriptions
4290Sstevel@tonic-gate * described in the tuple
4300Sstevel@tonic-gate */
4310Sstevel@tonic-gate uint32_t
cistpl_device_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)4320Sstevel@tonic-gate cistpl_device_handler(cistpl_callout_t *co, cistpl_t *tp,
4330Sstevel@tonic-gate uint32_t flags, void *arg)
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate cisdata_t dev_id;
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate * nothing special about our flags, so just call the
4390Sstevel@tonic-gate * generic handler for this
4400Sstevel@tonic-gate */
4410Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
4420Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate /*
4450Sstevel@tonic-gate * We don't currently validate this tuple. This call will
4460Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
4470Sstevel@tonic-gate */
4480Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
4490Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
4520Sstevel@tonic-gate convert_speed_t convert_speed;
4530Sstevel@tonic-gate cistpl_device_t *dt = (cistpl_device_t *)arg;
4540Sstevel@tonic-gate cistpl_device_node_t *cdn;
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate /*
4570Sstevel@tonic-gate * XXX - fix this to look for more than one device definition
4580Sstevel@tonic-gate * XXX - fix this to handle the OC fields for
4590Sstevel@tonic-gate * CISTPL_DEVICE_OC and CISTPL_DEVICE_OA
4600Sstevel@tonic-gate */
4610Sstevel@tonic-gate dt->num_devices = 1;
4620Sstevel@tonic-gate cdn = &dt->devnode[0];
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate cdn->flags = 0;
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate RESET_TP(tp);
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate dev_id = GET_BYTE(tp);
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate /*
4710Sstevel@tonic-gate * Get the device speed code. If it's 7, then there is an
4720Sstevel@tonic-gate * extended speed code table in use, so parse that.
4730Sstevel@tonic-gate * If it's anything else, get the speed information
4740Sstevel@tonic-gate * directly from the device speed code.
4750Sstevel@tonic-gate */
4760Sstevel@tonic-gate if ((dev_id & 7) == 7) {
4770Sstevel@tonic-gate cdn->nS_speed = cistpl_devspeed(tp, 0, CISTPL_DEVSPEED_EXT);
4780Sstevel@tonic-gate } else {
4790Sstevel@tonic-gate cdn->nS_speed = cistpl_devspeed(NULL, dev_id,
4800Sstevel@tonic-gate CISTPL_DEVSPEED_TABLE);
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate /*
4840Sstevel@tonic-gate * Convert the speed in nS to a device speed code.
4850Sstevel@tonic-gate * XXX - should check return code from cis_convert_devspeed()
4860Sstevel@tonic-gate */
4870Sstevel@tonic-gate convert_speed.Attributes = CONVERT_NS_TO_DEVSPEED;
4880Sstevel@tonic-gate convert_speed.nS = cdn->nS_speed;
4890Sstevel@tonic-gate (void) cis_convert_devspeed(&convert_speed);
4900Sstevel@tonic-gate cdn->speed = convert_speed.devspeed;
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate if (dev_id & 8)
4930Sstevel@tonic-gate cdn->flags |= CISTPL_DEVICE_WPS;
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate /*
4960Sstevel@tonic-gate * Set the device type. Note that we take the raw value
4970Sstevel@tonic-gate * from the tuple and pass it back to the caller.
4980Sstevel@tonic-gate * If the device type codes in the standard change,
4990Sstevel@tonic-gate * we will have to change our flags as well.
5000Sstevel@tonic-gate */
5010Sstevel@tonic-gate cdn->type = (dev_id>>4) & 0x0f;
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate /*
5040Sstevel@tonic-gate * XXX - what about the device_size byte? Is the spec wrong?
5050Sstevel@tonic-gate */
5060Sstevel@tonic-gate cdn->size = GET_BYTE(tp);
5070Sstevel@tonic-gate /* check for end of list */
5080Sstevel@tonic-gate if (cdn->size != 0x0ff) {
5090Sstevel@tonic-gate convert_size_t convert_size;
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate convert_size.devsize = cdn->size;
5120Sstevel@tonic-gate convert_size.Attributes = CONVERT_DEVSIZE_TO_BYTES;
5130Sstevel@tonic-gate (void) cis_convert_devsize(&convert_size);
5140Sstevel@tonic-gate cdn->size_in_bytes = convert_size.bytes;
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate return (CISTPLF_NOERROR);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate /*
5220Sstevel@tonic-gate * cistpl_cftable_handler - handler for the CISTPL_CFTABLE_ENTRY tuple
5230Sstevel@tonic-gate *
5240Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
5250Sstevel@tonic-gate *
5260Sstevel@tonic-gate * Return: CISTPLF_NOERROR - if no error parsing tuple
5270Sstevel@tonic-gate * HANDTPL_ERROR - if error parsing tuple
5280Sstevel@tonic-gate */
5290Sstevel@tonic-gate extern uint32_t cistpl_cftable_io_size_table[];
5300Sstevel@tonic-gate extern uint32_t cistpl_cftable_shift_table[];
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate uint32_t
cistpl_cftable_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)5330Sstevel@tonic-gate cistpl_cftable_handler(cistpl_callout_t *co, cistpl_t *tp,
5340Sstevel@tonic-gate uint32_t flags, void *arg)
5350Sstevel@tonic-gate {
5360Sstevel@tonic-gate cisdata_t tpce_indx, tpce_fs, tpce_td, sf, tpce_io, nr;
5370Sstevel@tonic-gate cisdata_t ior_desc, tpce_ir, tpce_msd;
5380Sstevel@tonic-gate int i, j;
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate /*
5410Sstevel@tonic-gate * nothing special about our flags, so just call the
5420Sstevel@tonic-gate * generic handler for this
5430Sstevel@tonic-gate */
5440Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
5450Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate * We don't currently validate this tuple. This call will
5490Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
5500Sstevel@tonic-gate */
5510Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
5520Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
5550Sstevel@tonic-gate cistpl_cftable_entry_t *ce = (cistpl_cftable_entry_t *)arg;
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate RESET_TP(tp);
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate * Check to see if we have an interface description byte. If
5610Sstevel@tonic-gate * we do, grab it and give it directly to the caller, and
5620Sstevel@tonic-gate * set a flag so the caller knows that it's there.
5630Sstevel@tonic-gate * We also setup the appropriate values in the ce->pin member
5640Sstevel@tonic-gate * so that clients can feed this value directly to the
5650Sstevel@tonic-gate * Card Services RequestConfiguration call.
5660Sstevel@tonic-gate */
5670Sstevel@tonic-gate if ((tpce_indx = GET_BYTE(tp)) & CISTPL_CFTABLE_TPCE_IFM) {
5680Sstevel@tonic-gate ce->ifc = GET_BYTE(tp);
5690Sstevel@tonic-gate
5700Sstevel@tonic-gate ce->pin = 0;
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_BVD)
5730Sstevel@tonic-gate ce->pin |= (PRR_BVD1_STATUS | PRR_BVD2_STATUS |
5740Sstevel@tonic-gate PRR_BVD1_EVENT | PRR_BVD2_EVENT);
5750Sstevel@tonic-gate if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_WP)
5760Sstevel@tonic-gate ce->pin |= (PRR_WP_STATUS | PRR_WP_EVENT);
5770Sstevel@tonic-gate if (ce->ifc & CISTPL_CFTABLE_TPCE_IF_RDY)
5780Sstevel@tonic-gate ce->pin |= (PRR_READY_STATUS | PRR_READY_EVENT);
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_IF;
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate /*
5840Sstevel@tonic-gate * Return the configuration index to the caller, and set the
5850Sstevel@tonic-gate * default configuration flag if this is a default
5860Sstevel@tonic-gate * configuration.
5870Sstevel@tonic-gate */
5880Sstevel@tonic-gate ce->index = tpce_indx & CISTPL_CFTABLE_TPCE_CFGENTRYM;
5890Sstevel@tonic-gate if (tpce_indx & CISTPL_CFTABLE_TPCE_DEFAULTM)
5900Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_DEFAULT;
5910Sstevel@tonic-gate
5920Sstevel@tonic-gate /*
5930Sstevel@tonic-gate * Feature selection flags.
5940Sstevel@tonic-gate */
5950Sstevel@tonic-gate tpce_fs = GET_BYTE(tp);
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate /*
5980Sstevel@tonic-gate * See what types of power information are available,
5990Sstevel@tonic-gate * and if there is any, set the global power
6000Sstevel@tonic-gate * information flag as well as a flag for each
6010Sstevel@tonic-gate * power description available.
6020Sstevel@tonic-gate */
6030Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_PWRM) {
6040Sstevel@tonic-gate cistpl_cftable_entry_pd_t *pd = &ce->pd;
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_PWR;
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate switch (tpce_fs & CISTPL_CFTABLE_TPCE_FS_PWRM) {
6090Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_PWR_VPP2M:
6100Sstevel@tonic-gate pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VPP2;
6110Sstevel@tonic-gate /* FALLTHROUGH */
6120Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_PWR_VPP1M:
6130Sstevel@tonic-gate pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VPP1;
6140Sstevel@tonic-gate /* FALLTHROUGH */
6150Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_PWR_VCCM:
6160Sstevel@tonic-gate pd->flags |= CISTPL_CFTABLE_TPCE_FS_PWR_VCC;
6170Sstevel@tonic-gate } /* switch */
6180Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_PWRM) */
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate /*
6210Sstevel@tonic-gate * Set up the global memory information flag.
6220Sstevel@tonic-gate */
6230Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MEMM)
6240Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_MEM;
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate /*
6270Sstevel@tonic-gate * Parse the various power description structures.
6280Sstevel@tonic-gate */
6290Sstevel@tonic-gate if (ce->flags & CISTPL_CFTABLE_TPCE_FS_PWR) {
6300Sstevel@tonic-gate cistpl_cftable_entry_pd_t *pd = &ce->pd;
6310Sstevel@tonic-gate cistpl_cftable_entry_pwr_t *pwr;
6320Sstevel@tonic-gate /*
6330Sstevel@tonic-gate * Collect any Vcc information.
6340Sstevel@tonic-gate */
6350Sstevel@tonic-gate if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VCC) {
6360Sstevel@tonic-gate pwr = &pd->pd_vcc;
6370Sstevel@tonic-gate cistpl_pd_parse(tp, pwr);
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate /*
6400Sstevel@tonic-gate * Collect any Vpp1 information.
6410Sstevel@tonic-gate */
6420Sstevel@tonic-gate if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VPP1) {
6430Sstevel@tonic-gate pwr = &pd->pd_vpp1;
6440Sstevel@tonic-gate cistpl_pd_parse(tp, pwr);
6450Sstevel@tonic-gate }
6460Sstevel@tonic-gate /*
6470Sstevel@tonic-gate * Collect any Vpp2 information.
6480Sstevel@tonic-gate */
6490Sstevel@tonic-gate if (pd->flags & CISTPL_CFTABLE_TPCE_FS_PWR_VPP2) {
6500Sstevel@tonic-gate pwr = &pd->pd_vpp2;
6510Sstevel@tonic-gate cistpl_pd_parse(tp, pwr);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_PWR) */
6540Sstevel@tonic-gate
6550Sstevel@tonic-gate /*
6560Sstevel@tonic-gate * Check to see if there's any timing information, and if
6570Sstevel@tonic-gate * so, parse the tuple data and store it in the
6580Sstevel@tonic-gate * caller's structure. Set a flag in the global
6590Sstevel@tonic-gate * flag field indicating that there is timing information.
6600Sstevel@tonic-gate */
6610Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_TDM) {
6620Sstevel@tonic-gate convert_speed_t convert_speed;
6630Sstevel@tonic-gate cistpl_cftable_entry_speed_t *sp = &ce->speed;
6640Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_TD;
6650Sstevel@tonic-gate tpce_td = GET_BYTE(tp);
6660Sstevel@tonic-gate /*
6670Sstevel@tonic-gate * Parse TPCE_TD to get the various timing
6680Sstevel@tonic-gate * scale factors. Each scale factor has
6690Sstevel@tonic-gate * a value that indicates that the particular
6700Sstevel@tonic-gate * timing parameter doesn't exist.
6710Sstevel@tonic-gate */
6720Sstevel@tonic-gate if ((sf = (tpce_td &
6730Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_WAITM)) !=
6740Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_WAITM) {
6750Sstevel@tonic-gate sp->nS_wait = cistpl_devspeed(tp,
6760Sstevel@tonic-gate GET_TPCE_FS_TD_WAITS(sf),
6770Sstevel@tonic-gate CISTPL_DEVSPEED_EXT);
6780Sstevel@tonic-gate convert_speed.Attributes =
6790Sstevel@tonic-gate CONVERT_NS_TO_DEVSPEED;
6800Sstevel@tonic-gate convert_speed.nS = sp->nS_wait;
6810Sstevel@tonic-gate (void) cis_convert_devspeed(&convert_speed);
6820Sstevel@tonic-gate sp->wait = convert_speed.devspeed;
6830Sstevel@tonic-gate sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_WAIT;
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate if ((sf = (tpce_td & CISTPL_CFTABLE_TPCE_FS_TD_RDYM)) !=
6870Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_RDYM) {
6880Sstevel@tonic-gate sp->nS_rdybsy = cistpl_devspeed(tp,
6890Sstevel@tonic-gate GET_TPCE_FS_TD_RDYS(sf),
6900Sstevel@tonic-gate CISTPL_DEVSPEED_EXT);
6910Sstevel@tonic-gate convert_speed.Attributes =
6920Sstevel@tonic-gate CONVERT_NS_TO_DEVSPEED;
6930Sstevel@tonic-gate convert_speed.nS = sp->nS_rdybsy;
6940Sstevel@tonic-gate (void) cis_convert_devspeed(&convert_speed);
6950Sstevel@tonic-gate sp->rdybsy = convert_speed.devspeed;
6960Sstevel@tonic-gate sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_RDY;
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate if ((sf = (tpce_td &
7000Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_RSVDM)) !=
7010Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_TD_RSVDM) {
7020Sstevel@tonic-gate sp->nS_rsvd = cistpl_devspeed(tp,
7030Sstevel@tonic-gate GET_TPCE_FS_TD_RSVDS(sf),
7040Sstevel@tonic-gate CISTPL_DEVSPEED_EXT);
7050Sstevel@tonic-gate convert_speed.Attributes =
7060Sstevel@tonic-gate CONVERT_NS_TO_DEVSPEED;
7070Sstevel@tonic-gate convert_speed.nS = sp->nS_rsvd;
7080Sstevel@tonic-gate (void) cis_convert_devspeed(&convert_speed);
7090Sstevel@tonic-gate sp->rsvd = convert_speed.devspeed;
7100Sstevel@tonic-gate sp->flags |= CISTPL_CFTABLE_TPCE_FS_TD_RSVD;
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_TDM) */
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate /*
7160Sstevel@tonic-gate * Parse any I/O address information. If there is I/O
7170Sstevel@tonic-gate * inforamtion, set a flag in the global flag field
7180Sstevel@tonic-gate * to let the caller know.
7190Sstevel@tonic-gate */
7200Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_IOM) {
7210Sstevel@tonic-gate cistpl_cftable_entry_io_t *io = &ce->io;
7220Sstevel@tonic-gate
7230Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_IO;
7240Sstevel@tonic-gate tpce_io = GET_BYTE(tp);
7250Sstevel@tonic-gate /*
7260Sstevel@tonic-gate * Pass any I/O flags that are in the tuple directly
7270Sstevel@tonic-gate * to the caller.
7280Sstevel@tonic-gate */
7290Sstevel@tonic-gate io->flags = tpce_io;
7300Sstevel@tonic-gate io->addr_lines = tpce_io &
7310Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_IO_ALM;
7320Sstevel@tonic-gate /*
7330Sstevel@tonic-gate * If there are any ranges, extract the number of
7340Sstevel@tonic-gate * ranges and the range descriptions.
7350Sstevel@tonic-gate */
7360Sstevel@tonic-gate if (tpce_io & CISTPL_CFTABLE_TPCE_FS_IO_RANGEM) {
7370Sstevel@tonic-gate cistpl_cftable_entry_io_range_t *ior;
7380Sstevel@tonic-gate ior_desc = GET_BYTE(tp);
7390Sstevel@tonic-gate /*
7400Sstevel@tonic-gate * Number of I/O ranges is the value specified
7410Sstevel@tonic-gate * in the tuple plus one, so there's
7420Sstevel@tonic-gate * always at least one I/O range if the
7430Sstevel@tonic-gate * CISTPL_CFTABLE_TPCE_FS_IO_RANGEM bit
7440Sstevel@tonic-gate * in the I/O flags register is set.
7450Sstevel@tonic-gate */
7460Sstevel@tonic-gate nr = (ior_desc & 0x0f) + 1;
7470Sstevel@tonic-gate io->ranges = nr;
7480Sstevel@tonic-gate /*
7490Sstevel@tonic-gate * Cycle through each I/O range.
7500Sstevel@tonic-gate */
7510Sstevel@tonic-gate for (i = 0; i < (int)nr; i++) {
7520Sstevel@tonic-gate ior = &io->range[i];
7530Sstevel@tonic-gate ior->addr = 0;
7540Sstevel@tonic-gate ior->length = 0;
7550Sstevel@tonic-gate /*
7560Sstevel@tonic-gate * Gather the address information.
7570Sstevel@tonic-gate * It's OK if there's no address
7580Sstevel@tonic-gate * information in which case this
7590Sstevel@tonic-gate * loop will never execute.
7600Sstevel@tonic-gate */
7610Sstevel@tonic-gate for (j = 0; j <
7620Sstevel@tonic-gate cistpl_cftable_io_size_table[
7630Sstevel@tonic-gate (ior_desc>>4)&3];
7640Sstevel@tonic-gate j++)
7650Sstevel@tonic-gate ior->addr |= (GET_BYTE(tp) <<
7660Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
7670Sstevel@tonic-gate /*
7680Sstevel@tonic-gate * Gather the length information.
7690Sstevel@tonic-gate * It's OK if there's no length
7700Sstevel@tonic-gate * information in which case this
7710Sstevel@tonic-gate * loop will never execute.
7720Sstevel@tonic-gate */
7730Sstevel@tonic-gate for (j = 0; j <
7740Sstevel@tonic-gate cistpl_cftable_io_size_table[
7750Sstevel@tonic-gate (ior_desc>>6)&3];
7760Sstevel@tonic-gate j++)
7770Sstevel@tonic-gate ior->length |= (GET_BYTE(tp) <<
7780Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
7790Sstevel@tonic-gate } /* for (nr) */
7800Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_IO_RANGEM) */
7810Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_IOM) */
7820Sstevel@tonic-gate
7830Sstevel@tonic-gate /*
7840Sstevel@tonic-gate * Parse any IRQ information. If there is IRQ inforamtion,
7850Sstevel@tonic-gate * set a flag in the global flag field to let the
7860Sstevel@tonic-gate * caller know.
7870Sstevel@tonic-gate */
7880Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_IRQM) {
7890Sstevel@tonic-gate cistpl_cftable_entry_irq_t *irq = &ce->irq;
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_IRQ;
7920Sstevel@tonic-gate tpce_ir = GET_BYTE(tp);
7930Sstevel@tonic-gate /*
7940Sstevel@tonic-gate * Pass any IRQ flags that are in the tuple directly
7950Sstevel@tonic-gate * to the caller.
7960Sstevel@tonic-gate */
7970Sstevel@tonic-gate irq->flags = tpce_ir;
7980Sstevel@tonic-gate /*
7990Sstevel@tonic-gate * Check for and parse the extended IRQ bitmask
8000Sstevel@tonic-gate * if it exists.
8010Sstevel@tonic-gate */
8020Sstevel@tonic-gate if (tpce_ir & CISTPL_CFTABLE_TPCE_FS_IRQ_MASKM) {
8030Sstevel@tonic-gate irq->irqs = GET_BYTE(tp) & 0x0ff;
8040Sstevel@tonic-gate irq->irqs |= (GET_BYTE(tp) << 8)&0x0ff00;
8050Sstevel@tonic-gate } else {
8060Sstevel@tonic-gate irq->irqs = (1<< (tpce_ir&0x0f));
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_IRQM) */
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate /*
8110Sstevel@tonic-gate * Parse any memory information.
8120Sstevel@tonic-gate *
8130Sstevel@tonic-gate * XXX - should be a cleaner way to parse this information.
8140Sstevel@tonic-gate */
8150Sstevel@tonic-gate if (ce->flags & CISTPL_CFTABLE_TPCE_FS_MEM) {
8160Sstevel@tonic-gate cistpl_cftable_entry_mem_t *mem = &ce->mem;
8170Sstevel@tonic-gate cistpl_cftable_entry_mem_window_t *win;
8180Sstevel@tonic-gate /*
8190Sstevel@tonic-gate * Switch on the type of memory description
8200Sstevel@tonic-gate * information that is available.
8210Sstevel@tonic-gate */
8220Sstevel@tonic-gate switch (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MEMM) {
8230Sstevel@tonic-gate /*
8240Sstevel@tonic-gate * variable length memory space description
8250Sstevel@tonic-gate */
8260Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_MEM3M:
8270Sstevel@tonic-gate mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM3;
8280Sstevel@tonic-gate /* memory space descriptor */
8290Sstevel@tonic-gate tpce_msd = GET_BYTE(tp);
8300Sstevel@tonic-gate mem->windows = ((tpce_msd &
8310Sstevel@tonic-gate (CISTPL_CFTABLE_ENTRY_MAX_MEM_WINDOWS -
8320Sstevel@tonic-gate 1)) + 1);
8330Sstevel@tonic-gate /*
8340Sstevel@tonic-gate * If there's host address information, let
8350Sstevel@tonic-gate * the caller know.
8360Sstevel@tonic-gate */
8370Sstevel@tonic-gate if (tpce_msd & CISTPL_CFTABLE_TPCE_FS_MEM_HOSTM)
8380Sstevel@tonic-gate mem->flags |=
8390Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_HOST;
8400Sstevel@tonic-gate /*
8410Sstevel@tonic-gate * Cycle through each window space description
8420Sstevel@tonic-gate * and collect all the interesting bits.
8430Sstevel@tonic-gate */
8440Sstevel@tonic-gate for (i = 0; i < mem->windows; i++) {
8450Sstevel@tonic-gate win = &mem->window[i];
8460Sstevel@tonic-gate win->length = 0;
8470Sstevel@tonic-gate win->card_addr = 0;
8480Sstevel@tonic-gate win->host_addr = 0;
8490Sstevel@tonic-gate /*
8500Sstevel@tonic-gate * Gather the length information.
8510Sstevel@tonic-gate * It's OK if there's no length
8520Sstevel@tonic-gate * information in which case this
8530Sstevel@tonic-gate * loop will never execute.
8540Sstevel@tonic-gate */
8550Sstevel@tonic-gate for (j = 0; j <
8560Sstevel@tonic-gate (int)((tpce_msd>>3)&3); j++)
8570Sstevel@tonic-gate win->length |= (GET_BYTE(tp) <<
8580Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
8590Sstevel@tonic-gate /*
8600Sstevel@tonic-gate * Gather the card address information.
8610Sstevel@tonic-gate * It's OK if there's no card
8620Sstevel@tonic-gate * address information in which
8630Sstevel@tonic-gate * case this loop will never
8640Sstevel@tonic-gate * execute.
8650Sstevel@tonic-gate */
8660Sstevel@tonic-gate for (j = 0; j <
8670Sstevel@tonic-gate (int)((tpce_msd>>5)&3); j++)
8680Sstevel@tonic-gate win->card_addr |=
8690Sstevel@tonic-gate (GET_BYTE(tp) <<
8700Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
8710Sstevel@tonic-gate /*
8720Sstevel@tonic-gate * If there's a host address
8730Sstevel@tonic-gate * description, grab that
8740Sstevel@tonic-gate * as well.
8750Sstevel@tonic-gate */
8760Sstevel@tonic-gate if (mem->flags &
8770Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_HOST) {
8780Sstevel@tonic-gate /*
8790Sstevel@tonic-gate * Gather the host address
8800Sstevel@tonic-gate * information. It's OK
8810Sstevel@tonic-gate * if there's no host
8820Sstevel@tonic-gate * address information in
8830Sstevel@tonic-gate * which case this loop
8840Sstevel@tonic-gate * will never execute.
8850Sstevel@tonic-gate * Note that we use the card
8860Sstevel@tonic-gate * address size to
8870Sstevel@tonic-gate * determine how many
8880Sstevel@tonic-gate * bytes of host address
8890Sstevel@tonic-gate * are present.
8900Sstevel@tonic-gate */
8910Sstevel@tonic-gate for (j = 0; j <
8920Sstevel@tonic-gate (int)((tpce_msd>>5)&3);
8930Sstevel@tonic-gate j++)
8940Sstevel@tonic-gate win->host_addr |=
8950Sstevel@tonic-gate (GET_BYTE(tp) <<
8960Sstevel@tonic-gate cistpl_cftable_shift_table[j]);
8970Sstevel@tonic-gate } else {
8980Sstevel@tonic-gate /*
8990Sstevel@tonic-gate * No host address information,
9000Sstevel@tonic-gate * so the host address is
9010Sstevel@tonic-gate * equal to the card
9020Sstevel@tonic-gate * address.
9030Sstevel@tonic-gate */
9040Sstevel@tonic-gate win->host_addr = win->card_addr;
9050Sstevel@tonic-gate }
9060Sstevel@tonic-gate } /* for (i<mem->windows) */
9070Sstevel@tonic-gate break;
9080Sstevel@tonic-gate /*
9090Sstevel@tonic-gate * single length and card base address specified
9100Sstevel@tonic-gate */
9110Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_MEM2M:
9120Sstevel@tonic-gate mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM2;
9130Sstevel@tonic-gate win = &mem->window[0];
9140Sstevel@tonic-gate mem->windows = 1;
9150Sstevel@tonic-gate /*
9160Sstevel@tonic-gate * Construct the size of the window.
9170Sstevel@tonic-gate */
9180Sstevel@tonic-gate win->length = GET_BYTE(tp);
9190Sstevel@tonic-gate win->length |= (GET_BYTE(tp)<<8);
9200Sstevel@tonic-gate win->length *=
9210Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE;
9220Sstevel@tonic-gate
9230Sstevel@tonic-gate /*
9240Sstevel@tonic-gate * Construct the card base address.
9250Sstevel@tonic-gate */
9260Sstevel@tonic-gate win->card_addr = GET_BYTE(tp);
9270Sstevel@tonic-gate win->card_addr |= (GET_BYTE(tp)<<8);
9280Sstevel@tonic-gate win->card_addr *=
9290Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE;
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate /*
9320Sstevel@tonic-gate * In this mode, both the host base address
9330Sstevel@tonic-gate * and the card base address are equal.
9340Sstevel@tonic-gate */
9350Sstevel@tonic-gate win->host_addr = win->card_addr;
9360Sstevel@tonic-gate break;
9370Sstevel@tonic-gate /*
9380Sstevel@tonic-gate * single length specified
9390Sstevel@tonic-gate */
9400Sstevel@tonic-gate case CISTPL_CFTABLE_TPCE_FS_MEM1M:
9410Sstevel@tonic-gate mem->flags |= CISTPL_CFTABLE_TPCE_FS_MEM1;
9420Sstevel@tonic-gate win = &mem->window[0];
9430Sstevel@tonic-gate mem->windows = 1;
9440Sstevel@tonic-gate win->card_addr = 0;
9450Sstevel@tonic-gate win->host_addr = 0;
9460Sstevel@tonic-gate /*
9470Sstevel@tonic-gate * Construct the size of the window.
9480Sstevel@tonic-gate */
9490Sstevel@tonic-gate win->length = GET_BYTE(tp);
9500Sstevel@tonic-gate win->length |= (GET_BYTE(tp)<<8);
9510Sstevel@tonic-gate win->length *=
9520Sstevel@tonic-gate CISTPL_CFTABLE_TPCE_FS_MEM_PGSIZE;
9530Sstevel@tonic-gate break;
9540Sstevel@tonic-gate } /* switch (CISTPL_CFTABLE_TPCE_FS_MEMM) */
9550Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_MEM) */
9560Sstevel@tonic-gate
9570Sstevel@tonic-gate /*
9580Sstevel@tonic-gate * Check for and parse any miscellaneous information.
9590Sstevel@tonic-gate *
9600Sstevel@tonic-gate * We only understand how to parse the first
9610Sstevel@tonic-gate * CISTPL_CFTABLE_TPCE_FS_MISC_MAX extension
9620Sstevel@tonic-gate * bytes specified in the PC Card 95 standard;
9630Sstevel@tonic-gate * we throw away any other extension bytes that
9640Sstevel@tonic-gate * are past these bytes.
9650Sstevel@tonic-gate * XXX Note that the assumption here is that the
9660Sstevel@tonic-gate * size of cistpl_cftable_entry_misc_t->flags
9670Sstevel@tonic-gate * is at least CISTPL_CFTABLE_TPCE_FS_MISC_MAX
9680Sstevel@tonic-gate * bytes in length.
9690Sstevel@tonic-gate */
9700Sstevel@tonic-gate if (tpce_fs & CISTPL_CFTABLE_TPCE_FS_MISCM) {
9710Sstevel@tonic-gate cistpl_cftable_entry_misc_t *misc = &ce->misc;
9720Sstevel@tonic-gate int mb = CISTPL_CFTABLE_TPCE_FS_MISC_MAX;
9730Sstevel@tonic-gate
9740Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_MISC;
9750Sstevel@tonic-gate misc->flags = 0;
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate do {
9780Sstevel@tonic-gate if (mb) {
9790Sstevel@tonic-gate misc->flags = (misc->flags << 8) | LOOK_BYTE(tp);
9800Sstevel@tonic-gate mb--;
9810Sstevel@tonic-gate }
9820Sstevel@tonic-gate } while ((GET_BYTE(tp) & CISTPL_EXT_BIT) &&
9830Sstevel@tonic-gate (!(tp->flags & CISTPLF_MEM_ERR)));
9840Sstevel@tonic-gate
9850Sstevel@tonic-gate /*
9860Sstevel@tonic-gate * Check to see if we tried to read past the
9870Sstevel@tonic-gate * end of the tuple data; if we have,
9880Sstevel@tonic-gate * there's no point in trying to parse
9890Sstevel@tonic-gate * any more of the tuple.
9900Sstevel@tonic-gate */
9910Sstevel@tonic-gate if (tp->flags & CISTPLF_MEM_ERR)
9920Sstevel@tonic-gate return (HANDTPL_ERROR);
9930Sstevel@tonic-gate } /* if (CISTPL_CFTABLE_TPCE_FS_MISCM) */
9940Sstevel@tonic-gate
9950Sstevel@tonic-gate /*
9960Sstevel@tonic-gate * Check for and parse any additional subtuple
9970Sstevel@tonic-gate * information. We know that there is
9980Sstevel@tonic-gate * additional information if we haven't
9990Sstevel@tonic-gate * reached the end of the tuple data area
10000Sstevel@tonic-gate * and if the additional information is
10010Sstevel@tonic-gate * in standard tuple format.
10020Sstevel@tonic-gate * If we don't recognize the additional info,
10030Sstevel@tonic-gate * then just silently ignore it, don't
10040Sstevel@tonic-gate * flag it as an error.
10050Sstevel@tonic-gate */
10060Sstevel@tonic-gate #ifdef PARSE_STCE_TUPLES
10070Sstevel@tonic-gate if (GET_LEN(tp) > 0) {
10080Sstevel@tonic-gate
10090Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_STCE_EV
10100Sstevel@tonic-gate ce->flags |= CISTPL_CFTABLE_TPCE_FS_STCE_PD
10110Sstevel@tonic-gate #endif
10120Sstevel@tonic-gate
10130Sstevel@tonic-gate } /* if (HANDTPL_PARSE_LTUPLE) */
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate return (CISTPLF_NOERROR);
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate
10180Sstevel@tonic-gate /*
10190Sstevel@tonic-gate * cistpl_pd_parse - read and parse a power description structure
10200Sstevel@tonic-gate *
10210Sstevel@tonic-gate * cisdata_t **ddp - pointer to pointer tuple data area
10220Sstevel@tonic-gate * cistpl_cftable_entry_pwr_t *pd - pointer to local power description
10230Sstevel@tonic-gate * structure
10240Sstevel@tonic-gate */
10250Sstevel@tonic-gate static void
10260Sstevel@tonic-gate cistpl_pd_parse(cistpl_t *tp, cistpl_cftable_entry_pwr_t *pd)
10270Sstevel@tonic-gate {
10280Sstevel@tonic-gate cisdata_t pdesc;
10290Sstevel@tonic-gate
10300Sstevel@tonic-gate pdesc = GET_BYTE(tp); /* power description selector */
10310Sstevel@tonic-gate
10320Sstevel@tonic-gate /* nominal supply voltage */
10330Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_NOMV) {
10340Sstevel@tonic-gate pd->nomV = cistpl_expd_parse(tp, &pd->nomV_flags) / 100;
10350Sstevel@tonic-gate pd->nomV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10360Sstevel@tonic-gate }
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate /* minimum supply voltage */
10390Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_MINV) {
10400Sstevel@tonic-gate pd->minV = cistpl_expd_parse(tp, &pd->minV_flags) / 100;
10410Sstevel@tonic-gate pd->minV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate /* maximum supply voltage */
10450Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_MAXV) {
10460Sstevel@tonic-gate pd->maxV = cistpl_expd_parse(tp, &pd->maxV_flags) / 100;
10470Sstevel@tonic-gate pd->maxV_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10480Sstevel@tonic-gate }
10490Sstevel@tonic-gate
10500Sstevel@tonic-gate /* continuous supply current */
10510Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_STATICI) {
10520Sstevel@tonic-gate pd->staticI_flags |= CISTPL_CFTABLE_PD_MUL10;
10530Sstevel@tonic-gate pd->staticI = cistpl_expd_parse(tp, &pd->staticI_flags);
10540Sstevel@tonic-gate pd->staticI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10550Sstevel@tonic-gate }
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate /* maximum current required averaged over 1 second */
10580Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_AVGI) {
10590Sstevel@tonic-gate pd->avgI_flags |= CISTPL_CFTABLE_PD_MUL10;
10600Sstevel@tonic-gate pd->avgI = cistpl_expd_parse(tp, &pd->avgI_flags);
10610Sstevel@tonic-gate pd->avgI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10620Sstevel@tonic-gate }
10630Sstevel@tonic-gate
10640Sstevel@tonic-gate /* maximum current required averaged over 10mS */
10650Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_PEAKI) {
10660Sstevel@tonic-gate pd->peakI_flags |= CISTPL_CFTABLE_PD_MUL10;
10670Sstevel@tonic-gate pd->peakI = cistpl_expd_parse(tp, &pd->peakI_flags);
10680Sstevel@tonic-gate pd->peakI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate
10710Sstevel@tonic-gate /* power down supply curent required */
10720Sstevel@tonic-gate if (pdesc & CISTPL_CFTABLE_PD_PDOWNI) {
10730Sstevel@tonic-gate pd->pdownI_flags |= CISTPL_CFTABLE_PD_MUL10;
10740Sstevel@tonic-gate pd->pdownI = cistpl_expd_parse(tp, &pd->pdownI_flags);
10750Sstevel@tonic-gate pd->pdownI_flags |= (pdesc | CISTPL_CFTABLE_PD_EXISTS);
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate }
10780Sstevel@tonic-gate
10790Sstevel@tonic-gate /*
10800Sstevel@tonic-gate * cistpl_expd_parse - read and parse an extended power description structure
10810Sstevel@tonic-gate *
10820Sstevel@tonic-gate * cistpl_t *tp - pointer to pointer tuple data area
10830Sstevel@tonic-gate * int *flags - flags that get for this parameter:
10840Sstevel@tonic-gate * CISTPL_CFTABLE_PD_NC_SLEEP - no connection on
10850Sstevel@tonic-gate * sleep/power down
10860Sstevel@tonic-gate * CISTPL_CFTABLE_PD_ZERO - zero value required
10870Sstevel@tonic-gate * CISTPL_CFTABLE_PD_NC - no connection ever
10880Sstevel@tonic-gate *
10890Sstevel@tonic-gate * The power consumption is returned in the following units:
10900Sstevel@tonic-gate *
10910Sstevel@tonic-gate * voltage - milliVOLTS
10920Sstevel@tonic-gate * current - microAMPS
10930Sstevel@tonic-gate */
10940Sstevel@tonic-gate extern cistpl_pd_struct_t cistpl_pd_struct;
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate uint32_t
10970Sstevel@tonic-gate cistpl_expd_parse(cistpl_t *tp, uint32_t *flags)
10980Sstevel@tonic-gate {
10990Sstevel@tonic-gate cisdata_t pdesc;
11000Sstevel@tonic-gate uint32_t exponent, mantisa, val, digits = 0;
11010Sstevel@tonic-gate
11020Sstevel@tonic-gate /*
11030Sstevel@tonic-gate * Get the power description parameter byte and break it up
11040Sstevel@tonic-gate * into mantissa and exponent.
11050Sstevel@tonic-gate */
11060Sstevel@tonic-gate pdesc = GET_BYTE(tp);
11070Sstevel@tonic-gate exponent = pdesc&7;
11080Sstevel@tonic-gate mantisa = (pdesc>>3)&0x0f;
11090Sstevel@tonic-gate
11100Sstevel@tonic-gate if (pdesc & CISTPL_EXT_BIT) {
11110Sstevel@tonic-gate do {
11120Sstevel@tonic-gate if (LOOK_BYTE(tp) <= 0x63)
11130Sstevel@tonic-gate digits = LOOK_BYTE(tp);
11140Sstevel@tonic-gate if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_NC_SLEEPM)
11150Sstevel@tonic-gate *flags |= CISTPL_CFTABLE_PD_NC_SLEEP;
11160Sstevel@tonic-gate if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_ZEROM)
11170Sstevel@tonic-gate *flags |= CISTPL_CFTABLE_PD_ZERO;
11180Sstevel@tonic-gate if (LOOK_BYTE(tp) == CISTPL_CFTABLE_PD_NCM)
11190Sstevel@tonic-gate *flags |= CISTPL_CFTABLE_PD_NC;
11200Sstevel@tonic-gate } while (GET_BYTE(tp) & CISTPL_EXT_BIT);
11210Sstevel@tonic-gate }
11220Sstevel@tonic-gate
11230Sstevel@tonic-gate val = CISTPL_PD_MAN(mantisa) * CISTPL_PD_EXP(exponent);
11240Sstevel@tonic-gate
11250Sstevel@tonic-gate /*
11260Sstevel@tonic-gate * If we have to multiply the power value by ten, then just
11270Sstevel@tonic-gate * don't bother dividing.
11280Sstevel@tonic-gate */
11290Sstevel@tonic-gate if (! (*flags & CISTPL_CFTABLE_PD_MUL10))
11300Sstevel@tonic-gate val = val/10; /* do this since our mantissa table is X 10 */
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate /*
11330Sstevel@tonic-gate * If we need to add some digits to the right of the decimal, do
11340Sstevel@tonic-gate * that here.
11350Sstevel@tonic-gate */
11360Sstevel@tonic-gate if (exponent)
11370Sstevel@tonic-gate val = val + (digits * CISTPL_PD_EXP(exponent-1));
11380Sstevel@tonic-gate
11390Sstevel@tonic-gate val /= 1000;
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate return (val);
11420Sstevel@tonic-gate }
11430Sstevel@tonic-gate
11440Sstevel@tonic-gate /*
11450Sstevel@tonic-gate * cistpl_devspeed - returns device speed in nS
11460Sstevel@tonic-gate *
11470Sstevel@tonic-gate * cistpl_t *tp - tuple pointer.
11480Sstevel@tonic-gate * cisdata_t spindex - device speed table index
11490Sstevel@tonic-gate * int flags - operation flags
11500Sstevel@tonic-gate * CISTPL_DEVSPEED_TABLE:
11510Sstevel@tonic-gate * Use the spindex argument as an index into a simple
11520Sstevel@tonic-gate * device speed table. ref: PCMCIA Release 2.01
11530Sstevel@tonic-gate * Card Metaformat pg. 5-14 table 5-12.
11540Sstevel@tonic-gate * When this flag is set, the spindex argument is ignored.
11550Sstevel@tonic-gate * CISTPL_DEVSPEED_EXT:
11560Sstevel@tonic-gate * Use the tp argument to access the
11570Sstevel@tonic-gate * tuple data area containing an extended speed
11580Sstevel@tonic-gate * code table. ref: PCMCIA Release 2.01 Card
11590Sstevel@tonic-gate * Metaformat pg. 5-15 table 5-13.
11600Sstevel@tonic-gate * The tp->read argument must point to the first byte of
11610Sstevel@tonic-gate * an extended speed code table.
11620Sstevel@tonic-gate * When this flag is set, the spindex argument is
11630Sstevel@tonic-gate * used as a power-of-10 scale factor. We only allow
11640Sstevel@tonic-gate * a maximum scale factor of 10^16.
11650Sstevel@tonic-gate *
11660Sstevel@tonic-gate * The device speed is returned in nS for all combinations of flags and
11670Sstevel@tonic-gate * speed table entries.
11680Sstevel@tonic-gate *
11690Sstevel@tonic-gate * Note if you pass the CISTPL_DEVSPEED_TABLE with a spindex index that
11700Sstevel@tonic-gate * refers to an extended speed table, you will get back an undefined
11710Sstevel@tonic-gate * speed value.
11720Sstevel@tonic-gate */
11730Sstevel@tonic-gate extern cistpl_devspeed_struct_t cistpl_devspeed_struct;
11740Sstevel@tonic-gate
11750Sstevel@tonic-gate uint32_t
11760Sstevel@tonic-gate cistpl_devspeed(cistpl_t *tp, cisdata_t spindex, uint32_t flags)
11770Sstevel@tonic-gate {
11780Sstevel@tonic-gate int scale = 1, first;
11790Sstevel@tonic-gate cisdata_t exspeed;
11800Sstevel@tonic-gate int exponent, mantisa;
11810Sstevel@tonic-gate uint32_t speed;
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate switch (flags) {
11840Sstevel@tonic-gate case CISTPL_DEVSPEED_TABLE:
11850Sstevel@tonic-gate speed = CISTPL_DEVSPEED_TBL(spindex);
11860Sstevel@tonic-gate break;
11870Sstevel@tonic-gate case CISTPL_DEVSPEED_EXT:
11880Sstevel@tonic-gate do {
11890Sstevel@tonic-gate exspeed = GET_BYTE(tp);
11900Sstevel@tonic-gate first = 1;
11910Sstevel@tonic-gate if (first) {
11920Sstevel@tonic-gate /*
11930Sstevel@tonic-gate * XXX - ugh! we don't understand additional
11940Sstevel@tonic-gate * exspeed bytes
11950Sstevel@tonic-gate */
11960Sstevel@tonic-gate first = 0;
11970Sstevel@tonic-gate exponent = (exspeed & 0x07);
11980Sstevel@tonic-gate mantisa = (exspeed >> 3) & 0x0f;
11990Sstevel@tonic-gate spindex &= 0x0f; /* only allow 10^16 */
12000Sstevel@tonic-gate while (spindex--)
12010Sstevel@tonic-gate scale *= 10;
12020Sstevel@tonic-gate } /* if (first) */
12030Sstevel@tonic-gate } while (exspeed & CISTPL_EXT_BIT);
12040Sstevel@tonic-gate speed = scale * CISTPL_DEVSPEED_MAN(mantisa) *
12050Sstevel@tonic-gate CISTPL_DEVSPEED_EXP(exponent);
12060Sstevel@tonic-gate speed = speed/10; /* XXX - mantissa table is all X 10 */
12070Sstevel@tonic-gate break;
12080Sstevel@tonic-gate default:
12090Sstevel@tonic-gate break;
12100Sstevel@tonic-gate }
12110Sstevel@tonic-gate
12120Sstevel@tonic-gate return (speed);
12130Sstevel@tonic-gate }
12140Sstevel@tonic-gate
12150Sstevel@tonic-gate /*
12160Sstevel@tonic-gate * cistpl_vers_2_handler - handler for the CISTPL_VERS_2 tuple
12170Sstevel@tonic-gate *
12180Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
12190Sstevel@tonic-gate */
12200Sstevel@tonic-gate uint32_t
12210Sstevel@tonic-gate cistpl_vers_2_handler(cistpl_callout_t *co, cistpl_t *tp,
12220Sstevel@tonic-gate uint32_t flags, void *arg)
12230Sstevel@tonic-gate {
12240Sstevel@tonic-gate /*
12250Sstevel@tonic-gate * nothing special about our flags, so just call the
12260Sstevel@tonic-gate * generic handler for this
12270Sstevel@tonic-gate */
12280Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
12290Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
12300Sstevel@tonic-gate
12310Sstevel@tonic-gate /*
12320Sstevel@tonic-gate * We don't currently validate this tuple. This call will
12330Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
12340Sstevel@tonic-gate */
12350Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
12360Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
12370Sstevel@tonic-gate
12380Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
12390Sstevel@tonic-gate cistpl_vers_2_t *cs = (cistpl_vers_2_t *)arg;
12400Sstevel@tonic-gate
12410Sstevel@tonic-gate RESET_TP(tp);
12420Sstevel@tonic-gate
12430Sstevel@tonic-gate cs->vers = GET_BYTE(tp);
12440Sstevel@tonic-gate cs->comply = GET_BYTE(tp);
12450Sstevel@tonic-gate cs->dindex = GET_SHORT(tp);
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate cs->reserved = GET_SHORT(tp);
12480Sstevel@tonic-gate
12490Sstevel@tonic-gate cs->vspec8 = GET_BYTE(tp);
12500Sstevel@tonic-gate cs->vspec9 = GET_BYTE(tp);
12510Sstevel@tonic-gate cs->nhdr = GET_BYTE(tp);
12520Sstevel@tonic-gate
12530Sstevel@tonic-gate (void) strcpy(cs->oem, cis_getstr(tp));
12540Sstevel@tonic-gate
12550Sstevel@tonic-gate if (GET_LEN(tp) > 0)
12560Sstevel@tonic-gate (void) strcpy(cs->info, cis_getstr(tp));
12570Sstevel@tonic-gate else
12580Sstevel@tonic-gate (void) strcpy(cs->info, "(no info)");
12590Sstevel@tonic-gate }
12600Sstevel@tonic-gate
12610Sstevel@tonic-gate return (CISTPLF_NOERROR);
12620Sstevel@tonic-gate }
12630Sstevel@tonic-gate
12640Sstevel@tonic-gate /*
12650Sstevel@tonic-gate * cistpl_jedec_handler - handler for JEDEC C and JEDEC A tuples
12660Sstevel@tonic-gate *
12670Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
12680Sstevel@tonic-gate */
12690Sstevel@tonic-gate uint32_t
12700Sstevel@tonic-gate cistpl_jedec_handler(cistpl_callout_t *co, cistpl_t *tp,
12710Sstevel@tonic-gate uint32_t flags, void *arg)
12720Sstevel@tonic-gate {
12730Sstevel@tonic-gate /*
12740Sstevel@tonic-gate * nothing special about our flags, so just call the
12750Sstevel@tonic-gate * generic handler for this
12760Sstevel@tonic-gate */
12770Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
12780Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
12790Sstevel@tonic-gate
12800Sstevel@tonic-gate /*
12810Sstevel@tonic-gate * We don't currently validate this tuple. This call will
12820Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
12830Sstevel@tonic-gate */
12840Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
12850Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
12880Sstevel@tonic-gate int nid;
12890Sstevel@tonic-gate cistpl_jedec_t *cs = (cistpl_jedec_t *)arg;
12900Sstevel@tonic-gate
12910Sstevel@tonic-gate RESET_TP(tp);
12920Sstevel@tonic-gate
12930Sstevel@tonic-gate for (nid = 0; GET_LEN(tp) > 0 &&
12940Sstevel@tonic-gate nid < CISTPL_JEDEC_MAX_IDENTIFIERS &&
12950Sstevel@tonic-gate LOOK_BYTE(tp) != 0xFF; nid++) {
12960Sstevel@tonic-gate cs->jid[nid].id = GET_BYTE(tp);
12970Sstevel@tonic-gate cs->jid[nid].info = GET_BYTE(tp);
12980Sstevel@tonic-gate }
12990Sstevel@tonic-gate cs->nid = nid;
13000Sstevel@tonic-gate }
13010Sstevel@tonic-gate
13020Sstevel@tonic-gate return (CISTPLF_NOERROR);
13030Sstevel@tonic-gate }
13040Sstevel@tonic-gate
13050Sstevel@tonic-gate /*
13060Sstevel@tonic-gate * cistpl_format_handler - handler for the CISTPL_FORMAT and
13070Sstevel@tonic-gate * CISTPL_FORMAT_A tuples
13080Sstevel@tonic-gate */
13090Sstevel@tonic-gate uint32_t
13100Sstevel@tonic-gate cistpl_format_handler(cistpl_callout_t *co, cistpl_t *tp,
13110Sstevel@tonic-gate uint32_t flags, void *arg)
13120Sstevel@tonic-gate {
13130Sstevel@tonic-gate /*
13140Sstevel@tonic-gate * nothing special about our flags, so just call the
13150Sstevel@tonic-gate * generic handler for this
13160Sstevel@tonic-gate */
13170Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
13180Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
13190Sstevel@tonic-gate
13200Sstevel@tonic-gate /*
13210Sstevel@tonic-gate * We don't currently validate this tuple. This call will
13220Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
13230Sstevel@tonic-gate */
13240Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
13250Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
13280Sstevel@tonic-gate cistpl_format_t *cs = (cistpl_format_t *)arg;
13290Sstevel@tonic-gate
13300Sstevel@tonic-gate RESET_TP(tp);
13310Sstevel@tonic-gate
13320Sstevel@tonic-gate cs->type = GET_BYTE(tp);
13330Sstevel@tonic-gate cs->edc_length = LOOK_BYTE(tp) & EDC_LENGTH_MASK;
13340Sstevel@tonic-gate cs->edc_type = ((uint32_t)GET_BYTE(tp) >> EDC_TYPE_SHIFT) &
13350Sstevel@tonic-gate EDC_TYPE_MASK;
13360Sstevel@tonic-gate cs->offset = GET_LONG(tp);
13370Sstevel@tonic-gate cs->nbytes = GET_LONG(tp);
13380Sstevel@tonic-gate
13390Sstevel@tonic-gate switch (cs->type) {
13400Sstevel@tonic-gate case TPLFMTTYPE_DISK:
13410Sstevel@tonic-gate cs->dev.disk.bksize = GET_SHORT(tp);
13420Sstevel@tonic-gate cs->dev.disk.nblocks = GET_LONG(tp);
13430Sstevel@tonic-gate cs->dev.disk.edcloc = GET_LONG(tp);
13440Sstevel@tonic-gate break;
13450Sstevel@tonic-gate
13460Sstevel@tonic-gate case TPLFMTTYPE_MEM:
13470Sstevel@tonic-gate cs->dev.mem.flags = GET_BYTE(tp);
13480Sstevel@tonic-gate cs->dev.mem.reserved = GET_BYTE(tp);
13490Sstevel@tonic-gate cs->dev.mem.address = (caddr_t)(uintptr_t)GET_LONG(tp);
13500Sstevel@tonic-gate cs->dev.disk.edcloc = GET_LONG(tp);
13510Sstevel@tonic-gate break;
13520Sstevel@tonic-gate default:
13530Sstevel@tonic-gate /* don't know about any other type */
13540Sstevel@tonic-gate break;
13550Sstevel@tonic-gate }
13560Sstevel@tonic-gate }
13570Sstevel@tonic-gate
13580Sstevel@tonic-gate return (CISTPLF_NOERROR);
13590Sstevel@tonic-gate }
13600Sstevel@tonic-gate
13610Sstevel@tonic-gate /*
13620Sstevel@tonic-gate * cistpl_geometry_handler - handler for the CISTPL_GEOMETRY tuple
13630Sstevel@tonic-gate *
13640Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
13650Sstevel@tonic-gate */
13660Sstevel@tonic-gate uint32_t
13670Sstevel@tonic-gate cistpl_geometry_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
13680Sstevel@tonic-gate void *arg)
13690Sstevel@tonic-gate {
13700Sstevel@tonic-gate /*
13710Sstevel@tonic-gate * nothing special about our flags, so just call the
13720Sstevel@tonic-gate * generic handler for this
13730Sstevel@tonic-gate */
13740Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
13750Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
13760Sstevel@tonic-gate
13770Sstevel@tonic-gate /*
13780Sstevel@tonic-gate * We don't currently validate this tuple. This call will
13790Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
13800Sstevel@tonic-gate */
13810Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
13820Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
13830Sstevel@tonic-gate
13840Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
13850Sstevel@tonic-gate cistpl_geometry_t *cs = (cistpl_geometry_t *)arg;
13860Sstevel@tonic-gate
13870Sstevel@tonic-gate RESET_TP(tp);
13880Sstevel@tonic-gate cs->spt = GET_BYTE(tp);
13890Sstevel@tonic-gate cs->tpc = GET_BYTE(tp);
13900Sstevel@tonic-gate cs->ncyl = GET_SHORT(tp);
13910Sstevel@tonic-gate }
13920Sstevel@tonic-gate return (CISTPLF_NOERROR);
13930Sstevel@tonic-gate }
13940Sstevel@tonic-gate
13950Sstevel@tonic-gate /*
13960Sstevel@tonic-gate * cistpl_byteorder_handler - handler for the CISTPL_BYTEORDER tuple
13970Sstevel@tonic-gate *
13980Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
13990Sstevel@tonic-gate */
14000Sstevel@tonic-gate uint32_t
14010Sstevel@tonic-gate cistpl_byteorder_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
14020Sstevel@tonic-gate void *arg)
14030Sstevel@tonic-gate {
14040Sstevel@tonic-gate /*
14050Sstevel@tonic-gate * nothing special about our flags, so just call the
14060Sstevel@tonic-gate * generic handler for this
14070Sstevel@tonic-gate */
14080Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
14090Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate /*
14120Sstevel@tonic-gate * We don't currently validate this tuple. This call will
14130Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
14140Sstevel@tonic-gate */
14150Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
14160Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14170Sstevel@tonic-gate
14180Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
14190Sstevel@tonic-gate cistpl_byteorder_t *cs = (cistpl_byteorder_t *)arg;
14200Sstevel@tonic-gate
14210Sstevel@tonic-gate RESET_TP(tp);
14220Sstevel@tonic-gate cs->order = GET_BYTE(tp);
14230Sstevel@tonic-gate cs->map = GET_BYTE(tp);
14240Sstevel@tonic-gate }
14250Sstevel@tonic-gate return (CISTPLF_NOERROR);
14260Sstevel@tonic-gate }
14270Sstevel@tonic-gate
14280Sstevel@tonic-gate /*
14290Sstevel@tonic-gate * cistpl_date_handler - handler for CISTPL_DATE card format tuple
14300Sstevel@tonic-gate *
14310Sstevel@tonic-gate * void *arg - points to a cistpl_date_t * where the
14320Sstevel@tonic-gate * information is stuffed into
14330Sstevel@tonic-gate */
14340Sstevel@tonic-gate uint32_t
14350Sstevel@tonic-gate cistpl_date_handler(cistpl_callout_t *co, cistpl_t *tp,
14360Sstevel@tonic-gate uint32_t flags, void *arg)
14370Sstevel@tonic-gate {
14380Sstevel@tonic-gate /*
14390Sstevel@tonic-gate * nothing special about our flags, so just call the
14400Sstevel@tonic-gate * generic handler for this
14410Sstevel@tonic-gate */
14420Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
14430Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14440Sstevel@tonic-gate
14450Sstevel@tonic-gate /*
14460Sstevel@tonic-gate * We don't currently validate this tuple. This call will
14470Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
14480Sstevel@tonic-gate */
14490Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
14500Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14510Sstevel@tonic-gate
14520Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
14530Sstevel@tonic-gate cistpl_date_t *cs = (cistpl_date_t *)arg;
14540Sstevel@tonic-gate
14550Sstevel@tonic-gate RESET_TP(tp);
14560Sstevel@tonic-gate cs->time = GET_SHORT(tp);
14570Sstevel@tonic-gate cs->day = GET_SHORT(tp);
14580Sstevel@tonic-gate }
14590Sstevel@tonic-gate return (CISTPLF_NOERROR);
14600Sstevel@tonic-gate }
14610Sstevel@tonic-gate
14620Sstevel@tonic-gate /*
14630Sstevel@tonic-gate * cistpl_battery_handler - handler for CISTPL_BATTERY battery replacement
14640Sstevel@tonic-gate * date tuple
14650Sstevel@tonic-gate *
14660Sstevel@tonic-gate * void *arg - points to a cistpl_battery_t * where the
14670Sstevel@tonic-gate * information is stuffed into
14680Sstevel@tonic-gate */
14690Sstevel@tonic-gate uint32_t
14700Sstevel@tonic-gate cistpl_battery_handler(cistpl_callout_t *co, cistpl_t *tp,
14710Sstevel@tonic-gate uint32_t flags, void *arg)
14720Sstevel@tonic-gate {
14730Sstevel@tonic-gate /*
14740Sstevel@tonic-gate * nothing special about our flags, so just call the
14750Sstevel@tonic-gate * generic handler for this
14760Sstevel@tonic-gate */
14770Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
14780Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14790Sstevel@tonic-gate
14800Sstevel@tonic-gate /*
14810Sstevel@tonic-gate * We don't currently validate this tuple. This call will
14820Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
14830Sstevel@tonic-gate */
14840Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
14850Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
14860Sstevel@tonic-gate
14870Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
14880Sstevel@tonic-gate cistpl_battery_t *cs = (cistpl_battery_t *)arg;
14890Sstevel@tonic-gate
14900Sstevel@tonic-gate RESET_TP(tp);
14910Sstevel@tonic-gate cs->rday = GET_SHORT(tp);
14920Sstevel@tonic-gate cs->xday = GET_SHORT(tp);
14930Sstevel@tonic-gate }
14940Sstevel@tonic-gate return (CISTPLF_NOERROR);
14950Sstevel@tonic-gate }
14960Sstevel@tonic-gate
14970Sstevel@tonic-gate /*
14980Sstevel@tonic-gate * cistpl_org_handler - handler for CISTPL_ORG data organization tuple
14990Sstevel@tonic-gate *
15000Sstevel@tonic-gate * void *arg - points to a cistpl_org_t * where the
15010Sstevel@tonic-gate * information is stuffed into
15020Sstevel@tonic-gate */
15030Sstevel@tonic-gate uint32_t
15040Sstevel@tonic-gate cistpl_org_handler(cistpl_callout_t *co, cistpl_t *tp,
15050Sstevel@tonic-gate uint32_t flags, void *arg)
15060Sstevel@tonic-gate {
15070Sstevel@tonic-gate /*
15080Sstevel@tonic-gate * nothing special about our flags, so just call the
15090Sstevel@tonic-gate * generic handler for this
15100Sstevel@tonic-gate */
15110Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
15120Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15130Sstevel@tonic-gate
15140Sstevel@tonic-gate /*
15150Sstevel@tonic-gate * We don't currently validate this tuple. This call will
15160Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
15170Sstevel@tonic-gate */
15180Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
15190Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15200Sstevel@tonic-gate
15210Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
15220Sstevel@tonic-gate cistpl_org_t *cs = (cistpl_org_t *)arg;
15230Sstevel@tonic-gate
15240Sstevel@tonic-gate RESET_TP(tp);
15250Sstevel@tonic-gate cs->type = GET_BYTE(tp);
15260Sstevel@tonic-gate
15270Sstevel@tonic-gate (void) strcpy(cs->desc, cis_getstr(tp));
15280Sstevel@tonic-gate }
15290Sstevel@tonic-gate
15300Sstevel@tonic-gate return (CISTPLF_NOERROR);
15310Sstevel@tonic-gate }
15320Sstevel@tonic-gate
15330Sstevel@tonic-gate
15340Sstevel@tonic-gate /*
15350Sstevel@tonic-gate * cistpl_manfid_handler - handler for CISTPL_MANFID, the manufacturer ID tuple
15360Sstevel@tonic-gate *
15370Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
15380Sstevel@tonic-gate */
15390Sstevel@tonic-gate uint32_t
15400Sstevel@tonic-gate cistpl_manfid_handler(cistpl_callout_t *co, cistpl_t *tp,
15410Sstevel@tonic-gate uint32_t flags, void *arg)
15420Sstevel@tonic-gate {
15430Sstevel@tonic-gate /*
15440Sstevel@tonic-gate * nothing special about our flags, so just call the
15450Sstevel@tonic-gate * generic handler for this
15460Sstevel@tonic-gate */
15470Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
15480Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15490Sstevel@tonic-gate
15500Sstevel@tonic-gate /*
15510Sstevel@tonic-gate * We don't currently validate this tuple. This call will
15520Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
15530Sstevel@tonic-gate */
15540Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
15550Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15560Sstevel@tonic-gate
15570Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
15580Sstevel@tonic-gate cistpl_manfid_t *cs = (cistpl_manfid_t *)arg;
15590Sstevel@tonic-gate
15600Sstevel@tonic-gate RESET_TP(tp);
15610Sstevel@tonic-gate cs->manf = GET_SHORT(tp);
15620Sstevel@tonic-gate cs->card = GET_SHORT(tp);
15630Sstevel@tonic-gate }
15640Sstevel@tonic-gate return (CISTPLF_NOERROR);
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate /*
15680Sstevel@tonic-gate * cistpl_funcid_handler - handler for CISTPL_FUNCID
15690Sstevel@tonic-gate *
15700Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
15710Sstevel@tonic-gate */
15720Sstevel@tonic-gate uint32_t
15730Sstevel@tonic-gate cistpl_funcid_handler(cistpl_callout_t *co, cistpl_t *tp,
15740Sstevel@tonic-gate uint32_t flags, void *arg)
15750Sstevel@tonic-gate {
15760Sstevel@tonic-gate /*
15770Sstevel@tonic-gate * nothing special about our flags, so just call the
15780Sstevel@tonic-gate * generic handler for this
15790Sstevel@tonic-gate */
15800Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
15810Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15820Sstevel@tonic-gate
15830Sstevel@tonic-gate /*
15840Sstevel@tonic-gate * We don't currently validate this tuple. This call will
15850Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
15860Sstevel@tonic-gate */
15870Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
15880Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
15890Sstevel@tonic-gate
15900Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
15910Sstevel@tonic-gate cistpl_funcid_t *cs = (cistpl_funcid_t *)arg;
15920Sstevel@tonic-gate
15930Sstevel@tonic-gate RESET_TP(tp);
15940Sstevel@tonic-gate
15950Sstevel@tonic-gate cs->function = GET_BYTE(tp);
15960Sstevel@tonic-gate cs->sysinit = GET_BYTE(tp);
15970Sstevel@tonic-gate }
15980Sstevel@tonic-gate return (CISTPLF_NOERROR);
15990Sstevel@tonic-gate }
16000Sstevel@tonic-gate
16010Sstevel@tonic-gate
16020Sstevel@tonic-gate /*
16030Sstevel@tonic-gate * cistpl_funce_serial_handler - handler for the CISTPL_FUNCE/SERIAL tuple
16040Sstevel@tonic-gate *
16050Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
16060Sstevel@tonic-gate */
16070Sstevel@tonic-gate uint32_t
16080Sstevel@tonic-gate cistpl_funce_serial_handler(cistpl_callout_t *co, cistpl_t *tp,
16090Sstevel@tonic-gate uint32_t flags, void *arg)
16100Sstevel@tonic-gate {
16110Sstevel@tonic-gate int subfunction;
16120Sstevel@tonic-gate
16130Sstevel@tonic-gate /*
16140Sstevel@tonic-gate * nothing special about our flags, so just call the
16150Sstevel@tonic-gate * generic handler for this
16160Sstevel@tonic-gate */
16170Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
16180Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
16190Sstevel@tonic-gate
16200Sstevel@tonic-gate /*
16210Sstevel@tonic-gate * We don't currently validate this tuple. This call will
16220Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
16230Sstevel@tonic-gate */
16240Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
16250Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
16260Sstevel@tonic-gate
16270Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
16280Sstevel@tonic-gate cistpl_funce_t *cs = (cistpl_funce_t *)arg;
16290Sstevel@tonic-gate
16300Sstevel@tonic-gate RESET_TP(tp);
16310Sstevel@tonic-gate
16320Sstevel@tonic-gate cs->function = TPLFUNC_SERIAL;
16330Sstevel@tonic-gate cs->subfunction = subfunction = GET_BYTE(tp);
16340Sstevel@tonic-gate switch (subfunction & 0xF) {
16350Sstevel@tonic-gate case TPLFE_SUB_SERIAL:
16360Sstevel@tonic-gate case TPLFE_CAP_SERIAL_DATA:
16370Sstevel@tonic-gate case TPLFE_CAP_SERIAL_FAX:
16380Sstevel@tonic-gate case TPLFE_CAP_SERIAL_VOICE:
16390Sstevel@tonic-gate cs->data.serial.ua = GET_BYTE(tp);
16400Sstevel@tonic-gate cs->data.serial.uc = GET_SHORT(tp);
16410Sstevel@tonic-gate break;
16420Sstevel@tonic-gate case TPLFE_SUB_MODEM_COMMON:
16430Sstevel@tonic-gate case TPLFE_CAP_MODEM_DATA:
16440Sstevel@tonic-gate case TPLFE_CAP_MODEM_FAX:
16450Sstevel@tonic-gate case TPLFE_CAP_MODEM_VOICE:
16460Sstevel@tonic-gate cs->data.modem.fc = GET_BYTE(tp);
16470Sstevel@tonic-gate cs->data.modem.cb = (GET_BYTE(tp) + 1) * 4;
16480Sstevel@tonic-gate cs->data.modem.eb = GET_INT24(tp);
16490Sstevel@tonic-gate cs->data.modem.tb = GET_INT24(tp);
16500Sstevel@tonic-gate break;
16510Sstevel@tonic-gate case TPLFE_SUB_MODEM_DATA:
16520Sstevel@tonic-gate cs->data.data_modem.ud = GET_BE_SHORT(tp) * 75;
16530Sstevel@tonic-gate cs->data.data_modem.ms = GET_SHORT(tp);
16540Sstevel@tonic-gate cs->data.data_modem.em = GET_BYTE(tp);
16550Sstevel@tonic-gate cs->data.data_modem.dc = GET_BYTE(tp);
16560Sstevel@tonic-gate cs->data.data_modem.cm = GET_BYTE(tp);
16570Sstevel@tonic-gate cs->data.data_modem.ex = GET_BYTE(tp);
16580Sstevel@tonic-gate cs->data.data_modem.dy = GET_BYTE(tp);
16590Sstevel@tonic-gate cs->data.data_modem.ef = GET_BYTE(tp);
16600Sstevel@tonic-gate for (cs->data.data_modem.ncd = 0;
16610Sstevel@tonic-gate GET_LEN(tp) > 0 && cs->data.data_modem.ncd < 16;
16620Sstevel@tonic-gate cs->data.data_modem.ncd++)
16630Sstevel@tonic-gate if (LOOK_BYTE(tp) != 255) {
16640Sstevel@tonic-gate cs->data.data_modem.cd[
16650Sstevel@tonic-gate cs->data.data_modem.ncd] =
16660Sstevel@tonic-gate GET_BYTE(tp);
16670Sstevel@tonic-gate } else {
16680Sstevel@tonic-gate GET_BYTE(tp);
16690Sstevel@tonic-gate break;
16700Sstevel@tonic-gate }
16710Sstevel@tonic-gate break;
16720Sstevel@tonic-gate case TPLFE_SUB_MODEM_FAX:
16730Sstevel@tonic-gate cs->data.fax.uf = GET_BE_SHORT(tp) * 75;
16740Sstevel@tonic-gate cs->data.fax.fm = GET_BYTE(tp);
16750Sstevel@tonic-gate cs->data.fax.fy = GET_BYTE(tp);
16760Sstevel@tonic-gate cs->data.fax.fs = GET_SHORT(tp);
16770Sstevel@tonic-gate for (cs->data.fax.ncf = 0;
16780Sstevel@tonic-gate GET_LEN(tp) > 0 && cs->data.fax.ncf < 16;
16790Sstevel@tonic-gate cs->data.fax.ncf++)
16800Sstevel@tonic-gate if (LOOK_BYTE(tp) != 255) {
16810Sstevel@tonic-gate cs->data.fax.cf[cs->data.fax.ncf] =
16820Sstevel@tonic-gate GET_BYTE(tp);
16830Sstevel@tonic-gate } else {
16840Sstevel@tonic-gate GET_BYTE(tp);
16850Sstevel@tonic-gate break;
16860Sstevel@tonic-gate }
16870Sstevel@tonic-gate break;
16880Sstevel@tonic-gate case TPLFE_SUB_VOICE:
16890Sstevel@tonic-gate cs->data.voice.uv = GET_BE_SHORT(tp) * 75;
16900Sstevel@tonic-gate for (cs->data.voice.nsr = 0; LOOK_BYTE(tp) != 0 &&
16910Sstevel@tonic-gate GET_LEN(tp) >= 2;
16920Sstevel@tonic-gate cs->data.voice.nsr++) {
16930Sstevel@tonic-gate cs->data.voice.sr[cs->data.voice.nsr] =
16940Sstevel@tonic-gate GET_BYTE(tp) * 1000;
16950Sstevel@tonic-gate cs->data.voice.sr[cs->data.voice.nsr] +=
16960Sstevel@tonic-gate GET_BYTE(tp) * 100;
16970Sstevel@tonic-gate }
16980Sstevel@tonic-gate for (cs->data.voice.nss = 0; LOOK_BYTE(tp) != 0 &&
16990Sstevel@tonic-gate GET_LEN(tp) >= 2;
17000Sstevel@tonic-gate cs->data.voice.nss++) {
17010Sstevel@tonic-gate cs->data.voice.ss[cs->data.voice.nss] =
17020Sstevel@tonic-gate GET_BYTE(tp) * 10;
17030Sstevel@tonic-gate cs->data.voice.ss[cs->data.voice.nss] +=
17040Sstevel@tonic-gate GET_BYTE(tp);
17050Sstevel@tonic-gate }
17060Sstevel@tonic-gate for (cs->data.voice.nsc = 0; LOOK_BYTE(tp) != 0 &&
17070Sstevel@tonic-gate GET_LEN(tp) >= 1;
17080Sstevel@tonic-gate cs->data.voice.nsc++) {
17090Sstevel@tonic-gate cs->data.voice.sc[cs->data.voice.nsc] =
17100Sstevel@tonic-gate GET_BYTE(tp);
17110Sstevel@tonic-gate }
17120Sstevel@tonic-gate break;
17130Sstevel@tonic-gate default:
17140Sstevel@tonic-gate break;
17150Sstevel@tonic-gate }
17160Sstevel@tonic-gate }
17170Sstevel@tonic-gate return (CISTPLF_NOERROR);
17180Sstevel@tonic-gate }
17190Sstevel@tonic-gate
17200Sstevel@tonic-gate /*
17210Sstevel@tonic-gate * cistpl_funce_lan_handler - handler for the CISTPL_FUNCE/LAN tuple
17220Sstevel@tonic-gate *
17230Sstevel@tonic-gate * void *arg - points to a XXX where the information is stuffed into
17240Sstevel@tonic-gate */
17250Sstevel@tonic-gate uint32_t
17260Sstevel@tonic-gate cistpl_funce_lan_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
17270Sstevel@tonic-gate void *arg)
17280Sstevel@tonic-gate {
17290Sstevel@tonic-gate int subfunction;
17300Sstevel@tonic-gate
17310Sstevel@tonic-gate /*
17320Sstevel@tonic-gate * nothing special about our flags, so just call the
17330Sstevel@tonic-gate * generic handler for this
17340Sstevel@tonic-gate */
17350Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
17360Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
17370Sstevel@tonic-gate
17380Sstevel@tonic-gate /*
17390Sstevel@tonic-gate * We don't currently validate this tuple. This call will
17400Sstevel@tonic-gate * always set tp->flags |= CISTPLF_VALID.
17410Sstevel@tonic-gate */
17420Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
17430Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
17440Sstevel@tonic-gate
17450Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
17460Sstevel@tonic-gate int i;
17470Sstevel@tonic-gate cistpl_funce_t *cs = (cistpl_funce_t *)arg;
17480Sstevel@tonic-gate
17490Sstevel@tonic-gate RESET_TP(tp);
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate cs->function = TPLFUNC_LAN;
17520Sstevel@tonic-gate cs->subfunction = subfunction = GET_BYTE(tp);
17530Sstevel@tonic-gate
17540Sstevel@tonic-gate switch (subfunction) {
17550Sstevel@tonic-gate case TPLFE_NETWORK_INFO:
17560Sstevel@tonic-gate cs->data.lan.tech = GET_BYTE(tp);
17570Sstevel@tonic-gate cs->data.lan.speed = GET_BYTE(tp);
17580Sstevel@tonic-gate i = GET_BYTE(tp);
17590Sstevel@tonic-gate if (i < 24) {
17600Sstevel@tonic-gate cs->data.lan.speed <<= i;
17610Sstevel@tonic-gate } else {
17620Sstevel@tonic-gate /*
17630Sstevel@tonic-gate * if speed is too large a value
17640Sstevel@tonic-gate * to hold in a uint32 flag it and
17650Sstevel@tonic-gate * store as [mantissa][exponent]
17660Sstevel@tonic-gate * in least significant 16 bits
17670Sstevel@tonic-gate */
17680Sstevel@tonic-gate cs->data.lan.speed = 0x80000000 |
17690Sstevel@tonic-gate (cs->data.lan.speed << 8) | i;
17700Sstevel@tonic-gate }
17710Sstevel@tonic-gate cs->data.lan.media = GET_BYTE(tp);
17720Sstevel@tonic-gate cs->data.lan.con = GET_BYTE(tp);
17730Sstevel@tonic-gate cs->data.lan.id_sz = GET_BYTE(tp);
17740Sstevel@tonic-gate if (cs->data.lan.id_sz <= 16) {
17750Sstevel@tonic-gate for (i = 0; i < cs->data.lan.id_sz; i++)
17760Sstevel@tonic-gate cs->data.lan.id[i] = GET_BYTE(tp);
17770Sstevel@tonic-gate }
17780Sstevel@tonic-gate break;
17790Sstevel@tonic-gate default:
17800Sstevel@tonic-gate /* unknown LAN tuple type */
17810Sstevel@tonic-gate return (CISTPLF_UNKNOWN);
17820Sstevel@tonic-gate }
17830Sstevel@tonic-gate }
17840Sstevel@tonic-gate return (CISTPLF_NOERROR);
17850Sstevel@tonic-gate }
17860Sstevel@tonic-gate
17870Sstevel@tonic-gate /*
17880Sstevel@tonic-gate * cistpl_linktarget_handler - handler for CISTPL_LINKTARGET tuple
17890Sstevel@tonic-gate *
17900Sstevel@tonic-gate * void *arg - points to a cistpl_linktarget_t * where the
17910Sstevel@tonic-gate * information is stuffed into
17920Sstevel@tonic-gate *
17930Sstevel@tonic-gate * If HANDTPL_COPY_DONE is set, we just validate the tuple but
17940Sstevel@tonic-gate * do not return any values.
17950Sstevel@tonic-gate * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and
17960Sstevel@tonic-gate * return the parsed tuple data if the tuple is valid.
17970Sstevel@tonic-gate *
17980Sstevel@tonic-gate * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag
17990Sstevel@tonic-gate * will be set in the tp->flags field and HANDTPL_ERROR
18000Sstevel@tonic-gate * will be returned.
18010Sstevel@tonic-gate *
18020Sstevel@tonic-gate * If the tuple data body is invalid, the CISTPLF_PARAMS_INVALID flag
18030Sstevel@tonic-gate * will be set in the tp->flags field and HANDTPL_ERROR
18040Sstevel@tonic-gate * will be returned.
18050Sstevel@tonic-gate *
18060Sstevel@tonic-gate * The tuple is considered invalid if it's link field is less than
18070Sstevel@tonic-gate * MIN_LINKTARGET_LENGTH or if the data body of the tuple
18080Sstevel@tonic-gate * does not contain the pattern CISTPL_LINKTARGET_MAGIC.
18090Sstevel@tonic-gate *
18100Sstevel@tonic-gate * XXX At some point we should revisit this to see if we can call
18110Sstevel@tonic-gate * cis_validate_longlink_acm instead of doing the validation
18120Sstevel@tonic-gate * in both places.
18130Sstevel@tonic-gate */
18140Sstevel@tonic-gate uint32_t
18150Sstevel@tonic-gate cistpl_linktarget_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
18160Sstevel@tonic-gate void *arg)
18170Sstevel@tonic-gate {
18180Sstevel@tonic-gate /*
18190Sstevel@tonic-gate * nothing special about our flags, so just call the
18200Sstevel@tonic-gate * generic handler for this
18210Sstevel@tonic-gate */
18220Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
18230Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
18240Sstevel@tonic-gate
18250Sstevel@tonic-gate /*
18260Sstevel@tonic-gate * Validate the tuple for both the HANDTPL_COPY_DONE case and
18270Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case. Only return data in
18280Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case.
18290Sstevel@tonic-gate */
18300Sstevel@tonic-gate if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) {
18310Sstevel@tonic-gate uchar_t *cp;
18320Sstevel@tonic-gate cisdata_t tl;
18330Sstevel@tonic-gate
18340Sstevel@tonic-gate if ((tl = tp->len) >= (cisdata_t)MIN_LINKTARGET_LENGTH) {
18350Sstevel@tonic-gate cisdata_t *ltm = (cisdata_t *)CISTPL_LINKTARGET_MAGIC;
18360Sstevel@tonic-gate int i;
18370Sstevel@tonic-gate
18380Sstevel@tonic-gate RESET_TP(tp);
18390Sstevel@tonic-gate
18400Sstevel@tonic-gate /*
18410Sstevel@tonic-gate * Save the start address of this string in case
18420Sstevel@tonic-gate * the tuple turns out to be OK since we
18430Sstevel@tonic-gate * need to pass this address to the caller.
18440Sstevel@tonic-gate */
18450Sstevel@tonic-gate cp = GET_BYTE_ADDR(tp);
18460Sstevel@tonic-gate
18470Sstevel@tonic-gate /*
18480Sstevel@tonic-gate * Check each byte of the tuple body to see if it
18490Sstevel@tonic-gate * matches what should be in a valid tuple.
18500Sstevel@tonic-gate * Note that we can't assume that this magic
18510Sstevel@tonic-gate * pattern is a string and we also only need
18520Sstevel@tonic-gate * to be sure that MIN_LINKTARGET_LENGTH bytes
18530Sstevel@tonic-gate * match; all bytes following this magic number
18540Sstevel@tonic-gate * in this tuple are ignored.
18550Sstevel@tonic-gate */
18560Sstevel@tonic-gate for (i = 0; i < MIN_LINKTARGET_LENGTH; i++) {
18570Sstevel@tonic-gate if (GET_BYTE(tp) != *ltm++) {
18580Sstevel@tonic-gate tp->flags |= CISTPLF_PARAMS_INVALID;
18590Sstevel@tonic-gate return (HANDTPL_ERROR);
18600Sstevel@tonic-gate }
18610Sstevel@tonic-gate } /* MIN_LINKTARGET_LENGTH */
18620Sstevel@tonic-gate
18630Sstevel@tonic-gate /*
18640Sstevel@tonic-gate * This tuple is valid.
18650Sstevel@tonic-gate */
18660Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
18670Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
18680Sstevel@tonic-gate
18690Sstevel@tonic-gate /*
18700Sstevel@tonic-gate * If we're also parsing this tuple, then
18710Sstevel@tonic-gate * setup the return values.
18720Sstevel@tonic-gate */
18730Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
18740Sstevel@tonic-gate cistpl_linktarget_t *cs =
18750Sstevel@tonic-gate (cistpl_linktarget_t *)arg;
18760Sstevel@tonic-gate
18770Sstevel@tonic-gate cs->length = tl;
18780Sstevel@tonic-gate (void) strncpy(cs->tpltg_tag, (char *)cp,
18790Sstevel@tonic-gate cs->length);
18800Sstevel@tonic-gate cs->tpltg_tag[cs->length] = NULL;
18810Sstevel@tonic-gate
18820Sstevel@tonic-gate } /* HANDTPL_PARSE_LTUPLE */
18830Sstevel@tonic-gate
18840Sstevel@tonic-gate } else {
18850Sstevel@tonic-gate
18860Sstevel@tonic-gate tp->flags |= CISTPLF_LINK_INVALID;
18870Sstevel@tonic-gate return (HANDTPL_ERROR);
18880Sstevel@tonic-gate
18890Sstevel@tonic-gate } /* CISTPL_LINKTARGET */
18900Sstevel@tonic-gate
18910Sstevel@tonic-gate } /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */
18920Sstevel@tonic-gate
18930Sstevel@tonic-gate return (CISTPLF_NOERROR);
18940Sstevel@tonic-gate }
18950Sstevel@tonic-gate
18960Sstevel@tonic-gate /*
18970Sstevel@tonic-gate * cistpl_longlink_ac_handler - handler for CISTPL_LONGLINK_A and
18980Sstevel@tonic-gate * CISTPL_LONGLINK_C tuples
18990Sstevel@tonic-gate *
19000Sstevel@tonic-gate * void *arg - points to a cistpl_longlink_ac_t * where the
19010Sstevel@tonic-gate * information is stuffed into
19020Sstevel@tonic-gate *
19030Sstevel@tonic-gate * If the passed in tuple is CISTPL_LONGLINK_A the CISTPL_LONGLINK_AC_AM
19040Sstevel@tonic-gate * flag in cistpl_longlink_ac_t->flags is set.
19050Sstevel@tonic-gate * If the passed in tuple is CISTPL_LONGLINK_C the CISTPL_LONGLINK_AC_CM
19060Sstevel@tonic-gate * flag in cistpl_longlink_ac_t->flags is set.
19070Sstevel@tonic-gate *
19080Sstevel@tonic-gate * If HANDTPL_COPY_DONE is set, we just validate the tuple but
19090Sstevel@tonic-gate * do not return any values.
19100Sstevel@tonic-gate * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and
19110Sstevel@tonic-gate * return the parsed tuple data if the tuple is valid.
19120Sstevel@tonic-gate *
19130Sstevel@tonic-gate * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag
19140Sstevel@tonic-gate * will be set in the tp->flags field and HANDTPL_ERROR
19150Sstevel@tonic-gate * will be returned.
19160Sstevel@tonic-gate *
19170Sstevel@tonic-gate * The tuple is considered invalid if it's link field is less than
19180Sstevel@tonic-gate * MIN_LONGLINK_AC_LENGTH.
19190Sstevel@tonic-gate */
19200Sstevel@tonic-gate uint32_t
19210Sstevel@tonic-gate cistpl_longlink_ac_handler(cistpl_callout_t *co, cistpl_t *tp, uint32_t flags,
19220Sstevel@tonic-gate void *arg)
19230Sstevel@tonic-gate {
19240Sstevel@tonic-gate /*
19250Sstevel@tonic-gate * nothing special about our flags, so just call the
19260Sstevel@tonic-gate * generic handler for this
19270Sstevel@tonic-gate */
19280Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
19290Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
19300Sstevel@tonic-gate
19310Sstevel@tonic-gate /*
19320Sstevel@tonic-gate * Validate the tuple for both the HANDTPL_COPY_DONE case and
19330Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case. Only return data in
19340Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case.
19350Sstevel@tonic-gate */
19360Sstevel@tonic-gate if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) {
19370Sstevel@tonic-gate
19380Sstevel@tonic-gate if (tp->len >= (cisdata_t)MIN_LONGLINK_AC_LENGTH) {
19390Sstevel@tonic-gate
19400Sstevel@tonic-gate /*
19410Sstevel@tonic-gate * This tuple is valid.
19420Sstevel@tonic-gate */
19430Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
19440Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
19450Sstevel@tonic-gate
19460Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
19470Sstevel@tonic-gate cistpl_longlink_ac_t *cs =
19480Sstevel@tonic-gate (cistpl_longlink_ac_t *)arg;
19490Sstevel@tonic-gate
19500Sstevel@tonic-gate switch (tp->type) {
19510Sstevel@tonic-gate case CISTPL_LONGLINK_A:
19520Sstevel@tonic-gate cs->flags = CISTPL_LONGLINK_AC_AM;
19530Sstevel@tonic-gate break;
19540Sstevel@tonic-gate
19550Sstevel@tonic-gate case CISTPL_LONGLINK_C:
19560Sstevel@tonic-gate cs->flags = CISTPL_LONGLINK_AC_CM;
19570Sstevel@tonic-gate break;
19580Sstevel@tonic-gate default:
19590Sstevel@tonic-gate break;
19600Sstevel@tonic-gate } /* switch */
19610Sstevel@tonic-gate
19620Sstevel@tonic-gate RESET_TP(tp);
19630Sstevel@tonic-gate
19640Sstevel@tonic-gate cs->tpll_addr = GET_LONG(tp);
19650Sstevel@tonic-gate
19660Sstevel@tonic-gate } /* HANDTPL_PARSE_LTUPLE */
19670Sstevel@tonic-gate
19680Sstevel@tonic-gate } else {
19690Sstevel@tonic-gate tp->flags |= CISTPLF_LINK_INVALID;
19700Sstevel@tonic-gate return (HANDTPL_ERROR);
19710Sstevel@tonic-gate } /* MIN_LONGLINK_AC_LENGTH */
19720Sstevel@tonic-gate
19730Sstevel@tonic-gate } /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */
19740Sstevel@tonic-gate
19750Sstevel@tonic-gate return (CISTPLF_NOERROR);
19760Sstevel@tonic-gate }
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate /*
19790Sstevel@tonic-gate * cistpl_longlink_mfc_handler - handler for CISTPL_LONGLINK_MFC tuples
19800Sstevel@tonic-gate *
19810Sstevel@tonic-gate * void *arg - points to a cistpl_longlink_mfc_t * where the
19820Sstevel@tonic-gate * information is stuffed into
19830Sstevel@tonic-gate *
19840Sstevel@tonic-gate * If HANDTPL_COPY_DONE is set, we just validate the tuple but
19850Sstevel@tonic-gate * do not return any values.
19860Sstevel@tonic-gate * If HANDTPL_PARSE_LTUPLE is set, we validate the tuple and
19870Sstevel@tonic-gate * return the parsed tuple data if the tuple is valid.
19880Sstevel@tonic-gate *
19890Sstevel@tonic-gate * If the tuple link field is invalid, the CISTPLF_LINK_INVALID flag
19900Sstevel@tonic-gate * will be set in the tp->flags field and HANDTPL_ERROR
19910Sstevel@tonic-gate * will be returned.
19920Sstevel@tonic-gate *
19930Sstevel@tonic-gate * If the number of register sets is invalid, the CISTPLF_PARAMS_INVALID
19940Sstevel@tonic-gate * flag be set in the tp->flags field and HANDTPL_ERROR will be
19950Sstevel@tonic-gate * returned.
19960Sstevel@tonic-gate *
19970Sstevel@tonic-gate * The tuple is considered invalid if it's link field is less than
19980Sstevel@tonic-gate * MIN_LONGLINK_MFC_LENGTH or if the number of register sets
19990Sstevel@tonic-gate * is not in the range [MIN_LONGLINK_MFC_NREGS..CIS_MAX_FUNCTIONS]
20000Sstevel@tonic-gate */
20010Sstevel@tonic-gate uint32_t
20020Sstevel@tonic-gate cistpl_longlink_mfc_handler(cistpl_callout_t *co, cistpl_t *tp,
20030Sstevel@tonic-gate uint32_t flags, void *arg)
20040Sstevel@tonic-gate {
20050Sstevel@tonic-gate /*
20060Sstevel@tonic-gate * nothing special about our flags, so just call the
20070Sstevel@tonic-gate * generic handler for this
20080Sstevel@tonic-gate */
20090Sstevel@tonic-gate if (flags & HANDTPL_SET_FLAGS)
20100Sstevel@tonic-gate return (cis_no_tuple_handler(co, tp, flags, arg));
20110Sstevel@tonic-gate
20120Sstevel@tonic-gate /*
20130Sstevel@tonic-gate * Validate the tuple for both the HANDTPL_COPY_DONE case and
20140Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case. Only return data in
20150Sstevel@tonic-gate * the HANDTPL_PARSE_LTUPLE case.
20160Sstevel@tonic-gate */
20170Sstevel@tonic-gate if (flags & (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE)) {
20180Sstevel@tonic-gate
20190Sstevel@tonic-gate if (tp->len >= (cisdata_t)MIN_LONGLINK_MFC_LENGTH) {
20200Sstevel@tonic-gate
20210Sstevel@tonic-gate /*
20220Sstevel@tonic-gate * This tuple is valid.
20230Sstevel@tonic-gate */
20240Sstevel@tonic-gate if (flags & HANDTPL_COPY_DONE)
20250Sstevel@tonic-gate tp->flags |= CISTPLF_VALID;
20260Sstevel@tonic-gate
20270Sstevel@tonic-gate if (flags & HANDTPL_PARSE_LTUPLE) {
20280Sstevel@tonic-gate cistpl_longlink_mfc_t *cs =
20290Sstevel@tonic-gate (cistpl_longlink_mfc_t *)arg;
20300Sstevel@tonic-gate int fn;
20310Sstevel@tonic-gate
20320Sstevel@tonic-gate RESET_TP(tp);
20330Sstevel@tonic-gate
20340Sstevel@tonic-gate /*
20350Sstevel@tonic-gate * Get the number of register sets described
20360Sstevel@tonic-gate * by this tuple. The number of register
20370Sstevel@tonic-gate * sets must be greter than or equal to
20380Sstevel@tonic-gate * MIN_LONGLINK_MFC_NREGS and less than
20390Sstevel@tonic-gate * CIS_MAX_FUNCTIONS.
20400Sstevel@tonic-gate * Note that the number of functions is equal
20410Sstevel@tonic-gate * to the number of register sets.
20420Sstevel@tonic-gate */
20430Sstevel@tonic-gate cs->nregs = GET_BYTE(tp);
20440Sstevel@tonic-gate cs->nfuncs = cs->nregs;
20450Sstevel@tonic-gate
20460Sstevel@tonic-gate if ((cs->nregs < MIN_LONGLINK_MFC_NREGS) ||
20470Sstevel@tonic-gate (cs->nregs > CIS_MAX_FUNCTIONS)) {
20480Sstevel@tonic-gate tp->flags |= CISTPLF_PARAMS_INVALID;
20490Sstevel@tonic-gate return (HANDTPL_ERROR);
20500Sstevel@tonic-gate }
20510Sstevel@tonic-gate
20520Sstevel@tonic-gate /*
20530Sstevel@tonic-gate * Cycle through each function and setup
20540Sstevel@tonic-gate * the appropriate parameter values.
20550Sstevel@tonic-gate */
20560Sstevel@tonic-gate for (fn = 0; fn < cs->nregs; fn++) {
20570Sstevel@tonic-gate cs->function[fn].tas = GET_BYTE(tp);
20580Sstevel@tonic-gate cs->function[fn].addr = GET_LONG(tp);
20590Sstevel@tonic-gate } /* for (fn) */
20600Sstevel@tonic-gate
20610Sstevel@tonic-gate } /* HANDTPL_PARSE_LTUPLE */
20620Sstevel@tonic-gate
20630Sstevel@tonic-gate } else {
20640Sstevel@tonic-gate tp->flags |= CISTPLF_LINK_INVALID;
20650Sstevel@tonic-gate return (HANDTPL_ERROR);
20660Sstevel@tonic-gate } /* MIN_LONGLINK_MFC_LENGTH */
20670Sstevel@tonic-gate
20680Sstevel@tonic-gate } /* (HANDTPL_COPY_DONE | HANDTPL_PARSE_LTUPLE) */
20690Sstevel@tonic-gate
20700Sstevel@tonic-gate return (CISTPLF_NOERROR);
20710Sstevel@tonic-gate }
20720Sstevel@tonic-gate
20730Sstevel@tonic-gate /*
20740Sstevel@tonic-gate * cis_validate_longlink_acm - Validates the secondary tuple chain pointed
20750Sstevel@tonic-gate * to by cisptr and specified by a previous
20760Sstevel@tonic-gate * CISTPL_LONGLINK_A, CISTPL_LONGLINK_C or
20770Sstevel@tonic-gate * CISTPL_LONGLINK_MFC tuple.
20780Sstevel@tonic-gate *
20790Sstevel@tonic-gate * cisptr->offset must be the offset to the first byte in the secondary
20800Sstevel@tonic-gate * tuple chain to validate
20810Sstevel@tonic-gate * cisptr->flags must be setup to specify the correct address space
20820Sstevel@tonic-gate *
20830Sstevel@tonic-gate * The cisptr->offset member is not updated after this function returns.
20840Sstevel@tonic-gate *
20850Sstevel@tonic-gate * BAD_CIS_ADDR is returned is the raw CIS data cound not be read.
20860Sstevel@tonic-gate * HANDTPL_ERROR is returned if the secondary tuple chain does not
20870Sstevel@tonic-gate * contain a valid CISTPL_LINKTARGET tuple.
20880Sstevel@tonic-gate */
20890Sstevel@tonic-gate uint32_t
20900Sstevel@tonic-gate cis_validate_longlink_acm(cisptr_t *cisptr)
20910Sstevel@tonic-gate {
20920Sstevel@tonic-gate uchar_t cb[MIN_LINKTARGET_LENGTH + LINKTARGET_AC_HEADER_LENGTH];
20930Sstevel@tonic-gate cisptr_t t_cisptr, *cpt;
20940Sstevel@tonic-gate int tl;
20950Sstevel@tonic-gate
20960Sstevel@tonic-gate /*
20970Sstevel@tonic-gate * Since the NEXT_CIS_ADDR macro increments the cisptr_t->offset
20980Sstevel@tonic-gate * member, make a local copy of the cisptr and use the local
20990Sstevel@tonic-gate * copy to read data from the card.
21000Sstevel@tonic-gate */
21010Sstevel@tonic-gate cpt = &t_cisptr;
21020Sstevel@tonic-gate bcopy((caddr_t)cisptr, (caddr_t)cpt, sizeof (cisptr_t));
21030Sstevel@tonic-gate
21040Sstevel@tonic-gate for (tl = 0; tl < MIN_LINKTARGET_LENGTH +
21050Sstevel@tonic-gate LINKTARGET_AC_HEADER_LENGTH; tl++) {
21060Sstevel@tonic-gate
21070Sstevel@tonic-gate cb[tl] = GET_CIS_DATA(cpt);
21080Sstevel@tonic-gate if (!NEXT_CIS_ADDR(cpt))
21090Sstevel@tonic-gate return ((uint32_t)BAD_CIS_ADDR);
21100Sstevel@tonic-gate
21110Sstevel@tonic-gate } /* for */
21120Sstevel@tonic-gate
21130Sstevel@tonic-gate if ((cb[0] == CISTPL_LINKTARGET) && (cb[1] >= MIN_LINKTARGET_LENGTH)) {
21140Sstevel@tonic-gate cisdata_t *ltm = (cisdata_t *)CISTPL_LINKTARGET_MAGIC;
21150Sstevel@tonic-gate
21160Sstevel@tonic-gate for (tl = 0; tl < MIN_LINKTARGET_LENGTH; tl++, ltm++) {
21170Sstevel@tonic-gate if (cb[tl + LINKTARGET_AC_HEADER_LENGTH] != *ltm)
21180Sstevel@tonic-gate return (HANDTPL_ERROR);
21190Sstevel@tonic-gate }
21200Sstevel@tonic-gate return (CISTPLF_NOERROR);
21210Sstevel@tonic-gate
21220Sstevel@tonic-gate } /* if */
21230Sstevel@tonic-gate
21240Sstevel@tonic-gate return (HANDTPL_ERROR);
21250Sstevel@tonic-gate }
21260Sstevel@tonic-gate
21270Sstevel@tonic-gate /*
21280Sstevel@tonic-gate * cis_getstr (tp)
21290Sstevel@tonic-gate * we want the address of the first character returned
21300Sstevel@tonic-gate * but need to skip past the string in the cistpl_t structure
21310Sstevel@tonic-gate */
21320Sstevel@tonic-gate char *
21330Sstevel@tonic-gate cis_getstr(cistpl_t *tp)
21340Sstevel@tonic-gate {
21350Sstevel@tonic-gate uchar_t *cp, *cpp;
21360Sstevel@tonic-gate uchar_t x;
21370Sstevel@tonic-gate
21380Sstevel@tonic-gate cp = tp->read.byte;
21390Sstevel@tonic-gate cpp = cp;
21400Sstevel@tonic-gate
21410Sstevel@tonic-gate while ((x = LOOK_BYTE(tp)) != 0 && x != 0xff) {
21420Sstevel@tonic-gate x = GET_BYTE(tp);
21430Sstevel@tonic-gate }
21440Sstevel@tonic-gate
21450Sstevel@tonic-gate (void) GET_BYTE(tp); /* get past that last byte */
21460Sstevel@tonic-gate
21470Sstevel@tonic-gate while ((*cpp != 0) && (*cpp != 0xff))
21480Sstevel@tonic-gate cpp++;
21490Sstevel@tonic-gate
21500Sstevel@tonic-gate *cpp = NULL;
21510Sstevel@tonic-gate
21520Sstevel@tonic-gate return ((char *)cp);
21530Sstevel@tonic-gate }
21540Sstevel@tonic-gate
21550Sstevel@tonic-gate /*
21560Sstevel@tonic-gate * cis_return_name - returns name of tuple
21570Sstevel@tonic-gate *
21580Sstevel@tonic-gate * calling: co - pointer to cistpl_callout_t entry that contains
21590Sstevel@tonic-gate * tuple name to return
21600Sstevel@tonic-gate * gtn - pointer to cistpl_get_tuple_name_t to return
21610Sstevel@tonic-gate * name into
21620Sstevel@tonic-gate */
21630Sstevel@tonic-gate static void
21640Sstevel@tonic-gate cis_return_name(cistpl_callout_t *co, cistpl_get_tuple_name_t *gtn)
21650Sstevel@tonic-gate {
21660Sstevel@tonic-gate (void) strncpy(gtn->name, co->text, CIS_MAX_TUPLE_NAME_LEN);
21670Sstevel@tonic-gate gtn->name[CIS_MAX_TUPLE_NAME_LEN - 1] = NULL;
21680Sstevel@tonic-gate }
21690Sstevel@tonic-gate
21700Sstevel@tonic-gate /*
21710Sstevel@tonic-gate * cis_malloc/cis_free
21720Sstevel@tonic-gate * wrappers around kmem_alloc()/kmem_free() that
21730Sstevel@tonic-gate * provide malloc/free style usage
21740Sstevel@tonic-gate */
21750Sstevel@tonic-gate
21760Sstevel@tonic-gate caddr_t
21770Sstevel@tonic-gate cis_malloc(size_t len)
21780Sstevel@tonic-gate {
21790Sstevel@tonic-gate caddr_t addr;
21800Sstevel@tonic-gate
21810Sstevel@tonic-gate addr = kmem_zalloc(len + sizeof (size_t), KM_SLEEP);
21820Sstevel@tonic-gate *(size_t *)addr = len + sizeof (size_t);
21830Sstevel@tonic-gate addr += sizeof (size_t);
21840Sstevel@tonic-gate return (addr);
21850Sstevel@tonic-gate }
21860Sstevel@tonic-gate
21870Sstevel@tonic-gate void
21880Sstevel@tonic-gate cis_free(caddr_t addr)
21890Sstevel@tonic-gate {
21900Sstevel@tonic-gate size_t len;
21910Sstevel@tonic-gate addr -= sizeof (size_t);
21920Sstevel@tonic-gate len = *(size_t *)addr;
21930Sstevel@tonic-gate kmem_free(addr, len);
21940Sstevel@tonic-gate }
2195