17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Driver to map the PIC for the chicago platform. 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <sys/time.h> 347c478bd9Sstevel@tonic-gate #include <sys/errno.h> 357c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 367c478bd9Sstevel@tonic-gate #include <sys/param.h> 377c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 387c478bd9Sstevel@tonic-gate #include <sys/conf.h> 397c478bd9Sstevel@tonic-gate #include <sys/open.h> 407c478bd9Sstevel@tonic-gate #include <sys/stat.h> 417c478bd9Sstevel@tonic-gate #include <sys/clock.h> 427c478bd9Sstevel@tonic-gate #include <sys/pic.h> 437c478bd9Sstevel@tonic-gate #include <sys/pic16f747.h> 447c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 457c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 467c478bd9Sstevel@tonic-gate #include <sys/file.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* dev_ops and cb_ops entry point function declarations */ 497c478bd9Sstevel@tonic-gate static int pic_attach(dev_info_t *, ddi_attach_cmd_t); 507c478bd9Sstevel@tonic-gate static int pic_detach(dev_info_t *, ddi_detach_cmd_t); 517c478bd9Sstevel@tonic-gate static int pic_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 527c478bd9Sstevel@tonic-gate static int pic_open(dev_t *, int, int, cred_t *); 537c478bd9Sstevel@tonic-gate static int pic_close(dev_t, int, int, cred_t *); 547c478bd9Sstevel@tonic-gate static int pic_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate struct cb_ops pic_cb_ops = { 577c478bd9Sstevel@tonic-gate pic_open, 587c478bd9Sstevel@tonic-gate pic_close, 597c478bd9Sstevel@tonic-gate nodev, 607c478bd9Sstevel@tonic-gate nodev, 617c478bd9Sstevel@tonic-gate nodev, /* dump */ 627c478bd9Sstevel@tonic-gate nodev, 637c478bd9Sstevel@tonic-gate nodev, 647c478bd9Sstevel@tonic-gate pic_ioctl, 657c478bd9Sstevel@tonic-gate nodev, /* devmap */ 667c478bd9Sstevel@tonic-gate nodev, 677c478bd9Sstevel@tonic-gate ddi_segmap, /* segmap */ 687c478bd9Sstevel@tonic-gate nochpoll, 697c478bd9Sstevel@tonic-gate ddi_prop_op, 707c478bd9Sstevel@tonic-gate NULL, /* for STREAMS drivers */ 717c478bd9Sstevel@tonic-gate D_NEW | D_MP /* driver compatibility flag */ 727c478bd9Sstevel@tonic-gate }; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static struct dev_ops pic_dev_ops = { 757c478bd9Sstevel@tonic-gate DEVO_REV, /* driver build version */ 767c478bd9Sstevel@tonic-gate 0, /* device reference count */ 777c478bd9Sstevel@tonic-gate pic_getinfo, 787c478bd9Sstevel@tonic-gate nulldev, 797c478bd9Sstevel@tonic-gate nulldev, /* probe */ 807c478bd9Sstevel@tonic-gate pic_attach, 817c478bd9Sstevel@tonic-gate pic_detach, 827c478bd9Sstevel@tonic-gate nulldev, /* reset */ 837c478bd9Sstevel@tonic-gate &pic_cb_ops, 847c478bd9Sstevel@tonic-gate (struct bus_ops *)NULL, 857c478bd9Sstevel@tonic-gate nulldev /* power */ 867c478bd9Sstevel@tonic-gate }; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * Fans' and sensors' node names and register offsets 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate static struct minor_node_info pic_nodes[N_PIC_NODES] = { 927c478bd9Sstevel@tonic-gate {NULL, 0, 0}, /* Reserved */ 93*b29b9e18Svenki {"fan_0", RF_FAN0_PERIOD, F0_FLT_BIT}, /* System Fan 0 */ 94*b29b9e18Svenki {"fan_1", RF_FAN1_PERIOD, F1_FLT_BIT}, /* System Fan 1 */ 95*b29b9e18Svenki {"fan_2", RF_FAN2_PERIOD, F2_FLT_BIT}, /* System Fan 2 */ 96*b29b9e18Svenki {"fan_3", RF_FAN3_PERIOD, F3_FLT_BIT}, /* System Fan 3 */ 97*b29b9e18Svenki {"fan_4", RF_FAN4_PERIOD, F4_FLT_BIT}, /* System Fan 4 */ 987c478bd9Sstevel@tonic-gate {"adt7462", RF_LOCAL_TEMP, 0}, /* ADT7462 Local Temperature */ 997c478bd9Sstevel@tonic-gate {"cpu_0", RF_REMOTE1_TEMP, 0}, /* CPU 0 temp */ 1007c478bd9Sstevel@tonic-gate {"cpu_1", RF_REMOTE2_TEMP, 0}, /* CPU 1 temp */ 1017c478bd9Sstevel@tonic-gate {"mb", RF_REMOTE3_TEMP, 0}, /* Motherboard temp */ 1027c478bd9Sstevel@tonic-gate {"lm95221", RF_LM95221_TEMP, 0}, /* LM95221 Local Temperature */ 1037c478bd9Sstevel@tonic-gate {"fire", RF_FIRE_TEMP, 0}, /* FIRE Temp */ 1047c478bd9Sstevel@tonic-gate {"lsi1064", RF_LSI1064_TEMP, 0}, /* LSI1064 Temp */ 105*b29b9e18Svenki {"front_panel", RF_FRONT_TEMP, 0}, /* Front Panel Temperature */ 106*b29b9e18Svenki {"psu", RF_PSU_TEMP, PSUF_FLT_BIT} /* PSU Temp (and ffault) */ 1077c478bd9Sstevel@tonic-gate }; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* 1107c478bd9Sstevel@tonic-gate * Soft state 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate struct pic_softc { 1137c478bd9Sstevel@tonic-gate dev_info_t *dip; 1147c478bd9Sstevel@tonic-gate kmutex_t mutex; 1157c478bd9Sstevel@tonic-gate uint8_t *cmd_reg; 1167c478bd9Sstevel@tonic-gate ddi_acc_handle_t cmd_handle; 1177c478bd9Sstevel@tonic-gate }; 1187c478bd9Sstevel@tonic-gate #define getsoftc(inst) ((struct pic_softc *)ddi_get_soft_state(statep, (inst))) 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* module configuration stuff */ 1217c478bd9Sstevel@tonic-gate static void *statep; 1227c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 1257c478bd9Sstevel@tonic-gate &mod_driverops, 1267c478bd9Sstevel@tonic-gate "pic_client driver (v.%I%) ", 1277c478bd9Sstevel@tonic-gate &pic_dev_ops 1287c478bd9Sstevel@tonic-gate }; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1317c478bd9Sstevel@tonic-gate MODREV_1, 1327c478bd9Sstevel@tonic-gate &modldrv, 1337c478bd9Sstevel@tonic-gate 0 1347c478bd9Sstevel@tonic-gate }; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate int 1377c478bd9Sstevel@tonic-gate _init(void) 1387c478bd9Sstevel@tonic-gate { 1397c478bd9Sstevel@tonic-gate int e; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate if (e = ddi_soft_state_init(&statep, sizeof (struct pic_softc), 1427c478bd9Sstevel@tonic-gate MAX_PIC_INSTANCES)) { 1437c478bd9Sstevel@tonic-gate return (e); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate if ((e = mod_install(&modlinkage)) != 0) 1477c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&statep); 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate return (e); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate int 1537c478bd9Sstevel@tonic-gate _fini(void) 1547c478bd9Sstevel@tonic-gate { 1557c478bd9Sstevel@tonic-gate int e; 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate if ((e = mod_remove(&modlinkage)) != 0) 1587c478bd9Sstevel@tonic-gate return (e); 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&statep); 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate int 1667c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 1677c478bd9Sstevel@tonic-gate { 1687c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1727c478bd9Sstevel@tonic-gate static int 1737c478bd9Sstevel@tonic-gate pic_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 1747c478bd9Sstevel@tonic-gate { 1757c478bd9Sstevel@tonic-gate int inst; 1767c478bd9Sstevel@tonic-gate int retval = DDI_SUCCESS; 1777c478bd9Sstevel@tonic-gate struct pic_softc *softc; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate inst = PIC_MINOR_TO_INST(getminor((dev_t)arg)); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate switch (cmd) { 1827c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 1837c478bd9Sstevel@tonic-gate if ((softc = getsoftc(inst)) == NULL) { 1847c478bd9Sstevel@tonic-gate *result = (void *)NULL; 1857c478bd9Sstevel@tonic-gate retval = DDI_FAILURE; 1867c478bd9Sstevel@tonic-gate } else 1877c478bd9Sstevel@tonic-gate *result = (void *)softc->dip; 1887c478bd9Sstevel@tonic-gate break; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 191bac66362Svenki *result = (void *)((uintptr_t)inst); 1927c478bd9Sstevel@tonic-gate break; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate default: 1957c478bd9Sstevel@tonic-gate retval = DDI_FAILURE; 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate return (retval); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate static int 2027c478bd9Sstevel@tonic-gate pic_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2037c478bd9Sstevel@tonic-gate { 2047c478bd9Sstevel@tonic-gate int inst; 2057c478bd9Sstevel@tonic-gate int i; 2067c478bd9Sstevel@tonic-gate struct pic_softc *softc = NULL; 2077c478bd9Sstevel@tonic-gate char *minor_name; 2087c478bd9Sstevel@tonic-gate int minor; 2097c478bd9Sstevel@tonic-gate char name[80]; 2107c478bd9Sstevel@tonic-gate ddi_device_acc_attr_t dev_attr; 2117c478bd9Sstevel@tonic-gate int res; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate switch (cmd) { 2147c478bd9Sstevel@tonic-gate case DDI_ATTACH: 2157c478bd9Sstevel@tonic-gate inst = ddi_get_instance(dip); 2167c478bd9Sstevel@tonic-gate if (inst >= MAX_PIC_INSTANCES) { 2177c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "attach failed, too many instances\n"); 2187c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate (void) sprintf(name, "env-monitor%d", inst); 2227c478bd9Sstevel@tonic-gate minor = PIC_INST_TO_MINOR(inst) | PIC_UNIT_TO_MINOR(0); 2237c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, name, S_IFCHR, minor, 2247c478bd9Sstevel@tonic-gate DDI_PSEUDO, NULL) == DDI_FAILURE) { 2257c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2267c478bd9Sstevel@tonic-gate "ddi_create_minor_node() failed for inst %d\n", 2277c478bd9Sstevel@tonic-gate inst); 2287c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* Allocate a soft state structure for this instance */ 2327c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(statep, inst) != DDI_SUCCESS) { 2337c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, " ddi_soft_state_zalloc() failed " 2347c478bd9Sstevel@tonic-gate "for inst %d\n", inst); 2357c478bd9Sstevel@tonic-gate goto attach_failed; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* Setup soft state */ 2397c478bd9Sstevel@tonic-gate softc = getsoftc(inst); 2407c478bd9Sstevel@tonic-gate softc->dip = dip; 2417c478bd9Sstevel@tonic-gate mutex_init(&softc->mutex, NULL, MUTEX_DRIVER, NULL); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /* Setup device attributes */ 2447c478bd9Sstevel@tonic-gate dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 2457c478bd9Sstevel@tonic-gate dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 2467c478bd9Sstevel@tonic-gate dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * The RF_COMMAND/RF_STATUS and RF_IND_DATA/RF_IND_ADDR 2507c478bd9Sstevel@tonic-gate * register pairs are mapped as one register set starting 2517c478bd9Sstevel@tonic-gate * from 0x0 and length 0x42. 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate res = ddi_regs_map_setup(dip, 0, (caddr_t *)&softc->cmd_reg, 2547c478bd9Sstevel@tonic-gate 0, 0x42, &dev_attr, &softc->cmd_handle); 2557c478bd9Sstevel@tonic-gate if (res != DDI_SUCCESS) { 2567c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ddi_regs_map_setup() failed\n"); 2577c478bd9Sstevel@tonic-gate goto attach_failed; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /* Set up fans' and sensors' device minor nodes */ 2617c478bd9Sstevel@tonic-gate for (i = 1; i < N_PIC_NODES; i++) { 2627c478bd9Sstevel@tonic-gate minor_name = pic_nodes[i].minor_name; 2637c478bd9Sstevel@tonic-gate minor = PIC_INST_TO_MINOR(inst) | PIC_UNIT_TO_MINOR(i); 2647c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, minor_name, S_IFCHR, 2657c478bd9Sstevel@tonic-gate minor, PICDEV_NODE_TYPE, NULL) == DDI_FAILURE) { 2667c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2677c478bd9Sstevel@tonic-gate "%s:%d ddi_create_minor_node failed", 2687c478bd9Sstevel@tonic-gate ddi_driver_name(dip), inst); 2697c478bd9Sstevel@tonic-gate (void) pic_detach(dip, DDI_DETACH); 2707c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* Create main environmental node */ 2757c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate case DDI_RESUME: 2807c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate default: 2837c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate attach_failed: 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* Free soft state, if allocated. remove minor node if added earlier */ 2897c478bd9Sstevel@tonic-gate if (softc) 2907c478bd9Sstevel@tonic-gate ddi_soft_state_free(statep, inst); 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate static int 2987c478bd9Sstevel@tonic-gate pic_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2997c478bd9Sstevel@tonic-gate { 3007c478bd9Sstevel@tonic-gate int inst; 3017c478bd9Sstevel@tonic-gate struct pic_softc *softc; 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate switch (cmd) { 3047c478bd9Sstevel@tonic-gate case DDI_DETACH: 3057c478bd9Sstevel@tonic-gate inst = ddi_get_instance(dip); 3067c478bd9Sstevel@tonic-gate if ((softc = getsoftc(inst)) == NULL) 3077c478bd9Sstevel@tonic-gate return (ENXIO); 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate (void) ddi_regs_map_free(&softc->cmd_handle); 3107c478bd9Sstevel@tonic-gate /* Free the soft state and remove minor node added earlier */ 3117c478bd9Sstevel@tonic-gate mutex_destroy(&softc->mutex); 3127c478bd9Sstevel@tonic-gate ddi_soft_state_free(statep, inst); 3137c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 3147c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 3177c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate default: 3207c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3257c478bd9Sstevel@tonic-gate static int 3267c478bd9Sstevel@tonic-gate pic_open(dev_t *devp, int flag, int otyp, cred_t *credp) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate int inst = PIC_MINOR_TO_INST(getminor(*devp)); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate return (getsoftc(inst) == NULL ? ENXIO : 0); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3347c478bd9Sstevel@tonic-gate static int 3357c478bd9Sstevel@tonic-gate pic_close(dev_t dev, int flag, int otyp, cred_t *credp) 3367c478bd9Sstevel@tonic-gate { 3377c478bd9Sstevel@tonic-gate int inst = PIC_MINOR_TO_INST(getminor(dev)); 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate return (getsoftc(inst) == NULL ? ENXIO : 0); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3437c478bd9Sstevel@tonic-gate static int 3447c478bd9Sstevel@tonic-gate pic_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) 3457c478bd9Sstevel@tonic-gate { 3467c478bd9Sstevel@tonic-gate int inst; 3477c478bd9Sstevel@tonic-gate int node; 3487c478bd9Sstevel@tonic-gate struct pic_softc *softc; 3497c478bd9Sstevel@tonic-gate uint8_t in_command; 3507c478bd9Sstevel@tonic-gate int16_t tempr; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate inst = PIC_MINOR_TO_INST(getminor(dev)); 3537c478bd9Sstevel@tonic-gate if ((softc = getsoftc(inst)) == NULL) 3547c478bd9Sstevel@tonic-gate return (ENXIO); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate mutex_enter(&softc->mutex); 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &in_command, sizeof (in_command), 3597c478bd9Sstevel@tonic-gate mode) != DDI_SUCCESS) { 3607c478bd9Sstevel@tonic-gate mutex_exit(&softc->mutex); 3617c478bd9Sstevel@tonic-gate return (EFAULT); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate node = PIC_MINOR_TO_UNIT(getminor(dev)); 3657c478bd9Sstevel@tonic-gate if ((node >= N_PIC_NODES) || (node < 1)) { 3667c478bd9Sstevel@tonic-gate mutex_exit(&softc->mutex); 3677c478bd9Sstevel@tonic-gate return (ENXIO); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate switch (cmd) { 3717c478bd9Sstevel@tonic-gate case PIC_GET_TEMPERATURE: 37266e1f439Svenki drv_usecwait(10); 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* select the temp sensor */ 3757c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 3767c478bd9Sstevel@tonic-gate RF_IND_ADDR, pic_nodes[node].reg_offset); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* retrieve temperature data */ 3797c478bd9Sstevel@tonic-gate tempr = (int16_t)ddi_get8(softc->cmd_handle, 3807c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA); 3817c478bd9Sstevel@tonic-gate mutex_exit(&softc->mutex); 38266e1f439Svenki 38366e1f439Svenki if (tempr == 0xff) 3847c478bd9Sstevel@tonic-gate return (EIO); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* 3877c478bd9Sstevel@tonic-gate * The temp is passed in as a uint8 value, we need to convert 3887c478bd9Sstevel@tonic-gate * it to a signed 16 bit value to be able to handle the range 3897c478bd9Sstevel@tonic-gate * of -64 to 190 degrees. 3907c478bd9Sstevel@tonic-gate */ 3917c478bd9Sstevel@tonic-gate tempr -= 64; 3927c478bd9Sstevel@tonic-gate (void) ddi_copyout(&tempr, (caddr_t)arg, sizeof (tempr), mode); 3937c478bd9Sstevel@tonic-gate return (0); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate case PIC_GET_FAN_SPEED: 39666e1f439Svenki drv_usecwait(10); 39766e1f439Svenki 3987c478bd9Sstevel@tonic-gate /* select fan */ 3997c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 4007c478bd9Sstevel@tonic-gate RF_IND_ADDR, pic_nodes[node].reg_offset); 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate /* retrieve fan data */ 4037c478bd9Sstevel@tonic-gate in_command = ddi_get8(softc->cmd_handle, 4047c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA); 40566e1f439Svenki mutex_exit(&softc->mutex); 4067c478bd9Sstevel@tonic-gate 40766e1f439Svenki if (in_command == 0xff) 40866e1f439Svenki return (EIO); 40966e1f439Svenki 41066e1f439Svenki (void) ddi_copyout(&in_command, (caddr_t)arg, 1, mode); 41166e1f439Svenki return (0); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate case PIC_SET_FAN_SPEED: 4147c478bd9Sstevel@tonic-gate /* select fan */ 4157c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 4167c478bd9Sstevel@tonic-gate RF_IND_ADDR, pic_nodes[node].reg_offset); 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate /* send the fan data */ 4197c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, 4207c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA, in_command); 4217c478bd9Sstevel@tonic-gate 42266e1f439Svenki mutex_exit(&softc->mutex); 42366e1f439Svenki return (0); 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate case PIC_GET_STATUS: 42666e1f439Svenki mutex_exit(&softc->mutex); 42766e1f439Svenki 428d619c1b8Svenki /* we don't read the status reg anymore */ 429d619c1b8Svenki in_command = 0; 43066e1f439Svenki (void) ddi_copyout(&in_command, (caddr_t)arg, 1, mode); 43166e1f439Svenki 43266e1f439Svenki return (0); 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate case PIC_GET_FAN_STATUS: 43566e1f439Svenki drv_usecwait(10); 43666e1f439Svenki 4377c478bd9Sstevel@tonic-gate /* read ffault register */ 4387c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 4397c478bd9Sstevel@tonic-gate RF_IND_ADDR, RF_FAN_STATUS); 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /* retrieve fan failure status */ 4427c478bd9Sstevel@tonic-gate in_command = ddi_get8(softc->cmd_handle, 4437c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA); 44466e1f439Svenki mutex_exit(&softc->mutex); 44566e1f439Svenki 44666e1f439Svenki if (in_command == 0xff) 44766e1f439Svenki return (EIO); 44866e1f439Svenki 4497c478bd9Sstevel@tonic-gate in_command = (in_command >> pic_nodes[node].ff_shift) & 0x1; 45066e1f439Svenki (void) ddi_copyout(&in_command, (caddr_t)arg, 1, mode); 45166e1f439Svenki return (0); 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate case PIC_SET_ESTAR_MODE: 4547c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, 4557c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_COMMAND, CMD_TO_ESTAR); 456d619c1b8Svenki mutex_exit(&softc->mutex); 45766e1f439Svenki return (0); 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate default: 4607c478bd9Sstevel@tonic-gate mutex_exit(&softc->mutex); 4617c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "cmd %d isnt valid", cmd); 4627c478bd9Sstevel@tonic-gate return (EINVAL); 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate } 465