|
|
| version 1.3, 2005/03/05 06:02:28 | version 1.9, 2005/04/06 16:46:07 |
|---|---|
| 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 12 | Line 17 |
| #include "atapicmd.h" | #include "atapicmd.h" |
| #include "sxsi.h" | #include "sxsi.h" |
| #define YUIDEBUG | |
| // INQUIRY | // INQUIRY |
| static const UINT8 cdrom_inquiry[] = { | static const UINT8 cdrom_inquiry[] = { |
| #ifdef YUIDEBUG | |
| // うちのドライブの奴 NECCDは Product Level 3.00以上で modesense10のコードがちげー | |
| 0x05, // CD-ROM | |
| 0x80, // bit7: Removable Medium Bit, other: Reserved | |
| 0x00, // version [7-6: ISO, ECMA: 5-3, 2-0: ANSI(00)] | |
| 0x21, // 7-4: ATAPI version, 3-0: Response Data Format | |
| 0x1f, // Additional length | |
| 0x00,0x00,0x00, // Reserved | |
| 'N', 'E', 'C', ' ', ' ', ' ', ' ', ' ', // Vendor ID | |
| 'C', 'D', '-', 'R', 'O', 'M', ' ', 'D', // Product ID | |
| 'R', 'I', 'V', 'E', ':', '2', '5', '1', // Product ID | |
| '4', '.', '0', '9' // Product Revision Level | |
| #else | |
| 0x05, // CD-ROM | 0x05, // CD-ROM |
| 0x80, // bit7: Removable Medium Bit, other: Reserved | 0x80, // bit7: Removable Medium Bit, other: Reserved |
| 0x00, // version [7-6: ISO, ECMA: 5-3, 2-0: ANSI(00)] | 0x00, // version [7-6: ISO, ECMA: 5-3, 2-0: ANSI(00)] |
| Line 25 static const UINT8 cdrom_inquiry[] = { | Line 45 static const UINT8 cdrom_inquiry[] = { |
| 'C', 'D', '-', 'R', 'O', 'M', ' ', 'D', // Product ID | 'C', 'D', '-', 'R', 'O', 'M', ' ', 'D', // Product ID |
| 'R', 'I', 'V', 'E', ' ', ' ', ' ', ' ', // Product ID | 'R', 'I', 'V', 'E', ' ', ' ', ' ', ' ', // Product ID |
| '1', '.', '0', ' ' // Product Revision Level | '1', '.', '0', ' ' // Product Revision Level |
| #endif | |
| }; | }; |
| static void senddata(IDEDRV drv, UINT size, UINT limit) { | static void senddata(IDEDRV drv, UINT size, UINT limit) { |
| Line 32 static void senddata(IDEDRV drv, UINT si | Line 53 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_readsubch(IDEDRV drv); | |
| static void atapi_cmd_readtoc(IDEDRV drv); | |
| static void atapi_cmd_playaudiomsf(IDEDRV drv); | |
| static void atapi_cmd_pauseresume(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 0x42: | |
| TRACEOUT(("atapicmd: read sub channel")); | |
| atapi_cmd_readsubch(drv); | |
| break; | |
| case 0x43: // read TOC | |
| TRACEOUT(("atapicmd: read TOC")); | |
| atapi_cmd_readtoc(drv); | |
| break; | |
| case 0x47: // Play Audio MSF | |
| TRACEOUT(("atapicmd: Play Audio MSF")); | |
| atapi_cmd_playaudiomsf(drv); | |
| break; | |
| case 0x4b: | |
| TRACEOUT(("atapicmd: pause resume")); | |
| atapi_cmd_pauseresume(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] = { | |
| #ifdef YUIDEBUG | |
| 0x2a, 0x12, 0x00, 0x00, 0x71, 0x65, 0x89, 0x07, | |
| 0x02, 0xc2, 0x00, 0xff, 0x00, 0x80, 0x02, 0xc2, | |
| 0x00, 0x00, 0x00, 0x00, | |
| #else | |
| 0x2a, 0x12, 0x00, 0x00, 0x00, 0x00, 0x20, 0x03, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, | |
| #endif | |
| }; | |
| // 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 if ((drv->media & (IDEIO_MEDIA_COMBINE)) == IDEIO_MEDIA_AUDIO) { | |
| drv->buf[2] = 0x02; // 120mm CD-ROM audio only | |
| } | |
| else if ((drv->media & (IDEIO_MEDIA_COMBINE)) == IDEIO_MEDIA_COMBINE) { | |
| drv->buf[2] = 0x03; // 120mm CD-ROM data & audio combined | |
| } | |
| else { | |
| drv->buf[2] = 0x01; // 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; | |
| } | |
| #if 0 | |
| /*FALLTHROUGH*/ | |
| case 0x00: | |
| #endif | |
| 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); | |
| } | |
| // ---- Audio | |
| static void storemsf(UINT8 *ptr, UINT32 pos) { | |
| UINT f; | |
| UINT m; | |
| f = pos % 75; | |
| pos = pos / 75; | |
| m = pos % 60; | |
| pos = pos / 60; | |
| ptr[0] = 0; | |
| ptr[1] = (UINT8)pos; | |
| ptr[2] = (UINT8)m; | |
| ptr[3] = (UINT8)f; | |
| } | |
| // 0x43: READ SUB CHANNEL | |
| static void atapi_cmd_readsubch(IDEDRV drv) { | |
| SXSIDEV sxsi; | |
| UINT leng; | |
| CDTRK trk; | |
| UINT tracks; | |
| UINT r; | |
| UINT32 pos; | |
| sxsi = sxsi_getptr(drv->sxsidrv); | |
| if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) || | |
| (!(sxsi->flag & SXSIFLAG_READY))) { | |
| senderror(drv); | |
| return; | |
| } | |
| trk = sxsicd_gettrk(sxsi, &tracks); | |
| leng = (drv->buf[7] << 8) + drv->buf[8]; | |
| switch(drv->buf[3]) { | |
| case 0x01: // CD-ROM current pos | |
| ZeroMemory(drv->buf, 16); | |
| drv->buf[4] = 0x01; | |
| pos = drv->dacurpos; | |
| if (drv->daflag & 2) { | |
| pos += (rand() & 7); | |
| } | |
| r = tracks; | |
| while(r) { | |
| r--; | |
| if (trk[r].pos <= pos) { | |
| break; | |
| } | |
| } | |
| drv->buf[5] = trk[r].type; | |
| drv->buf[6] = trk[r].track; | |
| drv->buf[7] = 1; | |
| storemsf(drv->buf + 8, pos + 150); | |
| storemsf(drv->buf + 12, pos - trk[r].pos); | |
| senddata(drv, 16, leng); | |
| break; | |
| default: | default: |
| TRACEOUT(("atapicmd: unknown command = %.2x", cmd)); | senderror(drv); |
| // sendabort(drv); | |
| break; | break; |
| } | } |
| } | } |
| // 0x43: READ TOC | |
| static void atapi_cmd_readtoc(IDEDRV drv) { | |
| SXSIDEV sxsi; | |
| UINT leng; | |
| UINT format; | |
| CDTRK trk; | |
| UINT tracks; | |
| UINT datasize; | |
| UINT8 *ptr; | |
| UINT i; | |
| sxsi = sxsi_getptr(drv->sxsidrv); | |
| if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) || | |
| (!(sxsi->flag & SXSIFLAG_READY))) { | |
| senderror(drv); | |
| return; | |
| } | |
| trk = sxsicd_gettrk(sxsi, &tracks); | |
| 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 0: // track info | |
| datasize = (tracks * 8) + 10; | |
| drv->buf[0] = (UINT8)(datasize >> 8); | |
| drv->buf[1] = (UINT8)(datasize >> 0); | |
| drv->buf[2] = 1; | |
| drv->buf[3] = (UINT8)tracks; | |
| ptr = drv->buf + 4; | |
| for (i=0; i<=tracks; i++) { | |
| ptr[0] = 0; | |
| ptr[1] = trk[i].type; | |
| ptr[2] = trk[i].track; | |
| ptr[3] = 0; | |
| storemsf(ptr + 4, trk[i].pos + 150); | |
| ptr += 8; | |
| } | |
| senddata(drv, (tracks * 8) + 12, leng); | |
| break; | |
| case 1: // multi session | |
| ZeroMemory(drv->buf, 12); | |
| drv->buf[1] = 0x0a; | |
| drv->buf[2] = 0x01; | |
| drv->buf[3] = 0x01; | |
| drv->buf[5] = 0x14; | |
| drv->buf[6] = 0x01; | |
| drv->buf[10] = 0x02; | |
| senddata(drv, 12, leng); | |
| break; | |
| default: | |
| senderror(drv); | |
| break; | |
| } | |
| } | |
| // 0x47: Play Audio MSF | |
| static void atapi_cmd_playaudiomsf(IDEDRV drv) { | |
| UINT32 pos; | |
| UINT32 leng; | |
| pos = (((drv->buf[3] * 60) + drv->buf[4]) * 75) + drv->buf[5]; | |
| leng = (((drv->buf[6] * 60) + drv->buf[7]) * 75) + drv->buf[8]; | |
| if (leng > pos) { | |
| leng -= pos; | |
| } | |
| else { | |
| leng = 0; | |
| } | |
| if (pos >= 150) { | |
| pos -= 150; | |
| } | |
| else { | |
| pos = 0; | |
| } | |
| ideio.daplaying |= 1 << (drv->sxsidrv & 3); | |
| drv->daflag = 1; | |
| drv->dacurpos = pos; | |
| drv->dalength = leng; | |
| drv->dabufrem = 0; | |
| cmddone(drv); | |
| } | |
| // 0x4B: PAUSE RESUME | |
| static void atapi_cmd_pauseresume(IDEDRV drv) { | |
| cmddone(drv); | |
| } | |
| #endif /* SUPPORT_IDEIO */ | #endif /* SUPPORT_IDEIO */ |