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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/file.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/modctl.h>
34 #include <sys/sunndi.h>
35 #include <sys/ddi_impldefs.h>
36 #include <sys/obpdefs.h>
37 #include <sys/cmn_err.h>
38 #include <sys/errno.h>
39 #include <sys/debug.h>
40 #include <sys/sysmacros.h>
41 #include <sys/autoconf.h>
42 #include <sys/stat.h>
43 #include <sys/kmem.h>
44 #include <sys/sgsbbc_mailbox.h>
45 #include <sys/sgfrutree.h>
46 #include <sys/sgfru_priv.h>
47 #include <sys/sgfru_mbox.h>
48
49 /*
50 * This driver implements the ioctls for the serengeti frutree picl plugin
51 * and the serengeti fruaccess library. These are all private,
52 * platform-dependent interfaces.
53 */
54
55 /* Global Variables */
56
57 #ifdef DEBUG
58 uint_t sgfru_debug = 0;
59 #endif /* DEBUG */
60
61 /* Opaque state structure pointer */
62 static void *sgfru_statep; /* sgfru soft state hook */
63
64 /*
65 * the maximum amount of time this driver is prepared to wait for the mailbox
66 * to reply before it decides to timeout.
67 */
68 int sgfru_mbox_wait = SGFRU_DEFAULT_MAX_MBOX_WAIT_TIME;
69
70 /* Module Variables */
71
72 /*
73 * Driver entry points. These are located in sgfru.c so as to
74 * not cause a warning for the sgfru adb macro.
75 */
76 static struct cb_ops sgfru_cb_ops = {
77 sgfru_open, /* open */
78 sgfru_close, /* close */
79 nulldev, /* strategy */
80 nulldev, /* print */
81 nulldev, /* dump */
82 nulldev, /* read */
83 nulldev, /* write */
84 sgfru_ioctl, /* ioctl */
85 nulldev, /* devmap */
86 nulldev, /* mmap */
87 nulldev, /* segmap */
88 nochpoll, /* poll */
89 ddi_prop_op, /* cb_prop_op */
90 NULL, /* streamtab */
91 D_NEW | D_MP /* Driver compatibility flag */
92 };
93
94 static struct dev_ops sgfru_ops = {
95 DEVO_REV, /* devo_rev, */
96 0, /* refcnt */
97 ddi_getinfo_1to1, /* info */
98 nulldev, /* identify */
99 nulldev, /* probe */
100 sgfru_attach, /* attach */
101 sgfru_detach, /* detach */
102 nodev, /* reset */
103 &sgfru_cb_ops, /* driver operations */
104 (struct bus_ops *)0, /* bus operations */
105 nulldev, /* power */
106 ddi_quiesce_not_needed, /* quiesce */
107 };
108
109 /*
110 * Loadable module support. This is located in sgfru.c so as to
111 * pick up the 1.8 version of sgfru.c.
112 */
113 extern struct mod_ops mod_driverops;
114
115 static struct modldrv modldrv = {
116 &mod_driverops, /* Type of module. This one is a pseudo driver */
117 "FRU Driver",
118 &sgfru_ops, /* driver ops */
119 };
120
121 static struct modlinkage modlinkage = {
122 MODREV_1,
123 (void *)&modldrv,
124 NULL
125 };
126
127 int
_init(void)128 _init(void)
129 {
130 int error = 0;
131
132 /* Allocate the soft state info and add the module. */
133 if ((error = ddi_soft_state_init(&sgfru_statep,
134 sizeof (sgfru_soft_state_t), 1)) == 0 &&
135 (error = mod_install(&modlinkage)) != 0) {
136 ddi_soft_state_fini(&sgfru_statep);
137 }
138 return (error);
139 }
140
141 int
_fini(void)142 _fini(void)
143 {
144 int error = 0;
145
146 /* Remove the module and free the soft state info. */
147 if ((error = mod_remove(&modlinkage)) == 0) {
148 ddi_soft_state_fini(&sgfru_statep);
149 }
150 return (error);
151 }
152
153 int
_info(struct modinfo * modinfop)154 _info(struct modinfo *modinfop)
155 {
156 return (mod_info(&modlinkage, modinfop));
157 }
158
159 static int
sgfru_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)160 sgfru_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
161 {
162 sgfru_soft_state_t *softsp;
163 int instance;
164 int error;
165 static fn_t f = "sgfru_attach";
166
167 switch (cmd) {
168 case DDI_ATTACH:
169 instance = ddi_get_instance(dip);
170
171 error = ddi_soft_state_zalloc(sgfru_statep, instance);
172 if (error != DDI_SUCCESS) {
173 cmn_err(CE_WARN, "sgfru:%s: cannot allocate fru state "
174 "for inst %d.", f, instance);
175 return (DDI_FAILURE);
176 }
177 softsp = ddi_get_soft_state(sgfru_statep, instance);
178 if (softsp == NULL) {
179 ddi_soft_state_free(sgfru_statep, instance);
180 cmn_err(CE_WARN, "sgfru:%s: could not get state "
181 "structure for inst %d.", f, instance);
182 return (DDI_FAILURE);
183 }
184 softsp->fru_dip = dip;
185 softsp->fru_pdip = ddi_get_parent(softsp->fru_dip);
186 softsp->instance = instance;
187
188 error = ddi_create_minor_node(dip, SGFRU_DRV_NAME, S_IFCHR,
189 instance, DDI_PSEUDO, 0);
190 if (error == DDI_FAILURE) {
191 ddi_soft_state_free(sgfru_statep, instance);
192 return (DDI_FAILURE);
193 }
194
195 ddi_report_dev(dip);
196
197 return (DDI_SUCCESS);
198
199 case DDI_RESUME:
200 return (DDI_SUCCESS);
201
202 default:
203 return (DDI_FAILURE);
204 }
205 }
206
207 static int
sgfru_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)208 sgfru_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
209 {
210 int instance;
211 sgfru_soft_state_t *softsp;
212 static fn_t f = "sgfru_detach";
213
214 instance = ddi_get_instance(dip);
215
216 softsp = ddi_get_soft_state(sgfru_statep, instance);
217 if (softsp == NULL) {
218 cmn_err(CE_WARN, "sgfru:%s: could not get state "
219 "structure for inst %d.", f, instance);
220 return (DDI_FAILURE);
221 }
222
223 switch (cmd) {
224 case DDI_DETACH:
225 ddi_soft_state_free(sgfru_statep, instance);
226 ddi_remove_minor_node(dip, NULL);
227 return (DDI_SUCCESS);
228
229 case DDI_SUSPEND:
230 return (DDI_SUCCESS);
231
232 default:
233 return (DDI_FAILURE);
234 }
235 }
236
237 /*ARGSUSED*/
238 static int
sgfru_open(dev_t * dev_p,int flag,int otyp,cred_t * cred_p)239 sgfru_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
240 {
241 int error = 0;
242 int instance = getminor(*dev_p);
243 sgfru_soft_state_t *softsp;
244 static fn_t f = "sgfru_open";
245
246 if ((error = drv_priv(cred_p)) != 0) {
247 cmn_err(CE_WARN, "sgfru:%s: inst %d drv_priv failed",
248 f, instance);
249 return (error);
250 }
251 softsp = (sgfru_soft_state_t *)ddi_get_soft_state(sgfru_statep,
252 instance);
253 if (softsp == (sgfru_soft_state_t *)NULL) {
254 cmn_err(CE_WARN, "sgfru:%s: inst %d ddi_get_soft_state failed",
255 f, instance);
256 return (ENXIO);
257 }
258 return (error);
259 }
260
261 /*ARGSUSED*/
262 static int
sgfru_close(dev_t dev,int flag,int otyp,cred_t * cred_p)263 sgfru_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
264 {
265 int instance = getminor(dev);
266 sgfru_soft_state_t *softsp = (sgfru_soft_state_t *)
267 ddi_get_soft_state(sgfru_statep, instance);
268
269 if (softsp == (sgfru_soft_state_t *)NULL)
270 return (ENXIO);
271 return (DDI_SUCCESS);
272 }
273
274 /*
275 * This function disperses the ioctls from the serengeti libpiclfruhier plugin
276 * and the serengeti libpiclfruaccess library to the appropriate sub-functions.
277 */
278 /*ARGSUSED*/
279 static int
sgfru_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cred_p,int * rval_p)280 sgfru_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
281 int *rval_p)
282 {
283 sgfru_soft_state_t *softsp;
284 int instance = getminor(dev);
285 sgfru_init_arg_t init_arg;
286 int32_t ret = 0;
287 static fn_t f = "sgfru_ioctl";
288
289
290 softsp = ddi_get_soft_state(sgfru_statep, instance);
291 if (softsp == NULL) {
292 return (ENXIO);
293 }
294 PR_STATE("sgfru:%s: dev %lx cmd %d, instance %d\n",
295 f, dev, cmd, instance);
296
297 init_arg.dev = dev;
298 init_arg.cmd = cmd;
299 init_arg.mode = mode;
300 init_arg.argp = arg;
301
302 switch (cmd) {
303
304 case SGFRU_GETSECTIONS:
305 ret = sgfru_getsections(&init_arg);
306 break;
307
308 case SGFRU_GETSEGMENTS:
309 ret = sgfru_getsegments(&init_arg);
310 break;
311
312 case SGFRU_ADDSEGMENT:
313 ret = sgfru_addsegment(&init_arg);
314 break;
315
316 case SGFRU_READRAWSEGMENT:
317 ret = sgfru_readsegment(&init_arg);
318 break;
319
320 case SGFRU_WRITERAWSEGMENT:
321 ret = sgfru_writesegment(&init_arg);
322 break;
323
324 case SGFRU_GETPACKETS:
325 ret = sgfru_getpackets(&init_arg);
326 break;
327
328 case SGFRU_APPENDPACKET:
329 ret = sgfru_appendpacket(&init_arg);
330 break;
331
332 case SGFRU_GETPAYLOAD:
333 ret = sgfru_getpayload(&init_arg);
334 break;
335
336 case SGFRU_UPDATEPAYLOAD:
337 ret = sgfru_updatepayload(&init_arg);
338 break;
339
340 case SGFRU_GETNUMSECTIONS:
341 case SGFRU_GETNUMSEGMENTS:
342 case SGFRU_GETNUMPACKETS:
343 ret = sgfru_getnum(&init_arg);
344 break;
345
346 case SGFRU_DELETESEGMENT:
347 case SGFRU_DELETEPACKET:
348 ret = sgfru_delete(&init_arg);
349 break;
350
351 case SGFRU_GETCHILDLIST:
352 ret = sgfru_getchildlist(&init_arg);
353 break;
354
355 case SGFRU_GETCHILDHANDLES:
356 ret = sgfru_getchildhandles(&init_arg);
357 break;
358
359 case SGFRU_GETNODEINFO:
360 ret = sgfru_getnodeinfo(&init_arg);
361 break;
362
363 default:
364 ret = EINVAL;
365 break;
366 }
367
368 return (ret);
369 }
370
371 /*
372 * Used for private SGFRU_GETCHILDLIST ioctl.
373 */
374 static int
sgfru_getchildlist(const sgfru_init_arg_t * iargp)375 sgfru_getchildlist(const sgfru_init_arg_t *iargp)
376 {
377 int32_t ret;
378 caddr_t datap;
379 size_t ssize, size;
380 frup_info_t clist;
381 fru_cnt_t max_cnt;
382 node_t *clistp;
383 static fn_t f = "sgfru_getchildlist";
384
385 /* copyin child_info_t aka frup_info_t */
386 if (sgfru_copyin_frup(iargp, &clist) != 0) {
387 return (EFAULT);
388 }
389
390 /* check on kmem_alloc space requirements */
391 max_cnt = clist.fru_cnt;
392 if ((max_cnt <= 0) || (max_cnt > MAX_HANDLES)) {
393 return (EINVAL);
394 }
395
396 /* allocate buffer for unpadded fru_info_t + node_t's */
397 size = (size_t)(FRU_INFO_SIZE + (max_cnt * NODE_SIZE));
398 datap = kmem_zalloc(size, KM_SLEEP);
399 PR_NODE("sgfru:%s: FRU_INFO_SIZE %lu NODE_SIZE %lu size %lu\n",
400 f, FRU_INFO_SIZE, NODE_SIZE, size);
401 PR_NODE("sgfru:%s: handle %lx cnt %d buffer 0x%p\n", f,
402 clist.fru_hdl, clist.fru_cnt, clist.frus);
403
404 /* call mailbox */
405 if ((ret = sgfru_mbox(iargp->cmd, datap, size, &clist.fru_info))
406 != 0) {
407 kmem_free(datap, size);
408 return (ret);
409 }
410
411 /* allocate buffer for padded node_t's */
412 ssize = (size_t)(max_cnt * sizeof (node_t));
413 clistp = (node_t *)kmem_zalloc(ssize, KM_SLEEP);
414
415 /* translate unpadded to padded fru_info_t + node_t's */
416 if ((ret = sgfru_node_pad(datap, max_cnt, &clist.fru_info, clistp))
417 != 0) {
418 kmem_free(datap, size);
419 kmem_free(clistp, ssize);
420 return (ret);
421 }
422 /* free node_t buffer */
423 kmem_free(datap, size);
424
425 /* copy out fru_info_t */
426 if (sgfru_copyout_fru(iargp, &clist.fru_info) != 0) {
427 kmem_free(clistp, ssize);
428 return (EFAULT);
429 }
430 /* copyout node_t's */
431 if (sgfru_copyout_nodes(iargp, &clist, clistp) != 0) {
432 kmem_free(clistp, ssize);
433 return (EFAULT);
434 }
435 /* free node_t buffer */
436 kmem_free(clistp, ssize);
437
438 return (ret);
439 }
440
441 /*
442 * Used for private SGFRU_GETCHILDHANDLES ioctl.
443 */
444 static int
sgfru_getchildhandles(const sgfru_init_arg_t * iargp)445 sgfru_getchildhandles(const sgfru_init_arg_t *iargp)
446 {
447 int32_t ret;
448 size_t size;
449 caddr_t datap, tdatap;
450 frup_info_t hdls;
451 fru_info_t hinfo;
452 fru_cnt_t max_cnt;
453 static fn_t f = "sgfru_getchildhandles";
454
455 /* copyin handles_t aka frup_info_t */
456 if (sgfru_copyin_frup(iargp, &hdls) != 0) {
457 return (EFAULT);
458 }
459 PR_HANDLE("sgfru:%s: handle %lx\n", f, hdls.fru_hdl);
460
461 /* check on kmem_alloc space requirements */
462 max_cnt = hdls.fru_cnt;
463 if ((max_cnt <= 0) || (max_cnt > MAX_HANDLES)) {
464 return (EINVAL);
465 }
466
467 /* allocate buffer for child fru_hdl_t's */
468 size = (size_t)(FRU_INFO_SIZE + (max_cnt * FRU_HDL_SIZE));
469 datap = kmem_zalloc(size, KM_SLEEP);
470
471 /* call mailbox */
472 ret = sgfru_mbox(iargp->cmd, datap, size, &hdls.fru_info);
473 if (ret != 0) {
474 kmem_free(datap, size);
475 return (ret);
476 }
477
478 /* translate unpadded to fru_info_t */
479 tdatap = sgfru_fru_pad(datap, &hinfo);
480
481 /* copyout actual fru_cnt */
482 if (sgfru_copyout_fru(iargp, &hinfo) != 0) {
483 kmem_free(datap, size);
484 return (EFAULT);
485 }
486 PR_HANDLE("sgfru:%s: count %x\n", f, hinfo.cnt);
487
488 /* copyout fru_hdl_t's */
489 if (sgfru_copyout_handles(iargp, &hdls, (fru_hdl_t *)tdatap) != 0) {
490 kmem_free(datap, size);
491 return (EFAULT);
492 }
493
494 /* free datap buffer */
495 kmem_free(datap, size);
496
497 return (ret);
498 }
499
500 /*
501 * Used for private SGFRU_GETNODEINFO ioctl.
502 */
503 static int
sgfru_getnodeinfo(const sgfru_init_arg_t * iargp)504 sgfru_getnodeinfo(const sgfru_init_arg_t *iargp)
505 {
506 int32_t ret;
507 caddr_t datap;
508 size_t size;
509 frup_info_t nodeinfo;
510 node_t node;
511 static fn_t f = "sgfru_getnodeinfo";
512
513 /* copyin node_info_t aka frup_info_t */
514 if (sgfru_copyin_frup(iargp, &nodeinfo) != 0) {
515 return (EFAULT);
516 }
517
518 /* allocate unpadded buffer for node_t */
519 size = (size_t)(NODE_SIZE);
520 datap = kmem_zalloc(size, KM_SLEEP);
521
522 PR_NODE("sgfru:%s: handle %lx size 0x%lx\n", f, nodeinfo.fru_hdl, size);
523 /* call mailbox */
524 ret = sgfru_mbox(iargp->cmd, datap, size, &nodeinfo.fru_info);
525 if (ret != 0) {
526 kmem_free(datap, size);
527 return (ret);
528 }
529
530 /* translate unpadded to padded node_t */
531 if ((ret = sgfru_node_pad(datap, 0, NULL, &node))
532 != 0) {
533 kmem_free(datap, size);
534 return (ret);
535 }
536
537 /* free node_t buffer */
538 kmem_free(datap, size);
539
540 /* copyout node_t */
541 if (sgfru_copyout_nodes(iargp, &nodeinfo, &node) != 0) {
542 return (EFAULT);
543 }
544 PR_NODE("sgfru:%s: handle %lx nodename %s has_children %d class %d\n",
545 f, node.handle, node.nodename, node.has_children, node.class);
546
547 return (ret);
548 }
549
550 /*
551 * Used for fru_get_sections().
552 */
553 static int
sgfru_getsections(const sgfru_init_arg_t * iargp)554 sgfru_getsections(const sgfru_init_arg_t *iargp)
555 {
556 int32_t ret;
557 caddr_t datap;
558 size_t ssize, size;
559 frup_info_t sects;
560 fru_cnt_t max_cnt;
561 section_t *sectp;
562
563 /* copyin sections_t aka frup_info_t */
564 if (sgfru_copyin_frup(iargp, §s) != 0) {
565 return (EFAULT);
566 }
567 /* check on kmem_alloc space requirements */
568 max_cnt = sects.fru_cnt;
569 if ((max_cnt <= 0) || (max_cnt > MAX_SECTIONS)) {
570 return (EINVAL);
571 }
572
573 /* allocate buffer for unpadded fru_info_t + section_t's */
574 size = (size_t)(FRU_INFO_SIZE + (max_cnt * SECTION_SIZE));
575 datap = kmem_zalloc(size, KM_SLEEP);
576
577 /* call mailbox */
578 if ((ret = sgfru_mbox(iargp->cmd, datap, size, §s.fru_info))
579 != 0) {
580 kmem_free(datap, size);
581 return (ret);
582 }
583
584 /* allocate buffer for padded section_t's */
585 ssize = (size_t)(max_cnt * sizeof (section_t));
586 sectp = (section_t *)kmem_zalloc(ssize, KM_SLEEP);
587
588 /* translate unpadded to padded fru_info_t + section_t's */
589 if ((ret = sgfru_section_pad(datap, max_cnt, §s.fru_info, sectp))
590 != 0) {
591 kmem_free(datap, size);
592 kmem_free(sectp, ssize);
593 return (ret);
594 }
595 /* free section_t buffer */
596 kmem_free(datap, size);
597
598 /* copy out fru_info_t */
599 if (sgfru_copyout_fru(iargp, §s.fru_info) != 0) {
600 kmem_free(sectp, ssize);
601 return (EFAULT);
602 }
603 /* copyout section_t's */
604 if (sgfru_copyout_sections(iargp, §s, sectp) != 0) {
605 kmem_free(sectp, ssize);
606 return (EFAULT);
607 }
608 /* free section_t buffer */
609 kmem_free(sectp, ssize);
610
611 return (ret);
612 }
613
614 /*
615 * Used for fru_get_segments().
616 */
617 static int
sgfru_getsegments(const sgfru_init_arg_t * iargp)618 sgfru_getsegments(const sgfru_init_arg_t *iargp)
619 {
620 int32_t ret;
621 caddr_t datap;
622 size_t ssize, size;
623 frup_info_t segs;
624 fru_cnt_t max_cnt;
625 segment_t *segp;
626
627 /* copyin frup_info_t */
628 if (sgfru_copyin_frup(iargp, &segs) != 0) {
629 return (EFAULT);
630 }
631 /* check on kmem_alloc space requirements */
632 max_cnt = segs.fru_cnt;
633 if ((max_cnt <= 0) || (max_cnt > MAX_SEGMENTS)) {
634 return (EINVAL);
635 }
636
637 /* allocate unpadded buffer for fru_info_t + segment_t's */
638 size = (size_t)(FRU_INFO_SIZE + (max_cnt * SEGMENT_SIZE));
639 datap = kmem_zalloc(size, KM_SLEEP);
640
641 /* call mailbox */
642 if ((ret = sgfru_mbox(iargp->cmd, datap, size, &segs.fru_info)) != 0) {
643 kmem_free(datap, size);
644 return (ret);
645 }
646
647 /* allocate buffer for padded segment_t's */
648 ssize = (size_t)(max_cnt * sizeof (segment_t));
649 segp = (segment_t *)kmem_zalloc(ssize, KM_SLEEP);
650
651 /* translate unpadded to padded fru_info_t + segment_t's */
652 if ((ret = sgfru_segment_pad(datap, max_cnt, &segs.fru_info, segp))
653 != 0) {
654 kmem_free(datap, size);
655 kmem_free(segp, ssize);
656 return (ret);
657 }
658 /* free segment_t buffer */
659 kmem_free(datap, size);
660
661 /* copy out fru_info_t */
662 if (sgfru_copyout_fru(iargp, &segs.fru_info) != 0) {
663 kmem_free(segp, ssize);
664 return (EFAULT);
665 }
666 /* copyout segment_t's */
667 if (sgfru_copyout_segments(iargp, &segs, segp) != 0) {
668 kmem_free(segp, ssize);
669 return (EFAULT);
670 }
671 /* free segment_t buffer */
672 kmem_free(segp, ssize);
673
674 return (ret);
675 }
676
677 static int
sgfru_addsegment(const sgfru_init_arg_t * iargp)678 sgfru_addsegment(const sgfru_init_arg_t *iargp)
679 {
680 int32_t ret;
681 caddr_t datap;
682 size_t size;
683 frup_info_t seg;
684 segment_t segment;
685 fru_hdl_t *hdlp;
686 static fn_t f = "sgfru_addsegment";
687
688 /* copyin frup_info_t */
689 if (sgfru_copyin_frup(iargp, &seg) != 0) {
690 return (EFAULT);
691 }
692 /* copyin segment_t */
693 if (sgfru_copyin_segment(iargp, &seg, &segment) != 0) {
694 return (EFAULT);
695 }
696 PR_SEGMENT("sgfru:%s: handle %lx, max cnt %d\n",
697 f, seg.fru_hdl, seg.fru_cnt);
698 PR_SEGMENT("sgfru:%s: handle %lx, name %s, descriptor 0x%x, "
699 "offset 0x%x, length 0x%x\n", f, segment.handle, segment.name,
700 segment.descriptor, segment.offset, segment.length);
701
702 /* allocate buffer for unpadded section_hdl_t + segment_t */
703 size = (size_t)(SECTION_HDL_SIZE + SEGMENT_SIZE);
704 datap = kmem_zalloc(size, KM_SLEEP);
705 /* translate padded to unpadded section_hdl_t + segment_t */
706 sgfru_segment_unpad(&seg.fru_info, &segment, datap);
707
708 /* call mailbox */
709 ret = sgfru_mbox(iargp->cmd, datap, size, &seg.fru_info);
710 if (ret != 0) {
711 kmem_free(datap, size);
712 return (ret);
713 }
714
715 /* copyout updated section_hdl_t */
716 hdlp = (fru_hdl_t *)(datap + sizeof (fru_hdl_t));
717 if (sgfru_copyout_handle(iargp, (void *)iargp->argp, hdlp) != 0) {
718 kmem_free(datap, size);
719 return (EFAULT);
720 }
721 /* copyout new segment_hdl_t */
722 if (sgfru_copyout_handle(iargp, seg.frus, --hdlp) != 0) {
723 kmem_free(datap, size);
724 return (EFAULT);
725 }
726 /* free segment_t buffer */
727 kmem_free(datap, size);
728
729 return (ret);
730 }
731
732 /*
733 * Used for fru_read_segment().
734 */
735 static int
sgfru_readsegment(const sgfru_init_arg_t * iargp)736 sgfru_readsegment(const sgfru_init_arg_t *iargp)
737 {
738 int32_t ret;
739 caddr_t datap, tdatap;
740 size_t size;
741 frup_info_t segs;
742 fru_info_t sinfo;
743 fru_cnt_t max_cnt;
744 static fn_t f = "sgfru_readsegment";
745
746 /* copyin one segments_t aka frup_info_t */
747 if (sgfru_copyin_frup(iargp, &segs) != 0) {
748 return (EFAULT);
749 }
750 /* check on kmem_alloc space requirements */
751 max_cnt = segs.fru_cnt;
752 if ((max_cnt <= 0) || (max_cnt > MAX_SEGMENTSIZE)) {
753 return (EINVAL);
754 }
755 PR_SEGMENT("sgfru:%s: handle %lx, max cnt %d\n",
756 f, segs.fru_hdl, segs.fru_cnt);
757
758 /* allocate unpadded buffer for raw data */
759 size = (size_t)(FRU_INFO_SIZE + max_cnt);
760 datap = kmem_zalloc(size, KM_SLEEP);
761
762 /* call mailbox */
763 if ((ret = sgfru_mbox(iargp->cmd, datap, size, &segs.fru_info)) != 0) {
764 kmem_free(datap, size);
765 return (ret);
766 }
767
768 /* translate unpadded to padded fru_info_t */
769 tdatap = sgfru_fru_pad(datap, &sinfo);
770 PR_SEGMENT("sgfru:%s: handle %lx, actual cnt %d\n",
771 f, sinfo.hdl, sinfo.cnt);
772
773 /* copyout actual fru_cnt */
774 if (sgfru_copyout_fru(iargp, &sinfo) != 0) {
775 kmem_free(datap, size);
776 return (EFAULT);
777 }
778 /* copyout raw segment data */
779 if (sgfru_copyout_buffer(iargp, &segs, tdatap) != 0) {
780 kmem_free(datap, size);
781 return (EFAULT);
782 }
783 /* free buffer */
784 kmem_free(datap, size);
785
786 return (ret);
787 }
788
789 /*
790 * Used for fru_write_segment().
791 */
792 static int
sgfru_writesegment(const sgfru_init_arg_t * iargp)793 sgfru_writesegment(const sgfru_init_arg_t *iargp)
794 {
795 int32_t ret;
796 caddr_t datap, tdatap;
797 size_t size;
798 frup_info_t segs;
799 fru_cnt_t max_cnt;
800 static fn_t f = "sgfru_writesegment";
801
802 /* copyin frup_info_t */
803 if (sgfru_copyin_frup(iargp, &segs) != 0) {
804 return (EFAULT);
805 }
806 /* check on kmem_alloc space requirements */
807 max_cnt = segs.fru_cnt;
808 if ((max_cnt <= 0) || (max_cnt > MAX_SEGMENTSIZE)) {
809 return (EINVAL);
810 }
811 PR_SEGMENT("sgfru:%s: handle %lx, max cnt %d\n",
812 f, segs.fru_hdl, segs.fru_cnt);
813
814 /* allocate unpadded buffer for fru_info_t + raw data */
815 size = (size_t)(FRU_INFO_SIZE + max_cnt);
816 datap = kmem_zalloc(size, KM_SLEEP);
817
818 /* translate padded to unpadded fru_info_t */
819 tdatap = sgfru_fru_unpad(&segs.fru_info, datap);
820
821 /* copyin raw segment data */
822 if (sgfru_copyin_buffer(iargp, segs.frus, max_cnt, tdatap) != 0) {
823 kmem_free(datap, size);
824 return (EFAULT);
825 }
826
827 /* call mailbox */
828 if ((ret = sgfru_mbox(iargp->cmd, datap, size, &segs.fru_info)) != 0) {
829 kmem_free(datap, size);
830 return (ret);
831 }
832 /* free buffer */
833 kmem_free(datap, size);
834
835 PR_SEGMENT("sgfru:%s: handle %lx, actual cnt %d\n",
836 f, segs.fru_hdl, segs.fru_cnt);
837 /* copyout updated segment handle and actual fru_cnt */
838 if (sgfru_copyout_fru(iargp, &segs.fru_info) != 0) {
839 return (EFAULT);
840 }
841
842 return (ret);
843 }
844
845 /*
846 * Used for fru_get_packets().
847 */
848 static int
sgfru_getpackets(const sgfru_init_arg_t * iargp)849 sgfru_getpackets(const sgfru_init_arg_t *iargp)
850 {
851 int32_t ret;
852 caddr_t datap;
853 size_t ssize, size;
854 frup_info_t packs;
855 fru_cnt_t max_cnt;
856 packet_t *packp;
857
858 /* copyin packets_t aka frup_info_t */
859 if (sgfru_copyin_frup(iargp, &packs) != 0) {
860 return (EFAULT);
861 }
862 /* check on kmem_alloc space requirements */
863 max_cnt = packs.fru_cnt;
864 if ((max_cnt <= 0) || (max_cnt > MAX_PACKETS)) {
865 return (EINVAL);
866 }
867
868 /* allocate buffer for unpadded fru_info_t + packet_t's */
869 size = (size_t)(FRU_INFO_SIZE + (max_cnt * PACKET_SIZE));
870 datap = kmem_zalloc(size, KM_SLEEP);
871
872 /* call mailbox */
873 if ((ret = sgfru_mbox(iargp->cmd, datap, size, &packs.fru_info))
874 != 0) {
875 kmem_free(datap, size);
876 return (ret);
877 }
878
879 /* allocate buffer for padded packet_t's */
880 ssize = (size_t)(max_cnt * sizeof (packet_t));
881 packp = (packet_t *)kmem_zalloc(ssize, KM_SLEEP);
882
883 /* translate unpadded to padded fru_info_t + packet_t's */
884 if ((ret = sgfru_packet_pad(datap, max_cnt, &packs.fru_info, packp))
885 != 0) {
886 kmem_free(datap, size);
887 kmem_free(packp, ssize);
888 return (ret);
889 }
890 /* free packet_t buffer */
891 kmem_free(datap, size);
892
893 /* copy out fru_info_t */
894 if (sgfru_copyout_fru(iargp, &packs.fru_info) != 0) {
895 kmem_free(packp, ssize);
896 return (EFAULT);
897 }
898 /* copyout packet_t's */
899 if (sgfru_copyout_packets(iargp, &packs, packp) != 0) {
900 kmem_free(packp, ssize);
901 return (EFAULT);
902 }
903 /* free packet_t buffer */
904 kmem_free(packp, ssize);
905
906 return (ret);
907 }
908
909 /*
910 * Used for fru_append_packet().
911 */
912 static int
sgfru_appendpacket(const sgfru_init_arg_t * iargp)913 sgfru_appendpacket(const sgfru_init_arg_t *iargp)
914 {
915 int32_t ret = 0;
916 caddr_t datap, tdatap;
917 size_t size;
918 append_info_t append;
919 fru_cnt_t max_cnt;
920 fru_hdl_t *hdlp;
921 caddr_t addr;
922
923 /* copyin append_info_t */
924 if (sgfru_copyin_append(iargp, &append) != 0) {
925 return (EFAULT);
926 }
927 /* check on kmem_alloc space requirements */
928 max_cnt = append.payload_cnt;
929 if ((max_cnt <= 0) || (max_cnt > MAX_PAYLOADSIZE)) {
930 return (EINVAL);
931 }
932
933 /* allocate buffer for unpadded fru_info_t + packet_t + payload */
934 size = (size_t)(FRU_INFO_SIZE + PACKET_SIZE + max_cnt);
935 datap = kmem_zalloc(size, KM_SLEEP);
936 /* translate padded to unpadded fru_info_t plus packet_t */
937 tdatap = sgfru_packet_unpad(&append.payload.fru_info, &append.packet,
938 datap);
939
940 /* copyin payload to the end of the unpadded buffer */
941 if (sgfru_copyin_buffer(iargp, append.payload_data, append.payload_cnt,
942 tdatap) != 0) {
943 kmem_free(datap, size);
944 return (EFAULT);
945 }
946
947 /* call mailbox */
948 if ((ret = sgfru_mbox(iargp->cmd, datap, size,
949 &append.payload.fru_info)) != 0) {
950 kmem_free(datap, size);
951 return (ret);
952 }
953
954 /* copyout new packet_hdl_t */
955 hdlp = (fru_hdl_t *)datap;
956 if (sgfru_copyout_handle(iargp, (void *)iargp->argp, hdlp) != 0) {
957 kmem_free(datap, size);
958 return (EFAULT);
959 }
960 /* copyout updated segment_hdl_t */
961 addr = (caddr_t)(iargp->argp + sizeof (packet_t));
962 if (sgfru_copyout_handle(iargp, addr, ++hdlp) != 0) {
963 kmem_free(datap, size);
964 return (EFAULT);
965 }
966
967 /* free buffer */
968 kmem_free(datap, size);
969
970 return (ret);
971 }
972
973 /*
974 * Used for fru_get_payload().
975 */
976 static int
sgfru_getpayload(const sgfru_init_arg_t * iargp)977 sgfru_getpayload(const sgfru_init_arg_t *iargp)
978 {
979 int32_t ret;
980 caddr_t datap, tdatap;
981 size_t size;
982 frup_info_t payld;
983 fru_info_t pinfo;
984 fru_cnt_t max_cnt;
985 static fn_t f = "sgfru_getpayload";
986
987 /* copyin payload_t aka frup_info_t */
988 if (sgfru_copyin_frup(iargp, &payld) != 0) {
989 return (EFAULT);
990 }
991 PR_PAYLOAD("sgfru:%s: handle %lx, max cnt %d\n",
992 f, payld.fru_hdl, payld.fru_cnt);
993
994 /* check on kmem_alloc space requirements */
995 max_cnt = payld.fru_cnt;
996 if ((max_cnt <= 0) || (max_cnt > MAX_PAYLOADSIZE)) {
997 return (EINVAL);
998 }
999
1000 /* allocate buffer for fru_info_t + payload */
1001 size = (size_t)(FRU_INFO_SIZE + max_cnt);
1002 datap = kmem_zalloc(size, KM_SLEEP);
1003
1004 /* call mailbox */
1005 if ((ret = sgfru_mbox(iargp->cmd, datap, size, &payld.fru_info))
1006 != 0) {
1007 kmem_free(datap, size);
1008 return (ret);
1009 }
1010
1011 /* translate unpadded to padded fru_info_t */
1012 tdatap = sgfru_fru_pad(datap, &pinfo);
1013 PR_PAYLOAD("sgfru:%s: handle %lx, max cnt %d\n",
1014 f, pinfo.hdl, pinfo.cnt);
1015
1016 /* copyout actual fru_cnt */
1017 if (sgfru_copyout_fru(iargp, &pinfo) != 0) {
1018 kmem_free(datap, size);
1019 return (EFAULT);
1020 }
1021 /* copyout raw packet data, aka the payload */
1022 if (sgfru_copyout_buffer(iargp, &payld, tdatap) != 0) {
1023 kmem_free(datap, size);
1024 return (EFAULT);
1025 }
1026
1027 /* free buffer */
1028 kmem_free(datap, size);
1029
1030 return (ret);
1031 }
1032
1033 /*
1034 * Used for fru_update_payload().
1035 */
1036 static int
sgfru_updatepayload(const sgfru_init_arg_t * iargp)1037 sgfru_updatepayload(const sgfru_init_arg_t *iargp)
1038 {
1039 int32_t ret;
1040 caddr_t datap, tdatap;
1041 size_t size;
1042 frup_info_t payld;
1043 fru_cnt_t max_cnt;
1044 static fn_t f = "sgfru_updatepayload";
1045
1046 /* copyin frup_info_t */
1047 if (sgfru_copyin_frup(iargp, &payld) != 0) {
1048 return (EFAULT);
1049 }
1050 /* check on kmem_alloc space requirements */
1051 max_cnt = payld.fru_cnt;
1052 if ((max_cnt <= 0) || (max_cnt > MAX_PAYLOADSIZE)) {
1053 return (EINVAL);
1054 }
1055
1056 /* allocate buffer for fru_info_t + payload */
1057 size = (size_t)(FRU_INFO_SIZE + max_cnt);
1058 datap = kmem_zalloc(size, KM_SLEEP);
1059
1060 /* translate padded to unpadded fru_info_t */
1061 tdatap = sgfru_fru_unpad(&payld.fru_info, datap);
1062
1063 /* copyin payload */
1064 if (sgfru_copyin_buffer(iargp, payld.frus, max_cnt, tdatap) != 0) {
1065 kmem_free(datap, size);
1066 return (EFAULT);
1067 }
1068 PR_PAYLOAD("sgfru_updatepayload: handle %lx, actual cnt %d\n",
1069 payld.fru_hdl, payld.fru_cnt);
1070
1071 /* call mailbox */
1072 if ((ret = sgfru_mbox(iargp->cmd, datap, size, &payld.fru_info))
1073 != 0) {
1074 kmem_free(datap, size);
1075 return (ret);
1076 }
1077
1078 /* free buffer */
1079 kmem_free(datap, size);
1080
1081 /* copyout new packet_hdl_t and actual count */
1082 if (sgfru_copyout_fru(iargp, &payld.fru_info) != 0) {
1083 return (EFAULT);
1084 }
1085 PR_PAYLOAD("sgfru:%s: new handle %lx, cnt %d\n",
1086 f, payld.fru_hdl, payld.fru_cnt);
1087
1088 return (ret);
1089 }
1090
1091 /*
1092 * Used for fru_get_num_[sections|segments|packets]().
1093 */
1094 static int
sgfru_getnum(const sgfru_init_arg_t * iargp)1095 sgfru_getnum(const sgfru_init_arg_t *iargp)
1096 {
1097 int32_t ret;
1098 caddr_t datap;
1099 size_t size;
1100 fru_info_t fru_info;
1101
1102 /* copyin fru_info_t */
1103 if (sgfru_copyin_fru(iargp, &fru_info) != 0) {
1104 return (EFAULT);
1105 }
1106
1107 size = sizeof (fru_cnt_t);
1108 datap = (caddr_t)&fru_info.cnt;
1109 if ((ret = sgfru_mbox(iargp->cmd, datap, size, &fru_info)) != 0) {
1110 return (ret);
1111 }
1112
1113 /* copyout fru_info_t */
1114 if (sgfru_copyout_fru(iargp, &fru_info) != 0) {
1115 return (EFAULT);
1116 }
1117 return (ret);
1118 }
1119
1120 /*
1121 * Used for fru_delete_[segment|packet].
1122 */
1123 static int
sgfru_delete(const sgfru_init_arg_t * iargp)1124 sgfru_delete(const sgfru_init_arg_t *iargp)
1125 {
1126 int32_t ret;
1127 caddr_t datap;
1128 size_t size;
1129 fru_info_t fru_info;
1130 static fn_t f = "sgfru_delete";
1131
1132 /* copyin fru_info_t */
1133 if (sgfru_copyin_fru(iargp, &fru_info) != 0) {
1134 return (EFAULT);
1135 }
1136 PR_SEGMENT("sgfru:%s: delete handle %lx\n", f, fru_info.hdl);
1137
1138 size = sizeof (fru_hdl_t);
1139 datap = (caddr_t)&fru_info.hdl;
1140 if ((ret = sgfru_mbox(iargp->cmd, datap, size, &fru_info)) != 0) {
1141 return (ret);
1142 }
1143
1144 PR_SEGMENT("sgfru:%s: new parent handle %lx\n", f, fru_info.hdl);
1145 /* copyout fru_info_t */
1146 if (sgfru_copyout_fru(iargp, &fru_info) != 0) {
1147 return (EFAULT);
1148 }
1149 return (ret);
1150 }
1151
1152 /*
1153 * Calls the sgsbbc mailbox with data, returns data and status info.
1154 */
1155 static int
sgfru_mbox(const int cmd,char * datap,const size_t size,fru_info_t * fru)1156 sgfru_mbox(const int cmd, char *datap, const size_t size, fru_info_t *fru)
1157 {
1158 sbbc_msg_t request, *reqp = &request;
1159 sbbc_msg_t response, *resp = &response;
1160 fru_hdl_t hdls[2] = {0, 0};
1161 fru_hdl_t hdl = fru->hdl;
1162 int rv = 0;
1163 static fn_t f = "sgfru_mbox";
1164
1165 bzero((caddr_t)&request, sizeof (sbbc_msg_t));
1166 reqp->msg_type.type = SGFRU_MBOX;
1167 bzero((caddr_t)&response, sizeof (sbbc_msg_t));
1168 resp->msg_type.type = SGFRU_MBOX;
1169 PR_MBOX("sgfru:%s: cmd 0x%x, size %lu\n", f, cmd, size);
1170
1171 switch (cmd) {
1172
1173 case SGFRU_GETCHILDLIST:
1174 reqp->msg_type.sub_type = SGFRU_MBOX_GETCHILDLIST;
1175 reqp->msg_len = sizeof (fru_info_t);
1176 reqp->msg_buf = (caddr_t)fru;
1177 resp->msg_type.sub_type = SGFRU_MBOX_GETCHILDLIST;
1178 resp->msg_len = size;
1179 resp->msg_buf = datap;
1180 break;
1181
1182 case SGFRU_GETCHILDHANDLES:
1183 reqp->msg_type.sub_type = SGFRU_MBOX_GETCHILDHANDLES;
1184 reqp->msg_len = sizeof (fru_info_t);
1185 reqp->msg_buf = (caddr_t)fru;
1186 resp->msg_type.sub_type = SGFRU_MBOX_GETCHILDHANDLES;
1187 resp->msg_len = size;
1188 resp->msg_buf = datap;
1189 break;
1190
1191 case SGFRU_GETNODEINFO:
1192 reqp->msg_type.sub_type = SGFRU_MBOX_GETNODEINFO;
1193 reqp->msg_len = sizeof (fru_hdl_t);
1194 reqp->msg_buf = (caddr_t)&hdl;
1195 resp->msg_type.sub_type = SGFRU_MBOX_GETNODEINFO;
1196 resp->msg_len = size;
1197 resp->msg_buf = datap;
1198 break;
1199
1200 case SGFRU_GETNUMSECTIONS:
1201 reqp->msg_type.sub_type = SGFRU_MBOX_GETNUMSECTIONS;
1202 reqp->msg_len = sizeof (fru_hdl_t);
1203 reqp->msg_buf = (caddr_t)&hdl;
1204 resp->msg_type.sub_type = SGFRU_MBOX_GETNUMSECTIONS;
1205 resp->msg_len = size;
1206 resp->msg_buf = datap;
1207 break;
1208
1209 case SGFRU_GETNUMSEGMENTS:
1210 reqp->msg_type.sub_type = SGFRU_MBOX_GETNUMSEGMENTS;
1211 reqp->msg_len = sizeof (fru_hdl_t);
1212 reqp->msg_buf = (caddr_t)&hdl;
1213 resp->msg_type.sub_type = SGFRU_MBOX_GETNUMSEGMENTS;
1214 resp->msg_len = size;
1215 resp->msg_buf = datap;
1216 break;
1217
1218 case SGFRU_GETNUMPACKETS:
1219 reqp->msg_type.sub_type = SGFRU_MBOX_GETNUMPACKETS;
1220 reqp->msg_len = sizeof (fru_hdl_t);
1221 reqp->msg_buf = (caddr_t)&hdl;
1222 resp->msg_type.sub_type = SGFRU_MBOX_GETNUMPACKETS;
1223 resp->msg_len = size;
1224 resp->msg_buf = datap;
1225 break;
1226
1227 case SGFRU_GETSECTIONS:
1228 reqp->msg_type.sub_type = SGFRU_MBOX_GETSECTIONS;
1229 reqp->msg_len = sizeof (fru_info_t);
1230 reqp->msg_buf = (caddr_t)fru;
1231 resp->msg_type.sub_type = SGFRU_MBOX_GETSECTIONS;
1232 resp->msg_len = size;
1233 resp->msg_buf = datap;
1234 break;
1235
1236 case SGFRU_GETSEGMENTS:
1237 reqp->msg_type.sub_type = SGFRU_MBOX_GETSEGMENTS;
1238 reqp->msg_len = sizeof (fru_info_t);
1239 reqp->msg_buf = (caddr_t)fru;
1240 resp->msg_type.sub_type = SGFRU_MBOX_GETSEGMENTS;
1241 resp->msg_len = size;
1242 resp->msg_buf = datap;
1243 break;
1244
1245 case SGFRU_GETPACKETS:
1246 reqp->msg_type.sub_type = SGFRU_MBOX_GETPACKETS;
1247 reqp->msg_len = sizeof (fru_info_t);
1248 reqp->msg_buf = (caddr_t)fru;
1249 resp->msg_type.sub_type = SGFRU_MBOX_GETPACKETS;
1250 resp->msg_len = size;
1251 resp->msg_buf = datap;
1252 break;
1253
1254 case SGFRU_ADDSEGMENT:
1255 reqp->msg_type.sub_type = SGFRU_MBOX_ADDSEGMENT;
1256 reqp->msg_len = size;
1257 reqp->msg_buf = datap;
1258 resp->msg_type.sub_type = SGFRU_MBOX_ADDSEGMENT;
1259 resp->msg_len = sizeof (hdls);
1260 resp->msg_buf = (caddr_t)&hdls;
1261 break;
1262
1263 case SGFRU_APPENDPACKET:
1264 reqp->msg_type.sub_type = SGFRU_MBOX_APPENDPACKET;
1265 reqp->msg_len = size;
1266 reqp->msg_buf = (caddr_t)datap;
1267 resp->msg_type.sub_type = SGFRU_MBOX_APPENDPACKET;
1268 resp->msg_len = sizeof (hdls);
1269 resp->msg_buf = (caddr_t)&hdls;
1270 break;
1271
1272 case SGFRU_DELETESEGMENT:
1273 reqp->msg_type.sub_type = SGFRU_MBOX_DELETESEGMENT;
1274 reqp->msg_len = size;
1275 reqp->msg_buf = (caddr_t)datap;
1276 resp->msg_type.sub_type = SGFRU_MBOX_DELETESEGMENT;
1277 resp->msg_len = sizeof (fru_hdl_t);
1278 resp->msg_buf = (caddr_t)&hdl;
1279 break;
1280
1281 case SGFRU_READRAWSEGMENT:
1282 reqp->msg_type.sub_type = SGFRU_MBOX_READRAWSEGMENT;
1283 reqp->msg_len = sizeof (fru_info_t);
1284 reqp->msg_buf = (caddr_t)fru;
1285 resp->msg_type.sub_type = SGFRU_READRAWSEGMENT;
1286 resp->msg_len = size;
1287 resp->msg_buf = datap;
1288 break;
1289
1290 case SGFRU_WRITERAWSEGMENT:
1291 reqp->msg_type.sub_type = SGFRU_MBOX_WRITERAWSEGMENT;
1292 reqp->msg_len = size;
1293 reqp->msg_buf = datap;
1294 resp->msg_type.sub_type = SGFRU_WRITERAWSEGMENT;
1295 resp->msg_len = sizeof (fru_info_t);
1296 resp->msg_buf = (caddr_t)fru;
1297 break;
1298
1299 case SGFRU_DELETEPACKET:
1300 reqp->msg_type.sub_type = SGFRU_MBOX_DELETEPACKET;
1301 reqp->msg_len = size;
1302 reqp->msg_buf = (caddr_t)datap;
1303 resp->msg_type.sub_type = SGFRU_MBOX_DELETEPACKET;
1304 resp->msg_len = sizeof (fru_hdl_t);
1305 resp->msg_buf = (caddr_t)&hdl;
1306 break;
1307
1308 case SGFRU_GETPAYLOAD:
1309 reqp->msg_type.sub_type = SGFRU_MBOX_GETPAYLOAD;
1310 reqp->msg_len = sizeof (fru_info_t);
1311 reqp->msg_buf = (caddr_t)fru;
1312 resp->msg_type.sub_type = SGFRU_MBOX_GETPAYLOAD;
1313 resp->msg_len = size;
1314 resp->msg_buf = datap;
1315 break;
1316
1317 case SGFRU_UPDATEPAYLOAD:
1318 reqp->msg_type.sub_type = SGFRU_MBOX_UPDATEPAYLOAD;
1319 reqp->msg_len = size;
1320 reqp->msg_buf = datap;
1321 resp->msg_type.sub_type = SGFRU_MBOX_UPDATEPAYLOAD;
1322 resp->msg_len = sizeof (fru_info_t);
1323 resp->msg_buf = (caddr_t)fru;
1324 break;
1325
1326 default:
1327 return (EINVAL);
1328 }
1329
1330 rv = sbbc_mbox_request_response(reqp, resp, sgfru_mbox_wait);
1331 PR_MBOX("sgfru:%s: rv %d, msg_status %d\n", f, rv, resp->msg_status);
1332
1333 if ((rv) || (resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
1334
1335 /* errors from sgsbbc */
1336 if (resp->msg_status > 0) {
1337 return (resp->msg_status);
1338 }
1339
1340 /* errors from SCAPP */
1341 switch (resp->msg_status) {
1342
1343 case SG_MBOX_STATUS_COMMAND_FAILURE:
1344 /* internal SCAPP error */
1345 return (EINTR);
1346
1347 case SG_MBOX_STATUS_HARDWARE_FAILURE:
1348 /* seprom read/write errors */
1349 return (EIO);
1350
1351 case SG_MBOX_STATUS_ILLEGAL_PARAMETER:
1352 /* illegal ioctl parameter */
1353 return (EINVAL);
1354
1355 case SG_MBOX_STATUS_BOARD_ACCESS_DENIED:
1356 /* board access denied */
1357 return (EACCES);
1358
1359 case SG_MBOX_STATUS_STALE_CONTENTS:
1360 /* stale contents */
1361 return (ESTALE);
1362
1363 case SG_MBOX_STATUS_STALE_OBJECT:
1364 /* stale handle */
1365 return (ENOENT);
1366
1367 case SG_MBOX_STATUS_NO_SEPROM_SPACE:
1368 /* seprom lacks space */
1369 return (ENOSPC);
1370
1371 case SG_MBOX_STATUS_NO_MEMORY:
1372 /* user prog. lacks space */
1373 return (ENOMEM);
1374
1375 case SG_MBOX_STATUS_NOT_SUPPORTED:
1376 /* unsupported operation */
1377 return (ENOTSUP);
1378
1379 default:
1380 return (EIO);
1381 }
1382 }
1383
1384 switch (cmd) {
1385
1386 /*
1387 * These two calls get back two handles, a new handle for the
1388 * added segment or packet, and an updated parent handle.
1389 */
1390 case SGFRU_ADDSEGMENT:
1391 case SGFRU_APPENDPACKET:
1392 bcopy(hdls, datap, sizeof (hdls));
1393 break;
1394
1395 /* These two calls get an updated parent handle. */
1396 case SGFRU_DELETESEGMENT:
1397 case SGFRU_DELETEPACKET:
1398 fru->hdl = hdl;
1399 break;
1400
1401 default:
1402 break;
1403 }
1404
1405 return (0);
1406 }
1407
1408 /*
1409 * Used to copy in one frup_info_t from user.
1410 */
1411 static int
sgfru_copyin_frup(const sgfru_init_arg_t * argp,frup_info_t * frup)1412 sgfru_copyin_frup(const sgfru_init_arg_t *argp, frup_info_t *frup)
1413 {
1414 static fn_t f = "sgfru_copyin_frup";
1415
1416 bzero((caddr_t)frup, sizeof (frup_info_t));
1417 #ifdef _MULTI_DATAMODEL
1418 if (ddi_model_convert_from(argp->mode & FMODELS) == DDI_MODEL_ILP32) {
1419 frup32_info_t frup32;
1420
1421 bzero((caddr_t)&frup32, sizeof (frup32_info_t));
1422 if (ddi_copyin((void *)argp->argp, (void *)&frup32,
1423 sizeof (frup32_info_t), argp->mode) != DDI_SUCCESS) {
1424 cmn_err(CE_WARN, "sgfru:%s: (32 bit) failed to copyin "
1425 "frup32_t struct", f);
1426 return (EFAULT);
1427 }
1428 frup->fru_hdl = frup32.fru_hdl;
1429 frup->fru_cnt = frup32.fru_cnt;
1430 frup->frus = (void *)(uintptr_t)frup32.frus;
1431 PR_STATE("sgfru:%s: frus %p %x hdl %lx cnt %d\n",
1432 f, frup->frus, frup32.frus, frup->fru_hdl, frup->fru_cnt);
1433
1434 } else
1435 #endif /* _MULTI_DATAMODEL */
1436 if (ddi_copyin((void *)argp->argp, (void *)frup,
1437 sizeof (frup_info_t), argp->mode) != DDI_SUCCESS) {
1438 cmn_err(CE_WARN,
1439 "sgfru:%s: failed to copyin frup_info_t struct", f);
1440 return (EFAULT);
1441 }
1442 return (0);
1443 }
1444
1445 /*
1446 * Used to copy in one fru_info_t from user.
1447 */
1448 static int
sgfru_copyin_fru(const sgfru_init_arg_t * argp,fru_info_t * fru)1449 sgfru_copyin_fru(const sgfru_init_arg_t *argp, fru_info_t *fru)
1450 {
1451 static fn_t f = "sgfru_copyin_fru";
1452
1453 bzero((caddr_t)fru, sizeof (fru_info_t));
1454 if (ddi_copyin((void *)argp->argp, (void *)fru,
1455 sizeof (fru_info_t), argp->mode) != DDI_SUCCESS) {
1456 cmn_err(CE_WARN,
1457 "sgfru:%s: failed to copyin fru_info_t struct", f);
1458 return (EFAULT);
1459 }
1460 return (0);
1461 }
1462
1463 /*
1464 * Used to copy in segment_t from user.
1465 */
1466 static int
sgfru_copyin_segment(const sgfru_init_arg_t * argp,const frup_info_t * frup,segment_t * segp)1467 sgfru_copyin_segment(const sgfru_init_arg_t *argp, const frup_info_t *frup,
1468 segment_t *segp)
1469 {
1470 static fn_t f = "sgfru_copyin_segment";
1471
1472 bzero((caddr_t)segp, sizeof (segment_t));
1473 if (ddi_copyin((void *)frup->frus, (void *)segp,
1474 sizeof (segment_t), argp->mode) != DDI_SUCCESS) {
1475 cmn_err(CE_WARN,
1476 "sgfru:%s: failed to copyin segment_t struct", f);
1477 return (EFAULT);
1478 }
1479 return (0);
1480 }
1481
1482 /*
1483 * Used to copy in segment handle, packet and payload data from user.
1484 */
1485 static int
sgfru_copyin_append(const sgfru_init_arg_t * argp,append_info_t * app)1486 sgfru_copyin_append(const sgfru_init_arg_t *argp, append_info_t *app)
1487 {
1488 static fn_t f = "sgfru_copyin_append";
1489
1490 bzero((caddr_t)app, sizeof (append_info_t));
1491 #ifdef _MULTI_DATAMODEL
1492 if (ddi_model_convert_from(argp->mode & FMODELS) == DDI_MODEL_ILP32) {
1493 append32_info_t app32;
1494
1495 bzero((caddr_t)&app32, sizeof (append32_info_t));
1496 if (ddi_copyin((void *)argp->argp, (void *)&app32,
1497 sizeof (append32_info_t), argp->mode) != DDI_SUCCESS) {
1498 cmn_err(CE_WARN, "sgfru:%s: (32 bit) failed to copyin "
1499 "append32_info_t struct", f);
1500 return (EFAULT);
1501 }
1502 app->packet = app32.packet;
1503 app->payload_hdl = app32.payload_hdl;
1504 app->payload_cnt = app32.payload_cnt;
1505 app->payload_data = (void *)(uintptr_t)app32.payload_data;
1506 PR_PAYLOAD("sgfru:%s:: data %p hdl %lx cnt %d\n",
1507 f, app->payload_data, app->payload_hdl, app->payload_cnt);
1508
1509 } else
1510 #endif /* _MULTI_DATAMODEL */
1511 if (ddi_copyin((void *)argp->argp, (void *)app,
1512 sizeof (append_info_t), argp->mode) != DDI_SUCCESS) {
1513 cmn_err(CE_WARN,
1514 "sgfru:%s: failed to copyin append_info_t struct", f);
1515 return (EFAULT);
1516 }
1517 PR_PAYLOAD("sgfru:%s: hdl %lx, cnt %d pkt hdl %lx "
1518 "tag %lx\n", f, app->payload_hdl, app->payload_cnt,
1519 app->packet.handle, app->packet.tag);
1520 return (0);
1521 }
1522
1523 /*
1524 * Used to copy in raw segment and payload data from user.
1525 */
1526 static int
sgfru_copyin_buffer(const sgfru_init_arg_t * argp,const caddr_t data,const int cnt,char * buffer)1527 sgfru_copyin_buffer(const sgfru_init_arg_t *argp, const caddr_t data,
1528 const int cnt, char *buffer)
1529 {
1530 static fn_t f = "sgfru_copyin_buffer";
1531
1532 if (ddi_copyin((void *)data, (void *)buffer, cnt, argp->mode)
1533 != DDI_SUCCESS) {
1534 cmn_err(CE_WARN, "sgfru:%s: failed to copyin buffer", f);
1535 return (EFAULT);
1536 }
1537 return (0);
1538 }
1539
1540 /*
1541 * Used to copy out one fru_info_t to user.
1542 */
1543 static int
sgfru_copyout_fru(const sgfru_init_arg_t * argp,const fru_info_t * frup)1544 sgfru_copyout_fru(const sgfru_init_arg_t *argp, const fru_info_t *frup)
1545 {
1546 static fn_t f = "sgfru_copyout_fru";
1547
1548 if (ddi_copyout((void *)frup, (void *)argp->argp,
1549 sizeof (fru_info_t), argp->mode) != DDI_SUCCESS) {
1550 cmn_err(CE_WARN, "sgfru:%s: failed to copyout fru", f);
1551 return (EFAULT);
1552 }
1553 return (0);
1554 }
1555
1556 /*
1557 * Used to copy out one fru_hdl_t to user.
1558 */
1559 static int
sgfru_copyout_handle(const sgfru_init_arg_t * argp,const void * addr,const fru_hdl_t * hdlp)1560 sgfru_copyout_handle(const sgfru_init_arg_t *argp, const void *addr,
1561 const fru_hdl_t *hdlp)
1562 {
1563 static fn_t f = "sgfru_copyout_handle";
1564
1565 if (ddi_copyout((void *)hdlp, (void *)addr, sizeof (fru_hdl_t),
1566 argp->mode) != DDI_SUCCESS) {
1567 cmn_err(CE_WARN, "sgfru:%s: failed to copyout handle", f);
1568 return (EFAULT);
1569 }
1570 return (0);
1571 }
1572
1573 /*
1574 * Used to copy out an array of fru_hdl_t's to user.
1575 */
1576 static int
sgfru_copyout_handles(const sgfru_init_arg_t * argp,const frup_info_t * frup,const fru_hdl_t * hdlp)1577 sgfru_copyout_handles(const sgfru_init_arg_t *argp, const frup_info_t *frup,
1578 const fru_hdl_t *hdlp)
1579 {
1580 static fn_t f = "sgfru_copyout_handles";
1581
1582 size_t size = (size_t)(frup->fru_cnt * sizeof (fru_hdl_t));
1583 /* copyout fru_hdl_t's */
1584 if (ddi_copyout((void *)hdlp, (void *)frup->frus, size, argp->mode)
1585 != DDI_SUCCESS) {
1586 cmn_err(CE_WARN, "sgfru:%s: failed to copyout handles", f);
1587 return (EFAULT);
1588 }
1589 return (0);
1590 }
1591
1592 /*
1593 * Used to copy out one or more node_t's to user.
1594 */
1595 static int
sgfru_copyout_nodes(const sgfru_init_arg_t * argp,const frup_info_t * frup,const node_t * nodep)1596 sgfru_copyout_nodes(const sgfru_init_arg_t *argp, const frup_info_t *frup,
1597 const node_t *nodep)
1598 {
1599 static fn_t f = "sgfru_copyout_nodes";
1600
1601 size_t size = (size_t)(frup->fru_cnt * sizeof (node_t));
1602 /* copyout node_t's */
1603 if (ddi_copyout((void *)nodep, (void *)frup->frus, size, argp->mode)
1604 != DDI_SUCCESS) {
1605 cmn_err(CE_WARN, "sgfru:%s: failed to copyout nodes", f);
1606 return (EFAULT);
1607 }
1608 return (0);
1609 }
1610
1611 /*
1612 * Used to copy out section_t's to user.
1613 */
1614 static int
sgfru_copyout_sections(const sgfru_init_arg_t * argp,const frup_info_t * frup,const section_t * sectp)1615 sgfru_copyout_sections(const sgfru_init_arg_t *argp, const frup_info_t *frup,
1616 const section_t *sectp)
1617 {
1618 static fn_t f = "sgfru_copyout_sections";
1619
1620 size_t size = (size_t)(frup->fru_cnt * sizeof (section_t));
1621 /* copyout section_t's */
1622 if (ddi_copyout((void *)sectp, (void *)frup->frus, size, argp->mode)
1623 != DDI_SUCCESS) {
1624 cmn_err(CE_WARN, "sgfru:%s: failed to copyout sections", f);
1625 return (EFAULT);
1626 }
1627 return (0);
1628 }
1629
1630 /*
1631 * Used to copy out segment_t's to user.
1632 */
1633 static int
sgfru_copyout_segments(const sgfru_init_arg_t * argp,const frup_info_t * frup,const segment_t * segp)1634 sgfru_copyout_segments(const sgfru_init_arg_t *argp, const frup_info_t *frup,
1635 const segment_t *segp)
1636 {
1637 static fn_t f = "sgfru_copyout_segments";
1638
1639 size_t size = (size_t)(frup->fru_cnt * sizeof (segment_t));
1640 /* copyout segment_t's */
1641 if (ddi_copyout((void *)segp, (void *)frup->frus, size, argp->mode)
1642 != DDI_SUCCESS) {
1643 cmn_err(CE_WARN, "sgfru:%s: failed to copyout segments", f);
1644 return (EFAULT);
1645 }
1646 return (0);
1647 }
1648
1649 /*
1650 * Used to copy out packet_t's to user.
1651 */
1652 static int
sgfru_copyout_packets(const sgfru_init_arg_t * argp,const frup_info_t * frup,const packet_t * packp)1653 sgfru_copyout_packets(const sgfru_init_arg_t *argp, const frup_info_t *frup,
1654 const packet_t *packp)
1655 {
1656 static fn_t f = "sgfru_copyout_packets";
1657
1658 size_t size = (size_t)(frup->fru_cnt * sizeof (packet_t));
1659 /* copyout packet_t's */
1660 if (ddi_copyout((void *)packp, (void *)frup->frus, size, argp->mode)
1661 != DDI_SUCCESS) {
1662 cmn_err(CE_WARN, "sgfru:%s: failed to copyout packets", f);
1663 return (EFAULT);
1664 }
1665 return (0);
1666 }
1667
1668 /*
1669 * Used to copy out raw segment and payload data to user.
1670 */
1671 static int
sgfru_copyout_buffer(const sgfru_init_arg_t * argp,const frup_info_t * frup,const char * buffer)1672 sgfru_copyout_buffer(const sgfru_init_arg_t *argp, const frup_info_t *frup,
1673 const char *buffer)
1674 {
1675 static fn_t f = "sgfru_copyout_buffer";
1676
1677 size_t size = (size_t)(frup->fru_cnt);
1678 /* copyout packet_t */
1679 if (ddi_copyout((void *)buffer, (void *)frup->frus, size, argp->mode)
1680 != DDI_SUCCESS) {
1681 cmn_err(CE_WARN, "sgfru:%s: failed to copyout buffer", f);
1682 return (EFAULT);
1683 }
1684 return (0);
1685 }
1686
1687 /*
1688 * Used to pad a Java (SCAPP) fru_info_t, in preparation for sending it to
1689 * C (Solaris). Assumes one fru_info_t.
1690 */
1691 static caddr_t
sgfru_fru_pad(const caddr_t datap,fru_info_t * fru)1692 sgfru_fru_pad(const caddr_t datap, fru_info_t *fru)
1693 {
1694 caddr_t tdatap = datap;
1695
1696 bcopy(tdatap, (caddr_t)&fru->hdl, FRU_HDL_SIZE);
1697 tdatap += FRU_HDL_SIZE;
1698 bcopy(tdatap, (caddr_t)&fru->cnt, FRU_CNT_SIZE);
1699 tdatap += FRU_CNT_SIZE;
1700 return (tdatap);
1701 }
1702
1703 /*
1704 * Used to pad a Java (SCAPP) node_t, in preparation for sending it to
1705 * C (Solaris). Assumes a fru_info_t and one or more node_t's.
1706 */
1707 static int
sgfru_node_pad(const caddr_t datap,const int max_cnt,fru_info_t * fru,node_t * nodep)1708 sgfru_node_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru,
1709 node_t *nodep)
1710 {
1711 caddr_t tdatap = datap;
1712 node_t *np;
1713 int i, cnt = 1;
1714
1715 if (fru != NULL) {
1716 tdatap = sgfru_fru_pad(datap, fru);
1717 if (max_cnt < fru->cnt) {
1718 return (ENOMEM);
1719 } else {
1720 cnt = fru->cnt;
1721 }
1722 }
1723 for (i = 0, np = nodep; i < cnt; i++, np++) {
1724 bcopy(tdatap, (caddr_t)&np->handle, FRU_HDL_SIZE);
1725 tdatap += FRU_HDL_SIZE;
1726 bcopy(tdatap, (caddr_t)&np->nodename, NODENAME_SIZE);
1727 tdatap += NODENAME_SIZE;
1728 bcopy(tdatap, (caddr_t)&np->has_children, HASCHILDREN_SIZE);
1729 tdatap += HASCHILDREN_SIZE;
1730 bcopy(tdatap, (caddr_t)&np->class, CLASS_SIZE);
1731 tdatap += CLASS_SIZE;
1732 if (np->class == LOCATION_CLASS) {
1733 bcopy(tdatap, (caddr_t)&np->location_slot, SLOT_SIZE);
1734 tdatap += SLOT_SIZE;
1735 bcopy(tdatap, (caddr_t)&np->location_label, LABEL_SIZE);
1736 tdatap += LABEL_SIZE;
1737 }
1738 }
1739 return (0);
1740 }
1741
1742 /*
1743 * Used to pad a Java (SCAPP) section, in preparation for sending it to
1744 * C (Solaris). Assumes a fru_info_t and multiple section_t's.
1745 */
1746 static int
sgfru_section_pad(const caddr_t datap,const int max_cnt,fru_info_t * fru,section_t * sectp)1747 sgfru_section_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru,
1748 section_t *sectp)
1749 {
1750 caddr_t tdatap = datap;
1751 section_t *sp;
1752 int i;
1753
1754 tdatap = sgfru_fru_pad(datap, fru);
1755 if (max_cnt < fru->cnt)
1756 return (ENOMEM);
1757 for (i = 0, sp = sectp; i < fru->cnt; i++, sp++) {
1758 bcopy(tdatap, (caddr_t)&sp->handle, FRU_HDL_SIZE);
1759 tdatap += FRU_HDL_SIZE;
1760 bcopy(tdatap, (caddr_t)&sp->offset, OFFSET_SIZE);
1761 tdatap += OFFSET_SIZE;
1762 bcopy(tdatap, (caddr_t)&sp->length, LENGTH_SIZE);
1763 tdatap += LENGTH_SIZE;
1764 bcopy(tdatap, (caddr_t)&sp->protected, PROTECTED_SIZE);
1765 tdatap += PROTECTED_SIZE;
1766 bcopy(tdatap, (caddr_t)&sp->version, VERSION_SIZE);
1767 tdatap += VERSION_SIZE;
1768 }
1769 return (0);
1770 }
1771
1772 /*
1773 * Used to pad a Java (SCAPP) segment, in preparation for sending it to
1774 * C (Solaris). Assumes a fru_info_t and multiple segment_t's.
1775 */
1776 static int
sgfru_segment_pad(const caddr_t datap,const int max_cnt,fru_info_t * fru,segment_t * segp)1777 sgfru_segment_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru,
1778 segment_t *segp)
1779 {
1780 caddr_t tdatap = datap;
1781 segment_t *sp;
1782 int i;
1783
1784 tdatap = sgfru_fru_pad(datap, fru);
1785 if (max_cnt < fru->cnt)
1786 return (ENOMEM);
1787 for (i = 0, sp = segp; i < fru->cnt; i++, sp++) {
1788 bcopy(tdatap, (caddr_t)&sp->handle, FRU_HDL_SIZE);
1789 tdatap += FRU_HDL_SIZE;
1790 bcopy(tdatap, (caddr_t)&sp->name, NAME_SIZE);
1791 tdatap += NAME_SIZE;
1792 bcopy(tdatap, (caddr_t)&sp->descriptor, DESCRIPTOR_SIZE);
1793 tdatap += DESCRIPTOR_SIZE;
1794 bcopy(tdatap, (caddr_t)&sp->offset, OFFSET_SIZE);
1795 tdatap += OFFSET_SIZE;
1796 bcopy(tdatap, (caddr_t)&sp->length, LENGTH_SIZE);
1797 tdatap += LENGTH_SIZE;
1798 }
1799 return (0);
1800 }
1801
1802 /*
1803 * Used to pad a Java (SCAPP) packet, in preparation for sending it to
1804 * C (Solaris). Assumes a fru_info_t and multiple packet_t's.
1805 */
1806 static int
sgfru_packet_pad(const caddr_t datap,const int max_cnt,fru_info_t * fru,packet_t * packp)1807 sgfru_packet_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru,
1808 packet_t *packp)
1809 {
1810 caddr_t tdatap = datap;
1811 packet_t *pp;
1812 int i;
1813
1814 tdatap = sgfru_fru_pad(datap, fru);
1815 if (max_cnt < fru->cnt)
1816 return (ENOMEM);
1817 for (i = 0, pp = packp; i < fru->cnt; i++, pp++) {
1818 bcopy(tdatap, (caddr_t)&pp->handle, FRU_HDL_SIZE);
1819 tdatap += FRU_HDL_SIZE;
1820 bcopy(tdatap, (caddr_t)&pp->tag, TAG_SIZE);
1821 tdatap += TAG_SIZE;
1822 }
1823 return (0);
1824 }
1825
1826 /*
1827 * Used to unpad a C (Solaris) fru_info_t, in preparation for sending it to
1828 * Java (SCAPP). Assumes a fru_info_t.
1829 */
1830 static caddr_t
sgfru_fru_unpad(const fru_info_t * fru,caddr_t datap)1831 sgfru_fru_unpad(const fru_info_t *fru, caddr_t datap)
1832 {
1833 caddr_t tdatap = datap;
1834
1835 bcopy((caddr_t)&fru->hdl, tdatap, FRU_HDL_SIZE);
1836 tdatap += FRU_HDL_SIZE;
1837 bcopy((caddr_t)&fru->cnt, tdatap, FRU_CNT_SIZE);
1838 tdatap += FRU_CNT_SIZE;
1839 return (tdatap);
1840 }
1841
1842 /*
1843 * Used to unpad a C (Solaris) segment, in preparation for sending it to
1844 * Java (SCAPP). Assumes a section_hdl_t and one segment_t.
1845 */
1846 static void
sgfru_segment_unpad(const fru_info_t * fru,const segment_t * segp,caddr_t datap)1847 sgfru_segment_unpad(const fru_info_t *fru, const segment_t *segp,
1848 caddr_t datap)
1849 {
1850 caddr_t tdatap = datap;
1851
1852 bcopy((caddr_t)&fru->hdl, tdatap, FRU_HDL_SIZE);
1853 tdatap += FRU_HDL_SIZE;
1854 bcopy((caddr_t)&segp->handle, tdatap, FRU_HDL_SIZE);
1855 tdatap += FRU_HDL_SIZE;
1856 bcopy((caddr_t)&segp->name, tdatap, NAME_SIZE);
1857 tdatap += NAME_SIZE;
1858 bcopy((caddr_t)&segp->descriptor, tdatap, DESCRIPTOR_SIZE);
1859 tdatap += DESCRIPTOR_SIZE;
1860 bcopy((caddr_t)&segp->offset, tdatap, OFFSET_SIZE);
1861 tdatap += OFFSET_SIZE;
1862 bcopy((caddr_t)&segp->length, tdatap, LENGTH_SIZE);
1863 }
1864
1865 /*
1866 * Used to unpad a C (Solaris) packet, in preparation for sending it to
1867 * Java (SCAPP). Assumes a fru_info_t and one packet_t.
1868 */
1869 static caddr_t
sgfru_packet_unpad(const fru_info_t * fru,const packet_t * packp,caddr_t datap)1870 sgfru_packet_unpad(const fru_info_t *fru, const packet_t *packp, caddr_t datap)
1871 {
1872 caddr_t tdatap = datap;
1873
1874 bcopy((caddr_t)&fru->hdl, tdatap, FRU_HDL_SIZE);
1875 tdatap += FRU_HDL_SIZE;
1876 bcopy((caddr_t)&fru->cnt, tdatap, FRU_CNT_SIZE);
1877 tdatap += FRU_CNT_SIZE;
1878 bcopy((caddr_t)&packp->handle, tdatap, FRU_HDL_SIZE);
1879 tdatap += FRU_HDL_SIZE;
1880 bcopy((caddr_t)&packp->tag, tdatap, TAG_SIZE);
1881 tdatap += TAG_SIZE;
1882 return (tdatap);
1883 }
1884