1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /* 28 * skeleton hub driver, the actual code is in hubdi.c 29 * as it is shared between the root hub and the other hub instances 30 */ 31 #if defined(lint) && !defined(DEBUG) 32 #define DEBUG 1 33 #endif 34 35 #include <sys/usb/usba/usbai_version.h> 36 #include <sys/usb/usba.h> 37 #include <sys/usb/usba/hubdi.h> 38 #include <sys/usb/hubd/hub.h> 39 #include <sys/usb/hubd/hubdvar.h> 40 41 static int hubd_open(dev_t *devp, int flags, int otyp, cred_t *credp); 42 static int hubd_close(dev_t dev, int flag, int otyp, cred_t *credp); 43 static int hubd_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 44 cred_t *credp, int *rvalp); 45 static int hubd_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 46 void *arg, void **result); 47 extern int usba_hubdi_power(dev_info_t *dip, int comp, int level); 48 49 50 static struct cb_ops hubd_cb_ops = { 51 hubd_open, /* open */ 52 hubd_close, /* close */ 53 nodev, /* strategy */ 54 nodev, /* print */ 55 nodev, /* dump */ 56 nodev, /* read */ 57 nodev, /* write */ 58 hubd_ioctl, /* ioctl */ 59 nodev, /* devmap */ 60 nodev, /* mmap */ 61 nodev, /* segmap */ 62 nochpoll, /* poll */ 63 ddi_prop_op, /* cb_prop_op */ 64 NULL, /* streamtab */ 65 D_MP /* Driver compatibility flag */ 66 }; 67 68 static struct dev_ops hubd_ops = { 69 DEVO_REV, /* devo_rev, */ 70 0, /* refcnt */ 71 hubd_info, /* info */ 72 nulldev, /* identify */ 73 nulldev, /* probe */ 74 usba_hubdi_attach, /* attach */ 75 usba_hubdi_detach, /* detach */ 76 nodev, /* reset */ 77 &hubd_cb_ops, /* driver operations */ 78 &usba_hubdi_busops, /* bus operations */ 79 usba_hubdi_power /* power */ 80 }; 81 82 static struct modldrv modldrv = { 83 &mod_driverops, /* Type of module. This one is a driver */ 84 "USB Hub Driver", /* Name of the module. */ 85 &hubd_ops, /* driver ops */ 86 }; 87 88 static struct modlinkage modlinkage = { 89 MODREV_1, (void *)&modldrv, NULL 90 }; 91 92 93 extern void *hubd_statep; 94 95 int 96 _init(void) 97 { 98 int rval; 99 100 /* Initialize the soft state structures */ 101 if ((rval = ddi_soft_state_init(&hubd_statep, 102 sizeof (hubd_t), HUBD_INITIAL_SOFT_SPACE)) != 0) { 103 return (rval); 104 } 105 106 if ((rval = mod_install(&modlinkage)) != 0) { 107 ddi_soft_state_fini(&hubd_statep); 108 109 return (rval); 110 } 111 112 return (rval); 113 } 114 115 116 int 117 _fini(void) 118 { 119 int rval = mod_remove(&modlinkage); 120 if (rval == 0) { 121 ddi_soft_state_fini(&hubd_statep); 122 } 123 124 return (rval); 125 } 126 127 128 int 129 _info(struct modinfo *modinfop) 130 { 131 return (mod_info(&modlinkage, modinfop)); 132 } 133 134 135 static dev_info_t * 136 hubd_get_dip(dev_t dev) 137 { 138 minor_t minor = getminor(dev); 139 int instance = (int)minor & ~HUBD_IS_ROOT_HUB; 140 hubd_t *hubd = ddi_get_soft_state(hubd_statep, instance); 141 142 if (hubd) { 143 return (hubd->h_dip); 144 } else { 145 return (NULL); 146 } 147 } 148 149 /* 150 * info handler 151 */ 152 /*ARGSUSED*/ 153 int 154 hubd_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 155 void *arg, void **result) 156 { 157 dev_t dev; 158 int instance; 159 int error = DDI_FAILURE; 160 161 switch (infocmd) { 162 case DDI_INFO_DEVT2DEVINFO: 163 *result = (void *)hubd_get_dip((dev_t)arg); 164 if (*result != NULL) { 165 error = DDI_SUCCESS; 166 } 167 break; 168 case DDI_INFO_DEVT2INSTANCE: 169 dev = (dev_t)arg; 170 instance = HUBD_UNIT(dev); 171 *result = (void *)(intptr_t)instance; 172 error = DDI_SUCCESS; 173 break; 174 default: 175 break; 176 } 177 return (error); 178 } 179 180 static int 181 hubd_open(dev_t *devp, int flags, int otyp, cred_t *credp) 182 { 183 dev_info_t *dip = hubd_get_dip(*devp); 184 185 return (usba_hubdi_open(dip, devp, flags, otyp, credp)); 186 } 187 188 189 static int 190 hubd_close(dev_t dev, int flag, int otyp, cred_t *credp) 191 { 192 dev_info_t *dip = hubd_get_dip(dev); 193 194 return (usba_hubdi_close(dip, dev, flag, otyp, credp)); 195 } 196 197 198 static int 199 hubd_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 200 cred_t *credp, int *rvalp) 201 { 202 dev_info_t *dip = hubd_get_dip(dev); 203 204 return (usba_hubdi_ioctl(dip, dev, cmd, arg, mode, 205 credp, rvalp)); 206 } 207