📄 ohci.c
字号:
#include "ioat91sam9260.h"
#include "ohci.h"
#include "includes.h"
#include "msd.h"
#include "mass.h"
#include "prio.h"
// =====================================
// Memory allocation for UHP:
// =====================================
// UHP HCCA memory location:
OHCIPS_t ohci = (OHCIPS_t)OHCI_REGS_BASE;
#define ohci_wr_reg(reg, val) {ohci->(reg) = (val)}
#define ohci_rd_reg(reg) {ohci->(reg)}
OHCI_S_UHP_HCCA HCCA __attribute__ ((aligned(256)));
PS_UHP_ED psUHPED[MAX_EDS];
volatile unsigned int o_sem = 0;
#ifdef OHCI_STAT
volatile unsigned int ohci_in_packet_count;
volatile unsigned int ohci_out_packet_count;
#endif
USBDevice_t USBDev[MAX_USB_DEV];
static unsigned int cur_dev_num = 0;
static unsigned int cur_td_num = 0;
static unsigned int cur_ed_num = 0;
static OS_EVENT *ohci_sem;
static OS_EVENT *ohci_int_sem;
static OS_EVENT *ohci_lock;
static OS_EVENT *OHCI_msg;
#define FRINTERVAL 0x2EDF
#define FSMAXPKTSZ (((FRINTERVAL - 210) * 6) / 7)
#define FMINTERVAL ((FSMAXPKTSZ << 16) | FRINTERVAL)
#define PRDSTRT 9*FRINTERVAL/10;
#define IMASK (OHCI_RHSC | OHCI_WDH)
//*********************** prototypes **********************************************
void print_dev_data(void *pDevData);
static int isr_process(unsigned int mask);
static void UHP_Isr_Handler();
static void ohci_hub_isr();
static int start_trans(PS_UHP_ED pED);
static void ohci_skip_ed(PS_UHP_ED pED);
PS_UHP_TD ohci_create_td(unsigned int td_type,
unsigned int del_int,
unsigned int direction,
unsigned int rounding,
unsigned int cbp,
unsigned int buf_len,
unsigned int next_td,
unsigned int cb,
unsigned int arg);
void ohci_add_td(PS_UHP_ED pED, PS_UHP_TD pTD);
/*
*
*/
static void ll_CreateEd(
unsigned int EDAddr,
unsigned int MaxPacket,
unsigned int TDFormat,
unsigned int Skip,
unsigned int Speed,
unsigned int Direction,
unsigned int EndPt,
unsigned int FuncAddress,
unsigned int TDQTailPntr,
unsigned int TDQHeadPntr,
unsigned int ToggleCarry,
unsigned int NextED)
{
OHCI_PS_UHP_ED pED = (OHCI_PS_UHP_ED) EDAddr;
pED->Control = (MaxPacket << 16) | (TDFormat << 15) |
(Skip << 14) | (Speed << 13) | (Direction << 11) |
(EndPt << 7) | FuncAddress;
pED->TailP = (TDQTailPntr & 0xFFFFFFF0);
pED->HeadP = (TDQHeadPntr & 0xFFFFFFF0) | (ToggleCarry << 1);
pED->NextEd = (NextED & 0xFFFFFFF0);
}
/*
*
*/
static void ll_CreateGenTd(
unsigned int GenTdAddr,
unsigned int DataToggle,
unsigned int DelayInterrupt,
unsigned int Direction,
unsigned int BufRnding,
unsigned int CurBufPtr,
unsigned int NextTD,
unsigned int BuffLen)
{
OHCI_PS_UHP_TD pTD = (OHCI_PS_UHP_TD) GenTdAddr;
pTD->Control = (DataToggle << 24) | (DelayInterrupt << 21) | (Direction << 19) | (BufRnding << 18);
pTD->CBP = CurBufPtr;
pTD->NextTD = (NextTD & 0xFFFFFFF0);
pTD->BE = (BuffLen) ? CurBufPtr + BuffLen - 1 : CurBufPtr;
}
/*
*
*/
static void ll_CreateGenITd(
unsigned int GenTdAddr,
unsigned int CondCode,
unsigned int FrameCount,
unsigned int DelayInterrupt,
unsigned int StartFrame,
unsigned int BuffPage0,
unsigned int NextTD,
unsigned int BufEnd,
unsigned int PswOffset0,
unsigned int PswOffset1,
unsigned int PswOffset2,
unsigned int PswOffset3,
unsigned int PswOffset4,
unsigned int PswOffset5,
unsigned int PswOffset6,
unsigned int PswOffset7)
{
OHCI_PS_UHP_ITD pITD = (OHCI_PS_UHP_ITD) GenTdAddr;
pITD->Control = (CondCode << 28) | (FrameCount << 24) | (DelayInterrupt << 21) | StartFrame;
pITD->BP0 = (BuffPage0 << 12);
pITD->NextTD = (NextTD << 4);
pITD->BE = BufEnd;
pITD->PSW0 = PswOffset0;
pITD->PSW1 = PswOffset1;
pITD->PSW2 = PswOffset2;
pITD->PSW3 = PswOffset3;
pITD->PSW4 = PswOffset4;
pITD->PSW5 = PswOffset5;
pITD->PSW6 = PswOffset6;
pITD->PSW7 = PswOffset7;
}
typedef struct _S_TIMEOUT {
unsigned int tick;
unsigned int second;
} S_TIMEOUT, *PS_TIMEOUT;
static void InitTimeout(PS_TIMEOUT pTimeout, unsigned int second)
{
pTimeout->tick = OSTimeGet();
pTimeout->second = second;
}
static int TestTimeout(PS_TIMEOUT pTimeout)
{
if (pTimeout->second != 0) {
if (((pTimeout->tick + (OS_TICKS_PER_SEC * pTimeout->second))) < OSTimeGet()) {
pTimeout->second = 0;
return 0;
}
}
return pTimeout->second;
}
//********* Platform dependent functions *********************************
inline void AT91F_PMC_EnablePeriphClock (
AT91PS_PMC pPMC, // \arg pointer to PMC controller
unsigned int periphIds) // \arg IDs of peripherals to enable
{
pPMC->PMC_PCER = periphIds;
}
inline void AT91F_UHP_CfgPMC (void)
{
AT91F_PMC_EnablePeriphClock(
AT91C_BASE_PMC, // PIO controller base address
((unsigned int) 1 << AT91C_ID_UHP));
}
//**************************************************************************
void CPU_ConfigureUHPClock() {
// for atmel CPU
AT91F_UHP_CfgPMC();
// enable UHP clock in PMC
AT91C_BASE_PMC->PMC_SCER |= (AT91C_PMC_UHP);
}
void CPU_DisableUHPClock() {
AT91C_BASE_PMC->PMC_SCDR |= (AT91C_PMC_UHP);
}
void ohci_clock_disable() {
CPU_DisableUHPClock();
}
static void lock_ohci() {
unsigned char err;
OSSemPend(ohci_lock, 0, &err);
}
static void unlock_ohci() {
OSSemPost(ohci_lock);
}
/*
*
*/
static void AT91_UHP_Isr_Init() {
AT91C_BASE_AIC->AIC_SVR[ AT91C_ID_UHP ] = ( unsigned int )UHP_Isr_Handler;
AT91C_BASE_AIC->AIC_SMR[ AT91C_ID_UHP ] = 0;
AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_UHP;
AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_UHP;
}
/*
*
*/
static void UHP_Isr_Init() {
AT91_UHP_Isr_Init();
}
static void CPU_ClearUHPPendingBit() {
// for atmel cpu
AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_UHP;
AT91C_BASE_AIC->AIC_EOICR = 0;
}
/*
*
*/
static void UHP_Isr_Handler() {
unsigned int status, status_s;
status = ohci->HcInterruptStatus;
status_s = status & IMASK;
if (!status_s) {
ohci->HcInterruptStatus = status;
CPU_ClearUHPPendingBit();
return;
}
isr_process(status_s);
ohci->HcInterruptStatus = status;
CPU_ClearUHPPendingBit();
}
/*
*
*/
static int isr_process(unsigned int mask) {
unsigned int intrs, eintrs;
unsigned int done;
OHCI_PS_UHP_HCCA uhp;
intrs = 0;
uhp = (OHCI_PS_UHP_HCCA)ohci->HcHCCA;
done = uhp->UHP_HccaDoneHead;
if (done != 0) {
#ifndef OHCI_POLING
OSSemPost(ohci_sem);
#endif
o_sem = 1;
uhp->UHP_HccaDoneHead = 0;
intrs = OHCI_WDH;
} else {
intrs = mask;
}
if (intrs == 0) {
/* nothing to be done ?! */
return (0);
}
intrs &= IMASK; /* mask out Master Interrupt Enable */
/* Acknowledge any interrupts that have happened */
ohci->HcInterruptStatus = intrs;
/* Any interrupts we had enabled? */
eintrs = intrs ;//& sc->sc_eintrs;
if (!eintrs)
return (0);
if (eintrs & OHCI_SO) {
OHCI_DBG("scheduling overrun\r\n");
/* XXX do what */
intrs &= ~OHCI_SO;
}
if (eintrs & OHCI_WDH) {
//ohci_process_done(sc, done);
//printf("!!!DONE: 0x%08X\r\n", uhp->UHP_HccaDoneHead );
intrs &= ~OHCI_WDH;
}
if (eintrs & OHCI_RD) {
OHCI_DBG("resume detect\r\n");
/* XXX process resume detect */
}
if (eintrs & OHCI_UE) {
OHCI_DBG("unrecoverable error, controller halted\r\n");
// OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
/* XXX what else */
}
if (eintrs & OHCI_RHSC) {
//ohci_rhsc(sc, sc->sc_intrxfer);
ohci_hub_isr();
intrs &= ~OHCI_RHSC;
}
/* Block unprocessed interrupts. XXX */
ohci->HcInterruptDisable = intrs;
return 0;
}
void print_dev_data(void *pDevData) {
USBDeviceDescriptor *p = (USBDeviceDescriptor *)pDevData;
printf("\r\n");
printf("bDescriptorType: %d\r\n",p->bDescriptorType);
printf("bcdUSB: 0x%04X\r\n",p->bcdUSB);
printf("bDeviceClass: %d\r\n",p->bDeviceClass);
printf("bDeviceSubClass: %d\r\n",p->bDeviceSubClass);
printf("bDeviceProtocol: %d\r\n",p->bDeviceProtocol);
printf("bMaxPacketSize0: %d\r\n",p->bMaxPacketSize0);
printf("idVendor: 0x%04X\r\n",p->idVendor);
printf("idProduct: 0x%04X\r\n",p->idProduct);
printf("bcdDevice: 0x%04X\r\n",p->bcdDevice);
printf("iManufacturer: %d\r\n",p->iManufacturer);
printf("iProduct: %d\r\n",p->iProduct);
printf("iSerialNumber: %d\r\n",p->iSerialNumber);
printf("bNumConfigurations: %d\r\n",p->bNumConfigurations);
printf("\r\n");
}
char *parse_subclass(unsigned int s_class) {
switch(s_class) {
case 0x01: return "RBC";
case 0x02: return "MMC-2 (ATAPI)";
case 0x03: return "QIC-157";
case 0x04: return "UFI";
case 0x05: return "SFF-8070i";
case 0x06: return "SCSI";
default: return "Unknown";
};
}
char *parse_protocol(unsigned int protocol) {
switch(protocol) {
case 0x00: return "Control/Bulk/Interrupt (with cc)";
case 0x01: return "Control/Bulk/Interrupt (without cc)";
case 0x50: return "Bulk-Only Transport";
default: return "Unknown";
};
}
void print_dev_config(void *pDevData) {
USBConfigDescriptor *p = (USBConfigDescriptor *)pDevData;
USBInterfaceDescriptor *e = (USBInterfaceDescriptor *)(pDevData + sizeof(USBConfigDescriptor));
USBEndpointDescriptor *ed1 = (USBEndpointDescriptor *)(pDevData + sizeof(USBConfigDescriptor) +
sizeof(USBInterfaceDescriptor));
USBEndpointDescriptor *ed2 = (USBEndpointDescriptor *)(pDevData + sizeof(USBConfigDescriptor) +
sizeof(USBInterfaceDescriptor) + sizeof(USBEndpointDescriptor));
printf("\r\n");
printf("bLength: %d\r\n",p->bLength);
printf("bDescriptorType: %d (%s)\r\n",p->bDescriptorType, "Configuration");
printf("wTotalLength: %d\r\n",p->wTotalLength);
printf("bNumInterfaces: %d\r\n",p->bNumInterfaces);
printf("bConfigurationValue: %d\r\n",p->bConfigurationValue);
printf("iConfiguration: %d\r\n",p->iConfiguration);
printf("bmAttributes: 0x%02X\r\n",p->bmAttributes);
printf("bMaxPower: %d\r\n",p->bMaxPower);
printf("\r\n");
if (p->wTotalLength >= (sizeof(USBConfigDescriptor) + sizeof(USBInterfaceDescriptor))) {
printf("\r\n");
printf("bLength: %d\r\n",e->bLength);
printf("bDescriptorType: %d (%s)\r\n",e->bDescriptorType, "Interface");
printf("bInterfaceNumber: %d\r\n",e->bInterfaceNumber);
printf("bAlternateSetting: %d\r\n",e->bAlternateSetting);
printf("bNumEndpoints: %d\r\n",e->bNumEndpoints);
printf("bInterfaceClass: %s\r\n",(e->bInterfaceClass == 0x08)?"MASS STORAGE":"OTHER");
printf("bInterfaceSubClass: %s\r\n",parse_subclass(e->bInterfaceSubClass));
printf("bInterfaceProtocol: %s\r\n",parse_protocol(e->bInterfaceProtocol));
printf("iInterface: %d\r\n",e->iInterface);
printf("\r\n");
}
if (p->wTotalLength >= (sizeof(USBConfigDescriptor) + sizeof(USBInterfaceDescriptor) +
sizeof(USBEndpointDescriptor))) {
printf("\r\n");
printf("bLength: %d\r\n",ed1->bLength);
printf("bDescriptorType: %d (%s)\r\n",ed1->bDescriptorType, "Endpoint");
printf("bEndpointAddress: %d (%s)\r\n",ed1->bEndpointAddress & 0x7F,
(ed1->bEndpointAddress & 0x80)?"OUT":"IN");
printf("bmAttributes: 0x%02X (%s)\r\n",ed1->bmAttributes, (ed1->bmAttributes & 0x02)?
"Bulk": "Other");
printf("wMaxPacketSize: %d\r\n",ed1->wMaxPacketSize);
printf("bInterval: %d\r\n",ed1->bInterval);
printf("\r\n");
}
if (p->wTotalLength >= (sizeof(USBConfigDescriptor) + sizeof(USBInterfaceDescriptor) +
sizeof(USBEndpointDescriptor) + sizeof(USBEndpointDescriptor))) {
printf("\r\n");
printf("bLength: %d\r\n",ed2->bLength);
printf("bDescriptorType: %d (%s)\r\n",ed2->bDescriptorType, "Endpoint");
printf("bEndpointAddress: %d (%s)\r\n",ed2->bEndpointAddress & 0x7F,
(ed2->bEndpointAddress & 0x80)?"OUT":"IN");
printf("bmAttributes: 0x%02X (%s)\r\n",ed2->bmAttributes, (ed2->bmAttributes & 0x02)?
"Bulk": "Other");
printf("wMaxPacketSize: %d\r\n",ed2->wMaxPacketSize);
printf("bInterval: %d\r\n",ed2->bInterval);
printf("\r\n");
}
}
/*
*
*/
void print_interface (void *pDevData) {
USBInterfaceDescriptor *p = (USBInterfaceDescriptor*)pDevData;
printf("\r\n");
printf("bLength: %d\r\n",p->bLength);
printf("bDescriptorType: %d\r\n",p->bDescriptorType);
printf("bInterfaceNumber: %d\r\n",p->bInterfaceNumber);
printf("bAlternateSetting: %d\r\n",p->bAlternateSetting);
printf("bNumEndpoints: %d\r\n",p->bNumEndpoints);
printf("bInterfaceClass: %d\r\n",p->bInterfaceClass);
printf("bInterfaceSubClass: 0x%02X\r\n",p->bInterfaceSubClass);
printf("bInterfaceProtocol: %d\r\n",p->bInterfaceProtocol);
printf("iInterface: %d\r\n",p->iInterface);
printf("\r\n");
}
/*
*
*/
void print_cc(unsigned int cc) {
switch (cc) {
case 1:
printf("EP ERROR: CRC\r\n");
return;
case 2:
printf("EP ERROR: BITSTUFFING\r\n");
return;
case 3:
printf("EP ERROR: DATATOGGLEMISMATCH\r\n");
return;
case 4:
printf("EP ERROR: STALL\r\n");
return;
case 5:
printf("EP ERROR: DEVICENOTRESPONDING\r\n");
return;
case 6:
printf("EP ERROR: PIDCHECKFAILURE\r\n");
return;
case 7:
printf("EP ERROR: UNEXPECTEDPID\r\n");
return;
case 8:
printf("EP ERROR: DATAOVERRUN\r\n");
return;
case 9:
printf("EP ERROR: DATAUNDERRUN\r\n");
return;
case 12:
printf("EP ERROR: BUFFEROVERRUN\r\n");
return;
case 13:
printf("EP ERROR: BUFFERUNDERRUN\r\n");
return;
default:
printf("EP ERROR: RESERVED 0x%02X\r\n", cc);
return;
}
}
/*
*
*/
PS_UHP_TD ohci_create_td(unsigned int td_type,
unsigned int del_int,
unsigned int direction,
unsigned int rounding,
unsigned int cbp,
unsigned int buf_len,
unsigned int next_td,
unsigned int cb,
unsigned int arg) {
PS_UHP_TD pTD = NULL;
OHCI_PS_UHP_TD pUTD ;
if (cur_td_num > MAX_TDS) {
OHCI_DBG("UH ERROR: MAX TD\r\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -