1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /***************************************************************************
4
5 AMD AM9517A
6 Intel 8237A
7 NEC uPD71037
8
9 NEC uPD71071 (extended version of above)
10
11 a variant is used in the V53 CPU which offers subsets of both the
12 uPD71071 and uPD71037 functionality depending on a mode bit.
13
14 Multimode DMA Controller emulation
15
16 ***************************************************************************/
17
18 /*
19
20 TODO:
21
22 - external EOP
23
24 */
25
26 /*
27
28 When the V53 operates in uPD71071 compatible mode there are the following
29 differences from a real uPD71071
30
31 V53 Real uPD71071
32 Software Reqs No Yes
33 Memory-to-Memory DMA No Yes
34 DMARQ active level High programmable
35 DMAAK active level Low programmable
36 Bus Cycle 4 4 or 3
37
38 we don't currently handle the differences
39
40 */
41
42 /*
43 * The EISA_DMA device represents the 82C37A-compatible DMA devices present in
44 * EISA bus systems, in particular those embedded within the i82357 Integrated
45 * System Peripheral. The device supports 32 bit addressing, 32 bit data sizes,
46 * and 24 bit transfer counts, allowing DMA across 64k boundaries. It also adds
47 * stop registers, supporting ring-buffer memory arrangements.
48 *
49 * TODO
50 * - stop registers
51 * - 16/32-bit transfer sizes
52 */
53
54 #include "emu.h"
55 #include "am9517a.h"
56
57 //#define VERBOSE 1
58 #include "logmacro.h"
59
60
61
62 //**************************************************************************
63 // DEVICE DEFINITIONS
64 //**************************************************************************
65
66 DEFINE_DEVICE_TYPE(AM9517A, am9517a_device, "am9517a", "AM9517A")
67 DEFINE_DEVICE_TYPE(V5X_DMAU, v5x_dmau_device, "v5x_dmau", "V5X DMAU")
68 DEFINE_DEVICE_TYPE(PCXPORT_DMAC, pcxport_dmac_device, "pcx_dmac", "PC Transporter DMAC")
69 DEFINE_DEVICE_TYPE(EISA_DMA, eisa_dma_device, "eisa_dma", "EISA DMA")
70
71
72 //**************************************************************************
73 // MACROS / CONSTANTS
74 //**************************************************************************
75
76
77 enum
78 {
79 REGISTER_ADDRESS = 0,
80 REGISTER_WORD_COUNT,
81 REGISTER_STATUS = 8,
82 REGISTER_COMMAND = REGISTER_STATUS,
83 REGISTER_REQUEST,
84 REGISTER_SINGLE_MASK,
85 REGISTER_MODE,
86 REGISTER_BYTE_POINTER,
87 REGISTER_TEMPORARY,
88 REGISTER_MASTER_CLEAR = REGISTER_TEMPORARY,
89 REGISTER_CLEAR_MASK,
90 REGISTER_MASK
91 };
92
93
94 #define COMMAND_MEM_TO_MEM BIT(m_command, 0)
95 #define COMMAND_CH0_ADDRESS_HOLD BIT(m_command, 1)
96 #define COMMAND_DISABLE BIT(m_command, 2)
97 #define COMMAND_COMPRESSED_TIMING BIT(m_command, 3)
98 #define COMMAND_ROTATING_PRIORITY BIT(m_command, 4)
99 #define COMMAND_EXTENDED_WRITE BIT(m_command, 5)
100 #define COMMAND_DREQ_ACTIVE_LOW BIT(m_command, 6)
101 #define COMMAND_DACK_ACTIVE_HIGH BIT(m_command, 7)
102
103
104 #define MODE_TRANSFER_MASK (m_channel[m_current_channel].m_mode & 0x0c)
105 #define MODE_TRANSFER_VERIFY 0x00
106 #define MODE_TRANSFER_WRITE 0x04
107 #define MODE_TRANSFER_READ 0x08
108 #define MODE_TRANSFER_ILLEGAL 0x0c
109 #define MODE_AUTOINITIALIZE BIT(m_channel[m_current_channel].m_mode, 4)
110 #define MODE_ADDRESS_DECREMENT BIT(m_channel[m_current_channel].m_mode, 5)
111 #define MODE_MASK (m_channel[m_current_channel].m_mode & 0xc0)
112 #define MODE_DEMAND 0x00
113 #define MODE_SINGLE 0x40
114 #define MODE_BLOCK 0x80
115 #define MODE_CASCADE 0xc0
116
117
118 enum
119 {
120 STATE_SI,
121 STATE_S0,
122 STATE_SC,
123 STATE_S1,
124 STATE_S2,
125 STATE_S3,
126 STATE_SW,
127 STATE_S4,
128 STATE_S11,
129 STATE_S12,
130 STATE_S13,
131 STATE_S14,
132 STATE_S21,
133 STATE_S22,
134 STATE_S23,
135 STATE_S24
136 };
137
138
139
140 //**************************************************************************
141 // INLINE HELPERS
142 //**************************************************************************
143
144 //-------------------------------------------------
145 // dma_request -
146 //-------------------------------------------------
147
dma_request(int channel,int state)148 void am9517a_device::dma_request(int channel, int state)
149 {
150 LOG("AM9517A Channel %u DMA Request: %u\n", channel, state);
151
152 if (state ^ COMMAND_DREQ_ACTIVE_LOW)
153 {
154 m_status |= (1 << (channel + 4));
155 }
156 else
157 {
158 m_status &= ~(1 << (channel + 4));
159 }
160 trigger(1);
161 }
162
163
164 //-------------------------------------------------
165 // is_request_active -
166 //-------------------------------------------------
167
is_request_active(int channel)168 inline bool am9517a_device::is_request_active(int channel)
169 {
170 return (BIT(m_status, channel + 4) & ~BIT(m_mask, channel)) ? true : false;
171 }
172
173
174 //-------------------------------------------------
175 // is_software_request_active -
176 //-------------------------------------------------
177
is_software_request_active(int channel)178 inline bool am9517a_device::is_software_request_active(int channel)
179 {
180 return BIT(m_request, channel) && ((m_channel[channel].m_mode & 0xc0) == MODE_BLOCK);
181 }
182
183
184 //-------------------------------------------------
185 // set_hreq
186 //-------------------------------------------------
187
set_hreq(int state)188 inline void am9517a_device::set_hreq(int state)
189 {
190 if (m_hreq != state)
191 {
192 m_out_hreq_cb(state);
193
194 m_hreq = state;
195 }
196 }
197
198
199 //-------------------------------------------------
200 // set_dack -
201 //-------------------------------------------------
202
set_dack()203 inline void am9517a_device::set_dack()
204 {
205 for (int channel = 0; channel < 4; channel++)
206 {
207 if ((channel == m_current_channel) && !COMMAND_MEM_TO_MEM)
208 m_out_dack_cb[channel](COMMAND_DACK_ACTIVE_HIGH);
209 else
210 m_out_dack_cb[channel](!COMMAND_DACK_ACTIVE_HIGH);
211 }
212 }
213
214
215 //-------------------------------------------------
216 // set_eop -
217 //-------------------------------------------------
218
set_eop(int state)219 inline void am9517a_device::set_eop(int state)
220 {
221 if (m_eop != state)
222 {
223 m_out_eop_cb(state);
224
225 m_eop = state;
226 }
227 }
228
229
230 //-------------------------------------------------
231 // get_state1 -
232 //-------------------------------------------------
233
get_state1(bool msb_changed)234 inline int am9517a_device::get_state1(bool msb_changed)
235 {
236 if (COMMAND_MEM_TO_MEM)
237 {
238 return msb_changed ? STATE_S11 : STATE_S12;
239 }
240 else
241 {
242 return msb_changed ? STATE_S1 : STATE_S2;
243 }
244 }
245
246
247 //-------------------------------------------------
248 // dma_read -
249 //-------------------------------------------------
250
dma_read()251 void am9517a_device::dma_read()
252 {
253 offs_t offset = m_channel[m_current_channel].m_address;
254
255 switch (MODE_TRANSFER_MASK)
256 {
257 case MODE_TRANSFER_VERIFY:
258 case MODE_TRANSFER_WRITE:
259 m_temp = m_in_ior_cb[m_current_channel](offset);
260 break;
261
262 case MODE_TRANSFER_READ:
263 m_temp = m_in_memr_cb(offset);
264 break;
265 }
266 }
267
268
269 //-------------------------------------------------
270 // dma_write -
271 //-------------------------------------------------
272
dma_write()273 void am9517a_device::dma_write()
274 {
275 offs_t offset = m_channel[m_current_channel].m_address;
276
277 switch (MODE_TRANSFER_MASK)
278 {
279 case MODE_TRANSFER_VERIFY:
280 {
281 uint8_t v1 = m_in_memr_cb(offset);
282 if(0 && m_temp != v1)
283 logerror("verify error %02x vs. %02x\n", m_temp, v1);
284 }
285 break;
286
287 case MODE_TRANSFER_WRITE:
288 m_out_memw_cb(offset, m_temp);
289 break;
290
291 case MODE_TRANSFER_READ:
292 m_out_iow_cb[m_current_channel](offset, m_temp);
293 break;
294 }
295 }
296
297
298 //-------------------------------------------------
299 // dma_advance -
300 //-------------------------------------------------
301
dma_advance()302 inline void am9517a_device::dma_advance()
303 {
304 bool msb_changed = false;
305
306 if (m_current_channel || !COMMAND_MEM_TO_MEM || !COMMAND_CH0_ADDRESS_HOLD)
307 {
308 if (MODE_ADDRESS_DECREMENT)
309 {
310 m_channel[m_current_channel].m_address -= transfer_size(m_current_channel);
311 m_channel[m_current_channel].m_address &= m_address_mask;
312
313 if ((m_channel[m_current_channel].m_address & 0xff) == 0xff)
314 {
315 msb_changed = true;
316 }
317 }
318 else
319 {
320 m_channel[m_current_channel].m_address += transfer_size(m_current_channel);
321 m_channel[m_current_channel].m_address &= m_address_mask;
322
323 if ((m_channel[m_current_channel].m_address & 0xff) == 0x00)
324 {
325 msb_changed = true;
326 }
327 }
328 }
329
330 if (m_channel[m_current_channel].m_count-- == 0)
331 {
332 end_of_process();
333 }
334 else
335 {
336 switch (MODE_MASK)
337 {
338 case MODE_DEMAND:
339 if (!is_request_active(m_current_channel))
340 {
341 set_hreq(0);
342 set_dack();
343 m_state = STATE_SI;
344 }
345 else
346 {
347 m_state = get_state1(msb_changed);
348 }
349 break;
350
351 case MODE_SINGLE:
352 set_hreq(0);
353 set_dack();
354 m_state = STATE_SI;
355 break;
356
357 case MODE_BLOCK:
358 m_state = get_state1(msb_changed);
359 break;
360
361 case MODE_CASCADE:
362 break;
363 }
364 }
365 }
366
367
368 //-------------------------------------------------
369 // end_of_process -
370 //-------------------------------------------------
371
end_of_process()372 void am9517a_device::end_of_process()
373 {
374 // terminal count
375 if (COMMAND_MEM_TO_MEM)
376 {
377 m_status |= 1 << 0;
378 m_status |= 1 << 1;
379 m_request &= ~(1 << 0);
380 m_request &= ~(1 << 1);
381 }
382 else
383 {
384 m_status |= 1 << m_current_channel;
385 m_request &= ~(1 << m_current_channel);
386 }
387
388 if (MODE_AUTOINITIALIZE)
389 {
390 // autoinitialize
391 m_channel[m_current_channel].m_address = m_channel[m_current_channel].m_base_address;
392 m_channel[m_current_channel].m_count = m_channel[m_current_channel].m_base_count;
393 }
394 else
395 {
396 // mask out channel
397 m_mask |= 1 << m_current_channel;
398 }
399
400 set_eop(CLEAR_LINE);
401 set_hreq(0);
402
403 m_current_channel = -1;
404 set_dack();
405
406 m_state = STATE_SI;
407 }
408
409
410
411 //**************************************************************************
412 // LIVE DEVICE
413 //**************************************************************************
414
415 //-------------------------------------------------
416 // am9517a_device - constructor
417 //-------------------------------------------------
418
419
am9517a_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)420 am9517a_device::am9517a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
421 : device_t(mconfig, type, tag, owner, clock),
422 device_execute_interface(mconfig, *this),
423 m_icount(0),
424 m_hack(0),
425 m_ready(1),
426 m_command(0),
427 m_out_hreq_cb(*this),
428 m_out_eop_cb(*this),
429 m_in_memr_cb(*this),
430 m_out_memw_cb(*this),
431 m_in_ior_cb(*this),
432 m_out_iow_cb(*this),
433 m_out_dack_cb(*this)
434 {
435 }
436
437
am9517a_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)438 am9517a_device::am9517a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
439 : am9517a_device(mconfig, AM9517A, tag, owner, clock)
440 {
441 }
442
v5x_dmau_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)443 v5x_dmau_device::v5x_dmau_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
444 : am9517a_device(mconfig, V5X_DMAU, tag, owner, clock)
445 , m_in_mem16r_cb(*this)
446 , m_out_mem16w_cb(*this)
447 , m_in_io16r_cb(*this)
448 , m_out_io16w_cb(*this)
449
450 {
451 }
452
pcxport_dmac_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)453 pcxport_dmac_device::pcxport_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
454 : am9517a_device(mconfig, PCXPORT_DMAC, tag, owner, clock)
455 {
456 }
457
458 //-------------------------------------------------
459 // device_start - device-specific startup
460 //-------------------------------------------------
461
device_start()462 void am9517a_device::device_start()
463 {
464 // set our instruction counter
465 set_icountptr(m_icount);
466
467 // resolve callbacks
468 m_out_hreq_cb.resolve_safe();
469 m_out_eop_cb.resolve_safe();
470 m_in_memr_cb.resolve_safe(0);
471 m_out_memw_cb.resolve_safe();
472 m_in_ior_cb.resolve_all_safe(0);
473 m_out_iow_cb.resolve_all_safe();
474 m_out_dack_cb.resolve_all_safe();
475
476 for(auto &elem : m_channel)
477 {
478 elem.m_address = 0;
479 elem.m_count = 0;
480 elem.m_base_address = 0;
481 elem.m_base_count = 0;
482 elem.m_mode = 0;
483 }
484
485 // state saving
486 save_item(NAME(m_msb));
487 save_item(NAME(m_hreq));
488 save_item(NAME(m_hack));
489 save_item(NAME(m_ready));
490 save_item(NAME(m_eop));
491 save_item(NAME(m_state));
492 save_item(NAME(m_current_channel));
493 save_item(NAME(m_last_channel));
494 save_item(NAME(m_command));
495 save_item(NAME(m_mask));
496 save_item(NAME(m_status));
497 save_item(NAME(m_temp));
498 save_item(NAME(m_request));
499
500 save_item(STRUCT_MEMBER(m_channel, m_address));
501 save_item(STRUCT_MEMBER(m_channel, m_count));
502 save_item(STRUCT_MEMBER(m_channel, m_base_address));
503 save_item(STRUCT_MEMBER(m_channel, m_base_count));
504 save_item(STRUCT_MEMBER(m_channel, m_mode));
505
506 m_address_mask = 0xffff;
507
508 // force clear upon initial reset
509 m_eop = ASSERT_LINE;
510 }
511
512
513 //-------------------------------------------------
514 // device_reset - device-specific reset
515 //-------------------------------------------------
516
device_reset()517 void am9517a_device::device_reset()
518 {
519 m_state = STATE_SI;
520 m_command = 0;
521 m_status = 0;
522 m_request = 0;
523 m_mask = 0x0f;
524 m_temp = 0;
525 m_msb = 0;
526 m_current_channel = -1;
527 m_last_channel = 3;
528 m_hreq = -1;
529
530 set_hreq(0);
531 set_eop(CLEAR_LINE);
532
533 set_dack();
534 }
535
536
537 //-------------------------------------------------
538 // execute_run -
539 //-------------------------------------------------
540
execute_run()541 void am9517a_device::execute_run()
542 {
543 do
544 {
545 switch (m_state)
546 {
547 case STATE_SI:
548 if (!COMMAND_DISABLE)
549 {
550 int priority[] = { 0, 1, 2, 3 };
551
552 if (COMMAND_ROTATING_PRIORITY)
553 {
554 int last_channel = m_last_channel;
555
556 for (int channel = 3; channel >= 0; channel--)
557 {
558 priority[channel] = last_channel;
559 last_channel--;
560 if (last_channel < 0) last_channel = 3;
561 }
562 }
563
564 for (int channel = 0; channel < 4; channel++)
565 {
566 if (is_request_active(priority[channel]) || is_software_request_active(priority[channel]))
567 {
568 m_current_channel = m_last_channel = priority[channel];
569 m_state = STATE_S0;
570 break;
571 }
572 else if (COMMAND_MEM_TO_MEM && BIT(m_request, channel) && ((m_channel[channel].m_mode & 0xc0) == MODE_SINGLE))
573 {
574 m_current_channel = m_last_channel = priority[channel];
575 m_state = STATE_S0;
576 break;
577 }
578 }
579 }
580 if(m_state == STATE_SI)
581 {
582 suspend_until_trigger(1, true);
583 m_icount = 0;
584 }
585 break;
586
587 case STATE_S0:
588 set_hreq(1);
589
590 if (m_hack)
591 {
592 m_state = (MODE_MASK == MODE_CASCADE) ? STATE_SC : get_state1(true);
593 }
594 else
595 {
596 suspend_until_trigger(1, true);
597 m_icount = 0;
598 }
599 break;
600
601 case STATE_SC:
602 if (!is_request_active(m_current_channel))
603 {
604 set_hreq(0);
605 m_current_channel = -1;
606 m_state = STATE_SI;
607 }
608 else
609 {
610 suspend_until_trigger(1, true);
611 m_icount = 0;
612 }
613
614 set_dack();
615 break;
616
617 case STATE_S1:
618 m_state = STATE_S2;
619 break;
620
621 case STATE_S2:
622 set_dack();
623 if (COMMAND_COMPRESSED_TIMING)
624 {
625 // signal end of process during last cycle
626 if (m_channel[m_current_channel].m_count == 0)
627 set_eop(ASSERT_LINE);
628
629 m_state = STATE_S4;
630 }
631 else
632 m_state = STATE_S3;
633 break;
634
635 case STATE_S3:
636 // signal end of process during last cycle
637 if (m_channel[m_current_channel].m_count == 0)
638 set_eop(ASSERT_LINE);
639
640 dma_read();
641
642 if (COMMAND_EXTENDED_WRITE)
643 {
644 dma_write();
645 }
646
647 m_state = m_ready ? STATE_S4 : STATE_SW;
648 break;
649
650 case STATE_SW:
651 m_state = m_ready ? STATE_S4 : STATE_SW;
652 break;
653
654 case STATE_S4:
655 if (COMMAND_COMPRESSED_TIMING)
656 {
657 dma_read();
658 dma_write();
659 }
660 else if (!COMMAND_EXTENDED_WRITE)
661 {
662 dma_write();
663 }
664
665 dma_advance();
666 break;
667
668 case STATE_S11:
669 m_current_channel = 0;
670
671 m_state = STATE_S12;
672 break;
673
674 case STATE_S12:
675 m_state = STATE_S13;
676 break;
677
678 case STATE_S13:
679 m_state = STATE_S14;
680 break;
681
682 case STATE_S14:
683 dma_read();
684
685 m_state = STATE_S21;
686 break;
687
688 case STATE_S21:
689 m_current_channel = 1;
690
691 m_state = STATE_S22;
692 break;
693
694 case STATE_S22:
695 m_state = STATE_S23;
696 break;
697
698 case STATE_S23:
699 // signal end of process during last cycle
700 if (m_channel[m_current_channel].m_count == 0)
701 set_eop(ASSERT_LINE);
702
703 m_state = STATE_S24;
704 break;
705
706 case STATE_S24:
707 dma_write();
708 dma_advance();
709
710 m_current_channel = 0;
711 m_channel[m_current_channel].m_count--;
712 if (MODE_ADDRESS_DECREMENT)
713 {
714 m_channel[m_current_channel].m_address -= transfer_size(m_current_channel);
715 m_channel[m_current_channel].m_address &= m_address_mask;
716 }
717 else
718 {
719 m_channel[m_current_channel].m_address += transfer_size(m_current_channel);
720 m_channel[m_current_channel].m_address &= m_address_mask;
721 }
722
723 break;
724 }
725
726 m_icount--;
727 } while (m_icount > 0);
728 }
729
730
731 //-------------------------------------------------
732 // read -
733 //-------------------------------------------------
734
read(offs_t offset)735 uint8_t am9517a_device::read(offs_t offset)
736 {
737 uint8_t data = 0;
738
739 if (!BIT(offset, 3))
740 {
741 int channel = (offset >> 1) & 0x03;
742
743 switch (offset & 0x01)
744 {
745 case REGISTER_ADDRESS:
746 if (m_msb)
747 {
748 data = m_channel[channel].m_address >> 8;
749 }
750 else
751 {
752 data = m_channel[channel].m_address & 0xff;
753 }
754 break;
755
756 case REGISTER_WORD_COUNT:
757 if (m_msb)
758 {
759 data = m_channel[channel].m_count >> 8;
760 }
761 else
762 {
763 data = m_channel[channel].m_count & 0xff;
764 }
765 break;
766 }
767
768 m_msb = !m_msb;
769 }
770 else
771 {
772 switch (offset & 0x0f)
773 {
774 case REGISTER_STATUS:
775 data = m_status;
776
777 // clear TC bits
778 m_status &= 0xf0;
779 break;
780
781 case REGISTER_TEMPORARY:
782 data = m_temp;
783 break;
784
785 case REGISTER_MASK:
786 data = m_mask;
787 break;
788 }
789 }
790
791 return data;
792 }
793
794
795 //-------------------------------------------------
796 // write -
797 //-------------------------------------------------
798
write(offs_t offset,uint8_t data)799 void am9517a_device::write(offs_t offset, uint8_t data)
800 {
801 if (!BIT(offset, 3))
802 {
803 int channel = (offset >> 1) & 0x03;
804
805 switch (offset & 0x01)
806 {
807 case REGISTER_ADDRESS:
808 if (m_msb)
809 {
810 m_channel[channel].m_base_address = (data << 8) | (m_channel[channel].m_base_address & 0xff);
811 m_channel[channel].m_address = (data << 8) | (m_channel[channel].m_address & 0xff);
812 }
813 else
814 {
815 m_channel[channel].m_base_address = (m_channel[channel].m_base_address & 0xff00) | data;
816 m_channel[channel].m_address = (m_channel[channel].m_address & 0xff00) | data;
817 }
818
819 LOG("AM9517A Channel %u Base Address: %04x\n", channel, m_channel[channel].m_base_address);
820 break;
821
822 case REGISTER_WORD_COUNT:
823 if (m_msb)
824 {
825 m_channel[channel].m_base_count = (data << 8) | (m_channel[channel].m_base_count & 0xff);
826 m_channel[channel].m_count = (data << 8) | (m_channel[channel].m_count & 0xff);
827 }
828 else
829 {
830 m_channel[channel].m_base_count = (m_channel[channel].m_base_count & 0xff00) | data;
831 m_channel[channel].m_count = (m_channel[channel].m_count & 0xff00) | data;
832 }
833
834 LOG("AM9517A Channel %u Base Word Count: %04x\n", channel, m_channel[channel].m_base_count);
835 break;
836 }
837
838 m_msb = !m_msb;
839 }
840 else
841 {
842 switch (offset & 0x0f)
843 {
844 case REGISTER_COMMAND:
845 m_command = data;
846
847 LOG("AM9517A Command Register: %02x\n", m_command);
848 break;
849
850 case REGISTER_REQUEST:
851 {
852 int channel = data & 0x03;
853
854 if (BIT(data, 2))
855 {
856 m_request |= (1 << (channel + 4));
857 if (COMMAND_MEM_TO_MEM)
858 {
859 m_request |= (1 << channel);
860 }
861 }
862 else
863 {
864 m_request &= ~(1 << (channel + 4));
865 }
866
867 LOG("AM9517A Request Register: %01x\n", m_request);
868 }
869 break;
870
871 case REGISTER_SINGLE_MASK:
872 {
873 int channel = data & 0x03;
874
875 if (BIT(data, 2))
876 {
877 m_mask |= (1 << channel);
878 }
879 else
880 {
881 m_mask &= ~(1 << channel);
882 }
883
884 LOG("AM9517A Mask Register: %01x\n", m_mask);
885 }
886 break;
887
888 case REGISTER_MODE:
889 {
890 int channel = data & 0x03;
891
892 m_channel[channel].m_mode = data & 0xfc;
893
894 // clear terminal count
895 m_status &= ~(1 << channel);
896
897 LOG("AM9517A Channel %u Mode: %02x\n", channel, data & 0xfc);
898 }
899 break;
900
901 case REGISTER_BYTE_POINTER:
902 LOG("AM9517A Clear Byte Pointer Flip-Flop\n");
903
904 m_msb = 0;
905 break;
906
907 case REGISTER_MASTER_CLEAR:
908 LOG("AM9517A Master Clear\n");
909
910 device_reset();
911 break;
912
913 case REGISTER_CLEAR_MASK:
914 LOG("AM9517A Clear Mask Register\n");
915
916 m_mask = 0;
917 break;
918
919 case REGISTER_MASK:
920 m_mask = data & 0x0f;
921
922 LOG("AM9517A Mask Register: %01x\n", m_mask);
923 break;
924 }
925 }
926 trigger(1);
927 }
928
929
930 //-------------------------------------------------
931 // hack_w - hold acknowledge
932 //-------------------------------------------------
933
WRITE_LINE_MEMBER(am9517a_device::hack_w)934 WRITE_LINE_MEMBER( am9517a_device::hack_w )
935 {
936 LOG("AM9517A Hold Acknowledge: %u\n", state);
937
938 m_hack = state;
939 trigger(1);
940 }
941
942
943 //-------------------------------------------------
944 // ready_w - ready
945 //-------------------------------------------------
946
WRITE_LINE_MEMBER(am9517a_device::ready_w)947 WRITE_LINE_MEMBER( am9517a_device::ready_w )
948 {
949 LOG("AM9517A Ready: %u\n", state);
950
951 m_ready = state;
952 }
953
954
955 //-------------------------------------------------
956 // eop_w - end of process
957 //-------------------------------------------------
958
WRITE_LINE_MEMBER(am9517a_device::eop_w)959 WRITE_LINE_MEMBER( am9517a_device::eop_w )
960 {
961 LOG("AM9517A End of Process: %u\n", state);
962 }
963
964
965 //-------------------------------------------------
966 // dreq0_w - DMA request for channel 0
967 //-------------------------------------------------
968
WRITE_LINE_MEMBER(am9517a_device::dreq0_w)969 WRITE_LINE_MEMBER( am9517a_device::dreq0_w )
970 {
971 dma_request(0, state);
972 }
973
974
975 //-------------------------------------------------
976 // dreq0_w - DMA request for channel 1
977 //-------------------------------------------------
978
WRITE_LINE_MEMBER(am9517a_device::dreq1_w)979 WRITE_LINE_MEMBER( am9517a_device::dreq1_w )
980 {
981 dma_request(1, state);
982 }
983
984
985 //-------------------------------------------------
986 // dreq1_w - DMA request for channel 2
987 //-------------------------------------------------
988
WRITE_LINE_MEMBER(am9517a_device::dreq2_w)989 WRITE_LINE_MEMBER( am9517a_device::dreq2_w )
990 {
991 dma_request(2, state);
992 }
993
994
995 //-------------------------------------------------
996 // dreq3_w - DMA request for channel 3
997 //-------------------------------------------------
998
WRITE_LINE_MEMBER(am9517a_device::dreq3_w)999 WRITE_LINE_MEMBER( am9517a_device::dreq3_w )
1000 {
1001 dma_request(3, state);
1002 }
1003
1004 //-------------------------------------------------
1005 // upd71071 register layouts
1006 //-------------------------------------------------
1007
device_start()1008 void v5x_dmau_device::device_start()
1009 {
1010 am9517a_device::device_start();
1011 m_address_mask = 0x00ffffff;
1012
1013 m_in_mem16r_cb.resolve_safe(0);
1014 m_out_mem16w_cb.resolve_safe();
1015 m_in_io16r_cb.resolve_all_safe(0);
1016 m_out_io16w_cb.resolve_all_safe();
1017
1018 m_selected_channel = 0;
1019 m_base = 0;
1020
1021 save_item(NAME(m_selected_channel));
1022 save_item(NAME(m_base));
1023 }
1024
device_reset()1025 void v5x_dmau_device::device_reset()
1026 {
1027 am9517a_device::device_reset();
1028
1029 m_selected_channel = 0;
1030 m_base = 0;
1031 }
1032
1033
read(offs_t offset)1034 uint8_t v5x_dmau_device::read(offs_t offset)
1035 {
1036 uint8_t ret = 0;
1037 int channel = m_selected_channel;
1038
1039 LOG("DMA: read from register %02x\n",offset);
1040
1041 switch (offset)
1042 {
1043 case 0x01: // Channel
1044 ret = (1 << m_selected_channel);
1045 if (m_base != 0)
1046 ret |= 0x10;
1047 break;
1048 case 0x02: // Count (low)
1049 if (m_base != 0)
1050 ret = m_channel[channel].m_base_count & 0xff;
1051 else
1052 ret = m_channel[channel].m_count & 0xff;
1053 break;
1054 case 0x03: // Count (high)
1055 if (m_base != 0)
1056 ret = (m_channel[channel].m_base_count >> 8) & 0xff;
1057 else
1058 ret = (m_channel[channel].m_count >> 8) & 0xff;
1059 break;
1060 case 0x04: // Address (low)
1061 if (m_base != 0)
1062 ret = m_channel[channel].m_base_address & 0xff;
1063 else
1064 ret = m_channel[channel].m_address & 0xff;
1065 break;
1066 case 0x05: // Address (mid)
1067 if (m_base != 0)
1068 ret = (m_channel[channel].m_base_address >> 8) & 0xff;
1069 else
1070 ret = (m_channel[channel].m_address >> 8) & 0xff;
1071 break;
1072 case 0x06: // Address (high)
1073 if (m_base != 0)
1074 ret = (m_channel[channel].m_base_address >> 16) & 0xff;
1075 else
1076 ret = (m_channel[channel].m_address >> 16) & 0xff;
1077 break;
1078 case 0x07: // Address (highest)
1079 if (m_base != 0)
1080 ret = (m_channel[channel].m_base_address >> 24) & 0xff;
1081 else
1082 ret = (m_channel[channel].m_address >> 24) & 0xff;
1083 break;
1084 case 0x0a: // Mode control
1085 ret = (m_channel[channel].m_mode);
1086 break;
1087
1088 case 0x08: // Device control (low)
1089 ret = m_command & 0xff;
1090 break;
1091 case 0x09: // Device control (high) // UPD71071 only?
1092 ret = m_command_high & 0xff;
1093 break;
1094 case 0x0b: // Status
1095 ret = m_status;
1096 // clear TC bits
1097 m_status &= 0xf0;
1098 break;
1099 case 0x0c: // Temporary (low)
1100 ret = m_temp & 0xff;
1101 break;
1102 case 0x0d: // Temporary (high) // UPD71071 only? (other doesn't do 16-bit?)
1103 ret = (m_temp >> 8 ) & 0xff;
1104 break;
1105 case 0x0e: // Request
1106 //ret = m_reg.request;
1107 ret = 0; // invalid?
1108 break;
1109 case 0x0f: // Mask
1110 ret = m_mask;
1111 break;
1112
1113 }
1114
1115 return ret;
1116 }
1117
write(offs_t offset,uint8_t data)1118 void v5x_dmau_device::write(offs_t offset, uint8_t data)
1119 {
1120 int channel = m_selected_channel;
1121
1122 switch (offset)
1123 {
1124 case 0x00: // Initialise
1125 // TODO: reset (bit 0)
1126 //m_buswidth = data & 0x02;
1127 //if (data & 0x01)
1128 // soft_reset();
1129 LOG("DMA: Initialise [%02x]\n", data);
1130 break;
1131 case 0x01: // Channel
1132 m_selected_channel = data & 0x03;
1133 m_base = data & 0x04;
1134 LOG("DMA: Channel selected [%02x]\n", data);
1135 break;
1136 case 0x02: // Count (low)
1137 m_channel[channel].m_base_count =
1138 (m_channel[channel].m_base_count & 0xff00) | data;
1139 if (m_base == 0)
1140 m_channel[channel].m_count =
1141 (m_channel[channel].m_count & 0xff00) | data;
1142 LOG("DMA: Channel %i Counter set [%04x]\n", m_selected_channel, m_channel[channel].m_base_count);
1143 break;
1144 case 0x03: // Count (high)
1145 m_channel[channel].m_base_count =
1146 (m_channel[channel].m_base_count & 0x00ff) | (data << 8);
1147 if (m_base == 0)
1148 m_channel[channel].m_count =
1149 (m_channel[channel].m_count & 0x00ff) | (data << 8);
1150 LOG("DMA: Channel %i Counter set [%04x]\n", m_selected_channel, m_channel[channel].m_base_count);
1151 break;
1152 case 0x04: // Address (low)
1153 m_channel[channel].m_base_address =
1154 (m_channel[channel].m_base_address & 0xffffff00) | data;
1155 if (m_base == 0)
1156 m_channel[channel].m_address =
1157 (m_channel[channel].m_address & 0xffffff00) | data;
1158 LOG("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address);
1159 break;
1160 case 0x05: // Address (mid)
1161 m_channel[channel].m_base_address =
1162 (m_channel[channel].m_base_address & 0xffff00ff) | (data << 8);
1163 if (m_base == 0)
1164 m_channel[channel].m_address =
1165 (m_channel[channel].m_address & 0xffff00ff) | (data << 8);
1166 LOG("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address);
1167 break;
1168 case 0x06: // Address (high)
1169 m_channel[channel].m_base_address =
1170 (m_channel[channel].m_base_address & 0xff00ffff) | (data << 16);
1171 if (m_base == 0)
1172 m_channel[channel].m_address =
1173 (m_channel[channel].m_address & 0xff00ffff) | (data << 16);
1174 LOG("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address);
1175 break;
1176 case 0x07: // Address (highest)
1177 m_channel[channel].m_base_address =
1178 (m_channel[channel].m_base_address & 0x00ffffff) | (data << 24);
1179 if (m_base == 0)
1180 m_channel[channel].m_address =
1181 (m_channel[channel].m_address & 0x00ffffff) | (data << 24);
1182 LOG("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address);
1183 break;
1184 case 0x0a: // Mode control
1185 m_channel[channel].m_mode = data;
1186 // clear terminal count
1187 m_status &= ~(1 << channel);
1188
1189 LOG("DMA: Channel %i Mode control set [%02x]\n",m_selected_channel,m_channel[channel].m_mode);
1190 break;
1191
1192 case 0x08: // Device control (low)
1193 m_command = data;
1194 LOG("DMA: Device control low set [%02x]\n",data);
1195 break;
1196 case 0x09: // Device control (high)
1197 m_command_high = data;
1198 LOG("DMA: Device control high set [%02x]\n",data);
1199 break;
1200 case 0x0e: // Request
1201 //m_reg.request = data;
1202 LOG("(invalid) DMA: Request set [%02x]\n",data); // no software requests on the v53 integrated version
1203 break;
1204 case 0x0f: // Mask
1205 m_mask = data & 0x0f;
1206 LOG("DMA: Mask set [%02x]\n",data);
1207 break;
1208
1209
1210 }
1211 trigger(1);
1212
1213 }
1214
dma_read()1215 void v5x_dmau_device::dma_read()
1216 {
1217 if (m_channel[m_current_channel].m_mode & 0x1)
1218 {
1219 offs_t const offset = m_channel[m_current_channel].m_address >> 1;
1220
1221 switch (MODE_TRANSFER_MASK)
1222 {
1223 case MODE_TRANSFER_VERIFY:
1224 case MODE_TRANSFER_WRITE:
1225 m_temp = m_in_io16r_cb[m_current_channel](offset);
1226 break;
1227
1228 case MODE_TRANSFER_READ:
1229 m_temp = m_in_mem16r_cb(offset);
1230 break;
1231 }
1232 }
1233 else
1234 am9517a_device::dma_read();
1235 }
1236
dma_write()1237 void v5x_dmau_device::dma_write()
1238 {
1239 if (m_channel[m_current_channel].m_mode & 0x1)
1240 {
1241 offs_t const offset = m_channel[m_current_channel].m_address >> 1;
1242
1243 switch (MODE_TRANSFER_MASK)
1244 {
1245 case MODE_TRANSFER_VERIFY:
1246 {
1247 u16 const v1 = m_in_mem16r_cb(offset);
1248 if (0 && m_temp != v1)
1249 logerror("verify error %04x vs. %04x\n", m_temp, v1);
1250 }
1251 break;
1252
1253 case MODE_TRANSFER_WRITE:
1254 m_out_mem16w_cb(offset, m_temp);
1255 break;
1256
1257 case MODE_TRANSFER_READ:
1258 m_out_io16w_cb[m_current_channel](offset, m_temp);
1259 break;
1260 }
1261 }
1262 else
1263 am9517a_device::dma_write();
1264 }
1265
device_reset()1266 void pcxport_dmac_device::device_reset()
1267 {
1268 m_state = STATE_SI;
1269 m_command = 0;
1270 m_status = 0;
1271 m_request = 0;
1272 m_mask = 0;
1273 m_temp = 0;
1274 m_msb = 0;
1275 m_current_channel = -1;
1276 m_last_channel = 3;
1277 m_hreq = -1;
1278
1279 set_hreq(0);
1280 set_eop(CLEAR_LINE);
1281
1282 set_dack();
1283 }
1284
end_of_process()1285 void pcxport_dmac_device::end_of_process()
1286 {
1287 // terminal count
1288 if (COMMAND_MEM_TO_MEM)
1289 {
1290 m_status |= 1 << 0;
1291 m_status |= 1 << 1;
1292 m_request &= ~(1 << 0);
1293 m_request &= ~(1 << 1);
1294 }
1295 else
1296 {
1297 m_status |= 1 << m_current_channel;
1298 m_request &= ~(1 << m_current_channel);
1299 }
1300
1301 if (MODE_AUTOINITIALIZE)
1302 {
1303 // autoinitialize
1304 m_channel[m_current_channel].m_address = m_channel[m_current_channel].m_base_address;
1305 m_channel[m_current_channel].m_count = m_channel[m_current_channel].m_base_count;
1306 }
1307 // don't mask out channel if not autoinitialize
1308
1309 set_eop(CLEAR_LINE);
1310 set_hreq(0);
1311
1312 m_current_channel = -1;
1313 set_dack();
1314
1315 m_state = STATE_SI;
1316 }
1317
eisa_dma_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1318 eisa_dma_device::eisa_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1319 : am9517a_device(mconfig, EISA_DMA, tag, owner, clock)
1320 {
1321 }
1322
device_start()1323 void eisa_dma_device::device_start()
1324 {
1325 am9517a_device::device_start();
1326
1327 m_address_mask = 0xffffffffU;
1328
1329 save_item(NAME(m_stop));
1330 save_item(NAME(m_ext_mode));
1331 }
1332