11708Sstevel /*
21708Sstevel * CDDL HEADER START
31708Sstevel *
41708Sstevel * The contents of this file are subject to the terms of the
51708Sstevel * Common Development and Distribution License (the "License").
61708Sstevel * You may not use this file except in compliance with the License.
71708Sstevel *
81708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel * or http://www.opensolaris.org/os/licensing.
101708Sstevel * See the License for the specific language governing permissions
111708Sstevel * and limitations under the License.
121708Sstevel *
131708Sstevel * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel *
191708Sstevel * CDDL HEADER END
201708Sstevel */
211708Sstevel
221708Sstevel /*
23*7656SSherry.Moore@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
241708Sstevel * Use is subject to license terms.
251708Sstevel */
261708Sstevel
271708Sstevel
281708Sstevel #include <sys/types.h>
291708Sstevel #include <sys/conf.h>
301708Sstevel #include <sys/file.h>
311708Sstevel #include <sys/ddi.h>
321708Sstevel #include <sys/sunddi.h>
331708Sstevel #include <sys/modctl.h>
341708Sstevel #include <sys/sunndi.h>
351708Sstevel #include <sys/ddi_impldefs.h>
361708Sstevel #include <sys/obpdefs.h>
371708Sstevel #include <sys/cmn_err.h>
381708Sstevel #include <sys/errno.h>
391708Sstevel #include <sys/debug.h>
401708Sstevel #include <sys/sysmacros.h>
411708Sstevel #include <sys/autoconf.h>
421708Sstevel #include <sys/stat.h>
431708Sstevel #include <sys/kmem.h>
441708Sstevel #include <sys/sgsbbc_mailbox.h>
451708Sstevel #include <sys/sgfrutree.h>
461708Sstevel #include <sys/sgfru_priv.h>
471708Sstevel #include <sys/sgfru_mbox.h>
481708Sstevel
491708Sstevel /*
501708Sstevel * This driver implements the ioctls for the serengeti frutree picl plugin
511708Sstevel * and the serengeti fruaccess library. These are all private,
521708Sstevel * platform-dependent interfaces.
531708Sstevel */
541708Sstevel
551708Sstevel /* Global Variables */
561708Sstevel
571708Sstevel #ifdef DEBUG
581708Sstevel uint_t sgfru_debug = 0;
591708Sstevel #endif /* DEBUG */
601708Sstevel
611708Sstevel /* Opaque state structure pointer */
621708Sstevel static void *sgfru_statep; /* sgfru soft state hook */
631708Sstevel
641708Sstevel /*
651708Sstevel * the maximum amount of time this driver is prepared to wait for the mailbox
661708Sstevel * to reply before it decides to timeout.
671708Sstevel */
681708Sstevel int sgfru_mbox_wait = SGFRU_DEFAULT_MAX_MBOX_WAIT_TIME;
691708Sstevel
701708Sstevel /* Module Variables */
711708Sstevel
721708Sstevel /*
731708Sstevel * Driver entry points. These are located in sgfru.c so as to
741708Sstevel * not cause a warning for the sgfru adb macro.
751708Sstevel */
761708Sstevel static struct cb_ops sgfru_cb_ops = {
771708Sstevel sgfru_open, /* open */
781708Sstevel sgfru_close, /* close */
791708Sstevel nulldev, /* strategy */
801708Sstevel nulldev, /* print */
811708Sstevel nulldev, /* dump */
821708Sstevel nulldev, /* read */
831708Sstevel nulldev, /* write */
841708Sstevel sgfru_ioctl, /* ioctl */
851708Sstevel nulldev, /* devmap */
861708Sstevel nulldev, /* mmap */
871708Sstevel nulldev, /* segmap */
881708Sstevel nochpoll, /* poll */
891708Sstevel ddi_prop_op, /* cb_prop_op */
901708Sstevel NULL, /* streamtab */
911708Sstevel D_NEW | D_MP /* Driver compatibility flag */
921708Sstevel };
931708Sstevel
941708Sstevel static struct dev_ops sgfru_ops = {
951708Sstevel DEVO_REV, /* devo_rev, */
961708Sstevel 0, /* refcnt */
971708Sstevel ddi_getinfo_1to1, /* info */
981708Sstevel nulldev, /* identify */
991708Sstevel nulldev, /* probe */
1001708Sstevel sgfru_attach, /* attach */
1011708Sstevel sgfru_detach, /* detach */
1021708Sstevel nodev, /* reset */
1031708Sstevel &sgfru_cb_ops, /* driver operations */
1041708Sstevel (struct bus_ops *)0, /* bus operations */
105*7656SSherry.Moore@Sun.COM nulldev, /* power */
106*7656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* quiesce */
1071708Sstevel };
1081708Sstevel
1091708Sstevel /*
1101708Sstevel * Loadable module support. This is located in sgfru.c so as to
111*7656SSherry.Moore@Sun.COM * pick up the 1.8 version of sgfru.c.
1121708Sstevel */
1131708Sstevel extern struct mod_ops mod_driverops;
1141708Sstevel
1151708Sstevel static struct modldrv modldrv = {
1161708Sstevel &mod_driverops, /* Type of module. This one is a pseudo driver */
117*7656SSherry.Moore@Sun.COM "FRU Driver",
1181708Sstevel &sgfru_ops, /* driver ops */
1191708Sstevel };
1201708Sstevel
1211708Sstevel static struct modlinkage modlinkage = {
1221708Sstevel MODREV_1,
1231708Sstevel (void *)&modldrv,
1241708Sstevel NULL
1251708Sstevel };
1261708Sstevel
1271708Sstevel int
_init(void)1281708Sstevel _init(void)
1291708Sstevel {
1301708Sstevel int error = 0;
1311708Sstevel
1321708Sstevel /* Allocate the soft state info and add the module. */
1331708Sstevel if ((error = ddi_soft_state_init(&sgfru_statep,
1341708Sstevel sizeof (sgfru_soft_state_t), 1)) == 0 &&
1351708Sstevel (error = mod_install(&modlinkage)) != 0) {
1361708Sstevel ddi_soft_state_fini(&sgfru_statep);
1371708Sstevel }
1381708Sstevel return (error);
1391708Sstevel }
1401708Sstevel
1411708Sstevel int
_fini(void)1421708Sstevel _fini(void)
1431708Sstevel {
1441708Sstevel int error = 0;
1451708Sstevel
1461708Sstevel /* Remove the module and free the soft state info. */
1471708Sstevel if ((error = mod_remove(&modlinkage)) == 0) {
1481708Sstevel ddi_soft_state_fini(&sgfru_statep);
1491708Sstevel }
1501708Sstevel return (error);
1511708Sstevel }
1521708Sstevel
1531708Sstevel int
_info(struct modinfo * modinfop)1541708Sstevel _info(struct modinfo *modinfop)
1551708Sstevel {
1561708Sstevel return (mod_info(&modlinkage, modinfop));
1571708Sstevel }
1581708Sstevel
1591708Sstevel static int
sgfru_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1601708Sstevel sgfru_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1611708Sstevel {
1621708Sstevel sgfru_soft_state_t *softsp;
1631708Sstevel int instance;
1641708Sstevel int error;
1651708Sstevel static fn_t f = "sgfru_attach";
1661708Sstevel
1671708Sstevel switch (cmd) {
1681708Sstevel case DDI_ATTACH:
1691708Sstevel instance = ddi_get_instance(dip);
1701708Sstevel
1711708Sstevel error = ddi_soft_state_zalloc(sgfru_statep, instance);
1721708Sstevel if (error != DDI_SUCCESS) {
1731708Sstevel cmn_err(CE_WARN, "sgfru:%s: cannot allocate fru state "
1741708Sstevel "for inst %d.", f, instance);
1751708Sstevel return (DDI_FAILURE);
1761708Sstevel }
1771708Sstevel softsp = ddi_get_soft_state(sgfru_statep, instance);
1781708Sstevel if (softsp == NULL) {
1791708Sstevel ddi_soft_state_free(sgfru_statep, instance);
1801708Sstevel cmn_err(CE_WARN, "sgfru:%s: could not get state "
1811708Sstevel "structure for inst %d.", f, instance);
1821708Sstevel return (DDI_FAILURE);
1831708Sstevel }
1841708Sstevel softsp->fru_dip = dip;
1851708Sstevel softsp->fru_pdip = ddi_get_parent(softsp->fru_dip);
1861708Sstevel softsp->instance = instance;
1871708Sstevel
1881708Sstevel error = ddi_create_minor_node(dip, SGFRU_DRV_NAME, S_IFCHR,
1891708Sstevel instance, DDI_PSEUDO, NULL);
1901708Sstevel if (error == DDI_FAILURE) {
1911708Sstevel ddi_soft_state_free(sgfru_statep, instance);
1921708Sstevel return (DDI_FAILURE);
1931708Sstevel }
1941708Sstevel
1951708Sstevel ddi_report_dev(dip);
1961708Sstevel
1971708Sstevel return (DDI_SUCCESS);
1981708Sstevel
1991708Sstevel case DDI_RESUME:
2001708Sstevel return (DDI_SUCCESS);
2011708Sstevel
2021708Sstevel default:
2031708Sstevel return (DDI_FAILURE);
2041708Sstevel }
2051708Sstevel }
2061708Sstevel
2071708Sstevel static int
sgfru_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2081708Sstevel sgfru_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2091708Sstevel {
2101708Sstevel int instance;
2111708Sstevel sgfru_soft_state_t *softsp;
2121708Sstevel static fn_t f = "sgfru_detach";
2131708Sstevel
2141708Sstevel instance = ddi_get_instance(dip);
2151708Sstevel
2161708Sstevel softsp = ddi_get_soft_state(sgfru_statep, instance);
2171708Sstevel if (softsp == NULL) {
2181708Sstevel cmn_err(CE_WARN, "sgfru:%s: could not get state "
2191708Sstevel "structure for inst %d.", f, instance);
2201708Sstevel return (DDI_FAILURE);
2211708Sstevel }
2221708Sstevel
2231708Sstevel switch (cmd) {
2241708Sstevel case DDI_DETACH:
2251708Sstevel ddi_soft_state_free(sgfru_statep, instance);
2261708Sstevel ddi_remove_minor_node(dip, NULL);
2271708Sstevel return (DDI_SUCCESS);
2281708Sstevel
2291708Sstevel case DDI_SUSPEND:
2301708Sstevel return (DDI_SUCCESS);
2311708Sstevel
2321708Sstevel default:
2331708Sstevel return (DDI_FAILURE);
2341708Sstevel }
2351708Sstevel }
2361708Sstevel
2371708Sstevel /*ARGSUSED*/
2381708Sstevel static int
sgfru_open(dev_t * dev_p,int flag,int otyp,cred_t * cred_p)2391708Sstevel sgfru_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
2401708Sstevel {
2411708Sstevel int error = 0;
2421708Sstevel int instance = getminor(*dev_p);
2431708Sstevel sgfru_soft_state_t *softsp;
2441708Sstevel static fn_t f = "sgfru_open";
2451708Sstevel
2461708Sstevel if ((error = drv_priv(cred_p)) != 0) {
2471708Sstevel cmn_err(CE_WARN, "sgfru:%s: inst %d drv_priv failed",
2481708Sstevel f, instance);
2491708Sstevel return (error);
2501708Sstevel }
2511708Sstevel softsp = (sgfru_soft_state_t *)ddi_get_soft_state(sgfru_statep,
2521708Sstevel instance);
2531708Sstevel if (softsp == (sgfru_soft_state_t *)NULL) {
2541708Sstevel cmn_err(CE_WARN, "sgfru:%s: inst %d ddi_get_soft_state failed",
2551708Sstevel f, instance);
2561708Sstevel return (ENXIO);
2571708Sstevel }
2581708Sstevel return (error);
2591708Sstevel }
2601708Sstevel
2611708Sstevel /*ARGSUSED*/
2621708Sstevel static int
sgfru_close(dev_t dev,int flag,int otyp,cred_t * cred_p)2631708Sstevel sgfru_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
2641708Sstevel {
2651708Sstevel int instance = getminor(dev);
2661708Sstevel sgfru_soft_state_t *softsp = (sgfru_soft_state_t *)
2671708Sstevel ddi_get_soft_state(sgfru_statep, instance);
2681708Sstevel
2691708Sstevel if (softsp == (sgfru_soft_state_t *)NULL)
2701708Sstevel return (ENXIO);
2711708Sstevel return (DDI_SUCCESS);
2721708Sstevel }
2731708Sstevel
2741708Sstevel /*
2751708Sstevel * This function disperses the ioctls from the serengeti libpiclfruhier plugin
2761708Sstevel * and the serengeti libpiclfruaccess library to the appropriate sub-functions.
2771708Sstevel */
2781708Sstevel /*ARGSUSED*/
2791708Sstevel static int
sgfru_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cred_p,int * rval_p)2801708Sstevel sgfru_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
2811708Sstevel int *rval_p)
2821708Sstevel {
2831708Sstevel sgfru_soft_state_t *softsp;
2841708Sstevel int instance = getminor(dev);
2851708Sstevel sgfru_init_arg_t init_arg;
2861708Sstevel int32_t ret = 0;
2871708Sstevel static fn_t f = "sgfru_ioctl";
2881708Sstevel
2891708Sstevel
2901708Sstevel softsp = ddi_get_soft_state(sgfru_statep, instance);
2911708Sstevel if (softsp == NULL) {
2921708Sstevel return (ENXIO);
2931708Sstevel }
2941708Sstevel PR_STATE("sgfru:%s: dev %lx cmd %d, instance %d\n",
2951708Sstevel f, dev, cmd, instance);
2961708Sstevel
2971708Sstevel init_arg.dev = dev;
2981708Sstevel init_arg.cmd = cmd;
2991708Sstevel init_arg.mode = mode;
3001708Sstevel init_arg.argp = arg;
3011708Sstevel
3021708Sstevel switch (cmd) {
3031708Sstevel
3041708Sstevel case SGFRU_GETSECTIONS:
3051708Sstevel ret = sgfru_getsections(&init_arg);
3061708Sstevel break;
3071708Sstevel
3081708Sstevel case SGFRU_GETSEGMENTS:
3091708Sstevel ret = sgfru_getsegments(&init_arg);
3101708Sstevel break;
3111708Sstevel
3121708Sstevel case SGFRU_ADDSEGMENT:
3131708Sstevel ret = sgfru_addsegment(&init_arg);
3141708Sstevel break;
3151708Sstevel
3161708Sstevel case SGFRU_READRAWSEGMENT:
3171708Sstevel ret = sgfru_readsegment(&init_arg);
3181708Sstevel break;
3191708Sstevel
3201708Sstevel case SGFRU_WRITERAWSEGMENT:
3211708Sstevel ret = sgfru_writesegment(&init_arg);
3221708Sstevel break;
3231708Sstevel
3241708Sstevel case SGFRU_GETPACKETS:
3251708Sstevel ret = sgfru_getpackets(&init_arg);
3261708Sstevel break;
3271708Sstevel
3281708Sstevel case SGFRU_APPENDPACKET:
3291708Sstevel ret = sgfru_appendpacket(&init_arg);
3301708Sstevel break;
3311708Sstevel
3321708Sstevel case SGFRU_GETPAYLOAD:
3331708Sstevel ret = sgfru_getpayload(&init_arg);
3341708Sstevel break;
3351708Sstevel
3361708Sstevel case SGFRU_UPDATEPAYLOAD:
3371708Sstevel ret = sgfru_updatepayload(&init_arg);
3381708Sstevel break;
3391708Sstevel
3401708Sstevel case SGFRU_GETNUMSECTIONS:
3411708Sstevel case SGFRU_GETNUMSEGMENTS:
3421708Sstevel case SGFRU_GETNUMPACKETS:
3431708Sstevel ret = sgfru_getnum(&init_arg);
3441708Sstevel break;
3451708Sstevel
3461708Sstevel case SGFRU_DELETESEGMENT:
3471708Sstevel case SGFRU_DELETEPACKET:
3481708Sstevel ret = sgfru_delete(&init_arg);
3491708Sstevel break;
3501708Sstevel
3511708Sstevel case SGFRU_GETCHILDLIST:
3521708Sstevel ret = sgfru_getchildlist(&init_arg);
3531708Sstevel break;
3541708Sstevel
3551708Sstevel case SGFRU_GETCHILDHANDLES:
3561708Sstevel ret = sgfru_getchildhandles(&init_arg);
3571708Sstevel break;
3581708Sstevel
3591708Sstevel case SGFRU_GETNODEINFO:
3601708Sstevel ret = sgfru_getnodeinfo(&init_arg);
3611708Sstevel break;
3621708Sstevel
3631708Sstevel default:
3641708Sstevel ret = EINVAL;
3651708Sstevel break;
3661708Sstevel }
3671708Sstevel
3681708Sstevel return (ret);
3691708Sstevel }
3701708Sstevel
3711708Sstevel /*
3721708Sstevel * Used for private SGFRU_GETCHILDLIST ioctl.
3731708Sstevel */
3741708Sstevel static int
sgfru_getchildlist(const sgfru_init_arg_t * iargp)3751708Sstevel sgfru_getchildlist(const sgfru_init_arg_t *iargp)
3761708Sstevel {
3771708Sstevel int32_t ret;
3781708Sstevel caddr_t datap;
3791708Sstevel size_t ssize, size;
3801708Sstevel frup_info_t clist;
3811708Sstevel fru_cnt_t max_cnt;
3821708Sstevel node_t *clistp;
3831708Sstevel static fn_t f = "sgfru_getchildlist";
3841708Sstevel
3851708Sstevel /* copyin child_info_t aka frup_info_t */
3861708Sstevel if (sgfru_copyin_frup(iargp, &clist) != 0) {
3871708Sstevel return (EFAULT);
3881708Sstevel }
3891708Sstevel
3901708Sstevel /* check on kmem_alloc space requirements */
3911708Sstevel max_cnt = clist.fru_cnt;
3921708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_HANDLES)) {
3931708Sstevel return (EINVAL);
3941708Sstevel }
3951708Sstevel
3961708Sstevel /* allocate buffer for unpadded fru_info_t + node_t's */
3971708Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * NODE_SIZE));
3981708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
3991708Sstevel PR_NODE("sgfru:%s: FRU_INFO_SIZE %lu NODE_SIZE %lu size %lu\n",
4001708Sstevel f, FRU_INFO_SIZE, NODE_SIZE, size);
4011708Sstevel PR_NODE("sgfru:%s: handle %lx cnt %d buffer 0x%p\n", f,
4021708Sstevel clist.fru_hdl, clist.fru_cnt, clist.frus);
4031708Sstevel
4041708Sstevel /* call mailbox */
4051708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &clist.fru_info))
4061708Sstevel != 0) {
4071708Sstevel kmem_free(datap, size);
4081708Sstevel return (ret);
4091708Sstevel }
4101708Sstevel
4111708Sstevel /* allocate buffer for padded node_t's */
4121708Sstevel ssize = (size_t)(max_cnt * sizeof (node_t));
4131708Sstevel clistp = (node_t *)kmem_zalloc(ssize, KM_SLEEP);
4141708Sstevel
4151708Sstevel /* translate unpadded to padded fru_info_t + node_t's */
4161708Sstevel if ((ret = sgfru_node_pad(datap, max_cnt, &clist.fru_info, clistp))
4171708Sstevel != 0) {
4181708Sstevel kmem_free(datap, size);
4191708Sstevel kmem_free(clistp, ssize);
4201708Sstevel return (ret);
4211708Sstevel }
4221708Sstevel /* free node_t buffer */
4231708Sstevel kmem_free(datap, size);
4241708Sstevel
4251708Sstevel /* copy out fru_info_t */
4261708Sstevel if (sgfru_copyout_fru(iargp, &clist.fru_info) != 0) {
4271708Sstevel kmem_free(clistp, ssize);
4281708Sstevel return (EFAULT);
4291708Sstevel }
4301708Sstevel /* copyout node_t's */
4311708Sstevel if (sgfru_copyout_nodes(iargp, &clist, clistp) != 0) {
4321708Sstevel kmem_free(clistp, ssize);
4331708Sstevel return (EFAULT);
4341708Sstevel }
4351708Sstevel /* free node_t buffer */
4361708Sstevel kmem_free(clistp, ssize);
4371708Sstevel
4381708Sstevel return (ret);
4391708Sstevel }
4401708Sstevel
4411708Sstevel /*
4421708Sstevel * Used for private SGFRU_GETCHILDHANDLES ioctl.
4431708Sstevel */
4441708Sstevel static int
sgfru_getchildhandles(const sgfru_init_arg_t * iargp)4451708Sstevel sgfru_getchildhandles(const sgfru_init_arg_t *iargp)
4461708Sstevel {
4471708Sstevel int32_t ret;
4481708Sstevel size_t size;
4491708Sstevel caddr_t datap, tdatap;
4501708Sstevel frup_info_t hdls;
4511708Sstevel fru_info_t hinfo;
4521708Sstevel fru_cnt_t max_cnt;
4531708Sstevel static fn_t f = "sgfru_getchildhandles";
4541708Sstevel
4551708Sstevel /* copyin handles_t aka frup_info_t */
4561708Sstevel if (sgfru_copyin_frup(iargp, &hdls) != 0) {
4571708Sstevel return (EFAULT);
4581708Sstevel }
4591708Sstevel PR_HANDLE("sgfru:%s: handle %lx\n", f, hdls.fru_hdl);
4601708Sstevel
4611708Sstevel /* check on kmem_alloc space requirements */
4621708Sstevel max_cnt = hdls.fru_cnt;
4631708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_HANDLES)) {
4641708Sstevel return (EINVAL);
4651708Sstevel }
4661708Sstevel
4671708Sstevel /* allocate buffer for child fru_hdl_t's */
4681708Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * FRU_HDL_SIZE));
4691708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
4701708Sstevel
4711708Sstevel /* call mailbox */
4721708Sstevel ret = sgfru_mbox(iargp->cmd, datap, size, &hdls.fru_info);
4731708Sstevel if (ret != 0) {
4741708Sstevel kmem_free(datap, size);
4751708Sstevel return (ret);
4761708Sstevel }
4771708Sstevel
4781708Sstevel /* translate unpadded to fru_info_t */
4791708Sstevel tdatap = sgfru_fru_pad(datap, &hinfo);
4801708Sstevel
4811708Sstevel /* copyout actual fru_cnt */
4821708Sstevel if (sgfru_copyout_fru(iargp, &hinfo) != 0) {
4831708Sstevel kmem_free(datap, size);
4841708Sstevel return (EFAULT);
4851708Sstevel }
4861708Sstevel PR_HANDLE("sgfru:%s: count %x\n", f, hinfo.cnt);
4871708Sstevel
4881708Sstevel /* copyout fru_hdl_t's */
4891708Sstevel if (sgfru_copyout_handles(iargp, &hdls, (fru_hdl_t *)tdatap) != 0) {
4901708Sstevel kmem_free(datap, size);
4911708Sstevel return (EFAULT);
4921708Sstevel }
4931708Sstevel
4941708Sstevel /* free datap buffer */
4951708Sstevel kmem_free(datap, size);
4961708Sstevel
4971708Sstevel return (ret);
4981708Sstevel }
4991708Sstevel
5001708Sstevel /*
5011708Sstevel * Used for private SGFRU_GETNODEINFO ioctl.
5021708Sstevel */
5031708Sstevel static int
sgfru_getnodeinfo(const sgfru_init_arg_t * iargp)5041708Sstevel sgfru_getnodeinfo(const sgfru_init_arg_t *iargp)
5051708Sstevel {
5061708Sstevel int32_t ret;
5071708Sstevel caddr_t datap;
5081708Sstevel size_t size;
5091708Sstevel frup_info_t nodeinfo;
5101708Sstevel node_t node;
5111708Sstevel static fn_t f = "sgfru_getnodeinfo";
5121708Sstevel
5131708Sstevel /* copyin node_info_t aka frup_info_t */
5141708Sstevel if (sgfru_copyin_frup(iargp, &nodeinfo) != 0) {
5151708Sstevel return (EFAULT);
5161708Sstevel }
5171708Sstevel
5181708Sstevel /* allocate unpadded buffer for node_t */
5191708Sstevel size = (size_t)(NODE_SIZE);
5201708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
5211708Sstevel
5221708Sstevel PR_NODE("sgfru:%s: handle %lx size 0x%lx\n", f, nodeinfo.fru_hdl, size);
5231708Sstevel /* call mailbox */
5241708Sstevel ret = sgfru_mbox(iargp->cmd, datap, size, &nodeinfo.fru_info);
5251708Sstevel if (ret != 0) {
5261708Sstevel kmem_free(datap, size);
5271708Sstevel return (ret);
5281708Sstevel }
5291708Sstevel
5301708Sstevel /* translate unpadded to padded node_t */
5311708Sstevel if ((ret = sgfru_node_pad(datap, 0, NULL, &node))
5321708Sstevel != 0) {
5331708Sstevel kmem_free(datap, size);
5341708Sstevel return (ret);
5351708Sstevel }
5361708Sstevel
5371708Sstevel /* free node_t buffer */
5381708Sstevel kmem_free(datap, size);
5391708Sstevel
5401708Sstevel /* copyout node_t */
5411708Sstevel if (sgfru_copyout_nodes(iargp, &nodeinfo, &node) != 0) {
5421708Sstevel return (EFAULT);
5431708Sstevel }
5441708Sstevel PR_NODE("sgfru:%s: handle %lx nodename %s has_children %d class %d\n",
5451708Sstevel f, node.handle, node.nodename, node.has_children, node.class);
5461708Sstevel
5471708Sstevel return (ret);
5481708Sstevel }
5491708Sstevel
5501708Sstevel /*
5511708Sstevel * Used for fru_get_sections().
5521708Sstevel */
5531708Sstevel static int
sgfru_getsections(const sgfru_init_arg_t * iargp)5541708Sstevel sgfru_getsections(const sgfru_init_arg_t *iargp)
5551708Sstevel {
5561708Sstevel int32_t ret;
5571708Sstevel caddr_t datap;
5581708Sstevel size_t ssize, size;
5591708Sstevel frup_info_t sects;
5601708Sstevel fru_cnt_t max_cnt;
5611708Sstevel section_t *sectp;
5621708Sstevel
5631708Sstevel /* copyin sections_t aka frup_info_t */
5641708Sstevel if (sgfru_copyin_frup(iargp, §s) != 0) {
5651708Sstevel return (EFAULT);
5661708Sstevel }
5671708Sstevel /* check on kmem_alloc space requirements */
5681708Sstevel max_cnt = sects.fru_cnt;
5691708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_SECTIONS)) {
5701708Sstevel return (EINVAL);
5711708Sstevel }
5721708Sstevel
5731708Sstevel /* allocate buffer for unpadded fru_info_t + section_t's */
5741708Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * SECTION_SIZE));
5751708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
5761708Sstevel
5771708Sstevel /* call mailbox */
5781708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, §s.fru_info))
5791708Sstevel != 0) {
5801708Sstevel kmem_free(datap, size);
5811708Sstevel return (ret);
5821708Sstevel }
5831708Sstevel
5841708Sstevel /* allocate buffer for padded section_t's */
5851708Sstevel ssize = (size_t)(max_cnt * sizeof (section_t));
5861708Sstevel sectp = (section_t *)kmem_zalloc(ssize, KM_SLEEP);
5871708Sstevel
5881708Sstevel /* translate unpadded to padded fru_info_t + section_t's */
5891708Sstevel if ((ret = sgfru_section_pad(datap, max_cnt, §s.fru_info, sectp))
5901708Sstevel != 0) {
5911708Sstevel kmem_free(datap, size);
5921708Sstevel kmem_free(sectp, ssize);
5931708Sstevel return (ret);
5941708Sstevel }
5951708Sstevel /* free section_t buffer */
5961708Sstevel kmem_free(datap, size);
5971708Sstevel
5981708Sstevel /* copy out fru_info_t */
5991708Sstevel if (sgfru_copyout_fru(iargp, §s.fru_info) != 0) {
6001708Sstevel kmem_free(sectp, ssize);
6011708Sstevel return (EFAULT);
6021708Sstevel }
6031708Sstevel /* copyout section_t's */
6041708Sstevel if (sgfru_copyout_sections(iargp, §s, sectp) != 0) {
6051708Sstevel kmem_free(sectp, ssize);
6061708Sstevel return (EFAULT);
6071708Sstevel }
6081708Sstevel /* free section_t buffer */
6091708Sstevel kmem_free(sectp, ssize);
6101708Sstevel
6111708Sstevel return (ret);
6121708Sstevel }
6131708Sstevel
6141708Sstevel /*
6151708Sstevel * Used for fru_get_segments().
6161708Sstevel */
6171708Sstevel static int
sgfru_getsegments(const sgfru_init_arg_t * iargp)6181708Sstevel sgfru_getsegments(const sgfru_init_arg_t *iargp)
6191708Sstevel {
6201708Sstevel int32_t ret;
6211708Sstevel caddr_t datap;
6221708Sstevel size_t ssize, size;
6231708Sstevel frup_info_t segs;
6241708Sstevel fru_cnt_t max_cnt;
6251708Sstevel segment_t *segp;
6261708Sstevel
6271708Sstevel /* copyin frup_info_t */
6281708Sstevel if (sgfru_copyin_frup(iargp, &segs) != 0) {
6291708Sstevel return (EFAULT);
6301708Sstevel }
6311708Sstevel /* check on kmem_alloc space requirements */
6321708Sstevel max_cnt = segs.fru_cnt;
6331708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_SEGMENTS)) {
6341708Sstevel return (EINVAL);
6351708Sstevel }
6361708Sstevel
6371708Sstevel /* allocate unpadded buffer for fru_info_t + segment_t's */
6381708Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * SEGMENT_SIZE));
6391708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
6401708Sstevel
6411708Sstevel /* call mailbox */
6421708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &segs.fru_info)) != 0) {
6431708Sstevel kmem_free(datap, size);
6441708Sstevel return (ret);
6451708Sstevel }
6461708Sstevel
6471708Sstevel /* allocate buffer for padded segment_t's */
6481708Sstevel ssize = (size_t)(max_cnt * sizeof (segment_t));
6491708Sstevel segp = (segment_t *)kmem_zalloc(ssize, KM_SLEEP);
6501708Sstevel
6511708Sstevel /* translate unpadded to padded fru_info_t + segment_t's */
6521708Sstevel if ((ret = sgfru_segment_pad(datap, max_cnt, &segs.fru_info, segp))
6531708Sstevel != 0) {
6541708Sstevel kmem_free(datap, size);
6551708Sstevel kmem_free(segp, ssize);
6561708Sstevel return (ret);
6571708Sstevel }
6581708Sstevel /* free segment_t buffer */
6591708Sstevel kmem_free(datap, size);
6601708Sstevel
6611708Sstevel /* copy out fru_info_t */
6621708Sstevel if (sgfru_copyout_fru(iargp, &segs.fru_info) != 0) {
6631708Sstevel kmem_free(segp, ssize);
6641708Sstevel return (EFAULT);
6651708Sstevel }
6661708Sstevel /* copyout segment_t's */
6671708Sstevel if (sgfru_copyout_segments(iargp, &segs, segp) != 0) {
6681708Sstevel kmem_free(segp, ssize);
6691708Sstevel return (EFAULT);
6701708Sstevel }
6711708Sstevel /* free segment_t buffer */
6721708Sstevel kmem_free(segp, ssize);
6731708Sstevel
6741708Sstevel return (ret);
6751708Sstevel }
6761708Sstevel
6771708Sstevel static int
sgfru_addsegment(const sgfru_init_arg_t * iargp)6781708Sstevel sgfru_addsegment(const sgfru_init_arg_t *iargp)
6791708Sstevel {
6801708Sstevel int32_t ret;
6811708Sstevel caddr_t datap;
6821708Sstevel size_t size;
6831708Sstevel frup_info_t seg;
6841708Sstevel segment_t segment;
6851708Sstevel fru_hdl_t *hdlp;
6861708Sstevel static fn_t f = "sgfru_addsegment";
6871708Sstevel
6881708Sstevel /* copyin frup_info_t */
6891708Sstevel if (sgfru_copyin_frup(iargp, &seg) != 0) {
6901708Sstevel return (EFAULT);
6911708Sstevel }
6921708Sstevel /* copyin segment_t */
6931708Sstevel if (sgfru_copyin_segment(iargp, &seg, &segment) != 0) {
6941708Sstevel return (EFAULT);
6951708Sstevel }
6961708Sstevel PR_SEGMENT("sgfru:%s: handle %lx, max cnt %d\n",
697*7656SSherry.Moore@Sun.COM f, seg.fru_hdl, seg.fru_cnt);
6981708Sstevel PR_SEGMENT("sgfru:%s: handle %lx, name %s, descriptor 0x%x, "
699*7656SSherry.Moore@Sun.COM "offset 0x%x, length 0x%x\n", f, segment.handle, segment.name,
700*7656SSherry.Moore@Sun.COM segment.descriptor, segment.offset, segment.length);
7011708Sstevel
7021708Sstevel /* allocate buffer for unpadded section_hdl_t + segment_t */
7031708Sstevel size = (size_t)(SECTION_HDL_SIZE + SEGMENT_SIZE);
7041708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
7051708Sstevel /* translate padded to unpadded section_hdl_t + segment_t */
7061708Sstevel sgfru_segment_unpad(&seg.fru_info, &segment, datap);
7071708Sstevel
7081708Sstevel /* call mailbox */
7091708Sstevel ret = sgfru_mbox(iargp->cmd, datap, size, &seg.fru_info);
7101708Sstevel if (ret != 0) {
7111708Sstevel kmem_free(datap, size);
7121708Sstevel return (ret);
7131708Sstevel }
7141708Sstevel
7151708Sstevel /* copyout updated section_hdl_t */
7161708Sstevel hdlp = (fru_hdl_t *)(datap + sizeof (fru_hdl_t));
7171708Sstevel if (sgfru_copyout_handle(iargp, (void *)iargp->argp, hdlp) != 0) {
7181708Sstevel kmem_free(datap, size);
7191708Sstevel return (EFAULT);
7201708Sstevel }
7211708Sstevel /* copyout new segment_hdl_t */
7221708Sstevel if (sgfru_copyout_handle(iargp, seg.frus, --hdlp) != 0) {
7231708Sstevel kmem_free(datap, size);
7241708Sstevel return (EFAULT);
7251708Sstevel }
7261708Sstevel /* free segment_t buffer */
7271708Sstevel kmem_free(datap, size);
7281708Sstevel
7291708Sstevel return (ret);
7301708Sstevel }
7311708Sstevel
7321708Sstevel /*
7331708Sstevel * Used for fru_read_segment().
7341708Sstevel */
7351708Sstevel static int
sgfru_readsegment(const sgfru_init_arg_t * iargp)7361708Sstevel sgfru_readsegment(const sgfru_init_arg_t *iargp)
7371708Sstevel {
7381708Sstevel int32_t ret;
7391708Sstevel caddr_t datap, tdatap;
7401708Sstevel size_t size;
7411708Sstevel frup_info_t segs;
7421708Sstevel fru_info_t sinfo;
7431708Sstevel fru_cnt_t max_cnt;
7441708Sstevel static fn_t f = "sgfru_readsegment";
7451708Sstevel
7461708Sstevel /* copyin one segments_t aka frup_info_t */
7471708Sstevel if (sgfru_copyin_frup(iargp, &segs) != 0) {
7481708Sstevel return (EFAULT);
7491708Sstevel }
7501708Sstevel /* check on kmem_alloc space requirements */
7511708Sstevel max_cnt = segs.fru_cnt;
7521708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_SEGMENTSIZE)) {
7531708Sstevel return (EINVAL);
7541708Sstevel }
7551708Sstevel PR_SEGMENT("sgfru:%s: handle %lx, max cnt %d\n",
756*7656SSherry.Moore@Sun.COM f, segs.fru_hdl, segs.fru_cnt);
7571708Sstevel
7581708Sstevel /* allocate unpadded buffer for raw data */
7591708Sstevel size = (size_t)(FRU_INFO_SIZE + max_cnt);
7601708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
7611708Sstevel
7621708Sstevel /* call mailbox */
7631708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &segs.fru_info)) != 0) {
7641708Sstevel kmem_free(datap, size);
7651708Sstevel return (ret);
7661708Sstevel }
7671708Sstevel
7681708Sstevel /* translate unpadded to padded fru_info_t */
7691708Sstevel tdatap = sgfru_fru_pad(datap, &sinfo);
7701708Sstevel PR_SEGMENT("sgfru:%s: handle %lx, actual cnt %d\n",
771*7656SSherry.Moore@Sun.COM f, sinfo.hdl, sinfo.cnt);
7721708Sstevel
7731708Sstevel /* copyout actual fru_cnt */
7741708Sstevel if (sgfru_copyout_fru(iargp, &sinfo) != 0) {
7751708Sstevel kmem_free(datap, size);
7761708Sstevel return (EFAULT);
7771708Sstevel }
7781708Sstevel /* copyout raw segment data */
7791708Sstevel if (sgfru_copyout_buffer(iargp, &segs, tdatap) != 0) {
7801708Sstevel kmem_free(datap, size);
7811708Sstevel return (EFAULT);
7821708Sstevel }
7831708Sstevel /* free buffer */
7841708Sstevel kmem_free(datap, size);
7851708Sstevel
7861708Sstevel return (ret);
7871708Sstevel }
7881708Sstevel
7891708Sstevel /*
7901708Sstevel * Used for fru_write_segment().
7911708Sstevel */
7921708Sstevel static int
sgfru_writesegment(const sgfru_init_arg_t * iargp)7931708Sstevel sgfru_writesegment(const sgfru_init_arg_t *iargp)
7941708Sstevel {
7951708Sstevel int32_t ret;
7961708Sstevel caddr_t datap, tdatap;
7971708Sstevel size_t size;
7981708Sstevel frup_info_t segs;
7991708Sstevel fru_cnt_t max_cnt;
8001708Sstevel static fn_t f = "sgfru_writesegment";
8011708Sstevel
8021708Sstevel /* copyin frup_info_t */
8031708Sstevel if (sgfru_copyin_frup(iargp, &segs) != 0) {
8041708Sstevel return (EFAULT);
8051708Sstevel }
8061708Sstevel /* check on kmem_alloc space requirements */
8071708Sstevel max_cnt = segs.fru_cnt;
8081708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_SEGMENTSIZE)) {
8091708Sstevel return (EINVAL);
8101708Sstevel }
8111708Sstevel PR_SEGMENT("sgfru:%s: handle %lx, max cnt %d\n",
812*7656SSherry.Moore@Sun.COM f, segs.fru_hdl, segs.fru_cnt);
8131708Sstevel
8141708Sstevel /* allocate unpadded buffer for fru_info_t + raw data */
8151708Sstevel size = (size_t)(FRU_INFO_SIZE + max_cnt);
8161708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
8171708Sstevel
8181708Sstevel /* translate padded to unpadded fru_info_t */
8191708Sstevel tdatap = sgfru_fru_unpad(&segs.fru_info, datap);
8201708Sstevel
8211708Sstevel /* copyin raw segment data */
8221708Sstevel if (sgfru_copyin_buffer(iargp, segs.frus, max_cnt, tdatap) != 0) {
8231708Sstevel kmem_free(datap, size);
8241708Sstevel return (EFAULT);
8251708Sstevel }
8261708Sstevel
8271708Sstevel /* call mailbox */
8281708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &segs.fru_info)) != 0) {
8291708Sstevel kmem_free(datap, size);
8301708Sstevel return (ret);
8311708Sstevel }
8321708Sstevel /* free buffer */
8331708Sstevel kmem_free(datap, size);
8341708Sstevel
8351708Sstevel PR_SEGMENT("sgfru:%s: handle %lx, actual cnt %d\n",
836*7656SSherry.Moore@Sun.COM f, segs.fru_hdl, segs.fru_cnt);
8371708Sstevel /* copyout updated segment handle and actual fru_cnt */
8381708Sstevel if (sgfru_copyout_fru(iargp, &segs.fru_info) != 0) {
8391708Sstevel return (EFAULT);
8401708Sstevel }
8411708Sstevel
8421708Sstevel return (ret);
8431708Sstevel }
8441708Sstevel
8451708Sstevel /*
8461708Sstevel * Used for fru_get_packets().
8471708Sstevel */
8481708Sstevel static int
sgfru_getpackets(const sgfru_init_arg_t * iargp)8491708Sstevel sgfru_getpackets(const sgfru_init_arg_t *iargp)
8501708Sstevel {
8511708Sstevel int32_t ret;
8521708Sstevel caddr_t datap;
8531708Sstevel size_t ssize, size;
8541708Sstevel frup_info_t packs;
8551708Sstevel fru_cnt_t max_cnt;
8561708Sstevel packet_t *packp;
8571708Sstevel
8581708Sstevel /* copyin packets_t aka frup_info_t */
8591708Sstevel if (sgfru_copyin_frup(iargp, &packs) != 0) {
8601708Sstevel return (EFAULT);
8611708Sstevel }
8621708Sstevel /* check on kmem_alloc space requirements */
8631708Sstevel max_cnt = packs.fru_cnt;
8641708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_PACKETS)) {
8651708Sstevel return (EINVAL);
8661708Sstevel }
8671708Sstevel
8681708Sstevel /* allocate buffer for unpadded fru_info_t + packet_t's */
8691708Sstevel size = (size_t)(FRU_INFO_SIZE + (max_cnt * PACKET_SIZE));
8701708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
8711708Sstevel
8721708Sstevel /* call mailbox */
8731708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &packs.fru_info))
8741708Sstevel != 0) {
8751708Sstevel kmem_free(datap, size);
8761708Sstevel return (ret);
8771708Sstevel }
8781708Sstevel
8791708Sstevel /* allocate buffer for padded packet_t's */
8801708Sstevel ssize = (size_t)(max_cnt * sizeof (packet_t));
8811708Sstevel packp = (packet_t *)kmem_zalloc(ssize, KM_SLEEP);
8821708Sstevel
8831708Sstevel /* translate unpadded to padded fru_info_t + packet_t's */
8841708Sstevel if ((ret = sgfru_packet_pad(datap, max_cnt, &packs.fru_info, packp))
8851708Sstevel != 0) {
8861708Sstevel kmem_free(datap, size);
8871708Sstevel kmem_free(packp, ssize);
8881708Sstevel return (ret);
8891708Sstevel }
8901708Sstevel /* free packet_t buffer */
8911708Sstevel kmem_free(datap, size);
8921708Sstevel
8931708Sstevel /* copy out fru_info_t */
8941708Sstevel if (sgfru_copyout_fru(iargp, &packs.fru_info) != 0) {
8951708Sstevel kmem_free(packp, ssize);
8961708Sstevel return (EFAULT);
8971708Sstevel }
8981708Sstevel /* copyout packet_t's */
8991708Sstevel if (sgfru_copyout_packets(iargp, &packs, packp) != 0) {
9001708Sstevel kmem_free(packp, ssize);
9011708Sstevel return (EFAULT);
9021708Sstevel }
9031708Sstevel /* free packet_t buffer */
9041708Sstevel kmem_free(packp, ssize);
9051708Sstevel
9061708Sstevel return (ret);
9071708Sstevel }
9081708Sstevel
9091708Sstevel /*
9101708Sstevel * Used for fru_append_packet().
9111708Sstevel */
9121708Sstevel static int
sgfru_appendpacket(const sgfru_init_arg_t * iargp)9131708Sstevel sgfru_appendpacket(const sgfru_init_arg_t *iargp)
9141708Sstevel {
9151708Sstevel int32_t ret = 0;
9161708Sstevel caddr_t datap, tdatap;
9171708Sstevel size_t size;
9181708Sstevel append_info_t append;
9191708Sstevel fru_cnt_t max_cnt;
9201708Sstevel fru_hdl_t *hdlp;
9211708Sstevel caddr_t addr;
9221708Sstevel
9231708Sstevel /* copyin append_info_t */
9241708Sstevel if (sgfru_copyin_append(iargp, &append) != 0) {
9251708Sstevel return (EFAULT);
9261708Sstevel }
9271708Sstevel /* check on kmem_alloc space requirements */
9281708Sstevel max_cnt = append.payload_cnt;
9291708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_PAYLOADSIZE)) {
9301708Sstevel return (EINVAL);
9311708Sstevel }
9321708Sstevel
9331708Sstevel /* allocate buffer for unpadded fru_info_t + packet_t + payload */
9341708Sstevel size = (size_t)(FRU_INFO_SIZE + PACKET_SIZE + max_cnt);
9351708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
9361708Sstevel /* translate padded to unpadded fru_info_t plus packet_t */
9371708Sstevel tdatap = sgfru_packet_unpad(&append.payload.fru_info, &append.packet,
9381708Sstevel datap);
9391708Sstevel
9401708Sstevel /* copyin payload to the end of the unpadded buffer */
9411708Sstevel if (sgfru_copyin_buffer(iargp, append.payload_data, append.payload_cnt,
9421708Sstevel tdatap) != 0) {
9431708Sstevel kmem_free(datap, size);
9441708Sstevel return (EFAULT);
9451708Sstevel }
9461708Sstevel
9471708Sstevel /* call mailbox */
9481708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size,
9491708Sstevel &append.payload.fru_info)) != 0) {
9501708Sstevel kmem_free(datap, size);
9511708Sstevel return (ret);
9521708Sstevel }
9531708Sstevel
9541708Sstevel /* copyout new packet_hdl_t */
9551708Sstevel hdlp = (fru_hdl_t *)datap;
9561708Sstevel if (sgfru_copyout_handle(iargp, (void *)iargp->argp, hdlp) != 0) {
9571708Sstevel kmem_free(datap, size);
9581708Sstevel return (EFAULT);
9591708Sstevel }
9601708Sstevel /* copyout updated segment_hdl_t */
9611708Sstevel addr = (caddr_t)(iargp->argp + sizeof (packet_t));
9621708Sstevel if (sgfru_copyout_handle(iargp, addr, ++hdlp) != 0) {
9631708Sstevel kmem_free(datap, size);
9641708Sstevel return (EFAULT);
9651708Sstevel }
9661708Sstevel
9671708Sstevel /* free buffer */
9681708Sstevel kmem_free(datap, size);
9691708Sstevel
9701708Sstevel return (ret);
9711708Sstevel }
9721708Sstevel
9731708Sstevel /*
9741708Sstevel * Used for fru_get_payload().
9751708Sstevel */
9761708Sstevel static int
sgfru_getpayload(const sgfru_init_arg_t * iargp)9771708Sstevel sgfru_getpayload(const sgfru_init_arg_t *iargp)
9781708Sstevel {
9791708Sstevel int32_t ret;
9801708Sstevel caddr_t datap, tdatap;
9811708Sstevel size_t size;
9821708Sstevel frup_info_t payld;
9831708Sstevel fru_info_t pinfo;
9841708Sstevel fru_cnt_t max_cnt;
9851708Sstevel static fn_t f = "sgfru_getpayload";
9861708Sstevel
9871708Sstevel /* copyin payload_t aka frup_info_t */
9881708Sstevel if (sgfru_copyin_frup(iargp, &payld) != 0) {
9891708Sstevel return (EFAULT);
9901708Sstevel }
9911708Sstevel PR_PAYLOAD("sgfru:%s: handle %lx, max cnt %d\n",
992*7656SSherry.Moore@Sun.COM f, payld.fru_hdl, payld.fru_cnt);
9931708Sstevel
9941708Sstevel /* check on kmem_alloc space requirements */
9951708Sstevel max_cnt = payld.fru_cnt;
9961708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_PAYLOADSIZE)) {
9971708Sstevel return (EINVAL);
9981708Sstevel }
9991708Sstevel
10001708Sstevel /* allocate buffer for fru_info_t + payload */
10011708Sstevel size = (size_t)(FRU_INFO_SIZE + max_cnt);
10021708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
10031708Sstevel
10041708Sstevel /* call mailbox */
10051708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &payld.fru_info))
10061708Sstevel != 0) {
10071708Sstevel kmem_free(datap, size);
10081708Sstevel return (ret);
10091708Sstevel }
10101708Sstevel
10111708Sstevel /* translate unpadded to padded fru_info_t */
10121708Sstevel tdatap = sgfru_fru_pad(datap, &pinfo);
10131708Sstevel PR_PAYLOAD("sgfru:%s: handle %lx, max cnt %d\n",
1014*7656SSherry.Moore@Sun.COM f, pinfo.hdl, pinfo.cnt);
10151708Sstevel
10161708Sstevel /* copyout actual fru_cnt */
10171708Sstevel if (sgfru_copyout_fru(iargp, &pinfo) != 0) {
10181708Sstevel kmem_free(datap, size);
10191708Sstevel return (EFAULT);
10201708Sstevel }
10211708Sstevel /* copyout raw packet data, aka the payload */
10221708Sstevel if (sgfru_copyout_buffer(iargp, &payld, tdatap) != 0) {
10231708Sstevel kmem_free(datap, size);
10241708Sstevel return (EFAULT);
10251708Sstevel }
10261708Sstevel
10271708Sstevel /* free buffer */
10281708Sstevel kmem_free(datap, size);
10291708Sstevel
10301708Sstevel return (ret);
10311708Sstevel }
10321708Sstevel
10331708Sstevel /*
10341708Sstevel * Used for fru_update_payload().
10351708Sstevel */
10361708Sstevel static int
sgfru_updatepayload(const sgfru_init_arg_t * iargp)10371708Sstevel sgfru_updatepayload(const sgfru_init_arg_t *iargp)
10381708Sstevel {
10391708Sstevel int32_t ret;
10401708Sstevel caddr_t datap, tdatap;
10411708Sstevel size_t size;
10421708Sstevel frup_info_t payld;
10431708Sstevel fru_cnt_t max_cnt;
10441708Sstevel static fn_t f = "sgfru_updatepayload";
10451708Sstevel
10461708Sstevel /* copyin frup_info_t */
10471708Sstevel if (sgfru_copyin_frup(iargp, &payld) != 0) {
10481708Sstevel return (EFAULT);
10491708Sstevel }
10501708Sstevel /* check on kmem_alloc space requirements */
10511708Sstevel max_cnt = payld.fru_cnt;
10521708Sstevel if ((max_cnt <= 0) || (max_cnt > MAX_PAYLOADSIZE)) {
10531708Sstevel return (EINVAL);
10541708Sstevel }
10551708Sstevel
10561708Sstevel /* allocate buffer for fru_info_t + payload */
10571708Sstevel size = (size_t)(FRU_INFO_SIZE + max_cnt);
10581708Sstevel datap = kmem_zalloc(size, KM_SLEEP);
10591708Sstevel
10601708Sstevel /* translate padded to unpadded fru_info_t */
10611708Sstevel tdatap = sgfru_fru_unpad(&payld.fru_info, datap);
10621708Sstevel
10631708Sstevel /* copyin payload */
10641708Sstevel if (sgfru_copyin_buffer(iargp, payld.frus, max_cnt, tdatap) != 0) {
10651708Sstevel kmem_free(datap, size);
10661708Sstevel return (EFAULT);
10671708Sstevel }
10681708Sstevel PR_PAYLOAD("sgfru_updatepayload: handle %lx, actual cnt %d\n",
1069*7656SSherry.Moore@Sun.COM payld.fru_hdl, payld.fru_cnt);
10701708Sstevel
10711708Sstevel /* call mailbox */
10721708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &payld.fru_info))
10731708Sstevel != 0) {
10741708Sstevel kmem_free(datap, size);
10751708Sstevel return (ret);
10761708Sstevel }
10771708Sstevel
10781708Sstevel /* free buffer */
10791708Sstevel kmem_free(datap, size);
10801708Sstevel
10811708Sstevel /* copyout new packet_hdl_t and actual count */
10821708Sstevel if (sgfru_copyout_fru(iargp, &payld.fru_info) != 0) {
10831708Sstevel return (EFAULT);
10841708Sstevel }
10851708Sstevel PR_PAYLOAD("sgfru:%s: new handle %lx, cnt %d\n",
1086*7656SSherry.Moore@Sun.COM f, payld.fru_hdl, payld.fru_cnt);
10871708Sstevel
10881708Sstevel return (ret);
10891708Sstevel }
10901708Sstevel
10911708Sstevel /*
10921708Sstevel * Used for fru_get_num_[sections|segments|packets]().
10931708Sstevel */
10941708Sstevel static int
sgfru_getnum(const sgfru_init_arg_t * iargp)10951708Sstevel sgfru_getnum(const sgfru_init_arg_t *iargp)
10961708Sstevel {
10971708Sstevel int32_t ret;
10981708Sstevel caddr_t datap;
10991708Sstevel size_t size;
11001708Sstevel fru_info_t fru_info;
11011708Sstevel
11021708Sstevel /* copyin fru_info_t */
11031708Sstevel if (sgfru_copyin_fru(iargp, &fru_info) != 0) {
11041708Sstevel return (EFAULT);
11051708Sstevel }
11061708Sstevel
11071708Sstevel size = sizeof (fru_cnt_t);
11081708Sstevel datap = (caddr_t)&fru_info.cnt;
11091708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &fru_info)) != 0) {
11101708Sstevel return (ret);
11111708Sstevel }
11121708Sstevel
11131708Sstevel /* copyout fru_info_t */
11141708Sstevel if (sgfru_copyout_fru(iargp, &fru_info) != 0) {
11151708Sstevel return (EFAULT);
11161708Sstevel }
11171708Sstevel return (ret);
11181708Sstevel }
11191708Sstevel
11201708Sstevel /*
11211708Sstevel * Used for fru_delete_[segment|packet].
11221708Sstevel */
11231708Sstevel static int
sgfru_delete(const sgfru_init_arg_t * iargp)11241708Sstevel sgfru_delete(const sgfru_init_arg_t *iargp)
11251708Sstevel {
11261708Sstevel int32_t ret;
11271708Sstevel caddr_t datap;
11281708Sstevel size_t size;
11291708Sstevel fru_info_t fru_info;
11301708Sstevel static fn_t f = "sgfru_delete";
11311708Sstevel
11321708Sstevel /* copyin fru_info_t */
11331708Sstevel if (sgfru_copyin_fru(iargp, &fru_info) != 0) {
11341708Sstevel return (EFAULT);
11351708Sstevel }
11361708Sstevel PR_SEGMENT("sgfru:%s: delete handle %lx\n", f, fru_info.hdl);
11371708Sstevel
11381708Sstevel size = sizeof (fru_hdl_t);
11391708Sstevel datap = (caddr_t)&fru_info.hdl;
11401708Sstevel if ((ret = sgfru_mbox(iargp->cmd, datap, size, &fru_info)) != 0) {
11411708Sstevel return (ret);
11421708Sstevel }
11431708Sstevel
11441708Sstevel PR_SEGMENT("sgfru:%s: new parent handle %lx\n", f, fru_info.hdl);
11451708Sstevel /* copyout fru_info_t */
11461708Sstevel if (sgfru_copyout_fru(iargp, &fru_info) != 0) {
11471708Sstevel return (EFAULT);
11481708Sstevel }
11491708Sstevel return (ret);
11501708Sstevel }
11511708Sstevel
11521708Sstevel /*
11531708Sstevel * Calls the sgsbbc mailbox with data, returns data and status info.
11541708Sstevel */
11551708Sstevel static int
sgfru_mbox(const int cmd,char * datap,const size_t size,fru_info_t * fru)11561708Sstevel sgfru_mbox(const int cmd, char *datap, const size_t size, fru_info_t *fru)
11571708Sstevel {
11581708Sstevel sbbc_msg_t request, *reqp = &request;
11591708Sstevel sbbc_msg_t response, *resp = &response;
11601708Sstevel fru_hdl_t hdls[2] = {0, 0};
11611708Sstevel fru_hdl_t hdl = fru->hdl;
11621708Sstevel int rv = 0;
11631708Sstevel static fn_t f = "sgfru_mbox";
11641708Sstevel
11651708Sstevel bzero((caddr_t)&request, sizeof (sbbc_msg_t));
11661708Sstevel reqp->msg_type.type = SGFRU_MBOX;
11671708Sstevel bzero((caddr_t)&response, sizeof (sbbc_msg_t));
11681708Sstevel resp->msg_type.type = SGFRU_MBOX;
11691708Sstevel PR_MBOX("sgfru:%s: cmd 0x%x, size %lu\n", f, cmd, size);
11701708Sstevel
11711708Sstevel switch (cmd) {
11721708Sstevel
11731708Sstevel case SGFRU_GETCHILDLIST:
11741708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETCHILDLIST;
11751708Sstevel reqp->msg_len = sizeof (fru_info_t);
11761708Sstevel reqp->msg_buf = (caddr_t)fru;
11771708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETCHILDLIST;
11781708Sstevel resp->msg_len = size;
11791708Sstevel resp->msg_buf = datap;
11801708Sstevel break;
11811708Sstevel
11821708Sstevel case SGFRU_GETCHILDHANDLES:
11831708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETCHILDHANDLES;
11841708Sstevel reqp->msg_len = sizeof (fru_info_t);
11851708Sstevel reqp->msg_buf = (caddr_t)fru;
11861708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETCHILDHANDLES;
11871708Sstevel resp->msg_len = size;
11881708Sstevel resp->msg_buf = datap;
11891708Sstevel break;
11901708Sstevel
11911708Sstevel case SGFRU_GETNODEINFO:
11921708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETNODEINFO;
11931708Sstevel reqp->msg_len = sizeof (fru_hdl_t);
11941708Sstevel reqp->msg_buf = (caddr_t)&hdl;
11951708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETNODEINFO;
11961708Sstevel resp->msg_len = size;
11971708Sstevel resp->msg_buf = datap;
11981708Sstevel break;
11991708Sstevel
12001708Sstevel case SGFRU_GETNUMSECTIONS:
12011708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETNUMSECTIONS;
12021708Sstevel reqp->msg_len = sizeof (fru_hdl_t);
12031708Sstevel reqp->msg_buf = (caddr_t)&hdl;
12041708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETNUMSECTIONS;
12051708Sstevel resp->msg_len = size;
12061708Sstevel resp->msg_buf = datap;
12071708Sstevel break;
12081708Sstevel
12091708Sstevel case SGFRU_GETNUMSEGMENTS:
12101708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETNUMSEGMENTS;
12111708Sstevel reqp->msg_len = sizeof (fru_hdl_t);
12121708Sstevel reqp->msg_buf = (caddr_t)&hdl;
12131708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETNUMSEGMENTS;
12141708Sstevel resp->msg_len = size;
12151708Sstevel resp->msg_buf = datap;
12161708Sstevel break;
12171708Sstevel
12181708Sstevel case SGFRU_GETNUMPACKETS:
12191708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETNUMPACKETS;
12201708Sstevel reqp->msg_len = sizeof (fru_hdl_t);
12211708Sstevel reqp->msg_buf = (caddr_t)&hdl;
12221708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETNUMPACKETS;
12231708Sstevel resp->msg_len = size;
12241708Sstevel resp->msg_buf = datap;
12251708Sstevel break;
12261708Sstevel
12271708Sstevel case SGFRU_GETSECTIONS:
12281708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETSECTIONS;
12291708Sstevel reqp->msg_len = sizeof (fru_info_t);
12301708Sstevel reqp->msg_buf = (caddr_t)fru;
12311708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETSECTIONS;
12321708Sstevel resp->msg_len = size;
12331708Sstevel resp->msg_buf = datap;
12341708Sstevel break;
12351708Sstevel
12361708Sstevel case SGFRU_GETSEGMENTS:
12371708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETSEGMENTS;
12381708Sstevel reqp->msg_len = sizeof (fru_info_t);
12391708Sstevel reqp->msg_buf = (caddr_t)fru;
12401708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETSEGMENTS;
12411708Sstevel resp->msg_len = size;
12421708Sstevel resp->msg_buf = datap;
12431708Sstevel break;
12441708Sstevel
12451708Sstevel case SGFRU_GETPACKETS:
12461708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETPACKETS;
12471708Sstevel reqp->msg_len = sizeof (fru_info_t);
12481708Sstevel reqp->msg_buf = (caddr_t)fru;
12491708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETPACKETS;
12501708Sstevel resp->msg_len = size;
12511708Sstevel resp->msg_buf = datap;
12521708Sstevel break;
12531708Sstevel
12541708Sstevel case SGFRU_ADDSEGMENT:
12551708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_ADDSEGMENT;
12561708Sstevel reqp->msg_len = size;
12571708Sstevel reqp->msg_buf = datap;
12581708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_ADDSEGMENT;
12591708Sstevel resp->msg_len = sizeof (hdls);
12601708Sstevel resp->msg_buf = (caddr_t)&hdls;
12611708Sstevel break;
12621708Sstevel
12631708Sstevel case SGFRU_APPENDPACKET:
12641708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_APPENDPACKET;
12651708Sstevel reqp->msg_len = size;
12661708Sstevel reqp->msg_buf = (caddr_t)datap;
12671708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_APPENDPACKET;
12681708Sstevel resp->msg_len = sizeof (hdls);
12691708Sstevel resp->msg_buf = (caddr_t)&hdls;
12701708Sstevel break;
12711708Sstevel
12721708Sstevel case SGFRU_DELETESEGMENT:
12731708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_DELETESEGMENT;
12741708Sstevel reqp->msg_len = size;
12751708Sstevel reqp->msg_buf = (caddr_t)datap;
12761708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_DELETESEGMENT;
12771708Sstevel resp->msg_len = sizeof (fru_hdl_t);
12781708Sstevel resp->msg_buf = (caddr_t)&hdl;
12791708Sstevel break;
12801708Sstevel
12811708Sstevel case SGFRU_READRAWSEGMENT:
12821708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_READRAWSEGMENT;
12831708Sstevel reqp->msg_len = sizeof (fru_info_t);
12841708Sstevel reqp->msg_buf = (caddr_t)fru;
12851708Sstevel resp->msg_type.sub_type = SGFRU_READRAWSEGMENT;
12861708Sstevel resp->msg_len = size;
12871708Sstevel resp->msg_buf = datap;
12881708Sstevel break;
12891708Sstevel
12901708Sstevel case SGFRU_WRITERAWSEGMENT:
12911708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_WRITERAWSEGMENT;
12921708Sstevel reqp->msg_len = size;
12931708Sstevel reqp->msg_buf = datap;
12941708Sstevel resp->msg_type.sub_type = SGFRU_WRITERAWSEGMENT;
12951708Sstevel resp->msg_len = sizeof (fru_info_t);
12961708Sstevel resp->msg_buf = (caddr_t)fru;
12971708Sstevel break;
12981708Sstevel
12991708Sstevel case SGFRU_DELETEPACKET:
13001708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_DELETEPACKET;
13011708Sstevel reqp->msg_len = size;
13021708Sstevel reqp->msg_buf = (caddr_t)datap;
13031708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_DELETEPACKET;
13041708Sstevel resp->msg_len = sizeof (fru_hdl_t);
13051708Sstevel resp->msg_buf = (caddr_t)&hdl;
13061708Sstevel break;
13071708Sstevel
13081708Sstevel case SGFRU_GETPAYLOAD:
13091708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_GETPAYLOAD;
13101708Sstevel reqp->msg_len = sizeof (fru_info_t);
13111708Sstevel reqp->msg_buf = (caddr_t)fru;
13121708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_GETPAYLOAD;
13131708Sstevel resp->msg_len = size;
13141708Sstevel resp->msg_buf = datap;
13151708Sstevel break;
13161708Sstevel
13171708Sstevel case SGFRU_UPDATEPAYLOAD:
13181708Sstevel reqp->msg_type.sub_type = SGFRU_MBOX_UPDATEPAYLOAD;
13191708Sstevel reqp->msg_len = size;
13201708Sstevel reqp->msg_buf = datap;
13211708Sstevel resp->msg_type.sub_type = SGFRU_MBOX_UPDATEPAYLOAD;
13221708Sstevel resp->msg_len = sizeof (fru_info_t);
13231708Sstevel resp->msg_buf = (caddr_t)fru;
13241708Sstevel break;
13251708Sstevel
13261708Sstevel default:
13271708Sstevel return (EINVAL);
13281708Sstevel }
13291708Sstevel
13301708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sgfru_mbox_wait);
13311708Sstevel PR_MBOX("sgfru:%s: rv %d, msg_status %d\n", f, rv, resp->msg_status);
13321708Sstevel
13331708Sstevel if ((rv) || (resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
13341708Sstevel
13351708Sstevel /* errors from sgsbbc */
13361708Sstevel if (resp->msg_status > 0) {
13371708Sstevel return (resp->msg_status);
13381708Sstevel }
13391708Sstevel
13401708Sstevel /* errors from SCAPP */
13411708Sstevel switch (resp->msg_status) {
13421708Sstevel
13431708Sstevel case SG_MBOX_STATUS_COMMAND_FAILURE:
13441708Sstevel /* internal SCAPP error */
13451708Sstevel return (EINTR);
13461708Sstevel
13471708Sstevel case SG_MBOX_STATUS_HARDWARE_FAILURE:
13481708Sstevel /* seprom read/write errors */
13491708Sstevel return (EIO);
13501708Sstevel
13511708Sstevel case SG_MBOX_STATUS_ILLEGAL_PARAMETER:
13521708Sstevel /* illegal ioctl parameter */
13531708Sstevel return (EINVAL);
13541708Sstevel
13551708Sstevel case SG_MBOX_STATUS_BOARD_ACCESS_DENIED:
13561708Sstevel /* board access denied */
13571708Sstevel return (EACCES);
13581708Sstevel
13591708Sstevel case SG_MBOX_STATUS_STALE_CONTENTS:
13601708Sstevel /* stale contents */
13611708Sstevel return (ESTALE);
13621708Sstevel
13631708Sstevel case SG_MBOX_STATUS_STALE_OBJECT:
13641708Sstevel /* stale handle */
13651708Sstevel return (ENOENT);
13661708Sstevel
13671708Sstevel case SG_MBOX_STATUS_NO_SEPROM_SPACE:
13681708Sstevel /* seprom lacks space */
13691708Sstevel return (ENOSPC);
13701708Sstevel
13711708Sstevel case SG_MBOX_STATUS_NO_MEMORY:
13721708Sstevel /* user prog. lacks space */
13731708Sstevel return (ENOMEM);
13741708Sstevel
13751708Sstevel case SG_MBOX_STATUS_NOT_SUPPORTED:
13761708Sstevel /* unsupported operation */
13771708Sstevel return (ENOTSUP);
13781708Sstevel
13791708Sstevel default:
13801708Sstevel return (EIO);
13811708Sstevel }
13821708Sstevel }
13831708Sstevel
13841708Sstevel switch (cmd) {
13851708Sstevel
13861708Sstevel /*
13871708Sstevel * These two calls get back two handles, a new handle for the
13881708Sstevel * added segment or packet, and an updated parent handle.
13891708Sstevel */
13901708Sstevel case SGFRU_ADDSEGMENT:
13911708Sstevel case SGFRU_APPENDPACKET:
13921708Sstevel bcopy(hdls, datap, sizeof (hdls));
13931708Sstevel break;
13941708Sstevel
13951708Sstevel /* These two calls get an updated parent handle. */
13961708Sstevel case SGFRU_DELETESEGMENT:
13971708Sstevel case SGFRU_DELETEPACKET:
13981708Sstevel fru->hdl = hdl;
13991708Sstevel break;
14001708Sstevel
14011708Sstevel default:
14021708Sstevel break;
14031708Sstevel }
14041708Sstevel
14051708Sstevel return (0);
14061708Sstevel }
14071708Sstevel
14081708Sstevel /*
14091708Sstevel * Used to copy in one frup_info_t from user.
14101708Sstevel */
14111708Sstevel static int
sgfru_copyin_frup(const sgfru_init_arg_t * argp,frup_info_t * frup)14121708Sstevel sgfru_copyin_frup(const sgfru_init_arg_t *argp, frup_info_t *frup)
14131708Sstevel {
14141708Sstevel static fn_t f = "sgfru_copyin_frup";
14151708Sstevel
14161708Sstevel bzero((caddr_t)frup, sizeof (frup_info_t));
14171708Sstevel #ifdef _MULTI_DATAMODEL
14181708Sstevel if (ddi_model_convert_from(argp->mode & FMODELS) == DDI_MODEL_ILP32) {
14191708Sstevel frup32_info_t frup32;
14201708Sstevel
14211708Sstevel bzero((caddr_t)&frup32, sizeof (frup32_info_t));
14221708Sstevel if (ddi_copyin((void *)argp->argp, (void *)&frup32,
14231708Sstevel sizeof (frup32_info_t), argp->mode) != DDI_SUCCESS) {
14241708Sstevel cmn_err(CE_WARN, "sgfru:%s: (32 bit) failed to copyin "
14251708Sstevel "frup32_t struct", f);
14261708Sstevel return (EFAULT);
14271708Sstevel }
14281708Sstevel frup->fru_hdl = frup32.fru_hdl;
14291708Sstevel frup->fru_cnt = frup32.fru_cnt;
14301708Sstevel frup->frus = (void *)(uintptr_t)frup32.frus;
14311708Sstevel PR_STATE("sgfru:%s: frus %p %x hdl %lx cnt %d\n",
14321708Sstevel f, frup->frus, frup32.frus, frup->fru_hdl, frup->fru_cnt);
14331708Sstevel
14341708Sstevel } else
14351708Sstevel #endif /* _MULTI_DATAMODEL */
14361708Sstevel if (ddi_copyin((void *)argp->argp, (void *)frup,
14371708Sstevel sizeof (frup_info_t), argp->mode) != DDI_SUCCESS) {
14381708Sstevel cmn_err(CE_WARN,
14391708Sstevel "sgfru:%s: failed to copyin frup_info_t struct", f);
14401708Sstevel return (EFAULT);
14411708Sstevel }
14421708Sstevel return (0);
14431708Sstevel }
14441708Sstevel
14451708Sstevel /*
14461708Sstevel * Used to copy in one fru_info_t from user.
14471708Sstevel */
14481708Sstevel static int
sgfru_copyin_fru(const sgfru_init_arg_t * argp,fru_info_t * fru)14491708Sstevel sgfru_copyin_fru(const sgfru_init_arg_t *argp, fru_info_t *fru)
14501708Sstevel {
14511708Sstevel static fn_t f = "sgfru_copyin_fru";
14521708Sstevel
14531708Sstevel bzero((caddr_t)fru, sizeof (fru_info_t));
14541708Sstevel if (ddi_copyin((void *)argp->argp, (void *)fru,
14551708Sstevel sizeof (fru_info_t), argp->mode) != DDI_SUCCESS) {
14561708Sstevel cmn_err(CE_WARN,
14571708Sstevel "sgfru:%s: failed to copyin fru_info_t struct", f);
14581708Sstevel return (EFAULT);
14591708Sstevel }
14601708Sstevel return (0);
14611708Sstevel }
14621708Sstevel
14631708Sstevel /*
14641708Sstevel * Used to copy in segment_t from user.
14651708Sstevel */
14661708Sstevel static int
sgfru_copyin_segment(const sgfru_init_arg_t * argp,const frup_info_t * frup,segment_t * segp)14671708Sstevel sgfru_copyin_segment(const sgfru_init_arg_t *argp, const frup_info_t *frup,
14681708Sstevel segment_t *segp)
14691708Sstevel {
14701708Sstevel static fn_t f = "sgfru_copyin_segment";
14711708Sstevel
14721708Sstevel bzero((caddr_t)segp, sizeof (segment_t));
14731708Sstevel if (ddi_copyin((void *)frup->frus, (void *)segp,
14741708Sstevel sizeof (segment_t), argp->mode) != DDI_SUCCESS) {
14751708Sstevel cmn_err(CE_WARN,
14761708Sstevel "sgfru:%s: failed to copyin segment_t struct", f);
14771708Sstevel return (EFAULT);
14781708Sstevel }
14791708Sstevel return (0);
14801708Sstevel }
14811708Sstevel
14821708Sstevel /*
14831708Sstevel * Used to copy in segment handle, packet and payload data from user.
14841708Sstevel */
14851708Sstevel static int
sgfru_copyin_append(const sgfru_init_arg_t * argp,append_info_t * app)14861708Sstevel sgfru_copyin_append(const sgfru_init_arg_t *argp, append_info_t *app)
14871708Sstevel {
14881708Sstevel static fn_t f = "sgfru_copyin_append";
14891708Sstevel
14901708Sstevel bzero((caddr_t)app, sizeof (append_info_t));
14911708Sstevel #ifdef _MULTI_DATAMODEL
14921708Sstevel if (ddi_model_convert_from(argp->mode & FMODELS) == DDI_MODEL_ILP32) {
14931708Sstevel append32_info_t app32;
14941708Sstevel
14951708Sstevel bzero((caddr_t)&app32, sizeof (append32_info_t));
14961708Sstevel if (ddi_copyin((void *)argp->argp, (void *)&app32,
14971708Sstevel sizeof (append32_info_t), argp->mode) != DDI_SUCCESS) {
14981708Sstevel cmn_err(CE_WARN, "sgfru:%s: (32 bit) failed to copyin "
14991708Sstevel "append32_info_t struct", f);
15001708Sstevel return (EFAULT);
15011708Sstevel }
15021708Sstevel app->packet = app32.packet;
15031708Sstevel app->payload_hdl = app32.payload_hdl;
15041708Sstevel app->payload_cnt = app32.payload_cnt;
15051708Sstevel app->payload_data = (void *)(uintptr_t)app32.payload_data;
15061708Sstevel PR_PAYLOAD("sgfru:%s:: data %p hdl %lx cnt %d\n",
15071708Sstevel f, app->payload_data, app->payload_hdl, app->payload_cnt);
15081708Sstevel
15091708Sstevel } else
15101708Sstevel #endif /* _MULTI_DATAMODEL */
15111708Sstevel if (ddi_copyin((void *)argp->argp, (void *)app,
15121708Sstevel sizeof (append_info_t), argp->mode) != DDI_SUCCESS) {
15131708Sstevel cmn_err(CE_WARN,
15141708Sstevel "sgfru:%s: failed to copyin append_info_t struct", f);
15151708Sstevel return (EFAULT);
15161708Sstevel }
15171708Sstevel PR_PAYLOAD("sgfru:%s: hdl %lx, cnt %d pkt hdl %lx "
1518*7656SSherry.Moore@Sun.COM "tag %lx\n", f, app->payload_hdl, app->payload_cnt,
1519*7656SSherry.Moore@Sun.COM app->packet.handle, app->packet.tag);
15201708Sstevel return (0);
15211708Sstevel }
15221708Sstevel
15231708Sstevel /*
15241708Sstevel * Used to copy in raw segment and payload data from user.
15251708Sstevel */
15261708Sstevel static int
sgfru_copyin_buffer(const sgfru_init_arg_t * argp,const caddr_t data,const int cnt,char * buffer)15271708Sstevel sgfru_copyin_buffer(const sgfru_init_arg_t *argp, const caddr_t data,
15281708Sstevel const int cnt, char *buffer)
15291708Sstevel {
15301708Sstevel static fn_t f = "sgfru_copyin_buffer";
15311708Sstevel
15321708Sstevel if (ddi_copyin((void *)data, (void *)buffer, cnt, argp->mode)
15331708Sstevel != DDI_SUCCESS) {
15341708Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyin buffer", f);
15351708Sstevel return (EFAULT);
15361708Sstevel }
15371708Sstevel return (0);
15381708Sstevel }
15391708Sstevel
15401708Sstevel /*
15411708Sstevel * Used to copy out one fru_info_t to user.
15421708Sstevel */
15431708Sstevel static int
sgfru_copyout_fru(const sgfru_init_arg_t * argp,const fru_info_t * frup)15441708Sstevel sgfru_copyout_fru(const sgfru_init_arg_t *argp, const fru_info_t *frup)
15451708Sstevel {
15461708Sstevel static fn_t f = "sgfru_copyout_fru";
15471708Sstevel
15481708Sstevel if (ddi_copyout((void *)frup, (void *)argp->argp,
15491708Sstevel sizeof (fru_info_t), argp->mode) != DDI_SUCCESS) {
15501708Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout fru", f);
15511708Sstevel return (EFAULT);
15521708Sstevel }
15531708Sstevel return (0);
15541708Sstevel }
15551708Sstevel
15561708Sstevel /*
15571708Sstevel * Used to copy out one fru_hdl_t to user.
15581708Sstevel */
15591708Sstevel static int
sgfru_copyout_handle(const sgfru_init_arg_t * argp,const void * addr,const fru_hdl_t * hdlp)15601708Sstevel sgfru_copyout_handle(const sgfru_init_arg_t *argp, const void *addr,
15611708Sstevel const fru_hdl_t *hdlp)
15621708Sstevel {
15631708Sstevel static fn_t f = "sgfru_copyout_handle";
15641708Sstevel
15651708Sstevel if (ddi_copyout((void *)hdlp, (void *)addr, sizeof (fru_hdl_t),
15661708Sstevel argp->mode) != DDI_SUCCESS) {
15671708Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout handle", f);
15681708Sstevel return (EFAULT);
15691708Sstevel }
15701708Sstevel return (0);
15711708Sstevel }
15721708Sstevel
15731708Sstevel /*
15741708Sstevel * Used to copy out an array of fru_hdl_t's to user.
15751708Sstevel */
15761708Sstevel static int
sgfru_copyout_handles(const sgfru_init_arg_t * argp,const frup_info_t * frup,const fru_hdl_t * hdlp)15771708Sstevel sgfru_copyout_handles(const sgfru_init_arg_t *argp, const frup_info_t *frup,
15781708Sstevel const fru_hdl_t *hdlp)
15791708Sstevel {
15801708Sstevel static fn_t f = "sgfru_copyout_handles";
15811708Sstevel
15821708Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (fru_hdl_t));
15831708Sstevel /* copyout fru_hdl_t's */
15841708Sstevel if (ddi_copyout((void *)hdlp, (void *)frup->frus, size, argp->mode)
15851708Sstevel != DDI_SUCCESS) {
15861708Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout handles", f);
15871708Sstevel return (EFAULT);
15881708Sstevel }
15891708Sstevel return (0);
15901708Sstevel }
15911708Sstevel
15921708Sstevel /*
15931708Sstevel * Used to copy out one or more node_t's to user.
15941708Sstevel */
15951708Sstevel static int
sgfru_copyout_nodes(const sgfru_init_arg_t * argp,const frup_info_t * frup,const node_t * nodep)15961708Sstevel sgfru_copyout_nodes(const sgfru_init_arg_t *argp, const frup_info_t *frup,
15971708Sstevel const node_t *nodep)
15981708Sstevel {
15991708Sstevel static fn_t f = "sgfru_copyout_nodes";
16001708Sstevel
16011708Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (node_t));
16021708Sstevel /* copyout node_t's */
16031708Sstevel if (ddi_copyout((void *)nodep, (void *)frup->frus, size, argp->mode)
16041708Sstevel != DDI_SUCCESS) {
16051708Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout nodes", f);
16061708Sstevel return (EFAULT);
16071708Sstevel }
16081708Sstevel return (0);
16091708Sstevel }
16101708Sstevel
16111708Sstevel /*
16121708Sstevel * Used to copy out section_t's to user.
16131708Sstevel */
16141708Sstevel static int
sgfru_copyout_sections(const sgfru_init_arg_t * argp,const frup_info_t * frup,const section_t * sectp)16151708Sstevel sgfru_copyout_sections(const sgfru_init_arg_t *argp, const frup_info_t *frup,
16161708Sstevel const section_t *sectp)
16171708Sstevel {
16181708Sstevel static fn_t f = "sgfru_copyout_sections";
16191708Sstevel
16201708Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (section_t));
16211708Sstevel /* copyout section_t's */
16221708Sstevel if (ddi_copyout((void *)sectp, (void *)frup->frus, size, argp->mode)
16231708Sstevel != DDI_SUCCESS) {
16241708Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout sections", f);
16251708Sstevel return (EFAULT);
16261708Sstevel }
16271708Sstevel return (0);
16281708Sstevel }
16291708Sstevel
16301708Sstevel /*
16311708Sstevel * Used to copy out segment_t's to user.
16321708Sstevel */
16331708Sstevel static int
sgfru_copyout_segments(const sgfru_init_arg_t * argp,const frup_info_t * frup,const segment_t * segp)16341708Sstevel sgfru_copyout_segments(const sgfru_init_arg_t *argp, const frup_info_t *frup,
16351708Sstevel const segment_t *segp)
16361708Sstevel {
16371708Sstevel static fn_t f = "sgfru_copyout_segments";
16381708Sstevel
16391708Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (segment_t));
16401708Sstevel /* copyout segment_t's */
16411708Sstevel if (ddi_copyout((void *)segp, (void *)frup->frus, size, argp->mode)
16421708Sstevel != DDI_SUCCESS) {
16431708Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout segments", f);
16441708Sstevel return (EFAULT);
16451708Sstevel }
16461708Sstevel return (0);
16471708Sstevel }
16481708Sstevel
16491708Sstevel /*
16501708Sstevel * Used to copy out packet_t's to user.
16511708Sstevel */
16521708Sstevel static int
sgfru_copyout_packets(const sgfru_init_arg_t * argp,const frup_info_t * frup,const packet_t * packp)16531708Sstevel sgfru_copyout_packets(const sgfru_init_arg_t *argp, const frup_info_t *frup,
16541708Sstevel const packet_t *packp)
16551708Sstevel {
16561708Sstevel static fn_t f = "sgfru_copyout_packets";
16571708Sstevel
16581708Sstevel size_t size = (size_t)(frup->fru_cnt * sizeof (packet_t));
16591708Sstevel /* copyout packet_t's */
16601708Sstevel if (ddi_copyout((void *)packp, (void *)frup->frus, size, argp->mode)
16611708Sstevel != DDI_SUCCESS) {
16621708Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout packets", f);
16631708Sstevel return (EFAULT);
16641708Sstevel }
16651708Sstevel return (0);
16661708Sstevel }
16671708Sstevel
16681708Sstevel /*
16691708Sstevel * Used to copy out raw segment and payload data to user.
16701708Sstevel */
16711708Sstevel static int
sgfru_copyout_buffer(const sgfru_init_arg_t * argp,const frup_info_t * frup,const char * buffer)16721708Sstevel sgfru_copyout_buffer(const sgfru_init_arg_t *argp, const frup_info_t *frup,
16731708Sstevel const char *buffer)
16741708Sstevel {
16751708Sstevel static fn_t f = "sgfru_copyout_buffer";
16761708Sstevel
16771708Sstevel size_t size = (size_t)(frup->fru_cnt);
16781708Sstevel /* copyout packet_t */
16791708Sstevel if (ddi_copyout((void *)buffer, (void *)frup->frus, size, argp->mode)
16801708Sstevel != DDI_SUCCESS) {
16811708Sstevel cmn_err(CE_WARN, "sgfru:%s: failed to copyout buffer", f);
16821708Sstevel return (EFAULT);
16831708Sstevel }
16841708Sstevel return (0);
16851708Sstevel }
16861708Sstevel
16871708Sstevel /*
16881708Sstevel * Used to pad a Java (SCAPP) fru_info_t, in preparation for sending it to
16891708Sstevel * C (Solaris). Assumes one fru_info_t.
16901708Sstevel */
16911708Sstevel static caddr_t
sgfru_fru_pad(const caddr_t datap,fru_info_t * fru)16921708Sstevel sgfru_fru_pad(const caddr_t datap, fru_info_t *fru)
16931708Sstevel {
16941708Sstevel caddr_t tdatap = datap;
16951708Sstevel
16961708Sstevel bcopy(tdatap, (caddr_t)&fru->hdl, FRU_HDL_SIZE);
16971708Sstevel tdatap += FRU_HDL_SIZE;
16981708Sstevel bcopy(tdatap, (caddr_t)&fru->cnt, FRU_CNT_SIZE);
16991708Sstevel tdatap += FRU_CNT_SIZE;
17001708Sstevel return (tdatap);
17011708Sstevel }
17021708Sstevel
17031708Sstevel /*
17041708Sstevel * Used to pad a Java (SCAPP) node_t, in preparation for sending it to
17051708Sstevel * C (Solaris). Assumes a fru_info_t and one or more node_t's.
17061708Sstevel */
17071708Sstevel static int
sgfru_node_pad(const caddr_t datap,const int max_cnt,fru_info_t * fru,node_t * nodep)17081708Sstevel sgfru_node_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru,
17091708Sstevel node_t *nodep)
17101708Sstevel {
17111708Sstevel caddr_t tdatap = datap;
17121708Sstevel node_t *np;
17131708Sstevel int i, cnt = 1;
17141708Sstevel
17151708Sstevel if (fru != NULL) {
17161708Sstevel tdatap = sgfru_fru_pad(datap, fru);
17171708Sstevel if (max_cnt < fru->cnt) {
17181708Sstevel return (ENOMEM);
17191708Sstevel } else {
17201708Sstevel cnt = fru->cnt;
17211708Sstevel }
17221708Sstevel }
17231708Sstevel for (i = 0, np = nodep; i < cnt; i++, np++) {
17241708Sstevel bcopy(tdatap, (caddr_t)&np->handle, FRU_HDL_SIZE);
17251708Sstevel tdatap += FRU_HDL_SIZE;
17261708Sstevel bcopy(tdatap, (caddr_t)&np->nodename, NODENAME_SIZE);
17271708Sstevel tdatap += NODENAME_SIZE;
17281708Sstevel bcopy(tdatap, (caddr_t)&np->has_children, HASCHILDREN_SIZE);
17291708Sstevel tdatap += HASCHILDREN_SIZE;
17301708Sstevel bcopy(tdatap, (caddr_t)&np->class, CLASS_SIZE);
17311708Sstevel tdatap += CLASS_SIZE;
17321708Sstevel if (np->class == LOCATION_CLASS) {
17331708Sstevel bcopy(tdatap, (caddr_t)&np->location_slot, SLOT_SIZE);
17341708Sstevel tdatap += SLOT_SIZE;
17351708Sstevel bcopy(tdatap, (caddr_t)&np->location_label, LABEL_SIZE);
17361708Sstevel tdatap += LABEL_SIZE;
17371708Sstevel }
17381708Sstevel }
17391708Sstevel return (0);
17401708Sstevel }
17411708Sstevel
17421708Sstevel /*
17431708Sstevel * Used to pad a Java (SCAPP) section, in preparation for sending it to
17441708Sstevel * C (Solaris). Assumes a fru_info_t and multiple section_t's.
17451708Sstevel */
17461708Sstevel static int
sgfru_section_pad(const caddr_t datap,const int max_cnt,fru_info_t * fru,section_t * sectp)17471708Sstevel sgfru_section_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru,
17481708Sstevel section_t *sectp)
17491708Sstevel {
17501708Sstevel caddr_t tdatap = datap;
17511708Sstevel section_t *sp;
17521708Sstevel int i;
17531708Sstevel
17541708Sstevel tdatap = sgfru_fru_pad(datap, fru);
17551708Sstevel if (max_cnt < fru->cnt)
17561708Sstevel return (ENOMEM);
17571708Sstevel for (i = 0, sp = sectp; i < fru->cnt; i++, sp++) {
17581708Sstevel bcopy(tdatap, (caddr_t)&sp->handle, FRU_HDL_SIZE);
17591708Sstevel tdatap += FRU_HDL_SIZE;
17601708Sstevel bcopy(tdatap, (caddr_t)&sp->offset, OFFSET_SIZE);
17611708Sstevel tdatap += OFFSET_SIZE;
17621708Sstevel bcopy(tdatap, (caddr_t)&sp->length, LENGTH_SIZE);
17631708Sstevel tdatap += LENGTH_SIZE;
17641708Sstevel bcopy(tdatap, (caddr_t)&sp->protected, PROTECTED_SIZE);
17651708Sstevel tdatap += PROTECTED_SIZE;
17661708Sstevel bcopy(tdatap, (caddr_t)&sp->version, VERSION_SIZE);
17671708Sstevel tdatap += VERSION_SIZE;
17681708Sstevel }
17691708Sstevel return (0);
17701708Sstevel }
17711708Sstevel
17721708Sstevel /*
17731708Sstevel * Used to pad a Java (SCAPP) segment, in preparation for sending it to
17741708Sstevel * C (Solaris). Assumes a fru_info_t and multiple segment_t's.
17751708Sstevel */
17761708Sstevel static int
sgfru_segment_pad(const caddr_t datap,const int max_cnt,fru_info_t * fru,segment_t * segp)17771708Sstevel sgfru_segment_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru,
17781708Sstevel segment_t *segp)
17791708Sstevel {
17801708Sstevel caddr_t tdatap = datap;
17811708Sstevel segment_t *sp;
17821708Sstevel int i;
17831708Sstevel
17841708Sstevel tdatap = sgfru_fru_pad(datap, fru);
17851708Sstevel if (max_cnt < fru->cnt)
17861708Sstevel return (ENOMEM);
17871708Sstevel for (i = 0, sp = segp; i < fru->cnt; i++, sp++) {
17881708Sstevel bcopy(tdatap, (caddr_t)&sp->handle, FRU_HDL_SIZE);
17891708Sstevel tdatap += FRU_HDL_SIZE;
17901708Sstevel bcopy(tdatap, (caddr_t)&sp->name, NAME_SIZE);
17911708Sstevel tdatap += NAME_SIZE;
17921708Sstevel bcopy(tdatap, (caddr_t)&sp->descriptor, DESCRIPTOR_SIZE);
17931708Sstevel tdatap += DESCRIPTOR_SIZE;
17941708Sstevel bcopy(tdatap, (caddr_t)&sp->offset, OFFSET_SIZE);
17951708Sstevel tdatap += OFFSET_SIZE;
17961708Sstevel bcopy(tdatap, (caddr_t)&sp->length, LENGTH_SIZE);
17971708Sstevel tdatap += LENGTH_SIZE;
17981708Sstevel }
17991708Sstevel return (0);
18001708Sstevel }
18011708Sstevel
18021708Sstevel /*
18031708Sstevel * Used to pad a Java (SCAPP) packet, in preparation for sending it to
18041708Sstevel * C (Solaris). Assumes a fru_info_t and multiple packet_t's.
18051708Sstevel */
18061708Sstevel static int
sgfru_packet_pad(const caddr_t datap,const int max_cnt,fru_info_t * fru,packet_t * packp)18071708Sstevel sgfru_packet_pad(const caddr_t datap, const int max_cnt, fru_info_t *fru,
18081708Sstevel packet_t *packp)
18091708Sstevel {
18101708Sstevel caddr_t tdatap = datap;
18111708Sstevel packet_t *pp;
18121708Sstevel int i;
18131708Sstevel
18141708Sstevel tdatap = sgfru_fru_pad(datap, fru);
18151708Sstevel if (max_cnt < fru->cnt)
18161708Sstevel return (ENOMEM);
18171708Sstevel for (i = 0, pp = packp; i < fru->cnt; i++, pp++) {
18181708Sstevel bcopy(tdatap, (caddr_t)&pp->handle, FRU_HDL_SIZE);
18191708Sstevel tdatap += FRU_HDL_SIZE;
18201708Sstevel bcopy(tdatap, (caddr_t)&pp->tag, TAG_SIZE);
18211708Sstevel tdatap += TAG_SIZE;
18221708Sstevel }
18231708Sstevel return (0);
18241708Sstevel }
18251708Sstevel
18261708Sstevel /*
18271708Sstevel * Used to unpad a C (Solaris) fru_info_t, in preparation for sending it to
18281708Sstevel * Java (SCAPP). Assumes a fru_info_t.
18291708Sstevel */
18301708Sstevel static caddr_t
sgfru_fru_unpad(const fru_info_t * fru,caddr_t datap)18311708Sstevel sgfru_fru_unpad(const fru_info_t *fru, caddr_t datap)
18321708Sstevel {
18331708Sstevel caddr_t tdatap = datap;
18341708Sstevel
18351708Sstevel bcopy((caddr_t)&fru->hdl, tdatap, FRU_HDL_SIZE);
18361708Sstevel tdatap += FRU_HDL_SIZE;
18371708Sstevel bcopy((caddr_t)&fru->cnt, tdatap, FRU_CNT_SIZE);
18381708Sstevel tdatap += FRU_CNT_SIZE;
18391708Sstevel return (tdatap);
18401708Sstevel }
18411708Sstevel
18421708Sstevel /*
18431708Sstevel * Used to unpad a C (Solaris) segment, in preparation for sending it to
18441708Sstevel * Java (SCAPP). Assumes a section_hdl_t and one segment_t.
18451708Sstevel */
18461708Sstevel static void
sgfru_segment_unpad(const fru_info_t * fru,const segment_t * segp,caddr_t datap)18471708Sstevel sgfru_segment_unpad(const fru_info_t *fru, const segment_t *segp,
18481708Sstevel caddr_t datap)
18491708Sstevel {
18501708Sstevel caddr_t tdatap = datap;
18511708Sstevel
18521708Sstevel bcopy((caddr_t)&fru->hdl, tdatap, FRU_HDL_SIZE);
18531708Sstevel tdatap += FRU_HDL_SIZE;
18541708Sstevel bcopy((caddr_t)&segp->handle, tdatap, FRU_HDL_SIZE);
18551708Sstevel tdatap += FRU_HDL_SIZE;
18561708Sstevel bcopy((caddr_t)&segp->name, tdatap, NAME_SIZE);
18571708Sstevel tdatap += NAME_SIZE;
18581708Sstevel bcopy((caddr_t)&segp->descriptor, tdatap, DESCRIPTOR_SIZE);
18591708Sstevel tdatap += DESCRIPTOR_SIZE;
18601708Sstevel bcopy((caddr_t)&segp->offset, tdatap, OFFSET_SIZE);
18611708Sstevel tdatap += OFFSET_SIZE;
18621708Sstevel bcopy((caddr_t)&segp->length, tdatap, LENGTH_SIZE);
18631708Sstevel }
18641708Sstevel
18651708Sstevel /*
18661708Sstevel * Used to unpad a C (Solaris) packet, in preparation for sending it to
18671708Sstevel * Java (SCAPP). Assumes a fru_info_t and one packet_t.
18681708Sstevel */
18691708Sstevel static caddr_t
sgfru_packet_unpad(const fru_info_t * fru,const packet_t * packp,caddr_t datap)18701708Sstevel sgfru_packet_unpad(const fru_info_t *fru, const packet_t *packp, caddr_t datap)
18711708Sstevel {
18721708Sstevel caddr_t tdatap = datap;
18731708Sstevel
18741708Sstevel bcopy((caddr_t)&fru->hdl, tdatap, FRU_HDL_SIZE);
18751708Sstevel tdatap += FRU_HDL_SIZE;
18761708Sstevel bcopy((caddr_t)&fru->cnt, tdatap, FRU_CNT_SIZE);
18771708Sstevel tdatap += FRU_CNT_SIZE;
18781708Sstevel bcopy((caddr_t)&packp->handle, tdatap, FRU_HDL_SIZE);
18791708Sstevel tdatap += FRU_HDL_SIZE;
18801708Sstevel bcopy((caddr_t)&packp->tag, tdatap, TAG_SIZE);
18811708Sstevel tdatap += TAG_SIZE;
18821708Sstevel return (tdatap);
18831708Sstevel }
1884