X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=client%2Fgoodfet.maxusbmass;h=0bda107ffe596f2c032b985b4a452f71609e9d44;hp=da42c90ccf8907382b9c739a99b3f8a25e4fed11;hb=0f09afa49bb8b723a270edd816acbdcaddeb7290;hpb=b0ffd16b9a06f71372d7943b531cffd45b1bd728 diff --git a/client/goodfet.maxusbmass b/client/goodfet.maxusbmass index da42c90..0bda107 100755 --- a/client/goodfet.maxusbmass +++ b/client/goodfet.maxusbmass @@ -11,6 +11,24 @@ import time; from GoodFETMAXUSB import *; + +# This constant is kinda complicated and very ugly. The idea is that +# if we take too long in any given transaction, the host will abort. +# How many blocks we can send depends upon timeouts on both sides, +# with (at least in Linux) the behavior that aborting early causes the +# disk to reset with only warning and no real errors. Somewhere +# there's a way to provide this constant to the host, in which case +# stalling and waiting for a reset will no longer be necessary. + +MAXBLOCKSPERTRANSFER=128 + +def zeros(length): + """Returns a list of zeroes of the specified length.""" + l=range(0,length); + for foo in l: + l[foo]=0; + return l; + class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): """This emulates a USB Mass Storage device.""" @@ -277,7 +295,7 @@ class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): #print "Responding to CB inquiry."; response=[ 0x00, # 00 for Direct, 1F for "no floppy" - 0x80, # make 0x80 for removable media + 0x80, # make 0x80 for removable media, 0x00 for fixed 0x00, # Version 0x01, # Response Data Format 0x1f, #Additional length. @@ -290,6 +308,8 @@ class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): ord('0'),ord('.'),ord('0'),ord('1')] #print "Sending %i byte reply to %i byte query." % ( # len(response),dtlen); + while len(response)32: + if count>MAXBLOCKSPERTRANSFER: count=0; - status=1; #Fail if we're asked to read more than 32 blocks. + #status=1; #Fail if we're asked to read more than 32 blocks. #Now we need to stall EP3. It's not acceptable to just forget to transmit. self.wreg(rEPSTALLS,0x10); + return; for i in range(0,count): data=self.getSectorData(baselba+i); - for j in range(0,8): - #print "Sending block fragment %i,%i" % (i,j); - #Transmit each 64-byte block fragment, then wait for next. - while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ): pass; - response=data[j*64:j*64+64]; - self.writebytes(rEP3INFIFO, - response); - self.wregAS(rEP3INBC, - 64); + self.fifo_ep3in_tx(data); + + # for j in range(0,8): + # #print "Sending block fragment %i,%i" % (i,j); + # #Transmit each 64-byte block fragment, then wait for next. + # while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ): pass; + # response=data[j*64:j*64+64]; + # self.writebytes(rEP3INFIFO, + # response); + # self.wregAS(rEP3INBC, + # 64); #sys.exit(); elif verb==0x2A: #WRITE SECTOR print "Haven't implemented WRITE SECTOR."; #sys.exit(); + elif verb==0x1B: #EJECT/RETRACT DISK + print "Haven't implemented SCSI Start Stop Unit Command (1B)"; + print "https://en.wikipedia.org/wiki/SCSI_Start_Stop_Unit_Command"; + #sys.exit(); else: print "ERROR: Unknown SCSI command block verb %02x." % verb; - status=1; #Command Failed + status=0x02; #Command Failed if dtlen>0: - print "Perhaps I should send %i bytes of dummy data here." % dtlen; - sys.exit(1); + print "Sending %i bytes of dummy data here." % dtlen; + self.fifo_ep3in_tx(zeros(dtlen)); + #sys.exit(1); cbw=self.lastCBW; #Now we need to send the CSW. @@ -446,6 +482,7 @@ class GoodFETMAXUSBMassFile(GoodFETMAXUSBMass): self.datafilelen%512); sys.exit(); return self.datafilelen/512-1; + if(len(sys.argv)==1): print "Usage: %s disk.img\n" % sys.argv[0]; sys.exit();