筆記寫的比較雜亂,僅供自己以后復習參考。
命令層 塊命令和流命令等
協(xié)議層 xxoo
物理層
第二章 SCSI基礎
協(xié)議的重要性
總線空閑條件:SCSI總線上沒有活動
選擇階段 SCSI ID表示總線控制權優(yōu)先級
消息階段 協(xié)議使用消息來報告錯誤 命令狀態(tài)和其他信息 也可以使用消息發(fā)送控制信息
命令階段 啟動器發(fā)送一個帶有命令指令和參數數據的數據塊給目標器 如果目標器要報告命令塊格式或者參數錯誤 那么事務處理又機虐了消息階段
數據階段 是否產生數據階段取決于發(fā)送的命令 命令決定了數據傳輸的方向
狀態(tài)階段 標志著SCSI命令的完成
最后的事務處理的還是消息階段
啟動器 SCSI設備
第三章 SCSI階段 在一個簡單的SCSI事務處理中 啟動器為取得總線的控制權而進行仲裁 一旦獲得了對總線的控制權它就選擇一個目標器進行連接 目標器做出反應
SCSI設備可以分為啟動器(initiator)或目標器(target),例如SCSI主機適配器是啟動器,硬盤驅動器是目標器.一個S最小的可行配置是一個啟動器和一個目標器. 計算機通過主機適配器連接到SCSI總線上,主機適配器一般在主板上,外圍設備通過一個控制器連接到SCSI總線上,控制器一般在設備的電路板上.有時一個控制器也可以連接多個設備,叫做橋式連接. 啟動器把一個命令發(fā)送到目標器,目標器執(zhí)行命令并把結果通知給啟動器,例如格式化硬盤就只需發(fā)送FORMAT UNIT命令然后就可以將控制權完全交給驅動器,格式化完成后,啟動器僅僅得到命令執(zhí)行成功或失敗的信息.
總線狀態(tài) BSY SEL C/D I/O MSG ATN
第五章 SCSI命令 SCSI的命令和參數被封裝在稱為CDB命令描述塊的結構中 不同的命令組對應于不同的長度命令描述符
0號組CDB是6字節(jié) 1號組和2號組是10字節(jié)長 5號組的CDB占用12個字節(jié) 其他由廠商自定義
CDB的第一個字節(jié)描述命令的操作碼 高三位表示命令組 0-7 低5位表示命令碼
CDB的第二個字節(jié)的高三位表示一個LUN(邏輯單元號) 低五位可能是保留的 也可能是以后字段的一部分 取決于命令組
命令參數 LUN字段后就是命令參數字段 對于直接存取設備來說 它包含的是邏輯塊地址 對于傳輸數據的命令來說 包含的是傳輸長度 也可以包含和特定命令或者設備類型相關的值
控制字段 每個命令描述符的最后一個字段是控制字段
參數列表
多字節(jié)字段是按大端法來存儲的 和X86相反
▲Scsi Pass through requests go to the miniport as SRB_FUNCTION_EXECUTE_SCSI
/////////////////////////////////////// 硬盤驅動器模型
IDE接口前身——ST506
ATAPI使用IDE作為其物理接口 但命令使用的是SCSI命令 數據通過邏輯塊號來定位(LBA?) 格式化整個磁盤則是由某個命令直接觸發(fā)的
SCSI-2總線可以對8個設備進行編址 SCSI-3可以更多
設備的SCSI總線地址稱為SCSI ID 這些設備扮演了啟動器或者目標器的角色
啟動器和目標器 啟動器是一個在SCSI總線上觸發(fā)任務的設備 而目標器則是執(zhí)行該任務的設備
邏輯單元LUN
LUN的概念 LUN的全稱是Logical Unit Number,也就是邏輯單元號。我們知道SCSI總線上可掛接的設備數量是有限的,一般為6個或者15個,我們可以用Target ID(也有稱為SCSI ID的)來描述這些設備,設備只要一加入系統(tǒng),就有一個代號,我們在區(qū)別設備的時候,只要說幾號幾號就ok了。 而實際上我們需要用來描述的對象,是遠遠超過該數字的,于是我們引進了LUN的概念,也就是說LUN ID的作用就是擴充了Target ID。每個Target下都可以有多個LUN Device,我們通常簡稱LUN Device為LUN,這樣就可以說每個設備的描述就有原來的Target x變成Target x LUN y了,那么顯而易見的,我們描述設備的能力增強了。就好比,以前你給別人郵寄東西,寫地址的時候,可以寫: xx市人民大街54號 xxx(收) 但是自從高樓大廈越來越多,你不得不這么寫: xx市人民大街54號xx大廈518室 xxx (收) 所以我們可以總結一下,LUN就是我們?yōu)榱耸褂煤兔枋龈嘣O備及對象而引進的一個方法而已,一點也沒什么特別的地方。
這里提到一點,由于TARGET Id的數量是有限的 那么我們?yōu)榱吮硎靖嗟腟CSI設備,就引入了LUN的概念 把設備一維的標示改成二維的標示TargetId = X, LUN = Y
客戶機-服務器模型是實現SCSI系統(tǒng)很好的途徑 從這個角度來說,PC是客戶端 它自己的SCSI硬盤是服務器 PC向硬盤發(fā)送一個請求 硬盤執(zhí)行請求并把數據傳送回來
LBA->CHS
SCSI命令模型: SCSI命令可以看作是對遠程過程的調用: Service Response = Execute Command(Task Identifier, Command, Descriptor Block, [Task Attribute], [Data Output Buffer], [Data Input Buffer], [Command Buffer], [Command Length], [Autosense Request], [Sense Data], Status) SCSI命令由一個啟動器發(fā)送到目標器的LUN,LUN的設備服務器執(zhí)行命令,并返回一個狀態(tài).命令的輸入輸出方向是以啟動器為參照的.
★在SCSI命令中必須實現: 1.任務標識符:只有SCSI-3中有,由一套64位的數字組成,分成啟動器標識符,目標器標識符和LUN標識符.排序后的任務還有一個附加的標簽.
2.命令描述塊(CDC):包含完整的SCSI命令.
3.狀態(tài)字節(jié):命令結束后,狀態(tài)字節(jié)給出一個命令是否被正確執(zhí)行的信息,而且它還提供了一些關于命令結束的附加信息.
DISK.SYS-類驅動 SCSIPORT.SYS-端口驅動 ATAPI.SYS-微端口驅動
IOCTL_SCSI_GET_INQUIRY_DATA 獲取每個SCSI總線和相應的驅動器所控制的設備的信息
在這些miniport驅動上面的是稱為SCSIPORT的驅動 SCSIPORT驅動對于系統(tǒng)中的所有SCSI請求提供了唯一的入口點 ~~~~~~~~~~~~ 把系統(tǒng)特有的SCSI IO請求轉化成標準的SCSI 命令描述塊COMMAND DESCRIPTOR BLOCK 也就是傳說中的CDB ~~~~~~~~~~~ 并把這些請求發(fā)送給適當的MINIPORT驅動 由于其硬件細節(jié)被隱藏在了miniport驅動中,所以高層驅動可以調用 scsiport驅動來執(zhí)行所有SCSI IO操作 而不用管硬件接口
一個限制 如果某驅動對一個特殊設備發(fā)出請求 我們要做的是向該類驅動發(fā)送和SCSI PASS-THOUGH命令 ~~~~~~~~~~~~ 而不是發(fā)送給SCSIPORT ~~~~~~~~~~~~~~~~~~~~ 避免應用程序在某有通知類驅動的情況下發(fā)送命令 而且還可以允許類驅動保持對設備的控制權
這里難道是為了防止繞過類驅動直接向SCSIPORT發(fā)送SCSI命令? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SCSI_PASS_THROUGH 和SCSI_REQUEST_BLOCK這兩個結構很像啊~ The values of the DataIn member correspond to the SCSI_IOCTL_DATA_IN, SCSI_IOCTL_DATA_OUT, and SCSI_IOCTL_DATA_UNSPECIFIED
SCSI_PASS_THOUGH是可以讓RING3通過DEVICE_IO_CONTROL來直接發(fā)CDB SCSI_REQUEST_BLOCK是在驅動下 自己構造IRP包來發(fā)CDB
■如果是讀取ATA設備 那么我們就不用填PATHID TARGRT ID LUN? 是的 這三個參數填0就行
[WIN32 SCSI支持模型]
win32應用程序 WIN32 ↓ 文件系統(tǒng)驅動 FSD ↓ 磁盤類驅動(DISK.SYS) CD-ROM類驅動... ↓ SCSIPORT驅動(SCSIPORT.SYS) 端口驅動 ↓ ATAPI(EIDE) Miniport驅動(atapi.sys atapi ide miniport driver) 微端口驅動 ↓ 標準IDE接口
詳細的圖參考 SCSI程序員指南p134
----------------------------------------分割線---------------------------------
[走aspi路線]
win32應用程序 ↓ ASPI管理器 ↓ ASPI驅動 ↓ SCSIPORT驅動 剩下的同上圖
atapi直接就可以接收SCSI指令。。。DISK.SYS也是通過CLASSPNP把SCSI轉發(fā)到atapi的
scsi設備和scsi指令是兩回事,DISK。SYS通過CLASSPNP把SCSI命令發(fā)到你的設備,如你是atapi的就發(fā)往他,如你是scsi設備就發(fā)往SCSI端口驅動
CDB命令描述塊結構
操作碼 命令特定參數 控制字節(jié)
每個命令的第0字節(jié)就是操作碼 他定義了命令的類型和長度 高三位代表命令所屬的命令組 低五位表示命令本身 每個命令組都有一個命令長度 因為對命令的第一個字節(jié)也就是操作碼進行解析后 目標器就知道這個命令還剩下多少字節(jié)
對于不同類型的設備來說同樣的操作碼可以被解釋為不同的命令 盡管通常它們之間還是有一點相似之處的 例如操作碼0AH在磁盤和磁帶設備表示WRITE 寫命令 然后對于處理器設備 它代表SEND命令 而且命令的結構也可能是不同的。 因此,你不能僅僅從操作碼來推斷命令,必須知道這個命令是用在哪個設備上的
命令組 代表命令組的高三位可以有2^3=8個不同組合 所以可以代表8個命令組 除了保留組絕對不可以使用外 剩下的都可以使用
我們知道,Windows管理驅動設備棧,是使用的DeviceObject 中的AttachedDevice域,例如在我的虛擬機上,一個磁盤請求IRP發(fā)送到Disk.sys的磁盤設備后,會被接著轉發(fā)到總線上的Atapi.sys的端口設備,實際是存在這樣的關系:Atapi.sys的設備(例如\Deivce\Ide\IdeDevicePOTOLO-3)的AttachedDevice域 = Disk.sys的設備(例如\Device\Harddisk0\DR0) 。
\Device\HarddiskX\DRX ---------> \Deivce\Ide\IdeDevicePOTOLO-X
SENSE DATA 當一個SCSI設備(通常是一個LUN)發(fā)現它自己處于異常狀態(tài)時,它就拒絕執(zhí)行下面的命令 并返回一個CHECK CONDITION狀態(tài) 它在這種狀態(tài)下產生18個字節(jié)的數據 這個數據包括經過編碼的關于錯誤的信息 就被稱作 SENSE DATA typedef struct _SENSE_DATA { BYTE Valid; BYTE SegmentNumber; BYTE FileMark; BYTE Information[4]; BYTE AdditionalSenseLength; BYTE CommandSpecificInformation[4]; BYTE AdditionalSenseCode; BYTE AdditionalSenseCodeQualifier; BYTE FieldReplaceableUnitCode; BYTE SenseKeySpecific[3]; } SENSE_DATA, *PSENSE_DATA;
SRB(SCSI_REQUEST_BLOCK結構)
typedef struct _SCSI_REQUEST_BLOCK { USHORT Length; UCHAR Function; UCHAR SrbStatus; UCHAR ScsiStatus; UCHAR PathId; UCHAR TargetId; UCHAR Lun; UCHAR QueueTag; UCHAR QueueAction; UCHAR CdbLength; UCHAR SenseInfoBufferLength; ULONG SrbFlags; ULONG DataTransferLength; ULONG TimeOutValue; PVOID DataBuffer; PVOID SenseInfoBuffer; struct _SCSI_REQUEST_BLOCK *NextSrb; PVOID OriginalRequest; PVOID SrbExtension; union { ULONG InternalStatus; ULONG QueueSortKey; }; UCHAR Cdb[16]; } SCSI_REQUEST_BLOCK, *PSCSI_REQUEST_BLOCK;
我的猜測: 由于ATA設備不是SCSI設備 那么其中的PathId(總線ID),TargetId(目標器ID)和LUN都沒有意義,這樣向ATA發(fā)SRB的時候,這些區(qū)域填0就OK(不知正確與否)
參考資料: 《SCSI程序員指南》 《SCSI總線和IDE接口:協(xié)議、應用和編程》
|