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