从第一份工作,主要从事USB dongle PCTV AVStream/BDA Windows驱动的开发,到现在从事USB3.0 device/xHCI host IP的开发,我的工作内容中,始终离不开一个词:通用串行接口--USB。
所以,我的第一篇技术博文,也从USB开始谈起。
USB3.0 IP的开发包括两大部分.
0: kd> !analyze -v DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1) Arguments: Arg1: ac6e2f68, memory referenced Arg2: 00000002, IRQL Arg3: 00000000, value 0 = read operation, 1 = write operation Arg4: 8ddcbcbf, address which referenced memory Debugging Details: ------------------ READ_ADDRESS: ac6e2f68 Special pool CURRENT_IRQL: 2 FAULTING_IP: USBXHCI!TransferRing_TransferEventHandler+403 8ddcbcbf 8b00 mov eax,dword ptr [eax]
TRAP_FRAME: 810f38c4 -- (.trap 0xffffffff810f38c4) ErrCode = 00000000 eax=ac6e2f68 ebx=00000000 ecx=0f048005 edx=ac6e2f68 esi=00000000 edi=ad625d10 eip=8ddcbcbf esp=810f3938 ebp=810f3990 iopl=0 nv up ei pl zr na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246 USBXHCI!TransferRing_TransferEventHandler+0x403: 8ddcbcbf 8b00 mov eax,dword ptr [eax] ds:0023:ac6e2f68=???????? Resetting default scope STACK_TEXT: 810f38a4 81f9dd9b 0000000a ac6e2f68 00000002 nt!KiBugCheck2 810f38a4 8ddcbcbf 0000000a ac6e2f68 00000002 nt!KiTrap0E+0x1b3 810f3990 8ddc303e ad625d10 00000000 8b8c6ee8 USBXHCI!TransferRing_TransferEventHandler+0x403 810f39fc 8589b49a 4e5871a0 71563188 00000000 USBXHCI!Interrupter_WdfEvtInterruptDpc+0x31e ---------
从!analyze -v的输出,可以看出:
0: kd> !pool ac6e2f68 Pool page ac6e2f68 region is Special pool Address ac6e2000 does not belong to any pool ac6e2000: Unable to get contents of special pool block
0: kd> !pte ac6e2f68 VA ac6e2f68 PDE at C0602B18 PTE at C0563710 contains 000000002F2EA863 contains 0008204600000000 pfn 2f2ea ---DA--KWEV not valid PageFile: 0 Offset: 82046 Protect: 0
0: kd> !usb3kd.xhci_eventring 0x8ea9cff0
Dumping dt _PRIMARY_INTERRUPTER_DATA b8668fc0
-----------------------------------------------------
[0] Interrupter : dt _INTERRUPTER_DATA 0xb1a78f68 !rcdrlogdump USBXHCI -a 0x8e126008
------------------------------------------------------------------------------------------------------
DequeueSegment: 3 DequeueIndex: 210 TotalEventRingSegments: 4 TRBsPerSegment: 256
CurrentBufferData : VA 0xad625000 LA 0xd7daf000 Size 4096
EventRingTableBufferData : VA 0xad631000 LA 0xd7dac000 Size 512
[0] VA 0xad61c000 LA 0xd7dbe000 Size 4096
[1] VA 0xad61f000 LA 0xd7dbb000 Size 4096
[2] VA 0xad622000 LA 0xd7db2000 Size 4096
[3] VA 0xad625000 LA 0xd7daf000 Size 4096
Event Ring TRBs:
[200] TRANSFER_EVENT 0xad625c80 CycleBit 1 SlotId 24 EndpointID 3 ED 1 Data 0x007f7e80007b0001 PacketId 123 Frame 0x7f7e80 CC_SHORT_PACKET
[201] TRANSFER_EVENT 0xad625c90 CycleBit 1 SlotId 24 EndpointID 3 ED 1 Data 0x007f7e80007c0001 PacketId 124 Frame 0x7f7e80 CC_SHORT_PACKET
[202] TRANSFER_EVENT 0xad625ca0 CycleBit 1 SlotId 24 EndpointID 3 ED 1 Data 0x007f7e80007d0001 PacketId 125 Frame 0x7f7e80 CC_SUCCESS
[203] TRANSFER_EVENT 0xad625cb0 CycleBit 1 SlotId 24 EndpointID 3 ED 1 Data 0x007f7e80007e0001 PacketId 126 Frame 0x7f7e80 CC_SHORT_PACKET
[204] TRANSFER_EVENT 0xad625cc0 CycleBit 1 SlotId 13 EndpointID 18 ED 1 Data 0x007f7e8d00030001 PacketId 3 Frame 0x7f7e8d CC_SUCCESS
[205] TRANSFER_EVENT 0xad625cd0 CycleBit 1 SlotId 24 EndpointID 3 ED 1 Data 0x007f7e80007f0001 PacketId 127 Frame 0x7f7e80 CC_SHORT_PACKET
[206] TRANSFER_EVENT 0xad625ce0 CycleBit 1 SlotId 13 EndpointID 4 ED 1 Data 0x00000000b5310f68 BytesTransferred 65536 CC_SUCCESS
[207] TRANSFER_EVENT 0xad625cf0 CycleBit 1 SlotId 15 EndpointID 4 ED 1 Data 0x00000000ac6e2f68 BytesTransferred 31 CC_SUCCESS
[208] TRANSFER_EVENT 0xad625d00 CycleBit 1 SlotId 13 EndpointID 3 ED 1 Data 0x007f7e9000000001 PacketId 0 Frame 0x7f7e90 CC_SHORT_PACKET
[209] TRANSFER_EVENT 0xad625d10 CycleBit 1 SlotId 15 EndpointID 4 ED 1 Data 0x00000000ac6e2f68 BytesTransferred 31 CC_SUCCESS
>>>>[210] TRANSFER_EVENT 0xad625d20 CycleBit 1 SlotId 24 EndpointID 3 ED 1 Data 0x007f7e9000000001 PacketId 0 Frame 0x7f7e90 CC_SUCCESS
[211] TRANSFER_EVENT 0xad625d30 CycleBit 1 SlotId 18 EndpointID 13 ED 1 Data 0x007f7e8a00060001 PacketId 6 Frame 0x7f7e8a CC_SHORT_PACKET
[212] TRANSFER_EVENT 0xad625d40 CycleBit 1 SlotId 24 EndpointID 5 ED 1 Data 0x007f7e9000000001 PacketId 0 Frame 0x7f7e90 CC_SHORT_PACKET
------------------------------------------------------------------------------------------
EndpointType_BulkOut Address: 0x2 PacketSize: 1024 Interval: 0
!ucx_endpoint 0xb6902dc8 !rcdrlogdump USBXHCI -a 0x88399b98
!xhci_esm 0xb5088f58
[0] dt _TRANSFERRING_DATA 0xb5f76f18 Events: 0x0 TransferRingState_Idle
------------------------------------------------------------------------------
WdfQueue: !wdfqueue 0x4a0892e0 (0 waiting)
USBXHCI!_TRANSFERRING_DATA
+0x000 ControllerHandle : 0x8eaeaee0 Void
+0x004 UsbDeviceHandle : 0xb4f56eb0 Void
+0x008 EndpointHandle : 0xb5088f58 Void
+0x00c StreamId : 0
+0x010 WdfQueue : 0x4a0892e0 WDFQUEUE__
+0x014 WdfDpc : 0x4b921080 WDFDPC__
+0x018 Attributes : _TRANSFER_RING_ATTRIBUTES
+0x030 Lock : 0
+0x034 Events : 0 ( TransferRingEvent_None )
+0x038 State : 1 ( TransferRingState_Idle )
+0x03c DispatchingEvents : 0
+0x040 TrbProcessedWaitCount : 0
+0x044 TimerSet : 0 ''
+0x045 ResourcesAllocated : 0x1 ''
+0x046 StopRequested : 0 ''
+0x047 IsochOverRunUnderRunEventSurelyExpected : 0 ''
+0x048 WdfControlTimer : (null)
+0x04c WdfStopTimer : 0x497950b8 WDFTIMER__
+0x050 MaxRingIndex : 0x1f
+0x054 CurrentRingIndex : 0x18
+0x058 CycleState : 1
+0x05c CurrentRing : 0xada77000 _TRB
+0x060 CurrentRingBufferData : 0xae958e7c _BUFFER_DATA
+0x064 PendingStageCount : 0
+0x068 PendingCountAfterStopEvent : 0
+0x06c InterrupterTarget : 0
+0x06e RingDoorbellOnFirstTD : 0 ''
+0x06f IsochPure : 0 ''
+0x070 FrameOfLastIsochTdInScheduleValid : 0 ''
+0x074 NextTransferStartFrame : 0
+0x078 FrameOfLastIsochTdInSchedule : 0
+0x07c NumberOfPacketsPerFrame : 0
+0x080 TransferRingList : _LIST_ENTRY [ 0xb9d64f0c - 0xb9d64e7c ]
+0x088 PendingTransferList : _LIST_ENTRY [ 0xb5f76fa0 - 0xb5f76fa0 ]
+0x090 DoubleBufferDataList : _LIST_ENTRY [ 0xb1bf0f3c - 0xb1bf0f3c ]
+0x098 CancelledOnQueueList : _LIST_ENTRY [ 0xb5f76fb0 - 0xb5f76fb0 ]
+0x0a0 CancelledDriverOwnedList : _LIST_ENTRY [ 0xb5f76fb8 - 0xb5f76fb8 ]
+0x0a8 AsyncCompletionTransferList : _LIST_ENTRY [ 0xb5f76fc0 - 0xb5f76fc0 ]
+0x0b0 PendingCancelledList : _LIST_ENTRY [ 0xb5f76fc8 - 0xb5f76fc8 ]
+0x0b8 Counter : _TRANSFERRING_COUNTER
+0x0bc PendingTransferData : (null)
+0x0c0 CommonBufferCallbackData : _COMMON_BUFFER_CALLBACK_DATA
+0x0dc ForwardProgressMdl : (null)
+0x0e0 CancelDpcQueued : 0n0
+0x0e4 RunCancelTransfersAfterSurpriseRemoval : 0n0
[ 0] NORMAL 0xda7e5000 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 1] EVENT_DATA 0xda7e5010 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xac65ef68 TotalBytes 31
[ 2] NORMAL 0xda7e5020 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 3] EVENT_DATA 0xda7e5030 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xbd594f68 TotalBytes 31
[ 4] NORMAL 0xda7e5040 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 5] EVENT_DATA 0xda7e5050 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xbd53cf68 TotalBytes 31
[ 6] NORMAL 0xda7e5060 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 7] EVENT_DATA 0xda7e5070 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xac6a6f68 TotalBytes 31
[ 8] NORMAL 0xda7e5080 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 9] EVENT_DATA 0xda7e5090 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xac6a4f68 TotalBytes 31
[ 10] NORMAL 0xda7e50a0 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 11] EVENT_DATA 0xda7e50b0 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xbd490f68 TotalBytes 31
[ 12] NORMAL 0xda7e50c0 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 13] EVENT_DATA 0xda7e50d0 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xbd564f68 TotalBytes 31
[ 14] NORMAL 0xda7e50e0 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 15] EVENT_DATA 0xda7e50f0 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xac752f68 TotalBytes 31
[ 16] NORMAL 0xda7e5100 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 17] EVENT_DATA 0xda7e5110 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0x8eab6f68 TotalBytes 31
[ 18] NORMAL 0xda7e5120 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 19] EVENT_DATA 0xda7e5130 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data0xbf4e8f68 TotalBytes 31
[ 20] NORMAL 0xda7e5140 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 21] EVENT_DATA 0xda7e5150 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data0xb67a6f68 TotalBytes 31
[ 22] NORMAL 0xda7e5160 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 23] EVENT_DATA 0xda7e5170 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data0xac6e2f68 TotalBytes 31
[ 0] TRANSFER_EVENT 0xad625a10 CycleBit 1 SlotId 15 EndpointID 4 ED 1 Data 0x00000000b67a6f68 BytesTransferred 31 CC_SUCCESS
[ 0] TRANSFER_EVENT 0xad625810 CycleBit 1 SlotId 15 EndpointID 4 ED 1 Data 0x00000000bf4e8f68 BytesTransferred 31 CC_SUCCESS
Transfer ring:
[ 18] NORMAL 0xda7e5120 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 19] EVENT_DATA 0xda7e5130 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xbf4e8f68 TotalBytes 31
[ 20] NORMAL 0xda7e5140 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 21] EVENT_DATA 0xda7e5150 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xb67a6f68 TotalBytes 31
[ 22] NORMAL 0xda7e5160 CycleBit 1 IOC 0 CH 1 BEI 0 InterrupterTarget 0 TransferLength 31 TDSize 0
[ 23] EVENT_DATA 0xda7e5170 CycleBit 1 IOC 1 CH 0 BEI 0 InterrupterTarget 0 Data 0xac6e2f68 TotalBytes 31
0xda7e5180 Empty Transfer Ring
0xda7e5180 Empty Transfer Ring
Event ring: [ 0]TRANSFER_EVENT 0xad625810 CycleBit 1 SlotId 15 EndpointID 4 ED 1 Data 0x00000000bf4e8f68 BytesTransferred 31 CC_SUCCESS [0 ]TRANSFER_EVENT 0xad625a10 CycleBit 1 SlotId 15 EndpointID 4 ED 1 Data 0x00000000b67a6f68 BytesTransferred 31 CC_SUCCESS [207]TRANSFER_EVENT 0xad625cf0 CycleBit 1 SlotId 15 EndpointID 4 ED 1 Data 0x00000000ac6e2f68 BytesTransferred 31 CC_SUCCESS [209]TRANSFER_EVENT 0xad625d10 CycleBit 1 SlotId 15 EndpointID 4 ED 1 Data 0x00000000ac6e2f68 BytesTransferred 31 CC_SUCCESS
第五,还可以检查这个出了问题的EVENT TRB所对应的Transfer TRB 中CBW中的字段,看他是否是带有DATA OUT传输的BOT。
通过刚才打印出来的SLOT 15, EP4的TRANSFER RING中,出问题的那个TRB物理地址:
0: kd> !dc 0xda7e5000 L200
#da7e5000 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5010 ac65ef68 00000000 00000000 00001c21 h.e.........!...
#da7e5020 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5030 bd594f68 00000000 00000000 00001c21 hOY.........!...
#da7e5040 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5050 bd53cf68 00000000 00000000 00001c21 h.S.........!...
#da7e5060 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5070 ac6a6f68 00000000 00000000 00001c21 hoj.........!...
#da7e5080 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5090 ac6a4f68 00000000 00000000 00001c21 hOj.........!...
#da7e50a0 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e50b0 bd490f68 00000000 00000000 00001c21 h.I.........!...
#da7e50c0 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e50d0 bd564f68 00000000 00000000 00001c21 hOV.........!...
#da7e50e0 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e50f0 ac752f68 00000000 00000000 00001c21 h/u.........!...
#da7e5100 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5110 8eab6f68 00000000 00000000 00001c21 ho..........!...
#da7e5120 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5130 bf4e8f68 00000000 00000000 00001c21 h.N.........!...
#da7e5140 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5150 b67a6f68 00000000 00000000 00001c21 hoz.........!...
#da7e5160 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5170 ac6e2f68 00000000 00000000 00001c21 h/n.........!...
#da7e5180 00000000 00000000 00000000 00000000 ................
#da7e5190 00000000 00000000 00000000 00000000 ................
其中:
0: kd> !dc 0xda7e5160
#da7e5160 da7eb800 00000000 0000001f 00000413 ..~.............
#da7e5170 ac6e2f68 00000000 00000000 00001c21 h/n.........!...
看一下XHCI SPEC关于NORMAL TRANSFER TRB的结构定义:
前8个字节(0到7)是,该TRB所指向的需要传输的数据的物理地址,这处为da7eb800
第8到第11个字节为:这个TRB所承载的传输数据的长度0x1f, 就是31个字节
得出,这个TRANSFER TRB就是CBW所对应的TRB
而TRB中的第一个32BIT地址,就是CBW 31字节的物理地址:
0: kd> !dc da7eb800
#da7eb800 43425355 b6870918 00020000 280a0080 USBC...........(
#da7eb810 2fdb0000 00010058 00000000 00000000 .../X...........
#da7eb820 00000000 00000000 00000000 00000000 ................
我们研究一下CBW 31字节中各字段的含义:
dCBWSignature: 43425355
dCBWTag: b6870918
dCBWDataTransferLength: 00020000,需要传输数据的长度,
bmCBWFlags: 80 是一个读操作(from device to host)
bCBWLUN: 00, LUN 0
bCBWCBLength: (0,1010 b) CBW CBR 的长度,10字节
CBWCB: 28 2f db 00 00 00 01 00 58 00
而这十字节的CBWCB,应该是一个SCSI命令
通过GOOGLE,发现这是一个READ (10 )命令
bit→ ↓byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
0 | Operation code = 28h | |||||||
1 | LUN | DPO | FUA | Reserved | RelAdr | |||
2–5 | LBA | |||||||
6 | Reserved | |||||||
7–8 | Transfer length | |||||||
9 | Control |
两次SLOT15,EP4的EVENT TRB就是USB HOST IP产生的错误.