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