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

📄 usb_ohci.c

📁 基于s3c2440的U盘读写程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Configuration descriptor */
static U8 root_hub_config_des[] =
{
    0x09,       /*  __u8  bLength; */
    0x02,       /*  __u8  bDescriptorType; Configuration */
    0x19,       /*  __u16 wTotalLength; */
    0x00,
    0x01,       /*  __u8  bNumInterfaces; */
    0x01,       /*  __u8  bConfigurationValue; */
    0x00,       /*  __u8  iConfiguration; */
    0x40,       /*  __u8  bmAttributes;	 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
    0x00,       /*  __u8  MaxPower; */
    /* interface */
    0x09,       /*  __u8  if_bLength; */
    0x04,       /*  __u8  if_bDescriptorType; Interface */
    0x00,       /*  __u8  if_bInterfaceNumber; */
    0x00,       /*  __u8  if_bAlternateSetting; */
    0x01,       /*  __u8  if_bNumEndpoints; */
    0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
    0x00,       /*  __u8  if_bInterfaceSubClass; */
    0x00,       /*  __u8  if_bInterfaceProtocol; */
    0x00,       /*  __u8  if_iInterface; */
    /* endpoint */
    0x07,       /*  __u8  ep_bLength; */
    0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
    0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
    0x03,       /*  __u8  ep_bmAttributes; Interrupt */
    0x02,       /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
    0x00,
    0xff        /*  __u8  ep_bInterval; 255 ms */
};


static unsigned char root_hub_str_index0[] =
{
    0x04,	/*  __u8  bLength; */
    0x03,	/*  __u8  bDescriptorType; String-descriptor */
    0x09,	/*  __u8  lang ID */
    0x04,	/*  __u8  lang ID */
};


static unsigned char root_hub_str_index1[] =
{
    28,			/*  __u8  bLength; */
    0x03,		/*  __u8  bDescriptorType; String-descriptor */
    'O',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    'H',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    'C',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    'I',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    ' ',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    'R',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    'o',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    'o',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    't',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    ' ',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    'H',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    'u',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
    'b',			/*  __u8  Unicode */
    0,			/*  __u8  Unicode */
};


/* Hub class-specific descriptor is constructed dynamically */
/*-------------------------------------------------------------------------*/
#define OK(x) 			len = (x); break
#ifdef DEBUG
#define WR_RH_STAT(x) 		\
{\
    info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);\
}


#define WR_RH_PORTSTAT(x) 	\
{\
    info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);\
}


#else
#define WR_RH_STAT(x) 		writel((x), &gohci.regs->roothub.status)
#define WR_RH_PORTSTAT(x) 	writel((x), &gohci.regs->roothub.portstatus[wIndex-1])
#endif
#define RD_RH_STAT		roothub_status(&gohci)
#define RD_RH_PORTSTAT		roothub_portstatus(&gohci,wIndex-1)
/* request to virtual root hub */
int rh_check_port_status(ohci_t *controller)
{
    U32 temp, ndp, i;
    int res;
    res = -1;
    temp = roothub_a (controller);
    ndp = (temp & RH_A_NDP);
    for (i = 0; i < ndp; i++) 
    {
        temp = roothub_portstatus (controller, i);
        /* check for a device disconnect */
        if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
        (RH_PS_PESC | RH_PS_CSC)) &&
        ((temp & RH_PS_CCS) == 0)) 
        {
            res = i;
            break;
        }
    }
    return res;
}


static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
void *buffer, int transfer_len, struct devrequest *cmd)
{
    void * data = buffer;
    int leni = transfer_len;
    int len = 0;
    int stat = 0;
    U32 datab[4];
    U8 *data_buf = (U8 *)datab;
    U16 bmRType_bReq;
    U16 wValue;
    U16 wIndex;
    U16 wLength;
    #ifdef DEBUG
    urb_priv.actual_length = 0;
    pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
    #else
    wait_ms(1);
    #endif
    if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) 
    {
        info("Root-Hub submit IRQ: NOT implemented");
        return 0;
    }
    bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
    wValue        = m16_swap (cmd->value);
    wIndex        = m16_swap (cmd->index);
    wLength       = m16_swap (cmd->length);
    info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",
    dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
    switch (bmRType_bReq) 
    {
        /* Request Destination:
        	   without flags: Device,
        	   RH_INTERFACE: interface,
        	   RH_ENDPOINT: endpoint,
        	   RH_CLASS means HUB here,
        	   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
        	*/
    case RH_GET_STATUS:
        *(U16 *) data_buf = m16_swap (1); OK (2);
    case RH_GET_STATUS | RH_INTERFACE:
        *(U16 *) data_buf = m16_swap (0); OK (2);
    case RH_GET_STATUS | RH_ENDPOINT:
        *(U16 *) data_buf = m16_swap (0); OK (2);
    case RH_GET_STATUS | RH_CLASS:
        *(U32 *) data_buf = m32_swap (
        RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
        OK (4);
    case RH_GET_STATUS | RH_OTHER | RH_CLASS:
        *(U32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4);
    case RH_CLEAR_FEATURE | RH_ENDPOINT:
        switch (wValue) 
        {
            case (RH_ENDPOINT_STALL): OK (0);
        }
        break;
    case RH_CLEAR_FEATURE | RH_CLASS:
        switch (wValue) 
        {
        case RH_C_HUB_LOCAL_POWER:
            OK(0);
        case (RH_C_HUB_OVER_CURRENT):
            WR_RH_STAT(RH_HS_OCIC); OK (0);
        }
        break;
    case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
        switch (wValue) 
        {
        case (RH_PORT_ENABLE):
            WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);
        case (RH_PORT_SUSPEND):
            WR_RH_PORTSTAT (RH_PS_POCI); OK (0);
        case (RH_PORT_POWER):
            WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);
        case (RH_C_PORT_CONNECTION):
            WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);
        case (RH_C_PORT_ENABLE):
            WR_RH_PORTSTAT (RH_PS_PESC); OK (0);
        case (RH_C_PORT_SUSPEND):
            WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);
        case (RH_C_PORT_OVER_CURRENT):
            WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);
        case (RH_C_PORT_RESET):
            WR_RH_PORTSTAT (RH_PS_PRSC); OK (0);
        }
        break;
    case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
        switch (wValue) 
        {
        case (RH_PORT_SUSPEND):
            WR_RH_PORTSTAT (RH_PS_PSS ); OK (0);
        case (RH_PORT_RESET): 
            /* BUG IN HUP CODE *********/
            if (RD_RH_PORTSTAT & RH_PS_CCS)
            WR_RH_PORTSTAT (RH_PS_PRS);
            OK (0);
        case (RH_PORT_POWER):
            WR_RH_PORTSTAT (RH_PS_PPS ); OK (0);
        case (RH_PORT_ENABLE): 
            /* BUG IN HUP CODE *********/
            if (RD_RH_PORTSTAT & RH_PS_CCS)
            WR_RH_PORTSTAT (RH_PS_PES );
            OK (0);
        }
        break;
        case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0);
    case RH_GET_DESCRIPTOR:
        switch ((wValue & 0xff00) >> 8) 
        {
        case (0x01): 
            /* device descriptor */
            /*
			len = min_t(unsigned int,
            leni,
            min_t(unsigned int,
            sizeof (root_hub_dev_des),
            wLength));*/
			len=min_t((unsigned int)leni,min_t(sizeof(root_hub_dev_des),(unsigned int)wLength));
            data_buf = root_hub_dev_des; OK(len);
        case (0x02): 
            /* configuration descriptor */
            /*len = min_t(unsigned int,
            leni,
            min_t(unsigned int,
            sizeof (root_hub_config_des),
            wLength));*/
			len=min_t((unsigned int)leni,min_t(sizeof(root_hub_config_des),(unsigned int)wLength));
            data_buf = root_hub_config_des; OK(len);
        case (0x03): 
            /* string descriptors */
            if(wValue==0x0300) 
            {                
				/*len = min_t(unsigned int,
                leni,
                min_t(unsigned int,
                sizeof (root_hub_str_index0),
                wLength));*/
				len=min_t((unsigned int)leni,min_t(sizeof(root_hub_str_index0),(unsigned int)wLength));
                data_buf = root_hub_str_index0;
                OK(len);
            }
            if(wValue==0x0301) 
            {
                /*len = min_t(unsigned int,
                leni,
                min_t(unsigned int,
                sizeof (root_hub_str_index1),
                wLength));*/
				len=min_t((unsigned int)leni,min_t(sizeof(root_hub_str_index1),(unsigned int)wLength));
                data_buf = root_hub_str_index1;
                OK(len);
            }
        default:
            stat = USB_ST_STALLED;
        }
        break;
    case RH_GET_DESCRIPTOR | RH_CLASS:
        {
            U32 temp = roothub_a (&gohci);
            data_buf [0] = 9;		/* min length; */
            data_buf [1] = 0x29;
            data_buf [2] = temp & RH_A_NDP;
            data_buf [3] = 0;
            if (temp & RH_A_PSM) 	/* per-port power switching? */
            data_buf [3] |= 0x1;
            if (temp & RH_A_NOCP)	/* no overcurrent reporting? */
            data_buf [3] |= 0x10;
            else if (temp & RH_A_OCPM)	/* per-port overcurrent reporting? */
            data_buf [3] |= 0x8;
            /* corresponds to data_buf[4-7] */
            datab [1] = 0;
            data_buf [5] = (temp & RH_A_POTPGT) >> 24;
            temp = roothub_b (&gohci);
            data_buf [7] = temp & RH_B_DR;
            if (data_buf [2] < 7) 
            {
                data_buf [8] = 0xff;
            } 
            else 
            {
                data_buf [0] += 2;
                data_buf [8] = (temp & RH_B_DR) >> 8;
                data_buf [10] = data_buf [9] = 0xff;
            }
            /*len = min_t(unsigned int, leni,
            min_t(unsigned int, data_buf [0], wLength));*/
			len=min_t((unsigned int)leni,min_t((unsigned int)data_buf[0],(unsigned int)wLength));
            OK (len);
        }
        case RH_GET_CONFIGURATION: 	*(U8 *) data_buf = 0x01; OK (1);
        case RH_SET_CONFIGURATION: 	WR_RH_STAT (0x10000); OK (0);
    default:
        s_UartPrint("unsupported root hub command\n");
        stat = USB_ST_STALLED;
    }
    #ifdef	DEBUG
    ohci_dump_roothub (&gohci, 1);
    #else
    wait_ms(1);
    #endif
    //len = min_t(int, len, leni);
    len=min_t_int(len,leni);
	if (data != data_buf)
    memcpy (data, data_buf, len);
    dev->act_len = len;
    dev->status = stat;
    #ifdef DEBUG
    if (transfer_len)
    urb_priv.actual_length = transfer_len;
    pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
    #else
    wait_ms(1);
    #endif
    return stat;
}


/*-------------------------------------------------------------------------*/
/* common code for handling submit messages - used for all but root hub */
/* accesses. */
int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len, struct devrequest *setup, int interval)
{
    int stat = 0;
    int maxsize = usb_maxpacket(dev, pipe);
    int timeout;
    /* device pulled? Shortcut the action. */
    //s_UartPrint("common_msg_step1\n");
    if (devgone == dev) 
    {
        dev->status = USB_ST_CRC_ERR;
        return 0;
    }
    //s_UartPrint("common_msg_step2\n");
    #ifdef DEBUG
    urb_priv.actual_length = 0;
    pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
    #else
    wait_ms(1);
    #endif
    if (!maxsize) 
    {
        err("submit_common_message: pipesize for pipe %lx is zero",
        pipe);
        return -1;
    }
    //s_UartPrint("common_msg_step3\n");
    if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) 
    {
        err("sohci_submit_job failed");
        return -1;
    }
    wait_ms(10);
    /* ohci_dump_status(&gohci); */
    /* allow more time for a BULK device to react - some are slow */
    #define BULK_TO	 5000	/* timeout in milliseconds */
    if (usb_pipetype (pipe) == PIPE_BULK)
    timeout = BULK_TO;
    else
    timeout = 100;//100
    //s_UartPrint("common_msg_step5 timeout=%d\n",timeout);
    /* wait for it to complete */
    for (;;) 
    {
        /* check whether the controller is done */
        stat = hc_interrupt();		
        //stat=hc_stat;
        if (stat < 0) 
        {
            stat = USB_ST_CRC_ERR;
			//=============du add 070302
			#ifdef du_debug
			s_UartPrint("@@@@@@@@@@@@@@@@@@@@");
			#endif
			//==========================
            break;
        }
        /* NOTE: since we are not interrupt driven in U-Boot and always
        		 * handle only one URB at a time, we cannot assume the
        		 * transaction finished on the first successful return from
        		 * hc_interrupt().. unless the flag for current URB is set,
        		 * meaning that all TD's to/from device got actually
        		 * transferred and processed. If the current URB is not
        		 * finished we need to re-iterate this loop so as
        		 * hc_interrupt() gets called again as there needs to be some
        		 * more TD's to process still */
        if ((stat >= 0) && (stat != 0xff) && (urb_finished)) 
        {
            /* 0xff is returned for an SF-interrupt */
            break;
        }
        if (--timeout) 
        {
            wait_ms(1);
            if (!urb_finished); 	dbg("/%");
        } 
        else 
        {
            err("CTL:TIMEOUT \nsubmit_common_msg: TO status %x", stat);
            stat = USB_ST_CRC_ERR;
            urb_finished = 1;
            break;
        }
    }
    //dbg("common_msg_step6\n");
    dev->status = stat;
    dev->act_len = transfer_len;
    #ifdef DEBUG
    pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
    #else
    wait_ms(1);
    #endif
    /* free TDs in urb_priv */
    urb_free_priv (&urb_priv);
    return 0;
}


/* submit routines called from usb.c */
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len)
{
    info("submit_bulk_msg\n");
    return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);
}


int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len, struct devrequest *setup)
{
    int maxsize = usb_maxpacket(dev, pipe);
    info("submit_control_msg");
    #ifdef DEBUG
    urb_priv.actual_length = 0;
    pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));

⌨️ 快捷键说明

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