1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This is a collection of routines that make up the Card Information 31*7c478bd9Sstevel@tonic-gate * Structure (CIS) interpreter. The algorigthms used are based 32*7c478bd9Sstevel@tonic-gate * on the Release 2.01 PCMCIA standard. 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * Note that a bunch of comments are not indented correctly with the 35*7c478bd9Sstevel@tonic-gate * code that they are commenting on. This is because cstyle is 36*7c478bd9Sstevel@tonic-gate * inflexible concerning 4-column indenting. 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/callb.h> 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate #include <sys/pctypes.h> 60*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_types.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/pcmcia.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/sservice.h> 63*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis.h> 64*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis_handlers.h> 65*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs.h> 66*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_priv.h> 67*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis_protos.h> 68*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_stubs.h> 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * Function declarations 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate void *CISParser(int function, ...); 74*7c478bd9Sstevel@tonic-gate static int (*cis_card_services)(int, ...) = NULL; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate static int cis_process_longlink(cistpl_callout_t *, cistpl_t *, 77*7c478bd9Sstevel@tonic-gate cis_info_t *, cisparse_t *); 78*7c478bd9Sstevel@tonic-gate static int cis_create_cis_chain(cs_socket_t *, cistpl_callout_t *, 79*7c478bd9Sstevel@tonic-gate cisptr_t *, cis_info_t *, cisparse_t *); 80*7c478bd9Sstevel@tonic-gate static void cis_store_cis_addr(cistpl_t *, cisptr_t *); 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate extern cistpl_callout_t cistpl_std_callout[]; 83*7c478bd9Sstevel@tonic-gate extern cistpl_devspeed_struct_t cistpl_devspeed_struct; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate #ifdef CIS_DEBUG 86*7c478bd9Sstevel@tonic-gate int cis_debug = 0; 87*7c478bd9Sstevel@tonic-gate #endif 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate /* 90*7c478bd9Sstevel@tonic-gate * cisp_init - initialize the CIS parser 91*7c478bd9Sstevel@tonic-gate */ 92*7c478bd9Sstevel@tonic-gate void 93*7c478bd9Sstevel@tonic-gate cisp_init() 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate #ifdef XXX 96*7c478bd9Sstevel@tonic-gate csregister_t csr; 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* 99*7c478bd9Sstevel@tonic-gate * Fill out the function for CISSetAddress 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate csr.cs_magic = PCCS_MAGIC; 102*7c478bd9Sstevel@tonic-gate csr.cs_version = PCCS_VERSION; 103*7c478bd9Sstevel@tonic-gate csr.cs_event = (f_t *)CISParser; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * We have to call SS instead of CS to register because we 107*7c478bd9Sstevel@tonic-gate * can't do a _depends_on for CS 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate SocketServices(CISSetAddress, &csr); 110*7c478bd9Sstevel@tonic-gate #endif /* XXX */ 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * cis_deinit - deinitialize the CIS parser 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate void 117*7c478bd9Sstevel@tonic-gate cis_deinit() 118*7c478bd9Sstevel@tonic-gate { 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * Tell CS that we're gone. 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate if (cis_card_services) 124*7c478bd9Sstevel@tonic-gate CIS_CARD_SERVICES(CISUnregister); 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate return; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * CISParser - this is the entrypoint for all of the CIS Interpreter 132*7c478bd9Sstevel@tonic-gate * functions 133*7c478bd9Sstevel@tonic-gate */ 134*7c478bd9Sstevel@tonic-gate void * 135*7c478bd9Sstevel@tonic-gate CISParser(int function, ...) 136*7c478bd9Sstevel@tonic-gate { 137*7c478bd9Sstevel@tonic-gate va_list arglist; 138*7c478bd9Sstevel@tonic-gate void *retcode = (void *)CS_UNSUPPORTED_FUNCTION; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate #if defined(CIS_DEBUG) 141*7c478bd9Sstevel@tonic-gate if (cis_debug > 1) { 142*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CISParser: called with function 0x%x\n", 143*7c478bd9Sstevel@tonic-gate function); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate #endif 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate va_start(arglist, function); 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate /* 150*7c478bd9Sstevel@tonic-gate * ...and here's the CIS Interpreter waterfall 151*7c478bd9Sstevel@tonic-gate */ 152*7c478bd9Sstevel@tonic-gate switch (function) { 153*7c478bd9Sstevel@tonic-gate case CISP_CIS_SETUP: { 154*7c478bd9Sstevel@tonic-gate csregister_t *csr; 155*7c478bd9Sstevel@tonic-gate cisregister_t cisr; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate csr = va_arg(arglist, csregister_t *); 158*7c478bd9Sstevel@tonic-gate cis_card_services = csr->cs_card_services; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate cisr.cis_magic = PCCS_MAGIC; 161*7c478bd9Sstevel@tonic-gate cisr.cis_version = PCCS_VERSION; 162*7c478bd9Sstevel@tonic-gate cisr.cis_parser = NULL; /* let the framework do this */ 163*7c478bd9Sstevel@tonic-gate cisr.cistpl_std_callout = cistpl_std_callout; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * Tell CS that we're here and what our 167*7c478bd9Sstevel@tonic-gate * entrypoint address is. 168*7c478bd9Sstevel@tonic-gate */ 169*7c478bd9Sstevel@tonic-gate CIS_CARD_SERVICES(CISRegister, &cisr); 170*7c478bd9Sstevel@tonic-gate } /* CISP_CIS_SETUP */ 171*7c478bd9Sstevel@tonic-gate break; 172*7c478bd9Sstevel@tonic-gate case CISP_CIS_LIST_CREATE: { 173*7c478bd9Sstevel@tonic-gate cistpl_callout_t *cistpl_callout; 174*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate cistpl_callout = va_arg(arglist, cistpl_callout_t *); 177*7c478bd9Sstevel@tonic-gate sp = va_arg(arglist, cs_socket_t *); 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate retcode = (void *) 180*7c478bd9Sstevel@tonic-gate (uintptr_t)cis_list_create(cistpl_callout, sp); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate break; 183*7c478bd9Sstevel@tonic-gate case CISP_CIS_LIST_DESTROY: { 184*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate sp = va_arg(arglist, cs_socket_t *); 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate retcode = (void *)(uintptr_t)cis_list_destroy(sp); 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate break; 191*7c478bd9Sstevel@tonic-gate case CISP_CIS_GET_LTUPLE: { 192*7c478bd9Sstevel@tonic-gate cistpl_t *tp; 193*7c478bd9Sstevel@tonic-gate cisdata_t type; 194*7c478bd9Sstevel@tonic-gate int flags; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate tp = va_arg(arglist, cistpl_t *); 197*7c478bd9Sstevel@tonic-gate type = va_arg(arglist, uint_t); 198*7c478bd9Sstevel@tonic-gate flags = va_arg(arglist, int); 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate retcode = (void *)cis_get_ltuple(tp, type, flags); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate break; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate case CISP_CIS_PARSE_TUPLE: { 205*7c478bd9Sstevel@tonic-gate cistpl_callout_t *co; 206*7c478bd9Sstevel@tonic-gate cistpl_t *tp; 207*7c478bd9Sstevel@tonic-gate int flags; 208*7c478bd9Sstevel@tonic-gate void *arg; 209*7c478bd9Sstevel@tonic-gate cisdata_t subtype; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate co = va_arg(arglist, cistpl_callout_t *); 212*7c478bd9Sstevel@tonic-gate tp = va_arg(arglist, cistpl_t *); 213*7c478bd9Sstevel@tonic-gate flags = va_arg(arglist, int); 214*7c478bd9Sstevel@tonic-gate arg = va_arg(arglist, void *); 215*7c478bd9Sstevel@tonic-gate subtype = va_arg(arglist, uint_t); 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate retcode = (void *)(uintptr_t)cis_tuple_handler(co, tp, 218*7c478bd9Sstevel@tonic-gate flags, arg, subtype); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate break; 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate case CISP_CIS_CONV_DEVSPEED: 223*7c478bd9Sstevel@tonic-gate retcode = (void *)(uintptr_t)cis_convert_devspeed( 224*7c478bd9Sstevel@tonic-gate va_arg(arglist, convert_speed_t *)); 225*7c478bd9Sstevel@tonic-gate break; 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate case CISP_CIS_CONV_DEVSIZE: 228*7c478bd9Sstevel@tonic-gate retcode = (void *)(uintptr_t)cis_convert_devsize( 229*7c478bd9Sstevel@tonic-gate va_arg(arglist, convert_size_t *)); 230*7c478bd9Sstevel@tonic-gate break; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate default: 233*7c478bd9Sstevel@tonic-gate break; 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate va_end(arglist); 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate return (retcode); 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /* 242*7c478bd9Sstevel@tonic-gate * cis_list_lcreate - read a PC card's CIS and create a local linked CIS list 243*7c478bd9Sstevel@tonic-gate * 244*7c478bd9Sstevel@tonic-gate * cistpl_callout_t *cistpl_callout - pointer to callout structure 245*7c478bd9Sstevel@tonic-gate * array to use to find tuples. 246*7c478bd9Sstevel@tonic-gate * cisptr_t cisptr - pointer to a structure containing the handle and 247*7c478bd9Sstevel@tonic-gate * offset from where we should start reading 248*7c478bd9Sstevel@tonic-gate * CIS bytes as well as misc flags. 249*7c478bd9Sstevel@tonic-gate * cis_info_t *cis_info - pointer to a cis_info_t structure; pass 250*7c478bd9Sstevel@tonic-gate * the cis_info->cis member as a NULL pointer 251*7c478bd9Sstevel@tonic-gate * if you want to create a new list. 252*7c478bd9Sstevel@tonic-gate * cisparse_t *cisparse - pointer to a cisparse_t struture to put 253*7c478bd9Sstevel@tonic-gate * parsed longlink tuple data into. 254*7c478bd9Sstevel@tonic-gate * cs_socket_t *sp - pointer to a cs_socket_t structure that describes 255*7c478bd9Sstevel@tonic-gate * the socket and card in this socket. 256*7c478bd9Sstevel@tonic-gate * 257*7c478bd9Sstevel@tonic-gate * We return the a count of the number of tuples that we saw, not including 258*7c478bd9Sstevel@tonic-gate * any CISTPL_END or CISTPL_NULL tuples if there were no problems 259*7c478bd9Sstevel@tonic-gate * processing the CIS. If a tuple handler returns an error, we 260*7c478bd9Sstevel@tonic-gate * immediately return with the error code from the handler. An 261*7c478bd9Sstevel@tonic-gate * error return code will always have the HANDTPL_ERROR bit set 262*7c478bd9Sstevel@tonic-gate * to allow the caller to distinguish an error from a valid tuple 263*7c478bd9Sstevel@tonic-gate * count. 264*7c478bd9Sstevel@tonic-gate * 265*7c478bd9Sstevel@tonic-gate * The nchains and ntuples counters in the cis_info_t structure are also 266*7c478bd9Sstevel@tonic-gate * updated to reflect the number of chains and number of tuples in 267*7c478bd9Sstevel@tonic-gate * this chain. 268*7c478bd9Sstevel@tonic-gate * 269*7c478bd9Sstevel@tonic-gate * XXX need to add CISTPL_END and CISTPL_NULL tuples to the list, and need 270*7c478bd9Sstevel@tonic-gate * to be sure that the tuple count reflects these tuples 271*7c478bd9Sstevel@tonic-gate * 272*7c478bd9Sstevel@tonic-gate * If we attempt to read beyond the end of the mapped in CIS address space, 273*7c478bd9Sstevel@tonic-gate * the BAD_CIS_ADDR error code is returned. 274*7c478bd9Sstevel@tonic-gate * 275*7c478bd9Sstevel@tonic-gate * This function only interprets the CISTPL_END and CISTPL_NULL tuples as 276*7c478bd9Sstevel@tonic-gate * well as any tuple with a link field of CISTPL_END. 277*7c478bd9Sstevel@tonic-gate * 278*7c478bd9Sstevel@tonic-gate * Tuples of type CISTPL_END or CISTPL_NULL are not added to the list. 279*7c478bd9Sstevel@tonic-gate * 280*7c478bd9Sstevel@tonic-gate * To append tuples to end of a local linked CIS list, pass a pointer to the 281*7c478bd9Sstevel@tonic-gate * address of the last element in the list that you want tuples appended 282*7c478bd9Sstevel@tonic-gate * to. This pointer should be passed in cis_info->cis. 283*7c478bd9Sstevel@tonic-gate * 284*7c478bd9Sstevel@tonic-gate * To process tuple chains with any long link targets, call this routine 285*7c478bd9Sstevel@tonic-gate * for each tuple chain you want to process using the list append method 286*7c478bd9Sstevel@tonic-gate * described above. The caller is responsible for vaildating any link 287*7c478bd9Sstevel@tonic-gate * target tuples to be sure that they describe a valid CIS chain. 288*7c478bd9Sstevel@tonic-gate * 289*7c478bd9Sstevel@tonic-gate * The cis_info->flags member is updated as follows: 290*7c478bd9Sstevel@tonic-gate * 291*7c478bd9Sstevel@tonic-gate * CW_VALID_CIS - if the CIS is valid 292*7c478bd9Sstevel@tonic-gate * CW_LONGLINK_MFC_FOUND - if a CISTPL_LONGLINK_MFC tuple 293*7c478bd9Sstevel@tonic-gate * was seen 294*7c478bd9Sstevel@tonic-gate * CW_LONGLINK_A_FOUND - if a CISTPL_LONGLINK_A tuple was 295*7c478bd9Sstevel@tonic-gate * seen 296*7c478bd9Sstevel@tonic-gate * CW_LONGLINK_C_FOUND - if a CISTPL_LONGLINK_C tuple was 297*7c478bd9Sstevel@tonic-gate * seen 298*7c478bd9Sstevel@tonic-gate * 299*7c478bd9Sstevel@tonic-gate * If a CISTPL_LONGLINK_MFC, CISTPL_LONGLINK_A or CISTPL_LONGLINK_C 300*7c478bd9Sstevel@tonic-gate * tuple is seen, the *cisparse argument will return an appropriate 301*7c478bd9Sstevel@tonic-gate * parsed longlink structure as follows: 302*7c478bd9Sstevel@tonic-gate * 303*7c478bd9Sstevel@tonic-gate * CW_LONGLINK_MFC_FOUND: 304*7c478bd9Sstevel@tonic-gate * *cisparse --> cistpl_longlink_mfc_t * 305*7c478bd9Sstevel@tonic-gate * CW_LONGLINK_A_FOUND, CW_LONGLINK_C_FOUND: 306*7c478bd9Sstevel@tonic-gate * *cisparse --> cistpl_longlink_ac_t * 307*7c478bd9Sstevel@tonic-gate * 308*7c478bd9Sstevel@tonic-gate * These flags are set and the tuples are parsed so that the caller does 309*7c478bd9Sstevel@tonic-gate * not have to traverse the CIS list to find out if any of these tuples 310*7c478bd9Sstevel@tonic-gate * have been seen. 311*7c478bd9Sstevel@tonic-gate * 312*7c478bd9Sstevel@tonic-gate * For each tuple that we see, the following flags in the tuple_t->flags member 313*7c478bd9Sstevel@tonic-gate * are set/cleared: 314*7c478bd9Sstevel@tonic-gate * 315*7c478bd9Sstevel@tonic-gate * CISTPLF_COPYOK - OK to copy tuple data 316*7c478bd9Sstevel@tonic-gate * CISTPLF_GLOBAL_CIS - tuple from global CIS 317*7c478bd9Sstevel@tonic-gate * CISTPLF_MF_CIS - tuple from MF CIS chain 318*7c478bd9Sstevel@tonic-gate * CISTPLF_FROM_AM - tuple read from AM space 319*7c478bd9Sstevel@tonic-gate * CISTPLF_FROM_CM - tuple read from CM space 320*7c478bd9Sstevel@tonic-gate * CISTPLF_LINK_INVALID - tuple link is invalid 321*7c478bd9Sstevel@tonic-gate * CISTPLF_PARAMS_INVALID - tuple body is invalid 322*7c478bd9Sstevel@tonic-gate * CISTPLF_AM_SPACE - this tuple is in AM space 323*7c478bd9Sstevel@tonic-gate * CISTPLF_CM_SPACE - this tuple is in CM space 324*7c478bd9Sstevel@tonic-gate * CISTPLF_LM_SPACE - this tuple is in local memory 325*7c478bd9Sstevel@tonic-gate */ 326*7c478bd9Sstevel@tonic-gate uint32_t 327*7c478bd9Sstevel@tonic-gate cis_list_lcreate(cistpl_callout_t *cistpl_callout, cisptr_t *cisptr, 328*7c478bd9Sstevel@tonic-gate cis_info_t *cis_info, cisparse_t *cisparse, cs_socket_t *sp) 329*7c478bd9Sstevel@tonic-gate { 330*7c478bd9Sstevel@tonic-gate cistpl_t *cp, *tp = NULL; 331*7c478bd9Sstevel@tonic-gate cisdata_t tl, td, *dp; 332*7c478bd9Sstevel@tonic-gate int done = 0, err; 333*7c478bd9Sstevel@tonic-gate get_socket_t get_socket; 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate /* 337*7c478bd9Sstevel@tonic-gate * If we were passed a non-NULL list base, that means that we should 338*7c478bd9Sstevel@tonic-gate * parse the CIS and add any tuples we find to the end of the list 339*7c478bd9Sstevel@tonic-gate * we were handed a pointer to. 340*7c478bd9Sstevel@tonic-gate */ 341*7c478bd9Sstevel@tonic-gate if (cis_info->cis) { 342*7c478bd9Sstevel@tonic-gate tp = cis_info->cis; 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 346*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 347*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 348*7c478bd9Sstevel@tonic-gate "cis_list_lcreate: socket %d SS_GetSocket failed\n", 349*7c478bd9Sstevel@tonic-gate sp->socket_num); 350*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate /* 354*7c478bd9Sstevel@tonic-gate * If this is primary CIS chain, the first tuple must be one 355*7c478bd9Sstevel@tonic-gate * from the following list. 356*7c478bd9Sstevel@tonic-gate * Ref. PC Card 95, Metaformat Specification, Page 7. 357*7c478bd9Sstevel@tonic-gate * XXX Need to think this out a bit more to deal with 3.3V 358*7c478bd9Sstevel@tonic-gate * cards and the description of where a CISTPL_DEVICE 359*7c478bd9Sstevel@tonic-gate * can show up. 360*7c478bd9Sstevel@tonic-gate */ 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate #if defined(CIS_DEBUG) 363*7c478bd9Sstevel@tonic-gate if (cis_debug > 1) { 364*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cis_list_lcreate: td=0x%x cisptr=%p\n", 365*7c478bd9Sstevel@tonic-gate GET_CIS_DATA(cisptr), (void *)cisptr); 366*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\t flags=0x%x CW_CHECK_PRIMARY_CHAIN=0x%x\n", 367*7c478bd9Sstevel@tonic-gate cis_info->flags, CW_CHECK_PRIMARY_CHAIN); 368*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\t IFType=0x%x IF_MEMORY=0x%x\n", 369*7c478bd9Sstevel@tonic-gate get_socket.IFType, IF_MEMORY); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate #endif 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate if (cis_info->flags & CW_CHECK_PRIMARY_CHAIN) { 374*7c478bd9Sstevel@tonic-gate switch (td = GET_CIS_DATA(cisptr)) { 375*7c478bd9Sstevel@tonic-gate case CISTPL_DEVICE: 376*7c478bd9Sstevel@tonic-gate case CISTPL_END: 377*7c478bd9Sstevel@tonic-gate case CISTPL_LINKTARGET: 378*7c478bd9Sstevel@tonic-gate break; 379*7c478bd9Sstevel@tonic-gate case CISTPL_NULL: 380*7c478bd9Sstevel@tonic-gate /* 381*7c478bd9Sstevel@tonic-gate * Magicram memory cards without attribute memory 382*7c478bd9Sstevel@tonic-gate * do not have a CIS and return CISTPL_NULL. 383*7c478bd9Sstevel@tonic-gate */ 384*7c478bd9Sstevel@tonic-gate if (get_socket.IFType == IF_MEMORY) 385*7c478bd9Sstevel@tonic-gate return (0); 386*7c478bd9Sstevel@tonic-gate break; 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate default: 389*7c478bd9Sstevel@tonic-gate return (0); 390*7c478bd9Sstevel@tonic-gate } /* switch */ 391*7c478bd9Sstevel@tonic-gate } /* CW_CHECK_PRIMARY_CHAIN */ 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* 394*7c478bd9Sstevel@tonic-gate * Update the number of chains counter 395*7c478bd9Sstevel@tonic-gate */ 396*7c478bd9Sstevel@tonic-gate cis_info->nchains++; 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate /* 399*7c478bd9Sstevel@tonic-gate * The main tuple processing loop. We'll exit this loop when either 400*7c478bd9Sstevel@tonic-gate * a tuple's link field is CISTPL_END or we've seen a tuple type 401*7c478bd9Sstevel@tonic-gate * field of CISTPL_END. 402*7c478bd9Sstevel@tonic-gate * 403*7c478bd9Sstevel@tonic-gate * Note that we also silently throw away CISTPL_NULL tuples, and don't 404*7c478bd9Sstevel@tonic-gate * include them in the tuple count that we return. 405*7c478bd9Sstevel@tonic-gate */ 406*7c478bd9Sstevel@tonic-gate while (!done && ((td = GET_CIS_DATA(cisptr)) != 407*7c478bd9Sstevel@tonic-gate (cisdata_t)CISTPL_END)) { 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate #if defined(CIS_DEBUG) 410*7c478bd9Sstevel@tonic-gate if ((cis_debug > 1) && (td != 0)) { 411*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cis_list_lcreate: td=0x%x cisptr=%p" 412*7c478bd9Sstevel@tonic-gate "offset=0x%x\n", 413*7c478bd9Sstevel@tonic-gate td, (void *)cisptr, cisptr->offset); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate #endif 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * Ignore CISTPL_NULL tuples 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate if (td != (cisdata_t)CISTPL_NULL) { 421*7c478bd9Sstevel@tonic-gate /* 422*7c478bd9Sstevel@tonic-gate * point to tuple link field and get the link value 423*7c478bd9Sstevel@tonic-gate */ 424*7c478bd9Sstevel@tonic-gate if (!NEXT_CIS_ADDR(cisptr)) 425*7c478bd9Sstevel@tonic-gate return ((uint32_t)BAD_CIS_ADDR); 426*7c478bd9Sstevel@tonic-gate tl = GET_CIS_DATA(cisptr); 427*7c478bd9Sstevel@tonic-gate /* 428*7c478bd9Sstevel@tonic-gate * This is an ugly PCMCIA hack - ugh! since the standard allows 429*7c478bd9Sstevel@tonic-gate * a link byte of CISTPL_END to signify that this is the 430*7c478bd9Sstevel@tonic-gate * last tuple. The problem is that this tuple might 431*7c478bd9Sstevel@tonic-gate * actually contain useful information, but we don't know 432*7c478bd9Sstevel@tonic-gate * the size of it. 433*7c478bd9Sstevel@tonic-gate * We do know that it can't be more than CIS_MAX_TUPLE_DATA_LEN 434*7c478bd9Sstevel@tonic-gate * bytes in length, however. So, we pretend that the link 435*7c478bd9Sstevel@tonic-gate * byte is CIS_MAX_TUPLE_DATA_LEN and also set a flag so 436*7c478bd9Sstevel@tonic-gate * that when we're done processing this tuple, we will 437*7c478bd9Sstevel@tonic-gate * break out of the while loop. 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate if (tl == (cisdata_t)CISTPL_END) { 440*7c478bd9Sstevel@tonic-gate tl = CIS_MAX_TUPLE_DATA_LEN; 441*7c478bd9Sstevel@tonic-gate done = 1; 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate /* 445*7c478bd9Sstevel@tonic-gate * point to first byte of tuple data, allocate a new list 446*7c478bd9Sstevel@tonic-gate * element and diddle with the list base and list 447*7c478bd9Sstevel@tonic-gate * control pointers 448*7c478bd9Sstevel@tonic-gate */ 449*7c478bd9Sstevel@tonic-gate if (!NEXT_CIS_ADDR(cisptr)) 450*7c478bd9Sstevel@tonic-gate return ((uint32_t)BAD_CIS_ADDR); 451*7c478bd9Sstevel@tonic-gate cp = (cistpl_t *)CIS_MEM_ALLOC(sizeof (cistpl_t)); 452*7c478bd9Sstevel@tonic-gate cp->next = NULL; 453*7c478bd9Sstevel@tonic-gate /* 454*7c478bd9Sstevel@tonic-gate * if we're not the first in the list, point to our 455*7c478bd9Sstevel@tonic-gate * next 456*7c478bd9Sstevel@tonic-gate */ 457*7c478bd9Sstevel@tonic-gate if (tp) 458*7c478bd9Sstevel@tonic-gate tp->next = cp; 459*7c478bd9Sstevel@tonic-gate /* 460*7c478bd9Sstevel@tonic-gate * will be NULL if we're the first element of the 461*7c478bd9Sstevel@tonic-gate * list 462*7c478bd9Sstevel@tonic-gate */ 463*7c478bd9Sstevel@tonic-gate cp->prev = tp; 464*7c478bd9Sstevel@tonic-gate tp = cp; 465*7c478bd9Sstevel@tonic-gate /* 466*7c478bd9Sstevel@tonic-gate * if this is the first element, save it's address 467*7c478bd9Sstevel@tonic-gate */ 468*7c478bd9Sstevel@tonic-gate if (!cis_info->cis) 469*7c478bd9Sstevel@tonic-gate cis_info->cis = tp; 470*7c478bd9Sstevel@tonic-gate tp->type = td; 471*7c478bd9Sstevel@tonic-gate tp->len = tl; 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate /* 474*7c478bd9Sstevel@tonic-gate * Save the address in CIS space that this tuple 475*7c478bd9Sstevel@tonic-gate * begins at, as well as set tuple flags. 476*7c478bd9Sstevel@tonic-gate */ 477*7c478bd9Sstevel@tonic-gate cis_store_cis_addr(tp, cisptr); 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate /* 480*7c478bd9Sstevel@tonic-gate * If this tuple has tuple data, we might need to 481*7c478bd9Sstevel@tonic-gate * copy it. 482*7c478bd9Sstevel@tonic-gate * Note that the tuple data pointer (tp->data) will 483*7c478bd9Sstevel@tonic-gate * be set to NULL for a tuple with no data. 484*7c478bd9Sstevel@tonic-gate */ 485*7c478bd9Sstevel@tonic-gate #ifdef XXX 486*7c478bd9Sstevel@tonic-gate if (tl) { 487*7c478bd9Sstevel@tonic-gate #endif 488*7c478bd9Sstevel@tonic-gate /* 489*7c478bd9Sstevel@tonic-gate * Read the data in the tuple and store it 490*7c478bd9Sstevel@tonic-gate * away locally if we're allowed to. If 491*7c478bd9Sstevel@tonic-gate * the CISTPLF_COPYOK flag is set, it means 492*7c478bd9Sstevel@tonic-gate * that it's OK to touch the data portion 493*7c478bd9Sstevel@tonic-gate * of the tuple. 494*7c478bd9Sstevel@tonic-gate * 495*7c478bd9Sstevel@tonic-gate * We need to make this check since some 496*7c478bd9Sstevel@tonic-gate * tuples might contain active registers 497*7c478bd9Sstevel@tonic-gate * that can alter the device state if they 498*7c478bd9Sstevel@tonic-gate * are read before the card is correctly 499*7c478bd9Sstevel@tonic-gate * initialized. What a stupid thing to 500*7c478bd9Sstevel@tonic-gate * allow in a standard, BTW. 501*7c478bd9Sstevel@tonic-gate * 502*7c478bd9Sstevel@tonic-gate * We first give the tuple handler a chance 503*7c478bd9Sstevel@tonic-gate * to set any tuple flags that it wants 504*7c478bd9Sstevel@tonic-gate * to, then we (optionally) do the data 505*7c478bd9Sstevel@tonic-gate * copy, and give the tuple handler another 506*7c478bd9Sstevel@tonic-gate * shot at the tuple. 507*7c478bd9Sstevel@tonic-gate * 508*7c478bd9Sstevel@tonic-gate * ref. PC Card Standard Release 2.01 in the 509*7c478bd9Sstevel@tonic-gate * Card Metaformat section, section 5.2.6, 510*7c478bd9Sstevel@tonic-gate * page 5-12. 511*7c478bd9Sstevel@tonic-gate */ 512*7c478bd9Sstevel@tonic-gate if ((err = cis_tuple_handler(cistpl_callout, tp, 513*7c478bd9Sstevel@tonic-gate HANDTPL_SET_FLAGS, NULL, 0)) & 514*7c478bd9Sstevel@tonic-gate HANDTPL_ERROR) 515*7c478bd9Sstevel@tonic-gate return (err); 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate if (tl > (unsigned)0) { 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * if we're supposed to make a local copy of 521*7c478bd9Sstevel@tonic-gate * the tuple data, allocate space for it, 522*7c478bd9Sstevel@tonic-gate * otherwise just record the PC card 523*7c478bd9Sstevel@tonic-gate * starting address of this tuple. 524*7c478bd9Sstevel@tonic-gate * The address was saved by cis_store_cis_addr. 525*7c478bd9Sstevel@tonic-gate */ 526*7c478bd9Sstevel@tonic-gate if (tp->flags & CISTPLF_COPYOK) { 527*7c478bd9Sstevel@tonic-gate tp->data = (cisdata_t *)CIS_MEM_ALLOC(tl); 528*7c478bd9Sstevel@tonic-gate dp = tp->data; 529*7c478bd9Sstevel@tonic-gate } else { 530*7c478bd9Sstevel@tonic-gate tp->data = GET_CIS_ADDR(tp); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate while (tl--) { 534*7c478bd9Sstevel@tonic-gate if (tp->flags & CISTPLF_COPYOK) 535*7c478bd9Sstevel@tonic-gate *dp++ = GET_CIS_DATA(cisptr); 536*7c478bd9Sstevel@tonic-gate if (!NEXT_CIS_ADDR(cisptr)) 537*7c478bd9Sstevel@tonic-gate return ((uint32_t)BAD_CIS_ADDR); 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate /* 541*7c478bd9Sstevel@tonic-gate * If we made a local copy of the tuple data, 542*7c478bd9Sstevel@tonic-gate * then clear the AM and CM flags; if the 543*7c478bd9Sstevel@tonic-gate * tuple data is still on the card, then 544*7c478bd9Sstevel@tonic-gate * leave the flags alone. 545*7c478bd9Sstevel@tonic-gate */ 546*7c478bd9Sstevel@tonic-gate if (tp->flags & CISTPLF_COPYOK) { 547*7c478bd9Sstevel@tonic-gate tp->flags &= ~CISTPLF_SPACE_MASK; 548*7c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_LM_SPACE; 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate /* 552*7c478bd9Sstevel@tonic-gate * This is a tuple with no data in it's body, so 553*7c478bd9Sstevel@tonic-gate * we just set the data pointer to NULL. 554*7c478bd9Sstevel@tonic-gate */ 555*7c478bd9Sstevel@tonic-gate } else { 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate tp->data = NULL; 558*7c478bd9Sstevel@tonic-gate /* 559*7c478bd9Sstevel@tonic-gate * tp->flags &= ~(CISTPLF_SPACE_MASK | 560*7c478bd9Sstevel@tonic-gate * CISTPLF_FROM_MASK); 561*7c478bd9Sstevel@tonic-gate */ 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate } /* if (tl > 0) */ 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate /* 566*7c478bd9Sstevel@tonic-gate * The main idea behind this call is to give 567*7c478bd9Sstevel@tonic-gate * the handler a chance to validate the 568*7c478bd9Sstevel@tonic-gate * tuple. 569*7c478bd9Sstevel@tonic-gate */ 570*7c478bd9Sstevel@tonic-gate if ((err = cis_tuple_handler(cistpl_callout, tp, 571*7c478bd9Sstevel@tonic-gate HANDTPL_COPY_DONE, NULL, 0)) & 572*7c478bd9Sstevel@tonic-gate HANDTPL_ERROR) 573*7c478bd9Sstevel@tonic-gate return (err); 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate #ifdef XXX 576*7c478bd9Sstevel@tonic-gate } else { /* if (tl) */ 577*7c478bd9Sstevel@tonic-gate tp->data = NULL; 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate #endif 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate /* 582*7c478bd9Sstevel@tonic-gate * Check to see if this is a longlink tuple and if 583*7c478bd9Sstevel@tonic-gate * so, do the necessary processing. 584*7c478bd9Sstevel@tonic-gate */ 585*7c478bd9Sstevel@tonic-gate if ((err = cis_process_longlink(cistpl_callout, tp, 586*7c478bd9Sstevel@tonic-gate cis_info, 587*7c478bd9Sstevel@tonic-gate cisparse)) & 588*7c478bd9Sstevel@tonic-gate HANDTPL_ERROR) 589*7c478bd9Sstevel@tonic-gate return (err); 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate cis_info->ntuples++; 592*7c478bd9Sstevel@tonic-gate } else { /* if (td == CISTPL_NULL) */ 593*7c478bd9Sstevel@tonic-gate /* 594*7c478bd9Sstevel@tonic-gate * If we're a CISTPL_NULL we need to skip to 595*7c478bd9Sstevel@tonic-gate * the beginning of the next tuple. 596*7c478bd9Sstevel@tonic-gate */ 597*7c478bd9Sstevel@tonic-gate if (!NEXT_CIS_ADDR(cisptr)) 598*7c478bd9Sstevel@tonic-gate return ((uint32_t)BAD_CIS_ADDR); 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate } /* while (!done && !CISTPL_END) */ 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate #if defined(CIS_DEBUG) 603*7c478bd9Sstevel@tonic-gate if (cis_debug > 1) { 604*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cis_list_lcreate: exit nchains=%x ntuples=%x\n", 605*7c478bd9Sstevel@tonic-gate cis_info->nchains, cis_info->ntuples); 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate #endif 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate return (cis_info->ntuples); 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate /* 613*7c478bd9Sstevel@tonic-gate * cis_process_longlink - processes longlink tuples 614*7c478bd9Sstevel@tonic-gate * 615*7c478bd9Sstevel@tonic-gate * This function examines the passed-in tuple type and if it is a 616*7c478bd9Sstevel@tonic-gate * longlink tuple, the tuple is parsed and the appropriate flags in 617*7c478bd9Sstevel@tonic-gate * cis_info->flags are set. 618*7c478bd9Sstevel@tonic-gate * 619*7c478bd9Sstevel@tonic-gate * If there is an error parsing the tuple, HANDTPL_ERROR is returned 620*7c478bd9Sstevel@tonic-gate * and the CW_LONGLINK_FOUND flags in cis_info->flags are cleared. 621*7c478bd9Sstevel@tonic-gate */ 622*7c478bd9Sstevel@tonic-gate static int 623*7c478bd9Sstevel@tonic-gate cis_process_longlink(cistpl_callout_t *cistpl_callout, cistpl_t *tp, 624*7c478bd9Sstevel@tonic-gate cis_info_t *cis_info, cisparse_t *cisparse) 625*7c478bd9Sstevel@tonic-gate { 626*7c478bd9Sstevel@tonic-gate /* 627*7c478bd9Sstevel@tonic-gate * If this is a CISTPL_LONGLINK_A, CISTPL_LONGLINK_C 628*7c478bd9Sstevel@tonic-gate * or CISTPL_LONGLINK_MFC tuple, parse the tuple 629*7c478bd9Sstevel@tonic-gate * and set appropriate CW_LONGLINK_XXX_FOUND flags. 630*7c478bd9Sstevel@tonic-gate * If this is a CISTPL_NO_LINK tuple, or if there is an 631*7c478bd9Sstevel@tonic-gate * error parsing the tuple, clear all the 632*7c478bd9Sstevel@tonic-gate * CW_LONGLINK_XXX_FOUND flags. 633*7c478bd9Sstevel@tonic-gate */ 634*7c478bd9Sstevel@tonic-gate switch (tp->type) { 635*7c478bd9Sstevel@tonic-gate case CISTPL_LONGLINK_A: 636*7c478bd9Sstevel@tonic-gate case CISTPL_LONGLINK_C: 637*7c478bd9Sstevel@tonic-gate case CISTPL_LONGLINK_MFC: 638*7c478bd9Sstevel@tonic-gate cis_info->flags &= ~CW_LONGLINK_FOUND; 639*7c478bd9Sstevel@tonic-gate if (cis_tuple_handler(cistpl_callout, tp, 640*7c478bd9Sstevel@tonic-gate HANDTPL_PARSE_LTUPLE, 641*7c478bd9Sstevel@tonic-gate cisparse, NULL) & 642*7c478bd9Sstevel@tonic-gate HANDTPL_ERROR) 643*7c478bd9Sstevel@tonic-gate return (HANDTPL_ERROR); 644*7c478bd9Sstevel@tonic-gate switch (tp->type) { 645*7c478bd9Sstevel@tonic-gate case CISTPL_LONGLINK_A: 646*7c478bd9Sstevel@tonic-gate cis_info->flags |= CW_LONGLINK_A_FOUND; 647*7c478bd9Sstevel@tonic-gate break; 648*7c478bd9Sstevel@tonic-gate case CISTPL_LONGLINK_C: 649*7c478bd9Sstevel@tonic-gate cis_info->flags |= CW_LONGLINK_C_FOUND; 650*7c478bd9Sstevel@tonic-gate break; 651*7c478bd9Sstevel@tonic-gate case CISTPL_LONGLINK_MFC: 652*7c478bd9Sstevel@tonic-gate cis_info->flags |= CW_LONGLINK_MFC_FOUND; 653*7c478bd9Sstevel@tonic-gate break; 654*7c478bd9Sstevel@tonic-gate } /* switch (tp->type) */ 655*7c478bd9Sstevel@tonic-gate break; 656*7c478bd9Sstevel@tonic-gate case CISTPL_NO_LINK: 657*7c478bd9Sstevel@tonic-gate cis_info->flags &= ~CW_LONGLINK_FOUND; 658*7c478bd9Sstevel@tonic-gate break; 659*7c478bd9Sstevel@tonic-gate } /* switch (tp->type) */ 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate return (HANDTPL_NOERROR); 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate /* 665*7c478bd9Sstevel@tonic-gate * cis_list_ldestroy - function to destroy a linked tuple list 666*7c478bd9Sstevel@tonic-gate * 667*7c478bd9Sstevel@tonic-gate * cistpl_t *cistplbase - pointer to a pointer to the base of a 668*7c478bd9Sstevel@tonic-gate * local linked CIS list to destroy; the 669*7c478bd9Sstevel@tonic-gate * data that this pointer points to is 670*7c478bd9Sstevel@tonic-gate * also destroyed 671*7c478bd9Sstevel@tonic-gate * 672*7c478bd9Sstevel@tonic-gate * Once this function returns, cistplbase is set to NULL. 673*7c478bd9Sstevel@tonic-gate */ 674*7c478bd9Sstevel@tonic-gate uint32_t 675*7c478bd9Sstevel@tonic-gate cis_list_ldestroy(cistpl_t **cistplbase) 676*7c478bd9Sstevel@tonic-gate { 677*7c478bd9Sstevel@tonic-gate cistpl_t *cp, *tp; 678*7c478bd9Sstevel@tonic-gate int tpcnt = 0; 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate /* 681*7c478bd9Sstevel@tonic-gate * First, check to see if we've got a 682*7c478bd9Sstevel@tonic-gate * non-NULL list pointer. 683*7c478bd9Sstevel@tonic-gate */ 684*7c478bd9Sstevel@tonic-gate if ((tp = *cistplbase) == NULL) 685*7c478bd9Sstevel@tonic-gate return (0); 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate while (tp) { 688*7c478bd9Sstevel@tonic-gate /* 689*7c478bd9Sstevel@tonic-gate * Free any data that may be allocated 690*7c478bd9Sstevel@tonic-gate */ 691*7c478bd9Sstevel@tonic-gate if ((tp->flags & CISTPLF_COPYOK) && 692*7c478bd9Sstevel@tonic-gate (tp->flags & CISTPLF_LM_SPACE) && 693*7c478bd9Sstevel@tonic-gate (tp->data)) 694*7c478bd9Sstevel@tonic-gate CIS_MEM_FREE((caddr_t)tp->data); 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate cp = tp->next; 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate /* 699*7c478bd9Sstevel@tonic-gate * Free this tuple 700*7c478bd9Sstevel@tonic-gate */ 701*7c478bd9Sstevel@tonic-gate CIS_MEM_FREE((caddr_t)tp); 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate tp = cp; 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate tpcnt++; 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate /* 709*7c478bd9Sstevel@tonic-gate * Now clear the pointer to the non-existant 710*7c478bd9Sstevel@tonic-gate * linked list. 711*7c478bd9Sstevel@tonic-gate */ 712*7c478bd9Sstevel@tonic-gate *cistplbase = NULL; 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate return (tpcnt); 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate /* 719*7c478bd9Sstevel@tonic-gate * cis_get_ltuple - function to walk local linked CIS list and return 720*7c478bd9Sstevel@tonic-gate * a tuple based on various criteria 721*7c478bd9Sstevel@tonic-gate * 722*7c478bd9Sstevel@tonic-gate * cistpl_t *tp - pointer to any valid tuple in the list 723*7c478bd9Sstevel@tonic-gate * cisdata_t type - type of tuple to search for 724*7c478bd9Sstevel@tonic-gate * int flags - type of action to perform (each is mutually exclusive) 725*7c478bd9Sstevel@tonic-gate * GET_FIRST_LTUPLEF, GET_LAST_LTUPLEF: 726*7c478bd9Sstevel@tonic-gate * Returns the {first|last} tuple in the list. 727*7c478bd9Sstevel@tonic-gate * FIND_LTUPLE_FWDF, FIND_LTUPLE_BACKF: 728*7c478bd9Sstevel@tonic-gate * FIND_NEXT_LTUPLEF, FIND_PREV_LTUPLEF: 729*7c478bd9Sstevel@tonic-gate * Returns the first tuple that matches the passed tuple type, 730*7c478bd9Sstevel@tonic-gate * searching the list {forward|backward}. 731*7c478bd9Sstevel@tonic-gate * GET_NEXT_LTUPLEF, GET_PREV_LTUPLEF: 732*7c478bd9Sstevel@tonic-gate * Returns the {next|previous} tuple in the list. 733*7c478bd9Sstevel@tonic-gate * 734*7c478bd9Sstevel@tonic-gate * The following bits can be set in the flags parameter: 735*7c478bd9Sstevel@tonic-gate * CIS_GET_LTUPLE_IGNORE - return tuples with 736*7c478bd9Sstevel@tonic-gate * CISTPLF_IGNORE_TUPLE set in cistpl_t->flags 737*7c478bd9Sstevel@tonic-gate * 738*7c478bd9Sstevel@tonic-gate * Note on searching: 739*7c478bd9Sstevel@tonic-gate * When using the FIND_LTUPLE_FWDF and FIND_LTUPLE_BACKF flags, 740*7c478bd9Sstevel@tonic-gate * the search starts at the passed tuple. Continually calling this 741*7c478bd9Sstevel@tonic-gate * function with a tuple that is the same type as the passed type will 742*7c478bd9Sstevel@tonic-gate * continually return the same tuple. 743*7c478bd9Sstevel@tonic-gate * 744*7c478bd9Sstevel@tonic-gate * When using the FIND_NEXT_LTUPLEF and FIND_PREV_LTUPLEF flags, 745*7c478bd9Sstevel@tonic-gate * the search starts at the {next|previous} tuple from the passed tuple. 746*7c478bd9Sstevel@tonic-gate * 747*7c478bd9Sstevel@tonic-gate * returns: 748*7c478bd9Sstevel@tonic-gate * cistpl_t * - pointer to tuple in list 749*7c478bd9Sstevel@tonic-gate * NULL - if error while processing list or tuple not found 750*7c478bd9Sstevel@tonic-gate */ 751*7c478bd9Sstevel@tonic-gate #define GET_NEXT_LTUPLE(tp) ((tp->next)?tp->next:NULL) 752*7c478bd9Sstevel@tonic-gate #define GET_PREV_LTUPLE(tp) ((tp->prev)?tp->prev:NULL) 753*7c478bd9Sstevel@tonic-gate cistpl_t * 754*7c478bd9Sstevel@tonic-gate cis_get_ltuple(cistpl_t *tp, cisdata_t type, uint32_t flags) 755*7c478bd9Sstevel@tonic-gate { 756*7c478bd9Sstevel@tonic-gate cistpl_t *ltp = NULL; 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate if (!tp) 759*7c478bd9Sstevel@tonic-gate return (NULL); 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate switch (flags & CIS_GET_LTUPLE_OPMASK) { 762*7c478bd9Sstevel@tonic-gate case GET_FIRST_LTUPLEF: /* return first tuple in list */ 763*7c478bd9Sstevel@tonic-gate do { 764*7c478bd9Sstevel@tonic-gate ltp = tp; 765*7c478bd9Sstevel@tonic-gate } while ((tp = GET_PREV_LTUPLE(tp)) != NULL); 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate if (!(flags & CIS_GET_LTUPLE_IGNORE)) 768*7c478bd9Sstevel@tonic-gate while (ltp && (ltp->flags & CISTPLF_IGNORE_TUPLE)) 769*7c478bd9Sstevel@tonic-gate ltp = GET_NEXT_LTUPLE(ltp); 770*7c478bd9Sstevel@tonic-gate break; 771*7c478bd9Sstevel@tonic-gate case GET_LAST_LTUPLEF: /* return last tuple in list */ 772*7c478bd9Sstevel@tonic-gate do { 773*7c478bd9Sstevel@tonic-gate ltp = tp; 774*7c478bd9Sstevel@tonic-gate } while ((tp = GET_NEXT_LTUPLE(tp)) != NULL); 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate if (!(flags & CIS_GET_LTUPLE_IGNORE)) 777*7c478bd9Sstevel@tonic-gate while (ltp && (ltp->flags & CISTPLF_IGNORE_TUPLE)) 778*7c478bd9Sstevel@tonic-gate ltp = GET_PREV_LTUPLE(ltp); 779*7c478bd9Sstevel@tonic-gate break; 780*7c478bd9Sstevel@tonic-gate case FIND_LTUPLE_FWDF: /* find tuple, fwd search from tp */ 781*7c478bd9Sstevel@tonic-gate do { 782*7c478bd9Sstevel@tonic-gate if (tp->type == type) 783*7c478bd9Sstevel@tonic-gate if ((flags & CIS_GET_LTUPLE_IGNORE) || 784*7c478bd9Sstevel@tonic-gate (!(tp->flags & CISTPLF_IGNORE_TUPLE))) 785*7c478bd9Sstevel@tonic-gate return (tp); /* note return here */ 786*7c478bd9Sstevel@tonic-gate } while ((tp = GET_NEXT_LTUPLE(tp)) != NULL); 787*7c478bd9Sstevel@tonic-gate break; 788*7c478bd9Sstevel@tonic-gate case FIND_LTUPLE_BACKF: 789*7c478bd9Sstevel@tonic-gate /* find tuple, backward search from tp */ 790*7c478bd9Sstevel@tonic-gate do { 791*7c478bd9Sstevel@tonic-gate if (tp->type == type) 792*7c478bd9Sstevel@tonic-gate if ((flags & CIS_GET_LTUPLE_IGNORE) || 793*7c478bd9Sstevel@tonic-gate (!(tp->flags & CISTPLF_IGNORE_TUPLE))) 794*7c478bd9Sstevel@tonic-gate return (tp); /* note return here */ 795*7c478bd9Sstevel@tonic-gate } while ((tp = GET_PREV_LTUPLE(tp)) != NULL); 796*7c478bd9Sstevel@tonic-gate break; 797*7c478bd9Sstevel@tonic-gate case FIND_NEXT_LTUPLEF: /* find tuple, fwd search from tp+1 */ 798*7c478bd9Sstevel@tonic-gate while ((tp = GET_NEXT_LTUPLE(tp)) != NULL) { 799*7c478bd9Sstevel@tonic-gate if (tp->type == type) 800*7c478bd9Sstevel@tonic-gate if ((flags & CIS_GET_LTUPLE_IGNORE) || 801*7c478bd9Sstevel@tonic-gate (!(tp->flags & CISTPLF_IGNORE_TUPLE))) 802*7c478bd9Sstevel@tonic-gate return (tp); /* note return here */ 803*7c478bd9Sstevel@tonic-gate } /* while */ 804*7c478bd9Sstevel@tonic-gate break; 805*7c478bd9Sstevel@tonic-gate case FIND_PREV_LTUPLEF: 806*7c478bd9Sstevel@tonic-gate /* find tuple, backward search from tp-1 */ 807*7c478bd9Sstevel@tonic-gate while ((tp = GET_PREV_LTUPLE(tp)) != NULL) { 808*7c478bd9Sstevel@tonic-gate if (tp->type == type) 809*7c478bd9Sstevel@tonic-gate if ((flags & CIS_GET_LTUPLE_IGNORE) || 810*7c478bd9Sstevel@tonic-gate (!(tp->flags & CISTPLF_IGNORE_TUPLE))) 811*7c478bd9Sstevel@tonic-gate return (tp); /* note return here */ 812*7c478bd9Sstevel@tonic-gate } /* while */ 813*7c478bd9Sstevel@tonic-gate break; 814*7c478bd9Sstevel@tonic-gate case GET_NEXT_LTUPLEF: /* return next tuple in list */ 815*7c478bd9Sstevel@tonic-gate ltp = tp; 816*7c478bd9Sstevel@tonic-gate while (((ltp = GET_NEXT_LTUPLE(ltp)) != NULL) && 817*7c478bd9Sstevel@tonic-gate (!(flags & CIS_GET_LTUPLE_IGNORE)) && 818*7c478bd9Sstevel@tonic-gate (ltp->flags & CISTPLF_IGNORE_TUPLE)) 819*7c478bd9Sstevel@tonic-gate ; 820*7c478bd9Sstevel@tonic-gate break; 821*7c478bd9Sstevel@tonic-gate case GET_PREV_LTUPLEF: /* return prev tuple in list */ 822*7c478bd9Sstevel@tonic-gate ltp = tp; 823*7c478bd9Sstevel@tonic-gate while (((ltp = GET_PREV_LTUPLE(ltp)) != NULL) && 824*7c478bd9Sstevel@tonic-gate (!(flags & CIS_GET_LTUPLE_IGNORE)) && 825*7c478bd9Sstevel@tonic-gate (ltp->flags & CISTPLF_IGNORE_TUPLE)) 826*7c478bd9Sstevel@tonic-gate ; 827*7c478bd9Sstevel@tonic-gate break; 828*7c478bd9Sstevel@tonic-gate default: /* ltp is already NULL in the initialization */ 829*7c478bd9Sstevel@tonic-gate break; 830*7c478bd9Sstevel@tonic-gate } /* switch */ 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate return (ltp); 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate /* 836*7c478bd9Sstevel@tonic-gate * cis_convert_devspeed - converts a devspeed value to nS or nS 837*7c478bd9Sstevel@tonic-gate * to a devspeed entry 838*7c478bd9Sstevel@tonic-gate */ 839*7c478bd9Sstevel@tonic-gate uint32_t 840*7c478bd9Sstevel@tonic-gate cis_convert_devspeed(convert_speed_t *cs) 841*7c478bd9Sstevel@tonic-gate { 842*7c478bd9Sstevel@tonic-gate cistpl_devspeed_struct_t *cd = &cistpl_devspeed_struct; 843*7c478bd9Sstevel@tonic-gate unsigned exponent = 0, mantissa = 0; 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate /* 846*7c478bd9Sstevel@tonic-gate * Convert nS to a devspeed value 847*7c478bd9Sstevel@tonic-gate */ 848*7c478bd9Sstevel@tonic-gate if (cs->Attributes & CONVERT_NS_TO_DEVSPEED) { 849*7c478bd9Sstevel@tonic-gate unsigned tnS, tmanv = 0, i; 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate /* 852*7c478bd9Sstevel@tonic-gate * There is no device speed code for 0nS 853*7c478bd9Sstevel@tonic-gate */ 854*7c478bd9Sstevel@tonic-gate if (!cs->nS) 855*7c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate /* 858*7c478bd9Sstevel@tonic-gate * Handle any nS value below 10nS specially since the code 859*7c478bd9Sstevel@tonic-gate * below only works for nS values >= 10. Now, why anyone 860*7c478bd9Sstevel@tonic-gate * would want to specify a nS value less than 10 is 861*7c478bd9Sstevel@tonic-gate * certainly questionable, but it is allowed by the spec. 862*7c478bd9Sstevel@tonic-gate */ 863*7c478bd9Sstevel@tonic-gate if (cs->nS < 10) { 864*7c478bd9Sstevel@tonic-gate tmanv = cs->nS * 10; 865*7c478bd9Sstevel@tonic-gate mantissa = CISTPL_DEVSPEED_MAX_MAN; 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate /* find the exponent */ 869*7c478bd9Sstevel@tonic-gate for (i = 0; i < CISTPL_DEVSPEED_MAX_EXP; i++) { 870*7c478bd9Sstevel@tonic-gate if ((!(tnS = ((cs->nS)/10))) || 871*7c478bd9Sstevel@tonic-gate (mantissa == CISTPL_DEVSPEED_MAX_MAN)) { 872*7c478bd9Sstevel@tonic-gate /* find the mantissa */ 873*7c478bd9Sstevel@tonic-gate for (mantissa = 0; mantissa < CISTPL_DEVSPEED_MAX_MAN; 874*7c478bd9Sstevel@tonic-gate mantissa++) { 875*7c478bd9Sstevel@tonic-gate if (cd->mantissa[mantissa] == tmanv) { 876*7c478bd9Sstevel@tonic-gate cs->devspeed = ((((mantissa<<3) | 877*7c478bd9Sstevel@tonic-gate (exponent & (CISTPL_DEVSPEED_MAX_EXP - 1))))); 878*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate } /* for (mantissa<CISTPL_DEVSPEED_MAX_MAN) */ 881*7c478bd9Sstevel@tonic-gate } else { 882*7c478bd9Sstevel@tonic-gate exponent = i + 1; 883*7c478bd9Sstevel@tonic-gate tmanv = cs->nS; 884*7c478bd9Sstevel@tonic-gate cs->nS = tnS; 885*7c478bd9Sstevel@tonic-gate } /* if (!tnS) */ 886*7c478bd9Sstevel@tonic-gate } /* for (i<CISTPL_DEVSPEED_MAX_EXP) */ 887*7c478bd9Sstevel@tonic-gate /* 888*7c478bd9Sstevel@tonic-gate * Convert a devspeed value to nS 889*7c478bd9Sstevel@tonic-gate */ 890*7c478bd9Sstevel@tonic-gate } else if (cs->Attributes & CONVERT_DEVSPEED_TO_NS) { 891*7c478bd9Sstevel@tonic-gate exponent = (cs->devspeed & (CISTPL_DEVSPEED_MAX_TBL - 1)); 892*7c478bd9Sstevel@tonic-gate if ((mantissa = (((cs->devspeed)>>3) & 893*7c478bd9Sstevel@tonic-gate (CISTPL_DEVSPEED_MAX_MAN - 1))) == NULL) { 894*7c478bd9Sstevel@tonic-gate if ((cs->nS = cd->table[exponent]) == NULL) 895*7c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 896*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 897*7c478bd9Sstevel@tonic-gate } else { 898*7c478bd9Sstevel@tonic-gate if ((cs->nS = ((cd->mantissa[mantissa] * 899*7c478bd9Sstevel@tonic-gate cd->exponent[exponent]) / 10)) == NULL) 900*7c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 901*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate } else { 904*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate /* 911*7c478bd9Sstevel@tonic-gate * This array is for the cis_convert_devsize function. 912*7c478bd9Sstevel@tonic-gate */ 913*7c478bd9Sstevel@tonic-gate static uint32_t cistpl_device_size[8] = 914*7c478bd9Sstevel@tonic-gate { 512, 2*1024, 8*1024, 32*1024, 128*1024, 512*1024, 2*1024*1024, 0 }; 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate /* 917*7c478bd9Sstevel@tonic-gate * cis_convert_devsize - converts a devsize value to a size in bytes value 918*7c478bd9Sstevel@tonic-gate * or a size in bytes value to a devsize value 919*7c478bd9Sstevel@tonic-gate */ 920*7c478bd9Sstevel@tonic-gate uint32_t 921*7c478bd9Sstevel@tonic-gate cis_convert_devsize(convert_size_t *cs) 922*7c478bd9Sstevel@tonic-gate { 923*7c478bd9Sstevel@tonic-gate int i; 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate if (cs->Attributes & CONVERT_BYTES_TO_DEVSIZE) { 926*7c478bd9Sstevel@tonic-gate if ((cs->bytes < cistpl_device_size[0]) || 927*7c478bd9Sstevel@tonic-gate (cs->bytes > (cistpl_device_size[6] * 32))) 928*7c478bd9Sstevel@tonic-gate return (CS_BAD_SIZE); 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate for (i = 6; i >= 0; i--) 931*7c478bd9Sstevel@tonic-gate if (cs->bytes >= cistpl_device_size[i]) 932*7c478bd9Sstevel@tonic-gate break; 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate cs->devsize = ((((cs->bytes/cistpl_device_size[i]) - 1) << 3) | 935*7c478bd9Sstevel@tonic-gate (i & 7)); 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate } else if (cs->Attributes & CONVERT_DEVSIZE_TO_BYTES) { 938*7c478bd9Sstevel@tonic-gate if ((cs->devsize & 7) == 7) 939*7c478bd9Sstevel@tonic-gate return (CS_BAD_SIZE); 940*7c478bd9Sstevel@tonic-gate cs->bytes = 941*7c478bd9Sstevel@tonic-gate cistpl_device_size[cs->devsize & 7] * ((cs->devsize >> 3) + 1); 942*7c478bd9Sstevel@tonic-gate } else { 943*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 947*7c478bd9Sstevel@tonic-gate } 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate /* 950*7c478bd9Sstevel@tonic-gate * cis_list_create - reads the card's CIS and creates local CIS lists for 951*7c478bd9Sstevel@tonic-gate * each function on the card 952*7c478bd9Sstevel@tonic-gate * 953*7c478bd9Sstevel@tonic-gate * This function will read the CIS on the card, follow all CISTPL_LONGLINK_A, 954*7c478bd9Sstevel@tonic-gate * CISTPL_LONGLINK_C and CISTPL_LONGLINK_MFC tuples and create local CIS 955*7c478bd9Sstevel@tonic-gate * lists for each major CIS chain on the card. 956*7c478bd9Sstevel@tonic-gate * 957*7c478bd9Sstevel@tonic-gate * If there are no errors, the parameters returned are: 958*7c478bd9Sstevel@tonic-gate * For a non-multifunction card: 959*7c478bd9Sstevel@tonic-gate * sp->cis_flags - CW_VALID_CIS set 960*7c478bd9Sstevel@tonic-gate * sp->nfuncs - set to 0x0 961*7c478bd9Sstevel@tonic-gate * sp->cis[CS_GLOBAL_CIS] - contains CIS list 962*7c478bd9Sstevel@tonic-gate * sp->cis[CS_GLOBAL_CIS].cis_flags - CW_VALID_CIS set 963*7c478bd9Sstevel@tonic-gate * 964*7c478bd9Sstevel@tonic-gate * For a multifunction card: 965*7c478bd9Sstevel@tonic-gate * Global CIS values: 966*7c478bd9Sstevel@tonic-gate * sp->cis_flags - CW_VALID_CIS & CW_MULTI_FUNCTION_CIS set 967*7c478bd9Sstevel@tonic-gate * sp->nfuncs - set to number of functions specified in 968*7c478bd9Sstevel@tonic-gate * the CISTPL_LONGLINK_MFC tuple 969*7c478bd9Sstevel@tonic-gate * sp->cis[CS_GLOBAL_CIS] - contains global CIS list 970*7c478bd9Sstevel@tonic-gate * sp->cis[CS_GLOBAL_CIS].cis_flags - CW_VALID_CIS set 971*7c478bd9Sstevel@tonic-gate * Function-specific CIS values: 972*7c478bd9Sstevel@tonic-gate * sp->cis[0..sp->nfuncs-1] - contains function-specific CIS lists 973*7c478bd9Sstevel@tonic-gate * sp->cis[0..sp->nfuncs-1].cis_flags - CW_VALID_CIS & 974*7c478bd9Sstevel@tonic-gate * CW_MULTI_FUNCTION_CIS set 975*7c478bd9Sstevel@tonic-gate * 976*7c478bd9Sstevel@tonic-gate * returns: 977*7c478bd9Sstevel@tonic-gate * CS_SUCCESS - if no errors 978*7c478bd9Sstevel@tonic-gate * CS_NO_CIS - if no CIS on card 979*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW or CS_GENERAL_FAILURE - if CIS window could 980*7c478bd9Sstevel@tonic-gate * not be setup 981*7c478bd9Sstevel@tonic-gate * CS_BAD_CIS - if error creating CIS chains 982*7c478bd9Sstevel@tonic-gate * CS_BAD_OFFSET - if cis_list_lcreate tried to read past the 983*7c478bd9Sstevel@tonic-gate * boundries of the allocated CIS window 984*7c478bd9Sstevel@tonic-gate */ 985*7c478bd9Sstevel@tonic-gate extern cistpl_ignore_list_t cistpl_ignore_list[]; 986*7c478bd9Sstevel@tonic-gate uint32_t 987*7c478bd9Sstevel@tonic-gate cis_list_create(cistpl_callout_t *cistpl_callout, cs_socket_t *sp) 988*7c478bd9Sstevel@tonic-gate { 989*7c478bd9Sstevel@tonic-gate cisptr_t cisptr; 990*7c478bd9Sstevel@tonic-gate cisparse_t cisparse; 991*7c478bd9Sstevel@tonic-gate cis_info_t *cis_info; 992*7c478bd9Sstevel@tonic-gate cistpl_longlink_ac_t *cistpl_longlink_ac; 993*7c478bd9Sstevel@tonic-gate cistpl_longlink_mfc_t cistpl_longlink_mfc, *mfc; 994*7c478bd9Sstevel@tonic-gate cistpl_ignore_list_t *cil; 995*7c478bd9Sstevel@tonic-gate int fn, ret; 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate /* 998*7c478bd9Sstevel@tonic-gate * Initialize the CIS structures 999*7c478bd9Sstevel@tonic-gate */ 1000*7c478bd9Sstevel@tonic-gate bzero((caddr_t)&sp->cis, ((sizeof (cis_info_t)) * CS_MAX_CIS)); 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate /* 1003*7c478bd9Sstevel@tonic-gate * Start reading the primary CIS chain at offset 0x0 of AM. Assume 1004*7c478bd9Sstevel@tonic-gate * that there is a CISTPL_LONGLINK_C tuple that points to 1005*7c478bd9Sstevel@tonic-gate * offset 0x0 of CM space. 1006*7c478bd9Sstevel@tonic-gate * Since this is the primary CIS chain, set CW_CHECK_PRIMARY_CHAIN 1007*7c478bd9Sstevel@tonic-gate * so that we'll check for a valid first tuple. 1008*7c478bd9Sstevel@tonic-gate */ 1009*7c478bd9Sstevel@tonic-gate cis_info = &sp->cis[CS_GLOBAL_CIS]; 1010*7c478bd9Sstevel@tonic-gate cis_info->flags = (CW_LONGLINK_C_FOUND | CW_CHECK_PRIMARY_CHAIN); 1011*7c478bd9Sstevel@tonic-gate cisptr.flags = (CISTPLF_AM_SPACE | CISTPLF_GLOBAL_CIS); 1012*7c478bd9Sstevel@tonic-gate cisptr.size = sp->cis_win_size - 1; 1013*7c478bd9Sstevel@tonic-gate cisptr.offset = 0; 1014*7c478bd9Sstevel@tonic-gate cistpl_longlink_ac = (cistpl_longlink_ac_t *)&cisparse; 1015*7c478bd9Sstevel@tonic-gate cistpl_longlink_ac->flags = CISTPL_LONGLINK_AC_CM; 1016*7c478bd9Sstevel@tonic-gate cistpl_longlink_ac->tpll_addr = 0; 1017*7c478bd9Sstevel@tonic-gate 1018*7c478bd9Sstevel@tonic-gate if ((ret = cis_create_cis_chain(sp, cistpl_callout, &cisptr, 1019*7c478bd9Sstevel@tonic-gate cis_info, &cisparse)) != 1020*7c478bd9Sstevel@tonic-gate CS_SUCCESS) { 1021*7c478bd9Sstevel@tonic-gate return (ret); 1022*7c478bd9Sstevel@tonic-gate } /* cis_create_cis_chain */ 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate /* 1025*7c478bd9Sstevel@tonic-gate * If there are no tuples in the primary CIS chain, it means that 1026*7c478bd9Sstevel@tonic-gate * this card doesn't have a CIS on it. 1027*7c478bd9Sstevel@tonic-gate */ 1028*7c478bd9Sstevel@tonic-gate if (cis_info->ntuples == 0) 1029*7c478bd9Sstevel@tonic-gate return (CS_NO_CIS); 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate /* 1032*7c478bd9Sstevel@tonic-gate * Mark this CIS list as being valid. 1033*7c478bd9Sstevel@tonic-gate */ 1034*7c478bd9Sstevel@tonic-gate cis_info->flags |= CW_VALID_CIS; 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate /* 1037*7c478bd9Sstevel@tonic-gate * Mark this socket as having at least one valid CIS chain. 1038*7c478bd9Sstevel@tonic-gate */ 1039*7c478bd9Sstevel@tonic-gate sp->cis_flags |= CW_VALID_CIS; 1040*7c478bd9Sstevel@tonic-gate sp->nfuncs = 0; 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate /* 1043*7c478bd9Sstevel@tonic-gate * If the primary CIS chain specified that there are function-specific 1044*7c478bd9Sstevel@tonic-gate * CIS chains, we need to create each of these chains. If not, 1045*7c478bd9Sstevel@tonic-gate * then we're all done and we can return. 1046*7c478bd9Sstevel@tonic-gate */ 1047*7c478bd9Sstevel@tonic-gate if (!(cis_info->flags & CW_LONGLINK_MFC_FOUND)) 1048*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate /* 1051*7c478bd9Sstevel@tonic-gate * Mark this socket as having a multi-function CIS. 1052*7c478bd9Sstevel@tonic-gate */ 1053*7c478bd9Sstevel@tonic-gate sp->cis_flags |= CW_MULTI_FUNCTION_CIS; 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate /* 1056*7c478bd9Sstevel@tonic-gate * At this point, cis_create_cis_chain has told us that the primary 1057*7c478bd9Sstevel@tonic-gate * CIS chain says that there are function-specific CIS chains 1058*7c478bd9Sstevel@tonic-gate * on the card that we need to follow. The cisparse variable now 1059*7c478bd9Sstevel@tonic-gate * contains the parsed output of the CISTPL_LONGLINK_MFC 1060*7c478bd9Sstevel@tonic-gate * tuple. We need to save that information and then process 1061*7c478bd9Sstevel@tonic-gate * each function-specific CIS chain. 1062*7c478bd9Sstevel@tonic-gate */ 1063*7c478bd9Sstevel@tonic-gate bcopy((caddr_t)&cisparse, (caddr_t)&cistpl_longlink_mfc, 1064*7c478bd9Sstevel@tonic-gate sizeof (cistpl_longlink_mfc_t)); 1065*7c478bd9Sstevel@tonic-gate mfc = &cistpl_longlink_mfc; 1066*7c478bd9Sstevel@tonic-gate sp->nfuncs = mfc->nregs; 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate /* 1069*7c478bd9Sstevel@tonic-gate * Go through and create a CIS list for each function-specific 1070*7c478bd9Sstevel@tonic-gate * CIS chain on the card. Set CW_CHECK_LINKTARGET since all 1071*7c478bd9Sstevel@tonic-gate * function-specific CIS chains must begin with a valid 1072*7c478bd9Sstevel@tonic-gate * CISTPL_LINKTARGET tuple. Also set CW_RET_ON_LINKTARGET_ERROR 1073*7c478bd9Sstevel@tonic-gate * since we want to return an error if the CISTPL_LINKTARGET 1074*7c478bd9Sstevel@tonic-gate * tuple is invalid or missing. 1075*7c478bd9Sstevel@tonic-gate */ 1076*7c478bd9Sstevel@tonic-gate for (fn = 0; fn < sp->nfuncs; fn++) { 1077*7c478bd9Sstevel@tonic-gate cis_info = &sp->cis[fn]; 1078*7c478bd9Sstevel@tonic-gate cis_info->flags = (CW_CHECK_LINKTARGET | 1079*7c478bd9Sstevel@tonic-gate CW_RET_ON_LINKTARGET_ERROR); 1080*7c478bd9Sstevel@tonic-gate /* 1081*7c478bd9Sstevel@tonic-gate * If the function-specific CIS chain starts 1082*7c478bd9Sstevel@tonic-gate * in AM space, then multiply address by 1083*7c478bd9Sstevel@tonic-gate * 2 since only even bytes are counted in 1084*7c478bd9Sstevel@tonic-gate * the CIS when AM addresses are specified, 1085*7c478bd9Sstevel@tonic-gate * otherwise use the 1086*7c478bd9Sstevel@tonic-gate * address as specified. 1087*7c478bd9Sstevel@tonic-gate */ 1088*7c478bd9Sstevel@tonic-gate if (mfc->function[fn].tas == CISTPL_LONGLINK_MFC_TAS_AM) { 1089*7c478bd9Sstevel@tonic-gate cisptr.flags = (CISTPLF_AM_SPACE | CISTPLF_MF_CIS); 1090*7c478bd9Sstevel@tonic-gate cisptr.offset = mfc->function[fn].addr * 2; 1091*7c478bd9Sstevel@tonic-gate } else { 1092*7c478bd9Sstevel@tonic-gate cisptr.flags = (CISTPLF_CM_SPACE | CISTPLF_MF_CIS); 1093*7c478bd9Sstevel@tonic-gate cisptr.offset = mfc->function[fn].addr; 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate if ((ret = cis_create_cis_chain(sp, cistpl_callout, &cisptr, 1097*7c478bd9Sstevel@tonic-gate cis_info, &cisparse)) != 1098*7c478bd9Sstevel@tonic-gate CS_SUCCESS) { 1099*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 1100*7c478bd9Sstevel@tonic-gate "cis_list_create: socket %d ERROR_MFC = 0x%x\n", 1101*7c478bd9Sstevel@tonic-gate sp->socket_num, ret); 1102*7c478bd9Sstevel@tonic-gate return (ret); 1103*7c478bd9Sstevel@tonic-gate } /* cis_create_cis_chain */ 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate /* 1106*7c478bd9Sstevel@tonic-gate * Mark this CIS list as being valid and as being a 1107*7c478bd9Sstevel@tonic-gate * function-specific CIS list. 1108*7c478bd9Sstevel@tonic-gate */ 1109*7c478bd9Sstevel@tonic-gate cis_info->flags |= (CW_VALID_CIS | CW_MULTI_FUNCTION_CIS); 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate /* 1112*7c478bd9Sstevel@tonic-gate * Check for tuples that we want to ignore 1113*7c478bd9Sstevel@tonic-gate * in the global CIS. If the tuple exists 1114*7c478bd9Sstevel@tonic-gate * in the global CIS and in at least one 1115*7c478bd9Sstevel@tonic-gate * of the function-specific CIS lists, then 1116*7c478bd9Sstevel@tonic-gate * we flag the tuple 1117*7c478bd9Sstevel@tonic-gate * in the global CIS to be ignored. 1118*7c478bd9Sstevel@tonic-gate */ 1119*7c478bd9Sstevel@tonic-gate cil = &cistpl_ignore_list[0]; 1120*7c478bd9Sstevel@tonic-gate while (cil->type != CISTPL_NULL) { 1121*7c478bd9Sstevel@tonic-gate if (cis_get_ltuple(sp->cis[fn].cis, cil->type, 1122*7c478bd9Sstevel@tonic-gate FIND_LTUPLE_FWDF | 1123*7c478bd9Sstevel@tonic-gate CIS_GET_LTUPLE_IGNORE) != NULL) { 1124*7c478bd9Sstevel@tonic-gate cistpl_t *gtp = sp->cis[CS_GLOBAL_CIS].cis; 1125*7c478bd9Sstevel@tonic-gate while ((gtp = cis_get_ltuple(gtp, cil->type, 1126*7c478bd9Sstevel@tonic-gate FIND_LTUPLE_FWDF | 1127*7c478bd9Sstevel@tonic-gate CIS_GET_LTUPLE_IGNORE)) != NULL) { 1128*7c478bd9Sstevel@tonic-gate gtp->flags |= CISTPLF_IGNORE_TUPLE; 1129*7c478bd9Sstevel@tonic-gate gtp = cis_get_ltuple(gtp, NULL, GET_NEXT_LTUPLEF | 1130*7c478bd9Sstevel@tonic-gate CIS_GET_LTUPLE_IGNORE); 1131*7c478bd9Sstevel@tonic-gate } /* while */ 1132*7c478bd9Sstevel@tonic-gate } /* if (cis_get_ltuple(cis[fn])) */ 1133*7c478bd9Sstevel@tonic-gate cil++; 1134*7c478bd9Sstevel@tonic-gate } /* while */ 1135*7c478bd9Sstevel@tonic-gate } /* for */ 1136*7c478bd9Sstevel@tonic-gate 1137*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1138*7c478bd9Sstevel@tonic-gate } 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate /* 1141*7c478bd9Sstevel@tonic-gate * cis_create_cis_chain - creates a single CIS chain 1142*7c478bd9Sstevel@tonic-gate * 1143*7c478bd9Sstevel@tonic-gate * This function reads the CIS on a card and follows any CISTPL_LONGLINK_A 1144*7c478bd9Sstevel@tonic-gate * and CISTPL_LONGLINK_C link tuples to create a single CIS chain. We 1145*7c478bd9Sstevel@tonic-gate * keep reading the CIS and following any CISTPL_LONGLINK_A and 1146*7c478bd9Sstevel@tonic-gate * CISTPL_LONGLINK_C tuples until we don't see anymore. If we see a 1147*7c478bd9Sstevel@tonic-gate * CISTPL_LONGLINK_MFC tuple, we return - the caller is responsible 1148*7c478bd9Sstevel@tonic-gate * for following CIS chains on a per-function level. 1149*7c478bd9Sstevel@tonic-gate * 1150*7c478bd9Sstevel@tonic-gate * The following parameters must be initialized by the caller: 1151*7c478bd9Sstevel@tonic-gate * 1152*7c478bd9Sstevel@tonic-gate * sp - pointer to a cs_socket_t structure that describes the socket 1153*7c478bd9Sstevel@tonic-gate * and card in this socket 1154*7c478bd9Sstevel@tonic-gate * cistpl_callout - pointer to a cistpl_callout_t array of structures 1155*7c478bd9Sstevel@tonic-gate * cisptr->flags - either CISTPLF_AM_SPACE or CISTPLF_CM_SPACE 1156*7c478bd9Sstevel@tonic-gate * cisptr->size - size of CIS window 1157*7c478bd9Sstevel@tonic-gate * cisptr->offset - offset in AM or CM space on card to start 1158*7c478bd9Sstevel@tonic-gate * reading tuples from 1159*7c478bd9Sstevel@tonic-gate * cis_info - pointer to a cis_info_t structure where this list will 1160*7c478bd9Sstevel@tonic-gate * be anchored on 1161*7c478bd9Sstevel@tonic-gate * cisparse - pointer to a cisparse_t structure where the last longlink 1162*7c478bd9Sstevel@tonic-gate * parsed tuple data will be returned 1163*7c478bd9Sstevel@tonic-gate * 1164*7c478bd9Sstevel@tonic-gate * To check the CISTPL_LINKTARGET tuple at the beginning of the first 1165*7c478bd9Sstevel@tonic-gate * CIS chain that this function encounters, set CW_CHECK_LINKTARGET 1166*7c478bd9Sstevel@tonic-gate * in cis_info->flags before calling this function. 1167*7c478bd9Sstevel@tonic-gate * 1168*7c478bd9Sstevel@tonic-gate * This function returns: 1169*7c478bd9Sstevel@tonic-gate * 1170*7c478bd9Sstevel@tonic-gate * CS_SUCCESS - if CIS chain was created sucessfully or there 1171*7c478bd9Sstevel@tonic-gate * were no tuples found on the first CIS chain 1172*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW or CS_GENERAL_FAILURE - if CIS window could 1173*7c478bd9Sstevel@tonic-gate * not be setup 1174*7c478bd9Sstevel@tonic-gate * CS_BAD_CIS - if error creating CIS chain 1175*7c478bd9Sstevel@tonic-gate * CS_BAD_OFFSET - if cis_list_lcreate tried to read past the 1176*7c478bd9Sstevel@tonic-gate * boundries of the allocated CIS window 1177*7c478bd9Sstevel@tonic-gate * 1178*7c478bd9Sstevel@tonic-gate * Note that if the first tuple of the target CIS chain is supposed 1179*7c478bd9Sstevel@tonic-gate * to contain a CISTPL_LINKTARGET and the target chain does not 1180*7c478bd9Sstevel@tonic-gate * contain that tuple (or that tuple is invalid in some way) and 1181*7c478bd9Sstevel@tonic-gate * the CW_RET_ON_LINKTARGET_ERROR flag is not set, we don't flag 1182*7c478bd9Sstevel@tonic-gate * this as an error, we just return. This is to handle the case 1183*7c478bd9Sstevel@tonic-gate * where the target chain is in uninitialized memory and will be 1184*7c478bd9Sstevel@tonic-gate * initialized later. 1185*7c478bd9Sstevel@tonic-gate * To return an error if an invalid CISTPL_LINKTARGET tuple is seen, 1186*7c478bd9Sstevel@tonic-gate * set the CW_RET_ON_LINKTARGET_ERROR flag in cis_info->flags 1187*7c478bd9Sstevel@tonic-gate * before calling this function. 1188*7c478bd9Sstevel@tonic-gate */ 1189*7c478bd9Sstevel@tonic-gate static int 1190*7c478bd9Sstevel@tonic-gate cis_create_cis_chain(cs_socket_t *sp, cistpl_callout_t *cistpl_callout, 1191*7c478bd9Sstevel@tonic-gate cisptr_t *cisptr, cis_info_t *cis_info, 1192*7c478bd9Sstevel@tonic-gate cisparse_t *cisparse) 1193*7c478bd9Sstevel@tonic-gate { 1194*7c478bd9Sstevel@tonic-gate cistpl_t *tps = NULL; 1195*7c478bd9Sstevel@tonic-gate uint32_t ret; 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate do { 1198*7c478bd9Sstevel@tonic-gate if ((ret = CIS_CARD_SERVICES(InitCISWindow, sp, &cisptr->offset, 1199*7c478bd9Sstevel@tonic-gate &cisptr->handle, cisptr->flags)) != CS_SUCCESS) 1200*7c478bd9Sstevel@tonic-gate return (ret); 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate /* 1203*7c478bd9Sstevel@tonic-gate * If we're pointing at a CIS chain that 1204*7c478bd9Sstevel@tonic-gate * is the target of a longlink tuple, 1205*7c478bd9Sstevel@tonic-gate * we need to validate the target chain 1206*7c478bd9Sstevel@tonic-gate * before we try to process it. If the 1207*7c478bd9Sstevel@tonic-gate * CISTPL_LINKTARGET tuple is invalid, 1208*7c478bd9Sstevel@tonic-gate * and the CW_RET_ON_LINKTARGET_ERROR 1209*7c478bd9Sstevel@tonic-gate * is not set, don't flag it as an error, 1210*7c478bd9Sstevel@tonic-gate * just return. 1211*7c478bd9Sstevel@tonic-gate */ 1212*7c478bd9Sstevel@tonic-gate if (cis_info->flags & CW_CHECK_LINKTARGET) { 1213*7c478bd9Sstevel@tonic-gate cis_info->flags &= ~CW_CHECK_LINKTARGET; 1214*7c478bd9Sstevel@tonic-gate if (cis_validate_longlink_acm(cisptr) != CISTPLF_NOERROR) { 1215*7c478bd9Sstevel@tonic-gate if (tps != NULL) 1216*7c478bd9Sstevel@tonic-gate cis_info->cis = tps; 1217*7c478bd9Sstevel@tonic-gate if (cis_info->flags & CW_RET_ON_LINKTARGET_ERROR) { 1218*7c478bd9Sstevel@tonic-gate cis_info->flags &= ~CW_RET_ON_LINKTARGET_ERROR; 1219*7c478bd9Sstevel@tonic-gate return (CS_BAD_CIS); 1220*7c478bd9Sstevel@tonic-gate } else { 1221*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1222*7c478bd9Sstevel@tonic-gate } /* CW_RET_ON_LINKTARGET_ERROR */ 1223*7c478bd9Sstevel@tonic-gate } /* cis_validate_longlink_acm */ 1224*7c478bd9Sstevel@tonic-gate } /* CW_CHECK_LINKTARGET */ 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate ret = cis_list_lcreate(cistpl_callout, cisptr, cis_info, cisparse, 1227*7c478bd9Sstevel@tonic-gate sp); 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate #if defined(CIS_DEBUG) 1230*7c478bd9Sstevel@tonic-gate if (cis_debug > 1) { 1231*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cis_create_cis_chain: ret=0x%x" 1232*7c478bd9Sstevel@tonic-gate " BAD_CIS_ADDR=0x%x CS_BAD_SOCKET=0x%x\n", 1233*7c478bd9Sstevel@tonic-gate ret, BAD_CIS_ADDR, CS_BAD_SOCKET); 1234*7c478bd9Sstevel@tonic-gate } 1235*7c478bd9Sstevel@tonic-gate #endif 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate 1238*7c478bd9Sstevel@tonic-gate if ((ret & HANDTPL_ERROR) || (ret == (uint32_t)BAD_CIS_ADDR)) { 1239*7c478bd9Sstevel@tonic-gate if (tps != NULL) 1240*7c478bd9Sstevel@tonic-gate cis_info->cis = tps; 1241*7c478bd9Sstevel@tonic-gate if (ret == (uint32_t)BAD_CIS_ADDR) 1242*7c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 1243*7c478bd9Sstevel@tonic-gate else 1244*7c478bd9Sstevel@tonic-gate return (CS_BAD_CIS); 1245*7c478bd9Sstevel@tonic-gate } 1246*7c478bd9Sstevel@tonic-gate 1247*7c478bd9Sstevel@tonic-gate /* 1248*7c478bd9Sstevel@tonic-gate * If we're creating the primary CIS chain 1249*7c478bd9Sstevel@tonic-gate * and we haven't seen any tuples, 1250*7c478bd9Sstevel@tonic-gate * then return CS_SUCCESS. The caller will 1251*7c478bd9Sstevel@tonic-gate * have to check cis_info->ntuples to find 1252*7c478bd9Sstevel@tonic-gate * out if any tuples were found. 1253*7c478bd9Sstevel@tonic-gate * If we're processing the target of a longlink 1254*7c478bd9Sstevel@tonic-gate * tuple, then by now we have already validated 1255*7c478bd9Sstevel@tonic-gate * the CISTPL_LINKTARGET tuple so that we 1256*7c478bd9Sstevel@tonic-gate * know we'll have at least one tuple in 1257*7c478bd9Sstevel@tonic-gate * our list. 1258*7c478bd9Sstevel@tonic-gate */ 1259*7c478bd9Sstevel@tonic-gate if (cis_info->ntuples == 0) 1260*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate /* 1263*7c478bd9Sstevel@tonic-gate * If we've just created a new list, we need to 1264*7c478bd9Sstevel@tonic-gate * save the pointer to the start of the list. 1265*7c478bd9Sstevel@tonic-gate */ 1266*7c478bd9Sstevel@tonic-gate if (tps == NULL) 1267*7c478bd9Sstevel@tonic-gate tps = cis_info->cis; 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate switch (cis_info->flags & CW_LONGLINK_FOUND) { 1270*7c478bd9Sstevel@tonic-gate cistpl_longlink_ac_t *cistpl_longlink_ac; 1271*7c478bd9Sstevel@tonic-gate 1272*7c478bd9Sstevel@tonic-gate case CW_LONGLINK_A_FOUND: 1273*7c478bd9Sstevel@tonic-gate cistpl_longlink_ac = (cistpl_longlink_ac_t *)cisparse; 1274*7c478bd9Sstevel@tonic-gate cisptr->flags &= ~(CISTPLF_SPACE_MASK | CISTPLF_FROM_MASK); 1275*7c478bd9Sstevel@tonic-gate cisptr->flags |= CISTPLF_AM_SPACE; 1276*7c478bd9Sstevel@tonic-gate /* 1277*7c478bd9Sstevel@tonic-gate * Multiply address by 2 since only 1278*7c478bd9Sstevel@tonic-gate * even bytes are counted in the CIS 1279*7c478bd9Sstevel@tonic-gate * when AM addresses are specified. 1280*7c478bd9Sstevel@tonic-gate */ 1281*7c478bd9Sstevel@tonic-gate cisptr->offset = cistpl_longlink_ac->tpll_addr * 2; 1282*7c478bd9Sstevel@tonic-gate cis_info->flags |= CW_CHECK_LINKTARGET; 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate /* 1285*7c478bd9Sstevel@tonic-gate * Point to the last tuple in the list. 1286*7c478bd9Sstevel@tonic-gate */ 1287*7c478bd9Sstevel@tonic-gate cis_info->cis = cis_get_ltuple(cis_info->cis, NULL, 1288*7c478bd9Sstevel@tonic-gate GET_LAST_LTUPLEF); 1289*7c478bd9Sstevel@tonic-gate break; 1290*7c478bd9Sstevel@tonic-gate case CW_LONGLINK_C_FOUND: 1291*7c478bd9Sstevel@tonic-gate cistpl_longlink_ac = (cistpl_longlink_ac_t *)cisparse; 1292*7c478bd9Sstevel@tonic-gate cisptr->flags &= ~(CISTPLF_SPACE_MASK | CISTPLF_FROM_MASK); 1293*7c478bd9Sstevel@tonic-gate cisptr->flags |= CISTPLF_CM_SPACE; 1294*7c478bd9Sstevel@tonic-gate cisptr->offset = cistpl_longlink_ac->tpll_addr; 1295*7c478bd9Sstevel@tonic-gate cis_info->flags |= CW_CHECK_LINKTARGET; 1296*7c478bd9Sstevel@tonic-gate 1297*7c478bd9Sstevel@tonic-gate /* 1298*7c478bd9Sstevel@tonic-gate * Point to the last tuple in the list. 1299*7c478bd9Sstevel@tonic-gate */ 1300*7c478bd9Sstevel@tonic-gate cis_info->cis = cis_get_ltuple(cis_info->cis, NULL, 1301*7c478bd9Sstevel@tonic-gate GET_LAST_LTUPLEF); 1302*7c478bd9Sstevel@tonic-gate break; 1303*7c478bd9Sstevel@tonic-gate case CW_LONGLINK_MFC_FOUND: 1304*7c478bd9Sstevel@tonic-gate break; 1305*7c478bd9Sstevel@tonic-gate default: 1306*7c478bd9Sstevel@tonic-gate break; 1307*7c478bd9Sstevel@tonic-gate } /* switch (cis_info->flags) */ 1308*7c478bd9Sstevel@tonic-gate 1309*7c478bd9Sstevel@tonic-gate } while (cis_info->flags & (CW_LONGLINK_A_FOUND | CW_LONGLINK_C_FOUND)); 1310*7c478bd9Sstevel@tonic-gate 1311*7c478bd9Sstevel@tonic-gate /* 1312*7c478bd9Sstevel@tonic-gate * If we needed to save a pointer to the start of the list because 1313*7c478bd9Sstevel@tonic-gate * we saw a longlink tuple, restore the list head pointer now. 1314*7c478bd9Sstevel@tonic-gate */ 1315*7c478bd9Sstevel@tonic-gate if (tps != NULL) 1316*7c478bd9Sstevel@tonic-gate cis_info->cis = tps; 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1319*7c478bd9Sstevel@tonic-gate } 1320*7c478bd9Sstevel@tonic-gate 1321*7c478bd9Sstevel@tonic-gate /* 1322*7c478bd9Sstevel@tonic-gate * cis_list_destroy - destroys the local CIS list 1323*7c478bd9Sstevel@tonic-gate */ 1324*7c478bd9Sstevel@tonic-gate uint32_t 1325*7c478bd9Sstevel@tonic-gate cis_list_destroy(cs_socket_t *sp) 1326*7c478bd9Sstevel@tonic-gate { 1327*7c478bd9Sstevel@tonic-gate int fn; 1328*7c478bd9Sstevel@tonic-gate 1329*7c478bd9Sstevel@tonic-gate /* 1330*7c478bd9Sstevel@tonic-gate * Destroy any CIS list that we may have created. It's OK to pass 1331*7c478bd9Sstevel@tonic-gate * a non-existant CIS list pointer to cis_list_ldestroy since 1332*7c478bd9Sstevel@tonic-gate * that function will not do anything if there is nothing in 1333*7c478bd9Sstevel@tonic-gate * the passed CIS list to cleanup. 1334*7c478bd9Sstevel@tonic-gate */ 1335*7c478bd9Sstevel@tonic-gate for (fn = 0; fn < CS_MAX_CIS; fn++) 1336*7c478bd9Sstevel@tonic-gate (void) cis_list_ldestroy(&sp->cis[fn].cis); 1337*7c478bd9Sstevel@tonic-gate 1338*7c478bd9Sstevel@tonic-gate /* 1339*7c478bd9Sstevel@tonic-gate * Clear out any remaining state. 1340*7c478bd9Sstevel@tonic-gate */ 1341*7c478bd9Sstevel@tonic-gate bzero((caddr_t)&sp->cis, ((sizeof (cis_info_t)) * CS_MAX_CIS)); 1342*7c478bd9Sstevel@tonic-gate sp->cis_flags = 0; 1343*7c478bd9Sstevel@tonic-gate sp->nfuncs = 0; 1344*7c478bd9Sstevel@tonic-gate 1345*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1346*7c478bd9Sstevel@tonic-gate } 1347*7c478bd9Sstevel@tonic-gate 1348*7c478bd9Sstevel@tonic-gate /* 1349*7c478bd9Sstevel@tonic-gate * cis_store_cis_addr - saves the current CIS address and space type 1350*7c478bd9Sstevel@tonic-gate * of the beginning of the tuple into the passed linked list element. 1351*7c478bd9Sstevel@tonic-gate * Note that this function will decrement the CIS address by two 1352*7c478bd9Sstevel@tonic-gate * elements prior to storing it to the linked list element to point 1353*7c478bd9Sstevel@tonic-gate * to the tuple type byte. 1354*7c478bd9Sstevel@tonic-gate * 1355*7c478bd9Sstevel@tonic-gate * This function also sets the following flags in tp->flags if they are set 1356*7c478bd9Sstevel@tonic-gate * in ptr->flags: 1357*7c478bd9Sstevel@tonic-gate * 1358*7c478bd9Sstevel@tonic-gate * CISTPLF_GLOBAL_CIS - tuple in global CIS 1359*7c478bd9Sstevel@tonic-gate * CISTPLF_MF_CIS - tuple in function-specific CIS 1360*7c478bd9Sstevel@tonic-gate */ 1361*7c478bd9Sstevel@tonic-gate static void 1362*7c478bd9Sstevel@tonic-gate cis_store_cis_addr(cistpl_t *tp, cisptr_t *ptr) 1363*7c478bd9Sstevel@tonic-gate { 1364*7c478bd9Sstevel@tonic-gate 1365*7c478bd9Sstevel@tonic-gate if (ptr->flags & CISTPLF_AM_SPACE) 1366*7c478bd9Sstevel@tonic-gate tp->offset = ptr->offset - 4; 1367*7c478bd9Sstevel@tonic-gate else 1368*7c478bd9Sstevel@tonic-gate tp->offset = ptr->offset - 2; 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate tp->flags &= ~(CISTPLF_SPACE_MASK | CISTPLF_FROM_MASK | 1371*7c478bd9Sstevel@tonic-gate CISTPLF_GLOBAL_CIS | CISTPLF_MF_CIS); 1372*7c478bd9Sstevel@tonic-gate tp->flags |= (ptr->flags & (CISTPLF_SPACE_MASK | 1373*7c478bd9Sstevel@tonic-gate CISTPLF_GLOBAL_CIS | CISTPLF_MF_CIS)); 1374*7c478bd9Sstevel@tonic-gate 1375*7c478bd9Sstevel@tonic-gate if (tp->flags & CISTPLF_AM_SPACE) 1376*7c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_FROM_AM; 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate if (tp->flags & CISTPLF_CM_SPACE) 1379*7c478bd9Sstevel@tonic-gate tp->flags |= CISTPLF_FROM_CM; 1380*7c478bd9Sstevel@tonic-gate } 1381