1 // license:BSD-3-Clause
2 // copyright-holders:Couriersud
3 /**********************************************************************
4
5 Z80 DMA interface and emulation
6
7 For datasheet http://www.zilog.com/docs/z80/ps0179.pdf
8
9 2008/01 couriersud
10
11 - architecture copied from 8257 DMA
12 - significant changes to implementation
13 - This is only a minimum implementation to support dkong3 and mario drivers
14 - Only memory to memory is tested!
15
16 TODO:
17 - reset command (C3) is handled improperly
18 - rewrite to match documentation
19 - implement missing features
20 - implement more asserts
21 - implement a INPUT_LINE_BUSREQ for Z80. As a workaround,
22 HALT is used. This implies burst mode.
23
24 **********************************************************************/
25
26 #include "emu.h"
27 #include "z80dma.h"
28
29 #define LOG_GENERAL (1U << 0)
30 #define LOG_DMA (1U << 1)
31
32 //#define VERBOSE (LOG_GENERAL | LOG_DMA)
33 #include "logmacro.h"
34
35 #define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__)
36
37 //**************************************************************************
38 // CONSTANTS
39 //**************************************************************************
40
41 enum
42 {
43 INT_RDY = 0,
44 INT_MATCH,
45 INT_END_OF_BLOCK,
46 INT_MATCH_END_OF_BLOCK
47 };
48
49 constexpr int COMMAND_RESET = 0xc3;
50 constexpr int COMMAND_RESET_PORT_A_TIMING = 0xc7;
51 constexpr int COMMAND_RESET_PORT_B_TIMING = 0xcb;
52 constexpr int COMMAND_LOAD = 0xcf;
53 constexpr int COMMAND_CONTINUE = 0xd3;
54 constexpr int COMMAND_DISABLE_INTERRUPTS = 0xaf;
55 constexpr int COMMAND_ENABLE_INTERRUPTS = 0xab;
56 constexpr int COMMAND_RESET_AND_DISABLE_INTERRUPTS = 0xa3;
57 constexpr int COMMAND_ENABLE_AFTER_RETI = 0xb7;
58 constexpr int COMMAND_READ_STATUS_BYTE = 0xbf;
59 constexpr int COMMAND_REINITIALIZE_STATUS_BYTE = 0x8b;
60 constexpr int COMMAND_INITIATE_READ_SEQUENCE = 0xa7;
61 constexpr int COMMAND_FORCE_READY = 0xb3;
62 constexpr int COMMAND_ENABLE_DMA = 0x87;
63 constexpr int COMMAND_DISABLE_DMA = 0x83;
64 constexpr int COMMAND_READ_MASK_FOLLOWS = 0xbb;
65
66 constexpr int TM_TRANSFER = 0x01;
67 constexpr int TM_SEARCH = 0x02;
68 constexpr int TM_SEARCH_TRANSFER = 0x03;
69
70
71
72 //**************************************************************************
73 // MACROS
74 //**************************************************************************
75
76 #define REGNUM(_m, _s) (((_m)<<3) + (_s))
77 #define GET_REGNUM(_r) (&(_r) - &(WR0))
78 #define REG(_m, _s) m_regs[REGNUM(_m,_s)]
79 #define WR0 REG(0, 0)
80 #define WR1 REG(1, 0)
81 #define WR2 REG(2, 0)
82 #define WR3 REG(3, 0)
83 #define WR4 REG(4, 0)
84 #define WR5 REG(5, 0)
85 #define WR6 REG(6, 0)
86
87 #define PORTA_ADDRESS_L REG(0,1)
88 #define PORTA_ADDRESS_H REG(0,2)
89
90 #define BLOCKLEN_L REG(0,3)
91 #define BLOCKLEN_H REG(0,4)
92
93 #define PORTA_TIMING REG(1,1)
94 #define PORTB_TIMING REG(2,1)
95
96 #define MASK_BYTE REG(3,1)
97 #define MATCH_BYTE REG(3,2)
98
99 #define PORTB_ADDRESS_L REG(4,1)
100 #define PORTB_ADDRESS_H REG(4,2)
101 #define INTERRUPT_CTRL REG(4,3)
102 #define INTERRUPT_VECTOR REG(4,4)
103 #define PULSE_CTRL REG(4,5)
104
105 #define READ_MASK REG(6,1)
106
107 #define PORTA_ADDRESS ((PORTA_ADDRESS_H<<8) | PORTA_ADDRESS_L)
108 #define PORTB_ADDRESS ((PORTB_ADDRESS_H<<8) | PORTB_ADDRESS_L)
109 #define BLOCKLEN ((BLOCKLEN_H<<8) | BLOCKLEN_L)
110
111 #define PORTA_INC (WR1 & 0x10)
112 #define PORTB_INC (WR2 & 0x10)
113 #define PORTA_FIXED (((WR1 >> 4) & 0x02) == 0x02)
114 #define PORTB_FIXED (((WR2 >> 4) & 0x02) == 0x02)
115 #define PORTA_MEMORY (((WR1 >> 3) & 0x01) == 0x00)
116 #define PORTB_MEMORY (((WR2 >> 3) & 0x01) == 0x00)
117
118 #define PORTA_CYCLE_LEN (4-(PORTA_TIMING & 0x03))
119 #define PORTB_CYCLE_LEN (4-(PORTB_TIMING & 0x03))
120
121 #define PORTA_IS_SOURCE ((WR0 >> 2) & 0x01)
122 #define PORTB_IS_SOURCE (!PORTA_IS_SOURCE)
123 #define TRANSFER_MODE (WR0 & 0x03)
124
125 #define MATCH_F_SET (m_status &= ~0x10)
126 #define MATCH_F_CLEAR (m_status |= 0x10)
127 #define EOB_F_SET (m_status &= ~0x20)
128 #define EOB_F_CLEAR (m_status |= 0x20)
129
130 #define READY_ACTIVE_HIGH ((WR5>>3) & 0x01)
131 #define AUTO_RESTART ((WR5>>5) & 0x01)
132
133 #define INTERRUPT_ENABLE (WR3 & 0x20)
134 #define INT_ON_MATCH (INTERRUPT_CTRL & 0x01)
135 #define INT_ON_END_OF_BLOCK (INTERRUPT_CTRL & 0x02)
136 #define INT_ON_READY (INTERRUPT_CTRL & 0x40)
137 #define STATUS_AFFECTS_VECTOR (INTERRUPT_CTRL & 0x20)
138
139
140
141 //**************************************************************************
142 // LIVE DEVICE
143 //**************************************************************************
144
145 // device type definition
146 DEFINE_DEVICE_TYPE(Z80DMA, z80dma_device, "z80dma", "Z80 DMA Controller")
147
148 //-------------------------------------------------
149 // z80dma_device - constructor
150 //-------------------------------------------------
151
z80dma_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)152 z80dma_device::z80dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
153 : device_t(mconfig, Z80DMA, tag, owner, clock)
154 , device_z80daisy_interface(mconfig, *this)
155 , m_out_busreq_cb(*this)
156 , m_out_int_cb(*this)
157 , m_out_ieo_cb(*this)
158 , m_out_bao_cb(*this)
159 , m_in_mreq_cb(*this)
160 , m_out_mreq_cb(*this)
161 , m_in_iorq_cb(*this)
162 , m_out_iorq_cb(*this)
163 {
164 }
165
166
167 //-------------------------------------------------
168 // device_start - device-specific startup
169 //-------------------------------------------------
170
device_start()171 void z80dma_device::device_start()
172 {
173 // resolve callbacks
174 m_out_busreq_cb.resolve_safe();
175 m_out_int_cb.resolve_safe();
176 m_out_ieo_cb.resolve_safe();
177 m_out_bao_cb.resolve_safe();
178 m_in_mreq_cb.resolve_safe(0);
179 m_out_mreq_cb.resolve_safe();
180 m_in_iorq_cb.resolve_safe(0);
181 m_out_iorq_cb.resolve_safe();
182
183 // allocate timer
184 m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z80dma_device::timerproc), this));
185
186 // register for state saving
187 save_item(NAME(m_regs));
188 save_item(NAME(m_regs_follow));
189 save_item(NAME(m_num_follow));
190 save_item(NAME(m_cur_follow));
191 save_item(NAME(m_status));
192 save_item(NAME(m_dma_enabled));
193 save_item(NAME(m_vector));
194 save_item(NAME(m_iei));
195 save_item(NAME(m_ip));
196 save_item(NAME(m_ius));
197 save_item(NAME(m_addressA));
198 save_item(NAME(m_addressB));
199 save_item(NAME(m_count));
200 save_item(NAME(m_rdy));
201 save_item(NAME(m_force_ready));
202 save_item(NAME(m_is_read));
203 save_item(NAME(m_cur_cycle));
204 save_item(NAME(m_latch));
205 }
206
207
208 //-------------------------------------------------
209 // device_reset - device-specific reset
210 //-------------------------------------------------
211
device_reset()212 void z80dma_device::device_reset()
213 {
214 m_status = 0;
215 m_rdy = 0;
216 m_force_ready = 0;
217 m_num_follow = 0;
218 m_dma_enabled = 0;
219 m_read_num_follow = m_read_cur_follow = 0;
220 m_reset_pointer = 0;
221 m_is_read = false;
222 memset(m_regs, 0, sizeof(m_regs));
223 memset(m_regs_follow, 0, sizeof(m_regs_follow));
224
225 // disable interrupts
226 WR3 &= ~0x20;
227 m_ip = 0;
228 m_ius = 0;
229 m_vector = 0;
230
231 update_status();
232 }
233
234
235
236 //**************************************************************************
237 // DAISY CHAIN INTERFACE
238 //**************************************************************************
239
240 //-------------------------------------------------
241 // z80daisy_irq_state - return the overall IRQ
242 // state for this device
243 //-------------------------------------------------
244
z80daisy_irq_state()245 int z80dma_device::z80daisy_irq_state()
246 {
247 int state = 0;
248
249 if (m_ip)
250 {
251 // interrupt pending
252 state = Z80_DAISY_INT;
253 }
254 else if (m_ius)
255 {
256 // interrupt under service
257 state = Z80_DAISY_IEO;
258 }
259
260 LOG("Z80DMA Interrupt State: %u\n", state);
261
262 return state;
263 }
264
265
266 //-------------------------------------------------
267 // z80daisy_irq_ack - acknowledge an IRQ and
268 // return the appropriate vector
269 //-------------------------------------------------
270
z80daisy_irq_ack()271 int z80dma_device::z80daisy_irq_ack()
272 {
273 if (m_ip)
274 {
275 LOG("Z80DMA Interrupt Acknowledge\n");
276
277 // clear interrupt pending flag
278 m_ip = 0;
279 interrupt_check();
280
281 // set interrupt under service flag
282 m_ius = 1;
283
284 return m_vector;
285 }
286
287 //logerror("z80dma_irq_ack: failed to find an interrupt to ack!\n");
288
289 return 0;
290 }
291
292
293 //-------------------------------------------------
294 // z80daisy_irq_reti - clear the interrupt
295 // pending state to allow other interrupts through
296 //-------------------------------------------------
297
z80daisy_irq_reti()298 void z80dma_device::z80daisy_irq_reti()
299 {
300 if (m_ius)
301 {
302 LOG("Z80DMA Return from Interrupt\n");
303
304 // clear interrupt under service flag
305 m_ius = 0;
306 interrupt_check();
307
308 return;
309 }
310
311 //logerror("z80dma_irq_reti: failed to find an interrupt to clear IEO on!\n");
312 }
313
314
315
316 //**************************************************************************
317 // INTERNAL STATE MANAGEMENT
318 //**************************************************************************
319
320 //-------------------------------------------------
321 // is_ready - ready for DMA transfer?
322 //-------------------------------------------------
323
is_ready()324 int z80dma_device::is_ready()
325 {
326 return (m_force_ready) || (m_rdy == READY_ACTIVE_HIGH);
327 }
328
329
330 //-------------------------------------------------
331 // interrupt_check - update IRQ line state
332 //-------------------------------------------------
333
interrupt_check()334 void z80dma_device::interrupt_check()
335 {
336 m_out_int_cb(m_ip ? ASSERT_LINE : CLEAR_LINE);
337 m_out_ieo_cb(m_iei && !m_ip);
338 }
339
340
341 //-------------------------------------------------
342 // trigger_interrupt - trigger DMA interrupt
343 //-------------------------------------------------
344
trigger_interrupt(int level)345 void z80dma_device::trigger_interrupt(int level)
346 {
347 if (!m_ius && INTERRUPT_ENABLE)
348 {
349 // set interrupt pending flag
350 m_ip = 1;
351
352 // set interrupt vector
353 if (STATUS_AFFECTS_VECTOR)
354 {
355 m_vector = (INTERRUPT_VECTOR & 0xf9) | (level << 1);
356 }
357 else
358 {
359 m_vector = INTERRUPT_VECTOR;
360 }
361
362 m_status &= ~0x08;
363
364 LOG("Z80DMA Interrupt Pending\n");
365
366 interrupt_check();
367 }
368 }
369
370
371 //-------------------------------------------------
372 // do_read - perform DMA read
373 //-------------------------------------------------
374
do_read()375 void z80dma_device::do_read()
376 {
377 uint8_t mode;
378
379 mode = TRANSFER_MODE;
380 switch(mode) {
381 case TM_TRANSFER:
382 case TM_SEARCH:
383 case TM_SEARCH_TRANSFER:
384 if (PORTA_IS_SOURCE)
385 {
386 if (PORTA_MEMORY)
387 m_latch = m_in_mreq_cb(m_addressA);
388 else
389 m_latch = m_in_iorq_cb(m_addressA);
390
391 LOGDMA("Z80DMA A src: %04x %s -> data: %02x\n", m_addressA, PORTA_MEMORY ? "mem" : "i/o", m_latch);
392 }
393 else
394 {
395 if (PORTB_MEMORY)
396 m_latch = m_in_mreq_cb(m_addressB);
397 else
398 m_latch = m_in_iorq_cb(m_addressB);
399
400 LOGDMA("Z80DMA B src: %04x %s -> data: %02x\n", m_addressB, PORTB_MEMORY ? "mem" : "i/o", m_latch);
401 }
402 break;
403 default:
404 logerror("z80dma_do_operation: invalid mode %d!\n", mode);
405 break;
406 }
407 }
408
409
410 //-------------------------------------------------
411 // do_write - perform DMA write
412 //-------------------------------------------------
413
do_transfer_write()414 void z80dma_device::do_transfer_write()
415 {
416 if (PORTA_IS_SOURCE)
417 {
418 if (PORTB_MEMORY)
419 m_out_mreq_cb((offs_t)m_addressB, m_latch);
420 else
421 m_out_iorq_cb((offs_t)m_addressB, m_latch);
422
423 LOGDMA("Z80DMA B dst: %04x %s\n", m_addressB, PORTB_MEMORY ? "mem" : "i/o");
424 }
425 else
426 {
427 if (PORTA_MEMORY)
428 m_out_mreq_cb((offs_t)m_addressA, m_latch);
429 else
430 m_out_iorq_cb((offs_t)m_addressA, m_latch);
431
432 LOGDMA("Z80DMA A dst: %04x %s\n", m_addressA, PORTA_MEMORY ? "mem" : "i/o");
433 }
434 }
435
do_search()436 void z80dma_device::do_search()
437 {
438 uint8_t load_byte,match_byte;
439 load_byte = m_latch | MASK_BYTE;
440 match_byte = MATCH_BYTE | MASK_BYTE;
441 //LOG("%02x %02x\n",load_byte,match_byte));
442 if (load_byte == match_byte)
443 {
444 if (INT_ON_MATCH)
445 {
446 trigger_interrupt(INT_MATCH);
447 }
448 }
449 }
450
do_write()451 int z80dma_device::do_write()
452 {
453 int done;
454 uint8_t mode;
455
456 mode = TRANSFER_MODE;
457 if (m_count == 0x0000)
458 {
459 //FIXME: Any signal here
460 }
461 switch(mode) {
462 case TM_TRANSFER:
463 do_transfer_write();
464 break;
465
466 case TM_SEARCH:
467 do_search();
468 break;
469
470 case TM_SEARCH_TRANSFER:
471 do_transfer_write();
472 do_search();
473 break;
474
475 default:
476 logerror("z80dma_do_operation: invalid mode %d!\n", mode);
477 break;
478 }
479
480 m_addressA += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
481 m_addressB += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
482
483 m_count--;
484 done = (m_count == 0xFFFF); //correct?
485
486 if (done)
487 {
488 //FIXME: interrupt ?
489 }
490 return done;
491 }
492
493
494 //-------------------------------------------------
495 // timerproc
496 //-------------------------------------------------
497
TIMER_CALLBACK_MEMBER(z80dma_device::timerproc)498 TIMER_CALLBACK_MEMBER(z80dma_device::timerproc)
499 {
500 int done;
501
502 if (--m_cur_cycle)
503 {
504 return;
505 }
506
507 if (m_is_read && !is_ready()) return;
508
509 if (m_is_read)
510 {
511 /* TODO: there's a nasty recursion bug with Alpha for Sharp X1 Turbo on the transfers with this function! */
512 do_read();
513 done = 0;
514 m_is_read = false;
515 m_cur_cycle = (PORTA_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN);
516 }
517 else
518 {
519 done = do_write();
520 m_is_read = true;
521 m_cur_cycle = (PORTB_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN);
522 }
523
524 if (done)
525 {
526 m_dma_enabled = 0; //FIXME: Correct?
527 m_status = 0x09;
528
529 m_status |= !is_ready() << 1; // ready line status
530
531 if(TRANSFER_MODE == TM_TRANSFER) m_status |= 0x10; // no match found
532
533 update_status();
534 LOG("Z80DMA End of Block\n");
535
536 if (INT_ON_END_OF_BLOCK)
537 {
538 trigger_interrupt(INT_END_OF_BLOCK);
539 }
540
541 if (AUTO_RESTART)
542 {
543 LOG("Z80DMA Auto Restart\n");
544
545 m_dma_enabled = 1;
546 m_addressA = PORTA_ADDRESS;
547 m_addressB = PORTB_ADDRESS;
548 m_count = BLOCKLEN;
549 m_status |= 0x30;
550 }
551 }
552 }
553
554
555 //-------------------------------------------------
556 // update_status - update DMA status
557 //-------------------------------------------------
558
update_status()559 void z80dma_device::update_status()
560 {
561 uint16_t pending_transfer;
562 attotime next;
563
564 // no transfer is active right now; is there a transfer pending right now?
565 pending_transfer = is_ready() & m_dma_enabled;
566
567 if (pending_transfer)
568 {
569 m_is_read = true;
570 m_cur_cycle = (PORTA_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN);
571 next = attotime::from_hz(clock());
572 m_timer->adjust(
573 attotime::zero,
574 0,
575 // 1 byte transferred in 4 clock cycles
576 next);
577 }
578 else
579 {
580 if (m_is_read)
581 {
582 // no transfers active right now
583 m_timer->reset();
584 }
585 }
586
587 // set the busreq line
588 m_out_busreq_cb(pending_transfer ? ASSERT_LINE : CLEAR_LINE);
589 }
590
591
592
593 //**************************************************************************
594 // READ/WRITE INTERFACES
595 //**************************************************************************
596
597 //-------------------------------------------------
598 // read - register read
599 //-------------------------------------------------
600
read()601 uint8_t z80dma_device::read()
602 {
603 uint8_t res;
604
605 if(m_read_num_follow == 0) // special case: Legend of Kage on X1 Turbo
606 res = m_status;
607 else {
608 res = m_read_regs_follow[m_read_cur_follow];
609 }
610
611 m_read_cur_follow++;
612
613 if(m_read_cur_follow >= m_read_num_follow)
614 m_read_cur_follow = 0;
615
616 LOG("Z80DMA Read %02x\n", res);
617
618 return res;
619 }
620
621
622 //-------------------------------------------------
623 // write - register write
624 //-------------------------------------------------
625
write(uint8_t data)626 void z80dma_device::write(uint8_t data)
627 {
628 if (m_num_follow == 0)
629 {
630 m_reset_pointer = 0;
631
632 if ((data & 0x87) == 0) // WR2
633 {
634 LOG("Z80DMA WR2 %02x\n", data);
635 WR2 = data;
636 if (data & 0x40)
637 m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_TIMING);
638 }
639 else if ((data & 0x87) == 0x04) // WR1
640 {
641 LOG("Z80DMA WR1 %02x\n", data);
642 WR1 = data;
643 if (data & 0x40)
644 m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_TIMING);
645 }
646 else if ((data & 0x80) == 0) // WR0
647 {
648 LOG("Z80DMA WR0 %02x\n", data);
649 WR0 = data;
650 if (data & 0x08)
651 m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_L);
652 if (data & 0x10)
653 m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_H);
654 if (data & 0x20)
655 m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_L);
656 if (data & 0x40)
657 m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_H);
658 }
659 else if ((data & 0x83) == 0x80) // WR3
660 {
661 LOG("Z80DMA WR3 %02x\n", data);
662 WR3 = data;
663 if (data & 0x08)
664 m_regs_follow[m_num_follow++] = GET_REGNUM(MASK_BYTE);
665 if (data & 0x10)
666 m_regs_follow[m_num_follow++] = GET_REGNUM(MATCH_BYTE);
667 }
668 else if ((data & 0x83) == 0x81) // WR4
669 {
670 LOG("Z80DMA WR4 %02x\n", data);
671 WR4 = data;
672 if (data & 0x04)
673 m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_L);
674 if (data & 0x08)
675 m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_H);
676 if (data & 0x10)
677 m_regs_follow[m_num_follow++] = GET_REGNUM(INTERRUPT_CTRL);
678 }
679 else if ((data & 0xC7) == 0x82) // WR5
680 {
681 LOG("Z80DMA WR5 %02x\n", data);
682 WR5 = data;
683 }
684 else if ((data & 0x83) == 0x83) // WR6
685 {
686 LOG("Z80DMA WR6 %02x\n", data);
687 m_dma_enabled = 0;
688
689 WR6 = data;
690
691 switch (data)
692 {
693 case COMMAND_ENABLE_AFTER_RETI:
694 fatalerror("Z80DMA '%s' Unimplemented WR6 command %02x\n", tag(), data);
695 case COMMAND_READ_STATUS_BYTE:
696 LOG("Z80DMA CMD Read status Byte\n");
697 READ_MASK = 1;
698 m_read_regs_follow[0] = m_status;
699 break;
700 case COMMAND_RESET_AND_DISABLE_INTERRUPTS:
701 WR3 &= ~0x20;
702 m_ip = 0;
703 m_ius = 0;
704 m_force_ready = 0;
705 m_status |= 0x08;
706 break;
707 case COMMAND_INITIATE_READ_SEQUENCE:
708 LOG("Z80DMA Initiate Read Sequence\n");
709 m_read_cur_follow = m_read_num_follow = 0;
710 if(READ_MASK & 0x01) { m_read_regs_follow[m_read_num_follow++] = m_status; }
711 if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = m_count & 0xff; } //byte counter (low)
712 if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = m_count >> 8; } //byte counter (high)
713 if(READ_MASK & 0x08) { m_read_regs_follow[m_read_num_follow++] = m_addressA & 0xff; } //port A address (low)
714 if(READ_MASK & 0x10) { m_read_regs_follow[m_read_num_follow++] = m_addressA >> 8; } //port A address (high)
715 if(READ_MASK & 0x20) { m_read_regs_follow[m_read_num_follow++] = m_addressB & 0xff; } //port B address (low)
716 if(READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = m_addressB >> 8; } //port B address (high)
717 break;
718 case COMMAND_RESET:
719 LOG("Z80DMA Reset\n");
720 m_dma_enabled = 0;
721 m_force_ready = 0;
722 m_ip = 0;
723 m_ius = 0;
724 interrupt_check();
725 // Needs six reset commands to reset the DMA
726 {
727 uint8_t WRi;
728
729 for(WRi=0;WRi<7;WRi++)
730 REG(WRi,m_reset_pointer) = 0;
731
732 m_reset_pointer++;
733 if(m_reset_pointer >= 6) { m_reset_pointer = 0; }
734 }
735 m_status = 0x38;
736 break;
737 case COMMAND_LOAD:
738 m_force_ready = 0;
739 m_addressA = PORTA_ADDRESS;
740 m_addressB = PORTB_ADDRESS;
741 m_count = BLOCKLEN;
742 m_status |= 0x30;
743
744 LOG("Z80DMA Load A: %x B: %x N: %x\n", m_addressA, m_addressB, m_count);
745 break;
746 case COMMAND_DISABLE_DMA:
747 LOG("Z80DMA Disable DMA\n");
748 m_dma_enabled = 0;
749 break;
750 case COMMAND_ENABLE_DMA:
751 LOG("Z80DMA Enable DMA\n");
752 m_dma_enabled = 1;
753 update_status();
754 break;
755 case COMMAND_READ_MASK_FOLLOWS:
756 LOG("Z80DMA Set Read Mask\n");
757 m_regs_follow[m_num_follow++] = GET_REGNUM(READ_MASK);
758 break;
759 case COMMAND_CONTINUE:
760 LOG("Z80DMA Continue\n");
761 m_count = BLOCKLEN;
762 m_dma_enabled = 1;
763 //"match not found" & "end of block" status flags zeroed here
764 m_status |= 0x30;
765 break;
766 case COMMAND_RESET_PORT_A_TIMING:
767 LOG("Z80DMA Reset Port A Timing\n");
768 PORTA_TIMING = 0;
769 break;
770 case COMMAND_RESET_PORT_B_TIMING:
771 LOG("Z80DMA Reset Port B Timing\n");
772 PORTB_TIMING = 0;
773 break;
774 case COMMAND_FORCE_READY:
775 LOG("Z80DMA Force Ready\n");
776 m_force_ready = 1;
777 update_status();
778 break;
779 case COMMAND_ENABLE_INTERRUPTS:
780 LOG("Z80DMA Enable IRQ\n");
781 WR3 |= 0x20;
782 break;
783 case COMMAND_DISABLE_INTERRUPTS:
784 LOG("Z80DMA Disable IRQ\n");
785 WR3 &= ~0x20;
786 break;
787 case COMMAND_REINITIALIZE_STATUS_BYTE:
788 LOG("Z80DMA Reinitialize status byte\n");
789 m_status |= 0x30;
790 m_ip = 0;
791 break;
792 case 0xFB:
793 case 0xFF: // TODO: p8k triggers this, it probably crashed.
794 LOG("Z80DMA undocumented command triggered 0x%02X!\n", data);
795 break;
796 default:
797 logerror("Z80DMA Unknown WR6 command %02x\n", data);
798 }
799 }
800 else if(data == 0x8e) //newtype on Sharp X1, unknown purpose
801 logerror("Z80DMA Unknown base register %02x\n", data);
802 else
803 fatalerror("Z80DMA '%s' Unknown base register %02x\n", tag(), data);
804 m_cur_follow = 0;
805 }
806 else
807 {
808 LOG("Z80DMA Write %02x\n", data);
809
810 int nreg = m_regs_follow[m_cur_follow];
811 m_regs[nreg] = data;
812 m_cur_follow++;
813 if (m_cur_follow>=m_num_follow)
814 m_num_follow = 0;
815 if (nreg == REGNUM(4,3))
816 {
817 m_num_follow=0;
818 if (data & 0x08)
819 m_regs_follow[m_num_follow++] = GET_REGNUM(PULSE_CTRL);
820 if (data & 0x10)
821 m_regs_follow[m_num_follow++] = GET_REGNUM(INTERRUPT_VECTOR);
822 m_cur_follow = 0;
823 }
824 else if(m_regs_follow[m_num_follow] == GET_REGNUM(READ_MASK))
825 {
826 m_read_cur_follow = m_read_num_follow = 0;
827
828 if(READ_MASK & 0x01) { m_read_regs_follow[m_read_num_follow++] = m_status; }
829 if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = m_count & 0xff; } //byte counter (low)
830 if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = m_count >> 8; } //byte counter (high)
831 if(READ_MASK & 0x08) { m_read_regs_follow[m_read_num_follow++] = m_addressA & 0xff; } //port A address (low)
832 if(READ_MASK & 0x10) { m_read_regs_follow[m_read_num_follow++] = m_addressA >> 8; } //port A address (high)
833 if(READ_MASK & 0x20) { m_read_regs_follow[m_read_num_follow++] = m_addressB & 0xff; } //port B address (low)
834 if(READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = m_addressB >> 8; } //port B address (high)
835 }
836
837 m_reset_pointer++;
838 if(m_reset_pointer >= 6) { m_reset_pointer = 0; }
839 }
840 }
841
842
843 //-------------------------------------------------
844 // rdy_write_callback - deferred RDY signal write
845 //-------------------------------------------------
846
TIMER_CALLBACK_MEMBER(z80dma_device::rdy_write_callback)847 TIMER_CALLBACK_MEMBER(z80dma_device::rdy_write_callback)
848 {
849 // normalize state
850 m_rdy = param;
851 m_status = (m_status & 0xFD) | (!is_ready() << 1);
852
853 update_status();
854
855 if (is_ready() && INT_ON_READY)
856 {
857 trigger_interrupt(INT_RDY);
858 }
859 }
860
861
862 //-------------------------------------------------
863 // rdy_w - ready input
864 //-------------------------------------------------
865
WRITE_LINE_MEMBER(z80dma_device::rdy_w)866 WRITE_LINE_MEMBER(z80dma_device::rdy_w)
867 {
868 LOG("Z80DMA RDY: %d Active High: %d\n", state, READY_ACTIVE_HIGH);
869 machine().scheduler().synchronize(timer_expired_delegate(FUNC(z80dma_device::rdy_write_callback),this), state);
870 }
871
872
873 //-------------------------------------------------
874 // wait_w - wait input
875 //-------------------------------------------------
876
WRITE_LINE_MEMBER(z80dma_device::wait_w)877 WRITE_LINE_MEMBER(z80dma_device::wait_w)
878 {
879 }
880
881
882 //-------------------------------------------------
883 // bai_w - bus acknowledge input
884 //-------------------------------------------------
885
WRITE_LINE_MEMBER(z80dma_device::bai_w)886 WRITE_LINE_MEMBER(z80dma_device::bai_w)
887 {
888 }
889