sl811hs.c revision 1.1 1 1.1 isaki /* $NetBSD: sl811hs.c,v 1.1 2002/08/11 13:17:53 isaki 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.1 isaki __KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.1 2002/08/11 13:17:53 isaki 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.1 isaki static int slhci_str(usb_string_descriptor_t *, int, 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.1 isaki static 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.1 isaki if (xfer)
573 1.1 isaki SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
574 1.1 isaki else
575 1.1 isaki xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
576 1.1 isaki
577 1.1 isaki if (xfer)
578 1.1 isaki memset(xfer, 0, sizeof(*xfer));
579 1.1 isaki
580 1.1 isaki return xfer;
581 1.1 isaki }
582 1.1 isaki
583 1.1 isaki void
584 1.1 isaki slhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
585 1.1 isaki {
586 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)bus;
587 1.1 isaki
588 1.1 isaki DPRINTF(D_MEM, ("SLfreex"));
589 1.1 isaki SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
590 1.1 isaki }
591 1.1 isaki
592 1.1 isaki void
593 1.1 isaki slhci_noop(usbd_pipe_handle pipe)
594 1.1 isaki {
595 1.1 isaki DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
596 1.1 isaki }
597 1.1 isaki
598 1.1 isaki /*
599 1.1 isaki * Data structures and routines to emulate the root hub.
600 1.1 isaki */
601 1.1 isaki usb_device_descriptor_t slhci_devd = {
602 1.1 isaki USB_DEVICE_DESCRIPTOR_SIZE,
603 1.1 isaki UDESC_DEVICE, /* type */
604 1.1 isaki {0x01, 0x01}, /* USB version */
605 1.1 isaki UDCLASS_HUB, /* class */
606 1.1 isaki UDSUBCLASS_HUB, /* subclass */
607 1.1 isaki 0, /* protocol */
608 1.1 isaki 64, /* max packet */
609 1.1 isaki {USB_VENDOR_SCANLOGIC & 0xff, /* vendor ID (low) */
610 1.1 isaki USB_VENDOR_SCANLOGIC >> 8 }, /* vendor ID (high) */
611 1.1 isaki {0} /* ? */, /* product ID */
612 1.1 isaki {0}, /* device */
613 1.1 isaki 1, /* index to manufacturer */
614 1.1 isaki 2, /* index to product */
615 1.1 isaki 0, /* index to serial number */
616 1.1 isaki 1 /* number of configurations */
617 1.1 isaki };
618 1.1 isaki
619 1.1 isaki usb_config_descriptor_t slhci_confd = {
620 1.1 isaki USB_CONFIG_DESCRIPTOR_SIZE,
621 1.1 isaki UDESC_CONFIG,
622 1.1 isaki {USB_CONFIG_DESCRIPTOR_SIZE +
623 1.1 isaki USB_INTERFACE_DESCRIPTOR_SIZE +
624 1.1 isaki USB_ENDPOINT_DESCRIPTOR_SIZE},
625 1.1 isaki 1, /* number of interfaces */
626 1.1 isaki 1, /* configuration value */
627 1.1 isaki 0, /* index to configuration */
628 1.1 isaki UC_SELF_POWERED, /* attributes */
629 1.1 isaki 15 /* max current is 30mA... */
630 1.1 isaki };
631 1.1 isaki
632 1.1 isaki usb_interface_descriptor_t slhci_ifcd = {
633 1.1 isaki USB_INTERFACE_DESCRIPTOR_SIZE,
634 1.1 isaki UDESC_INTERFACE,
635 1.1 isaki 0, /* interface number */
636 1.1 isaki 0, /* alternate setting */
637 1.1 isaki 1, /* number of endpoint */
638 1.1 isaki UICLASS_HUB, /* class */
639 1.1 isaki UISUBCLASS_HUB, /* subclass */
640 1.1 isaki 0, /* protocol */
641 1.1 isaki 0 /* index to interface */
642 1.1 isaki };
643 1.1 isaki
644 1.1 isaki usb_endpoint_descriptor_t slhci_endpd = {
645 1.1 isaki USB_ENDPOINT_DESCRIPTOR_SIZE,
646 1.1 isaki UDESC_ENDPOINT,
647 1.1 isaki UE_DIR_IN | SLHCI_INTR_ENDPT, /* endpoint address */
648 1.1 isaki UE_INTERRUPT, /* attributes */
649 1.1 isaki {8}, /* max packet size */
650 1.1 isaki 255 /* interval */
651 1.1 isaki };
652 1.1 isaki
653 1.1 isaki usb_hub_descriptor_t slhci_hubd = {
654 1.1 isaki USB_HUB_DESCRIPTOR_SIZE,
655 1.1 isaki UDESC_HUB,
656 1.1 isaki 1, /* number of ports */
657 1.1 isaki {UHD_PWR_INDIVIDUAL | UHD_OC_NONE, 0}, /* hub characteristics */
658 1.1 isaki 20 /* ? */, /* 5:power on to power good */
659 1.1 isaki 50, /* 6:maximum current */
660 1.1 isaki { 0x00 }, /* both ports are removable */
661 1.1 isaki { 0x00 } /* port power control mask */
662 1.1 isaki };
663 1.1 isaki
664 1.1 isaki static int
665 1.1 isaki slhci_str(usb_string_descriptor_t *p, int l, char *s)
666 1.1 isaki {
667 1.1 isaki int i;
668 1.1 isaki
669 1.1 isaki if (l == 0)
670 1.1 isaki return 0;
671 1.1 isaki p->bLength = 2 * strlen(s) + 2;
672 1.1 isaki if (l == 1)
673 1.1 isaki return 1;
674 1.1 isaki p->bDescriptorType = UDESC_STRING;
675 1.1 isaki l -= 2;
676 1.1 isaki for (i = 0; s[i] && l > 1; i++, l -= 2)
677 1.1 isaki USETW2(p->bString[i], 0, s[i]);
678 1.1 isaki return 2 * i + 2;
679 1.1 isaki }
680 1.1 isaki
681 1.1 isaki usbd_status
682 1.1 isaki slhci_root_ctrl_transfer(usbd_xfer_handle xfer)
683 1.1 isaki {
684 1.1 isaki usbd_status error;
685 1.1 isaki
686 1.1 isaki DPRINTF(D_TRACE, ("SLRCtrans "));
687 1.1 isaki
688 1.1 isaki /* Insert last in queue */
689 1.1 isaki error = usb_insert_transfer(xfer);
690 1.1 isaki if (error) {
691 1.1 isaki DPRINTF(D_MSG, ("usb_insert_transfer returns err! "));
692 1.1 isaki return error;
693 1.1 isaki }
694 1.1 isaki
695 1.1 isaki /*
696 1.1 isaki * Pipe isn't running (otherwise error would be USBD_INPROG),
697 1.1 isaki * so start it first.
698 1.1 isaki */
699 1.1 isaki return slhci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
700 1.1 isaki }
701 1.1 isaki
702 1.1 isaki usbd_status
703 1.1 isaki slhci_root_ctrl_start(usbd_xfer_handle xfer)
704 1.1 isaki {
705 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)xfer->pipe->device->bus;
706 1.1 isaki usb_device_request_t *req;
707 1.1 isaki int len, value, index, l, s, status;
708 1.1 isaki int totlen = 0;
709 1.1 isaki void *buf = NULL;
710 1.1 isaki usb_port_status_t ps;
711 1.1 isaki usbd_status error;
712 1.1 isaki char slbuf[50];
713 1.1 isaki u_int8_t r;
714 1.1 isaki
715 1.1 isaki DPRINTF(D_TRACE, ("SLRCstart "));
716 1.1 isaki
717 1.1 isaki req = &xfer->request;
718 1.1 isaki
719 1.1 isaki len = UGETW(req->wLength);
720 1.1 isaki value = UGETW(req->wValue);
721 1.1 isaki index = UGETW(req->wIndex);
722 1.1 isaki
723 1.1 isaki if (len)
724 1.1 isaki buf = KERNADDR(&xfer->dmabuf, 0);
725 1.1 isaki
726 1.1 isaki #ifdef SLHCI_DEBUG
727 1.1 isaki if ((slhci_debud & D_TRACE))
728 1.1 isaki print_req_hub(req);
729 1.1 isaki #endif
730 1.1 isaki
731 1.1 isaki #define C(x,y) ((x) | ((y) << 8))
732 1.1 isaki switch (C(req->bRequest, req->bmRequestType)) {
733 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
734 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
735 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
736 1.1 isaki DPRINTF(D_MSG, ("UR_CLEAR_FEATURE "));
737 1.1 isaki break;
738 1.1 isaki case C(UR_GET_CONFIG, UT_READ_DEVICE):
739 1.1 isaki DPRINTF(D_MSG, ("UR_GET_CONFIG "));
740 1.1 isaki if (len > 0) {
741 1.1 isaki *(u_int8_t *)buf = sc->sc_conf;
742 1.1 isaki totlen = 1;
743 1.1 isaki }
744 1.1 isaki break;
745 1.1 isaki case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
746 1.1 isaki switch (value >> 8) {
747 1.1 isaki case UDESC_DEVICE:
748 1.1 isaki DPRINTF(D_MSG, ("UDESC_DEVICE "));
749 1.1 isaki if ((value & 0xff) != 0) {
750 1.1 isaki error = USBD_IOERROR;
751 1.1 isaki goto ret;
752 1.1 isaki }
753 1.1 isaki totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
754 1.1 isaki memcpy(buf, &slhci_devd, l);
755 1.1 isaki break;
756 1.1 isaki case UDESC_CONFIG:
757 1.1 isaki DPRINTF(D_MSG, ("UDESC_CONFIG "));
758 1.1 isaki if ((value & 0xff) != 0) {
759 1.1 isaki error = USBD_IOERROR;
760 1.1 isaki goto ret;
761 1.1 isaki }
762 1.1 isaki totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
763 1.1 isaki memcpy(buf, &slhci_confd, l);
764 1.1 isaki buf = (char *)buf + l;
765 1.1 isaki len -= l;
766 1.1 isaki
767 1.1 isaki l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
768 1.1 isaki totlen += l;
769 1.1 isaki memcpy(buf, &slhci_ifcd, l);
770 1.1 isaki buf = (char *)buf + l;
771 1.1 isaki len -= l;
772 1.1 isaki
773 1.1 isaki l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
774 1.1 isaki totlen += l;
775 1.1 isaki memcpy(buf, &slhci_endpd, l);
776 1.1 isaki break;
777 1.1 isaki case UDESC_STRING:
778 1.1 isaki DPRINTF(D_MSG, ("UDESC_STR "));
779 1.1 isaki if (len == 0)
780 1.1 isaki break;
781 1.1 isaki *(u_int8_t *)buf = 0;
782 1.1 isaki totlen = 1;
783 1.1 isaki switch (value & 0xff) {
784 1.1 isaki case 0:
785 1.1 isaki break;
786 1.1 isaki case 1: /* Vendor */
787 1.1 isaki totlen = slhci_str(buf, len, "ScanLogic");
788 1.1 isaki break;
789 1.1 isaki case 2: /* Product */
790 1.1 isaki sprintf(slbuf, "%s root hub", sltypestr[sc->sc_sltype]);
791 1.1 isaki totlen = slhci_str(buf, len, slbuf);
792 1.1 isaki break;
793 1.1 isaki default:
794 1.1 isaki printf("strerr%d ", value & 0xff);
795 1.1 isaki break;
796 1.1 isaki }
797 1.1 isaki break;
798 1.1 isaki default:
799 1.1 isaki printf("unknownGetDescriptor=%x", value);
800 1.1 isaki error = USBD_IOERROR;
801 1.1 isaki break;
802 1.1 isaki }
803 1.1 isaki break;
804 1.1 isaki case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
805 1.1 isaki /* Get Interface, 9.4.4 */
806 1.1 isaki if (len > 0) {
807 1.1 isaki *(u_int8_t *)buf = 0;
808 1.1 isaki totlen = 1;
809 1.1 isaki }
810 1.1 isaki break;
811 1.1 isaki case C(UR_GET_STATUS, UT_READ_DEVICE):
812 1.1 isaki /* Get Status from device, 9.4.5 */
813 1.1 isaki if (len > 1) {
814 1.1 isaki USETW(((usb_status_t *)buf)->wStatus, UDS_SELF_POWERED);
815 1.1 isaki totlen = 2;
816 1.1 isaki }
817 1.1 isaki break;
818 1.1 isaki case C(UR_GET_STATUS, UT_READ_INTERFACE):
819 1.1 isaki case C(UR_GET_STATUS, UT_READ_ENDPOINT):
820 1.1 isaki /* Get Status from interface, endpoint, 9.4.5 */
821 1.1 isaki if (len > 1) {
822 1.1 isaki USETW(((usb_status_t *)buf)->wStatus, 0);
823 1.1 isaki totlen = 2;
824 1.1 isaki }
825 1.1 isaki break;
826 1.1 isaki case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
827 1.1 isaki /* Set Address, 9.4.6 */
828 1.1 isaki DPRINTF(D_MSG, ("UR_SET_ADDRESS "));
829 1.1 isaki if (value >= USB_MAX_DEVICES) {
830 1.1 isaki error = USBD_IOERROR;
831 1.1 isaki goto ret;
832 1.1 isaki }
833 1.1 isaki sc->sc_addr = value;
834 1.1 isaki break;
835 1.1 isaki case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
836 1.1 isaki /* Set Configuration, 9.4.7 */
837 1.1 isaki DPRINTF(D_MSG, ("UR_SET_CONFIG "));
838 1.1 isaki if (value != 0 && value != 1) {
839 1.1 isaki error = USBD_IOERROR;
840 1.1 isaki goto ret;
841 1.1 isaki }
842 1.1 isaki sc->sc_conf = value;
843 1.1 isaki break;
844 1.1 isaki case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
845 1.1 isaki /* Set Descriptor, 9.4.8, not supported */
846 1.1 isaki DPRINTF(D_MSG, ("UR_SET_DESCRIPTOR,WRITE_DEVICE not supported\n"));
847 1.1 isaki break;
848 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
849 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
850 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
851 1.1 isaki /* Set Feature, 9.4.9, not supported */
852 1.1 isaki DPRINTF(D_MSG, ("UR_SET_FEATURE not supported\n"));
853 1.1 isaki error = USBD_IOERROR;
854 1.1 isaki break;
855 1.1 isaki case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
856 1.1 isaki /* Set Interface, 9.4.10, not supported */
857 1.1 isaki break;
858 1.1 isaki case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
859 1.1 isaki /* Synch Frame, 9.4.11, not supported */
860 1.1 isaki break;
861 1.1 isaki
862 1.1 isaki /*
863 1.1 isaki * Hub specific requests
864 1.1 isaki */
865 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
866 1.1 isaki /* Clear Hub Feature, 11.16.2.1, not supported */
867 1.1 isaki DPRINTF(D_MSG, ("ClearHubFeature not supported\n"));
868 1.1 isaki break;
869 1.1 isaki case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
870 1.1 isaki /* Clear Port Feature, 11.16.2.2 */
871 1.1 isaki if (index != 1) {
872 1.1 isaki error = USBD_IOERROR;
873 1.1 isaki goto ret;
874 1.1 isaki }
875 1.1 isaki switch (value) {
876 1.1 isaki case UHF_PORT_POWER:
877 1.1 isaki DPRINTF(D_MSG, ("POWER_OFF "));
878 1.1 isaki sc->sc_powerstat = POWER_OFF;
879 1.1 isaki /* x68k Nereid USB controller needs it */
880 1.1 isaki if (sc->sc_enable_power)
881 1.1 isaki sc->sc_enable_power(sc, sc->sc_powerstat);
882 1.1 isaki break;
883 1.1 isaki case UHF_PORT_SUSPEND:
884 1.1 isaki DPRINTF(D_MSG, ("SUSPEND "));
885 1.1 isaki sl11write(sc, SL11_CTRL,
886 1.1 isaki sl11read(sc, SL11_CTRL) & ~SL11_CTRL_SUSPEND);
887 1.1 isaki break;
888 1.1 isaki case UHF_C_PORT_CONNECTION:
889 1.1 isaki sc->sc_change &= ~UPS_C_CONNECT_STATUS;
890 1.1 isaki break;
891 1.1 isaki case UHF_C_PORT_RESET:
892 1.1 isaki sc->sc_change &= ~UPS_C_PORT_RESET;
893 1.1 isaki break;
894 1.1 isaki case UHF_PORT_ENABLE:
895 1.1 isaki break;
896 1.1 isaki case UHF_C_PORT_SUSPEND:
897 1.1 isaki case UHF_C_PORT_ENABLE:
898 1.1 isaki case UHF_C_PORT_OVER_CURRENT:
899 1.1 isaki default:
900 1.1 isaki printf("ClrPortFeatERR:value=0x%x ", value);
901 1.1 isaki error = USBD_IOERROR;
902 1.1 isaki break;
903 1.1 isaki }
904 1.1 isaki //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change));
905 1.1 isaki break;
906 1.1 isaki case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
907 1.1 isaki /* Get Bus State, 11.16.2.3, not supported */
908 1.1 isaki /* shall return a STALL... */
909 1.1 isaki break;
910 1.1 isaki case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
911 1.1 isaki /* Get Hub Descriptor, 11.16.2.4 */
912 1.1 isaki if (value != 0) {
913 1.1 isaki error = USBD_IOERROR;
914 1.1 isaki goto ret;
915 1.1 isaki }
916 1.1 isaki l = min(len, USB_HUB_DESCRIPTOR_SIZE);
917 1.1 isaki totlen = l;
918 1.1 isaki memcpy(buf, &slhci_hubd, l);
919 1.1 isaki break;
920 1.1 isaki case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
921 1.1 isaki /* Get Hub Status, 11.16.2.5 */
922 1.1 isaki DPRINTF(D_MSG, ("UR_GET_STATUS RCD"));
923 1.1 isaki if (len != 4) {
924 1.1 isaki error = USBD_IOERROR;
925 1.1 isaki goto ret;
926 1.1 isaki }
927 1.1 isaki memset(buf, 0, len);
928 1.1 isaki totlen = len;
929 1.1 isaki break;
930 1.1 isaki case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
931 1.1 isaki /* Get Port Status, 11.16.2.6 */
932 1.1 isaki if (index != 1 || len != 4) {
933 1.1 isaki printf("index=%d,len=%d ", index, len);
934 1.1 isaki error = USBD_IOERROR;
935 1.1 isaki goto ret;
936 1.1 isaki }
937 1.1 isaki /*
938 1.1 isaki * change
939 1.1 isaki * o port is always enabled.
940 1.1 isaki * o cannot detect over current.
941 1.1 isaki */
942 1.1 isaki s = splusb();
943 1.1 isaki sc->sc_change &= ~(UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET);
944 1.1 isaki if ((sc->sc_flags & SLF_INSERT)) {
945 1.1 isaki sc->sc_flags &= ~SLF_INSERT;
946 1.1 isaki sc->sc_change |= UPS_C_CONNECT_STATUS;
947 1.1 isaki }
948 1.1 isaki if ((sc->sc_flags & SLF_RESET)) {
949 1.1 isaki sc->sc_flags &= ~SLF_RESET;
950 1.1 isaki sc->sc_change |= UPS_C_PORT_RESET;
951 1.1 isaki }
952 1.1 isaki splx(s);
953 1.1 isaki /*
954 1.1 isaki * XXX It can recognize that device is detached,
955 1.1 isaki * while there is sl11_speed() here.
956 1.1 isaki */
957 1.1 isaki if (sc->sc_change)
958 1.1 isaki sl11_speed(sc);
959 1.1 isaki /*
960 1.1 isaki * status
961 1.1 isaki * o port is always enabled.
962 1.1 isaki * o cannot detect over current.
963 1.1 isaki */
964 1.1 isaki status = 0;
965 1.1 isaki if (sc->sc_connect)
966 1.1 isaki status |= UPS_CURRENT_CONNECT_STATUS | UPS_PORT_ENABLED;
967 1.1 isaki r = sl11read(sc, SL11_CTRL);
968 1.1 isaki if (r & SL11_CTRL_SUSPEND)
969 1.1 isaki status |= UPS_SUSPEND;
970 1.1 isaki if (sc->sc_powerstat)
971 1.1 isaki status |= UPS_PORT_POWER;
972 1.1 isaki if (!sc->sc_fullspeed)
973 1.1 isaki status |= UPS_LOW_SPEED;
974 1.1 isaki
975 1.1 isaki //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change));
976 1.1 isaki USETW(ps.wPortStatus, status);
977 1.1 isaki USETW(ps.wPortChange, sc->sc_change);
978 1.1 isaki l = min(len, sizeof(ps));
979 1.1 isaki memcpy(buf, &ps, l);
980 1.1 isaki totlen = l;
981 1.1 isaki break;
982 1.1 isaki case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
983 1.1 isaki /* Set Hub Descriptor, 11.16.2.7, not supported */
984 1.1 isaki /* STALL ? */
985 1.1 isaki error = USBD_IOERROR;
986 1.1 isaki break;
987 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
988 1.1 isaki /* Set Hub Feature, 11.16.2.8, not supported */
989 1.1 isaki break;
990 1.1 isaki case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
991 1.1 isaki /* Set Port Feature, 11.16.2.9 */
992 1.1 isaki if (index != 1) {
993 1.1 isaki printf("index=%d ", index);
994 1.1 isaki error = USBD_IOERROR;
995 1.1 isaki goto ret;
996 1.1 isaki }
997 1.1 isaki switch (value) {
998 1.1 isaki case UHF_PORT_RESET:
999 1.1 isaki DPRINTF(D_MSG, ("PORT_RESET "));
1000 1.1 isaki sl11_reset(sc);
1001 1.1 isaki sl11_speed(sc);
1002 1.1 isaki sc->sc_change = 0;
1003 1.1 isaki break;
1004 1.1 isaki case UHF_PORT_POWER:
1005 1.1 isaki DPRINTF(D_MSG, ("PORT_POWER "));
1006 1.1 isaki sc->sc_powerstat = POWER_ON;
1007 1.1 isaki /* x68k Nereid USB controller needs it */
1008 1.1 isaki if (sc->sc_enable_power)
1009 1.1 isaki sc->sc_enable_power(sc, sc->sc_powerstat);
1010 1.1 isaki delay_ms(25);
1011 1.1 isaki break;
1012 1.1 isaki default:
1013 1.1 isaki printf("SetPortFeatERR=0x%x ", value);
1014 1.1 isaki error = USBD_IOERROR;
1015 1.1 isaki break;
1016 1.1 isaki }
1017 1.1 isaki break;
1018 1.1 isaki default:
1019 1.1 isaki DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ",
1020 1.1 isaki req->bRequest, req->bmRequestType));
1021 1.1 isaki error = USBD_IOERROR;
1022 1.1 isaki goto ret;
1023 1.1 isaki }
1024 1.1 isaki xfer->actlen = totlen;
1025 1.1 isaki error = USBD_NORMAL_COMPLETION;
1026 1.1 isaki ret:
1027 1.1 isaki xfer->status = error;
1028 1.1 isaki s = splusb();
1029 1.1 isaki usb_transfer_complete(xfer);
1030 1.1 isaki splx(s);
1031 1.1 isaki return USBD_IN_PROGRESS;
1032 1.1 isaki }
1033 1.1 isaki
1034 1.1 isaki void
1035 1.1 isaki slhci_root_ctrl_abort(usbd_xfer_handle xfer)
1036 1.1 isaki {
1037 1.1 isaki DPRINTF(D_TRACE, ("SLRCabort "));
1038 1.1 isaki }
1039 1.1 isaki
1040 1.1 isaki void
1041 1.1 isaki slhci_root_ctrl_close(usbd_pipe_handle pipe)
1042 1.1 isaki {
1043 1.1 isaki DPRINTF(D_TRACE, ("SLRCclose "));
1044 1.1 isaki }
1045 1.1 isaki
1046 1.1 isaki void
1047 1.1 isaki slhci_root_ctrl_done(usbd_xfer_handle xfer)
1048 1.1 isaki {
1049 1.1 isaki DPRINTF(D_TRACE, ("SLRCdone\n"));
1050 1.1 isaki }
1051 1.1 isaki
1052 1.1 isaki static usbd_status
1053 1.1 isaki slhci_root_intr_transfer(usbd_xfer_handle xfer)
1054 1.1 isaki {
1055 1.1 isaki usbd_status error;
1056 1.1 isaki
1057 1.1 isaki DPRINTF(D_TRACE, ("SLRItransfer "));
1058 1.1 isaki
1059 1.1 isaki /* Insert last in queue */
1060 1.1 isaki error = usb_insert_transfer(xfer);
1061 1.1 isaki if (error)
1062 1.1 isaki return error;
1063 1.1 isaki
1064 1.1 isaki /*
1065 1.1 isaki * Pipe isn't running (otherwise error would be USBD_INPROG),
1066 1.1 isaki * start first.
1067 1.1 isaki */
1068 1.1 isaki return slhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
1069 1.1 isaki }
1070 1.1 isaki
1071 1.1 isaki static usbd_status
1072 1.1 isaki slhci_root_intr_start(usbd_xfer_handle xfer)
1073 1.1 isaki {
1074 1.1 isaki usbd_pipe_handle pipe = xfer->pipe;
1075 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1076 1.1 isaki
1077 1.1 isaki DPRINTF(D_TRACE, ("SLRIstart "));
1078 1.1 isaki
1079 1.1 isaki sc->sc_interval = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval);
1080 1.1 isaki usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer);
1081 1.1 isaki sc->sc_intr_xfer = xfer;
1082 1.1 isaki return USBD_IN_PROGRESS;
1083 1.1 isaki }
1084 1.1 isaki
1085 1.1 isaki static void
1086 1.1 isaki slhci_root_intr_abort(usbd_xfer_handle xfer)
1087 1.1 isaki {
1088 1.1 isaki DPRINTF(D_TRACE, ("SLRIabort "));
1089 1.1 isaki }
1090 1.1 isaki
1091 1.1 isaki static void
1092 1.1 isaki slhci_root_intr_close(usbd_pipe_handle pipe)
1093 1.1 isaki {
1094 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1095 1.1 isaki
1096 1.1 isaki DPRINTF(D_TRACE, ("SLRIclose "));
1097 1.1 isaki
1098 1.1 isaki usb_uncallout(sc->sc_poll_handle, slhci_poll_hub, sc->sc_intr_xfer);
1099 1.1 isaki sc->sc_intr_xfer = NULL;
1100 1.1 isaki }
1101 1.1 isaki
1102 1.1 isaki static void
1103 1.1 isaki slhci_root_intr_done(usbd_xfer_handle xfer)
1104 1.1 isaki {
1105 1.1 isaki //DPRINTF(D_XFER, ("RIdn "));
1106 1.1 isaki }
1107 1.1 isaki
1108 1.1 isaki static usbd_status
1109 1.1 isaki slhci_device_ctrl_transfer(usbd_xfer_handle xfer)
1110 1.1 isaki {
1111 1.1 isaki usbd_status error;
1112 1.1 isaki
1113 1.1 isaki DPRINTF(D_TRACE, ("C"));
1114 1.1 isaki
1115 1.1 isaki error = usb_insert_transfer(xfer);
1116 1.1 isaki if (error)
1117 1.1 isaki return error;
1118 1.1 isaki
1119 1.1 isaki return slhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
1120 1.1 isaki }
1121 1.1 isaki
1122 1.1 isaki static usbd_status
1123 1.1 isaki slhci_device_ctrl_start(usbd_xfer_handle xfer)
1124 1.1 isaki {
1125 1.1 isaki usb_device_request_t *req = &xfer->request;
1126 1.1 isaki usbd_pipe_handle pipe = xfer->pipe;
1127 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1128 1.1 isaki usbd_status status = USBD_NORMAL_COMPLETION;
1129 1.1 isaki void *buf;
1130 1.1 isaki int pid = SL11_PID_OUT;
1131 1.1 isaki int len, actlen, size;
1132 1.1 isaki int s;
1133 1.1 isaki u_int8_t toggle = 0;
1134 1.1 isaki
1135 1.1 isaki DPRINTF(D_TRACE, ("st "));
1136 1.1 isaki #ifdef SLHCI_DEBUG
1137 1.1 isaki if ((slhci_debug & D_TRACE))
1138 1.1 isaki print_req_hub(req));
1139 1.1 isaki #endif
1140 1.1 isaki
1141 1.1 isaki /* SETUP transaction */
1142 1.1 isaki if (slhci_transaction(sc, pipe, SL11_PID_SETUP,
1143 1.1 isaki sizeof(*req), (u_char*)req, toggle) == -1) {
1144 1.1 isaki status = USBD_IOERROR;
1145 1.1 isaki goto ret;
1146 1.1 isaki }
1147 1.1 isaki toggle ^= SL11_EPCTRL_DATATOGGLE;
1148 1.1 isaki
1149 1.1 isaki /* DATA transaction */
1150 1.1 isaki actlen = 0;
1151 1.1 isaki len = UGETW(req->wLength);
1152 1.1 isaki if (len) {
1153 1.1 isaki buf = KERNADDR(&xfer->dmabuf, 0);
1154 1.1 isaki if (req->bmRequestType & UT_READ)
1155 1.1 isaki pid = SL11_PID_IN;
1156 1.1 isaki for (; actlen < len; ) {
1157 1.1 isaki size = min(len - actlen, 8/* Minimum size */);
1158 1.1 isaki if (slhci_transaction(sc, pipe, pid, size, buf, toggle) == -1)
1159 1.1 isaki break;
1160 1.1 isaki toggle ^= SL11_EPCTRL_DATATOGGLE;
1161 1.1 isaki (u_char*)buf += size;
1162 1.1 isaki actlen += size;
1163 1.1 isaki }
1164 1.1 isaki }
1165 1.1 isaki xfer->actlen = actlen;
1166 1.1 isaki
1167 1.1 isaki /* ACK (status) */
1168 1.1 isaki if (pid == SL11_PID_IN)
1169 1.1 isaki pid = SL11_PID_OUT;
1170 1.1 isaki else
1171 1.1 isaki pid = SL11_PID_IN;
1172 1.1 isaki if (slhci_transaction(sc, pipe, pid, 0, NULL, toggle) == -1)
1173 1.1 isaki status = USBD_IOERROR;
1174 1.1 isaki
1175 1.1 isaki ret:
1176 1.1 isaki xfer->status = status;
1177 1.1 isaki
1178 1.1 isaki #ifdef SLHCI_DEBUG
1179 1.1 isaki if((slhci_debug & D_TRACE) && UGETW(req->wLength) > 0){
1180 1.1 isaki int i;
1181 1.1 isaki for(i=0; i < UGETW(req->wLength); i++)
1182 1.1 isaki printf("%02x", *(unsigned char*)(KERNADDR(&xfer->dmabuf, i)));
1183 1.1 isaki printf(" ");
1184 1.1 isaki }
1185 1.1 isaki #endif
1186 1.1 isaki s = splusb();
1187 1.1 isaki usb_transfer_complete(xfer);
1188 1.1 isaki splx(s);
1189 1.1 isaki return USBD_IN_PROGRESS;
1190 1.1 isaki }
1191 1.1 isaki
1192 1.1 isaki static void
1193 1.1 isaki slhci_device_ctrl_abort(usbd_xfer_handle xfer)
1194 1.1 isaki {
1195 1.1 isaki DPRINTF(D_TRACE, ("Cab "));
1196 1.1 isaki slhci_abort_xfer(xfer, USBD_CANCELLED);
1197 1.1 isaki }
1198 1.1 isaki
1199 1.1 isaki static void
1200 1.1 isaki slhci_device_ctrl_close(usbd_pipe_handle pipe)
1201 1.1 isaki {
1202 1.1 isaki DPRINTF(D_TRACE, ("Ccl "));
1203 1.1 isaki }
1204 1.1 isaki
1205 1.1 isaki static void
1206 1.1 isaki slhci_device_ctrl_done(usbd_xfer_handle xfer)
1207 1.1 isaki {
1208 1.1 isaki DPRINTF(D_TRACE, ("Cdn "));
1209 1.1 isaki }
1210 1.1 isaki
1211 1.1 isaki static usbd_status
1212 1.1 isaki slhci_device_intr_transfer(usbd_xfer_handle xfer)
1213 1.1 isaki {
1214 1.1 isaki usbd_status error;
1215 1.1 isaki
1216 1.1 isaki DPRINTF(D_TRACE, ("INTRtrans "));
1217 1.1 isaki
1218 1.1 isaki error = usb_insert_transfer(xfer);
1219 1.1 isaki if (error)
1220 1.1 isaki return error;
1221 1.1 isaki
1222 1.1 isaki return slhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
1223 1.1 isaki }
1224 1.1 isaki
1225 1.1 isaki static usbd_status
1226 1.1 isaki slhci_device_intr_start(usbd_xfer_handle xfer)
1227 1.1 isaki {
1228 1.1 isaki usbd_pipe_handle pipe = xfer->pipe;
1229 1.1 isaki struct slhci_xfer *sx;
1230 1.1 isaki
1231 1.1 isaki DPRINTF(D_TRACE, ("INTRstart "));
1232 1.1 isaki
1233 1.1 isaki sx = malloc(sizeof(*sx), M_USB, M_NOWAIT);
1234 1.1 isaki if (sx == NULL)
1235 1.1 isaki goto reterr;
1236 1.1 isaki memset(sx, 0, sizeof(*sx));
1237 1.1 isaki sx->sx_xfer = xfer;
1238 1.1 isaki xfer->hcpriv = sx;
1239 1.1 isaki
1240 1.1 isaki /* initialize callout */
1241 1.1 isaki usb_callout_init(sx->sx_callout_t);
1242 1.1 isaki usb_callout(sx->sx_callout_t,
1243 1.1 isaki MS_TO_TICKS(pipe->endpoint->edesc->bInterval),
1244 1.1 isaki slhci_poll_device, sx);
1245 1.1 isaki
1246 1.1 isaki /* ACK */
1247 1.1 isaki return USBD_IN_PROGRESS;
1248 1.1 isaki
1249 1.1 isaki reterr:
1250 1.1 isaki return USBD_IOERROR;
1251 1.1 isaki }
1252 1.1 isaki
1253 1.1 isaki static void
1254 1.1 isaki slhci_poll_device(void *arg)
1255 1.1 isaki {
1256 1.1 isaki struct slhci_xfer *sx = (struct slhci_xfer *)arg;
1257 1.1 isaki usbd_xfer_handle xfer = sx->sx_xfer;
1258 1.1 isaki usbd_pipe_handle pipe = xfer->pipe;
1259 1.1 isaki struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1260 1.1 isaki void *buf;
1261 1.1 isaki int pid;
1262 1.1 isaki int r;
1263 1.1 isaki int s;
1264 1.1 isaki
1265 1.1 isaki DPRINTF(D_TRACE, ("pldev"));
1266 1.1 isaki
1267 1.1 isaki usb_callout(sx->sx_callout_t,
1268 1.1 isaki MS_TO_TICKS(pipe->endpoint->edesc->bInterval),
1269 1.1 isaki slhci_poll_device, sx);
1270 1.1 isaki
1271 1.1 isaki /* interrupt transfer */
1272 1.1 isaki pid = (UE_GET_DIR(pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN)
1273 1.1 isaki ? SL11_PID_IN : SL11_PID_OUT;
1274 1.1 isaki buf = KERNADDR(&xfer->dmabuf, 0);
1275 1.1 isaki
1276 1.1 isaki r = slhci_transaction(sc, pipe, pid, xfer->length, buf, 0/*toggle*/);
1277 1.1 isaki if (r < 0) {
1278 1.1 isaki DPRINTF(D_MSG, ("%s error", __FUNCTION__));
1279 1.1 isaki return;
1280 1.1 isaki }
1281 1.1 isaki /* no change, return NAK */
1282 1.1 isaki if (r == 0)
1283 1.1 isaki return;
1284 1.1 isaki
1285 1.1 isaki xfer->status = USBD_NORMAL_COMPLETION;
1286 1.1 isaki s = splusb();
1287 1.1 isaki xfer->device->bus->intr_context++;
1288 1.1 isaki usb_transfer_complete(xfer);
1289 1.1 isaki xfer->device->bus->intr_context--;
1290 1.1 isaki splx(s);
1291 1.1 isaki }
1292 1.1 isaki
1293 1.1 isaki static void
1294 1.1 isaki slhci_device_intr_abort(usbd_xfer_handle xfer)
1295 1.1 isaki {
1296 1.1 isaki struct slhci_xfer *sx;
1297 1.1 isaki
1298 1.1 isaki DPRINTF(D_TRACE, ("INTRabort "));
1299 1.1 isaki
1300 1.1 isaki sx = xfer->hcpriv;
1301 1.1 isaki if (sx) {
1302 1.1 isaki usb_uncallout(sx->sx_callout_t, slhci_poll_device, sx);
1303 1.1 isaki free(sx, M_USB);
1304 1.1 isaki xfer->hcpriv = NULL;
1305 1.1 isaki } else {
1306 1.1 isaki printf("%s: sx == NULL!\n", __FUNCTION__);
1307 1.1 isaki }
1308 1.1 isaki slhci_abort_xfer(xfer, USBD_CANCELLED);
1309 1.1 isaki }
1310 1.1 isaki
1311 1.1 isaki static void
1312 1.1 isaki slhci_device_intr_close(usbd_pipe_handle pipe)
1313 1.1 isaki {
1314 1.1 isaki DPRINTF(D_TRACE, ("INTRclose "));
1315 1.1 isaki }
1316 1.1 isaki
1317 1.1 isaki static void
1318 1.1 isaki slhci_device_intr_done(usbd_xfer_handle xfer)
1319 1.1 isaki {
1320 1.1 isaki DPRINTF(D_TRACE, ("INTRdone "));
1321 1.1 isaki }
1322 1.1 isaki
1323 1.1 isaki static usbd_status
1324 1.1 isaki slhci_device_isoc_transfer(usbd_xfer_handle xfer)
1325 1.1 isaki {
1326 1.1 isaki DPRINTF(D_TRACE, ("S"));
1327 1.1 isaki return USBD_NORMAL_COMPLETION;
1328 1.1 isaki }
1329 1.1 isaki
1330 1.1 isaki static usbd_status
1331 1.1 isaki slhci_device_isoc_start(usbd_xfer_handle xfer)
1332 1.1 isaki {
1333 1.1 isaki DPRINTF(D_TRACE, ("st "));
1334 1.1 isaki return USBD_NORMAL_COMPLETION;
1335 1.1 isaki }
1336 1.1 isaki
1337 1.1 isaki static void
1338 1.1 isaki slhci_device_isoc_abort(usbd_xfer_handle xfer)
1339 1.1 isaki {
1340 1.1 isaki DPRINTF(D_TRACE, ("Sab "));
1341 1.1 isaki }
1342 1.1 isaki
1343 1.1 isaki static void
1344 1.1 isaki slhci_device_isoc_close(usbd_pipe_handle pipe)
1345 1.1 isaki {
1346 1.1 isaki DPRINTF(D_TRACE, ("Scl "));
1347 1.1 isaki }
1348 1.1 isaki
1349 1.1 isaki static void
1350 1.1 isaki slhci_device_isoc_done(usbd_xfer_handle xfer)
1351 1.1 isaki {
1352 1.1 isaki DPRINTF(D_TRACE, ("Sdn "));
1353 1.1 isaki }
1354 1.1 isaki
1355 1.1 isaki static usbd_status
1356 1.1 isaki slhci_device_bulk_transfer(usbd_xfer_handle xfer)
1357 1.1 isaki {
1358 1.1 isaki DPRINTF(D_TRACE, ("B"));
1359 1.1 isaki return USBD_NORMAL_COMPLETION;
1360 1.1 isaki }
1361 1.1 isaki
1362 1.1 isaki static usbd_status
1363 1.1 isaki slhci_device_bulk_start(usbd_xfer_handle xfer)
1364 1.1 isaki {
1365 1.1 isaki DPRINTF(D_TRACE, ("st "));
1366 1.1 isaki return USBD_NORMAL_COMPLETION;
1367 1.1 isaki }
1368 1.1 isaki
1369 1.1 isaki static void
1370 1.1 isaki slhci_device_bulk_abort(usbd_xfer_handle xfer)
1371 1.1 isaki {
1372 1.1 isaki DPRINTF(D_TRACE, ("Bab "));
1373 1.1 isaki }
1374 1.1 isaki
1375 1.1 isaki static void
1376 1.1 isaki slhci_device_bulk_close(usbd_pipe_handle pipe)
1377 1.1 isaki {
1378 1.1 isaki DPRINTF(D_TRACE, ("Bcl "));
1379 1.1 isaki }
1380 1.1 isaki
1381 1.1 isaki static void
1382 1.1 isaki slhci_device_bulk_done(usbd_xfer_handle xfer)
1383 1.1 isaki {
1384 1.1 isaki DPRINTF(D_TRACE, ("Bdn "));
1385 1.1 isaki }
1386 1.1 isaki
1387 1.1 isaki #define DATA0_RD (0x03)
1388 1.1 isaki #define DATA0_WR (0x07)
1389 1.1 isaki #define SLHCI_TIMEOUT (5000)
1390 1.1 isaki
1391 1.1 isaki /*
1392 1.1 isaki * Do a transaction.
1393 1.1 isaki * return 1 if ACK, 0 if NAK, -1 if error.
1394 1.1 isaki */
1395 1.1 isaki static int
1396 1.1 isaki slhci_transaction(struct slhci_softc *sc, usbd_pipe_handle pipe,
1397 1.1 isaki u_int8_t pid, int len, u_char *buf, u_int8_t toggle)
1398 1.1 isaki {
1399 1.1 isaki #ifdef SLHCI_DEBUG
1400 1.1 isaki char str[64];
1401 1.1 isaki int i;
1402 1.1 isaki #endif
1403 1.1 isaki int timeout;
1404 1.1 isaki int ls_via_hub = 0;
1405 1.1 isaki int pl;
1406 1.1 isaki u_int8_t isr;
1407 1.1 isaki u_int8_t result = 0;
1408 1.1 isaki u_int8_t devaddr = pipe->device->address;
1409 1.1 isaki u_int8_t endpointaddr = pipe->endpoint->edesc->bEndpointAddress;
1410 1.1 isaki u_int8_t endpoint;
1411 1.1 isaki u_int8_t cmd = DATA0_RD;
1412 1.1 isaki
1413 1.1 isaki endpoint = UE_GET_ADDR(endpointaddr);
1414 1.1 isaki DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ",
1415 1.1 isaki pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint));
1416 1.1 isaki
1417 1.1 isaki /* Set registers */
1418 1.1 isaki sl11write(sc, SL11_E0ADDR, 0x40);
1419 1.1 isaki sl11write(sc, SL11_E0LEN, len);
1420 1.1 isaki sl11write(sc, SL11_E0PID, (pid << 4) + endpoint);
1421 1.1 isaki sl11write(sc, SL11_E0DEV, devaddr);
1422 1.1 isaki
1423 1.1 isaki /* Set buffer unless PID_IN */
1424 1.1 isaki if (pid != SL11_PID_IN) {
1425 1.1 isaki if (len > 0)
1426 1.1 isaki sl11write_region(sc, 0x40, buf, len);
1427 1.1 isaki cmd = DATA0_WR;
1428 1.1 isaki }
1429 1.1 isaki
1430 1.1 isaki /* timing ? */
1431 1.1 isaki pl = (len >> 3) + 3;
1432 1.1 isaki
1433 1.1 isaki /* Low speed device via HUB */
1434 1.1 isaki /* XXX does not work... */
1435 1.1 isaki if ((sc->sc_fullspeed) && pipe->device->speed == USB_SPEED_LOW) {
1436 1.1 isaki pl = len + 16;
1437 1.1 isaki cmd |= SL11_EPCTRL_PREAMBLE;
1438 1.1 isaki
1439 1.1 isaki /*
1440 1.1 isaki * SL811HS/T rev 1.2 has a bug, when it got PID_IN
1441 1.1 isaki * from LowSpeed device via HUB.
1442 1.1 isaki */
1443 1.1 isaki if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) {
1444 1.1 isaki ls_via_hub = 1;
1445 1.1 isaki DPRINTF(D_MSG, ("LSvH "));
1446 1.1 isaki }
1447 1.1 isaki }
1448 1.1 isaki
1449 1.1 isaki /* timing ? */
1450 1.1 isaki if (sl11read(sc, SL811_CSOF) <= (u_int8_t)pl)
1451 1.1 isaki cmd |= SL11_EPCTRL_SOF;
1452 1.1 isaki
1453 1.1 isaki /* Transfer */
1454 1.1 isaki sl11write(sc, SL11_ISR, 0xff);
1455 1.1 isaki sl11write(sc, SL11_E0CTRL, cmd | toggle);
1456 1.1 isaki
1457 1.1 isaki /* Polling */
1458 1.1 isaki for (timeout = SLHCI_TIMEOUT; timeout; timeout--) {
1459 1.1 isaki isr = sl11read(sc, SL11_ISR);
1460 1.1 isaki if ((isr & SL11_ISR_USBA))
1461 1.1 isaki break;
1462 1.1 isaki }
1463 1.1 isaki
1464 1.1 isaki /* Check result status */
1465 1.1 isaki result = sl11read(sc, SL11_E0STAT);
1466 1.1 isaki if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) {
1467 1.1 isaki /* Resend PID_IN within 20usec */
1468 1.1 isaki sl11write(sc, SL11_ISR, 0xff);
1469 1.1 isaki sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM);
1470 1.1 isaki }
1471 1.1 isaki
1472 1.1 isaki sl11write(sc, SL11_ISR, 0xff);
1473 1.1 isaki
1474 1.1 isaki DPRINTF(D_XFER, ("t=%d i=%x ", SLHCI_TIMEOUT - timeout, isr));
1475 1.1 isaki #if SLHCI_DEBUG
1476 1.1 isaki bitmask_snprintf(result,
1477 1.1 isaki "\20\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK",
1478 1.1 isaki str, sizeof(str));
1479 1.1 isaki DPRINTF(D_XFER, ("STAT=%s ", str));
1480 1.1 isaki #endif
1481 1.1 isaki
1482 1.1 isaki if ((result & SL11_EPSTAT_ERROR))
1483 1.1 isaki return -1;
1484 1.1 isaki
1485 1.1 isaki if ((result & SL11_EPSTAT_NAK))
1486 1.1 isaki return 0;
1487 1.1 isaki
1488 1.1 isaki /* Read buffer if PID_IN */
1489 1.1 isaki if (pid == SL11_PID_IN && len > 0) {
1490 1.1 isaki sl11read_region(sc, buf, 0x40, len);
1491 1.1 isaki #if SLHCI_DEBUG
1492 1.1 isaki for (i = 0; i < len; i++)
1493 1.1 isaki DPRINTF(D_XFER, ("%02X ", buf[i]));
1494 1.1 isaki #endif
1495 1.1 isaki }
1496 1.1 isaki
1497 1.1 isaki return 1;
1498 1.1 isaki }
1499 1.1 isaki
1500 1.1 isaki void
1501 1.1 isaki slhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
1502 1.1 isaki {
1503 1.1 isaki xfer->status = status;
1504 1.1 isaki usb_transfer_complete(xfer);
1505 1.1 isaki }
1506 1.1 isaki
1507 1.1 isaki void
1508 1.1 isaki slhci_device_clear_toggle(usbd_pipe_handle pipe)
1509 1.1 isaki {
1510 1.1 isaki DPRINTF(D_TRACE, ("SLdevice_clear_toggle "));
1511 1.1 isaki }
1512 1.1 isaki
1513 1.1 isaki #ifdef SLHCI_DEBUG
1514 1.1 isaki void
1515 1.1 isaki print_req(usb_device_request_t *r)
1516 1.1 isaki {
1517 1.1 isaki char *xmes[]={
1518 1.1 isaki "GETSTAT",
1519 1.1 isaki "CLRFEAT",
1520 1.1 isaki "res",
1521 1.1 isaki "SETFEAT",
1522 1.1 isaki "res",
1523 1.1 isaki "SETADDR",
1524 1.1 isaki "GETDESC",
1525 1.1 isaki "SETDESC",
1526 1.1 isaki "GETCONF",
1527 1.1 isaki "SETCONF",
1528 1.1 isaki "GETIN/F",
1529 1.1 isaki "SETIN/F",
1530 1.1 isaki "SYNC_FR"
1531 1.1 isaki };
1532 1.1 isaki int req, type, value, index, len;
1533 1.1 isaki
1534 1.1 isaki req = r->bRequest;
1535 1.1 isaki type = r->bmRequestType;
1536 1.1 isaki value = UGETW(r->wValue);
1537 1.1 isaki index = UGETW(r->wIndex);
1538 1.1 isaki len = UGETW(r->wLength);
1539 1.1 isaki
1540 1.1 isaki printf("%x,%s,v=%d,i=%d,l=%d ",
1541 1.1 isaki type, xmes[req], value, index, len);
1542 1.1 isaki }
1543 1.1 isaki
1544 1.1 isaki void
1545 1.1 isaki print_req_hub(usb_device_request_t *r)
1546 1.1 isaki {
1547 1.1 isaki struct {
1548 1.1 isaki int req;
1549 1.1 isaki int type;
1550 1.1 isaki char *str;
1551 1.1 isaki } conf[] = {
1552 1.1 isaki { 1, 0x20, "ClrHubFeat" },
1553 1.1 isaki { 1, 0x23, "ClrPortFeat" },
1554 1.1 isaki { 2, 0xa3, "GetBusState" },
1555 1.1 isaki { 6, 0xa0, "GetHubDesc" },
1556 1.1 isaki { 0, 0xa0, "GetHubStat" },
1557 1.1 isaki { 0, 0xa3, "GetPortStat" },
1558 1.1 isaki { 7, 0x20, "SetHubDesc" },
1559 1.1 isaki { 3, 0x20, "SetHubFeat" },
1560 1.1 isaki { 3, 0x23, "SetPortFeat" },
1561 1.1 isaki {-1, 0, NULL},
1562 1.1 isaki };
1563 1.1 isaki int i;
1564 1.1 isaki int value, index, len;
1565 1.1 isaki
1566 1.1 isaki value = UGETW(r->wValue);
1567 1.1 isaki index = UGETW(r->wIndex);
1568 1.1 isaki len = UGETW(r->wLength);
1569 1.1 isaki for (i = 0; ; i++) {
1570 1.1 isaki if (conf[i].req == -1 )
1571 1.1 isaki return print_req(r);
1572 1.1 isaki if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) {
1573 1.1 isaki printf("%s", conf[i].str);
1574 1.1 isaki break;
1575 1.1 isaki }
1576 1.1 isaki }
1577 1.1 isaki printf(",v=%d,i=%d,l=%d ", value, index, len);
1578 1.1 isaki }
1579 1.1 isaki
1580 1.1 isaki void
1581 1.1 isaki print_dumpreg(struct slhci_softc *sc)
1582 1.1 isaki {
1583 1.1 isaki printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x,"
1584 1.1 isaki "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,",
1585 1.1 isaki sl11read(sc, 0), sl11read(sc, 1),
1586 1.1 isaki sl11read(sc, 2), sl11read(sc, 3),
1587 1.1 isaki sl11read(sc, 4), sl11read(sc, 8),
1588 1.1 isaki sl11read(sc, 9), sl11read(sc, 10),
1589 1.1 isaki sl11read(sc, 11), sl11read(sc, 12)
1590 1.1 isaki );
1591 1.1 isaki printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ",
1592 1.1 isaki sl11read(sc, 5), sl11read(sc, 6),
1593 1.1 isaki sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15)
1594 1.1 isaki );
1595 1.1 isaki }
1596 1.1 isaki
1597 1.1 isaki void
1598 1.1 isaki print_xfer(usbd_xfer_handle xfer)
1599 1.1 isaki {
1600 1.1 isaki printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,",
1601 1.1 isaki xfer->length, xfer->actlen, xfer->flags, xfer->timeout);
1602 1.1 isaki printf("request{ ");
1603 1.1 isaki print_req_hub(&xfer->request);
1604 1.1 isaki printf("} ");
1605 1.1 isaki }
1606 1.1 isaki #endif /* SLHCI_DEBUG */
1607