Previous 199869 Revisions Next

r26170 Friday 15th November, 2013 at 07:16:23 UTC by Jürgen Buchmüller
Use CPU execution loop calling disk word bitclk instead of a super fast timer.
[/branches/alto2/src/emu/cpu/alto2]a2disk.c alto2.c alto2.h
[/branches/alto2/src/emu/machine]diablo_hd.c

branches/alto2/src/emu/cpu/alto2/alto2.c
r26169r26170
4242alto2_cpu_device::alto2_cpu_device(const machine_config& mconfig, const char* tag, device_t* owner, UINT32 clock) :
4343   cpu_device(mconfig, ALTO2, "Xerox Alto-II", tag, owner, clock, "alto2", __FILE__),
4444#if   ALTO2_DEBUG
45   m_log_types(LOG_0),
46   m_log_level(9),
45   m_log_types(LOG_ALL),
46   m_log_level(8),
4747   m_log_newline(true),
4848#endif
4949   m_ucode_config("ucode", ENDIANNESS_BIG, 32, 12, -2 ),
r26169r26170
9090   m_dsp_state(0),
9191   m_unload_time(0),
9292   m_unload_word(0),
93   m_bitclk_time(0),
94   m_bitclk_index(0),
9395   m_ctl2k_u3(0),
9496   m_ctl2k_u38(0),
9597   m_ctl2k_u76(0),
r26169r26170
127129   m_is_octal = true;
128130}
129131
132#if   ALTO2_DEBUG
133// FIXME: define types (sections) and print the section like [emu] [kwd] ...
134// FIXME: use the level to suppress messages if logging is less verbose than level
135void alto2_cpu_device::logprintf(int type, int level, const char* format, ...)
136{
137   static const char* type_name[] = {
138      "[CPU]",
139      "[EMU]",
140      "[T01]",
141      "[T02]",
142      "[T03]",
143      "[KSEC]",
144      "[T05]",
145      "[T06]",
146      "[ETH]",
147      "[MRT]",
148      "[DWT]",
149      "[CURT]",
150      "[DHT]",
151      "[DVT]",
152      "[PART]",
153      "[KWD]",
154      "[T17]",
155      "[MEM]",
156      "[RAM]",
157      "[DRIVE]",
158      "[DISK]",
159      "[DISPL]",
160      "[MOUSE]",
161      "[HW]",
162      "[KBD]"
163   };
164   if (!(m_log_types & type))
165      return;
166   if (level > m_log_level)
167      return;
168   if (m_log_newline) {
169      // last line had a \n - print type name
170      for (int i = 0; i < sizeof(type_name)/sizeof(type_name[0]); i++)
171         if (type & (1 << i))
172            logerror("%-7s ", type_name[i]);
173   }
174   va_list ap;
175   va_start(ap, format);
176   vlogerror(format, ap);
177   va_end(ap);
178   m_log_newline = format[strlen(format) - 1] == '\n';
179}
180#endif
181
130182//-------------------------------------------------
131183// driver interface to set diablo_hd_device
132184//-------------------------------------------------
r26169r26170
918970   save_item(NAME(m_dsp_state));
919971   save_item(NAME(m_unload_time));
920972   save_item(NAME(m_unload_word));
973#if   (USE_BITCLK_TIMER == 0)
974   save_item(NAME(m_bitclk_time));
975   save_item(NAME(m_bitclk_index));
976#endif
921977   save_item(NAME(m_mouse.x));
922978   save_item(NAME(m_mouse.y));
923979   save_item(NAME(m_mouse.dx));
r26169r26170
11921248   }
11931249}
11941250
1195#if   ALTO2_DEBUG
1196// FIXME: define types (sections) and print the section like [emu] [kwd] ...
1197// FIXME: use the level to suppress messages if logging is less verbose than level
1198void alto2_cpu_device::logprintf(int type, int level, const char* format, ...)
1199{
1200   static const char* type_name[] = {
1201      "[CPU]",
1202      "[EMU]",
1203      "[T01]",
1204      "[T02]",
1205      "[T03]",
1206      "[KSEC]",
1207      "[T05]",
1208      "[T06]",
1209      "[ETH]",
1210      "[MRT]",
1211      "[DWT]",
1212      "[CURT]",
1213      "[DHT]",
1214      "[DVT]",
1215      "[PART]",
1216      "[KWD]",
1217      "[T17]",
1218      "[MEM]",
1219      "[RAM]",
1220      "[DRIVE]",
1221      "[DISK]",
1222      "[DISPL]",
1223      "[MOUSE]",
1224      "[HW]",
1225      "[KBD]"
1226   };
1227   if (!(m_log_types & type))
1228      return;
1229   if (level > m_log_level)
1230      return;
1231   if (m_log_newline) {
1232      // last line had a \n - print type name
1233      for (int i = 0; i < sizeof(type_name)/sizeof(type_name[0]); i++)
1234         if (type & (1 << i))
1235            logerror("%-7s ", type_name[i]);
1236   }
1237   va_list ap;
1238   va_start(ap, format);
1239   vlogerror(format, ap);
1240   va_end(ap);
1241   m_log_newline = format[strlen(format) - 1] == '\n';
1242}
1243#endif
1244
12451251// FIXME
12461252void alto2_cpu_device::fatal(int exitcode, const char *format, ...)
12471253{
r26169r26170
24502456      if (m_unload_time >= 0) {
24512457         /*
24522458          * Subtract the microcycle time from the unload time accu.
2453          * If it underflows call the unload word function which adds
2459          * If it underflows, call the unload word function which adds
24542460          * the time for 16 or 32 pixel clocks to the accu, or ends
24552461          * the unloading by leaving m_unload_time at -1.
24562462          */
r26169r26170
24592465            m_unload_word = unload_word(m_unload_word);
24602466         }
24612467      }
2468#if   (USE_BITCLK_TIMER == 0)
2469      if (m_bitclk_time >= 0) {
2470         /*
2471          * Subtract the microcycle time from the bitclk time accu.
2472          * If it underflows, call the disk bitclk function which adds
2473          * the time for one bit as clocks to the accu, or ends
2474          * the bitclk sequence by leaving m_bitclk_time at -1.
2475          */
2476         m_bitclk_time -= ALTO2_UCYCLE;
2477         disk_bitclk(0, m_bitclk_index);
2478         m_bitclk_index++;
2479      }
2480#endif
24622481
24632482      m_cycle++;
24642483      /* nano seconds per cycle */
branches/alto2/src/emu/cpu/alto2/alto2.h
r26169r26170
2323#define   ALTO2_DEBUG         1
2424#endif
2525
26#define   USE_PRIO_F9318   0         //!< define to 1 to use the F9318 priority encoder code
27#define   USE_ALU_74181   0         //!< define to 1 to use the SN74181 ALU code
26#define   USE_PRIO_F9318         0   //!< define to 1 to use the F9318 priority encoder code
27#define   USE_ALU_74181         0   //!< define to 1 to use the SN74181 ALU code
2828#define   DEBUG_DISPLAY_TIMING   0   //!< define to 1 to debug the display timing
29#define   USE_BITCLK_TIMER      0   //!< define to 1 to use a very high rate timer for the disk bit clock
2930
3031#define   ALTO2_TASKS      16         //!< 16 task slots
3132#define   ALTO2_REGS      32         //!< 32 16-bit words in the R register file
r26169r26170
3435#define   ALTO2_F1MAX      16         //!< 16 F1 functions
3536#define   ALTO2_F2MAX      16         //!< 16 F2 functions
3637//! time in nano seconds for a CPU micro cycle
37#define   ALTO2_UCYCLE   static_cast<int>(clocks_to_attotime(1).as_double()/ATTOSECONDS_PER_NANOSECOND)
38#define   ALTO2_UCYCLE   271         //!< 29.4912MHz/8 -> 3.6864MHz ~= 271ns/clock
3839
3940#define   ALTO2_ETHER_FIFO_SIZE   16
4041
r26169r26170
809810   int m_dsp_state;                        //!< display_state_machine() previous state
810811   int m_unload_time;                        //!< unload word time accu
811812   int m_unload_word;                        //!< unload word number
813   int   m_bitclk_time;                        //!< bitclk call time accu
814   int m_bitclk_index;                        //!< bitclk index (bit number)
812815
813816   static const char *task_name(int task);         //!< human readable task names
814817   static const char *r_name(UINT8 reg);         //!< human readable register names
r26169r26170
13931396      UINT8 strobe;               //!< strobe (still) active
13941397      emu_timer* strobon_timer;      //!< set strobe on timer
13951398      UINT8 bitclk;               //!< current bitclk state (either crystal clock, or rdclk from the drive)
1399#if   USE_BITCLK_TIMER
13961400      emu_timer* bitclk_timer;      //!< bit clock timer
1401#else
1402      int bitclk_time;            //!< time in clocks per bit
1403#endif
1404      UINT8 sect4;               //!< current sector_mark_0 (aka SECT[4]) from the drive
13971405      UINT8 datin;               //!< current datin from the drive
13981406      UINT8 bitcount;               //!< bit counter
13991407      UINT8 carry;               //!< carry output of the bitcounter
r26169r26170
14321440   TIMER_CALLBACK_MEMBER( disk_ok_to_run );      //!< timer callback to take away the OK TO RUN pulse (reset)
14331441   TIMER_CALLBACK_MEMBER( disk_strobon );         //!< timer callback to pulse the STROBE' signal to the drive
14341442   TIMER_CALLBACK_MEMBER( disk_ready_mf31a );      //!< timer callback to change the READY monoflop 31a
1443#if   USE_BITCLK_TIMER
1444   TIMER_CALLBACK_MEMBER( disk_bitclk );         //!< callback to update the disk controller with a new bitclk
1445#else
1446   void disk_bitclk(void *ptr, int arg);         //!< function to update the disk controller with a new bitclk
1447#endif
14351448   void disk_block(int task);                  //!< called if one of the disk tasks (task_kwd or task_ksec) blocks
14361449   void bs_read_kstat_0();                     //!< bs_read_kstat early: bus driven by disk status register KSTAT
14371450   void bs_read_kdata_0();                     //!< bs_read_kdata early: bus driven by disk data register KDATA input
r26169r26170
14491462   void f2_swrnrdy_1();                     //!< f2_swrnrdy late: branch on the disk ready signal
14501463   void f2_nfer_1();                        //!< f2_nfer late: branch on the disk fatal error condition
14511464   void f2_strobon_1();                     //!< f2_strobon late: branch on the seek busy status
1452   TIMER_CALLBACK_MEMBER( disk_bitclk );         //!< callback to update the disk controller with a new bitclk
14531465   void init_disk();                        //!< initialize the disk context and insert a disk wort timer
14541466
14551467   // ************************************************
branches/alto2/src/emu/cpu/alto2/a2disk.c
r26169r26170
6666#define   GET_KCOM_SENDADR(kcom)         A2_GET16(kcom,16,5,5)            //!< get send address flag from controller command (hardware command register)
6767#define   PUT_KCOM_SENDADR(kcom,val)      A2_PUT16(kcom,16,5,5,val)         //!< put send address flag into controller command (hardware command register)
6868
69/**
70 * @brief callback is called by the drive timer whenever a new sector starts
71 *
72 * @param unit the unit number
73 */
74static void disk_sector_start(void* cookie, int unit)
75{
76   alto2_cpu_device* cpu = reinterpret_cast<alto2_cpu_device *>(cookie);
77   cpu->next_sector(unit);
78}
79
6980/** @brief completion codes (only for documentation, since this is microcode defined) */
7081enum {
7182   STATUS_COMPLETION_GOOD,
r26169r26170
125136            /* both J and K' are 0: set Q to 0, Q' to 1 */
126137            s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
127138            if (s0 & JKFF_Q) {
128               LOG((LOG_DISK,5,"%s J:0 K':0 → Q:0\n", jkff_name));
139               LOG((LOG_DISK,9,"%s J:0 K':0 → Q:0\n", jkff_name));
129140            }
130141            break;
131142         case JKFF_J:
r26169r26170
134145               s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
135146            else
136147               s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
137            LOG((LOG_DISK,5,"%s J:0 K':1 flip-flop Q:%d\n", jkff_name, (s1 & JKFF_Q) ? 1 : 0));
148            LOG((LOG_DISK,9,"%s J:0 K':1 flip-flop Q:%d\n", jkff_name, (s1 & JKFF_Q) ? 1 : 0));
138149            break;
139150         case JKFF_K:
140151            if ((s0 ^ s1) & JKFF_Q) {
141               LOG((LOG_DISK,5,"%s J:0 K':1 keep Q:%d\n", jkff_name, (s1 & JKFF_Q) ? 1 : 0));
152               LOG((LOG_DISK,9,"%s J:0 K':1 keep Q:%d\n", jkff_name, (s1 & JKFF_Q) ? 1 : 0));
142153            }
143154            /* J is 0, and K' is 1: keep Q as is */
144155            if (s0 & JKFF_Q)
r26169r26170
150161            /* both J and K' are 1: set Q to 1 */
151162            s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
152163            if (!(s0 & JKFF_Q)) {
153               LOG((LOG_DISK,5,"%s J:1 K':1 → Q:1\n", jkff_name));
164               LOG((LOG_DISK,9,"%s J:1 K':1 → Q:1\n", jkff_name));
154165            }
155166            break;
156167         }
r26169r26170
163174      /* S' is 1, C' is 0: set Q to 0, Q' to 1 */
164175      s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
165176      if (s0 & JKFF_Q) {
166         LOG((LOG_DISK,5,"%s C':0 → Q:0\n", jkff_name));
177         LOG((LOG_DISK,9,"%s C':0 → Q:0\n", jkff_name));
167178      }
168179      break;
169180   case JKFF_C:
170181      /* S' is 0, C' is 1: set Q to 1, Q' to 0 */
171182      s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
172183      if (!(s0 & JKFF_Q)) {
173         LOG((LOG_DISK,5,"%s S':0 → Q:1\n", jkff_name));
184         LOG((LOG_DISK,9,"%s S':0 → Q:1\n", jkff_name));
174185      }
175186      break;
176187   case 0:
177188   default:
178189      /* unstable state (what to do?) */
179190      s1 = s1 | JKFF_Q | JKFF_Q0;
180      LOG((LOG_DISK,5,"%s C':0 S':0 → Q:1 and Q':1 <unstable>\n", jkff_name));
191      LOG((LOG_DISK,9,"%s C':0 S':0 → Q:1 and Q':1 <unstable>\n", jkff_name));
181192      break;
182193   }
183194   return static_cast<jkff_t>(s1);
r26169r26170
770781{
771782   UINT8 result = jkff_lookup[s1 & 63][ s0 & 63];
772783#if   ALTO2_DEBUG
773   LOG((LOG_DISK,8,"%s : ", jkff_name));
784   LOG((LOG_DISK,9,"%s : ", jkff_name));
774785   if ((s0 ^ result) & JKFF_CLK)
775      LOG((LOG_DISK,8," CLK%s", raise_lower[result & 1]));
786      LOG((LOG_DISK,9," CLK%s", raise_lower[result & 1]));
776787   if ((s0 ^ result) & JKFF_J)
777      LOG((LOG_DISK,8," J%s", raise_lower[(result >> 1) & 1]));
788      LOG((LOG_DISK,9," J%s", raise_lower[(result >> 1) & 1]));
778789   if ((s0 ^ result) & JKFF_K)
779      LOG((LOG_DISK,8," K'%s", raise_lower[(result >> 2) & 1]));
790      LOG((LOG_DISK,9," K'%s", raise_lower[(result >> 2) & 1]));
780791   if ((s0 ^ result) & JKFF_S)
781      LOG((LOG_DISK,8," S'%s", raise_lower[(result >> 3) & 1]));
792      LOG((LOG_DISK,9," S'%s", raise_lower[(result >> 3) & 1]));
782793   if ((s0 ^ result) & JKFF_C)
783      LOG((LOG_DISK,8," C'%s", raise_lower[(result >> 4) & 1]));
794      LOG((LOG_DISK,9," C'%s", raise_lower[(result >> 4) & 1]));
784795   if ((s0 ^ result) & JKFF_Q)
785      LOG((LOG_DISK,8," Q%s", raise_lower[(result >> 5) & 1]));
796      LOG((LOG_DISK,9," Q%s", raise_lower[(result >> 5) & 1]));
786797   if ((s0 ^ result) & JKFF_Q0)
787      LOG((LOG_DISK,8," Q'%s", raise_lower[(result >> 6) & 1]));
788   LOG((LOG_DISK,8,"\n"));
798      LOG((LOG_DISK,9," Q'%s", raise_lower[(result >> 6) & 1]));
799   LOG((LOG_DISK,9,"\n"));
789800#endif
790801   return static_cast<jkff_t>(result);
791802}
r26169r26170
10441055 */
10451056void alto2_cpu_device::kwd_timing(int bitclk, int datin, int block)
10461057{
1047   int wddone = m_dsk.wddone;
1058   diablo_hd_device* dhd = m_drive[m_dsk.drive];
1059   int wddone = m_dsk.wddone;      // get previous state of word-done
10481060   int i;
10491061   UINT8 s0, s1;
10501062
1051   diablo_hd_device* dhd = m_drive[m_dsk.drive];
1052   if (!dhd) {
1053      LOG((LOG_DISK,3,"   unit #%d\n", m_dsk.drive));
1054      // FIXME: set all signals for a not connected drive
1055      return;
1063   LOG((LOG_DISK,8,"   >>> KWD timing bitclk:%d datin:%d sect4:%d\n", bitclk, datin, m_dsk.sect4));
1064   if (m_dsk.sect4 != dhd->get_sector_mark_0()) {
1065      // SECT[4] transition
1066      m_dsk.sect4 = dhd->get_sector_mark_0();
1067      LOG((LOG_DISK,7,"   SECT[4]:%d changed\n", m_dsk.sect4));
10561068   }
1057   LOG((LOG_DISK,5,"   >>> KWD timing bitclk:%d datin:%d sect4:%d\n", bitclk, datin, dhd->get_sector_mark_0()));
10581069
10591070   if (0 == m_dsk.seclate) {
1060      /* If SECLATE is 0, WDDONE' never goes low (counter's clear has precedence). */
1061      LOG((LOG_DISK,3,"   SECLATE:0 clears bitcount:0\n"));
1062      m_dsk.bitcount = 0;
1063      m_dsk.carry = 0;
1064   } else if (m_dsk.bitclk && !bitclk) {
1065      /*
1066       * If SECLATE is 1, the counter will count or load:
1067       */
1071      // if SECLATE is 0, WDDONE' never goes low (counter's clear has precedence).
1072      if (m_dsk.bitcount || m_dsk.carry) {
1073         LOG((LOG_DISK,7,"   SECLATE:0 clears bitcount:0\n"));
1074         m_dsk.bitcount = 0;
1075         m_dsk.carry = 0;
1076      }
1077   }
1078   if (0 != m_dsk.seclate && m_dsk.bitclk && !bitclk) {
1079       // if SECLATE is 1, the counter will count or load:
10681080      if ((m_dsk.shiftin & (1 << 16)) && !WFFO) {
10691081         /*
10701082          * If HIORDBIT is 1 at the falling edge of BITCLK, it sets the
r26169r26170
10721084          * counter. It has been loaded with 15, so it counts to 16 on
10731085          * the next rising edge and makes WDDONE' go to 0.
10741086          */
1075         LOG((LOG_DISK,3,"   HIORDBIT:1 sets WFFO:1\n"));
1087         LOG((LOG_DISK,7,"   HIORDBIT:1 sets WFFO:1\n"));
10761088         PUT_KCOM_WFFO(m_dsk.kcom, 1);
10771089         // TODO: show disk indicators
10781090      }
r26169r26170
10891101          */
10901102         m_dsk.bitcount = (m_dsk.bitcount + 1) % 16;
10911103         m_dsk.carry = m_dsk.bitcount == 15;
1092         LOG((LOG_DISK,3,"   WFFO:1 count bitcount:%2d\n", m_dsk.bitcount));
1104         LOG((LOG_DISK,7,"   WFFO:1 count bitcount:%2d\n", m_dsk.bitcount));
10931105      } else {
10941106         /*
10951107          * If BUS[4] (WFFO) was 0, both J and K' will be 0, and Q
r26169r26170
10971109          */
10981110         m_dsk.bitcount = 15;
10991111         m_dsk.carry = 1;
1100         LOG((LOG_DISK,3,"   WFFO:0 load bitcount:%2d\n", m_dsk.bitcount));
1112         LOG((LOG_DISK,7,"   WFFO:0 load bitcount:%2d\n", m_dsk.bitcount));
11011113      }
11021114   } else if (!m_dsk.bitclk && bitclk) {
1103      // clock the shift register on the rising edge of bitclk
1104      m_dsk.shiftin = (m_dsk.shiftin << 1) | datin;
1105      // and the output shift register too
1106      m_dsk.shiftout = m_dsk.shiftout << 1;
1115      m_dsk.shiftin = (m_dsk.shiftin << 1) | datin;      // clock the shift register on the rising edge of bitclk
1116      m_dsk.shiftout = m_dsk.shiftout << 1;            // and the output shift register too
11071117   }
11081118
11091119   if (m_dsk.wddone != wddone) {
1110      LOG((LOG_DISK,2,"   WDDONE':%d→%d\n", m_dsk.wddone, wddone));
1120      LOG((LOG_DISK,8,"   WDDONE':%d→%d\n", m_dsk.wddone, wddone));
11111121   }
11121122
11131123   if (m_dsk.carry) {
11141124      /* CARRY = 1 -> WDDONE' = 0 */
11151125      wddone = 0;
1116      if (wddone == 0) {
1126      if (m_dsk.wddone == 0) {
11171127         /*
11181128          * Latch a new data word while WDDONE is 0
11191129          * Note: The shifter outputs for bits 0 to 14 are connected
r26169r26170
11241134         m_dsk.datain = m_dsk.shiftin & 0177777;
11251135         /* load the output shift register */
11261136         m_dsk.shiftout = m_dsk.dataout;
1127         LOG((LOG_DISK,6,"    LATCH in:%06o (0x%04x) out:%06o (0x%04x)\n", m_dsk.datain, m_dsk.datain, m_dsk.dataout, m_dsk.dataout));
1137         LOG((LOG_DISK,8,"    LATCH in:%06o (0x%04x) out:%06o (0x%04x)\n", m_dsk.datain, m_dsk.datain, m_dsk.dataout, m_dsk.dataout));
11281138      }
11291139   } else {
11301140      /* CARRY = 0 -> WDDONE' = 1 */
11311141      wddone = 1;
11321142   }
11331143
1134   /* remember previous state of wddone */
1144   // remember previous state of word-done
11351145   m_dsk.wddone = wddone;
11361146
11371147   /**
r26169r26170
11601170   for (i = 0; i < 4; i++) {
11611171
11621172      if (m_sysclka0[i] != m_sysclka1[i]) {
1163         LOG((LOG_DISK,7,"   SYSCLKA' %s\n", raise_lower[m_sysclka1[i]]));
1173         LOG((LOG_DISK,9,"   SYSCLKA' %s\n", raise_lower[m_sysclka1[i]]));
11641174      }
11651175      if (m_sysclkb0[i] != m_sysclkb1[i]) {
1166         LOG((LOG_DISK,7,"   SYSCLKB' %s\n", raise_lower[m_sysclkb1[i]]));
1176         LOG((LOG_DISK,9,"   SYSCLKB' %s\n", raise_lower[m_sysclkb1[i]]));
11671177      }
11681178
11691179      /**
r26169r26170
13491359      // rising edge immediately
13501360      if ((m_dsk.wdinit = WDINIT) == 1)
13511361         m_dsk.wdinit0 = 1;
1352      LOG((LOG_DISK,2,"   WDINIT:%d\n", m_dsk.wdinit));
1362      LOG((LOG_DISK,8,"   WDINIT:%d\n", m_dsk.wdinit));
13531363   }
13541364
13551365   /*
r26169r26170
13731383      }
13741384   }
13751385
1376   if (m_dsk.kfer) {
1386   if (0 != m_dsk.kfer) {
13771387      // no fatal error: ready AND not seqerr AND seekok
13781388      if (!RDYLAT && !SEQERR && SEEKOK) {
1379         LOG((LOG_DISK,2,"   reset KFER\n"));
1389         LOG((LOG_DISK,6,"   reset KFER\n"));
13801390         m_dsk.kfer = 0;
13811391      }
1382   } else {
1392   }
1393   if (0 == m_dsk.kfer) {
13831394      // fatal error: not ready OR seqerr OR not seekok
13841395      if (RDYLAT) {
1385         LOG((LOG_DISK,2,"   RDYLAT sets KFER\n"));
1396         LOG((LOG_DISK,6,"   RDYLAT sets KFER\n"));
13861397         m_dsk.kfer = 1;
13871398      }
13881399      if (SEQERR) {
1389         LOG((LOG_DISK,2,"   SEQERR sets KFER\n"));
1400         LOG((LOG_DISK,6,"   SEQERR sets KFER\n"));
13901401         m_dsk.kfer = 1;
13911402      }
13921403      if (!SEEKOK) {
1393         LOG((LOG_DISK,2,"   not SEEKOK sets KFER\n"));
1404         LOG((LOG_DISK,6,"   not SEEKOK sets KFER\n"));
13941405         m_dsk.kfer = 1;
13951406      }
13961407   }
r26169r26170
14011412    */
14021413   if (m_dsk.ff_22b & JKFF_Q) {
14031414      if (0 == (m_task_wakeup & (1 << task_ksec))) {
1404         LOG((LOG_DISK,2,"   STSKENA:1; WAKEST':0 wake KSEC\n"));
1415         LOG((LOG_DISK,6,"   STSKENA:1; WAKEST':0 wake KSEC\n"));
14051416         m_task_wakeup |= 1 << task_kwd;
14061417      }
14071418   } else {
14081419      if (0 != (m_task_wakeup & (1 << task_ksec))) {
1409         LOG((LOG_DISK,2,"   STSKENA:0; WAKEST':1\n"));
1420         LOG((LOG_DISK,6,"   STSKENA:0; WAKEST':1\n"));
14101421         m_task_wakeup &= ~(1 << task_kwd);
14111422      }
14121423   }
r26169r26170
14241435    */
14251436   DEBUG_NAME("\t\t21a KSEC  ");
14261437   s0 = m_dsk.ff_21a;
1427   s1 = 0 == dhd->get_sector_mark_0() ? JKFF_CLK : JKFF_0;
1438   s1 = 0 == m_dsk.sect4 ? JKFF_CLK : JKFF_0;
14281439   if (m_dsk.ff_22b & JKFF_Q0)
14291440      s1 |= JKFF_J;
14301441   s1 |= JKFF_K;
r26169r26170
14421453      m_dsk.seclate_timer->adjust(attotime::from_nsec(TW_SECLATE), 1);
14431454      if (m_dsk.seclate) {
14441455         m_dsk.seclate = 0;
1445         LOG((LOG_DISK,4,"   SECLATE -> 0 pulse until %lldns\n", ntime() + TW_SECLATE));
1456         LOG((LOG_DISK,6,"   SECLATE -> 0 pulse until %lldns\n", ntime() + TW_SECLATE));
14461457      }
14471458   }
14481459
1449   /*
1450    * check if write and erase gate, or read gate are changed
1451    */
1460   // check if write and erase gate, or read gate are changed
14521461   if ((m_task_wakeup & (1 << task_ksec)) || GET_KCOM_XFEROFF(m_dsk.kcom) || m_dsk.kfer) {
14531462      // sector task is active OR xferoff is set OR fatal error
14541463      dhd->set_egate(1);
14551464      dhd->set_wrgate(1);
14561465      dhd->set_rdgate(1);
14571466   } else {
1458      // assert either read or write gates depending on current record R/W
1467      // assert either erase and read or write gates depending on current record R/W
14591468      if (m_dsk.krwc & RWC_WRITE) {
14601469         // assert erase and write gates only if OKTORUN is high
14611470         if (m_dsk.ok_to_run) {
r26169r26170
14711480   m_dsk.ff_21a_old = m_dsk.ff_21a;
14721481   m_dsk.bitclk = bitclk;
14731482   m_dsk.datin = datin;
1474   LOG((LOG_DISK,5,"   <<< KWD timing\n"));
1483   LOG((LOG_DISK,8,"   <<< KWD timing\n"));
14751484}
14761485
14771486
r26169r26170
14911500   LOG((LOG_DISK,2,"   OK TO RUN -> %d\n", arg));
14921501   m_dsk.ok_to_run = arg;
14931502   m_dsk.ok_to_run_timer->enable(false);
1503
1504   for (int unit = 0; unit < diablo_hd_device::DIABLO_UNIT_MAX; unit++) {
1505      diablo_hd_device* dhd = m_drive[unit];
1506      dhd->set_sector_callback(this, &disk_sector_start);
1507   }
14941508}
14951509
14961510/**
r26169r26170
21992213{
22002214   (void)ptr;
22012215   diablo_hd_device* dhd = m_drive[m_dsk.drive];
2202   int bits = dhd ? dhd->bits_per_sector() : 0;
2216   int bits = dhd->bits_per_sector();
22032217   int clk = arg & 1;
22042218   int bit = 0;
22052219
r26169r26170
22212235         /* do anything, if the transfer is off? */
22222236      } else {
22232237         LOG((LOG_DISK,7,"   BITCLK#%d bit:%d (write) @%lldns\n", arg, bit, ntime()));
2224         if (dhd) {
2225            if (clk)
2226               dhd->wr_data(arg, bit);
2227            else
2228               dhd->wr_data(arg, 1);
2229         }
2238         if (clk)
2239            dhd->wr_data(arg, bit);
2240         else
2241            dhd->wr_data(arg, 1);
22302242      }
22312243   } else if (GET_KCOM_BCLKSRC(m_dsk.kcom)) {
22322244      /* always select the crystal clock */
2233      if (dhd)
2234         bit = dhd->rd_data(arg);
2245      bit = dhd->rd_data(arg);
22352246      LOG((LOG_DISK,7,"   BITCLK#%d bit:%d (read, crystal) @%lldns\n", arg, bit, ntime()));
22362247      kwd_timing(clk, bit, 0);
22372248   } else {
22382249      /* if XFEROFF is set, keep the bit at 1 (RDGATE' is high) */
22392250      if (GET_KCOM_XFEROFF(m_dsk.kcom)) {
2251         clk = dhd->rd_clock(arg);
22402252         bit = 1;
22412253      } else {
2242         if (dhd) {
2243            clk = dhd->rd_clock(arg & ~1);
2244            bit = dhd->rd_data(arg | 1);
2245         }
2254         bit = dhd->rd_data(arg);
22462255         LOG((LOG_DISK,7,"   BITCLK#%d bit:%d (read, driveclk) @%lldns\n", arg, bit, ntime()));
22472256      }
22482257      kwd_timing(clk, bit, 0);
r26169r26170
22502259
22512260   /* more bits to clock? */
22522261   if (++arg < bits) {
2253      assert(dhd != NULL);
2262#if   USE_BITCLK_TIMER
22542263      m_dsk.bitclk_timer->adjust(dhd->bit_time(), arg);
2264#else
2265      if (!m_dsk.bitclk_time)
2266         m_dsk.bitclk_time = static_cast<int>(dhd->bit_time().as_double() * ATTOSECONDS_PER_NANOSECOND);
2267      m_bitclk_time += m_dsk.bitclk_time;
2268#endif
22552269   }
22562270}
22572271
r26169r26170
22642278{
22652279   diablo_hd_device* dhd = m_drive[unit];
22662280   LOG((LOG_DISK,0,"%s dhd=%p\n", __FUNCTION__, dhd));
2281#if   USE_BITCLK_TIMER
22672282   if (m_dsk.bitclk_timer) {
2268      LOG((LOG_DISK,0,"   unit #%d stop bitclk\n", m_dsk.bitclk));
2283      LOG((LOG_DISK,0,"   unit #%d stop bitclk\n", unit));
22692284      m_dsk.bitclk_timer->reset();
22702285   }
2286#else
2287   if (m_bitclk_time >= 0) {
2288      LOG((LOG_DISK,0,"   unit #%d stop bitclk\n", unit));
2289      m_bitclk_time = -1;
2290   }
2291#endif
22712292
22722293   /* KSTAT[0-3] update the current sector in the kstat field */
2273   PUT_KSTAT_SECTOR(m_dsk.kstat, dhd ? dhd->get_sector() : 017);
2294   PUT_KSTAT_SECTOR(m_dsk.kstat, dhd->get_sector());
22742295
22752296   /* clear input and output shift registers (?) */
22762297   m_dsk.shiftin = 0;
r26169r26170
22782299
22792300   LOG((LOG_DISK,1,"   unit #%d sector %d start\n", unit, GET_KSTAT_SECTOR(m_dsk.kstat)));
22802301
2281   /* HACK: no command, no bit clock */
2282//   if (debug_read_mem(0521))
2283   /* start a timer chain for the bit clock */
2284   disk_bitclk(0, 0);
2285}
22862302
2287/**
2288 * @brief callback is called by the drive timer whenever a new sector starts
2289 *
2290 * @param unit the unit number
2291 */
2292static void disk_sector_start(void* cookie, int unit)
2293{
2294   alto2_cpu_device* cpu = reinterpret_cast<alto2_cpu_device *>(cookie);
2295   cpu->next_sector(unit);
2303#if   USE_BITCLK_TIMER
2304   // HACK: no command, no bit clock
2305   if (debug_read_mem(0521))
2306      /* start a timer chain for the bit clock */
2307      disk_bitclk(0, 0);
2308#else
2309   // TODO: verify current sector == requested sector and only then run the bitclk?
2310   // HACK: no command, no bit clock
2311   if (debug_read_mem(0521)) {
2312      // Make the CPU execution loop call disk_bitclk
2313      m_bitclk_time = 0;
2314      m_bitclk_index = 0;
2315   }
2316#endif
22962317}
22972318
22982319/**
r26169r26170
23332354   m_dsk.seclate = 0;
23342355   m_dsk.ok_to_run = 0;
23352356
2357#if   USE_BITCLK_TIMER
23362358   m_dsk.bitclk_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_bitclk),this));
2359#endif
23372360
23382361   m_dsk.seclate_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_seclate),this));
23392362   m_dsk.seclate_timer->adjust(attotime::from_nsec(TW_SECLATE), 1);
r26169r26170
23432366
23442367   m_dsk.ready_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_ready_mf31a),this));
23452368   m_dsk.ready_timer->reset();
2346
2347   diablo_hd_device* dhd;
2348   for (int unit = 0; unit < diablo_hd_device::DIABLO_UNIT_MAX; unit++) {
2349      dhd = m_drive[unit];
2350      if (!dhd)
2351         continue;
2352      dhd->set_sector_callback(this, &disk_sector_start);
2353   }
23542369}
23552370
branches/alto2/src/emu/machine/diablo_hd.c
r26169r26170
123123
124124void diablo_hd_device::set_sector_callback(void *cookie, void (*callback)(void *, int))
125125{
126   LOG_DRIVE((0,"[DHD] %s cookie=%p callback=%p\n", __FUNCTION__, cookie, callback));
126127   m_sector_callback_cookie = cookie;
127128   m_sector_callback = callback;
128129}
r26169r26170
826827
827828/**
828829 * @brief return the seek/read/write status of a drive
829 * @return the seek/read/write status for the drive unit (0: active, 1: inactive)
830 * @return the seek/read/write status for the drive unit (0:active 1:inactive)
830831 */
831832int diablo_hd_device::get_seek_read_write_0() const
832833{
r26169r26170
835836
836837/**
837838 * @brief return the ready status of a drive
838 * @return the ready status for the drive unit (0: ready, 1: not ready)
839 * @return the ready status for the drive unit (0:ready 1:not ready)
839840 */
840841int diablo_hd_device::get_ready_0() const
841842{
r26169r26170
861862
862863/**
863864 * @brief return the address acknowledge state
864 * @return the address acknowledge state
865 * @return the address acknowledge state (0:active 1:inactive)
865866 */
866867int diablo_hd_device::get_addx_acknowledge_0() const
867868{
r26169r26170
889890/**
890891 * @brief return the current cylinder of a drive unit
891892 *
892 * Note: the bus lines are active low, thus the XOR with DRIVE_CYLINDER_MASK.
893 * Note: The bus lines are active low
894 * The value on the BUS needs an XOR with DIABLO_CYLINDER_MASK
893895 *
894896 * @return the current cylinder number for the drive
895897 */
896898int diablo_hd_device::get_cylinder() const
897899{
898   return m_cylinder ^ DIABLO_CYLINDER_MASK;
900   return m_cylinder;
899901}
900902
901903/**
902904 * @brief return the current head of a drive unit
903905 *
904 * Note: the bus lines are active low, thus the XOR with DRIVE_HEAD_MASK.
906 * Note: The bus lines are active low
907 * The value on the BUS needs an XOR with DIABLO_HEAD_MASK
905908 *
906909 * @return the currently selected head for the drive
907910 */
908911int diablo_hd_device::get_head() const
909912{
910   return m_head ^ DIABLO_HEAD_MASK;
913   return m_head;
911914}
912915
913916/**
r26169r26170
915918 *
916919 * The current sector number is derived from the time since the
917920 * most recent track rotation started.
921 * It counts modulo DIABLO_SPT
918922 *
919 * Note: the bus lines are active low, thus the XOR with DRIVE_SECTOR_MASK.
923 * Note: The bus lines are active low
924 * The value on the BUS needs an XOR with DIABLO_SECTOR_MASK
920925 *
921926 * @return the current sector for the drive
922927 */
923928int diablo_hd_device::get_sector() const
924929{
925   return m_sector ^ DIABLO_SECTOR_MASK;
930   return m_sector;
926931}
927932
928933/**
r26169r26170
950955   /* this drive is selected */
951956   if ((head & DIABLO_HEAD_MASK) != m_head) {
952957      m_head = head & DIABLO_HEAD_MASK;
953      printf("select unit:%d head:%d\n", unit, head);
958      LOG_DRIVE((0,"[DHD]   %s: unit:%d head:%d\n", __FUNCTION__, unit, head));
954959   }
955960
956961   if (m_image) {
r26169r26170
978983/**
979984 * @brief strobe a seek operation
980985 *
981 * Seek to the cylinder cylinder, or restore.
986 * Seek to the cylinder %cylinder, or restore to cylinder 0.
982987 *
983988 * @param unit unit number
984989 * @param cylinder cylinder number to seek to
r26169r26170
990995   int seekto = restore ? 0 : cylinder;
991996   if (strobe) {
992997      LOG_DRIVE((1,"[DHD]   %s: STROBE end of interlock\n", __FUNCTION__, seekto));
993      /* deassert the log address interlock */
998      // deassert the log address interlock
994999      m_log_addx_interlock_0 = 1;
9951000      return;
9961001   }
9971002
998   /* assert the log address interlock */
1003   // assert the log address interlock
9991004   m_log_addx_interlock_0 = 0;
10001005
10011006   if (seekto == m_cylinder) {
10021007      LOG_DRIVE((1,"[DHD]   %s: STROBE to cylinder %d acknowledge\n", __FUNCTION__, seekto));
1003      m_addx_acknowledge_0 = 0;   /* address acknowledge, if cylinder is reached */
1004      m_seek_incomplete_0 = 1;   /* reset seek incomplete */
1008      m_addx_acknowledge_0 = 0;   // address acknowledge, if cylinder is reached
1009      m_seek_incomplete_0 = 1;   // reset seek incomplete
10051010      return;
10061011   }
1007
1012   // assert the seek-read-write signal
10081013   m_s_r_w_0 = 0;
10091014
10101015   if (seekto < m_cylinder) {
1011      /* decrement cylinder */
1012      m_cylinder--;
1016      m_cylinder--;               // previous cylinder
10131017      if (m_cylinder < 0) {
10141018         m_cylinder = 0;
1015         m_log_addx_interlock_0 = 1;   /* deassert the log address interlock */
1016         m_seek_incomplete_0 = 1;   /* deassert seek incomplete */
1017         m_addx_acknowledge_0 = 0;   /* assert address acknowledge  */
1019         m_log_addx_interlock_0 = 1;   // deassert the log address interlock signal
1020         m_seek_incomplete_0 = 1;   // deassert seek incomplete signal
1021         m_addx_acknowledge_0 = 0;   // assert address acknowledge signal
10181022         LOG_DRIVE((1,"[DHD]   %s: STROBE to cylinder %d incomplete\n", __FUNCTION__, seekto));
10191023         return;
10201024      }
1021   } else {
1025   }
1026   if (seekto > m_cylinder) {
10221027      /* increment cylinder */
10231028      m_cylinder++;
10241029      if (m_cylinder >= DIABLO_CYLINDERS) {
10251030         m_cylinder = DIABLO_CYLINDERS - 1;
1026         m_log_addx_interlock_0 = 1;   /* deassert the log address interlock */
1027         m_seek_incomplete_0 = 1;   /* deassert seek incomplete */
1028         m_addx_acknowledge_0 = 0;   /* assert address acknowledge  */
1031         m_log_addx_interlock_0 = 1;   // deassert the log address interlock signal
1032         m_seek_incomplete_0 = 1;   // deassert seek incomplete signal
1033         m_addx_acknowledge_0 = 0;   // assert address acknowledge signal
10291034         LOG_DRIVE((1,"[DHD]   %s: STROBE to cylinder %d incomplete\n", __FUNCTION__, seekto));
10301035         return;
10311036      }
10321037   }
10331038   LOG_DRIVE((1,"[DHD]   %s: STROBE to cylinder %d (now %d) - interlock\n", __FUNCTION__, seekto, m_cylinder));
10341039
1035   m_addx_acknowledge_0 = 1;   /* deassert address acknowledge  */
1036   m_seek_incomplete_0 = 1;   /* deassert seek incomplete */
1040   m_addx_acknowledge_0 = 1;   // deassert address acknowledge signal
1041   m_seek_incomplete_0 = 1;   // deassert seek incomplete signal
10371042   read_sector();
10381043}
10391044
r26169r26170
10831088 */
10841089void diablo_hd_device::wr_data(int index, int wrdata)
10851090{
1086   if (m_wrgate_0) {
1087      /* write gate is not asserted (active 0) */
1088      return;
1089   }
1091   if (m_wrgate_0)
1092      return;   // write gate is not asserted (active 0)
10901093
1091   /* don't write before or beyond the sector */
10921094   if (index < 0 || index >= bits_per_sector())
1093      return;
1095      return;   // don't write before or beyond the sector
10941096
1095   if (-1 == m_page) {
1096      /* invalid page */
1097      return;
1098   }
1097   if (-1 == m_page)
1098      return;   // invalid page
10991099
11001100   UINT32 *bits = expand_sector();
11011101   if (-1 == m_wrfirst)
r26169r26170
11241124{
11251125   int bit = 0;
11261126
1127   if (m_rdgate_0) {
1128      /* read gate is not asserted (active 0) */
1129      return 0;
1130   }
1127   if (m_rdgate_0)
1128      return 0;   // read gate is not asserted (active 0)
11311129
1132   /* don't read before or beyond the sector */
11331130   if (index < 0 || index >= bits_per_sector())
1134      return 1;
1131      return 1;   // don't read before or beyond the sector
11351132
1136   /* no data while sector mark is low (?) */
11371133   if (0 == m_sector_mark_0)
1138      return 1;
1134      return 1;   // no data while sector mark is low (?)
11391135
1140   if (-1 == m_page) {
1141      /* invalid page */
1142      return 1;
1143   }
1136   if (-1 == m_page)
1137      return 1;   // invalid page
11441138
11451139   UINT32 *bits = expand_sector();
1146
11471140   if (-1 == m_rdfirst)
11481141      m_rdfirst = index;
11491142
r26169r26170
11661159{
11671160   int clk = 0;
11681161
1169   /* don't read before or beyond the sector */
11701162   if (index < 0 || index >= bits_per_sector())
1171      return 1;
1163      return 1;   // don't read before or beyond the sector
11721164
1173   /* no clock while sector mark is low (?) */
11741165   if (0 == m_sector_mark_0)
1175      return 1;
1166      return 1;   // no clock while sector mark is low (?)
11761167
1177   if (-1 == m_page) {
1178      /* invalid page */
1179      return 1;
1180   }
1168   if (-1 == m_page)
1169      return 1;   // invalid page
11811170
11821171   UINT32 *bits = expand_sector();
1183
11841172   if (-1 == m_rdfirst)
11851173      m_rdfirst = index;
11861174
r26169r26170
12181206{
12191207   LOG_DRIVE((9,"[DHD]   %s: unit #%d C/H/S:%d/%d/%d\n", __FUNCTION__, m_unit, m_cylinder, m_head, m_sector));
12201208
1221   /* squeeze previous sector, if it was written to */
1209   // squeeze previous sector bits, if it was written to
12221210   squeeze_sector();
12231211
12241212   m_sector_mark_0 = 0;
12251213
1226   /* reset read and write bit locations */
1214   // reset read and write bit locations
12271215   m_rdfirst = -1;
12281216   m_rdlast = -1;
12291217   m_wrfirst = -1;
12301218   m_wrlast = -1;
12311219
1232   /* count sectors */
1220   // count up the sector number
12331221   m_sector = (m_sector + 1) % DIABLO_SPT;
1234   /* read the sector */
12351222   read_sector();
12361223}
12371224
r26169r26170
12771264   LOG_DRIVE((0,"[DHD]   %s: sector mark 1 time  : %.0fns\n", __FUNCTION__, 1e9 * m_sector_mark_1_time.as_double()));
12781265   LOG_DRIVE((0,"[DHD]   %s: bit time            : %.0fns\n", __FUNCTION__, 1e9 * m_bit_time.as_double()));
12791266
1280   m_s_r_w_0 = 1;               /* seek/read/write not ready */
1281   m_ready_0 = 1;               /* drive is not ready */
1282   m_sector_mark_0 = 1;         /* sector mark clear */
1283   m_addx_acknowledge_0 = 1;      /* drive address acknowledge is not active */
1284   m_log_addx_interlock_0 = 1;   /* drive log address interlock is not active */
1285   m_seek_incomplete_0 = 1;      /* drive seek incomplete is not active */
1267   m_s_r_w_0 = 1;               // deassert seek/read/write ready
1268   m_ready_0 = 1;               // deassert drive ready
1269   m_sector_mark_0 = 1;         // deassert sector mark
1270   m_addx_acknowledge_0 = 1;      // deassert drive address acknowledge
1271   m_log_addx_interlock_0 = 1;      // deassert drive log address interlock
1272   m_seek_incomplete_0 = 1;      // deassert drive seek incomplete
12861273
1287   /* reset the disk drive's address */
1288   m_cylinder = 0;
1289   m_head = 0;
1290   m_sector = DIABLO_SPT - 1;
1274   // reset the disk drive's address
1275   m_cylinder = -1;
1276   m_head = -1;
1277   m_sector = -1;
12911278   m_page = -1;
12921279
1293   /* disable the gates */
1280   // disable the erase, write and read gates
12941281   m_egate_0 = 1;
12951282   m_wrgate_0 = 1;
12961283   m_rdgate_0 = 1;
12971284
1298   /* reset read/write first and last indices */
1285   // reset read and write first and last indices
12991286   m_wrfirst = -1;
13001287   m_wrlast = -1;
13011288   m_rdfirst = -1;
13021289   m_rdlast = -1;
13031290
1291   // for units with a CHD assigned to them start the timer
13041292   if (m_handle)
13051293      timer_set(m_sector_time - m_sector_mark_0_time, 1, 0);
13061294}

Previous 199869 Revisions Next


© 1997-2024 The MAME Team