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

📄 ohci.c

📁 usb host driver OHCI
💻 C
📖 第 1 页 / 共 4 页
字号:
 							ED_SKIP,			// Skip
 							ED_LOW_SPEED,		// Speed
 							ED_IN,		// Direction
 							0,					// Endpoint number
 							0,					// Func Address
 							0,					// TDQTailPointer
 							0,					// TDQHeadPointer
 							0,					// ToggleCarry
 							0,					// NextED
 							OHCI_INT_ED,
 							64);	
	if (!pInt)
		return -1;
	
	ohci->HcPeriodCurrentED = (unsigned int) pInt->phED;
	pHcca->UHP_HccaInterruptTable[0] = (unsigned int) pInt->phED;	
	return 0;
}

void ohci_os_init() {
	ohci_sem = OSSemCreate(0);
	ohci_int_sem = OSSemCreate(0);
	OHCI_msg = OSMboxCreate(NULL);
	ohci_lock = OSSemCreate(1);
}
/*
 * 
 */
void ohci_cpu_init() {
	int i;	
	// Open clocks for USB host
	CPU_ConfigureUHPClock();
	// Forcing UHP_Hc to reset
	// Disabling port power
	ohci->HcRhPortStatus[0] = (1 << 9);
	ohci->HcRhPortStatus[1] = (1 << 9);
	OSTimeDly(100);
	ohci->HcControl = 0;	
	OSTimeDly(10);	
	ohci->HcCommandStatus = 0x01;
	
	for (i = 0; i < 10; i++) {	
		int hcr;
		OSTimeDly(1);
		hcr = ohci->HcCommandStatus & 0x01;
		if (!hcr) break;
	}
	ohci->HcInterruptEnable = (IMASK | OHCI_MIE);		
	// Writing the UHP_HCCA
	ohci->HcHCCA = (unsigned int) &HCCA;
	// Enabling list processing
	ohci->HcControl = 0;
	// Set the frame interval
	ohci->HcFmInterval = FMINTERVAL;
	ohci->HcPeriodicStart = PRDSTRT;
	// Create a default endpoint descriptors
	ohci_init_ed_list();
	// Initializing the UHP_HcDoneHead
	ohci->HcDoneHead = 0;
	HCCA.UHP_HccaDoneHead = 0x0000;

	// Forcing UHP_Hc to Operational State
	ohci->HcControl = 0x80;
	ohci->HcRhStatus = (1 << 16);
	// Enabling port power
	ohci->HcRhPortStatus[0] = 0x00000100;
	ohci->HcRhPortStatus[1] = 0x00000100;

	ohci->HcRhStatus = 0x00010000;

	UHP_Isr_Init();
}

/*
 * 
 */
static void ohci_free_all_eds(USBDevice_t *pD) {
	unsigned int i;
	
	for (i = 0;i < MAX_EDS;i++) {
		if (pD->dev_eds[i].present) {
			ohci_skip_ed((PS_UHP_ED)pD->dev_eds[i].pED);
			if (ohci_remove_ed((PS_UHP_ED)pD->dev_eds[i].pED)) {
				OHCI_DBG("ERROR: Ed is not in phisical Ed list\r\n");
			}
			ohci_free_ed((PS_UHP_ED)pD->dev_eds[i].pED);
			memset(&pD->dev_eds[i], 0, sizeof(dev_ed_t));
		}
	}
}

void ohci_int_disable() {
	AT91C_BASE_AIC->AIC_IDCR = 1 << AT91C_ID_UHP;
	AT91C_BASE_AIC->AIC_SVR[ AT91C_ID_UHP ] = 0;
	AT91C_BASE_AIC->AIC_SMR[ AT91C_ID_UHP ] = 0;	
}

void ohci_free_ed_list() {
	unsigned int i;
	
	for (i = 0;i < 3;i++) {
		if (psUHPED[i]) {
			ohci_skip_ed((PS_UHP_ED)psUHPED[i]);
			ohci_free_ed((PS_UHP_ED)psUHPED[i]);
		}
	}
}

void ohci_os_shutdown() {
	unsigned char err;
	OSSemDel(ohci_sem, OS_DEL_ALWAYS, &err);
	OSSemDel(ohci_int_sem, OS_DEL_ALWAYS, &err);
	OSSemDel(OHCI_msg, OS_DEL_ALWAYS, &err);
	OSSemDel(ohci_lock, OS_DEL_ALWAYS, &err);
}

void ohci_shutdown() {
	unsigned char err;
	// Disable INT and CLOCK
	ohci_int_disable();
	// Disable port power
	ohci->HcRhPortStatus[0] = (1 << 9);
	ohci->HcRhPortStatus[1] = (1 << 9);
	ohci->HcRhStatus = (1 << 0);
	//ohci_os_shutdown();
	// Kill ED list
	for (err = 0;err < 2;err++) {
		if (USBDev[err].present) {
			ohci_free_all_eds(&USBDev[err]);
		}
	}		
	ohci_free_ed_list();
	ohci_clock_disable();
}

/*
 * 
 */
static unsigned int hub_status = 0;

static void ohci_hub_isr() {
	unsigned int hub_msg = 0;
	
	if ( (ohci->HcRhPortStatus[0] & 0x01) && (!(hub_status & (1 << 0))) ) {		
		hub_msg = OHCI_MSG_DEVICE_POWERED_1;
		hub_status |= (1 << 0);
		ohci_post_event(OHCI_msg, hub_msg);
	} else if ((ohci->HcRhPortStatus[1] & 0x01) && (!(hub_status & (1 << 1)))) {		
		hub_msg = OHCI_MSG_DEVICE_POWERED_2;
		hub_status |= (1 << 1);
		ohci_post_event(OHCI_msg, hub_msg);
	} else if (!(ohci->HcRhPortStatus[0] & 0x01) && (hub_status & (1 << 0))) {
		//OHCI_DBG("-I- Device detached from port 0\n\r");
		hub_status &= ~(1 << 0);
		ohci_post_event(OHCI_msg, OHCI_MSG_DEVICE_DETACHED_1);
		ohci->HcRhPortStatus[0] = (1 << 0);
	} else if (!(ohci->HcRhPortStatus[1] & 0x01) && (hub_status & (1 << 1))) {
		//OHCI_DBG("-I- Device detached from port 1\n\r");
		hub_status &= ~(1 << 1);
		ohci_post_event(OHCI_msg, OHCI_MSG_DEVICE_DETACHED_2);
		ohci->HcRhPortStatus[1] = (1 << 0);
	}
}



/*
 * 
 */
static int ohci_attach_device(USBDevice_t *pD) {
	
	cur_dev_num = 1;
	
	pD->state = DEVICE_STATE_POWERED;
	
	if (ohci_create_control_ed(pD)) {
		cur_dev_num = 0;
		return -1;				
	}
	ohci->HcControl |= (USBOPERATIONAL | OHCI_CL_CLE );
	if (ohci_get_device_info(pD)) {
		ohci_free_all_eds(pD);
		memset(pD, 0, sizeof(USBDevice_t));
		cur_dev_num = 0;
		return -1;
	}
		
	pD->state = DEVICE_STATE_CONFIGURED;
	
	if (ohci_set_device_configuration(pD)) {
		ohci_free_all_eds(pD);
		memset(pD, 0, sizeof(USBDevice_t));
		cur_dev_num = 0;
		return -1;
	}
	ohci->HcControl |= (USBOPERATIONAL | OHCI_CL_BLE | OHCI_CL_PLE);
	pD->lock_sem = OSSemCreate(1);
	return 0;
}

/*
 * 
 */
static int ohci_remove_device(USBDevice_t *pD) {
	unsigned char err;
	OSSemDel(pD->lock_sem, OS_DEL_ALWAYS, &err);
	ohci_free_all_eds(pD);
	pD->state = DEVICE_STATE_DETACHED;
	return 0;
}

#ifndef WITH_FS
extern int msd_init(unsigned int Unit);
#endif
/*
 * 
 */
int usb_load_driver(USBDevice_t *pD) {
	if (pD->interface_descriptor.bInterfaceClass == 0x08) {
#ifdef WITH_FS		
		if (FS_Init(pD->dev_num)) {
			//printf("ERROR init FS\r\n");
			return -1;
		}
#else 	
	msd_init(pD->dev_num);
#endif
	} /*else if (pD->interface_descriptor.bInterfaceClass == 0x03) {
		if (pD->interface_descriptor.bInterfaceProtocol == 0x02) {
			if (um_create_driver(pD)) {
				//printf("ERROR init HID\r\n");
				return -1;
			}
		} 
		
	}*/ else {
		//printf("ERROR can not create unknown device driver\r\n");
		return -1;
	}
	
	return 0;
}

/*
 * 
 */
int usb_unload_driver(USBDevice_t *pD) {
	if (pD->interface_descriptor.bInterfaceClass == 0x08) {
#ifdef WITH_FS		
		FS_Exit();
#endif		
		ohci_remove_device(pD);	
		return 0;
	} /*else if (pD->interface_descriptor.bInterfaceClass == 0x03) {
		if (pD->interface_descriptor.bInterfaceProtocol == 0x02) {
			um_remove_driver(pD);
			ohci_remove_device(pD);
			return 0;
		}		
	} */else {
		ohci_remove_device(pD);
		//printf("Unknown device!\r\n");
		return -1;
	}
	return -1;
}


#define OHCI_TASK_STK_SIZE    4096

static unsigned int ohci_stack[OHCI_TASK_STK_SIZE];

void ohci_task(void *parg) {
	USBDevice_t *pDevice = NULL;
	static unsigned int ohci_state = OHCI_IDLE;
	unsigned int message;
	unsigned int device = 0;
	OS_CPU_SR cpu_sr;
	volatile unsigned int i;
	
	ohci_os_init();
	ohci_cpu_init();
	
	while (1) {		
		switch (ohci_state) {
		case OHCI_IDLE:
			
			message = (unsigned int)ohci_wait_event(OHCI_msg, 0);
			
			if ((message & 0x7F) == OHCI_MSG_DEVICE_POWERED_1)  {
				device = 0;
				OS_ENTER_CRITICAL();
				// This loop is very important
				for (i = 0;i < 10000;i++);
				OS_EXIT_CRITICAL();
				ohci->HcRhPortStatus[0] = (1 << 4); // SetPortReset
				while (ohci->HcRhPortStatus[0] & (1 << 4)); // Wait for the end of reset
				ohci->HcRhPortStatus[0] = (1 << 1); // SetPortEnable				
				if (ohci->HcRhPortStatus[0] & OHCI_RH_LSDA)
					message |= OHCI_DEV_LOW_SPEED;
				
			} else if ((message & 0x7F) == OHCI_MSG_DEVICE_POWERED_2) {
				device = 1;
				OS_ENTER_CRITICAL();
				// This loop is very important
				for (i = 0;i < 10000;i++);
				OS_EXIT_CRITICAL();
				ohci->HcRhPortStatus[1] = (1 << 4); // SetPortReset
				while (ohci->HcRhPortStatus[1] & (1 << 4)); // Wait for the end of reset
				ohci->HcRhPortStatus[1] = (1 << 1); // SetPortEnable
				if (ohci->HcRhPortStatus[1] & OHCI_RH_LSDA)
					message |= OHCI_DEV_LOW_SPEED;
			} else if (message == OHCI_MSG_DEVICE_DETACHED_1) {
				device = 0;
			} else if (message == OHCI_MSG_DEVICE_DETACHED_2) {
				device = 1;
			}
				// create new device type
			pDevice = &USBDev[device];
						
			if (((message & 0x7F) == OHCI_MSG_DEVICE_POWERED_1) || 
				((message & 0x7F) == OHCI_MSG_DEVICE_POWERED_2))  {
				if (ohci->HcRhPortStatus[0] & OHCI_RH_LSDA)
				
				OSTimeDly(50);
				
				memset(pDevice, 0, sizeof(USBDevice_t));
				pDevice->speed = (message & 0x80);
				pDevice->dev_num = device;
				pDevice->present = 1;
							
				if (ohci_attach_device(pDevice)) {
					if (device == 0) {
						ohci->HcRhPortStatus[0] = (1 << 9);
						ohci->HcRhPortStatus[0] = (1 << 0);
					} else {
						ohci->HcRhPortStatus[1] = (1 << 9);
						ohci->HcRhPortStatus[1] = (1 << 0);
					}
					continue;
				} 
				usb_load_driver(pDevice);
				
			} else if ((message == OHCI_MSG_DEVICE_DETACHED_1) ||
					(message == OHCI_MSG_DEVICE_DETACHED_2)) {
				pDevice->present = 0;
				usb_unload_driver(pDevice);
			}
			
			break;
		case OHCI_DEVICE:
			break;
		case OHCI_OPER:
			break;
		case OHCI_ERROR:
			break;
		default:
			ohci_state = OHCI_IDLE;
			break;
		} //end of switch
		
	} //end of while
}

#define UF_START_BLOCK		1048576 // 1MB
#define UF_TEST_SIZE		1048576 * 1

static int usb_flash_test(unsigned int iter, unsigned int rw, unsigned int size) {
	unsigned int i;
	double time1, time2, per;
	unsigned char *pBufw, *pBufr;
	char *wdata = "ABCDEFJHIJKLMNOPQRSTUVWXYZ";
	unsigned int size_table[] = { 512, 1024, 2048, 4096, 8192, 16384, 32768,
			49152, 65536 };
	USBDevice_t *pDevice = &USBDev[0];
	unsigned int sz = 0;
#ifdef OHCI_STAT
	unsigned int byte_cnt_in = 0;
	unsigned int byte_cnt_out = 0;
	double dt = 0, din = 0, dout = 0;
	unsigned int terr = 0;
#endif		
	if (pDevice->state != DEVICE_STATE_CONFIGURED) {
		printf("No USB Flash device 0\r\n");
		return -1;
	}
		
	for (i = 0; i < sizeof(size_table); i++) {
		if (size == size_table[i]) { 
			sz = size;			
		}
	}

	if (!sz)
		sz = 512;

	pBufw = (unsigned char *)safe_malloc(sz);
	pBufr = (unsigned char *)safe_malloc(sz);
	if (!pBufw || !pBufr) {
		printf("Not enough memory\r\n");
		return -1;
	}
	puts("Test starting\r\n");
	time1 = (double)OSTimeGet();
#ifdef OHCI_STAT				
	byte_cnt_in = ohci_in_packet_count;
	byte_cnt_out = ohci_out_packet_count;
#endif		
	for (i = 0; i < ((UF_TEST_SIZE * iter)/sz); i++) {
		memset(pBufw, wdata[(i % 26)], sz);
		if (rw & 1) {
			if (usb_flash_write(pDevice, (void *)pBufw, ((UF_START_BLOCK + (i * sz)) / 512), sz)) {
				printf("Write err\r\n");		
				terr++;
				break;
			}
		}

		if (rw & 2) {
			if (usb_flash_read(pDevice, (void *)pBufr, ((UF_START_BLOCK + (i * sz))/ 512), sz)) {
				printf("Read err\r\n");
				break;
			}
		}
		if (rw == 3) {
			if (memcmp(pBufw, pBufr, sz)) {
				printf("Data comparsion error\r\n");
				printf("Block: %d\r\n", ((UF_START_BLOCK + (i * sz))/ 512));
			}
		}
		
		per = (double)((((double)i)/((UF_TEST_SIZE * iter)/sz)) * 100);

		printf("Complete: %.f%%\r", per);

	}
	safe_free(pBufw);
	safe_free(pBufr);

	time2 = (double)OSTimeGet();
	printf("\r\n");
#ifdef OHCI_STAT	
	dt = (double)((time2 - time1)/OS_TICKS_PER_SEC);
	printf("Time: %.2f Sec\r\n", dt);
	if (rw & 2)
		din = (ohci_in_packet_count - byte_cnt_in)/dt;
	if (rw & 1)
		dout = (ohci_out_packet_count - byte_cnt_out)/dt;
	printf("USB Total speed: %.2f Bytes/s\r\n", (din + dout));
#endif
	return 0;
}

int usbh_test(char *command, char *operation, int iter, int size) {
	unsigned int rw = 0;

	if (!strcmp(operation, "rw"))
		rw = 3;
	else if (!strcmp(operation, "w"))
		rw = 1;
	else if (!strcmp(operation, "r"))
		rw = 2;
	else
		rw = 2;

	//usb_flash_test(iter, rw, size);
	usb_flash_test(iter, rw, size);
	return 0;
}

int usbh_clear_ep(char *command, int epnum, int param2, int param3) {
	PS_UHP_ED pED;
	USBDevice_t *pD = &USBDev[0];
	pED = (PS_UHP_ED)(pD->dev_eds[OHCI_CONTROL_ED].pED);
	ohci_usb_clear_halt(pED, epnum);
	return 0;
}

int usbh_restart_uhp(char *command, int param1, int param2, int param3) {
	ohci_shutdown();
	OSTimeDly(50);
	ohci_cpu_init();
	OSTimeDly(50);
	ohci_post_event(OHCI_msg, OHCI_MSG_DEVICE_POWERED_1);
	return 0;
}

/*
 *  
 */
void InitUHP(void) {
	
	OSTaskCreateExt( ohci_task,
                     ( void * ) 0,
                     ( OS_STK * ) &ohci_stack[ OHCI_TASK_STK_SIZE - 1 ],
                     OHCI_TASK_PRIORITY,
                     OHCI_TASK_PRIORITY,
                     ( OS_STK * ) &ohci_stack[ 0 ],
                     OHCI_TASK_STK_SIZE,
                     ( void * ) 0,
                     OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR );
	
		
}

⌨️ 快捷键说明

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