Commit 70347aa3 authored by Robert Sprowson's avatar Robert Sprowson

Fix for quirky devices which report bad residues

There's a class of devices which manage to get the dCSWDataResidue value wrong (for example, reversed endianness, or just garbage). This causes an error to be propagated up to SCSIDriver in and the initial CDB_CAPACITY to fail (only 8 bytes are expected). The error response is to fill the capacity with 0xFFFFFFFF's, which are then reported as a device of apparently 512TB in size.
Take the stance that umass.c revision 1.146 in NetBSD takes, and simply ignore the device's residue; use the actual number of bytes transferred by the USB stack instead.
umass.c: Compute dCSWDataResidue locally.
global.h: Fix debug build, pointer type of states[] needs constifying.
glue.c: Simplify the entry to glue_Tick; it is assumed to be entered with interrupts disabled, and all exits restore the interrupt state, so unconditionally disable - note that this is only needed for debugging when debuglib might enable interrupts for some output types, and thus allow reentrancy via RTSupport. Clean up a few comments in passing.

Tested with a known bogus USB stick - now mounts successfully. Ref: Elesar ticket #78A-D76-74EC3.

Version 0.27. Tagged as 'SCSISoftUSB-0_27'
parent 63867af3
/* (0.26)
/* (0.27)
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
#define Module_MajorVersion_CMHG 0.26
#define Module_MajorVersion_CMHG 0.27
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 13 Apr 2019
#define Module_Date_CMHG 18 Apr 2019
#define Module_MajorVersion "0.26"
#define Module_Version 26
#define Module_MajorVersion "0.27"
#define Module_Version 27
#define Module_MinorVersion ""
#define Module_Date "13 Apr 2019"
#define Module_Date "18 Apr 2019"
#define Module_ApplicationDate "13-Apr-19"
#define Module_ApplicationDate "18-Apr-19"
#define Module_ComponentName "SCSISoftUSB"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/SCSI/SCSISoftUSB"
#define Module_FullVersion "0.26"
#define Module_HelpVersion "0.26 (13 Apr 2019)"
#define Module_LibraryVersionInfo "0:26"
#define Module_FullVersion "0.27"
#define Module_HelpVersion "0.27 (18 Apr 2019)"
#define Module_LibraryVersionInfo "0:27"
......@@ -317,10 +317,10 @@ void glue_ResetDevice(my_usb_device_t *device, int reason)
_kernel_oserror *glue_DoCommand(my_usb_device_t *device, uint32_t lun, uint32_t data_direction, const char *control_block, size_t control_block_length, scatter_entry_t *scatter_list, size_t transfer_length, void (*callback)(void), void *callback_pw, void *callback_wp)
DEBUGf("\nDoCommand device %p lun %x\n",device,lun);
if(lun > device->maxlun )
DEBUGf("\nDoCommand device %p lun %x\n",(void *)device,lun);
if (lun > device->maxlun)
DEBUGf("\nLUN was too large asked %d max %d %p\n",lun,device->maxlun);
DEBUGf("\nLUN was too large asked %d max %d\n",lun,device->maxlun);
return (_kernel_oserror *)(ErrorNumber_SCSI_Died & 0xFF);
......@@ -485,18 +485,19 @@ _kernel_oserror *glue_DoCommand(my_usb_device_t *device, uint32_t lun, uint32_t
void glue_Tick(my_usb_device_t *device)
/* Assume interrupts are disabled on entry - */
/* this will be true for TickerV and the RTSupport wrapper */
_kernel_irqs_off(); /* In case PRINTF_OUTPUT */
/* Semaphore check .. out quickly if already here */
bool irqs_were_off = _kernel_irqs_disabled();
if (!irqs_were_off) _kernel_irqs_off();
if (device->ticker_semaphore) {if(!irqs_were_off)_kernel_irqs_on();return;}
if (device->ticker_semaphore) return;
device->ticker_semaphore = true;
DEBUGf("\nTick ");
struct umass_softc *softc = (struct umass_softc *)device->softc;
DEBUGf("Initial state, status = %x %x ", softc->transfer_state, device->status);
/* Assume interrupts are disabled on entry - */
/* this will be true for TickerV and the RTSupport wrapper */
_kernel_oserror *e;
size_t buffer_used;
......@@ -677,11 +678,6 @@ void glue_Tick(my_usb_device_t *device)
DEBUGf("Still in RX buffer: = %x, needed: = %x ", buffer_used,device->curr_transferlength);
// if (buffer_used > device->curr_transferlength)
// {
// // flush the buffer.. we're done here
// REMOVE_BLOCK(device->current_pipe->buffer, softc->scbulkoutbuf, buffer_used);
// }
e = _swix(DeviceFS_CallDevice, _INR(0,2),
......@@ -736,7 +732,7 @@ void glue_Tick(my_usb_device_t *device)
DEBUGf("Calling SCSIDriver from Tick, addr=%x err=%x r0=%x r4=%x r5=%x r12=%x\n", (int)device->callback, (int)device->callback_error, device->callback_status_byte, device->callback_not_transferred, (int)device->callback_pw, (int)device->callback_wp);
softc->transfer_priv = NULL; // make sure it cannot be repeated
softc->transfer_priv = NULL; /* make sure it cannot be repeated */
......@@ -860,7 +856,7 @@ static void Callback(struct umass_softc *softc, void *void_device, int not_trans
my_usb_device_t *device = (my_usb_device_t *)void_device;
DEBUGf("Callback, status %d\n",status);
if(!device)return; // already handled when it went wrong
if (!device) return; /* Already handled when it went wrong */
switch (status)
......@@ -1542,6 +1542,13 @@ umass_bbb_state(
DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw));
#ifdef __riscos
/* Based on an idea from umass.c revision 1.146 (which is some way
* ahead), rather than have a large table of UMASS_QUIRK_IGNORE_RESIDUE
* ignore the csw and always use what the USB stack actually transferred.
USETDW(sc->csw.dCSWDataResidue, sc->transfer_datalen - sc->transfer_actlen);
/* Translate weird command-status signatures. */
if ((sc->sc_quirks & UMASS_QUIRK_WRONG_CSWSIG) &&
......@@ -193,7 +193,7 @@ extern int global_RTSupportHandle; /* RTSupport handle */
extern callback_type global_CallbackType; /* Type of our registered callback, if any */
extern uint32_t global_PopUpDelay; /* Delay before SCSIFS gets told about new devices */
extern char *states[];
extern const char *states[];
* Function prototypes
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment