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

📄 ohci.c

📁 usb host driver OHCI
💻 C
📖 第 1 页 / 共 4 页
字号:
		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 + -