| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: uftdi.c,v 1.40 2009/04/21 16:26:01 taca Exp $ */ | | 1 | /* $NetBSD: uftdi.c,v 1.41 2009/05/24 16:24:25 nisimura Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Lennart Augustsson (lennart@augustsson.net). | | 8 | * by Lennart Augustsson (lennart@augustsson.net). |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -19,32 +19,28 @@ | | | @@ -19,32 +19,28 @@ |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | | |
33 | * FTDI FT8U100AX serial adapter driver | | | |
34 | */ | | | |
35 | | | | |
36 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
37 | __KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1.40 2009/04/21 16:26:01 taca Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1.41 2009/05/24 16:24:25 nisimura Exp $"); |
38 | | | 34 | |
39 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
40 | #include <sys/systm.h> | | 36 | #include <sys/systm.h> |
41 | #include <sys/kernel.h> | | 37 | #include <sys/kernel.h> |
42 | #include <sys/device.h> | | 38 | #include <sys/device.h> |
43 | #include <sys/conf.h> | | 39 | #include <sys/conf.h> |
44 | #include <sys/tty.h> | | 40 | #include <sys/tty.h> |
45 | | | 41 | |
46 | #include <dev/usb/usb.h> | | 42 | #include <dev/usb/usb.h> |
47 | | | 43 | |
48 | #include <dev/usb/usbdi.h> | | 44 | #include <dev/usb/usbdi.h> |
49 | #include <dev/usb/usbdi_util.h> | | 45 | #include <dev/usb/usbdi_util.h> |
50 | #include <dev/usb/usbdevs.h> | | 46 | #include <dev/usb/usbdevs.h> |
| @@ -54,52 +50,54 @@ __KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1. | | | @@ -54,52 +50,54 @@ __KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1. |
54 | #include <dev/usb/uftdireg.h> | | 50 | #include <dev/usb/uftdireg.h> |
55 | | | 51 | |
56 | #ifdef UFTDI_DEBUG | | 52 | #ifdef UFTDI_DEBUG |
57 | #define DPRINTF(x) if (uftdidebug) printf x | | 53 | #define DPRINTF(x) if (uftdidebug) printf x |
58 | #define DPRINTFN(n,x) if (uftdidebug>(n)) printf x | | 54 | #define DPRINTFN(n,x) if (uftdidebug>(n)) printf x |
59 | int uftdidebug = 0; | | 55 | int uftdidebug = 0; |
60 | #else | | 56 | #else |
61 | #define DPRINTF(x) | | 57 | #define DPRINTF(x) |
62 | #define DPRINTFN(n,x) | | 58 | #define DPRINTFN(n,x) |
63 | #endif | | 59 | #endif |
64 | | | 60 | |
65 | #define UFTDI_CONFIG_INDEX 0 | | 61 | #define UFTDI_CONFIG_INDEX 0 |
66 | #define UFTDI_IFACE_INDEX 0 | | 62 | #define UFTDI_IFACE_INDEX 0 |
67 | #define UFTDI_MAX_PORTS 2 | | 63 | #define UFTDI_MAX_PORTS 4 |
68 | | | 64 | |
69 | /* | | 65 | /* |
70 | * These are the maximum number of bytes transferred per frame. | | 66 | * These are the maximum number of bytes transferred per frame. |
71 | * The output buffer size cannot be increased due to the size encoding. | | 67 | * The output buffer size cannot be increased due to the size encoding. |
72 | */ | | 68 | */ |
73 | #define UFTDIIBUFSIZE 64 | | 69 | #define UFTDIIBUFSIZE 64 |
74 | #define UFTDIOBUFSIZE 64 | | 70 | #define UFTDIOBUFSIZE 64 |
75 | | | 71 | |
76 | struct uftdi_softc { | | 72 | struct uftdi_softc { |
77 | USBBASEDEVICE sc_dev; /* base device */ | | 73 | USBBASEDEVICE sc_dev; /* base device */ |
78 | usbd_device_handle sc_udev; /* device */ | | 74 | usbd_device_handle sc_udev; /* device */ |
79 | usbd_interface_handle sc_iface[UFTDI_MAX_PORTS]; /* interface */ | | 75 | usbd_interface_handle sc_iface[UFTDI_MAX_PORTS]; /* interface */ |
80 | | | 76 | |
81 | enum uftdi_type sc_type; | | 77 | enum uftdi_type sc_type; |
82 | u_int sc_hdrlen; | | 78 | u_int sc_hdrlen; |
83 | u_int sc_numports; | | 79 | u_int sc_numports; |
| | | 80 | u_int sc_chiptype; |
84 | | | 81 | |
85 | u_char sc_msr; | | 82 | u_char sc_msr; |
86 | u_char sc_lsr; | | 83 | u_char sc_lsr; |
87 | | | 84 | |
88 | device_ptr_t sc_subdev[UFTDI_MAX_PORTS]; | | 85 | device_ptr_t sc_subdev[UFTDI_MAX_PORTS]; |
89 | | | 86 | |
90 | u_char sc_dying; | | 87 | u_char sc_dying; |
91 | | | 88 | |
92 | u_int last_lcr; | | 89 | u_int last_lcr; |
| | | 90 | |
93 | }; | | 91 | }; |
94 | | | 92 | |
95 | Static void uftdi_get_status(void *, int portno, u_char *lsr, u_char *msr); | | 93 | Static void uftdi_get_status(void *, int portno, u_char *lsr, u_char *msr); |
96 | Static void uftdi_set(void *, int, int, int); | | 94 | Static void uftdi_set(void *, int, int, int); |
97 | Static int uftdi_param(void *, int, struct termios *); | | 95 | Static int uftdi_param(void *, int, struct termios *); |
98 | Static int uftdi_open(void *sc, int portno); | | 96 | Static int uftdi_open(void *sc, int portno); |
99 | Static void uftdi_read(void *sc, int portno, u_char **ptr,u_int32_t *count); | | 97 | Static void uftdi_read(void *sc, int portno, u_char **ptr,u_int32_t *count); |
100 | Static void uftdi_write(void *sc, int portno, u_char *to, u_char *from, | | 98 | Static void uftdi_write(void *sc, int portno, u_char *to, u_char *from, |
101 | u_int32_t *count); | | 99 | u_int32_t *count); |
102 | Static void uftdi_break(void *sc, int portno, int onoff); | | 100 | Static void uftdi_break(void *sc, int portno, int onoff); |
103 | | | 101 | |
104 | struct ucom_methods uftdi_methods = { | | 102 | struct ucom_methods uftdi_methods = { |
105 | uftdi_get_status, | | 103 | uftdi_get_status, |
| @@ -169,70 +167,76 @@ USB_MATCH(uftdi) | | | @@ -169,70 +167,76 @@ USB_MATCH(uftdi) |
169 | | | 167 | |
170 | DPRINTFN(20,("uftdi: vendor=0x%x, product=0x%x\n", | | 168 | DPRINTFN(20,("uftdi: vendor=0x%x, product=0x%x\n", |
171 | uaa->vendor, uaa->product)); | | 169 | uaa->vendor, uaa->product)); |
172 | | | 170 | |
173 | return (uftdi_lookup(uaa->vendor, uaa->product) != NULL ? | | 171 | return (uftdi_lookup(uaa->vendor, uaa->product) != NULL ? |
174 | UMATCH_VENDOR_PRODUCT : UMATCH_NONE); | | 172 | UMATCH_VENDOR_PRODUCT : UMATCH_NONE); |
175 | } | | 173 | } |
176 | | | 174 | |
177 | USB_ATTACH(uftdi) | | 175 | USB_ATTACH(uftdi) |
178 | { | | 176 | { |
179 | USB_ATTACH_START(uftdi, sc, uaa); | | 177 | USB_ATTACH_START(uftdi, sc, uaa); |
180 | usbd_device_handle dev = uaa->device; | | 178 | usbd_device_handle dev = uaa->device; |
181 | usbd_interface_handle iface; | | 179 | usbd_interface_handle iface; |
| | | 180 | usb_device_descriptor_t *ddesc; |
182 | usb_interface_descriptor_t *id; | | 181 | usb_interface_descriptor_t *id; |
183 | usb_endpoint_descriptor_t *ed; | | 182 | usb_endpoint_descriptor_t *ed; |
184 | char *devinfop; | | 183 | char *devinfop; |
185 | const char *devname = device_xname(self); | | 184 | const char *devname = device_xname(self); |
186 | int i,idx; | | 185 | int i,idx; |
187 | usbd_status err; | | 186 | usbd_status err; |
188 | struct ucom_attach_args uca; | | 187 | struct ucom_attach_args uca; |
189 | | | 188 | |
190 | DPRINTFN(10,("\nuftdi_attach: sc=%p\n", sc)); | | 189 | DPRINTFN(10,("\nuftdi_attach: sc=%p\n", sc)); |
191 | | | 190 | |
192 | /* Move the device into the configured state. */ | | 191 | /* Move the device into the configured state. */ |
193 | err = usbd_set_config_index(dev, UFTDI_CONFIG_INDEX, 1); | | 192 | err = usbd_set_config_index(dev, UFTDI_CONFIG_INDEX, 1); |
194 | if (err) { | | 193 | if (err) { |
195 | aprint_error("\n%s: failed to set configuration, err=%s\n", | | 194 | aprint_error("\n%s: failed to set configuration, err=%s\n", |
196 | devname, usbd_errstr(err)); | | 195 | devname, usbd_errstr(err)); |
197 | goto bad; | | 196 | goto bad; |
198 | } | | 197 | } |
199 | | | 198 | |
200 | devinfop = usbd_devinfo_alloc(dev, 0); | | 199 | devinfop = usbd_devinfo_alloc(dev, 0); |
201 | USB_ATTACH_SETUP; | | 200 | USB_ATTACH_SETUP; |
202 | aprint_normal_dev(self, "%s\n", devinfop); | | 201 | aprint_normal_dev(self, "%s\n", devinfop); |
203 | usbd_devinfo_free(devinfop); | | 202 | usbd_devinfo_free(devinfop); |
204 | | | 203 | |
205 | sc->sc_dev = self; | | 204 | sc->sc_dev = self; |
206 | sc->sc_udev = dev; | | 205 | sc->sc_udev = dev; |
207 | sc->sc_numports = 1; | | 206 | sc->sc_numports = 1; |
208 | switch( uaa->vendor ) { | | 207 | sc->sc_type = UFTDI_TYPE_8U232AM; /* most devices are post-8U232AM */ |
209 | case USB_VENDOR_FTDI: | | 208 | sc->sc_hdrlen = 0; |
210 | switch (uaa->product) { | | 209 | if (uaa->vendor == USB_VENDOR_FTDI |
211 | case USB_PRODUCT_FTDI_SERIAL_8U100AX: | | 210 | && uaa->product == USB_PRODUCT_FTDI_SERIAL_8U100AX) { |
212 | sc->sc_type = UFTDI_TYPE_SIO; | | 211 | sc->sc_type = UFTDI_TYPE_SIO; |
213 | sc->sc_hdrlen = 1; | | 212 | sc->sc_hdrlen = 1; |
214 | break; | | 213 | } |
215 | case USB_PRODUCT_FTDI_SERIAL_2232C: | | 214 | |
216 | sc->sc_numports = 2; | | 215 | ddesc = usbd_get_device_descriptor(dev); |
217 | /* FALLTHROUGH */ | | 216 | sc->sc_chiptype = UGETW(ddesc->bcdDevice); |
218 | default: /* Most uftdi devices are 8U232AM */ | | 217 | switch (sc->sc_chiptype) { |
219 | sc->sc_type = UFTDI_TYPE_8U232AM; | | 218 | case 0x500: /* 2232D */ |
220 | sc->sc_hdrlen = 0; | | 219 | case 0x700: /* 2232H */ |
221 | } | | 220 | sc->sc_numports = 2; |
| | | 221 | break; |
| | | 222 | case 0x800: /* 4232H */ |
| | | 223 | sc->sc_numports = 4; |
| | | 224 | break; |
| | | 225 | case 0x200: /* 232/245AM */ |
| | | 226 | case 0x400: /* 232/245BL */ |
| | | 227 | case 0x600: /* 232/245R */ |
| | | 228 | default: |
222 | break; | | 229 | break; |
223 | default: /* Most uftdi devices are 8U232AM */ | | | |
224 | sc->sc_type = UFTDI_TYPE_8U232AM; | | | |
225 | sc->sc_hdrlen = 0; | | | |
226 | } | | 230 | } |
227 | | | 231 | |
228 | for (idx = UFTDI_IFACE_INDEX; idx < sc->sc_numports; idx++) { | | 232 | for (idx = UFTDI_IFACE_INDEX; idx < sc->sc_numports; idx++) { |
229 | err = usbd_device2interface_handle(dev, idx, &iface); | | 233 | err = usbd_device2interface_handle(dev, idx, &iface); |
230 | if (err) { | | 234 | if (err) { |
231 | aprint_error( | | 235 | aprint_error( |
232 | "\n%s: failed to get interface idx=%d, err=%s\n", | | 236 | "\n%s: failed to get interface idx=%d, err=%s\n", |
233 | devname, idx, usbd_errstr(err)); | | 237 | devname, idx, usbd_errstr(err)); |
234 | goto bad; | | 238 | goto bad; |
235 | } | | 239 | } |
236 | | | 240 | |
237 | id = usbd_get_interface_descriptor(iface); | | 241 | id = usbd_get_interface_descriptor(iface); |
238 | | | 242 | |
| @@ -276,28 +280,28 @@ USB_ATTACH(uftdi) | | | @@ -276,28 +280,28 @@ USB_ATTACH(uftdi) |
276 | uca.portno = FTDI_PIT_SIOA + idx; | | 280 | uca.portno = FTDI_PIT_SIOA + idx; |
277 | /* bulkin, bulkout set above */ | | 281 | /* bulkin, bulkout set above */ |
278 | uca.ibufsize = UFTDIIBUFSIZE; | | 282 | uca.ibufsize = UFTDIIBUFSIZE; |
279 | uca.obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen; | | 283 | uca.obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen; |
280 | uca.ibufsizepad = UFTDIIBUFSIZE; | | 284 | uca.ibufsizepad = UFTDIIBUFSIZE; |
281 | uca.opkthdrlen = sc->sc_hdrlen; | | 285 | uca.opkthdrlen = sc->sc_hdrlen; |
282 | uca.device = dev; | | 286 | uca.device = dev; |
283 | uca.iface = iface; | | 287 | uca.iface = iface; |
284 | uca.methods = &uftdi_methods; | | 288 | uca.methods = &uftdi_methods; |
285 | uca.arg = sc; | | 289 | uca.arg = sc; |
286 | uca.info = NULL; | | 290 | uca.info = NULL; |
287 | | | 291 | |
288 | DPRINTF(("uftdi: in=0x%x out=0x%x\n", uca.bulkin, uca.bulkout)); | | 292 | DPRINTF(("uftdi: in=0x%x out=0x%x\n", uca.bulkin, uca.bulkout)); |
289 | sc->sc_subdev[idx] = config_found_sm_loc(self, "ucombus", NULL, &uca, | | 293 | sc->sc_subdev[idx] = config_found_sm_loc(self, "ucombus", NULL, |
290 | ucomprint, ucomsubmatch); | | 294 | &uca, ucomprint, ucomsubmatch); |
291 | } | | 295 | } |
292 | | | 296 | |
293 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, | | 297 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, |
294 | USBDEV(sc->sc_dev)); | | 298 | USBDEV(sc->sc_dev)); |
295 | | | 299 | |
296 | USB_ATTACH_SUCCESS_RETURN; | | 300 | USB_ATTACH_SUCCESS_RETURN; |
297 | | | 301 | |
298 | bad: | | 302 | bad: |
299 | DPRINTF(("uftdi_attach: ATTACH ERROR\n")); | | 303 | DPRINTF(("uftdi_attach: ATTACH ERROR\n")); |
300 | sc->sc_dying = 1; | | 304 | sc->sc_dying = 1; |
301 | USB_ATTACH_ERROR_RETURN; | | 305 | USB_ATTACH_ERROR_RETURN; |
302 | } | | 306 | } |
303 | | | 307 | |