[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/sl811hs.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  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: src/sys/dev/usb/sl811hs.c,v 1.6 2007/06/19 10:28:08 delphij Exp $");
 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                 ? "\2\x8""D+\7RESUME\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA"
471                 : "\2\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(