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 media_available;
static uint8_t media_changed;
static uint8_t contingent_allegiance;
static uint8_t keep_contingent_allegiance;
uint8_t media_available;
void msc_media_insert_change (int available)
{
contingent_allegiance = 1;
media_available = available;
media_changed = 1;
if (available)
set_scsi_sense_data (0x06, 0x28); /* UNIT_ATTENTION */
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;
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)
{
@@ -291,36 +280,42 @@ static void msc_send_result (const uint8_t *p, size_t n)
}
void msc_handle_err (int err)
{
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)
void msc_handle_command (void)
{
size_t n;
uint32_t nblocks, secsize;
uint8_t lun;
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;
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;
switch (CBW.CBWCB[0]) {
@@ -331,12 +326,13 @@ int msc_handle_cbw (void)
else
msc_send_result ((uint8_t *)&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);
}
return 1;
return;
case SCSI_INQUIRY:
if (CBW.CBWCB[1] & 0x01) /* EVPD */
/* assume page 00 */
@@ -345,7 +341,7 @@ int msc_handle_cbw (void)
else
msc_send_result ((uint8_t *)&scsi_inquiry_data,
sizeof scsi_inquiry_data);
return 1;
return;
case SCSI_READ_FORMAT_CAPACITIES:
buf[8] = scsi_read_format_capacities (&nblocks, &secsize);
buf[0] = buf[1] = buf[2] = 0;
@@ -358,14 +354,14 @@ int msc_handle_cbw (void)
buf[10] = (uint8_t)(secsize >> 8);
buf[11] = (uint8_t)(secsize >> 0);
msc_send_result (buf, 12);
return 1;
return;
case SCSI_TEST_UNIT_READY:
if (media_available == 0 || media_changed)
if (contingent_allegiance)
{
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
CSW.dCSWDataResidue = 0;
msc_send_result (NULL, 0);
return 1;
return;
}
/* fall through */
case SCSI_SYNCHRONIZE_CACHE:
@@ -375,12 +371,12 @@ int msc_handle_cbw (void)
CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
CSW.dCSWDataResidue = CBW.dCBWDataTransferLength;
msc_send_result (NULL, 0);
return 1;
return;
case SCSI_MODE_SENSE6:
buf[0] = 0x03;
buf[1] = buf[2] = buf[3] = 0;
msc_send_result (buf, 4);
return 1;
return;
case SCSI_READ_CAPACITY10:
scsi_read_format_capacities (&nblocks, &secsize);
buf[0] = (uint8_t)((nblocks - 1) >> 24);
@@ -392,7 +388,7 @@ int msc_handle_cbw (void)
buf[6] = (uint8_t)(secsize >> 8);
buf[7] = (uint8_t)(secsize >> 0);
msc_send_result (buf, 8);
return 1;
return;
case SCSI_READ10:
case SCSI_WRITE10:
break;
@@ -402,12 +398,19 @@ int msc_handle_cbw (void)
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
CSW.dCSWDataResidue = 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)
| (CBW.CBWCB[4] << 8) | CBW.CBWCB[5];
@@ -429,7 +432,7 @@ int msc_handle_cbw (void)
break;
}
if ((p = msc_scsi_read (lun, lba)))
if ((r = msc_scsi_read (lba, &p)) == 0)
{
msc_send_data (p, 512);
if (++CBW.CBWCB[5] == 0)
@@ -443,6 +446,11 @@ int msc_handle_cbw (void)
else
{
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;
}
}
@@ -466,7 +474,7 @@ int msc_handle_cbw (void)
}
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[4] == 0)
@@ -479,6 +487,11 @@ int msc_handle_cbw (void)
else
{
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;
}
}
@@ -486,6 +499,4 @@ int msc_handle_cbw (void)
msc_send_result (NULL, 0);
}
}
return 1;
}

View File

@@ -43,3 +43,10 @@ struct CSW {
uint32_t dCSWDataResidue;
uint8_t bCSWStatus;
} __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;
#define TOTAL_SECTOR 68
/*
blk=0: master boot record sector
@@ -17,7 +19,7 @@ blk=4: fat cluster #2
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 */
0x90, /* NOP */
@@ -29,7 +31,7 @@ static const uint8_t d0_0_sector[512] = {
0x01, 0x00, /* reserved sector count: 1 */
0x02, /* Number of FATs: 2 */
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 */
0x01, 0x00, /* sectors per FAT: 1 */
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 */
0x0e, 0x1f,
0xbe, 0x5b, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b,
0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10,
0x5e, 0xeb, 0xf0, 0x32, 0xe4, 0xcd, 0x16, 0xcd,
0x19,
0xeb, 0xfe, /* loop: jmp loop */
0x0e, /* push cs */
0x1f, /* pop ds */
0xbe, 0x5b, 0x7c, /* mov si, offset message_txt */
0xac, /* 1: lodsb */
0x22, 0xc0, /* and al, al */
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,
0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61,
0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c,
@@ -67,59 +79,14 @@ static const uint8_t d0_0_sector[512] = {
0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74,
0x72, 0x79, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e,
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 */
0xff, 0xff, 0xff, /* cluster 2: used */ /* cluster 3: used */
0xff, 0xff, 0xff, /* cluster 4: used */ /* cluster 5: used */
0xff, 0xff, 0xff, /* cluster 6: used */ /* cluster 7: used */
0xff, 0x0f, 0x00, /* cluster 8: used */ /* cluster 9: free */
0x00,
};
static const uint8_t zero_sector[512] = {
0x00,
};
static uint8_t the_sector[512];
@@ -157,14 +124,13 @@ static uint8_t *fill_file_entry (uint8_t *p, const uint8_t *filename,
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);
int i;
uint8_t filename[11] = { 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20 };
uint8_t child;
uint8_t *p_orig = p;
memset (p, 0, 512);
@@ -184,20 +150,33 @@ static const uint8_t *build_directory_sector (uint8_t *p, uint8_t index)
}
else
break;
return p_orig;
}
const uint8_t *
msc_scsi_read (uint8_t lun, uint32_t lba)
int
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)
{
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 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 4:
case 5:
@@ -206,9 +185,13 @@ msc_scsi_read (uint8_t lun, uint32_t lba)
case 8:
case 9:
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:
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
msc_scsi_write (uint8_t lun, uint32_t lba, const uint8_t *buf, size_t size)
{
if (lba <= 2)
return 1; /* error */
if (!media_available)
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
{
uint8_t index = LBA_TO_FOLDER_INDEX (lba);
parse_directory_sector (buf, index);
return 0;
}
return 1;
}