Home | History | Annotate | Line # | Download | only in usb
ehcivar.h revision 1.49
      1  1.49     skrll /*	$NetBSD: ehcivar.h,v 1.49 2021/12/22 21:45:02 skrll Exp $ */
      2   1.1  augustss 
      3   1.1  augustss /*
      4   1.4  augustss  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5   1.1  augustss  * All rights reserved.
      6   1.1  augustss  *
      7   1.1  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1  augustss  * by Lennart Augustsson (lennart (at) augustsson.net).
      9   1.1  augustss  *
     10   1.1  augustss  * Redistribution and use in source and binary forms, with or without
     11   1.1  augustss  * modification, are permitted provided that the following conditions
     12   1.1  augustss  * are met:
     13   1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     14   1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     15   1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     17   1.1  augustss  *    documentation and/or other materials provided with the distribution.
     18   1.1  augustss  *
     19   1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1  augustss  */
     31   1.1  augustss 
     32  1.41  christos #ifndef _EHCIVAR_H_
     33  1.41  christos #define _EHCIVAR_H_
     34  1.41  christos 
     35  1.41  christos #include <sys/pool.h>
     36  1.41  christos 
     37   1.7  augustss typedef struct ehci_soft_qtd {
     38   1.7  augustss 	ehci_qtd_t qtd;
     39  1.43     skrll 	struct ehci_soft_qtd *nextqtd;	/* mirrors nextqtd in TD */
     40  1.43     skrll 	ehci_physaddr_t physaddr;	/* qTD's physical address */
     41  1.43     skrll 	usb_dma_t dma;			/* qTD's DMA infos */
     42  1.43     skrll 	int offs;			/* qTD's offset in usb_dma_t */
     43  1.43     skrll 	struct usbd_xfer *xfer;		/* xfer back pointer */
     44  1.43     skrll 	uint16_t len;
     45   1.7  augustss } ehci_soft_qtd_t;
     46  1.42      matt #define EHCI_SQTD_ALIGN	MAX(EHCI_QTD_ALIGN, CACHE_LINE_SIZE)
     47  1.48     skrll #define EHCI_SQTD_SIZE (roundup(sizeof(struct ehci_soft_qtd), EHCI_SQTD_ALIGN))
     48   1.7  augustss #define EHCI_SQTD_CHUNK (EHCI_PAGE_SIZE / EHCI_SQTD_SIZE)
     49   1.7  augustss 
     50   1.7  augustss typedef struct ehci_soft_qh {
     51   1.7  augustss 	ehci_qh_t qh;
     52   1.7  augustss 	struct ehci_soft_qh *next;
     53   1.9  augustss 	struct ehci_soft_qtd *sqtd;
     54   1.7  augustss 	ehci_physaddr_t physaddr;
     55  1.43     skrll 	usb_dma_t dma;			/* QH's DMA infos */
     56  1.43     skrll 	int offs;			/* QH's offset in usb_dma_t */
     57  1.15  augustss 	int islot;
     58   1.7  augustss } ehci_soft_qh_t;
     59  1.48     skrll #define EHCI_SQH_SIZE (roundup(sizeof(struct ehci_soft_qh), EHCI_QH_ALIGN))
     60   1.7  augustss #define EHCI_SQH_CHUNK (EHCI_PAGE_SIZE / EHCI_SQH_SIZE)
     61   1.7  augustss 
     62  1.32  jmcneill typedef struct ehci_soft_itd {
     63  1.43     skrll 	union {
     64  1.43     skrll 		ehci_itd_t itd;
     65  1.43     skrll 		ehci_sitd_t sitd;
     66  1.43     skrll 	};
     67  1.32  jmcneill 	union {
     68  1.32  jmcneill 		struct {
     69  1.43     skrll 			/* soft_itds links in a periodic frame */
     70  1.32  jmcneill 			struct ehci_soft_itd *next;
     71  1.32  jmcneill 			struct ehci_soft_itd *prev;
     72  1.32  jmcneill 		} frame_list;
     73  1.32  jmcneill 		/* circular list of free itds */
     74  1.32  jmcneill 		LIST_ENTRY(ehci_soft_itd) free_list;
     75  1.43     skrll 	};
     76  1.32  jmcneill 	struct ehci_soft_itd *xfer_next; /* Next soft_itd in xfer */
     77  1.32  jmcneill 	ehci_physaddr_t physaddr;
     78  1.32  jmcneill 	usb_dma_t dma;
     79  1.32  jmcneill 	int offs;
     80  1.32  jmcneill 	int slot;
     81  1.32  jmcneill 	struct timeval t; /* store free time */
     82  1.32  jmcneill } ehci_soft_itd_t;
     83  1.48     skrll #define EHCI_ITD_SIZE (roundup(sizeof(struct ehci_soft_itd), EHCI_ITD_ALIGN))
     84  1.32  jmcneill #define EHCI_ITD_CHUNK (EHCI_PAGE_SIZE / EHCI_ITD_SIZE)
     85  1.32  jmcneill 
     86  1.43     skrll #define ehci_soft_sitd_t ehci_soft_itd_t
     87  1.43     skrll #define ehci_soft_sitd ehci_soft_itd
     88  1.43     skrll #define sc_softsitds sc_softitds
     89  1.48     skrll #define EHCI_SITD_SIZE (roundup(sizeof(struct ehci_soft_sitd), EHCI_SITD_ALIGN))
     90  1.43     skrll #define EHCI_SITD_CHUNK (EHCI_PAGE_SIZE / EHCI_SITD_SIZE)
     91  1.43     skrll 
     92  1.11  augustss struct ehci_xfer {
     93  1.43     skrll 	struct usbd_xfer ex_xfer;
     94  1.43     skrll 	TAILQ_ENTRY(ehci_xfer) ex_next; /* list of active xfers */
     95  1.43     skrll 	enum {
     96  1.43     skrll 		EX_NONE,
     97  1.43     skrll 		EX_CTRL,
     98  1.43     skrll 		EX_BULK,
     99  1.43     skrll 		EX_INTR,
    100  1.43     skrll 		EX_ISOC,
    101  1.43     skrll 		EX_FS_ISOC
    102  1.43     skrll 	} ex_type;
    103  1.43     skrll 	/* ctrl/bulk/intr */
    104  1.43     skrll 	struct {
    105  1.43     skrll 		ehci_soft_qtd_t **ex_sqtds;
    106  1.43     skrll 		size_t ex_nsqtd;
    107  1.43     skrll 	};
    108  1.43     skrll 	union {
    109  1.43     skrll 		/* ctrl */
    110  1.43     skrll 		struct {
    111  1.43     skrll 			ehci_soft_qtd_t *ex_setup;
    112  1.43     skrll 			ehci_soft_qtd_t *ex_data;
    113  1.43     skrll 			ehci_soft_qtd_t *ex_status;
    114  1.43     skrll 		};
    115  1.43     skrll 		/* bulk/intr */
    116  1.43     skrll 		struct {
    117  1.43     skrll 			ehci_soft_qtd_t *ex_sqtdstart;
    118  1.43     skrll 			ehci_soft_qtd_t *ex_sqtdend;
    119  1.43     skrll 		};
    120  1.43     skrll 		/* isoc */
    121  1.43     skrll 		struct {
    122  1.43     skrll 			ehci_soft_itd_t *ex_itdstart;
    123  1.43     skrll 			ehci_soft_itd_t *ex_itdend;
    124  1.43     skrll 		};
    125  1.43     skrll 		/* split (aka fs) isoc */
    126  1.43     skrll 		struct {
    127  1.43     skrll 			ehci_soft_sitd_t *ex_sitdstart;
    128  1.43     skrll 			ehci_soft_sitd_t *ex_sitdend;
    129  1.43     skrll 		};
    130  1.43     skrll 	};
    131  1.43     skrll 	bool ex_isdone;	/* used only when DIAGNOSTIC is defined */
    132  1.11  augustss };
    133  1.43     skrll 
    134  1.43     skrll #define EHCI_BUS2SC(bus)	((bus)->ub_hcpriv)
    135  1.43     skrll #define EHCI_PIPE2SC(pipe)	EHCI_BUS2SC((pipe)->up_dev->ud_bus)
    136  1.43     skrll #define EHCI_XFER2SC(xfer)	EHCI_BUS2SC((xfer)->ux_bus)
    137  1.43     skrll #define EHCI_EPIPE2SC(epipe)	EHCI_BUS2SC((epipe)->pipe.up_dev->ud_bus)
    138  1.43     skrll 
    139  1.43     skrll #define EHCI_XFER2EXFER(xfer)	((struct ehci_xfer *)(xfer))
    140  1.43     skrll 
    141  1.43     skrll #define EHCI_XFER2EPIPE(xfer)	((struct ehci_pipe *)((xfer)->ux_pipe))
    142  1.43     skrll #define EHCI_PIPE2EPIPE(pipe)	((struct ehci_pipe *)(pipe))
    143  1.11  augustss 
    144  1.15  augustss /* Information about an entry in the interrupt list. */
    145  1.15  augustss struct ehci_soft_islot {
    146  1.15  augustss 	ehci_soft_qh_t *sqh;	/* Queue Head. */
    147  1.15  augustss };
    148  1.15  augustss 
    149  1.15  augustss #define EHCI_FRAMELIST_MAXCOUNT	1024
    150  1.15  augustss #define EHCI_IPOLLRATES		8 /* Poll rates (1ms, 2, 4, 8 .. 128) */
    151  1.15  augustss #define EHCI_INTRQHS		((1 << EHCI_IPOLLRATES) - 1)
    152  1.18  augustss #define EHCI_MAX_POLLRATE	(1 << (EHCI_IPOLLRATES - 1))
    153  1.15  augustss #define EHCI_IQHIDX(lev, pos) \
    154  1.15  augustss 	((((pos) & ((1 << (lev)) - 1)) | (1 << (lev))) - 1)
    155  1.15  augustss #define EHCI_ILEV_IVAL(lev)	(1 << (lev))
    156  1.15  augustss 
    157   1.7  augustss 
    158   1.7  augustss #define EHCI_HASH_SIZE 128
    159   1.3  augustss #define EHCI_COMPANION_MAX 8
    160   1.7  augustss 
    161  1.32  jmcneill #define EHCI_FREE_LIST_INTERVAL 100
    162  1.32  jmcneill 
    163   1.1  augustss typedef struct ehci_softc {
    164  1.29  drochner 	device_t sc_dev;
    165  1.40       mrg 	kmutex_t sc_lock;
    166  1.40       mrg 	kmutex_t sc_intr_lock;
    167  1.40       mrg 	kcondvar_t sc_doorbell;
    168  1.40       mrg 	void *sc_doorbell_si;
    169  1.40       mrg 	void *sc_pcd_si;
    170  1.29  drochner 	struct usbd_bus sc_bus;
    171   1.1  augustss 	bus_space_tag_t iot;
    172   1.1  augustss 	bus_space_handle_t ioh;
    173   1.1  augustss 	bus_size_t sc_size;
    174  1.49     skrll 	bus_dma_tag_t sc_dmatag;	/* for control data structures */
    175   1.2  augustss 	u_int sc_offs;			/* offset to operational regs */
    176  1.23   xtraeme 	int sc_flags;			/* misc flags */
    177  1.23   xtraeme #define EHCIF_DROPPED_INTR_WORKAROUND	0x01
    178  1.38      matt #define EHCIF_ETTF			0x02 /* Emb. Transaction Translater func. */
    179   1.1  augustss 
    180  1.43     skrll 	uint32_t sc_cmd;		/* shadow of cmd reg during suspend */
    181   1.1  augustss 
    182   1.3  augustss 	u_int sc_ncomp;
    183   1.5  augustss 	u_int sc_npcomp;
    184  1.29  drochner 	device_t sc_comps[EHCI_COMPANION_MAX];
    185   1.3  augustss 
    186  1.46       mrg 	/* This chunk to handle early RB_ASKNAME hand over. */
    187  1.46       mrg 	callout_t sc_compcallout;
    188  1.46       mrg 	kmutex_t sc_complock;
    189  1.46       mrg 	kcondvar_t sc_compcv;
    190  1.46       mrg 	enum {
    191  1.46       mrg 		CO_EARLY,
    192  1.46       mrg 		CO_SCHED,
    193  1.46       mrg 		CO_DONE,
    194  1.46       mrg 	} sc_comp_state;
    195  1.46       mrg 
    196   1.3  augustss 	usb_dma_t sc_fldma;
    197  1.15  augustss 	ehci_link_t *sc_flist;
    198   1.3  augustss 	u_int sc_flsize;
    199  1.15  augustss 	u_int sc_rand;			/* XXX need proper intr scheduling */
    200  1.15  augustss 
    201  1.15  augustss 	struct ehci_soft_islot sc_islots[EHCI_INTRQHS];
    202   1.3  augustss 
    203  1.43     skrll 	/*
    204  1.43     skrll 	 * an array matching sc_flist, but with software pointers,
    205  1.32  jmcneill 	 * not hardware address pointers
    206  1.32  jmcneill 	 */
    207  1.32  jmcneill 	struct ehci_soft_itd **sc_softitds;
    208  1.32  jmcneill 
    209  1.33  jmcneill 	TAILQ_HEAD(, ehci_xfer) sc_intrhead;
    210  1.11  augustss 
    211   1.7  augustss 	ehci_soft_qh_t *sc_freeqhs;
    212   1.7  augustss 	ehci_soft_qtd_t *sc_freeqtds;
    213  1.32  jmcneill 	LIST_HEAD(sc_freeitds, ehci_soft_itd) sc_freeitds;
    214  1.43     skrll 	LIST_HEAD(sc_freesitds, ehci_soft_sitd) sc_freesitds;
    215   1.7  augustss 
    216   1.4  augustss 	int sc_noport;
    217  1.43     skrll 	uint8_t sc_hasppc;		/* has Port Power Control */
    218  1.43     skrll 	uint8_t sc_istthreshold;	/* ISOC Scheduling Threshold (uframes) */
    219  1.43     skrll 	struct usbd_xfer *sc_intrxfer;
    220  1.21  augustss 	char sc_isreset[EHCI_MAX_PORTS];
    221   1.5  augustss 
    222  1.43     skrll 	uint32_t sc_eintrs;
    223   1.9  augustss 	ehci_soft_qh_t *sc_async_head;
    224   1.4  augustss 
    225  1.41  christos 	pool_cache_t sc_xferpool;	/* free xfer pool */
    226   1.8  augustss 
    227  1.34    dyoung 	struct callout sc_tmo_intrlist;
    228   1.4  augustss 
    229  1.34    dyoung 	device_t sc_child; /* /dev/usb# device */
    230   1.4  augustss 	char sc_dying;
    231  1.37  kiyohara 
    232  1.37  kiyohara 	void (*sc_vendor_init)(struct ehci_softc *);
    233  1.37  kiyohara 	int (*sc_vendor_port_status)(struct ehci_softc *, uint32_t, int);
    234   1.1  augustss } ehci_softc_t;
    235   1.2  augustss 
    236   1.3  augustss #define EREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a))
    237   1.3  augustss #define EREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (a))
    238   1.3  augustss #define EREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (a))
    239   1.3  augustss #define EWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (a), (x))
    240   1.3  augustss #define EWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (a), (x))
    241   1.3  augustss #define EWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (a), (x))
    242   1.2  augustss #define EOREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a))
    243   1.2  augustss #define EOREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a))
    244   1.2  augustss #define EOREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a))
    245   1.2  augustss #define EOWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x))
    246   1.2  augustss #define EOWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x))
    247   1.2  augustss #define EOWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x))
    248   1.1  augustss 
    249  1.43     skrll int		ehci_init(ehci_softc_t *);
    250   1.1  augustss int		ehci_intr(void *);
    251   1.1  augustss int		ehci_detach(ehci_softc_t *, int);
    252  1.27    dyoung int		ehci_activate(device_t, enum devact);
    253  1.27    dyoung void		ehci_childdet(device_t, device_t);
    254  1.36    dyoung bool		ehci_suspend(device_t, const pmf_qual_t *);
    255  1.36    dyoung bool		ehci_resume(device_t, const pmf_qual_t *);
    256  1.28    dyoung bool		ehci_shutdown(device_t, int);
    257  1.41  christos 
    258  1.41  christos #endif /* _EHCIVAR_H_ */
    259