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