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