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