📄 usb-ohci.h
字号:
#define RH_A_NPS (1 << 9) /* no power switching */#define RH_A_DT (1 << 10) /* device type (mbz) */#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 *//* urb */typedef struct { ed_t * ed; __u16 length; // number of tds associated with this request __u16 td_cnt; // number of tds already serviced int state; wait_queue_head_t * wait; td_t * td[0]; // list pointer to all corresponding TDs associated with this request} urb_priv_t;#define URB_DEL 1/* Hash struct used for TD/ED hashing */struct hash_t { void *virt; dma_addr_t dma; struct hash_t *next; // chaining for collision cases};/* List of TD/ED hash entries */struct hash_list_t { struct hash_t *head; struct hash_t *tail;};#define TD_HASH_SIZE 64 /* power'o'two */#define ED_HASH_SIZE 64 /* power'o'two */#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE)#define ED_HASH_FUNC(ed_dma) ((ed_dma ^ (ed_dma >> 5)) % ED_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) */typedef struct ohci { struct ohci_hcca *hcca; /* hcca */ dma_addr_t hcca_dma; int irq; int disabled; /* e.g. got a UE, we're hung */ int sleeping; atomic_t resume_count; /* defending against multiple resumes */ unsigned long flags; /* for HC bugs */#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ struct ohci_regs * regs; /* OHCI controller's memory */ struct list_head ohci_hcd_list; /* list of all ohci_hcd */ struct ohci * next; // chain of ohci device contexts struct list_head timeout_list; // struct list_head urb_list; // list of all pending urbs // spinlock_t urb_list_lock; // lock to keep consistency int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ ed_t * ed_rm_list[2]; /* lists of all endpoints to be removed */ ed_t * ed_bulktail; /* last endpoint of bulk list */ ed_t * ed_controltail; /* last endpoint of control list */ ed_t * ed_isotail; /* last endpoint of iso list */ int intrstatus; __u32 hc_control; /* copy of the hc control reg */ struct usb_bus * bus; struct usb_device * dev[128]; struct virt_root_hub rh; /* PCI device handle, settings, ... */ struct pci_dev *ohci_dev; const char *slot_name; u8 pci_latency; struct pci_pool *td_cache; struct pci_pool *dev_cache; struct hash_list_t td_hash[TD_HASH_SIZE]; struct hash_list_t ed_hash[ED_HASH_SIZE];} ohci_t;#define NUM_EDS 32 /* num of preallocated endpoint descriptors */struct ohci_device { ed_t ed[NUM_EDS]; dma_addr_t dma; int ed_cnt; wait_queue_head_t * wait;};// #define ohci_to_usb(ohci) ((ohci)->usb)#define usb_to_ohci(usb) ((struct ohci_device *)(usb)->hcpriv)#ifndef OHCI_HW_DRIVER/* hcd *//* endpoint */static int ep_link(ohci_t * ohci, ed_t * edi);static int ep_unlink(ohci_t * ohci, ed_t * ed);static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load, int mem_flags);static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed);/* td */static void td_fill(ohci_t * ohci, unsigned int info, dma_addr_t data, int len, urb_t * urb, int index);static void td_submit_urb(urb_t * urb);/* root hub */static int rh_submit_urb(urb_t * urb);static int rh_unlink_urb(urb_t * urb);static int rh_init_int_timer(urb_t * urb);/*-------------------------------------------------------------------------*/#define ALLOC_FLAGS (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL)#ifdef DEBUG# define OHCI_MEM_FLAGS SLAB_POISON#else# define OHCI_MEM_FLAGS 0#endif #ifndef CONFIG_PCI//# error "usb-ohci currently requires PCI-based controllers" /* to support non-PCI OHCIs, you need custom bus/mem/... glue */#endif/* Recover a TD/ED using its collision chain */static inline void *dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma){ struct hash_t * scan = entry->head; while (scan && scan->dma != dma) scan = scan->next; if (!scan) BUG(); return scan->virt;}static inline struct ed *dma_to_ed (struct ohci * hc, dma_addr_t ed_dma){ return (struct ed *) dma_to_ed_td(&(hc->ed_hash[ED_HASH_FUNC(ed_dma)]), ed_dma);}static inline struct td *dma_to_td (struct ohci * hc, dma_addr_t td_dma){ return (struct td *) dma_to_ed_td(&(hc->td_hash[TD_HASH_FUNC(td_dma)]), td_dma);}/* Add a hash entry for a TD/ED; return true on success */static inline inthash_add_ed_td(struct hash_list_t * entry, void * virt, dma_addr_t dma){ struct hash_t * scan; scan = (struct hash_t *)kmalloc(sizeof(struct hash_t), ALLOC_FLAGS); if (!scan) return 0; if (!entry->tail) { entry->head = entry->tail = scan; } else { entry->tail->next = scan; entry->tail = scan; } scan->virt = virt; scan->dma = dma; scan->next = NULL; return 1;}static inline inthash_add_ed (struct ohci * hc, struct ed * ed){ return hash_add_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed, ed->dma);}static inline inthash_add_td (struct ohci * hc, struct td * td){ return hash_add_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td, td->td_dma);}static inline voidhash_free_ed_td (struct hash_list_t * entry, void * virt){ struct hash_t *scan, *prev; scan = prev = entry->head; // Find and unlink hash entry while (scan && scan->virt != virt) { prev = scan; scan = scan->next; } if (scan) { if (scan == entry->head) { if (entry->head == entry->tail) entry->head = entry->tail = NULL; else entry->head = scan->next; } else if (scan == entry->tail) { entry->tail = prev; prev->next = NULL; } else prev->next = scan->next; kfree(scan); }}static inline voidhash_free_ed (struct ohci * hc, struct ed * ed){ hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed);}static inline voidhash_free_td (struct ohci * hc, struct td * td){ hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td);}static int ohci_mem_init (struct ohci *ohci){ ohci->td_cache = pci_pool_create ("ohci_td", ohci->ohci_dev, sizeof (struct td), 32 /* byte alignment */, 0 /* no page-crossing issues */, GFP_KERNEL | OHCI_MEM_FLAGS); if (!ohci->td_cache) return -ENOMEM; ohci->dev_cache = pci_pool_create ("ohci_dev", ohci->ohci_dev, sizeof (struct ohci_device), 16 /* byte alignment */, 0 /* no page-crossing issues */, GFP_KERNEL | OHCI_MEM_FLAGS); if (!ohci->dev_cache) return -ENOMEM; return 0;}static void ohci_mem_cleanup (struct ohci *ohci){ if (ohci->td_cache) { printk(__FUNCTION__"(%d)\n", __LINE__); pci_pool_destroy (ohci->td_cache); printk(__FUNCTION__"(%d)\n", __LINE__); ohci->td_cache = 0; } if (ohci->dev_cache) { printk(__FUNCTION__"(%d)\n", __LINE__); pci_pool_destroy (ohci->dev_cache); printk(__FUNCTION__"(%d)\n", __LINE__); ohci->dev_cache = 0; }}/* TDs ... */static inline struct td *td_alloc (struct ohci *hc, int mem_flags){ dma_addr_t dma; struct td *td; td = pci_pool_alloc (hc->td_cache, mem_flags, &dma); if (td) { td->td_dma = dma; /* hash it for later reverse mapping */ if (!hash_add_td (hc, td)) { pci_pool_free (hc->td_cache, td, dma); return NULL; } } return td;}static inline voidtd_free (struct ohci *hc, struct td *td){ hash_free_td (hc, td); pci_pool_free (hc->td_cache, td, td->td_dma);}/* DEV + EDs ... only the EDs need to be consistent */static inline struct ohci_device *dev_alloc (struct ohci *hc, int mem_flags){ dma_addr_t dma; struct ohci_device *dev; int i, offset; dev = pci_pool_alloc (hc->dev_cache, mem_flags, &dma); if (dev) { memset (dev, 0, sizeof (*dev)); dev->dma = dma; offset = ((char *)&dev->ed) - ((char *)dev); for (i = 0; i < NUM_EDS; i++, offset += sizeof dev->ed [0]) dev->ed [i].dma = dma + offset; /* add to hashtable if used */ } return dev;}static inline voiddev_free (struct ohci *hc, struct ohci_device *dev){ pci_pool_free (hc->dev_cache, dev, dev->dma);}#endif // not OHCI_HW_DRIVER#endif // USB_OHCI_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -