📄 sl811.c
字号:
//
#define NC 128
typedef struct _BC {
UINT Ref : 31;
UINT Modified:1;
ULONG st;
UCHAR *Data;
} BC;
//
// 缓冲区
//
static BC acc[NC];
//
// 初始化缓冲区
//
static void
BCInit(void) {
int i;
for(i = 0; i < NC; i++) {
acc[i].st = 0xFFFF00FF;
acc[i].Modified = 0;
acc[i].Ref = 0;
}
}
//
// 引用被缓冲的扇区
//
static void
Refer(UINT b) {
ULONG i, max;
max = acc[b].Ref;
for(i = 0; i < NC; i++)
if(acc[i].Ref > max)
max = acc[i].Ref;
acc[b].Ref = max + 1;
}
//
// 查找被缓冲的扇区
//
static int
Lookup(ULONG st) {
UINT b;
for(b = 0; b < NC; b++)
if(acc[b].st == st)
return b;
return -1;
}
//
// 回写缓冲取中被修改的扇区
//
static void
XX_Flush(UINT b) {
acc[b].Modified = 0;
__usbWriteBlock(&MassStor, acc[b].st, acc[b].Data);
}
//
// 新建一个扇区缓冲区
//
static int
NewEntry(ULONG lba) {
UINT i, b;
b = 0;
for(i = 0; i < NC; i++) {
if(!acc[i].Data) {
// 分配内存
acc[i].Data = (UCHAR *)kmalloc(MassStor.BlockSize);
b = i;
break;
}
if(acc[i].Modified <= acc[b].Modified && acc[i].Ref < acc[b].Ref)
b = i;
}
ASSERT(b < NC);
// 回写被修改的扇区
if(acc[b].Modified)
XX_Flush(b);
acc[b].st = lba;
acc[b].Modified = 0;
return b;
}
//
// 同步海量存储设备
//
void
UsbSync(void) {
UINT b;
if(!UsbDsk.Connected)
return;
//LockDrive(&UsbDsk);
for(b = 0; b < NC; b++)
if(acc[b].Modified)
XX_Flush(b);
//UnlockDrive(&UsbDsk);
}
//
// 读海量存储设备扇区
//
// ms: 海量存储设备
// lba:扇区号
// buf:数据指针
//
int
usbReadBlock(MASS_STOR *ms, ULONG lba, void *buf) {
struct us_cbw cbw;
struct us_csw csw;
int b;
if(lba >= ms->BlockNumber)
return FALSE;
// 缓冲命中
b = Lookup(lba);
if(b != -1)
goto retOk;
// 缓冲失败,申请一个缓冲区
b = NewEntry(lba);
//DBG2("usbReadBlock(%u, %08X)...\n", lba, buf);
// 组"SCSI读扇区"命令包
cbw.dSignature = CBW_SIGNATURE;
cbw.dTag = 0x60a624de;
cbw.dXferLength = ms->BlockSize;
cbw.bFlags = 0x80;
cbw.bLUN = 0;
cbw.bCBDLength = 10;
/////////////////////////////////
cbw.aCmd[0] = 0x28; // operation code
cbw.aCmd[1] = 0;
// LBA
cbw.aCmd[2] = lba >> 24;
cbw.aCmd[3] = lba >> 16;
cbw.aCmd[4] = lba >> 8;
cbw.aCmd[5] = lba;
// Transfer Length
cbw.aCmd[7] = 0;
cbw.aCmd[8] = 1;
cbw.aCmd[9] = 0; // Control = 00h
////////////////////////////////
// 下发"SCSI读扇区"命令包
if(BulkOut(ms, (UCHAR *)&cbw, sizeof(cbw)) != TRUE)
return FALSE;
// 读出数据
if(BulkIn(ms, acc[b].Data, ms->BlockSize) != TRUE)
return FALSE;
// 读出命令操作状态
if(BulkIn(ms, (UCHAR *)&csw, sizeof(csw)) != TRUE)
return FALSE;
if(csw.bStatus != CSW_STATUS_OK)
return FALSE;
retOk:
Refer(b);
// 从缓冲区中读出数据
Memcpy(buf, acc[b].Data, ms->BlockSize);
return TRUE;
}
//
// 写海量存储设备扇区(缓冲)
//
// ms: 海量存储设备
// lba:扇区号
// buf:数据指针
//
int
usbWriteBlock(MASS_STOR *ms, ULONG lba, void *buf) {
int b;
if(lba >= ms->BlockNumber)
return FALSE;
// 缓冲命中
b = Lookup(lba);
if(b == -1)
b = NewEntry(lba); // 缓冲失败,申请一个缓冲区
Refer(b);
// 写入缓冲区
Memcpy(acc[b].Data, buf, ms->BlockSize);
acc[b].Modified = TRUE;
return TRUE;
}
//
// 读驱动器扇区
//
static int
cb_rdsect(DRIVE *d, ULONG st, UCHAR *buf) {
return usbReadBlock(d->ms, st, buf);
}
//
// 写驱动器扇区
//
static int
cb_wrsect(DRIVE *d, ULONG st, UCHAR *buf) {
return usbWriteBlock(d->ms, st, buf);
}
//
// 同步驱动器
//
static void
cb_sync(DRIVE *d) {
UsbSync();
}
//
// 同步驱动器单个扇区
//
static void
cb_sync2(DRIVE *d, UINT st) {
int b;
b = Lookup(st);
ASSERT(b < NC);
if(b != -1) {
acc[b].Ref = 0;
XX_Flush(b);
}
}
////////////////////////////////////////////////////////
// USB主机控制器复位
//
void
hc_reset(HC *hc) {
PSW
UCHAR t;
// 假定没有设备接入
UsbDsk.Connected = FALSE;
hc->reset = FALSE;
hc->enumed = FALSE;
hc->devfound = FALSE;
DISABLE;
/* 禁止中断
*/
hc_write(hc, SL_INTEN, 0);
/* 停止传输,复位控制器
*/
hc_write(hc, SL_HCR_A, 0);
hc_write(hc, SL_HCR_B, 0);
hc_write(hc, SL_SOF_HI, SL_SOFH_Master);
ENABLE;
/* 延时等待
*/
tm_delay(50);
DISABLE;
/* 清除中断
*/
hc_write(hc, SL_ISTATUS, 0xFF);
/* 检查总线连接状态
*/
t = hc_read(hc, SL_ISTATUS);
ENABLE;
if(t & 0x40) {
hc->connected = FALSE;
//DBG("SL811HS: No device or no power\n");
} else {
hc->connected = TRUE;
hc->reset = TRUE;
if (!(t & 0x80 )) {
//
// 慢速设备接入
//
hc->lowSpeed = TRUE;
//DBG("SL811HS: Low speed device connected\n");
} else {
//
// 全速设备接入
//
hc->lowSpeed = FALSE;
DISABLE;
hc_write(hc, SL_SOF_HI,SL_SOFH_1ms|SL_SOFH_Master);
hc_write(hc, SL_SOF_LOW, SL_SOFL_1ms);
hc_write(hc, SL_CTRL1,SL_CTRL1_SOF_en|SL_CTRL1_Reset|SL_CTRL1_EOF2);
ENABLE;
tm_delay(50);
DISABLE;
hc_write(hc, SL_CTRL1,SL_CTRL1_SOF_en|SL_CTRL1_EOF2);
ENABLE;
//DBG("SL811HS: Full speed device connected\n");
}
DISABLE;
/* start the SOF or EOP */
hc_write(hc, SL_HPID_A, SL_MAKE_HPID(SL_HPID_SOF,0));
hc_write(hc, SL_HDA_A, 0);
hc_write(hc, SL_HCR_A, SL_HCR_Arm);
ENABLE;
}
// 延时
tm_delay(10);
DISABLE;
/* 清除USB中断
*/
hc_write(hc, SL_ISTATUS, 0xFF);
/* 设置USB中断允许寄存器,允许某些中断
*/
hc_write(hc, SL_INTEN, INTS);
ENABLE;
}
////////////////////////////////////////////////////////
// USB主机控制器初始化
//
static void
hc_init(HC *hc) {
//
// 初始化变量
//
Memset(hc, 0, sizeof(HC));
hc->AddrPort = SL811_ADDR_PORT;
hc->DataPort = SL811_DATA_PORT;
// 创建信号量
(void)sm_create("SLSM", 0, 0, &hc->sm);
/* 设置中断向量
*/
IntConnect(ISR_SL811, (UINT)SL811Handler);
ASSERT(rINTMSK & BIT_SL811);
// 允许USB中断
rINTMSK &= ~(BIT_SL811);
//
// 需要复位USB控制器
//
hc->reset = TRUE;
}
////////////////////////////////////////////////////
// USB任务入口
//
void
usbMain(void *args) {
HC *hc = &SL811;
Memset(acc, 0, sizeof(acc));
UsbDsk.Connected = FALSE;
//DBG("Usb testing...\n");
hc_init(hc);
while(1) {
// 等待U盘插入
sm_p(smSL811, FOREVER);
// 需要复位USB控制器
if(hc->reset) {
(void)hc_reset(hc);
if(!hc->connected) {
UsbDsk.Connected = FALSE;
// U盘拔出,卸载U盘驱动器
if(UsbDsk.Flags & DRIVE_MOUNT)
FatUnmount(&UsbDsk);
continue;
}
}
// USB设备插入,但是未枚举
if(hc->connected && !hc->enumed) {
struct usb_device_descriptor *dev;
hc->ep0.Payload = 16;
hc->ep0.Endpoint = 0;
hc->ep0.Toggle = 0;
hc->enumed = TRUE;
// 取得设备描述符
Memset(&MassStor, 0, sizeof(MassStor));
MassStor.hc = hc;
if(!GetDevDesc(&MassStor)) {
//DBG("GET DEVICE DESCRIPTOR FAILED!\n");
continue;
}
dev = &hc->dev;
//DBG("USB Device %x.%x\n", dev->bcdUSB >> 8, (dev->bcdUSB & 0xF0)>>4);
//DBG("bMaxPacketSize0 %u Bytes\n", dev->bMaxPacketSize0);
// 设置设备地址
if(!SetAddress(&MassStor)) {
//DBG("SET ADDRESS FAILED!\n");
hc->reset = TRUE;
continue;
}
MassStor.DeviceAddress = USB_ADDR;
// 检测海量存储设备
if(!UsbMassDetect(&MassStor)) {
//DBG("Usb Mass Storage detect FAILED!\n");
hc->reset = TRUE;
continue;
}
DBG("USB Mass Storage Device found!\n");
// 质询USB设备
if(!Inquiry(&MassStor)) {
//DBG("Inquiry FAILED!\n");
hc->reset = TRUE;
continue;
}
// 获取USB设备参数
if(!ReadCapacity(&MassStor)) {
//DBG("ReadCapacity FAILED!\n");
hc->reset = TRUE;
continue;
}
// 缓冲区初始化
BCInit();
// 挂载USB驱动器
Memset(&UsbDsk, 0, sizeof(UsbDsk));
UsbDsk.ms = &MassStor;
UsbDsk.Sectors = MassStor.BlockNumber;
UsbDsk.BytesPerSector = MassStor.BlockSize;
UsbDsk.BytesPerSectorShift = MassStor.BlockSizeShift;
UsbDsk.ReadSector = (CALLBACK)cb_rdsect;
UsbDsk.WriteSector = (CALLBACK)cb_wrsect;
UsbDsk.Sync = cb_sync;
UsbDsk.Sync2 = cb_sync2;
if(!FatMount(&UsbDsk, "USBd"))
continue;
UsbDsk.Connected = TRUE;
}
//tm_delay(20);
//DBG(">");
}
}
/*
USB任务
|----------------|
| 设置中断向量 |
|----------------|
| <-----------|
|----------------| |
|等待U盘插入,拔出| |
|----------------| |
| |
|----------------| |
| 复位USB总线 | |
|----------------| |
| |
|----------------| 是 |
| U盘拔出? |----+
|----------------| |
|(否,U盘插入)|
|----------------| |
| 取得设备描述符 | |
|----------------| |
| |
|----------------| |
| 设置设备地址 | |
|----------------| |
| |
|----------------| |
| 获取配置描述 | |
|----------------| |
| |
|----------------| |
|获取接口,端点描述| |
|----------------| |
| |
|----------------| |
| 设置配置 | |
|----------------| |
| |
|----------------| |
| 质询USB设备 | |
|----------------| |
| |
|----------------| |
| 获取U盘参数 | |
|----------------| |
| |
|----------------| |
| 缓冲区初始化 | |
|----------------| |
| |
|----------------| |
| 挂载U盘驱动器 | |
|----------------| |
| |
+-------------|
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -