diff options
Diffstat (limited to 'bootloaders/diskloader/src/SCSI.cpp')
-rw-r--r-- | bootloaders/diskloader/src/SCSI.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/bootloaders/diskloader/src/SCSI.cpp b/bootloaders/diskloader/src/SCSI.cpp new file mode 100644 index 0000000..dbbf9cf --- /dev/null +++ b/bootloaders/diskloader/src/SCSI.cpp @@ -0,0 +1,213 @@ + + +/* Copyright (c) 2010, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#include "Platform.h" + +#ifdef MSC_ENABLED + +// SCSI Commands +#define TEST_UNIT_READY 0x00 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define INQUIRY 0x12 +#define MODE_SENSE 0x1A +#define START_STOP_UNIT 0x1B +#define MEDIA_REMOVAL 0x1E +#define READ_FORMAT_CAPACITIES 0x23 +#define READ_CAPACITY 0x25 +#define READ10 0x28 +#define WRITE10 0x2A +#define VERIFY10 0x2F + + +// In FakeFAT +void SendSector(u8 b); +void RecvSector(u8 b); + +// In USBCore +u8 RecvPacket(u8 ep, u8* dst, u8 len); +u8 SendPacket(u8 ep, const u8* src, u8 len); +void Reboot(); + +#define MSC_TX MSC_ENDPOINT_IN +#define MSC_RX MSC_ENDPOINT_OUT + +extern const u8 P_Inquiry[36] PROGMEM; +extern const u8 P_RequestSense[18] PROGMEM; +extern const u8 P_ReadCapacity[8-3] PROGMEM; +extern const u8 P_ModeSense[4] PROGMEM; + +typedef struct +{ + u8 signature[4]; + u8 tag[4]; + u32 transferLength; + u8 flags; + u8 lun; + u8 cblength; + u8 cb[16]; +} CBW; + +const u8 P_Inquiry[36] = +{ + 0x00, // Direct Access Device + 0x80, // Removable Medium + 0x00, // Version + 0x01, + + 36-4, // Additional Length + 0x80, // Storage Controller Component + 0x00, + 0x00, + + 'r','o','s','s','u','m','u','r', // Vendor + + 'm','i','c','r','o','t','o','u', // Product + 'c','h',' ',' ',' ',' ',' ',' ', + + '2','.','4',' ' // Revision +}; + +const u8 P_RequestSense[18] = +{ + 0x70, // Response Code + 0x00, +// 0x02, // Sense Key + 0x00, + 0x00, + + 0x00, + 0x00, + 0x00, + 0x0A, // Additional Length + + 0x00, + 0x00, + 0x00, + 0x00, + + 0x30, // ASC + 0x01, // ASCQ + + 0x00, + 0x00, + 0x00, + 0x00 +}; + +// Save 3 bytes if merging +const u8 P_ReadCapacity[8-3] = +{ +// 0x00, +// 0x00, +// 0x00, // Steal 3 zero bytes from end of P_RequestSense + 64+4, // block count 64 + 4 + 0x00, + 0x00, + 0x02, // block size = 512 + 0x00 +}; + +const u8 P_ModeSense[4] = +{ + 0x03, + 0x00, + 0x00, + 0x00 +}; + +extern volatile u8 _ejected; + +void SCSI(CBW& cbw) +{ + const u8* pgm = 0; + u8 status = 0; + u8 blen = 0; + + u8 cmd = cbw.cb[0]; + if (START_STOP_UNIT == cmd) + { + _ejected = 1; // Stopped; going away + } + else if (TEST_UNIT_READY == cmd || MEDIA_REMOVAL == cmd) + { +#ifdef MSC_NO_MEDIA + status = 1; +#else + status = _ejected; +#endif + } + else if (REQUEST_SENSE == cmd) + { + pgm = P_RequestSense; + blen = sizeof(P_RequestSense); + } + else if (INQUIRY == cmd) + { + pgm = P_Inquiry; + blen = sizeof(P_Inquiry); + } + else if (WRITE10 == cmd || READ10 == cmd) + { + // Write 10 byte form + // Read 10 byte form + { + u8 lba = cbw.cb[5]; + u8 count = cbw.cb[8]; + u8 read = READ10 == cbw.cb[0]; + while (count--) + { + if (read) + SendSector(lba); + else + RecvSector(lba); + lba++; + cbw.transferLength -= 512; // 24 bytes + } + } + } + else if (MODE_SENSE == cmd) + { + pgm = P_ModeSense; + blen = 4; + } + else + { + pgm = P_ReadCapacity-3; + blen = 8; + if (READ_CAPACITY != cmd) + status = 1; // Faking a data phase for unknown commands + } + + if (pgm) + Transfer(MSC_TX | TRANSFER_PGM | TRANSFER_RELEASE,pgm,blen); + + cbw.flags = status; + cbw.transferLength -= blen; + cbw.signature[3] = 'S'; + Transfer(MSC_TX | TRANSFER_RELEASE,(u8*)&cbw,13); +} + +CBW cbw; // 38 byte savings by making this global +void SCSITask() +{ + Recv(MSC_RX,(u8*)&cbw,sizeof(CBW)); + SCSI(cbw); +} + +#endif
\ No newline at end of file |