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