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