Previous 199869 Revisions Next

r26594 Wednesday 11th December, 2013 at 23:49:42 UTC by Michael Zapf
(MESS) ti99: Fixing the TI floppy controller; still issues. (nw)
[src/mess/machine/ti99]ti_fdc.c ti_fdc.h

trunk/src/mess/machine/ti99/ti_fdc.c
r26593r26594
1515#include "emu.h"
1616#include "peribox.h"
1717#include "ti_fdc.h"
18#include "machine/wd17xx.h"
1918#include "formats/ti99_dsk.h"
2019
21#define LOG logerror
22#define VERBOSE 1
20// ----------------------------------
21// Flags for debugging
2322
24#define fdc_IRQ 1
25#define fdc_DRQ 2
23// Show read and write accesses
24#define TRACE_RW 0
2625
26// Show CRU bit accesses
27#define TRACE_CRU 0
28
29// Show ready line activity
30#define TRACE_READY 0
31
32// Show detailed signal activity
33#define TRACE_SIGNALS 0
34
35// Show sector data
36#define TRACE_DATA 0
37
38// Show address bus operations
39#define TRACE_ADDRESS 0
40
41// Show address bus operations
42#define TRACE_MOTOR 0
43
44// ----------------------------------
45
2746#define TI_FDC_TAG "ti_dssd_controller"
2847
2948#define FDC_TAG "wd1771"
r26593r26594
3958};
4059
4160ti_fdc_device::ti_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
42: ti_expansion_card_device(mconfig, TI99_FDC, "TI-99 Standard DSSD Floppy Controller", tag, owner, clock, "ti99_fdc", __FILE__)
43{
44}
61         : ti_expansion_card_device(mconfig, TI99_FDC, "TI-99 Standard DSSD Floppy Controller", tag, owner, clock, "ti99_fdc", __FILE__),
62         m_fd1771(*this, FDC_TAG) { }
4563
4664/*
4765    callback called at the end of DVENA pulse
r26593r26594
4967void ti_fdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
5068{
5169   m_DVENA = CLEAR_LINE;
52   handle_hold();
70   if (TRACE_MOTOR) logerror("tifdc: Motor off\n");
71   set_ready_line();
5372}
5473
74/*
75    Operate the wait state logic.
76*/
77void ti_fdc_device::set_ready_line()
78{
79   // This is the wait state logic
80   if (TRACE_SIGNALS) logerror("tifdc: address=%04x, DRQ=%d, INTRQ=%d, MOTOR=%d\n", m_address & 0xffff, m_DRQ, m_IRQ, m_DVENA);
81   line_state nready = (m_WDsel &&             // Are we accessing 5ffx?
82         m_WAITena &&                        // and the wait state generation is active (SBO 2)
83         (m_DRQ==CLEAR_LINE) &&              // and we are waiting for a byte
84         (m_IRQ==CLEAR_LINE) &&              // and there is no interrupt yet
85         (m_DVENA==ASSERT_LINE)              // and the motor is turning?
86         )? ASSERT_LINE : CLEAR_LINE;        // In that case, clear READY and thus trigger wait states
87
88   if (TRACE_READY) if (nready==ASSERT_LINE) logerror("tifdc: READY line = %d\n", (nready==CLEAR_LINE)? 1:0);
89   m_slot->set_ready((nready==CLEAR_LINE)? ASSERT_LINE : CLEAR_LINE);
90}
91
92SETADDRESS_DBIN_MEMBER( ti_fdc_device::setaddress_dbin )
93{
94   // Selection login in the PAL and some circuits on the board
95
96   // Is the card being selected?
97   m_address = offset;
98   m_inDsrArea = ((m_address & m_select_mask)==m_select_value);
99
100   if (!m_inDsrArea) return;
101
102   if (TRACE_ADDRESS) logerror("tifdc: set address = %04x\n", offset & 0xffff);
103
104   // Is the WD chip on the card being selected?
105   m_WDsel = m_inDsrArea && ((m_address & 0x1ff0)==0x1ff0);
106
107   // Clear or assert the outgoing READY line
108   set_ready_line();
109}
110
55111READ8Z_MEMBER(ti_fdc_device::readz)
56112{
57   if (m_selected)
113   if (m_inDsrArea && m_selected)
58114   {
59      if ((offset & m_select_mask)==m_select_value)
115      // only use the even addresses from 1ff0 to 1ff6.
116      // Note that data is inverted.
117      // 0101 1111 1111 0xx0
118      UINT8 reply = 0;
119
120      if (m_WDsel && ((m_address & 1)==0))
60121      {
61         // only use the even addresses from 1ff0 to 1ff6.
62         // Note that data is inverted.
63         // 0101 1111 1111 0xx0
64         UINT8 reply = 0;
65
66         if ((offset & 0x1ff9)==0x1ff0)
122         if (!space.debugger_access()) reply = wd17xx_r(m_fd1771, space, (offset >> 1)&0x03);
123         if (TRACE_DATA)
67124         {
68            if (!space.debugger_access()) reply = wd17xx_r(m_controller, space, (offset >> 1)&0x03);
125            if ((m_address & 0xffff)==0x5ff6) logerror("%02x ", ~reply & 0xff);
126            else logerror("\n%04x: %02x", m_address&0xffff, ~reply & 0xff);
69127         }
70         else
71         {
72            reply = m_dsrrom[offset & 0x1fff];
73         }
74         *value = reply;
75         if (VERBOSE>5) LOG("ti_fdc: %04x -> %02x\n", offset & 0xffff, *value);
76128      }
129      else
130      {
131         reply = m_dsrrom[m_address & 0x1fff];
132      }
133      *value = reply;
134      if (TRACE_RW) logerror("ti_fdc: %04x -> %02x\n", offset & 0xffff, *value);
77135   }
78136}
79137
80138WRITE8_MEMBER(ti_fdc_device::write)
81139{
82   if (m_selected)
140   if (m_inDsrArea && m_selected)
83141   {
84      if ((offset & m_select_mask)==m_select_value)
142      if (TRACE_RW) logerror("ti_fdc: %04x <- %02x\n", offset & 0xffff, ~data & 0xff);
143      // only use the even addresses from 1ff8 to 1ffe.
144      // Note that data is inverted.
145      // 0101 1111 1111 1xx0
146      if (m_WDsel && ((m_address & 9)==8))
85147      {
86         if (VERBOSE>5) LOG("ti_fdc: %04x <- %02x\n", offset & 0xffff, data);
87         // only use the even addresses from 1ff8 to 1ffe.
88         // Note that data is inverted.
89         // 0101 1111 1111 1xx0
90         if ((offset & 0x1ff9)==0x1ff8)
91         {
92            if (!space.debugger_access()) wd17xx_w(m_controller, space, (offset >> 1)&0x03, data);
93         }
148         if (!space.debugger_access()) wd17xx_w(m_fd1771, space, (offset >> 1)&0x03, data);
94149      }
95150   }
96151}
r26593r26594
121176         if (m_SIDSEL) reply |= 0x80;
122177      }
123178      *value = reply;
179      if (TRACE_CRU) logerror("tifdc: Read CRU = %02x\n", *value);
124180   }
125181}
126182
r26593r26594
136192      case 0:
137193         /* (De)select the card. Indicated by a LED on the board. */
138194         m_selected = (data!=0);
139         if (VERBOSE>4) LOG("ti_fdc: Map DSR = %d\n", m_selected);
195         if (TRACE_CRU) logerror("tifdc: Map DSR (bit 0) = %d\n", m_selected);
140196         break;
141197      case 1:
142198         /* Activate motor */
143         if (data && !m_strobe_motor)
199         if (data==1 && m_lastval==0)
144200         {   /* on rising edge, set motor_running for 4.23s */
201            if (TRACE_CRU) logerror("tifdc: trigger motor (bit 1)\n");
145202            m_DVENA = ASSERT_LINE;
146            handle_hold();
203            if (TRACE_MOTOR) logerror("tifdc: motor on\n");
204            set_ready_line();
147205            m_motor_on_timer->adjust(attotime::from_msec(4230));
148206         }
149         m_strobe_motor = (data!=0);
207         m_lastval = data;
150208         break;
151209
152210      case 2:
r26593r26594
155213         // 1: TMS9900 is stopped until IRQ or DRQ are set
156214         // OR the motor stops rotating - rotates for 4.23s after write
157215         // to CRU bit 1
158         // This is not emulated and could cause the TI99 to lock up
159         m_hold = (data != 0);
160         handle_hold();
216         m_WAITena = (data != 0);
217         if (TRACE_CRU) logerror("tifdc: arm wait state logic (bit 2) = %d\n", data);
161218         break;
162219
163220      case 3:
164221         /* Load disk heads (HLT pin) (bit 3). Not implemented. */
222         if (TRACE_CRU) logerror("tifdc: set head load (bit 3) = %d\n", data);
165223         break;
166224
167225      case 4:
r26593r26594
169227      case 6:
170228         /* Select drive X (bits 4-6) */
171229         drive = bit-4;                  /* drive # (0-2) */
230         if (TRACE_CRU) logerror("tifdc: set drive (bit %d) = %d\n", bit, data);
172231         drivebit = 1<<drive;
173232
174         if (data)
233         if (data != 0)
175234         {
176            if ((m_DSEL & drivebit)!=0)         /* select drive */
235            if ((m_DSEL & drivebit) == 0)         /* select drive */
177236            {
178237               if (m_DSEL != 0)
179                  LOG("ti_fdc: Multiple drives selected, %02x\n", m_DSEL);
238                  logerror("tifdc: Multiple drives selected, %02x\n", m_DSEL);
180239               m_DSEL |= drivebit;
181               wd17xx_set_drive(m_controller, drive);
182               /*wd17xx_set_side(DSKside);*/
240               wd17xx_set_drive(m_fd1771, drive);
183241            }
184242         }
185243         else
r26593r26594
189247      case 7:
190248         /* Select side of disk (bit 7) */
191249         m_SIDSEL = data;
192         wd17xx_set_side(m_controller, data);
250         if (TRACE_CRU) logerror("tifdc: set side (bit 7) = %d\n", data);
251         wd17xx_set_side(m_fd1771, data);
193252         break;
194253      }
195254   }
196255}
197256
198257/*
199    Call this when the state of DSKhold or DRQ/IRQ or DVENA change
200
201    Emulation is faulty because the CPU is actually stopped in the midst of
202    instruction, at the end of the memory access
203
204    TODO: This has to be replaced by the proper READY handling that is already
205    prepared here. (Requires READY handling by the CPU.)
206*/
207void ti_fdc_device::handle_hold()
208{
209   line_state state;
210
211   if (m_hold && !m_DRQ && !m_IRQ && (m_DVENA==ASSERT_LINE))
212      state = ASSERT_LINE;
213   else
214      state = CLEAR_LINE;
215
216   m_slot->set_ready((state==CLEAR_LINE)? ASSERT_LINE : CLEAR_LINE);
217//  machine().device("maincpu")->execute().set_input_line(INPUT_LINE_HALT, state);
218}
219
220/*
221258    Resets the drive geometry. This is required because the heuristic of
222259    the default implementation sets the drive geometry to the geometry
223260    of the medium.
r26593r26594
243280*/
244281WRITE_LINE_MEMBER( ti_fdc_device::intrq_w )
245282{
246   if (VERBOSE>8) LOG("ti_fdc: set irq = %02x\n", state);
247   m_IRQ = (state==ASSERT_LINE);
283   if (TRACE_SIGNALS) logerror("ti_fdc: set irq = %d\n", state);
284   m_IRQ = (line_state)state;
248285   // Note that INTB is actually not used in the TI-99 family. But the
249286   // controller asserts the line nevertheless, probably intended for
250287   // use in another planned TI system
251288   m_slot->set_intb(state);
252
253   handle_hold();
289   set_ready_line();
254290}
255291
256292WRITE_LINE_MEMBER( ti_fdc_device::drq_w )
257293{
258   if (VERBOSE>8) LOG("ti_fdc: set drq = %02x\n", state);
259   m_DRQ = (state == ASSERT_LINE);
260   handle_hold();
294   if (TRACE_SIGNALS) logerror("ti_fdc: set drq = %d\n", state);
295   m_DRQ = (line_state)state;
296   set_ready_line();
261297}
262298
263299void ti_fdc_device::device_start(void)
264300{
265   if (VERBOSE>5) LOG("ti_fdc: TI FDC start\n");
301   logerror("ti_fdc: TI FDC start\n");
266302   m_dsrrom = memregion(DSRROM)->base();
267303   m_motor_on_timer = timer_alloc(MOTOR_TIMER);
268   m_controller = subdevice(FDC_TAG);
269
270304   m_cru_base = 0x1100;
271305}
272306
273307void ti_fdc_device::device_reset(void)
274308{
275   if (VERBOSE>5) LOG("ti_fdc: TI FDC reset\n");
309   logerror("ti_fdc: TI FDC reset\n");
276310   m_DSEL = 0;
277311   m_SIDSEL = 0;
278312   m_DVENA = CLEAR_LINE;
279   m_strobe_motor = false;
313   m_lastval = 0;
280314   if (m_genmod)
281315   {
282316      m_select_mask = 0x1fe000;
r26593r26594
287321      m_select_mask = 0x7e000;
288322      m_select_value = 0x74000;
289323   }
290   m_DRQ = false;
291   m_IRQ = false;
292   m_hold = false;
324   m_DRQ = CLEAR_LINE;
325   m_IRQ = CLEAR_LINE;
326   m_WAITena = false;
293327   m_selected = false;
294328
295329   ti99_set_80_track_drives(FALSE);
trunk/src/mess/machine/ti99/ti_fdc.h
r26593r26594
1616#define __TIFDC__
1717
1818#include "ti99defs.h"
19#include "machine/wd17xx.h"
1920#include "imagedev/flopdrv.h"
2021
2122extern const device_type TI99_FDC;
r26593r26594
2627   ti_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
2728   DECLARE_READ8Z_MEMBER(readz);
2829   DECLARE_WRITE8_MEMBER(write);
30   DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin);
2931
3032   DECLARE_WRITE_LINE_MEMBER( intrq_w );
3133   DECLARE_WRITE_LINE_MEMBER( drq_w );
r26593r26594
4143   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
4244
4345private:
44   void handle_hold(void);
46   void set_ready_line();
4547   void set_all_geometries(floppy_type_t type);
4648   void set_geometry(device_t *drive, floppy_type_t type);
4749
50   // Recent address
51   int             m_address;
4852
4953   // Holds the status of the DRQ and IRQ lines.
50   bool        m_DRQ, m_IRQ;
54   line_state  m_DRQ, m_IRQ;
5155
52   // When TRUE, keeps DVENA high.
53   bool        m_strobe_motor;
56   // Needed for triggering the motor monoflop
57   UINT8       m_lastval;
5458
5559   // Signal DVENA. When TRUE, makes some drive turning.
5660   line_state  m_DVENA;
5761
5862   // When TRUE the CPU is halted while DRQ/IRQ are true.
59   bool        m_hold;
63   bool        m_WAITena;
6064
65   // WD chip selected
66   bool        m_WDsel;
67
68   // Set when address is in card area
69   bool        m_inDsrArea;
70
6171   // Indicates which drive has been selected. Values are 0, 1, 2, and 4.
6272   // 000 = no drive
6373   // 001 = drive 1
r26593r26594
7282   emu_timer*  m_motor_on_timer;
7383
7484   // Link to the FDC1771 controller on the board.
75   device_t*   m_controller;
85   required_device<fd1771_device>   m_fd1771;
7686
7787   // DSR ROM
7888   UINT8*      m_dsrrom;

Previous 199869 Revisions Next


© 1997-2024 The MAME Team