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