EHCI的interrupt在HCD中被分为了6种类型,如下宏定义:
/* these STS_* flags are also intr_enable bits (USBINTR) */
#define STS_IAA (1<<5) /* Interrupted on async advance */
#define STS_FATAL (1<<4) /* such as some PCI access errors */
#define STS_FLR (1<<3) /* frame list rolled over */
#define STS_PCD (1<<2) /* port change detect */
#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */
#define STS_INT (1<<0) /* "normal" completion (short, ...) */
这些就是触发EHCI产生中断的各种类型,在中断处理函数ehci_irq()中要对这几种interrupt作出不同的处理,先简单介绍一下各个interrupt的情况。
IAA是指当要从asynchronous schedule传输队列中移除一个QH时,为了解决被移除的QH的值可能在HC(host controller)中有缓存,为了使内存和HC中的 qh保持一致,而需要在HCD(host controller driver)移除某个QH后对HC的缓存进行更新,从而使内存中的QH队列与HC的缓存保持一致,当HC完成缓存更新后,且相应的中断enable,就会发出一个IAA中断告之HCD更新完成。
PCD(port change detect)是指root hub上某个端口上有设备插入或拔出所产生的中断,需要进一步的读取root hub上各port对应的register判断是插入还是拔出。
ERR是指在HC和device间数据传输失败后发出的传输出错中断,出错的原因会被回写到当前用于传输的描述中,如qtd的token中。
INT是指正确完成一次数据传输后所发出的中断,这个中断并不是在传输完成后马上产生的,它要等到下一个中断时隙的到来后才产生。
EHCI HC中与中断相关的register有USBSTS和USBINTR两个,而在linux 中的执行EHCI的irq处理函数就是ehci_irq(),代码如下:
1. static irqreturn_t ehci_irq (struct usb_hcd *hcd)
2. {
3. struct ehci_hcd *ehci = hcd_to_ehci (hcd);
4. u32 status, masked_status, pcd_status = 0, cmd;
5. int bh;
6. spin_lock (&ehci->lock);
7. status = ehci_readl(ehci, &ehci->regs->status);<