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
cis_get_short(cistpl_t * tp)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
cis_get_be_short(cistpl_t * tp)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
cis_get_int24(cistpl_t * tp)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
cis_get_long(cistpl_t * tp)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
cis_tuple_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg,cisdata_t subtype)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
cis_no_tuple_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)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
cis_unknown_tuple_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)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
cistpl_vers_1_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)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
cistpl_config_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)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
cistpl_device_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)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
cistpl_cftable_handler(cistpl_callout_t * co,cistpl_t * tp,uint32_t flags,void * arg)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 }
2195