uhcivar.h revision 1.52.14.11
11.52.14.11Sskrll/*	$NetBSD: uhcivar.h,v 1.52.14.11 2015/10/27 14:05:29 skrll Exp $	*/
21.1Saugustss
31.1Saugustss/*
41.1Saugustss * Copyright (c) 1998 The NetBSD Foundation, Inc.
51.1Saugustss * All rights reserved.
61.1Saugustss *
71.4Saugustss * This code is derived from software contributed to The NetBSD Foundation
81.30Saugustss * by Lennart Augustsson (lennart@augustsson.net) at
91.4Saugustss * Carlstedt Research & Technology.
101.1Saugustss *
111.1Saugustss * Redistribution and use in source and binary forms, with or without
121.1Saugustss * modification, are permitted provided that the following conditions
131.1Saugustss * are met:
141.1Saugustss * 1. Redistributions of source code must retain the above copyright
151.1Saugustss *    notice, this list of conditions and the following disclaimer.
161.1Saugustss * 2. Redistributions in binary form must reproduce the above copyright
171.1Saugustss *    notice, this list of conditions and the following disclaimer in the
181.1Saugustss *    documentation and/or other materials provided with the distribution.
191.1Saugustss *
201.1Saugustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
211.1Saugustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
221.1Saugustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
231.1Saugustss * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
241.1Saugustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
251.1Saugustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
261.1Saugustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
271.1Saugustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
281.1Saugustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
291.1Saugustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
301.1Saugustss * POSSIBILITY OF SUCH DAMAGE.
311.1Saugustss */
321.1Saugustss
331.52Schristos#ifndef _UHCIVAR_H_
341.52Schristos#define _UHCIVAR_H_
351.52Schristos
361.52Schristos#include <sys/pool.h>
371.52Schristos
381.1Saugustss/*
391.1Saugustss * To avoid having 1024 TDs for each isochronous transfer we introduce
401.1Saugustss * a virtual frame list.  Every UHCI_VFRAMELIST_COUNT entries in the real
411.34Saugustss * frame list points to a non-active TD.  These, in turn, form the
421.34Saugustss * starts of the virtual frame list.  This also has the advantage that it
431.28Saugustss * simplifies linking in/out of TDs/QHs in the schedule.
441.1Saugustss * Furthermore, initially each of the inactive TDs point to an inactive
451.1Saugustss * QH that forms the start of the interrupt traffic for that slot.
461.1Saugustss * Each of these QHs point to the same QH that is the start of control
471.28Saugustss * traffic.  This QH points at another QH which is the start of the
481.28Saugustss * bulk traffic.
491.1Saugustss *
501.1Saugustss * UHCI_VFRAMELIST_COUNT should be a power of 2 and <= UHCI_FRAMELIST_COUNT.
511.1Saugustss */
521.1Saugustss#define UHCI_VFRAMELIST_COUNT 128
531.1Saugustss
541.1Saugustsstypedef struct uhci_soft_qh uhci_soft_qh_t;
551.1Saugustsstypedef struct uhci_soft_td uhci_soft_td_t;
561.1Saugustss
571.11Saugustsstypedef union {
581.11Saugustss	struct uhci_soft_qh *sqh;
591.11Saugustss	struct uhci_soft_td *std;
601.11Saugustss} uhci_soft_td_qh_t;
611.11Saugustss
621.26Saugustssstruct uhci_xfer {
631.26Saugustss	struct usbd_xfer xfer;
641.33Saugustss	struct usb_task	abort_task;
651.52.14.11Sskrll	uhci_soft_td_t *stdstart;
661.52.14.11Sskrll	uhci_soft_td_t *stdend;
671.52.14.11Sskrll	TAILQ_ENTRY(uhci_xfer) list;
681.26Saugustss	int curframe;
691.52.14.11Sskrll	bool isdone;	/* used only when DIAGNOSTIC is defined */
701.26Saugustss};
711.26Saugustss
721.52.14.8Sskrll#define UHCI_BUS2SC(bus)	((bus)->ub_hcpriv)
731.52.14.8Sskrll#define UHCI_PIPE2SC(pipe)	UHCI_BUS2SC((pipe)->up_dev->ud_bus)
741.52.14.9Sskrll#define UHCI_XFER2SC(xfer)	UHCI_BUS2SC((xfer)->ux_bus)
751.52.14.8Sskrll#define UHCI_UPIPE2SC(d)	UHCI_BUS2SC((d)->pipe.up_dev->ud_bus)
761.52.14.8Sskrll
771.52.14.8Sskrll#define UHCI_XFER2UXFER(xfer)	((struct uhci_xfer *)(xfer))
781.26Saugustss
791.1Saugustss/*
801.1Saugustss * Extra information that we need for a TD.
811.1Saugustss */
821.1Saugustssstruct uhci_soft_td {
831.11Saugustss	uhci_td_t td;			/* The real TD, must be first */
841.11Saugustss	uhci_soft_td_qh_t link; 	/* soft version of the td_link field */
851.11Saugustss	uhci_physaddr_t physaddr;	/* TD's physical address. */
861.45Sbouyer	usb_dma_t dma;			/* TD's DMA infos */
871.45Sbouyer	int offs;			/* TD's offset in usb_dma_t */
881.1Saugustss};
891.34Saugustss/*
901.11Saugustss * Make the size such that it is a multiple of UHCI_TD_ALIGN.  This way
911.19Saugustss * we can pack a number of soft TD together and have the real TD well
921.11Saugustss * aligned.
931.12Saugustss * NOTE: Minimum size is 32 bytes.
941.11Saugustss */
951.52.14.7Sskrll#define UHCI_STD_SIZE ((sizeof(struct uhci_soft_td) + UHCI_TD_ALIGN - 1) / UHCI_TD_ALIGN * UHCI_TD_ALIGN)
961.11Saugustss#define UHCI_STD_CHUNK 128 /*(PAGE_SIZE / UHCI_TD_SIZE)*/
971.1Saugustss
981.1Saugustss/*
991.1Saugustss * Extra information that we need for a QH.
1001.1Saugustss */
1011.1Saugustssstruct uhci_soft_qh {
1021.11Saugustss	uhci_qh_t qh;			/* The real QH, must be first */
1031.11Saugustss	uhci_soft_qh_t *hlink;		/* soft version of qh_hlink */
1041.11Saugustss	uhci_soft_td_t *elink;		/* soft version of qh_elink */
1051.11Saugustss	uhci_physaddr_t physaddr;	/* QH's physical address. */
1061.1Saugustss	int pos;			/* Timeslot position */
1071.45Sbouyer	usb_dma_t dma;			/* QH's DMA infos */
1081.45Sbouyer	int offs;			/* QH's offset in usb_dma_t */
1091.1Saugustss};
1101.11Saugustss/* See comment about UHCI_STD_SIZE. */
1111.52.14.7Sskrll#define UHCI_SQH_SIZE ((sizeof(struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) / UHCI_QH_ALIGN * UHCI_QH_ALIGN)
1121.11Saugustss#define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/
1131.1Saugustss
1141.1Saugustss/*
1151.19Saugustss * Information about an entry in the virtual frame list.
1161.1Saugustss */
1171.1Saugustssstruct uhci_vframe {
1181.1Saugustss	uhci_soft_td_t *htd;		/* pointer to dummy TD */
1191.1Saugustss	uhci_soft_td_t *etd;		/* pointer to last TD */
1201.1Saugustss	uhci_soft_qh_t *hqh;		/* pointer to dummy QH */
1211.1Saugustss	uhci_soft_qh_t *eqh;		/* pointer to last QH */
1221.1Saugustss	u_int bandwidth;		/* max bandwidth used by this frame */
1231.1Saugustss};
1241.1Saugustss
1251.1Saugustsstypedef struct uhci_softc {
1261.43Sdrochner	device_t sc_dev;
1271.43Sdrochner	struct usbd_bus sc_bus;
1281.8Saugustss	bus_space_tag_t iot;
1291.8Saugustss	bus_space_handle_t ioh;
1301.29Saugustss	bus_size_t sc_size;
1311.1Saugustss
1321.51Smrg	kmutex_t sc_lock;
1331.51Smrg	kmutex_t sc_intr_lock;
1341.51Smrg	kcondvar_t sc_softwake_cv;
1351.51Smrg
1361.1Saugustss	uhci_physaddr_t *sc_pframes;
1371.7Saugustss	usb_dma_t sc_dma;
1381.1Saugustss	struct uhci_vframe sc_vframes[UHCI_VFRAMELIST_COUNT];
1391.1Saugustss
1401.32Saugustss	uhci_soft_qh_t *sc_lctl_start;	/* dummy QH for low speed control */
1411.32Saugustss	uhci_soft_qh_t *sc_lctl_end;	/* last control QH */
1421.32Saugustss	uhci_soft_qh_t *sc_hctl_start;	/* dummy QH for high speed control */
1431.32Saugustss	uhci_soft_qh_t *sc_hctl_end;	/* last control QH */
1441.1Saugustss	uhci_soft_qh_t *sc_bulk_start;	/* dummy QH for bulk */
1451.1Saugustss	uhci_soft_qh_t *sc_bulk_end;	/* last bulk transfer */
1461.32Saugustss	uhci_soft_qh_t *sc_last_qh;	/* dummy QH at the end */
1471.52.14.1Sskrll	uint32_t sc_loops;		/* number of QHs that wants looping */
1481.1Saugustss
1491.19Saugustss	uhci_soft_td_t *sc_freetds;	/* TD free list */
1501.19Saugustss	uhci_soft_qh_t *sc_freeqhs;	/* QH free list */
1511.21Saugustss
1521.52Schristos	pool_cache_t sc_xferpool;	/* free xfer pool */
1531.1Saugustss
1541.52.14.1Sskrll	uint8_t sc_saved_sof;
1551.52.14.1Sskrll	uint16_t sc_saved_frnum;
1561.1Saugustss
1571.33Saugustss	char sc_softwake;
1581.35Saugustss
1591.1Saugustss	char sc_isreset;
1601.7Saugustss	char sc_suspend;
1611.22Saugustss	char sc_dying;
1621.1Saugustss
1631.52.14.11Sskrll	TAILQ_HEAD(, uhci_xfer) sc_intrhead;
1641.1Saugustss
1651.28Saugustss	/* Info for the root hub interrupt "pipe". */
1661.28Saugustss	int sc_ival;			/* time between root hub intrs */
1671.52.14.5Sskrll	struct usbd_xfer *sc_intr_xfer;	/* root hub interrupt transfer */
1681.48Sdyoung	struct callout sc_poll_handle;
1691.3Saugustss
1701.36Saugustss	char sc_vendor[32];		/* vendor string for root hub */
1711.19Saugustss	int sc_id_vendor;		/* vendor ID for root hub */
1721.19Saugustss
1731.48Sdyoung	device_t sc_child;		/* /dev/usb# device */
1741.1Saugustss} uhci_softc_t;
1751.1Saugustss
1761.52.14.4Sskrllint		uhci_init(uhci_softc_t *);
1771.31Saugustssint		uhci_intr(void *);
1781.31Saugustssint		uhci_detach(uhci_softc_t *, int);
1791.42Sdyoungvoid		uhci_childdet(device_t, device_t);
1801.42Sdyoungint		uhci_activate(device_t, enum devact);
1811.47Sdyoungbool		uhci_resume(device_t, const pmf_qual_t *);
1821.47Sdyoungbool		uhci_suspend(device_t, const pmf_qual_t *);
1831.52Schristos
1841.52Schristos#endif /* _UHCIVAR_H_ */
185