103831d35Sstevel /* 203831d35Sstevel * CDDL HEADER START 303831d35Sstevel * 403831d35Sstevel * The contents of this file are subject to the terms of the 503831d35Sstevel * Common Development and Distribution License (the "License"). 603831d35Sstevel * You may not use this file except in compliance with the License. 703831d35Sstevel * 803831d35Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 903831d35Sstevel * or http://www.opensolaris.org/os/licensing. 1003831d35Sstevel * See the License for the specific language governing permissions 1103831d35Sstevel * and limitations under the License. 1203831d35Sstevel * 1303831d35Sstevel * When distributing Covered Code, include this CDDL HEADER in each 1403831d35Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1503831d35Sstevel * If applicable, add the following below this CDDL HEADER, with the 1603831d35Sstevel * fields enclosed by brackets "[]" replaced with your own identifying 1703831d35Sstevel * information: Portions Copyright [yyyy] [name of copyright owner] 1803831d35Sstevel * 1903831d35Sstevel * CDDL HEADER END 2003831d35Sstevel */ 2103831d35Sstevel 2203831d35Sstevel /* 23*19397407SSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2403831d35Sstevel * Use is subject to license terms. 2503831d35Sstevel */ 2603831d35Sstevel 2703831d35Sstevel 2803831d35Sstevel #include <sys/types.h> 2903831d35Sstevel #include <sys/conf.h> 3003831d35Sstevel #include <sys/file.h> 3103831d35Sstevel #include <sys/ddi.h> 3203831d35Sstevel #include <sys/sunddi.h> 3303831d35Sstevel #include <sys/modctl.h> 3403831d35Sstevel #include <sys/sunndi.h> 3503831d35Sstevel #include <sys/ddi_impldefs.h> 3603831d35Sstevel #include <sys/obpdefs.h> 3703831d35Sstevel #include <sys/cmn_err.h> 3803831d35Sstevel #include <sys/errno.h> 3903831d35Sstevel #include <sys/debug.h> 4003831d35Sstevel #include <sys/sysmacros.h> 4103831d35Sstevel #include <sys/autoconf.h> 4203831d35Sstevel #include <sys/stat.h> 4303831d35Sstevel #include <sys/kmem.h> 4403831d35Sstevel #include <sys/sgsbbc_mailbox.h> 4503831d35Sstevel #include <sys/sgfrutree.h> 4603831d35Sstevel #include <sys/sgfru_priv.h> 4703831d35Sstevel #include <sys/sgfru_mbox.h> 4803831d35Sstevel 4903831d35Sstevel /* 5003831d35Sstevel * This driver implements the ioctls for the serengeti frutree picl plugin 5103831d35Sstevel * and the serengeti fruaccess library. These are all private, 5203831d35Sstevel * platform-dependent interfaces. 5303831d35Sstevel */ 5403831d35Sstevel 5503831d35Sstevel /* Global Variables */ 5603831d35Sstevel 5703831d35Sstevel #ifdef DEBUG 5803831d35Sstevel uint_t sgfru_debug = 0; 5903831d35Sstevel #endif /* DEBUG */ 6003831d35Sstevel 6103831d35Sstevel /* Opaque state structure pointer */ 6203831d35Sstevel static void *sgfru_statep; /* sgfru soft state hook */ 6303831d35Sstevel 6403831d35Sstevel /* 6503831d35Sstevel * the maximum amount of time this driver is prepared to wait for the mailbox 6603831d35Sstevel * to reply before it decides to timeout. 6703831d35Sstevel */ 6803831d35Sstevel int sgfru_mbox_wait = SGFRU_DEFAULT_MAX_MBOX_WAIT_TIME; 6903831d35Sstevel 7003831d35Sstevel /* Module Variables */ 7103831d35Sstevel 7203831d35Sstevel /* 7303831d35Sstevel * Driver entry points. These are located in sgfru.c so as to 7403831d35Sstevel * not cause a warning for the sgfru adb macro. 7503831d35Sstevel */ 7603831d35Sstevel static struct cb_ops sgfru_cb_ops = { 7703831d35Sstevel sgfru_open, /* open */ 7803831d35Sstevel sgfru_close, /* close */ 7903831d35Sstevel nulldev, /* strategy */ 8003831d35Sstevel nulldev, /* print */ 8103831d35Sstevel nulldev, /* dump */ 8203831d35Sstevel nulldev, /* read */ 8303831d35Sstevel nulldev, /* write */ 8403831d35Sstevel sgfru_ioctl, /* ioctl */ 8503831d35Sstevel nulldev, /* devmap */ 8603831d35Sstevel nulldev, /* mmap */ 8703831d35Sstevel nulldev, /* segmap */ 8803831d35Sstevel nochpoll, /* poll */ 8903831d35Sstevel ddi_prop_op, /* cb_prop_op */ 9003831d35Sstevel NULL, /* streamtab */ 9103831d35Sstevel D_NEW | D_MP /* Driver compatibility flag */ 9203831d35Sstevel }; 9303831d35Sstevel 9403831d35Sstevel static struct dev_ops sgfru_ops = { 9503831d35Sstevel DEVO_REV, /* devo_rev, */ 9603831d35Sstevel 0, /* refcnt */ 9703831d35Sstevel ddi_getinfo_1to1, /* info */ 9803831d35Sstevel nulldev, /* identify */ 9903831d35Sstevel nulldev, /* probe */ 10003831d35Sstevel sgfru_attach, /* attach */ 10103831d35Sstevel sgfru_detach, /* detach */ 10203831d35Sstevel nodev, /* reset */ 10303831d35Sstevel &sgfru_cb_ops, /* driver operations */ 10403831d35Sstevel (struct bus_ops *)0, /* bus operations */ 105*19397407SSherry Moore nulldev, /* power */ 106*19397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */ 10703831d35Sstevel }; 10803831d35Sstevel 10903831d35Sstevel /* 11003831d35Sstevel * Loadable module support. This is located in sgfru.c so as to 111*19397407SSherry Moore * pick up the 1.8 version of sgfru.c. 11203831d35Sstevel */ 11303831d35Sstevel extern struct mod_ops mod_driverops; 11403831d35Sstevel 11503831d35Sstevel static struct modldrv modldrv = { 11603831d35Sstevel &mod_driverops, /* Type of module. This one is a pseudo driver */ 117*19397407SSherry Moore "FRU Driver", 11803831d35Sstevel &sgfru_ops, /* driver ops */ 11903831d35Sstevel }; 12003831d35Sstevel 12103831d35Sstevel static struct modlinkage modlinkage = { 12203831d35Sstevel MODREV_1, 12303831d35Sstevel (void *)&modldrv, 12403831d35Sstevel NULL 12503831d35Sstevel }; 12603831d35Sstevel 12703831d35Sstevel int 12803831d35Sstevel _init(void) 12903831d35Sstevel { 13003831d35Sstevel int error = 0; 13103831d35Sstevel 13203831d35Sstevel /* Allocate the soft state info and add the module. */ 13303831d35Sstevel if ((error = ddi_soft_state_init(&sgfru_statep, 13403831d35Sstevel sizeof (sgfru_soft_state_t), 1)) == 0 && 13503831d35Sstevel (error = mod_install(&modlinkage)) != 0) { 13603831d35Sstevel ddi_soft_state_fini(&sgfru_statep); 13703831d35Sstevel } 13803831d35Sstevel return (error); 13903831d35Sstevel } 14003831d35Sstevel 14103831d35Sstevel int 14203831d35Sstevel _fini(void) 14303831d35Sstevel { 14403831d35Sstevel int error = 0; 14503831d35Sstevel 14603831d35Sstevel /* Remove the module and free the soft state info. */ 14703831d35Sstevel if ((error = mod_remove(&modlinkage)) == 0) { 14803831d35Sstevel ddi_soft_state_fini(&sgfru_statep); 14903831d35Sstevel } 15003831d35Sstevel return (error); 15103831d35Sstevel } 15203831d35Sstevel 15303831d35Sstevel int 15403831d35Sstevel _info(struct modinfo *modinfop) 15503831d35Sstevel { 15603831d35Sstevel return (mod_info(&modlinkage, modinfop)); 15703831d35Sstevel } 15803831d35Sstevel 15903831d35Sstevel static int 16003831d35Sstevel sgfru_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 16103831d35Sstevel { 16203831d35Sstevel sgfru_soft_state_t *softsp; 16303831d35Sstevel int instance; 16403831d35Sstevel int error; 16503831d35Sstevel static fn_t f = "sgfru_attach"; 16603831d35Sstevel 16703831d35Sstevel switch (cmd) { 16803831d35Sstevel case DDI_ATTACH: 16903831d35Sstevel instance = ddi_get_instance(dip); 17003831d35Sstevel 17103831d35Sstevel error = ddi_soft_state_zalloc(sgfru_statep, instance); 17203831d35Sstevel if (error != DDI_SUCCESS) { 17303831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: cannot allocate fru state " 17403831d35Sstevel "for inst %d.", f, instance); 17503831d35Sstevel return (DDI_FAILURE); 17603831d35Sstevel } 17703831d35Sstevel softsp = ddi_get_soft_state(sgfru_statep, instance); 17803831d35Sstevel if (softsp == NULL) { 17903831d35Sstevel ddi_soft_state_free(sgfru_statep, instance); 18003831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: could not get state " 18103831d35Sstevel "structure for inst %d.", f, instance); 18203831d35Sstevel return (DDI_FAILURE); 18303831d35Sstevel } 18403831d35Sstevel softsp->fru_dip = dip; 18503831d35Sstevel softsp->fru_pdip = ddi_get_parent(softsp->fru_dip); 18603831d35Sstevel softsp->instance = instance; 18703831d35Sstevel 18803831d35Sstevel error = ddi_create_minor_node(dip, SGFRU_DRV_NAME, S_IFCHR, 18903831d35Sstevel instance, DDI_PSEUDO, NULL); 19003831d35Sstevel if (error == DDI_FAILURE) { 19103831d35Sstevel ddi_soft_state_free(sgfru_statep, instance); 19203831d35Sstevel return (DDI_FAILURE); 19303831d35Sstevel } 19403831d35Sstevel 19503831d35Sstevel ddi_report_dev(dip); 19603831d35Sstevel 19703831d35Sstevel return (DDI_SUCCESS); 19803831d35Sstevel 19903831d35Sstevel case DDI_RESUME: 20003831d35Sstevel return (DDI_SUCCESS); 20103831d35Sstevel 20203831d35Sstevel default: 20303831d35Sstevel return (DDI_FAILURE); 20403831d35Sstevel } 20503831d35Sstevel } 20603831d35Sstevel 20703831d35Sstevel static int 20803831d35Sstevel sgfru_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 20903831d35Sstevel { 21003831d35Sstevel int instance; 21103831d35Sstevel sgfru_soft_state_t *softsp; 21203831d35Sstevel static fn_t f = "sgfru_detach"; 21303831d35Sstevel 21403831d35Sstevel instance = ddi_get_instance(dip); 21503831d35Sstevel 21603831d35Sstevel softsp = ddi_get_soft_state(sgfru_statep, instance); 21703831d35Sstevel if (softsp == NULL) { 21803831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: could not get state " 21903831d35Sstevel "structure for inst %d.", f, instance); 22003831d35Sstevel return (DDI_FAILURE); 22103831d35Sstevel } 22203831d35Sstevel 22303831d35Sstevel switch (cmd) { 22403831d35Sstevel case DDI_DETACH: 22503831d35Sstevel ddi_soft_state_free(sgfru_statep, instance); 22603831d35Sstevel ddi_remove_minor_node(dip, NULL); 22703831d35Sstevel return (DDI_SUCCESS); 22803831d35Sstevel 22903831d35Sstevel case DDI_SUSPEND: 23003831d35Sstevel return (DDI_SUCCESS); 23103831d35Sstevel 23203831d35Sstevel default: 23303831d35Sstevel return (DDI_FAILURE); 23403831d35Sstevel } 23503831d35Sstevel } 23603831d35Sstevel 23703831d35Sstevel /*ARGSUSED*/ 23803831d35Sstevel static int 23903831d35Sstevel sgfru_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p) 24003831d35Sstevel { 24103831d35Sstevel int error = 0; 24203831d35Sstevel int instance = getminor(*dev_p); 24303831d35Sstevel sgfru_soft_state_t *softsp; 24403831d35Sstevel static fn_t f = "sgfru_open"; 24503831d35Sstevel 24603831d35Sstevel if ((error = drv_priv(cred_p)) != 0) { 24703831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: inst %d drv_priv failed", 24803831d35Sstevel f, instance); 24903831d35Sstevel return (error); 25003831d35Sstevel } 25103831d35Sstevel softsp = (sgfru_soft_state_t *)ddi_get_soft_state(sgfru_statep, 25203831d35Sstevel instance); 25303831d35Sstevel if (softsp == (sgfru_soft_state_t *)NULL) { 25403831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: inst %d ddi_get_soft_state failed", 25503831d35Sstevel f, instance); 25603831d35Sstevel return (ENXIO); 25703831d35Sstevel } 25803831d35Sstevel return (error); 25903831d35Sstevel } 26003831d35Sstevel 26103831d35Sstevel /*ARGSUSED*/ 26203831d35Sstevel static int 26303831d35Sstevel sgfru_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 26403831d35Sstevel { 26503831d35Sstevel int instance = getminor(dev); 26603831d35Sstevel sgfru_soft_state_t *softsp = (sgfru_soft_state_t *) 26703831d35Sstevel ddi_get_soft_state(sgfru_statep, instance); 26803831d35Sstevel 26903831d35Sstevel if (softsp == (sgfru_soft_state_t *)NULL) 27003831d35Sstevel return (ENXIO); 27103831d35Sstevel return (DDI_SUCCESS); 27203831d35Sstevel } 27303831d35Sstevel 27403831d35Sstevel /* 27503831d35Sstevel * This function disperses the ioctls from the serengeti libpiclfruhier plugin 27603831d35Sstevel * and the serengeti libpiclfruaccess library to the appropriate sub-functions. 27703831d35Sstevel */ 27803831d35Sstevel /*ARGSUSED*/ 27903831d35Sstevel static int 28003831d35Sstevel sgfru_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p, 28103831d35Sstevel int *rval_p) 28203831d35Sstevel { 28303831d35Sstevel sgfru_soft_state_t *softsp; 28403831d35Sstevel int instance = getminor(dev); 28503831d35Sstevel sgfru_init_arg_t init_arg; 28603831d35Sstevel int32_t ret = 0; 28703831d35Sstevel static fn_t f = "sgfru_ioctl"; 28803831d35Sstevel 28903831d35Sstevel 29003831d35Sstevel softsp = ddi_get_soft_state(sgfru_statep, instance); 29103831d35Sstevel if (softsp == NULL) { 29203831d35Sstevel return (ENXIO); 29303831d35Sstevel } 29403831d35Sstevel PR_STATE("sgfru:%s: dev %lx cmd %d, instance %d\n", 29503831d35Sstevel f, dev, cmd, instance); 29603831d35Sstevel 29703831d35Sstevel init_arg.dev = dev; 29803831d35Sstevel init_arg.cmd = cmd; 29903831d35Sstevel init_arg.mode = mode; 30003831d35Sstevel init_arg.argp = arg; 30103831d35Sstevel 30203831d35Sstevel switch (cmd) { 30303831d35Sstevel 30403831d35Sstevel case SGFRU_GETSECTIONS: 30503831d35Sstevel ret = sgfru_getsections(&init_arg); 30603831d35Sstevel break; 30703831d35Sstevel 30803831d35Sstevel case SGFRU_GETSEGMENTS: 30903831d35Sstevel ret = sgfru_getsegments(&init_arg); 31003831d35Sstevel break; 31103831d35Sstevel 31203831d35Sstevel case SGFRU_ADDSEGMENT: 31303831d35Sstevel ret = sgfru_addsegment(&init_arg); 31403831d35Sstevel break; 31503831d35Sstevel 31603831d35Sstevel case SGFRU_READRAWSEGMENT: 31703831d35Sstevel ret = sgfru_readsegment(&init_arg); 31803831d35Sstevel break; 31903831d35Sstevel 32003831d35Sstevel case SGFRU_WRITERAWSEGMENT: 32103831d35Sstevel ret = sgfru_writesegment(&init_arg); 32203831d35Sstevel break; 32303831d35Sstevel 32403831d35Sstevel case SGFRU_GETPACKETS: 32503831d35Sstevel ret = sgfru_getpackets(&init_arg); 32603831d35Sstevel break; 32703831d35Sstevel 32803831d35Sstevel case SGFRU_APPENDPACKET: 32903831d35Sstevel ret = sgfru_appendpacket(&init_arg); 33003831d35Sstevel break; 33103831d35Sstevel 33203831d35Sstevel case SGFRU_GETPAYLOAD: 33303831d35Sstevel ret = sgfru_getpayload(&init_arg); 33403831d35Sstevel break; 33503831d35Sstevel 33603831d35Sstevel case SGFRU_UPDATEPAYLOAD: 33703831d35Sstevel ret = sgfru_updatepayload(&init_arg); 33803831d35Sstevel break; 33903831d35Sstevel 34003831d35Sstevel case SGFRU_GETNUMSECTIONS: 34103831d35Sstevel case SGFRU_GETNUMSEGMENTS: 34203831d35Sstevel case SGFRU_GETNUMPACKETS: 34303831d35Sstevel ret = sgfru_getnum(&init_arg); 34403831d35Sstevel break; 34503831d35Sstevel 34603831d35Sstevel case SGFRU_DELETESEGMENT: 34703831d35Sstevel case SGFRU_DELETEPACKET: 34803831d35Sstevel ret = sgfru_delete(&init_arg); 34903831d35Sstevel break; 35003831d35Sstevel 35103831d35Sstevel case SGFRU_GETCHILDLIST: 35203831d35Sstevel ret = sgfru_getchildlist(&init_arg); 35303831d35Sstevel break; 35403831d35Sstevel 35503831d35Sstevel case SGFRU_GETCHILDHANDLES: 35603831d35Sstevel ret = sgfru_getchildhandles(&init_arg); 35703831d35Sstevel break; 35803831d35Sstevel 35903831d35Sstevel case SGFRU_GETNODEINFO: 36003831d35Sstevel ret = sgfru_getnodeinfo(&init_arg); 36103831d35Sstevel break; 36203831d35Sstevel 36303831d35Sstevel default: 36403831d35Sstevel ret = EINVAL; 36503831d35Sstevel break; 36603831d35Sstevel } 36703831d35Sstevel 36803831d35Sstevel return (ret); 36903831d35Sstevel } 37003831d35Sstevel 37103831d35Sstevel /* 37203831d35Sstevel * Used for private SGFRU_GETCHILDLIST ioctl. 37303831d35Sstevel */ 37403831d35Sstevel static int 37503831d35Sstevel sgfru_getchildlist(const sgfru_init_arg_t *iargp) 37603831d35Sstevel { 37703831d35Sstevel int32_t ret; 37803831d35Sstevel caddr_t datap; 37903831d35Sstevel size_t ssize, size; 38003831d35Sstevel frup_info_t clist; 38103831d35Sstevel fru_cnt_t max_cnt; 38203831d35Sstevel node_t *clistp; 38303831d35Sstevel static fn_t f = "sgfru_getchildlist"; 38403831d35Sstevel 38503831d35Sstevel /* copyin child_info_t aka frup_info_t */ 38603831d35Sstevel if (sgfru_copyin_frup(iargp, &clist) != 0) { 38703831d35Sstevel return (EFAULT); 38803831d35Sstevel } 38903831d35Sstevel 39003831d35Sstevel /* check on kmem_alloc space requirements */ 39103831d35Sstevel max_cnt = clist.fru_cnt; 39203831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_HANDLES)) { 39303831d35Sstevel return (EINVAL); 39403831d35Sstevel } 39503831d35Sstevel 39603831d35Sstevel /* allocate buffer for unpadded fru_info_t + node_t's */ 39703831d35Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * NODE_SIZE)); 39803831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 39903831d35Sstevel PR_NODE("sgfru:%s: FRU_INFO_SIZE %lu NODE_SIZE %lu size %lu\n", 40003831d35Sstevel f, FRU_INFO_SIZE, NODE_SIZE, size); 40103831d35Sstevel PR_NODE("sgfru:%s: handle %lx cnt %d buffer 0x%p\n", f, 40203831d35Sstevel clist.fru_hdl, clist.fru_cnt, clist.frus); 40303831d35Sstevel 40403831d35Sstevel /* call mailbox */ 40503831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &clist.fru_info)) 40603831d35Sstevel != 0) { 40703831d35Sstevel kmem_free(datap, size); 40803831d35Sstevel return (ret); 40903831d35Sstevel } 41003831d35Sstevel 41103831d35Sstevel /* allocate buffer for padded node_t's */ 41203831d35Sstevel ssize = (size_t)(max_cnt * sizeof (node_t)); 41303831d35Sstevel clistp = (node_t *)kmem_zalloc(ssize, KM_SLEEP); 41403831d35Sstevel 41503831d35Sstevel /* translate unpadded to padded fru_info_t + node_t's */ 41603831d35Sstevel if ((ret = sgfru_node_pad(datap, max_cnt, &clist.fru_info, clistp)) 41703831d35Sstevel != 0) { 41803831d35Sstevel kmem_free(datap, size); 41903831d35Sstevel kmem_free(clistp, ssize); 42003831d35Sstevel return (ret); 42103831d35Sstevel } 42203831d35Sstevel /* free node_t buffer */ 42303831d35Sstevel kmem_free(datap, size); 42403831d35Sstevel 42503831d35Sstevel /* copy out fru_info_t */ 42603831d35Sstevel if (sgfru_copyout_fru(iargp, &clist.fru_info) != 0) { 42703831d35Sstevel kmem_free(clistp, ssize); 42803831d35Sstevel return (EFAULT); 42903831d35Sstevel } 43003831d35Sstevel /* copyout node_t's */ 43103831d35Sstevel if (sgfru_copyout_nodes(iargp, &clist, clistp) != 0) { 43203831d35Sstevel kmem_free(clistp, ssize); 43303831d35Sstevel return (EFAULT); 43403831d35Sstevel } 43503831d35Sstevel /* free node_t buffer */ 43603831d35Sstevel kmem_free(clistp, ssize); 43703831d35Sstevel 43803831d35Sstevel return (ret); 43903831d35Sstevel } 44003831d35Sstevel 44103831d35Sstevel /* 44203831d35Sstevel * Used for private SGFRU_GETCHILDHANDLES ioctl. 44303831d35Sstevel */ 44403831d35Sstevel static int 44503831d35Sstevel sgfru_getchildhandles(const sgfru_init_arg_t *iargp) 44603831d35Sstevel { 44703831d35Sstevel int32_t ret; 44803831d35Sstevel size_t size; 44903831d35Sstevel caddr_t datap, tdatap; 45003831d35Sstevel frup_info_t hdls; 45103831d35Sstevel fru_info_t hinfo; 45203831d35Sstevel fru_cnt_t max_cnt; 45303831d35Sstevel static fn_t f = "sgfru_getchildhandles"; 45403831d35Sstevel 45503831d35Sstevel /* copyin handles_t aka frup_info_t */ 45603831d35Sstevel if (sgfru_copyin_frup(iargp, &hdls) != 0) { 45703831d35Sstevel return (EFAULT); 45803831d35Sstevel } 45903831d35Sstevel PR_HANDLE("sgfru:%s: handle %lx\n", f, hdls.fru_hdl); 46003831d35Sstevel 46103831d35Sstevel /* check on kmem_alloc space requirements */ 46203831d35Sstevel max_cnt = hdls.fru_cnt; 46303831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_HANDLES)) { 46403831d35Sstevel return (EINVAL); 46503831d35Sstevel } 46603831d35Sstevel 46703831d35Sstevel /* allocate buffer for child fru_hdl_t's */ 46803831d35Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * FRU_HDL_SIZE)); 46903831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 47003831d35Sstevel 47103831d35Sstevel /* call mailbox */ 47203831d35Sstevel ret = sgfru_mbox(iargp->cmd, datap, size, &hdls.fru_info); 47303831d35Sstevel if (ret != 0) { 47403831d35Sstevel kmem_free(datap, size); 47503831d35Sstevel return (ret); 47603831d35Sstevel } 47703831d35Sstevel 47803831d35Sstevel /* translate unpadded to fru_info_t */ 47903831d35Sstevel tdatap = sgfru_fru_pad(datap, &hinfo); 48003831d35Sstevel 48103831d35Sstevel /* copyout actual fru_cnt */ 48203831d35Sstevel if (sgfru_copyout_fru(iargp, &hinfo) != 0) { 48303831d35Sstevel kmem_free(datap, size); 48403831d35Sstevel return (EFAULT); 48503831d35Sstevel } 48603831d35Sstevel PR_HANDLE("sgfru:%s: count %x\n", f, hinfo.cnt); 48703831d35Sstevel 48803831d35Sstevel /* copyout fru_hdl_t's */ 48903831d35Sstevel if (sgfru_copyout_handles(iargp, &hdls, (fru_hdl_t *)tdatap) != 0) { 49003831d35Sstevel kmem_free(datap, size); 49103831d35Sstevel return (EFAULT); 49203831d35Sstevel } 49303831d35Sstevel 49403831d35Sstevel /* free datap buffer */ 49503831d35Sstevel kmem_free(datap, size); 49603831d35Sstevel 49703831d35Sstevel return (ret); 49803831d35Sstevel } 49903831d35Sstevel 50003831d35Sstevel /* 50103831d35Sstevel * Used for private SGFRU_GETNODEINFO ioctl. 50203831d35Sstevel */ 50303831d35Sstevel static int 50403831d35Sstevel sgfru_getnodeinfo(const sgfru_init_arg_t *iargp) 50503831d35Sstevel { 50603831d35Sstevel int32_t ret; 50703831d35Sstevel caddr_t datap; 50803831d35Sstevel size_t size; 50903831d35Sstevel frup_info_t nodeinfo; 51003831d35Sstevel node_t node; 51103831d35Sstevel static fn_t f = "sgfru_getnodeinfo"; 51203831d35Sstevel 51303831d35Sstevel /* copyin node_info_t aka frup_info_t */ 51403831d35Sstevel if (sgfru_copyin_frup(iargp, &nodeinfo) != 0) { 51503831d35Sstevel return (EFAULT); 51603831d35Sstevel } 51703831d35Sstevel 51803831d35Sstevel /* allocate unpadded buffer for node_t */ 51903831d35Sstevel size = (size_t)(NODE_SIZE); 52003831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 52103831d35Sstevel 52203831d35Sstevel PR_NODE("sgfru:%s: handle %lx size 0x%lx\n", f, nodeinfo.fru_hdl, size); 52303831d35Sstevel /* call mailbox */ 52403831d35Sstevel ret = sgfru_mbox(iargp->cmd, datap, size, &nodeinfo.fru_info); 52503831d35Sstevel if (ret != 0) { 52603831d35Sstevel kmem_free(datap, size); 52703831d35Sstevel return (ret); 52803831d35Sstevel } 52903831d35Sstevel 53003831d35Sstevel /* translate unpadded to padded node_t */ 53103831d35Sstevel if ((ret = sgfru_node_pad(datap, 0, NULL, &node)) 53203831d35Sstevel != 0) { 53303831d35Sstevel kmem_free(datap, size); 53403831d35Sstevel return (ret); 53503831d35Sstevel } 53603831d35Sstevel 53703831d35Sstevel /* free node_t buffer */ 53803831d35Sstevel kmem_free(datap, size); 53903831d35Sstevel 54003831d35Sstevel /* copyout node_t */ 54103831d35Sstevel if (sgfru_copyout_nodes(iargp, &nodeinfo, &node) != 0) { 54203831d35Sstevel return (EFAULT); 54303831d35Sstevel } 54403831d35Sstevel PR_NODE("sgfru:%s: handle %lx nodename %s has_children %d class %d\n", 54503831d35Sstevel f, node.handle, node.nodename, node.has_children, node.class); 54603831d35Sstevel 54703831d35Sstevel return (ret); 54803831d35Sstevel } 54903831d35Sstevel 55003831d35Sstevel /* 55103831d35Sstevel * Used for fru_get_sections(). 55203831d35Sstevel */ 55303831d35Sstevel static int 55403831d35Sstevel sgfru_getsections(const sgfru_init_arg_t *iargp) 55503831d35Sstevel { 55603831d35Sstevel int32_t ret; 55703831d35Sstevel caddr_t datap; 55803831d35Sstevel size_t ssize, size; 55903831d35Sstevel frup_info_t sects; 56003831d35Sstevel fru_cnt_t max_cnt; 56103831d35Sstevel section_t *sectp; 56203831d35Sstevel 56303831d35Sstevel /* copyin sections_t aka frup_info_t */ 56403831d35Sstevel if (sgfru_copyin_frup(iargp, §s) != 0) { 56503831d35Sstevel return (EFAULT); 56603831d35Sstevel } 56703831d35Sstevel /* check on kmem_alloc space requirements */ 56803831d35Sstevel max_cnt = sects.fru_cnt; 56903831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_SECTIONS)) { 57003831d35Sstevel return (EINVAL); 57103831d35Sstevel } 57203831d35Sstevel 57303831d35Sstevel /* allocate buffer for unpadded fru_info_t + section_t's */ 57403831d35Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * SECTION_SIZE)); 57503831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 57603831d35Sstevel 57703831d35Sstevel /* call mailbox */ 57803831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, §s.fru_info)) 57903831d35Sstevel != 0) { 58003831d35Sstevel kmem_free(datap, size); 58103831d35Sstevel return (ret); 58203831d35Sstevel } 58303831d35Sstevel 58403831d35Sstevel /* allocate buffer for padded section_t's */ 58503831d35Sstevel ssize = (size_t)(max_cnt * sizeof (section_t)); 58603831d35Sstevel sectp = (section_t *)kmem_zalloc(ssize, KM_SLEEP); 58703831d35Sstevel 58803831d35Sstevel /* translate unpadded to padded fru_info_t + section_t's */ 58903831d35Sstevel if ((ret = sgfru_section_pad(datap, max_cnt, §s.fru_info, sectp)) 59003831d35Sstevel != 0) { 59103831d35Sstevel kmem_free(datap, size); 59203831d35Sstevel kmem_free(sectp, ssize); 59303831d35Sstevel return (ret); 59403831d35Sstevel } 59503831d35Sstevel /* free section_t buffer */ 59603831d35Sstevel kmem_free(datap, size); 59703831d35Sstevel 59803831d35Sstevel /* copy out fru_info_t */ 59903831d35Sstevel if (sgfru_copyout_fru(iargp, §s.fru_info) != 0) { 60003831d35Sstevel kmem_free(sectp, ssize); 60103831d35Sstevel return (EFAULT); 60203831d35Sstevel } 60303831d35Sstevel /* copyout section_t's */ 60403831d35Sstevel if (sgfru_copyout_sections(iargp, §s, sectp) != 0) { 60503831d35Sstevel kmem_free(sectp, ssize); 60603831d35Sstevel return (EFAULT); 60703831d35Sstevel } 60803831d35Sstevel /* free section_t buffer */ 60903831d35Sstevel kmem_free(sectp, ssize); 61003831d35Sstevel 61103831d35Sstevel return (ret); 61203831d35Sstevel } 61303831d35Sstevel 61403831d35Sstevel /* 61503831d35Sstevel * Used for fru_get_segments(). 61603831d35Sstevel */ 61703831d35Sstevel static int 61803831d35Sstevel sgfru_getsegments(const sgfru_init_arg_t *iargp) 61903831d35Sstevel { 62003831d35Sstevel int32_t ret; 62103831d35Sstevel caddr_t datap; 62203831d35Sstevel size_t ssize, size; 62303831d35Sstevel frup_info_t segs; 62403831d35Sstevel fru_cnt_t max_cnt; 62503831d35Sstevel segment_t *segp; 62603831d35Sstevel 62703831d35Sstevel /* copyin frup_info_t */ 62803831d35Sstevel if (sgfru_copyin_frup(iargp, &segs) != 0) { 62903831d35Sstevel return (EFAULT); 63003831d35Sstevel } 63103831d35Sstevel /* check on kmem_alloc space requirements */ 63203831d35Sstevel max_cnt = segs.fru_cnt; 63303831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_SEGMENTS)) { 63403831d35Sstevel return (EINVAL); 63503831d35Sstevel } 63603831d35Sstevel 63703831d35Sstevel /* allocate unpadded buffer for fru_info_t + segment_t's */ 63803831d35Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * SEGMENT_SIZE)); 63903831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 64003831d35Sstevel 64103831d35Sstevel /* call mailbox */ 64203831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &segs.fru_info)) != 0) { 64303831d35Sstevel kmem_free(datap, size); 64403831d35Sstevel return (ret); 64503831d35Sstevel } 64603831d35Sstevel 64703831d35Sstevel /* allocate buffer for padded segment_t's */ 64803831d35Sstevel ssize = (size_t)(max_cnt * sizeof (segment_t)); 64903831d35Sstevel segp = (segment_t *)kmem_zalloc(ssize, KM_SLEEP); 65003831d35Sstevel 65103831d35Sstevel /* translate unpadded to padded fru_info_t + segment_t's */ 65203831d35Sstevel if ((ret = sgfru_segment_pad(datap, max_cnt, &segs.fru_info, segp)) 65303831d35Sstevel != 0) { 65403831d35Sstevel kmem_free(datap, size); 65503831d35Sstevel kmem_free(segp, ssize); 65603831d35Sstevel return (ret); 65703831d35Sstevel } 65803831d35Sstevel /* free segment_t buffer */ 65903831d35Sstevel kmem_free(datap, size); 66003831d35Sstevel 66103831d35Sstevel /* copy out fru_info_t */ 66203831d35Sstevel if (sgfru_copyout_fru(iargp, &segs.fru_info) != 0) { 66303831d35Sstevel kmem_free(segp, ssize); 66403831d35Sstevel return (EFAULT); 66503831d35Sstevel } 66603831d35Sstevel /* copyout segment_t's */ 66703831d35Sstevel if (sgfru_copyout_segments(iargp, &segs, segp) != 0) { 66803831d35Sstevel kmem_free(segp, ssize); 66903831d35Sstevel return (EFAULT); 67003831d35Sstevel } 67103831d35Sstevel /* free segment_t buffer */ 67203831d35Sstevel kmem_free(segp, ssize); 67303831d35Sstevel 67403831d35Sstevel return (ret); 67503831d35Sstevel } 67603831d35Sstevel 67703831d35Sstevel static int 67803831d35Sstevel sgfru_addsegment(const sgfru_init_arg_t *iargp) 67903831d35Sstevel { 68003831d35Sstevel int32_t ret; 68103831d35Sstevel caddr_t datap; 68203831d35Sstevel size_t size; 68303831d35Sstevel frup_info_t seg; 68403831d35Sstevel segment_t segment; 68503831d35Sstevel fru_hdl_t *hdlp; 68603831d35Sstevel static fn_t f = "sgfru_addsegment"; 68703831d35Sstevel 68803831d35Sstevel /* copyin frup_info_t */ 68903831d35Sstevel if (sgfru_copyin_frup(iargp, &seg) != 0) { 69003831d35Sstevel return (EFAULT); 69103831d35Sstevel } 69203831d35Sstevel /* copyin segment_t */ 69303831d35Sstevel if (sgfru_copyin_segment(iargp, &seg, &segment) != 0) { 69403831d35Sstevel return (EFAULT); 69503831d35Sstevel } 69603831d35Sstevel PR_SEGMENT("sgfru:%s: handle %lx, max cnt %d\n", 69703831d35Sstevel f, seg.fru_hdl, seg.fru_cnt); 69803831d35Sstevel PR_SEGMENT("sgfru:%s: handle %lx, name %s, descriptor 0x%x, " 69903831d35Sstevel "offset 0x%x, length 0x%x\n", f, segment.handle, segment.name, 70003831d35Sstevel segment.descriptor, segment.offset, segment.length); 70103831d35Sstevel 70203831d35Sstevel /* allocate buffer for unpadded section_hdl_t + segment_t */ 70303831d35Sstevel size = (size_t)(SECTION_HDL_SIZE + SEGMENT_SIZE); 70403831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 70503831d35Sstevel /* translate padded to unpadded section_hdl_t + segment_t */ 70603831d35Sstevel sgfru_segment_unpad(&seg.fru_info, &segment, datap); 70703831d35Sstevel 70803831d35Sstevel /* call mailbox */ 70903831d35Sstevel ret = sgfru_mbox(iargp->cmd, datap, size, &seg.fru_info); 71003831d35Sstevel if (ret != 0) { 71103831d35Sstevel kmem_free(datap, size); 71203831d35Sstevel return (ret); 71303831d35Sstevel } 71403831d35Sstevel 71503831d35Sstevel /* copyout updated section_hdl_t */ 71603831d35Sstevel hdlp = (fru_hdl_t *)(datap + sizeof (fru_hdl_t)); 71703831d35Sstevel if (sgfru_copyout_handle(iargp, (void *)iargp->argp, hdlp) != 0) { 71803831d35Sstevel kmem_free(datap, size); 71903831d35Sstevel return (EFAULT); 72003831d35Sstevel } 72103831d35Sstevel /* copyout new segment_hdl_t */ 72203831d35Sstevel if (sgfru_copyout_handle(iargp, seg.frus, --hdlp) != 0) { 72303831d35Sstevel kmem_free(datap, size); 72403831d35Sstevel return (EFAULT); 72503831d35Sstevel } 72603831d35Sstevel /* free segment_t buffer */ 72703831d35Sstevel kmem_free(datap, size); 72803831d35Sstevel 72903831d35Sstevel return (ret); 73003831d35Sstevel } 73103831d35Sstevel 73203831d35Sstevel /* 73303831d35Sstevel * Used for fru_read_segment(). 73403831d35Sstevel */ 73503831d35Sstevel static int 73603831d35Sstevel sgfru_readsegment(const sgfru_init_arg_t *iargp) 73703831d35Sstevel { 73803831d35Sstevel int32_t ret; 73903831d35Sstevel caddr_t datap, tdatap; 74003831d35Sstevel size_t size; 74103831d35Sstevel frup_info_t segs; 74203831d35Sstevel fru_info_t sinfo; 74303831d35Sstevel fru_cnt_t max_cnt; 74403831d35Sstevel static fn_t f = "sgfru_readsegment"; 74503831d35Sstevel 74603831d35Sstevel /* copyin one segments_t aka frup_info_t */ 74703831d35Sstevel if (sgfru_copyin_frup(iargp, &segs) != 0) { 74803831d35Sstevel return (EFAULT); 74903831d35Sstevel } 75003831d35Sstevel /* check on kmem_alloc space requirements */ 75103831d35Sstevel max_cnt = segs.fru_cnt; 75203831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_SEGMENTSIZE)) { 75303831d35Sstevel return (EINVAL); 75403831d35Sstevel } 75503831d35Sstevel PR_SEGMENT("sgfru:%s: handle %lx, max cnt %d\n", 75603831d35Sstevel f, segs.fru_hdl, segs.fru_cnt); 75703831d35Sstevel 75803831d35Sstevel /* allocate unpadded buffer for raw data */ 75903831d35Sstevel size = (size_t)(FRU_INFO_SIZE + max_cnt); 76003831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 76103831d35Sstevel 76203831d35Sstevel /* call mailbox */ 76303831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &segs.fru_info)) != 0) { 76403831d35Sstevel kmem_free(datap, size); 76503831d35Sstevel return (ret); 76603831d35Sstevel } 76703831d35Sstevel 76803831d35Sstevel /* translate unpadded to padded fru_info_t */ 76903831d35Sstevel tdatap = sgfru_fru_pad(datap, &sinfo); 77003831d35Sstevel PR_SEGMENT("sgfru:%s: handle %lx, actual cnt %d\n", 77103831d35Sstevel f, sinfo.hdl, sinfo.cnt); 77203831d35Sstevel 77303831d35Sstevel /* copyout actual fru_cnt */ 77403831d35Sstevel if (sgfru_copyout_fru(iargp, &sinfo) != 0) { 77503831d35Sstevel kmem_free(datap, size); 77603831d35Sstevel return (EFAULT); 77703831d35Sstevel } 77803831d35Sstevel /* copyout raw segment data */ 77903831d35Sstevel if (sgfru_copyout_buffer(iargp, &segs, tdatap) != 0) { 78003831d35Sstevel kmem_free(datap, size); 78103831d35Sstevel return (EFAULT); 78203831d35Sstevel } 78303831d35Sstevel /* free buffer */ 78403831d35Sstevel kmem_free(datap, size); 78503831d35Sstevel 78603831d35Sstevel return (ret); 78703831d35Sstevel } 78803831d35Sstevel 78903831d35Sstevel /* 79003831d35Sstevel * Used for fru_write_segment(). 79103831d35Sstevel */ 79203831d35Sstevel static int 79303831d35Sstevel sgfru_writesegment(const sgfru_init_arg_t *iargp) 79403831d35Sstevel { 79503831d35Sstevel int32_t ret; 79603831d35Sstevel caddr_t datap, tdatap; 79703831d35Sstevel size_t size; 79803831d35Sstevel frup_info_t segs; 79903831d35Sstevel fru_cnt_t max_cnt; 80003831d35Sstevel static fn_t f = "sgfru_writesegment"; 80103831d35Sstevel 80203831d35Sstevel /* copyin frup_info_t */ 80303831d35Sstevel if (sgfru_copyin_frup(iargp, &segs) != 0) { 80403831d35Sstevel return (EFAULT); 80503831d35Sstevel } 80603831d35Sstevel /* check on kmem_alloc space requirements */ 80703831d35Sstevel max_cnt = segs.fru_cnt; 80803831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_SEGMENTSIZE)) { 80903831d35Sstevel return (EINVAL); 81003831d35Sstevel } 81103831d35Sstevel PR_SEGMENT("sgfru:%s: handle %lx, max cnt %d\n", 81203831d35Sstevel f, segs.fru_hdl, segs.fru_cnt); 81303831d35Sstevel 81403831d35Sstevel /* allocate unpadded buffer for fru_info_t + raw data */ 81503831d35Sstevel size = (size_t)(FRU_INFO_SIZE + max_cnt); 81603831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 81703831d35Sstevel 81803831d35Sstevel /* translate padded to unpadded fru_info_t */ 81903831d35Sstevel tdatap = sgfru_fru_unpad(&segs.fru_info, datap); 82003831d35Sstevel 82103831d35Sstevel /* copyin raw segment data */ 82203831d35Sstevel if (sgfru_copyin_buffer(iargp, segs.frus, max_cnt, tdatap) != 0) { 82303831d35Sstevel kmem_free(datap, size); 82403831d35Sstevel return (EFAULT); 82503831d35Sstevel } 82603831d35Sstevel 82703831d35Sstevel /* call mailbox */ 82803831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &segs.fru_info)) != 0) { 82903831d35Sstevel kmem_free(datap, size); 83003831d35Sstevel return (ret); 83103831d35Sstevel } 83203831d35Sstevel /* free buffer */ 83303831d35Sstevel kmem_free(datap, size); 83403831d35Sstevel 83503831d35Sstevel PR_SEGMENT("sgfru:%s: handle %lx, actual cnt %d\n", 83603831d35Sstevel f, segs.fru_hdl, segs.fru_cnt); 83703831d35Sstevel /* copyout updated segment handle and actual fru_cnt */ 83803831d35Sstevel if (sgfru_copyout_fru(iargp, &segs.fru_info) != 0) { 83903831d35Sstevel return (EFAULT); 84003831d35Sstevel } 84103831d35Sstevel 84203831d35Sstevel return (ret); 84303831d35Sstevel } 84403831d35Sstevel 84503831d35Sstevel /* 84603831d35Sstevel * Used for fru_get_packets(). 84703831d35Sstevel */ 84803831d35Sstevel static int 84903831d35Sstevel sgfru_getpackets(const sgfru_init_arg_t *iargp) 85003831d35Sstevel { 85103831d35Sstevel int32_t ret; 85203831d35Sstevel caddr_t datap; 85303831d35Sstevel size_t ssize, size; 85403831d35Sstevel frup_info_t packs; 85503831d35Sstevel fru_cnt_t max_cnt; 85603831d35Sstevel packet_t *packp; 85703831d35Sstevel 85803831d35Sstevel /* copyin packets_t aka frup_info_t */ 85903831d35Sstevel if (sgfru_copyin_frup(iargp, &packs) != 0) { 86003831d35Sstevel return (EFAULT); 86103831d35Sstevel } 86203831d35Sstevel /* check on kmem_alloc space requirements */ 86303831d35Sstevel max_cnt = packs.fru_cnt; 86403831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_PACKETS)) { 86503831d35Sstevel return (EINVAL); 86603831d35Sstevel } 86703831d35Sstevel 86803831d35Sstevel /* allocate buffer for unpadded fru_info_t + packet_t's */ 86903831d35Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * PACKET_SIZE)); 87003831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 87103831d35Sstevel 87203831d35Sstevel /* call mailbox */ 87303831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &packs.fru_info)) 87403831d35Sstevel != 0) { 87503831d35Sstevel kmem_free(datap, size); 87603831d35Sstevel return (ret); 87703831d35Sstevel } 87803831d35Sstevel 87903831d35Sstevel /* allocate buffer for padded packet_t's */ 88003831d35Sstevel ssize = (size_t)(max_cnt * sizeof (packet_t)); 88103831d35Sstevel packp = (packet_t *)kmem_zalloc(ssize, KM_SLEEP); 88203831d35Sstevel 88303831d35Sstevel /* translate unpadded to padded fru_info_t + packet_t's */ 88403831d35Sstevel if ((ret = sgfru_packet_pad(datap, max_cnt, &packs.fru_info, packp)) 88503831d35Sstevel != 0) { 88603831d35Sstevel kmem_free(datap, size); 88703831d35Sstevel kmem_free(packp, ssize); 88803831d35Sstevel return (ret); 88903831d35Sstevel } 89003831d35Sstevel /* free packet_t buffer */ 89103831d35Sstevel kmem_free(datap, size); 89203831d35Sstevel 89303831d35Sstevel /* copy out fru_info_t */ 89403831d35Sstevel if (sgfru_copyout_fru(iargp, &packs.fru_info) != 0) { 89503831d35Sstevel kmem_free(packp, ssize); 89603831d35Sstevel return (EFAULT); 89703831d35Sstevel } 89803831d35Sstevel /* copyout packet_t's */ 89903831d35Sstevel if (sgfru_copyout_packets(iargp, &packs, packp) != 0) { 90003831d35Sstevel kmem_free(packp, ssize); 90103831d35Sstevel return (EFAULT); 90203831d35Sstevel } 90303831d35Sstevel /* free packet_t buffer */ 90403831d35Sstevel kmem_free(packp, ssize); 90503831d35Sstevel 90603831d35Sstevel return (ret); 90703831d35Sstevel } 90803831d35Sstevel 90903831d35Sstevel /* 91003831d35Sstevel * Used for fru_append_packet(). 91103831d35Sstevel */ 91203831d35Sstevel static int 91303831d35Sstevel sgfru_appendpacket(const sgfru_init_arg_t *iargp) 91403831d35Sstevel { 91503831d35Sstevel int32_t ret = 0; 91603831d35Sstevel caddr_t datap, tdatap; 91703831d35Sstevel size_t size; 91803831d35Sstevel append_info_t append; 91903831d35Sstevel fru_cnt_t max_cnt; 92003831d35Sstevel fru_hdl_t *hdlp; 92103831d35Sstevel caddr_t addr; 92203831d35Sstevel 92303831d35Sstevel /* copyin append_info_t */ 92403831d35Sstevel if (sgfru_copyin_append(iargp, &append) != 0) { 92503831d35Sstevel return (EFAULT); 92603831d35Sstevel } 92703831d35Sstevel /* check on kmem_alloc space requirements */ 92803831d35Sstevel max_cnt = append.payload_cnt; 92903831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_PAYLOADSIZE)) { 93003831d35Sstevel return (EINVAL); 93103831d35Sstevel } 93203831d35Sstevel 93303831d35Sstevel /* allocate buffer for unpadded fru_info_t + packet_t + payload */ 93403831d35Sstevel size = (size_t)(FRU_INFO_SIZE + PACKET_SIZE + max_cnt); 93503831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 93603831d35Sstevel /* translate padded to unpadded fru_info_t plus packet_t */ 93703831d35Sstevel tdatap = sgfru_packet_unpad(&append.payload.fru_info, &append.packet, 93803831d35Sstevel datap); 93903831d35Sstevel 94003831d35Sstevel /* copyin payload to the end of the unpadded buffer */ 94103831d35Sstevel if (sgfru_copyin_buffer(iargp, append.payload_data, append.payload_cnt, 94203831d35Sstevel tdatap) != 0) { 94303831d35Sstevel kmem_free(datap, size); 94403831d35Sstevel return (EFAULT); 94503831d35Sstevel } 94603831d35Sstevel 94703831d35Sstevel /* call mailbox */ 94803831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, 94903831d35Sstevel &append.payload.fru_info)) != 0) { 95003831d35Sstevel kmem_free(datap, size); 95103831d35Sstevel return (ret); 95203831d35Sstevel } 95303831d35Sstevel 95403831d35Sstevel /* copyout new packet_hdl_t */ 95503831d35Sstevel hdlp = (fru_hdl_t *)datap; 95603831d35Sstevel if (sgfru_copyout_handle(iargp, (void *)iargp->argp, hdlp) != 0) { 95703831d35Sstevel kmem_free(datap, size); 95803831d35Sstevel return (EFAULT); 95903831d35Sstevel } 96003831d35Sstevel /* copyout updated segment_hdl_t */ 96103831d35Sstevel addr = (caddr_t)(iargp->argp + sizeof (packet_t)); 96203831d35Sstevel if (sgfru_copyout_handle(iargp, addr, ++hdlp) != 0) { 96303831d35Sstevel kmem_free(datap, size); 96403831d35Sstevel return (EFAULT); 96503831d35Sstevel } 96603831d35Sstevel 96703831d35Sstevel /* free buffer */ 96803831d35Sstevel kmem_free(datap, size); 96903831d35Sstevel 97003831d35Sstevel return (ret); 97103831d35Sstevel } 97203831d35Sstevel 97303831d35Sstevel /* 97403831d35Sstevel * Used for fru_get_payload(). 97503831d35Sstevel */ 97603831d35Sstevel static int 97703831d35Sstevel sgfru_getpayload(const sgfru_init_arg_t *iargp) 97803831d35Sstevel { 97903831d35Sstevel int32_t ret; 98003831d35Sstevel caddr_t datap, tdatap; 98103831d35Sstevel size_t size; 98203831d35Sstevel frup_info_t payld; 98303831d35Sstevel fru_info_t pinfo; 98403831d35Sstevel fru_cnt_t max_cnt; 98503831d35Sstevel static fn_t f = "sgfru_getpayload"; 98603831d35Sstevel 98703831d35Sstevel /* copyin payload_t aka frup_info_t */ 98803831d35Sstevel if (sgfru_copyin_frup(iargp, &payld) != 0) { 98903831d35Sstevel return (EFAULT); 99003831d35Sstevel } 99103831d35Sstevel PR_PAYLOAD("sgfru:%s: handle %lx, max cnt %d\n", 99203831d35Sstevel f, payld.fru_hdl, payld.fru_cnt); 99303831d35Sstevel 99403831d35Sstevel /* check on kmem_alloc space requirements */ 99503831d35Sstevel max_cnt = payld.fru_cnt; 99603831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_PAYLOADSIZE)) { 99703831d35Sstevel return (EINVAL); 99803831d35Sstevel } 99903831d35Sstevel 100003831d35Sstevel /* allocate buffer for fru_info_t + payload */ 100103831d35Sstevel size = (size_t)(FRU_INFO_SIZE + max_cnt); 100203831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 100303831d35Sstevel 100403831d35Sstevel /* call mailbox */ 100503831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &payld.fru_info)) 100603831d35Sstevel != 0) { 100703831d35Sstevel kmem_free(datap, size); 100803831d35Sstevel return (ret); 100903831d35Sstevel } 101003831d35Sstevel 101103831d35Sstevel /* translate unpadded to padded fru_info_t */ 101203831d35Sstevel tdatap = sgfru_fru_pad(datap, &pinfo); 101303831d35Sstevel PR_PAYLOAD("sgfru:%s: handle %lx, max cnt %d\n", 101403831d35Sstevel f, pinfo.hdl, pinfo.cnt); 101503831d35Sstevel 101603831d35Sstevel /* copyout actual fru_cnt */ 101703831d35Sstevel if (sgfru_copyout_fru(iargp, &pinfo) != 0) { 101803831d35Sstevel kmem_free(datap, size); 101903831d35Sstevel return (EFAULT); 102003831d35Sstevel } 102103831d35Sstevel /* copyout raw packet data, aka the payload */ 102203831d35Sstevel if (sgfru_copyout_buffer(iargp, &payld, tdatap) != 0) { 102303831d35Sstevel kmem_free(datap, size); 102403831d35Sstevel return (EFAULT); 102503831d35Sstevel } 102603831d35Sstevel 102703831d35Sstevel /* free buffer */ 102803831d35Sstevel kmem_free(datap, size); 102903831d35Sstevel 103003831d35Sstevel return (ret); 103103831d35Sstevel } 103203831d35Sstevel 103303831d35Sstevel /* 103403831d35Sstevel * Used for fru_update_payload(). 103503831d35Sstevel */ 103603831d35Sstevel static int 103703831d35Sstevel sgfru_updatepayload(const sgfru_init_arg_t *iargp) 103803831d35Sstevel { 103903831d35Sstevel int32_t ret; 104003831d35Sstevel caddr_t datap, tdatap; 104103831d35Sstevel size_t size; 104203831d35Sstevel frup_info_t payld; 104303831d35Sstevel fru_cnt_t max_cnt; 104403831d35Sstevel static fn_t f = "sgfru_updatepayload"; 104503831d35Sstevel 104603831d35Sstevel /* copyin frup_info_t */ 104703831d35Sstevel if (sgfru_copyin_frup(iargp, &payld) != 0) { 104803831d35Sstevel return (EFAULT); 104903831d35Sstevel } 105003831d35Sstevel /* check on kmem_alloc space requirements */ 105103831d35Sstevel max_cnt = payld.fru_cnt; 105203831d35Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_PAYLOADSIZE)) { 105303831d35Sstevel return (EINVAL); 105403831d35Sstevel } 105503831d35Sstevel 105603831d35Sstevel /* allocate buffer for fru_info_t + payload */ 105703831d35Sstevel size = (size_t)(FRU_INFO_SIZE + max_cnt); 105803831d35Sstevel datap = kmem_zalloc(size, KM_SLEEP); 105903831d35Sstevel 106003831d35Sstevel /* translate padded to unpadded fru_info_t */ 106103831d35Sstevel tdatap = sgfru_fru_unpad(&payld.fru_info, datap); 106203831d35Sstevel 106303831d35Sstevel /* copyin payload */ 106403831d35Sstevel if (sgfru_copyin_buffer(iargp, payld.frus, max_cnt, tdatap) != 0) { 106503831d35Sstevel kmem_free(datap, size); 106603831d35Sstevel return (EFAULT); 106703831d35Sstevel } 106803831d35Sstevel PR_PAYLOAD("sgfru_updatepayload: handle %lx, actual cnt %d\n", 106903831d35Sstevel payld.fru_hdl, payld.fru_cnt); 107003831d35Sstevel 107103831d35Sstevel /* call mailbox */ 107203831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &payld.fru_info)) 107303831d35Sstevel != 0) { 107403831d35Sstevel kmem_free(datap, size); 107503831d35Sstevel return (ret); 107603831d35Sstevel } 107703831d35Sstevel 107803831d35Sstevel /* free buffer */ 107903831d35Sstevel kmem_free(datap, size); 108003831d35Sstevel 108103831d35Sstevel /* copyout new packet_hdl_t and actual count */ 108203831d35Sstevel if (sgfru_copyout_fru(iargp, &payld.fru_info) != 0) { 108303831d35Sstevel return (EFAULT); 108403831d35Sstevel } 108503831d35Sstevel PR_PAYLOAD("sgfru:%s: new handle %lx, cnt %d\n", 108603831d35Sstevel f, payld.fru_hdl, payld.fru_cnt); 108703831d35Sstevel 108803831d35Sstevel return (ret); 108903831d35Sstevel } 109003831d35Sstevel 109103831d35Sstevel /* 109203831d35Sstevel * Used for fru_get_num_[sections|segments|packets](). 109303831d35Sstevel */ 109403831d35Sstevel static int 109503831d35Sstevel sgfru_getnum(const sgfru_init_arg_t *iargp) 109603831d35Sstevel { 109703831d35Sstevel int32_t ret; 109803831d35Sstevel caddr_t datap; 109903831d35Sstevel size_t size; 110003831d35Sstevel fru_info_t fru_info; 110103831d35Sstevel 110203831d35Sstevel /* copyin fru_info_t */ 110303831d35Sstevel if (sgfru_copyin_fru(iargp, &fru_info) != 0) { 110403831d35Sstevel return (EFAULT); 110503831d35Sstevel } 110603831d35Sstevel 110703831d35Sstevel size = sizeof (fru_cnt_t); 110803831d35Sstevel datap = (caddr_t)&fru_info.cnt; 110903831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &fru_info)) != 0) { 111003831d35Sstevel return (ret); 111103831d35Sstevel } 111203831d35Sstevel 111303831d35Sstevel /* copyout fru_info_t */ 111403831d35Sstevel if (sgfru_copyout_fru(iargp, &fru_info) != 0) { 111503831d35Sstevel return (EFAULT); 111603831d35Sstevel } 111703831d35Sstevel return (ret); 111803831d35Sstevel } 111903831d35Sstevel 112003831d35Sstevel /* 112103831d35Sstevel * Used for fru_delete_[segment|packet]. 112203831d35Sstevel */ 112303831d35Sstevel static int 112403831d35Sstevel sgfru_delete(const sgfru_init_arg_t *iargp) 112503831d35Sstevel { 112603831d35Sstevel int32_t ret; 112703831d35Sstevel caddr_t datap; 112803831d35Sstevel size_t size; 112903831d35Sstevel fru_info_t fru_info; 113003831d35Sstevel static fn_t f = "sgfru_delete"; 113103831d35Sstevel 113203831d35Sstevel /* copyin fru_info_t */ 113303831d35Sstevel if (sgfru_copyin_fru(iargp, &fru_info) != 0) { 113403831d35Sstevel return (EFAULT); 113503831d35Sstevel } 113603831d35Sstevel PR_SEGMENT("sgfru:%s: delete handle %lx\n", f, fru_info.hdl); 113703831d35Sstevel 113803831d35Sstevel size = sizeof (fru_hdl_t); 113903831d35Sstevel datap = (caddr_t)&fru_info.hdl; 114003831d35Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &fru_info)) != 0) { 114103831d35Sstevel return (ret); 114203831d35Sstevel } 114303831d35Sstevel 114403831d35Sstevel PR_SEGMENT("sgfru:%s: new parent handle %lx\n", f, fru_info.hdl); 114503831d35Sstevel /* copyout fru_info_t */ 114603831d35Sstevel if (sgfru_copyout_fru(iargp, &fru_info) != 0) { 114703831d35Sstevel return (EFAULT); 114803831d35Sstevel } 114903831d35Sstevel return (ret); 115003831d35Sstevel } 115103831d35Sstevel 115203831d35Sstevel /* 115303831d35Sstevel * Calls the sgsbbc mailbox with data, returns data and status info. 115403831d35Sstevel */ 115503831d35Sstevel static int 115603831d35Sstevel sgfru_mbox(const int cmd, char *datap, const size_t size, fru_info_t *fru) 115703831d35Sstevel { 115803831d35Sstevel sbbc_msg_t request, *reqp = &request; 115903831d35Sstevel sbbc_msg_t response, *resp = &response; 116003831d35Sstevel fru_hdl_t hdls[2] = {0, 0}; 116103831d35Sstevel fru_hdl_t hdl = fru->hdl; 116203831d35Sstevel int rv = 0; 116303831d35Sstevel static fn_t f = "sgfru_mbox"; 116403831d35Sstevel 116503831d35Sstevel bzero((caddr_t)&request, sizeof (sbbc_msg_t)); 116603831d35Sstevel reqp->msg_type.type = SGFRU_MBOX; 116703831d35Sstevel bzero((caddr_t)&response, sizeof (sbbc_msg_t)); 116803831d35Sstevel resp->msg_type.type = SGFRU_MBOX; 116903831d35Sstevel PR_MBOX("sgfru:%s: cmd 0x%x, size %lu\n", f, cmd, size); 117003831d35Sstevel 117103831d35Sstevel switch (cmd) { 117203831d35Sstevel 117303831d35Sstevel case SGFRU_GETCHILDLIST: 117403831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETCHILDLIST; 117503831d35Sstevel reqp->msg_len = sizeof (fru_info_t); 117603831d35Sstevel reqp->msg_buf = (caddr_t)fru; 117703831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETCHILDLIST; 117803831d35Sstevel resp->msg_len = size; 117903831d35Sstevel resp->msg_buf = datap; 118003831d35Sstevel break; 118103831d35Sstevel 118203831d35Sstevel case SGFRU_GETCHILDHANDLES: 118303831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETCHILDHANDLES; 118403831d35Sstevel reqp->msg_len = sizeof (fru_info_t); 118503831d35Sstevel reqp->msg_buf = (caddr_t)fru; 118603831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETCHILDHANDLES; 118703831d35Sstevel resp->msg_len = size; 118803831d35Sstevel resp->msg_buf = datap; 118903831d35Sstevel break; 119003831d35Sstevel 119103831d35Sstevel case SGFRU_GETNODEINFO: 119203831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETNODEINFO; 119303831d35Sstevel reqp->msg_len = sizeof (fru_hdl_t); 119403831d35Sstevel reqp->msg_buf = (caddr_t)&hdl; 119503831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETNODEINFO; 119603831d35Sstevel resp->msg_len = size; 119703831d35Sstevel resp->msg_buf = datap; 119803831d35Sstevel break; 119903831d35Sstevel 120003831d35Sstevel case SGFRU_GETNUMSECTIONS: 120103831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETNUMSECTIONS; 120203831d35Sstevel reqp->msg_len = sizeof (fru_hdl_t); 120303831d35Sstevel reqp->msg_buf = (caddr_t)&hdl; 120403831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETNUMSECTIONS; 120503831d35Sstevel resp->msg_len = size; 120603831d35Sstevel resp->msg_buf = datap; 120703831d35Sstevel break; 120803831d35Sstevel 120903831d35Sstevel case SGFRU_GETNUMSEGMENTS: 121003831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETNUMSEGMENTS; 121103831d35Sstevel reqp->msg_len = sizeof (fru_hdl_t); 121203831d35Sstevel reqp->msg_buf = (caddr_t)&hdl; 121303831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETNUMSEGMENTS; 121403831d35Sstevel resp->msg_len = size; 121503831d35Sstevel resp->msg_buf = datap; 121603831d35Sstevel break; 121703831d35Sstevel 121803831d35Sstevel case SGFRU_GETNUMPACKETS: 121903831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETNUMPACKETS; 122003831d35Sstevel reqp->msg_len = sizeof (fru_hdl_t); 122103831d35Sstevel reqp->msg_buf = (caddr_t)&hdl; 122203831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETNUMPACKETS; 122303831d35Sstevel resp->msg_len = size; 122403831d35Sstevel resp->msg_buf = datap; 122503831d35Sstevel break; 122603831d35Sstevel 122703831d35Sstevel case SGFRU_GETSECTIONS: 122803831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETSECTIONS; 122903831d35Sstevel reqp->msg_len = sizeof (fru_info_t); 123003831d35Sstevel reqp->msg_buf = (caddr_t)fru; 123103831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETSECTIONS; 123203831d35Sstevel resp->msg_len = size; 123303831d35Sstevel resp->msg_buf = datap; 123403831d35Sstevel break; 123503831d35Sstevel 123603831d35Sstevel case SGFRU_GETSEGMENTS: 123703831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETSEGMENTS; 123803831d35Sstevel reqp->msg_len = sizeof (fru_info_t); 123903831d35Sstevel reqp->msg_buf = (caddr_t)fru; 124003831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETSEGMENTS; 124103831d35Sstevel resp->msg_len = size; 124203831d35Sstevel resp->msg_buf = datap; 124303831d35Sstevel break; 124403831d35Sstevel 124503831d35Sstevel case SGFRU_GETPACKETS: 124603831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETPACKETS; 124703831d35Sstevel reqp->msg_len = sizeof (fru_info_t); 124803831d35Sstevel reqp->msg_buf = (caddr_t)fru; 124903831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETPACKETS; 125003831d35Sstevel resp->msg_len = size; 125103831d35Sstevel resp->msg_buf = datap; 125203831d35Sstevel break; 125303831d35Sstevel 125403831d35Sstevel case SGFRU_ADDSEGMENT: 125503831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_ADDSEGMENT; 125603831d35Sstevel reqp->msg_len = size; 125703831d35Sstevel reqp->msg_buf = datap; 125803831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_ADDSEGMENT; 125903831d35Sstevel resp->msg_len = sizeof (hdls); 126003831d35Sstevel resp->msg_buf = (caddr_t)&hdls; 126103831d35Sstevel break; 126203831d35Sstevel 126303831d35Sstevel case SGFRU_APPENDPACKET: 126403831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_APPENDPACKET; 126503831d35Sstevel reqp->msg_len = size; 126603831d35Sstevel reqp->msg_buf = (caddr_t)datap; 126703831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_APPENDPACKET; 126803831d35Sstevel resp->msg_len = sizeof (hdls); 126903831d35Sstevel resp->msg_buf = (caddr_t)&hdls; 127003831d35Sstevel break; 127103831d35Sstevel 127203831d35Sstevel case SGFRU_DELETESEGMENT: 127303831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_DELETESEGMENT; 127403831d35Sstevel reqp->msg_len = size; 127503831d35Sstevel reqp->msg_buf = (caddr_t)datap; 127603831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_DELETESEGMENT; 127703831d35Sstevel resp->msg_len = sizeof (fru_hdl_t); 127803831d35Sstevel resp->msg_buf = (caddr_t)&hdl; 127903831d35Sstevel break; 128003831d35Sstevel 128103831d35Sstevel case SGFRU_READRAWSEGMENT: 128203831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_READRAWSEGMENT; 128303831d35Sstevel reqp->msg_len = sizeof (fru_info_t); 128403831d35Sstevel reqp->msg_buf = (caddr_t)fru; 128503831d35Sstevel resp->msg_type.sub_type = SGFRU_READRAWSEGMENT; 128603831d35Sstevel resp->msg_len = size; 128703831d35Sstevel resp->msg_buf = datap; 128803831d35Sstevel break; 128903831d35Sstevel 129003831d35Sstevel case SGFRU_WRITERAWSEGMENT: 129103831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_WRITERAWSEGMENT; 129203831d35Sstevel reqp->msg_len = size; 129303831d35Sstevel reqp->msg_buf = datap; 129403831d35Sstevel resp->msg_type.sub_type = SGFRU_WRITERAWSEGMENT; 129503831d35Sstevel resp->msg_len = sizeof (fru_info_t); 129603831d35Sstevel resp->msg_buf = (caddr_t)fru; 129703831d35Sstevel break; 129803831d35Sstevel 129903831d35Sstevel case SGFRU_DELETEPACKET: 130003831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_DELETEPACKET; 130103831d35Sstevel reqp->msg_len = size; 130203831d35Sstevel reqp->msg_buf = (caddr_t)datap; 130303831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_DELETEPACKET; 130403831d35Sstevel resp->msg_len = sizeof (fru_hdl_t); 130503831d35Sstevel resp->msg_buf = (caddr_t)&hdl; 130603831d35Sstevel break; 130703831d35Sstevel 130803831d35Sstevel case SGFRU_GETPAYLOAD: 130903831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETPAYLOAD; 131003831d35Sstevel reqp->msg_len = sizeof (fru_info_t); 131103831d35Sstevel reqp->msg_buf = (caddr_t)fru; 131203831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETPAYLOAD; 131303831d35Sstevel resp->msg_len = size; 131403831d35Sstevel resp->msg_buf = datap; 131503831d35Sstevel break; 131603831d35Sstevel 131703831d35Sstevel case SGFRU_UPDATEPAYLOAD: 131803831d35Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_UPDATEPAYLOAD; 131903831d35Sstevel reqp->msg_len = size; 132003831d35Sstevel reqp->msg_buf = datap; 132103831d35Sstevel resp->msg_type.sub_type = SGFRU_MBOX_UPDATEPAYLOAD; 132203831d35Sstevel resp->msg_len = sizeof (fru_info_t); 132303831d35Sstevel resp->msg_buf = (caddr_t)fru; 132403831d35Sstevel break; 132503831d35Sstevel 132603831d35Sstevel default: 132703831d35Sstevel return (EINVAL); 132803831d35Sstevel } 132903831d35Sstevel 133003831d35Sstevel rv = sbbc_mbox_request_response(reqp, resp, sgfru_mbox_wait); 133103831d35Sstevel PR_MBOX("sgfru:%s: rv %d, msg_status %d\n", f, rv, resp->msg_status); 133203831d35Sstevel 133303831d35Sstevel if ((rv) || (resp->msg_status != SG_MBOX_STATUS_SUCCESS)) { 133403831d35Sstevel 133503831d35Sstevel /* errors from sgsbbc */ 133603831d35Sstevel if (resp->msg_status > 0) { 133703831d35Sstevel return (resp->msg_status); 133803831d35Sstevel } 133903831d35Sstevel 134003831d35Sstevel /* errors from SCAPP */ 134103831d35Sstevel switch (resp->msg_status) { 134203831d35Sstevel 134303831d35Sstevel case SG_MBOX_STATUS_COMMAND_FAILURE: 134403831d35Sstevel /* internal SCAPP error */ 134503831d35Sstevel return (EINTR); 134603831d35Sstevel 134703831d35Sstevel case SG_MBOX_STATUS_HARDWARE_FAILURE: 134803831d35Sstevel /* seprom read/write errors */ 134903831d35Sstevel return (EIO); 135003831d35Sstevel 135103831d35Sstevel case SG_MBOX_STATUS_ILLEGAL_PARAMETER: 135203831d35Sstevel /* illegal ioctl parameter */ 135303831d35Sstevel return (EINVAL); 135403831d35Sstevel 135503831d35Sstevel case SG_MBOX_STATUS_BOARD_ACCESS_DENIED: 135603831d35Sstevel /* board access denied */ 135703831d35Sstevel return (EACCES); 135803831d35Sstevel 135903831d35Sstevel case SG_MBOX_STATUS_STALE_CONTENTS: 136003831d35Sstevel /* stale contents */ 136103831d35Sstevel return (ESTALE); 136203831d35Sstevel 136303831d35Sstevel case SG_MBOX_STATUS_STALE_OBJECT: 136403831d35Sstevel /* stale handle */ 136503831d35Sstevel return (ENOENT); 136603831d35Sstevel 136703831d35Sstevel case SG_MBOX_STATUS_NO_SEPROM_SPACE: 136803831d35Sstevel /* seprom lacks space */ 136903831d35Sstevel return (ENOSPC); 137003831d35Sstevel 137103831d35Sstevel case SG_MBOX_STATUS_NO_MEMORY: 137203831d35Sstevel /* user prog. lacks space */ 137303831d35Sstevel return (ENOMEM); 137403831d35Sstevel 137503831d35Sstevel case SG_MBOX_STATUS_NOT_SUPPORTED: 137603831d35Sstevel /* unsupported operation */ 137703831d35Sstevel return (ENOTSUP); 137803831d35Sstevel 137903831d35Sstevel default: 138003831d35Sstevel return (EIO); 138103831d35Sstevel } 138203831d35Sstevel } 138303831d35Sstevel 138403831d35Sstevel switch (cmd) { 138503831d35Sstevel 138603831d35Sstevel /* 138703831d35Sstevel * These two calls get back two handles, a new handle for the 138803831d35Sstevel * added segment or packet, and an updated parent handle. 138903831d35Sstevel */ 139003831d35Sstevel case SGFRU_ADDSEGMENT: 139103831d35Sstevel case SGFRU_APPENDPACKET: 139203831d35Sstevel bcopy(hdls, datap, sizeof (hdls)); 139303831d35Sstevel break; 139403831d35Sstevel 139503831d35Sstevel /* These two calls get an updated parent handle. */ 139603831d35Sstevel case SGFRU_DELETESEGMENT: 139703831d35Sstevel case SGFRU_DELETEPACKET: 139803831d35Sstevel fru->hdl = hdl; 139903831d35Sstevel break; 140003831d35Sstevel 140103831d35Sstevel default: 140203831d35Sstevel break; 140303831d35Sstevel } 140403831d35Sstevel 140503831d35Sstevel return (0); 140603831d35Sstevel } 140703831d35Sstevel 140803831d35Sstevel /* 140903831d35Sstevel * Used to copy in one frup_info_t from user. 141003831d35Sstevel */ 141103831d35Sstevel static int 141203831d35Sstevel sgfru_copyin_frup(const sgfru_init_arg_t *argp, frup_info_t *frup) 141303831d35Sstevel { 141403831d35Sstevel static fn_t f = "sgfru_copyin_frup"; 141503831d35Sstevel 141603831d35Sstevel bzero((caddr_t)frup, sizeof (frup_info_t)); 141703831d35Sstevel #ifdef _MULTI_DATAMODEL 141803831d35Sstevel if (ddi_model_convert_from(argp->mode & FMODELS) == DDI_MODEL_ILP32) { 141903831d35Sstevel frup32_info_t frup32; 142003831d35Sstevel 142103831d35Sstevel bzero((caddr_t)&frup32, sizeof (frup32_info_t)); 142203831d35Sstevel if (ddi_copyin((void *)argp->argp, (void *)&frup32, 142303831d35Sstevel sizeof (frup32_info_t), argp->mode) != DDI_SUCCESS) { 142403831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: (32 bit) failed to copyin " 142503831d35Sstevel "frup32_t struct", f); 142603831d35Sstevel return (EFAULT); 142703831d35Sstevel } 142803831d35Sstevel frup->fru_hdl = frup32.fru_hdl; 142903831d35Sstevel frup->fru_cnt = frup32.fru_cnt; 143003831d35Sstevel frup->frus = (void *)(uintptr_t)frup32.frus; 143103831d35Sstevel PR_STATE("sgfru:%s: frus %p %x hdl %lx cnt %d\n", 143203831d35Sstevel f, frup->frus, frup32.frus, frup->fru_hdl, frup->fru_cnt); 143303831d35Sstevel 143403831d35Sstevel } else 143503831d35Sstevel #endif /* _MULTI_DATAMODEL */ 143603831d35Sstevel if (ddi_copyin((void *)argp->argp, (void *)frup, 143703831d35Sstevel sizeof (frup_info_t), argp->mode) != DDI_SUCCESS) { 143803831d35Sstevel cmn_err(CE_WARN, 143903831d35Sstevel "sgfru:%s: failed to copyin frup_info_t struct", f); 144003831d35Sstevel return (EFAULT); 144103831d35Sstevel } 144203831d35Sstevel return (0); 144303831d35Sstevel } 144403831d35Sstevel 144503831d35Sstevel /* 144603831d35Sstevel * Used to copy in one fru_info_t from user. 144703831d35Sstevel */ 144803831d35Sstevel static int 144903831d35Sstevel sgfru_copyin_fru(const sgfru_init_arg_t *argp, fru_info_t *fru) 145003831d35Sstevel { 145103831d35Sstevel static fn_t f = "sgfru_copyin_fru"; 145203831d35Sstevel 145303831d35Sstevel bzero((caddr_t)fru, sizeof (fru_info_t)); 145403831d35Sstevel if (ddi_copyin((void *)argp->argp, (void *)fru, 145503831d35Sstevel sizeof (fru_info_t), argp->mode) != DDI_SUCCESS) { 145603831d35Sstevel cmn_err(CE_WARN, 145703831d35Sstevel "sgfru:%s: failed to copyin fru_info_t struct", f); 145803831d35Sstevel return (EFAULT); 145903831d35Sstevel } 146003831d35Sstevel return (0); 146103831d35Sstevel } 146203831d35Sstevel 146303831d35Sstevel /* 146403831d35Sstevel * Used to copy in segment_t from user. 146503831d35Sstevel */ 146603831d35Sstevel static int 146703831d35Sstevel sgfru_copyin_segment(const sgfru_init_arg_t *argp, const frup_info_t *frup, 146803831d35Sstevel segment_t *segp) 146903831d35Sstevel { 147003831d35Sstevel static fn_t f = "sgfru_copyin_segment"; 147103831d35Sstevel 147203831d35Sstevel bzero((caddr_t)segp, sizeof (segment_t)); 147303831d35Sstevel if (ddi_copyin((void *)frup->frus, (void *)segp, 147403831d35Sstevel sizeof (segment_t), argp->mode) != DDI_SUCCESS) { 147503831d35Sstevel cmn_err(CE_WARN, 147603831d35Sstevel "sgfru:%s: failed to copyin segment_t struct", f); 147703831d35Sstevel return (EFAULT); 147803831d35Sstevel } 147903831d35Sstevel return (0); 148003831d35Sstevel } 148103831d35Sstevel 148203831d35Sstevel /* 148303831d35Sstevel * Used to copy in segment handle, packet and payload data from user. 148403831d35Sstevel */ 148503831d35Sstevel static int 148603831d35Sstevel sgfru_copyin_append(const sgfru_init_arg_t *argp, append_info_t *app) 148703831d35Sstevel { 148803831d35Sstevel static fn_t f = "sgfru_copyin_append"; 148903831d35Sstevel 149003831d35Sstevel bzero((caddr_t)app, sizeof (append_info_t)); 149103831d35Sstevel #ifdef _MULTI_DATAMODEL 149203831d35Sstevel if (ddi_model_convert_from(argp->mode & FMODELS) == DDI_MODEL_ILP32) { 149303831d35Sstevel append32_info_t app32; 149403831d35Sstevel 149503831d35Sstevel bzero((caddr_t)&app32, sizeof (append32_info_t)); 149603831d35Sstevel if (ddi_copyin((void *)argp->argp, (void *)&app32, 149703831d35Sstevel sizeof (append32_info_t), argp->mode) != DDI_SUCCESS) { 149803831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: (32 bit) failed to copyin " 149903831d35Sstevel "append32_info_t struct", f); 150003831d35Sstevel return (EFAULT); 150103831d35Sstevel } 150203831d35Sstevel app->packet = app32.packet; 150303831d35Sstevel app->payload_hdl = app32.payload_hdl; 150403831d35Sstevel app->payload_cnt = app32.payload_cnt; 150503831d35Sstevel app->payload_data = (void *)(uintptr_t)app32.payload_data; 150603831d35Sstevel PR_PAYLOAD("sgfru:%s:: data %p hdl %lx cnt %d\n", 150703831d35Sstevel f, app->payload_data, app->payload_hdl, app->payload_cnt); 150803831d35Sstevel 150903831d35Sstevel } else 151003831d35Sstevel #endif /* _MULTI_DATAMODEL */ 151103831d35Sstevel if (ddi_copyin((void *)argp->argp, (void *)app, 151203831d35Sstevel sizeof (append_info_t), argp->mode) != DDI_SUCCESS) { 151303831d35Sstevel cmn_err(CE_WARN, 151403831d35Sstevel "sgfru:%s: failed to copyin append_info_t struct", f); 151503831d35Sstevel return (EFAULT); 151603831d35Sstevel } 151703831d35Sstevel PR_PAYLOAD("sgfru:%s: hdl %lx, cnt %d pkt hdl %lx " 151803831d35Sstevel "tag %lx\n", f, app->payload_hdl, app->payload_cnt, 151903831d35Sstevel app->packet.handle, app->packet.tag); 152003831d35Sstevel return (0); 152103831d35Sstevel } 152203831d35Sstevel 152303831d35Sstevel /* 152403831d35Sstevel * Used to copy in raw segment and payload data from user. 152503831d35Sstevel */ 152603831d35Sstevel static int 152703831d35Sstevel sgfru_copyin_buffer(const sgfru_init_arg_t *argp, const caddr_t data, 152803831d35Sstevel const int cnt, char *buffer) 152903831d35Sstevel { 153003831d35Sstevel static fn_t f = "sgfru_copyin_buffer"; 153103831d35Sstevel 153203831d35Sstevel if (ddi_copyin((void *)data, (void *)buffer, cnt, argp->mode) 153303831d35Sstevel != DDI_SUCCESS) { 153403831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyin buffer", f); 153503831d35Sstevel return (EFAULT); 153603831d35Sstevel } 153703831d35Sstevel return (0); 153803831d35Sstevel } 153903831d35Sstevel 154003831d35Sstevel /* 154103831d35Sstevel * Used to copy out one fru_info_t to user. 154203831d35Sstevel */ 154303831d35Sstevel static int 154403831d35Sstevel sgfru_copyout_fru(const sgfru_init_arg_t *argp, const fru_info_t *frup) 154503831d35Sstevel { 154603831d35Sstevel static fn_t f = "sgfru_copyout_fru"; 154703831d35Sstevel 154803831d35Sstevel if (ddi_copyout((void *)frup, (void *)argp->argp, 154903831d35Sstevel sizeof (fru_info_t), argp->mode) != DDI_SUCCESS) { 155003831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout fru", f); 155103831d35Sstevel return (EFAULT); 155203831d35Sstevel } 155303831d35Sstevel return (0); 155403831d35Sstevel } 155503831d35Sstevel 155603831d35Sstevel /* 155703831d35Sstevel * Used to copy out one fru_hdl_t to user. 155803831d35Sstevel */ 155903831d35Sstevel static int 156003831d35Sstevel sgfru_copyout_handle(const sgfru_init_arg_t *argp, const void *addr, 156103831d35Sstevel const fru_hdl_t *hdlp) 156203831d35Sstevel { 156303831d35Sstevel static fn_t f = "sgfru_copyout_handle"; 156403831d35Sstevel 156503831d35Sstevel if (ddi_copyout((void *)hdlp, (void *)addr, sizeof (fru_hdl_t), 156603831d35Sstevel argp->mode) != DDI_SUCCESS) { 156703831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout handle", f); 156803831d35Sstevel return (EFAULT); 156903831d35Sstevel } 157003831d35Sstevel return (0); 157103831d35Sstevel } 157203831d35Sstevel 157303831d35Sstevel /* 157403831d35Sstevel * Used to copy out an array of fru_hdl_t's to user. 157503831d35Sstevel */ 157603831d35Sstevel static int 157703831d35Sstevel sgfru_copyout_handles(const sgfru_init_arg_t *argp, const frup_info_t *frup, 157803831d35Sstevel const fru_hdl_t *hdlp) 157903831d35Sstevel { 158003831d35Sstevel static fn_t f = "sgfru_copyout_handles"; 158103831d35Sstevel 158203831d35Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (fru_hdl_t)); 158303831d35Sstevel /* copyout fru_hdl_t's */ 158403831d35Sstevel if (ddi_copyout((void *)hdlp, (void *)frup->frus, size, argp->mode) 158503831d35Sstevel != DDI_SUCCESS) { 158603831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout handles", f); 158703831d35Sstevel return (EFAULT); 158803831d35Sstevel } 158903831d35Sstevel return (0); 159003831d35Sstevel } 159103831d35Sstevel 159203831d35Sstevel /* 159303831d35Sstevel * Used to copy out one or more node_t's to user. 159403831d35Sstevel */ 159503831d35Sstevel static int 159603831d35Sstevel sgfru_copyout_nodes(const sgfru_init_arg_t *argp, const frup_info_t *frup, 159703831d35Sstevel const node_t *nodep) 159803831d35Sstevel { 159903831d35Sstevel static fn_t f = "sgfru_copyout_nodes"; 160003831d35Sstevel 160103831d35Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (node_t)); 160203831d35Sstevel /* copyout node_t's */ 160303831d35Sstevel if (ddi_copyout((void *)nodep, (void *)frup->frus, size, argp->mode) 160403831d35Sstevel != DDI_SUCCESS) { 160503831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout nodes", f); 160603831d35Sstevel return (EFAULT); 160703831d35Sstevel } 160803831d35Sstevel return (0); 160903831d35Sstevel } 161003831d35Sstevel 161103831d35Sstevel /* 161203831d35Sstevel * Used to copy out section_t's to user. 161303831d35Sstevel */ 161403831d35Sstevel static int 161503831d35Sstevel sgfru_copyout_sections(const sgfru_init_arg_t *argp, const frup_info_t *frup, 161603831d35Sstevel const section_t *sectp) 161703831d35Sstevel { 161803831d35Sstevel static fn_t f = "sgfru_copyout_sections"; 161903831d35Sstevel 162003831d35Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (section_t)); 162103831d35Sstevel /* copyout section_t's */ 162203831d35Sstevel if (ddi_copyout((void *)sectp, (void *)frup->frus, size, argp->mode) 162303831d35Sstevel != DDI_SUCCESS) { 162403831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout sections", f); 162503831d35Sstevel return (EFAULT); 162603831d35Sstevel } 162703831d35Sstevel return (0); 162803831d35Sstevel } 162903831d35Sstevel 163003831d35Sstevel /* 163103831d35Sstevel * Used to copy out segment_t's to user. 163203831d35Sstevel */ 163303831d35Sstevel static int 163403831d35Sstevel sgfru_copyout_segments(const sgfru_init_arg_t *argp, const frup_info_t *frup, 163503831d35Sstevel const segment_t *segp) 163603831d35Sstevel { 163703831d35Sstevel static fn_t f = "sgfru_copyout_segments"; 163803831d35Sstevel 163903831d35Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (segment_t)); 164003831d35Sstevel /* copyout segment_t's */ 164103831d35Sstevel if (ddi_copyout((void *)segp, (void *)frup->frus, size, argp->mode) 164203831d35Sstevel != DDI_SUCCESS) { 164303831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout segments", f); 164403831d35Sstevel return (EFAULT); 164503831d35Sstevel } 164603831d35Sstevel return (0); 164703831d35Sstevel } 164803831d35Sstevel 164903831d35Sstevel /* 165003831d35Sstevel * Used to copy out packet_t's to user. 165103831d35Sstevel */ 165203831d35Sstevel static int 165303831d35Sstevel sgfru_copyout_packets(const sgfru_init_arg_t *argp, const frup_info_t *frup, 165403831d35Sstevel const packet_t *packp) 165503831d35Sstevel { 165603831d35Sstevel static fn_t f = "sgfru_copyout_packets"; 165703831d35Sstevel 165803831d35Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (packet_t)); 165903831d35Sstevel /* copyout packet_t's */ 166003831d35Sstevel if (ddi_copyout((void *)packp, (void *)frup->frus, size, argp->mode) 166103831d35Sstevel != DDI_SUCCESS) { 166203831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout packets", f); 166303831d35Sstevel return (EFAULT); 166403831d35Sstevel } 166503831d35Sstevel return (0); 166603831d35Sstevel } 166703831d35Sstevel 166803831d35Sstevel /* 166903831d35Sstevel * Used to copy out raw segment and payload data to user. 167003831d35Sstevel */ 167103831d35Sstevel static int 167203831d35Sstevel sgfru_copyout_buffer(const sgfru_init_arg_t *argp, const frup_info_t *frup, 167303831d35Sstevel const char *buffer) 167403831d35Sstevel { 167503831d35Sstevel static fn_t f = "sgfru_copyout_buffer"; 167603831d35Sstevel 167703831d35Sstevel size_t size = (size_t)(frup->fru_cnt); 167803831d35Sstevel /* copyout packet_t */ 167903831d35Sstevel if (ddi_copyout((void *)buffer, (void *)frup->frus, size, argp->mode) 168003831d35Sstevel != DDI_SUCCESS) { 168103831d35Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout buffer", f); 168203831d35Sstevel return (EFAULT); 168303831d35Sstevel } 168403831d35Sstevel return (0); 168503831d35Sstevel } 168603831d35Sstevel 168703831d35Sstevel /* 168803831d35Sstevel * Used to pad a Java (SCAPP) fru_info_t, in preparation for sending it to 168903831d35Sstevel * C (Solaris). Assumes one fru_info_t. 169003831d35Sstevel */ 169103831d35Sstevel static caddr_t 169203831d35Sstevel sgfru_fru_pad(const caddr_t datap, fru_info_t *fru) 169303831d35Sstevel { 169403831d35Sstevel caddr_t tdatap = datap; 169503831d35Sstevel 169603831d35Sstevel bcopy(tdatap, (caddr_t)&fru->hdl, FRU_HDL_SIZE); 169703831d35Sstevel tdatap += FRU_HDL_SIZE; 169803831d35Sstevel bcopy(tdatap, (caddr_t)&fru->cnt, FRU_CNT_SIZE); 169903831d35Sstevel tdatap += FRU_CNT_SIZE; 170003831d35Sstevel return (tdatap); 170103831d35Sstevel } 170203831d35Sstevel 170303831d35Sstevel /* 170403831d35Sstevel * Used to pad a Java (SCAPP) node_t, in preparation for sending it to 170503831d35Sstevel * C (Solaris). Assumes a fru_info_t and one or more node_t's. 170603831d35Sstevel */ 170703831d35Sstevel static int 170803831d35Sstevel sgfru_node_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru, 170903831d35Sstevel node_t *nodep) 171003831d35Sstevel { 171103831d35Sstevel caddr_t tdatap = datap; 171203831d35Sstevel node_t *np; 171303831d35Sstevel int i, cnt = 1; 171403831d35Sstevel 171503831d35Sstevel if (fru != NULL) { 171603831d35Sstevel tdatap = sgfru_fru_pad(datap, fru); 171703831d35Sstevel if (max_cnt < fru->cnt) { 171803831d35Sstevel return (ENOMEM); 171903831d35Sstevel } else { 172003831d35Sstevel cnt = fru->cnt; 172103831d35Sstevel } 172203831d35Sstevel } 172303831d35Sstevel for (i = 0, np = nodep; i < cnt; i++, np++) { 172403831d35Sstevel bcopy(tdatap, (caddr_t)&np->handle, FRU_HDL_SIZE); 172503831d35Sstevel tdatap += FRU_HDL_SIZE; 172603831d35Sstevel bcopy(tdatap, (caddr_t)&np->nodename, NODENAME_SIZE); 172703831d35Sstevel tdatap += NODENAME_SIZE; 172803831d35Sstevel bcopy(tdatap, (caddr_t)&np->has_children, HASCHILDREN_SIZE); 172903831d35Sstevel tdatap += HASCHILDREN_SIZE; 173003831d35Sstevel bcopy(tdatap, (caddr_t)&np->class, CLASS_SIZE); 173103831d35Sstevel tdatap += CLASS_SIZE; 173203831d35Sstevel if (np->class == LOCATION_CLASS) { 173303831d35Sstevel bcopy(tdatap, (caddr_t)&np->location_slot, SLOT_SIZE); 173403831d35Sstevel tdatap += SLOT_SIZE; 173503831d35Sstevel bcopy(tdatap, (caddr_t)&np->location_label, LABEL_SIZE); 173603831d35Sstevel tdatap += LABEL_SIZE; 173703831d35Sstevel } 173803831d35Sstevel } 173903831d35Sstevel return (0); 174003831d35Sstevel } 174103831d35Sstevel 174203831d35Sstevel /* 174303831d35Sstevel * Used to pad a Java (SCAPP) section, in preparation for sending it to 174403831d35Sstevel * C (Solaris). Assumes a fru_info_t and multiple section_t's. 174503831d35Sstevel */ 174603831d35Sstevel static int 174703831d35Sstevel sgfru_section_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru, 174803831d35Sstevel section_t *sectp) 174903831d35Sstevel { 175003831d35Sstevel caddr_t tdatap = datap; 175103831d35Sstevel section_t *sp; 175203831d35Sstevel int i; 175303831d35Sstevel 175403831d35Sstevel tdatap = sgfru_fru_pad(datap, fru); 175503831d35Sstevel if (max_cnt < fru->cnt) 175603831d35Sstevel return (ENOMEM); 175703831d35Sstevel for (i = 0, sp = sectp; i < fru->cnt; i++, sp++) { 175803831d35Sstevel bcopy(tdatap, (caddr_t)&sp->handle, FRU_HDL_SIZE); 175903831d35Sstevel tdatap += FRU_HDL_SIZE; 176003831d35Sstevel bcopy(tdatap, (caddr_t)&sp->offset, OFFSET_SIZE); 176103831d35Sstevel tdatap += OFFSET_SIZE; 176203831d35Sstevel bcopy(tdatap, (caddr_t)&sp->length, LENGTH_SIZE); 176303831d35Sstevel tdatap += LENGTH_SIZE; 176403831d35Sstevel bcopy(tdatap, (caddr_t)&sp->protected, PROTECTED_SIZE); 176503831d35Sstevel tdatap += PROTECTED_SIZE; 176603831d35Sstevel bcopy(tdatap, (caddr_t)&sp->version, VERSION_SIZE); 176703831d35Sstevel tdatap += VERSION_SIZE; 176803831d35Sstevel } 176903831d35Sstevel return (0); 177003831d35Sstevel } 177103831d35Sstevel 177203831d35Sstevel /* 177303831d35Sstevel * Used to pad a Java (SCAPP) segment, in preparation for sending it to 177403831d35Sstevel * C (Solaris). Assumes a fru_info_t and multiple segment_t's. 177503831d35Sstevel */ 177603831d35Sstevel static int 177703831d35Sstevel sgfru_segment_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru, 177803831d35Sstevel segment_t *segp) 177903831d35Sstevel { 178003831d35Sstevel caddr_t tdatap = datap; 178103831d35Sstevel segment_t *sp; 178203831d35Sstevel int i; 178303831d35Sstevel 178403831d35Sstevel tdatap = sgfru_fru_pad(datap, fru); 178503831d35Sstevel if (max_cnt < fru->cnt) 178603831d35Sstevel return (ENOMEM); 178703831d35Sstevel for (i = 0, sp = segp; i < fru->cnt; i++, sp++) { 178803831d35Sstevel bcopy(tdatap, (caddr_t)&sp->handle, FRU_HDL_SIZE); 178903831d35Sstevel tdatap += FRU_HDL_SIZE; 179003831d35Sstevel bcopy(tdatap, (caddr_t)&sp->name, NAME_SIZE); 179103831d35Sstevel tdatap += NAME_SIZE; 179203831d35Sstevel bcopy(tdatap, (caddr_t)&sp->descriptor, DESCRIPTOR_SIZE); 179303831d35Sstevel tdatap += DESCRIPTOR_SIZE; 179403831d35Sstevel bcopy(tdatap, (caddr_t)&sp->offset, OFFSET_SIZE); 179503831d35Sstevel tdatap += OFFSET_SIZE; 179603831d35Sstevel bcopy(tdatap, (caddr_t)&sp->length, LENGTH_SIZE); 179703831d35Sstevel tdatap += LENGTH_SIZE; 179803831d35Sstevel } 179903831d35Sstevel return (0); 180003831d35Sstevel } 180103831d35Sstevel 180203831d35Sstevel /* 180303831d35Sstevel * Used to pad a Java (SCAPP) packet, in preparation for sending it to 180403831d35Sstevel * C (Solaris). Assumes a fru_info_t and multiple packet_t's. 180503831d35Sstevel */ 180603831d35Sstevel static int 180703831d35Sstevel sgfru_packet_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru, 180803831d35Sstevel packet_t *packp) 180903831d35Sstevel { 181003831d35Sstevel caddr_t tdatap = datap; 181103831d35Sstevel packet_t *pp; 181203831d35Sstevel int i; 181303831d35Sstevel 181403831d35Sstevel tdatap = sgfru_fru_pad(datap, fru); 181503831d35Sstevel if (max_cnt < fru->cnt) 181603831d35Sstevel return (ENOMEM); 181703831d35Sstevel for (i = 0, pp = packp; i < fru->cnt; i++, pp++) { 181803831d35Sstevel bcopy(tdatap, (caddr_t)&pp->handle, FRU_HDL_SIZE); 181903831d35Sstevel tdatap += FRU_HDL_SIZE; 182003831d35Sstevel bcopy(tdatap, (caddr_t)&pp->tag, TAG_SIZE); 182103831d35Sstevel tdatap += TAG_SIZE; 182203831d35Sstevel } 182303831d35Sstevel return (0); 182403831d35Sstevel } 182503831d35Sstevel 182603831d35Sstevel /* 182703831d35Sstevel * Used to unpad a C (Solaris) fru_info_t, in preparation for sending it to 182803831d35Sstevel * Java (SCAPP). Assumes a fru_info_t. 182903831d35Sstevel */ 183003831d35Sstevel static caddr_t 183103831d35Sstevel sgfru_fru_unpad(const fru_info_t *fru, caddr_t datap) 183203831d35Sstevel { 183303831d35Sstevel caddr_t tdatap = datap; 183403831d35Sstevel 183503831d35Sstevel bcopy((caddr_t)&fru->hdl, tdatap, FRU_HDL_SIZE); 183603831d35Sstevel tdatap += FRU_HDL_SIZE; 183703831d35Sstevel bcopy((caddr_t)&fru->cnt, tdatap, FRU_CNT_SIZE); 183803831d35Sstevel tdatap += FRU_CNT_SIZE; 183903831d35Sstevel return (tdatap); 184003831d35Sstevel } 184103831d35Sstevel 184203831d35Sstevel /* 184303831d35Sstevel * Used to unpad a C (Solaris) segment, in preparation for sending it to 184403831d35Sstevel * Java (SCAPP). Assumes a section_hdl_t and one segment_t. 184503831d35Sstevel */ 184603831d35Sstevel static void 184703831d35Sstevel sgfru_segment_unpad(const fru_info_t *fru, const segment_t *segp, 184803831d35Sstevel caddr_t datap) 184903831d35Sstevel { 185003831d35Sstevel caddr_t tdatap = datap; 185103831d35Sstevel 185203831d35Sstevel bcopy((caddr_t)&fru->hdl, tdatap, FRU_HDL_SIZE); 185303831d35Sstevel tdatap += FRU_HDL_SIZE; 185403831d35Sstevel bcopy((caddr_t)&segp->handle, tdatap, FRU_HDL_SIZE); 185503831d35Sstevel tdatap += FRU_HDL_SIZE; 185603831d35Sstevel bcopy((caddr_t)&segp->name, tdatap, NAME_SIZE); 185703831d35Sstevel tdatap += NAME_SIZE; 185803831d35Sstevel bcopy((caddr_t)&segp->descriptor, tdatap, DESCRIPTOR_SIZE); 185903831d35Sstevel tdatap += DESCRIPTOR_SIZE; 186003831d35Sstevel bcopy((caddr_t)&segp->offset, tdatap, OFFSET_SIZE); 186103831d35Sstevel tdatap += OFFSET_SIZE; 186203831d35Sstevel bcopy((caddr_t)&segp->length, tdatap, LENGTH_SIZE); 186303831d35Sstevel } 186403831d35Sstevel 186503831d35Sstevel /* 186603831d35Sstevel * Used to unpad a C (Solaris) packet, in preparation for sending it to 186703831d35Sstevel * Java (SCAPP). Assumes a fru_info_t and one packet_t. 186803831d35Sstevel */ 186903831d35Sstevel static caddr_t 187003831d35Sstevel sgfru_packet_unpad(const fru_info_t *fru, const packet_t *packp, caddr_t datap) 187103831d35Sstevel { 187203831d35Sstevel caddr_t tdatap = datap; 187303831d35Sstevel 187403831d35Sstevel bcopy((caddr_t)&fru->hdl, tdatap, FRU_HDL_SIZE); 187503831d35Sstevel tdatap += FRU_HDL_SIZE; 187603831d35Sstevel bcopy((caddr_t)&fru->cnt, tdatap, FRU_CNT_SIZE); 187703831d35Sstevel tdatap += FRU_CNT_SIZE; 187803831d35Sstevel bcopy((caddr_t)&packp->handle, tdatap, FRU_HDL_SIZE); 187903831d35Sstevel tdatap += FRU_HDL_SIZE; 188003831d35Sstevel bcopy((caddr_t)&packp->tag, tdatap, TAG_SIZE); 188103831d35Sstevel tdatap += TAG_SIZE; 188203831d35Sstevel return (tdatap); 188303831d35Sstevel } 1884