cy7c67200_300_pcd.c

来自「linux嵌入式课程实践中的一个关于声卡驱动程序 。」· C语言 代码 · 共 2,215 行 · 第 1/5 页

C
2,215
字号
                /* Re-enable Missing Start Of Frame interrupt */                lcd_read_reg (SIE1_INT_EN_REG, &value, cy_priv);                lcd_write_reg(SIE1_INT_EN_REG, value | 0x0800, cy_priv);            }#else            HWTrace(0x7005);            if( otg != NULL )            {                HWTrace(0x7003);                otg->a_bus_suspend = TRUE;                otg->b_bus_suspend = TRUE;                otg->b_bus_req = TRUE;                update_otg_state(otg);            }#endif            break;        case 0x4000: /* b_hnp_enable */            if( otg != NULL )            {                pcd_dbg("b_hnp_enable");                //cy_err("b_hnp_enable");                otg->b_hnp_en = TRUE;                update_otg_state(otg);            }            break;        }    }}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: Void. */void ep_receive_data(struct usb_endpoint_instance *endpoint,                       int sie_num, cy_priv_t * cy_priv){    unsigned short length;    TRANSFER_FRAME frame;    int port_num;    //pcd_dbg("ep_receive_data enter: sie_num = %d", sie_num);    if( sie->sie_number != sie_num )    {        cy_err("message received on wrong sie: exptected=%d, actual= %d",                 sie->sie_number, sie_num);        return;    }    port_num = (sie_num == SIE0) ? PORT0 : PORT2;    if(endpoint->rcv_urb == NULL)     {        endpoint->rcv_urb = first_urb_detached(&endpoint->rdy);    }    /* check to see that we have an URB to receive data */    if(endpoint->rcv_urb)     {        int ep = endpoint->endpoint_address & 0xf;        unsigned short struct_location =             sie->recv_struct_location + ep*TXRX_STRUCT_SIZE;        unsigned short buff_location =            sie->recv_buffer_location + ep*RECV_BUFF_LENGTH;        /* read the buffer remainder and compute the number of bytes sent */        lcd_read_memory( struct_location + 4,                         2,                         (char *)&length,                         cy_priv);                length = sie->recv_buffer_length - length;        lcd_read_memory(buff_location,                         length,                         endpoint->rcv_urb->buffer,                         cy_priv);        /* submit the urb to the function driver */        usbd_rcv_complete_irq(endpoint, length, 0);                /* set the endpoint up to receive again with a pending receive SW           interrupt */        frame.link_pointer = 0x0000;        frame.absolute_address = buff_location;        frame.data_length = sie->recv_buffer_length;         frame.callback_function_location =  0;                   lcd_recv_data(struct_location,                       port_num,                       ep,                      8,                       (char*)&frame,                       NULL,                       0,                       cy_priv);                    }                  else    {        sie->rcv_data_pend_ep[endpoint->endpoint_address & 0xf] = endpoint;    }}/* *  DESCRIPTION: Notification from the core layer that an urb has been  *  recycled by the function driver. */void udc_rcv_urb_recycled(void){    size_t i;    struct usb_endpoint_instance *endpoint;    for(i=0; i<UDC_MAX_ENDPOINTS; i++)    {        endpoint = sie->rcv_data_pend_ep[i];        if( endpoint != 0 )        {            sie->rcv_data_pend_ep[i] = 0;            ep_receive_data(endpoint, sie->sie_number, sie->cy_priv);        }    }}/* *  PARAMETERS:  usb_endpoint_instance *endpoint -> a pointer to the endpoint *  that will transmit the URB data. * *  DESCRIPTION:  Called by bi_send_urb, this function is registered with  *  the peripheral core layer to transmit URB's onto the bus.  Called with  *  interrupts disabled. * *  We are requiring the URB buffer to be <= the send_data_buffer on the Lyberty *  chip, so we check that it meets this requirement, and then move on.  We  *  write the data to the buffer in Lyberty, and then trigger the SUSBx_SEND_INT *  SW interrupt.  Lyberty then will take care of sending the data in packets  *  over the bus.  When it is completed, it calls our callback function to  *  notify us of success of failure.  It is possible to handle urb buffers  *  larger than the Lyberty RAM send buffer space, by setting a flag here and  *  then waiting for the callback to clear the flag, letting us know we can send *  more data down to Lyberty.  For now anyway, we will keep it simple. If the  *  data length of the URB is larger than the RAM buffer, we signal an error to  *  the function driver.  * *  RETURNS:  Void. */void udc_start_in_irq(struct usb_endpoint_instance * endpoint,                      struct usb_device_instance * device){    int sie;    int port_num;    int ep_addr;    struct usbd_urb * urb;    sie_info * sie_data;        //pcd_dbg("udc_start_in_irq enter");    /* determine the SIE this endpoint is associated with */    sie_data = (sie_info *)device->bus->privdata;    sie = sie_data->sie_number;        if (sie == SIE0)         port_num = PORT0;    else        port_num = PORT2;    ep_addr = endpoint->endpoint_address & 0x000f;        /*    if( endpoint->tx_urb == 0 )    {        usbd_tx_complete_irq(endpoint, 0);    }    */    urb = endpoint->tx_urb;    /* check that we have an active URB to transmit */    if (urb) {        if ((urb->actual_length - endpoint->sent) > 0)         {            endpoint->last = MIN(urb->actual_length - endpoint->sent,                                  sie_data->send_buffer_length);        }        else         {            endpoint->last = 0; // XXX zero length packet        }        /* write the data to the RAM buffer */        if (lcd_write_memory(sie_data->send_buffer_location,                              endpoint->last,                              urb->buffer + endpoint->sent,                              sie_data->cy_priv) == SUCCESS)         {            TRANSFER_FRAME frame;            extern int free_urb;            frame.link_pointer = 0x0000;            frame.absolute_address = sie_data->send_buffer_location;            frame.data_length = endpoint->last;            frame.callback_function_location = 0;            //frame.callback_function_location =            //  lcd_get_cb_address( port_num, ep_addr, sie_data->cy_priv );            /*            cy_warn("size:%d, off:%d, free:%d",                     endpoint->last, endpoint->sent, free_urb);                    */            lcd_send_data(sie_data->send_struct_location,                           port_num,                           ep_addr,                           8,                           &frame,                           NULL,                           0,                           sie_data->cy_priv);            //cy_warn("lcd_send_data");            HWTrace(0x7272);        }                    }    else    {        pcd_dbg("No urb for transmit");    }}/*******************************************************************************    PARAMETERS:     ep -> the endpoint number                    device -> pointer to the usb_device_instance structure      DESCRIPTION:    This function will trigger the SUSBx_STALL_INT software     interrupt on Lyberty.  This software interrupt is specific to the control    endpoint, so the only valid endpoint number is zero.  Triggering this     interrupt will cause Lyberty to stall the next transaction on the default    endpoint.      RETURNS:        Void. */void udc_stall_ep(unsigned int ep, struct usb_device_instance * device){    sie_info * sie_data = (sie_info *) device->bus->privdata;    lcd_int_data_t int_data;        pcd_dbg("udc_stall_ep enter: ep=%d", ep);    int_data.int_num = sie_data->susb_stall_interrupt;        /* ensure that the stall is for endpoint zero, otherwise do nothing */    if (ep == 0) {        lcd_exec_interrupt(&int_data, NULL, 0, sie_data->cy_priv);    }}/*******************************************************************************    PARAMETERS:     ep -> the endpoint number                    device -> pointer to the usb_device_instance structure      DESCRIPTION:    The BIOS does not provide a way to directly reset a specific    endpoint, so nothing will be done inside of this function.  The purpose of    the function is for bus interfaces that allow direct manipulation of each    endpoint, this gives the peripheral core a chance to reset each endpoint    during initialization.  However, with the Lyberty BIOS, this is performed    by calling the SUSB_INIT_INT software interrupt, to reset all endpoints     based on the configuration loaded to Lyberty.          RETURNS:        Void.*/void udc_reset_ep(unsigned int ep, struct usb_device_instance * device){    //pcd_dbg("udc_reset_ep enter");}/*******************************************************************************    PARAMETERS:     ep -> the endpoint number                    device -> pointer to the usb_device_instance structure      DESCRIPTION:              RETURNS:        Void.*/int udc_endpoint_halted(unsigned int ep,                         struct usb_device_instance * device){    //pcd_dbg("udc_endpoint_halted enter");    return(0);}/*******************************************************************************    PARAMETERS:     ep -> the endpoint number                    device -> pointer to the usb_device_instance structure      DESCRIPTION:    Called from control endpoint function after it decodes a set                     address setup packet.          RETURNS:        Void.*/void udc_set_address(unsigned char address,                      struct usb_device_instance * device){    sie_info * sie_data = (sie_info * ) device->bus->privdata;        //pcd_dbg("udc_set_address enter");    sie_data->usb_address = address;}/*******************************************************************************    PARAMETERS:     bus -> bus instance      DESCRIPTION:              RETURNS:        SUCCESS or ERROR*/int __init udc_serial_init(struct usb_bus_instance * bus){    /* At this time, the device instance does not exist */    /* The sie global should have been initialized by now in perhiperhal init */    //pcd_dbg("udc_serial_init enter");    bus->privdata = sie;    sie->bus = bus;    return SUCCESS;}/** * udc_max_endpoints - max physical endpoints  * * Return number of physical endpoints. */ /*******************************************************************************    PARAMETERS:     ep -> the endpoint number                    device -> pointer to the usb_device_instance structure      DESCRIPTION:              RETURNS:        Void.*/ int udc_max_endpoints(void){    //pcd_dbg("udc_max_endpoints enter");    return(UDC_MAX_ENDPOINTS);}/** * udc_check_ep - check logical endpoint  * * @lep:  the logical endpoint is the bEndpointAddress from the endpoint  *        descriptor the lower four bits are the endpoint address, bit 7 is  *        the endpoint direction, 1 for IN, 0 for OUT.           * * @packetsize: bits 0 through 10 indicate the max packet size for the  *              endpoint. * * Return physical endpoint number to use for this logical endpoint or zero  * if not valid.  TODO:  The packetsize for isochronous can be larger than 64, so we need to         check the endpoint type, and then check packet size.  Also possible         to pass in the endpoint type for this case. */ /*******************************************************************************    PARAMETERS:     logical_endpoint -> bEndpointAddress from the endpoint                     descriptor.                                        packetsize -> packetsize from the endpoint descriptor.                                        device -> pointer to usb_device_instance, used to obtain                    access to private data.      DESCRIPTION:    This function will verify whether a function driver has set                    up its endpoint descriptors properly.  It will retrieve the                    endpoint descriptors, and then check their endpoint numbers                    against what the bus interface is capable of handling, i.e.                    whether or not a function driver tries to implement nine                    endpoints, when only eight are supported on the hardware.          RETURNS:        Void.*/ int udc_check_ep(int logical_endpoint, int packetsize,                  struct usb_device_instance * device){    int pys_ep;    //pcd_dbg("udc_check_ep ep:%d, pktsz:%d", logical_endpoint, packetsize);    pys_ep = (((logical_endpoint & 0xf) >= UDC_MAX_ENDPOINTS)             || (packetsize > 64)) ?  0 : (logical_endpoint & 0xf);    //pcd_dbg("udc_check_ep pys_ep:%d", pys_ep);    return pys_ep;}/** * udc_set_ep - setup endpoint  * @ep: * @endpoint: * * Associate a physical endpoint with endpoint_instance */ /*******************************************************************************

⌨️ 快捷键说明

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