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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 
  27 /*
  28  * This driver supports Prolific PL-2303H/HX/X USB-to-serial adapters. It is a
  29  * device-specific driver (DSD) working with USB generic serial driver (GSD). It
  30  * implements the USB-to-serial device-specific driver interface (DSDI) which is
  31  * offered by GSD. The interface is defined by ds_ops_t structure.
  32  *
  33  *
  34  * PL-2303HX and PL-2303X devices have different hardware, but from the
  35  * perspective of device driver, they have the same software interface.
  36  */
  37 
  38 /*
  39  *
  40  * USB Prolific PL2303 driver glue code
  41  *
  42  */
  43 #include <sys/types.h>
  44 #include <sys/param.h>
  45 #include <sys/stream.h>
  46 #include <sys/conf.h>
  47 #include <sys/ddi.h>
  48 #include <sys/sunddi.h>
  49 
  50 #include <sys/usb/clients/usbser/usbser.h>
  51 #include <sys/usb/clients/usbser/usbsprl/pl2303_var.h>
  52 
  53 
  54 /* configuration entry points */
  55 static int      usbser_pl2303_attach(dev_info_t *, ddi_attach_cmd_t);
  56 static int      usbser_pl2303_detach(dev_info_t *, ddi_detach_cmd_t);
  57 static int      usbser_pl2303_getinfo(dev_info_t *, ddi_info_cmd_t, void *,
  58                 void **);
  59 static int      usbser_pl2303_open(queue_t *, dev_t *, int, int, cred_t *);
  60 static void     *usbser_pl2303_statep;  /* soft state */
  61 
  62 extern          ds_ops_t pl2303_ds_ops; /* DSD operations */
  63 
  64 
  65 /*
  66  * STREAMS structures
  67  */
  68 struct module_info usbser_pl2303_modinfo = {
  69         0,                      /* module id */
  70         "usbsprl",              /* module name */
  71         USBSER_MIN_PKTSZ,       /* min pkt size */
  72         USBSER_MAX_PKTSZ,       /* max pkt size */
  73         USBSER_HIWAT,           /* hi watermark */
  74         USBSER_LOWAT            /* low watermark */
  75 };
  76 
  77 
  78 static struct qinit usbser_pl2303_rinit = {
  79         putq,
  80         usbser_rsrv,
  81         usbser_pl2303_open,
  82         usbser_close,
  83         NULL,
  84         &usbser_pl2303_modinfo,
  85         NULL
  86 };
  87 
  88 
  89 static struct qinit usbser_pl2303_winit = {
  90         usbser_wput,
  91         usbser_wsrv,
  92         NULL,
  93         NULL,
  94         NULL,
  95         &usbser_pl2303_modinfo,
  96         NULL
  97 };
  98 
  99 
 100 struct streamtab usbser_pl2303_str_info = {
 101         &usbser_pl2303_rinit, &usbser_pl2303_winit, NULL, NULL
 102 };
 103 
 104 
 105 static struct cb_ops usbser_pl2303_cb_ops = {
 106         nodev,                  /* cb_open */
 107         nodev,                  /* cb_close */
 108         nodev,                  /* cb_strategy */
 109         nodev,                  /* cb_print */
 110         nodev,                  /* cb_dump */
 111         nodev,                  /* cb_read */
 112         nodev,                  /* cb_write */
 113         nodev,                  /* cb_ioctl */
 114         nodev,                  /* cb_devmap */
 115         nodev,                  /* cb_mmap */
 116         nodev,                  /* cb_segmap */
 117         nochpoll,               /* cb_chpoll */
 118         ddi_prop_op,            /* cb_prop_op */
 119         &usbser_pl2303_str_info,                    /* cb_stream */
 120         (int)(D_64BIT | D_NEW | D_MP | D_HOTPLUG)       /* cb_flag */
 121 };
 122 
 123 
 124 /*
 125  * auto configuration ops
 126  */
 127 struct dev_ops usbser_pl2303_ops = {
 128         DEVO_REV,               /* devo_rev */
 129         0,                      /* devo_refcnt */
 130         usbser_pl2303_getinfo,  /* devo_getinfo */
 131         nulldev,                /* devo_identify */
 132         nulldev,                /* devo_probe */
 133         usbser_pl2303_attach,   /* devo_attach */
 134         usbser_pl2303_detach,   /* devo_detach */
 135         nodev,                  /* devo_reset */
 136         &usbser_pl2303_cb_ops,      /* devo_cb_ops */
 137         (struct bus_ops *)NULL, /* devo_bus_ops */
 138         usbser_power,           /* devo_power */
 139         ddi_quiesce_not_needed, /* devo_quiesce */
 140 };
 141 
 142 
 143 extern struct mod_ops mod_driverops;
 144 
 145 
 146 static struct modldrv modldrv = {
 147         &mod_driverops,             /* type of module - driver */
 148         "USB Prolific PL2303 driver",
 149         &usbser_pl2303_ops,
 150 };
 151 
 152 
 153 static struct modlinkage modlinkage = {
 154         MODREV_1, { &modldrv, NULL }
 155 };
 156 
 157 
 158 /*
 159  * entry points
 160  * ------------
 161  *
 162  */
 163 int
 164 _init(void)
 165 {
 166         int    error;
 167 
 168         if ((error = mod_install(&modlinkage)) == 0) {
 169                 error = ddi_soft_state_init(&usbser_pl2303_statep,
 170                     usbser_soft_state_size(), 1);
 171         }
 172 
 173         return (error);
 174 }
 175 
 176 
 177 int
 178 _fini(void)
 179 {
 180         int    error;
 181 
 182         if ((error = mod_remove(&modlinkage)) == 0) {
 183                 ddi_soft_state_fini(&usbser_pl2303_statep);
 184         }
 185 
 186         return (error);
 187 }
 188 
 189 
 190 int
 191 _info(struct modinfo *modinfop)
 192 {
 193         return (mod_info(&modlinkage, modinfop));
 194 }
 195 
 196 
 197 int
 198 usbser_pl2303_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
 199                 void **result)
 200 {
 201         return (usbser_getinfo(dip, infocmd, arg, result,
 202             usbser_pl2303_statep));
 203 }
 204 
 205 
 206 static int
 207 usbser_pl2303_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 208 {
 209         return (usbser_attach(dip, cmd, usbser_pl2303_statep, &pl2303_ds_ops));
 210 }
 211 
 212 
 213 static int
 214 usbser_pl2303_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 215 {
 216         return (usbser_detach(dip, cmd, usbser_pl2303_statep));
 217 }
 218 
 219 
 220 static int
 221 usbser_pl2303_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr)
 222 {
 223         return (usbser_open(rq, dev, flag, sflag, cr, usbser_pl2303_statep));
 224 }