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