⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hc_sl811.c~

📁 基于linux嵌入式操作系统,sl811芯片的usb驱动源代码以及例子和Makefile.
💻 C~
📖 第 1 页 / 共 3 页
字号:
	    if (len > maxps)    {        len = maxps;    }    speed = hp->RHportStatus->portStatus;    if (speed & PORT_LOW_SPEED_DEV_ATTACH_STAT)    {//	ii = (8*7*8 + 6*3) * len + 800;         ii = 8*8*len + 1024;     }    else    {        if (slow)	{//	    ii = (8*7*8 + 6*3) * len + 800; 	    ii = 8*8*len + 2048;	}	else	//	    ii = (8*7 + 6*3)*len + 110;            ii = 8*len + 256;        }    ii += 2*10 * len;    jj = SL811Read(hci, SL11H_SOFTMRREG);    kk = (jj & 0xFF) * 64 - ii;    if (kk < 0)    {        DBGVERBOSE ("hc_add_trans: no bandwidth for schedule, ii = 0x%x,"                  "jj = 0x%x, len =0x%x, active_trans = 0x%x\n", ii, jj,                  len, hci->active_trans);        return (-1);    }     if (pid != PID_IN)     {        /* Load data into hc */	SL811BufWrite(hci, SL11H_DATA_START, (__u8 *) data, len);    }		        /* transmit */    SL11StartXaction(hci, (__u8) address, (__u8) endpoint,                     (__u8) pid, len, toggle, slow, urb_state);    return len;}/************************************************************************ * Function Name : hc_parse_trans *   * This function checks the status of the transmitted or received packet * and copy the data from the SL811HS register into a buffer. * * 1) Check the status of the packet  * 2) If successful, and IN packet then copy the data from the SL811HS register *    into a buffer * * Input:  hci = data structure for the host controller *         actbytes = pointer to actual number of bytes *         data = data buffer *         cc = packet status *         length = the urb transmit length *         pid = packet ID *         urb_state = the current stage of USB transaction *        * Return: 0  ***********************************************************************/static inline int hc_parse_trans (hci_t * hci, int * actbytes, __u8 * data, 		int * cc, int * toggle, int length, int pid, int urb_state){    __u8 addr;    __u8 len;    DBGFUNC ("enter hc_parse_trans\n");	    /* get packet status; convert ack rcvd to ack-not-rcvd */    *cc = (int) SL811Read(hci, SL11H_PKTSTATREG);    if (*cc & (SL11H_STATMASK_ERROR | SL11H_STATMASK_TMOUT |         SL11H_STATMASK_OVF | SL11H_STATMASK_NAK | SL11H_STATMASK_STALL))    { 	if (*cc & SL11H_STATMASK_OVF)            DBGERR ("parse trans: error recv ack, cc = 0x%x, TX_BASE_Len = "                "0x%x, TX_count=0x%x\n", *cc,                  SL811Read(hci, SL11H_BUFLNTHREG),                  SL811Read(hci, SL11H_XFERCNTREG));	    }    else     {        DBGVERBOSE ("parse trans: recv ack, cc = 0x%x, len = 0x%x, \n", 	 	 *cc, length);			/* Successful data */	if ((pid == PID_IN) && (urb_state != US_CTRL_SETUP))	{	    /* Find the base address */ 	    addr = SL811Read(hci, SL11H_BUFADDRREG);	    /* Find the Transmit Length */ 	    len = SL811Read(hci, SL11H_BUFLNTHREG);	    /* The actual data length = xmit length reg - xfer count reg */	    *actbytes = len - SL811Read(hci, SL11H_XFERCNTREG);	    if ((data != NULL) && (*actbytes > 0))	    {		SL811BufRead (hci, addr, data, *actbytes); 				    }	    else if ((data == NULL) && (*actbytes <=0))	    {		        DBGERR ("hc_parse_trans: data = NULL or actbyte = 0x%x\n",                          *actbytes);		return 0;	    }	}	else if (pid == PID_OUT)        {	    *actbytes = length;        }	else	{         // printk ("ERR:parse_trans, pid != IN or OUT, pid = 0x%x\n", pid);        }		*toggle = !*toggle;    }		    return 0;}/************************************************************************ * Function Name : hc_start_int *   * This function enables SL811HS interrupts * * Input:  hci = data structure for the host controller *        * Return: none  ***********************************************************************/static void hc_start_int (hci_t *hci){#ifdef HC_SWITCH_INT	    int mask = SL11H_INTMASK_XFERDONE | SL11H_INTMASK_SOFINTR |               SL11H_INTMASK_INSRMV | SL11H_INTMASK_USBRESET;    SL811Write (hci, IntEna, mask); #endif}	/************************************************************************ * Function Name : hc_stop_int *   * This function disables SL811HS interrupts * * Input:  hci = data structure for the host controller *        * Return: none  ***********************************************************************/static void hc_stop_int (hci_t *hci){#ifdef HC_SWITCH_INT    SL811Write(hci, SL11H_INTSTATREG, 0xff); //  SL811Write(hci, SL11H_INTENBLREG, SL11H_INTMASK_INSRMV);#endif}/************************************************************************ * Function Name : handleInsRmvIntr *   * This function handles the insertion or removal of device on  SL811HS.  * It resets the controller and updates the port status * * Input:  hci = data structure for the host controller *        * Return: none  ***********************************************************************/void handleInsRmvIntr (hci_t * hci){    hcipriv_t * hp = &hci->hp;     USBReset(hci);	    /* Changes in connection status */    hp->RHportStatus->portChange |=  PORT_CONNECT_CHANGE;    /* Port Enable or Disable */    if (hp->RHportStatus->portStatus & PORT_CONNECT_STAT)    {    /* device is connected to the port:     *    1) Enable port      *    2) Resume ??      *///               hp->RHportStatus->portChange |= PORT_ENABLE_CHANGE;		/* Over Current is not supported by the SL811 HW ?? */		/* How about the Port Power ?? */    }    else    {        /* Device has disconnect:	 *    1) Disable port	 */	 hp->RHportStatus->portStatus &= ~(PORT_ENABLE_STAT);	 hp->RHportStatus->portChange |= PORT_ENABLE_CHANGE;				    }}/***************************************************************** * * Function Name: SL11StartXaction *   * This functions load the registers with appropriate value and  * transmit the packet.				   * * Input:  hci = data structure for the host controller *         addr = USB address of the device *         epaddr = endpoint number *         pid = packet ID *         len = data length *         toggle = USB toggle bit, either 0 or 1 *         slow = speed of the device *         urb_state = the current stage of USB transaction * * Return: 0 = error; 1 = successful *                 *****************************************************************/int SL11StartXaction(hci_t *hci, __u8 addr, __u8 epaddr, int pid, int len,                      int toggle, int slow, int urb_state){	    hcipriv_t * hp = &hci->hp;     __u8 cmd = 0;    __u8 setup_data[4];    __u16 speed;    speed = hp->RHportStatus->portStatus;    if (!(speed & PORT_LOW_SPEED_DEV_ATTACH_STAT) && slow)    {        cmd |= SL11H_HCTLMASK_PREAMBLE;     }    switch (pid)    {        case PID_SETUP:	cmd &= SL11H_HCTLMASK_PREAMBLE;	cmd |= (SL11H_HCTLMASK_ARM | SL11H_HCTLMASK_ENBLEP             | SL11H_HCTLMASK_WRITE);	break;	case PID_OUT:	cmd &= (SL11H_HCTLMASK_SEQ | SL11H_HCTLMASK_PREAMBLE);	cmd |= (SL11H_HCTLMASK_ARM | SL11H_HCTLMASK_ENBLEP             | SL11H_HCTLMASK_WRITE); 	if (toggle)	{	    cmd |= SL11H_HCTLMASK_SEQ;	}	break;		case PID_IN:	cmd &= (SL11H_HCTLMASK_SEQ | SL11H_HCTLMASK_PREAMBLE);	cmd |= (SL11H_HCTLMASK_ARM | SL11H_HCTLMASK_ENBLEP);	break;	        default:	DBGERR ("ERR: SL11StartXaction: unknow pid = 0x%x\n", pid);	return 0;       }    setup_data[0] = SL11H_DATA_START;    setup_data[1] = len;    setup_data[2] = (((pid & 0x0F) << 4 ) | (epaddr & 0xF));    setup_data[3] = addr & 0x7F;    SL811BufWrite(hci, SL11H_BUFADDRREG, (__u8 *) &setup_data[0], 4);    SL811Write(hci, SL11H_HOSTCTLREG, cmd);#if 0    /* The SL811 has a hardware flaw when hub devices sends out     * SE0 between packets. It has been found in a TI chipset and     * cypress hub chipset. It causes the SL811 to hang     * The workaround is to re-issue the preample again.     */    if ((cmd & SL11H_HCTLMASK_PREAMBLE))    {        SL811Write (hci, SL11H_PIDEPREG_B, 0xc0); 	SL811Write (hci, SL11H_HOSTCTLREG_B, 0x1); // send the premable    }#endif    return 1;}/***************************************************************** * * Function Name: hc_interrupt * * Interrupt service routine.  * * 1) determine the causes of interrupt * 2) clears all interrupts * 3) calls appropriate function to service the interrupt * * Input:  irq = interrupt line associated with the controller  *         hci = data structure for the host controller *         r = holds the snapshot of the processor's context before  *             the processor entered interrupt code. (not used here)  * * Return value  : None. *                 *****************************************************************/static void hc_interrupt (int irq, void * __hci, struct pt_regs * r){    char ii;    hci_t * hci = __hci;    int isExcessNak = 0;    int urb_state = 0;    char tmpIrq = 0;     if((_reg_PORTD_ISR & 0x40)==0)return;      /* Get value from interrupt status register */	    ii = SL811Read(hci, SL11H_INTSTATREG);   SL811Write(hci, SL11H_INTSTATREG, 0xff);  _reg_PORTD_ISR |= 0x40;//if(ii==0x80)return;    if (ii & SL11H_INTMASK_INSRMV)    {        /* Device insertion or removal detected for the USB port */        SL811Write(hci, SL11H_INTENBLREG,0);		SL811Write(hci, SL11H_CTLREG1,0);	mdelay(100);			// wait for device stable         handleInsRmvIntr(hci);        return;    }    /* Clear all interrupts */    //    SL811Write(hci, SL11H_INTSTATREG, 0xff);   	    	    if (ii & SL11H_INTMASK_XFERDONE)    {        /* USB Done interrupt occurred */	urb_state = sh_done_list(hci, &isExcessNak);#ifdef WARNING	if (hci->td_array->len >0)	    printk ("WARNING: IRQ, td_array->len = 0x%x, s/b:0\n",	 	    hci->td_array->len);#endif	if (hci->td_array->len == 0 && !isExcessNak && 	    !(ii & SL11H_INTMASK_SOFINTR) && (urb_state ==0))	{	    if (urb_state == 0)            {                /* All urb_state has not been finished yet!                  * continue with the current urb transaction                  */		if (hci->last_packet_nak == 0)			{                    if (!usb_pipecontrol (hci->td_array->td[0].urb->pipe)) 		        sh_add_packet(hci, hci->td_array->td [0].urb); 	        }	    }            else	    {                /* The last transaction has completed:                 * schedule the next transaction                  */               	sh_schedule_trans(hci, 0);	    }        }	//        SL811Write(hci, SL11H_INTSTATREG, 0xff);   		return;    }    if (ii & SL11H_INTMASK_SOFINTR)    {        hci->frame_number = (hci->frame_number + 1) % 2048;	if (hci->td_array->len == 0)            sh_schedule_trans(hci, 1);	else	{	    if (sofWaitCnt++ > 100)		    {	        /* The last transaction has not completed.                 * Need to retire the current td, and let                 * it transmit again later on.		 * (THIS NEEDS TO BE WORK ON MORE, IT SHOULD NEVER 		 *  GET TO THIS POINT)                 */			        DBGERR ("SOF interrupt: td_array->len = 0x%x, s/b: 0\n",                          hci->td_array->len);		urb_print (hci->td_array->td [hci->td_array->len-1].urb,				       "INTERRUPT", 0);	        sh_done_list (hci, &isExcessNak);		SL811Write(hci, SL11H_INTSTATREG, 0xff);   			hci->td_array->len =0;	        sofWaitCnt=0;	    }	}	tmpIrq = SL811Read(hci, SL11H_INTSTATREG) 		 & SL811Read(hci, SL11H_INTENBLREG);	if (tmpIrq)	{	    DBG("IRQ occurred while service SOF: irq = 0x%x\n",tmpIrq);	    /* If we receive a DONE IRQ after schedule, need to 	     * handle DONE IRQ again 	     */	    if (tmpIrq & SL11H_INTMASK_XFERDONE)	    {	        DBGERR ("IRQ occurred while service SOF: irq = 0x%x\n",tmpIrq);		urb_state = sh_done_list (hci, &isExcessNak);	    }	    SL811Write(hci, SL11H_INTSTATREG, 0xff);   		}    }    else    {         DBG("SL811 ISR: unknown, int = 0x%x \n", ii);    }    // SL811Write(hci, SL11H_INTSTATREG, 0xff);   	    return;}/***************************************************************** * * Function Name: hc_reset * * This function does register test and resets the SL811HS  * controller. * * Input:  hci = data structure for the host controller * * Return value  : 0 *                 *****************************************************************/static int hc_reset (hci_t * hci){    int attachFlag = 0;    //Clear_interrupt();    //set_interrupt();    (*((volatile unsigned long *)0xf021b808)) &=0xfffffffd;  //cs3 or csd1    DBGFUNC ("Enter hc_reset\n");    regTest(hci);    attachFlag = USBReset(hci);    if (attachFlag)    {        setPortChange (hci, PORT_CONNECT_CHANGE);    }    return (0);}/***************************************************************** * * Function Name: hc_alloc_trans_buffer * * This function allocates all transfer buffer   * * 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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -