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