阅读:2356回复:5
关于Bulk Only数据传输的疑问...
我最近在做U盘驱动,前面的控制传输阶段通过了,但是对使用SCSI Command Set的bulk only传输有些疑问:
我参考的例子代码如下: ////////////////////////////////// void Ep2()//端口2中断处理函数 { unsigned char data i; unsigned char data Buf[64]; i = ReadEp(2,Buf); bulk_CSW[4] = Buf[4]; bulk_CSW[5] = Buf[5]; bulk_CSW[6] = Buf[6]; bulk_CSW[7] = Buf[7]; for(i=0;i<12;i++) bulk_CBW.CBWCB = Buf[i+15]; switch(bulk_CBW.CBWCB[0]) { case Inquiry :WriteEpBulk(1,36,B_InquiryData);break; case Mode_Sense :SCSI_Mode_Sense(); break; case Read10 :SCSI_Read10(); break; case Read_Capacity :WriteEpBulk(1, sizeof(B_Read_Capacity), B_Read_Capacity);break; case Read_Format_Capacities :SCSI_Read_Format_Capacities(); break; case Test_Unit_Ready :TransmitCSW(); break; case Verify :TransmitCSW(); break; case Write10 :SCSI_Write10(); break; case Medium_Removal :TransmitCSW(); break; } } //SCSI_Read10()代码 ///////////////////////////////////////////////////////////////////////// void SCSI_Read10()//FLASH读处理函数 { unsigned char data i; unsigned char Addr[4]; unsigned char length; /*读操作的起始地址*/ Addr[2] = bulk_CBW.CBWCB[4]; Addr[3] = bulk_CBW.CBWCB[5]; /*读操作的扇区长度*/ length = bulk_CBW.CBWCB[8]; while(length>0) { P5 = COMMAND; io_port1 = 0x00;//FLASH读命令码 P5 = ADDRESS; io_port1 = 0; io_port1 = Addr[3]; io_port1 = Addr[2]; P5 = D_DATA; UEPNUM=0x01; UEPSTAX|=DIR; while(!(P5 & RB)); /*读取一个扇区的数据*/ for(i=0;i<8;i++) { ReadFlash(); UEPSTAX|=TXRDY; while(!(UEPSTAX&TXCMP)); UEPSTAX&=(~(TXCMP)); } io_port1 = INACTIVE; length--; Addr[3]++; if(Addr[3]==255) { Addr[3]=0; Addr[2]++; } } TransmitCSW(); } /////////////////////////////////疑问如下/////////////////////////////// 结合相关资料,对于一次bulk-in传输流程我是这样理解的: 1.Host发送CBW到OUT端点,Device回送ACK读取CBW,没有数据阶段。 2.Host发送PID为IN的数据包,指示Device传数据,Device向Host传数据,Host应答。 3.Host发送PID为IN的数据包,指示Device传状态,Device向Host传CSW,Host应答。 但从上述代码看,设备端收到CBW并解析后就直接回传数据和CSW,这样Host能正确区分这些数据吗?? 请高人指点。。。 |
|
沙发#
发布于:2007-05-08 09:23
这个驱动很急啊,请各位不吝赐教!!
|
|
板凳#
发布于:2007-05-08 13:01
可能是讲的不够清楚,重新发一下:
关于Bulk only传输的疑问: Bulk-Only传输模块按照规范协议将SCSI-2指令打包成CBW命令包,通过输出请求,由主机向设备送出,在没有传输失败的情况下,紧接着发出输入请求接收命令请求所要获取的数据,而后发出输入请求得到CSW状态包,用以判断数据的传输正常与否。也就是说一次Bulk only传输中间Host会发出3次请求,但下面代码不是这样做的: void Ep2()//端口2中断处理函数 { unsigned char data i; unsigned char data Buf[64]; i = ReadEp(2,Buf); bulk_CSW[4] = Buf[4]; bulk_CSW[5] = Buf[5]; bulk_CSW[6] = Buf[6]; bulk_CSW[7] = Buf[7]; for(i=0;i<12;i++) bulk_CBW.CBWCB = Buf[i+15]; switch(bulk_CBW.CBWCB[0]) { case Inquiry: WriteEpBulk(1,36,B_InquiryData);break; case Mode_Sense: SCSI_Mode_Sense(); break; case Read10: SCSI_Read10(); break; case Read_Capacity: WriteEpBulk(1, sizeof(B_Read_Capacity), Read_Capacity();break; case Read_Format_Capacities: SCSI_Read_Format_Capacities(); break; case Test_Unit_Ready: TransmitCSW(); break; case Verify: TransmitCSW(); break; case Write10: SCSI_Write10(); break; case Medium_Removal: TransmitCSW(); break; } } SCSI_Read10()代码: void SCSI_Read10()//FLASH读处理函数 { unsigned char data i; unsigned char Addr[4]; unsigned char length; /*读操作的起始地址*/ Addr[2] = bulk_CBW.CBWCB[4]; Addr[3] = bulk_CBW.CBWCB[5]; /*读操作的扇区长度*/ length = bulk_CBW.CBWCB[8]; while(length>0) { P5 = COMMAND; io_port1 = 0x00;//FLASH读命令码 P5 = ADDRESS; io_port1 = 0; io_port1 = Addr[3]; io_port1 = Addr[2]; P5 = D_DATA; UEPNUM=0x01; UEPSTAX|=DIR; while(!(P5 & RB)); /*读取一个扇区的数据*/ for(i=0;i<8;i++) { ReadFlash(); UEPSTAX|=TXRDY; while(!(UEPSTAX&TXCMP)); UEPSTAX&=(~(TXCMP)); } io_port1 = INACTIVE; length--; Addr[3]++; if(Addr[3]==255) { Addr[3]=0; Addr[2]++; } }//End while(length>0) TransmitCSW(); } 我的疑问是: 1。为什么在端点2中断中读出数据包分析为Read10命令后就直接向主机发数据了,为什么不等待下一个IN令牌包再发数据? 2。在SCSI_Read10()函数中为什么数据和CSW是连续发送的?CSW应该在数据发送完成后,等待接到一个IN令牌包才被发送啊。。。 这些问题很急,望不吝赐教,非常感谢! ![]() |
|
地板#
发布于:2007-05-08 19:33
while(!(UEPSTAX&TXCMP)); 好象是在等待传输完成吧。
![]() |
|
地下室#
发布于:2007-05-08 21:03
while(!(UEPSTAX&TXCMP)); 确实是在等待数据传输完成,但我不清楚的是:
Device在收到CBW后应答Host,然后Host会发起下一次数据传输,也就是会先发送一个IN令牌包,引起Device的IN端口中断,然后device向host发送数据,发完后,host应答device,之后host发起第3次数据传输,会先发送一个IN令牌包要求device发送CSW,device发送完CSW后,host应答,这样一次Bulk In数据传输过程才结束,包括CBW -> DATA -> CSW三次数据传输事务,应该引起device端的3次中断,可是上述程序好像没有明确区分!??? 不知我说的有道理否。。。。。。。 |
|
5楼#
发布于:2007-05-09 12:51
顶一下...
![]() |
|