| version 1.1, 2004/03/19 03:36:52 | version 1.5, 2005/03/05 16:35:48 | 
| 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 13 | Line 18 | 
 | #include        "sxsi.h" | #include        "sxsi.h" | 
 |  |  | 
 |  |  | 
| static const BYTE cdrom_inquiry[] = { | // INQUIRY | 
| 0x05,0x80,0x00,0x21,0x1f,0x00,0x00,0x00, | static const UINT8 cdrom_inquiry[] = { | 
| 'N', 'E', 'C', 0x20,0x20,0x20,0x20,0x20, | 0x05,   // CD-ROM | 
| 'C', 'D', '-', 'R', 'O', 'M', ' ', 'D', | 0x80,   // bit7: Removable Medium Bit, other: Reserved | 
| 'R', 'I', 'V', 'E', 0x20,0x20,0x20,0x20, | 0x00,   // version [7-6: ISO, ECMA: 5-3, 2-0: ANSI(00)] | 
| '1', '.', '0', ' '}; | 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', ' ', ' ', ' ', ' ', // Product ID | 
|  | '1', '.', '0', ' '      // Product Revision Level | 
|  | }; | 
 |  |  | 
 | static void senddata(IDEDRV drv, UINT size, UINT limit) { | static void senddata(IDEDRV drv, UINT size, UINT limit) { | 
 |  |  | 
 | 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 | 
 |  |  | 
 |  | 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 | 
| leng = drv->buf[4]; | TRACEOUT(("atapicmd: test unit ready")); | 
| CopyMemory(drv->buf, cdrom_inquiry, sizeof(cdrom_inquiry)); | if (!(drv->media & IDEIO_MEDIA_LOADED)) { | 
| senddata(drv, sizeof(cdrom_inquiry), leng); | /* medium not present */ | 
|  | ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); | 
|  | drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; | 
|  | senderror(drv); | 
 | break; | break; | 
|  | } | 
| case 0x5a:              // mode sense(10) | 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; | 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; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  |  | 
 |  | //-- command | 
 |  |  | 
 |  | // 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 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 | #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); | 
 |  | } | 
 |  |  | 
 |  | 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: | 
 |  | senderror(drv); | 
 |  | break; | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | #endif  /* SUPPORT_IDEIO */ |