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