📄 ohci.c
字号:
return NULL;
}
pTD = (PS_UHP_TD)safe_malloc(sizeof(UHP_TD));
if(!pTD) {
OHCI_DBG("UH ERROR: Not enough memory\r\n");
return NULL;
}
memset(pTD, 0, sizeof(UHP_TD));
pUTD = (OHCI_PS_UHP_TD)aligned_malloc(sizeof(OHCI_S_UHP_TD), 16);
if(!pUTD) {
OHCI_DBG("UH ERROR: Not enough memory\r\n");
return NULL;
}
memset(pUTD, 0, sizeof(OHCI_S_UHP_TD));
pTD->Buf_Len = buf_len;
pTD->CBP = cbp;
pTD->Data_Toggle = td_type;
pTD->DelayInterrupt = del_int;
pTD->Direction = direction;
pTD->NextTD = 0;
pTD->Rounding = rounding;
pTD->TDAddress = (unsigned int) pUTD;
pTD->callback = cb;
pTD->arg = arg;
ll_CreateGenTd(
pTD->TDAddress,
pTD->Data_Toggle,
pTD->DelayInterrupt,
pTD->Direction,
pTD->Rounding,
pTD->CBP,
0,
pTD->Buf_Len);
cur_td_num++;
return pTD;
}
/*
*
*/
void ohci_add_td(PS_UHP_ED pED, PS_UHP_TD pTD) {
OHCI_PS_UHP_TD psTD;
OHCI_PS_UHP_ED phED;
phED = pED->phED;
if (!phED) return;
if (!pTD) {
OHCI_DBG("UH ERROR: Invalid TD\r\n");
return;
}
if (cur_td_num > MAX_TDS) {
OHCI_DBG("UH ERROR: MAX TD\r\n");
return;
}
if(!phED->HeadP) {
phED->HeadP = (((unsigned int) pTD->TDAddress) & 0xFFFFFFF0);
} else {
psTD = (OHCI_PS_UHP_TD)phED->HeadP;
for (;psTD->NextTD;psTD = (OHCI_PS_UHP_TD)psTD->NextTD);
psTD->NextTD = pTD->TDAddress;
}
phED->TailP = (((unsigned int) pTD->TDAddress) & 0xFFFFFFF0);
}
/*
*
*/
void ohci_free_td(PS_UHP_TD pTD) {
if (!pTD) {
OHCI_DBG("UH ERROR: TD is not valid\r\n");
return;
}
aligned_free((void *)(pTD->TDAddress));
safe_free(pTD);
cur_td_num --;
}
/*
*
*/
int ohci_make_td_chain(PS_UHP_ED pED,
unsigned int len,
unsigned int slice,
unsigned int ed_dir,
void *pBuf) {
void *p = pBuf;
PS_UHP_TD pTD[(len/4096) + 2];
OHCI_PS_UHP_ED phED;
int i = 0;
unsigned int trigger = pED->Trigger;
if (!pED) return -1;
phED = pED->phED;
if (!phED) return -1;
while (len > 4096) {
pTD[i] = ohci_create_td(trigger, 0, ed_dir, 1, (unsigned int)p, 4096, 0, 0, 0);
if (!pTD[i]) return -1;
ohci_add_td(pED, pTD[i]);
len -= 4096;
p += 4096;
i++;
#ifdef OHCI_STAT
if (ed_dir == ED_IN)
ohci_in_packet_count += 4096;
else
ohci_out_packet_count += 4096;
#endif
}
pTD[i] = ohci_create_td(trigger, 0, ed_dir, 1, (unsigned int)p, len, 0, 0, 0);
if (!pTD[i]) return -1;
ohci_add_td(pED, pTD[i]);
i++;
/*
for (i = 0;i < (len/slice);i++) {
pTD[i] = ohci_create_td(trigger, 0, ed_dir, 1, (unsigned int)p, slice, 0, 0, 0);
if (!pTD[i]) {
//unlock_ohci();
return -1;
}
ohci_add_td(pED, pTD[i]);
//trigger = (((trigger ^ 1) & 0x1) | 0x2);
p += slice;
}
*/
pTD[i] = ohci_create_td(trigger, 0, ed_dir, 1, (unsigned int)0, 0, 0, 0, 0);
if (!pTD[i]) return -1;
ohci_add_td(pED, pTD[i]);
if (start_trans(pED)) {
/* for (i = 0;i < ((len/slice)+1);i++) {
ohci_free_td(pTD[i]);
}*/
for (;i >= 0;i--) {
ohci_free_td(pTD[i]);
}
OHCI_DBG("OHCI: Trans ERROR\r\n");
return -1;
}
#ifdef OHCI_STAT
if (ed_dir == ED_IN)
ohci_in_packet_count += len;
else
ohci_out_packet_count += len;
#endif
phED->TailP = 0x00000000;
phED->HeadP = 0x00000000;
/* for (i = 0;i < ((len/slice)+1);i++) {
ohci_free_td(pTD[i]);
}*/
for (;i >= 0;i--) {
ohci_free_td(pTD[i]);
}
return 0;
}
/*
*
*/
PS_UHP_ED ohci_create_ed(unsigned int max_packet,
unsigned int td_format,
unsigned int skip,
unsigned int speed,
unsigned int direction,
unsigned int ed_num,
unsigned int func,
unsigned int td_head,
unsigned int td_tail,
unsigned int toggle,
unsigned int next_ed,
unsigned int type,
unsigned int amount) {
PS_UHP_ED pED = NULL;
OHCI_PS_UHP_ED pUED ;
if (cur_ed_num > MAX_EDS) {
OHCI_DBG("UH ERROR: MAX ED\r\n");
return NULL;
}
pED = (PS_UHP_ED)safe_malloc(sizeof(UHP_ED));
if(!pED) {
OHCI_DBG("UH ERROR: Not enough memory\r\n");
return NULL;
}
memset(pED, 0, sizeof(PS_UHP_ED));
pUED = (OHCI_PS_UHP_ED)aligned_malloc(sizeof(OHCI_S_UHP_ED), 16);
if(!pUED) {
OHCI_DBG("UH ERROR: Not enough memory\r\n");
safe_free(pED);
return NULL;
}
memset(pUED, 0, sizeof(OHCI_PS_UHP_ED));
psUHPED[cur_ed_num] = pED;
pED->Max_packet = max_packet;
pED->TD_format = td_format;
pED->Skip = skip;
pED->Speed = speed;
pED->Direction = direction;
pED->Endpoint = ed_num;
pED->Func_Address = func;
pED->TDQHeadPtr = td_head;
pED->TDQTailPtr = td_tail;
pED->ToggleCarry = toggle;
pED->NextED = NULL;
pED->EDAddress = (unsigned int)pUED;
pED->phED = pUED;
pED->Type = type;
pED->Trigger = 0;
pED->Data_amount = amount;
ll_CreateEd(
pED->EDAddress, // ED Address
pED->Max_packet, // Max packet
pED->TD_format, // TD format
pED->Skip, // Skip
pED->Speed, // Speed
pED->Direction, // Direction
pED->Endpoint, // Endpoint
pED->Func_Address, // Func Address
pED->TDQHeadPtr,//(unsigned int) &pUHPTd[3], // TDQTailPointer
pED->TDQTailPtr,//(unsigned int) &pUHPTd[0], // TDQHeadPointer
pED->ToggleCarry, // ToggleCarry
0); // NextED
cur_ed_num++;
return pED;
}
/*
*
*/
void ohci_add_ed(PS_UHP_ED pED) {
OHCI_PS_UHP_ED ppED = NULL;
PS_UHP_ED pfED = NULL;
unsigned int i;
if (pED->Type == OHCI_CONTROL_ED) {
ppED = (OHCI_PS_UHP_ED) ohci->HcControlHeadED;
} else if (pED->Type == OHCI_BULK_ED) {
ppED = (OHCI_PS_UHP_ED) ohci->HcBulkHeadED;
} else if (pED->Type == OHCI_INT_ED) {
for (i = 0;i < MAX_EDS;i++) {
if ((psUHPED[i]->Type == OHCI_INT_ED) && (psUHPED[i] != pED)) {
pfED = psUHPED[i];
break;
}
}
}
// Find first phisical ED in virtual ED list
if (pED->Type != OHCI_INT_ED) {
for (i = 0;i < MAX_EDS;i++) {
if (psUHPED[i]->phED == ppED) {
pfED = psUHPED[i];
break;
}
}
}
// Return if we did not find appropriate virtual ED
if (!pfED) return;
// Roll the list to find the last ED in the queue
for (;pfED->NextED;pfED = pfED->NextED);
pfED->NextED = pED;
pfED->phED->NextEd = (((unsigned int)pED->phED) & 0xFFFFFFF0);
pED->phED->NextEd = 0;
}
/*
*
*/
static int ohci_remove_ed(PS_UHP_ED pED) {
OHCI_PS_UHP_ED pfED = NULL;
unsigned int i;
if (!pED) return -1;
if (pED->Type == ED_TYPE_CONTROL) {
pfED = (OHCI_PS_UHP_ED)ohci->HcControlHeadED;
} else if (pED->Type == ED_TYPE_BULK) {
pfED = (OHCI_PS_UHP_ED)ohci->HcBulkHeadED;
} else if (pED->Type == ED_TYPE_INT) {
for (i = 0;i < MAX_EDS;i++) {
if (psUHPED[i] == pED) {
pfED = psUHPED[i]->phED;
}
}
}
// Remove logical ED
for (i = 0;i < MAX_EDS;i++) {
if (psUHPED[i]->NextED == pED) {
psUHPED[i]->NextED = pED->NextED;
break;
}
}
// Remove phisical ED
for (;pfED->NextEd;pfED = (OHCI_PS_UHP_ED)pfED->NextEd) {
if (pfED->NextEd == pED->EDAddress) {
pfED->NextEd = pED->phED->NextEd;
return 0;
}
}
return 0;
}
/*
*
*/
void ohci_free_ed(PS_UHP_ED pED) {
unsigned int i;
int j = -1;
if (!pED) {
OHCI_DBG("UH ERROR: TD is not valid\r\n");
return;
}
// free hw pointer
aligned_free(pED->phED);
// find ed in pointer list
for (i = 0;i < MAX_EDS;i++) {
if (pED == psUHPED[i]) {
//psUHPED[i] = 0;
j = i;
break;
}
}
if (j < 0) return;
// free ed
safe_free(pED);
// clear ed in pointer list
if (j >= 0)
psUHPED[j] = 0;
// decrement ed number
cur_ed_num--;
}
/*
*
*/
static void ohci_skip_ed(PS_UHP_ED pED) {
OHCI_PS_UHP_ED phED = pED->phED;
if (!phED) return;
phED->Control |= (1 << 14);
}
/*
*
*/
int ohci_new_control_trans(PS_UHP_ED pED, int request_type, void *pIn, void *pSetup, unsigned int len) {
PS_UHP_TD pTDin, pTDout, pTDempty;
OHCI_PS_UHP_ED phED = pED->phED;
//lock_ohci();
if (!phED) {
//unlock_ohci();
return -1;
}
// create OUT transaction
pTDout = ohci_create_td(2, 0, 0, 1, (unsigned int)pSetup, 8, 0, 0, 0);
if (!pTDout) {
//unlock_ohci();
return -1;
}
ohci_add_td(pED, pTDout);
// create IN transaction
pTDin = ohci_create_td(3, 0, ED_IN, 1, (unsigned int)pIn, len, 0, 0, 0);
if (!pTDin) {
//unlock_ohci();
return -1;
}
ohci_add_td(pED, pTDin);
//create EMTY transaction
pTDempty = ohci_create_td(2, 0, 0, 1, 0, 0, 0, 0, 0);
if (!pTDempty) {
//unlock_ohci();
return -1;
}
ohci_add_td(pED, pTDempty);
//unlock_ohci();
if (start_trans(pED)) {
ohci_free_td(pTDout);
ohci_free_td(pTDin);
ohci_free_td(pTDempty);
////unlock_ohci();
return -1;
}
phED->TailP = 0x00000000;
phED->HeadP = 0x00000000;
ohci_free_td(pTDout);
ohci_free_td(pTDin);
ohci_free_td(pTDempty);
////unlock_ohci();
return 0;
}
/*
*
*/
int ohci_device_config_request(PS_UHP_ED pED, void *out) {
unsigned char setup[] = {0x80,0x06,0x00,0x01,0x00,0x00,0x40,0x00};
return ohci_new_control_trans(pED, 0, out, setup, 18);
}
/*
*
*/
int ohci_config_request(PS_UHP_ED pED, void *out) {
unsigned char setup[] = {0x80,0x06,0x00,0x02,0x00,0x00,0x40,0x00};
return ohci_new_control_trans(pED, 0, out, setup, 64);
}
/*
*
*/
int ohci_interface_descriptor_request(PS_UHP_ED pED, void *out) {
unsigned char setup[] = {0x80,0x06,0x00,0x04,0x00,0x00,0x40,0x00};
return ohci_new_control_trans(pED, 0, out, setup, 64);
}
/*
*
*/
int ohci_set_address_request(PS_UHP_ED pED, void *out, unsigned int address) {
unsigned char setup[] = {0x00,0x05,(unsigned char)address,0x02,0x00,0x00,0x00,0x00};
int result = -1;
OHCI_PS_UHP_ED phED = pED->phED;
result = ohci_new_control_trans(pED, 0, out, setup, 0);
phED->Control |= (unsigned int) address;
pED->Func_Address = address;
return result;
}
/*
*
*/
int ohci_set_configured_request(PS_UHP_ED pED, void *out) {
unsigned char setup[] = {0x00,0x09,0x01,0x00,0x00,0x00,0x00,0x00};
return ohci_new_control_trans(pED, 0, out, setup, 0);
}
/*
*
*/
int ohci_clear_future_request(PS_UHP_ED pED, void *out, unsigned int future, unsigned int ep_addr) {
unsigned char setup[] = {0x02,0x01,future,0x00,ep_addr,0x00,0x00,0x00};
return ohci_new_control_trans(pED, 0, out, setup, 0);
}
int ohci_usb_clear_halt(PS_UHP_ED pED, unsigned int epnum) {
return ohci_clear_future_request(pED, NULL, 0x00, epnum);
}
/*
*
*/
int ohci_bulk_write(PS_UHP_ED pED, void *pOut, unsigned int size, unsigned int tm) {
PS_UHP_TD pTDout;
OHCI_PS_UHP_ED phED = pED->phED;
int trans = 0;
//lock_ohci();
if (!phED) {
//unlock_ohci();
return -1;
}
// create OUT transaction
pTDout = ohci_create_td(pED->Trigger, 0, ED_OUT, 1, (unsigned int)pOut, size, 0, 0, 0);
if (!pTDout) {
//unlock_ohci();
return -1;
}
ohci_add_td(pED, pTDout);
// create OUT transaction
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -