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 5*7656SSherry.Moore@Sun.COM * Common Development and Distribution License (the "License"). 6*7656SSherry.Moore@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*7656SSherry.Moore@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/stat.h> /* ddi_create_minor_node S_IFCHR */ 290Sstevel@tonic-gate #include <sys/modctl.h> /* for modldrv */ 300Sstevel@tonic-gate #include <sys/open.h> /* for open params. */ 310Sstevel@tonic-gate #include <sys/types.h> 320Sstevel@tonic-gate #include <sys/kmem.h> 330Sstevel@tonic-gate #include <sys/sunddi.h> 340Sstevel@tonic-gate #include <sys/conf.h> /* req. by dev_ops flags MTSAFE etc. */ 350Sstevel@tonic-gate #include <sys/ddi.h> 360Sstevel@tonic-gate #include <sys/file.h> 370Sstevel@tonic-gate #include <sys/note.h> 380Sstevel@tonic-gate 390Sstevel@tonic-gate #include <sys/i2c/clients/pic16f819_impl.h> 400Sstevel@tonic-gate 410Sstevel@tonic-gate static void *pic16f819soft_statep; 420Sstevel@tonic-gate 430Sstevel@tonic-gate static int pic16f819_set(struct pic16f819_unit *, int, uchar_t); 440Sstevel@tonic-gate static int pic16f819_get(struct pic16f819_unit *, int, uchar_t *, int); 450Sstevel@tonic-gate 460Sstevel@tonic-gate 470Sstevel@tonic-gate static int pic16f819_do_attach(dev_info_t *); 480Sstevel@tonic-gate static int pic16f819_do_detach(dev_info_t *); 490Sstevel@tonic-gate static int pic16f819_do_resume(void); 500Sstevel@tonic-gate static int pic16f819_do_suspend(void); 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* 530Sstevel@tonic-gate * cb ops (only need ioctl) 540Sstevel@tonic-gate */ 550Sstevel@tonic-gate static int pic16f819_open(dev_t *, int, int, cred_t *); 560Sstevel@tonic-gate static int pic16f819_close(dev_t, int, int, cred_t *); 570Sstevel@tonic-gate static int pic16f819_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 580Sstevel@tonic-gate 590Sstevel@tonic-gate static struct cb_ops pic16f819_cbops = { 600Sstevel@tonic-gate pic16f819_open, /* open */ 610Sstevel@tonic-gate pic16f819_close, /* close */ 620Sstevel@tonic-gate nodev, /* strategy */ 630Sstevel@tonic-gate nodev, /* print */ 640Sstevel@tonic-gate nodev, /* dump */ 650Sstevel@tonic-gate nodev, /* read */ 660Sstevel@tonic-gate nodev, /* write */ 670Sstevel@tonic-gate pic16f819_ioctl, /* ioctl */ 680Sstevel@tonic-gate nodev, /* devmap */ 690Sstevel@tonic-gate nodev, /* mmap */ 700Sstevel@tonic-gate nodev, /* segmap */ 710Sstevel@tonic-gate nochpoll, /* poll */ 720Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 730Sstevel@tonic-gate NULL, /* streamtab */ 740Sstevel@tonic-gate D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ 750Sstevel@tonic-gate CB_REV, /* rev */ 760Sstevel@tonic-gate nodev, /* int (*cb_aread)() */ 770Sstevel@tonic-gate nodev /* int (*cb_awrite)() */ 780Sstevel@tonic-gate }; 790Sstevel@tonic-gate 800Sstevel@tonic-gate /* 810Sstevel@tonic-gate * dev ops 820Sstevel@tonic-gate */ 830Sstevel@tonic-gate static int pic16f819_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 840Sstevel@tonic-gate static int pic16f819_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 850Sstevel@tonic-gate 860Sstevel@tonic-gate static struct dev_ops pic16f819_ops = { 870Sstevel@tonic-gate DEVO_REV, 880Sstevel@tonic-gate 0, 890Sstevel@tonic-gate ddi_no_info, 900Sstevel@tonic-gate nulldev, 910Sstevel@tonic-gate nulldev, 920Sstevel@tonic-gate pic16f819_attach, 930Sstevel@tonic-gate pic16f819_detach, 940Sstevel@tonic-gate nodev, 950Sstevel@tonic-gate &pic16f819_cbops, 96*7656SSherry.Moore@Sun.COM NULL, /* bus ops */ 97*7656SSherry.Moore@Sun.COM NULL, /* power */ 98*7656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* quiesce */ 990Sstevel@tonic-gate }; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate extern struct mod_ops mod_driverops; 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate static struct modldrv pic16f819_modldrv = { 1040Sstevel@tonic-gate &mod_driverops, /* type of module - driver */ 105*7656SSherry.Moore@Sun.COM "PIC16F819 i2c device driver: v1.6", 1060Sstevel@tonic-gate &pic16f819_ops 1070Sstevel@tonic-gate }; 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate static struct modlinkage pic16f819_modlinkage = { 1100Sstevel@tonic-gate MODREV_1, 1110Sstevel@tonic-gate &pic16f819_modldrv, 1120Sstevel@tonic-gate 0 1130Sstevel@tonic-gate }; 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate int 1170Sstevel@tonic-gate _init(void) 1180Sstevel@tonic-gate { 1190Sstevel@tonic-gate int error; 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate error = mod_install(&pic16f819_modlinkage); 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate if (!error) 1240Sstevel@tonic-gate (void) ddi_soft_state_init(&pic16f819soft_statep, 125*7656SSherry.Moore@Sun.COM sizeof (struct pic16f819_unit), 1); 1260Sstevel@tonic-gate return (error); 1270Sstevel@tonic-gate } 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate int 1300Sstevel@tonic-gate _fini(void) 1310Sstevel@tonic-gate { 1320Sstevel@tonic-gate int error; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate error = mod_remove(&pic16f819_modlinkage); 1350Sstevel@tonic-gate if (!error) 1360Sstevel@tonic-gate ddi_soft_state_fini(&pic16f819soft_statep); 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate return (error); 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate int 1420Sstevel@tonic-gate _info(struct modinfo *modinfop) 1430Sstevel@tonic-gate { 1440Sstevel@tonic-gate return (mod_info(&pic16f819_modlinkage, modinfop)); 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate static int 1480Sstevel@tonic-gate pic16f819_get(struct pic16f819_unit *unitp, int reg, uchar_t *byte, int flags) 1490Sstevel@tonic-gate { 1500Sstevel@tonic-gate i2c_transfer_t *i2c_tran_pointer; 1510Sstevel@tonic-gate int err; 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate (void) i2c_transfer_alloc(unitp->pic16f819_hdl, &i2c_tran_pointer, 154*7656SSherry.Moore@Sun.COM 1, 1, flags); 1550Sstevel@tonic-gate if (i2c_tran_pointer == NULL) { 1560Sstevel@tonic-gate return (ENOMEM); 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate i2c_tran_pointer->i2c_flags = I2C_WR_RD; 1600Sstevel@tonic-gate i2c_tran_pointer->i2c_wbuf[0] = (uchar_t)reg; 1610Sstevel@tonic-gate err = i2c_transfer(unitp->pic16f819_hdl, i2c_tran_pointer); 1620Sstevel@tonic-gate if (err) { 1630Sstevel@tonic-gate D2CMN_ERR((CE_WARN, "%s: pic16f819_get failed reg=%x", 164*7656SSherry.Moore@Sun.COM unitp->pic16f819_name, reg)); 1650Sstevel@tonic-gate } else { 1660Sstevel@tonic-gate *byte = i2c_tran_pointer->i2c_rbuf[0]; 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate i2c_transfer_free(unitp->pic16f819_hdl, i2c_tran_pointer); 1700Sstevel@tonic-gate return (err); 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate static int 1740Sstevel@tonic-gate pic16f819_set(struct pic16f819_unit *unitp, int reg, uchar_t byte) 1750Sstevel@tonic-gate { 1760Sstevel@tonic-gate i2c_transfer_t *i2c_tran_pointer; 1770Sstevel@tonic-gate int err; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate (void) i2c_transfer_alloc(unitp->pic16f819_hdl, &i2c_tran_pointer, 180*7656SSherry.Moore@Sun.COM 2, 0, I2C_SLEEP); 1810Sstevel@tonic-gate if (i2c_tran_pointer == NULL) { 1820Sstevel@tonic-gate D2CMN_ERR((CE_WARN, "%s: Failed in pic16f819_set " 1830Sstevel@tonic-gate "i2c_tran_pointer not allocated", unitp->pic16f819_name)); 1840Sstevel@tonic-gate return (ENOMEM); 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate i2c_tran_pointer->i2c_flags = I2C_WR; 1880Sstevel@tonic-gate i2c_tran_pointer->i2c_wbuf[0] = (uchar_t)reg; 1890Sstevel@tonic-gate i2c_tran_pointer->i2c_wbuf[1] = byte; 1900Sstevel@tonic-gate D1CMN_ERR((CE_NOTE, "%s: set reg %x to %x", 191*7656SSherry.Moore@Sun.COM unitp->pic16f819_name, reg, byte)); 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate err = i2c_transfer(unitp->pic16f819_hdl, i2c_tran_pointer); 1940Sstevel@tonic-gate if (err) { 1950Sstevel@tonic-gate D2CMN_ERR((CE_WARN, "%s: Failed in the pic16f819_set" 196*7656SSherry.Moore@Sun.COM " i2c_transfer routine", unitp->pic16f819_name)); 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate i2c_transfer_free(unitp->pic16f819_hdl, i2c_tran_pointer); 1990Sstevel@tonic-gate return (err); 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate static int 2030Sstevel@tonic-gate pic16f819_open(dev_t *devp, int flags, int otyp, cred_t *credp) 2040Sstevel@tonic-gate { 2050Sstevel@tonic-gate _NOTE(ARGUNUSED(credp)) 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate struct pic16f819_unit *unitp; 2080Sstevel@tonic-gate int instance; 2090Sstevel@tonic-gate int error = 0; 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate instance = getminor(*devp); 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate if (instance < 0) { 2140Sstevel@tonic-gate return (ENXIO); 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate unitp = (struct pic16f819_unit *) 218*7656SSherry.Moore@Sun.COM ddi_get_soft_state(pic16f819soft_statep, instance); 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate if (unitp == NULL) { 2210Sstevel@tonic-gate return (ENXIO); 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate if (otyp != OTYP_CHR) { 2250Sstevel@tonic-gate return (EINVAL); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate mutex_enter(&unitp->pic16f819_mutex); 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate if (flags & FEXCL) { 2310Sstevel@tonic-gate if (unitp->pic16f819_oflag != 0) { 2320Sstevel@tonic-gate error = EBUSY; 2330Sstevel@tonic-gate } else { 2340Sstevel@tonic-gate unitp->pic16f819_oflag = FEXCL; 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate } else { 2370Sstevel@tonic-gate if (unitp->pic16f819_oflag == FEXCL) { 2380Sstevel@tonic-gate error = EBUSY; 2390Sstevel@tonic-gate } else { 2400Sstevel@tonic-gate unitp->pic16f819_oflag = FOPEN; 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate mutex_exit(&unitp->pic16f819_mutex); 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate return (error); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate static int 2500Sstevel@tonic-gate pic16f819_close(dev_t dev, int flags, int otyp, cred_t *credp) 2510Sstevel@tonic-gate { 2520Sstevel@tonic-gate _NOTE(ARGUNUSED(flags, otyp, credp)) 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate struct pic16f819_unit *unitp; 2550Sstevel@tonic-gate int instance; 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate instance = getminor(dev); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate if (instance < 0) { 2600Sstevel@tonic-gate return (ENXIO); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate unitp = (struct pic16f819_unit *) 264*7656SSherry.Moore@Sun.COM ddi_get_soft_state(pic16f819soft_statep, instance); 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate if (unitp == NULL) { 2670Sstevel@tonic-gate return (ENXIO); 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate mutex_enter(&unitp->pic16f819_mutex); 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate unitp->pic16f819_oflag = 0; 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate mutex_exit(&unitp->pic16f819_mutex); 2750Sstevel@tonic-gate return (DDI_SUCCESS); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate static int 2790Sstevel@tonic-gate pic16f819_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 2800Sstevel@tonic-gate cred_t *credp, int *rvalp) 2810Sstevel@tonic-gate { 2820Sstevel@tonic-gate _NOTE(ARGUNUSED(credp, rvalp)) 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate struct pic16f819_unit *unitp; 2850Sstevel@tonic-gate int instance; 2860Sstevel@tonic-gate int err = 0; 2870Sstevel@tonic-gate i2c_reg_t ioctl_reg; 2880Sstevel@tonic-gate uchar_t val8; 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate if (arg == NULL) { 2910Sstevel@tonic-gate D2CMN_ERR((CE_WARN, "PIC16F819: ioctl: arg passed in to ioctl " 292*7656SSherry.Moore@Sun.COM "= NULL\n")); 2930Sstevel@tonic-gate err = EINVAL; 2940Sstevel@tonic-gate return (err); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate instance = getminor(dev); 2970Sstevel@tonic-gate unitp = (struct pic16f819_unit *) 298*7656SSherry.Moore@Sun.COM ddi_get_soft_state(pic16f819soft_statep, instance); 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate mutex_enter(&unitp->pic16f819_mutex); 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate switch (cmd) { 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate case I2C_GET_REG: 3050Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_reg, 306*7656SSherry.Moore@Sun.COM sizeof (i2c_reg_t), mode) != DDI_SUCCESS) { 3070Sstevel@tonic-gate err = EFAULT; 3080Sstevel@tonic-gate break; 3090Sstevel@tonic-gate } 3100Sstevel@tonic-gate err = pic16f819_get(unitp, ioctl_reg.reg_num, &val8, 311*7656SSherry.Moore@Sun.COM I2C_SLEEP); 3120Sstevel@tonic-gate if (err != I2C_SUCCESS) { 3130Sstevel@tonic-gate break; 3140Sstevel@tonic-gate } 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate ioctl_reg.reg_value = val8; 3170Sstevel@tonic-gate if (ddi_copyout((caddr_t)&ioctl_reg, (caddr_t)arg, 318*7656SSherry.Moore@Sun.COM sizeof (i2c_reg_t), mode) != DDI_SUCCESS) { 3190Sstevel@tonic-gate err = EFAULT; 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate break; 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate case I2C_SET_REG: 3240Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_reg, 325*7656SSherry.Moore@Sun.COM sizeof (i2c_reg_t), mode) != DDI_SUCCESS) { 3260Sstevel@tonic-gate err = EFAULT; 3270Sstevel@tonic-gate break; 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate err = pic16f819_set(unitp, ioctl_reg.reg_num, 330*7656SSherry.Moore@Sun.COM ioctl_reg.reg_value); 3310Sstevel@tonic-gate break; 3320Sstevel@tonic-gate default: 3330Sstevel@tonic-gate D2CMN_ERR((CE_WARN, "%s: Invalid IOCTL cmd: %x\n", 334*7656SSherry.Moore@Sun.COM unitp->pic16f819_name, cmd)); 3350Sstevel@tonic-gate err = EINVAL; 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate mutex_exit(&unitp->pic16f819_mutex); 3390Sstevel@tonic-gate return (err); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate static int 3430Sstevel@tonic-gate pic16f819_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 3440Sstevel@tonic-gate { 3450Sstevel@tonic-gate switch (cmd) { 3460Sstevel@tonic-gate case DDI_ATTACH: 3470Sstevel@tonic-gate return (pic16f819_do_attach(dip)); 3480Sstevel@tonic-gate case DDI_RESUME: 3490Sstevel@tonic-gate return (pic16f819_do_resume()); 3500Sstevel@tonic-gate default: 3510Sstevel@tonic-gate return (DDI_FAILURE); 3520Sstevel@tonic-gate } 3530Sstevel@tonic-gate } 3540Sstevel@tonic-gate 3550Sstevel@tonic-gate static int 3560Sstevel@tonic-gate pic16f819_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3570Sstevel@tonic-gate { 3580Sstevel@tonic-gate switch (cmd) { 3590Sstevel@tonic-gate case DDI_DETACH: 3600Sstevel@tonic-gate return (pic16f819_do_detach(dip)); 3610Sstevel@tonic-gate case DDI_SUSPEND: 3620Sstevel@tonic-gate return (pic16f819_do_suspend()); 3630Sstevel@tonic-gate default: 3640Sstevel@tonic-gate return (DDI_FAILURE); 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate static int 3690Sstevel@tonic-gate pic16f819_do_attach(dev_info_t *dip) 3700Sstevel@tonic-gate { 3710Sstevel@tonic-gate struct pic16f819_unit *unitp; 3720Sstevel@tonic-gate int instance; 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate instance = ddi_get_instance(dip); 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate if (ddi_soft_state_zalloc(pic16f819soft_statep, instance) != 0) { 3770Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: failed to zalloc softstate\n", 378*7656SSherry.Moore@Sun.COM ddi_get_name(dip), instance); 3790Sstevel@tonic-gate return (DDI_FAILURE); 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate unitp = ddi_get_soft_state(pic16f819soft_statep, instance); 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate if (unitp == NULL) { 3850Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: unitp not filled\n", 386*7656SSherry.Moore@Sun.COM ddi_get_name(dip), instance); 3870Sstevel@tonic-gate return (ENOMEM); 3880Sstevel@tonic-gate } 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate (void) snprintf(unitp->pic16f819_name, sizeof (unitp->pic16f819_name), 391*7656SSherry.Moore@Sun.COM "%s%d", ddi_node_name(dip), instance); 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate if (ddi_create_minor_node(dip, "fan_1", S_IFCHR, instance, 394*7656SSherry.Moore@Sun.COM "ddi_i2c:pic", NULL) == DDI_FAILURE) { 3950Sstevel@tonic-gate cmn_err(CE_WARN, "%s ddi_create_minor_node failed for " 396*7656SSherry.Moore@Sun.COM "%s\n", unitp->pic16f819_name, "pic16f819"); 3970Sstevel@tonic-gate ddi_soft_state_free(pic16f819soft_statep, instance); 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate return (DDI_FAILURE); 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate if (i2c_client_register(dip, &unitp->pic16f819_hdl) != I2C_SUCCESS) { 4030Sstevel@tonic-gate cmn_err(CE_WARN, "%s i2c_client_register failed\n", 404*7656SSherry.Moore@Sun.COM unitp->pic16f819_name); 4050Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 4060Sstevel@tonic-gate ddi_soft_state_free(pic16f819soft_statep, instance); 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate return (DDI_FAILURE); 4090Sstevel@tonic-gate } 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate mutex_init(&unitp->pic16f819_mutex, NULL, MUTEX_DRIVER, NULL); 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate return (DDI_SUCCESS); 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate static int 4170Sstevel@tonic-gate pic16f819_do_resume() 4180Sstevel@tonic-gate { 4190Sstevel@tonic-gate int ret = DDI_SUCCESS; 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate return (ret); 4220Sstevel@tonic-gate } 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate static int 4250Sstevel@tonic-gate pic16f819_do_suspend() 4260Sstevel@tonic-gate { 4270Sstevel@tonic-gate int ret = DDI_SUCCESS; 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate return (ret); 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate static int 4330Sstevel@tonic-gate pic16f819_do_detach(dev_info_t *dip) 4340Sstevel@tonic-gate { 4350Sstevel@tonic-gate struct pic16f819_unit *unitp; 4360Sstevel@tonic-gate int instance; 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate instance = ddi_get_instance(dip); 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate unitp = ddi_get_soft_state(pic16f819soft_statep, instance); 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate if (unitp == NULL) { 4430Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: unitp not filled\n", 444*7656SSherry.Moore@Sun.COM ddi_get_name(dip), instance); 4450Sstevel@tonic-gate return (ENOMEM); 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate i2c_client_unregister(unitp->pic16f819_hdl); 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate mutex_destroy(&unitp->pic16f819_mutex); 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate ddi_soft_state_free(pic16f819soft_statep, instance); 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate return (DDI_SUCCESS); 4570Sstevel@tonic-gate } 458