📄 sl811.c
字号:
DISABLE;
// 读中断状态寄存器
st = hc_read(hc, SL_ISTATUS);
DoScript = FALSE;
// 命令完成中断
if(st & SL_INTEN_DONE_A) {
hc->DoneInts++;
urb = hc->CurURB;
if(urb != NULL) {
// 执行USB请求的下一步骤
r = (*AllScripts[urb->NextStep].End)(hc, urb);
if(r == ISR_CONTINUE) {
urb->NextStep++;
DoScript = TRUE;
} else if(r == ISR_SUSPEND) {
/* Wait until the next SOF, the device is not ready (NAK)
* The toggle bit stays with the packet.
*/
goto sus; // ****DON'T FORGET ACK INTR****
} else if(r != ISR_REPEAT) {
urb->Flags |= URB_FLAG_COMPLETE;
/* If there was an error the packet *is* complete
*/
if (r != ISR_DONE)
urb->Flags |= URB_FLAG_ERROR;
hc->CurURB = NULL;
sm_v(hc->sm);
goto ret;
} else {
DoScript = TRUE;
}
}
}
// USB设备插入或拔出中断
if(st & SL_INTEN_Insert) {
hc->InsRmvInts++;
hc->reset = TRUE;
hc->PrevURB = NULL;
if(smSL811 == 0)
goto ret;
// 唤醒USB任务
sm_v(smSL811);
// 撤销当前USB请求
if(hc->CurURB != NULL) {
hc->CurURB->Flags |= URB_FLAG_ERROR;
hc->CurURB = NULL;
sm_v(hc->sm);
DoScript = FALSE;
goto ret;
}
}
// SOF被关闭,功能未用
if(st & SL_INTEN_SOF) {
hc->SofInts++;
hc_write(hc, SL_INTEN, INTS);
if(!DoScript) {
//
// SL_INTEN_SOF set always
//
urb = hc->PrevURB;
if(urb != NULL) {
hc->PrevURB = NULL;
hc->CurURB = urb;
DoScript = TRUE;
}
}
}
//执行脚本
if (DoScript)
{
/* Execute the start action. It might tell us that there is not enough
* time left in the current frame, or that all is fine (ISR_CONTINUE).
*/
r = (*AllScripts[urb->NextStep].Start)(hc, urb);
if (r != ISR_CONTINUE) {
sus: hc->SusCnt++;
hc->PrevURB = urb;
hc->CurURB = NULL;
hc_write(hc, SL_INTEN, INTS | SL_INTEN_SOF);
}
}
ret:
/* Ack the interrrupt
*/
hc_write(hc, SL_ISTATUS, 0xFF);
rI_ISPC = BIT_SL811;
ENABLE;
}
////////////////////////////////////////////////////////
// 启动USB请求
//
// hc: 主控制器
// urb: USB请求
//
int
SL_Start(HC *hc, URB *urb) {
PSW
//DBG1("NextStep = %u\n", urb->NextStep);
ASSERT(urb->NextStep <= 9);
DISABLE;
// 启动第一个阶段。。。
//
sm_init(hc->sm);
hc->CurURB = urb;
(*AllScripts[urb->NextStep].Start)(hc, urb);
ENABLE;
// 等待USB请求结束
sm_p(hc->sm, FOREVER);
if(urb->Flags & URB_FLAG_ERROR)
return ISR_ERROR;
return ISR_DONE;
}
//
// 获取设备的设备描述符
//
int
GetDevDesc(MASS_STOR *ms) {
HC *hc = ms->hc;
int r;
URB urb;
struct usb_ctrlrequest req;
//DBG("GET_DEVICE_DESCRIPTOR...\n");
req.bRequestType = USB_DIR_IN;
req.bRequest = USB_REQ_GET_DESCRIPTOR;
req.wValue = USB_DT_DEVICE << 8;
req.wIndex = 0;
req.wLength = USB_DT_DEVICE_SIZE;
urb.Ep = &ms->hc->ep0;
urb.Flags = URB_FLAG_IN | URB_FLAG_CONTROL;
urb.Data = (UCHAR *)&hc->dev;
urb.ExpectedDataLength = sizeof(hc->dev);
urb.ActualDataLength = 0;
urb.SetupLength = 8;
urb.SetupData = (void *)&req;
urb.FinalStatus = 0;
urb.DeviceAddress = ms->DeviceAddress;
urb.NextStep = ControlReadScript;
r = SL_Start(hc, &urb);
hc->ep0.Payload = hc->dev.bMaxPacketSize0;
if(r != ISR_DONE)
return FALSE;
return TRUE;
}
//
// 设置USB设备地址
//
int
SetAddress(MASS_STOR *ms) {
int r;
URB urb;
struct usb_ctrlrequest req;
// SET_ADDRESS
req.bRequestType = USB_DIR_OUT;
req.bRequest = USB_REQ_SET_ADDRESS;
req.wValue = USB_ADDR;
req.wIndex = 0;
req.wLength = 0;
urb.Ep = &ms->hc->ep0;
urb.Flags = URB_FLAG_OUT | URB_FLAG_CONTROL;
urb.Data = NULL;
urb.ExpectedDataLength = 0;
urb.ActualDataLength = 0;
urb.SetupLength = 8;
urb.SetupData = (void *)&req;
urb.FinalStatus = 0;
urb.DeviceAddress = ms->DeviceAddress;
urb.NextStep = NoDataControlScript;
r = SL_Start(ms->hc, &urb);
if(r != ISR_DONE)
return FALSE;
return TRUE;
}
//
// 检测USB海量存储设备
//
int
UsbMassDetect(MASS_STOR *ms) {
HC *hc = ms->hc;
int r;
URB urb;
UCHAR in, out;
struct usb_ctrlrequest req;
UCHAR buf[128];
// 获取配置
// GET_CONFIGURATION *HEADER*
//DBG("GET_CONFIGURATION *HEADER*...\n");
req.bRequestType = USB_DIR_IN;
req.bRequest = USB_REQ_GET_DESCRIPTOR;
req.wValue = __le16(USB_DT_CONFIG << 8);
req.wLength = __le16(USB_DT_CONFIG_SIZE);
urb.Ep = &ms->hc->ep0;
urb.Flags = URB_FLAG_IN | URB_FLAG_CONTROL;
urb.Data = (void *)hc->conf;
urb.ExpectedDataLength = USB_DT_CONFIG_SIZE;
urb.ActualDataLength = 0;
urb.SetupLength = 8;
urb.SetupData = (void *)&req;
urb.FinalStatus = 0;
urb.DeviceAddress = ms->DeviceAddress;
urb.NextStep = ControlReadScript;
r = SL_Start(hc, &urb);
if(r != ISR_DONE)
return FALSE;
//
// 获取配置、接口、端点描述
//
////GET_CONFIGURATION *HEADER + INTERFACE + ENDPOINTS*
//DBG("GET_CONFIGURATION *HEADER + INTERFACE + ENDPOINTS*...\n");
req.bRequestType = USB_DIR_IN;
req.bRequest = USB_REQ_GET_DESCRIPTOR;
req.wValue = __le16(USB_DT_CONFIG << 8);
req.wLength = __le16(hc->conf[0].wTotalLength);
urb.Flags = URB_FLAG_IN | URB_FLAG_CONTROL;
urb.Data = buf;
urb.ExpectedDataLength = __le16(hc->conf[0].wTotalLength);
urb.ActualDataLength = 0;
urb.SetupLength = 8;
urb.SetupData = (void *)&req;
urb.FinalStatus = 0;
urb.DeviceAddress = ms->DeviceAddress;
urb.NextStep = ControlReadScript;
r = SL_Start(hc, &urb);
if(r != ISR_DONE)
return FALSE;
// copy interface descriptors
Memcpy((void *)hc->intf,
buf + USB_DT_CONFIG_SIZE,
1 * USB_DT_INTERFACE_SIZE);
// 复制端点描述符
for(r = 0; r < hc->intf[0].bNumEndpoints; r++)
Memcpy((void *)&hc->ep[r],
buf + USB_DT_CONFIG_SIZE + USB_DT_INTERFACE_SIZE +
r * USB_DT_ENDPOINT_SIZE,
USB_DT_ENDPOINT_SIZE);
// 获取设备输入、输出端点地址
if(hc->ep[0].bEndpointAddress & 0x80) {
in = 0;
out = 1;
}
else {
out = 0;
in = 1;
}
ms->In.Payload = hc->ep[in].wMaxPacketSize;
ms->In.Endpoint = hc->ep[in].bEndpointAddress & 0xF;
ms->Out.Payload = hc->ep[out].wMaxPacketSize;
ms->Out.Endpoint = hc->ep[out].bEndpointAddress & 0xF;
ms->In.Toggle = 0;
ms->Out.Toggle = 0;
//
// 设置配置
//
// SET_CONFIGURATION
//DBG("SET_CONFIGURATION...\n");
req.bRequestType = USB_DIR_OUT;
req.bRequest = USB_REQ_SET_CONFIGURATION;
req.wValue = 1;
req.wIndex = 0;
req.wLength = 0;
urb.Flags = URB_FLAG_OUT | URB_FLAG_CONTROL;
urb.Data = NULL;
urb.ExpectedDataLength = 0;
urb.ActualDataLength = 0;
urb.SetupLength = 8;
urb.SetupData = (void *)&req;
urb.FinalStatus = 0;
urb.DeviceAddress = ms->DeviceAddress;
urb.NextStep = NoDataControlScript;
r = SL_Start(hc, &urb);
if(r != ISR_DONE)
return FALSE;
hc->devfound = TRUE;
return TRUE;
}
//
// 批量输入
//
// ms: 海量存储设备
// buf:数据指针
// len:数据长度
//
static int
BulkIn(MASS_STOR *ms, UCHAR *buf, UINT len) {
int r;
URB urb;
urb.Ep = &ms->In;
urb.Flags = URB_FLAG_IN;
urb.Data = buf;
urb.ExpectedDataLength = len;
urb.ActualDataLength = 0;
urb.FinalStatus = 0;
urb.DeviceAddress = ms->DeviceAddress;
urb.NextStep = ReadScript;
r = SL_Start(ms->hc, &urb);
if(r != ISR_DONE)
return FALSE;
return TRUE;
}
//
// 批量输出
//
// ms: 海量存储设备
// buf:数据指针
// len:数据长度
//
static int
BulkOut(MASS_STOR *ms, UCHAR *buf, UINT len) {
int r;
URB urb;
urb.Ep = &ms->Out;
urb.Flags = URB_FLAG_OUT;
urb.Data = buf;
urb.ExpectedDataLength = len;
urb.ActualDataLength = 0;
urb.FinalStatus = 0;
urb.DeviceAddress = ms->DeviceAddress;
urb.NextStep = WriteScript;
r = SL_Start(ms->hc, &urb);
if(r != ISR_DONE)
return FALSE;
return TRUE;
}
//
// 质询设备
//
static int
Inquiry(MASS_STOR *ms) {
struct us_cbw cbw;
struct us_csw csw;
UCHAR buf[36];
//DBG("INQUIRY...\n");
// 组"SCSI质询"命令包
cbw.dSignature = CBW_SIGNATURE;
cbw.dTag = 0x60a624de;
cbw.dXferLength = __le16(36);
cbw.bFlags = 0x80;
cbw.bLUN = 0;
cbw.bCBDLength = 6;
cbw.aCmd[0] = 0x12;
cbw.aCmd[1] = 0;
cbw.aCmd[2] = 0;
cbw.aCmd[3] = 0;
cbw.aCmd[4] = 36;
cbw.aCmd[5] = 0;
////////////////////////////////
// 下发"SCSI质询"命令包
if(BulkOut(ms, (UCHAR *)&cbw, sizeof(cbw)) != TRUE)
return FALSE;
// 读出质询结果
if(BulkIn(ms, buf, 36) != TRUE)
return FALSE;
// 读出命令操作状态
if(BulkIn(ms, (UCHAR *)&csw, sizeof(csw)) != TRUE)
return FALSE;
if(csw.bStatus != CSW_STATUS_OK) {
return FALSE;
}
return TRUE;
}
// 从指定地址取一个小端序列长字
__inline static ULONG
makelong(UCHAR *p) {
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}
// 取2的近似对数
UINT
mylog2(ULONG x) {
UINT i;
i = 0;
while((1 << i) < x)
i++;
return i;
}
//
// 获取设备参数
//
// ms: 海量存储设备
//
static int
ReadCapacity(MASS_STOR *ms) {
struct us_cbw cbw;
struct us_csw csw;
UCHAR buf[16];
//DBG("ReadCapacity...\n");
// 组"SCSI读参数"命令包
cbw.dSignature = CBW_SIGNATURE;
cbw.dTag = 0x60a624de;
cbw.dXferLength = 8;
cbw.bFlags = 0x80;
cbw.bLUN = 0;
cbw.bCBDLength = 10;
/////////////////////////////////
cbw.aCmd[0] = 0x25; // operation code
cbw.aCmd[9] = 0; // Control = 00h
////////////////////////////////
// 下发"SCSI读参数"命令包
if(BulkOut(ms, (UCHAR *)&cbw, sizeof(cbw)) != TRUE)
return FALSE;
// 读出参数
if(BulkIn(ms, buf, 8) != TRUE)
return FALSE;
// 读出命令操作状态
if(BulkIn(ms, (UCHAR *)&csw, sizeof(csw)) != TRUE)
return FALSE;
if(csw.bStatus != CSW_STATUS_OK) {
return FALSE;
}
// U盘块数
ms->BlockNumber = makelong(buf) + 1;
// 块大小,一般为512
ms->BlockSize = makelong(buf + 4);
if(ms->BlockSize > 1024)
DBG("*******注意********\nUSB盘块大小 > 1K字节!\n");
//
// BlockSize = 1 << BlockSizeShift
//
ms->BlockSizeShift = mylog2(ms->BlockSize);
// ms->DiskSize = (unsigned long long)ms->BlockNumber
// * (unsigned long long)ms->BlockSize;
DBG1("%u Bytes/Block\n", ms->BlockSize);
// DBG3("USB盘 %luMB, %lu 块, %lu 字节每块\n",
// (ULONG)((ms->DiskSize + 1024*1024-1)/1024/1024), ms->BlockNumber, ms->BlockSize);
return TRUE;
}
//
// 写海量存储设备扇区
//
// ms: 海量存储设备
// lba:扇区号
// buf:数据指针
//
int
__usbWriteBlock(MASS_STOR *ms, ULONG lba, void *buf) {
struct us_cbw cbw;
struct us_csw csw;
//DBG2("usbWriteBlock(%u, %08X)...\n", lba, buf);
// 组"SCSI写扇区"命令包
cbw.dSignature = CBW_SIGNATURE;
cbw.dTag = 0x60a624de;
cbw.dXferLength = ms->BlockSize;
cbw.bFlags = 0x0;
cbw.bLUN = 0;
cbw.bCBDLength = 10;
/////////////////////////////////
cbw.aCmd[0] = 0x2a; // 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;
//tm_delay(5);
// 发送数据
if(BulkOut(ms, buf, ms->BlockSize) != TRUE)
return FALSE;
// 读出命令操作状态
if(BulkIn(ms, (UCHAR *)&csw, sizeof(csw)) != TRUE)
return FALSE;
if(csw.bStatus != CSW_STATUS_OK)
return FALSE;
return TRUE;
}
//
// 缓冲区定义
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -