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