Make SCSI structs and definitions complete. Change all CDB size 6 commands to format version2, version 3, soon.

This commit is contained in:
Andrew J. Kroll 2013-09-20 01:41:36 -04:00
parent 643972ad51
commit fee903bbac
2 changed files with 394 additions and 243 deletions

View file

@ -54,6 +54,22 @@ boolean BulkOnly::WriteProtected(uint8_t lun) {
return WriteOk[lun]; return WriteOk[lun];
} }
/**
* Wrap and execute a SCSI CDB with length of 6
*
* @param cdb CDB to execute
* @param buf_size Size of expected transaction
* @param buf Buffer
* @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
* @return
*/
uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
// promote to 32bits.
CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
SetCurLUN(cdb->LUN);
return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
}
/** /**
* Lock or Unlock the tray or door on device. * Lock or Unlock the tray or door on device.
* Caution: Some devices with buggy firmware will lock up. * Caution: Some devices with buggy firmware will lock up.
@ -65,24 +81,8 @@ boolean BulkOnly::WriteProtected(uint8_t lun) {
uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) { uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
Notify(PSTR("\r\nLockMedia\r\n"), 0x80); Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
Notify(PSTR("---------\r\n"), 0x80); Notify(PSTR("---------\r\n"), 0x80);
CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock);
CommandBlockWrapper cbw; return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN);
SetCurLUN(lun);
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = 0;
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 6;
for (uint8_t i = 0; i < 16; i++)
cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = SCSI_CMD_PREVENT_REMOVAL;
cbw.CBWCB[4] = lock;
return (HandleSCSIError(Transaction(&cbw, 0, NULL, 0)));
} }
/** /**
@ -96,26 +96,17 @@ uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) { uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
Notify(PSTR("\r\nMediaCTL\r\n"), 0x80); Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
Notify(PSTR("-----------------\r\n"), 0x80); Notify(PSTR("-----------------\r\n"), 0x80);
SetCurLUN(lun); //SetCurLUN(lun);
uint8_t rcode = MASS_ERR_UNIT_NOT_READY; uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
if (bAddress) { if (bAddress) {
CommandBlockWrapper cbw; //CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, 0, MASS_CMD_DIR_OUT, lun, 6, SCSI_CMD_START_STOP_UNIT);
//cbw.CBWCB[1] = lun << 5;
cbw.dCBWSignature = MASS_CBW_SIGNATURE; //cbw.CBWCB[4] = ctl & 0x03;
cbw.dCBWTag = ++dCBWTag; //rcode = HandleSCSIError(Transaction(&cbw, 0, NULL));
cbw.dCBWDataTransferLength = 0; CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);
cbw.bmCBWFlags = MASS_CMD_DIR_OUT; rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT);
cbw.bmCBWLUN = lun; } else {
cbw.bmCBWCBLength = 6; SetCurLUN(lun);
for (uint8_t i = 0; i < 16; i++)
cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = SCSI_CMD_START_STOP_UNIT;
cbw.CBWCB[1] = lun << 5;
cbw.CBWCB[4] = ctl & 0x03;
rcode = HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
} }
return rcode; return rcode;
} }
@ -142,28 +133,18 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
Notify(PSTR("\r\nblock size:\t"), 0x90); Notify(PSTR("\r\nblock size:\t"), 0x90);
D_PrintHex<uint16_t > (bsize, 0x90); D_PrintHex<uint16_t > (bsize, 0x90);
Notify(PSTR("\r\n---------\r\n"), 0x80); Notify(PSTR("\r\n---------\r\n"), 0x80);
CommandBlockWrapper cbw; CommandBlockWrapper cbw = CommandBlockWrapper(0, ((uint32_t)bsize * blocks), MASS_CMD_DIR_IN, lun, 10, SCSI_CMD_READ_10);
again:
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 10;
for (uint8_t i = 0; i < 16; i++)
cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = SCSI_CMD_READ_10;
cbw.CBWCB[1] = lun << 5; cbw.CBWCB[1] = lun << 5;
cbw.CBWCB[2] = ((addr >> 24) & 0xff); cbw.CBWCB[2] = ((addr >> 24) & 0xff);
cbw.CBWCB[3] = ((addr >> 16) & 0xff); cbw.CBWCB[3] = ((addr >> 16) & 0xff);
cbw.CBWCB[4] = ((addr >> 8) & 0xff); cbw.CBWCB[4] = ((addr >> 8) & 0xff);
cbw.CBWCB[5] = (addr & 0xff); cbw.CBWCB[5] = (addr & 0xff);
cbw.CBWCB[8] = blocks; cbw.CBWCB[8] = blocks;
again:
cbw.dCBWTag = ++dCBWTag; cbw.dCBWTag = ++dCBWTag;
SetCurLUN(lun); SetCurLUN(lun);
uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, buf, 0)); uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, buf));
if (er == MASS_ERR_STALL) { if (er == MASS_ERR_STALL) {
MediaCTL(lun, 1); MediaCTL(lun, 1);
delay(150); delay(150);
@ -196,20 +177,7 @@ uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t bloc
D_PrintHex<uint16_t > (bsize, 0x90); D_PrintHex<uint16_t > (bsize, 0x90);
Notify(PSTR("\r\n---------\r\n"), 0x80); Notify(PSTR("\r\n---------\r\n"), 0x80);
//MediaCTL(lun, 0x01); //MediaCTL(lun, 0x01);
CommandBlockWrapper cbw; CommandBlockWrapper cbw = CommandBlockWrapper(0, ((uint32_t)bsize * blocks), MASS_CMD_DIR_OUT, lun, 10, SCSI_CMD_WRITE_10);
again:
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
cbw.bmCBWFlags = MASS_CMD_DIR_OUT;
cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 10;
for (uint8_t i = 0; i < 16; i++)
cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = SCSI_CMD_WRITE_10;
cbw.CBWCB[1] = lun << 5; cbw.CBWCB[1] = lun << 5;
cbw.CBWCB[2] = ((addr >> 24) & 0xff); cbw.CBWCB[2] = ((addr >> 24) & 0xff);
cbw.CBWCB[3] = ((addr >> 16) & 0xff); cbw.CBWCB[3] = ((addr >> 16) & 0xff);
@ -217,8 +185,10 @@ again:
cbw.CBWCB[5] = (addr & 0xff); cbw.CBWCB[5] = (addr & 0xff);
cbw.CBWCB[8] = 1; cbw.CBWCB[8] = 1;
again:
cbw.dCBWTag = ++dCBWTag;
SetCurLUN(lun); SetCurLUN(lun);
uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, (void*)buf, 0)); uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, (void*)buf));
if (er == MASS_ERR_WRITE_STALL) { if (er == MASS_ERR_WRITE_STALL) {
MediaCTL(lun, 1); MediaCTL(lun, 1);
delay(150); delay(150);
@ -243,7 +213,7 @@ bIface(0),
bNumEP(1), bNumEP(1),
qNextPollTime(0), qNextPollTime(0),
bPollEnable(false), bPollEnable(false),
dCBWTag(0), //dCBWTag(0),
bLastUsbError(0) { bLastUsbError(0) {
ClearAllEP(); ClearAllEP();
dCBWTag = 0; dCBWTag = 0;
@ -692,23 +662,15 @@ uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
Notify(PSTR("\r\nInquiry\r\n"), 0x80); Notify(PSTR("\r\nInquiry\r\n"), 0x80);
Notify(PSTR("---------\r\n"), 0x80); Notify(PSTR("---------\r\n"), 0x80);
CommandBlockWrapper cbw; //CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, bsize, MASS_CMD_DIR_IN, lun, 6, SCSI_CMD_INQUIRY);
SetCurLUN(lun); //SetCurLUN(lun);
cbw.dCBWSignature = MASS_CBW_SIGNATURE; //cbw.CBWCB[1] = lun << 5;
cbw.dCBWTag = ++dCBWTag; //cbw.CBWCB[4] = bsize;
cbw.dCBWDataTransferLength = bsize;
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 6;
for (uint8_t i = 0; i < 16; i++) //uint8_t rc = HandleSCSIError(Transaction(&cbw, bsize, buf));
cbw.CBWCB[i] = 0; CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0);
uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);
cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
cbw.CBWCB[1] = lun << 5;
cbw.CBWCB[4] = bsize;
uint8_t rc = HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
#if 0 #if 0
if (!rc) { if (!rc) {
printf("LUN %i `", lun); printf("LUN %i `", lun);
@ -752,6 +714,54 @@ uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
return rc; return rc;
} }
/**
* For driver use only.
*
* @param lun Logical Unit Number
* @return
*/
uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
//SetCurLUN(lun);
if (!bAddress)
return MASS_ERR_UNIT_NOT_READY;
Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
Notify(PSTR("-----------------\r\n"), 0x80);
//CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, 0, MASS_CMD_DIR_OUT, lun, 6, SCSI_CMD_TEST_UNIT_READY);
//cbw.CBWCB[1] = lun;
//uint8_t rc = HandleSCSIError(Transaction(&cbw, 0, NULL));
//return (rc);
CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0);
return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN);
}
/**
* For driver use only.
*
* @param lun Logical Unit Number
* @param pc
* @param page
* @param subpage
* @param len
* @param pbuf
* @return
*/
uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
Notify(PSTR("\r\rModeSense\r\n"), 0x80);
Notify(PSTR("------------\r\n"), 0x80);
//CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, ((uint32_t)len), MASS_CMD_DIR_IN, lun, 6, SCSI_CMD_MODE_SENSE_6);
//SetCurLUN(lun);
//cbw.CBWCB[2] = ((pc << 6) | page);
//cbw.CBWCB[3] = subpage;
//cbw.CBWCB[4] = len;
//return HandleSCSIError(Transaction(&cbw, 512, pbuf));
CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage) , len, 0);
return SCSITransaction6(&cdb, 512, pbuf, (uint8_t)MASS_CMD_DIR_IN);
}
/** /**
* For driver use only. * For driver use only.
* *
@ -764,87 +774,16 @@ uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
Notify(PSTR("\r\nRequestSense\r\n"), 0x80); Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
Notify(PSTR("----------------\r\n"), 0x80); Notify(PSTR("----------------\r\n"), 0x80);
CommandBlockWrapper cbw;
//CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, size, MASS_CMD_DIR_IN, lun, 6, SCSI_CMD_REQUEST_SENSE);
//SetCurLUN(lun);
//cbw.CBWCB[1] = lun << 5;
//cbw.CBWCB[4] = size;
CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0);
CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);
SetCurLUN(lun); SetCurLUN(lun);
return Transaction(&cbw, size, buf);
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = size;
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 6;
for (uint8_t i = 0; i < 16; i++)
cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE;
cbw.CBWCB[1] = lun << 5;
cbw.CBWCB[4] = size;
return Transaction(&cbw, size, buf, 0);
}
/**
* For driver use only.
*
* @param lun Logical Unit Number
* @param bsize
* @param buf
* @return
*/
uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
Notify(PSTR("---------------\r\n"), 0x80);
CommandBlockWrapper cbw;
SetCurLUN(lun);
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = bsize;
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 10;
for (uint8_t i = 0; i < 16; i++)
cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = SCSI_CMD_READ_CAPACITY_10;
cbw.CBWCB[1] = lun << 5;
return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
}
/**
* For driver use only.
*
* @param lun Logical Unit Number
* @return
*/
uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
SetCurLUN(lun);
if (!bAddress)
return MASS_ERR_UNIT_NOT_READY;
Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
Notify(PSTR("-----------------\r\n"), 0x80);
CommandBlockWrapper cbw;
uint8_t rc;
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = 0;
cbw.bmCBWFlags = MASS_CMD_DIR_OUT;
cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 6;
for (uint8_t i = 0; i < 16; i++)
cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = SCSI_CMD_TEST_UNIT_READY;
cbw.CBWCB[1] = lun;
rc = HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
return (rc);
} }
/** /**
@ -874,6 +813,25 @@ uint8_t BulkOnly::Page3F(uint8_t lun) {
return rc; return rc;
} }
/**
* For driver use only.
*
* @param lun Logical Unit Number
* @param bsize
* @param buf
* @return
*/
uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
Notify(PSTR("---------------\r\n"), 0x80);
CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, bsize, MASS_CMD_DIR_IN, lun, 10, SCSI_CMD_READ_CAPACITY_10);
SetCurLUN(lun);
cbw.CBWCB[1] = lun << 5;
return HandleSCSIError(Transaction(&cbw, bsize, buf));
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1056,6 +1014,13 @@ uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS); return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
} }
#if WANT_PARSER
uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
}
#endif
/** /**
* For driver use only. * For driver use only.
* *
@ -1065,16 +1030,24 @@ uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
* @param flags * @param flags
* @return * @return
*/ */
uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, uint8_t flags) { uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
#if WANT_PARSER
, uint8_t flags
#endif
) {
uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength; uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
boolean write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN; boolean write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
#if WANT_PARSER
boolean callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK; boolean callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
#endif
uint8_t ret = 0; uint8_t ret = 0;
uint8_t usberr; uint8_t usberr;
CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles. CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
// Not needed any longer, the constructor ensures this now
// Fix reserved bits. // Fix reserved bits.
pcbw->bmReserved1 = 0; //pcbw->bmReserved1 = 0;
pcbw->bmReserved2 = 0; //pcbw->bmReserved2 = 0;
ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1); while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
@ -1086,13 +1059,18 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
} else { } else {
if (bytes) { if (bytes) {
if (!write) { if (!write) {
#if WANT_PARSER
if (callback) { if (callback) {
uint8_t rbuf[bytes]; uint8_t rbuf[bytes];
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1); while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0); if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
} else { } else {
#endif
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1); while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
#if WANT_PARSER
} }
#endif
ret = HandleUsbError(usberr, epDataInIndex); ret = HandleUsbError(usberr, epDataInIndex);
} else { } else {
while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1); while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
@ -1104,7 +1082,6 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
} }
} }
//if (!ret || ret == MASS_ERR_WRITE_STALL || ret == MASS_ERR_STALL) {
{ {
bytes = sizeof (CommandStatusWrapper); bytes = sizeof (CommandStatusWrapper);
int tries = 2; int tries = 2;
@ -1112,7 +1089,6 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1); while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
if (!usberr) break; if (!usberr) break;
ClearEpHalt(epDataInIndex); ClearEpHalt(epDataInIndex);
//HandleUsbError(usberr, epDataInIndex);
if (tries) ResetRecovery(); if (tries) ResetRecovery();
} }
if (!ret) { if (!ret) {
@ -1120,7 +1096,6 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
Notify(PSTR("Data Stage:\tOK\r\n"), 0x80); Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
} else { } else {
// Throw away csw, IT IS NOT OF ANY USE. // Throw away csw, IT IS NOT OF ANY USE.
//HandleUsbError(usberr, epDataInIndex);
ResetRecovery(); ResetRecovery();
return ret; return ret;
} }
@ -1151,42 +1126,6 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
return ret; return ret;
} }
/**
* For driver use only.
*
* @param lun Logical Unit Number
* @param pc
* @param page
* @param subpage
* @param len
* @param pbuf
* @return
*/
uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
Notify(PSTR("\r\rModeSense\r\n"), 0x80);
Notify(PSTR("------------\r\n"), 0x80);
CommandBlockWrapper cbw;
SetCurLUN(lun);
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = ((uint32_t)len);
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 6;
for (uint8_t i = 0; i < 16; i++)
cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = SCSI_CMD_MODE_SENSE_6;
cbw.CBWCB[2] = ((pc << 6) | page);
cbw.CBWCB[3] = subpage;
cbw.CBWCB[4] = len;
return HandleSCSIError(Transaction(&cbw, 512, pbuf, 0));
}
/** /**
* For driver use only. * For driver use only.
* *
@ -1325,11 +1264,11 @@ void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {
/* We won't be needing this... */ /* We won't be needing this... */
uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) { uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA; if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
#if 0 #if WANT_PARSER
Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80); Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
Notify(PSTR("---------\r\n"), 0x80); Notify(PSTR("---------\r\n"), 0x80);
CommandBlockWrapper cbw; CommandBlockWrapper cbw = CommandBlockWrapper();
cbw.dCBWSignature = MASS_CBW_SIGNATURE; cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag; cbw.dCBWTag = ++dCBWTag;
@ -1338,8 +1277,8 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
cbw.bmCBWLUN = lun; cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 10; cbw.bmCBWCBLength = 10;
for (uint8_t i = 0; i < 16; i++) //for (uint8_t i = 0; i < 16; i++)
cbw.CBWCB[i] = 0; // cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = SCSI_CMD_READ_10; cbw.CBWCB[0] = SCSI_CMD_READ_10;
cbw.CBWCB[8] = blocks; cbw.CBWCB[8] = blocks;
@ -1351,25 +1290,3 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
return HandleSCSIError(Transaction(&cbw, bsize, prs, 1)); return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
#endif #endif
} }
#if 0
// TO-DO: Unify CBW creation as much as possible.
// Make and submit CBW.
// if stalled, delay retry
// exit on 100 retries, or anything except stall.
uint8_t SubmitCBW(uint8_t cmd, uint8_t cmdsz, uint8_t lun, uint16_t bsize, uint8_t *buf, uint8_t flags) {
CommandBlockWrapper cbw;
SetCurLUN(lun);
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = bsize;
cbw.bmCBWFlags = flags;
cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = cmdsz;
for (uint8_t i = 0; i < 16; i++) cbw.CBWCB[i] = 0;
cbw.CBWCB[0] = cmd;
cbw.CBWCB[1] = lun << 5;
cbw.CBWCB[4] = bsize;
}
#endif

View file

@ -9,7 +9,14 @@
// <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>> // <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>>
// Set this to 1 to support single LUN devices, and save RAM. -- I.E. thumb drives. // Set this to 1 to support single LUN devices, and save RAM. -- I.E. thumb drives.
// Each LUN needs ~13 bytes to be able to track the state of each unit. // Each LUN needs ~13 bytes to be able to track the state of each unit.
#ifndef MASS_MAX_SUPPORTED_LUN
#define MASS_MAX_SUPPORTED_LUN 8 #define MASS_MAX_SUPPORTED_LUN 8
#endif
// Cruft removal, makes driver smaller, faster.
#ifndef WANT_PARSER
#define WANT_PARSER 0
#endif
#include <inttypes.h> #include <inttypes.h>
#include "avrpins.h" #include "avrpins.h"
@ -64,32 +71,98 @@
#define MASS_CBW_SIGNATURE 0x43425355 #define MASS_CBW_SIGNATURE 0x43425355
#define MASS_CSW_SIGNATURE 0x53425355 #define MASS_CSW_SIGNATURE 0x53425355
#define MASS_CMD_DIR_OUT (0 << 7) #define MASS_CMD_DIR_OUT 0 // (0 << 7)
#define MASS_CMD_DIR_IN (1 << 7) #define MASS_CMD_DIR_IN 0x80 //(1 << 7)
#define SCSI_CMD_INQUIRY 0x12 /*
#define SCSI_CMD_REPORT_LUNS 0xA0 * Reference documents from T10 (http://www.t10.org)
* SCSI Primary Commands - 3 (SPC-3)
* SCSI Block Commands - 2 (SBC-2)
* Multi-Media Commands - 5 (MMC-5)
*/
/* Group 1 commands (CDB's here are should all be 6-bytes) */
#define SCSI_CMD_TEST_UNIT_READY 0x00
#define SCSI_CMD_REQUEST_SENSE 0x03 #define SCSI_CMD_REQUEST_SENSE 0x03
#define SCSI_CMD_FORMAT_UNIT 0x04 #define SCSI_CMD_FORMAT_UNIT 0x04
#define SCSI_CMD_READ_6 0x08 #define SCSI_CMD_READ_6 0x08
#define SCSI_CMD_READ_10 0x28
#define SCSI_CMD_READ_CAPACITY_10 0x25
#define SCSI_CMD_TEST_UNIT_READY 0x00
#define SCSI_CMD_WRITE_6 0x0A #define SCSI_CMD_WRITE_6 0x0A
#define SCSI_CMD_WRITE_10 0x2A #define SCSI_CMD_INQUIRY 0x12
#define SCSI_CMD_MODE_SELECT_6 0x15
#define SCSI_CMD_MODE_SENSE_6 0x1A #define SCSI_CMD_MODE_SENSE_6 0x1A
#define SCSI_CMD_MODE_SENSE_10 0x5A
#define SCSI_CMD_START_STOP_UNIT 0x1B #define SCSI_CMD_START_STOP_UNIT 0x1B
#define SCSI_CMD_PREVENT_REMOVAL 0x1E #define SCSI_CMD_PREVENT_REMOVAL 0x1E
/* Group 2 Commands (CDB's here are 10-bytes) */
#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23
#define SCSI_CMD_READ_CAPACITY_10 0x25
#define SCSI_CMD_READ_10 0x28
#define SCSI_CMD_WRITE_10 0x2A
#define SCSI_CMD_SEEK_10 0x2B
#define SCSI_CMD_ERASE_10 0x2C
#define SCSI_CMD_WRITE_AND_VERIFY_10 0x2E
#define SCSI_CMD_VERIFY_10 0x2F
#define SCSI_CMD_SYNCHRONIZE_CACHE 0x35
#define SCSI_CMD_WRITE_BUFFER 0x3B
#define SCSI_CMD_READ_BUFFER 0x3C
#define SCSI_CMD_READ_SUBCHANNEL 0x42
#define SCSI_CMD_READ_TOC 0x43
#define SCSI_CMD_READ_HEADER 0x44
#define SCSI_CMD_PLAY_AUDIO_10 0x45
#define SCSI_CMD_GET_CONFIGURATION 0x46
#define SCSI_CMD_PLAY_AUDIO_MSF 0x47
#define SCSI_CMD_PLAY_AUDIO_TI 0x48
#define SCSI_CMD_PLAY_TRACK_REL_10 0x49
#define SCSI_CMD_GET_EVENT_STATUS 0x4A
#define SCSI_CMD_PAUSE_RESUME 0x4B
#define SCSI_CMD_READ_DISC_INFORMATION 0x51
#define SCSI_CMD_READ_TRACK_INFORMATION 0x52
#define SCSI_CMD_RESERVE_TRACK 0x53
#define SCSI_CMD_SEND_OPC_INFORMATION 0x54
#define SCSI_CMD_MODE_SELECT_10 0x55
#define SCSI_CMD_REPAIR_TRACK 0x58
#define SCSI_CMD_MODE_SENSE_10 0x5A
#define SCSI_CMD_CLOSE_TRACK_SESSION 0x5B
#define SCSI_CMD_READ_BUFFER_CAPACITY 0x5C
#define SCSI_CMD_SEND_CUE_SHEET 0x5D
/* Group 5 Commands (CDB's here are 12-bytes) */
#define SCSI_CMD_REPORT_LUNS 0xA0
#define SCSI_CMD_BLANK 0xA1
#define SCSI_CMD_SECURITY_PROTOCOL_IN 0xA2
#define SCSI_CMD_SEND_KEY 0xA3
#define SCSI_CMD_REPORT_KEY 0xA4
#define SCSI_CMD_PLAY_AUDIO_12 0xA5
#define SCSI_CMD_LOAD_UNLOAD 0xA6
#define SCSI_CMD_SET_READ_AHEAD 0xA7
#define SCSI_CMD_READ_12 0xA8
#define SCSI_CMD_PLAY_TRACK_REL_12 0xA9
#define SCSI_CMD_WRITE_12 0xAA
#define SCSI_CMD_READ_MEDIA_SERIAL_12 0xAB
#define SCSI_CMD_GET_PERFORMANCE 0xAC
#define SCSI_CMD_READ_DVD_STRUCTURE 0xAD
#define SCSI_CMD_SECURITY_PROTOCOL_OUT 0xB5
#define SCSI_CMD_SET_STREAMING 0xB6
#define SCSI_CMD_READ_MSF 0xB9
#define SCSI_CMD_SET_SPEED 0xBB
#define SCSI_CMD_MECHANISM_STATUS 0xBD
#define SCSI_CMD_READ_CD 0xBE
#define SCSI_CMD_SEND_DISC_STRUCTURE 0xBF
/* Vendor-unique Commands, included for completeness */
#define SCSI_CMD_CD_PLAYBACK_STATUS 0xC4 /* SONY unique */
#define SCSI_CMD_PLAYBACK_CONTROL 0xC9 /* SONY unique */
#define SCSI_CMD_READ_CDDA 0xD8 /* Vendor unique */
#define SCSI_CMD_READ_CDXA 0xDB /* Vendor unique */
#define SCSI_CMD_READ_ALL_SUBCODES 0xDF /* Vendor unique */
/* SCSI error codes */
#define SCSI_S_NOT_READY 0x02 #define SCSI_S_NOT_READY 0x02
#define SCSI_S_MEDIUM_ERROR 0x03 #define SCSI_S_MEDIUM_ERROR 0x03
#define SCSI_S_ILLEGAL_REQUEST 0x05 #define SCSI_S_ILLEGAL_REQUEST 0x05
#define SCSI_S_UNIT_ATTENTION 0x06 #define SCSI_S_UNIT_ATTENTION 0x06
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21 #define SCSI_ASC_LBA_OUT_OF_RANGE 0x21
#define SCSI_ASC_MEDIA_CHANGED 0x28 #define SCSI_ASC_MEDIA_CHANGED 0x28
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
/* USB error codes */
#define MASS_ERR_SUCCESS 0x00 #define MASS_ERR_SUCCESS 0x00
#define MASS_ERR_PHASE_ERROR 0x02 #define MASS_ERR_PHASE_ERROR 0x02
#define MASS_ERR_UNIT_NOT_READY 0x03 #define MASS_ERR_UNIT_NOT_READY 0x03
@ -123,6 +196,116 @@ struct Capacity {
//uint32_t dwBlockLength; //uint32_t dwBlockLength;
} __attribute__((packed)); } __attribute__((packed));
struct CDB6 {
uint8_t Opcode;
unsigned LBAMSB : 5;
unsigned LUN : 3;
uint8_t LBAHB;
uint8_t LBALB;
uint8_t AllocationLength;
uint8_t Control;
public:
CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) :
Opcode(_Opcode), LUN(_LUN), LBAMSB((LBA >>16) & 0x1f), LBAHB((LBA >> 8) & 0xff), LBALB(LBA & 0xff),
AllocationLength(_AllocationLength), Control(_Control) {}
CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) :
Opcode(_Opcode), LUN(_LUN), LBAMSB(0), LBAHB(0), LBALB(0),
AllocationLength(_AllocationLength), Control(_Control) {}
} __attribute__((packed));
typedef CDB6 CDB6_t;
struct CDB10 {
uint8_t Opcode;
unsigned Service_Action : 5;
unsigned Misc : 3;
uint8_t LBA_L_M_MB;
uint8_t LBA_L_M_LB;
uint8_t LBA_L_L_MB;
uint8_t LBA_L_L_LB;
uint8_t Misc2;
uint8_t ALC_MB;
uint8_t ALC_LB;
uint8_t Control;
};
typedef CDB10 CDB10_t;
struct CDB12 {
uint8_t Opcode;
unsigned Service_Action : 5;
unsigned Misc : 3;
uint8_t LBA_L_M_LB;
uint8_t LBA_L_L_MB;
uint8_t LBA_L_L_LB;
uint8_t ALC_M_LB;
uint8_t ALC_L_MB;
uint8_t ALC_L_LB;
uint8_t Control;
};
typedef CDB12 CDB12_t;
struct CDB_LBA32_16 {
uint8_t Opcode;
unsigned Service_Action : 5;
unsigned Misc : 3;
uint8_t LBA_L_M_MB;
uint8_t LBA_L_M_LB;
uint8_t LBA_L_L_MB;
uint8_t LBA_L_L_LB;
uint8_t A_M_M_MB;
uint8_t A_M_M_LB;
uint8_t A_M_L_MB;
uint8_t A_M_L_LB;
uint8_t ALC_M_MB;
uint8_t ALC_M_LB;
uint8_t ALC_L_MB;
uint8_t ALC_L_LB;
uint8_t Misc2;
uint8_t Control;
};
struct CDB_LBA64_16 {
uint8_t Opcode;
uint8_t Misc;
uint8_t LBA_M_M_MB;
uint8_t LBA_M_M_LB;
uint8_t LBA_M_L_MB;
uint8_t LBA_M_L_LB;
uint8_t LBA_L_M_MB;
uint8_t LBA_L_M_LB;
uint8_t LBA_L_L_MB;
uint8_t LBA_L_L_LB;
uint8_t ALC_M_MB;
uint8_t ALC_M_LB;
uint8_t ALC_L_MB;
uint8_t ALC_L_LB;
uint8_t Misc2;
uint8_t Control;
};
struct InquiryResponse { struct InquiryResponse {
uint8_t DeviceType : 5; uint8_t DeviceType : 5;
uint8_t PeripheralQualifier : 3; uint8_t PeripheralQualifier : 3;
@ -133,13 +316,29 @@ struct InquiryResponse {
uint8_t Version; uint8_t Version;
unsigned ResponseDataFormat : 4; unsigned ResponseDataFormat : 4;
unsigned Reserved2 : 1; unsigned HISUP : 1;
unsigned NormACA : 1; unsigned NormACA : 1;
unsigned TrmTsk : 1; unsigned TrmTsk : 1;
unsigned AERC : 1; unsigned AERC : 1;
uint8_t AdditionalLength; uint8_t AdditionalLength;
uint8_t Reserved3[2]; //uint8_t Reserved3[2];
unsigned PROTECT : 1;
unsigned Res : 2;
unsigned ThreePC : 1;
unsigned TPGS : 2;
unsigned ACC : 1;
unsigned SCCS : 1;
unsigned ADDR16 : 1;
unsigned R1 : 1;
unsigned R2 : 1;
unsigned MCHNGR : 1;
unsigned MULTIP : 1;
unsigned VS : 1;
unsigned ENCSERV : 1;
unsigned BQUE : 1;
unsigned SoftReset : 1; unsigned SoftReset : 1;
unsigned CmdQue : 1; unsigned CmdQue : 1;
@ -160,6 +359,14 @@ struct CommandBlockWrapperBase {
uint32_t dCBWTag; uint32_t dCBWTag;
uint32_t dCBWDataTransferLength; uint32_t dCBWDataTransferLength;
uint8_t bmCBWFlags; uint8_t bmCBWFlags;
public:
CommandBlockWrapperBase() {
}
CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) :
dCBWSignature(MASS_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) {
}
} __attribute__((packed)); } __attribute__((packed));
struct CommandBlockWrapper : public CommandBlockWrapperBase { struct CommandBlockWrapper : public CommandBlockWrapperBase {
@ -175,6 +382,26 @@ struct CommandBlockWrapper : public CommandBlockWrapperBase {
}; };
uint8_t CBWCB[16]; uint8_t CBWCB[16];
CommandBlockWrapper() : bmReserved1(0), bmReserved2(0) {
for(uint8_t i = 0; i < 16; i++) CBWCB[i] = 0;
}
public:
// Generic Wrap
CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) :
CommandBlockWrapperBase(tag, xflen, flgs),
bmReserved1(0), bmReserved2(0), bmCBWLUN(lu), bmCBWCBLength(cmdlen) {
for(uint8_t i = 1; i < cmdlen; i++) CBWCB[i] = 0;
CBWCB[0] = cmd;
}
// Wrap for CDB of 6
CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB6_t *cdb, uint8_t dir) :
CommandBlockWrapperBase(tag, xflen, dir),
bmReserved1(0), bmReserved2(0), bmCBWLUN(cdb->LUN), bmCBWCBLength(6) {
memcpy(CBWCB, cdb, 6);
}
} __attribute__((packed)); } __attribute__((packed));
struct CommandStatusWrapper { struct CommandStatusWrapper {
@ -275,8 +502,12 @@ public:
// UsbConfigXtracter implementation // UsbConfigXtracter implementation
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
virtual boolean DEVCLASSOK(uint8_t klass) { return (klass == USB_CLASS_MASS_STORAGE); }
virtual boolean DEVCLASSOK(uint8_t klass) {
return(klass == USB_CLASS_MASS_STORAGE);
}
uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
private: private:
uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf); uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
@ -298,7 +529,10 @@ private:
bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw); bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw);
uint8_t ClearEpHalt(uint8_t index); uint8_t ClearEpHalt(uint8_t index);
#if WANT_PARSER
uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags); uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);
#endif
uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf);
uint8_t HandleUsbError(uint8_t error, uint8_t index); uint8_t HandleUsbError(uint8_t error, uint8_t index);
uint8_t HandleSCSIError(uint8_t status); uint8_t HandleSCSIError(uint8_t status);