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