さてそのUASPの目的であるが、基本的には転送オーバーヘッドの軽減である。USB 2.0までで使われてきたMass Storage Class Deviceでは、BOT(Bulk Only Transport)が利用されてきた。このプロトコルは非常に簡単で、基本的にはSingle Threadedである。つまりHostがTransferを開始し、これを受け取ったDeviceがTransferを終了する。そして、そのTransfer終了の状態通知がHost側に伝わるまで、次のTransferは開始されない。
これは単純明快なプロトコルであるが、それゆえオーバーヘッドも大きい(概ね20%)。USB 2.0の場合、最大で480Mbps(=60MB/sec)の理論上の転送速度が得られるが、理論値に近い状態で駆動しても、12MB/sec分はプロトコルオーバーヘッドになり、実質的な転送速度は50MB/secに及ばない計算だ。
これがUSB 3.0だとさらに状況が悪い。USB 3.0では帯域も5Gbps(500MB/sec)に広がるが、BOTのオーバーヘッドにより、例えば2.4GHz駆動のCore 2 Duo(*1)の場合でも実質的には250MB/secどまりとなり、しかも12%ほどのCPU負荷になると見込まれている。
(*1) UASP Revision 1.0によれば"2.4GHz Core Duo"になっているが、この速度で動くCore Duoは無い(最高でもT2700の2.33GHz)ので、これは単にCore 2 Duoの間違いだと思われる。
これを解決するのがUASPである。UASPはUSB 2.0と3.0の両方で利用できるが、UASPはBOTへの後方互換性を維持しており、さらにUSB 3.0での利用時は全二重動作を行う(BOTはUSB 1.1/2.0を前提に半二重動作となっている)ことで、USB 3.0における実質的な転送速度を400MB/sec近くまで引き上げられる、としている。
これを実現するにあたり、UASPはSCSIのソフトウェアスタックを利用する形でインプリメントを行った。このため、OSからみるとUASPドライバはあたかも(USBを利用した)SCSI Host Adapterとして見える形になる。
では具体的にどんなシーケンスになるのか、をちょっと見てみたい。Photo01は、UASPを使ってUSB 2.0 Deviceに対してNon-Data Transferを行った場合のシーケンスである。まず上位アプリケーション(WindowsならDisk Managerあたりであろう)から、UAS Driverに対してリクエストが来る。これを受けたら、まずStatus Pipe経由でInput Transfer Requestを発行、次いでCommand Pipe経由でCommand及びCIU(Command Information Unit)のOutput Transfer Request(OTr)を発行する。Input Transfer RequestはそのままEHCI Driver経由でEHCI Controllerに渡され、これによりStatus Pipe経由でDeviceにInput Transactionが(IN)発行される。最初のINに対する返事はNAKで有るべきであり、これが返ってくれば正常である。一方2つ目のINの返事としては、Sense Information Unit(SIU)が返ってくる。これがOTrとしてDeviceに送ったCIUに対する返答である。こちらはInput Transfer request completion(ITc)としてECHI ControllerからEHCI Driverを経てUAS Driverまで送られ、Statusとして上位に返すものとなる。
ただその前に、OTrをEHCI ControllerからOutput Transaction(OUT)及びData Transaction(DATA)としてそれぞれDeviceに送り出す必要がある。利用するのはどちらもCommand Pipeであるが、OUTにしてもDATAにしても、直接的にDeviceからControllerに返ってくるのは単にACK(なりNACK)のみなので、きちんとDeviceからStatusを取るためには別にINを発行しないといけない訳だ。またDATAに対するACKがOutput Transfer request completion(OTc)としてUAS Driverまで到達するが、これは単に「Deviceが問い合わせを受け取った」だけでしかないので、UAS Driverが受け取ってそのまま破棄されてしまう。
同じ事をUSB 3.0 Deviceにするとどうなるのか? がPhoto02である。シーケンスそのものは殆ど変わらない。UAS DriverがITrとOTrを発行し、その結果としてxHCI ControllerがまずInput Acknowledgment(IN ACK)、次いでOutput Data Packet(DP)を発行、その後にもう一度IN ACKを発行、その返答のDPにSIUが含まれるので、それが最終的にUAS DriverにITcの形でSIUが渡され、それがStatusとして上位アプリケーションに返される形だ。
ただ実は細かいところが2カ所ほどちょっと異なっている。先ず、USB 2.0ではDeviceに対するリクエストをOUTとDATAの2回に分けて送る必要があるが、USB 3.0では1個のDPでこれをまとめて行うこと出来る。2つ目は、SIUを受け取るタイミングだ。USB 2.0の場合、(図には描かれていないが)DeviceからACKがEHCI Controllerに返ってきた後、EHCI Controllerは定期的にINを発行する。で、Device側が準備ができるまでは(1回目のINと同じように)ひたすらNAKが返ってくるわけだ。要するにポーリング動作がここで行われている形である。対してUSB 3.0の場合、ACKに続いてDeviceからERDYが返ってくるまでxHCI ControllerはDeviceを放置している。で、ERDYが返ってきたら直ちにIN ACKを発行、今度はSIUが入ったDPを受け取る事になる。つまりポーリング動作をしないで済むわけだ。
勿論、余程の事が無い限りDeviceがコマンドを受け取ったらすぐに返答を返すはずで、これによるオーバーヘッドの差は微々たるものかもしれないが、あくまでもプロトコル上でもこうしたオーバーヘッド軽減策が講じられていることが判る。
(続く)