10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * Driver to map the PIC for the chicago platform. 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate #include <sys/types.h> 330Sstevel@tonic-gate #include <sys/time.h> 340Sstevel@tonic-gate #include <sys/errno.h> 350Sstevel@tonic-gate #include <sys/cmn_err.h> 360Sstevel@tonic-gate #include <sys/param.h> 370Sstevel@tonic-gate #include <sys/modctl.h> 380Sstevel@tonic-gate #include <sys/conf.h> 390Sstevel@tonic-gate #include <sys/open.h> 400Sstevel@tonic-gate #include <sys/stat.h> 410Sstevel@tonic-gate #include <sys/clock.h> 420Sstevel@tonic-gate #include <sys/pic.h> 430Sstevel@tonic-gate #include <sys/pic16f747.h> 440Sstevel@tonic-gate #include <sys/ddi.h> 450Sstevel@tonic-gate #include <sys/sunddi.h> 460Sstevel@tonic-gate #include <sys/file.h> 470Sstevel@tonic-gate 480Sstevel@tonic-gate /* dev_ops and cb_ops entry point function declarations */ 490Sstevel@tonic-gate static int pic_attach(dev_info_t *, ddi_attach_cmd_t); 500Sstevel@tonic-gate static int pic_detach(dev_info_t *, ddi_detach_cmd_t); 510Sstevel@tonic-gate static int pic_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 520Sstevel@tonic-gate static int pic_open(dev_t *, int, int, cred_t *); 530Sstevel@tonic-gate static int pic_close(dev_t, int, int, cred_t *); 540Sstevel@tonic-gate static int pic_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 550Sstevel@tonic-gate 560Sstevel@tonic-gate struct cb_ops pic_cb_ops = { 570Sstevel@tonic-gate pic_open, 580Sstevel@tonic-gate pic_close, 590Sstevel@tonic-gate nodev, 600Sstevel@tonic-gate nodev, 610Sstevel@tonic-gate nodev, /* dump */ 620Sstevel@tonic-gate nodev, 630Sstevel@tonic-gate nodev, 640Sstevel@tonic-gate pic_ioctl, 650Sstevel@tonic-gate nodev, /* devmap */ 660Sstevel@tonic-gate nodev, 670Sstevel@tonic-gate ddi_segmap, /* segmap */ 680Sstevel@tonic-gate nochpoll, 690Sstevel@tonic-gate ddi_prop_op, 700Sstevel@tonic-gate NULL, /* for STREAMS drivers */ 710Sstevel@tonic-gate D_NEW | D_MP /* driver compatibility flag */ 720Sstevel@tonic-gate }; 730Sstevel@tonic-gate 740Sstevel@tonic-gate static struct dev_ops pic_dev_ops = { 750Sstevel@tonic-gate DEVO_REV, /* driver build version */ 760Sstevel@tonic-gate 0, /* device reference count */ 770Sstevel@tonic-gate pic_getinfo, 780Sstevel@tonic-gate nulldev, 790Sstevel@tonic-gate nulldev, /* probe */ 800Sstevel@tonic-gate pic_attach, 810Sstevel@tonic-gate pic_detach, 820Sstevel@tonic-gate nulldev, /* reset */ 830Sstevel@tonic-gate &pic_cb_ops, 840Sstevel@tonic-gate (struct bus_ops *)NULL, 850Sstevel@tonic-gate nulldev /* power */ 860Sstevel@tonic-gate }; 870Sstevel@tonic-gate 880Sstevel@tonic-gate /* 890Sstevel@tonic-gate * Fans' and sensors' node names and register offsets 900Sstevel@tonic-gate */ 910Sstevel@tonic-gate static struct minor_node_info pic_nodes[N_PIC_NODES] = { 920Sstevel@tonic-gate {NULL, 0, 0}, /* Reserved */ 930Sstevel@tonic-gate {"fan_0", RF_FAN0_PERIOD, 0}, /* System Fan 0 */ 940Sstevel@tonic-gate {"fan_1", RF_FAN1_PERIOD, 1}, /* System Fan 1 */ 950Sstevel@tonic-gate {"fan_2", RF_FAN2_PERIOD, 2}, /* System Fan 2 */ 960Sstevel@tonic-gate {"fan_3", RF_FAN3_PERIOD, 3}, /* System Fan 3 */ 970Sstevel@tonic-gate {"fan_4", RF_FAN4_PERIOD, 4}, /* System Fan 4 in P0.1 */ 980Sstevel@tonic-gate {"adt7462", RF_LOCAL_TEMP, 0}, /* ADT7462 Local Temperature */ 990Sstevel@tonic-gate {"cpu_0", RF_REMOTE1_TEMP, 0}, /* CPU 0 temp */ 1000Sstevel@tonic-gate {"cpu_1", RF_REMOTE2_TEMP, 0}, /* CPU 1 temp */ 1010Sstevel@tonic-gate {"mb", RF_REMOTE3_TEMP, 0}, /* Motherboard temp */ 1020Sstevel@tonic-gate {"lm95221", RF_LM95221_TEMP, 0}, /* LM95221 Local Temperature */ 1030Sstevel@tonic-gate {"fire", RF_FIRE_TEMP, 0}, /* FIRE Temp */ 1040Sstevel@tonic-gate {"lsi1064", RF_LSI1064_TEMP, 0}, /* LSI1064 Temp */ 1050Sstevel@tonic-gate {"front_panel", RF_FRONT_TEMP, 0} /* Front Panel Temperature */ 1060Sstevel@tonic-gate }; 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate /* 1090Sstevel@tonic-gate * Soft state 1100Sstevel@tonic-gate */ 1110Sstevel@tonic-gate struct pic_softc { 1120Sstevel@tonic-gate dev_info_t *dip; 1130Sstevel@tonic-gate kmutex_t mutex; 1140Sstevel@tonic-gate uint8_t *cmd_reg; 1150Sstevel@tonic-gate ddi_acc_handle_t cmd_handle; 1160Sstevel@tonic-gate }; 1170Sstevel@tonic-gate #define getsoftc(inst) ((struct pic_softc *)ddi_get_soft_state(statep, (inst))) 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate /* module configuration stuff */ 1200Sstevel@tonic-gate static void *statep; 1210Sstevel@tonic-gate extern struct mod_ops mod_driverops; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate static struct modldrv modldrv = { 1240Sstevel@tonic-gate &mod_driverops, 1250Sstevel@tonic-gate "pic_client driver (v.%I%) ", 1260Sstevel@tonic-gate &pic_dev_ops 1270Sstevel@tonic-gate }; 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate static struct modlinkage modlinkage = { 1300Sstevel@tonic-gate MODREV_1, 1310Sstevel@tonic-gate &modldrv, 1320Sstevel@tonic-gate 0 1330Sstevel@tonic-gate }; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate int 1360Sstevel@tonic-gate _init(void) 1370Sstevel@tonic-gate { 1380Sstevel@tonic-gate int e; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate if (e = ddi_soft_state_init(&statep, sizeof (struct pic_softc), 1410Sstevel@tonic-gate MAX_PIC_INSTANCES)) { 1420Sstevel@tonic-gate return (e); 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate if ((e = mod_install(&modlinkage)) != 0) 1460Sstevel@tonic-gate ddi_soft_state_fini(&statep); 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate return (e); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate int 1520Sstevel@tonic-gate _fini(void) 1530Sstevel@tonic-gate { 1540Sstevel@tonic-gate int e; 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate if ((e = mod_remove(&modlinkage)) != 0) 1570Sstevel@tonic-gate return (e); 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate ddi_soft_state_fini(&statep); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate return (DDI_SUCCESS); 1620Sstevel@tonic-gate } 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate int 1650Sstevel@tonic-gate _info(struct modinfo *modinfop) 1660Sstevel@tonic-gate { 1670Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate /*ARGSUSED*/ 1710Sstevel@tonic-gate static int 1720Sstevel@tonic-gate pic_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 1730Sstevel@tonic-gate { 1740Sstevel@tonic-gate int inst; 1750Sstevel@tonic-gate int retval = DDI_SUCCESS; 1760Sstevel@tonic-gate struct pic_softc *softc; 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate inst = PIC_MINOR_TO_INST(getminor((dev_t)arg)); 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate switch (cmd) { 1810Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 1820Sstevel@tonic-gate if ((softc = getsoftc(inst)) == NULL) { 1830Sstevel@tonic-gate *result = (void *)NULL; 1840Sstevel@tonic-gate retval = DDI_FAILURE; 1850Sstevel@tonic-gate } else 1860Sstevel@tonic-gate *result = (void *)softc->dip; 1870Sstevel@tonic-gate break; 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 190*592Svenki *result = (void *)((uintptr_t)inst); 1910Sstevel@tonic-gate break; 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate default: 1940Sstevel@tonic-gate retval = DDI_FAILURE; 1950Sstevel@tonic-gate } 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate return (retval); 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate static int 2010Sstevel@tonic-gate pic_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2020Sstevel@tonic-gate { 2030Sstevel@tonic-gate int inst; 2040Sstevel@tonic-gate int i; 2050Sstevel@tonic-gate struct pic_softc *softc = NULL; 2060Sstevel@tonic-gate char *minor_name; 2070Sstevel@tonic-gate int minor; 2080Sstevel@tonic-gate char name[80]; 2090Sstevel@tonic-gate ddi_device_acc_attr_t dev_attr; 2100Sstevel@tonic-gate int res; 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate switch (cmd) { 2130Sstevel@tonic-gate case DDI_ATTACH: 2140Sstevel@tonic-gate inst = ddi_get_instance(dip); 2150Sstevel@tonic-gate if (inst >= MAX_PIC_INSTANCES) { 2160Sstevel@tonic-gate cmn_err(CE_WARN, "attach failed, too many instances\n"); 2170Sstevel@tonic-gate return (DDI_FAILURE); 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate (void) sprintf(name, "env-monitor%d", inst); 2210Sstevel@tonic-gate minor = PIC_INST_TO_MINOR(inst) | PIC_UNIT_TO_MINOR(0); 2220Sstevel@tonic-gate if (ddi_create_minor_node(dip, name, S_IFCHR, minor, 2230Sstevel@tonic-gate DDI_PSEUDO, NULL) == DDI_FAILURE) { 2240Sstevel@tonic-gate cmn_err(CE_WARN, 2250Sstevel@tonic-gate "ddi_create_minor_node() failed for inst %d\n", 2260Sstevel@tonic-gate inst); 2270Sstevel@tonic-gate return (DDI_FAILURE); 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate /* Allocate a soft state structure for this instance */ 2310Sstevel@tonic-gate if (ddi_soft_state_zalloc(statep, inst) != DDI_SUCCESS) { 2320Sstevel@tonic-gate cmn_err(CE_WARN, " ddi_soft_state_zalloc() failed " 2330Sstevel@tonic-gate "for inst %d\n", inst); 2340Sstevel@tonic-gate goto attach_failed; 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate /* Setup soft state */ 2380Sstevel@tonic-gate softc = getsoftc(inst); 2390Sstevel@tonic-gate softc->dip = dip; 2400Sstevel@tonic-gate mutex_init(&softc->mutex, NULL, MUTEX_DRIVER, NULL); 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate /* Setup device attributes */ 2430Sstevel@tonic-gate dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 2440Sstevel@tonic-gate dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 2450Sstevel@tonic-gate dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate /* 2480Sstevel@tonic-gate * The RF_COMMAND/RF_STATUS and RF_IND_DATA/RF_IND_ADDR 2490Sstevel@tonic-gate * register pairs are mapped as one register set starting 2500Sstevel@tonic-gate * from 0x0 and length 0x42. 2510Sstevel@tonic-gate */ 2520Sstevel@tonic-gate res = ddi_regs_map_setup(dip, 0, (caddr_t *)&softc->cmd_reg, 2530Sstevel@tonic-gate 0, 0x42, &dev_attr, &softc->cmd_handle); 2540Sstevel@tonic-gate if (res != DDI_SUCCESS) { 2550Sstevel@tonic-gate cmn_err(CE_WARN, "ddi_regs_map_setup() failed\n"); 2560Sstevel@tonic-gate goto attach_failed; 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate /* Set up fans' and sensors' device minor nodes */ 2600Sstevel@tonic-gate for (i = 1; i < N_PIC_NODES; i++) { 2610Sstevel@tonic-gate minor_name = pic_nodes[i].minor_name; 2620Sstevel@tonic-gate minor = PIC_INST_TO_MINOR(inst) | PIC_UNIT_TO_MINOR(i); 2630Sstevel@tonic-gate if (ddi_create_minor_node(dip, minor_name, S_IFCHR, 2640Sstevel@tonic-gate minor, PICDEV_NODE_TYPE, NULL) == DDI_FAILURE) { 2650Sstevel@tonic-gate cmn_err(CE_WARN, 2660Sstevel@tonic-gate "%s:%d ddi_create_minor_node failed", 2670Sstevel@tonic-gate ddi_driver_name(dip), inst); 2680Sstevel@tonic-gate (void) pic_detach(dip, DDI_DETACH); 2690Sstevel@tonic-gate return (DDI_FAILURE); 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate /* Create main environmental node */ 2740Sstevel@tonic-gate ddi_report_dev(dip); 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate return (DDI_SUCCESS); 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate case DDI_RESUME: 2790Sstevel@tonic-gate return (DDI_SUCCESS); 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate default: 2820Sstevel@tonic-gate return (DDI_FAILURE); 2830Sstevel@tonic-gate } 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate attach_failed: 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate /* Free soft state, if allocated. remove minor node if added earlier */ 2880Sstevel@tonic-gate if (softc) 2890Sstevel@tonic-gate ddi_soft_state_free(statep, inst); 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate return (DDI_FAILURE); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate static int 2970Sstevel@tonic-gate pic_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2980Sstevel@tonic-gate { 2990Sstevel@tonic-gate int inst; 3000Sstevel@tonic-gate struct pic_softc *softc; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate switch (cmd) { 3030Sstevel@tonic-gate case DDI_DETACH: 3040Sstevel@tonic-gate inst = ddi_get_instance(dip); 3050Sstevel@tonic-gate if ((softc = getsoftc(inst)) == NULL) 3060Sstevel@tonic-gate return (ENXIO); 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate (void) ddi_regs_map_free(&softc->cmd_handle); 3090Sstevel@tonic-gate /* Free the soft state and remove minor node added earlier */ 3100Sstevel@tonic-gate mutex_destroy(&softc->mutex); 3110Sstevel@tonic-gate ddi_soft_state_free(statep, inst); 3120Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 3130Sstevel@tonic-gate return (DDI_SUCCESS); 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate case DDI_SUSPEND: 3160Sstevel@tonic-gate return (DDI_SUCCESS); 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate default: 3190Sstevel@tonic-gate return (DDI_FAILURE); 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate /*ARGSUSED*/ 3240Sstevel@tonic-gate static int 3250Sstevel@tonic-gate pic_open(dev_t *devp, int flag, int otyp, cred_t *credp) 3260Sstevel@tonic-gate { 3270Sstevel@tonic-gate int inst = PIC_MINOR_TO_INST(getminor(*devp)); 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate return (getsoftc(inst) == NULL ? ENXIO : 0); 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate /*ARGSUSED*/ 3330Sstevel@tonic-gate static int 3340Sstevel@tonic-gate pic_close(dev_t dev, int flag, int otyp, cred_t *credp) 3350Sstevel@tonic-gate { 3360Sstevel@tonic-gate int inst = PIC_MINOR_TO_INST(getminor(dev)); 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate return (getsoftc(inst) == NULL ? ENXIO : 0); 3390Sstevel@tonic-gate } 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate /*ARGSUSED*/ 3420Sstevel@tonic-gate static int 3430Sstevel@tonic-gate pic_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) 3440Sstevel@tonic-gate { 3450Sstevel@tonic-gate int inst; 3460Sstevel@tonic-gate int node; 3470Sstevel@tonic-gate struct pic_softc *softc; 3480Sstevel@tonic-gate uint8_t in_command; 3490Sstevel@tonic-gate int16_t tempr; 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate inst = PIC_MINOR_TO_INST(getminor(dev)); 3520Sstevel@tonic-gate if ((softc = getsoftc(inst)) == NULL) 3530Sstevel@tonic-gate return (ENXIO); 3540Sstevel@tonic-gate 3550Sstevel@tonic-gate mutex_enter(&softc->mutex); 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &in_command, sizeof (in_command), 3580Sstevel@tonic-gate mode) != DDI_SUCCESS) { 3590Sstevel@tonic-gate mutex_exit(&softc->mutex); 3600Sstevel@tonic-gate return (EFAULT); 3610Sstevel@tonic-gate } 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate node = PIC_MINOR_TO_UNIT(getminor(dev)); 3640Sstevel@tonic-gate if ((node >= N_PIC_NODES) || (node < 1)) { 3650Sstevel@tonic-gate mutex_exit(&softc->mutex); 3660Sstevel@tonic-gate return (ENXIO); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate switch (cmd) { 3700Sstevel@tonic-gate case PIC_GET_TEMPERATURE: 371138Svenki drv_usecwait(10); 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate /* select the temp sensor */ 3740Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 3750Sstevel@tonic-gate RF_IND_ADDR, pic_nodes[node].reg_offset); 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* retrieve temperature data */ 3780Sstevel@tonic-gate tempr = (int16_t)ddi_get8(softc->cmd_handle, 3790Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA); 380138Svenki mutex_exit(&softc->mutex); 3810Sstevel@tonic-gate 382138Svenki if (tempr == 0xff) 3830Sstevel@tonic-gate return (EIO); 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate /* 3860Sstevel@tonic-gate * The temp is passed in as a uint8 value, we need to convert 3870Sstevel@tonic-gate * it to a signed 16 bit value to be able to handle the range 3880Sstevel@tonic-gate * of -64 to 190 degrees. 3890Sstevel@tonic-gate */ 3900Sstevel@tonic-gate tempr -= 64; 3910Sstevel@tonic-gate (void) ddi_copyout(&tempr, (caddr_t)arg, sizeof (tempr), mode); 3920Sstevel@tonic-gate return (0); 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate case PIC_GET_FAN_SPEED: 395138Svenki drv_usecwait(10); 396138Svenki 3970Sstevel@tonic-gate /* select fan */ 3980Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 3990Sstevel@tonic-gate RF_IND_ADDR, pic_nodes[node].reg_offset); 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate /* retrieve fan data */ 4020Sstevel@tonic-gate in_command = ddi_get8(softc->cmd_handle, 4030Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA); 404138Svenki mutex_exit(&softc->mutex); 4050Sstevel@tonic-gate 406138Svenki if (in_command == 0xff) 407138Svenki return (EIO); 408138Svenki 409138Svenki (void) ddi_copyout(&in_command, (caddr_t)arg, 1, mode); 410138Svenki return (0); 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate case PIC_SET_FAN_SPEED: 4130Sstevel@tonic-gate /* select fan */ 4140Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 4150Sstevel@tonic-gate RF_IND_ADDR, pic_nodes[node].reg_offset); 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate /* send the fan data */ 4180Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, 4190Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA, in_command); 4200Sstevel@tonic-gate 421138Svenki mutex_exit(&softc->mutex); 422138Svenki return (0); 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate case PIC_GET_STATUS: 425138Svenki mutex_exit(&softc->mutex); 426138Svenki 427365Svenki /* we don't read the status reg anymore */ 428365Svenki in_command = 0; 429138Svenki (void) ddi_copyout(&in_command, (caddr_t)arg, 1, mode); 430138Svenki 431138Svenki return (0); 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate case PIC_GET_FAN_STATUS: 434138Svenki drv_usecwait(10); 435138Svenki 4360Sstevel@tonic-gate /* read ffault register */ 4370Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 4380Sstevel@tonic-gate RF_IND_ADDR, RF_FAN_STATUS); 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate /* retrieve fan failure status */ 4410Sstevel@tonic-gate in_command = ddi_get8(softc->cmd_handle, 4420Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA); 443138Svenki mutex_exit(&softc->mutex); 4440Sstevel@tonic-gate 445138Svenki if (in_command == 0xff) 446138Svenki return (EIO); 4470Sstevel@tonic-gate 448138Svenki in_command = (in_command >> pic_nodes[node].ff_shift) & 0x1; 449138Svenki (void) ddi_copyout(&in_command, (caddr_t)arg, 1, mode); 450138Svenki return (0); 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate case PIC_SET_ESTAR_MODE: 4530Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, 4540Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_COMMAND, CMD_TO_ESTAR); 455365Svenki mutex_exit(&softc->mutex); 456138Svenki return (0); 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate default: 4590Sstevel@tonic-gate mutex_exit(&softc->mutex); 4600Sstevel@tonic-gate cmn_err(CE_NOTE, "cmd %d isnt valid", cmd); 4610Sstevel@tonic-gate return (EINVAL); 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate } 464