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, 0
155 };
156 
157 
158 /*
159  * entry points
160  * ------------
161  *
162  */
163 int
_init(void)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
_fini(void)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
_info(struct modinfo * modinfop)191 _info(struct modinfo *modinfop)
192 {
193 	return (mod_info(&modlinkage, modinfop));
194 }
195 
196 
197 int
usbser_pl2303_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)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
usbser_pl2303_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)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
usbser_pl2303_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)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
usbser_pl2303_open(queue_t * rq,dev_t * dev,int flag,int sflag,cred_t * cr)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 }
225