📄 3332 驱动源码.c
字号:
/*****************************************************************
*
* 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);
kfree (ps);
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);
if (hp->hcport > 0) {
release_region (hp->hcport, 2);
hp->hcport = 0;
}
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);
}
#ifndef CONFIG_COLDFIRE
/*****************************************************************
*
* Function Name: init_irq
*
* This function is board specific. It sets up the interrupt to
* be an edge trigger and trigger on the rising edge
*
* Input: none
*
* Return value : none
*
*****************************************************************/
void init_irq (void)
{
//GPDR &= ~(1 << 13);
//set_GPIO_IRQ_edge (1 << 13, GPIO_RISING_EDGE);
int i;
i=0;
i++;
}
#endif
/*****************************************************************
*
* 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 addr, int addr2, int irq)
{
hci_t *hci;
hcipriv_t *hp;
DBGFUNC ("Enter hc_found_hci\n");
hci = hc_alloc_hci ();
if (!hci) {
return -ENOMEM;
}
#ifndef CONFIG_COLDFIRE
/*
* This is arm specific!
*/
init_irq ();
hp = &hci->hp;
#endif
if (!request_region (addr, 256, "SL811 USB HOST")) {
DBGERR ("request address %d failed", addr);
hc_release_hci (hci);
return -EBUSY;
}
hp->hcport = addr;
if (!hp->hcport) {
DBGERR ("Error mapping SL811 Memory 0x%x", hp->hcport);
}
if (!request_region (addr2, 256, "SL811 USB HOST")) {
DBGERR ("request address %d failed", addr2);
hc_release_hci (hci);
return -EBUSY;
}
hp->hcport2 = addr2;
if (!hp->hcport2) {
DBGERR ("Error mapping SL811 Memory 0x%x", hp->hcport2);
}
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;
printk (KERN_INFO __FILE__ ": USB SL811 at %x, addr2 = %x, IRQ %d\n",
addr, addr2, irq);
hc_reset (hci);
if (hc_start (hci) < 0) {
DBGERR ("can't start usb-%x", addr);
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;
#ifdef CONFIG_USB_SL811HC_AUTO
int index;
DBGFUNC ("Enter hci_hcd_init with auto probe!\n");
for( index = 0, ret = -1; sl811hc_portlist[index], ret; index++ )
ret = hc_found_hci ( sl811hc_portlist[index], sl811hc_datalist[index], sl811hc_irqlist[index] );
#else
DBGFUNC ("Enter hci_hcd_init\n");
ret = hc_found_hci (base_addr, data_reg_addr, 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 + -