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 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * This driver supports FTDI FT232R USB-to-serial adapters. It is a
29 * device-specific driver (DSD) working with the USB generic serial
30 * driver (GSD) usbser.
31 *
32 * It implements the USB-to-serial device-specific driver interface (DSDI)
33 * which is exported by GSD. The DSDI is defined by ds_ops_t structure.
34 *
35 * Also may work with the older FTDI 8U232AM devices.
36 */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/stream.h>
41 #include <sys/conf.h>
42 #include <sys/ddi.h>
43 #include <sys/sunddi.h>
44
45 #include <sys/usb/clients/usbser/usbser.h>
46 #include <sys/usb/clients/usbser/usbftdi/uftdi_var.h>
47
48 static void *usbser_uftdi_statep; /* soft state handle for usbser */
49
50 extern ds_ops_t uftdi_ds_ops; /* DSD operations */
51
52 static int
usbser_uftdi_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)53 usbser_uftdi_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
54 void **result)
55 {
56 return (usbser_getinfo(dip, infocmd, arg, result, usbser_uftdi_statep));
57 }
58
59
60 static int
usbser_uftdi_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)61 usbser_uftdi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
62 {
63 return (usbser_attach(dip, cmd, usbser_uftdi_statep, &uftdi_ds_ops));
64 }
65
66
67 static int
usbser_uftdi_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)68 usbser_uftdi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
69 {
70 return (usbser_detach(dip, cmd, usbser_uftdi_statep));
71 }
72
73
74 static int
usbser_uftdi_open(queue_t * rq,dev_t * dev,int flag,int sflag,cred_t * cr)75 usbser_uftdi_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr)
76 {
77 return (usbser_open(rq, dev, flag, sflag, cr, usbser_uftdi_statep));
78 }
79
80 /*
81 * Several linked data structures to tie it together ..
82 */
83 struct module_info uftdi_modinfo = {
84 0, /* module id */
85 "uftdi", /* module name */
86 USBSER_MIN_PKTSZ, /* min pkt size */
87 USBSER_MAX_PKTSZ, /* max pkt size */
88 USBSER_HIWAT, /* hi watermark */
89 USBSER_LOWAT /* low watermark */
90 };
91
92 static struct qinit uftdi_rinit = {
93 putq,
94 usbser_rsrv,
95 usbser_uftdi_open,
96 usbser_close,
97 NULL,
98 &uftdi_modinfo,
99 };
100
101 static struct qinit uftdi_winit = {
102 usbser_wput,
103 usbser_wsrv,
104 NULL,
105 NULL,
106 NULL,
107 &uftdi_modinfo,
108 };
109
110 static struct streamtab uftdi_str_info = {
111 &uftdi_rinit,
112 &uftdi_winit,
113 };
114
115 static struct cb_ops uftdi_cb_ops = {
116 nodev, /* cb_open */
117 nodev, /* cb_close */
118 nodev, /* cb_strategy */
119 nodev, /* cb_print */
120 nodev, /* cb_dump */
121 nodev, /* cb_read */
122 nodev, /* cb_write */
123 nodev, /* cb_ioctl */
124 nodev, /* cb_devmap */
125 nodev, /* cb_mmap */
126 nodev, /* cb_segmap */
127 nochpoll, /* cb_chpoll */
128 ddi_prop_op, /* cb_prop_op */
129 &uftdi_str_info, /* cb_stream */
130 (int)(D_64BIT | D_NEW | D_MP | D_HOTPLUG) /* cb_flag */
131 };
132
133 static struct dev_ops uftdi_ops = {
134 DEVO_REV, /* devo_rev */
135 0, /* devo_refcnt */
136 usbser_uftdi_getinfo,
137 nulldev, /* devo_identify */
138 nulldev, /* devo_probe */
139 usbser_uftdi_attach,
140 usbser_uftdi_detach,
141 nodev, /* devo_reset */
142 &uftdi_cb_ops,
143 (struct bus_ops *)NULL, /* devo_bus_ops */
144 usbser_power, /* devo_power */
145 ddi_quiesce_not_needed
146 };
147
148 static struct modldrv modldrv = {
149 &mod_driverops,
150 "FTDI FT232R USB UART driver",
151 &uftdi_ops,
152 };
153
154 static struct modlinkage modlinkage = {
155 MODREV_1,
156 &modldrv
157 };
158
159 int
_init(void)160 _init(void)
161 {
162 int error;
163
164 if ((error = mod_install(&modlinkage)) != 0)
165 return (error);
166 if ((error = ddi_soft_state_init(&usbser_uftdi_statep,
167 usbser_soft_state_size(), 1)) != 0)
168 (void) mod_remove(&modlinkage);
169 return (error);
170 }
171
172
173 int
_fini(void)174 _fini(void)
175 {
176 int error;
177
178 if ((error = mod_remove(&modlinkage)) == 0)
179 ddi_soft_state_fini(&usbser_uftdi_statep);
180 return (error);
181 }
182
183
184 int
_info(struct modinfo * modinfop)185 _info(struct modinfo *modinfop)
186 {
187 return (mod_info(&modlinkage, modinfop));
188 }
189