xref: /freebsd/sys/dev/usb/controller/uss820dci.c (revision 25dd52cdb10d223b9258836e23cc6ae4ea333b86)
1 /* $FreeBSD$ */
2 /*-
3  * Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 /*
29  * This file contains the driver for the USS820 series USB Device
30  * Controller
31  *
32  * NOTE: The datasheet does not document everything.
33  */
34 
35 #include <dev/usb/usb.h>
36 #include <dev/usb/usb_mfunc.h>
37 #include <dev/usb/usb_revision.h>
38 #include <dev/usb/usb_error.h>
39 
40 #define	USB_DEBUG_VAR uss820dcidebug
41 
42 #include <dev/usb/usb_core.h>
43 #include <dev/usb/usb_debug.h>
44 #include <dev/usb/usb_busdma.h>
45 #include <dev/usb/usb_process.h>
46 #include <dev/usb/usb_transfer.h>
47 #include <dev/usb/usb_device.h>
48 #include <dev/usb/usb_hub.h>
49 #include <dev/usb/usb_util.h>
50 
51 #include <dev/usb/usb_controller.h>
52 #include <dev/usb/usb_bus.h>
53 #include <dev/usb/controller/uss820dci.h>
54 
55 #define	USS820_DCI_BUS2SC(bus) \
56    ((struct uss820dci_softc *)(((uint8_t *)(bus)) - \
57     ((uint8_t *)&(((struct uss820dci_softc *)0)->sc_bus))))
58 
59 #define	USS820_DCI_PC2SC(pc) \
60    USS820_DCI_BUS2SC(USB_DMATAG_TO_XROOT((pc)->tag_parent)->bus)
61 
62 #if USB_DEBUG
63 static int uss820dcidebug = 0;
64 
65 SYSCTL_NODE(_hw_usb, OID_AUTO, uss820dci, CTLFLAG_RW, 0, "USB uss820dci");
66 SYSCTL_INT(_hw_usb_uss820dci, OID_AUTO, debug, CTLFLAG_RW,
67     &uss820dcidebug, 0, "uss820dci debug level");
68 #endif
69 
70 #define	USS820_DCI_INTR_ENDPT 1
71 
72 /* prototypes */
73 
74 struct usb_bus_methods uss820dci_bus_methods;
75 struct usb_pipe_methods uss820dci_device_bulk_methods;
76 struct usb_pipe_methods uss820dci_device_ctrl_methods;
77 struct usb_pipe_methods uss820dci_device_intr_methods;
78 struct usb_pipe_methods uss820dci_device_isoc_fs_methods;
79 
80 static uss820dci_cmd_t uss820dci_setup_rx;
81 static uss820dci_cmd_t uss820dci_data_rx;
82 static uss820dci_cmd_t uss820dci_data_tx;
83 static uss820dci_cmd_t uss820dci_data_tx_sync;
84 static void	uss820dci_device_done(struct usb_xfer *, usb_error_t);
85 static void	uss820dci_do_poll(struct usb_bus *);
86 static void	uss820dci_standard_done(struct usb_xfer *);
87 static void	uss820dci_intr_set(struct usb_xfer *, uint8_t);
88 static void	uss820dci_update_shared_1(struct uss820dci_softc *, uint8_t,
89 		    uint8_t, uint8_t);
90 static void	uss820dci_root_intr(struct uss820dci_softc *);
91 
92 /*
93  * Here is a list of what the USS820D chip can support. The main
94  * limitation is that the sum of the buffer sizes must be less than
95  * 1120 bytes.
96  */
97 static const struct usb_hw_ep_profile
98 	uss820dci_ep_profile[] = {
99 
100 	[0] = {
101 		.max_in_frame_size = 32,
102 		.max_out_frame_size = 32,
103 		.is_simplex = 0,
104 		.support_control = 1,
105 	},
106 	[1] = {
107 		.max_in_frame_size = 64,
108 		.max_out_frame_size = 64,
109 		.is_simplex = 0,
110 		.support_multi_buffer = 1,
111 		.support_bulk = 1,
112 		.support_interrupt = 1,
113 		.support_in = 1,
114 		.support_out = 1,
115 	},
116 	[2] = {
117 		.max_in_frame_size = 8,
118 		.max_out_frame_size = 8,
119 		.is_simplex = 0,
120 		.support_multi_buffer = 1,
121 		.support_bulk = 1,
122 		.support_interrupt = 1,
123 		.support_in = 1,
124 		.support_out = 1,
125 	},
126 	[3] = {
127 		.max_in_frame_size = 256,
128 		.max_out_frame_size = 256,
129 		.is_simplex = 0,
130 		.support_multi_buffer = 1,
131 		.support_isochronous = 1,
132 		.support_in = 1,
133 		.support_out = 1,
134 	},
135 };
136 
137 static void
138 uss820dci_update_shared_1(struct uss820dci_softc *sc, uint8_t reg,
139     uint8_t keep_mask, uint8_t set_mask)
140 {
141 	uint8_t temp;
142 
143 	USS820_WRITE_1(sc, USS820_PEND, 1);
144 	temp = USS820_READ_1(sc, reg);
145 	temp &= (keep_mask);
146 	temp |= (set_mask);
147 	USS820_WRITE_1(sc, reg, temp);
148 	USS820_WRITE_1(sc, USS820_PEND, 0);
149 }
150 
151 static void
152 uss820dci_get_hw_ep_profile(struct usb_device *udev,
153     const struct usb_hw_ep_profile **ppf, uint8_t ep_addr)
154 {
155 	if (ep_addr == 0) {
156 		*ppf = uss820dci_ep_profile + 0;
157 	} else if (ep_addr < 5) {
158 		*ppf = uss820dci_ep_profile + 1;
159 	} else if (ep_addr < 7) {
160 		*ppf = uss820dci_ep_profile + 2;
161 	} else if (ep_addr == 7) {
162 		*ppf = uss820dci_ep_profile + 3;
163 	} else {
164 		*ppf = NULL;
165 	}
166 }
167 
168 static void
169 uss820dci_pull_up(struct uss820dci_softc *sc)
170 {
171 	uint8_t temp;
172 
173 	/* pullup D+, if possible */
174 
175 	if (!sc->sc_flags.d_pulled_up &&
176 	    sc->sc_flags.port_powered) {
177 		sc->sc_flags.d_pulled_up = 1;
178 
179 		DPRINTF("\n");
180 
181 		temp = USS820_READ_1(sc, USS820_MCSR);
182 		temp |= USS820_MCSR_DPEN;
183 		USS820_WRITE_1(sc, USS820_MCSR, temp);
184 	}
185 }
186 
187 static void
188 uss820dci_pull_down(struct uss820dci_softc *sc)
189 {
190 	uint8_t temp;
191 
192 	/* pulldown D+, if possible */
193 
194 	if (sc->sc_flags.d_pulled_up) {
195 		sc->sc_flags.d_pulled_up = 0;
196 
197 		DPRINTF("\n");
198 
199 		temp = USS820_READ_1(sc, USS820_MCSR);
200 		temp &= ~USS820_MCSR_DPEN;
201 		USS820_WRITE_1(sc, USS820_MCSR, temp);
202 	}
203 }
204 
205 static void
206 uss820dci_wakeup_peer(struct uss820dci_softc *sc)
207 {
208 	if (!(sc->sc_flags.status_suspend)) {
209 		return;
210 	}
211 	DPRINTFN(0, "not supported\n");
212 }
213 
214 static void
215 uss820dci_set_address(struct uss820dci_softc *sc, uint8_t addr)
216 {
217 	DPRINTFN(5, "addr=%d\n", addr);
218 
219 	USS820_WRITE_1(sc, USS820_FADDR, addr);
220 }
221 
222 static uint8_t
223 uss820dci_setup_rx(struct uss820dci_td *td)
224 {
225 	struct uss820dci_softc *sc;
226 	struct usb_device_request req;
227 	uint16_t count;
228 	uint8_t rx_stat;
229 	uint8_t temp;
230 
231 	/* select the correct endpoint */
232 	bus_space_write_1(td->io_tag, td->io_hdl,
233 	    USS820_EPINDEX, td->ep_index);
234 
235 	/* read out FIFO status */
236 	rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
237 	    USS820_RXSTAT);
238 
239 	/* get pointer to softc */
240 	sc = USS820_DCI_PC2SC(td->pc);
241 
242 	DPRINTFN(5, "rx_stat=0x%02x rem=%u\n", rx_stat, td->remainder);
243 
244 	if (!(rx_stat & USS820_RXSTAT_RXSETUP)) {
245 		goto not_complete;
246 	}
247 	/* clear did stall */
248 	td->did_stall = 0;
249 
250 	/* clear stall and all I/O */
251 	uss820dci_update_shared_1(sc, USS820_EPCON,
252 	    0xFF ^ (USS820_EPCON_TXSTL |
253 	    USS820_EPCON_RXSTL |
254 	    USS820_EPCON_RXIE |
255 	    USS820_EPCON_TXOE), 0);
256 
257 	/* clear end overwrite flag */
258 	uss820dci_update_shared_1(sc, USS820_RXSTAT,
259 	    0xFF ^ USS820_RXSTAT_EDOVW, 0);
260 
261 	/* get the packet byte count */
262 	count = bus_space_read_1(td->io_tag, td->io_hdl,
263 	    USS820_RXCNTL);
264 	count |= (bus_space_read_1(td->io_tag, td->io_hdl,
265 	    USS820_RXCNTH) << 8);
266 	count &= 0x3FF;
267 
268 	/* verify data length */
269 	if (count != td->remainder) {
270 		DPRINTFN(0, "Invalid SETUP packet "
271 		    "length, %d bytes\n", count);
272 		goto setup_not_complete;
273 	}
274 	if (count != sizeof(req)) {
275 		DPRINTFN(0, "Unsupported SETUP packet "
276 		    "length, %d bytes\n", count);
277 		goto setup_not_complete;
278 	}
279 	/* receive data */
280 	bus_space_read_multi_1(td->io_tag, td->io_hdl,
281 	    USS820_RXDAT, (void *)&req, sizeof(req));
282 
283 	/* read out FIFO status */
284 	rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
285 	    USS820_RXSTAT);
286 
287 	if (rx_stat & (USS820_RXSTAT_EDOVW |
288 	    USS820_RXSTAT_STOVW)) {
289 		DPRINTF("new SETUP packet received\n");
290 		return (1);		/* not complete */
291 	}
292 	/* clear receive setup bit */
293 	uss820dci_update_shared_1(sc, USS820_RXSTAT,
294 	    0xFF ^ (USS820_RXSTAT_RXSETUP |
295 	    USS820_RXSTAT_EDOVW |
296 	    USS820_RXSTAT_STOVW), 0);
297 
298 	/* set RXFFRC bit */
299 	temp = bus_space_read_1(td->io_tag, td->io_hdl,
300 	    USS820_RXCON);
301 	temp |= USS820_RXCON_RXFFRC;
302 	bus_space_write_1(td->io_tag, td->io_hdl,
303 	    USS820_RXCON, temp);
304 
305 	/* copy data into real buffer */
306 	usb2_copy_in(td->pc, 0, &req, sizeof(req));
307 
308 	td->offset = sizeof(req);
309 	td->remainder = 0;
310 
311 	/* sneak peek the set address */
312 	if ((req.bmRequestType == UT_WRITE_DEVICE) &&
313 	    (req.bRequest == UR_SET_ADDRESS)) {
314 		sc->sc_dv_addr = req.wValue[0] & 0x7F;
315 	} else {
316 		sc->sc_dv_addr = 0xFF;
317 	}
318 	return (0);			/* complete */
319 
320 setup_not_complete:
321 
322 	/* set RXFFRC bit */
323 	temp = bus_space_read_1(td->io_tag, td->io_hdl,
324 	    USS820_RXCON);
325 	temp |= USS820_RXCON_RXFFRC;
326 	bus_space_write_1(td->io_tag, td->io_hdl,
327 	    USS820_RXCON, temp);
328 
329 	/* FALLTHROUGH */
330 
331 not_complete:
332 	/* abort any ongoing transfer */
333 	if (!td->did_stall) {
334 		DPRINTFN(5, "stalling\n");
335 		/* set stall */
336 		uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF,
337 		    (USS820_EPCON_TXSTL | USS820_EPCON_RXSTL));
338 
339 		td->did_stall = 1;
340 	}
341 
342 	/* clear end overwrite flag, if any */
343 	if (rx_stat & USS820_RXSTAT_RXSETUP) {
344 		uss820dci_update_shared_1(sc, USS820_RXSTAT,
345 		    0xFF ^ (USS820_RXSTAT_EDOVW |
346 		    USS820_RXSTAT_STOVW |
347 		    USS820_RXSTAT_RXSETUP), 0);
348 	}
349 	return (1);			/* not complete */
350 
351 }
352 
353 static uint8_t
354 uss820dci_data_rx(struct uss820dci_td *td)
355 {
356 	struct usb_page_search buf_res;
357 	uint16_t count;
358 	uint8_t rx_flag;
359 	uint8_t rx_stat;
360 	uint8_t rx_cntl;
361 	uint8_t to;
362 	uint8_t got_short;
363 
364 	to = 2;				/* don't loop forever! */
365 	got_short = 0;
366 
367 	/* select the correct endpoint */
368 	bus_space_write_1(td->io_tag, td->io_hdl, USS820_EPINDEX, td->ep_index);
369 
370 	/* check if any of the FIFO banks have data */
371 repeat:
372 	/* read out FIFO flag */
373 	rx_flag = bus_space_read_1(td->io_tag, td->io_hdl,
374 	    USS820_RXFLG);
375 	/* read out FIFO status */
376 	rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
377 	    USS820_RXSTAT);
378 
379 	DPRINTFN(5, "rx_stat=0x%02x rx_flag=0x%02x rem=%u\n",
380 	    rx_stat, rx_flag, td->remainder);
381 
382 	if (rx_stat & (USS820_RXSTAT_RXSETUP |
383 	    USS820_RXSTAT_RXSOVW |
384 	    USS820_RXSTAT_EDOVW)) {
385 		if (td->remainder == 0) {
386 			/*
387 			 * We are actually complete and have
388 			 * received the next SETUP
389 			 */
390 			DPRINTFN(5, "faking complete\n");
391 			return (0);	/* complete */
392 		}
393 		/*
394 	         * USB Host Aborted the transfer.
395 	         */
396 		td->error = 1;
397 		return (0);		/* complete */
398 	}
399 	/* check for errors */
400 	if (rx_flag & (USS820_RXFLG_RXOVF |
401 	    USS820_RXFLG_RXURF)) {
402 		DPRINTFN(5, "overflow or underflow\n");
403 		/* should not happen */
404 		td->error = 1;
405 		return (0);		/* complete */
406 	}
407 	/* check status */
408 	if (!(rx_flag & (USS820_RXFLG_RXFIF0 |
409 	    USS820_RXFLG_RXFIF1))) {
410 
411 		/* read out EPCON register */
412 		/* enable RX input */
413 		if (!td->did_enable) {
414 			uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc),
415 			    USS820_EPCON, 0xFF, USS820_EPCON_RXIE);
416 			td->did_enable = 1;
417 		}
418 		return (1);		/* not complete */
419 	}
420 	/* get the packet byte count */
421 	count = bus_space_read_1(td->io_tag, td->io_hdl,
422 	    USS820_RXCNTL);
423 
424 	count |= (bus_space_read_1(td->io_tag, td->io_hdl,
425 	    USS820_RXCNTH) << 8);
426 	count &= 0x3FF;
427 
428 	DPRINTFN(5, "count=0x%04x\n", count);
429 
430 	/* verify the packet byte count */
431 	if (count != td->max_packet_size) {
432 		if (count < td->max_packet_size) {
433 			/* we have a short packet */
434 			td->short_pkt = 1;
435 			got_short = 1;
436 		} else {
437 			/* invalid USB packet */
438 			td->error = 1;
439 			return (0);	/* we are complete */
440 		}
441 	}
442 	/* verify the packet byte count */
443 	if (count > td->remainder) {
444 		/* invalid USB packet */
445 		td->error = 1;
446 		return (0);		/* we are complete */
447 	}
448 	while (count > 0) {
449 		usb2_get_page(td->pc, td->offset, &buf_res);
450 
451 		/* get correct length */
452 		if (buf_res.length > count) {
453 			buf_res.length = count;
454 		}
455 		/* receive data */
456 		bus_space_read_multi_1(td->io_tag, td->io_hdl,
457 		    USS820_RXDAT, buf_res.buffer, buf_res.length);
458 
459 		/* update counters */
460 		count -= buf_res.length;
461 		td->offset += buf_res.length;
462 		td->remainder -= buf_res.length;
463 	}
464 
465 	/* set RXFFRC bit */
466 	rx_cntl = bus_space_read_1(td->io_tag, td->io_hdl,
467 	    USS820_RXCON);
468 	rx_cntl |= USS820_RXCON_RXFFRC;
469 	bus_space_write_1(td->io_tag, td->io_hdl,
470 	    USS820_RXCON, rx_cntl);
471 
472 	/* check if we are complete */
473 	if ((td->remainder == 0) || got_short) {
474 		if (td->short_pkt) {
475 			/* we are complete */
476 			return (0);
477 		}
478 		/* else need to receive a zero length packet */
479 	}
480 	if (--to) {
481 		goto repeat;
482 	}
483 	return (1);			/* not complete */
484 }
485 
486 static uint8_t
487 uss820dci_data_tx(struct uss820dci_td *td)
488 {
489 	struct usb_page_search buf_res;
490 	uint16_t count;
491 	uint16_t count_copy;
492 	uint8_t rx_stat;
493 	uint8_t tx_flag;
494 	uint8_t to;
495 
496 	/* select the correct endpoint */
497 	bus_space_write_1(td->io_tag, td->io_hdl,
498 	    USS820_EPINDEX, td->ep_index);
499 
500 	to = 2;				/* don't loop forever! */
501 
502 repeat:
503 	/* read out TX FIFO flags */
504 	tx_flag = bus_space_read_1(td->io_tag, td->io_hdl,
505 	    USS820_TXFLG);
506 
507 	/* read out RX FIFO status last */
508 	rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
509 	    USS820_RXSTAT);
510 
511 	DPRINTFN(5, "rx_stat=0x%02x tx_flag=0x%02x rem=%u\n",
512 	    rx_stat, tx_flag, td->remainder);
513 
514 	if (rx_stat & (USS820_RXSTAT_RXSETUP |
515 	    USS820_RXSTAT_RXSOVW |
516 	    USS820_RXSTAT_EDOVW)) {
517 		/*
518 	         * The current transfer was aborted
519 	         * by the USB Host
520 	         */
521 		td->error = 1;
522 		return (0);		/* complete */
523 	}
524 	if (tx_flag & (USS820_TXFLG_TXOVF |
525 	    USS820_TXFLG_TXURF)) {
526 		td->error = 1;
527 		return (0);		/* complete */
528 	}
529 	if (tx_flag & USS820_TXFLG_TXFIF0) {
530 		if (tx_flag & USS820_TXFLG_TXFIF1) {
531 			return (1);	/* not complete */
532 		}
533 	}
534 	if ((!td->support_multi_buffer) &&
535 	    (tx_flag & (USS820_TXFLG_TXFIF0 |
536 	    USS820_TXFLG_TXFIF1))) {
537 		return (1);		/* not complete */
538 	}
539 	count = td->max_packet_size;
540 	if (td->remainder < count) {
541 		/* we have a short packet */
542 		td->short_pkt = 1;
543 		count = td->remainder;
544 	}
545 	count_copy = count;
546 	while (count > 0) {
547 
548 		usb2_get_page(td->pc, td->offset, &buf_res);
549 
550 		/* get correct length */
551 		if (buf_res.length > count) {
552 			buf_res.length = count;
553 		}
554 		/* transmit data */
555 		bus_space_write_multi_1(td->io_tag, td->io_hdl,
556 		    USS820_TXDAT, buf_res.buffer, buf_res.length);
557 
558 		/* update counters */
559 		count -= buf_res.length;
560 		td->offset += buf_res.length;
561 		td->remainder -= buf_res.length;
562 	}
563 
564 	/* post-write high packet byte count first */
565 	bus_space_write_1(td->io_tag, td->io_hdl,
566 	    USS820_TXCNTH, count_copy >> 8);
567 
568 	/* post-write low packet byte count last */
569 	bus_space_write_1(td->io_tag, td->io_hdl,
570 	    USS820_TXCNTL, count_copy);
571 
572 	/*
573 	 * Enable TX output, which must happen after that we have written
574 	 * data into the FIFO. This is undocumented.
575 	 */
576 	if (!td->did_enable) {
577 		uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc),
578 		    USS820_EPCON, 0xFF, USS820_EPCON_TXOE);
579 		td->did_enable = 1;
580 	}
581 	/* check remainder */
582 	if (td->remainder == 0) {
583 		if (td->short_pkt) {
584 			return (0);	/* complete */
585 		}
586 		/* else we need to transmit a short packet */
587 	}
588 	if (--to) {
589 		goto repeat;
590 	}
591 	return (1);			/* not complete */
592 }
593 
594 static uint8_t
595 uss820dci_data_tx_sync(struct uss820dci_td *td)
596 {
597 	struct uss820dci_softc *sc;
598 	uint8_t rx_stat;
599 	uint8_t tx_flag;
600 
601 	/* select the correct endpoint */
602 	bus_space_write_1(td->io_tag, td->io_hdl,
603 	    USS820_EPINDEX, td->ep_index);
604 
605 	/* read out TX FIFO flag */
606 	tx_flag = bus_space_read_1(td->io_tag, td->io_hdl,
607 	    USS820_TXFLG);
608 
609 	/* read out RX FIFO status last */
610 	rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
611 	    USS820_RXSTAT);
612 
613 	DPRINTFN(5, "rx_stat=0x%02x rem=%u\n", rx_stat, td->remainder);
614 
615 	if (rx_stat & (USS820_RXSTAT_RXSETUP |
616 	    USS820_RXSTAT_RXSOVW |
617 	    USS820_RXSTAT_EDOVW)) {
618 		DPRINTFN(5, "faking complete\n");
619 		/* Race condition */
620 		return (0);		/* complete */
621 	}
622 	DPRINTFN(5, "tx_flag=0x%02x rem=%u\n",
623 	    tx_flag, td->remainder);
624 
625 	if (tx_flag & (USS820_TXFLG_TXOVF |
626 	    USS820_TXFLG_TXURF)) {
627 		td->error = 1;
628 		return (0);		/* complete */
629 	}
630 	if (tx_flag & (USS820_TXFLG_TXFIF0 |
631 	    USS820_TXFLG_TXFIF1)) {
632 		return (1);		/* not complete */
633 	}
634 	sc = USS820_DCI_PC2SC(td->pc);
635 	if (sc->sc_dv_addr != 0xFF) {
636 		/* write function address */
637 		uss820dci_set_address(sc, sc->sc_dv_addr);
638 	}
639 	return (0);			/* complete */
640 }
641 
642 static uint8_t
643 uss820dci_xfer_do_fifo(struct usb_xfer *xfer)
644 {
645 	struct uss820dci_td *td;
646 
647 	DPRINTFN(9, "\n");
648 
649 	td = xfer->td_transfer_cache;
650 	while (1) {
651 		if ((td->func) (td)) {
652 			/* operation in progress */
653 			break;
654 		}
655 		if (((void *)td) == xfer->td_transfer_last) {
656 			goto done;
657 		}
658 		if (td->error) {
659 			goto done;
660 		} else if (td->remainder > 0) {
661 			/*
662 			 * We had a short transfer. If there is no alternate
663 			 * next, stop processing !
664 			 */
665 			if (!td->alt_next) {
666 				goto done;
667 			}
668 		}
669 		/*
670 		 * Fetch the next transfer descriptor.
671 		 */
672 		td = td->obj_next;
673 		xfer->td_transfer_cache = td;
674 	}
675 	return (1);			/* not complete */
676 
677 done:
678 	/* compute all actual lengths */
679 
680 	uss820dci_standard_done(xfer);
681 
682 	return (0);			/* complete */
683 }
684 
685 static void
686 uss820dci_interrupt_poll(struct uss820dci_softc *sc)
687 {
688 	struct usb_xfer *xfer;
689 
690 repeat:
691 	TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
692 		if (!uss820dci_xfer_do_fifo(xfer)) {
693 			/* queue has been modified */
694 			goto repeat;
695 		}
696 	}
697 }
698 
699 static void
700 uss820dci_wait_suspend(struct uss820dci_softc *sc, uint8_t on)
701 {
702 	uint8_t scr;
703 	uint8_t scratch;
704 
705 	scr = USS820_READ_1(sc, USS820_SCR);
706 	scratch = USS820_READ_1(sc, USS820_SCRATCH);
707 
708 	if (on) {
709 		scr |= USS820_SCR_IE_SUSP;
710 		scratch &= ~USS820_SCRATCH_IE_RESUME;
711 	} else {
712 		scr &= ~USS820_SCR_IE_SUSP;
713 		scratch |= USS820_SCRATCH_IE_RESUME;
714 	}
715 
716 	USS820_WRITE_1(sc, USS820_SCR, scr);
717 	USS820_WRITE_1(sc, USS820_SCRATCH, scratch);
718 }
719 
720 void
721 uss820dci_interrupt(struct uss820dci_softc *sc)
722 {
723 	uint8_t ssr;
724 	uint8_t event;
725 
726 	USB_BUS_LOCK(&sc->sc_bus);
727 
728 	ssr = USS820_READ_1(sc, USS820_SSR);
729 
730 	ssr &= (USS820_SSR_SUSPEND |
731 	    USS820_SSR_RESUME |
732 	    USS820_SSR_RESET);
733 
734 	/* acknowledge all interrupts */
735 
736 	uss820dci_update_shared_1(sc, USS820_SSR, 0, 0);
737 
738 	/* check for any bus state change interrupts */
739 
740 	if (ssr) {
741 
742 		event = 0;
743 
744 		if (ssr & USS820_SSR_RESET) {
745 			sc->sc_flags.status_bus_reset = 1;
746 			sc->sc_flags.status_suspend = 0;
747 			sc->sc_flags.change_suspend = 0;
748 			sc->sc_flags.change_connect = 1;
749 
750 			/* disable resume interrupt */
751 			uss820dci_wait_suspend(sc, 1);
752 
753 			event = 1;
754 		}
755 		/*
756 	         * If "RESUME" and "SUSPEND" is set at the same time
757 	         * we interpret that like "RESUME". Resume is set when
758 	         * there is at least 3 milliseconds of inactivity on
759 	         * the USB BUS.
760 	         */
761 		if (ssr & USS820_SSR_RESUME) {
762 			if (sc->sc_flags.status_suspend) {
763 				sc->sc_flags.status_suspend = 0;
764 				sc->sc_flags.change_suspend = 1;
765 				/* disable resume interrupt */
766 				uss820dci_wait_suspend(sc, 1);
767 				event = 1;
768 			}
769 		} else if (ssr & USS820_SSR_SUSPEND) {
770 			if (!sc->sc_flags.status_suspend) {
771 				sc->sc_flags.status_suspend = 1;
772 				sc->sc_flags.change_suspend = 1;
773 				/* enable resume interrupt */
774 				uss820dci_wait_suspend(sc, 0);
775 				event = 1;
776 			}
777 		}
778 		if (event) {
779 
780 			DPRINTF("real bus interrupt 0x%02x\n", ssr);
781 
782 			/* complete root HUB interrupt endpoint */
783 			uss820dci_root_intr(sc);
784 		}
785 	}
786 	/* acknowledge all SBI interrupts */
787 	uss820dci_update_shared_1(sc, USS820_SBI, 0, 0);
788 
789 	/* acknowledge all SBI1 interrupts */
790 	uss820dci_update_shared_1(sc, USS820_SBI1, 0, 0);
791 
792 	/* poll all active transfers */
793 	uss820dci_interrupt_poll(sc);
794 
795 	USB_BUS_UNLOCK(&sc->sc_bus);
796 }
797 
798 static void
799 uss820dci_setup_standard_chain_sub(struct uss820_std_temp *temp)
800 {
801 	struct uss820dci_td *td;
802 
803 	/* get current Transfer Descriptor */
804 	td = temp->td_next;
805 	temp->td = td;
806 
807 	/* prepare for next TD */
808 	temp->td_next = td->obj_next;
809 
810 	/* fill out the Transfer Descriptor */
811 	td->func = temp->func;
812 	td->pc = temp->pc;
813 	td->offset = temp->offset;
814 	td->remainder = temp->len;
815 	td->error = 0;
816 	td->did_enable = 0;
817 	td->did_stall = temp->did_stall;
818 	td->short_pkt = temp->short_pkt;
819 	td->alt_next = temp->setup_alt_next;
820 }
821 
822 static void
823 uss820dci_setup_standard_chain(struct usb_xfer *xfer)
824 {
825 	struct uss820_std_temp temp;
826 	struct uss820dci_softc *sc;
827 	struct uss820dci_td *td;
828 	uint32_t x;
829 	uint8_t ep_no;
830 
831 	DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
832 	    xfer->address, UE_GET_ADDR(xfer->endpoint),
833 	    xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
834 
835 	temp.max_frame_size = xfer->max_frame_size;
836 
837 	td = xfer->td_start[0];
838 	xfer->td_transfer_first = td;
839 	xfer->td_transfer_cache = td;
840 
841 	/* setup temp */
842 
843 	temp.td = NULL;
844 	temp.td_next = xfer->td_start[0];
845 	temp.offset = 0;
846 	temp.setup_alt_next = xfer->flags_int.short_frames_ok;
847 	temp.did_stall = !xfer->flags_int.control_stall;
848 
849 	sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
850 	ep_no = (xfer->endpoint & UE_ADDR);
851 
852 	/* check if we should prepend a setup message */
853 
854 	if (xfer->flags_int.control_xfr) {
855 		if (xfer->flags_int.control_hdr) {
856 
857 			temp.func = &uss820dci_setup_rx;
858 			temp.len = xfer->frlengths[0];
859 			temp.pc = xfer->frbuffers + 0;
860 			temp.short_pkt = temp.len ? 1 : 0;
861 			/* check for last frame */
862 			if (xfer->nframes == 1) {
863 				/* no STATUS stage yet, SETUP is last */
864 				if (xfer->flags_int.control_act)
865 					temp.setup_alt_next = 0;
866 			}
867 
868 			uss820dci_setup_standard_chain_sub(&temp);
869 		}
870 		x = 1;
871 	} else {
872 		x = 0;
873 	}
874 
875 	if (x != xfer->nframes) {
876 		if (xfer->endpoint & UE_DIR_IN) {
877 			temp.func = &uss820dci_data_tx;
878 		} else {
879 			temp.func = &uss820dci_data_rx;
880 		}
881 
882 		/* setup "pc" pointer */
883 		temp.pc = xfer->frbuffers + x;
884 	}
885 	while (x != xfer->nframes) {
886 
887 		/* DATA0 / DATA1 message */
888 
889 		temp.len = xfer->frlengths[x];
890 
891 		x++;
892 
893 		if (x == xfer->nframes) {
894 			if (xfer->flags_int.control_xfr) {
895 				if (xfer->flags_int.control_act) {
896 					temp.setup_alt_next = 0;
897 				}
898 			} else {
899 				temp.setup_alt_next = 0;
900 			}
901 		}
902 		if (temp.len == 0) {
903 
904 			/* make sure that we send an USB packet */
905 
906 			temp.short_pkt = 0;
907 
908 		} else {
909 
910 			/* regular data transfer */
911 
912 			temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1;
913 		}
914 
915 		uss820dci_setup_standard_chain_sub(&temp);
916 
917 		if (xfer->flags_int.isochronous_xfr) {
918 			temp.offset += temp.len;
919 		} else {
920 			/* get next Page Cache pointer */
921 			temp.pc = xfer->frbuffers + x;
922 		}
923 	}
924 
925 	/* check for control transfer */
926 	if (xfer->flags_int.control_xfr) {
927 		uint8_t need_sync;
928 
929 		/* always setup a valid "pc" pointer for status and sync */
930 		temp.pc = xfer->frbuffers + 0;
931 		temp.len = 0;
932 		temp.short_pkt = 0;
933 		temp.setup_alt_next = 0;
934 
935 		/* check if we should append a status stage */
936 		if (!xfer->flags_int.control_act) {
937 
938 			/*
939 			 * Send a DATA1 message and invert the current
940 			 * endpoint direction.
941 			 */
942 			if (xfer->endpoint & UE_DIR_IN) {
943 				temp.func = &uss820dci_data_rx;
944 				need_sync = 0;
945 			} else {
946 				temp.func = &uss820dci_data_tx;
947 				need_sync = 1;
948 			}
949 			temp.len = 0;
950 			temp.short_pkt = 0;
951 
952 			uss820dci_setup_standard_chain_sub(&temp);
953 			if (need_sync) {
954 				/* we need a SYNC point after TX */
955 				temp.func = &uss820dci_data_tx_sync;
956 				uss820dci_setup_standard_chain_sub(&temp);
957 			}
958 		}
959 	}
960 	/* must have at least one frame! */
961 	td = temp.td;
962 	xfer->td_transfer_last = td;
963 }
964 
965 static void
966 uss820dci_timeout(void *arg)
967 {
968 	struct usb_xfer *xfer = arg;
969 
970 	DPRINTF("xfer=%p\n", xfer);
971 
972 	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
973 
974 	/* transfer is transferred */
975 	uss820dci_device_done(xfer, USB_ERR_TIMEOUT);
976 }
977 
978 static void
979 uss820dci_intr_set(struct usb_xfer *xfer, uint8_t set)
980 {
981 	struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
982 	uint8_t ep_no = (xfer->endpoint & UE_ADDR);
983 	uint8_t ep_reg;
984 	uint8_t temp;
985 
986 	DPRINTFN(15, "endpoint 0x%02x\n", xfer->endpoint);
987 
988 	if (ep_no > 3) {
989 		ep_reg = USS820_SBIE1;
990 	} else {
991 		ep_reg = USS820_SBIE;
992 	}
993 
994 	ep_no &= 3;
995 	ep_no = 1 << (2 * ep_no);
996 
997 	if (xfer->flags_int.control_xfr) {
998 		if (xfer->flags_int.control_hdr) {
999 			ep_no <<= 1;	/* RX interrupt only */
1000 		} else {
1001 			ep_no |= (ep_no << 1);	/* RX and TX interrupt */
1002 		}
1003 	} else {
1004 		if (!(xfer->endpoint & UE_DIR_IN)) {
1005 			ep_no <<= 1;
1006 		}
1007 	}
1008 	temp = USS820_READ_1(sc, ep_reg);
1009 	if (set) {
1010 		temp |= ep_no;
1011 	} else {
1012 		temp &= ~ep_no;
1013 	}
1014 	USS820_WRITE_1(sc, ep_reg, temp);
1015 }
1016 
1017 static void
1018 uss820dci_start_standard_chain(struct usb_xfer *xfer)
1019 {
1020 	DPRINTFN(9, "\n");
1021 
1022 	/* poll one time */
1023 	if (uss820dci_xfer_do_fifo(xfer)) {
1024 
1025 		/*
1026 		 * Only enable the endpoint interrupt when we are
1027 		 * actually waiting for data, hence we are dealing
1028 		 * with level triggered interrupts !
1029 		 */
1030 		uss820dci_intr_set(xfer, 1);
1031 
1032 		/* put transfer on interrupt queue */
1033 		usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
1034 
1035 		/* start timeout, if any */
1036 		if (xfer->timeout != 0) {
1037 			usb2_transfer_timeout_ms(xfer,
1038 			    &uss820dci_timeout, xfer->timeout);
1039 		}
1040 	}
1041 }
1042 
1043 static void
1044 uss820dci_root_intr(struct uss820dci_softc *sc)
1045 {
1046 	DPRINTFN(9, "\n");
1047 
1048 	USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
1049 
1050 	/* set port bit */
1051 	sc->sc_hub_idata[0] = 0x02;	/* we only have one port */
1052 
1053 	uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
1054 	    sizeof(sc->sc_hub_idata));
1055 }
1056 
1057 static usb_error_t
1058 uss820dci_standard_done_sub(struct usb_xfer *xfer)
1059 {
1060 	struct uss820dci_td *td;
1061 	uint32_t len;
1062 	uint8_t error;
1063 
1064 	DPRINTFN(9, "\n");
1065 
1066 	td = xfer->td_transfer_cache;
1067 
1068 	do {
1069 		len = td->remainder;
1070 
1071 		if (xfer->aframes != xfer->nframes) {
1072 			/*
1073 		         * Verify the length and subtract
1074 		         * the remainder from "frlengths[]":
1075 		         */
1076 			if (len > xfer->frlengths[xfer->aframes]) {
1077 				td->error = 1;
1078 			} else {
1079 				xfer->frlengths[xfer->aframes] -= len;
1080 			}
1081 		}
1082 		/* Check for transfer error */
1083 		if (td->error) {
1084 			/* the transfer is finished */
1085 			error = 1;
1086 			td = NULL;
1087 			break;
1088 		}
1089 		/* Check for short transfer */
1090 		if (len > 0) {
1091 			if (xfer->flags_int.short_frames_ok) {
1092 				/* follow alt next */
1093 				if (td->alt_next) {
1094 					td = td->obj_next;
1095 				} else {
1096 					td = NULL;
1097 				}
1098 			} else {
1099 				/* the transfer is finished */
1100 				td = NULL;
1101 			}
1102 			error = 0;
1103 			break;
1104 		}
1105 		td = td->obj_next;
1106 
1107 		/* this USB frame is complete */
1108 		error = 0;
1109 		break;
1110 
1111 	} while (0);
1112 
1113 	/* update transfer cache */
1114 
1115 	xfer->td_transfer_cache = td;
1116 
1117 	return (error ?
1118 	    USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION);
1119 }
1120 
1121 static void
1122 uss820dci_standard_done(struct usb_xfer *xfer)
1123 {
1124 	usb_error_t err = 0;
1125 
1126 	DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
1127 	    xfer, xfer->pipe);
1128 
1129 	/* reset scanner */
1130 
1131 	xfer->td_transfer_cache = xfer->td_transfer_first;
1132 
1133 	if (xfer->flags_int.control_xfr) {
1134 
1135 		if (xfer->flags_int.control_hdr) {
1136 
1137 			err = uss820dci_standard_done_sub(xfer);
1138 		}
1139 		xfer->aframes = 1;
1140 
1141 		if (xfer->td_transfer_cache == NULL) {
1142 			goto done;
1143 		}
1144 	}
1145 	while (xfer->aframes != xfer->nframes) {
1146 
1147 		err = uss820dci_standard_done_sub(xfer);
1148 		xfer->aframes++;
1149 
1150 		if (xfer->td_transfer_cache == NULL) {
1151 			goto done;
1152 		}
1153 	}
1154 
1155 	if (xfer->flags_int.control_xfr &&
1156 	    !xfer->flags_int.control_act) {
1157 
1158 		err = uss820dci_standard_done_sub(xfer);
1159 	}
1160 done:
1161 	uss820dci_device_done(xfer, err);
1162 }
1163 
1164 /*------------------------------------------------------------------------*
1165  *	uss820dci_device_done
1166  *
1167  * NOTE: this function can be called more than one time on the
1168  * same USB transfer!
1169  *------------------------------------------------------------------------*/
1170 static void
1171 uss820dci_device_done(struct usb_xfer *xfer, usb_error_t error)
1172 {
1173 	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
1174 
1175 	DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
1176 	    xfer, xfer->pipe, error);
1177 
1178 	if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
1179 		uss820dci_intr_set(xfer, 0);
1180 	}
1181 	/* dequeue transfer and start next transfer */
1182 	usb2_transfer_done(xfer, error);
1183 }
1184 
1185 static void
1186 uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
1187     struct usb_pipe *pipe)
1188 {
1189 	struct uss820dci_softc *sc;
1190 	uint8_t ep_no;
1191 	uint8_t ep_type;
1192 	uint8_t ep_dir;
1193 	uint8_t temp;
1194 
1195 	USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
1196 
1197 	DPRINTFN(5, "pipe=%p\n", pipe);
1198 
1199 	if (xfer) {
1200 		/* cancel any ongoing transfers */
1201 		uss820dci_device_done(xfer, USB_ERR_STALLED);
1202 	}
1203 	/* set FORCESTALL */
1204 	sc = USS820_DCI_BUS2SC(udev->bus);
1205 	ep_no = (pipe->edesc->bEndpointAddress & UE_ADDR);
1206 	ep_dir = (pipe->edesc->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT));
1207 	ep_type = (pipe->edesc->bmAttributes & UE_XFERTYPE);
1208 
1209 	if (ep_type == UE_CONTROL) {
1210 		/* should not happen */
1211 		return;
1212 	}
1213 	USS820_WRITE_1(sc, USS820_EPINDEX, ep_no);
1214 
1215 	if (ep_dir == UE_DIR_IN) {
1216 		temp = USS820_EPCON_TXSTL;
1217 	} else {
1218 		temp = USS820_EPCON_RXSTL;
1219 	}
1220 	uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF, temp);
1221 }
1222 
1223 static void
1224 uss820dci_clear_stall_sub(struct uss820dci_softc *sc,
1225     uint8_t ep_no, uint8_t ep_type, uint8_t ep_dir)
1226 {
1227 	uint8_t temp;
1228 
1229 	if (ep_type == UE_CONTROL) {
1230 		/* clearing stall is not needed */
1231 		return;
1232 	}
1233 	/* select endpoint index */
1234 	USS820_WRITE_1(sc, USS820_EPINDEX, ep_no);
1235 
1236 	/* clear stall and disable I/O transfers */
1237 	if (ep_dir == UE_DIR_IN) {
1238 		temp = 0xFF ^ (USS820_EPCON_TXOE |
1239 		    USS820_EPCON_TXSTL);
1240 	} else {
1241 		temp = 0xFF ^ (USS820_EPCON_RXIE |
1242 		    USS820_EPCON_RXSTL);
1243 	}
1244 	uss820dci_update_shared_1(sc, USS820_EPCON, temp, 0);
1245 
1246 	if (ep_dir == UE_DIR_IN) {
1247 		/* reset data toggle */
1248 		USS820_WRITE_1(sc, USS820_TXSTAT,
1249 		    USS820_TXSTAT_TXSOVW);
1250 
1251 		/* reset FIFO */
1252 		temp = USS820_READ_1(sc, USS820_TXCON);
1253 		temp |= USS820_TXCON_TXCLR;
1254 		USS820_WRITE_1(sc, USS820_TXCON, temp);
1255 		temp &= ~USS820_TXCON_TXCLR;
1256 		USS820_WRITE_1(sc, USS820_TXCON, temp);
1257 	} else {
1258 
1259 		/* reset data toggle */
1260 		uss820dci_update_shared_1(sc, USS820_RXSTAT,
1261 		    0, USS820_RXSTAT_RXSOVW);
1262 
1263 		/* reset FIFO */
1264 		temp = USS820_READ_1(sc, USS820_RXCON);
1265 		temp |= USS820_RXCON_RXCLR;
1266 		temp &= ~USS820_RXCON_RXFFRC;
1267 		USS820_WRITE_1(sc, USS820_RXCON, temp);
1268 		temp &= ~USS820_RXCON_RXCLR;
1269 		USS820_WRITE_1(sc, USS820_RXCON, temp);
1270 	}
1271 }
1272 
1273 static void
1274 uss820dci_clear_stall(struct usb_device *udev, struct usb_pipe *pipe)
1275 {
1276 	struct uss820dci_softc *sc;
1277 	struct usb_endpoint_descriptor *ed;
1278 
1279 	USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
1280 
1281 	DPRINTFN(5, "pipe=%p\n", pipe);
1282 
1283 	/* check mode */
1284 	if (udev->flags.usb_mode != USB_MODE_DEVICE) {
1285 		/* not supported */
1286 		return;
1287 	}
1288 	/* get softc */
1289 	sc = USS820_DCI_BUS2SC(udev->bus);
1290 
1291 	/* get endpoint descriptor */
1292 	ed = pipe->edesc;
1293 
1294 	/* reset endpoint */
1295 	uss820dci_clear_stall_sub(sc,
1296 	    (ed->bEndpointAddress & UE_ADDR),
1297 	    (ed->bmAttributes & UE_XFERTYPE),
1298 	    (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT)));
1299 }
1300 
1301 usb_error_t
1302 uss820dci_init(struct uss820dci_softc *sc)
1303 {
1304 	const struct usb_hw_ep_profile *pf;
1305 	uint8_t n;
1306 	uint8_t temp;
1307 
1308 	DPRINTF("start\n");
1309 
1310 	/* set up the bus structure */
1311 	sc->sc_bus.usbrev = USB_REV_1_1;
1312 	sc->sc_bus.methods = &uss820dci_bus_methods;
1313 
1314 	USB_BUS_LOCK(&sc->sc_bus);
1315 
1316 	/* we always have VBUS */
1317 	sc->sc_flags.status_vbus = 1;
1318 
1319 	/* reset the chip */
1320 	USS820_WRITE_1(sc, USS820_SCR, USS820_SCR_SRESET);
1321 	DELAY(100);
1322 	USS820_WRITE_1(sc, USS820_SCR, 0);
1323 
1324 	/* wait for reset to complete */
1325 	for (n = 0;; n++) {
1326 
1327 		temp = USS820_READ_1(sc, USS820_MCSR);
1328 
1329 		if (temp & USS820_MCSR_INIT) {
1330 			break;
1331 		}
1332 		if (n == 100) {
1333 			USB_BUS_UNLOCK(&sc->sc_bus);
1334 			return (USB_ERR_INVAL);
1335 		}
1336 		/* wait a little for things to stabilise */
1337 		DELAY(100);
1338 	}
1339 
1340 	/* do a pulldown */
1341 	uss820dci_pull_down(sc);
1342 
1343 	/* wait 10ms for pulldown to stabilise */
1344 	usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100);
1345 
1346 	/* check hardware revision */
1347 	temp = USS820_READ_1(sc, USS820_REV);
1348 
1349 	if (temp < 0x13) {
1350 		USB_BUS_UNLOCK(&sc->sc_bus);
1351 		return (USB_ERR_INVAL);
1352 	}
1353 	/* enable interrupts */
1354 	USS820_WRITE_1(sc, USS820_SCR,
1355 	    USS820_SCR_T_IRQ |
1356 	    USS820_SCR_IE_RESET |
1357 	/* USS820_SCR_RWUPE | */
1358 	    USS820_SCR_IE_SUSP |
1359 	    USS820_SCR_IRQPOL);
1360 
1361 	/* enable interrupts */
1362 	USS820_WRITE_1(sc, USS820_SCRATCH,
1363 	    USS820_SCRATCH_IE_RESUME);
1364 
1365 	/* enable features */
1366 	USS820_WRITE_1(sc, USS820_MCSR,
1367 	    USS820_MCSR_BDFEAT |
1368 	    USS820_MCSR_FEAT);
1369 
1370 	sc->sc_flags.mcsr_feat = 1;
1371 
1372 	/* disable interrupts */
1373 	USS820_WRITE_1(sc, USS820_SBIE, 0);
1374 
1375 	/* disable interrupts */
1376 	USS820_WRITE_1(sc, USS820_SBIE1, 0);
1377 
1378 	/* disable all endpoints */
1379 	for (n = 0; n != USS820_EP_MAX; n++) {
1380 
1381 		/* select endpoint */
1382 		USS820_WRITE_1(sc, USS820_EPINDEX, n);
1383 
1384 		/* disable endpoint */
1385 		uss820dci_update_shared_1(sc, USS820_EPCON, 0, 0);
1386 	}
1387 
1388 	/*
1389 	 * Initialise default values for some registers that cannot be
1390 	 * changed during operation!
1391 	 */
1392 	for (n = 0; n != USS820_EP_MAX; n++) {
1393 
1394 		uss820dci_get_hw_ep_profile(NULL, &pf, n);
1395 
1396 		/* the maximum frame sizes should be the same */
1397 		if (pf->max_in_frame_size != pf->max_out_frame_size) {
1398 			DPRINTF("Max frame size mismatch %u != %u\n",
1399 			    pf->max_in_frame_size, pf->max_out_frame_size);
1400 		}
1401 		if (pf->support_isochronous) {
1402 			if (pf->max_in_frame_size <= 64) {
1403 				temp = (USS820_TXCON_FFSZ_16_64 |
1404 				    USS820_TXCON_TXISO |
1405 				    USS820_TXCON_ATM);
1406 			} else if (pf->max_in_frame_size <= 256) {
1407 				temp = (USS820_TXCON_FFSZ_64_256 |
1408 				    USS820_TXCON_TXISO |
1409 				    USS820_TXCON_ATM);
1410 			} else if (pf->max_in_frame_size <= 512) {
1411 				temp = (USS820_TXCON_FFSZ_8_512 |
1412 				    USS820_TXCON_TXISO |
1413 				    USS820_TXCON_ATM);
1414 			} else {	/* 1024 bytes */
1415 				temp = (USS820_TXCON_FFSZ_32_1024 |
1416 				    USS820_TXCON_TXISO |
1417 				    USS820_TXCON_ATM);
1418 			}
1419 		} else {
1420 			if ((pf->max_in_frame_size <= 8) &&
1421 			    (sc->sc_flags.mcsr_feat)) {
1422 				temp = (USS820_TXCON_FFSZ_8_512 |
1423 				    USS820_TXCON_ATM);
1424 			} else if (pf->max_in_frame_size <= 16) {
1425 				temp = (USS820_TXCON_FFSZ_16_64 |
1426 				    USS820_TXCON_ATM);
1427 			} else if ((pf->max_in_frame_size <= 32) &&
1428 			    (sc->sc_flags.mcsr_feat)) {
1429 				temp = (USS820_TXCON_FFSZ_32_1024 |
1430 				    USS820_TXCON_ATM);
1431 			} else {	/* 64 bytes */
1432 				temp = (USS820_TXCON_FFSZ_64_256 |
1433 				    USS820_TXCON_ATM);
1434 			}
1435 		}
1436 
1437 		/* need to configure the chip early */
1438 
1439 		USS820_WRITE_1(sc, USS820_EPINDEX, n);
1440 		USS820_WRITE_1(sc, USS820_TXCON, temp);
1441 		USS820_WRITE_1(sc, USS820_RXCON, temp);
1442 
1443 		if (pf->support_control) {
1444 			temp = USS820_EPCON_CTLEP |
1445 			    USS820_EPCON_RXSPM |
1446 			    USS820_EPCON_RXIE |
1447 			    USS820_EPCON_RXEPEN |
1448 			    USS820_EPCON_TXOE |
1449 			    USS820_EPCON_TXEPEN;
1450 		} else {
1451 			temp = USS820_EPCON_RXEPEN | USS820_EPCON_TXEPEN;
1452 		}
1453 
1454 		uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF, temp);
1455 	}
1456 
1457 	USB_BUS_UNLOCK(&sc->sc_bus);
1458 
1459 	/* catch any lost interrupts */
1460 
1461 	uss820dci_do_poll(&sc->sc_bus);
1462 
1463 	return (0);			/* success */
1464 }
1465 
1466 void
1467 uss820dci_uninit(struct uss820dci_softc *sc)
1468 {
1469 	uint8_t temp;
1470 
1471 	USB_BUS_LOCK(&sc->sc_bus);
1472 
1473 	/* disable all interrupts */
1474 	temp = USS820_READ_1(sc, USS820_SCR);
1475 	temp &= ~USS820_SCR_T_IRQ;
1476 	USS820_WRITE_1(sc, USS820_SCR, temp);
1477 
1478 	sc->sc_flags.port_powered = 0;
1479 	sc->sc_flags.status_vbus = 0;
1480 	sc->sc_flags.status_bus_reset = 0;
1481 	sc->sc_flags.status_suspend = 0;
1482 	sc->sc_flags.change_suspend = 0;
1483 	sc->sc_flags.change_connect = 1;
1484 
1485 	uss820dci_pull_down(sc);
1486 	USB_BUS_UNLOCK(&sc->sc_bus);
1487 }
1488 
1489 void
1490 uss820dci_suspend(struct uss820dci_softc *sc)
1491 {
1492 	return;
1493 }
1494 
1495 void
1496 uss820dci_resume(struct uss820dci_softc *sc)
1497 {
1498 	return;
1499 }
1500 
1501 static void
1502 uss820dci_do_poll(struct usb_bus *bus)
1503 {
1504 	struct uss820dci_softc *sc = USS820_DCI_BUS2SC(bus);
1505 
1506 	USB_BUS_LOCK(&sc->sc_bus);
1507 	uss820dci_interrupt_poll(sc);
1508 	USB_BUS_UNLOCK(&sc->sc_bus);
1509 }
1510 
1511 /*------------------------------------------------------------------------*
1512  * at91dci bulk support
1513  *------------------------------------------------------------------------*/
1514 static void
1515 uss820dci_device_bulk_open(struct usb_xfer *xfer)
1516 {
1517 	return;
1518 }
1519 
1520 static void
1521 uss820dci_device_bulk_close(struct usb_xfer *xfer)
1522 {
1523 	uss820dci_device_done(xfer, USB_ERR_CANCELLED);
1524 }
1525 
1526 static void
1527 uss820dci_device_bulk_enter(struct usb_xfer *xfer)
1528 {
1529 	return;
1530 }
1531 
1532 static void
1533 uss820dci_device_bulk_start(struct usb_xfer *xfer)
1534 {
1535 	/* setup TDs */
1536 	uss820dci_setup_standard_chain(xfer);
1537 	uss820dci_start_standard_chain(xfer);
1538 }
1539 
1540 struct usb_pipe_methods uss820dci_device_bulk_methods =
1541 {
1542 	.open = uss820dci_device_bulk_open,
1543 	.close = uss820dci_device_bulk_close,
1544 	.enter = uss820dci_device_bulk_enter,
1545 	.start = uss820dci_device_bulk_start,
1546 };
1547 
1548 /*------------------------------------------------------------------------*
1549  * at91dci control support
1550  *------------------------------------------------------------------------*/
1551 static void
1552 uss820dci_device_ctrl_open(struct usb_xfer *xfer)
1553 {
1554 	return;
1555 }
1556 
1557 static void
1558 uss820dci_device_ctrl_close(struct usb_xfer *xfer)
1559 {
1560 	uss820dci_device_done(xfer, USB_ERR_CANCELLED);
1561 }
1562 
1563 static void
1564 uss820dci_device_ctrl_enter(struct usb_xfer *xfer)
1565 {
1566 	return;
1567 }
1568 
1569 static void
1570 uss820dci_device_ctrl_start(struct usb_xfer *xfer)
1571 {
1572 	/* setup TDs */
1573 	uss820dci_setup_standard_chain(xfer);
1574 	uss820dci_start_standard_chain(xfer);
1575 }
1576 
1577 struct usb_pipe_methods uss820dci_device_ctrl_methods =
1578 {
1579 	.open = uss820dci_device_ctrl_open,
1580 	.close = uss820dci_device_ctrl_close,
1581 	.enter = uss820dci_device_ctrl_enter,
1582 	.start = uss820dci_device_ctrl_start,
1583 };
1584 
1585 /*------------------------------------------------------------------------*
1586  * at91dci interrupt support
1587  *------------------------------------------------------------------------*/
1588 static void
1589 uss820dci_device_intr_open(struct usb_xfer *xfer)
1590 {
1591 	return;
1592 }
1593 
1594 static void
1595 uss820dci_device_intr_close(struct usb_xfer *xfer)
1596 {
1597 	uss820dci_device_done(xfer, USB_ERR_CANCELLED);
1598 }
1599 
1600 static void
1601 uss820dci_device_intr_enter(struct usb_xfer *xfer)
1602 {
1603 	return;
1604 }
1605 
1606 static void
1607 uss820dci_device_intr_start(struct usb_xfer *xfer)
1608 {
1609 	/* setup TDs */
1610 	uss820dci_setup_standard_chain(xfer);
1611 	uss820dci_start_standard_chain(xfer);
1612 }
1613 
1614 struct usb_pipe_methods uss820dci_device_intr_methods =
1615 {
1616 	.open = uss820dci_device_intr_open,
1617 	.close = uss820dci_device_intr_close,
1618 	.enter = uss820dci_device_intr_enter,
1619 	.start = uss820dci_device_intr_start,
1620 };
1621 
1622 /*------------------------------------------------------------------------*
1623  * at91dci full speed isochronous support
1624  *------------------------------------------------------------------------*/
1625 static void
1626 uss820dci_device_isoc_fs_open(struct usb_xfer *xfer)
1627 {
1628 	return;
1629 }
1630 
1631 static void
1632 uss820dci_device_isoc_fs_close(struct usb_xfer *xfer)
1633 {
1634 	uss820dci_device_done(xfer, USB_ERR_CANCELLED);
1635 }
1636 
1637 static void
1638 uss820dci_device_isoc_fs_enter(struct usb_xfer *xfer)
1639 {
1640 	struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
1641 	uint32_t temp;
1642 	uint32_t nframes;
1643 
1644 	DPRINTFN(6, "xfer=%p next=%d nframes=%d\n",
1645 	    xfer, xfer->pipe->isoc_next, xfer->nframes);
1646 
1647 	/* get the current frame index - we don't need the high bits */
1648 
1649 	nframes = USS820_READ_1(sc, USS820_SOFL);
1650 
1651 	/*
1652 	 * check if the frame index is within the window where the
1653 	 * frames will be inserted
1654 	 */
1655 	temp = (nframes - xfer->pipe->isoc_next) & USS820_SOFL_MASK;
1656 
1657 	if ((xfer->pipe->is_synced == 0) ||
1658 	    (temp < xfer->nframes)) {
1659 		/*
1660 		 * If there is data underflow or the pipe queue is
1661 		 * empty we schedule the transfer a few frames ahead
1662 		 * of the current frame position. Else two isochronous
1663 		 * transfers might overlap.
1664 		 */
1665 		xfer->pipe->isoc_next = (nframes + 3) & USS820_SOFL_MASK;
1666 		xfer->pipe->is_synced = 1;
1667 		DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next);
1668 	}
1669 	/*
1670 	 * compute how many milliseconds the insertion is ahead of the
1671 	 * current frame position:
1672 	 */
1673 	temp = (xfer->pipe->isoc_next - nframes) & USS820_SOFL_MASK;
1674 
1675 	/*
1676 	 * pre-compute when the isochronous transfer will be finished:
1677 	 */
1678 	xfer->isoc_time_complete =
1679 	    usb2_isoc_time_expand(&sc->sc_bus, nframes) + temp +
1680 	    xfer->nframes;
1681 
1682 	/* compute frame number for next insertion */
1683 	xfer->pipe->isoc_next += xfer->nframes;
1684 
1685 	/* setup TDs */
1686 	uss820dci_setup_standard_chain(xfer);
1687 }
1688 
1689 static void
1690 uss820dci_device_isoc_fs_start(struct usb_xfer *xfer)
1691 {
1692 	/* start TD chain */
1693 	uss820dci_start_standard_chain(xfer);
1694 }
1695 
1696 struct usb_pipe_methods uss820dci_device_isoc_fs_methods =
1697 {
1698 	.open = uss820dci_device_isoc_fs_open,
1699 	.close = uss820dci_device_isoc_fs_close,
1700 	.enter = uss820dci_device_isoc_fs_enter,
1701 	.start = uss820dci_device_isoc_fs_start,
1702 };
1703 
1704 /*------------------------------------------------------------------------*
1705  * at91dci root control support
1706  *------------------------------------------------------------------------*
1707  * Simulate a hardware HUB by handling all the necessary requests.
1708  *------------------------------------------------------------------------*/
1709 
1710 static const struct usb_device_descriptor uss820dci_devd = {
1711 	.bLength = sizeof(struct usb_device_descriptor),
1712 	.bDescriptorType = UDESC_DEVICE,
1713 	.bcdUSB = {0x00, 0x02},
1714 	.bDeviceClass = UDCLASS_HUB,
1715 	.bDeviceSubClass = UDSUBCLASS_HUB,
1716 	.bDeviceProtocol = UDPROTO_HSHUBSTT,
1717 	.bMaxPacketSize = 64,
1718 	.bcdDevice = {0x00, 0x01},
1719 	.iManufacturer = 1,
1720 	.iProduct = 2,
1721 	.bNumConfigurations = 1,
1722 };
1723 
1724 static const struct usb_device_qualifier uss820dci_odevd = {
1725 	.bLength = sizeof(struct usb_device_qualifier),
1726 	.bDescriptorType = UDESC_DEVICE_QUALIFIER,
1727 	.bcdUSB = {0x00, 0x02},
1728 	.bDeviceClass = UDCLASS_HUB,
1729 	.bDeviceSubClass = UDSUBCLASS_HUB,
1730 	.bDeviceProtocol = UDPROTO_FSHUB,
1731 	.bMaxPacketSize0 = 0,
1732 	.bNumConfigurations = 0,
1733 };
1734 
1735 static const struct uss820dci_config_desc uss820dci_confd = {
1736 	.confd = {
1737 		.bLength = sizeof(struct usb_config_descriptor),
1738 		.bDescriptorType = UDESC_CONFIG,
1739 		.wTotalLength[0] = sizeof(uss820dci_confd),
1740 		.bNumInterface = 1,
1741 		.bConfigurationValue = 1,
1742 		.iConfiguration = 0,
1743 		.bmAttributes = UC_SELF_POWERED,
1744 		.bMaxPower = 0,
1745 	},
1746 	.ifcd = {
1747 		.bLength = sizeof(struct usb_interface_descriptor),
1748 		.bDescriptorType = UDESC_INTERFACE,
1749 		.bNumEndpoints = 1,
1750 		.bInterfaceClass = UICLASS_HUB,
1751 		.bInterfaceSubClass = UISUBCLASS_HUB,
1752 		.bInterfaceProtocol = UIPROTO_HSHUBSTT,
1753 	},
1754 
1755 	.endpd = {
1756 		.bLength = sizeof(struct usb_endpoint_descriptor),
1757 		.bDescriptorType = UDESC_ENDPOINT,
1758 		.bEndpointAddress = (UE_DIR_IN | USS820_DCI_INTR_ENDPT),
1759 		.bmAttributes = UE_INTERRUPT,
1760 		.wMaxPacketSize[0] = 8,
1761 		.bInterval = 255,
1762 	},
1763 };
1764 
1765 static const struct usb_hub_descriptor_min uss820dci_hubd = {
1766 	.bDescLength = sizeof(uss820dci_hubd),
1767 	.bDescriptorType = UDESC_HUB,
1768 	.bNbrPorts = 1,
1769 	.wHubCharacteristics[0] =
1770 	(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) & 0xFF,
1771 	.wHubCharacteristics[1] =
1772 	(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 8,
1773 	.bPwrOn2PwrGood = 50,
1774 	.bHubContrCurrent = 0,
1775 	.DeviceRemovable = {0},		/* port is removable */
1776 };
1777 
1778 #define	STRING_LANG \
1779   0x09, 0x04,				/* American English */
1780 
1781 #define	STRING_VENDOR \
1782   'A', 0, 'G', 0, 'E', 0, 'R', 0, 'E', 0
1783 
1784 #define	STRING_PRODUCT \
1785   'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
1786   'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
1787   'U', 0, 'B', 0,
1788 
1789 USB_MAKE_STRING_DESC(STRING_LANG, uss820dci_langtab);
1790 USB_MAKE_STRING_DESC(STRING_VENDOR, uss820dci_vendor);
1791 USB_MAKE_STRING_DESC(STRING_PRODUCT, uss820dci_product);
1792 
1793 static usb_error_t
1794 uss820dci_roothub_exec(struct usb_device *udev,
1795     struct usb_device_request *req, const void **pptr, uint16_t *plength)
1796 {
1797 	struct uss820dci_softc *sc = USS820_DCI_BUS2SC(udev->bus);
1798 	const void *ptr;
1799 	uint16_t len;
1800 	uint16_t value;
1801 	uint16_t index;
1802 	usb_error_t err;
1803 
1804 	USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
1805 
1806 	/* buffer reset */
1807 	ptr = (const void *)&sc->sc_hub_temp;
1808 	len = 0;
1809 	err = 0;
1810 
1811 	value = UGETW(req->wValue);
1812 	index = UGETW(req->wIndex);
1813 
1814 	/* demultiplex the control request */
1815 
1816 	switch (req->bmRequestType) {
1817 	case UT_READ_DEVICE:
1818 		switch (req->bRequest) {
1819 		case UR_GET_DESCRIPTOR:
1820 			goto tr_handle_get_descriptor;
1821 		case UR_GET_CONFIG:
1822 			goto tr_handle_get_config;
1823 		case UR_GET_STATUS:
1824 			goto tr_handle_get_status;
1825 		default:
1826 			goto tr_stalled;
1827 		}
1828 		break;
1829 
1830 	case UT_WRITE_DEVICE:
1831 		switch (req->bRequest) {
1832 		case UR_SET_ADDRESS:
1833 			goto tr_handle_set_address;
1834 		case UR_SET_CONFIG:
1835 			goto tr_handle_set_config;
1836 		case UR_CLEAR_FEATURE:
1837 			goto tr_valid;	/* nop */
1838 		case UR_SET_DESCRIPTOR:
1839 			goto tr_valid;	/* nop */
1840 		case UR_SET_FEATURE:
1841 		default:
1842 			goto tr_stalled;
1843 		}
1844 		break;
1845 
1846 	case UT_WRITE_ENDPOINT:
1847 		switch (req->bRequest) {
1848 		case UR_CLEAR_FEATURE:
1849 			switch (UGETW(req->wValue)) {
1850 			case UF_ENDPOINT_HALT:
1851 				goto tr_handle_clear_halt;
1852 			case UF_DEVICE_REMOTE_WAKEUP:
1853 				goto tr_handle_clear_wakeup;
1854 			default:
1855 				goto tr_stalled;
1856 			}
1857 			break;
1858 		case UR_SET_FEATURE:
1859 			switch (UGETW(req->wValue)) {
1860 			case UF_ENDPOINT_HALT:
1861 				goto tr_handle_set_halt;
1862 			case UF_DEVICE_REMOTE_WAKEUP:
1863 				goto tr_handle_set_wakeup;
1864 			default:
1865 				goto tr_stalled;
1866 			}
1867 			break;
1868 		case UR_SYNCH_FRAME:
1869 			goto tr_valid;	/* nop */
1870 		default:
1871 			goto tr_stalled;
1872 		}
1873 		break;
1874 
1875 	case UT_READ_ENDPOINT:
1876 		switch (req->bRequest) {
1877 		case UR_GET_STATUS:
1878 			goto tr_handle_get_ep_status;
1879 		default:
1880 			goto tr_stalled;
1881 		}
1882 		break;
1883 
1884 	case UT_WRITE_INTERFACE:
1885 		switch (req->bRequest) {
1886 		case UR_SET_INTERFACE:
1887 			goto tr_handle_set_interface;
1888 		case UR_CLEAR_FEATURE:
1889 			goto tr_valid;	/* nop */
1890 		case UR_SET_FEATURE:
1891 		default:
1892 			goto tr_stalled;
1893 		}
1894 		break;
1895 
1896 	case UT_READ_INTERFACE:
1897 		switch (req->bRequest) {
1898 		case UR_GET_INTERFACE:
1899 			goto tr_handle_get_interface;
1900 		case UR_GET_STATUS:
1901 			goto tr_handle_get_iface_status;
1902 		default:
1903 			goto tr_stalled;
1904 		}
1905 		break;
1906 
1907 	case UT_WRITE_CLASS_INTERFACE:
1908 	case UT_WRITE_VENDOR_INTERFACE:
1909 		/* XXX forward */
1910 		break;
1911 
1912 	case UT_READ_CLASS_INTERFACE:
1913 	case UT_READ_VENDOR_INTERFACE:
1914 		/* XXX forward */
1915 		break;
1916 
1917 	case UT_WRITE_CLASS_DEVICE:
1918 		switch (req->bRequest) {
1919 		case UR_CLEAR_FEATURE:
1920 			goto tr_valid;
1921 		case UR_SET_DESCRIPTOR:
1922 		case UR_SET_FEATURE:
1923 			break;
1924 		default:
1925 			goto tr_stalled;
1926 		}
1927 		break;
1928 
1929 	case UT_WRITE_CLASS_OTHER:
1930 		switch (req->bRequest) {
1931 		case UR_CLEAR_FEATURE:
1932 			goto tr_handle_clear_port_feature;
1933 		case UR_SET_FEATURE:
1934 			goto tr_handle_set_port_feature;
1935 		case UR_CLEAR_TT_BUFFER:
1936 		case UR_RESET_TT:
1937 		case UR_STOP_TT:
1938 			goto tr_valid;
1939 
1940 		default:
1941 			goto tr_stalled;
1942 		}
1943 		break;
1944 
1945 	case UT_READ_CLASS_OTHER:
1946 		switch (req->bRequest) {
1947 		case UR_GET_TT_STATE:
1948 			goto tr_handle_get_tt_state;
1949 		case UR_GET_STATUS:
1950 			goto tr_handle_get_port_status;
1951 		default:
1952 			goto tr_stalled;
1953 		}
1954 		break;
1955 
1956 	case UT_READ_CLASS_DEVICE:
1957 		switch (req->bRequest) {
1958 		case UR_GET_DESCRIPTOR:
1959 			goto tr_handle_get_class_descriptor;
1960 		case UR_GET_STATUS:
1961 			goto tr_handle_get_class_status;
1962 
1963 		default:
1964 			goto tr_stalled;
1965 		}
1966 		break;
1967 	default:
1968 		goto tr_stalled;
1969 	}
1970 	goto tr_valid;
1971 
1972 tr_handle_get_descriptor:
1973 	switch (value >> 8) {
1974 	case UDESC_DEVICE:
1975 		if (value & 0xff) {
1976 			goto tr_stalled;
1977 		}
1978 		len = sizeof(uss820dci_devd);
1979 		ptr = (const void *)&uss820dci_devd;
1980 		goto tr_valid;
1981 	case UDESC_CONFIG:
1982 		if (value & 0xff) {
1983 			goto tr_stalled;
1984 		}
1985 		len = sizeof(uss820dci_confd);
1986 		ptr = (const void *)&uss820dci_confd;
1987 		goto tr_valid;
1988 	case UDESC_STRING:
1989 		switch (value & 0xff) {
1990 		case 0:		/* Language table */
1991 			len = sizeof(uss820dci_langtab);
1992 			ptr = (const void *)&uss820dci_langtab;
1993 			goto tr_valid;
1994 
1995 		case 1:		/* Vendor */
1996 			len = sizeof(uss820dci_vendor);
1997 			ptr = (const void *)&uss820dci_vendor;
1998 			goto tr_valid;
1999 
2000 		case 2:		/* Product */
2001 			len = sizeof(uss820dci_product);
2002 			ptr = (const void *)&uss820dci_product;
2003 			goto tr_valid;
2004 		default:
2005 			break;
2006 		}
2007 		break;
2008 	default:
2009 		goto tr_stalled;
2010 	}
2011 	goto tr_stalled;
2012 
2013 tr_handle_get_config:
2014 	len = 1;
2015 	sc->sc_hub_temp.wValue[0] = sc->sc_conf;
2016 	goto tr_valid;
2017 
2018 tr_handle_get_status:
2019 	len = 2;
2020 	USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED);
2021 	goto tr_valid;
2022 
2023 tr_handle_set_address:
2024 	if (value & 0xFF00) {
2025 		goto tr_stalled;
2026 	}
2027 	sc->sc_rt_addr = value;
2028 	goto tr_valid;
2029 
2030 tr_handle_set_config:
2031 	if (value >= 2) {
2032 		goto tr_stalled;
2033 	}
2034 	sc->sc_conf = value;
2035 	goto tr_valid;
2036 
2037 tr_handle_get_interface:
2038 	len = 1;
2039 	sc->sc_hub_temp.wValue[0] = 0;
2040 	goto tr_valid;
2041 
2042 tr_handle_get_tt_state:
2043 tr_handle_get_class_status:
2044 tr_handle_get_iface_status:
2045 tr_handle_get_ep_status:
2046 	len = 2;
2047 	USETW(sc->sc_hub_temp.wValue, 0);
2048 	goto tr_valid;
2049 
2050 tr_handle_set_halt:
2051 tr_handle_set_interface:
2052 tr_handle_set_wakeup:
2053 tr_handle_clear_wakeup:
2054 tr_handle_clear_halt:
2055 	goto tr_valid;
2056 
2057 tr_handle_clear_port_feature:
2058 	if (index != 1) {
2059 		goto tr_stalled;
2060 	}
2061 	DPRINTFN(9, "UR_CLEAR_PORT_FEATURE on port %d\n", index);
2062 
2063 	switch (value) {
2064 	case UHF_PORT_SUSPEND:
2065 		uss820dci_wakeup_peer(sc);
2066 		break;
2067 
2068 	case UHF_PORT_ENABLE:
2069 		sc->sc_flags.port_enabled = 0;
2070 		break;
2071 
2072 	case UHF_PORT_TEST:
2073 	case UHF_PORT_INDICATOR:
2074 	case UHF_C_PORT_ENABLE:
2075 	case UHF_C_PORT_OVER_CURRENT:
2076 	case UHF_C_PORT_RESET:
2077 		/* nops */
2078 		break;
2079 	case UHF_PORT_POWER:
2080 		sc->sc_flags.port_powered = 0;
2081 		uss820dci_pull_down(sc);
2082 		break;
2083 	case UHF_C_PORT_CONNECTION:
2084 		sc->sc_flags.change_connect = 0;
2085 		break;
2086 	case UHF_C_PORT_SUSPEND:
2087 		sc->sc_flags.change_suspend = 0;
2088 		break;
2089 	default:
2090 		err = USB_ERR_IOERROR;
2091 		goto done;
2092 	}
2093 	goto tr_valid;
2094 
2095 tr_handle_set_port_feature:
2096 	if (index != 1) {
2097 		goto tr_stalled;
2098 	}
2099 	DPRINTFN(9, "UR_SET_PORT_FEATURE\n");
2100 
2101 	switch (value) {
2102 	case UHF_PORT_ENABLE:
2103 		sc->sc_flags.port_enabled = 1;
2104 		break;
2105 	case UHF_PORT_SUSPEND:
2106 	case UHF_PORT_RESET:
2107 	case UHF_PORT_TEST:
2108 	case UHF_PORT_INDICATOR:
2109 		/* nops */
2110 		break;
2111 	case UHF_PORT_POWER:
2112 		sc->sc_flags.port_powered = 1;
2113 		break;
2114 	default:
2115 		err = USB_ERR_IOERROR;
2116 		goto done;
2117 	}
2118 	goto tr_valid;
2119 
2120 tr_handle_get_port_status:
2121 
2122 	DPRINTFN(9, "UR_GET_PORT_STATUS\n");
2123 
2124 	if (index != 1) {
2125 		goto tr_stalled;
2126 	}
2127 	if (sc->sc_flags.status_vbus) {
2128 		uss820dci_pull_up(sc);
2129 	} else {
2130 		uss820dci_pull_down(sc);
2131 	}
2132 
2133 	/* Select FULL-speed and Device Side Mode */
2134 
2135 	value = UPS_PORT_MODE_DEVICE;
2136 
2137 	if (sc->sc_flags.port_powered) {
2138 		value |= UPS_PORT_POWER;
2139 	}
2140 	if (sc->sc_flags.port_enabled) {
2141 		value |= UPS_PORT_ENABLED;
2142 	}
2143 	if (sc->sc_flags.status_vbus &&
2144 	    sc->sc_flags.status_bus_reset) {
2145 		value |= UPS_CURRENT_CONNECT_STATUS;
2146 	}
2147 	if (sc->sc_flags.status_suspend) {
2148 		value |= UPS_SUSPEND;
2149 	}
2150 	USETW(sc->sc_hub_temp.ps.wPortStatus, value);
2151 
2152 	value = 0;
2153 
2154 	if (sc->sc_flags.change_connect) {
2155 		value |= UPS_C_CONNECT_STATUS;
2156 	}
2157 	if (sc->sc_flags.change_suspend) {
2158 		value |= UPS_C_SUSPEND;
2159 	}
2160 	USETW(sc->sc_hub_temp.ps.wPortChange, value);
2161 	len = sizeof(sc->sc_hub_temp.ps);
2162 	goto tr_valid;
2163 
2164 tr_handle_get_class_descriptor:
2165 	if (value & 0xFF) {
2166 		goto tr_stalled;
2167 	}
2168 	ptr = (const void *)&uss820dci_hubd;
2169 	len = sizeof(uss820dci_hubd);
2170 	goto tr_valid;
2171 
2172 tr_stalled:
2173 	err = USB_ERR_STALLED;
2174 tr_valid:
2175 done:
2176 	*plength = len;
2177 	*pptr = ptr;
2178 	return (err);
2179 }
2180 
2181 static void
2182 uss820dci_xfer_setup(struct usb_setup_params *parm)
2183 {
2184 	const struct usb_hw_ep_profile *pf;
2185 	struct uss820dci_softc *sc;
2186 	struct usb_xfer *xfer;
2187 	void *last_obj;
2188 	uint32_t ntd;
2189 	uint32_t n;
2190 	uint8_t ep_no;
2191 
2192 	sc = USS820_DCI_BUS2SC(parm->udev->bus);
2193 	xfer = parm->curr_xfer;
2194 
2195 	/*
2196 	 * NOTE: This driver does not use any of the parameters that
2197 	 * are computed from the following values. Just set some
2198 	 * reasonable dummies:
2199 	 */
2200 	parm->hc_max_packet_size = 0x500;
2201 	parm->hc_max_packet_count = 1;
2202 	parm->hc_max_frame_size = 0x500;
2203 
2204 	usb2_transfer_setup_sub(parm);
2205 
2206 	/*
2207 	 * compute maximum number of TDs
2208 	 */
2209 	if (parm->methods == &uss820dci_device_ctrl_methods) {
2210 
2211 		ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC */ ;
2212 
2213 	} else if (parm->methods == &uss820dci_device_bulk_methods) {
2214 
2215 		ntd = xfer->nframes + 1 /* SYNC */ ;
2216 
2217 	} else if (parm->methods == &uss820dci_device_intr_methods) {
2218 
2219 		ntd = xfer->nframes + 1 /* SYNC */ ;
2220 
2221 	} else if (parm->methods == &uss820dci_device_isoc_fs_methods) {
2222 
2223 		ntd = xfer->nframes + 1 /* SYNC */ ;
2224 
2225 	} else {
2226 
2227 		ntd = 0;
2228 	}
2229 
2230 	/*
2231 	 * check if "usb2_transfer_setup_sub" set an error
2232 	 */
2233 	if (parm->err) {
2234 		return;
2235 	}
2236 	/*
2237 	 * allocate transfer descriptors
2238 	 */
2239 	last_obj = NULL;
2240 
2241 	/*
2242 	 * get profile stuff
2243 	 */
2244 	if (ntd) {
2245 
2246 		ep_no = xfer->endpoint & UE_ADDR;
2247 		uss820dci_get_hw_ep_profile(parm->udev, &pf, ep_no);
2248 
2249 		if (pf == NULL) {
2250 			/* should not happen */
2251 			parm->err = USB_ERR_INVAL;
2252 			return;
2253 		}
2254 	} else {
2255 		ep_no = 0;
2256 		pf = NULL;
2257 	}
2258 
2259 	/* align data */
2260 	parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
2261 
2262 	for (n = 0; n != ntd; n++) {
2263 
2264 		struct uss820dci_td *td;
2265 
2266 		if (parm->buf) {
2267 
2268 			td = USB_ADD_BYTES(parm->buf, parm->size[0]);
2269 
2270 			/* init TD */
2271 			td->io_tag = sc->sc_io_tag;
2272 			td->io_hdl = sc->sc_io_hdl;
2273 			td->max_packet_size = xfer->max_packet_size;
2274 			td->ep_index = ep_no;
2275 			if (pf->support_multi_buffer &&
2276 			    (parm->methods != &uss820dci_device_ctrl_methods)) {
2277 				td->support_multi_buffer = 1;
2278 			}
2279 			td->obj_next = last_obj;
2280 
2281 			last_obj = td;
2282 		}
2283 		parm->size[0] += sizeof(*td);
2284 	}
2285 
2286 	xfer->td_start[0] = last_obj;
2287 }
2288 
2289 static void
2290 uss820dci_xfer_unsetup(struct usb_xfer *xfer)
2291 {
2292 	return;
2293 }
2294 
2295 static void
2296 uss820dci_pipe_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc,
2297     struct usb_pipe *pipe)
2298 {
2299 	struct uss820dci_softc *sc = USS820_DCI_BUS2SC(udev->bus);
2300 
2301 	DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
2302 	    pipe, udev->address,
2303 	    edesc->bEndpointAddress, udev->flags.usb_mode,
2304 	    sc->sc_rt_addr);
2305 
2306 	if (udev->device_index != sc->sc_rt_addr) {
2307 
2308 		if (udev->flags.usb_mode != USB_MODE_DEVICE) {
2309 			/* not supported */
2310 			return;
2311 		}
2312 		if (udev->speed != USB_SPEED_FULL) {
2313 			/* not supported */
2314 			return;
2315 		}
2316 		switch (edesc->bmAttributes & UE_XFERTYPE) {
2317 		case UE_CONTROL:
2318 			pipe->methods = &uss820dci_device_ctrl_methods;
2319 			break;
2320 		case UE_INTERRUPT:
2321 			pipe->methods = &uss820dci_device_intr_methods;
2322 			break;
2323 		case UE_ISOCHRONOUS:
2324 			pipe->methods = &uss820dci_device_isoc_fs_methods;
2325 			break;
2326 		case UE_BULK:
2327 			pipe->methods = &uss820dci_device_bulk_methods;
2328 			break;
2329 		default:
2330 			/* do nothing */
2331 			break;
2332 		}
2333 	}
2334 }
2335 
2336 struct usb_bus_methods uss820dci_bus_methods =
2337 {
2338 	.pipe_init = &uss820dci_pipe_init,
2339 	.xfer_setup = &uss820dci_xfer_setup,
2340 	.xfer_unsetup = &uss820dci_xfer_unsetup,
2341 	.get_hw_ep_profile = &uss820dci_get_hw_ep_profile,
2342 	.set_stall = &uss820dci_set_stall,
2343 	.clear_stall = &uss820dci_clear_stall,
2344 	.roothub_exec = &uss820dci_roothub_exec,
2345 };
2346