📄 usb_phci.c
字号:
} /* phci_init_map_buffers */
/* This function is called when ep is linked to the oprational ep list.
It searches for the free td_ptd_index.
If the ping pong ptd is not set, sets the next free td_ptd_index to
pong ptd index */
/*--------------------------------------------------------------*
* HC get td ptd index from TD-PTD map buffer *
*--------------------------------------------------------------*/
void phci_get_td_ptd_index(ed_t *ed) {
__u8 buff_type = td_ptd_pipe_x_buff_type[ed->type];
__u8 td_ptd_index, index;
__u8 max_ptds;
td_ptd_map_buff_t *ptd_map_buff = &(td_ptd_map_buff[buff_type]);
func_debug(("phci_get_td_ptd_index(ed = 0x%p)\n",ed))
/* ATL PTDs can wait */
max_ptds = (buff_type == TD_PTD_BUFF_TYPE_ATL) ? TD_PTD_MAX_BUFF_TDS : ptd_map_buff->max_ptds;
for(td_ptd_index = 0; td_ptd_index < max_ptds; td_ptd_index++) { /* Find the first free slot */
if(ptd_map_buff->map_list[td_ptd_index].state == TD_PTD_NEW) {
/* Found a free slot */
if( ed->td_ptd_index == TD_PTD_INV_PTD_INDEX ) {
ed->td_ptd_index = td_ptd_index;
}
#ifdef CONFIG_USB_PHCD_PING_PONG
else {
/* Might be a bulk pong ptd index (bulk, not already
* ping is running and not a pending one) */
if( (ed->type != PIPE_BULK) ||
(td_ptd_index >= ptd_map_buff->max_ptds) ||
(ptd_map_buff->ping_ptd_index != TD_PTD_INV_PTD_INDEX) ) {
break;
}
ptd_map_buff->ping_ptd_index = ed->td_ptd_index;
ptd_map_buff->pong_ptd_index = td_ptd_index;
}
#endif /* CONFIG_USB_PHCD_PING_PONG */
ptd_map_buff->map_list[td_ptd_index].state = TD_PTD_OPER; /* put ptd_index to operational state */
ptd_map_buff->map_list[td_ptd_index].td = NULL; /* No td transfer is in progress */
ptd_map_buff->map_list[td_ptd_index].ed = ed; /* initialize the ed pointer */
ptd_map_buff->map_list[td_ptd_index].ping_pong = 0; /* initialize the ping pong flag */
ptd_map_buff->total_ptds ++; /* update # of total td's */
if( ed->type == PIPE_ISOCHRONOUS) { /* reserve additional indexes for ISTL buffer */
for(index=0; index < ptd_map_buff->regs.toggle_rate;index++) { /* for serving till the toggle rate */
ptd_map_buff->map_list[td_ptd_index+index].state = TD_PTD_OPER;
ptd_map_buff->map_list[td_ptd_index+index].ed = ed; /* initialize the ed pointer */
}
ptd_map_buff = &(td_ptd_map_buff[TD_PTD_BUFF_TYPE_ISTL1]);
for(index=0; index < ptd_map_buff->regs.toggle_rate;index++) { /* for serving till the toggle rate */
ptd_map_buff->map_list[td_ptd_index+index].state = TD_PTD_OPER;
ptd_map_buff->map_list[td_ptd_index+index].ed = ed; /* initialize the ed pointer */
}
}
break;
}
}
return;
} /* phci_get_td_ptd_index */
/*--------------------------------------------------------------*
* HC release td ptd index from TD-PTD map buffer *
*--------------------------------------------------------------*/
void phci_release_td_ptd_index(ed_t *ed) {
__u8 td_ptd_index = ed->td_ptd_index;
__u8 buff_type = td_ptd_pipe_x_buff_type[ed->type];
td_ptd_map_buff_t *ptd_map_buff;
td_ptd_map_buff_t *ptd_map_buff1;
td_ptd_map_t *ptd_map;
__u8 index;
__u32 ptd_bitmap = 0, skip_map;
func_debug(("phci_release_td_ptd_index(ed = 0x%p)\n",ed))
if( td_ptd_index != TD_PTD_INV_PTD_INDEX) {
ptd_map_buff = &(td_ptd_map_buff[buff_type]);
#ifdef CONFIG_USB_PHCD_PING_PONG
/* Check if this is ping pong ptd ed or not, if yes clear the pong ptd index also */
if( ed->type == PIPE_BULK && ptd_map_buff->ping_ptd_index == td_ptd_index){
ptd_map = &(ptd_map_buff->map_list[ptd_map_buff->pong_ptd_index]);
ptd_map_buff->total_ptds --;
if(ptd_map->td) ptd_map_buff->active_ptds--;
ptd_map_buff->active_ptd_bitmap &= (~(ptd_map->ptd_bitmap));
ptd_map->state = TD_PTD_NEW;
ptd_map->td = NULL;
ptd_map->ed = NULL;
ptd_bitmap |= ptd_map->ptd_bitmap;
ptd_map_buff->ping_ptd_index = TD_PTD_INV_PTD_INDEX;
ptd_map_buff->pong_ptd_index = TD_PTD_INV_PTD_INDEX;
ptd_map_buff->ping_pong.fill_status = 0;
ptd_map_buff->ping_pong.fill_seq = PP_SEQ_PING_PONG;
ptd_map_buff->ping_pong.fill_count = 0;
}
#endif /* CONFIG_USB_PHCD_PING_PONG */
ptd_map = &(ptd_map_buff->map_list[td_ptd_index]);
ptd_map_buff->total_ptds --;
if(ed->type == PIPE_ISOCHRONOUS) {
/* For isochronous pipe, clear all the td_ptd_index of toggle rate */
for(index = 0; index < ptd_map_buff->regs.toggle_rate; index++) {
ptd_map = &(ptd_map_buff->map_list[td_ptd_index+index]);
ptd_map_buff->active_ptd_bitmap &= (~(ptd_map->ptd_bitmap));
ptd_map->state = TD_PTD_NEW;
ptd_map->td = NULL;
ptd_map->ed = NULL;
}
ptd_map_buff1 = &(td_ptd_map_buff[TD_PTD_BUFF_TYPE_ISTL1]);
for(index = 0; index < ptd_map_buff->regs.toggle_rate; index++) {
ptd_map = &(ptd_map_buff1->map_list[td_ptd_index+index]);
ptd_map_buff1->active_ptd_bitmap &= (~(ptd_map->ptd_bitmap));
ptd_map->state = TD_PTD_NEW;
ptd_map->td = NULL;
ptd_map->ed = NULL;
}
} else {
if(ptd_map->td) ptd_map_buff->active_ptds--; /* this ed is deleted in between */
ptd_map_buff->active_ptd_bitmap &= (~(ptd_map->ptd_bitmap));
ptd_map->state = TD_PTD_NEW;
ptd_map->td = NULL;
ptd_map->ed = NULL;
ptd_bitmap |= ptd_map->ptd_bitmap;
}
ed->td_ptd_index = TD_PTD_INV_PTD_INDEX;
if(buff_type == TD_PTD_BUFF_TYPE_ATL) {
phci_reg_read32(REG_ATL_PTD_SKIP_MAP, &skip_map); /* Read the ATL skip map */
skip_map |= ptd_map->ptd_bitmap;
phci_reg_write32(REG_ATL_PTD_SKIP_MAP,skip_map); /* Skip all ptds */
}
}
return;
} /* end of phci_release_td_ptd_index */
/* Applicable only for ATL buffer */
void phci_move_pending_td_ptds(td_ptd_map_buff_t *ptd_map_buff) {
ed_t *ed;
td_t *td;
td_ptd_map_t *ptd_map;
__u8 td_ptd_index;
if(ptd_map_buff->pending_ptd_bitmap) {
/* There are some pending ptd maps that need to be moved to Active ptd map */
for(td_ptd_index = 0; td_ptd_index < TD_PTD_MAX_BUFF_TDS; td_ptd_index++) {
ptd_map = &(ptd_map_buff->map_list[td_ptd_index]);
if(ptd_map->ptd_bitmap & ptd_map_buff->pending_ptd_bitmap) {
/* This PTD is pending */
if(td_ptd_index < ptd_map_buff->max_ptds) {
/* Just update the Active map */
ptd_map_buff->active_ptd_bitmap |= ptd_map->ptd_bitmap;
ptd_map_buff->pending_ptd_bitmap &= (~ptd_map->ptd_bitmap);
} else {
/* Check if there is room to accomodate this */
if((ptd_map_buff->active_ptd_bitmap & ptd_map_buff->active_ptd_bitmask) !=
ptd_map_buff->active_ptd_bitmask){
ed = ptd_map->ed; /* Store ED and TD */
td = ptd_map->td;
phci_release_td_ptd_index(ed);
phci_get_td_ptd_index(ed);
ptd_map_buff->active_ptd_bitmap |= ptd_map_buff->map_list[ed->td_ptd_index].ptd_bitmap;
ptd_map_buff->pending_ptd_bitmap &= (~ptd_map->ptd_bitmap);
}
/* Otherwise wait for some one to come to get free */
}
}
}
}
}
/*--------------------------------------------------------------*
*--------------------------------------------------------------*
phci_fill_send_ptd::
send_ptd_bitmap: 32bit map for the ptds to be sent
ptd_map_buff: map buffer pointer of buffer to be written
Skip all the PTDs that are going to be filled by this function.
fill the ptd buffer and send it to HC
Fill into the HC buffer all the ptd's indicated by the bitmap
into their corresponding locations in the buffer.
Check and update the Last Ptd, thereshold level.
remove the skip map so that PTD's processing starts
*--------------------------------------------------------------*
*--------------------------------------------------------------*/
void phci_fill_send_ptd(phci_t *phci,__u32 send_ptd_bitmap,td_ptd_map_buff_t *ptd_map_buff) {
td_ptd_map_t *td_ptd_map;
__u8 *ptd_payload = NULL;
__u8 ram_data[HC_PTD_HEADER_SIZE];
__u8 byte_data = 0;
__u16 payload_bytes = 0; /* ptd payload bytes */
__u16 total_bytes = HC_PTD_HEADER_SIZE; /* ptd total bytes to be written to HC buffer */
__u32 active_ptd_bitmap = 0x0;
td_t *td;
ed_t *ed;
__u8 index = 0;
__u32 finished_map = send_ptd_bitmap;
__u32 ram_addr;
__u32 data_read;
func_debug(("phci_fill_send_ptd(phci = 0x%p, send_ptd_map = 0x%x, ptd_map_buff = 0x%p)\n",phci,send_ptd_bitmap, ptd_map_buff))
if(!send_ptd_bitmap) {
if(ptd_map_buff->buffer_type == TD_PTD_BUFF_TYPE_ATL) {
if(!ptd_map_buff->total_ptds){
phci_reg_write32(REG_ATL_PTD_SKIP_MAP,0xFFFFFFFF); /* Skip all ptds */
phci_reg_read16(REG_BUFF_STS,&data_read); /* Read the buffer status register */
data_read &= (~ATL_ACTIVE); /* Deactivate ATL */
g_buff_sts &= (~ATL_ACTIVE);
phci->hcd_operational_flags &= (~ATL_ACTIVE);
phci_reg_write16(REG_BUFF_STS,data_read); /* Deactivate ATL buffers */
}
}
if(ptd_map_buff->buffer_type == TD_PTD_BUFF_TYPE_INTL) {
if(!ptd_map_buff->active_ptds){
phci_reg_write32(REG_INTL_PTD_SKIP_MAP,0xFFFFFFFF);/* Skip all ptds */
phci_reg_read16(REG_BUFF_STS,&data_read); /* Read the buffer status register */
data_read &= (~INTL_ACTIVE); /* Deactivate ATL */
phci->hcd_operational_flags &= (~INTL_ACTIVE);
phci_reg_write16(REG_BUFF_STS,data_read); /* Deactivate ATL/INTL buffers */
}
}
return; /* If there is nothing to do, just return it */
}
/* Take care of pending ATL ptds */
if(ptd_map_buff->buffer_type == TD_PTD_BUFF_TYPE_ATL) {
ptd_map_buff->pending_ptd_bitmap |= (send_ptd_bitmap & (~ptd_map_buff->active_ptd_bitmask));
send_ptd_bitmap &= ptd_map_buff->active_ptd_bitmask;
if(!send_ptd_bitmap) return;
}
switch(ptd_map_buff->buffer_type) {
case TD_PTD_BUFF_TYPE_INTL:
/* Skip the PTD's in ATL & INTL so that we can write the PTD's into the buffer */
phci_reg_read32(REG_INTL_PTD_SKIP_MAP, &(ptd_map_buff->regs.ptd_skip_map)); /* Read the ATL skip map */
ptd_map_buff->regs.ptd_skip_map |= send_ptd_bitmap; /* Add the new ptds to be skipped */
phci_reg_write32(REG_INTL_PTD_SKIP_MAP,ptd_map_buff->regs.ptd_skip_map); /* The HC don;t touch the ptds */
break;
case TD_PTD_BUFF_TYPE_ATL:
/* Skip the PTD's in ATL & INTL so that we can write the PTD's into the buffer */
phci_reg_read32(REG_ATL_PTD_SKIP_MAP, &(ptd_map_buff->regs.ptd_skip_map)); /* Read the ATL skip map */
ptd_map_buff->regs.ptd_skip_map |= send_ptd_bitmap; /* Add the new ptds to be skipped */
phci_reg_write32(REG_ATL_PTD_SKIP_MAP,ptd_map_buff->regs.ptd_skip_map); /* The HC don;t touch the ptds */
break;
}
for( index = 0; (index < ptd_map_buff->max_ptds) || (finished_map != 0); index++) {
td_ptd_map = &(ptd_map_buff->map_list[index]);
if(td_ptd_map->ptd_bitmap & finished_map) { /* This ptd needs to be filled */
/* Start filling the ram_data to send it to HC */
td = td_ptd_map->td;
ed = td->ed;
/* start filling the ptd header */
total_bytes = HC_PTD_HEADER_SIZE; /* ptd total bytes to be written to HC buffer, initialize to ptd header */
/**********************************************************************/
/* ptd_header[0]: 7..0 actual bytes(7...0) 0(always) */
/**********************************************************************/
ram_data[0] = 0;
/************************************************************************/
/* ptd_header[1]: 7..4 completion code(3...0) 1111 (always) */
/* ptd_header[1]: 3 active(0) 1 (always) */
/* ptd_header[1]: 2 toggle(0) from ed&td */
/* ptd_header[1]: 1..0 actual bytes(9..8) 0 (always) */
/************************************************************************/
ram_data[1] = (PTD_CC_MASK | PTD_ACTIVE);
if( td->hwINFO & HC_GTD_MLSB) { /* fill toggle bit from td hw info */
ram_data[1] |= (((__u8)((td->hwINFO & HC_GTD_TLSB) >> 24)) << 2);
} else { /* fill toggle bit from ed hw info */
ram_data[1] |= (((__u8)((ed->swHeadP & HC_ED_TOGGLE) >> 1)) << 2);
}
/**********************************************************************/
/* ptd_header[2]: 7..0 Max.PacketSize(7...0) from ed MPS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -