aboutsummaryrefslogtreecommitdiff
path: root/bootloaders/diskloader/src/SCSI.cpp
diff options
context:
space:
mode:
authorZach Eveland <zeveland@blacklabel-development.com>2011-08-11 10:31:39 -0400
committerZach Eveland <zeveland@blacklabel-development.com>2011-08-11 10:31:39 -0400
commit3e3e4be2a3a0e9ea4186a616f53fa15083b2214f (patch)
tree9d0eaee995723fef99be7dd1e75f9ccbe1690aab /bootloaders/diskloader/src/SCSI.cpp
parentd59bda6ac69ed1d87b57de738c4442888defa537 (diff)
diskloader source and binary for 32u4
Diffstat (limited to 'bootloaders/diskloader/src/SCSI.cpp')
-rw-r--r--bootloaders/diskloader/src/SCSI.cpp213
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