📄 ohci.c
字号:
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 + -