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