Diff for /xmil/io/fdc.c between versions 1.7 and 1.13

version 1.7, 2004/08/11 12:08:16 version 1.13, 2004/08/13 01:35:59
Line 13 Line 13
 static const UINT8 fdctype[] = {1,1,1,1,1,1,1,1,2,2,2,2,3,4,3,3};  static const UINT8 fdctype[] = {1,1,1,1,1,1,1,1,2,2,2,2,3,4,3,3};
   
   
 void nvitem_fdcbusy(UINT id) {  void neitem_fdcbusy(UINT id) {
   
         fdc.s.busy = FALSE;          fdc.s.busy = FALSE;
         if (fdc.s.bufdir) {          if (fdc.s.bufdir) {
                 TRACEOUT(("dma ready!"));                  TRACEOUT(("dma ready!"));
                 dma.DMA_REDY = 0;                  dmac_sendready(TRUE);
         }          }
           (void)id;
 }  }
   
 static void setbusy(UINT clock) {  static void setbusy(SINT32 clock) {
   
         fdc.s.busy = TRUE;          if (clock > 0) {
         nevent_set(NEVENT_FDC, clock, nvitem_fdcbusy, NEVENT_ABSOLUTE);                  fdc.s.busy = TRUE;
                   nevent_set(NEVENT_FDC, clock, neitem_fdcbusy, NEVENT_ABSOLUTE);
           }
   }
   
   static void setmotor(REG8 drvcmd) {
   
           UINT    drv;
           SINT32  clock;
   
           drv = drvcmd & 3;
           clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
           if (drvcmd & 0x80) {
                   if (fdc.s.motorevent[drv] == FDCMOTOR_STOP) {
                           fdc.s.motorevent[drv] = FDCMOTOR_STARTING;
                           fdc.s.motorclock[drv] = clock;
                   }
                   else if (fdc.s.motorevent[drv] == FDCMOTOR_STOPING) {
                           fdc.s.motorevent[drv] = FDCMOTOR_READY;
                   }
           }
           else {
                   if ((fdc.s.motorevent[drv] == FDCMOTOR_STARTING) ||
                           (fdc.s.motorevent[drv] == FDCMOTOR_READY)) {
                           fdc.s.motorevent[drv] = FDCMOTOR_STOPING;
                           fdc.s.motorclock[drv] = clock;
                   }
           }
   }
   
   void fdc_callback(void) {
   
           SINT32  clock;
           UINT    i;
   
           clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
           for (i=0; i<4; i++) {
                   if (fdc.s.motorevent[i] == FDCMOTOR_STARTING) {
                           if ((clock - fdc.s.motorclock[i]) >= (SINT32)pccore.realclock) {
                                   fdc.s.motorevent[i] = FDCMOTOR_READY;
                           }
                   }
                   else if (fdc.s.motorevent[i] == FDCMOTOR_STOPING) {
                           if ((clock - fdc.s.motorclock[i]) >= (SINT32)pccore.realclock) {
                                   fdc.s.motorevent[i] = FDCMOTOR_STOP;
                           }
                   }
           }
 }  }
   
 static REG8 getstat(void) {  static REG8 getstat(void) {
Line 97  static REG8 type2cmd(REG8 sc) { Line 145  static REG8 type2cmd(REG8 sc) {
         FDDFILE fdd;          FDDFILE fdd;
         UINT    size;          UINT    size;
         REG8    stat;          REG8    stat;
   #if defined(SUPPORT_DISKEXT)
           SINT32  clock;
           SINT32  curclock;
           SINT32  nextclock;
           UINT32  secinfo;
   #endif
   
         track = (fdc.s.c << 1) + fdc.s.h;          track = (fdc.s.c << 1) + fdc.s.h;
         if (!(fdc.s.cmd & 0x20)) {          if (!(fdc.s.cmd & 0x20)) {
Line 130  static REG8 type2cmd(REG8 sc) { Line 184  static REG8 type2cmd(REG8 sc) {
         fdc.s.bufmark = fdc.s.cmd & 1;          fdc.s.bufmark = fdc.s.cmd & 1;
         fdc.s.bufpos = 0;          fdc.s.bufpos = 0;
         fdc.s.bufsize = size;          fdc.s.bufsize = size;
           fdc.s.curtime = 0;
   
   #if defined(SUPPORT_DISKEXT)
           // ウェイト値を計算
           clock = 0;
           if (fdc.s.motorevent[fdc.s.drv] == FDCMOTOR_STARTING) {
                   curclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
                   curclock -= fdc.s.motorclock[fdc.s.drv];
                   if (curclock < (SINT32)pccore.realclock) {
                           nextclock = pccore.realclock - curclock;
                           TRACEOUT(("motor starting busy %d", nextclock));
                           clock += nextclock;
                   }
           }
           secinfo = fdd->sec(fdd, fdc.s.media, track, sc);
           if (secinfo) {
                   nextclock = LOW16(secinfo);
                   nextclock *= fdc.s.loopclock;
                   nextclock /= LOW16(secinfo >> 16);
                   curclock = nevent_getwork(NEVENT_RTC);
                   nextclock -= curclock;
                   if (nextclock < 0) {
                           nextclock += fdc.s.loopclock;
                   }
                   TRACEOUT(("wait clock -> %d [%d/%d]", nextclock,
                                                                           LOW16(secinfo), LOW16(secinfo >> 16)));
                   clock += nextclock;
           }
           setbusy(max(clock, 500));
   #else
           setbusy(500);
   #endif
         return(stat);          return(stat);
 }  }
   
Line 169  static REG8 crccmd(void) { Line 255  static REG8 crccmd(void) {
                 fdc.s.bufsize = 0;                  fdc.s.bufsize = 0;
         }          }
         fdc.s.bufwrite = FALSE;          fdc.s.bufwrite = FALSE;
           fdc.s.curtime = 0;
         return(stat);          return(stat);
 }  }
   
Line 181  static void bufposinc(void) { Line 268  static void bufposinc(void) {
                 return;                  return;
         }          }
         fdc.s.bufpos++;          fdc.s.bufpos++;
           fdc.s.curtime = 0;
         if (fdc.s.bufpos >= fdc.s.bufsize) {          if (fdc.s.bufpos >= fdc.s.bufsize) {
                 r = FALSE;                  r = FALSE;
                 if (fdc.s.type == 2) {                  if (fdc.s.type == 2) {
Line 195  static void bufposinc(void) { Line 283  static void bufposinc(void) {
                                 }                                  }
                                 fdc.s.stat = stat;                                  fdc.s.stat = stat;
                         }                          }
                         if (r) {  
                                 fdc.s.rreg = fdc.s.r + 1;  
                                 stat = type2cmd(fdc.s.rreg);  
                                 if (!(stat & FDDSTAT_RECNFND)) {  
                                         fdc.s.r = fdc.s.r + 1;  
                                         fdc.s.stat = stat;  
                                 }  
                                 else {  
                                         r = FALSE;  
                                 }  
                         }  
                 }                  }
                 if (!r) {                  fdc.s.bufdir = FDCDIR_NONE;
                         dma.DMA_REDY = 8;                  dmac_sendready(FALSE);
                         fdc.s.bufdir = FDCDIR_NONE;                  if (r) {
                           fdc.s.rreg = fdc.s.r + 1;
                           stat = type2cmd(fdc.s.rreg);
                           if (!(stat & FDDSTAT_RECNFND)) {
                                   fdc.s.r = fdc.s.r + 1;
                                   fdc.s.stat = stat;
                           }
                 }                  }
         }          }
 }  }
Line 222  void IOOUTCALL fdc_o(UINT port, REG8 val Line 305  void IOOUTCALL fdc_o(UINT port, REG8 val
                 return;                  return;
         }          }
         TRACEOUT(("fdc %.4x,%.2x [%.4x]", port, value, Z80_PC));          TRACEOUT(("fdc %.4x,%.2x [%.4x]", port, value, Z80_PC));
         port &= 0xf;          switch(port & 7) {
         if (port == 8) {                                                // コマンド                  case 0:                                                                 // コマンド
                 fdc.s.cmd = value;                          fdc.s.cmd = value;
                 cmd = (REG8)(value >> 4);                          cmd = (REG8)(value >> 4);
                 fdc.s.type = fdctype[cmd];                          fdc.s.type = fdctype[cmd];
                 TRACEOUT(("fdc cmd: %.2x", value));                          TRACEOUT(("fdc cmd: %.2x", value));
                 if (fdc.s.bufwrite) {                          if (fdc.s.bufwrite) {
                         fdc.s.stat = type2flash();                                  fdc.s.stat = type2flash();
                 }                          }
                 fdc.s.bufdir = FDCDIR_NONE;                          fdc.s.bufdir = FDCDIR_NONE;
                 setbusy(20);                          // リストアコマンドにおいて
                 switch(cmd) {                          //  マリオは コマンド発行後にbusyを見張る
                         case 0x00:                                                              // リストア                          //  逆にソーサリアンとかは busyだとエラーになる…
                                 if (value & 8) {                                        // LAYDOCK                          // 条件は何?
                                         setbusy(0);                          setbusy(20);
                                 }                          switch(cmd) {
                                 fdc.s.motor = 0x80;                                     // モーターOn?                                  case 0x00:                                                              // リストア
                                 fdc.s.c = 0;                                  //      if (value & 8) {                                        // LAYDOCK
                                 fdc.s.step = 1;                                  //              setbusy(0);
                                 fdc.s.r = 0;                                            // デゼニワールド                                  //      }
                                 seekcmd();                                          fdc.s.motor = 0x80;                                     // モーターOn?
                                 fdc.s.rreg = 0;                                          fdc.s.c = 0;
                                 break;                                          fdc.s.step = 1;
                                           fdc.s.r = 0;                                            // デゼニワールド
                                           seekcmd();
                                           fdc.s.rreg = 0;
                                           break;
   
                         case 0x01:                                                              // シーク                                  case 0x01:                                                              // シーク
                                 fdc.s.motor = 0x80;                                     // モーターOn                                          fdc.s.motor = 0x80;                                     // モーターOn
                                 fdc.s.step = (SINT8)((fdc.s.c<=fdc.s.data)?1:-1);                                          fdc.s.step = (SINT8)((fdc.s.c<=fdc.s.data)?1:-1);
                                 fdc.s.c = fdc.s.data;                                          fdc.s.c = fdc.s.data;
                                 seekcmd();                                          seekcmd();
                                 break;                                          break;
   
                         case 0x02:                                                              // ステップ                                  case 0x02:                                                              // ステップ
                         case 0x03:                                  case 0x03:
                                 if (fdc.s.motor) {                                          if (fdc.s.motor) {
                                         fdc.s.c += fdc.s.step;                                                  fdc.s.c += fdc.s.step;
                                         if (cmd & 1) {                                                  if (cmd & 1) {
                                                 seekcmd();                                                          seekcmd();
                                                   }
                                         }                                          }
                                 }                                          break;
                                 break;  
   
                         case 0x04:                                                              // ステップイン                                  case 0x04:                                                              // ステップイン
                         case 0x05:                                  case 0x05:
                                 if (fdc.s.motor) {                                          if (fdc.s.motor) {
                                         fdc.s.step = 1;                                                  fdc.s.step = 1;
                                         fdc.s.c++;                                                  fdc.s.c++;
                                         if (cmd & 1) {                                                  if (cmd & 1) {
                                                 seekcmd();                                                          seekcmd();
                                                   }
                                         }                                          }
                                 }                                          break;
                                 break;  
   
                         case 0x06:                                                              // ステップアウト                                  case 0x06:                                                              // ステップアウト
                         case 0x07:                                  case 0x07:
                                 if (fdc.s.motor) {                                          if (fdc.s.motor) {
                                         fdc.s.step = -1;                                                  fdc.s.step = -1;
                                         fdc.s.c--;                                                  fdc.s.c--;
                                         if (cmd & 1) {                                                  if (cmd & 1) {
                                                 seekcmd();                                                          seekcmd();
                                                   }
                                         }                                          }
                                 }                                          break;
                                 break;  
   
                         case 0x08:                                                              // リードデータ                                  case 0x08:                                                              // リードデータ
                         case 0x09:                                  case 0x09:
                         case 0x0a:                                                              // ライトデータ                                  case 0x0a:                                                              // ライトデータ
                         case 0x0b:                                  case 0x0b:
                                 setbusy(500);                                          fdc.s.stat = type2cmd(fdc.s.r);
                                 fdc.s.stat = type2cmd(fdc.s.r);                                          break;
                                 break;  
                                   case 0xc:                                                               // リードアドレス
                         case 0xc:                                                               // リードアドレス                                          setbusy(200);
                                 setbusy(200);                                          fdc.s.stat = crccmd();
                                 fdc.s.stat = crccmd();                                          break;
                                 break;  
                                   case 0x0d:                                                              // フォースインタラプト
                         case 0x0d:                                                              // フォースインタラプト                                          setbusy(0);                                                     // 必要ない?
                                 setbusy(0);                                                     // 必要ない?  //                                      fdc.s.skip = 0;                                         // 000330
 //                              fdc.s.skip = 0;                                         // 000330                                          dmac_sendready(FALSE);
                                 dma.DMA_REDY = 8;                                       // ver0.25                                          break;
                                 break;  
                                   case 0x0e:                                                              // リードトラック
                         case 0x0e:                                                              // リードトラック                                          setbusy(200);
                                 setbusy(200);                                          ZeroMemory(fdc.s.buffer, 0x1a00);
                                 ZeroMemory(fdc.s.buffer, 0x1a00);                                          fdc.s.bufpos = 0;
                                 fdc.s.bufpos = 0;                                          fdc.s.bufsize = 0x1a00;
                                 fdc.s.bufsize = 0x1a00;                                          fdc.s.bufdir = FDCDIR_IN;
                                 fdc.s.bufdir = FDCDIR_IN;                                          break;
                                 break;  
   
                         case 0x0f:                                                              // ライトトラック  
 #if 0  
                                 {  
                                         FDDFILE fdd = fddfile + fdc.s.drv;  
                                         switch(fdd->type) {  
                                                 case DISKTYPE_NOTREADY:  
                                                 case DISKTYPE_BETA:  
                                                         break;  
   
                                                 case DISKTYPE_D88:  
                                                 default:  
                                                         if (fdc.s.motor) {                                              // ver0.25  
                                                                 init_tao_d88();  
                                                                 if (dma.DMA_ENBL) {  
                                                                         dma.DMA_REDY = 0;  
                                                                 }  
                                                         }  
                                                         break;  
                                         }  
                                 }  
 #endif  
                                 break;  
                 }  
         }  
         else {  
                 cmd = (REG8)(fdc.s.cmd >> 4);  
                 switch(port) {  
                         case 0x09:                                                              // トラック  
                                 fdc.s.c = value;  
                                 break;  
   
                         case 0x0a:                                                              // セクタ  
                                 FDDMTR_WAITSEC(value);  
                                 fdc.s.r = value;  
                                 fdc.s.rreg = value;  
                                 break;  
   
                         case 0x0b:                                                              // データ  
                                 fdc.s.data = value;  
                                 if ((fdc.s.motor) && (fdc.s.bufdir == FDCDIR_OUT)) {  
                                         fdc.s.buffer[fdc.s.bufpos] = value;  
                                         fdc.s.bufwrite = TRUE;  
                                         bufposinc();  
                                 }  
 #if 0  
                                 else if (cmd == 0x0f) {                         // TRACK WRITE  
                                         FDDFILE fdd = fddfile + fdc.s.drv;  
                                         switch(fdd->type) {  
                                                 case DISKTYPE_NOTREADY:  
                                                 case DISKTYPE_BETA:  
                                                         break;  
   
                                                 case DISKTYPE_D88:  
                                                 default:  
                                                         fdd_wtao_d88(value);  
                                                         break;  
                                         }  
                                 }  
 #endif  
                                 break;  
   
                         case 0x0c:                                                              // ドライブ・サイド                                  case 0x0f:                                                              // ライトトラック
                                 fdc.s.ctbl[fdc.s.drv] = fdc.s.c;                                          break;
                                 fdc.s.c = fdc.s.ctbl[value & 0x03];                          }
                                 fdc.s.motor = (UINT8)(value & 0x80);                          break;
                                 fdc.s.drv = (UINT8)(value & 0x03);  
                                 fdc.s.h = (UINT8)((value >> 4) & 1);                  case 1:                                                                 // トラック
                                 fdc.s.cmd = 0;                                                  // T&E SORCERIAN                          fdc.s.c = value;
                                 fdc.s.type = 0;                          break;
   
                                 FDDMTR_DRVSET;                  case 2:                                                                 // セクタ
                                 if (!fdc.s.motor) {                          FDDMTR_WAITSEC(value);
                                         fdc.s.r = 0;                                            // SACOM TELENET                          fdc.s.r = value;
                                         fdc.s.rreg = 0;                          fdc.s.rreg = value;
                                 }                          break;
                                 break;  
                 }                  case 3:                                                                 // データ
                           fdc.s.data = value;
                           if ((fdc.s.motor) && (fdc.s.bufdir == FDCDIR_OUT)) {
                                   fdc.s.buffer[fdc.s.bufpos] = value;
                                   fdc.s.bufwrite = TRUE;
                                   bufposinc();
                           }
                           break;
   
                   case 4:                                                                 // ドライブ・サイド
                           fdc.s.ctbl[fdc.s.drv] = fdc.s.c;
                           fdc.s.c = fdc.s.ctbl[value & 0x03];
                           fdc.s.motor = (UINT8)(value & 0x80);
                           fdc.s.drv = (UINT8)(value & 0x03);
                           fdc.s.h = (UINT8)((value >> 4) & 1);
                           fdc.s.cmd = 0;                                                  // T&E SORCERIAN
                           fdc.s.type = 0;
   
                           FDDMTR_DRVSET;
                           if (!fdc.s.motor) {
                                   fdc.s.r = 0;                                            // SACOM TELENET
                                   fdc.s.rreg = 0;
                           }
                           setmotor(value);
                           break;
         }          }
 }  }
   
 REG8 IOINPCALL fdc_i(UINT port) {  REG8 IOINPCALL fdc_i(UINT port) {
   
 static  BYTE    timeoutwait;  
 static  BYTE    last_r;  
 static  short   last_off;  
         REG8    cmd;  
         REG8    ret;          REG8    ret;
   
           TRACEOUT(("fdc inp %.4x", port));
   
         if ((port & (~7)) != 0x0ff8) {          if ((port & (~7)) != 0x0ff8) {
                 return(0xff);                  return(0xff);
         }          }
         cmd = (REG8)(fdc.s.cmd >> 4);          switch(port & 7) {
         if ((port &= 0xf) != 8) {                  case 0:                                                                 // ステータス
                 last_r = -1;  
                 last_off = -1;  
                 timeoutwait = 4;  
         }  
         switch(port) {  
                 case 0x8:       // ステータス  
                         ret = fdc.s.busy;                          ret = fdc.s.busy;
                         if (ret) {                          if (ret) {
                                 return(ret);                                  return(ret);
                         }                          }
 #if 0  #if 1
                         if (fdc.s.type == 2) {                          if (fdc.s.bufdir) {                                     // YsII
                                 if (last_r == _fdc.r && last_off == fdc.off &&                                  fdc.s.curtime++;
                                                 !(--timeoutwait)) {                                  if (fdc.s.curtime >= 8) {
                                         inc_off();                                          fdc.s.stat |= 0x04;
                                         timeoutwait = 4;                                          bufposinc();
                                 }                                  }
                                 last_r = _fdc.r;                          }
                                 last_off = fdc.off;  
                         }                                                       // Read Write時のみの変化でいい筈  
 #endif  #endif
                         ret = getstat();                          ret = getstat();
                         if (!(ret & 0x02)) {                          if (!(ret & 0x02)) {
                                 dma.DMA_REDY = 8;                                  dmac_sendready(FALSE);
                         }                          }
                           TRACEOUT(("ret->%.2x", ret));
                         return(ret);                          return(ret);
   
                 case 0x9:                                                       // トラック                  case 1:                                                                 // トラック
                         return(fdc.s.creg);                          return(fdc.s.creg);
   
                 case 0xa:                                                       // セクタ                  case 2:                                                                 // セクタ
                         return(fdc.s.rreg);                          return(fdc.s.rreg);
   
                 case 0xb:                                                       // データ                  case 3:                                                                 // データ
                         if (fdc.s.motor) {                          if (fdc.s.motor) {
                                 if (fdc.s.bufdir == FDCDIR_IN) {                                  if (fdc.s.bufdir == FDCDIR_IN) {
                                         fdc.s.data = fdc.s.buffer[fdc.s.bufpos];                                          fdc.s.data = fdc.s.buffer[fdc.s.bufpos];
                                         TRACEOUT(("sector read %.2x (%.2x) [%.4x]", fdc.s.data, fdc.s.bufpos, Z80_PC));  // TRACEOUT(("read %.2x %.2x [%.4x]", fdc.s.data, fdc.s.bufpos, Z80_PC));
                                         bufposinc();                                          bufposinc();
                                 }                                  }
                         }                          }
                         return(fdc.s.data);                                     // WOODY POCO !!!                          return(fdc.s.data);
   
 //              case 0xc:                                                               // FM                  case 4:                                                                 // FM
 //              case 0xd:                                                               // MFM                  case 5:                                                                 // MFM
 //                      break;                          return(0x00);
   
                 case 0xe:                                                               // 1.6M                  case 6:                                                                 // 1.6M
                         fdc.s.media = DISKTYPE_2HD;                          fdc.s.media = DISKTYPE_2HD;
                         return(0xff);                          break;
   
                 case 0xf:                                                               // 500K/1M                  case 7:                                                                 // 500K/1M
                         fdc.s.media = DISKTYPE_2D;                          fdc.s.media = DISKTYPE_2D;
                         return(0xff);                          break;
         }          }
         return(0);          return(0xff);
 }  }
   
   
Line 471  void fdc_reset(void) { Line 511  void fdc_reset(void) {
         FDDMTR_INIT;          FDDMTR_INIT;
         ZeroMemory(&fdc, sizeof(fdc));          ZeroMemory(&fdc, sizeof(fdc));
         fdc.s.step = 1;          fdc.s.step = 1;
           fdc.s.equip = xmilcfg.fddequip;
           fdc.s.loopclock = pccore.realclock / 5;
 }  }
   

Removed from v.1.7  
changed lines
  Added in v.1.13


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