Previous 199869 Revisions Next

r24865 Tuesday 13th August, 2013 at 11:03:14 UTC by Dirk Best
i8089.c: implemented dma engine, apricot now successfully runs the 8089 self-test
[src/emu/machine]i8089.c

trunk/src/emu/machine/i8089.c
r24864r24865
1111//  MACROS/CONSTANTS
1212//**************************************************************************
1313
14#define VERBOSE 1
14#define VERBOSE      1
15#define VERBOSE_DMA  1
1516
17// channel control register fields
18#define CC_TMC     ((m_r[CC].w >>  0) & 0x07)   // terminate on masked compare
19#define CC_TBC     ((m_r[CC].w >>  3) & 0x03)   // terminate on byte count
20#define CC_TX      ((m_r[CC].w >>  5) & 0x03)   // terminate on external signal
21#define CC_TS      ((m_r[CC].w >>  7) & 0x01)   // terminate on single transfer
22#define CC_CHAIN   ((m_r[CC].w >>  8) & 0x01)   // chaining
23#define CC_LOCK    ((m_r[CC].w >>  9) & 0x01)   // actuate lock
24#define CC_SOURCE  ((m_r[CC].w >> 10) & 0x01)   // source register
25#define CC_SYNC    ((m_r[CC].w >> 11) & 0x03)   // synchronization
26#define CC_TRANS   ((m_r[CC].w >> 13) & 0x01)   // translation
27#define CC_FUNC    ((m_r[CC].w >> 14) & 0x03)   // function
1628
29
1730//**************************************************************************
1831//  I/O CHANNEL
1932//**************************************************************************
r24864r24865
149162
150163   i8089_device *m_iop;
151164
165   // dma
166   void terminate_dma(int offset);
167
168   bool m_xfer_pending;
169   UINT16 m_dma_value;
170   int m_dma_state;
171
172   // dma state
173   enum
174   {
175      DMA_IDLE,
176      DMA_WAIT_FOR_SOURCE_DRQ,
177      DMA_FETCH,
178      DMA_TRANSLATE,
179      DMA_WAIT_FOR_DEST_DRQ,
180      DMA_STORE,
181      DMA_STORE_BYTE_HIGH,
182      DMA_COMPARE,
183      DMA_TERMINATE
184   };
185
152186   // register
153187   enum
154188   {
r24864r24865
179213   device_t(mconfig, I8089_CHANNEL, "Intel 8089 I/O Channel", tag, owner, clock, "i8089_channel", __FILE__),
180214   device_execute_interface(mconfig, *this),
181215   m_icount(0),
182   m_write_sintr(*this)
216   m_write_sintr(*this),
217   m_xfer_pending(false),
218   m_dma_value(0),
219   m_dma_state(DMA_IDLE)
183220{
184221}
185222
r24864r24865
195232   m_write_sintr.resolve_safe();
196233
197234   // register for save states
235   save_item(NAME(m_xfer_pending));
236   save_item(NAME(m_dma_value));
237   save_item(NAME(m_dma_state));
238
198239   for (int i = 0; i < ARRAY_LENGTH(m_r); i++)
199240   {
200241      save_item(NAME(m_r[i].w), i);
r24864r24865
204245
205246void i8089_channel::device_reset()
206247{
248   m_xfer_pending = false;
249
207250   // initialize registers
208251   for (int i = 0; i < ARRAY_LENGTH(m_r); i++)
209252   {
r24864r24865
257300
258301UINT16 i8089_channel::imm16()
259302{
260   UINT8 imm16 = m_iop->read_word(m_r[TP].w);
303   UINT16 imm16 = m_iop->read_word(m_r[TP].w);
261304   m_r[TP].w += 2;
262305   return imm16;
263306}
264307
308// adjust task pointer and continue execution
309void i8089_channel::terminate_dma(int offset)
310{
311   logerror("%s('%s'): terminating dma transfer\n", shortname(), tag());
312   m_r[TP].w += offset;
313   m_r[PSW].w |= 1 << 2;
314   m_r[PSW].w &= ~(1 << 6);
315   m_dma_state = DMA_IDLE;
316}
317
265318void i8089_channel::execute_run()
266319{
267320   do
r24864r24865
269322      // active transfer?
270323      if (BIT(m_r[PSW].w, 6))
271324      {
272         m_icount = 0;
325         // new transfer?
326         if (BIT(m_r[PSW].w, 2))
327         {
328            // we are no longer executing task blocks
329            m_r[PSW].w &= ~(1 << 2);
330            m_xfer_pending = false;
331
332            if (VERBOSE)
333            {
334               logerror("%s('%s'): ---- starting dma transfer ----\n", shortname(), tag());
335               logerror("%s('%s'): ga = %06x, gb = %06x, gc = %06x\n", shortname(), tag(), m_r[GA].w, m_r[GB].w, m_r[GC].w);
336               logerror("%s('%s'): bc = %04x, cc = %04x, mc = %04x\n", shortname(), tag(), m_r[BC].w, m_r[CC].w, m_r[MC].w);
337            }
338         }
339
340         // todo: port transfers
341         if (CC_FUNC != 0x03)
342            fatalerror("%s('%s'): port transfer\n", shortname(), tag());
343
344         switch (m_dma_state)
345         {
346         case DMA_IDLE:
347            if (VERBOSE_DMA)
348               logerror("%s('%s'): entering state: DMA_IDLE (bc = %04x)\n", shortname(), tag(), m_r[BC].w);
349
350            // synchronize on source?
351            if (CC_SYNC == 0x01)
352               m_dma_state = DMA_WAIT_FOR_SOURCE_DRQ;
353            else
354               m_dma_state = DMA_FETCH;
355            break;
356
357         case DMA_WAIT_FOR_SOURCE_DRQ:
358            fatalerror("%s('%s'): wait for source drq not supported\n", shortname(), tag());
359            break;
360
361         case DMA_FETCH:
362            if (VERBOSE_DMA)
363               logerror("%s('%s'): entering state: DMA_FETCH", shortname(), tag());
364
365            // source is 16-bit?
366            if (BIT(m_r[PSW].w, 1))
367            {
368               m_dma_value = m_iop->read_word(m_r[GA + CC_SOURCE].w);
369               m_r[GA + CC_SOURCE].w += 2;
370               m_r[BC].w -= 2;
371            }
372            // destination is 16-bit, byte count is even
373            else if (BIT(m_r[PSW].w, 0) && !(m_r[BC].w & 1))
374            {
375               m_dma_value = m_iop->read_byte(m_r[GA + CC_SOURCE].w);
376               m_r[GA + CC_SOURCE].w++;
377               m_r[BC].w--;
378            }
379            // destination is 16-bit, byte count is odd
380            else if (BIT(m_r[PSW].w, 0) && (m_r[BC].w & 1))
381            {
382               m_dma_value |= m_iop->read_byte(m_r[GA + CC_SOURCE].w) << 8;
383               m_r[GA + CC_SOURCE].w++;
384               m_r[BC].w--;
385            }
386            // 8-bit transfer
387            else
388            {
389               m_dma_value = m_iop->read_byte(m_r[GA + CC_SOURCE].w);
390               m_r[GA + CC_SOURCE].w++;
391               m_r[BC].w--;
392            }
393
394            if (VERBOSE_DMA)
395               logerror("[ %04x ]\n", m_dma_value);
396
397            if (BIT(m_r[PSW].w, 0) && (m_r[BC].w & 1))
398               m_dma_state = DMA_FETCH;
399            else if (CC_TRANS)
400               m_dma_state = DMA_TRANSLATE;
401            else if (CC_SYNC == 0x02)
402               m_dma_state = DMA_WAIT_FOR_DEST_DRQ;
403            else
404               m_dma_state = DMA_STORE;
405
406            break;
407
408         case DMA_TRANSLATE:
409            fatalerror("%s('%s'): dma translate requested\n", shortname(), tag());
410            break;
411
412         case DMA_WAIT_FOR_DEST_DRQ:
413            fatalerror("%s('%s'): wait for destination drq not supported\n", shortname(), tag());
414            break;
415
416         case DMA_STORE:
417            if (VERBOSE_DMA)
418               logerror("%s('%s'): entering state: DMA_STORE", shortname(), tag());
419
420            // destination is 16-bit?
421            if (BIT(m_r[PSW].w, 0))
422            {
423               m_iop->write_word(m_r[GB - CC_SOURCE].w, m_dma_value);
424               m_r[GB - CC_SOURCE].w += 2;
425
426               if (VERBOSE_DMA)
427                  logerror("[ %04x ]\n", m_dma_value);
428            }
429            // destination is 8-bit
430            else
431            {
432               m_iop->write_byte(m_r[GB - CC_SOURCE].w, m_dma_value & 0xff);
433               m_r[GB - CC_SOURCE].w++;
434
435               if (VERBOSE_DMA)
436                  logerror("[ %02x ]\n", m_dma_value & 0xff);
437            }
438
439            if (CC_TMC & 0x03)
440               m_dma_state = DMA_COMPARE;
441            else
442               m_dma_state = DMA_TERMINATE;
443
444            break;
445
446         case DMA_COMPARE:
447            fatalerror("%s('%s'): dma compare requested\n", shortname(), tag());
448            break;
449
450         case DMA_TERMINATE:
451            if (VERBOSE_DMA)
452               logerror("%s('%s'): entering state: DMA_TERMINATE\n", shortname(), tag());
453
454            // terminate on masked compare?
455            if (CC_TMC & 0x03)
456               fatalerror("%s('%s'): terminate on masked compare not supported\n", shortname(), tag());
457
458            // terminate on byte count?
459            else if (CC_TBC && m_r[BC].w == 0)
460               terminate_dma((CC_TBC - 1) * 4);
461
462            // terminate on external signal
463            else if (CC_TX)
464               fatalerror("%s('%s'): terminate on external signal not supported\n", shortname(), tag());
465
466            // terminate on single transfer
467            else if (CC_TS)
468               fatalerror("%s('%s'): terminate on single transfer not supported\n", shortname(), tag());
469
470            // not terminated, continue transfer
471            else
472               // do we need to read another byte?
473               if (BIT(m_r[PSW].w, 1) && !BIT(m_r[PSW].w, 0))
474                  if (CC_SYNC == 0x02)
475                     m_dma_state = DMA_WAIT_FOR_DEST_DRQ;
476                  else
477                     m_dma_state = DMA_STORE_BYTE_HIGH;
478
479               // transfer done
480               else
481                  m_dma_state = DMA_IDLE;
482
483            break;
484
485         case DMA_STORE_BYTE_HIGH:
486            if (VERBOSE_DMA)
487               logerror("%s('%s'): entering state: DMA_STORE_BYTE_HIGH[ %02x ]\n", shortname(), tag(), (m_dma_value >> 8) & 0xff);
488
489            m_iop->write_byte(m_r[GB - CC_SOURCE].w, (m_dma_value >> 8) & 0xff);
490            m_r[GB - CC_SOURCE].w++;
491            m_dma_state = DMA_TERMINATE;
492
493            break;
494         }
495
496         m_icount--;
273497      }
274498
275499      // executing task block instructions?
276500      else if (BIT(m_r[PSW].w, 2))
277501      {
502         // dma transfer pending?
503         if (m_xfer_pending)
504            m_r[PSW].w |= 1 << 6;
505
278506         // fetch first two instruction bytes
279507         UINT16 op = m_iop->read_word(m_r[TP].w);
280508         m_r[TP].w += 2;
r24864r24865
296524         UINT8 o;
297525         UINT16 off, seg;
298526
527         logerror("%s('%s'): executing %x %x %x %x %02x %x\n", shortname(), tag(), brp, wb, aa, w, opc, mm);
528
299529         switch (opc)
300530         {
301531         case 0x00: // control
r24864r24865
305535            case 1: invalid(opc); break;
306536            case 2: sintr(); break;
307537            case 3: xfer(); break;
308            default:
309               if (BIT(brp, 2))
310                  wid(BIT(brp, 1), BIT(brp, 0));
538            default: wid(BIT(brp, 1), BIT(brp, 0));
311539            }
312540            break;
313541
r24864r24865
659887void i8089_channel::movb_rm(int r, int m, int o)
660888{
661889   UINT8 byte = m_iop->read_byte(m_r[m].w + o);
662   m_r[r].w = (BIT(byte, 7) ? 0xffff0 : 0x00000) | byte;
890   m_r[r].w = (BIT(byte, 7) ? 0xfff00 : 0x00000) | byte;
663891   m_r[r].t = 1;
664892}
665893
r24864r24865
673901// move immediate byte to register
674902void i8089_channel::movbi_ri(int r, int i)
675903{
676   m_r[r].w = (BIT(i, 7) ? 0xffff0 : 0x00000) | (i & 0xff);
904   m_r[r].w = (BIT(i, 7) ? 0xfff00 : 0x00000) | (i & 0xff);
677905   m_r[r].t = 1;
678906}
679907
r24864r24865
686914// move immediate word to register
687915void i8089_channel::movi_ri(int r, int i)
688916{
689   m_r[r].w = (BIT(i, 15) ? 0xffff0 : 0x00000) | (i & 0xffff);
917   m_r[r].w = (BIT(i, 15) ? 0xf0000 : 0x00000) | (i & 0xffff);
690918   m_r[r].t = 1;
691919}
692920
693921// move immediate word to memory word
694922void i8089_channel::movi_mi(int m, int i, int o)
695923{
696   m_iop->write_word(m_r[m].w + o, (BIT(i, 15) ? 0xffff0 : 0x00000) | (i & 0xffff));
924   m_iop->write_word(m_r[m].w + o, (BIT(i, 15) ? 0xf0000 : 0x00000) | (i & 0xffff));
697925}
698926
699927// move pointer to memory (store)
r24864r24865
753981   m_r[PSW].w |= s << 1;
754982}
755983
756void i8089_channel::xfer() { UNIMPLEMENTED }
984// enter dma transfer mode after next instruction
985void i8089_channel::xfer()
986{
987   m_xfer_pending = true;
988}
757989
758990void i8089_channel::invalid(int opc)
759991{

Previous 199869 Revisions Next


© 1997-2024 The MAME Team