📄 hc_sl811.c
字号:
* Input: hci = data structure for the host controller * * Return value : 0 * *****************************************************************/static int hc_alloc_trans_buffer (hci_t * hci){ hcipriv_t *hp = &hci->hp; int maxlen; hp->itl0_len = 0; hp->itl1_len = 0; hp->atl_len = 0; hp->itl_buffer_len = 1024; hp->atl_buffer_len = 4096 - 2 * hp->itl_buffer_len; /* 2048 */ maxlen = (hp->itl_buffer_len > hp->atl_buffer_len) ? hp->itl_buffer_len : hp->atl_buffer_len; hp->tl = kmalloc (maxlen, GFP_KERNEL); if (!hp->tl) return -ENOMEM; memset (hp->tl, 0, maxlen); return 0;}/***************************************************************** * * Function Name: getPortStatusAndChange * * This function gets the ports status from SL811 and format it * to a USB request format * * Input: hci = data structure for the host controller * * Return value : port status and change * *****************************************************************/static __u32 getPortStatusAndChange (hci_t * hci){ hcipriv_t *hp = &hci->hp; __u32 portstatus; DBGFUNC ("enter getPorStatusAndChange\n"); portstatus = hp->RHportStatus->portChange << 16 | hp->RHportStatus->portStatus; return (portstatus);}/***************************************************************** * * Function Name: setPortChange * * This function set the bit position of portChange. * * Input: hci = data structure for the host controller * bitPos = the bit position * * Return value : none * *****************************************************************/static void setPortChange (hci_t * hci, __u16 bitPos){ hcipriv_t *hp = &hci->hp; switch (bitPos) { case PORT_CONNECT_STAT: hp->RHportStatus->portChange |= bitPos; break; case PORT_ENABLE_STAT: hp->RHportStatus->portChange |= bitPos; break; case PORT_RESET_STAT: hp->RHportStatus->portChange |= bitPos; break; case PORT_POWER_STAT: hp->RHportStatus->portChange |= bitPos; break; case PORT_SUSPEND_STAT: hp->RHportStatus->portChange |= bitPos; break; case PORT_OVER_CURRENT_STAT: hp->RHportStatus->portChange |= bitPos; break; }}/***************************************************************** * * Function Name: clrPortChange * * This function clear the bit position of portChange. * * Input: hci = data structure for the host controller * bitPos = the bit position * * Return value : none * *****************************************************************/static void clrPortChange (hci_t * hci, __u16 bitPos){ hcipriv_t *hp = &hci->hp; switch (bitPos) { case PORT_CONNECT_CHANGE: hp->RHportStatus->portChange &= ~bitPos; break; case PORT_ENABLE_CHANGE: hp->RHportStatus->portChange &= ~bitPos; break; case PORT_RESET_CHANGE: hp->RHportStatus->portChange &= ~bitPos; break; case PORT_SUSPEND_CHANGE: hp->RHportStatus->portChange &= ~bitPos; break; case PORT_OVER_CURRENT_CHANGE: hp->RHportStatus->portChange &= ~bitPos; break; }}/***************************************************************** * * Function Name: clrPortStatus * * This function clear the bit position of portStatus. * * Input: hci = data structure for the host controller * bitPos = the bit position * * Return value : none * *****************************************************************/static void clrPortStatus (hci_t * hci, __u16 bitPos){ hcipriv_t *hp = &hci->hp; switch (bitPos) { case PORT_ENABLE_STAT: hp->RHportStatus->portStatus &= ~bitPos; break; case PORT_RESET_STAT: hp->RHportStatus->portStatus &= ~bitPos; break; case PORT_POWER_STAT: hp->RHportStatus->portStatus &= ~bitPos; break; case PORT_SUSPEND_STAT: hp->RHportStatus->portStatus &= ~bitPos; break; }}/***************************************************************** * * Function Name: setPortStatus * * This function set the bit position of portStatus. * * Input: hci = data structure for the host controller * bitPos = the bit position * * Return value : none * *****************************************************************/static void setPortStatus (hci_t * hci, __u16 bitPos){ hcipriv_t *hp = &hci->hp; switch (bitPos) { case PORT_ENABLE_STAT: hp->RHportStatus->portStatus |= bitPos; break; case PORT_RESET_STAT: hp->RHportStatus->portStatus |= bitPos; break; case PORT_POWER_STAT: hp->RHportStatus->portStatus |= bitPos; break; case PORT_SUSPEND_STAT: hp->RHportStatus->portStatus |= bitPos; break; }}/***************************************************************** * * Function Name: hc_start * * This function starts the root hub functionality. * * Input: hci = data structure for the host controller * * Return value : 0 * *****************************************************************/static int hc_start (hci_t * hci){ DBGFUNC ("Enter hc_start\n"); rh_connect_rh (hci); return 0;}/***************************************************************** * * Function Name: hc_alloc_hci * * This function allocates all data structure and store in the * private data structure. * * Input: hci = data structure for the host controller * * Return value : 0 * *****************************************************************/static hci_t *__devinit hc_alloc_hci (void){ hci_t *hci; hcipriv_t *hp; portstat_t *ps; struct usb_bus *bus; DBGFUNC ("Enter hc_alloc_hci\n"); hci = (hci_t *) kmalloc (sizeof (hci_t), GFP_KERNEL); if (!hci) return NULL; memset (hci, 0, sizeof (hci_t)); hp = &hci->hp; hp->irq = -1; hp->hcport = -1; /* setup root hub port status */ ps = (portstat_t *) kmalloc (sizeof (portstat_t), GFP_KERNEL); if (!ps) return NULL; ps->portStatus = PORT_STAT_DEFAULT; ps->portChange = PORT_CHANGE_DEFAULT; hp->RHportStatus = ps; hci->nakCnt = 0; hci->last_packet_nak = 0; hci->a_td_array.len = 0; hci->i_td_array[0].len = 0; hci->i_td_array[1].len = 0; hci->td_array = &hci->a_td_array; hci->active_urbs = 0; hci->active_trans = 0; INIT_LIST_HEAD (&hci->hci_hcd_list); list_add (&hci->hci_hcd_list, &hci_hcd_list); init_waitqueue_head (&hci->waitq); INIT_LIST_HEAD (&hci->ctrl_list); INIT_LIST_HEAD (&hci->bulk_list); INIT_LIST_HEAD (&hci->iso_list); INIT_LIST_HEAD (&hci->intr_list); INIT_LIST_HEAD (&hci->del_list); bus = usb_alloc_bus (&hci_device_operations); if (!bus) { kfree (hci); return NULL; } hci->bus = bus; bus->bus_name = "sl811"; bus->hcpriv = (void *) hci; return hci;}/***************************************************************** * * Function Name: hc_release_hci * * This function De-allocate all resources * * Input: hci = data structure for the host controller * * Return value : 0 * *****************************************************************/static void hc_release_hci (hci_t * hci){ hcipriv_t *hp = &hci->hp; DBGFUNC ("Enter hc_release_hci\n"); /* disconnect all devices */ if (hci->bus->root_hub) usb_disconnect (&hci->bus->root_hub); hc_reset (hci); if (hp->tl) kfree (hp->tl); /* (hne) */ release_regions(hp); if (hp->irq >= 0) { free_irq (hp->irq, hci); hp->irq = -1; } usb_deregister_bus (hci->bus); usb_free_bus (hci->bus); list_del (&hci->hci_hcd_list); INIT_LIST_HEAD (&hci->hci_hcd_list); kfree (hci);}/***************************************************************** * * Function Name: hc_found_hci * * This function request IO memory regions, request IRQ, and * allocate all other resources. * * Input: addr = first IO address * addr2 = second IO address * irq = interrupt number * * Return: 0 = success or error condition * *****************************************************************/static int __devinit hc_found_hci (int irq){ hci_t *hci; hcipriv_t *hp; DBGFUNC ("Enter hc_found_hci\n"); hci = hc_alloc_hci (); if (!hci) { return -ENOMEM; } init_irq (); hp = &hci->hp; if (request_regions (hp)) { hc_release_hci (hci); return -EBUSY; } if (hc_alloc_trans_buffer (hci)) { hc_release_hci (hci); return -ENOMEM; } usb_register_bus (hci->bus); if (request_irq (irq, hc_interrupt, 0, "SL811", hci) != 0) { DBGERR ("request interrupt %d failed", irq); hc_release_hci (hci); return -EBUSY; } hp->irq = irq;#ifdef CONFIG_SA1100_ACCELENT printk (KERN_INFO __FILE__ ": USB SL811 at %x, addr2 = %x, IRQ %d\n", hp->hcport, hp->hcport2, irq);#endif #ifdef SL811_DEBUG_VERBOSE { __u8 u = SL811Read (hci, SL11H_HWREVREG); DBGVERBOSE ("SL811 HW: %02Xh ", u); switch (u & 0xF0) { case 0x00: DBGVERBOSE ("SL11H\n"); break; case 0x10: DBGVERBOSE ("SL811HS rev1.2\n"); break; case 0x20: DBGVERBOSE ("SL811HS rev1.5\n"); break; default: DBGVERBOSE ("unknown!\n"); } } #endif // SL811_DEBUG_VERBOSE hc_reset (hci); if (hc_start (hci) < 0) { DBGERR ("can't start usb-%x", hp->hcport); hc_release_hci (hci); return -EBUSY; } return 0;}/***************************************************************** * * Function Name: hci_hcd_init * * This is an init function, and it is the first function being called * * Input: none * * Return: 0 = success or error condition * *****************************************************************/static int __init hci_hcd_init (void){ int ret; DBGFUNC ("Enter hci_hcd_init\n"); DBGVERBOSE ("SL811 VERBOSE enabled\n");#ifdef CONFIG_SA1110_ACCELENT ret = hc_found_hci (irq);#endif#ifdef CONFIG_ARCH_RAMSES ret = hc_found_hci(SL811HS_IRQ);#endif return ret;}/***************************************************************** * * Function Name: hci_hcd_cleanup * * This is a cleanup function, and it is called when module is * unloaded. * * Input: none * * Return: none * *****************************************************************/static void __exit hci_hcd_cleanup (void){ struct list_head *hci_l; hci_t *hci; DBGFUNC ("Enter hci_hcd_cleanup\n"); for (hci_l = hci_hcd_list.next; hci_l != &hci_hcd_list;) { hci = list_entry (hci_l, hci_t, hci_hcd_list); hci_l = hci_l->next; hc_release_hci (hci); }}module_init (hci_hcd_init);module_exit (hci_hcd_cleanup);MODULE_AUTHOR ("Pei Liu <pbl@cypress.com>");MODULE_DESCRIPTION ("USB SL811HS Host Controller Driver");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -