Commit 2e97c8b1 authored by Jeffrey Lee's avatar Jeffrey Lee
Browse files

Limit max transfer length to 64K, fix issues with transfer lengths being incorrectly modified

  s/ScsiFs00, s/ScsiFs15 - As a workaround for numerous USB devices that fail when asked to transfer large amounts of data, SCSIFS now limits the maximum transfer length to 64K.
  This length seems to match the limit used by most operating systems. If necessary this code can be turned off via the XferLenMax64K switch.
  Additionally, a couple of bugs with the CheckXferLen and UseSpecialScatterBlk code have been fixed:
  - When CheckXferLen (and XferLenMax64K) limit the block count in the CDB, the code now calculates a new value of R4 to send to the SCSI driver instead of using the original. This ensures there's no ambiguity in the transfer length.
  - After the SCSI op is completed, the returned value of R4 is then adjusted to represent the real amount of untransferred data from FileCore's perspective.
  - When the special scatter block is in use, the code now returns to FileCore with R3 pointing to the correct location in the source buffer, and with R4 adjusted to take into account the extra padding that had been inserted. Previously the old code would have returned with R3 and R4 left unmodified (i.e. R3 would have been pointing at SCSIFS's temp scatter list)
  Tested in ROM on a rev C2 beagleboard over the course of a few hours with the help of an automated test script.
  No more 'no sense' errors when attempting large block transfers to USB devices, and no sign of data corruption for large or small transfers.
  See the forums for more discussion of these issues:

Version 1.18. Tagged as 'SCSIFS-1_18'
parent 39a2a6e0
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "1.17"
Module_Version SETA 117
Module_MajorVersion SETS "1.18"
Module_Version SETA 118
Module_MinorVersion SETS ""
Module_Date SETS "14 Jul 2009"
Module_ApplicationDate SETS "14-Jul-09"
Module_Date SETS "15 Dec 2010"
Module_ApplicationDate SETS "15-Dec-10"
Module_ComponentName SETS "SCSIFS"
Module_ComponentPath SETS "castle/RiscOS/Sources/FileSys/SCSIFS/SCSIFS"
Module_FullVersion SETS "1.17"
Module_HelpVersion SETS "1.17 (14 Jul 2009)"
Module_FullVersion SETS "1.18"
Module_HelpVersion SETS "1.18 (15 Dec 2010)"
/* (1.17)
/* (1.18)
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
#define Module_MajorVersion_CMHG 1.17
#define Module_MajorVersion_CMHG 1.18
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 14 Jul 2009
#define Module_Date_CMHG 15 Dec 2010
#define Module_MajorVersion "1.17"
#define Module_Version 117
#define Module_MajorVersion "1.18"
#define Module_Version 118
#define Module_MinorVersion ""
#define Module_Date "14 Jul 2009"
#define Module_Date "15 Dec 2010"
#define Module_ApplicationDate "14-Jul-09"
#define Module_ApplicationDate "15-Dec-10"
#define Module_ComponentName "SCSIFS"
#define Module_ComponentPath "castle/RiscOS/Sources/FileSys/SCSIFS/SCSIFS"
#define Module_FullVersion "1.17"
#define Module_HelpVersion "1.17 (14 Jul 2009)"
#define Module_LibraryVersionInfo "1:17"
#define Module_FullVersion "1.18"
#define Module_HelpVersion "1.18 (15 Dec 2010)"
#define Module_LibraryVersionInfo "1:18"
......@@ -50,8 +50,8 @@ CheckXferLen SETL T
;CheckSpareRMA SETL F
;ExtraRMA * 1024 * 33 ; usb mak pkt of 32k, + 1k ???
GBLL XferLenMax255
XferLenMax255 SETL F
GBLL XferLenMax64K
XferLenMax64K SETL T
GBLL RetryIfBusy
RetryIfBusy SETL T
......@@ -288,15 +288,21 @@ DontNeedScatBlk
; If the byte count given by filecore, converted to a block count exceeds this,
; put 65535 in the CDB. Filecore will see that not all of the data has been
; transfered and call us again for the residue.
; This condition will probably never arise, since it represents 16/32/64 Mbyte
; (for 256/512/1024 byte blocks).
; XferLenMax255 switch introduced for test purposes .. some devices found
; that won't do more than 256 blocks at a time safely (JB 20050131)
[ XferLenMax255
CMP R5,#&100
; Now renamed & repurposed for limiting the max length to 64K, as that seems
; to be the limit which most OS's use for USB mass storage transfers (and
; potentially all other I/O transfers, but my main interest is finding a fix
; for all the shoddy USB devices) (JL 20101214)
[ XferLenMax64K
MOV R3,#65536
CMP R5,#65536 ; Just in case we have a device with a block size of 1
SUBEQ R5,R5,#1
CMP R5,#&10000
......@@ -306,12 +312,12 @@ DontNeedScatBlk
MOV R3,R5,LSR #8
MOV R3,R3,LSL #24 ;MSB in CDB[7] {R3 bits 24..31}
AND R5,R5,#&FF ;LSB in CDB[8] {R4 bits 0..7 }
AND R6,R5,#&FF ;LSB in CDB[8] {R4 bits 0..7 }
ORR R1,R1,R7,LSL #16 ;Add sex changed block address
ORR R3,R3,R7,LSR #16 ; to CDB
STMIA R2,{R1,R3,R5} ;Copy 12bytes of CDB onto stack
STMIA R2,{R1,R3,R6} ;Copy 12bytes of CDB onto stack
;R2,R3,R4,R9 stacked
......@@ -321,21 +327,32 @@ DontNeedScatBlk
Pull "R2,R3,R4,R9"
[ UseSpecialScatterBlk
LDR R5, ScatterFlag ;Are we using the special ScatterBlock ?
CMP R5, #0
LDR R6, ScatterFlag ;Are we using the special ScatterBlock ?
CMP R6, #0
ADRNE R3, WriteScatBlk ;Yes ! Better make RAMptr point to it,
LDRNE R4, ScatterData ;and use the rounded up total length
; If we're transferring less than what was requested, clamp R4 so that
; SCSI drivers won't get confused by the CDB saying one thing but R4 saying
; something else
; But remember how much we clamped by, so that we can return the correct unread
; amount to FileCore
[ BigDisc
Push "R6,R8"
Push "R6"
MOV R5, #0
LDRNE R6, WinnieCallAfter ;Callback address
LDRNE R7, FileCorePrivate ; & wsptr (if needed)
[ BigDisc
Push "R8"
MOV R8, R12 ;AccessKey
[ RetryIfBusy
......@@ -363,6 +380,10 @@ DontNeedScatBlk
LDR LR, FCFeatures
; Adjust R4 by our stacked R6
Pull "R6"
ADD R4,R4,R6
TST LR, #FC_NewErrors
ORREQ R0, R0, #ExternalErrorBit
MOVVC R0, #0
......@@ -372,6 +393,23 @@ DontNeedScatBlk
ADD StkPtr,StkPtr,#12 ;Discard the stacked CBD
LDMIB SP, {R1-R2,R6-R7}
[ UseSpecialScatterBlk
; If we used the temp scatter block then we need to restore the correct R3
; value and 'forget' the extra bytes that we transferred
LDR R9, ScatterFlag
TEQ R9, #0
LDR R9, ScatterData ; Get adjusted length
SUB R9, R9, R7 ; Calculate the amount of padding we used
SUB R4, R4, R9 ; Forget the padding
TEQ R4, #0 ; Preserve V
MOVMI R4, #0 ; Clamp R4 if we managed to transfer everything we were originally asked to
SUB R7, R7, R4 ; Get amount transferred
ADD R3, R6, R7 ; And calculate the correct value of R3 to return
SUB R7, R7, R4 ;Amount Xfered
[ BigDisc
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment