📄 cy7c67200_300_pcd.c
字号:
lcd_read_reg (HOST1_IRQ_EN_REG, &intStat, cy_priv); intStat &= ~VBUS_IRQ_EN; lcd_write_reg(HOST1_IRQ_EN_REG, intStat, cy_priv); /* Acknowledge interrupt */ lcd_write_reg(HOST1_STAT_REG, VBUS_IRQ_FLG, cy_priv); if( cy_priv->lcd_priv == NULL || cy_priv->otg == NULL ) { return; } vbus_timer.function = vbus_timeout; vbus_timer.data = (unsigned long)cy_priv; mod_timer( &vbus_timer, jiffies + 3 ); // 50 ms}/*****************************************************************/void pcd_irq_id(cy_priv_t *cy_priv){ unsigned short otg_stat_reg; otg_t *otg = cy_priv->otg; int prev_otg_id; pcd_dbg("pcd_irq_id enter"); /* Acknowledge interrupt */ // Need to do this first since there is no conditioning on the // interrupt. lcd_write_reg(HOST1_STAT_REG, ID_IRQ_FLG, cy_priv); // not initialized if( cy_priv->lcd_priv == NULL || otg == NULL ) { return; } /* OTG ID has changed - we think */ /* Read the OTG ID Status bit USB Status Register for OTG ID pin */ lcd_read_reg(OTG_CTL_REG, &otg_stat_reg, cy_priv); prev_otg_id = otg->id; if (otg_stat_reg & OTG_ID_STAT) { otg->id = B_DEV; } else { otg->id = A_DEV; } if( prev_otg_id != otg->id ) { update_otg_state(otg); }}/*****************************************************************/void pcd_irq_mb_in(cy_priv_t *cy_priv){ // not used}/*****************************************************************/void pcd_irq_mb_out(unsigned int message, int sie, cy_priv_t * cy_priv){ unsigned i; /* loop index */ unsigned short ep_number; struct usb_endpoint_instance * endpoint; sie_info *sie_var = (sie_info *)cy_priv->pcdi; otg_t * otg = cy_priv->otg; // not initialized yet, or wrong sie, ignore interrupt if( sie_var == NULL || sie_var->sie_number != sie || sie_var->bus == NULL ) { return; } for( i=1,ep_number=0; i!=0; ep_number++, i<<=1 ) { //pcd_dbg("i:0x%04x, ep_num:%d", i, ep_number); switch( message & i ) { case SUSB_EP0_MSG: /* ignore ep0 */ default: break; case SUSB_EP1_MSG: /* endpoint done */ case SUSB_EP2_MSG: case SUSB_EP3_MSG: case SUSB_EP4_MSG: case SUSB_EP5_MSG: case SUSB_EP6_MSG: case SUSB_EP7_MSG: //pcd_dbg("EP_DONE_MSG_ID RECEIVED. Endpoint: %d", ep_number); endpoint = &sie_var->bus->endpoint_array[ep_number]; if (endpoint->endpoint_address & USB_DIR_IN) { usbd_tx_complete_irq(endpoint, 0); if( endpoint->tx_urb ) { udc_start_in_irq(endpoint, endpoint->tx_urb->device); } } else { ep_receive_data(endpoint, sie, cy_priv); } break; case SUSB_RST_MSG: /* reset */ pcd_dbg("SUSB_RST_MSG"); usbd_device_event(sie_var->bus->device, DEVICE_RESET, 0); if( otg != NULL ) { otg->b_hnp_en = FALSE; otg->a_bus_suspend = FALSE; otg->b_bus_suspend = FALSE; update_otg_state(otg); } break; case SUSB_SOF_MSG: /* active */ pcd_dbg("SUSB_SOF_MSG"); usbd_device_event(sie_var->bus->device, DEVICE_BUS_ACTIVITY, 0); if( otg != NULL ) { otg->a_bus_suspend = FALSE; otg->b_bus_suspend = FALSE; update_otg_state(otg); } break; case SUSB_CFG_MSG: /* configured */ pcd_dbg("SUSB_CFG_MSG"); usbd_device_event(sie_var->bus->device, DEVICE_BUS_ACTIVITY, 0); usbd_device_event(sie_var->bus->device, DEVICE_CONFIGURED, 0); if( otg != NULL ) { otg->a_bus_suspend = FALSE; otg->b_bus_suspend = FALSE; update_otg_state(otg); } break; case SUSB_SUS_MSG: /* suspend */ pcd_dbg("SUSB_SUS_MSG"); usbd_device_event(sie_var->bus->device, DEVICE_BUS_INACTIVE, 0); if( otg != NULL ) { otg->a_bus_suspend = TRUE; otg->b_bus_suspend = TRUE; otg->b_bus_req = TRUE; update_otg_state(otg); } break; case 0x4000: /* b_hnp_enable */ if( otg != NULL ) { pcd_dbg("b_hnp_enable"); otg->b_hnp_en = TRUE; update_otg_state(otg); } break; } }}/***************************************************************** * * Function Name: ep_receive_data * * Description: This function sets up an endpoint to receive data * on the EZ-HOST. * *****************************************************************/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 == SIE1) ? 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; }}/***************************************************************** * * Function Name: udc_rcv_urb_recycled * * 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); } }}/***************************************************************** * * Function Name: udc_start_in_irq * * 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 EZ-HOST * chip, so we check that it meets this requirement, and then move on. We * write the data to the buffer in EZ-HOST, and then trigger the SUSBx_SEND_INT * SW interrupt. EZ-HOST 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 EZ-HOST 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 EZ-HOST. 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. * *****************************************************************/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 == SIE1) port_num = PORT0; else port_num = PORT2; ep_addr = endpoint->endpoint_address & 0x000f; 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; // 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; frame.link_pointer = 0x0000; frame.absolute_address = sie_data->send_buffer_location; frame.data_length = endpoint->last; frame.callback_function_location = 0; lcd_send_data(sie_data->send_struct_location, port_num, ep_addr, 8, (char *)&frame, NULL, 0, sie_data->cy_priv); } } else { pcd_dbg("No urb for transmit"); }}/***************************************************************** * * Function Name: udc_stall_ep * * * Description: This function will trigger the SUSBx_STALL_INT software * interrupt on EZ-HOST. This software interrupt is specific to the control * endpoint, so the only valid endpoint number is zero. Triggering this * interrupt will cause EZ-HOST to stall the next transaction on the default * endpoint. * *****************************************************************/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); }}/***************************************************************** * * Function Name: udc_reset_ep * * 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 EZ-HOST BIOS, this is performed * by calling the SUSB_INIT_INT software interrupt, to reset all endpoints * based on the configuration loaded to EZ-HOST. * *****************************************************************/void udc_reset_ep(unsigned int ep, struct usb_device_instance * device){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -