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