Here is my code for the device interrupt request:
Code: Select all
bool EhciDevIntr(UsbPipe *pipe, int len, void *obuff) {
UsbDevice *dev = (UsbDevice *)pipe->usbDev;
EhciController *ctrl = (EhciController *)dev->priv_data;
if (pipe->controller_info == NULL) {
// allocate and PREPARE the Queue Head and the TD, put them into periodic list.
EhciTD *td = EhciAllocTD(ctrl);
if (!td) {
return false;
}
EhciInitTD(td,NULL,dev->last_toggle,USB_PACKET_IN,len,buff);
EhciQueueHead *qh = EhciAllocQH(ctrl);
// allocated queue head CAN have the H bit set, remove it.
if (!qh) {
td->active = 0;
return false;
}
qh->curLink = PTR_TERMINATE;
EhciInitQH(qh,td,false,dev->speed,dev->addr,dev->in_endp.addr,dev->maxPacketSize,dev);
qh->caps &= ~(1<<15);
qh->caps |= (0x01 <<0) | (0x1c << 8);
qh->qhLinkPtr = PTR_TERMINATE;
qh->ch |= QH_CH_H;
int interval = dev->in_endp.interval;
uint32_t physOfQh = (uint32_t)(uintptr_t)arch_mmu_getPhysical(qh);
EhciPipeInfo *my_pipe = (EhciPipeInfo *)kmalloc(sizeof(EhciPipeInfo));
memset(my_pipe,0,sizeof(EhciPipeInfo));
my_pipe->qh = qh;
my_pipe->td = td;
my_pipe->physOfTd = (uint32_t)(uintptr_t)arch_mmu_getPhysical(td);
pipe->controller_info = my_pipe;
for (int i = 0; i < 1024; i += (1 << (interval - 1))) {
uint32_t old = ctrl->periodicList[i];
qh->qhLinkPtr = old;
ctrl->periodicList[i] = physOfQh | PTR_QH;
}
} else {
EhciPipeInfo *my_pipe = (EhciPipeInfo *)pipe->controller_info;
if ((my_pipe->td->token & TD_TOK_ACTIVE) != 0) {
// kprintf("EHCI says transfer didn't end....(0x%x, qh td = 0x%x)\r\n",my_pipe->td->token,my_pipe->qh->nextLink);
// stil active, nothing to process.
kprintf("token still active!\r\n");
return false;
}
EhciInitTD(my_pipe->td,NULL,dev->last_toggle,USB_PACKET_IN,len,buff);
my_pipe->qh->nextLink = (my_pipe->physOfTd);
my_pipe->qh->caps &= ~(1 << 15);
my_pipe->qh->qhLinkPtr = PTR_TERMINATE;
}
dev->last_toggle ^= 1;
return true;
}

