xref: /illumos-gate/usr/src/uts/common/io/usb/clients/usbser/usbftdi/usbser_uftdi.c (revision 8883f1c270cc8e33c18dd088e744840092b47bbb)
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
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
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
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
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
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
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
185 _info(struct modinfo *modinfop)
186 {
187 	return (mod_info(&modlinkage, modinfop));
188 }
189