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 */ 937c478bd9Sstevel@tonic-gate {"fan_0", RF_FAN0_PERIOD, 0}, /* System Fan 0 */ 947c478bd9Sstevel@tonic-gate {"fan_1", RF_FAN1_PERIOD, 1}, /* System Fan 1 */ 957c478bd9Sstevel@tonic-gate {"fan_2", RF_FAN2_PERIOD, 2}, /* System Fan 2 */ 967c478bd9Sstevel@tonic-gate {"fan_3", RF_FAN3_PERIOD, 3}, /* System Fan 3 */ 977c478bd9Sstevel@tonic-gate {"fan_4", RF_FAN4_PERIOD, 4}, /* System Fan 4 in P0.1 */ 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 */ 1057c478bd9Sstevel@tonic-gate {"front_panel", RF_FRONT_TEMP, 0} /* Front Panel Temperature */ 1067c478bd9Sstevel@tonic-gate }; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate /* 1097c478bd9Sstevel@tonic-gate * Soft state 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate struct pic_softc { 1127c478bd9Sstevel@tonic-gate dev_info_t *dip; 1137c478bd9Sstevel@tonic-gate kmutex_t mutex; 1147c478bd9Sstevel@tonic-gate uint8_t *cmd_reg; 1157c478bd9Sstevel@tonic-gate ddi_acc_handle_t cmd_handle; 1167c478bd9Sstevel@tonic-gate }; 1177c478bd9Sstevel@tonic-gate #define getsoftc(inst) ((struct pic_softc *)ddi_get_soft_state(statep, (inst))) 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* module configuration stuff */ 1207c478bd9Sstevel@tonic-gate static void *statep; 1217c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 1247c478bd9Sstevel@tonic-gate &mod_driverops, 1257c478bd9Sstevel@tonic-gate "pic_client driver (v.%I%) ", 1267c478bd9Sstevel@tonic-gate &pic_dev_ops 1277c478bd9Sstevel@tonic-gate }; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1307c478bd9Sstevel@tonic-gate MODREV_1, 1317c478bd9Sstevel@tonic-gate &modldrv, 1327c478bd9Sstevel@tonic-gate 0 1337c478bd9Sstevel@tonic-gate }; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate int 1367c478bd9Sstevel@tonic-gate _init(void) 1377c478bd9Sstevel@tonic-gate { 1387c478bd9Sstevel@tonic-gate int e; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate if (e = ddi_soft_state_init(&statep, sizeof (struct pic_softc), 1417c478bd9Sstevel@tonic-gate MAX_PIC_INSTANCES)) { 1427c478bd9Sstevel@tonic-gate return (e); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate if ((e = mod_install(&modlinkage)) != 0) 1467c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&statep); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate return (e); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate int 1527c478bd9Sstevel@tonic-gate _fini(void) 1537c478bd9Sstevel@tonic-gate { 1547c478bd9Sstevel@tonic-gate int e; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if ((e = mod_remove(&modlinkage)) != 0) 1577c478bd9Sstevel@tonic-gate return (e); 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&statep); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate int 1657c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 1667c478bd9Sstevel@tonic-gate { 1677c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1717c478bd9Sstevel@tonic-gate static int 1727c478bd9Sstevel@tonic-gate pic_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 1737c478bd9Sstevel@tonic-gate { 1747c478bd9Sstevel@tonic-gate int inst; 1757c478bd9Sstevel@tonic-gate int retval = DDI_SUCCESS; 1767c478bd9Sstevel@tonic-gate struct pic_softc *softc; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate inst = PIC_MINOR_TO_INST(getminor((dev_t)arg)); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate switch (cmd) { 1817c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 1827c478bd9Sstevel@tonic-gate if ((softc = getsoftc(inst)) == NULL) { 1837c478bd9Sstevel@tonic-gate *result = (void *)NULL; 1847c478bd9Sstevel@tonic-gate retval = DDI_FAILURE; 1857c478bd9Sstevel@tonic-gate } else 1867c478bd9Sstevel@tonic-gate *result = (void *)softc->dip; 1877c478bd9Sstevel@tonic-gate break; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 190*bac66362Svenki *result = (void *)((uintptr_t)inst); 1917c478bd9Sstevel@tonic-gate break; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate default: 1947c478bd9Sstevel@tonic-gate retval = DDI_FAILURE; 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate return (retval); 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate static int 2017c478bd9Sstevel@tonic-gate pic_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2027c478bd9Sstevel@tonic-gate { 2037c478bd9Sstevel@tonic-gate int inst; 2047c478bd9Sstevel@tonic-gate int i; 2057c478bd9Sstevel@tonic-gate struct pic_softc *softc = NULL; 2067c478bd9Sstevel@tonic-gate char *minor_name; 2077c478bd9Sstevel@tonic-gate int minor; 2087c478bd9Sstevel@tonic-gate char name[80]; 2097c478bd9Sstevel@tonic-gate ddi_device_acc_attr_t dev_attr; 2107c478bd9Sstevel@tonic-gate int res; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate switch (cmd) { 2137c478bd9Sstevel@tonic-gate case DDI_ATTACH: 2147c478bd9Sstevel@tonic-gate inst = ddi_get_instance(dip); 2157c478bd9Sstevel@tonic-gate if (inst >= MAX_PIC_INSTANCES) { 2167c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "attach failed, too many instances\n"); 2177c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate (void) sprintf(name, "env-monitor%d", inst); 2217c478bd9Sstevel@tonic-gate minor = PIC_INST_TO_MINOR(inst) | PIC_UNIT_TO_MINOR(0); 2227c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, name, S_IFCHR, minor, 2237c478bd9Sstevel@tonic-gate DDI_PSEUDO, NULL) == DDI_FAILURE) { 2247c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2257c478bd9Sstevel@tonic-gate "ddi_create_minor_node() failed for inst %d\n", 2267c478bd9Sstevel@tonic-gate inst); 2277c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* Allocate a soft state structure for this instance */ 2317c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(statep, inst) != DDI_SUCCESS) { 2327c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, " ddi_soft_state_zalloc() failed " 2337c478bd9Sstevel@tonic-gate "for inst %d\n", inst); 2347c478bd9Sstevel@tonic-gate goto attach_failed; 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* Setup soft state */ 2387c478bd9Sstevel@tonic-gate softc = getsoftc(inst); 2397c478bd9Sstevel@tonic-gate softc->dip = dip; 2407c478bd9Sstevel@tonic-gate mutex_init(&softc->mutex, NULL, MUTEX_DRIVER, NULL); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* Setup device attributes */ 2437c478bd9Sstevel@tonic-gate dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 2447c478bd9Sstevel@tonic-gate dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 2457c478bd9Sstevel@tonic-gate dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* 2487c478bd9Sstevel@tonic-gate * The RF_COMMAND/RF_STATUS and RF_IND_DATA/RF_IND_ADDR 2497c478bd9Sstevel@tonic-gate * register pairs are mapped as one register set starting 2507c478bd9Sstevel@tonic-gate * from 0x0 and length 0x42. 2517c478bd9Sstevel@tonic-gate */ 2527c478bd9Sstevel@tonic-gate res = ddi_regs_map_setup(dip, 0, (caddr_t *)&softc->cmd_reg, 2537c478bd9Sstevel@tonic-gate 0, 0x42, &dev_attr, &softc->cmd_handle); 2547c478bd9Sstevel@tonic-gate if (res != DDI_SUCCESS) { 2557c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ddi_regs_map_setup() failed\n"); 2567c478bd9Sstevel@tonic-gate goto attach_failed; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* Set up fans' and sensors' device minor nodes */ 2607c478bd9Sstevel@tonic-gate for (i = 1; i < N_PIC_NODES; i++) { 2617c478bd9Sstevel@tonic-gate minor_name = pic_nodes[i].minor_name; 2627c478bd9Sstevel@tonic-gate minor = PIC_INST_TO_MINOR(inst) | PIC_UNIT_TO_MINOR(i); 2637c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, minor_name, S_IFCHR, 2647c478bd9Sstevel@tonic-gate minor, PICDEV_NODE_TYPE, NULL) == DDI_FAILURE) { 2657c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2667c478bd9Sstevel@tonic-gate "%s:%d ddi_create_minor_node failed", 2677c478bd9Sstevel@tonic-gate ddi_driver_name(dip), inst); 2687c478bd9Sstevel@tonic-gate (void) pic_detach(dip, DDI_DETACH); 2697c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* Create main environmental node */ 2747c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate case DDI_RESUME: 2797c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate default: 2827c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate attach_failed: 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* Free soft state, if allocated. remove minor node if added earlier */ 2887c478bd9Sstevel@tonic-gate if (softc) 2897c478bd9Sstevel@tonic-gate ddi_soft_state_free(statep, inst); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate static int 2977c478bd9Sstevel@tonic-gate pic_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate int inst; 3007c478bd9Sstevel@tonic-gate struct pic_softc *softc; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate switch (cmd) { 3037c478bd9Sstevel@tonic-gate case DDI_DETACH: 3047c478bd9Sstevel@tonic-gate inst = ddi_get_instance(dip); 3057c478bd9Sstevel@tonic-gate if ((softc = getsoftc(inst)) == NULL) 3067c478bd9Sstevel@tonic-gate return (ENXIO); 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate (void) ddi_regs_map_free(&softc->cmd_handle); 3097c478bd9Sstevel@tonic-gate /* Free the soft state and remove minor node added earlier */ 3107c478bd9Sstevel@tonic-gate mutex_destroy(&softc->mutex); 3117c478bd9Sstevel@tonic-gate ddi_soft_state_free(statep, inst); 3127c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 3137c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 3167c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate default: 3197c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3247c478bd9Sstevel@tonic-gate static int 3257c478bd9Sstevel@tonic-gate pic_open(dev_t *devp, int flag, int otyp, cred_t *credp) 3267c478bd9Sstevel@tonic-gate { 3277c478bd9Sstevel@tonic-gate int inst = PIC_MINOR_TO_INST(getminor(*devp)); 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate return (getsoftc(inst) == NULL ? ENXIO : 0); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3337c478bd9Sstevel@tonic-gate static int 3347c478bd9Sstevel@tonic-gate pic_close(dev_t dev, int flag, int otyp, cred_t *credp) 3357c478bd9Sstevel@tonic-gate { 3367c478bd9Sstevel@tonic-gate int inst = PIC_MINOR_TO_INST(getminor(dev)); 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate return (getsoftc(inst) == NULL ? ENXIO : 0); 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3427c478bd9Sstevel@tonic-gate static int 3437c478bd9Sstevel@tonic-gate pic_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) 3447c478bd9Sstevel@tonic-gate { 3457c478bd9Sstevel@tonic-gate int inst; 3467c478bd9Sstevel@tonic-gate int node; 3477c478bd9Sstevel@tonic-gate struct pic_softc *softc; 3487c478bd9Sstevel@tonic-gate uint8_t in_command; 3497c478bd9Sstevel@tonic-gate int16_t tempr; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate inst = PIC_MINOR_TO_INST(getminor(dev)); 3527c478bd9Sstevel@tonic-gate if ((softc = getsoftc(inst)) == NULL) 3537c478bd9Sstevel@tonic-gate return (ENXIO); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate mutex_enter(&softc->mutex); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &in_command, sizeof (in_command), 3587c478bd9Sstevel@tonic-gate mode) != DDI_SUCCESS) { 3597c478bd9Sstevel@tonic-gate mutex_exit(&softc->mutex); 3607c478bd9Sstevel@tonic-gate return (EFAULT); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate node = PIC_MINOR_TO_UNIT(getminor(dev)); 3647c478bd9Sstevel@tonic-gate if ((node >= N_PIC_NODES) || (node < 1)) { 3657c478bd9Sstevel@tonic-gate mutex_exit(&softc->mutex); 3667c478bd9Sstevel@tonic-gate return (ENXIO); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate switch (cmd) { 3707c478bd9Sstevel@tonic-gate case PIC_GET_TEMPERATURE: 37166e1f439Svenki drv_usecwait(10); 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* select the temp sensor */ 3747c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 3757c478bd9Sstevel@tonic-gate RF_IND_ADDR, pic_nodes[node].reg_offset); 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* retrieve temperature data */ 3787c478bd9Sstevel@tonic-gate tempr = (int16_t)ddi_get8(softc->cmd_handle, 3797c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA); 3807c478bd9Sstevel@tonic-gate mutex_exit(&softc->mutex); 38166e1f439Svenki 38266e1f439Svenki if (tempr == 0xff) 3837c478bd9Sstevel@tonic-gate return (EIO); 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * The temp is passed in as a uint8 value, we need to convert 3877c478bd9Sstevel@tonic-gate * it to a signed 16 bit value to be able to handle the range 3887c478bd9Sstevel@tonic-gate * of -64 to 190 degrees. 3897c478bd9Sstevel@tonic-gate */ 3907c478bd9Sstevel@tonic-gate tempr -= 64; 3917c478bd9Sstevel@tonic-gate (void) ddi_copyout(&tempr, (caddr_t)arg, sizeof (tempr), mode); 3927c478bd9Sstevel@tonic-gate return (0); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate case PIC_GET_FAN_SPEED: 39566e1f439Svenki drv_usecwait(10); 39666e1f439Svenki 3977c478bd9Sstevel@tonic-gate /* select fan */ 3987c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 3997c478bd9Sstevel@tonic-gate RF_IND_ADDR, pic_nodes[node].reg_offset); 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* retrieve fan data */ 4027c478bd9Sstevel@tonic-gate in_command = ddi_get8(softc->cmd_handle, 4037c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA); 40466e1f439Svenki mutex_exit(&softc->mutex); 4057c478bd9Sstevel@tonic-gate 40666e1f439Svenki if (in_command == 0xff) 40766e1f439Svenki return (EIO); 40866e1f439Svenki 40966e1f439Svenki (void) ddi_copyout(&in_command, (caddr_t)arg, 1, mode); 41066e1f439Svenki return (0); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate case PIC_SET_FAN_SPEED: 4137c478bd9Sstevel@tonic-gate /* select fan */ 4147c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 4157c478bd9Sstevel@tonic-gate RF_IND_ADDR, pic_nodes[node].reg_offset); 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* send the fan data */ 4187c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, 4197c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA, in_command); 4207c478bd9Sstevel@tonic-gate 42166e1f439Svenki mutex_exit(&softc->mutex); 42266e1f439Svenki return (0); 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate case PIC_GET_STATUS: 42566e1f439Svenki mutex_exit(&softc->mutex); 42666e1f439Svenki 427d619c1b8Svenki /* we don't read the status reg anymore */ 428d619c1b8Svenki in_command = 0; 42966e1f439Svenki (void) ddi_copyout(&in_command, (caddr_t)arg, 1, mode); 43066e1f439Svenki 43166e1f439Svenki return (0); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate case PIC_GET_FAN_STATUS: 43466e1f439Svenki drv_usecwait(10); 43566e1f439Svenki 4367c478bd9Sstevel@tonic-gate /* read ffault register */ 4377c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, (uint8_t *)softc->cmd_reg + 4387c478bd9Sstevel@tonic-gate RF_IND_ADDR, RF_FAN_STATUS); 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate /* retrieve fan failure status */ 4417c478bd9Sstevel@tonic-gate in_command = ddi_get8(softc->cmd_handle, 4427c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_IND_DATA); 44366e1f439Svenki mutex_exit(&softc->mutex); 44466e1f439Svenki 44566e1f439Svenki if (in_command == 0xff) 44666e1f439Svenki return (EIO); 44766e1f439Svenki 4487c478bd9Sstevel@tonic-gate in_command = (in_command >> pic_nodes[node].ff_shift) & 0x1; 44966e1f439Svenki (void) ddi_copyout(&in_command, (caddr_t)arg, 1, mode); 45066e1f439Svenki return (0); 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate case PIC_SET_ESTAR_MODE: 4537c478bd9Sstevel@tonic-gate (void) ddi_put8(softc->cmd_handle, 4547c478bd9Sstevel@tonic-gate (uint8_t *)softc->cmd_reg + RF_COMMAND, CMD_TO_ESTAR); 455d619c1b8Svenki mutex_exit(&softc->mutex); 45666e1f439Svenki return (0); 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate default: 4597c478bd9Sstevel@tonic-gate mutex_exit(&softc->mutex); 4607c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "cmd %d isnt valid", cmd); 4617c478bd9Sstevel@tonic-gate return (EINVAL); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 464