1*1708Sstevel /* 2*1708Sstevel * CDDL HEADER START 3*1708Sstevel * 4*1708Sstevel * The contents of this file are subject to the terms of the 5*1708Sstevel * Common Development and Distribution License (the "License"). 6*1708Sstevel * You may not use this file except in compliance with the License. 7*1708Sstevel * 8*1708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1708Sstevel * or http://www.opensolaris.org/os/licensing. 10*1708Sstevel * See the License for the specific language governing permissions 11*1708Sstevel * and limitations under the License. 12*1708Sstevel * 13*1708Sstevel * When distributing Covered Code, include this CDDL HEADER in each 14*1708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1708Sstevel * If applicable, add the following below this CDDL HEADER, with the 16*1708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying 17*1708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner] 18*1708Sstevel * 19*1708Sstevel * CDDL HEADER END 20*1708Sstevel */ 21*1708Sstevel 22*1708Sstevel /* 23*1708Sstevel * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*1708Sstevel * Use is subject to license terms. 25*1708Sstevel */ 26*1708Sstevel 27*1708Sstevel #pragma ident "%Z%%M% %I% %E% SMI" 28*1708Sstevel 29*1708Sstevel #include <sys/stat.h> 30*1708Sstevel #include <sys/conf.h> 31*1708Sstevel #include <sys/modctl.h> 32*1708Sstevel #include <sys/ddi.h> 33*1708Sstevel #include <sys/rmc_comm_dp.h> 34*1708Sstevel #include <sys/rmc_comm_dp_boot.h> 35*1708Sstevel #include <sys/rmc_comm_drvintf.h> 36*1708Sstevel #include <sys/cyclic.h> 37*1708Sstevel #include <sys/rmc_comm.h> 38*1708Sstevel #include <sys/machsystm.h> 39*1708Sstevel #include <sys/file.h> 40*1708Sstevel #include <sys/rmcadm.h> 41*1708Sstevel 42*1708Sstevel /* 43*1708Sstevel * functions local to this driver. 44*1708Sstevel */ 45*1708Sstevel static int rmcadm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, 46*1708Sstevel void **resultp); 47*1708Sstevel static int rmcadm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 48*1708Sstevel static int rmcadm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 49*1708Sstevel static int rmcadm_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p); 50*1708Sstevel static int rmcadm_close(dev_t dev, int flag, int otyp, cred_t *cred_p); 51*1708Sstevel static int rmcadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 52*1708Sstevel cred_t *cred_p, int *rval_p); 53*1708Sstevel 54*1708Sstevel /* 55*1708Sstevel * Driver entry points 56*1708Sstevel */ 57*1708Sstevel static struct cb_ops rmcadm_cb_ops = { 58*1708Sstevel rmcadm_open, /* open */ 59*1708Sstevel rmcadm_close, /* close */ 60*1708Sstevel nodev, /* strategy() */ 61*1708Sstevel nodev, /* print() */ 62*1708Sstevel nodev, /* dump() */ 63*1708Sstevel nodev, /* read() */ 64*1708Sstevel nodev, /* write() */ 65*1708Sstevel rmcadm_ioctl, /* ioctl() */ 66*1708Sstevel nodev, /* devmap() */ 67*1708Sstevel nodev, /* mmap() */ 68*1708Sstevel ddi_segmap, /* segmap() */ 69*1708Sstevel nochpoll, /* poll() */ 70*1708Sstevel ddi_prop_op, /* prop_op() */ 71*1708Sstevel NULL, /* cb_str */ 72*1708Sstevel D_NEW | D_MP /* cb_flag */ 73*1708Sstevel }; 74*1708Sstevel 75*1708Sstevel 76*1708Sstevel static struct dev_ops rmcadm_ops = { 77*1708Sstevel DEVO_REV, 78*1708Sstevel 0, /* ref count */ 79*1708Sstevel rmcadm_getinfo, /* getinfo() */ 80*1708Sstevel nulldev, /* identify() */ 81*1708Sstevel nulldev, /* probe() */ 82*1708Sstevel rmcadm_attach, /* attach() */ 83*1708Sstevel rmcadm_detach, /* detach */ 84*1708Sstevel nodev, /* reset */ 85*1708Sstevel &rmcadm_cb_ops, /* pointer to cb_ops structure */ 86*1708Sstevel (struct bus_ops *)NULL, 87*1708Sstevel nulldev /* power() */ 88*1708Sstevel }; 89*1708Sstevel 90*1708Sstevel /* 91*1708Sstevel * Loadable module support. 92*1708Sstevel */ 93*1708Sstevel extern struct mod_ops mod_driverops; 94*1708Sstevel 95*1708Sstevel static struct modldrv modldrv = { 96*1708Sstevel &mod_driverops, /* Type of module. This is a driver */ 97*1708Sstevel "rmcadm control driver v%I%", /* Name of the module */ 98*1708Sstevel &rmcadm_ops /* pointer to the dev_ops structure */ 99*1708Sstevel }; 100*1708Sstevel 101*1708Sstevel static struct modlinkage modlinkage = { 102*1708Sstevel MODREV_1, 103*1708Sstevel &modldrv, 104*1708Sstevel NULL 105*1708Sstevel }; 106*1708Sstevel 107*1708Sstevel static dev_info_t *rmcadm_dip = NULL; 108*1708Sstevel 109*1708Sstevel extern void pmugpio_reset(); 110*1708Sstevel 111*1708Sstevel /* 112*1708Sstevel * Utilities... 113*1708Sstevel */ 114*1708Sstevel 115*1708Sstevel /* 116*1708Sstevel * to return the errno from the rmc_comm error status 117*1708Sstevel */ 118*1708Sstevel int 119*1708Sstevel rmcadm_get_errno(int status) 120*1708Sstevel { 121*1708Sstevel int retval = EIO; 122*1708Sstevel 123*1708Sstevel /* errors from RMC */ 124*1708Sstevel switch (status) { 125*1708Sstevel case RCENOSOFTSTATE: 126*1708Sstevel /* invalid/NULL soft state structure */ 127*1708Sstevel retval = EIO; 128*1708Sstevel break; 129*1708Sstevel case RCENODATALINK: 130*1708Sstevel /* data protocol not available (down) */ 131*1708Sstevel retval = EIO; 132*1708Sstevel break; 133*1708Sstevel case RCENOMEM: 134*1708Sstevel /* memory problems */ 135*1708Sstevel retval = ENOMEM; 136*1708Sstevel break; 137*1708Sstevel case RCECANTRESEND: 138*1708Sstevel /* resend failed */ 139*1708Sstevel retval = EIO; 140*1708Sstevel break; 141*1708Sstevel case RCEMAXRETRIES: 142*1708Sstevel /* reply not received - retries exceeded */ 143*1708Sstevel retval = EINTR; 144*1708Sstevel break; 145*1708Sstevel case RCETIMEOUT: 146*1708Sstevel /* reply not received - command has timed out */ 147*1708Sstevel retval = EINTR; 148*1708Sstevel break; 149*1708Sstevel case RCEINVCMD: 150*1708Sstevel /* data protocol cmd not supported */ 151*1708Sstevel retval = ENOTSUP; 152*1708Sstevel break; 153*1708Sstevel case RCEINVARG: 154*1708Sstevel /* invalid argument(s) */ 155*1708Sstevel retval = ENOTSUP; 156*1708Sstevel break; 157*1708Sstevel case RCEGENERIC: 158*1708Sstevel /* generic error */ 159*1708Sstevel retval = EIO; 160*1708Sstevel break; 161*1708Sstevel default: 162*1708Sstevel retval = EIO; 163*1708Sstevel break; 164*1708Sstevel } 165*1708Sstevel return (retval); 166*1708Sstevel } 167*1708Sstevel 168*1708Sstevel int 169*1708Sstevel _init(void) 170*1708Sstevel { 171*1708Sstevel int error = 0; 172*1708Sstevel 173*1708Sstevel error = mod_install(&modlinkage); 174*1708Sstevel return (error); 175*1708Sstevel } 176*1708Sstevel 177*1708Sstevel 178*1708Sstevel int 179*1708Sstevel _info(struct modinfo *modinfop) 180*1708Sstevel { 181*1708Sstevel return (mod_info(&modlinkage, modinfop)); 182*1708Sstevel } 183*1708Sstevel 184*1708Sstevel 185*1708Sstevel int 186*1708Sstevel _fini(void) 187*1708Sstevel { 188*1708Sstevel int error = 0; 189*1708Sstevel 190*1708Sstevel error = mod_remove(&modlinkage); 191*1708Sstevel if (error) 192*1708Sstevel return (error); 193*1708Sstevel return (error); 194*1708Sstevel } 195*1708Sstevel 196*1708Sstevel 197*1708Sstevel /* ARGSUSED */ 198*1708Sstevel static int 199*1708Sstevel rmcadm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp) 200*1708Sstevel { 201*1708Sstevel minor_t m = getminor((dev_t)arg); 202*1708Sstevel 203*1708Sstevel switch (cmd) { 204*1708Sstevel case DDI_INFO_DEVT2DEVINFO: 205*1708Sstevel if ((m != 0) || (rmcadm_dip == NULL)) { 206*1708Sstevel *resultp = NULL; 207*1708Sstevel return (DDI_FAILURE); 208*1708Sstevel } 209*1708Sstevel *resultp = rmcadm_dip; 210*1708Sstevel return (DDI_SUCCESS); 211*1708Sstevel case DDI_INFO_DEVT2INSTANCE: 212*1708Sstevel *resultp = (void *)(uintptr_t)m; 213*1708Sstevel return (DDI_SUCCESS); 214*1708Sstevel default: 215*1708Sstevel return (DDI_FAILURE); 216*1708Sstevel } 217*1708Sstevel } 218*1708Sstevel 219*1708Sstevel 220*1708Sstevel static int 221*1708Sstevel rmcadm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 222*1708Sstevel { 223*1708Sstevel int instance; 224*1708Sstevel int err; 225*1708Sstevel 226*1708Sstevel switch (cmd) { 227*1708Sstevel case DDI_ATTACH: 228*1708Sstevel /* 229*1708Sstevel * only allow one instance 230*1708Sstevel */ 231*1708Sstevel instance = ddi_get_instance(dip); 232*1708Sstevel if (instance != 0) 233*1708Sstevel return (DDI_FAILURE); 234*1708Sstevel 235*1708Sstevel err = ddi_create_minor_node(dip, "rmcadm", S_IFCHR, 236*1708Sstevel instance, DDI_PSEUDO, NULL); 237*1708Sstevel if (err != DDI_SUCCESS) 238*1708Sstevel return (DDI_FAILURE); 239*1708Sstevel 240*1708Sstevel /* 241*1708Sstevel * Register with rmc_comm to prevent it being detached 242*1708Sstevel */ 243*1708Sstevel err = rmc_comm_register(); 244*1708Sstevel if (err != DDI_SUCCESS) { 245*1708Sstevel ddi_remove_minor_node(dip, NULL); 246*1708Sstevel return (DDI_FAILURE); 247*1708Sstevel } 248*1708Sstevel 249*1708Sstevel /* Remember the dev info */ 250*1708Sstevel rmcadm_dip = dip; 251*1708Sstevel 252*1708Sstevel ddi_report_dev(dip); 253*1708Sstevel return (DDI_SUCCESS); 254*1708Sstevel case DDI_RESUME: 255*1708Sstevel return (DDI_SUCCESS); 256*1708Sstevel default: 257*1708Sstevel return (DDI_FAILURE); 258*1708Sstevel } 259*1708Sstevel } 260*1708Sstevel 261*1708Sstevel 262*1708Sstevel static int 263*1708Sstevel rmcadm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 264*1708Sstevel { 265*1708Sstevel int instance; 266*1708Sstevel 267*1708Sstevel switch (cmd) { 268*1708Sstevel case DDI_DETACH: 269*1708Sstevel instance = ddi_get_instance(dip); 270*1708Sstevel if (instance != 0) 271*1708Sstevel return (DDI_FAILURE); 272*1708Sstevel 273*1708Sstevel rmcadm_dip = NULL; 274*1708Sstevel ddi_remove_minor_node(dip, NULL); 275*1708Sstevel rmc_comm_unregister(); 276*1708Sstevel return (DDI_SUCCESS); 277*1708Sstevel case DDI_SUSPEND: 278*1708Sstevel return (DDI_SUCCESS); 279*1708Sstevel default: 280*1708Sstevel return (DDI_FAILURE); 281*1708Sstevel } 282*1708Sstevel } 283*1708Sstevel 284*1708Sstevel /*ARGSUSED*/ 285*1708Sstevel static int 286*1708Sstevel rmcadm_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p) 287*1708Sstevel { 288*1708Sstevel int error = 0; 289*1708Sstevel int instance = getminor(*dev_p); 290*1708Sstevel 291*1708Sstevel if (instance != 0) 292*1708Sstevel return (ENXIO); 293*1708Sstevel 294*1708Sstevel if ((error = drv_priv(cred_p)) != 0) { 295*1708Sstevel cmn_err(CE_WARN, "rmcadm: inst %d drv_priv failed", 296*1708Sstevel instance); 297*1708Sstevel return (error); 298*1708Sstevel } 299*1708Sstevel return (error); 300*1708Sstevel } 301*1708Sstevel 302*1708Sstevel /*ARGSUSED*/ 303*1708Sstevel static int 304*1708Sstevel rmcadm_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 305*1708Sstevel { 306*1708Sstevel return (DDI_SUCCESS); 307*1708Sstevel } 308*1708Sstevel 309*1708Sstevel /*ARGSUSED*/ 310*1708Sstevel static int 311*1708Sstevel rmcadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p, 312*1708Sstevel int *rval_p) 313*1708Sstevel { 314*1708Sstevel int instance = getminor(dev); 315*1708Sstevel int retval = 0; 316*1708Sstevel rmcadm_request_response_t rr; 317*1708Sstevel rmcadm_send_srecord_bp_t ssbp; 318*1708Sstevel rmc_comm_msg_t rmc_req, *rmc_reqp = &rmc_req; 319*1708Sstevel rmc_comm_msg_t rmc_resp, *rmc_respp = &rmc_resp; 320*1708Sstevel caddr_t user_req_buf; 321*1708Sstevel caddr_t user_data_buf; 322*1708Sstevel caddr_t user_resp_buf; 323*1708Sstevel 324*1708Sstevel if (instance != 0) 325*1708Sstevel return (ENXIO); 326*1708Sstevel 327*1708Sstevel switch (cmd) { 328*1708Sstevel 329*1708Sstevel case RMCADM_REQUEST_RESPONSE: 330*1708Sstevel case RMCADM_REQUEST_RESPONSE_BP: 331*1708Sstevel 332*1708Sstevel /* 333*1708Sstevel * first copy in the request_response structure 334*1708Sstevel */ 335*1708Sstevel #ifdef _MULTI_DATAMODEL 336*1708Sstevel switch (ddi_model_convert_from(mode & FMODELS)) { 337*1708Sstevel case DDI_MODEL_ILP32: 338*1708Sstevel { 339*1708Sstevel /* 340*1708Sstevel * For use when a 32 bit app makes a call into a 341*1708Sstevel * 64 bit ioctl 342*1708Sstevel */ 343*1708Sstevel rmcadm_request_response32_t rr32; 344*1708Sstevel 345*1708Sstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&rr32, 346*1708Sstevel sizeof (rr32), mode)) { 347*1708Sstevel return (EFAULT); 348*1708Sstevel } 349*1708Sstevel rr.req.msg_type = rr32.req.msg_type; 350*1708Sstevel rr.req.msg_len = rr32.req.msg_len; 351*1708Sstevel rr.req.msg_bytes = rr32.req.msg_bytes; 352*1708Sstevel rr.req.msg_buf = (caddr_t)(uintptr_t)rr32.req.msg_buf; 353*1708Sstevel rr.resp.msg_type = rr32.resp.msg_type; 354*1708Sstevel rr.resp.msg_len = rr32.resp.msg_len; 355*1708Sstevel rr.resp.msg_bytes = rr32.resp.msg_bytes; 356*1708Sstevel rr.resp.msg_buf = (caddr_t)(uintptr_t)rr32.resp.msg_buf; 357*1708Sstevel rr.wait_time = rr32.wait_time; 358*1708Sstevel break; 359*1708Sstevel } 360*1708Sstevel case DDI_MODEL_NONE: 361*1708Sstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&rr, 362*1708Sstevel sizeof (rr), mode)) { 363*1708Sstevel return (EFAULT); 364*1708Sstevel } 365*1708Sstevel break; 366*1708Sstevel } 367*1708Sstevel #else /* ! _MULTI_DATAMODEL */ 368*1708Sstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&rr, 369*1708Sstevel sizeof (rr), mode) != 0) { 370*1708Sstevel return (EFAULT); 371*1708Sstevel } 372*1708Sstevel #endif /* _MULTI_DATAMODEL */ 373*1708Sstevel 374*1708Sstevel /* 375*1708Sstevel * save the user request buffer pointer 376*1708Sstevel */ 377*1708Sstevel user_req_buf = rr.req.msg_buf; 378*1708Sstevel 379*1708Sstevel if (user_req_buf != NULL) { 380*1708Sstevel /* 381*1708Sstevel * copy in the request data 382*1708Sstevel */ 383*1708Sstevel rr.req.msg_buf = kmem_alloc(rr.req.msg_len, KM_SLEEP); 384*1708Sstevel 385*1708Sstevel if (ddi_copyin(user_req_buf, rr.req.msg_buf, 386*1708Sstevel rr.req.msg_len, mode) != 0) { 387*1708Sstevel 388*1708Sstevel kmem_free(rr.req.msg_buf, rr.req.msg_len); 389*1708Sstevel rr.req.msg_buf = user_req_buf; 390*1708Sstevel return (EFAULT); 391*1708Sstevel } 392*1708Sstevel } else { 393*1708Sstevel if (rr.req.msg_len > 0) 394*1708Sstevel /* 395*1708Sstevel * msg_len should be 0 if buffer is NULL! 396*1708Sstevel */ 397*1708Sstevel return (EINVAL); 398*1708Sstevel } 399*1708Sstevel 400*1708Sstevel /* 401*1708Sstevel * save the user request buffer pointer 402*1708Sstevel */ 403*1708Sstevel user_resp_buf = rr.resp.msg_buf; 404*1708Sstevel if (user_resp_buf != NULL) { 405*1708Sstevel rr.resp.msg_buf = kmem_alloc(rr.resp.msg_len, KM_SLEEP); 406*1708Sstevel } 407*1708Sstevel 408*1708Sstevel /* 409*1708Sstevel * send the request (or BP request) via the rmc_comm driver 410*1708Sstevel */ 411*1708Sstevel rmc_reqp->msg_type = rr.req.msg_type; 412*1708Sstevel rmc_reqp->msg_buf = rr.req.msg_buf; 413*1708Sstevel rmc_reqp->msg_len = rr.req.msg_len; 414*1708Sstevel rmc_reqp->msg_bytes = rr.req.msg_bytes; 415*1708Sstevel 416*1708Sstevel if (cmd == RMCADM_REQUEST_RESPONSE) { 417*1708Sstevel 418*1708Sstevel /* 419*1708Sstevel * check if response is expected. If so, fill in 420*1708Sstevel * the response data structure 421*1708Sstevel */ 422*1708Sstevel if (rr.resp.msg_type != DP_NULL_MSG) { 423*1708Sstevel 424*1708Sstevel rmc_respp->msg_type = rr.resp.msg_type; 425*1708Sstevel rmc_respp->msg_buf = rr.resp.msg_buf; 426*1708Sstevel rmc_respp->msg_len = rr.resp.msg_len; 427*1708Sstevel rmc_respp->msg_bytes = rr.resp.msg_bytes; 428*1708Sstevel 429*1708Sstevel } else { 430*1708Sstevel 431*1708Sstevel rmc_respp = (rmc_comm_msg_t *)NULL; 432*1708Sstevel } 433*1708Sstevel 434*1708Sstevel rr.status = rmc_comm_request_response( 435*1708Sstevel rmc_reqp, rmc_respp, rr.wait_time); 436*1708Sstevel 437*1708Sstevel } else { /* RMCADM_REQUEST_RESPONSE_BP */ 438*1708Sstevel 439*1708Sstevel /* 440*1708Sstevel * check if a BP message is expected back. If so, 441*1708Sstevel * fill in the response data structure 442*1708Sstevel */ 443*1708Sstevel if (rr.resp.msg_buf != NULL) { 444*1708Sstevel 445*1708Sstevel rmc_respp->msg_type = rr.resp.msg_type; 446*1708Sstevel rmc_respp->msg_buf = rr.resp.msg_buf; 447*1708Sstevel rmc_respp->msg_len = rr.resp.msg_len; 448*1708Sstevel rmc_respp->msg_bytes = rr.resp.msg_bytes; 449*1708Sstevel 450*1708Sstevel } else { 451*1708Sstevel 452*1708Sstevel rmc_respp = (rmc_comm_msg_t *)NULL; 453*1708Sstevel } 454*1708Sstevel 455*1708Sstevel rr.status = rmc_comm_request_response_bp( 456*1708Sstevel rmc_reqp, rmc_respp, rr.wait_time); 457*1708Sstevel } 458*1708Sstevel 459*1708Sstevel /* 460*1708Sstevel * if a response was expected, copy back the (actual) number 461*1708Sstevel * of bytes of the response returned by the 462*1708Sstevel * rmc_comm_request_response function (msg_bytes field) 463*1708Sstevel */ 464*1708Sstevel if (rmc_respp != NULL) { 465*1708Sstevel rr.resp.msg_bytes = rmc_respp->msg_bytes; 466*1708Sstevel } 467*1708Sstevel 468*1708Sstevel if (rr.status != RCNOERR) { 469*1708Sstevel 470*1708Sstevel retval = rmcadm_get_errno(rr.status); 471*1708Sstevel 472*1708Sstevel } else if (user_resp_buf != NULL) { 473*1708Sstevel /* 474*1708Sstevel * copy out the user response buffer 475*1708Sstevel */ 476*1708Sstevel if (ddi_copyout(rr.resp.msg_buf, user_resp_buf, 477*1708Sstevel rr.resp.msg_bytes, mode) != 0) { 478*1708Sstevel retval = EFAULT; 479*1708Sstevel } 480*1708Sstevel } 481*1708Sstevel 482*1708Sstevel /* 483*1708Sstevel * now copy out the updated request_response structure 484*1708Sstevel */ 485*1708Sstevel if (rr.req.msg_buf) 486*1708Sstevel kmem_free(rr.req.msg_buf, rr.req.msg_len); 487*1708Sstevel if (rr.resp.msg_buf) 488*1708Sstevel kmem_free(rr.resp.msg_buf, rr.resp.msg_len); 489*1708Sstevel 490*1708Sstevel rr.req.msg_buf = user_req_buf; 491*1708Sstevel rr.resp.msg_buf = user_resp_buf; 492*1708Sstevel 493*1708Sstevel #ifdef _MULTI_DATAMODEL 494*1708Sstevel switch (ddi_model_convert_from(mode & FMODELS)) { 495*1708Sstevel case DDI_MODEL_ILP32: 496*1708Sstevel { 497*1708Sstevel /* 498*1708Sstevel * For use when a 32 bit app makes a call into a 499*1708Sstevel * 64 bit ioctl 500*1708Sstevel */ 501*1708Sstevel rmcadm_request_response32_t rr32; 502*1708Sstevel 503*1708Sstevel rr32.req.msg_type = rr.req.msg_type; 504*1708Sstevel rr32.req.msg_len = rr.req.msg_len; 505*1708Sstevel rr32.req.msg_bytes = rr.req.msg_bytes; 506*1708Sstevel rr32.req.msg_buf = (caddr32_t)(uintptr_t)rr.req.msg_buf; 507*1708Sstevel rr32.resp.msg_type = rr.resp.msg_type; 508*1708Sstevel rr32.resp.msg_len = rr.resp.msg_len; 509*1708Sstevel rr32.resp.msg_bytes = rr.resp.msg_bytes; 510*1708Sstevel rr32.resp.msg_buf = 511*1708Sstevel (caddr32_t)(uintptr_t)rr.resp.msg_buf; 512*1708Sstevel rr32.wait_time = rr.wait_time; 513*1708Sstevel rr32.status = rr.status; 514*1708Sstevel if (ddi_copyout((caddr_t)&rr32, (caddr_t)arg, 515*1708Sstevel sizeof (rr32), mode)) { 516*1708Sstevel return (EFAULT); 517*1708Sstevel } 518*1708Sstevel break; 519*1708Sstevel } 520*1708Sstevel case DDI_MODEL_NONE: 521*1708Sstevel if (ddi_copyout((caddr_t)&rr, (caddr_t)arg, 522*1708Sstevel sizeof (rr), mode)) 523*1708Sstevel return (EFAULT); 524*1708Sstevel break; 525*1708Sstevel } 526*1708Sstevel #else /* ! _MULTI_DATAMODEL */ 527*1708Sstevel if (ddi_copyout((caddr_t)&rr, (caddr_t)arg, sizeof (rr), 528*1708Sstevel mode) != 0) 529*1708Sstevel return (EFAULT); 530*1708Sstevel #endif /* _MULTI_DATAMODEL */ 531*1708Sstevel break; 532*1708Sstevel 533*1708Sstevel 534*1708Sstevel case RMCADM_SEND_SRECORD_BP: 535*1708Sstevel 536*1708Sstevel /* 537*1708Sstevel * first copy in the request_response structure 538*1708Sstevel */ 539*1708Sstevel #ifdef _MULTI_DATAMODEL 540*1708Sstevel switch (ddi_model_convert_from(mode & FMODELS)) { 541*1708Sstevel case DDI_MODEL_ILP32: 542*1708Sstevel { 543*1708Sstevel /* 544*1708Sstevel * For use when a 32 bit app makes a call into a 545*1708Sstevel * 64 bit ioctl 546*1708Sstevel */ 547*1708Sstevel rmcadm_send_srecord_bp32_t ssbp32; 548*1708Sstevel 549*1708Sstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&ssbp32, 550*1708Sstevel sizeof (ssbp32), mode)) { 551*1708Sstevel return (EFAULT); 552*1708Sstevel } 553*1708Sstevel ssbp.data_len = ssbp32.data_len; 554*1708Sstevel ssbp.data_buf = (caddr_t)(uintptr_t)ssbp32.data_buf; 555*1708Sstevel ssbp.resp_bp.msg_type = ssbp32.resp_bp.msg_type; 556*1708Sstevel ssbp.resp_bp.msg_len = ssbp32.resp_bp.msg_len; 557*1708Sstevel ssbp.resp_bp.msg_bytes = ssbp32.resp_bp.msg_bytes; 558*1708Sstevel ssbp.resp_bp.msg_buf = 559*1708Sstevel (caddr_t)(uintptr_t)ssbp32.resp_bp.msg_buf; 560*1708Sstevel ssbp.wait_time = ssbp32.wait_time; 561*1708Sstevel break; 562*1708Sstevel } 563*1708Sstevel case DDI_MODEL_NONE: 564*1708Sstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&ssbp, 565*1708Sstevel sizeof (ssbp), mode)) 566*1708Sstevel return (EFAULT); 567*1708Sstevel break; 568*1708Sstevel } 569*1708Sstevel #else /* ! _MULTI_DATAMODEL */ 570*1708Sstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&ssbp, 571*1708Sstevel sizeof (ssbp), mode) != 0) 572*1708Sstevel return (EFAULT); 573*1708Sstevel #endif /* _MULTI_DATAMODEL */ 574*1708Sstevel 575*1708Sstevel /* 576*1708Sstevel * save the user data buffer pointer 577*1708Sstevel */ 578*1708Sstevel user_data_buf = ssbp.data_buf; 579*1708Sstevel 580*1708Sstevel if (user_data_buf != NULL) { 581*1708Sstevel /* 582*1708Sstevel * copy in the srecord data 583*1708Sstevel */ 584*1708Sstevel ssbp.data_buf = kmem_alloc(ssbp.data_len, KM_SLEEP); 585*1708Sstevel 586*1708Sstevel if (ddi_copyin(user_data_buf, ssbp.data_buf, 587*1708Sstevel ssbp.data_len, mode) != 0) { 588*1708Sstevel 589*1708Sstevel kmem_free(ssbp.data_buf, ssbp.data_len); 590*1708Sstevel ssbp.data_buf = user_data_buf; 591*1708Sstevel return (EFAULT); 592*1708Sstevel } 593*1708Sstevel } else { 594*1708Sstevel return (EINVAL); /* request can't be NULL! */ 595*1708Sstevel } 596*1708Sstevel 597*1708Sstevel /* 598*1708Sstevel * save the user request buffer pointer 599*1708Sstevel */ 600*1708Sstevel user_resp_buf = ssbp.resp_bp.msg_buf; 601*1708Sstevel if (user_resp_buf != NULL) { 602*1708Sstevel ssbp.resp_bp.msg_buf = 603*1708Sstevel kmem_alloc(ssbp.resp_bp.msg_len, KM_SLEEP); 604*1708Sstevel } else { 605*1708Sstevel 606*1708Sstevel kmem_free(ssbp.data_buf, ssbp.data_len); 607*1708Sstevel return (EINVAL); 608*1708Sstevel } 609*1708Sstevel 610*1708Sstevel /* 611*1708Sstevel * send the srecord via the rmc_comm driver and get the reply 612*1708Sstevel * back (BP message) 613*1708Sstevel */ 614*1708Sstevel 615*1708Sstevel rmc_respp->msg_type = ssbp.resp_bp.msg_type; 616*1708Sstevel rmc_respp->msg_buf = ssbp.resp_bp.msg_buf; 617*1708Sstevel rmc_respp->msg_len = ssbp.resp_bp.msg_len; 618*1708Sstevel rmc_respp->msg_bytes = ssbp.resp_bp.msg_bytes; 619*1708Sstevel 620*1708Sstevel ssbp.status = rmc_comm_send_srecord_bp(ssbp.data_buf, 621*1708Sstevel ssbp.data_len, rmc_respp, ssbp.wait_time); 622*1708Sstevel 623*1708Sstevel /* 624*1708Sstevel * copy back the actual size of the returned message 625*1708Sstevel */ 626*1708Sstevel ssbp.resp_bp.msg_bytes = rmc_respp->msg_bytes; 627*1708Sstevel 628*1708Sstevel if (ssbp.status != RCNOERR) { 629*1708Sstevel retval = rmcadm_get_errno(ssbp.status); 630*1708Sstevel 631*1708Sstevel } else if (user_resp_buf != NULL) { 632*1708Sstevel /* 633*1708Sstevel * copy out the user BP response buffer 634*1708Sstevel */ 635*1708Sstevel if (ddi_copyout(ssbp.resp_bp.msg_buf, user_resp_buf, 636*1708Sstevel ssbp.resp_bp.msg_bytes, mode) != 0) { 637*1708Sstevel retval = EFAULT; 638*1708Sstevel } 639*1708Sstevel } 640*1708Sstevel 641*1708Sstevel /* 642*1708Sstevel * now copy out the updated request_response structure 643*1708Sstevel */ 644*1708Sstevel if (ssbp.data_buf) 645*1708Sstevel kmem_free(ssbp.data_buf, ssbp.data_len); 646*1708Sstevel if (ssbp.resp_bp.msg_buf) 647*1708Sstevel kmem_free(ssbp.resp_bp.msg_buf, ssbp.resp_bp.msg_len); 648*1708Sstevel 649*1708Sstevel ssbp.data_buf = user_data_buf; 650*1708Sstevel ssbp.resp_bp.msg_buf = user_resp_buf; 651*1708Sstevel 652*1708Sstevel #ifdef _MULTI_DATAMODEL 653*1708Sstevel switch (ddi_model_convert_from(mode & FMODELS)) { 654*1708Sstevel case DDI_MODEL_ILP32: 655*1708Sstevel { 656*1708Sstevel /* 657*1708Sstevel * For use when a 32 bit app makes a call into a 658*1708Sstevel * 64 bit ioctl 659*1708Sstevel */ 660*1708Sstevel rmcadm_send_srecord_bp32_t ssbp32; 661*1708Sstevel 662*1708Sstevel ssbp32.data_len = ssbp.data_len; 663*1708Sstevel ssbp32.data_buf = (caddr32_t)(uintptr_t)ssbp.data_buf; 664*1708Sstevel ssbp32.resp_bp.msg_type = ssbp.resp_bp.msg_type; 665*1708Sstevel ssbp32.resp_bp.msg_len = ssbp.resp_bp.msg_len; 666*1708Sstevel ssbp32.resp_bp.msg_bytes = ssbp.resp_bp.msg_bytes; 667*1708Sstevel ssbp32.resp_bp.msg_buf = 668*1708Sstevel (caddr32_t)(uintptr_t)ssbp.resp_bp.msg_buf; 669*1708Sstevel ssbp32.wait_time = ssbp.wait_time; 670*1708Sstevel 671*1708Sstevel if (ddi_copyout((caddr_t)&ssbp32, (caddr_t)arg, 672*1708Sstevel sizeof (ssbp32), mode)) { 673*1708Sstevel return (EFAULT); 674*1708Sstevel } 675*1708Sstevel break; 676*1708Sstevel } 677*1708Sstevel case DDI_MODEL_NONE: 678*1708Sstevel if (ddi_copyout((caddr_t)&ssbp, (caddr_t)arg, 679*1708Sstevel sizeof (ssbp), mode)) 680*1708Sstevel return (EFAULT); 681*1708Sstevel break; 682*1708Sstevel } 683*1708Sstevel #else /* ! _MULTI_DATAMODEL */ 684*1708Sstevel if (ddi_copyout((caddr_t)&ssbp, (caddr_t)arg, sizeof (ssbp), 685*1708Sstevel mode) != 0) 686*1708Sstevel return (EFAULT); 687*1708Sstevel #endif /* _MULTI_DATAMODEL */ 688*1708Sstevel break; 689*1708Sstevel 690*1708Sstevel 691*1708Sstevel case RMCADM_RESET_SP: 692*1708Sstevel pmugpio_reset(); 693*1708Sstevel retval = 0; 694*1708Sstevel break; 695*1708Sstevel default: 696*1708Sstevel retval = ENOTSUP; 697*1708Sstevel break; 698*1708Sstevel } 699*1708Sstevel return (retval); 700*1708Sstevel } 701