]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/usb/sl811hs.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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 <dev/usb/usb_port.h>
68 #include "usbdevs.h"
69
70 #include <dev/usb/sl811hsreg.h>
71 #include <dev/usb/sl811hsvar.h>
72
73 __FBSDID("$FreeBSD$");
74
75 static inline u_int8_t sl11read(struct slhci_softc *, int);
76 static inline void     sl11write(struct slhci_softc *, int, u_int8_t);
77 static inline void sl11read_region(struct slhci_softc *, u_char *, int, int);
78 static inline void sl11write_region(struct slhci_softc *, int, u_char *, int);
79
80 static void             sl11_reset(struct slhci_softc *);
81 static void             sl11_speed(struct slhci_softc *);
82
83 static usbd_status      slhci_open(usbd_pipe_handle);
84 static void             slhci_softintr(void *);
85 static void             slhci_poll(struct usbd_bus *);
86 static void             slhci_poll_hub(void *);
87 static void             slhci_poll_device(void *arg);
88 static usbd_status      slhci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
89 static void             slhci_freem(struct usbd_bus *, usb_dma_t *);
90 static usbd_xfer_handle slhci_allocx(struct usbd_bus *);
91 static void             slhci_freex(struct usbd_bus *, usbd_xfer_handle);
92
93 static int              slhci_str(usb_string_descriptor_t *, int, const char *);
94
95 static usbd_status      slhci_root_ctrl_transfer(usbd_xfer_handle);
96 static usbd_status      slhci_root_ctrl_start(usbd_xfer_handle);
97 static void             slhci_root_ctrl_abort(usbd_xfer_handle);
98 static void             slhci_root_ctrl_close(usbd_pipe_handle);
99 static void             slhci_root_ctrl_done(usbd_xfer_handle);
100
101 static usbd_status      slhci_root_intr_transfer(usbd_xfer_handle);
102 static usbd_status      slhci_root_intr_start(usbd_xfer_handle);
103 static void             slhci_root_intr_abort(usbd_xfer_handle);
104 static void             slhci_root_intr_close(usbd_pipe_handle);
105 static void             slhci_root_intr_done(usbd_xfer_handle);
106
107 static usbd_status      slhci_device_ctrl_transfer(usbd_xfer_handle);
108 static usbd_status      slhci_device_ctrl_start(usbd_xfer_handle);
109 static void             slhci_device_ctrl_abort(usbd_xfer_handle);
110 static void             slhci_device_ctrl_close(usbd_pipe_handle);
111 static void             slhci_device_ctrl_done(usbd_xfer_handle);
112
113 static usbd_status      slhci_device_intr_transfer(usbd_xfer_handle);
114 static usbd_status      slhci_device_intr_start(usbd_xfer_handle);
115 static void             slhci_device_intr_abort(usbd_xfer_handle);
116 static void             slhci_device_intr_close(usbd_pipe_handle);
117 static void             slhci_device_intr_done(usbd_xfer_handle);
118
119 static usbd_status      slhci_device_isoc_transfer(usbd_xfer_handle);
120 static usbd_status      slhci_device_isoc_start(usbd_xfer_handle);
121 static void             slhci_device_isoc_abort(usbd_xfer_handle);
122 static void             slhci_device_isoc_close(usbd_pipe_handle);
123 static void             slhci_device_isoc_done(usbd_xfer_handle);
124
125 static usbd_status      slhci_device_bulk_transfer(usbd_xfer_handle);
126 static usbd_status      slhci_device_bulk_start(usbd_xfer_handle);
127 static void             slhci_device_bulk_abort(usbd_xfer_handle);
128 static void             slhci_device_bulk_close(usbd_pipe_handle);
129 static void             slhci_device_bulk_done(usbd_xfer_handle);
130
131 static int              slhci_transaction(struct slhci_softc *,
132         usbd_pipe_handle, u_int8_t, int, u_char *, u_int8_t);
133 static void             slhci_noop(usbd_pipe_handle);
134 static void             slhci_abort_xfer(usbd_xfer_handle, usbd_status);
135 static void             slhci_device_clear_toggle(usbd_pipe_handle);
136
137 extern int usbdebug;
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                 device_get_nameunit(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.parent_dmatag = NULL; /* XXX */
399         sc->sc_bus.buffer_dmatag = NULL; /* XXX */
400         STAILQ_INIT(&sc->sc_free_xfers);
401
402         usb_callout_init(sc->sc_poll_handle);
403
404         /* Disable interrupt, then wait 40msec */
405         sl11write(sc, SL11_IER, 0x00);
406         delay_ms(40);
407
408         /* Initialize controller */
409         sl11write(sc, SL811_CSOF, SL811_CSOF_MASTER | 0x2e);
410         delay_ms(40);
411
412         sl11write(sc, SL11_ISR, 0xff);
413
414         /* Disable interrupt, then wait 40msec */
415         sl11write(sc, SL11_IER, 0x00);
416
417         /* Reset USB engine */
418         sl11write(sc, SL11_CTRL, SL11_CTRL_JKSTATE| SL11_CTRL_RESETENGINE);
419         delay_ms(40);
420         sl11write(sc, SL11_CTRL, 0x00);
421         delay_ms(10);
422
423         /* USB Bus reset for GET_PORT_STATUS */
424         sl11_reset(sc);
425         sc->sc_flags = SLF_ATTACHED;
426
427         /* Enable interrupt */
428         sl11write(sc, SL11_IER, SL11_IER_INSERT);
429         /* x68k Nereid USB controller needs it */
430         if (sc->sc_enable_intr)
431                 sc->sc_enable_intr(sc->sc_arg, INTR_ON);
432 #ifdef USB_DEBUG
433         usbdebug = 0;
434 #endif
435
436         return 0;
437 }
438
439 int
440 slhci_intr(void *arg)
441 {
442         struct slhci_softc *sc = arg;
443         u_int8_t r;
444 #ifdef SLHCI_DEBUG
445         char bitbuf[256];
446 #endif
447
448
449         if((sc->sc_flags & SLF_ATTACHED) == 0)
450           return 0;
451
452         r = sl11read(sc, SL11_ISR);
453
454
455
456         sl11write(sc, SL11_ISR, SL11_ISR_DATA | SL11_ISR_SOFTIMER);
457
458         if ((r & SL11_ISR_RESET)) {
459                 sc->sc_flags |= SLF_RESET;
460                 sl11write(sc, SL11_ISR, SL11_ISR_RESET);
461         }
462         if ((r & SL11_ISR_INSERT)) {
463                 sc->sc_flags |= SLF_INSERT;
464                 sl11write(sc, SL11_ISR, SL11_ISR_INSERT);
465         }
466
467 #ifdef SLHCI_DEBUG
468         bitmask_snprintf(r,
469                 (sl11read(sc, SL11_CTRL) & SL11_CTRL_SUSPEND)
470                 ? "\20\x8""D+\7RESUME\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA"
471                 : "\20\x8""D+\7RESET\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA",
472                 bitbuf, sizeof(bitbuf));
473         DPRINTF(D_XFER, ("I=%s ", bitbuf));
474 #endif /* SLHCI_DEBUG */
475
476         return 0;
477 }
478
479 usbd_status
480 slhci_open(usbd_pipe_handle pipe)
481 {
482         usbd_device_handle dev = pipe->device;
483         struct slhci_softc *sc = (struct slhci_softc *)dev->bus;
484         usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
485
486         DPRINTF(D_TRACE, ("slhci_open(addr=%d,ep=%d,scaddr=%d)",
487                 dev->address, ed->bEndpointAddress, sc->sc_addr));
488
489         if (dev->address == sc->sc_addr) {
490                 switch (ed->bEndpointAddress) {
491                 case USB_CONTROL_ENDPOINT:
492                         pipe->methods = &slhci_root_ctrl_methods;
493                         break;
494                 case UE_DIR_IN | SLHCI_INTR_ENDPT:
495                         pipe->methods = &slhci_root_intr_methods;
496                         break;
497                 default:
498                         printf("open:endpointErr!\n");
499                         return USBD_INVAL;
500                 }
501         } else {
502                 switch (ed->bmAttributes & UE_XFERTYPE) {
503                 case UE_CONTROL:
504                         DPRINTF(D_MSG, ("control "));
505                         pipe->methods = &slhci_device_ctrl_methods;
506                         break;
507                 case UE_INTERRUPT:
508                         DPRINTF(D_MSG, ("interrupt "));
509                         pipe->methods = &slhci_device_intr_methods;
510                         break;
511                 case UE_ISOCHRONOUS:
512                         DPRINTF(D_MSG, ("isochronous "));
513                         pipe->methods = &slhci_device_isoc_methods;
514                         break;
515                 case UE_BULK:
516                         DPRINTF(D_MSG, ("bluk "));
517                         pipe->methods = &slhci_device_bulk_methods;
518                         break;
519                 }
520         }
521         return USBD_NORMAL_COMPLETION;
522 }
523
524 void
525 slhci_softintr(void *arg)
526 {
527         DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
528 }
529
530 void
531 slhci_poll(struct usbd_bus *bus)
532 {
533         DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
534 }
535
536 /*
537  * Emulation of interrupt transfer for status change endpoint
538  * of root hub.
539  */
540 void
541 slhci_poll_hub(void *arg)
542 {
543         usbd_xfer_handle xfer = arg;
544         usbd_pipe_handle pipe = xfer->pipe;
545         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
546         int s;
547         u_char *p;
548
549         usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer);
550
551         /* USB spec 11.13.3 (p.260) */
552         p = xfer->buffer;
553         p[0] = 0;
554         if ((sc->sc_flags & (SLF_INSERT | SLF_RESET))) {
555                 p[0] = 2;
556                 DPRINTF(D_TRACE, ("!"));
557         }
558
559         /* no change, return NAK */
560         if (p[0] == 0)
561                 return;
562
563         xfer->actlen = 1;
564         xfer->status = USBD_NORMAL_COMPLETION;
565         s = splusb();
566         xfer->device->bus->intr_context++;
567         usb_transfer_complete(xfer);
568         xfer->device->bus->intr_context--;
569         splx(s);
570 }
571
572 usbd_status
573 slhci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size)
574 {
575         struct slhci_softc *sc = (struct slhci_softc *)bus;
576
577         DPRINTF(D_MEM, ("SLallocm"));
578         return usb_allocmem(&sc->sc_bus, size, 0, dma);
579 }
580
581 void
582 slhci_freem(struct usbd_bus *bus, usb_dma_t *dma)
583 {
584         struct slhci_softc *sc = (struct slhci_softc *)bus;
585
586         DPRINTF(D_MEM, ("SLfreem"));
587         usb_freemem(&sc->sc_bus, dma);
588 }
589
590 usbd_xfer_handle
591 slhci_allocx(struct usbd_bus *bus)
592 {
593         struct slhci_softc *sc = (struct slhci_softc *)bus;
594         usbd_xfer_handle xfer;
595
596         DPRINTF(D_MEM, ("SLallocx"));
597
598         xfer = STAILQ_FIRST(&sc->sc_free_xfers);
599         if (xfer) {
600                 STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
601 #ifdef DIAGNOSTIC
602                 if (xfer->busy_free != XFER_FREE) {
603                         printf("slhci_allocx: xfer=%p not free, 0x%08x\n",
604                                 xfer, xfer->busy_free);
605                 }
606 #endif
607         } else {
608                 xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
609         }
610
611         if (xfer) {
612                 memset(xfer, 0, sizeof(*xfer));
613 #ifdef DIAGNOSTIC
614                 xfer->busy_free = XFER_BUSY;
615 #endif
616         }
617
618         return xfer;
619 }
620
621 void
622 slhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
623 {
624         struct slhci_softc *sc = (struct slhci_softc *)bus;
625
626         DPRINTF(D_MEM, ("SLfreex"));
627
628 #ifdef DIAGNOSTIC
629         if (xfer->busy_free != XFER_BUSY) {
630                 printf("slhci_freex: xfer=%p not busy, 0x%08x\n",
631                         xfer, xfer->busy_free);
632                 return;
633         }
634         xfer->busy_free = XFER_FREE;
635 #endif
636         STAILQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
637 }
638
639 void
640 slhci_noop(usbd_pipe_handle pipe)
641 {
642         DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
643 }
644
645 /*
646  * Data structures and routines to emulate the root hub.
647  */
648 usb_device_descriptor_t slhci_devd = {
649         USB_DEVICE_DESCRIPTOR_SIZE,
650         UDESC_DEVICE,           /* type */
651         {0x01, 0x01},                   /* USB version */
652         UDCLASS_HUB,            /* class */
653         UDSUBCLASS_HUB,         /* subclass */
654         0,                      /* protocol */
655         64,                     /* max packet */
656         {USB_VENDOR_SCANLOGIC & 0xff,   /* vendor ID (low)  */
657          USB_VENDOR_SCANLOGIC >> 8  },  /* vendor ID (high) */
658         {0} /* ? */,            /* product ID */
659         {0},                    /* device */
660         1,                      /* index to manufacturer */
661         2,                      /* index to product */
662         0,                      /* index to serial number */
663         1                       /* number of configurations */
664 };
665
666 usb_config_descriptor_t slhci_confd = {
667         USB_CONFIG_DESCRIPTOR_SIZE,
668         UDESC_CONFIG,
669         {USB_CONFIG_DESCRIPTOR_SIZE +
670          USB_INTERFACE_DESCRIPTOR_SIZE +
671          USB_ENDPOINT_DESCRIPTOR_SIZE},
672         1,                      /* number of interfaces */
673         1,                      /* configuration value */
674         0,                      /* index to configuration */
675         UC_SELF_POWERED,        /* attributes */
676         15                      /* max current is 30mA... */
677 };
678
679 usb_interface_descriptor_t slhci_ifcd = {
680         USB_INTERFACE_DESCRIPTOR_SIZE,
681         UDESC_INTERFACE,
682         0,                      /* interface number */
683         0,                      /* alternate setting */
684         1,                      /* number of endpoint */
685         UICLASS_HUB,            /* class */
686         UISUBCLASS_HUB,         /* subclass */
687         0,                      /* protocol */
688         0                       /* index to interface */
689 };
690
691 usb_endpoint_descriptor_t slhci_endpd = {
692         USB_ENDPOINT_DESCRIPTOR_SIZE,
693         UDESC_ENDPOINT,
694         UE_DIR_IN | SLHCI_INTR_ENDPT,   /* endpoint address */
695         UE_INTERRUPT,           /* attributes */
696         {8},                    /* max packet size */
697         255                     /* interval */
698 };
699
700 usb_hub_descriptor_t slhci_hubd = {
701         USB_HUB_DESCRIPTOR_SIZE,
702         UDESC_HUB,
703         1,                      /* number of ports */
704         {UHD_PWR_INDIVIDUAL | UHD_OC_NONE, 0},  /* hub characteristics */
705         20 /* ? */,             /* 5:power on to power good */
706         50,                     /* 6:maximum current */
707         { 0x00 },               /* both ports are removable */
708         { 0x00 }                /* port power control mask */
709 };
710
711 static int
712 slhci_str(usb_string_descriptor_t *p, int l, const char *s)
713 {
714         int i;
715
716         if (l == 0)
717                 return 0;
718         p->bLength = 2 * strlen(s) + 2;
719         if (l == 1)
720                 return 1;
721         p->bDescriptorType = UDESC_STRING;
722         l -= 2;
723         for (i = 0; s[i] && l > 1; i++, l -= 2)
724                 USETW2(p->bString[i], 0, s[i]);
725         return 2 * i + 2;
726 }
727
728 usbd_status
729 slhci_root_ctrl_transfer(usbd_xfer_handle xfer)
730 {
731         usbd_status error;
732
733         DPRINTF(D_TRACE, ("SLRCtrans "));
734
735         /* Insert last in queue */
736         error = usb_insert_transfer(xfer);
737         if (error) {
738                 DPRINTF(D_MSG, ("usb_insert_transfer returns err! "));
739                 return error;
740         }
741
742         /*
743          * Pipe isn't running (otherwise error would be USBD_INPROG),
744          * so start it first.
745          */
746         return slhci_root_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue));
747 }
748
749 usbd_status
750 slhci_root_ctrl_start(usbd_xfer_handle xfer)
751 {
752         struct slhci_softc *sc = (struct slhci_softc *)xfer->pipe->device->bus;
753         usb_device_request_t *req;
754         int len, value, index, l, s, status;
755         int totlen = 0;
756         void *buf = NULL;
757         usb_port_status_t ps;
758         usbd_status error;
759         char slbuf[50];
760         u_int8_t r;
761
762         DPRINTF(D_TRACE, ("SLRCstart "));
763
764         req = &xfer->request;
765
766         len = UGETW(req->wLength);
767         value = UGETW(req->wValue);
768         index = UGETW(req->wIndex);
769
770         if (len)
771                 buf = xfer->buffer;
772
773 #ifdef SLHCI_DEBUG
774         if ((slhci_debug & D_TRACE))
775                 print_req_hub(req);
776 #endif
777
778 #define C(x,y) ((x) | ((y) << 8))
779         switch (C(req->bRequest, req->bmRequestType)) {
780         case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
781         case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
782         case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
783                 DPRINTF(D_MSG, ("UR_CLEAR_FEATURE "));
784                 break;
785         case C(UR_GET_CONFIG, UT_READ_DEVICE):
786                 DPRINTF(D_MSG, ("UR_GET_CONFIG "));
787                 if (len > 0) {
788                         *(u_int8_t *)buf = sc->sc_conf;
789                         totlen = 1;
790                 }
791                 break;
792         case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
793                 switch (value >> 8) {
794                 case UDESC_DEVICE:
795                         DPRINTF(D_MSG, ("UDESC_DEVICE "));
796                         if ((value & 0xff) != 0) {
797                                 error = USBD_IOERROR;
798                                 goto ret;
799                         }
800                         totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
801                         memcpy(buf, &slhci_devd, l);
802                         break;
803                 case UDESC_CONFIG:
804                         DPRINTF(D_MSG, ("UDESC_CONFIG "));
805                         if ((value & 0xff) != 0) {
806                                 error = USBD_IOERROR;
807                                 goto ret;
808                         }
809                         totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
810                         memcpy(buf, &slhci_confd, l);
811                         buf = (char *)buf + l;
812                         len -= l;
813
814                         l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
815                         totlen += l;
816                         memcpy(buf, &slhci_ifcd, l);
817                         buf = (char *)buf + l;
818                         len -= l;
819
820                         l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
821                         totlen += l;
822                         memcpy(buf, &slhci_endpd, l);
823                         break;
824                 case UDESC_STRING:
825                         DPRINTF(D_MSG, ("UDESC_STR "));
826                         if (len == 0)
827                                 break;
828                         *(u_int8_t *)buf = 0;
829                         totlen = 1;
830                         switch (value & 0xff) {
831                         case 0:
832                                 break;
833                         case 1: /* Vendor */
834                                 totlen = slhci_str(buf, len, "ScanLogic");
835                                 break;
836                         case 2: /* Product */
837                                 snprintf(slbuf, sizeof(slbuf), "%s root hub",
838                                     sltypestr[sc->sc_sltype>0]);
839                                 totlen = slhci_str(buf, len, slbuf);
840                                 break;
841                         default:
842                                 printf("strerr%d ", value & 0xff);
843                                 break;
844                         }
845                         break;
846                 default:
847                         printf("unknownGetDescriptor=%x", value);
848                         error = USBD_IOERROR;
849                         break;
850                 }
851                 break;
852         case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
853                 /* Get Interface, 9.4.4 */
854                 if (len > 0) {
855                         *(u_int8_t *)buf = 0;
856                         totlen = 1;
857                 }
858                 break;
859         case C(UR_GET_STATUS, UT_READ_DEVICE):
860                 /* Get Status from device, 9.4.5 */
861                 if (len > 1) {
862                         USETW(((usb_status_t *)buf)->wStatus, UDS_SELF_POWERED);
863                         totlen = 2;
864                 }
865                 break;
866         case C(UR_GET_STATUS, UT_READ_INTERFACE):
867         case C(UR_GET_STATUS, UT_READ_ENDPOINT):
868                 /* Get Status from interface, endpoint, 9.4.5 */
869                 if (len > 1) {
870                         USETW(((usb_status_t *)buf)->wStatus, 0);
871                         totlen = 2;
872                 }
873                 break;
874         case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
875                 /* Set Address, 9.4.6 */
876                 DPRINTF(D_MSG, ("UR_SET_ADDRESS "));
877                 if (value >= USB_MAX_DEVICES) {
878                         error = USBD_IOERROR;
879                         goto ret;
880                 }
881                 sc->sc_addr = value;
882                 break;
883         case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
884                 /* Set Configuration, 9.4.7 */
885                 DPRINTF(D_MSG, ("UR_SET_CONFIG "));
886                 if (value != 0 && value != 1) {
887                         error = USBD_IOERROR;
888                         goto ret;
889                 }
890                 sc->sc_conf = value;
891                 break;
892         case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
893                 /* Set Descriptor, 9.4.8, not supported */
894                 DPRINTF(D_MSG, ("UR_SET_DESCRIPTOR,WRITE_DEVICE not supported\n"));
895                 break;
896         case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
897         case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
898         case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
899                 /* Set Feature, 9.4.9, not supported */
900                 DPRINTF(D_MSG, ("UR_SET_FEATURE not supported\n"));
901                 error = USBD_IOERROR;
902                 break;
903         case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
904                 /* Set Interface, 9.4.10, not supported */
905                 break;
906         case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
907                 /* Synch Frame, 9.4.11, not supported */
908                 break;
909
910         /*
911          * Hub specific requests
912          */
913         case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
914                 /* Clear Hub Feature, 11.16.2.1, not supported */
915                 DPRINTF(D_MSG, ("ClearHubFeature not supported\n"));
916                 break;
917         case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
918                 /* Clear Port Feature, 11.16.2.2 */
919                 if (index != 1) {
920                         error = USBD_IOERROR;
921                         goto ret;
922                 }
923                 switch (value) {
924                 case UHF_PORT_POWER:
925                         DPRINTF(D_MSG, ("POWER_OFF "));
926                         sc->sc_powerstat = POWER_OFF;
927                         /* x68k Nereid USB controller needs it */
928                         if (sc->sc_enable_power)
929                                 sc->sc_enable_power(sc, sc->sc_powerstat);
930                         break;
931                 case UHF_PORT_SUSPEND:
932                         DPRINTF(D_MSG, ("SUSPEND "));
933                         sl11write(sc, SL11_CTRL,
934                                 sl11read(sc, SL11_CTRL) & ~SL11_CTRL_SUSPEND);
935                         break;
936                 case UHF_C_PORT_CONNECTION:
937                         sc->sc_change &= ~UPS_C_CONNECT_STATUS;
938                         break;
939                 case UHF_C_PORT_RESET:
940                         sc->sc_change &= ~UPS_C_PORT_RESET;
941                         break;
942                 case UHF_PORT_ENABLE:
943                         break;
944                 case UHF_C_PORT_SUSPEND:
945                 case UHF_C_PORT_ENABLE:
946                 case UHF_C_PORT_OVER_CURRENT:
947                 default:
948                         printf("ClrPortFeatERR:value=0x%x ", value);
949                         error = USBD_IOERROR;
950                         break;
951                 }
952                 //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change));
953                 break;
954         case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
955                 /* Get Bus State, 11.16.2.3, not supported */
956                 /* shall return a STALL... */
957                 break;
958         case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
959                 /* Get Hub Descriptor, 11.16.2.4 */
960                 if (value != 0) {
961                         error = USBD_IOERROR;
962                         goto ret;
963                 }
964                 l = min(len, USB_HUB_DESCRIPTOR_SIZE);
965                 totlen = l;
966                 memcpy(buf, &slhci_hubd, l);
967                 break;
968         case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
969                 /* Get Hub Status, 11.16.2.5 */
970                 DPRINTF(D_MSG, ("UR_GET_STATUS RCD"));
971                 if (len != 4) {
972                         error = USBD_IOERROR;
973                         goto ret;
974                 }
975                 memset(buf, 0, len);
976                 totlen = len;
977                 break;
978         case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
979                 /* Get Port Status, 11.16.2.6 */
980                 if (index != 1 || len != 4) {
981                         printf("index=%d,len=%d ", index, len);
982                         error = USBD_IOERROR;
983                         goto ret;
984                 }
985                 /*
986                  * change
987                  * o port is always enabled.
988                  * o cannot detect over current.
989                  */
990                 s = splusb();
991                 sc->sc_change &= ~(UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET);
992                 if ((sc->sc_flags & SLF_INSERT)) {
993                         sc->sc_flags &= ~SLF_INSERT;
994                         sc->sc_change |= UPS_C_CONNECT_STATUS;
995                 }
996                 if ((sc->sc_flags & SLF_RESET)) {
997                         sc->sc_flags &= ~SLF_RESET;
998                         sc->sc_change |= UPS_C_PORT_RESET;
999                 }
1000                 splx(s);
1001                 /*
1002                  * XXX It can recognize that device is detached,
1003                  * while there is sl11_speed() here.
1004                  */
1005                 if (sc->sc_change)
1006                         sl11_speed(sc);
1007                 /*
1008                  * status
1009                  * o port is always enabled.
1010                  * o cannot detect over current.
1011                  */
1012                 status = 0;
1013                 if (sc->sc_connect)
1014                         status |= UPS_CURRENT_CONNECT_STATUS | UPS_PORT_ENABLED;
1015                 r = sl11read(sc, SL11_CTRL);
1016                 if (r & SL11_CTRL_SUSPEND)
1017                         status |= UPS_SUSPEND;
1018                 if (sc->sc_powerstat)
1019                         status |= UPS_PORT_POWER;
1020                 if (!sc->sc_fullspeed)
1021                         status |= UPS_LOW_SPEED;
1022
1023                 //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change));
1024                 USETW(ps.wPortStatus, status);
1025                 USETW(ps.wPortChange, sc->sc_change);
1026                 l = min(len, sizeof(ps));
1027                 memcpy(buf, &ps, l);
1028                 totlen = l;
1029                 break;
1030         case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
1031                 /* Set Hub Descriptor, 11.16.2.7, not supported */
1032                 /* STALL ? */
1033                 error = USBD_IOERROR;
1034                 break;
1035         case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
1036                 /* Set Hub Feature, 11.16.2.8, not supported */
1037                 break;
1038         case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
1039                 /* Set Port Feature, 11.16.2.9 */
1040                 if (index != 1) {
1041                         printf("index=%d ", index);
1042                         error = USBD_IOERROR;
1043                         goto ret;
1044                 }
1045                 switch (value) {
1046                 case UHF_PORT_RESET:
1047                         DPRINTF(D_MSG, ("PORT_RESET "));
1048                         sl11_reset(sc);
1049                         sl11_speed(sc);
1050                         sc->sc_change = 0;
1051                         break;
1052                 case UHF_PORT_POWER:
1053                         DPRINTF(D_MSG, ("PORT_POWER "));
1054                         sc->sc_powerstat = POWER_ON;
1055                         /* x68k Nereid USB controller needs it */
1056                         if (sc->sc_enable_power)
1057                                 sc->sc_enable_power(sc, sc->sc_powerstat);
1058                         delay_ms(25);
1059                         break;
1060                 default:
1061                         printf("SetPortFeatERR=0x%x ", value);
1062                         error = USBD_IOERROR;
1063                         break;
1064                 }
1065                 break;
1066         default:
1067                 DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ",
1068                         req->bRequest, req->bmRequestType));
1069                 error = USBD_IOERROR;
1070                 goto ret;
1071         }
1072         xfer->actlen = totlen;
1073         error = USBD_NORMAL_COMPLETION;
1074  ret:
1075         xfer->status = error;
1076         s = splusb();
1077         usb_transfer_complete(xfer);
1078         splx(s);
1079         return USBD_IN_PROGRESS;
1080 }
1081
1082 void
1083 slhci_root_ctrl_abort(usbd_xfer_handle xfer)
1084 {
1085         DPRINTF(D_TRACE, ("SLRCabort "));
1086 }
1087
1088 void
1089 slhci_root_ctrl_close(usbd_pipe_handle pipe)
1090 {
1091         DPRINTF(D_TRACE, ("SLRCclose "));
1092 }
1093
1094 void
1095 slhci_root_ctrl_done(usbd_xfer_handle xfer)
1096 {
1097         DPRINTF(D_TRACE, ("SLRCdone\n"));
1098 }
1099
1100 static usbd_status
1101 slhci_root_intr_transfer(usbd_xfer_handle xfer)
1102 {
1103         usbd_status error;
1104
1105         DPRINTF(D_TRACE, ("SLRItransfer "));
1106
1107         /* Insert last in queue */
1108         error = usb_insert_transfer(xfer);
1109         if (error)
1110                 return error;
1111
1112         /*
1113          * Pipe isn't running (otherwise error would be USBD_INPROG),
1114          * start first.
1115          */
1116         return slhci_root_intr_start(STAILQ_FIRST(&xfer->pipe->queue));
1117 }
1118
1119 static usbd_status
1120 slhci_root_intr_start(usbd_xfer_handle xfer)
1121 {
1122         usbd_pipe_handle pipe = xfer->pipe;
1123         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1124
1125         DPRINTF(D_TRACE, ("SLRIstart "));
1126
1127         sc->sc_interval = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval);
1128         usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer);
1129         sc->sc_intr_xfer = xfer;
1130         return USBD_IN_PROGRESS;
1131 }
1132
1133 static void
1134 slhci_root_intr_abort(usbd_xfer_handle xfer)
1135 {
1136         DPRINTF(D_TRACE, ("SLRIabort "));
1137 }
1138
1139 static void
1140 slhci_root_intr_close(usbd_pipe_handle pipe)
1141 {
1142         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1143
1144         DPRINTF(D_TRACE, ("SLRIclose "));
1145
1146         usb_uncallout(sc->sc_poll_handle, slhci_poll_hub, sc->sc_intr_xfer);
1147         sc->sc_intr_xfer = NULL;
1148 }
1149
1150 static void
1151 slhci_root_intr_done(usbd_xfer_handle xfer)
1152 {
1153         //DPRINTF(D_XFER, ("RIdn "));
1154 }
1155
1156 static usbd_status
1157 slhci_device_ctrl_transfer(usbd_xfer_handle xfer)
1158 {
1159         usbd_status error;
1160
1161         DPRINTF(D_TRACE, ("C"));
1162
1163         error = usb_insert_transfer(xfer);
1164         if (error)
1165                 return error;
1166
1167         return slhci_device_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue));
1168 }
1169
1170 static usbd_status
1171 slhci_device_ctrl_start(usbd_xfer_handle xfer)
1172 {
1173         usb_device_request_t *req = &xfer->request;
1174         usbd_pipe_handle pipe = xfer->pipe;
1175         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1176         usbd_status status =  USBD_NORMAL_COMPLETION;
1177         u_char *buf;
1178         int pid = SL11_PID_OUT;
1179         int len, actlen, size;
1180         int s;
1181         u_int8_t toggle = 0;
1182
1183         DPRINTF(D_TRACE, ("st "));
1184 #ifdef SLHCI_DEBUG
1185         if ((slhci_debug & D_TRACE))
1186                 print_req_hub(req);
1187 #endif
1188
1189         /* SETUP transaction */
1190         if (slhci_transaction(sc, pipe, SL11_PID_SETUP,
1191                         sizeof(*req), (u_char*)req, toggle) == -1) {
1192                 status = USBD_IOERROR;
1193                 goto ret;
1194         }
1195         toggle ^= SL11_EPCTRL_DATATOGGLE;
1196
1197         /* DATA transaction */
1198         actlen = 0;
1199         len = UGETW(req->wLength);
1200         if (len) {
1201                 buf = xfer->buffer;
1202                 if (req->bmRequestType & UT_READ)
1203                         pid = SL11_PID_IN;
1204                 for (; actlen < len; ) {
1205                         size = min(len - actlen, 8/* Minimum size */);
1206                         if (slhci_transaction(sc, pipe, pid, size, buf, toggle) == -1)
1207                                 break;
1208                         toggle ^= SL11_EPCTRL_DATATOGGLE;
1209                         buf += size;
1210                         actlen += size;
1211                 }
1212         }
1213         xfer->actlen = actlen;
1214
1215         /* ACK (status) */
1216         if (pid == SL11_PID_IN)
1217                 pid = SL11_PID_OUT;
1218         else
1219                 pid = SL11_PID_IN;
1220         if (slhci_transaction(sc, pipe, pid, 0, NULL, toggle) == -1)
1221                 status = USBD_IOERROR;
1222
1223  ret:
1224         xfer->status = status;
1225
1226 #ifdef SLHCI_DEBUG
1227         if((slhci_debug & D_TRACE) && UGETW(req->wLength) > 0){
1228                 int i;
1229                 for(i=0; i < UGETW(req->wLength); i++)
1230                         printf("%02x", ((unsigned char *)xfer->buffer)[i]);
1231                 printf(" ");
1232         }
1233 #endif
1234         s = splusb();
1235         usb_transfer_complete(xfer);
1236         splx(s);
1237         return USBD_IN_PROGRESS;
1238 }
1239
1240 static void
1241 slhci_device_ctrl_abort(usbd_xfer_handle xfer)
1242 {
1243         DPRINTF(D_TRACE, ("Cab "));
1244         slhci_abort_xfer(xfer, USBD_CANCELLED);
1245 }
1246
1247 static void
1248 slhci_device_ctrl_close(usbd_pipe_handle pipe)
1249 {
1250         DPRINTF(D_TRACE, ("Ccl "));
1251 }
1252
1253 static void
1254 slhci_device_ctrl_done(usbd_xfer_handle xfer)
1255 {
1256         DPRINTF(D_TRACE, ("Cdn "));
1257 }
1258
1259 static usbd_status
1260 slhci_device_intr_transfer(usbd_xfer_handle xfer)
1261 {
1262         usbd_status error;
1263
1264         DPRINTF(D_TRACE, ("INTRtrans "));
1265
1266         error = usb_insert_transfer(xfer);
1267         if (error)
1268                 return error;
1269
1270         return slhci_device_intr_start(STAILQ_FIRST(&xfer->pipe->queue));
1271 }
1272
1273 static usbd_status
1274 slhci_device_intr_start(usbd_xfer_handle xfer)
1275 {
1276         usbd_pipe_handle pipe = xfer->pipe;
1277         struct slhci_xfer *sx;
1278
1279         DPRINTF(D_TRACE, ("INTRstart "));
1280
1281         sx = malloc(sizeof(*sx), M_USB, M_NOWAIT);
1282         if (sx == NULL)
1283                 goto reterr;
1284         memset(sx, 0, sizeof(*sx));
1285         sx->sx_xfer  = xfer;
1286         xfer->hcpriv = sx;
1287
1288         /* initialize callout */
1289         usb_callout_init(sx->sx_callout_t);
1290         usb_callout(sx->sx_callout_t,
1291                 MS_TO_TICKS(pipe->endpoint->edesc->bInterval),
1292                 slhci_poll_device, sx);
1293
1294         /* ACK */
1295         return USBD_IN_PROGRESS;
1296
1297  reterr:
1298         return USBD_IOERROR;
1299 }
1300
1301 static void
1302 slhci_poll_device(void *arg)
1303 {
1304         struct slhci_xfer *sx = (struct slhci_xfer *)arg;
1305         usbd_xfer_handle xfer = sx->sx_xfer;
1306         usbd_pipe_handle pipe = xfer->pipe;
1307         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
1308         void *buf;
1309         int pid;
1310         int r;
1311         int s;
1312
1313         DPRINTF(D_TRACE, ("pldev"));
1314
1315         usb_callout(sx->sx_callout_t,
1316                 MS_TO_TICKS(pipe->endpoint->edesc->bInterval),
1317                 slhci_poll_device, sx);
1318
1319         /* interrupt transfer */
1320         pid = (UE_GET_DIR(pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN)
1321             ? SL11_PID_IN : SL11_PID_OUT;
1322         buf = xfer->buffer;
1323
1324         r = slhci_transaction(sc, pipe, pid, xfer->length, buf, 0/*toggle*/);
1325         if (r < 0) {
1326                 DPRINTF(D_MSG, ("%s error", __FUNCTION__));
1327                 return;
1328         }
1329         /* no change, return NAK */
1330         if (r == 0)
1331                 return;
1332
1333         xfer->status = USBD_NORMAL_COMPLETION;
1334         s = splusb();
1335         xfer->device->bus->intr_context++;
1336         usb_transfer_complete(xfer);
1337         xfer->device->bus->intr_context--;
1338         splx(s);
1339 }
1340
1341 static void
1342 slhci_device_intr_abort(usbd_xfer_handle xfer)
1343 {
1344         struct slhci_xfer *sx;
1345
1346         DPRINTF(D_TRACE, ("INTRabort "));
1347
1348         sx = xfer->hcpriv;
1349         if (sx) {
1350                 usb_uncallout(sx->sx_callout_t, slhci_poll_device, sx);
1351                 free(sx, M_USB);
1352                 xfer->hcpriv = NULL;
1353         } else {
1354                 printf("%s: sx == NULL!\n", __FUNCTION__);
1355         }
1356         slhci_abort_xfer(xfer, USBD_CANCELLED);
1357 }
1358
1359 static void
1360 slhci_device_intr_close(usbd_pipe_handle pipe)
1361 {
1362         DPRINTF(D_TRACE, ("INTRclose "));
1363 }
1364
1365 static void
1366 slhci_device_intr_done(usbd_xfer_handle xfer)
1367 {
1368         DPRINTF(D_TRACE, ("INTRdone "));
1369 }
1370
1371 static usbd_status
1372 slhci_device_isoc_transfer(usbd_xfer_handle xfer)
1373 {
1374         DPRINTF(D_TRACE, ("S"));
1375         return USBD_NORMAL_COMPLETION;
1376 }
1377
1378 static usbd_status
1379 slhci_device_isoc_start(usbd_xfer_handle xfer)
1380 {
1381         DPRINTF(D_TRACE, ("st "));
1382         return USBD_NORMAL_COMPLETION;
1383 }
1384
1385 static void
1386 slhci_device_isoc_abort(usbd_xfer_handle xfer)
1387 {
1388         DPRINTF(D_TRACE, ("Sab "));
1389 }
1390
1391 static void
1392 slhci_device_isoc_close(usbd_pipe_handle pipe)
1393 {
1394         DPRINTF(D_TRACE, ("Scl "));
1395 }
1396
1397 static void
1398 slhci_device_isoc_done(usbd_xfer_handle xfer)
1399 {
1400         DPRINTF(D_TRACE, ("Sdn "));
1401 }
1402
1403 static usbd_status
1404 slhci_device_bulk_transfer(usbd_xfer_handle xfer)
1405 {
1406         DPRINTF(D_TRACE, ("B"));
1407         return USBD_NORMAL_COMPLETION;
1408 }
1409
1410 static usbd_status
1411 slhci_device_bulk_start(usbd_xfer_handle xfer)
1412 {
1413         DPRINTF(D_TRACE, ("st "));
1414         return USBD_NORMAL_COMPLETION;
1415 }
1416
1417 static void
1418 slhci_device_bulk_abort(usbd_xfer_handle xfer)
1419 {
1420         DPRINTF(D_TRACE, ("Bab "));
1421 }
1422
1423 static void
1424 slhci_device_bulk_close(usbd_pipe_handle pipe)
1425 {
1426         DPRINTF(D_TRACE, ("Bcl "));
1427 }
1428
1429 static void
1430 slhci_device_bulk_done(usbd_xfer_handle xfer)
1431 {
1432         DPRINTF(D_TRACE, ("Bdn "));
1433 }
1434
1435 #define DATA0_RD        (0x03)
1436 #define DATA0_WR        (0x07)
1437 #define SLHCI_TIMEOUT   (5000)
1438
1439 /*
1440  * Do a transaction.
1441  * return 1 if ACK, 0 if NAK, -1 if error.
1442  */
1443 static int
1444 slhci_transaction(struct slhci_softc *sc, usbd_pipe_handle pipe,
1445         u_int8_t pid, int len, u_char *buf, u_int8_t toggle)
1446 {
1447 #ifdef SLHCI_DEBUG
1448         char str[64];
1449         int i;
1450 #endif
1451         int timeout;
1452         int ls_via_hub = 0;
1453         int pl;
1454         u_int8_t isr;
1455         u_int8_t result = 0;
1456         u_int8_t devaddr = pipe->device->address;
1457         u_int8_t endpointaddr = pipe->endpoint->edesc->bEndpointAddress;
1458         u_int8_t endpoint;
1459         u_int8_t cmd = DATA0_RD;
1460
1461         endpoint = UE_GET_ADDR(endpointaddr);
1462         DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ",
1463                 pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint));
1464
1465         /* Set registers */
1466         sl11write(sc, SL11_E0ADDR, 0x40);
1467         sl11write(sc, SL11_E0LEN,  len);
1468         sl11write(sc, SL11_E0PID,  (pid << 4) + endpoint);
1469         sl11write(sc, SL11_E0DEV,  devaddr);
1470
1471         /* Set buffer unless PID_IN */
1472         if (pid != SL11_PID_IN) {
1473                 if (len > 0)
1474                         sl11write_region(sc, 0x40, buf, len);
1475                 cmd = DATA0_WR;
1476         }
1477
1478         /* timing ? */
1479         pl = (len >> 3) + 3;
1480
1481         /* Low speed device via HUB */
1482         /* XXX does not work... */
1483         if ((sc->sc_fullspeed) && pipe->device->speed == USB_SPEED_LOW) {
1484                 pl = len + 16;
1485                 cmd |= SL11_EPCTRL_PREAMBLE;
1486
1487                 /*
1488                  * SL811HS/T rev 1.2 has a bug, when it got PID_IN
1489                  * from LowSpeed device via HUB.
1490                  */
1491                 if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) {
1492                         ls_via_hub = 1;
1493                         DPRINTF(D_MSG, ("LSvH "));
1494                 }
1495         }
1496
1497         /* timing ? */
1498         if (sl11read(sc, SL811_CSOF) <= (u_int8_t)pl)
1499                 cmd |= SL11_EPCTRL_SOF;
1500
1501         /* Transfer */
1502         sl11write(sc, SL11_ISR, 0xff);
1503         sl11write(sc, SL11_E0CTRL, cmd | toggle);
1504
1505         /* Polling */
1506         for (timeout = SLHCI_TIMEOUT; timeout; timeout--) {
1507                 isr = sl11read(sc, SL11_ISR);
1508                 if ((isr & SL11_ISR_USBA))
1509                         break;
1510         }
1511
1512         /* Check result status */
1513         result = sl11read(sc, SL11_E0STAT);
1514         if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) {
1515                 /* Resend PID_IN within 20usec */
1516                 sl11write(sc, SL11_ISR, 0xff);
1517                 sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM);
1518         }
1519
1520         sl11write(sc, SL11_ISR, 0xff);
1521
1522         DPRINTF(D_XFER, ("t=%d i=%x ", SLHCI_TIMEOUT - timeout, isr));
1523 #ifdef SLHCI_DEBUG
1524         bitmask_snprintf(result,
1525                 "\20\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK",
1526                 str, sizeof(str));
1527         DPRINTF(D_XFER, ("STAT=%s ", str));
1528 #endif
1529
1530         if ((result & SL11_EPSTAT_ERROR))
1531                 return -1;
1532
1533         if ((result & SL11_EPSTAT_NAK))
1534                 return 0;
1535
1536         /* Read buffer if PID_IN */
1537         if (pid == SL11_PID_IN && len > 0) {
1538                 sl11read_region(sc, buf, 0x40, len);
1539 #ifdef SLHCI_DEBUG
1540                 for (i = 0; i < len; i++)
1541                         DPRINTF(D_XFER, ("%02X ", buf[i]));
1542 #endif
1543         }
1544
1545         return 1;
1546 }
1547
1548 void
1549 slhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
1550 {
1551         xfer->status = status;
1552         usb_transfer_complete(xfer);
1553 }
1554
1555 void
1556 slhci_device_clear_toggle(usbd_pipe_handle pipe)
1557 {
1558         DPRINTF(D_TRACE, ("SLdevice_clear_toggle "));
1559 }
1560
1561 #ifdef SLHCI_DEBUG
1562 void
1563 print_req(usb_device_request_t *r)
1564 {
1565         char *xmes[]={
1566                 "GETSTAT",
1567                 "CLRFEAT",
1568                 "res",
1569                 "SETFEAT",
1570                 "res",
1571                 "SETADDR",
1572                 "GETDESC",
1573                 "SETDESC",
1574                 "GETCONF",
1575                 "SETCONF",
1576                 "GETIN/F",
1577                 "SETIN/F",
1578                 "SYNC_FR"
1579         };
1580         int req, type, value, index, len;
1581
1582         req   = r->bRequest;
1583         type  = r->bmRequestType;
1584         value = UGETW(r->wValue);
1585         index = UGETW(r->wIndex);
1586         len   = UGETW(r->wLength);
1587
1588         printf("%x,%s,v=%d,i=%d,l=%d ",
1589                 type, xmes[req], value, index, len);
1590 }
1591
1592 void
1593 print_req_hub(usb_device_request_t *r)
1594 {
1595         struct {
1596                 int req;
1597                 int type;
1598                 char *str;
1599         } conf[] = {
1600                 { 1, 0x20, "ClrHubFeat"  },
1601                 { 1, 0x23, "ClrPortFeat" },
1602                 { 2, 0xa3, "GetBusState" },
1603                 { 6, 0xa0, "GetHubDesc"  },
1604                 { 0, 0xa0, "GetHubStat"  },
1605                 { 0, 0xa3, "GetPortStat" },
1606                 { 7, 0x20, "SetHubDesc"  },
1607                 { 3, 0x20, "SetHubFeat"  },
1608                 { 3, 0x23, "SetPortFeat" },
1609                 {-1, 0, NULL},
1610         };
1611         int i;
1612         int value, index, len;
1613
1614         value = UGETW(r->wValue);
1615         index = UGETW(r->wIndex);
1616         len   = UGETW(r->wLength);
1617         for (i = 0; ; i++) {
1618                 if (conf[i].req == -1 )
1619                         return print_req(r);
1620                 if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) {
1621                         printf("%s", conf[i].str);
1622                         break;
1623                 }
1624         }
1625         printf(",v=%d,i=%d,l=%d ", value, index, len);
1626 }
1627
1628 void
1629 print_dumpreg(struct slhci_softc *sc)
1630 {
1631         printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x,"
1632                "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,",
1633                 sl11read(sc, 0),  sl11read(sc, 1),
1634                 sl11read(sc, 2),  sl11read(sc, 3),
1635                 sl11read(sc, 4),  sl11read(sc, 8),
1636                 sl11read(sc, 9),  sl11read(sc, 10),
1637                 sl11read(sc, 11), sl11read(sc, 12)
1638         );
1639         printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ",
1640                 sl11read(sc, 5), sl11read(sc, 6),
1641                 sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15)
1642         );
1643 }
1644
1645 void
1646 print_xfer(usbd_xfer_handle xfer)
1647 {
1648         printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,",
1649                 xfer->length, xfer->actlen, xfer->flags, xfer->timeout);
1650         printf("request{ ");
1651         print_req_hub(&xfer->request);
1652         printf("} ");
1653 }
1654 #endif /* SLHCI_DEBUG */