不可部分完成的總線作業
若要使用SPB連線周邊裝置的特定硬體功能,SPB 控制器的用戶端 (也就是說,周邊驅動程式) 可能需要以不可部分完成的總線作業的形式,在裝置之間執行一連串數據傳輸。 傳輸順序是不可部分完成的,因為沒有其他用戶端可以在總線上的裝置上傳送數據,直到順序完成為止。
用戶端以不可部分完成的總線作業執行傳輸順序的一般方式,就是將 IOCTL_SPB_EXECUTE_SEQUENCE 要求傳送至目標裝置。 在此要求中,用戶端會將順序指定為簡單讀取和寫入傳輸的清單。 清單可以是任意長度。 讀取和寫入會依照列出的順序執行,而每個讀取或寫入都可以傳輸任意數目的位元組。 大部分SPB控制器都支援 IOCTL_SPB_EXECUTE_SEQUENCE 要求。
SPB 控制器鎖定
執行不可部分完成傳輸序列的較不常見方式是使用SPB控制器鎖定。 用戶端會傳送 IOCTL_SPB_LOCK_CONTROLLER 要求來取得鎖定,以及 釋放鎖定的IOCTL_SPB_UNLOCK_CONTROLLER 要求。 當用戶端持有控制器鎖定時,任何一連串的簡單讀取和寫入 (IRP_MJ_READ和IRP_MJ_WRITE) 要求用戶端傳送到裝置時,都會在總線上以不可部分完成的作業執行。
大部分的SPB連線周邊裝置不需要控制器鎖定,而且大部分的SPB控制器驅動程式不會實作這些鎖定的支援。 不過,少數用戶端可能需要使用控制器鎖定來存取具有異常功能的裝置。
例如,裝置可能會實作只能透過總線上不可部分完成的讀寫作業來存取的裝置函式。 若要執行這類作業,用戶端會依顯示的順序傳送下列四個 I/O 要求 () :
- IOCTL_SPB_LOCK_CONTROLLER – 取得控制器鎖定。
- IRP_MJ_READ – 從目標裝置讀取數據區塊。
- IRP_MJ_WRITE – 將修改過的數據寫回裝置。
- IOCTL_SPB_UNLOCK_CONTROLLER – 釋放控制器鎖定。
在上述清單中的讀取作業之後,用戶端會解譯從裝置讀取的數據,並在將數據寫回裝置之前修改數據。
不過,少數SPB連線的裝置具有需要控制器鎖定的功能。 對於需要不可部分完成總線作業的大部分裝置, IOCTL_SPB_EXECUTE_SEQUENCE 要求就已足夠。
請勿混淆 SPB 控制器鎖定與 SPB 連線鎖定。 在兩個用戶端共用相同SPB連線周邊裝置存取權的非典型案例中,任一用戶端都可以使用聯機鎖定暫時取得裝置的獨佔存取權。 如需詳細資訊,請參閱 SPB連線鎖定。
硬體總線訊號
若要處理 IOCTL_SPB_EXECUTE_SEQUENCE 要求,SPB 控制器驅動程式會將控制器硬體設定為在傳輸順序期間於總線上產生適當的訊號。 附加至總線的周邊裝置可能依賴這些訊號來偵測何時進行不可部分完成的總線作業。 SPB 控制器用來執行傳輸順序作為不可部分完成總線作業的硬體訊號集,取決於總線類型。
針對 I2C 總線,控制器會藉由在總線上傳輸開始位來啟動序列,並藉由傳輸停止位結束序列。 在開始和停止位之間,往返裝置的數據傳輸順序會以單一不可部分完成的總線作業的形式執行。 除了序列中的最後一個傳輸之外,每個傳輸後面都會接著 I2C 重新啟動作業, (重複的啟動位,且前面沒有停止位) 。
針對 SPI 總線,控制器會藉由判斷晶片選取線路至目標裝置來啟動序列,並藉由取消組譯晶片選取線路來結束序列。 藉由讓晶元選取行在透過總線的一連串數據傳輸期間持續判斷提示,傳輸會以單一不可部分完成的總線作業的形式執行。
I2C 裝置範例
I2C 總線上的一般周邊裝置可能會實作數個內部裝置功能。 若要存取其中一些函式,用戶端可能會使用 IOCTL_SPB_EXECUTE_SEQUENCE 要求。
例如,I2C 周邊裝置可能包含下列兩個內部緩存器:
- 用戶端寫入裝置函式內部位址以存取的 函式位址緩存器 。
- 數據快取器,用戶端會從中讀取數據,或將數據寫入指定的函式位址。
本範例中的 I2C 周邊裝置會解譯開始位之後寫入裝置的第一個字節,成為要載入函式位址緩存器中的函式位址。 序列結束之前傳送至裝置或從裝置傳送的任何其他位元組, (,如停止位) 所指示,裝置會視為透過數據緩存器傳輸的數據。
若要執行寫入作業,用戶端會傳送寫入 (IRP_MJ_WRITE) 要求,其中寫入緩衝區中的第一個字節是函式位址,而緩衝區中的其餘位元組則是要寫入至函式地址的數據。
從裝置讀取更為複雜。 假設本範例中的 I2C 裝置支援「快速讀取」功能,當總線上偵測到停止位時,會自動將函式位址緩存器重設為預設值 0。 使用這項功能,用戶端可以從函式位址 0 讀取數據,而不需要先寫入函式位址緩存器。 這項功能可以改善裝置讀取作業的速度,特別是大部分的讀取都是來自函式位址 0 且相對短時。
不過,若要從非零函式位址讀取數據區塊,用戶端仍必須將位元組寫入函式位址緩存器,再從數據緩存器讀取數據區塊。 用戶端必須執行這些寫入和讀取傳輸作為不可部分完成的總線作業,以防止總線控制器在寫入函式位址緩存器之後以及從數據緩存器讀取之前傳輸停止位。 否則,停止位會導致數據從函式位址 0 讀取,而不是從非零函式位址讀取。
下列清單描述用戶端在此範例中傳送至 I2C 裝置的 I/O 要求系列,以對位於裝置中非零函式地址的數據執行讀寫作業:
- IOCTL_SPB_EXECUTE_SEQUENCE - 執行 I/O 傳輸順序,以從裝置讀取數據。 此序列中的第一個傳輸是位元組寫入函式位址快取器。 序列中的第二個傳輸是從選取的函式位址讀取一些位元組。 這兩個傳輸會在總線上以不可部分完成的方式執行。
- IRP_MJ_WRITE - 將數據寫入裝置。 這個要求的寫入緩衝區中第一個字節是寫入函式位址緩存器的值。 緩衝區中的其餘位元組是要寫入所選函式地址的數據。
可能會改用其他要求模式來執行此讀取-修改-寫入作業。 例如,步驟 2 中的 IRP_MJ_WRITE 要求可以取代為指定兩個數據傳輸的 IOCTL_SPB_EXECUTE_SEQUENCE 要求,這兩者都是寫入。 序列中的第一個傳輸會將位元組載入函式位址緩存器。 第二個傳輸會將數據位元組寫入選取的函式位址。 此要求與步驟 2 中的 IRP_MJ_WRITE 要求不同,不需要用戶端在相同的寫入緩衝區中合併函式位址位元組和數據位元組。
若要在此裝置中對函式位址 0 執行讀取-修改-寫入,先前清單中步驟 1 中的 IOCTL_SPB_EXECUTE_SEQUENCE 要求可以取代為簡單的讀取 (IRP_MJ_READ) 要求。