📄 ohci.h
字号:
#define RH_A_OCPM (1 << 11) /* over current protection mode */#define RH_A_NOCP (1 << 12) /* no over current protection */#define RH_A_POTPGT (0xff << 24) /* power on to power good time *//* hcd-private per-urb state */typedef struct urb_priv { struct ed *ed; u16 length; // # tds in this request u16 td_cnt; // tds already serviced struct list_head pending; struct td *td [0]; // all TDs in this request} urb_priv_t;#define TD_HASH_SIZE 64 /* power'o'two */// sizeof (struct td) ~= 64 == 2^6 ... #define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE)/* * This is the full ohci controller description * * Note how the "proper" USB information is just * a subset of what the full implementation needs. (Linus) */struct ohci_hcd { spinlock_t lock; /* * I/O memory used to communicate with the HC (dma-consistent) */ struct ohci_regs __iomem *regs; /* * main memory used to communicate with the HC (dma-consistent). * hcd adds to schedule for a live hc any time, but removals finish * only at the start of the next frame. */ struct ohci_hcca *hcca; dma_addr_t hcca_dma; struct ed *ed_rm_list; /* to be removed */ struct ed *ed_bulktail; /* last in bulk list */ struct ed *ed_controltail; /* last in ctrl list */ struct ed *periodic [NUM_INTS]; /* shadow int_table */ /* * OTG controllers and transceivers need software interaction; * other external transceivers should be software-transparent */ struct otg_transceiver *transceiver; /* * memory management for queue data structures */ struct dma_pool *td_cache; struct dma_pool *ed_cache; struct td *td_hash [TD_HASH_SIZE]; struct list_head pending; /* * driver state */ int num_ports; int load [NUM_INTS]; u32 hc_control; /* copy of hc control reg */ unsigned long next_statechange; /* suspend/resume */ u32 fminterval; /* saved register */ struct notifier_block reboot_notifier; unsigned long flags; /* for HC bugs */#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */#define OHCI_BIG_ENDIAN 0x08 /* big endian HC */#define OHCI_QUIRK_ZFMICRO 0x10 /* Compaq ZFMicro chipset*/ // there are also chip quirks/bugs in init logic};/* convert between an hcd pointer and the corresponding ohci_hcd */static inline struct ohci_hcd *hcd_to_ohci (struct usb_hcd *hcd){ return (struct ohci_hcd *) (hcd->hcd_priv);}static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci){ return container_of ((void *) ohci, struct usb_hcd, hcd_priv);}/*-------------------------------------------------------------------------*/#ifndef DEBUG#define STUB_DEBUG_FILES#endif /* DEBUG */#define ohci_dbg(ohci, fmt, args...) \ dev_dbg (ohci_to_hcd(ohci)->self.controller , fmt , ## args )#define ohci_err(ohci, fmt, args...) \ dev_err (ohci_to_hcd(ohci)->self.controller , fmt , ## args )#define ohci_info(ohci, fmt, args...) \ dev_info (ohci_to_hcd(ohci)->self.controller , fmt , ## args )#define ohci_warn(ohci, fmt, args...) \ dev_warn (ohci_to_hcd(ohci)->self.controller , fmt , ## args )#ifdef OHCI_VERBOSE_DEBUG# define ohci_vdbg ohci_dbg#else# define ohci_vdbg(ohci, fmt, args...) do { } while (0)#endif/*-------------------------------------------------------------------------*//* * While most USB host controllers implement their registers and * in-memory communication descriptors in little-endian format, * a minority (notably the IBM STB04XXX and the Motorola MPC5200 * processors) implement them in big endian format. * * This attempts to support either format at compile time without a * runtime penalty, or both formats with the additional overhead * of checking a flag bit. */#ifdef CONFIG_USB_OHCI_BIG_ENDIAN#ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN#define big_endian(ohci) (ohci->flags & OHCI_BIG_ENDIAN) /* either */#else#define big_endian(ohci) 1 /* only big endian */#endif/* * Big-endian read/write functions are arch-specific. * Other arches can be added if/when they're needed. */#if defined(CONFIG_PPC)#define readl_be(addr) in_be32((__force unsigned *)addr)#define writel_be(val, addr) out_be32((__force unsigned *)addr, val)#endifstatic inline unsigned int ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs){ return big_endian(ohci) ? readl_be (regs) : readl ((__force u32 *)regs);}static inline void ohci_writel (const struct ohci_hcd *ohci, const unsigned int val, __hc32 __iomem *regs){ big_endian(ohci) ? writel_be (val, regs) : writel (val, (__force u32 *)regs);}#else /* !CONFIG_USB_OHCI_BIG_ENDIAN */#define big_endian(ohci) 0 /* only little endian */#ifdef CONFIG_ARCH_LH7A404 /* Marc Singer: at the time this code was written, the LH7A404 * had a problem reading the USB host registers. This * implementation of the ohci_readl function performs the read * twice as a work-around. */static inline unsigned intohci_readl (const struct ohci_hcd *ohci, const __hc32 *regs){ *(volatile __force unsigned int*) regs; return *(volatile __force unsigned int*) regs;}#else /* Standard version of ohci_readl uses standard, platform * specific implementation. */static inline unsigned intohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs){ return readl(regs);}#endifstatic inline void ohci_writel (const struct ohci_hcd *ohci, const unsigned int val, __hc32 __iomem *regs){ writel (val, regs);}#endif /* !CONFIG_USB_OHCI_BIG_ENDIAN *//*-------------------------------------------------------------------------*//* cpu to ohci */static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x){ return big_endian(ohci) ? (__force __hc16)cpu_to_be16(x) : (__force __hc16)cpu_to_le16(x);}static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x){ return big_endian(ohci) ? cpu_to_be16p(x) : cpu_to_le16p(x);}static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x){ return big_endian(ohci) ? (__force __hc32)cpu_to_be32(x) : (__force __hc32)cpu_to_le32(x);}static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x){ return big_endian(ohci) ? cpu_to_be32p(x) : cpu_to_le32p(x);}/* ohci to cpu */static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x){ return big_endian(ohci) ? be16_to_cpu((__force __be16)x) : le16_to_cpu((__force __le16)x);}static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x){ return big_endian(ohci) ? be16_to_cpup((__force __be16 *)x) : le16_to_cpup((__force __le16 *)x);}static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x){ return big_endian(ohci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x);}static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x){ return big_endian(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x);}/*-------------------------------------------------------------------------*//* HCCA frame number is 16 bits, but is accessed as 32 bits since not all * hardware handles 16 bit reads. That creates a different confusion on * some big-endian SOC implementations. Same thing happens with PSW access. */#ifdef CONFIG_STB03xxx#define OHCI_BE_FRAME_NO_SHIFT 16#else#define OHCI_BE_FRAME_NO_SHIFT 0#endifstatic inline u16 ohci_frame_no(const struct ohci_hcd *ohci){ u32 tmp; if (big_endian(ohci)) { tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no); tmp >>= OHCI_BE_FRAME_NO_SHIFT; } else tmp = le32_to_cpup((__force __le32 *)&ohci->hcca->frame_no); return (u16)tmp;}static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci, const struct td *td, int index){ return (__hc16 *)(big_endian(ohci) ? &td->hwPSW[index ^ 1] : &td->hwPSW[index]);}static inline u16 ohci_hwPSW(const struct ohci_hcd *ohci, const struct td *td, int index){ return hc16_to_cpup(ohci, ohci_hwPSWp(ohci, td, index));}/*-------------------------------------------------------------------------*/static inline void disable (struct ohci_hcd *ohci){ ohci_to_hcd(ohci)->state = HC_STATE_HALT;}#define FI 0x2edf /* 12000 bits per frame (-1) */#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))#define FIT (1 << 31)#define LSTHRESH 0x628 /* lowspeed bit threshold */static void periodic_reinit (struct ohci_hcd *ohci){ u32 fi = ohci->fminterval & 0x03fff; u32 fit = ohci_readl(ohci, &ohci->regs->fminterval) & FIT; ohci_writel (ohci, (fit ^ FIT) | ohci->fminterval, &ohci->regs->fminterval); ohci_writel (ohci, ((9 * fi) / 10) & 0x3fff, &ohci->regs->periodicstart);}/* AMD-756 (D2 rev) reports corrupt register contents in some cases. * The erratum (#4) description is incorrect. AMD's workaround waits * till some bits (mostly reserved) are clear; ok for all revs. */#define read_roothub(hc, register, mask) ({ \ u32 temp = ohci_readl (hc, &hc->regs->roothub.register); \ if (temp == -1) \ disable (hc); \ else if (hc->flags & OHCI_QUIRK_AMD756) \ while (temp & mask) \ temp = ohci_readl (hc, &hc->regs->roothub.register); \ temp; })static u32 roothub_a (struct ohci_hcd *hc) { return read_roothub (hc, a, 0xfc0fe000); }static inline u32 roothub_b (struct ohci_hcd *hc) { return ohci_readl (hc, &hc->regs->roothub.b); }static inline u32 roothub_status (struct ohci_hcd *hc) { return ohci_readl (hc, &hc->regs->roothub.status); }static u32 roothub_portstatus (struct ohci_hcd *hc, int i) { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -