This commit is contained in:
NIIBE Yutaka
2011-12-09 15:05:34 +09:00
parent 696de23b52
commit 231c50d9b5
3 changed files with 134 additions and 128 deletions

View File

@@ -193,17 +193,22 @@ static void set_scsi_sense_data(uint8_t sense_key, uint8_t asc) {
static uint8_t buf[512]; static uint8_t buf[512];
static uint8_t media_available; static uint8_t contingent_allegiance;
static uint8_t media_changed; static uint8_t keep_contingent_allegiance;
uint8_t media_available;
void msc_media_insert_change (int available) void msc_media_insert_change (int available)
{ {
contingent_allegiance = 1;
media_available = available; media_available = available;
media_changed = 1;
if (available) if (available)
set_scsi_sense_data (0x06, 0x28); /* UNIT_ATTENTION */ set_scsi_sense_data (0x06, 0x28); /* UNIT_ATTENTION */
else else
set_scsi_sense_data (0x02, 0x3a); /* NOT_READY */ {
set_scsi_sense_data (0x02, 0x3a); /* NOT_READY */
keep_contingent_allegiance = 1;
}
} }
@@ -222,22 +227,6 @@ static struct CBW CBW;
static struct CSW CSW; static struct CSW CSW;
int msc_recv_cbw (void)
{
msg_t msg;
chSysLock();
msc_state = MSC_IDLE;
the_thread = chThdSelf ();
usb_start_receive ((uint8_t *)&CBW, sizeof CBW);
chSchGoSleepTimeoutS (THD_STATE_SUSPENDED, MS2ST (1000));
msg = chThdSelf ()->p_u.rdymsg;
chSysUnlock ();
if (msg == RDY_OK)
return 0;
else
return -1;
}
static int msc_recv_data (void) static int msc_recv_data (void)
{ {
@@ -291,36 +280,42 @@ static void msc_send_result (const uint8_t *p, size_t n)
} }
void msc_handle_err (int err) void msc_handle_command (void)
{
if (err == 0)
{
msc_state = MSC_ERROR;
chSysLock ();
usb_stall_receive ();
chSysUnlock ();
}
else
{
msc_state = MSC_ERROR;
chSysLock ();
usb_stall_transmit ();
usb_stall_receive ();
chSysUnlock ();
}
}
int msc_handle_cbw (void)
{ {
size_t n; size_t n;
uint32_t nblocks, secsize; uint32_t nblocks, secsize;
uint8_t lun;
uint32_t lba; uint32_t lba;
int r;
msg_t msg;
chSysLock();
msc_state = MSC_IDLE;
the_thread = chThdSelf ();
usb_start_receive ((uint8_t *)&CBW, sizeof CBW);
chSchGoSleepTimeoutS (THD_STATE_SUSPENDED, MS2ST (1000));
msg = chThdSelf ()->p_u.rdymsg;
chSysUnlock ();
if (msg != RDY_OK)
{
/* Error occured, ignore the request and go into error state */
msc_state = MSC_ERROR;
chSysLock ();
usb_stall_receive ();
chSysUnlock ();
return;
}
n = ep7_out.rxcnt; n = ep7_out.rxcnt;
if ((n != sizeof (struct CBW)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE)) if ((n != sizeof (struct CBW)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE))
return 0; {
msc_state = MSC_ERROR;
chSysLock ();
usb_stall_receive ();
chSysUnlock ();
return;
}
CSW.dCSWTag = CBW.dCBWTag; CSW.dCSWTag = CBW.dCBWTag;
switch (CBW.CBWCB[0]) { switch (CBW.CBWCB[0]) {
@@ -331,12 +326,13 @@ int msc_handle_cbw (void)
else else
msc_send_result ((uint8_t *)&scsi_sense_data_fixed, msc_send_result ((uint8_t *)&scsi_sense_data_fixed,
sizeof scsi_sense_data_fixed); sizeof scsi_sense_data_fixed);
if (media_changed && media_available) /* After the error is reported, clear it, if it's . */
if (!keep_contingent_allegiance)
{ {
media_changed = 0; contingent_allegiance = 0;
set_scsi_sense_data (0x00, 0x00); set_scsi_sense_data (0x00, 0x00);
} }
return 1; return;
case SCSI_INQUIRY: case SCSI_INQUIRY:
if (CBW.CBWCB[1] & 0x01) /* EVPD */ if (CBW.CBWCB[1] & 0x01) /* EVPD */
/* assume page 00 */ /* assume page 00 */
@@ -345,7 +341,7 @@ int msc_handle_cbw (void)
else else
msc_send_result ((uint8_t *)&scsi_inquiry_data, msc_send_result ((uint8_t *)&scsi_inquiry_data,
sizeof scsi_inquiry_data); sizeof scsi_inquiry_data);
return 1; return;
case SCSI_READ_FORMAT_CAPACITIES: case SCSI_READ_FORMAT_CAPACITIES:
buf[8] = scsi_read_format_capacities (&nblocks, &secsize); buf[8] = scsi_read_format_capacities (&nblocks, &secsize);
buf[0] = buf[1] = buf[2] = 0; buf[0] = buf[1] = buf[2] = 0;
@@ -358,14 +354,14 @@ int msc_handle_cbw (void)
buf[10] = (uint8_t)(secsize >> 8); buf[10] = (uint8_t)(secsize >> 8);
buf[11] = (uint8_t)(secsize >> 0); buf[11] = (uint8_t)(secsize >> 0);
msc_send_result (buf, 12); msc_send_result (buf, 12);
return 1; return;
case SCSI_TEST_UNIT_READY: case SCSI_TEST_UNIT_READY:
if (media_available == 0 || media_changed) if (contingent_allegiance)
{ {
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
CSW.dCSWDataResidue = 0; CSW.dCSWDataResidue = 0;
msc_send_result (NULL, 0); msc_send_result (NULL, 0);
return 1; return;
} }
/* fall through */ /* fall through */
case SCSI_SYNCHRONIZE_CACHE: case SCSI_SYNCHRONIZE_CACHE:
@@ -375,12 +371,12 @@ int msc_handle_cbw (void)
CSW.bCSWStatus = MSC_CSW_STATUS_PASSED; CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
CSW.dCSWDataResidue = CBW.dCBWDataTransferLength; CSW.dCSWDataResidue = CBW.dCBWDataTransferLength;
msc_send_result (NULL, 0); msc_send_result (NULL, 0);
return 1; return;
case SCSI_MODE_SENSE6: case SCSI_MODE_SENSE6:
buf[0] = 0x03; buf[0] = 0x03;
buf[1] = buf[2] = buf[3] = 0; buf[1] = buf[2] = buf[3] = 0;
msc_send_result (buf, 4); msc_send_result (buf, 4);
return 1; return;
case SCSI_READ_CAPACITY10: case SCSI_READ_CAPACITY10:
scsi_read_format_capacities (&nblocks, &secsize); scsi_read_format_capacities (&nblocks, &secsize);
buf[0] = (uint8_t)((nblocks - 1) >> 24); buf[0] = (uint8_t)((nblocks - 1) >> 24);
@@ -392,7 +388,7 @@ int msc_handle_cbw (void)
buf[6] = (uint8_t)(secsize >> 8); buf[6] = (uint8_t)(secsize >> 8);
buf[7] = (uint8_t)(secsize >> 0); buf[7] = (uint8_t)(secsize >> 0);
msc_send_result (buf, 8); msc_send_result (buf, 8);
return 1; return;
case SCSI_READ10: case SCSI_READ10:
case SCSI_WRITE10: case SCSI_WRITE10:
break; break;
@@ -402,12 +398,19 @@ int msc_handle_cbw (void)
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
CSW.dCSWDataResidue = 0; CSW.dCSWDataResidue = 0;
msc_send_result (NULL, 0); msc_send_result (NULL, 0);
return 1; return;
}
else
{
msc_state = MSC_ERROR;
chSysLock ();
usb_stall_transmit ();
usb_stall_receive ();
chSysUnlock ();
return;
} }
return -1;
} }
lun = CBW.bCBWLUN;
lba = (CBW.CBWCB[2] << 24) | (CBW.CBWCB[3] << 16) lba = (CBW.CBWCB[2] << 24) | (CBW.CBWCB[3] << 16)
| (CBW.CBWCB[4] << 8) | CBW.CBWCB[5]; | (CBW.CBWCB[4] << 8) | CBW.CBWCB[5];
@@ -429,7 +432,7 @@ int msc_handle_cbw (void)
break; break;
} }
if ((p = msc_scsi_read (lun, lba))) if ((r = msc_scsi_read (lba, &p)) == 0)
{ {
msc_send_data (p, 512); msc_send_data (p, 512);
if (++CBW.CBWCB[5] == 0) if (++CBW.CBWCB[5] == 0)
@@ -443,6 +446,11 @@ int msc_handle_cbw (void)
else else
{ {
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
contingent_allegiance = 1;
if (r == SCSI_ERROR_NOT_READY)
set_scsi_sense_data (SCSI_ERROR_NOT_READY, 0x3a);
else
set_scsi_sense_data (r, 0x00);
break; break;
} }
} }
@@ -466,7 +474,7 @@ int msc_handle_cbw (void)
} }
msc_recv_data (); msc_recv_data ();
if (msc_scsi_write (lun, lba, buf, 512)) if ((r = msc_scsi_write (lba, buf, 512)) == 0)
{ {
if (++CBW.CBWCB[5] == 0) if (++CBW.CBWCB[5] == 0)
if (++CBW.CBWCB[4] == 0) if (++CBW.CBWCB[4] == 0)
@@ -479,6 +487,11 @@ int msc_handle_cbw (void)
else else
{ {
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
contingent_allegiance = 1;
if (r == SCSI_ERROR_NOT_READY)
set_scsi_sense_data (SCSI_ERROR_NOT_READY, 0x3a);
else
set_scsi_sense_data (r, 0x00);
break; break;
} }
} }
@@ -486,6 +499,4 @@ int msc_handle_cbw (void)
msc_send_result (NULL, 0); msc_send_result (NULL, 0);
} }
} }
return 1;
} }

View File

@@ -43,3 +43,10 @@ struct CSW {
uint32_t dCSWDataResidue; uint32_t dCSWDataResidue;
uint8_t bCSWStatus; uint8_t bCSWStatus;
} __attribute__((packed)); } __attribute__((packed));
#define SCSI_ERROR_NOT_READY 2
#define SCSI_ERROR_ILLEAGAL_REQUEST 5
#define SCSI_ERROR_UNIT_ATTENTION 6
#define SCSI_ERROR_DATA_PROTECT 7
extern uint8_t media_available;

View File

@@ -6,6 +6,8 @@
extern Thread *main_thread; extern Thread *main_thread;
#define TOTAL_SECTOR 68
/* /*
blk=0: master boot record sector blk=0: master boot record sector
@@ -17,7 +19,7 @@ blk=4: fat cluster #2
blk=4+63: fat cluster #2+63 blk=4+63: fat cluster #2+63
*/ */
static const uint8_t d0_0_sector[512] = { static const uint8_t d0_0_sector[] = {
0xeb, 0x3c, /* Jump instruction */ 0xeb, 0x3c, /* Jump instruction */
0x90, /* NOP */ 0x90, /* NOP */
@@ -29,7 +31,7 @@ static const uint8_t d0_0_sector[512] = {
0x01, 0x00, /* reserved sector count: 1 */ 0x01, 0x00, /* reserved sector count: 1 */
0x02, /* Number of FATs: 2 */ 0x02, /* Number of FATs: 2 */
0x10, 0x00, /* Max. root directory entries: 16 (1 sector) */ 0x10, 0x00, /* Max. root directory entries: 16 (1 sector) */
0x44, 0x00, /* total sectors: 68 */ TOTAL_SECTOR, 0x00, /* total sectors: 68 */
0xf8, /* media descriptor: fixed disk */ 0xf8, /* media descriptor: fixed disk */
0x01, 0x00, /* sectors per FAT: 1 */ 0x01, 0x00, /* sectors per FAT: 1 */
0x04, 0x00, /* sectors per track: 4 */ 0x04, 0x00, /* sectors per track: 4 */
@@ -46,14 +48,24 @@ static const uint8_t d0_0_sector[512] = {
0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, /* FAT12 */ 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, /* FAT12 */
0x0e, 0x1f, 0x0e, /* push cs */
0xbe, 0x5b, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b, 0x1f, /* pop ds */
0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0xbe, 0x5b, 0x7c, /* mov si, offset message_txt */
0x5e, 0xeb, 0xf0, 0x32, 0xe4, 0xcd, 0x16, 0xcd, 0xac, /* 1: lodsb */
0x19, 0x22, 0xc0, /* and al, al */
0xeb, 0xfe, /* loop: jmp loop */ 0x74, 0x0b, /* jz 2f */
0x56, /* push si */
0xb4, 0x0e, /* mov ah, 0eh */
0xbb, 0x07, 0x00, /* mov bx, 0007h */
0xcd, 0x10, /* int 10h ; output char color=white */
0x5e, /* pop si */
0xeb, 0xf0, /* jmp 1b */
0x32, 0xe4, /* 2: xor ah, ah */
0xcd, 0x16, /* int 16h; key input */
0xcd, 0x19, /* int 19h; load OS */
0xeb, 0xfe, /* 3: jmp 3b */
/* "Thisis not a bootable disk... \r\n" */ /* "This is not a bootable disk... \r\n" */
0x54, 0x68, 0x69, 0x73, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20,
0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61,
0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c,
@@ -67,61 +79,16 @@ static const uint8_t d0_0_sector[512] = {
0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74,
0x72, 0x79, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x72, 0x79, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e,
0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x0d, 0x0a, 0x00, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x0d, 0x0a, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
}; };
static const uint8_t d0_fat0_sector[512] = { static const uint8_t d0_fat0_sector[] = {
0xf8, 0xff, 0xff, /* Media descriptor: fixed disk */ /* EOC */ 0xf8, 0xff, 0xff, /* Media descriptor: fixed disk */ /* EOC */
0xff, 0xff, 0xff, /* cluster 2: used */ /* cluster 3: used */ 0xff, 0xff, 0xff, /* cluster 2: used */ /* cluster 3: used */
0xff, 0xff, 0xff, /* cluster 4: used */ /* cluster 5: used */ 0xff, 0xff, 0xff, /* cluster 4: used */ /* cluster 5: used */
0xff, 0xff, 0xff, /* cluster 6: used */ /* cluster 7: used */ 0xff, 0xff, 0xff, /* cluster 6: used */ /* cluster 7: used */
0xff, 0x0f, 0x00, /* cluster 8: used */ /* cluster 9: free */ 0xff, 0x0f, 0x00, /* cluster 8: used */ /* cluster 9: free */
0x00,
}; };
static const uint8_t zero_sector[512] = {
0x00,
};
static uint8_t the_sector[512]; static uint8_t the_sector[512];
struct folder { struct folder {
@@ -157,14 +124,13 @@ static uint8_t *fill_file_entry (uint8_t *p, const uint8_t *filename,
return p; return p;
} }
static const uint8_t *build_directory_sector (uint8_t *p, uint8_t index) static void build_directory_sector (uint8_t *p, uint8_t index)
{ {
uint16_t cluster_no = FOLDER_INDEX_TO_CLUSTER_NO (index); uint16_t cluster_no = FOLDER_INDEX_TO_CLUSTER_NO (index);
int i; int i;
uint8_t filename[11] = { 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, uint8_t filename[11] = { 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20 }; 0x20, 0x20, 0x20 };
uint8_t child; uint8_t child;
uint8_t *p_orig = p;
memset (p, 0, 512); memset (p, 0, 512);
@@ -184,20 +150,33 @@ static const uint8_t *build_directory_sector (uint8_t *p, uint8_t index)
} }
else else
break; break;
return p_orig;
} }
const uint8_t * int
msc_scsi_read (uint8_t lun, uint32_t lba) msc_scsi_read (uint32_t lba, const uint8_t **sector_p)
{ {
if (!media_available)
return SCSI_ERROR_NOT_READY;
if (lba >= TOTAL_SECTOR)
return SCSI_ERROR_ILLEAGAL_REQUEST;
switch (lba) switch (lba)
{ {
case 0: case 0:
return d0_0_sector; *sector_p = the_sector;
memcpy (the_sector, d0_0_sector, sizeof d0_0_sector);
memset (the_sector + sizeof d0_0_sector, 0, 512 - sizeof d0_0_sector);
the_sector[510] = 0x55;
the_sector[511] = 0xaa;
return 0;
case 1: case 1:
case 2: case 2:
return d0_fat0_sector; *sector_p = the_sector;
memcpy (the_sector, d0_fat0_sector, sizeof d0_fat0_sector);
memset (the_sector + sizeof d0_fat0_sector, 0,
512 - sizeof d0_fat0_sector);
return 0;
case 3: case 3:
case 4: case 4:
case 5: case 5:
@@ -206,9 +185,13 @@ msc_scsi_read (uint8_t lun, uint32_t lba)
case 8: case 8:
case 9: case 9:
case 10: case 10:
return build_directory_sector (the_sector, LBA_TO_FOLDER_INDEX (lba)); *sector_p = the_sector;
build_directory_sector (the_sector, LBA_TO_FOLDER_INDEX (lba));
return 0;
default: default:
return zero_sector; *sector_p = the_sector;
memset (the_sector, 0, 512);
return 0;
} }
} }
@@ -258,14 +241,19 @@ static void parse_directory_sector (const uint8_t *p, uint8_t index)
int int
msc_scsi_write (uint8_t lun, uint32_t lba, const uint8_t *buf, size_t size) msc_scsi_write (uint8_t lun, uint32_t lba, const uint8_t *buf, size_t size)
{ {
if (lba <= 2) if (!media_available)
return 1; /* error */ return SCSI_ERROR_NOT_READY;
if (lba >= TOTAL_SECTOR)
return SCSI_ERROR_ILLEAGAL_REQUEST;
if (lba <= 2 || lba >= 11)
return SCSI_ERROR_DATA_PROTECT;
else else
{ {
uint8_t index = LBA_TO_FOLDER_INDEX (lba); uint8_t index = LBA_TO_FOLDER_INDEX (lba);
parse_directory_sector (buf, index); parse_directory_sector (buf, index);
return 0;
} }
return 1;
} }