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