📄 edb7312-usb.c
字号:
return r;}static void csw_write(struct d12 *p){ struct cbw *cbw; struct csw *csw; cbw = &p->cbw; csw = &p->csw; csw->dCSWDataResidue = cbw->dCBWDataTransferLength - p->bxferptr; if (csw->dCSWDataResidue) { if (cbw->bmCBWFlags & CBW_FLAGS_DIR_IN) { d12_status_set(p, EPX_BULK_I, 1); p->fsm_bulk = FSM_BULK_STALL_TO_CSW; return; } else d12_status_set(p, EPX_BULK_O, 1); } d12_buf_write(p, EPX_BULK_I, &p->csw, sizeof(struct csw)); p->fsm_bulk = FSM_BULK_IDLE;}/* --- */static int lba_chk(struct d12 *p, int lun, __u32 lba, __u32 blks){ if (lba >= p->atd_lba_capacity[lun]) return 1; if (lba + blks > p->atd_lba_capacity[lun]) return 1; p->scsi_lba = lba; p->scsi_blks = blks; return 0;}static void scsi_sense_set(struct d12 *p, int skey, int asc){ unsigned char *b; b = p->scsi_sense; memset (b, 0, MAX_SCSI_DATA_SENSE); b[0] = 0x70; /* current error */ b[2] = skey; b[7] = MAX_SCSI_DATA_SENSE - 8; b[12] = (asc >> 8) & 0xFF; b[13] = (asc >> 0) & 0xFF;}static void scsi_sense_lba_set(struct d12 *p, __u32 lba, int asc){ unsigned char *b; p->csw.bCSWStatus = CSW_STAT_FAILED; scsi_sense_set(p, SCSI_SKEY_MEDIUM_ERROR, asc); b = p->scsi_sense; b[0] |= 0x80; /* valid */ put_32be(b + 3, lba); /* information */}static int scsi_cmd_request_sense(struct d12 *p, int lun){ int r; r = bulk_xfer(p, BULK_IN, p->scsi_sense, MAX_SCSI_DATA_SENSE); scsi_sense_set(p, SCSI_SKEY_NO_SENSE, SCSI_ASC_NO); return r;}static int scsi_cmd_test_unit_ready(struct d12 *p, int lun){ if (p->atd_stat[lun] & ATD_STAT_READY) { scsi_sense_set(p, SCSI_SKEY_NO_SENSE, SCSI_ASC_NO); } else { p->csw.bCSWStatus = CSW_STAT_FAILED; scsi_sense_set(p, SCSI_SKEY_NOT_READY, SCSI_ASC_LOGICAL_UNIT_NOT_READY); } return bulk_xfer(p, BULK_NONE, 0, 0);}static int scsi_cmd_inquiry(struct d12 *p, int lun){ unsigned char *b, *t; b = p->cbw.CBWCB; t = p->tmp; memset(t, 0, MAX_SCSI_DATA_INQUIRY); if ((b[1] & 0x03) || b[2]) /* no CmdDT & EVPD support */ goto err; else { /* standard */// t[0] = 0x00; /* peripheral connected, direct-access device */ t[1] = 0x80; /* RMB = 1 */ t[2] = 0x02; t[3] = 0x02; t[4] = MAX_SCSI_DATA_INQUIRY - 5; memcpy(t + 8, p->scsi_str_vendor[lun], 8); memcpy(t + 16, p->scsi_str_product[lun], 16); memcpy(t + 32, p->scsi_str_revision[lun], 4); } scsi_sense_set(p, SCSI_SKEY_NO_SENSE, SCSI_ASC_NO); return bulk_xfer(p, BULK_IN, t, MAX_SCSI_DATA_INQUIRY);err: return SCHD_ERR_INVALID_CDB;}static int scsi_cmd_read_capacity10(struct d12 *p, int lun){ unsigned char *b, *t; b = p->cbw.CBWCB; t = p->tmp; memset(t, 0, MAX_SCSI_DATA_CAPACITY10); if ((b[1] & 0x01) || (b[8] & 0x01)) /* RELADR & PMI */ goto err; put_32be(t + 0, p->atd_lba_capacity[lun] - 1); /* last LBA */ put_32be(t + 4, p->atd_blk[lun]); /* block size */ scsi_sense_set(p, SCSI_SKEY_NO_SENSE, SCSI_ASC_NO); return bulk_xfer(p, BULK_IN, t, MAX_SCSI_DATA_CAPACITY10);err: return SCHD_ERR_INVALID_CDB;}static int scsi_cmd_read_capacity16(struct d12 *p, int lun){ unsigned char *b, *t; b = p->cbw.CBWCB; t = p->tmp; memset(t, 0, MAX_SCSI_DATA_CAPACITY16); if (((b[1] & 0x1F) != 0x10) || (b[14] & 0x03)) /* RELADR & PMI */ goto err; put_64be(t + 0, p->atd_lba_capacity[lun] - 1); /* last LBA */ put_32be(t + 8, p->atd_blk[lun]); /* block size */ scsi_sense_set(p, SCSI_SKEY_NO_SENSE, SCSI_ASC_NO); return bulk_xfer(p, BULK_IN, t, MAX_SCSI_DATA_CAPACITY16);err: return SCHD_ERR_INVALID_CDB;}static void bhd_read(struct d12 *p, int lun, int len){ volatile struct dioreq *dio; int blks; dio = &p->dio; blks = (p->scsi_blks > p->atd_chunkblk[lun]) ? p->atd_chunkblk[lun] : p->scsi_blks; if (blks) { dio->cmd = DIO_CMD_READ; dio->lun = lun; dio->lba = p->scsi_lba; dio->blks = blks; dio->buf = p->chunkbuf; up(&p->wait_dio_cmd); p->scsi_lba += blks; p->scsi_blks -= blks; }}static int do_read(struct d12 *p, int lun, __u32 lba, __u32 blks){ volatile struct dioreq *dio; int r; if (lba_chk(p, lun, lba, blks)) goto lbaerr; scsi_sense_set(p, SCSI_SKEY_NO_SENSE, SCSI_ASC_NO); dio = &p->dio; r = bulk_xfer_chk(p, BULK_IN, blks * p->atd_blk[lun]); if (!r && blks) { p->bhd = bhd_read; if (blks > p->atd_chunkblk[lun]) blks = p->atd_chunkblk[lun]; dio->cmd = DIO_CMD_READ; dio->lun = lun; dio->lba = lba; dio->blks = blks; dio->buf = p->chunkbuf; up(&p->wait_dio_cmd); p->scsi_lba += blks; p->scsi_blks -= blks; } return r;lbaerr: return SCHD_ERR_INVALID_LBA;}static int scsi_cmd_read6(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; lba = get_u32be(b + 0) & 0x001FFFFF; blks = b[4]; if (!blks) blks = 256; return do_read(p, lun, lba, blks);}static int scsi_cmd_read10(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; if (b[1] & 0x01) /* RELADR */ goto err; lba = get_u32be(b + 2); blks = get_u16be(b + 7); return do_read(p, lun, lba, blks);err: return SCHD_ERR_INVALID_CDB;}static int scsi_cmd_read12(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; if (b[1] & 0x01) /* RELADR */ goto err; lba = get_u32be(b + 2); blks = get_u32be(b + 6); return do_read(p, lun, lba, blks);err: return SCHD_ERR_INVALID_CDB;}static int scsi_cmd_read16(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; if (b[1] & 0x01) /* RELADR */ goto err; lba = get_u64be(b + 2); blks = get_u32be(b + 10); return do_read(p, lun, lba, blks);err: return SCHD_ERR_INVALID_CDB;}static void bhd_write(struct d12 *p, int lun, int len){ volatile struct dioreq *dio; int blks; dio = &p->dio; blks = len / p->atd_blk[lun]; if (blks) { p->scsi_lba += blks; p->scsi_blks -= blks; dio->cmd = DIO_CMD_WRITE; dio->lun = lun; dio->lba = p->scsi_lba - blks; dio->blks = blks; dio->nblks = p->scsi_blks; dio->buf = p->chunkbuf; up(&p->wait_dio_cmd); }}static int do_write(struct d12 *p, int lun, __u32 lba, __u32 blks){ int r; if (lba_chk(p, lun, lba, blks)) goto lbaerr; scsi_sense_set(p, SCSI_SKEY_NO_SENSE, SCSI_ASC_NO); r = bulk_xfer_chk(p, BULK_OUT, blks * p->atd_blk[lun]); if (!r && blks) { p->bhd = bhd_write; ep_bulk_read(p, p->chunkbuf, blks * p->atd_blk[lun]); } return r;lbaerr: return SCHD_ERR_INVALID_LBA;}static int scsi_cmd_write6(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; lba = get_u32be(b + 0) & 0x001FFFFF; blks = b[4]; if (!blks) blks = 256; return do_write(p, lun, lba, blks);}static int scsi_cmd_write10(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; if (b[1] & 0x01) /* RELADR */ goto err; lba = get_u32be(b + 2); blks = get_u16be(b + 7); return do_write(p, lun, lba, blks);err: return SCHD_ERR_INVALID_CDB;}static int scsi_cmd_write12(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; if (b[1] & 0x01) /* RELADR */ goto err; lba = get_u32be(b + 2); blks = get_u32be(b + 6); return do_write(p, lun, lba, blks);err: return SCHD_ERR_INVALID_CDB;}static int scsi_cmd_write16(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; if (b[1] & 0x01) /* RELADR */ goto err; lba = get_u64be(b + 2); blks = get_u32be(b + 10); return do_write(p, lun, lba, blks);err: return SCHD_ERR_INVALID_CDB;}static int do_verify(struct d12 *p, int lun, __u32 lba, __u32 blks){ volatile struct dioreq *dio; int r; if (lba_chk(p, lun, lba, blks)) goto lbaerr; scsi_sense_set(p, SCSI_SKEY_NO_SENSE, SCSI_ASC_NO); dio = &p->dio; r = bulk_xfer_chk(p, BULK_NONE, 0); if (!r && blks) { p->cswdelay = 1; dio->cmd = DIO_CMD_VERIFY; dio->lun = lun; dio->lba = lba; dio->blks = blks; up(&p->wait_dio_cmd); } return r;lbaerr: return SCHD_ERR_INVALID_LBA;}static int scsi_cmd_verify10(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; if (b[1] & 0x07) /* BLKVFY, BYTCHK & RELADR */ goto err; lba = get_u32be(b + 2); blks = get_u16be(b + 7); return do_verify(p, lun, lba, blks);err: return SCHD_ERR_INVALID_CDB;}static int scsi_cmd_verify12(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; if (b[1] & 0x07) /* BLKVFY, BYTCHK & RELADR */ goto err; lba = get_u32be(b + 2); blks = get_u32be(b + 6); return do_verify(p, lun, lba, blks);err: return SCHD_ERR_INVALID_CDB;}static int scsi_cmd_verify16(struct d12 *p, int lun){ unsigned char *b; __u32 lba, blks; b = p->cbw.CBWCB; if (b[1] & 0x07) /* BLKVFY, BYTCHK & RELADR */ goto err; lba = get_u64be(b + 2); blks = get_u32be(b + 10); return do_verify(p, lun, lba, blks);err: return SCHD_ERR_INVALID_CDB;}/* --- */struct scsi_cmd_hd { int len; int (*hd)(struct d12 *, int);};static const struct scsi_cmd_hd T_SCSI_HD[256] = { {6, scsi_cmd_test_unit_ready}, /* 0x00 */ {0, 0}, /* 0x01 */ {0, 0}, /* 0x02 */ {0, scsi_cmd_request_sense}, /* 0x03 */ {0, 0}, /* 0x04 */ {0, 0}, /* 0x05 */ {0, 0}, /* 0x06 */ {0, 0}, /* 0x07 */ {6, scsi_cmd_read6}, /* 0x08 */ {0, 0}, /* 0x09 */ {6, scsi_cmd_write6}, /* 0x0A */ {0, 0}, /* 0x0B */ {0, 0}, /* 0x0C */ {0, 0}, /* 0x0D */ {0, 0}, /* 0x0E */ {0, 0}, /* 0x0F */ {0, 0}, /* 0x10 */ {0, 0}, /* 0x11 */ {6, scsi_cmd_inquiry}, /* 0x12 */ {0, 0}, /* 0x13 */ {0, 0}, /* 0x14 */ {0, 0}, /* 0x15 */ {0, 0}, /* 0x16 */ {0, 0}, /* 0x17 */ {0, 0}, /* 0x18 */ {0, 0}, /* 0x19 */ {0, 0}, /* 0x1A */ {0, 0}, /* 0x1B */ {0, 0}, /* 0x1C */ {0, 0}, /* 0x1D */ {0, 0}, /* 0x1E */ {0, 0}, /* 0x1F */ {0, 0}, /* 0x20 */ {0, 0}, /* 0x21 */ {0, 0}, /* 0x22 */ {0, 0}, /* 0x23 */ {0, 0}, /* 0x24 */ {10, scsi_cmd_read_capacity10}, /* 0x25 */ {0, 0}, /* 0x26 */ {0, 0}, /* 0x27 */ {10, scsi_cmd_read10}, /* 0x28 */ {0, 0}, /* 0x29 */ {10, scsi_cmd_write10}, /* 0x2A */ {0, 0}, /* 0x2B */ {0, 0}, /* 0x2C */ {0, 0}, /* 0x2D */ {0, 0}, /* 0x2E */ {10, scsi_cmd_verify10}, /* 0x2F */ {0, 0}, /* 0x30 */ {0, 0}, /* 0x31 */ {0, 0}, /* 0x32 */ {0, 0}, /* 0x33 */ {0, 0}, /* 0x34 */ {0, 0}, /* 0x35 */ {0, 0}, /* 0x36 */ {0, 0}, /* 0x37 */ {0, 0}, /* 0x38 */ {0, 0}, /* 0x39 */ {0, 0}, /* 0x3A */ {0, 0}, /* 0x3B */ {0, 0}, /* 0x3C */ {0, 0}, /* 0x3D */ {0, 0}, /* 0x3E */ {0, 0}, /* 0x3F */ {0, 0}, /* 0x40 */ {0, 0}, /* 0x41 */ {0, 0}, /* 0x42 */ {0, 0}, /* 0x43 */ {0, 0}, /* 0x44 */ {0, 0}, /* 0x45 */ {0, 0}, /* 0x46 */ {0, 0}, /* 0x47 */ {0, 0}, /* 0x48 */ {0, 0}, /* 0x49 */ {0, 0}, /* 0x4A */ {0, 0}, /* 0x4B */ {0, 0}, /* 0x4C */ {0, 0}, /* 0x4D */ {0, 0}, /* 0x4E */ {0, 0}, /* 0x4F */ {0, 0}, /* 0x50 */ {0, 0}, /* 0x51 */ {0, 0}, /* 0x52 */ {0, 0}, /* 0x53 */ {0, 0}, /* 0x54 */ {0, 0}, /* 0x55 */ {0, 0}, /* 0x56 */ {0, 0}, /* 0x57 */ {0, 0}, /* 0x58 */ {0, 0}, /* 0x59 */ {0, 0}, /* 0x5A */ {0, 0}, /* 0x5B */ {0, 0}, /* 0x5C */ {0, 0}, /* 0x5D */ {0, 0}, /* 0x5E */ {0, 0}, /* 0x5F */ {0, 0}, /* 0x60 */ {0, 0}, /* 0x61 */ {0, 0}, /* 0x62 */ {0, 0}, /* 0x63 */ {0, 0}, /* 0x64 */ {0, 0}, /* 0x65 */ {0, 0}, /* 0x66 */ {0, 0}, /* 0x67 */ {0, 0}, /* 0x68 */ {0, 0}, /* 0x69 */ {0, 0}, /* 0x6A */ {0, 0}, /* 0x6B */ {0, 0}, /* 0x6C */ {0, 0}, /* 0x6D */ {0, 0}, /* 0x6E */ {0, 0}, /* 0x6F */ {0, 0}, /* 0x70 */ {0, 0}, /* 0x71 */ {0, 0}, /* 0x72 */ {0, 0}, /* 0x73 */ {0, 0}, /* 0x74 */ {0, 0}, /* 0x75 */ {0, 0}, /* 0x76 */ {0, 0}, /* 0x77 */ {0, 0}, /* 0x78 */ {0, 0}, /* 0x79 */ {0, 0}, /* 0x7A */ {0, 0}, /* 0x7B */ {0, 0}, /* 0x7C */ {0, 0}, /* 0x7D */ {0, 0}, /* 0x7E */ {0, 0}, /* 0x7F */ {0, 0}, /* 0x80 */ {0, 0}, /* 0x81 */ {0, 0}, /* 0x82 */ {0, 0}, /* 0x83 */ {0, 0}, /* 0x84 */ {0, 0}, /* 0x85 */ {0, 0}, /* 0x86 */ {0, 0}, /* 0x87 */ {16, scsi_cmd_read16}, /* 0x88 */ {0, 0}, /* 0x89 */ {16, scsi_cmd_write16}, /* 0x8A */ {0, 0}, /* 0x8B */ {0, 0}, /* 0x8C */ {0, 0}, /* 0x8D */ {0, 0}, /* 0x8E */ {16, scsi_cmd_verify16}, /* 0x8F */ {0, 0}, /* 0x90 */ {0, 0}, /* 0x91 */ {0, 0}, /* 0x92 */ {0, 0}, /* 0x93 */ {0, 0}, /* 0x94 */ {0, 0}, /* 0x95 */ {0, 0}, /* 0x96 */ {0, 0}, /* 0x97 */ {0, 0}, /* 0x98 */ {0, 0}, /* 0x99 */ {0, 0}, /* 0x9A */ {0, 0}, /* 0x9B */ {0, 0}, /* 0x9C */ {0, 0}, /* 0x9D */ {16, scsi_cmd_read_capacity16}, /* 0x9E */ {0, 0}, /* 0x9F */ {0, 0}, /* 0xA0 */ {0, 0}, /* 0xA1 */ {0, 0}, /* 0xA2 */ {0, 0}, /* 0xA3 */ {0, 0}, /* 0xA4 */ {0, 0}, /* 0xA5 */ {0, 0}, /* 0xA6 */ {0, 0}, /* 0xA7 */ {12, scsi_cmd_read12}, /* 0xA8 */ {0, 0}, /* 0xA9 */ {12, scsi_cmd_write12}, /* 0xAA */ {0, 0}, /* 0xAB */ {0, 0}, /* 0xAC */ {0, 0}, /* 0xAD */ {0, 0}, /* 0xAE */ {12, scsi_cmd_verify12}, /* 0xAF */ {0, 0}, /* 0xB0 */ {0, 0}, /* 0xB1 */ {0, 0}, /* 0xB2 */ {0, 0}, /* 0xB3 */ {0, 0}, /* 0xB4 */ {0, 0}, /* 0xB5 */ {0, 0}, /* 0xB6 */ {0, 0}, /* 0xB7 */ {0, 0}, /* 0xB8 */ {0, 0}, /* 0xB9 */ {0, 0}, /* 0xBA */ {0, 0}, /* 0xBB */ {0, 0}, /* 0xBC */ {0, 0}, /* 0xBD */ {0, 0}, /* 0xBE */ {0, 0}, /* 0xBF */ {0, 0}, /* 0xC0 */ {0, 0}, /* 0xC1 */ {0, 0}, /* 0xC2 */ {0, 0}, /* 0xC3 */ {0, 0}, /* 0xC4 */ {0, 0}, /* 0xC5 */ {0, 0}, /* 0xC6 */ {0, 0}, /* 0xC7 */ {0, 0}, /* 0xC8 */ {0, 0}, /* 0xC9 */ {0, 0}, /* 0xCA */ {0, 0}, /* 0xCB */ {0, 0}, /* 0xCC */ {0, 0}, /* 0xCD */ {0, 0}, /* 0xCE */ {0, 0}, /* 0xCF */ {0, 0}, /* 0xD0 */ {0, 0}, /* 0xD1 */ {0, 0}, /* 0xD2 */ {0, 0}, /* 0xD3 */ {0, 0}, /* 0xD4 */ {0, 0}, /* 0xD5 */ {0, 0}, /* 0xD6 */ {0, 0}, /* 0xD7 */ {0, 0}, /* 0xD8 */ {0, 0}, /* 0xD9 */ {0, 0}, /* 0xDA */ {0, 0}, /* 0xDB */ {0, 0}, /* 0xDC */ {0, 0}, /* 0xDD */ {0, 0}, /* 0xDE */ {0, 0}, /* 0xDF */ {0, 0}, /* 0xE0 */ {0, 0}, /* 0xE1 */ {0, 0}, /* 0xE2 */ {0, 0}, /* 0xE3 */ {0, 0}, /* 0xE4 */ {0, 0}, /* 0xE5 */ {0, 0}, /* 0xE6 */ {0, 0}, /* 0xE7 */ {0, 0}, /* 0xE8 */ {0, 0}, /* 0xE9 */ {0, 0}, /* 0xEA */ {0, 0}, /* 0xEB */ {0, 0}, /* 0xEC */ {0, 0}, /* 0xED */ {0, 0}, /* 0xEE */ {0, 0}, /* 0xEF */ {0, 0}, /* 0xF0 */ {0, 0}, /* 0xF1 */ {0, 0}, /* 0xF2 */ {0, 0}, /* 0xF3 */ {0, 0}, /* 0xF4 */ {0, 0}, /* 0xF5 */ {0, 0}, /* 0xF6 */ {0, 0}, /* 0xF7 */ {0, 0}, /* 0xF8 */ {0, 0}, /* 0xF9 */ {0, 0}, /* 0xFA */ {0, 0}, /* 0xFB */ {0, 0}, /* 0xFC */ {0, 0}, /* 0xFD */ {0, 0}, /* 0xFE */ {0, 0} /* 0xFF */};/* ------------------------------------------------------------------------- *//* * interrupt handler and supporting functions */static void ep0_rx(struct d12 *p){ struct devreq *drq; int stat, len, req; stat = d12_read_last_trans(p, EPX_CTRL_O); if (!(stat & D_READ_LTRNS_SUCCESS))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -