sl811hs.c revision 1.6 1 1.6 drochner /* $NetBSD: sl811hs.c,v 1.6 2005/06/01 19:40:58 drochner Exp $ */
2 1.1 isaki
3 1.1 isaki /*
4 1.1 isaki * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 1.1 isaki * All rights reserved.
6 1.1 isaki *
7 1.1 isaki * This code is derived from software contributed to The NetBSD Foundation
8 1.1 isaki * by Tetsuya Isaki.
9 1.1 isaki *
10 1.1 isaki * Redistribution and use in source and binary forms, with or without
11 1.1 isaki * modification, are permitted provided that the following conditions
12 1.1 isaki * are met:
13 1.1 isaki * 1. Redistributions of source code must retain the above copyright
14 1.1 isaki * notice, this list of conditions and the following disclaimer.
15 1.1 isaki * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 isaki * notice, this list of conditions and the following disclaimer in the
17 1.1 isaki * documentation and/or other materials provided with the distribution.
18 1.1 isaki * 3. All advertising materials mentioning features or use of this software
19 1.1 isaki * must display the following acknowledgement:
20 1.1 isaki * This product includes software developed by the NetBSD
21 1.1 isaki * Foundation, Inc. and its contributors.
22 1.1 isaki * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 isaki * contributors may be used to endorse or promote products derived
24 1.1 isaki * from this software without specific prior written permission.
25 1.1 isaki *
26 1.1 isaki * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 isaki * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 isaki * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 isaki * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 isaki * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 isaki * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 isaki * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 isaki * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 isaki * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 isaki * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 isaki * POSSIBILITY OF SUCH DAMAGE.
37 1.1 isaki */
38 1.1 isaki
39 1.1 isaki /*
40 1.1 isaki * ScanLogic SL811HS/T USB Host Controller
41 1.1 isaki */
42 1.1 isaki /*
43 1.1 isaki * !! HIGHLY EXPERIMENTAL CODE !!
44 1.1 isaki */
45 1.1 isaki
46 1.1 isaki #include <sys/cdefs.h>
47 1.6 drochner __KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.6 2005/06/01 19:40:58 drochner Exp $");
48 1.1 isaki
49 1.1 isaki #include "opt_slhci.h"
50 1.1 isaki
51 1.1 isaki #include <sys/param.h>
52 1.1 isaki #include <sys/systm.h>
53 1.1 isaki #include <sys/kernel.h>
54 1.1 isaki #include <sys/proc.h>
55 1.1 isaki #include <sys/device.h>
56 1.1 isaki #include <sys/malloc.h>
57 1.1 isaki
58 1.1 isaki #include <machine/bus.h>
59 1.1 isaki #include <machine/cpu.h>
60 1.1 isaki
61 1.1 isaki #include <dev/usb/usb.h>
62 1.1 isaki #include <dev/usb/usbdi.h>
63 1.1 isaki #include <dev/usb/usbdivar.h>
64 1.1 isaki #include <dev/usb/usb_mem.h>
65 1.1 isaki #include <dev/usb/usbdevs.h>
66 1.1 isaki
67 1.1 isaki #include <dev/ic/sl811hsreg.h>
68 1.1 isaki #include <dev/ic/sl811hsvar.h>
69 1.1 isaki
70 1.1 isaki static inline u_int8_t sl11read(struct slhci_softc *, int);
71 1.1 isaki static inline void sl11write(struct slhci_softc *, int, u_int8_t);
72 1.1 isaki static inline void sl11read_region(struct slhci_softc *, u_char *, int, int);
73 1.1 isaki static inline void sl11write_region(struct slhci_softc *, int, u_char *, int);
74 1.1 isaki
75 1.1 isaki static void sl11_reset(struct slhci_softc *);
76 1.1 isaki static void sl11_speed(struct slhci_softc *);
77 1.1 isaki
78 1.1 isaki static usbd_status slhci_open(usbd_pipe_handle);
79 1.1 isaki static void slhci_softintr(void *);
80 1.1 isaki static void slhci_poll(struct usbd_bus *);
81 1.1 isaki static void slhci_poll_hub(void *);
82 1.1 isaki static void slhci_poll_device(void *arg);
83 1.1 isaki static usbd_status slhci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
84 1.1 isaki static void slhci_freem(struct usbd_bus *, usb_dma_t *);
85 1.1 isaki static usbd_xfer_handle slhci_allocx(struct usbd_bus *);
86 1.1 isaki static void slhci_freex(struct usbd_bus *, usbd_xfer_handle);
87 1.1 isaki
88 1.6 drochner static int slhci_str(usb_string_descriptor_t *, int, const char *);
89 1.1 isaki
90 1.1 isaki static usbd_status slhci_root_ctrl_transfer(usbd_xfer_handle);
91 1.1 isaki static usbd_status slhci_root_ctrl_start(usbd_xfer_handle);
92 1.1 isaki static void slhci_root_ctrl_abort(usbd_xfer_handle);
93 1.1 isaki static void slhci_root_ctrl_close(usbd_pipe_handle);
94 1.1 isaki static void slhci_root_ctrl_done(usbd_xfer_handle);
95 1.1 isaki
96 1.1 isaki static usbd_status slhci_root_intr_transfer(usbd_xfer_handle);
97 1.1 isaki static usbd_status slhci_root_intr_start(usbd_xfer_handle);
98 1.1 isaki static void slhci_root_intr_abort(usbd_xfer_handle);
99 1.1 isaki static void slhci_root_intr_close(usbd_pipe_handle);
100 1.1 isaki static void slhci_root_intr_done(usbd_xfer_handle);
101 1.1 isaki
102 1.1 isaki static usbd_status slhci_device_ctrl_transfer(usbd_xfer_handle);
103 1.1 isaki static usbd_status slhci_device_ctrl_start(usbd_xfer_handle);
104 1.1 isaki static void slhci_device_ctrl_abort(usbd_xfer_handle);
105 1.1 isaki static void slhci_device_ctrl_close(usbd_pipe_handle);
106 1.1 isaki static void slhci_device_ctrl_done(usbd_xfer_handle);
107 1.1 isaki
108 1.1 isaki static usbd_status slhci_device_intr_transfer(usbd_xfer_handle);
109 1.1 isaki static usbd_status slhci_device_intr_start(usbd_xfer_handle);
110 1.1 isaki static void slhci_device_intr_abort(usbd_xfer_handle);
111 1.1 isaki static void slhci_device_intr_close(usbd_pipe_handle);
112 1.1 isaki static void slhci_device_intr_done(usbd_xfer_handle);
113 1.1 isaki
114 1.1 isaki static usbd_status slhci_device_isoc_transfer(usbd_xfer_handle);
115 1.1 isaki static usbd_status slhci_device_isoc_start(usbd_xfer_handle);
116 1.1 isaki static void slhci_device_isoc_abort(usbd_xfer_handle);
117 1.1 isaki static void slhci_device_isoc_close(usbd_pipe_handle);
118 1.1 isaki static void slhci_device_isoc_done(usbd_xfer_handle);
119 1.1 isaki
120 1.1 isaki static usbd_status slhci_device_bulk_transfer(usbd_xfer_handle);
121 1.1 isaki static usbd_status slhci_device_bulk_start(usbd_xfer_handle);
122 1.1 isaki static void slhci_device_bulk_abort(usbd_xfer_handle);
123 1.1 isaki static void slhci_device_bulk_close(usbd_pipe_handle);
124 1.1 isaki static void slhci_device_bulk_done(usbd_xfer_handle);
125 1.1 isaki
126 1.1 isaki static int slhci_transaction(struct slhci_softc *,
127 1.1 isaki usbd_pipe_handle, u_int8_t, int, u_char *, u_int8_t);
128 1.1 isaki static void slhci_noop(usbd_pipe_handle);
129 1.1 isaki static void slhci_abort_xfer(usbd_xfer_handle, usbd_status);
130 1.1 isaki static void slhci_device_clear_toggle(usbd_pipe_handle);
131 1.1 isaki
132 1.1 isaki extern int usbdebug;
133 1.1 isaki int slhci_dummy;
134 1.1 isaki
135 1.1 isaki /* For root hub */
136 1.1 isaki #define SLHCI_INTR_ENDPT (1)
137 1.1 isaki
138 1.1 isaki #ifdef SLHCI_DEBUG
139 1.1 isaki #define D_TRACE (0x0001) /* function trace */
140 1.1 isaki #define D_MSG (0x0002) /* debug messages */
141 1.1 isaki #define D_XFER (0x0004) /* transfer messages (noisy!) */
142 1.1 isaki #define D_MEM (0x0008) /* memory allocation */
143 1.1 isaki
144 1.1 isaki int slhci_debug = D_MSG | D_XFER;
145 1.1 isaki #define DPRINTF(z,x) if((slhci_debug&(z))!=0)printf x
146 1.1 isaki void print_req(usb_device_request_t *);
147 1.1 isaki void print_req_hub(usb_device_request_t *);
148 1.1 isaki void print_dumpreg(struct slhci_softc *);
149 1.1 isaki void print_xfer(usbd_xfer_handle);
150 1.1 isaki #else
151 1.1 isaki #define DPRINTF(z,x)
152 1.1 isaki #endif
153 1.1 isaki
154 1.1 isaki
155 1.1 isaki /* XXX: sync with argument */
156 1.6 drochner static const char *sltypestr [] = {
157 1.1 isaki "SL11H/T",
158 1.1 isaki "SL811HS/T",
159 1.1 isaki };
160 1.1 isaki
161 1.1 isaki
162 1.1 isaki struct usbd_bus_methods slhci_bus_methods = {
163 1.1 isaki slhci_open,
164 1.1 isaki slhci_softintr,
165 1.1 isaki slhci_poll,
166 1.1 isaki slhci_allocm,
167 1.1 isaki slhci_freem,
168 1.1 isaki slhci_allocx,
169 1.1 isaki slhci_freex,
170 1.1 isaki };
171 1.1 isaki
172 1.1 isaki struct usbd_pipe_methods slhci_root_ctrl_methods = {
173 1.1 isaki slhci_root_ctrl_transfer,
174 1.1 isaki slhci_root_ctrl_start,
175 1.1 isaki slhci_root_ctrl_abort,
176 1.1 isaki slhci_root_ctrl_close,
177 1.1 isaki slhci_noop,
178 1.1 isaki slhci_root_ctrl_done,
179 1.1 isaki };
180 1.1 isaki
181 1.1 isaki struct usbd_pipe_methods slhci_root_intr_methods = {
182 1.1 isaki slhci_root_intr_transfer,
183 1.1 isaki slhci_root_intr_start,
184 1.1 isaki slhci_root_intr_abort,
185 1.1 isaki slhci_root_intr_close,
186 1.1 isaki slhci_noop,
187 1.1 isaki slhci_root_intr_done,
188 1.1 isaki };
189 1.1 isaki
190 1.1 isaki struct usbd_pipe_methods slhci_device_ctrl_methods = {
191 1.1 isaki slhci_device_ctrl_transfer,
192 1.1 isaki slhci_device_ctrl_start,
193 1.1 isaki slhci_device_ctrl_abort,
194 1.1 isaki slhci_device_ctrl_close,
195 1.1 isaki slhci_noop,
196 1.1 isaki slhci_device_ctrl_done,
197 1.1 isaki };
198 1.1 isaki
199 1.1 isaki struct usbd_pipe_methods slhci_device_intr_methods = {
200 1.1 isaki slhci_device_intr_transfer,
201 1.1 isaki slhci_device_intr_start,
202 1.1 isaki slhci_device_intr_abort,
203 1.1 isaki slhci_device_intr_close,
204 1.1 isaki slhci_device_clear_toggle,
205 1.1 isaki slhci_device_intr_done,
206 1.1 isaki };
207 1.1 isaki
208 1.1 isaki struct usbd_pipe_methods slhci_device_isoc_methods = {
209 1.1 isaki slhci_device_isoc_transfer,
210 1.1 isaki slhci_device_isoc_start,
211 1.1 isaki slhci_device_isoc_abort,
212 1.1 isaki slhci_device_isoc_close,
213 1.1 isaki slhci_noop,
214 1.1 isaki slhci_device_isoc_done,
215 1.1 isaki };
216 1.1 isaki
217 1.1 isaki struct usbd_pipe_methods slhci_device_bulk_methods = {
218 1.1 isaki slhci_device_bulk_transfer,
219 1.1 isaki slhci_device_bulk_start,
220 1.1 isaki slhci_device_bulk_abort,
221 1.1 isaki slhci_device_bulk_close,
222 1.1 isaki slhci_noop,
223 1.1 isaki slhci_device_bulk_done,
224 1.1 isaki };
225 1.1 isaki
226 1.1 isaki struct slhci_pipe {
227 1.1 isaki struct usbd_pipe pipe;
228 1.1 isaki };
229 1.1 isaki
230 1.1 isaki
231 1.1 isaki /*
232 1.1 isaki * SL811HS Register read/write routine
233 1.1 isaki */
234 1.1 isaki static inline u_int8_t
235 1.1 isaki sl11read(struct slhci_softc *sc, int reg)
236 1.1 isaki {
237 1.1 isaki bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg);
238 1.1 isaki return bus_space_read_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA);
239 1.1 isaki }
240 1.1 isaki
241 1.1 isaki static inline void
242 1.1 isaki sl11write(struct slhci_softc *sc, int reg, u_int8_t data)
243 1.1 isaki {
244 1.1 isaki bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg);
245 1.1 isaki bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA, data);
246 1.1 isaki }
247 1.1 isaki
248 1.1 isaki static inline void
249 1.1 isaki sl11read_region(struct slhci_softc *sc, u_char *buf, int reg, int len)
250 1.1 isaki {
251 1.1 isaki int i;
252 1.1 isaki bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg);
253 1.1 isaki for (i = 0; i < len; i++)
254 1.1 isaki buf[i] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA);
255 1.1 isaki }
256 1.1 isaki
257 1.1 isaki static inline void
258 1.1 isaki sl11write_region(struct slhci_softc *sc, int reg, u_char *buf, int len)
259 1.1 isaki {
260 1.1 isaki int i;
261 1.1 isaki bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg);
262 1.1 isaki for (i = 0; i < len; i++)
263 1.1 isaki bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA, buf[i]);
264 1.1 isaki }
265 1.1 isaki
266 1.1 isaki /*
267 1.1 isaki * USB bus reset. From sl811hs_appnote.pdf, p22
268 1.1 isaki */
269 1.1 isaki static void
270 1.1 isaki sl11_reset(struct slhci_softc *sc)
271 1.1 isaki {
272 1.1 isaki u_int8_t r;
273 1.1 isaki
274 1.1 isaki DPRINTF(D_TRACE, ("%s() ", __FUNCTION__));
275 1.1 isaki r = sl11read(sc, SL11_CTRL);
276 1.1 isaki sl11write(sc, SL11_CTRL, r | SL11_CTRL_RESETENGINE);
277 1.1 isaki delay_ms(250);
278 1.1 isaki sl11write(sc, SL11_CTRL, r | SL11_CTRL_RESETENGINE | SL11_CTRL_SUSPEND);
279 1.1 isaki delay_ms(150);
280 1.1 isaki sl11write(sc, SL11_CTRL, r | SL11_CTRL_RESETENGINE);
281 1.1 isaki delay_ms(10);
282 1.1 isaki sl11write(sc, SL11_CTRL, r);
283 1.1 isaki }
284 1.1 isaki
285 1.1 isaki /*
286 1.1 isaki * Detect the speed of attached device.
287 1.1 isaki */
288 1.1 isaki static void
289 1.1 isaki sl11_speed(struct slhci_softc *sc)
290 1.1 isaki {
291 1.1 isaki u_int8_t r;
292 1.1 isaki
293 1.1 isaki sl11write(sc, SL11_ISR, 0xff);
294 1.1 isaki r = sl11read(sc, SL11_ISR);
295 1.1 isaki if ((r & SL11_ISR_RESET)) {
296 1.1 isaki DPRINTF(D_MSG, ("NC "));
297 1.1 isaki sl11write(sc, SL11_ISR, SL11_ISR_RESET);
298 1.1 isaki sc->sc_connect = 0;
299 1.1 isaki }
300 1.1 isaki
301 1.1 isaki if ((sl11read(sc, SL11_ISR) & SL11_ISR_RESET)) {
302 1.1 isaki sl11write(sc, SL11_ISR, 0xff);
303 1.1 isaki } else {
304 1.1 isaki u_int8_t pol = 0, ctrl = 0;
305 1.1 isaki
306 1.1 isaki sc->sc_connect = 1;
307 1.1 isaki if (r & SL11_ISR_DATA) {
308 1.1 isaki DPRINTF(D_MSG, ("FS "));
309 1.1 isaki pol = 0;
310 1.1 isaki ctrl = SL11_CTRL_EOF2;
311 1.1 isaki sc->sc_fullspeed = 1;
312 1.1 isaki } else {
313 1.1 isaki DPRINTF(D_MSG, ("LS "));
314 1.1 isaki pol = SL811_CSOF_POLARITY;
315 1.1 isaki ctrl = SL11_CTRL_LOWSPEED;
316 1.1 isaki sc->sc_fullspeed = 0;
317 1.1 isaki }
318 1.1 isaki sl11write(sc, SL811_CSOF, pol | SL811_CSOF_MASTER | 0x2e);
319 1.1 isaki sl11write(sc, SL11_DATA, 0xe0);
320 1.1 isaki sl11write(sc, SL11_CTRL, ctrl | SL11_CTRL_ENABLESOF);
321 1.1 isaki }
322 1.1 isaki
323 1.1 isaki sl11write(sc, SL11_E0PID, (SL11_PID_SOF << 4) + 0);
324 1.1 isaki sl11write(sc, SL11_E0DEV, 0);
325 1.1 isaki sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM);
326 1.1 isaki delay_ms(30);
327 1.1 isaki }
328 1.1 isaki
329 1.1 isaki /*
330 1.1 isaki * If detect some known controller, return the type.
331 1.1 isaki * If does not, return -1.
332 1.1 isaki */
333 1.1 isaki int
334 1.1 isaki sl811hs_find(struct slhci_softc *sc)
335 1.1 isaki {
336 1.1 isaki int rev;
337 1.1 isaki
338 1.1 isaki sc->sc_sltype = -1;
339 1.1 isaki rev = sl11read(sc, SL11_REV) >> 4;
340 1.1 isaki if (rev >= SLTYPE_SL11H && rev <= SLTYPE_SL811HS_R14)
341 1.1 isaki sc->sc_sltype = rev;
342 1.1 isaki return sc->sc_sltype;
343 1.1 isaki }
344 1.1 isaki
345 1.1 isaki /*
346 1.1 isaki * Attach SL11H/SL811HS. Return 0 if success.
347 1.1 isaki */
348 1.1 isaki int
349 1.1 isaki slhci_attach(struct slhci_softc *sc, struct device *self)
350 1.1 isaki {
351 1.1 isaki int rev;
352 1.1 isaki
353 1.1 isaki /* Detect and check the controller type */
354 1.1 isaki rev = sl811hs_find(sc);
355 1.1 isaki if (rev == -1)
356 1.1 isaki return -1;
357 1.1 isaki
358 1.1 isaki printf("%s: ScanLogic %s USB Host Controller",
359 1.1 isaki sc->sc_bus.bdev.dv_xname, sltypestr[(rev > 0)]);
360 1.1 isaki switch (rev) {
361 1.1 isaki case SLTYPE_SL11H:
362 1.1 isaki break;
363 1.1 isaki case SLTYPE_SL811HS_R12:
364 1.1 isaki printf(" (rev 1.2)");
365 1.1 isaki break;
366 1.1 isaki case SLTYPE_SL811HS_R14:
367 1.1 isaki printf(" (rev 1.4)");
368 1.1 isaki break;
369 1.1 isaki default:
370 1.1 isaki printf(" (unknown revision)");
371 1.1 isaki break;
372 1.1 isaki }
373 1.1 isaki printf("\n");
374 1.1 isaki
375 1.1 isaki /* Initialize sc */
376 1.1 isaki sc->sc_bus.usbrev = USBREV_1_1;
377 1.1 isaki sc->sc_bus.methods = &slhci_bus_methods;
378 1.1 isaki sc->sc_bus.pipe_size = sizeof(struct slhci_pipe);
379 1.1 isaki sc->sc_bus.dmatag = sc->sc_dmat;
380 1.1 isaki
381 1.1 isaki SIMPLEQ_INIT(&sc->sc_free_xfers);
382 1.1 isaki
383 1.1 isaki usb_callout_init(sc->sc_poll_handle);
384 1.1 isaki
385 1.1 isaki /* Initialize controller */
386 1.1 isaki sl11write(sc, SL811_CSOF, SL811_CSOF_MASTER | 0x2e);
387 1.1 isaki sl11write(sc, SL11_ISR, 0xff);
388 1.1 isaki
389 1.1 isaki /* Disable interrupt, then wait 40msec */
390 1.1 isaki sl11write(sc, SL11_IER, 0x00);
391 1.1 isaki delay_ms(40);
392 1.1 isaki
393 1.1 isaki /* Reset USB engine */
394 1.1 isaki sl11write(sc, SL11_CTRL, SL11_CTRL_RESETENGINE | SL11_CTRL_SUSPEND);
395 1.1 isaki delay_ms(40);
396 1.1 isaki sl11write(sc, SL11_CTRL, 0x00);
397 1.1 isaki delay_ms(10);
398 1.1 isaki
399 1.1 isaki /* USB Bus reset for GET_PORT_STATUS */
400 1.1 isaki sl11_reset(sc);
401 1.1 isaki
402 1.1 isaki /* Enable interrupt */
403 1.1 isaki sl11write(sc, SL11_IER, SL11_IER_INSERT);
404 1.1 isaki /* x68k Nereid USB controller needs it */
405 1.1 isaki if (sc->sc_enable_intr)
406 1.1 isaki sc->sc_enable_intr(sc->sc_arg, INTR_ON);
407 1.1 isaki
408 1.1 isaki #ifdef USB_DEBUG
409 1.1 isaki usbdebug = 0;
410 1.1 isaki #endif
411 1.1 isaki
412 1.1 isaki /* Attach USB devices */
413 1.1 isaki sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint);
414 1.1 isaki
415 1.1 isaki return 0;
416 1.1 isaki }
417 1.1 isaki
418 1.1 isaki int
419 1.1 isaki slhci_intr(void *arg)
420 1.1 isaki {
421 1.1 isaki struct slhci_softc *sc = arg;
422 1.1 isaki u_int8_t r;
423 1.1 isaki #ifdef SLHCI_DEBUG
424 1.1 isaki char bitbuf[256];
425 1.1 isaki #endif
426 1.1 isaki
427 1.1 isaki r = sl11read(sc, SL11_ISR);
428 1.1 isaki
429 1.1 isaki sl11write(sc, SL11_ISR, SL11_ISR_DATA | SL11_ISR_SOFTIMER);
430 1.1 isaki
431 1.1 isaki if ((r & SL11_ISR_RESET)) {
432 1.1 isaki sc->sc_flags |= SLF_RESET;
433 1.1 isaki sl11write(sc, SL11_ISR, SL11_ISR_RESET);
434 1.1 isaki }
435 1.1 isaki if ((r & SL11_ISR_INSERT)) {
436 1.1 isaki sc->sc_flags |= SLF_INSERT;
437 1.1 isaki sl11write(sc, SL11_ISR, SL11_ISR_INSERT);
438 1.1 isaki }
439 1.1 isaki
440 1.1 isaki #ifdef SLHCI_DEBUG
441 1.1 isaki bitmask_snprintf(r,
442 1.1 isaki (sl11read(sc, SL11_CTRL) & SL11_CTRL_SUSPEND)
443 1.1 isaki ? "\20\x8""D+\7RESUME\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA"
444 1.1 isaki : "\20\x8""D+\7RESET\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA",
445 1.1 isaki bitbuf, sizeof(bitbuf));
446 1.1 isaki DPRINTF(D_XFER, ("I=%s ", bitbuf));
447 1.1 isaki #endif /* SLHCI_DEBUG */
448 1.1 isaki
449 1.1 isaki return 0;
450 1.1 isaki }
451 1.1 isaki
452 1.1 isaki usbd_status
453 1.1 isaki slhci_open(usbd_pipe_handle pipe)
454 1.1 isaki {
455 1.1 isaki usbd_device_handle dev = pipe->device;
456 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)dev->bus;
457 1.1 isaki usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
458 1.1 isaki
459 1.1 isaki DPRINTF(D_TRACE, ("slhci_open(addr=%d,ep=%d,scaddr=%d)",
460 1.1 isaki dev->address, ed->bEndpointAddress, sc->sc_addr));
461 1.1 isaki
462 1.1 isaki if (dev->address == sc->sc_addr) {
463 1.1 isaki switch (ed->bEndpointAddress) {
464 1.1 isaki case USB_CONTROL_ENDPOINT:
465 1.1 isaki pipe->methods = &slhci_root_ctrl_methods;
466 1.1 isaki break;
467 1.1 isaki case UE_DIR_IN | SLHCI_INTR_ENDPT:
468 1.1 isaki pipe->methods = &slhci_root_intr_methods;
469 1.1 isaki break;
470 1.1 isaki default:
471 1.1 isaki printf("open:endpointErr!\n");
472 1.1 isaki return USBD_INVAL;
473 1.1 isaki }
474 1.1 isaki } else {
475 1.1 isaki switch (ed->bmAttributes & UE_XFERTYPE) {
476 1.1 isaki case UE_CONTROL:
477 1.1 isaki DPRINTF(D_MSG, ("control "));
478 1.1 isaki pipe->methods = &slhci_device_ctrl_methods;
479 1.1 isaki break;
480 1.1 isaki case UE_INTERRUPT:
481 1.1 isaki DPRINTF(D_MSG, ("interrupt "));
482 1.1 isaki pipe->methods = &slhci_device_intr_methods;
483 1.1 isaki break;
484 1.1 isaki case UE_ISOCHRONOUS:
485 1.1 isaki DPRINTF(D_MSG, ("isochronous "));
486 1.1 isaki pipe->methods = &slhci_device_isoc_methods;
487 1.1 isaki break;
488 1.1 isaki case UE_BULK:
489 1.1 isaki DPRINTF(D_MSG, ("bluk "));
490 1.1 isaki pipe->methods = &slhci_device_bulk_methods;
491 1.1 isaki break;
492 1.1 isaki }
493 1.1 isaki }
494 1.1 isaki return USBD_NORMAL_COMPLETION;
495 1.1 isaki }
496 1.1 isaki
497 1.1 isaki void
498 1.1 isaki slhci_softintr(void *arg)
499 1.1 isaki {
500 1.1 isaki DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
501 1.1 isaki }
502 1.1 isaki
503 1.1 isaki void
504 1.1 isaki slhci_poll(struct usbd_bus *bus)
505 1.1 isaki {
506 1.1 isaki DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
507 1.1 isaki }
508 1.1 isaki
509 1.1 isaki /*
510 1.1 isaki * Emulation of interrupt transfer for status change endpoint
511 1.1 isaki * of root hub.
512 1.1 isaki */
513 1.1 isaki void
514 1.1 isaki slhci_poll_hub(void *arg)
515 1.1 isaki {
516 1.1 isaki usbd_xfer_handle xfer = arg;
517 1.1 isaki usbd_pipe_handle pipe = xfer->pipe;
518 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
519 1.1 isaki int s;
520 1.1 isaki u_char *p;
521 1.1 isaki
522 1.1 isaki usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer);
523 1.1 isaki
524 1.1 isaki /* USB spec 11.13.3 (p.260) */
525 1.1 isaki p = KERNADDR(&xfer->dmabuf, 0);
526 1.1 isaki p[0] = 0;
527 1.1 isaki if ((sc->sc_flags & (SLF_INSERT | SLF_RESET))) {
528 1.1 isaki p[0] = 2;
529 1.1 isaki DPRINTF(D_TRACE, ("!"));
530 1.1 isaki }
531 1.1 isaki
532 1.1 isaki /* no change, return NAK */
533 1.1 isaki if (p[0] == 0)
534 1.1 isaki return;
535 1.1 isaki
536 1.1 isaki xfer->actlen = 1;
537 1.1 isaki xfer->status = USBD_NORMAL_COMPLETION;
538 1.1 isaki s = splusb();
539 1.1 isaki xfer->device->bus->intr_context++;
540 1.1 isaki usb_transfer_complete(xfer);
541 1.1 isaki xfer->device->bus->intr_context--;
542 1.1 isaki splx(s);
543 1.1 isaki }
544 1.1 isaki
545 1.1 isaki usbd_status
546 1.1 isaki slhci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size)
547 1.1 isaki {
548 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)bus;
549 1.1 isaki
550 1.1 isaki DPRINTF(D_MEM, ("SLallocm"));
551 1.1 isaki return usb_allocmem(&sc->sc_bus, size, 0, dma);
552 1.1 isaki }
553 1.1 isaki
554 1.1 isaki void
555 1.1 isaki slhci_freem(struct usbd_bus *bus, usb_dma_t *dma)
556 1.1 isaki {
557 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)bus;
558 1.1 isaki
559 1.1 isaki DPRINTF(D_MEM, ("SLfreem"));
560 1.1 isaki usb_freemem(&sc->sc_bus, dma);
561 1.1 isaki }
562 1.1 isaki
563 1.1 isaki usbd_xfer_handle
564 1.1 isaki slhci_allocx(struct usbd_bus *bus)
565 1.1 isaki {
566 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)bus;
567 1.1 isaki usbd_xfer_handle xfer;
568 1.1 isaki
569 1.1 isaki DPRINTF(D_MEM, ("SLallocx"));
570 1.1 isaki
571 1.1 isaki xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
572 1.2 isaki if (xfer) {
573 1.1 isaki SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
574 1.2 isaki #ifdef DIAGNOSTIC
575 1.2 isaki if (xfer->busy_free != XFER_FREE) {
576 1.2 isaki printf("slhci_allocx: xfer=%p not free, 0x%08x\n",
577 1.2 isaki xfer, xfer->busy_free);
578 1.2 isaki }
579 1.2 isaki #endif
580 1.2 isaki } else {
581 1.1 isaki xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
582 1.2 isaki }
583 1.1 isaki
584 1.2 isaki if (xfer) {
585 1.1 isaki memset(xfer, 0, sizeof(*xfer));
586 1.2 isaki #ifdef DIAGNOSTIC
587 1.2 isaki xfer->busy_free = XFER_BUSY;
588 1.2 isaki #endif
589 1.2 isaki }
590 1.1 isaki
591 1.1 isaki return xfer;
592 1.1 isaki }
593 1.1 isaki
594 1.1 isaki void
595 1.1 isaki slhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
596 1.1 isaki {
597 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)bus;
598 1.1 isaki
599 1.1 isaki DPRINTF(D_MEM, ("SLfreex"));
600 1.2 isaki
601 1.2 isaki #ifdef DIAGNOSTIC
602 1.2 isaki if (xfer->busy_free != XFER_BUSY) {
603 1.2 isaki printf("slhci_freex: xfer=%p not busy, 0x%08x\n",
604 1.2 isaki xfer, xfer->busy_free);
605 1.2 isaki return;
606 1.2 isaki }
607 1.2 isaki xfer->busy_free = XFER_FREE;
608 1.2 isaki #endif
609 1.1 isaki SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
610 1.1 isaki }
611 1.1 isaki
612 1.1 isaki void
613 1.1 isaki slhci_noop(usbd_pipe_handle pipe)
614 1.1 isaki {
615 1.1 isaki DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
616 1.1 isaki }
617 1.1 isaki
618 1.1 isaki /*
619 1.1 isaki * Data structures and routines to emulate the root hub.
620 1.1 isaki */
621 1.1 isaki usb_device_descriptor_t slhci_devd = {
622 1.1 isaki USB_DEVICE_DESCRIPTOR_SIZE,
623 1.1 isaki UDESC_DEVICE, /* type */
624 1.1 isaki {0x01, 0x01}, /* USB version */
625 1.1 isaki UDCLASS_HUB, /* class */
626 1.1 isaki UDSUBCLASS_HUB, /* subclass */
627 1.1 isaki 0, /* protocol */
628 1.1 isaki 64, /* max packet */
629 1.1 isaki {USB_VENDOR_SCANLOGIC & 0xff, /* vendor ID (low) */
630 1.1 isaki USB_VENDOR_SCANLOGIC >> 8 }, /* vendor ID (high) */
631 1.1 isaki {0} /* ? */, /* product ID */
632 1.1 isaki {0}, /* device */
633 1.1 isaki 1, /* index to manufacturer */
634 1.1 isaki 2, /* index to product */
635 1.1 isaki 0, /* index to serial number */
636 1.1 isaki 1 /* number of configurations */
637 1.1 isaki };
638 1.1 isaki
639 1.1 isaki usb_config_descriptor_t slhci_confd = {
640 1.1 isaki USB_CONFIG_DESCRIPTOR_SIZE,
641 1.1 isaki UDESC_CONFIG,
642 1.1 isaki {USB_CONFIG_DESCRIPTOR_SIZE +
643 1.1 isaki USB_INTERFACE_DESCRIPTOR_SIZE +
644 1.1 isaki USB_ENDPOINT_DESCRIPTOR_SIZE},
645 1.1 isaki 1, /* number of interfaces */
646 1.1 isaki 1, /* configuration value */
647 1.1 isaki 0, /* index to configuration */
648 1.1 isaki UC_SELF_POWERED, /* attributes */
649 1.1 isaki 15 /* max current is 30mA... */
650 1.1 isaki };
651 1.1 isaki
652 1.1 isaki usb_interface_descriptor_t slhci_ifcd = {
653 1.1 isaki USB_INTERFACE_DESCRIPTOR_SIZE,
654 1.1 isaki UDESC_INTERFACE,
655 1.1 isaki 0, /* interface number */
656 1.1 isaki 0, /* alternate setting */
657 1.1 isaki 1, /* number of endpoint */
658 1.1 isaki UICLASS_HUB, /* class */
659 1.1 isaki UISUBCLASS_HUB, /* subclass */
660 1.1 isaki 0, /* protocol */
661 1.1 isaki 0 /* index to interface */
662 1.1 isaki };
663 1.1 isaki
664 1.1 isaki usb_endpoint_descriptor_t slhci_endpd = {
665 1.1 isaki USB_ENDPOINT_DESCRIPTOR_SIZE,
666 1.1 isaki UDESC_ENDPOINT,
667 1.1 isaki UE_DIR_IN | SLHCI_INTR_ENDPT, /* endpoint address */
668 1.1 isaki UE_INTERRUPT, /* attributes */
669 1.1 isaki {8}, /* max packet size */
670 1.1 isaki 255 /* interval */
671 1.1 isaki };
672 1.1 isaki
673 1.1 isaki usb_hub_descriptor_t slhci_hubd = {
674 1.1 isaki USB_HUB_DESCRIPTOR_SIZE,
675 1.1 isaki UDESC_HUB,
676 1.1 isaki 1, /* number of ports */
677 1.1 isaki {UHD_PWR_INDIVIDUAL | UHD_OC_NONE, 0}, /* hub characteristics */
678 1.1 isaki 20 /* ? */, /* 5:power on to power good */
679 1.1 isaki 50, /* 6:maximum current */
680 1.1 isaki { 0x00 }, /* both ports are removable */
681 1.1 isaki { 0x00 } /* port power control mask */
682 1.1 isaki };
683 1.1 isaki
684 1.1 isaki static int
685 1.6 drochner slhci_str(usb_string_descriptor_t *p, int l, const char *s)
686 1.1 isaki {
687 1.1 isaki int i;
688 1.1 isaki
689 1.1 isaki if (l == 0)
690 1.1 isaki return 0;
691 1.1 isaki p->bLength = 2 * strlen(s) + 2;
692 1.1 isaki if (l == 1)
693 1.1 isaki return 1;
694 1.1 isaki p->bDescriptorType = UDESC_STRING;
695 1.1 isaki l -= 2;
696 1.1 isaki for (i = 0; s[i] && l > 1; i++, l -= 2)
697 1.1 isaki USETW2(p->bString[i], 0, s[i]);
698 1.1 isaki return 2 * i + 2;
699 1.1 isaki }
700 1.1 isaki
701 1.1 isaki usbd_status
702 1.1 isaki slhci_root_ctrl_transfer(usbd_xfer_handle xfer)
703 1.1 isaki {
704 1.1 isaki usbd_status error;
705 1.1 isaki
706 1.1 isaki DPRINTF(D_TRACE, ("SLRCtrans "));
707 1.1 isaki
708 1.1 isaki /* Insert last in queue */
709 1.1 isaki error = usb_insert_transfer(xfer);
710 1.1 isaki if (error) {
711 1.1 isaki DPRINTF(D_MSG, ("usb_insert_transfer returns err! "));
712 1.1 isaki return error;
713 1.1 isaki }
714 1.1 isaki
715 1.1 isaki /*
716 1.1 isaki * Pipe isn't running (otherwise error would be USBD_INPROG),
717 1.1 isaki * so start it first.
718 1.1 isaki */
719 1.1 isaki return slhci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
720 1.1 isaki }
721 1.1 isaki
722 1.1 isaki usbd_status
723 1.1 isaki slhci_root_ctrl_start(usbd_xfer_handle xfer)
724 1.1 isaki {
725 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)xfer->pipe->device->bus;
726 1.1 isaki usb_device_request_t *req;
727 1.1 isaki int len, value, index, l, s, status;
728 1.1 isaki int totlen = 0;
729 1.1 isaki void *buf = NULL;
730 1.1 isaki usb_port_status_t ps;
731 1.1 isaki usbd_status error;
732 1.1 isaki char slbuf[50];
733 1.1 isaki u_int8_t r;
734 1.1 isaki
735 1.1 isaki DPRINTF(D_TRACE, ("SLRCstart "));
736 1.1 isaki
737 1.1 isaki req = &xfer->request;
738 1.1 isaki
739 1.1 isaki len = UGETW(req->wLength);
740 1.1 isaki value = UGETW(req->wValue);
741 1.1 isaki index = UGETW(req->wIndex);
742 1.1 isaki
743 1.1 isaki if (len)
744 1.1 isaki buf = KERNADDR(&xfer->dmabuf, 0);
745 1.1 isaki
746 1.1 isaki #ifdef SLHCI_DEBUG
747 1.3 bsh if ((slhci_debug & D_TRACE))
748 1.1 isaki print_req_hub(req);
749 1.1 isaki #endif
750 1.1 isaki
751 1.1 isaki #define C(x,y) ((x) | ((y) << 8))
752 1.1 isaki switch (C(req->bRequest, req->bmRequestType)) {
753 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
754 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
755 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
756 1.1 isaki DPRINTF(D_MSG, ("UR_CLEAR_FEATURE "));
757 1.1 isaki break;
758 1.1 isaki case C(UR_GET_CONFIG, UT_READ_DEVICE):
759 1.1 isaki DPRINTF(D_MSG, ("UR_GET_CONFIG "));
760 1.1 isaki if (len > 0) {
761 1.1 isaki *(u_int8_t *)buf = sc->sc_conf;
762 1.1 isaki totlen = 1;
763 1.1 isaki }
764 1.1 isaki break;
765 1.1 isaki case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
766 1.1 isaki switch (value >> 8) {
767 1.1 isaki case UDESC_DEVICE:
768 1.1 isaki DPRINTF(D_MSG, ("UDESC_DEVICE "));
769 1.1 isaki if ((value & 0xff) != 0) {
770 1.1 isaki error = USBD_IOERROR;
771 1.1 isaki goto ret;
772 1.1 isaki }
773 1.1 isaki totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
774 1.1 isaki memcpy(buf, &slhci_devd, l);
775 1.1 isaki break;
776 1.1 isaki case UDESC_CONFIG:
777 1.1 isaki DPRINTF(D_MSG, ("UDESC_CONFIG "));
778 1.1 isaki if ((value & 0xff) != 0) {
779 1.1 isaki error = USBD_IOERROR;
780 1.1 isaki goto ret;
781 1.1 isaki }
782 1.1 isaki totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
783 1.1 isaki memcpy(buf, &slhci_confd, l);
784 1.1 isaki buf = (char *)buf + l;
785 1.1 isaki len -= l;
786 1.1 isaki
787 1.1 isaki l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
788 1.1 isaki totlen += l;
789 1.1 isaki memcpy(buf, &slhci_ifcd, l);
790 1.1 isaki buf = (char *)buf + l;
791 1.1 isaki len -= l;
792 1.1 isaki
793 1.1 isaki l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
794 1.1 isaki totlen += l;
795 1.1 isaki memcpy(buf, &slhci_endpd, l);
796 1.1 isaki break;
797 1.1 isaki case UDESC_STRING:
798 1.1 isaki DPRINTF(D_MSG, ("UDESC_STR "));
799 1.1 isaki if (len == 0)
800 1.1 isaki break;
801 1.1 isaki *(u_int8_t *)buf = 0;
802 1.1 isaki totlen = 1;
803 1.1 isaki switch (value & 0xff) {
804 1.1 isaki case 0:
805 1.1 isaki break;
806 1.1 isaki case 1: /* Vendor */
807 1.1 isaki totlen = slhci_str(buf, len, "ScanLogic");
808 1.1 isaki break;
809 1.1 isaki case 2: /* Product */
810 1.4 itojun snprintf(slbuf, sizeof(slbuf), "%s root hub",
811 1.4 itojun sltypestr[sc->sc_sltype]);
812 1.1 isaki totlen = slhci_str(buf, len, slbuf);
813 1.1 isaki break;
814 1.1 isaki default:
815 1.1 isaki printf("strerr%d ", value & 0xff);
816 1.1 isaki break;
817 1.1 isaki }
818 1.1 isaki break;
819 1.1 isaki default:
820 1.1 isaki printf("unknownGetDescriptor=%x", value);
821 1.1 isaki error = USBD_IOERROR;
822 1.1 isaki break;
823 1.1 isaki }
824 1.1 isaki break;
825 1.1 isaki case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
826 1.1 isaki /* Get Interface, 9.4.4 */
827 1.1 isaki if (len > 0) {
828 1.1 isaki *(u_int8_t *)buf = 0;
829 1.1 isaki totlen = 1;
830 1.1 isaki }
831 1.1 isaki break;
832 1.1 isaki case C(UR_GET_STATUS, UT_READ_DEVICE):
833 1.1 isaki /* Get Status from device, 9.4.5 */
834 1.1 isaki if (len > 1) {
835 1.1 isaki USETW(((usb_status_t *)buf)->wStatus, UDS_SELF_POWERED);
836 1.1 isaki totlen = 2;
837 1.1 isaki }
838 1.1 isaki break;
839 1.1 isaki case C(UR_GET_STATUS, UT_READ_INTERFACE):
840 1.1 isaki case C(UR_GET_STATUS, UT_READ_ENDPOINT):
841 1.1 isaki /* Get Status from interface, endpoint, 9.4.5 */
842 1.1 isaki if (len > 1) {
843 1.1 isaki USETW(((usb_status_t *)buf)->wStatus, 0);
844 1.1 isaki totlen = 2;
845 1.1 isaki }
846 1.1 isaki break;
847 1.1 isaki case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
848 1.1 isaki /* Set Address, 9.4.6 */
849 1.1 isaki DPRINTF(D_MSG, ("UR_SET_ADDRESS "));
850 1.1 isaki if (value >= USB_MAX_DEVICES) {
851 1.1 isaki error = USBD_IOERROR;
852 1.1 isaki goto ret;
853 1.1 isaki }
854 1.1 isaki sc->sc_addr = value;
855 1.1 isaki break;
856 1.1 isaki case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
857 1.1 isaki /* Set Configuration, 9.4.7 */
858 1.1 isaki DPRINTF(D_MSG, ("UR_SET_CONFIG "));
859 1.1 isaki if (value != 0 && value != 1) {
860 1.1 isaki error = USBD_IOERROR;
861 1.1 isaki goto ret;
862 1.1 isaki }
863 1.1 isaki sc->sc_conf = value;
864 1.1 isaki break;
865 1.1 isaki case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
866 1.1 isaki /* Set Descriptor, 9.4.8, not supported */
867 1.1 isaki DPRINTF(D_MSG, ("UR_SET_DESCRIPTOR,WRITE_DEVICE not supported\n"));
868 1.1 isaki break;
869 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
870 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
871 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
872 1.1 isaki /* Set Feature, 9.4.9, not supported */
873 1.1 isaki DPRINTF(D_MSG, ("UR_SET_FEATURE not supported\n"));
874 1.1 isaki error = USBD_IOERROR;
875 1.1 isaki break;
876 1.1 isaki case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
877 1.1 isaki /* Set Interface, 9.4.10, not supported */
878 1.1 isaki break;
879 1.1 isaki case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
880 1.1 isaki /* Synch Frame, 9.4.11, not supported */
881 1.1 isaki break;
882 1.1 isaki
883 1.1 isaki /*
884 1.1 isaki * Hub specific requests
885 1.1 isaki */
886 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
887 1.1 isaki /* Clear Hub Feature, 11.16.2.1, not supported */
888 1.1 isaki DPRINTF(D_MSG, ("ClearHubFeature not supported\n"));
889 1.1 isaki break;
890 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
891 1.1 isaki /* Clear Port Feature, 11.16.2.2 */
892 1.1 isaki if (index != 1) {
893 1.1 isaki error = USBD_IOERROR;
894 1.1 isaki goto ret;
895 1.1 isaki }
896 1.1 isaki switch (value) {
897 1.1 isaki case UHF_PORT_POWER:
898 1.1 isaki DPRINTF(D_MSG, ("POWER_OFF "));
899 1.1 isaki sc->sc_powerstat = POWER_OFF;
900 1.1 isaki /* x68k Nereid USB controller needs it */
901 1.1 isaki if (sc->sc_enable_power)
902 1.1 isaki sc->sc_enable_power(sc, sc->sc_powerstat);
903 1.1 isaki break;
904 1.1 isaki case UHF_PORT_SUSPEND:
905 1.1 isaki DPRINTF(D_MSG, ("SUSPEND "));
906 1.1 isaki sl11write(sc, SL11_CTRL,
907 1.1 isaki sl11read(sc, SL11_CTRL) & ~SL11_CTRL_SUSPEND);
908 1.1 isaki break;
909 1.1 isaki case UHF_C_PORT_CONNECTION:
910 1.1 isaki sc->sc_change &= ~UPS_C_CONNECT_STATUS;
911 1.1 isaki break;
912 1.1 isaki case UHF_C_PORT_RESET:
913 1.1 isaki sc->sc_change &= ~UPS_C_PORT_RESET;
914 1.1 isaki break;
915 1.1 isaki case UHF_PORT_ENABLE:
916 1.1 isaki break;
917 1.1 isaki case UHF_C_PORT_SUSPEND:
918 1.1 isaki case UHF_C_PORT_ENABLE:
919 1.1 isaki case UHF_C_PORT_OVER_CURRENT:
920 1.1 isaki default:
921 1.1 isaki printf("ClrPortFeatERR:value=0x%x ", value);
922 1.1 isaki error = USBD_IOERROR;
923 1.1 isaki break;
924 1.1 isaki }
925 1.1 isaki //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change));
926 1.1 isaki break;
927 1.1 isaki case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
928 1.1 isaki /* Get Bus State, 11.16.2.3, not supported */
929 1.1 isaki /* shall return a STALL... */
930 1.1 isaki break;
931 1.1 isaki case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
932 1.1 isaki /* Get Hub Descriptor, 11.16.2.4 */
933 1.1 isaki if (value != 0) {
934 1.1 isaki error = USBD_IOERROR;
935 1.1 isaki goto ret;
936 1.1 isaki }
937 1.1 isaki l = min(len, USB_HUB_DESCRIPTOR_SIZE);
938 1.1 isaki totlen = l;
939 1.1 isaki memcpy(buf, &slhci_hubd, l);
940 1.1 isaki break;
941 1.1 isaki case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
942 1.1 isaki /* Get Hub Status, 11.16.2.5 */
943 1.1 isaki DPRINTF(D_MSG, ("UR_GET_STATUS RCD"));
944 1.1 isaki if (len != 4) {
945 1.1 isaki error = USBD_IOERROR;
946 1.1 isaki goto ret;
947 1.1 isaki }
948 1.1 isaki memset(buf, 0, len);
949 1.1 isaki totlen = len;
950 1.1 isaki break;
951 1.1 isaki case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
952 1.1 isaki /* Get Port Status, 11.16.2.6 */
953 1.1 isaki if (index != 1 || len != 4) {
954 1.1 isaki printf("index=%d,len=%d ", index, len);
955 1.1 isaki error = USBD_IOERROR;
956 1.1 isaki goto ret;
957 1.1 isaki }
958 1.1 isaki /*
959 1.1 isaki * change
960 1.1 isaki * o port is always enabled.
961 1.1 isaki * o cannot detect over current.
962 1.1 isaki */
963 1.1 isaki s = splusb();
964 1.1 isaki sc->sc_change &= ~(UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET);
965 1.1 isaki if ((sc->sc_flags & SLF_INSERT)) {
966 1.1 isaki sc->sc_flags &= ~SLF_INSERT;
967 1.1 isaki sc->sc_change |= UPS_C_CONNECT_STATUS;
968 1.1 isaki }
969 1.1 isaki if ((sc->sc_flags & SLF_RESET)) {
970 1.1 isaki sc->sc_flags &= ~SLF_RESET;
971 1.1 isaki sc->sc_change |= UPS_C_PORT_RESET;
972 1.1 isaki }
973 1.1 isaki splx(s);
974 1.1 isaki /*
975 1.1 isaki * XXX It can recognize that device is detached,
976 1.1 isaki * while there is sl11_speed() here.
977 1.1 isaki */
978 1.1 isaki if (sc->sc_change)
979 1.1 isaki sl11_speed(sc);
980 1.1 isaki /*
981 1.1 isaki * status
982 1.1 isaki * o port is always enabled.
983 1.1 isaki * o cannot detect over current.
984 1.1 isaki */
985 1.1 isaki status = 0;
986 1.1 isaki if (sc->sc_connect)
987 1.1 isaki status |= UPS_CURRENT_CONNECT_STATUS | UPS_PORT_ENABLED;
988 1.1 isaki r = sl11read(sc, SL11_CTRL);
989 1.1 isaki if (r & SL11_CTRL_SUSPEND)
990 1.1 isaki status |= UPS_SUSPEND;
991 1.1 isaki if (sc->sc_powerstat)
992 1.1 isaki status |= UPS_PORT_POWER;
993 1.1 isaki if (!sc->sc_fullspeed)
994 1.1 isaki status |= UPS_LOW_SPEED;
995 1.1 isaki
996 1.1 isaki //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change));
997 1.1 isaki USETW(ps.wPortStatus, status);
998 1.1 isaki USETW(ps.wPortChange, sc->sc_change);
999 1.1 isaki l = min(len, sizeof(ps));
1000 1.1 isaki memcpy(buf, &ps, l);
1001 1.1 isaki totlen = l;
1002 1.1 isaki break;
1003 1.1 isaki case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
1004 1.1 isaki /* Set Hub Descriptor, 11.16.2.7, not supported */
1005 1.1 isaki /* STALL ? */
1006 1.1 isaki error = USBD_IOERROR;
1007 1.1 isaki break;
1008 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
1009 1.1 isaki /* Set Hub Feature, 11.16.2.8, not supported */
1010 1.1 isaki break;
1011 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
1012 1.1 isaki /* Set Port Feature, 11.16.2.9 */
1013 1.1 isaki if (index != 1) {
1014 1.1 isaki printf("index=%d ", index);
1015 1.1 isaki error = USBD_IOERROR;
1016 1.1 isaki goto ret;
1017 1.1 isaki }
1018 1.1 isaki switch (value) {
1019 1.1 isaki case UHF_PORT_RESET:
1020 1.1 isaki DPRINTF(D_MSG, ("PORT_RESET "));
1021 1.1 isaki sl11_reset(sc);
1022 1.1 isaki sl11_speed(sc);
1023 1.1 isaki sc->sc_change = 0;
1024 1.1 isaki break;
1025 1.1 isaki case UHF_PORT_POWER:
1026 1.1 isaki DPRINTF(D_MSG, ("PORT_POWER "));
1027 1.1 isaki sc->sc_powerstat = POWER_ON;
1028 1.1 isaki /* x68k Nereid USB controller needs it */
1029 1.1 isaki if (sc->sc_enable_power)
1030 1.1 isaki sc->sc_enable_power(sc, sc->sc_powerstat);
1031 1.1 isaki delay_ms(25);
1032 1.1 isaki break;
1033 1.1 isaki default:
1034 1.1 isaki printf("SetPortFeatERR=0x%x ", value);
1035 1.1 isaki error = USBD_IOERROR;
1036 1.1 isaki break;
1037 1.1 isaki }
1038 1.1 isaki break;
1039 1.1 isaki default:
1040 1.1 isaki DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ",
1041 1.1 isaki req->bRequest, req->bmRequestType));
1042 1.1 isaki error = USBD_IOERROR;
1043 1.1 isaki goto ret;
1044 1.1 isaki }
1045 1.1 isaki xfer->actlen = totlen;
1046 1.1 isaki error = USBD_NORMAL_COMPLETION;
1047 1.1 isaki ret:
1048 1.1 isaki xfer->status = error;
1049 1.1 isaki s = splusb();
1050 1.1 isaki usb_transfer_complete(xfer);
1051 1.1 isaki splx(s);
1052 1.1 isaki return USBD_IN_PROGRESS;
1053 1.1 isaki }
1054 1.1 isaki
1055 1.1 isaki void
1056 1.1 isaki slhci_root_ctrl_abort(usbd_xfer_handle xfer)
1057 1.1 isaki {
1058 1.1 isaki DPRINTF(D_TRACE, ("SLRCabort "));
1059 1.1 isaki }
1060 1.1 isaki
1061 1.1 isaki void
1062 1.1 isaki slhci_root_ctrl_close(usbd_pipe_handle pipe)
1063 1.1 isaki {
1064 1.1 isaki DPRINTF(D_TRACE, ("SLRCclose "));
1065 1.1 isaki }
1066 1.1 isaki
1067 1.1 isaki void
1068 1.1 isaki slhci_root_ctrl_done(usbd_xfer_handle xfer)
1069 1.1 isaki {
1070 1.1 isaki DPRINTF(D_TRACE, ("SLRCdone\n"));
1071 1.1 isaki }
1072 1.1 isaki
1073 1.1 isaki static usbd_status
1074 1.1 isaki slhci_root_intr_transfer(usbd_xfer_handle xfer)
1075 1.1 isaki {
1076 1.1 isaki usbd_status error;
1077 1.1 isaki
1078 1.1 isaki DPRINTF(D_TRACE, ("SLRItransfer "));
1079 1.1 isaki
1080 1.1 isaki /* Insert last in queue */
1081 1.1 isaki error = usb_insert_transfer(xfer);
1082 1.1 isaki if (error)
1083 1.1 isaki return error;
1084 1.1 isaki
1085 1.1 isaki /*
1086 1.1 isaki * Pipe isn't running (otherwise error would be USBD_INPROG),
1087 1.1 isaki * start first.
1088 1.1 isaki */
1089 1.1 isaki return slhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
1090 1.1 isaki }
1091 1.1 isaki
1092 1.1 isaki static usbd_status
1093 1.1 isaki slhci_root_intr_start(usbd_xfer_handle xfer)
1094 1.1 isaki {
1095 1.1 isaki usbd_pipe_handle pipe = xfer->pipe;
1096 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1097 1.1 isaki
1098 1.1 isaki DPRINTF(D_TRACE, ("SLRIstart "));
1099 1.1 isaki
1100 1.1 isaki sc->sc_interval = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval);
1101 1.1 isaki usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer);
1102 1.1 isaki sc->sc_intr_xfer = xfer;
1103 1.1 isaki return USBD_IN_PROGRESS;
1104 1.1 isaki }
1105 1.1 isaki
1106 1.1 isaki static void
1107 1.1 isaki slhci_root_intr_abort(usbd_xfer_handle xfer)
1108 1.1 isaki {
1109 1.1 isaki DPRINTF(D_TRACE, ("SLRIabort "));
1110 1.1 isaki }
1111 1.1 isaki
1112 1.1 isaki static void
1113 1.1 isaki slhci_root_intr_close(usbd_pipe_handle pipe)
1114 1.1 isaki {
1115 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1116 1.1 isaki
1117 1.1 isaki DPRINTF(D_TRACE, ("SLRIclose "));
1118 1.1 isaki
1119 1.1 isaki usb_uncallout(sc->sc_poll_handle, slhci_poll_hub, sc->sc_intr_xfer);
1120 1.1 isaki sc->sc_intr_xfer = NULL;
1121 1.1 isaki }
1122 1.1 isaki
1123 1.1 isaki static void
1124 1.1 isaki slhci_root_intr_done(usbd_xfer_handle xfer)
1125 1.1 isaki {
1126 1.1 isaki //DPRINTF(D_XFER, ("RIdn "));
1127 1.1 isaki }
1128 1.1 isaki
1129 1.1 isaki static usbd_status
1130 1.1 isaki slhci_device_ctrl_transfer(usbd_xfer_handle xfer)
1131 1.1 isaki {
1132 1.1 isaki usbd_status error;
1133 1.1 isaki
1134 1.1 isaki DPRINTF(D_TRACE, ("C"));
1135 1.1 isaki
1136 1.1 isaki error = usb_insert_transfer(xfer);
1137 1.1 isaki if (error)
1138 1.1 isaki return error;
1139 1.1 isaki
1140 1.1 isaki return slhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
1141 1.1 isaki }
1142 1.1 isaki
1143 1.1 isaki static usbd_status
1144 1.1 isaki slhci_device_ctrl_start(usbd_xfer_handle xfer)
1145 1.1 isaki {
1146 1.1 isaki usb_device_request_t *req = &xfer->request;
1147 1.1 isaki usbd_pipe_handle pipe = xfer->pipe;
1148 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1149 1.1 isaki usbd_status status = USBD_NORMAL_COMPLETION;
1150 1.1 isaki void *buf;
1151 1.1 isaki int pid = SL11_PID_OUT;
1152 1.1 isaki int len, actlen, size;
1153 1.1 isaki int s;
1154 1.1 isaki u_int8_t toggle = 0;
1155 1.1 isaki
1156 1.1 isaki DPRINTF(D_TRACE, ("st "));
1157 1.1 isaki #ifdef SLHCI_DEBUG
1158 1.1 isaki if ((slhci_debug & D_TRACE))
1159 1.3 bsh print_req_hub(req);
1160 1.1 isaki #endif
1161 1.1 isaki
1162 1.1 isaki /* SETUP transaction */
1163 1.1 isaki if (slhci_transaction(sc, pipe, SL11_PID_SETUP,
1164 1.1 isaki sizeof(*req), (u_char*)req, toggle) == -1) {
1165 1.1 isaki status = USBD_IOERROR;
1166 1.1 isaki goto ret;
1167 1.1 isaki }
1168 1.1 isaki toggle ^= SL11_EPCTRL_DATATOGGLE;
1169 1.1 isaki
1170 1.1 isaki /* DATA transaction */
1171 1.1 isaki actlen = 0;
1172 1.1 isaki len = UGETW(req->wLength);
1173 1.1 isaki if (len) {
1174 1.1 isaki buf = KERNADDR(&xfer->dmabuf, 0);
1175 1.1 isaki if (req->bmRequestType & UT_READ)
1176 1.1 isaki pid = SL11_PID_IN;
1177 1.1 isaki for (; actlen < len; ) {
1178 1.1 isaki size = min(len - actlen, 8/* Minimum size */);
1179 1.1 isaki if (slhci_transaction(sc, pipe, pid, size, buf, toggle) == -1)
1180 1.1 isaki break;
1181 1.1 isaki toggle ^= SL11_EPCTRL_DATATOGGLE;
1182 1.1 isaki (u_char*)buf += size;
1183 1.1 isaki actlen += size;
1184 1.1 isaki }
1185 1.1 isaki }
1186 1.1 isaki xfer->actlen = actlen;
1187 1.1 isaki
1188 1.1 isaki /* ACK (status) */
1189 1.1 isaki if (pid == SL11_PID_IN)
1190 1.1 isaki pid = SL11_PID_OUT;
1191 1.1 isaki else
1192 1.1 isaki pid = SL11_PID_IN;
1193 1.1 isaki if (slhci_transaction(sc, pipe, pid, 0, NULL, toggle) == -1)
1194 1.1 isaki status = USBD_IOERROR;
1195 1.1 isaki
1196 1.1 isaki ret:
1197 1.1 isaki xfer->status = status;
1198 1.1 isaki
1199 1.1 isaki #ifdef SLHCI_DEBUG
1200 1.1 isaki if((slhci_debug & D_TRACE) && UGETW(req->wLength) > 0){
1201 1.1 isaki int i;
1202 1.1 isaki for(i=0; i < UGETW(req->wLength); i++)
1203 1.1 isaki printf("%02x", *(unsigned char*)(KERNADDR(&xfer->dmabuf, i)));
1204 1.1 isaki printf(" ");
1205 1.1 isaki }
1206 1.1 isaki #endif
1207 1.1 isaki s = splusb();
1208 1.1 isaki usb_transfer_complete(xfer);
1209 1.1 isaki splx(s);
1210 1.1 isaki return USBD_IN_PROGRESS;
1211 1.1 isaki }
1212 1.1 isaki
1213 1.1 isaki static void
1214 1.1 isaki slhci_device_ctrl_abort(usbd_xfer_handle xfer)
1215 1.1 isaki {
1216 1.1 isaki DPRINTF(D_TRACE, ("Cab "));
1217 1.1 isaki slhci_abort_xfer(xfer, USBD_CANCELLED);
1218 1.1 isaki }
1219 1.1 isaki
1220 1.1 isaki static void
1221 1.1 isaki slhci_device_ctrl_close(usbd_pipe_handle pipe)
1222 1.1 isaki {
1223 1.1 isaki DPRINTF(D_TRACE, ("Ccl "));
1224 1.1 isaki }
1225 1.1 isaki
1226 1.1 isaki static void
1227 1.1 isaki slhci_device_ctrl_done(usbd_xfer_handle xfer)
1228 1.1 isaki {
1229 1.1 isaki DPRINTF(D_TRACE, ("Cdn "));
1230 1.1 isaki }
1231 1.1 isaki
1232 1.1 isaki static usbd_status
1233 1.1 isaki slhci_device_intr_transfer(usbd_xfer_handle xfer)
1234 1.1 isaki {
1235 1.1 isaki usbd_status error;
1236 1.1 isaki
1237 1.1 isaki DPRINTF(D_TRACE, ("INTRtrans "));
1238 1.1 isaki
1239 1.1 isaki error = usb_insert_transfer(xfer);
1240 1.1 isaki if (error)
1241 1.1 isaki return error;
1242 1.1 isaki
1243 1.1 isaki return slhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
1244 1.1 isaki }
1245 1.1 isaki
1246 1.1 isaki static usbd_status
1247 1.1 isaki slhci_device_intr_start(usbd_xfer_handle xfer)
1248 1.1 isaki {
1249 1.1 isaki usbd_pipe_handle pipe = xfer->pipe;
1250 1.1 isaki struct slhci_xfer *sx;
1251 1.1 isaki
1252 1.1 isaki DPRINTF(D_TRACE, ("INTRstart "));
1253 1.1 isaki
1254 1.1 isaki sx = malloc(sizeof(*sx), M_USB, M_NOWAIT);
1255 1.1 isaki if (sx == NULL)
1256 1.1 isaki goto reterr;
1257 1.1 isaki memset(sx, 0, sizeof(*sx));
1258 1.1 isaki sx->sx_xfer = xfer;
1259 1.1 isaki xfer->hcpriv = sx;
1260 1.1 isaki
1261 1.1 isaki /* initialize callout */
1262 1.1 isaki usb_callout_init(sx->sx_callout_t);
1263 1.5 perry usb_callout(sx->sx_callout_t,
1264 1.1 isaki MS_TO_TICKS(pipe->endpoint->edesc->bInterval),
1265 1.1 isaki slhci_poll_device, sx);
1266 1.1 isaki
1267 1.1 isaki /* ACK */
1268 1.1 isaki return USBD_IN_PROGRESS;
1269 1.1 isaki
1270 1.1 isaki reterr:
1271 1.1 isaki return USBD_IOERROR;
1272 1.1 isaki }
1273 1.1 isaki
1274 1.1 isaki static void
1275 1.1 isaki slhci_poll_device(void *arg)
1276 1.1 isaki {
1277 1.1 isaki struct slhci_xfer *sx = (struct slhci_xfer *)arg;
1278 1.1 isaki usbd_xfer_handle xfer = sx->sx_xfer;
1279 1.1 isaki usbd_pipe_handle pipe = xfer->pipe;
1280 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1281 1.1 isaki void *buf;
1282 1.1 isaki int pid;
1283 1.1 isaki int r;
1284 1.1 isaki int s;
1285 1.1 isaki
1286 1.1 isaki DPRINTF(D_TRACE, ("pldev"));
1287 1.1 isaki
1288 1.1 isaki usb_callout(sx->sx_callout_t,
1289 1.1 isaki MS_TO_TICKS(pipe->endpoint->edesc->bInterval),
1290 1.1 isaki slhci_poll_device, sx);
1291 1.1 isaki
1292 1.1 isaki /* interrupt transfer */
1293 1.1 isaki pid = (UE_GET_DIR(pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN)
1294 1.1 isaki ? SL11_PID_IN : SL11_PID_OUT;
1295 1.1 isaki buf = KERNADDR(&xfer->dmabuf, 0);
1296 1.1 isaki
1297 1.1 isaki r = slhci_transaction(sc, pipe, pid, xfer->length, buf, 0/*toggle*/);
1298 1.1 isaki if (r < 0) {
1299 1.1 isaki DPRINTF(D_MSG, ("%s error", __FUNCTION__));
1300 1.1 isaki return;
1301 1.1 isaki }
1302 1.1 isaki /* no change, return NAK */
1303 1.1 isaki if (r == 0)
1304 1.1 isaki return;
1305 1.1 isaki
1306 1.1 isaki xfer->status = USBD_NORMAL_COMPLETION;
1307 1.1 isaki s = splusb();
1308 1.1 isaki xfer->device->bus->intr_context++;
1309 1.1 isaki usb_transfer_complete(xfer);
1310 1.1 isaki xfer->device->bus->intr_context--;
1311 1.1 isaki splx(s);
1312 1.1 isaki }
1313 1.1 isaki
1314 1.1 isaki static void
1315 1.1 isaki slhci_device_intr_abort(usbd_xfer_handle xfer)
1316 1.1 isaki {
1317 1.1 isaki struct slhci_xfer *sx;
1318 1.1 isaki
1319 1.1 isaki DPRINTF(D_TRACE, ("INTRabort "));
1320 1.1 isaki
1321 1.1 isaki sx = xfer->hcpriv;
1322 1.1 isaki if (sx) {
1323 1.1 isaki usb_uncallout(sx->sx_callout_t, slhci_poll_device, sx);
1324 1.1 isaki free(sx, M_USB);
1325 1.1 isaki xfer->hcpriv = NULL;
1326 1.1 isaki } else {
1327 1.1 isaki printf("%s: sx == NULL!\n", __FUNCTION__);
1328 1.1 isaki }
1329 1.1 isaki slhci_abort_xfer(xfer, USBD_CANCELLED);
1330 1.1 isaki }
1331 1.1 isaki
1332 1.1 isaki static void
1333 1.1 isaki slhci_device_intr_close(usbd_pipe_handle pipe)
1334 1.1 isaki {
1335 1.1 isaki DPRINTF(D_TRACE, ("INTRclose "));
1336 1.1 isaki }
1337 1.1 isaki
1338 1.1 isaki static void
1339 1.1 isaki slhci_device_intr_done(usbd_xfer_handle xfer)
1340 1.1 isaki {
1341 1.1 isaki DPRINTF(D_TRACE, ("INTRdone "));
1342 1.1 isaki }
1343 1.1 isaki
1344 1.1 isaki static usbd_status
1345 1.1 isaki slhci_device_isoc_transfer(usbd_xfer_handle xfer)
1346 1.1 isaki {
1347 1.1 isaki DPRINTF(D_TRACE, ("S"));
1348 1.1 isaki return USBD_NORMAL_COMPLETION;
1349 1.1 isaki }
1350 1.1 isaki
1351 1.1 isaki static usbd_status
1352 1.1 isaki slhci_device_isoc_start(usbd_xfer_handle xfer)
1353 1.1 isaki {
1354 1.1 isaki DPRINTF(D_TRACE, ("st "));
1355 1.1 isaki return USBD_NORMAL_COMPLETION;
1356 1.1 isaki }
1357 1.1 isaki
1358 1.1 isaki static void
1359 1.1 isaki slhci_device_isoc_abort(usbd_xfer_handle xfer)
1360 1.1 isaki {
1361 1.1 isaki DPRINTF(D_TRACE, ("Sab "));
1362 1.1 isaki }
1363 1.1 isaki
1364 1.1 isaki static void
1365 1.1 isaki slhci_device_isoc_close(usbd_pipe_handle pipe)
1366 1.1 isaki {
1367 1.1 isaki DPRINTF(D_TRACE, ("Scl "));
1368 1.1 isaki }
1369 1.1 isaki
1370 1.1 isaki static void
1371 1.1 isaki slhci_device_isoc_done(usbd_xfer_handle xfer)
1372 1.1 isaki {
1373 1.1 isaki DPRINTF(D_TRACE, ("Sdn "));
1374 1.1 isaki }
1375 1.1 isaki
1376 1.1 isaki static usbd_status
1377 1.1 isaki slhci_device_bulk_transfer(usbd_xfer_handle xfer)
1378 1.1 isaki {
1379 1.1 isaki DPRINTF(D_TRACE, ("B"));
1380 1.1 isaki return USBD_NORMAL_COMPLETION;
1381 1.1 isaki }
1382 1.1 isaki
1383 1.1 isaki static usbd_status
1384 1.1 isaki slhci_device_bulk_start(usbd_xfer_handle xfer)
1385 1.1 isaki {
1386 1.1 isaki DPRINTF(D_TRACE, ("st "));
1387 1.1 isaki return USBD_NORMAL_COMPLETION;
1388 1.1 isaki }
1389 1.1 isaki
1390 1.1 isaki static void
1391 1.1 isaki slhci_device_bulk_abort(usbd_xfer_handle xfer)
1392 1.1 isaki {
1393 1.1 isaki DPRINTF(D_TRACE, ("Bab "));
1394 1.1 isaki }
1395 1.1 isaki
1396 1.1 isaki static void
1397 1.1 isaki slhci_device_bulk_close(usbd_pipe_handle pipe)
1398 1.1 isaki {
1399 1.1 isaki DPRINTF(D_TRACE, ("Bcl "));
1400 1.1 isaki }
1401 1.1 isaki
1402 1.1 isaki static void
1403 1.1 isaki slhci_device_bulk_done(usbd_xfer_handle xfer)
1404 1.1 isaki {
1405 1.1 isaki DPRINTF(D_TRACE, ("Bdn "));
1406 1.1 isaki }
1407 1.1 isaki
1408 1.1 isaki #define DATA0_RD (0x03)
1409 1.1 isaki #define DATA0_WR (0x07)
1410 1.1 isaki #define SLHCI_TIMEOUT (5000)
1411 1.1 isaki
1412 1.1 isaki /*
1413 1.1 isaki * Do a transaction.
1414 1.1 isaki * return 1 if ACK, 0 if NAK, -1 if error.
1415 1.1 isaki */
1416 1.1 isaki static int
1417 1.1 isaki slhci_transaction(struct slhci_softc *sc, usbd_pipe_handle pipe,
1418 1.1 isaki u_int8_t pid, int len, u_char *buf, u_int8_t toggle)
1419 1.1 isaki {
1420 1.1 isaki #ifdef SLHCI_DEBUG
1421 1.1 isaki char str[64];
1422 1.1 isaki int i;
1423 1.1 isaki #endif
1424 1.1 isaki int timeout;
1425 1.1 isaki int ls_via_hub = 0;
1426 1.1 isaki int pl;
1427 1.1 isaki u_int8_t isr;
1428 1.1 isaki u_int8_t result = 0;
1429 1.1 isaki u_int8_t devaddr = pipe->device->address;
1430 1.1 isaki u_int8_t endpointaddr = pipe->endpoint->edesc->bEndpointAddress;
1431 1.1 isaki u_int8_t endpoint;
1432 1.1 isaki u_int8_t cmd = DATA0_RD;
1433 1.1 isaki
1434 1.1 isaki endpoint = UE_GET_ADDR(endpointaddr);
1435 1.1 isaki DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ",
1436 1.1 isaki pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint));
1437 1.1 isaki
1438 1.1 isaki /* Set registers */
1439 1.1 isaki sl11write(sc, SL11_E0ADDR, 0x40);
1440 1.1 isaki sl11write(sc, SL11_E0LEN, len);
1441 1.1 isaki sl11write(sc, SL11_E0PID, (pid << 4) + endpoint);
1442 1.1 isaki sl11write(sc, SL11_E0DEV, devaddr);
1443 1.1 isaki
1444 1.1 isaki /* Set buffer unless PID_IN */
1445 1.1 isaki if (pid != SL11_PID_IN) {
1446 1.1 isaki if (len > 0)
1447 1.1 isaki sl11write_region(sc, 0x40, buf, len);
1448 1.1 isaki cmd = DATA0_WR;
1449 1.1 isaki }
1450 1.1 isaki
1451 1.1 isaki /* timing ? */
1452 1.1 isaki pl = (len >> 3) + 3;
1453 1.1 isaki
1454 1.1 isaki /* Low speed device via HUB */
1455 1.1 isaki /* XXX does not work... */
1456 1.1 isaki if ((sc->sc_fullspeed) && pipe->device->speed == USB_SPEED_LOW) {
1457 1.1 isaki pl = len + 16;
1458 1.1 isaki cmd |= SL11_EPCTRL_PREAMBLE;
1459 1.1 isaki
1460 1.1 isaki /*
1461 1.1 isaki * SL811HS/T rev 1.2 has a bug, when it got PID_IN
1462 1.1 isaki * from LowSpeed device via HUB.
1463 1.1 isaki */
1464 1.1 isaki if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) {
1465 1.1 isaki ls_via_hub = 1;
1466 1.1 isaki DPRINTF(D_MSG, ("LSvH "));
1467 1.1 isaki }
1468 1.1 isaki }
1469 1.1 isaki
1470 1.1 isaki /* timing ? */
1471 1.1 isaki if (sl11read(sc, SL811_CSOF) <= (u_int8_t)pl)
1472 1.1 isaki cmd |= SL11_EPCTRL_SOF;
1473 1.1 isaki
1474 1.1 isaki /* Transfer */
1475 1.1 isaki sl11write(sc, SL11_ISR, 0xff);
1476 1.1 isaki sl11write(sc, SL11_E0CTRL, cmd | toggle);
1477 1.1 isaki
1478 1.1 isaki /* Polling */
1479 1.1 isaki for (timeout = SLHCI_TIMEOUT; timeout; timeout--) {
1480 1.1 isaki isr = sl11read(sc, SL11_ISR);
1481 1.1 isaki if ((isr & SL11_ISR_USBA))
1482 1.1 isaki break;
1483 1.1 isaki }
1484 1.1 isaki
1485 1.1 isaki /* Check result status */
1486 1.1 isaki result = sl11read(sc, SL11_E0STAT);
1487 1.1 isaki if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) {
1488 1.1 isaki /* Resend PID_IN within 20usec */
1489 1.1 isaki sl11write(sc, SL11_ISR, 0xff);
1490 1.1 isaki sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM);
1491 1.1 isaki }
1492 1.1 isaki
1493 1.1 isaki sl11write(sc, SL11_ISR, 0xff);
1494 1.1 isaki
1495 1.1 isaki DPRINTF(D_XFER, ("t=%d i=%x ", SLHCI_TIMEOUT - timeout, isr));
1496 1.1 isaki #if SLHCI_DEBUG
1497 1.1 isaki bitmask_snprintf(result,
1498 1.1 isaki "\20\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK",
1499 1.1 isaki str, sizeof(str));
1500 1.1 isaki DPRINTF(D_XFER, ("STAT=%s ", str));
1501 1.1 isaki #endif
1502 1.1 isaki
1503 1.1 isaki if ((result & SL11_EPSTAT_ERROR))
1504 1.1 isaki return -1;
1505 1.1 isaki
1506 1.1 isaki if ((result & SL11_EPSTAT_NAK))
1507 1.1 isaki return 0;
1508 1.1 isaki
1509 1.1 isaki /* Read buffer if PID_IN */
1510 1.1 isaki if (pid == SL11_PID_IN && len > 0) {
1511 1.1 isaki sl11read_region(sc, buf, 0x40, len);
1512 1.1 isaki #if SLHCI_DEBUG
1513 1.1 isaki for (i = 0; i < len; i++)
1514 1.1 isaki DPRINTF(D_XFER, ("%02X ", buf[i]));
1515 1.1 isaki #endif
1516 1.1 isaki }
1517 1.1 isaki
1518 1.1 isaki return 1;
1519 1.1 isaki }
1520 1.1 isaki
1521 1.1 isaki void
1522 1.1 isaki slhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
1523 1.1 isaki {
1524 1.1 isaki xfer->status = status;
1525 1.1 isaki usb_transfer_complete(xfer);
1526 1.1 isaki }
1527 1.1 isaki
1528 1.1 isaki void
1529 1.1 isaki slhci_device_clear_toggle(usbd_pipe_handle pipe)
1530 1.1 isaki {
1531 1.1 isaki DPRINTF(D_TRACE, ("SLdevice_clear_toggle "));
1532 1.1 isaki }
1533 1.1 isaki
1534 1.1 isaki #ifdef SLHCI_DEBUG
1535 1.1 isaki void
1536 1.1 isaki print_req(usb_device_request_t *r)
1537 1.1 isaki {
1538 1.1 isaki char *xmes[]={
1539 1.1 isaki "GETSTAT",
1540 1.1 isaki "CLRFEAT",
1541 1.1 isaki "res",
1542 1.1 isaki "SETFEAT",
1543 1.1 isaki "res",
1544 1.1 isaki "SETADDR",
1545 1.1 isaki "GETDESC",
1546 1.1 isaki "SETDESC",
1547 1.1 isaki "GETCONF",
1548 1.1 isaki "SETCONF",
1549 1.1 isaki "GETIN/F",
1550 1.1 isaki "SETIN/F",
1551 1.1 isaki "SYNC_FR"
1552 1.1 isaki };
1553 1.1 isaki int req, type, value, index, len;
1554 1.1 isaki
1555 1.1 isaki req = r->bRequest;
1556 1.1 isaki type = r->bmRequestType;
1557 1.1 isaki value = UGETW(r->wValue);
1558 1.1 isaki index = UGETW(r->wIndex);
1559 1.1 isaki len = UGETW(r->wLength);
1560 1.1 isaki
1561 1.1 isaki printf("%x,%s,v=%d,i=%d,l=%d ",
1562 1.1 isaki type, xmes[req], value, index, len);
1563 1.1 isaki }
1564 1.1 isaki
1565 1.1 isaki void
1566 1.1 isaki print_req_hub(usb_device_request_t *r)
1567 1.1 isaki {
1568 1.1 isaki struct {
1569 1.1 isaki int req;
1570 1.1 isaki int type;
1571 1.1 isaki char *str;
1572 1.1 isaki } conf[] = {
1573 1.1 isaki { 1, 0x20, "ClrHubFeat" },
1574 1.1 isaki { 1, 0x23, "ClrPortFeat" },
1575 1.1 isaki { 2, 0xa3, "GetBusState" },
1576 1.1 isaki { 6, 0xa0, "GetHubDesc" },
1577 1.1 isaki { 0, 0xa0, "GetHubStat" },
1578 1.1 isaki { 0, 0xa3, "GetPortStat" },
1579 1.1 isaki { 7, 0x20, "SetHubDesc" },
1580 1.1 isaki { 3, 0x20, "SetHubFeat" },
1581 1.1 isaki { 3, 0x23, "SetPortFeat" },
1582 1.1 isaki {-1, 0, NULL},
1583 1.1 isaki };
1584 1.1 isaki int i;
1585 1.1 isaki int value, index, len;
1586 1.1 isaki
1587 1.1 isaki value = UGETW(r->wValue);
1588 1.1 isaki index = UGETW(r->wIndex);
1589 1.1 isaki len = UGETW(r->wLength);
1590 1.1 isaki for (i = 0; ; i++) {
1591 1.1 isaki if (conf[i].req == -1 )
1592 1.1 isaki return print_req(r);
1593 1.1 isaki if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) {
1594 1.1 isaki printf("%s", conf[i].str);
1595 1.1 isaki break;
1596 1.1 isaki }
1597 1.1 isaki }
1598 1.1 isaki printf(",v=%d,i=%d,l=%d ", value, index, len);
1599 1.1 isaki }
1600 1.1 isaki
1601 1.1 isaki void
1602 1.1 isaki print_dumpreg(struct slhci_softc *sc)
1603 1.1 isaki {
1604 1.1 isaki printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x,"
1605 1.1 isaki "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,",
1606 1.1 isaki sl11read(sc, 0), sl11read(sc, 1),
1607 1.1 isaki sl11read(sc, 2), sl11read(sc, 3),
1608 1.1 isaki sl11read(sc, 4), sl11read(sc, 8),
1609 1.1 isaki sl11read(sc, 9), sl11read(sc, 10),
1610 1.1 isaki sl11read(sc, 11), sl11read(sc, 12)
1611 1.1 isaki );
1612 1.1 isaki printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ",
1613 1.1 isaki sl11read(sc, 5), sl11read(sc, 6),
1614 1.1 isaki sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15)
1615 1.1 isaki );
1616 1.1 isaki }
1617 1.1 isaki
1618 1.1 isaki void
1619 1.1 isaki print_xfer(usbd_xfer_handle xfer)
1620 1.1 isaki {
1621 1.1 isaki printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,",
1622 1.1 isaki xfer->length, xfer->actlen, xfer->flags, xfer->timeout);
1623 1.1 isaki printf("request{ ");
1624 1.1 isaki print_req_hub(&xfer->request);
1625 1.1 isaki printf("} ");
1626 1.1 isaki }
1627 1.1 isaki #endif /* SLHCI_DEBUG */
1628