共用方式為


原子匯流排作業

若要使用某些透過 SPB 連線的周邊裝置的硬體功能,SPB 控制器的客戶端(也就是周邊驅動程式)可能需要以不可中斷的匯流排操作形式,完成向裝置進行的一連串資料傳輸。 傳輸順序是原子性的,因為在序列完成之前,沒有其他客戶端可以將資料傳送到匯流排上的裝置或從匯流排上的裝置接收資料。

用戶端以原子性匯流排作業的方式執行傳輸順序的一般方式是將 IOCTL_SPB_EXECUTE_SEQUENCE 要求傳送至目標裝置。 在此要求中,用戶端會將序列指定為簡單讀取和寫入傳輸的清單。 清單可以是任意長度。 讀取和寫入會依列出的順序執行,而且每次讀取或寫入都可以傳輸任意數目的位元組。 大多數 SPB 控制器都支援 IOCTL_SPB_EXECUTE_SEQUENCE 要求。

SPB 控制器鎖定

執行原子傳輸序列的較不常見的方式是使用 SPB 控制器鎖定。 用戶端會傳送 IOCTL_SPB_LOCK_CONTROLLER 要求以取得鎖定,並傳送 IOCTL_SPB_UNLOCK_CONTROLLER 要求以釋放鎖定。 當用戶端持有控制器鎖定時,用戶端傳送至裝置的任何簡單讀取和寫入(IRP_MJ_READIRP_MJ_WRITE)要求序列都會作為匯流排上的原子操作執行。

大部分的 SPB 連線周邊裝置不需要控制器鎖定,而且大部分的 SPB 控制器驅動程式都不會實作這些鎖定的支援。 不過,一些用戶端可能需要使用控制器鎖定來存取具有異常功能的裝置。

例如,裝置可能會實作一些函式,這些函式只能透過在匯流排上具有原子性的讀取-修改-寫入操作來存取。 若要執行這類作業,用戶端會傳送下列四個 I/O 要求 (依顯示的順序):

  1. IOCTL_SPB_LOCK_CONTROLLER – 獲取控制器鎖。
  2. IRP_MJ_READ — 從目標裝置讀取資料區塊。
  3. IRP_MJ_WRITE – 將修改後的資料寫回裝置。
  4. 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 要求,以對位於裝置中非零函式位址的資料執行讀取-修改-寫入作業:

  1. IOCTL_SPB_EXECUTE_SEQUENCE - 執行 I/O 傳輸序列以從裝置讀取資料。 此序列中的第一個傳輸是將位元組寫入函數位址暫存器。 序列中的第二個傳輸是從所選函數位址讀取一定數量的位元組。 這兩種傳輸在匯流排上以原子方式執行。
  2. IRP_MJ_WRITE - 將資料寫入裝置。 此請求的寫入緩衝區中的第一個位元組是要寫入函數位址暫存器的值。 緩衝區中的剩餘位元組是要寫入指定函數位址的資料。

可以改用其他要求型樣來執行此讀取-修改-寫入作業。 例如,步驟 2 中的 IRP_MJ_WRITE 要求可以被 IOCTL_SPB_EXECUTE_SEQUENCE 要求取代,此要求指定了兩個資料傳輸操作,這兩個都是寫入操作。 序列中的第一次傳輸將一個字節加載到函數地址暫存器中。 第二次傳輸將資料字節寫入所選功能位址。 此要求與步驟 2 中的 IRP_MJ_WRITE 要求不同,不需要用戶端將函式位址位元組和資料位元組結合在相同的寫入緩衝區中。

若要在此裝置中的函數位址 0 上執行讀取-修改-寫入,可以將上一個清單步驟 1 中的 IOCTL_SPB_EXECUTE_SEQUENCE 請求替換為簡單的讀取 (IRP_MJ_READ) 請求。