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