Diff for /np2/cbus/atapicmd.c between versions 1.2 and 1.4

version 1.2, 2005/02/07 14:46:08 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 13 Line 18
 #include        "sxsi.h"  #include        "sxsi.h"
   
   
   // INQUIRY
 static const UINT8 cdrom_inquiry[] = {  static const UINT8 cdrom_inquiry[] = {
                                 0x05,0x80,0x00,0x21,0x1f,0x00,0x00,0x00,          0x05,   // CD-ROM
                                 'N', 'E', 'C', 0x20,0x20,0x20,0x20,0x20,          0x80,   // bit7: Removable Medium Bit, other: Reserved
                                 'C', 'D', '-', 'R', 'O', 'M', ' ', 'D',          0x00,   // version [7-6: ISO, ECMA: 5-3, 2-0: ANSI(00)]
                                 'R', 'I', 'V', 'E', 0x20,0x20,0x20,0x20,          0x21,   // 7-4: ATAPI version, 3-0: Response Data Format
                                 '1', '.', '0', ' '};          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;
                   }
                   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;
           }
   }
   
   
   //-- 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 {
                   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;                          break;
                   }
                   /*FALLTHROUGH*/
   
                 case 0x5a:              // mode sense(10)          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;                          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);
 }  }
   
 #endif  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 */

Removed from v.1.2  
changed lines
  Added in v.1.4


RetroPC.NET-CVS <cvs@retropc.net>