diff options
author | barthess <barthess@yandex.ru> | 2016-10-28 14:25:08 +0300 |
---|---|---|
committer | barthess <barthess@yandex.ru> | 2016-10-28 14:25:08 +0300 |
commit | 92c371470649d58e1e76e6c255fe3c010fc8ef54 (patch) | |
tree | 3c4181aebf78313e43e5dbb8c2c5a8eacad0cbaa /os | |
parent | b7cefd6fac81a164017c4f81b8b53584e104db0b (diff) | |
download | ChibiOS-Contrib-92c371470649d58e1e76e6c255fe3c010fc8ef54.tar.gz ChibiOS-Contrib-92c371470649d58e1e76e6c255fe3c010fc8ef54.tar.bz2 ChibiOS-Contrib-92c371470649d58e1e76e6c255fe3c010fc8ef54.zip |
USB_MSD. Added READ_FORMAT_CAPACITIES handler
Diffstat (limited to 'os')
-rw-r--r-- | os/hal/src/hal_usb_msd.c | 35 | ||||
-rw-r--r-- | os/various/lib_scsi.c | 107 | ||||
-rw-r--r-- | os/various/lib_scsi.h | 11 | ||||
-rw-r--r-- | os/various/ramdisk.c | 10 |
4 files changed, 120 insertions, 43 deletions
diff --git a/os/hal/src/hal_usb_msd.c b/os/hal/src/hal_usb_msd.c index 9c49192..068d698 100644 --- a/os/hal/src/hal_usb_msd.c +++ b/os/hal/src/hal_usb_msd.c @@ -262,22 +262,47 @@ bool msd_request_hook(USBDriver *usbp) { /* check that it is a HOST2DEV request */ if (((usbp->setup[0] & USB_RTYPE_DIR_MASK) != USB_RTYPE_DIR_HOST2DEV) || (MSD_SETUP_LENGTH(usbp->setup) != 0) || - (MSD_SETUP_VALUE(usbp->setup) != 0)) + (MSD_SETUP_VALUE(usbp->setup) != 0)) { return false; + } - /* reset all endpoints */ - /* TODO!*/ + /* + As required by the BOT specification, the Bulk-only mass storage reset request (classspecific + request) is implemented. This request is used to reset the mass storage device and + its associated interface. This class-specific request should prepare the device for the next + CBW from the host. + To generate the BOT Mass Storage Reset, the host must send a device request on the + default pipe of: + • bmRequestType: Class, interface, host to device + • bRequest field set to 255 (FFh) + • wValue field set to ‘0’ + • wIndex field set to the interface number + • wLength field set to ‘0’ + */ + chSysLockFromISR(); + + /* release and abandon current transmission */ + usbStallReceiveI(usbp, 1); + usbStallTransmitI(usbp, 1); /* The device shall NAK the status stage of the device request until * the Bulk-Only Mass Storage Reset is complete. - */ + * NAK EP1 in and out */ + usbp->otg->ie[1].DIEPCTL = DIEPCTL_SNAK; + usbp->otg->oe[1].DOEPCTL = DOEPCTL_SNAK; + + chSysUnlockFromISR(); + + /* response to this request using EP0 */ + usbSetupTransfer(usbp, 0, 0, NULL); return true; case MSD_GET_MAX_LUN: /* check that it is a DEV2HOST request */ if (((usbp->setup[0] & USB_RTYPE_DIR_MASK) != USB_RTYPE_DIR_DEV2HOST) || (MSD_SETUP_LENGTH(usbp->setup) != 1) || - (MSD_SETUP_VALUE(usbp->setup) != 0)) + (MSD_SETUP_VALUE(usbp->setup) != 0)) { return false; + } /* stall to indicate that we don't support LUN */ osalSysLockFromISR(); diff --git a/os/various/lib_scsi.c b/os/various/lib_scsi.c index 11842ef..55aeb7e 100644 --- a/os/various/lib_scsi.c +++ b/os/various/lib_scsi.c @@ -25,10 +25,17 @@ #include <string.h> #include "hal.h" -//#include "chprintf.h" #include "lib_scsi.h" +#define DEBUG_TRACE_PRINT FALSE +#define DEBUG_TRACE_WARNING FALSE +#define DEBUG_TRACE_ERROR FALSE +#include "dbgtrace.h" + +#define ARCH_LITTLE_ENDIAN +#include "bswap.h" + /*===========================================================================*/ /* Driver local definitions. */ /*===========================================================================*/ @@ -51,25 +58,6 @@ typedef struct { /*===========================================================================*/ /** - * @brief Byte swapping function. - * - * @notapi - */ -static uint32_t swap_uint32(uint32_t val) { - val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0x00FF00FF); - return ((val << 16) & 0xFFFF0000) | ((val >> 16) & 0x0000FFFF); -} - -/** - * @brief Byte swapping function. - * - * @notapi - */ -static uint16_t swap_uint16(uint16_t val) { - return ((val >> 8) & 0xff) | ((val & 0xff) << 8); -} - -/** * @brief Combines data request from byte array. * * @notapi @@ -83,8 +71,8 @@ static data_request_t decode_data_request(const uint8_t *cmd) { memcpy(&lba, &cmd[2], sizeof(lba)); memcpy(&blk, &cmd[7], sizeof(blk)); - req.first_lba = swap_uint32(lba); - req.blk_cnt = swap_uint16(blk); + req.first_lba = be32_to_cpu(lba); + req.blk_cnt = be16_to_cpu(blk); return req; } @@ -254,6 +242,51 @@ static bool mode_sense6(SCSITarget *scsip, const uint8_t *cmd) { } /** + * @brief SCSI read format capacities command handler. + * + * @param[in] scsip pointer to @p SCSITarget structure + * @param[in] cmd pointer to SCSI command data + * + * @return The operation status. + * + * @notapi + */ +static bool read_format_capacities(SCSITarget *scsip, const uint8_t *cmd) { + + /* An Allocation Length of zero indicates that no data shall be transferred. + This condition shall not be considered as an error. The Logical Unit + shall terminate the data transfer when Allocation Length bytes have + been transferred or when all available data have been transferred to + the Initiator, whatever is less. */ + + uint16_t len = cmd[7] << 8 | cmd[8]; + + if (0 == len) { + return SCSI_SUCCESS; + } + else { + scsi_read_format_capacities_response_t ret; + BlockDeviceInfo bdi; + blkGetInfo(scsip->config->blkdev, &bdi); + + uint32_t tmp = cpu_to_be32(bdi.blk_num); + memcpy(ret.blocknum, &tmp, 4); + + uint8_t formatted_media = 0b10; + uint16_t blocklen = bdi.blk_size; + ret.blocklen[0] = formatted_media; + ret.blocklen[1] = 0; + ret.blocklen[2] = blocklen >> 8; + ret.blocklen[3] = blocklen & 0xFF; + + ret.header[3] = 1 * 8; + + return transmit_data(scsip, (uint8_t *)&ret, + sizeof(scsi_read_format_capacities_response_t)); + } +} + +/** * @brief SCSI read capacity (10) command handler. * * @param[in] scsip pointer to @p SCSITarget structure @@ -270,8 +303,8 @@ static bool read_capacity10(SCSITarget *scsip, const uint8_t *cmd) { BlockDeviceInfo bdi; blkGetInfo(scsip->config->blkdev, &bdi); scsi_read_capacity10_response_t ret; - ret.block_size = swap_uint32(bdi.blk_size); - ret.last_block_addr = swap_uint32(bdi.blk_num - 1); + ret.block_size = cpu_to_be32(bdi.blk_size); + ret.last_block_addr = cpu_to_be32(bdi.blk_num - 1); return transmit_data(scsip, (uint8_t *)&ret, sizeof(scsi_read_capacity10_response_t)); @@ -370,39 +403,47 @@ bool scsiExecCmd(SCSITarget *scsip, const uint8_t *cmd) { switch (cmd[0]) { case SCSI_CMD_INQUIRY: - //chprintf(SDDBG, "SCSI_CMD_INQUIRY\r\n"); + dbgprintf("SCSI_CMD_INQUIRY\r\n"); return inquiry(scsip, cmd); case SCSI_CMD_REQUEST_SENSE: - //chprintf(SDDBG, "SCSI_CMD_REQUEST_SENSE\r\n"); + dbgprintf("SCSI_CMD_REQUEST_SENSE\r\n"); return request_sense(scsip, cmd); case SCSI_CMD_READ_CAPACITY_10: - //chprintf(SDDBG, "SCSI_CMD_READ_CAPACITY_10\r\n"); + dbgprintf("SCSI_CMD_READ_CAPACITY_10\r\n"); return read_capacity10(scsip, cmd); case SCSI_CMD_READ_10: - //chprintf(SDDBG, "SCSI_CMD_READ_10\r\n"); + dbgprintf("SCSI_CMD_READ_10\r\n"); return data_read_write10(scsip, cmd); case SCSI_CMD_WRITE_10: - //chprintf(SDDBG, "SCSI_CMD_WRITE_10\r\n"); + dbgprintf("SCSI_CMD_WRITE_10\r\n"); return data_read_write10(scsip, cmd); case SCSI_CMD_TEST_UNIT_READY: - //chprintf(SDDBG, "SCSI_CMD_TEST_UNIT_READY\r\n"); + dbgprintf("SCSI_CMD_TEST_UNIT_READY\r\n"); return cmd_ignored(scsip, cmd); case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: - //chprintf(SDDBG, "SCSI_CMD_ALLOW_MEDIUM_REMOVAL\r\n"); + dbgprintf("SCSI_CMD_ALLOW_MEDIUM_REMOVAL\r\n"); return cmd_ignored(scsip, cmd); case SCSI_CMD_MODE_SENSE_6: - //chprintf(SDDBG, "SCSI_CMD_MODE_SENSE_6\r\n"); + dbgprintf("SCSI_CMD_MODE_SENSE_6\r\n"); return mode_sense6(scsip, cmd); + case SCSI_CMD_READ_FORMAT_CAPACITIES: + dbgprintf("SCSI_CMD_READ_FORMAT_CAPACITIES\r\n"); + return read_format_capacities(scsip, cmd); + + case SCSI_CMD_VERIFY_10: + dbgprintf("SCSI_CMD_VERIFY_10\r\n"); + return cmd_ignored(scsip, cmd); + default: - //(SDDBG, "SCSI unhandled command: %d\r\n", cmd[0]); + warnprintf("SCSI unhandled command: %X\r\n", cmd[0]); return cmd_unhandled(scsip, cmd); } } diff --git a/os/various/lib_scsi.h b/os/various/lib_scsi.h index 21ab5d8..97badb0 100644 --- a/os/various/lib_scsi.h +++ b/os/various/lib_scsi.h @@ -37,6 +37,7 @@ #define SCSI_CMD_SEND_DIAGNOSTIC 0x1D #define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E #define SCSI_CMD_READ_CAPACITY_10 0x25 +#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23 #define SCSI_CMD_READ_10 0x28 #define SCSI_CMD_WRITE_10 0x2A #define SCSI_CMD_VERIFY_10 0x2F @@ -157,6 +158,16 @@ typedef struct PACKED_VAR { } scsi_read_capacity10_response_t; /** + * @brief Represents SCSI read format capacity response structure. + * @details See SCSI specification. + */ +typedef struct PACKED_VAR { + uint8_t header[4]; + uint8_t blocknum[4]; + uint8_t blocklen[4]; +} scsi_read_format_capacities_response_t; + +/** * @brief Type of a SCSI transport transmit call. * * @param[in] usbp pointer to the @p SCSITransport object diff --git a/os/various/ramdisk.c b/os/various/ramdisk.c index b9a40ef..08abdca 100644 --- a/os/various/ramdisk.c +++ b/os/various/ramdisk.c @@ -58,7 +58,7 @@ static bool is_inserted(void *instance) { static bool is_protected(void *instance) { RamDisk *rd = instance; - if (rd->state != BLK_READY) { + if (BLK_READY == rd->state) { return rd->readonly; } else { @@ -68,7 +68,7 @@ static bool is_protected(void *instance) { static bool connect(void *instance) { RamDisk *rd = instance; - if (rd->state == BLK_STOP) { + if (BLK_STOP == rd->state) { rd->state = BLK_READY; } return HAL_SUCCESS; @@ -76,7 +76,7 @@ static bool connect(void *instance) { static bool disconnect(void *instance) { RamDisk *rd = instance; - if (rd->state != BLK_STOP) { + if (BLK_STOP != rd->state) { rd->state = BLK_STOP; } return HAL_SUCCESS; @@ -114,7 +114,7 @@ static bool write(void *instance, uint32_t startblk, static bool sync(void *instance) { RamDisk *rd = instance; - if (rd->state != BLK_READY) { + if (BLK_READY != rd->state) { return HAL_FAILED; } else { @@ -125,7 +125,7 @@ static bool sync(void *instance) { static bool get_info(void *instance, BlockDeviceInfo *bdip) { RamDisk *rd = instance; - if (rd->state != BLK_READY) { + if (BLK_READY != rd->state) { return HAL_FAILED; } else { |