|
|
| version 1.3, 2005/03/05 06:02:28 | version 1.4, 2005/03/05 11:58:02 |
|---|---|
| Line 1 | Line 1 |
| #include "compiler.h" | #include "compiler.h" |
| #ifdef TRACEOUT | |
| #undef TRACEOUT | |
| #endif | |
| #define TRACEOUT(s) trace_fmt s | |
| // これ、scsicmdとどう統合するのよ? | // これ、scsicmdとどう統合するのよ? |
| #if defined(SUPPORT_IDEIO) | #if defined(SUPPORT_IDEIO) |
| Line 32 static void senddata(IDEDRV drv, UINT si | Line 37 static void senddata(IDEDRV drv, UINT si |
| size = min(size, limit); | size = min(size, limit); |
| drv->sc = IDEINTR_IO; | drv->sc = IDEINTR_IO; |
| drv->cy = size; | drv->cy = size; |
| drv->status &= ~IDESTAT_BSY; | drv->status &= ~(IDESTAT_BSY|IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); |
| drv->status |= IDESTAT_DRQ; | drv->status |= IDESTAT_DRQ; |
| drv->error = 0; | drv->error = 0; |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); | |
| drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; | |
| drv->bufdir = IDEDIR_IN; | drv->bufdir = IDEDIR_IN; |
| drv->buftc = IDETC_TRANSFEREND; | |
| drv->bufpos = 0; | drv->bufpos = 0; |
| drv->bufsize = size; | drv->bufsize = size; |
| ideio.bank[0] = ideio.bank[1] | 0x80; // ???? | if (!(drv->ctrl & IDECTRL_NIEN)) { |
| pic_setirq(IDE_IRQ); | TRACEOUT(("atapicmd: senddata()")); |
| ideio.bank[0] = ideio.bank[1] | 0x80; // ???? | |
| pic_setirq(IDE_IRQ); | |
| } | |
| } | |
| static void cmddone(IDEDRV drv) { | |
| drv->sc = IDEINTR_IO|IDEINTR_CD; | |
| drv->status &= ~(IDESTAT_BSY|IDESTAT_DRQ|IDESTAT_SERV|IDESTAT_CHK); | |
| drv->status |= IDESTAT_DRDY; | |
| drv->error = 0; | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); | |
| drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; | |
| if (!(drv->ctrl & IDECTRL_NIEN)) { | |
| TRACEOUT(("atapicmd: cmddone()")); | |
| ideio.bank[0] = ideio.bank[1] | 0x80; // ???? | |
| pic_setirq(IDE_IRQ); | |
| } | |
| } | |
| static void senderror(IDEDRV drv) { | |
| drv->sc = IDEINTR_IO; | |
| drv->status &= ~(IDESTAT_BSY|IDESTAT_DMRD|IDESTAT_SERV); | |
| drv->status |= IDESTAT_CHK; | |
| if (!(drv->ctrl & IDECTRL_NIEN)) { | |
| TRACEOUT(("atapicmd: senderror()")); | |
| ideio.bank[0] = ideio.bank[1] | 0x80; // ???? | |
| pic_setirq(IDE_IRQ); | |
| } | |
| } | |
| static void sendabort(IDEDRV drv) { | |
| drv->sk = ATAPI_SK_ABORTED_COMMAND; | |
| drv->error = IDEERR_ABRT; | |
| senderror(drv); | |
| } | } |
| // ----- ATAPI packet command | // ----- ATAPI packet command |
| static void atapi_cmd_start_stop_unit(IDEDRV drv); | |
| static void atapi_cmd_prevent_allow_medium_removal(IDEDRV drv); | |
| static void atapi_cmd_read_capacity(IDEDRV drv); | |
| static void atapi_cmd_read(IDEDRV drv, UINT32 lba, UINT32 leng); | |
| static void atapi_cmd_mode_select(IDEDRV drv); | |
| static void atapi_cmd_mode_sense(IDEDRV drv); | |
| static void atapi_cmd_readtoc(IDEDRV drv); | |
| void atapicmd_a0(IDEDRV drv) { | void atapicmd_a0(IDEDRV drv) { |
| UINT32 lba, leng; | |
| UINT8 cmd; | UINT8 cmd; |
| UINT leng; | |
| cmd = drv->buf[0]; | cmd = drv->buf[0]; |
| switch(cmd) { | switch (cmd) { |
| case 0x12: // inquiry | case 0x00: // test unit ready |
| TRACEOUT(("atapicmd: inquiry")); | TRACEOUT(("atapicmd: test unit ready")); |
| leng = drv->buf[4]; | if (!(drv->media & IDEIO_MEDIA_LOADED)) { |
| CopyMemory(drv->buf, cdrom_inquiry, sizeof(cdrom_inquiry)); | /* medium not present */ |
| senddata(drv, sizeof(cdrom_inquiry), leng); | ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); |
| drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; | |
| senderror(drv); | |
| break; | break; |
| } | |
| if (drv->media & IDEIO_MEDIA_CHANGED) { | |
| drv->media &= ~IDEIO_MEDIA_CHANGED; | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); | |
| drv->asc = ATAPI_ASC_NOT_READY_TO_READY_TRANSITION; | |
| senderror(drv); | |
| break; | |
| } | |
| cmddone(drv); | |
| break; | |
| case 0x03: // request sense | |
| TRACEOUT(("atapicmd: request sense")); | |
| leng = drv->buf[4]; | |
| ZeroMemory(drv->buf, 18); | |
| drv->buf[0] = 0x70; | |
| drv->buf[2] = drv->sk; | |
| drv->buf[7] = 11; // length | |
| drv->buf[12] = (BYTE)(drv->asc & 0xff); | |
| senddata(drv, 18, leng); | |
| break; | |
| case 0x12: // inquiry | |
| TRACEOUT(("atapicmd: inquiry")); | |
| leng = drv->buf[4]; | |
| CopyMemory(drv->buf, cdrom_inquiry, sizeof(cdrom_inquiry)); | |
| senddata(drv, sizeof(cdrom_inquiry), leng); | |
| break; | |
| case 0x1b: // start stop unit | |
| TRACEOUT(("atapicmd: start stop unit")); | |
| atapi_cmd_start_stop_unit(drv); | |
| break; | |
| case 0x1e: // prevent allow medium removal | |
| TRACEOUT(("atapicmd: prevent allow medium removal")); | |
| atapi_cmd_prevent_allow_medium_removal(drv); | |
| break; | |
| case 0x25: // read capacity | |
| TRACEOUT(("atapicmd: read capacity")); | |
| atapi_cmd_read_capacity(drv); | |
| break; | |
| case 0x28: // read(10) | |
| TRACEOUT(("atapicmd: read(10)")); | |
| lba = (drv->buf[2] << 24) + (drv->buf[3] << 16) + (drv->buf[4] << 8) + drv->buf[5]; | |
| leng = (drv->buf[7] << 8) + drv->buf[8]; | |
| atapi_cmd_read(drv, lba, leng); | |
| break; | |
| case 0x55: // mode select | |
| TRACEOUT(("atapicmd: mode select")); | |
| atapi_cmd_mode_select(drv); | |
| break; | |
| case 0x5a: // mode sense(10) | |
| TRACEOUT(("atapicmd: mode sense(10)")); | |
| atapi_cmd_mode_sense(drv); | |
| break; | |
| case 0x43: // read TOC | |
| TRACEOUT(("atapicmd: read TOC")); | |
| atapi_cmd_readtoc(drv); | |
| break; | |
| default: | |
| TRACEOUT(("atapicmd: unknown command = %.2x", cmd)); | |
| sendabort(drv); | |
| break; | |
| } | |
| } | |
| // case 0x5a: // mode sense(10) | //-- command |
| // break; | |
| // 0x1b: START/STOP UNIT | |
| static void atapi_cmd_start_stop_unit(IDEDRV drv) { | |
| UINT power; | |
| power = (drv->buf[4] >> 4); | |
| if (power != 0) { | |
| /* power control is not supported */ | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); | |
| drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; | |
| goto send_error; | |
| } | |
| if (drv->buf[4] & 2) { | |
| /* lock/eject op. is not supported */ | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); | |
| drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; | |
| goto send_error; | |
| } | |
| if (!(drv->media & IDEIO_MEDIA_LOADED)) { | |
| /* medium not present */ | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); | |
| drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; | |
| goto send_error; | |
| } | |
| /* XXX play/read TOC, stop */ | |
| cmddone(drv); | |
| return; | |
| send_error: | |
| senderror(drv); | |
| } | |
| // 0x1e: PREVENT/ALLOW MEDIUM REMOVAL | |
| static void atapi_cmd_prevent_allow_medium_removal(IDEDRV drv) { | |
| /* XXX */ | |
| cmddone(drv); | |
| } | |
| // 0x25: READ CAPACITY | |
| static void atapi_cmd_read_capacity(IDEDRV drv) { | |
| /* XXX */ | |
| cmddone(drv); | |
| } | |
| // 0x28: READ(10) | |
| void atapi_dataread(IDEDRV drv) { | |
| // エラー処理目茶苦茶〜 | |
| if (drv->nsectors == 0) { | |
| sendabort(drv); | |
| return; | |
| } | |
| if (sxsi_read(drv->sxsidrv, drv->sector, drv->buf, 2048) != 0) { | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); | |
| drv->asc = 0x21; | |
| senderror(drv); | |
| return; | |
| } | |
| drv->sector++; | |
| drv->nsectors--; | |
| drv->sc = IDEINTR_IO; | |
| drv->cy = 2048; | |
| drv->status &= ~(IDESTAT_BSY|IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); | |
| drv->status |= IDESTAT_DRQ; | |
| drv->error = 0; | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); | |
| drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; | |
| drv->bufdir = IDEDIR_IN; | |
| drv->buftc = (drv->nsectors)?IDETC_ATAPIREAD:IDETC_TRANSFEREND; | |
| drv->bufpos = 0; | |
| drv->bufsize = 2048; | |
| if (!(drv->ctrl & IDECTRL_NIEN)) { | |
| TRACEOUT(("atapicmd: senddata()")); | |
| ideio.bank[0] = ideio.bank[1] | 0x80; // ???? | |
| pic_setirq(IDE_IRQ); | |
| } | |
| } | |
| static void atapi_cmd_read(IDEDRV drv, UINT32 lba, UINT32 nsec) { | |
| drv->sector = lba; | |
| drv->nsectors = nsec; | |
| atapi_dataread(drv); | |
| } | |
| // -- MODE SELECT/SENSE | |
| #define PC_01_SIZE 8 | |
| #define PC_0D_SIZE 8 | |
| #define PC_0E_SIZE 16 | |
| #define PC_2A_SIZE 20 | |
| // page code changeable value | |
| static const BYTE chgval_pagecode_01[PC_01_SIZE] = { | |
| 0x00, 0x00, 0x37, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| }; | |
| static const BYTE chgval_pagecode_0d[PC_0D_SIZE] = { | |
| 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, | |
| }; | |
| static const BYTE chgval_pagecode_0e[PC_0E_SIZE] = { | |
| 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| }; | |
| static const BYTE chgval_pagecode_2a[PC_2A_SIZE] = { | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x02, 0xc2, 0x00, 0x02, 0x00, 0x00, 0x02, 0xc2, | |
| 0x00, 0x00, 0x00, 0x00, | |
| }; | |
| // page code default value | |
| static const BYTE defval_pagecode_01[PC_01_SIZE] = { | |
| 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| }; | |
| static const BYTE defval_pagecode_0d[PC_0D_SIZE] = { | |
| 0x0d, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x4b, | |
| }; | |
| static const BYTE defval_pagecode_0e[PC_0E_SIZE] = { | |
| 0x0e, 0x0e, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, | |
| 0x01, 0xff, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| }; | |
| static const BYTE defval_pagecode_2a[PC_2A_SIZE] = { | |
| 0x2a, 0x12, 0x00, 0x00, 0x00, 0x00, 0x20, 0x03, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, | |
| }; | |
| // 0x55: MODE SELECT | |
| static void atapi_cmd_mode_select(IDEDRV drv) { | |
| if (drv->buf[1] & 1) { | |
| /* Saved Page is not supported */ | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); | |
| drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; | |
| senderror(drv); | |
| return; | |
| } | |
| sendabort(drv); /* XXX */ | |
| } | |
| // 0x5a: MODE SENSE | |
| static void atapi_cmd_mode_sense(IDEDRV drv) { | |
| const BYTE *ptr; | |
| UINT leng; | |
| UINT cnt; | |
| UINT8 pctrl, pcode; | |
| leng = (drv->buf[7] << 8) + drv->buf[8]; | |
| pctrl = (drv->buf[2] >> 6) & 3; // 0: current, 1: changeable, 2: default | |
| pcode = drv->buf[2] & 0x3f; | |
| if (pctrl == 3) { | |
| /* Saved Page is not supported */ | |
| TRACEOUT(("Saved Page is not supported")); | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); | |
| drv->asc = ATAPI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED; | |
| senderror(drv); | |
| return; | |
| } | |
| /* Mode Parameter Header */ | |
| ZeroMemory(drv->buf, 8); | |
| if (!(drv->media & IDEIO_MEDIA_LOADED)) { | |
| drv->buf[2] = 0x70; // Door closed, no disc present | |
| } | |
| else { | |
| drv->buf[2] = 0x00; // 120mm CD-ROM data only | |
| } | |
| cnt = 8; | |
| if (cnt > leng) { | |
| goto length_exceeded; | |
| } | |
| /* Mode Page */ | |
| TRACEOUT(("pcode = %.2x", pcode)); | |
| switch (pcode) { | |
| case 0x3f: | |
| /*FALLTHROUGH*/ | |
| case 0x01: /* Read Error Recovery Parameters Page */ | |
| if (pctrl == 1) { | |
| ptr = chgval_pagecode_01; | |
| } | |
| else { | |
| ptr = defval_pagecode_01; | |
| } | |
| CopyMemory(drv->buf + cnt, ptr, min((leng - cnt), PC_01_SIZE)); | |
| cnt += PC_01_SIZE; | |
| if (cnt > leng) { | |
| goto length_exceeded; | |
| } | |
| if (pcode == 0x01) { | |
| break; | |
| } | |
| /*FALLTHROUGH*/ | |
| case 0x0d: /* CD-ROM Device Parameters Page */ | |
| if (pctrl == 1) { | |
| ptr = chgval_pagecode_0d; | |
| } | |
| else { | |
| ptr = defval_pagecode_0d; | |
| } | |
| CopyMemory(drv->buf + cnt, ptr, min((leng - cnt), PC_0D_SIZE)); | |
| cnt += PC_0D_SIZE; | |
| if (cnt > leng) { | |
| goto length_exceeded; | |
| } | |
| if (pcode == 0x0d) { | |
| break; | |
| } | |
| /*FALLTHROUGH*/ | |
| case 0x0e: /* CD-ROM Audio Control Paramater Page */ | |
| if (pctrl == 1) { | |
| ptr = chgval_pagecode_0e; | |
| } | |
| else { | |
| ptr = defval_pagecode_0e; | |
| } | |
| CopyMemory(drv->buf + cnt, ptr, min((leng - cnt), PC_0E_SIZE)); | |
| cnt += PC_0E_SIZE; | |
| if (cnt > leng) { | |
| goto length_exceeded; | |
| } | |
| if (pcode == 0x0e) { | |
| break; | |
| } | |
| /*FALLTHROUGH*/ | |
| case 0x2a: /* CD-ROM Capabilities & Mechanical Status Page */ | |
| if (pctrl == 1) { | |
| ptr = chgval_pagecode_2a; | |
| } | |
| else { | |
| ptr = defval_pagecode_2a; | |
| } | |
| CopyMemory(drv->buf + cnt, ptr, min((leng - cnt), PC_2A_SIZE)); | |
| cnt += PC_2A_SIZE; | |
| if (cnt > leng) { | |
| goto length_exceeded; | |
| } | |
| break; | |
| default: | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); | |
| drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; | |
| senderror(drv); | |
| return; | |
| } | |
| drv->buf[0] = (UINT8)((cnt - 2) >> 8); | |
| drv->buf[1] = (UINT8)(cnt - 2); | |
| senddata(drv, cnt, leng); | |
| return; | |
| length_exceeded: | |
| if (cnt >= 65536) { | |
| ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); | |
| drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; | |
| senderror(drv); | |
| return; | |
| } | |
| drv->buf[0] = (UINT8)((leng - 2) >> 8); | |
| drv->buf[1] = (UINT8)(leng - 2); | |
| senddata(drv, cnt, leng); | |
| } | |
| static void atapi_cmd_readtoc(IDEDRV drv) { | |
| UINT leng; | |
| UINT format; | |
| leng = (drv->buf[7] << 8) + drv->buf[8]; | |
| format = (drv->buf[9] >> 6); | |
| TRACEOUT(("atapi_cmd_readtoc fmt=%d leng=%d", format, leng)); | |
| switch(format) { | |
| case 1: // multi session | |
| ZeroMemory(drv->buf, 12); | |
| drv->buf[1] = 0x0a; | |
| drv->buf[2] = 0x01; | |
| drv->buf[3] = 0x01; | |
| senddata(drv, 12, leng); | |
| break; | |
| default: | default: |
| TRACEOUT(("atapicmd: unknown command = %.2x", cmd)); | senderror(drv); |
| // sendabort(drv); | |
| break; | break; |
| } | } |
| } | } |
| #endif /* SUPPORT_IDEIO */ | #endif /* SUPPORT_IDEIO */ |