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