本文展示基於 OHCI 協議的 USB 主機控制器中,針對 UFI(Uniform Floppy Interface)協議的寫扇區命令實現代碼。該功能用於向 USB 大容量存儲設備(如 U 盤)寫入單個 512 字節扇區數據。
/**
* 寫磁盤扇區命令
* @param sect 物理扇區號 (LBA)
* @param *buf 數據緩衝區指針
* @return 0 - 成功
*/
short ufiWriteSect(DWORD sect, BYTE *buf)
{
WRITE_10 *write10;
CBW *cbw;
// 設置 Bulk-Only 協議參數 (CBW)
cbw = &ufiCmdRunning.cbw;
cbw->dCBW_Signature = CBW_SIGNATURE; // 固定簽名 0x43425355
cbw->dCBW_Tag = 0x60a624de; // 命令標籤,用於匹配 CSW
cbw->dCBW_DataXferLen = 512; // 傳輸長度:單扇區 512 字節
cbw->bCBW_Flag = 0x00; // 方向標誌:0 = Data-Out (主機到設備)
cbw->bCBW_LUN = 0; // 邏輯單元號
cbw->bCBW_CDBLen = 16; // CDB 長度
// 設置 UFI WRITE_10 命令參數 (CDB)
write10 = &(cbw->cdbRBC.ufiWrite10);
write10->OperationCode = 0x2A; // WRITE_10 操作碼
write10->LBA_0 = byteInInt(sect, 0); // LBA 位元組 0 (最高位)
write10->LBA_1 = byteInInt(sect, 1);
write10->LBA_2 = byteInInt(sect, 2);
write10->LBA_3 = byteInInt(sect, 3); // LBA 位元組 3 (最低位)
write10->XferLen_0 = 0x01; // 傳輸扇區數高位元組
write10->XferLen_1 = 0x00; // 傳輸扇區數低位元組 (共 1 個扇區)
// 設置狀態掃描函數所需參數
ufiCmdRunning.funUfiCmd = bulkWrite; // 批量寫入處理函數
ufiCmdRunning.pBuf = buf; // 數據緩衝區
ufiCmdRunning.state = UFI_STATE_BEGIN; // 初始狀態
// 通過 Bulk 端點發送寫命令
bulkWrite((unsigned char *)&ufiCmdRunning.cbw,
buf,
(unsigned char *)&ufiCmdRunning.csw);
return 0;
}
Bulk-Only 協議規定的命令塊包裝結構,包含簽名、標籤、傳輸長度、方向標誌、LUN、CDB 長度及 CDB 本體。
SCSI WRITE_10 命令結構,OperationCode 0x2A 表示寫入 10 位元組 CDB 格式。LBA 為 4 位元組大端序扇區地址,傳輸長度為 2 位元組扇區計數。
bulkWrite、數據緩衝區、初始狀態。bulkWrite 發送 CBW、數據階段、接收 CSW 的完整 Bulk 事務。byteInInt 為輔助宏/函數,用於從 32 位整數提取指定位元組(大端序)。bulkWrite 異步處理,包含 CBW 傳輸、數據傳輸、CSW 接收三個階段,中斷處理程序負責狀態機推進。bulkWrite 及中斷處理中實現,此處略去。