Previous 199869 Revisions Next

r31126 Friday 27th June, 2014 at 18:59:33 UTC by Michael Zapf
(MESS) Some more steps towards a new HFDC. Legacy implementation to be
kept as default (hfdc) until new HFDC is done.
[src/emu/bus/ti99_peb]hfdc.c hfdc.h
[src/emu/machine]hdc9234.c hdc9234.h

trunk/src/emu/bus/ti99_peb/hfdc.c
r31125r31126
22// copyright-holders:Michael Zapf
33/****************************************************************************
44
5    Myarc Hard and Floppy Disk Controller
6    based on SMC9234
7    High Density, Double-sided
5    Myarc Hard and Floppy Disk Controller ("HFDC")
86
9    FIXME: HFDC does not work at CRU addresses other than 1100
10    (test shows
11        hfdc: reado 41f5 (00): 00
12        hfdc: reado 41f4 (00): 00 -> wrong rom page? (should be (02)))
7    The HFDC is based on the HDC9234 controller chip from Standard
8    Microsystems Corporation (SMC). It can work with up to three MFM hard disk
9    drives and up to four floppy disk drives.
1310
14    Michael Zapf
11    Data flow is detached from the main CPU. The HDC transfers data to/from
12    the drives using direct memory access to attached memory circuits. That
13    is, to write a sector on a drive the CPU must set up the contents in the
14    memory, then initiate a sector write operation.
1515
16    February 2012: Rewritten as class
16    The advantage is a much higher data rate (in particular important when
17    working with hard disks) with less load for the main CPU. Also, we do not
18    need a READY line control (as seen with the WD17xx-based controllers).
19    Any kinds of asynchronous events are propagated via INTA* (configurable
20    to INTB*).
1721
22    Most of the control logic is hidden in the custom Gate Array chip. We do
23    not have details on its contents, but the specifications in the HFDC manual
24    and in the schematics are sufficient to create a (functionally) proper
25    emulation.
26
27    The HDC9234 can also control tape drives. In early HFDC controller card
28    layouts, a socket for connecting a drive is available. However, there
29    never was a support from the DSR (firmware), so this feature was eliminated
30    in later releases.
31
32    Components
33
34    HDC 9234      - Universal Disk Controller
35    FDC 9216      - Floppy disk data separator (8 MHz, divider is set by CD0 and CD1)
36    HDC 92C26     - MFM hard disk data separator (10 MHz, also used for 9234)
37    HDC 9223      - Analog data separator support
38    DS 1000-50    - Delay circuit
39    MM 58274BN    - Real time clock
40    HM 6264-LP15  - SRAM 8K x 8   (may also be 32K x 8)
41    27C128        - EPROM 16K x 8
42
43    Author: Michael Zapf
1844    June 2014: Rewritten for modern floppy implementation
1945
2046    WORK IN PROGRESS
2147
2248*****************************************************************************/
2349
50/*
51    FIXME: HFDC does not work at CRU addresses other than 1100
52    (test shows
53        hfdc: reado 41f5 (00): 00
54        hfdc: reado 41f4 (00): 00 -> wrong rom page? (should be (02)))
55*/
56
2457#include "emu.h"
2558#include "peribox.h"
2659#include "hfdc.h"
2760#include "machine/ti99_hd.h"
28#include "imagedev/flopdrv.h"
2961#include "formats/ti99_dsk.h"       // Format
3062
3163#define BUFFER "ram"
r31125r31126
4274
4375#define TRACE_EMU 1
4476#define TRACE_CRU 1
77#define TRACE_COMP 1
78#define TRACE_RAM 0
79#define TRACE_ROM 0
80#define TRACE_LINES 1
81#define TRACE_MOTOR 1
4582
4683// =========================================================================
4784
r31125r31126
4986    Modern implementation.
5087*/
5188myarc_hfdc_device::myarc_hfdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
52   : ti_expansion_card_device(mconfig, TI99_HFDC, "Myarc Hard and Floppy Disk Controller", tag, owner, clock, "ti99_hfdc", __FILE__),
89   : ti_expansion_card_device(mconfig, TI99_HFDC, "Myarc Hard and Floppy Disk Controller", tag, owner, clock, "ti99_hfdc_new", __FILE__),
5390      m_hdc9234(*this, FDC_TAG),
5491      m_clock(*this, CLOCK_TAG)
5592{
5693}
5794
95
96SETADDRESS_DBIN_MEMBER( myarc_hfdc_device::setaddress_dbin )
97{
98   // Selection login in the PAL and some circuits on the board
99
100   // Is the card being selected?
101   // Area = 4000-5fff
102   // 010x xxxx xxxx xxxx
103   m_address = offset;
104   m_inDsrArea = ((m_address & m_select_mask)==m_select_value);
105
106   if (!m_inDsrArea) return;
107
108   // Is the HDC chip on the card being selected?
109   // HDC9234: read: 4fd0,4 (mirror 8,c)
110   // HDC9234: write: 4fd2,6 (mirror a,e)
111   // read:  ...0 1111 1101 xx00
112   // write: ...0 1111 1101 xx10
113
114   m_HDCsel = m_inDsrArea &&
115            ((state==ASSERT_LINE && ((m_address & 0x1ff3)==HDC_R_ADDR))    // read
116            || (state==CLEAR_LINE && ((m_address & 0x1ff3)==HDC_W_ADDR)));  // write
117
118   // Is the tape selected?
119   // ...0 1111 1100 xxxx
120   m_tapesel = m_inDsrArea && ((m_address & 0x1ff0)==TAPE_ADDR);
121
122   // Is the RTC selected on the card? (even addr)
123   // ...0 1111 111x xxx0
124   m_RTCsel = m_inDsrArea && ((m_address & 0x1fe1)==CLK_ADDR);
125
126   // Is RAM selected?
127   // ...1 xxxx xxxx xxxx
128   m_RAMsel = m_inDsrArea && ((m_address & 0x1000)==RAM_ADDR);
129
130   // Is ROM selected?
131   // not 0100 1111 11xx xxxx
132   m_ROMsel = m_inDsrArea && !m_RAMsel && !((m_address & 0x0fc0)==0x0fc0);
133}
134
58135/*
59136    Read a byte from the memory address space of the HFDC
60137
r31125r31126
72149*/
73150READ8Z_MEMBER(myarc_hfdc_device::readz)
74151{
75   if (m_selected && ((offset & m_select_mask)==m_select_value))
152   if (m_inDsrArea && m_selected)
76153   {
77      logerror("%s: Read access to %04x\n", tag(), offset & 0xffff);
154      if (m_tapesel)
155      {
156         logerror("%s: Tape support not available on this HFDC version (access to address %04x)\n", tag(), m_address & 0xffff);
157         return;
158      }
159
160      if (m_HDCsel)
161      {
162         if (!space.debugger_access()) *value = m_hdc9234->read(space, (m_address>>2)&1, 0xff);
163         if (TRACE_COMP) logerror("%s: %04x[HDC] -> %02x\n", tag(), m_address & 0xffff, *value);
164         return;
165      }
166
167      if (m_RTCsel)
168      {
169         if (!space.debugger_access()) *value = m_clock->read(space, (m_address & 0x001e) >> 1);
170         if (TRACE_COMP) logerror("%s: %04x[CLK] -> %02x\n", tag(), m_address & 0xffff, *value);
171         return;
172      }
173
174      if (m_RAMsel)
175      {
176         // 0101 00xx xxxx xxxx  static 0x08
177         // 0101 01xx xxxx xxxx  bank 1
178         // 0101 10xx xxxx xxxx  bank 2
179         // 0101 11xx xxxx xxxx  bank 3
180         int bank = (m_address & 0x0c00) >> 10;
181         *value = m_buffer_ram[(m_ram_page[bank]<<10) | (m_address & 0x03ff)];
182         if (TRACE_RAM) logerror("%s: %04x[%02x] -> %02x\n", tag(), m_address & 0xffff, m_ram_page[bank], *value);
183         return;
184      }
185
186      if (m_ROMsel)
187      {
188         *value = m_dsrrom[(m_rom_page << 12) | (m_address & 0x0fff)];
189         if (TRACE_ROM) logerror("%s: %04x[%02x] -> %02x\n", tag(), m_address & 0xffff, m_rom_page, *value);
190         return;
191      }
78192   }
79193}
80194
r31125r31126
92206*/
93207WRITE8_MEMBER( myarc_hfdc_device::write )
94208{
95   if (m_selected && ((offset & m_select_mask)==m_select_value))
209   if (m_inDsrArea && m_selected)
96210   {
97      logerror("%s: Write access to %04x: %02x\n", tag(), offset & 0xffff, data);
211      if (m_tapesel)
212      {
213         logerror("%s: Tape support not available on this HFDC version (write access to address %04x: %02x)\n", tag(), m_address & 0xffff, data);
214         return;
215      }
216
217      if (m_HDCsel)
218      {
219         if (TRACE_COMP) logerror("%s: %04x[HDC] <- %02x\n", tag(), m_address & 0xffff, data);
220         if (!space.debugger_access()) m_hdc9234->write(space, (m_address>>2)&1, data, 0xff);
221         return;
222      }
223
224      if (m_RTCsel)
225      {
226         if (TRACE_COMP) logerror("%s: %04x[CLK] <- %02x\n", tag(), m_address & 0xffff, data);
227         if (!space.debugger_access()) m_clock->write(space, (m_address & 0x001e) >> 1, data);
228         return;
229      }
230
231      if (m_RAMsel)
232      {
233         // 0101 00xx xxxx xxxx  static 0x08
234         // 0101 01xx xxxx xxxx  bank 1
235         // 0101 10xx xxxx xxxx  bank 2
236         // 0101 11xx xxxx xxxx  bank 3
237         int bank = (m_address & 0x0c00) >> 10;
238         if (TRACE_RAM) logerror("%s: %04x[%02x] <- %02x\n", tag(), m_address & 0xffff, m_ram_page[bank], data);
239         m_buffer_ram[(m_ram_page[bank]<<10) | (m_address & 0x03ff)] = data;
240         return;
241      }
242      // The rest is ROM
243      if (m_ROMsel)
244      {
245         if (TRACE_ROM) logerror("%s: Ignoring write ROM %04x[%02x]: %02x\n", tag(), m_address & 0xffff, m_rom_page, data);
246      }
98247   }
99248}
100249
r31125r31126
130279*/
131280READ8Z_MEMBER(myarc_hfdc_device::crureadz)
132281{
282   UINT8 reply;
133283   if ((offset & 0xff00)==m_cru_base)
134284   {
135      if (TRACE_CRU) logerror("%s: CRU read access to %04x\n", tag(), offset & 0xffff);
285      if ((offset & 0x00ff)==0)  // CRU bits 0-7
286      {
287         if (m_see_switches)
288         {
289            // DIP switches.  Logic levels are inverted (on->0, off->1).  CRU
290            // bit order is the reverse of DIP-switch order, too (dip 1 -> bit 7,
291            // dip 8 -> bit 0).
292            // MZ: 00 should not be used since there is a bug in the
293            // DSR of the HFDC which causes problems with SD disks
294            // (controller tries DD and then fails to fall back to SD) */
295            reply = ~(ioport("HFDCDIP")->read());
296         }
297         else
298         {
299            reply = 0;
300            if (m_irq == ASSERT_LINE)  reply |= 0x01;
301            if (m_dip == ASSERT_LINE)  reply |= 0x02;
302            if (m_motor_running) reply |= 0x04;
303         }
304         *value = reply;
305      }
306      else   // CRU bits 8+
307      {
308         *value = 0;
309      }
310
311      if (TRACE_CRU) logerror("%s: CRU %04x -> %02x\n", tag(), offset & 0xffff, *value);
136312   }
137313}
138314
r31125r31126
141317
142318       7     6     5     4     3     2     1     0
143319    +-----+-----+-----+-----+-----+-----+-----+-----+
144    |  0  | MON | DIP | ROM1| ROM0| MON | RES | SEL |
320    |  0  | MON | DIP | ROM1| ROM0| MON | RES*| SEL |
145321    |     |     |     | CSEL| CD1 | CD0 |     |     |
146322    +-----+-----+-----+-----+-----+-----+-----+-----+
147323
r31125r31126
150326    |    RAM page select @5C00    |    RAM page select @5800    |     RAM page select @5400   |  -  |
151327    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
152328
153    SEL = Select card (and map ROM into address space)
154    RES = Reset controller
155    MON = Motor on
329    SEL  = Select card (and map ROM into address space)
330    RES* = Reset controller
331    MON  = Motor on / same line goes to CD0 input of floppy separator
156332    ROM bank select: bank 0..3; bit 3 = MSB, 4 = LSB
157333    RAM bank select: bank 0..31; bit 9 = LSB (accordingly for other two areas)
158334    CD0 and CD1 are Clock Divider selections for the Floppy Data Separator (FDC9216)
159    CSEL = cru_select
335    CSEL = CRU input select (m_see_switches)
160336
161337    HFDC manual p. 43
162338*/
r31125r31126
164340{
165341   if ((offset & 0xff00)==m_cru_base)
166342   {
167      if (TRACE_CRU) logerror("%s: CRU write access to %04x: %d\n", tag(), offset & 0xffff, data);
343      if (TRACE_CRU) logerror("%s: CRU %04x <- %d\n", tag(), offset & 0xffff, data);
168344
169345      int bit = (offset >> 1) & 0x1f;
170346
r31125r31126
185361         m_selected = (data!=0);
186362         if (TRACE_CRU) logerror("%s: selected = %d\n", tag(), m_selected);
187363         break;
364
365      case 1:
366         if (TRACE_CRU) if (data==0) logerror("%s: trigger HDC reset\n", tag());
367         m_hdc9234->reset((data == 0)? ASSERT_LINE : CLEAR_LINE);
368         break;
369
370      case 2:
371         m_CD = (data != 0)? (m_CD | 1) : (m_CD & 0xfe);
372
373         // Activate motor
374         if (data==0 && m_lastval==1)
375         {   // on falling edge, set motor_running for 4.23s
376            if (TRACE_CRU) logerror("%s: trigger motor (falling edge)\n", tag());
377            set_floppy_motors_running(true);
378         }
379         m_lastval = data;
380         break;
381
382      case 3:
383         m_CD = (data != 0)? (m_CD | 2) : (m_CD & 0xfd);
384         m_rom_page = (data != 0)? (m_rom_page | 2) : (m_rom_page & 0xfd);
385         break;
386
387      case 4:
388         m_see_switches = (data != 0);
389         m_rom_page = (data != 0)? (m_rom_page | 1) : (m_rom_page & 0xfe);
390         break;
391
392      default:
393         logerror("%s: Attempt to set undefined CRU bit %d\n", tag(), bit);
188394      }
189395   }
190396}
191397
192398/*
193    Called whenever the state of the HDC9234 interrupt pin changes.
399    Monoflop has gone back to the OFF state.
194400*/
195WRITE_LINE_MEMBER( myarc_hfdc_device::intrq_w )
401void myarc_hfdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
196402{
197   m_irq = state;
403   set_floppy_motors_running(false);
404}
198405
199   // Set INTA*
200   // Signal from SMC is active high, INTA* is active low; board inverts signal
201   // Anyway, we keep with ASSERT_LINE and CLEAR_LINE
202   m_slot->set_inta(state);
406/*
407    This is called back from the floppy when an index hole is passing by.
408*/
409void myarc_hfdc_device::floppy_index_callback(floppy_image_device *floppy, int state)
410{
411   logerror("%s: Index callback level=%d\n", tag(), state);
412   // m_status_latch = (state==ASSERT_LINE)? (m_status_latch | HDC_DS_INDEX) :  (m_status_latch & ~HDC_DS_INDEX);
413   set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE));
203414}
204415
416void myarc_hfdc_device::set_bits(UINT8& byte, int mask, bool set)
417{
418   if (set) byte |= mask;
419   else byte &= ~mask;
420}
421
205422/*
206    Called whenever the state of the HDC9234 DMA in progress changes.
423    Calculate the logarithm. This is needed to determine the index of a drive.
424    Returns -1 for value=0
207425*/
208WRITE_LINE_MEMBER( myarc_hfdc_device::dip_w )
426int myarc_hfdc_device::slog2(int value)
209427{
210   m_dip = state;
428   int i=-1;
429   while (value!=0)
430   {
431      value >>= 1;
432      i++;
433   }
434   return i;
211435}
212436
437/*
438    Read the selected latch via the auxbus. This is always the status register.
439*/
440READ8_MEMBER( myarc_hfdc_device::auxbus_in )
441{
442   UINT8 reply = 0;
443   int index = 0;
444
445   if ((m_output1_latch & 0xf0)==0)
446   {
447      logerror("%s: no drive selected, returning 0\n", tag());
448      // No HD and no floppy
449      return 0; /* is that the correct default value? */
450   }
451
452   return m_status_latch;
453}
454
455
456/*
457    When the HDC outputs a byte via its AB (auxiliary bus), we need to latch it.
458    The target of the transfer is determined by two control lines (S1,S0).
459    (0,0) = input drive status
460    (0,1) = DMA address
461    (1,0) = OUTPUT1
462    (1,1) = OUTPUT2
463*/
213464WRITE8_MEMBER( myarc_hfdc_device::auxbus_out )
214465{
215   logerror("%s: Write access to auxbus at %04x: %02x\n", tag(), offset & 0xffff, data);
466   int index;
467   switch (offset)
468   {
469   case HDC_INPUT_STATUS:
470      logerror("%s: Invalid operation: S0=S1=0, but tried to write (expected: read drive status)\n", tag());
471      break;
472
473   case HDC_OUTPUT_DMA_ADDR:
474      // Value is dma address byte. Shift previous contents to the left.
475      // The value is latched inside the Gate Array.
476      m_dma_address = ((m_dma_address << 8) + (data&0xff))&0xffffff;
477      break;
478
479   case HDC_OUTPUT_1:
480      // value is output1
481      // The HFDC interprets the value as follows:
482      // WDS = Winchester Drive System, old name for hard disk
483      // +------+------+------+------+------+------+------+------+
484      // | WDS3 | WDS2 | WDS1 | DSKx | x=4  | x=3  | x=2  | x=1  |
485      // +------+------+------+------+------+------+------+------+
486      // Accordingly, drive 0 is always the floppy; selected by the low nibble
487
488      logerror("%s: Setting OUTPUT1 latch to %02x\n", tag(), data);
489      m_output1_latch = data;
490
491      if ((data & 0x10) != 0)
492      {
493         // Floppy selected
494         connect_floppy_unit(slog2(data & 0x0f));
495      }
496      else
497      {
498         // HD selected
499//          index = slog2((data>>4) & 0x0f);
500//          if (index>=0) m_hdc9234->connect_hard_drive(m_harddisk_unit[index-1]);
501         set_bits(m_status_latch, HDC_DS_READY, false);
502      }
503      break;
504
505   case HDC_OUTPUT_2:
506      // value is output2
507      logerror("%s: Setting OUTPUT2 latch to %02x\n", tag(), data);
508      m_output2_latch = data;
509      break;
510   }
216511}
217512
218READ8_MEMBER( myarc_hfdc_device::auxbus_in )
513enum
219514{
220   logerror("%s: Read access to auxbus at %04x\n", tag(), offset & 0xffff);
221   return 0;
515   HFDC_FLOPPY = 1,
516   HFDC_HARDDISK = 2
517};
518
519void myarc_hfdc_device::connect_floppy_unit(int index)
520{
521   // Check if we have a new floppy
522   if (index>=0)
523   {
524      if (m_floppy_unit[index] != m_current_floppy)
525      {
526         logerror("%s: Connect floppy drive %d\n", tag(), index);
527         if (m_current_floppy != NULL)
528         {
529            // Disconnect old drive from index line
530            m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
531
532            // Connect new drive
533            m_current_floppy = m_floppy_unit[index];
534
535            // We don't use the READY line of floppy drives.
536            // READY is asserted when DSKx = 1
537            // The controller fetches the state with the auxbus access
538            m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(myarc_hfdc_device::floppy_index_callback), this));
539         }
540         m_hdc9234->connect_floppy_drive(m_floppy_unit[index]);
541      }
542      set_ready(HFDC_FLOPPY, true);
543   }
544   else
545   {
546      logerror("%s: Disconnect all floppy drives\n", tag());
547      // Disconnect current floppy
548      if (m_current_floppy != NULL)
549      {
550         m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
551         m_current_floppy = NULL;
552      }
553      set_ready(HFDC_FLOPPY, false);
554   }
222555}
223556
557void myarc_hfdc_device::connect_harddisk_unit(int index)
558{
559   set_ready(HFDC_HARDDISK, false);
560}
561
224562/*
563    Joins the ready lines from the floppy drives and the hard drives
564*/
565void myarc_hfdc_device::set_ready(int dev, bool ready)
566{
567   m_readyflags = ready? (m_readyflags | dev) : (m_readyflags & ~dev);
568   set_bits(m_status_latch, HDC_DS_READY, (m_readyflags != 0));
569}
570
571/*
572    All floppy motors are operated by the same line.
573*/
574void myarc_hfdc_device::set_floppy_motors_running(bool run)
575{
576   if (run)
577   {
578      if (TRACE_MOTOR)
579         if (m_MOTOR_ON==CLEAR_LINE) logerror("%s: Motor START\n", tag());
580      m_MOTOR_ON = ASSERT_LINE;
581      m_motor_on_timer->adjust(attotime::from_msec(4230));
582   }
583   else
584   {
585      if (TRACE_MOTOR)
586         if (m_MOTOR_ON==ASSERT_LINE) logerror("%s: Motor STOP\n", tag());
587      m_MOTOR_ON = CLEAR_LINE;
588   }
589
590   // Set all motors
591   for (int i=0; i < 4; i++)
592      if (m_floppy_unit[i] != NULL) m_floppy_unit[i]->mon_w((run)? 0 : 1);
593}
594
595/*
596    Called whenever the state of the HDC9234 interrupt pin changes.
597*/
598WRITE_LINE_MEMBER( myarc_hfdc_device::intrq_w )
599{
600   m_irq = (line_state)state;
601   if (TRACE_LINES) logerror("%s: INT pin from controller = %d, propagating to INTA*\n", tag(), state);
602
603   // Set INTA*
604   // Signal from SMC is active high, INTA* is active low; board inverts signal
605   // Anyway, we stay with ASSERT_LINE and CLEAR_LINE
606   m_slot->set_inta(state);
607}
608
609/*
610    Called whenever the state of the HDC9234 DMA in progress changes.
611*/
612WRITE_LINE_MEMBER( myarc_hfdc_device::dip_w )
613{
614   m_dip = (line_state)state;
615}
616
617/*
225618    Read a byte from the onboard SRAM
226619*/
227620READ8_MEMBER( myarc_hfdc_device::read_buffer )
r31125r31126
272665   for (int i=1; i < 4; i++) m_ram_page[i] = 0;
273666
274667   m_output1_latch = m_output2_latch = 0;
275   m_dip = m_irq = false;
668   m_dip = m_irq = CLEAR_LINE;
276669   m_see_switches = false;
277670   m_CD = 0;
278671   m_motor_running = false;
279672   m_selected = false;
673   m_lastval = 0;
674   m_readyflags = 0;
675
676   for (int i=0; i < 4; i++)
677   {
678      if (m_floppy_unit[i] != NULL)
679         logerror("%s: Connector %d with %s\n", tag(), i, m_floppy_unit[i]->name());
680      else
681         logerror("%s: Connector %d has no floppy attached\n", tag(), i);
682   }
683
684   // Disconnect all units
685   connect_floppy_unit(-1);
686   connect_harddisk_unit(-1);
280687}
281688
689void myarc_hfdc_device::device_config_complete()
690{
691   for (int i=0; i < 4; i++)
692      m_floppy_unit[i] = NULL;
693
694   // Seems to be null when doing a "-listslots"
695   if (subdevice("0")!=NULL) m_floppy_unit[0] = static_cast<floppy_image_device*>(subdevice("0")->first_subdevice());
696   if (subdevice("1")!=NULL) m_floppy_unit[1] = static_cast<floppy_image_device*>(subdevice("1")->first_subdevice());
697   if (subdevice("2")!=NULL) m_floppy_unit[2] = static_cast<floppy_image_device*>(subdevice("2")->first_subdevice());
698   if (subdevice("3")!=NULL) m_floppy_unit[3] = static_cast<floppy_image_device*>(subdevice("3")->first_subdevice());
699}
700
282701INPUT_PORTS_START( ti99_hfdc )
283702   PORT_START( "CRUHFDC" )
284703   PORT_DIPNAME( 0x1f00, 0x1100, "HFDC CRU base" )
r31125r31126
307726      PORT_DIPSETTING( 0xff, "80 track HD, 2 ms")
308727INPUT_PORTS_END
309728
729FLOPPY_FORMATS_MEMBER(myarc_hfdc_device::floppy_formats)
730   FLOPPY_TI99_SDF_FORMAT,
731   FLOPPY_TI99_TDF_FORMAT
732FLOPPY_FORMATS_END
733
734static SLOT_INTERFACE_START( hfdc_floppies )
735   SLOT_INTERFACE( "525dd", FLOPPY_525_DD )        // 40 tracks
736   SLOT_INTERFACE( "525qd", FLOPPY_525_QD )        // 80 tracks
737   SLOT_INTERFACE( "35dd", FLOPPY_35_DD )          // 80 tracks
738SLOT_INTERFACE_END
739
310740MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
311741   MCFG_DEVICE_ADD(FDC_TAG, HDC9234, 0)
312742   MCFG_HDC9234_INTRQ_CALLBACK(WRITELINE(myarc_hfdc_device, intrq_w))
r31125r31126
316746   MCFG_HDC9234_DMA_IN_CALLBACK(READ8(myarc_hfdc_device, read_buffer))
317747   MCFG_HDC9234_DMA_OUT_CALLBACK(WRITE8(myarc_hfdc_device, write_buffer))
318748
749   MCFG_FLOPPY_DRIVE_ADD("0", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats)
750   MCFG_FLOPPY_DRIVE_ADD("1", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats)
751   MCFG_FLOPPY_DRIVE_ADD("2", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
752   MCFG_FLOPPY_DRIVE_ADD("3", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
753
319754   MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
320755   MCFG_MM58274C_MODE24(1) // 24 hour
321756   MCFG_MM58274C_DAY1(0)   // sunday
r31125r31126
355790#define LOG logerror
356791
357792myarc_hfdc_legacy_device::myarc_hfdc_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
358   : ti_expansion_card_device(mconfig, TI99_HFDC_LEG, "Myarc Hard and Floppy Disk Controller LEGACY", tag, owner, clock, "ti99_hfdc_leg", __FILE__),
793   : ti_expansion_card_device(mconfig, TI99_HFDC_LEG, "Myarc Hard and Floppy Disk Controller LEGACY", tag, owner, clock, "ti99_hfdc", __FILE__),
359794      m_hdc9234(*this, FDC_TAG),
360795      m_clock(*this, CLOCK_TAG)
361796{
r31125r31126
8331268   for (int i=1; i < 4; i++) m_ram_page[i] = 0;
8341269   m_dma_address = 0;
8351270   m_output1_latch = m_output2_latch = 0;
836   m_dip = m_irq = false;
1271   m_dip = m_irq = 0;
8371272   m_cru_select = false;
8381273   m_CD0 = m_CD1 = 0;
8391274   m_motor_running = false;
trunk/src/emu/bus/ti99_peb/hfdc.h
r31125r31126
2020#define HFDC_MAX_FLOPPY 4
2121#define HFDC_MAX_HARD 4
2222
23#include "imagedev/floppy.h"
2324#include "machine/mm58274c.h"
2425#include "machine/hdc9234.h"
2526
r31125r31126
3536
3637   DECLARE_READ8Z_MEMBER(readz);
3738   DECLARE_WRITE8_MEMBER(write);
39   DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin);
3840   DECLARE_READ8Z_MEMBER(crureadz);
3941   DECLARE_WRITE8_MEMBER(cruwrite);
4042
r31125r31126
4547   DECLARE_READ8_MEMBER( read_buffer );
4648   DECLARE_WRITE8_MEMBER( write_buffer );
4749
50   DECLARE_FLOPPY_FORMATS( floppy_formats );
51
4852private:
53   void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
4954   void device_start();
5055   void device_reset();
56   void device_config_complete();
5157
5258   const rom_entry *device_rom_region() const;
5359   machine_config_constructor device_mconfig_additions() const;
5460   ioport_constructor device_input_ports() const;
5561
62   // Callback for the index hole
63   void floppy_index_callback(floppy_image_device *floppy, int state);
64
65   // Operate the floppy motors
66   void set_floppy_motors_running(bool run);
67
68   // Connect or disconnect floppy drives
69   void connect_floppy_unit(int index);
70
71   // Connect or disconnect harddisk drives
72   void connect_harddisk_unit(int index);
73
5674   // Motor monoflop (4.23 sec)
5775   emu_timer*      m_motor_on_timer;
5876
r31125r31126
6280   // Clock chip on the board
6381   required_device<mm58274c_device> m_clock;
6482
83   // Link to the attached floppy drives
84   floppy_image_device*    m_floppy_unit[4];
85
86   // Currently selected floppy drive
87   floppy_image_device*    m_current_floppy;
88
6589   // True: Access to DIP switch settings, false: access to line states
6690   bool    m_see_switches;
6791
6892   // IRQ state
69   bool    m_irq;
93   line_state    m_irq;
7094
7195   // DMA in Progress state
72   bool    m_dip;
96   line_state    m_dip;
7397
7498   // When true, motor monoflop is high
7599   bool    m_motor_running;
76100
101   // Address in card area
102   bool m_inDsrArea;
103
104   // HDC selected
105   bool m_HDCsel;
106
107   // RTC selected
108   bool m_RTCsel;
109
110   // Tape selected
111   bool m_tapesel;
112
113   // RAM selected
114   bool m_RAMsel;
115
116   // RAM selected
117   bool m_ROMsel;
118
119   // Recent address
120   int m_address;
121
77122   // Device Service Routine ROM (firmware)
78123   UINT8*  m_dsrrom;
79124
80125   // ROM banks.
81126   int     m_rom_page;
82127
83   // HFDC on-board SRAM (32K)
128   // HFDC on-board SRAM (8K or 32K)
84129   UINT8*  m_buffer_ram;
85130
86131   // RAM page registers
87132   int     m_ram_page[4];
88133
89   // Output 1 latch
134   // Drive status latch (STB0)
135   UINT8   m_status_latch;
136
137   // DMA address latch (in Gate Array) (STB1)
138   UINT32  m_dma_address;
139
140   // Output 1 latch (STB2)
90141   UINT8   m_output1_latch;
91142
92   // Output 2 latch
143   // Output 2 latch (STB3)
93144   UINT8   m_output2_latch;
94145
95146   // Clock divider bits 0 and 1. Unused in this emulation. */
96147   int     m_CD;
148
149   // Needed for triggering the motor monoflop
150   UINT8 m_lastval;
151
152   // Signal motor_on. When TRUE, makes all drives turning.
153   line_state m_MOTOR_ON;
154
155   // Calculates a simple version of a binary logarithm
156   int     slog2(int value);
157
158   // Utility function to set or unset bits in a byte
159   void set_bits(UINT8& byte, int mask, bool set);
160
161   // Joined ready line towards the controller
162   void set_ready(int dev, bool ready);
163   int  m_readyflags;
97164};
98165
99166// =========================================================================
trunk/src/emu/machine/hdc9234.c
r31125r31126
1/*
1/**************************************************************************
2
23    HDC9234 Hard and Floppy Disk Controller
4    Standard Microsystems Corporation (SMC)
35
46    This controller handles MFM and FM encoded floppy disks and hard disks.
5    The SMC9224 is used in some DEC systems.  The HDC9234 is used in the
6    Myarc HFDC card for the TI99/4A.
7    A variant, the SMC9224, is used in some DEC systems.
78
9    The HDC9234 is used in the Myarc HFDC card for the TI99/4A.
10
811    References:
9    * SMC HDC9234 preliminary data book (1988)
12    [1] SMC HDC9234 preliminary data book (1988)
1013
14    The HDC9234 controller is also referred to as the "Universal Disk Controller" (UDC)
15    by the data book
16
1117    Michael Zapf, June 2014
12*/
1318
19***************************************************************************/
20
1421#include "emu.h"
1522#include "hdc9234.h"
1623
24#define TRACE_REG 1
25#define TRACE_ACT 1
26
27/*
28    Register names of the HDC. The left part is the set of write registers,
29    while the right part are the read registers.
30*/
31enum
32{
33   // Write registers   |   Read registers
34   //--------------------------------------
35   DMA7_0=0,
36   DMA15_8=1,
37   DMA23_16=2,
38   DESIRED_SECTOR=3,
39   DESIRED_HEAD=4,         CURRENT_HEAD=4,
40   DESIRED_CYLINDER=5,     CURRENT_CYLINDER=5,
41   SECTOR_COUNT=6,         CURRENT_IDENT=6,
42   RETRY_COUNT=7,          TEMP_STORAGE2=7,
43   MODE=8,                 CHIP_STATUS=8,
44   INT_COMM_TERM=9,        DRIVE_STATUS=9,
45   DATA_DELAY=10,          DATA=10,
46   COMMAND=11,             INT_STATUS=11
47};
48
49/*
50    Definition of bits in the status register [1] p.7
51*/
52enum
53{
54   ST_INTPEND = 0x80 ,       // interrupt pending
55   ST_DMAREQ  = 0x40 ,       // DMA request
56   ST_DONE    = 0x20 ,       // command done
57   ST_TERMCOD = 0x18 ,       // termination code (see below)
58      TC_SUCCESS = 0x00 ,    // Successful completion
59      TC_RDIDERR = 0x08 ,    // Error in READ-ID sequence
60      TC_SEEKERR = 0x10 ,    // Error in SEEK sequence
61      TC_DATAERR = 0x18 ,    // Error in DATA-TRANSFER seq.
62   ST_RDYCHNG = 0x04 ,       // ready change
63   ST_OVRUN   = 0x02 ,       // overrun/underrun
64   ST_BADSECT = 0x01         // bad sector
65};
66
67/*
68    Bits in the internal output registers. The registers are output via the
69    auxiliary bus (AB)
70
71    OUTPUT1
72    AB7     drive select 3
73    AB6     drive select 2
74    AB5     drive select 1
75    AB4     drive select 0
76    AB3     programmable outputs
77    AB2     programmable outputs
78    AB1     programmable outputs
79    AB0     programmable outputs
80
81    OUTPUT2
82    AB7     drive select 3* (active low, used for tape operations)
83    AB6     reduce write current
84    AB5     step direction
85    AB4     step pulse
86    AB3     desired head 3
87    AB2     desired head 2
88    AB1     desired head 1
89    AB0     desired head 0
90*/
91enum
92{
93   OUT1_DRVSEL3    = 0x80,
94   OUT1_DRVSEL2    = 0x40,
95   OUT1_DRVSEL1    = 0x20,
96   OUT1_DRVSEL0    = 0x10,
97   OUT2_DRVSEL3I   = 0x80,
98   OUT2_REDWRT     = 0x40,
99   OUT2_STEPDIR    = 0x20,
100   OUT2_STEPPULSE  = 0x10,
101   OUT2_HEADSEL3   = 0x08,
102   OUT2_HEADSEL2   = 0x04,
103   OUT2_HEADSEL1   = 0x02,
104   OUT2_HEADSEL0   = 0x01
105};
106
107enum
108{
109   TYPE_AT = 0x00,
110   TYPE_HD = 0x01,
111   TYPE_FLOPPY8 = 0x02,
112   TYPE_FLOPPY5 = 0x03
113};
114
17115hdc9234_device::hdc9234_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
18116   : device_t(mconfig, HDC9234, "SMC HDC9234 Universal Disk Controller", tag, owner, clock, "hdc9234", __FILE__),
19117   m_out_intrq(*this),
r31125r31126
26124}
27125
28126/*
127    Set or reset some bits.
128*/
129void hdc9234_device::set_bits(UINT8& byte, int mask, bool set)
130{
131   if (set) byte |= mask;
132   else byte &= ~mask;
133}
134
135/*
136    Set/clear INT
137
138    Interupts are generated in the following occasions:
139    - when the DONE bit is set to 1 in the ISR and ST_DONE is set to 1
140    - when the READY_CHANGE bit is set to 1 in the ISR and ST_RDYCHNG is set to 1
141    (ready change: 1->0 or 0->1)
142*/
143void hdc9234_device::set_interrupt(line_state intr)
144{
145   if (intr == ASSERT_LINE)
146   {
147      // Only if there is not already a pending interrupt
148      if ((m_register_r[INT_STATUS] & ST_INTPEND) == 0)
149      {
150         m_register_r[INT_STATUS] |= ST_INTPEND;
151         m_out_intrq(intr);
152      }
153   }
154   else
155   {
156      // if there is a pending interrupt
157      if ((m_register_r[INT_STATUS] & ST_INTPEND) != 0)
158         m_out_intrq(intr);
159   }
160}
161
162/*
163    Process a command
164*/
165void hdc9234_device::process_command(UINT8 opcode)
166{
167   // Reset DONE and BAD_SECTOR [1], p.7
168   set_bits(m_register_r[INT_STATUS], ST_DONE | ST_BADSECT, false);
169
170/*
171    // Reset interrupt line (not explicitly mentioned in spec, but seems reasonable
172    set_interrupt(CLEAR_LINE);
173
174    // Clear Interrupt Pending and Ready Change
175    set_bits(m_register_r[INT_STATUS], ST_INTPEND | ST_RDYCHNG, false);
176*/
177   m_command = opcode;
178
179   if (opcode == 0x00)
180   {
181      // RESET
182      // same effect as the RST* pin being active
183      if (TRACE_ACT) logerror("%s: Reset command\n", tag());
184      device_reset();
185   }
186   else if (opcode == 0x01)
187   {
188      // DESELECT DRIVE
189      // done when no drive is in use
190      if (TRACE_ACT) logerror("%s: drdeselect command\n", tag());
191      set_bits(m_output1, OUT1_DRVSEL3|OUT1_DRVSEL2|OUT1_DRVSEL1|OUT1_DRVSEL0, false);
192      set_bits(m_output2, OUT2_DRVSEL3I, true); // inverted level
193   }
194   else if (opcode >= 0x20 && opcode <= 0x3f)
195   {
196      // DRIVE SELECT
197      if (TRACE_ACT) logerror("%s: drselect command %02x\n", tag(), opcode);
198      drive_select(opcode&0x1f);
199   }
200   else if (opcode >= 0x40 && opcode <= 0x4f)
201   {
202      // SETREGPTR
203      if (TRACE_ACT) logerror("%s: setregptr command %02x\n", tag(), opcode);
204      m_register_pointer = opcode & 0xf;
205      // Spec does not say anything about the effect of setting an
206      // invalid value (only "care should be taken")
207      if (m_register_pointer > 10)
208      {
209         logerror("%s: set register pointer: Invalid register number: %d. Setting to 10.\n", tag(), m_register_pointer);
210         m_register_pointer = 10;
211      }
212   }
213}
214
215void hdc9234_device::drive_select(int driveparm)
216{
217   // Command word
218   //
219   //        7     6     5     4     3     2     1     0
220   //     +-----+-----+-----+-----+-----+-----+-----+-----+
221   //     |  0  |  0  |  1  |Delay|    Type   |   Drive   |
222   //     +-----+-----+-----+-----+-----+-----+-----+-----+
223   //
224   // [1] p.5: lower 4 bits of retry count register is put on OUTPUT1
225   m_output1 = (0x10 << (driveparm & 0x03)) | (m_register_w[RETRY_COUNT]&0x0f);
226
227   // The drive type is used to configure DMA burst mode ([1], p.12)
228   // and to select the timing parameters
229   m_selected_drive_type = (driveparm>>2) & 0x03;
230   m_head_load_delay_enable = (driveparm>>4)&0x01;
231
232/*
233    // We need to store the type of the drive for the poll_drives command
234    // to be able to correctly select the device (floppy or hard disk).
235    m_types[driveparm&0x03] = m_selected_drive_type;
236*/
237   // Copy the DMA registers to registers CURRENT_HEAD, CURRENT_CYLINDER,
238   // and CURRENT_IDENT. This is required during formatting ([1], p. 14)
239   // as the format command reuses the registers for formatting parameters.
240   m_register_r[CURRENT_HEAD] = m_register_r[DMA7_0];
241   m_register_r[CURRENT_CYLINDER] = m_register_r[DMA15_8];
242   m_register_r[CURRENT_IDENT] = m_register_r[DMA23_16];
243
244   m_register_r[CHIP_STATUS] = (m_register_r[CHIP_STATUS] & 0xfc) | (driveparm & 0x03);
245
246   sync_latches_out();
247   sync_status_in();
248}
249
250/*
251    This is pretty simple here, compared to wd17xx, because index and ready
252    callbacks have to be tied to the controller board outside the chip.
253*/
254void hdc9234_device::connect_floppy_drive(floppy_image_device* floppy)
255{
256   m_floppy = floppy;
257}
258
259/*
260    Get the state from outside and latch it in the register.
261    There should be a bus driver on the PCB which provides the signals from
262    both the hard and floppy drives during S0=S1=0 and STB*=0 times via the
263    auxiliary bus.
264*/
265void hdc9234_device::sync_status_in()
266{
267   UINT8 prev = m_register_r[DRIVE_STATUS];
268   m_register_r[DRIVE_STATUS] = m_in_auxbus(0);
269
270   // Raise interrupt if ready changes.
271   if (((m_register_r[DRIVE_STATUS] & HDC_DS_READY) != (prev & HDC_DS_READY))
272      & (m_register_r[INT_STATUS] & ST_RDYCHNG))
273   {
274      set_interrupt(ASSERT_LINE);
275   }
276}
277
278/*
279    Push the output registers over the auxiliary bus. It is expected that
280    the PCB contains latches to store the values.
281    TODO: Timing (the spec is not clear at that point)
282*/
283void hdc9234_device::sync_latches_out()
284{
285   m_output1 = (m_output1 & 0xf0) | (m_register_w[RETRY_COUNT]&0x0f);
286   m_out_auxbus((offs_t)HDC_OUTPUT_1, m_output1);
287   m_out_auxbus((offs_t)HDC_OUTPUT_2, m_output2);
288}
289
290/*
29291    Read a byte of data from the controller
30292    The address (offset) encodes the C/D* line (command and /data)
31293*/
32294READ8_MEMBER( hdc9234_device::read )
33295{
34   logerror("%s: Read access to %04x\n", tag(), offset & 0xffff);
35   return 0;
296   UINT8 reply = 0;
297
298   if ((offset & 1) == 0)
299   {
300      // Data register
301      reply = m_register_r[m_register_pointer];
302      if (TRACE_REG) logerror("%s: register[%d] -> %02x\n", tag(), m_register_pointer, reply);
303
304      // Autoincrement until DATA is reached.
305      if (m_register_pointer < DATA)  m_register_pointer++;
306   }
307   else
308   {
309      // Status register
310      reply = m_register_r[INT_STATUS];
311
312      // "The interrupt pin is reset to its inactive state
313      // when the UDC interrupt status register is read." [1] (p.3)
314      if (TRACE_REG) logerror("%s: interrupt status register -> %02x\n", tag(), reply);
315      set_interrupt(CLEAR_LINE);
316
317      // Clear the bits due to interrupt status register read.
318      m_register_r[INT_STATUS] &= ~(ST_INTPEND | ST_RDYCHNG);
319   }
320   return reply;
36321}
37322
38323/*
r31125r31126
41326*/
42327WRITE8_MEMBER( hdc9234_device::write )
43328{
44   logerror("%s: Write access to %04x: %d\n", tag(), offset & 0xffff, data);
329//  logerror("%s: Write access to %04x: %d\n", tag(), offset & 0xffff, data);
330
331   data &= 0xff;
332   if ((offset & 1)==0)
333   {
334      // Writing data to registers
335
336      // Data register
337      if (TRACE_REG) logerror("%s: register[%d] <- %02x\n", tag(), m_register_pointer, data);
338      m_register_w[m_register_pointer] = data;
339
340      // The DMA registers and the sector register for read and
341      // write are identical, so in that case we copy the contents
342      if (m_register_pointer < DESIRED_HEAD)  m_register_r[m_register_pointer] = data;
343
344      // Autoincrement until DATA is reached.
345      if (m_register_pointer < DATA)  m_register_pointer++;
346   }
347   else
348   {
349      process_command(data);
350   }
45351}
46352
353/*
354    Reset the controller. Negative logic, but we use ASSERT_LINE.
355*/
356WRITE_LINE_MEMBER( hdc9234_device::reset )
357{
358   if (state == ASSERT_LINE)
359   {
360      logerror("%s: Reset via RST line\n", tag());
361      device_reset();
362   }
363}
364
47365void hdc9234_device::device_start()
48366{
49367   logerror("%s: start\n", tag());
r31125r31126
59377
60378void hdc9234_device::device_reset()
61379{
62   logerror("%s: reset\n", tag());
380   m_command = 0;
381   m_selected_drive_type = 0;
382   m_head_load_delay_enable = false;
383   m_register_pointer = 0;
63384}
64385
65386const device_type HDC9234 = &device_creator<hdc9234_device>;
trunk/src/emu/machine/hdc9234.h
r31125r31126
88#define __HDC9234_H__
99
1010#include "emu.h"
11#include "imagedev/floppy.h"
1112
1213extern const device_type HDC9234;
1314
15/*
16    Enumeration of the latches outside of the controller
17*/
18enum
19{
20   HDC_INPUT_STATUS    = 0x00,
21   HDC_OUTPUT_DMA_ADDR = 0x01,
22   HDC_OUTPUT_1        = 0x02,
23   HDC_OUTPUT_2        = 0x03
24};
25
26
27/*
28    Definition of bits in the Disk-Status register
29*/
30enum
31{
32   HDC_DS_ECCERR  = 0x80,        // ECC error
33   HDC_DS_INDEX   = 0x40,        // index hole
34   HDC_DS_SKCOM   = 0x20,        // seek complete
35   HDC_DS_TRK00   = 0x10,        // track 0
36   HDC_DS_UDEF    = 0x08,        // user-defined
37   HDC_DS_WRPROT  = 0x04,        // write-protected
38   HDC_DS_READY   = 0x02,        // drive ready bit
39   HDC_DS_WRFAULT = 0x01         // write fault
40};
41
1442//===================================================================
1543
1644/* Interrupt line. To be connected with the controller PCB. */
r31125r31126
5381   // Accesors from the CPU side
5482   DECLARE_READ8_MEMBER( read );
5583   DECLARE_WRITE8_MEMBER( write );
84   DECLARE_WRITE_LINE_MEMBER( reset );
5685
5786   // Callbacks
5887   template<class _Object> static devcb_base &set_intrq_wr_callback(device_t &device, _Object object) { return downcast<hdc9234_device &>(device).m_out_intrq.set_callback(object); }
r31125r31126
6291   template<class _Object> static devcb_base &set_dma_rd_callback(device_t &device, _Object object) { return downcast<hdc9234_device &>(device).m_in_dma.set_callback(object); }
6392   template<class _Object> static devcb_base &set_dma_wr_callback(device_t &device, _Object object) { return downcast<hdc9234_device &>(device).m_out_dma.set_callback(object); }
6493
94   // Used to reconfigure the drive connections. Floppy drive selection is done
95   // using the user-programmable outputs. Hence, the connection
96   // is changed outside of the controller, and by this way we let it know.
97   void connect_floppy_drive(floppy_image_device *floppy);
98
6599protected:
66100   void device_start();
67101   void device_reset();
r31125r31126
73107   devcb_read8        m_in_auxbus;    // AB0-7 lines (S0=S1=0)
74108   devcb_read8        m_in_dma;       // DMA read access to the cache buffer
75109   devcb_write8       m_out_dma;      // DMA write access to the cache buffer
110
111   // Internal register pointer used for sequential register loading
112   int m_register_pointer;
113
114   // Read and write registers
115   UINT8 m_register_r[12];
116   UINT8 m_register_w[12];
117
118   // Command processing
119   void  process_command(UINT8 opcode);
120
121   // Recent command.
122   UINT8 m_command;
123
124   // Interrupt management (outgoing INT pin)
125   void set_interrupt(line_state intr);
126
127   // Currently connected floppy
128   floppy_image_device* m_floppy;
129
130   // internal register OUTPUT1
131   UINT8 m_output1;
132
133   // internal register OUTPUT2
134   UINT8 m_output2;
135
136   // Sample the values of the incoming status bits
137   void sync_status_in();
138
139   // Write the output registers to the latches
140   void sync_latches_out();
141
142   // Utility routine to set or reset bits
143   void set_bits(UINT8& byte, int mask, bool set);
144
145   // Drive type that has been selected in drive_select
146   int m_selected_drive_type;
147
148   // Enable head load delays
149   bool m_head_load_delay_enable;
150
151   // ===================================================
152   //   Commands
153   // ===================================================
154   void drive_select(int driveparm);
76155};
77156
78157#endif

Previous 199869 Revisions Next


© 1997-2024 The MAME Team