1 // license:BSD-3-Clause
2 // copyright-holders:Hans Ostermeyer, R. Belmont
3 /*
4  * apollo.c - Apollo DS3500 CPU Board
5  *
6  *  Created on: Jan 20, 2011
7  *      Author: Hans Ostermeyer
8  *
9  * Contains:
10  * - apollo_config.c - APOLLO DS3500 configuration
11  * - apollo_csr.c - APOLLO DS3500 CPU Control and Status registers
12  * - apollo_dma.c - APOLLO DS3500 DMA controllers
13  * - apollo_pic.c - APOLLO DS3500 PIC8259 controllers
14  * - apollo_ptm.c - APOLLO DS3500 Programmable Timer 6840
15  * - apollo_rtc.c - APOLLO DS3500 RTC MC146818
16  * - apollo_sio.c - APOLLO DS3500 SIO
17  * - apollo_sio2.c - APOLLO DS3500 SIO2
18  * - apollo_stdio.c - stdio terminal for mess
19  * - apollo_3c505.h - Apollo 3C505 Ethernet controller
20  *
21  * see also:
22  * - http://www.bitsavers.org/pdf/apollo/008778-03_DOMAIN_Series_3000_4000_Technical_Reference_Aug87.pdf
23  * - http://www.freescale.com/files/32bit/doc/inactive/MC68681UM.pdf
24  *
25  *  SIO usage:
26  *      SIO: ch A keyboard, ch B serial console
27  *      SIO2: modem/printer?
28  *
29  */
30 
31 #include "emu.h"
32 #include "includes/apollo.h"
33 
34 #include "bus/isa/omti8621.h"
35 #include "bus/isa/sc499.h"
36 #include "bus/isa/3c505.h"
37 
38 #include "softlist.h"
39 
40 #define APOLLO_IRQ_VECTOR 0xa0
41 #define APOLLO_IRQ_PTM 0
42 #define APOLLO_IRQ_SIO1 1
43 #define APOLLO_IRQ_PIC_SLAVE 3
44 #define APOLLO_IRQ_CTAPE 5
45 #define APOLLO_IRQ_FDC 6
46 #define APOLLO_IRQ_RTC 8 // DN3000 only
47 #define APOLLO_IRQ_SIO2 8 // DN3500
48 #define APOLLO_IRQ_ETH2 9
49 #define APOLLO_IRQ_ETH1 10
50 #define APOLLO_IRQ_DIAG 13
51 #define APOLLO_IRQ_WIN1 14
52 
53 #define APOLLO_DMA_ETH1 6
54 #define APOLLO_DMA_ETH2 3
55 
56 //##########################################################################
57 // machine/apollo_config.c - APOLLO DS3500 configuration
58 //##########################################################################
59 
60 #undef VERBOSE
61 #define VERBOSE 0
62 
63 static uint16_t config = 0;
64 
65 /***************************************************************************
66  apollo_config - check configuration setting
67  ***************************************************************************/
68 
apollo_config(int mask)69 int apollo_config(int mask)
70 {
71 	return config & mask ? 1 : 0;
72 }
73 
74 /***************************************************************************
75  Input Ports
76  ***************************************************************************/
77 
78 INPUT_PORTS_START( apollo_config )
79 	PORT_START( "apollo_config" )
80 		PORT_CONFNAME(APOLLO_CONF_SERVICE_MODE, 0x00, "Normal/Service" )
81 		PORT_CONFSETTING(0x00, "Service" )
82 		PORT_CONFSETTING(APOLLO_CONF_SERVICE_MODE, "Normal" )
83 
84 		PORT_CONFNAME(APOLLO_CONF_DISPLAY, APOLLO_CONF_8_PLANES, "Graphics Controller")
85 		PORT_CONFSETTING(APOLLO_CONF_8_PLANES, "8-Plane Color")
86 		PORT_CONFSETTING(APOLLO_CONF_4_PLANES, "4-Plane Color")
87 		PORT_CONFSETTING(APOLLO_CONF_MONO_15I, "15\" Monochrome")
88 //      PORT_CONFSETTING(APOLLO_CONF_MONO_19I, "19\" Monochrome")
89 
90 		PORT_CONFNAME(APOLLO_CONF_GERMAN_KBD, 0x00, "German Keyboard")
91 		PORT_CONFSETTING(0x00, DEF_STR ( Off ) )
92 		PORT_CONFSETTING(APOLLO_CONF_GERMAN_KBD, DEF_STR ( On ) )
93 
94 		PORT_CONFNAME(APOLLO_CONF_30_YEARS_AGO, APOLLO_CONF_30_YEARS_AGO, "30 Years Ago ...")
95 		PORT_CONFSETTING(0x00, DEF_STR ( Off ) )
96 		PORT_CONFSETTING(APOLLO_CONF_30_YEARS_AGO, DEF_STR ( On ) )
97 
98 		PORT_CONFNAME(APOLLO_CONF_25_YEARS_AGO, APOLLO_CONF_25_YEARS_AGO, "25 Years Ago ...")
99 		PORT_CONFSETTING(0x00, DEF_STR ( Off ) )
100 		PORT_CONFSETTING(APOLLO_CONF_25_YEARS_AGO, DEF_STR ( On ) )
101 
102 		PORT_CONFNAME(APOLLO_CONF_NODE_ID, APOLLO_CONF_NODE_ID, "Node ID from Disk")
103 		PORT_CONFSETTING(0x00, DEF_STR ( Off ) )
104 		PORT_CONFSETTING(APOLLO_CONF_NODE_ID, DEF_STR ( On ) )
105 
106 //      PORT_CONFNAME(APOLLO_CONF_IDLE_SLEEP, 0x00, "Idle Sleep")
107 //      PORT_CONFSETTING(0x00, DEF_STR ( Off ) )
108 //      PORT_CONFSETTING(APOLLO_CONF_IDLE_SLEEP, DEF_STR ( On ) )
109 #ifdef APOLLO_XXL
110 		PORT_CONFNAME(APOLLO_CONF_TRAP_TRACE, 0x00, "Trap Trace")
111 		PORT_CONFSETTING(0x00, DEF_STR ( Off ) )
112 		PORT_CONFSETTING(APOLLO_CONF_TRAP_TRACE, DEF_STR ( On ) )
113 
114 		PORT_CONFNAME(APOLLO_CONF_FPU_TRACE, 0x00, "FPU Trace")
115 		PORT_CONFSETTING(0x00, DEF_STR ( Off ) )
116 		PORT_CONFSETTING(APOLLO_CONF_FPU_TRACE, DEF_STR ( On ) )
117 
118 		PORT_CONFNAME(APOLLO_CONF_DISK_TRACE, 0x00, "Disk Trace")
119 		PORT_CONFSETTING(0x00, DEF_STR ( Off ) )
120 		PORT_CONFSETTING(APOLLO_CONF_DISK_TRACE, DEF_STR ( On ) )
121 
122 		PORT_CONFNAME(APOLLO_CONF_NET_TRACE, 0x00, "Network Trace")
123 		PORT_CONFSETTING(0x00, DEF_STR ( Off ) )
124 		PORT_CONFSETTING(APOLLO_CONF_NET_TRACE, DEF_STR ( On ) )
125 #endif
126 INPUT_PORTS_END
127 
128 class apollo_config_device : public device_t
129 {
130 public:
131 	apollo_config_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
132 protected:
133 	// device-level overrides
134 	virtual void device_start() override;
135 	virtual void device_reset() override;
136 private:
137 	// internal state
138 };
139 
140 DEFINE_DEVICE_TYPE(APOLLO_CONF, apollo_config_device, "apollo_config", "Apollo Configuration")
141 
apollo_config_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)142 apollo_config_device::apollo_config_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
143 	: device_t(mconfig, APOLLO_CONF, tag, owner, clock)
144 {
145 }
146 
147 //-------------------------------------------------
148 //  device_start - device-specific startup
149 //-------------------------------------------------
150 
device_start()151 void apollo_config_device::device_start()
152 {
153 	MLOG1(("start apollo_config"));
154 }
155 
156 //-------------------------------------------------
157 //  device_reset - device-specific reset
158 //-------------------------------------------------
159 
device_reset()160 void apollo_config_device::device_reset()
161 {
162 	MLOG1(("reset apollo_config"));
163 	// load configuration
164 	config = machine().root_device().ioport("apollo_config")->read();
165 }
166 
167 
168 
169 //##########################################################################
170 // machine/apollo_csr.c - APOLLO DS3500 CPU Control and Status registers
171 //##########################################################################
172 
173 #undef VERBOSE
174 #define VERBOSE 0
175 
176 #define CPU_CONTROL_REGISTER_ADDRESS 0x010100
177 
178 static uint16_t cpu_status_register = APOLLO_CSR_SR_BIT15 | APOLLO_CSR_SR_SERVICE;
179 static uint16_t cpu_control_register = 0x0000;
180 
181 /*-------------------------------------------------
182   apollo_csr_get/set_servicemode
183  -------------------------------------------------*/
184 
185 /*static int apollo_csr_get_servicemode()
186 {
187     return cpu_status_register & APOLLO_CSR_SR_SERVICE ? 0 : 1;
188 }*/
189 
apollo_csr_set_servicemode(int mode)190 static void apollo_csr_set_servicemode(int mode)
191 {
192 	apollo_csr_set_status_register(1, mode ? APOLLO_CSR_SR_SERVICE : 0);
193 }
194 
apollo_csr_get_control_register(void)195 uint16_t apollo_csr_get_control_register(void)
196 {
197 	return cpu_control_register;
198 }
199 
apollo_csr_get_status_register(void)200 uint16_t apollo_csr_get_status_register(void)
201 {
202 	return cpu_status_register;
203 }
204 
apollo_csr_set_status_register(uint16_t mask,uint16_t data)205 void apollo_csr_set_status_register(uint16_t mask, uint16_t data)
206 {
207 	uint16_t new_value = (cpu_status_register & ~mask) | (data & mask);
208 
209 	if (new_value != cpu_status_register)
210 	{
211 		cpu_status_register = new_value;
212 		//LOG1(("#### setting CPU Status Register with data=%04x & %04x to %04x", data, mask, cpu_status_register));
213 	}
214 }
215 
216 /*-------------------------------------------------
217  DN3000/DN3500 CPU Status Register at 0x8000/0x10000
218  -------------------------------------------------*/
219 
apollo_csr_status_register_w(offs_t offset,uint16_t data,uint16_t mem_mask)220 void apollo_state::apollo_csr_status_register_w(offs_t offset, uint16_t data, uint16_t mem_mask){
221 	// To clear bus timeouts or parity conditions from status register,
222 	// write to the status register. This register is readonly.
223 	// in DN3500 bit 15 is always set (undocumented !?)
224 	cpu_status_register &= (APOLLO_CSR_SR_BIT15 | APOLLO_CSR_SR_FP_TRAP | APOLLO_CSR_SR_SERVICE);
225 	SLOG1(("writing CPU Status Register at offset %X = %04x & %04x (%04x)", offset, data, mem_mask, cpu_status_register));
226 }
227 
apollo_csr_status_register_r(offs_t offset,uint16_t mem_mask)228 uint16_t apollo_state::apollo_csr_status_register_r(offs_t offset, uint16_t mem_mask){
229 	SLOG2(("reading CPU Status Register at offset %X = %04x & %04x", offset, cpu_status_register, mem_mask));
230 	return cpu_status_register & mem_mask;
231 }
232 
233 /*-------------------------------------------------
234  DN3000/DN3500 CPU Control Register at 0x8100/0x10100
235  -------------------------------------------------*/
236 
apollo_csr_control_register_w(offs_t offset,uint16_t data,uint16_t mem_mask)237 void apollo_state::apollo_csr_control_register_w(offs_t offset, uint16_t data, uint16_t mem_mask)
238 {
239 	int leds;
240 
241 	if ((mem_mask & APOLLO_CSR_CR_FPU_TRAP_ENABLE) == 0)
242 	{
243 		// FPU Trap enable not involved
244 	}
245 	else if (((data ^ cpu_control_register) & APOLLO_CSR_CR_FPU_TRAP_ENABLE) == 0)
246 	{
247 		// FPU Trap enable remains unchanged
248 	}
249 	else if ((data & APOLLO_CSR_CR_FPU_TRAP_ENABLE) == 0)
250 	{
251 		// enable FPU (i.e. FPU opcodes in CPU)
252 		apollo_set_cpu_has_fpu(m_maincpu, 1);
253 	}
254 	else
255 	{
256 		// disable FPU (i.e. FPU opcodes in CPU)
257 		apollo_set_cpu_has_fpu(m_maincpu, 0);
258 
259 		if (!apollo_is_dn3000() && !m_maincpu->get_pmmu_enable())
260 		{
261 			// hack: set APOLLO_CSR_SR_FP_TRAP in cpu status register for /sau7/self_test
262 			// APOLLO_CSR_SR_FP_TRAP in status register should be set by next fmove instruction
263 			cpu_status_register |= APOLLO_CSR_SR_FP_TRAP;
264 		}
265 	}
266 
267 	COMBINE_DATA(&cpu_control_register);
268 
269 	for (int i = 0; i < 4; i++)
270 		m_internal_leds[i] = BIT(cpu_control_register, 15 - i);
271 	for (int i = 0; i < 4; i++)
272 		m_external_leds[i] = BIT(cpu_control_register, 11 - i);
273 
274 	leds = ((cpu_control_register >> 8) & 0xff) ^ 0xff;
275 
276 	SLOG1(("writing CPU Control Register at offset %X = %04x & %04x (%04x - %d%d%d%d %d%d%d%d)",
277 					offset, data, mem_mask, cpu_control_register,
278 					(leds >> 3) & 1,(leds >> 2) & 1, (leds >> 1) & 1, (leds >> 0) & 1,
279 					(leds >> 7) & 1,(leds >> 6) & 1, (leds >> 5) & 1, (leds >> 4) & 1 ));
280 
281 	if (data & APOLLO_CSR_CR_RESET_DEVICES)
282 	{
283 		// FIXME: reset all devices (but not SIO lines!)
284 	}
285 }
286 
apollo_csr_control_register_r(offs_t offset,uint16_t mem_mask)287 uint16_t apollo_state::apollo_csr_control_register_r(offs_t offset, uint16_t mem_mask)
288 {
289 	SLOG1(("reading CPU Control Register at offset %X = %04x & %04x", offset, cpu_control_register, mem_mask));
290 	return cpu_control_register & mem_mask;
291 }
292 
293 //##########################################################################
294 // machine/apollo_dma.c - APOLLO DS3500 DMA
295 //##########################################################################
296 
297 #undef VERBOSE
298 #define VERBOSE 0
299 
300 static uint16_t address_translation_map[0x400];
301 
302 static uint16_t dma_page_register[16] =
303 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
304 
305 static const uint8_t channel2page_register[8] = { 7, 3, 1, 2, 0, 11, 9, 10};
306 
307 static uint8_t dn3000_dma_channel1 = 1; // 1 = memory/ctape, 2 = floppy dma channel
308 static uint8_t dn3000_dma_channel2 = 5; // 5 = memory dma channel
309 
310 /*-------------------------------------------------
311  DN3000/DN3500 DMA Controller 1 at 0x9000/0x10c00
312  -------------------------------------------------*/
313 
apollo_dma_1_w(offs_t offset,uint8_t data)314 void apollo_state::apollo_dma_1_w(offs_t offset, uint8_t data){
315 	SLOG1(("apollo_dma_1_w: writing DMA Controller 1 at offset %02x = %02x", offset, data));
316 	m_dma8237_1->write(offset, data);
317 }
318 
apollo_dma_1_r(offs_t offset)319 uint8_t apollo_state::apollo_dma_1_r(offs_t offset){
320 	uint8_t data = m_dma8237_1->read(offset);
321 	SLOG1(("apollo_dma_1_r: reading DMA Controller 1 at offset %02x = %02x", offset, data));
322 	return data;
323 }
324 
325 /*-------------------------------------------------
326  DN3000/DN3500 DMA Controller 2 at 0x9100/0x10d00
327  -------------------------------------------------*/
328 
apollo_dma_2_w(offs_t offset,uint8_t data)329 void apollo_state::apollo_dma_2_w(offs_t offset, uint8_t data){
330 	SLOG1(("apollo_dma_2_w: writing DMA Controller 2 at offset %02x = %02x", offset/2, data));
331 	m_dma8237_2->write(offset / 2, data);
332 }
333 
apollo_dma_2_r(offs_t offset)334 uint8_t apollo_state::apollo_dma_2_r(offs_t offset){
335 	// Nasty hack (13-06-15 - ost):
336 	// MD self_test will test wrong DMA register and
337 	// mem-to-mem DMA in am9517a.c is often starting much too late (for MD self_test)
338 	// (8237dma.c was always fast enough to omit these problems)
339 	if (offset == 8)
340 	{
341 		switch (m_maincpu->pcbase())
342 		{
343 		case 0x00102e22: // DN3000
344 		case 0x01002f3c: // DN3500
345 		case 0x010029a6: // DN5500
346 			offset = 16;
347 			break;
348 		}
349 	}
350 	uint8_t data = m_dma8237_2->read(offset / 2);
351 	SLOG1(("apollo_dma_2_r: reading DMA Controller 2 at offset %02x = %02x", offset/2, data));
352 	return data;
353 }
354 
355 /***************************************************************************
356  DN3000 DMA Page Register at 0x9200
357  ***************************************************************************/
358 
apollo_dma_page_register_w(offs_t offset,uint8_t data)359 void apollo_state::apollo_dma_page_register_w(offs_t offset, uint8_t data){
360 	dma_page_register[offset & 0x0f] = data;
361 	SLOG1(("writing DMA Page Register at offset %02x = %02x", offset,  data));
362 }
363 
apollo_dma_page_register_r(offs_t offset)364 uint8_t apollo_state::apollo_dma_page_register_r(offs_t offset){
365 	uint8_t data = dma_page_register[offset & 0x0f];
366 	SLOG1(("reading DMA Page Register at offset %02x = %02x", offset, data));
367 	return data;
368 }
369 
370 /*-------------------------------------------------
371  DN3500 Address Translation Map at 0x017000
372  -------------------------------------------------*/
373 
apollo_address_translation_map_w(offs_t offset,uint16_t data)374 void apollo_state::apollo_address_translation_map_w(offs_t offset, uint16_t data){
375 	address_translation_map[offset & 0x3ff] = data;
376 	SLOG2(("writing Address Translation Map at offset %02x = %04x", offset, data));
377 }
378 
apollo_address_translation_map_r(offs_t offset)379 uint16_t apollo_state::apollo_address_translation_map_r(offs_t offset){
380 	uint16_t data = address_translation_map[offset & 0x3ff];
381 	SLOG2(("reading Address Translation Map at offset %02x = %04x", offset, data));
382 	return data;
383 }
384 
apollo_dma_read_byte(offs_t offset)385 uint8_t apollo_state::apollo_dma_read_byte(offs_t offset){
386 	uint8_t data;
387 	offs_t page_offset;
388 
389 	if (apollo_is_dn3000()) {
390 		page_offset = dma_page_register[channel2page_register[dn3000_dma_channel1]] << 16;
391 	} else {
392 		// FIXME: address_translation_map[0x200] ?
393 		page_offset = (((offs_t) address_translation_map[0x200 + (offset >> 10)]) << 10) & 0x7FFFFC00;
394 		offset &= 0x3ff;
395 	}
396 
397 	data = m_maincpu->space(AS_PROGRAM).read_byte(page_offset + offset);
398 
399 	if (VERBOSE > 1 || offset < 4 || (offset & 0xff) == 0 || (offset & 0xff) == 0xff)
400 	{
401 		SLOG1(("dma read byte at offset %x+%03x = %02x", page_offset, offset, data));
402 	}
403 //  logerror(" %02x", data);
404 	return data;
405 }
406 
apollo_dma_write_byte(offs_t offset,uint8_t data)407 void apollo_state::apollo_dma_write_byte(offs_t offset, uint8_t data){
408 	offs_t page_offset;
409 	if (apollo_is_dn3000()) {
410 		page_offset = dma_page_register[channel2page_register[dn3000_dma_channel1]] << 16;
411 	} else {
412 		// FIXME: address_translation_map[0x200] ?
413 		page_offset = (((offs_t) address_translation_map[0x200 + (offset >> 10)]) << 10) & 0x7FFFFC00;
414 		offset &= 0x3ff;
415 	}
416 	// FIXME: MSB not available, writing only LSB
417 	m_maincpu->space(AS_PROGRAM).write_byte(page_offset + offset, data);
418 
419 	if (VERBOSE > 1 || offset < 4 || (offset & 0xff) == 0 || (offset & 0xff) == 0xff)
420 	{
421 		SLOG1(("dma write byte at offset %x+%03x = %02x", page_offset, offset , data));
422 	}
423 //  logerror(" %02x", data);
424 }
425 
apollo_dma_read_word(offs_t offset)426 uint8_t apollo_state::apollo_dma_read_word(offs_t offset){
427 	uint16_t data;
428 	offs_t page_offset;
429 
430 	if (apollo_is_dn3000()) {
431 		page_offset = dma_page_register[channel2page_register[dn3000_dma_channel2]] << 16;
432 		page_offset &= 0xfffe0000;
433 		offset <<= 1;
434 	} else {
435 		// FIXME: address_translation_map[0x200] ?
436 		page_offset = (((offs_t) address_translation_map[0x200 + (offset >> 9)]) << 10) & 0x7FFFFC00;
437 		offset = (offset << 1) & 0x3ff;
438 	}
439 
440 	data = m_maincpu->space(AS_PROGRAM).read_byte(page_offset + offset);
441 
442 	SLOG1(("dma read word at offset %x+%03x = %04x", page_offset, offset , data));
443 	// FIXME: MSB will get lost
444 	return data;
445 }
446 
apollo_dma_write_word(offs_t offset,uint8_t data)447 void apollo_state::apollo_dma_write_word(offs_t offset, uint8_t data){
448 	offs_t page_offset;
449 
450 	SLOG1(("dma write word at offset %x = %02x", offset, data));
451 
452 	if (apollo_is_dn3000()) {
453 		page_offset = dma_page_register[channel2page_register[dn3000_dma_channel2]] << 16;
454 		page_offset &= 0xfffe0000;
455 		offset <<= 1;
456 	} else {
457 		// FIXME: address_translation_map[0x200] ?
458 		page_offset
459 				= (((offs_t) address_translation_map[0x200 + (offset >> 9)])
460 						<< 10) & 0x7FFFFC00;
461 		offset = (offset << 1) & 0x3ff;
462 	}
463 
464 	m_maincpu->space(AS_PROGRAM).write_byte(page_offset + offset, data);
465 	SLOG1(("dma write word at offset %x+%03x = %02x", page_offset, offset, data));
466 }
467 
WRITE_LINE_MEMBER(apollo_state::apollo_dma8237_out_eop)468 WRITE_LINE_MEMBER(apollo_state::apollo_dma8237_out_eop ) {
469 	CLOG1(("dma out eop state %02x", state));
470 	m_cur_eop = state == ASSERT_LINE;
471 	if(m_dma_channel != -1)
472 		m_isa->eop_w(m_dma_channel, m_cur_eop ? ASSERT_LINE : CLEAR_LINE );
473 }
474 
WRITE_LINE_MEMBER(apollo_state::apollo_dma_1_hrq_changed)475 WRITE_LINE_MEMBER(apollo_state::apollo_dma_1_hrq_changed ) {
476 	CLOG2(("dma 1 hrq changed state %02x", state));
477 	m_dma8237_1->dreq0_w(state);
478 
479 	/* Assert HLDA */
480 	m_dma8237_1->hack_w(state);
481 
482 	// cascade mode?
483 	// i8237_hlda_w(get_device_dma8237_2(device), state);
484 }
485 
WRITE_LINE_MEMBER(apollo_state::apollo_dma_2_hrq_changed)486 WRITE_LINE_MEMBER(apollo_state::apollo_dma_2_hrq_changed ) {
487 	CLOG2(("dma 2 hrq changed state %02x", state));
488 	m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
489 
490 	/* Assert HLDA */
491 	m_dma8237_2->hack_w(state);
492 }
493 
pc_dma8237_0_dack_r()494 uint8_t apollo_state::pc_dma8237_0_dack_r() { return m_isa->dack_r(0); }
pc_dma8237_1_dack_r()495 uint8_t apollo_state::pc_dma8237_1_dack_r() { return m_isa->dack_r(1); }
pc_dma8237_2_dack_r()496 uint8_t apollo_state::pc_dma8237_2_dack_r() { return m_isa->dack_r(2); }
pc_dma8237_3_dack_r()497 uint8_t apollo_state::pc_dma8237_3_dack_r() { return m_isa->dack_r(3); }
pc_dma8237_5_dack_r()498 uint8_t apollo_state::pc_dma8237_5_dack_r() { return m_isa->dack_r(5); }
pc_dma8237_6_dack_r()499 uint8_t apollo_state::pc_dma8237_6_dack_r() { return m_isa->dack_r(6); }
pc_dma8237_7_dack_r()500 uint8_t apollo_state::pc_dma8237_7_dack_r() { return m_isa->dack_r(7); }
501 
pc_dma8237_0_dack_w(uint8_t data)502 void apollo_state::pc_dma8237_0_dack_w(uint8_t data){ m_isa->dack_w(0, data); }
pc_dma8237_1_dack_w(uint8_t data)503 void apollo_state::pc_dma8237_1_dack_w(uint8_t data){ m_isa->dack_w(1, data); }
pc_dma8237_2_dack_w(uint8_t data)504 void apollo_state::pc_dma8237_2_dack_w(uint8_t data){ m_isa->dack_w(2, data); }
pc_dma8237_3_dack_w(uint8_t data)505 void apollo_state::pc_dma8237_3_dack_w(uint8_t data){ m_isa->dack_w(3, data); }
pc_dma8237_5_dack_w(uint8_t data)506 void apollo_state::pc_dma8237_5_dack_w(uint8_t data){ m_isa->dack_w(5, data); }
pc_dma8237_6_dack_w(uint8_t data)507 void apollo_state::pc_dma8237_6_dack_w(uint8_t data){ m_isa->dack_w(6, data); }
pc_dma8237_7_dack_w(uint8_t data)508 void apollo_state::pc_dma8237_7_dack_w(uint8_t data){ m_isa->dack_w(7, data); }
509 
WRITE_LINE_MEMBER(apollo_state::pc_dack0_w)510 WRITE_LINE_MEMBER( apollo_state::pc_dack0_w ) { select_dma_channel(0, state); }
WRITE_LINE_MEMBER(apollo_state::pc_dack1_w)511 WRITE_LINE_MEMBER( apollo_state::pc_dack1_w ) { select_dma_channel(1, state); }
WRITE_LINE_MEMBER(apollo_state::pc_dack2_w)512 WRITE_LINE_MEMBER( apollo_state::pc_dack2_w ) { select_dma_channel(2, state); }
WRITE_LINE_MEMBER(apollo_state::pc_dack3_w)513 WRITE_LINE_MEMBER( apollo_state::pc_dack3_w ) { select_dma_channel(3, state); }
WRITE_LINE_MEMBER(apollo_state::pc_dack4_w)514 WRITE_LINE_MEMBER( apollo_state::pc_dack4_w ) { m_dma8237_1->hack_w( state ? 0 : 1); } // it's inverted
WRITE_LINE_MEMBER(apollo_state::pc_dack5_w)515 WRITE_LINE_MEMBER( apollo_state::pc_dack5_w ) { select_dma_channel(5, state); }
WRITE_LINE_MEMBER(apollo_state::pc_dack6_w)516 WRITE_LINE_MEMBER( apollo_state::pc_dack6_w ) { select_dma_channel(6, state); }
WRITE_LINE_MEMBER(apollo_state::pc_dack7_w)517 WRITE_LINE_MEMBER( apollo_state::pc_dack7_w ) { select_dma_channel(7, state); }
518 
select_dma_channel(int channel,bool state)519 void apollo_state::select_dma_channel(int channel, bool state)
520 {
521 	if(!state) {
522 		m_dma_channel = channel;
523 		if(m_cur_eop)
524 			m_isa->eop_w(channel, ASSERT_LINE );
525 
526 	} else if(m_dma_channel == channel) {
527 		m_dma_channel = -1;
528 		if(m_cur_eop)
529 			m_isa->eop_w(channel, CLEAR_LINE );
530 	}
531 }
532 
533 //##########################################################################
534 // machine/apollo_pic.c - APOLLO DS3500 PIC 8259 controllers
535 //##########################################################################
536 
537 #undef VERBOSE
538 #define VERBOSE 0
539 
apollo_pic_set_irq_line(int irq,int state)540 void apollo_state::apollo_pic_set_irq_line(int irq, int state)
541 {
542 	switch (irq) {
543 	case 0: m_pic8259_master->ir0_w(state); break;
544 	case 1: m_pic8259_master->ir1_w(state); break;
545 	case 2: m_pic8259_master->ir2_w(state); break;
546 	case 3: m_pic8259_master->ir3_w(state); break;
547 	case 4: m_pic8259_master->ir4_w(state); break;
548 	case 5: m_pic8259_master->ir5_w(state); break;
549 	case 6: m_pic8259_master->ir6_w(state); break;
550 	case 7: m_pic8259_master->ir7_w(state); break;
551 
552 	case 8:  m_pic8259_slave->ir0_w(state); break;
553 	case 9:  m_pic8259_slave->ir1_w(state); break;
554 	case 10: m_pic8259_slave->ir2_w(state); break;
555 	case 11: m_pic8259_slave->ir3_w(state); break;
556 	case 12: m_pic8259_slave->ir4_w(state); break;
557 	case 13: m_pic8259_slave->ir5_w(state); break;
558 	case 14: m_pic8259_slave->ir6_w(state); break;
559 	case 15: m_pic8259_slave->ir7_w(state); break;
560 	}
561 }
562 
apollo_pic_get_vector()563 u16 apollo_state::apollo_pic_get_vector()
564 {
565 	uint32_t vector = m_pic8259_master->acknowledge();
566 	if ((vector & 0x0f) == APOLLO_IRQ_PIC_SLAVE) {
567 		vector = m_pic8259_slave->acknowledge();
568 	}
569 
570 	if (!machine().side_effects_disabled()) {
571 		// don't log ptm interrupts
572 		if (vector != APOLLO_IRQ_VECTOR+APOLLO_IRQ_PTM) {
573 			MLOG1(("apollo_pic_acknowledge: irq=%d vector=%x", vector & 0x0f, vector));
574 		}
575 
576 		if (apollo_is_dn3000()) {
577 			apollo_csr_set_status_register(APOLLO_CSR_SR_INTERRUPT_PENDING, 0);
578 		} else {
579 			// clear bit Interrupt Pending in Cache Status Register
580 			apollo_set_cache_status_register(this,0x10, 0x00);
581 		}
582 	}
583 	return vector;
584 }
585 
586 /*************************************************************
587  * pic8259 configuration
588  *************************************************************/
589 
apollo_pic8259_get_slave_ack(offs_t offset)590 uint8_t apollo_state::apollo_pic8259_get_slave_ack(offs_t offset)
591 {
592 		MLOG1(("apollo_pic8259_get_slave_ack: offset=%x", offset));
593 
594 		return offset == 3 ? m_pic8259_slave->acknowledge() : 0;
595 }
596 
WRITE_LINE_MEMBER(apollo_state::apollo_pic8259_master_set_int_line)597 WRITE_LINE_MEMBER( apollo_state::apollo_pic8259_master_set_int_line ) {
598 	static int interrupt_line = -1;
599 	if (state != interrupt_line) {
600 		device_t *device = m_pic8259_master;
601 		DLOG1(("apollo_pic8259_master_set_int_line: %x", state));
602 	}
603 	interrupt_line = state;
604 
605 	if (apollo_is_dn3000()) {
606 		apollo_csr_set_status_register(APOLLO_CSR_SR_INTERRUPT_PENDING,
607 				state ? APOLLO_CSR_SR_INTERRUPT_PENDING : 0);
608 	} else {
609 		// set bit Interrupt Pending in Cache Status Register
610 		apollo_set_cache_status_register(this,0x10, state ? 0x10 : 0x00);
611 	}
612 
613 	m_maincpu->set_input_line(M68K_IRQ_6,state ? ASSERT_LINE : CLEAR_LINE);
614 }
615 
WRITE_LINE_MEMBER(apollo_state::apollo_pic8259_slave_set_int_line)616 WRITE_LINE_MEMBER( apollo_state::apollo_pic8259_slave_set_int_line ) {
617 	static int interrupt_line = -1;
618 	if (state != interrupt_line) {
619 		device_t *device = m_pic8259_slave;
620 		DLOG1(("apollo_pic8259_slave_set_int_line: %x", state));
621 		interrupt_line = state;
622 		apollo_pic_set_irq_line(3, state);
623 	}
624 }
625 
626 //##########################################################################
627 // machine/apollo_ptm.c - APOLLO DS3500 Programmable Timer 6840
628 //##########################################################################
629 
630 #undef VERBOSE
631 #define VERBOSE 0
632 
WRITE_LINE_MEMBER(apollo_state::apollo_ptm_timer_tick)633 WRITE_LINE_MEMBER(apollo_state::apollo_ptm_timer_tick)
634 {
635 	if ((state) && (m_ptm->started()))
636 	{
637 		ptm_counter++;
638 		m_ptm->set_c1( 1);
639 		m_ptm->set_c1( 0);
640 		m_ptm->set_c2(ptm_counter & 1);
641 
642 		if ((ptm_counter & 1) == 0)
643 		{
644 			m_ptm->set_c3((ptm_counter >> 1) & 1);
645 		}
646 	}
647 }
648 
WRITE_LINE_MEMBER(apollo_state::apollo_ptm_irq_function)649 WRITE_LINE_MEMBER(apollo_state::apollo_ptm_irq_function)
650 {
651 	apollo_pic_set_irq_line(APOLLO_IRQ_PTM, state);
652 }
653 
654 //  Timer 1's input is a 250-kHz (4-microsecond period) signal.
655 //  Timer 2's input is a 125-kHz (8-microsecond period) signal.
656 //  Timer 3's input is a 62.5-kHz (16-microsecond period) signal.
657 //  The Timer 3 input may be prescaled to make the effective input signal have a 128-microsecond period.
658 
659 
660 //##########################################################################
661 // machine/apollo_rtc.c - APOLLO DS3500 RTC MC146818
662 //##########################################################################
663 
664 #undef VERBOSE
665 #define VERBOSE 0
666 
667 /***************************************************************************
668  DN3000/DN3500 Realtime Calendar MC146818 at 0x8900/0x10900
669  ***************************************************************************/
670 
apollo_rtc_w(offs_t offset,uint8_t data)671 void apollo_state::apollo_rtc_w(offs_t offset, uint8_t data)
672 {
673 	m_rtc->write_direct(offset, data);
674 	if (offset >= 0x0b && offset <= 0x0c)
675 	{
676 		SLOG2(("writing MC146818 at offset %02x = %02x", offset, data));
677 	}
678 }
679 
apollo_rtc_r(offs_t offset)680 uint8_t apollo_state::apollo_rtc_r(offs_t offset)
681 {
682 	uint8_t data;
683 	data = m_rtc->read_direct(offset);
684 	if (offset >= 0x0b && offset <= 0x0c)
685 	{
686 		SLOG2(("reading MC146818 at offset %02x = %02x", offset, data));
687 	}
688 	return data;
689 }
690 
WRITE_LINE_MEMBER(apollo_state::apollo_rtc_irq_function)691 WRITE_LINE_MEMBER(apollo_state::apollo_rtc_irq_function)
692 {
693 	apollo_pic_set_irq_line(APOLLO_IRQ_RTC, state);
694 }
695 
696 //##########################################################################
697 // machine/apollo_sio.c - DN3000/DS3500 SIO at 0x8400/0x10400
698 //##########################################################################
699 
700 #undef VERBOSE
701 #define VERBOSE 0
702 
apollo_sio(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)703 apollo_sio::apollo_sio(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
704 	duart_base_device(mconfig, APOLLO_SIO, tag, owner, clock),
705 	m_csrb(0)
706 {
707 }
708 
device_reset()709 void apollo_sio::device_reset()
710 {
711 	uint8_t input_data = apollo_get_ram_config_byte();
712 	ip0_w((input_data & 0x01) ? ASSERT_LINE : CLEAR_LINE);
713 	ip1_w((input_data & 0x02) ? ASSERT_LINE : CLEAR_LINE);
714 	ip2_w((input_data & 0x04) ? ASSERT_LINE : CLEAR_LINE);
715 	ip3_w((input_data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
716 	ip4_w((input_data & 0x10) ? ASSERT_LINE : CLEAR_LINE);
717 	ip5_w((input_data & 0x20) ? ASSERT_LINE : CLEAR_LINE);
718 	ip6_w((input_data & 0x40) ? ASSERT_LINE : CLEAR_LINE);
719 }
720 
read(offs_t offset)721 uint8_t apollo_sio::read(offs_t offset)
722 {
723 	static int last_read8_offset[2] = { -1, -1 };
724 	static int last_read8_value[2] = { -1, -1 };
725 
726 	static const char * const duart68681_reg_read_names[0x10] = { "MRA", "SRA",
727 			"BRG Test", "RHRA", "IPCR", "ISR", "CTU", "CTL", "MRB", "SRB",
728 			"1X/16X Test", "RHRB", "IVR", "Input Ports", "Start Counter",
729 			"Stop Counter" };
730 
731 	int data = duart_base_device::read(offset/2);
732 
733 	switch (offset / 2)
734 	{
735 	case 0x0b: /* RHRB */
736 		if (m_csrb == 0x77 && data == 0xfe)
737 		{
738 			// special fix for the MD ROM baudrate recognition
739 			// fix data only if CR is entered while baudrate is set to 2000 Baud
740 
741 			// Receive and transmit clock in diserial.c are not precise enough
742 			// to support the baudrate recognition done in the Apollo MD ROM
743 			// use 0xff instead of 0xfe to set the baudrate recognition for 9600 Bd
744 			// (to prevent that the MD selftest or SK command will hang in Service mode)
745 			data = 0xff;
746 		}
747 		break;
748 	}
749 
750 	// omit logging if sio is being polled from the boot rom
751 	if ((offset != last_read8_offset[1] || data != last_read8_value[1]) && \
752 		(offset != last_read8_offset[0] || data != last_read8_value[0]))
753 	{
754 		last_read8_offset[0] = last_read8_offset[1];
755 		last_read8_value[0] = last_read8_value[1];
756 		last_read8_offset[1] = offset;
757 		last_read8_value[1] = data;
758 		CLOG2(("reading MC2681 reg %02x (%s) returned %02x",
759 				offset, duart68681_reg_read_names[(offset/2) & 15], data));
760 	}
761 
762 	return data;
763 }
764 
write(offs_t offset,uint8_t data)765 void apollo_sio::write(offs_t offset, uint8_t data)
766 {
767 	static const char * const duart68681_reg_write_names[0x10] = { "MRA",
768 			"CSRA", "CRA", "THRA", "ACR", "IMR", "CRUR", "CTLR", "MRB", "CSRB",
769 			"CRB", "THRB", "IVR", "OPCR", "Set OP Bits", "Reset OP Bits" };
770 
771 	CLOG2(("writing MC2681 reg %02x (%s) with %02x",
772 			offset, duart68681_reg_write_names[(offset/2) & 15], data));
773 
774 	switch (offset / 2) {
775 	case 0x09: /* CSRB */
776 		// remember CSRB to handle MD selftest or SK command
777 		m_csrb = data;
778 		break;
779 #if 1
780 	case 0x0b: /* THRB */
781 		// tee output of SIO1 to stdout
782 		// sad: ceterm will get confused from '\r'
783 		if (apollo_is_dsp3x00() && data != '\r') ::putchar(data);
784 		break;
785 #endif
786 	}
787 	duart_base_device::write(offset/2, data);
788 }
789 
790 // device type definition
791 DEFINE_DEVICE_TYPE(APOLLO_SIO, apollo_sio, "apollo_sio", "DN3000/DS3500 SIO (MC2681)")
792 
WRITE_LINE_MEMBER(apollo_state::sio_irq_handler)793 WRITE_LINE_MEMBER(apollo_state::sio_irq_handler)
794 {
795 	apollo_pic_set_irq_line(APOLLO_IRQ_SIO1, state);
796 }
797 
sio_output(uint8_t data)798 void apollo_state::sio_output(uint8_t data)
799 {
800 //  CLOG2(("apollo_sio - sio_output %02x", data));
801 
802 	if ((data & 0x80) != (sio_output_data & 0x80))
803 	{
804 		apollo_pic_set_irq_line(APOLLO_IRQ_DIAG, (data & 0x80) ? 1 : 0);
805 	}
806 
807 	// The counter/timer on the SIO chip is used for the RAM refresh count.
808 	// This is set up in the timer mode to produce a square wave output on output OP3.
809 	// The period of the output is 15 microseconds.
810 
811 	if ((data & 0x08) != (sio_output_data & 0x08))
812 	{
813 		m_sio->ip0_w((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
814 	}
815 
816 	sio_output_data = data;
817 }
818 
819 //##########################################################################
820 // machine/apollo_sio2.c - APOLLO DS3500 SIO2
821 //##########################################################################
822 
WRITE_LINE_MEMBER(apollo_state::sio2_irq_handler)823 WRITE_LINE_MEMBER(apollo_state::sio2_irq_handler)
824 {
825 	apollo_pic_set_irq_line(APOLLO_IRQ_SIO2, state);
826 }
827 
828 //##########################################################################
829 // machine/apollo_ni.c - APOLLO DS3500 node ID
830 //##########################################################################
831 
832 #undef VERBOSE
833 #define VERBOSE 0
834 
835 #define DEFAULT_NODE_ID 0x12345
836 
837 /***************************************************************************
838  IMPLEMENTATION
839  ***************************************************************************/
840 
841 /*** Apollo Node ID device ***/
842 
843 // device type definition
844 DEFINE_DEVICE_TYPE(APOLLO_NI, apollo_ni, "node_id", "Apollo Node ID")
845 
846 //-------------------------------------------------
847 //  apollo_ni - constructor
848 //-------------------------------------------------
849 
apollo_ni(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)850 apollo_ni::apollo_ni(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
851 	device_t(mconfig, APOLLO_NI, tag, owner, clock),
852 	device_image_interface(mconfig, *this),
853 	m_wdc(*this, ":isa1:wdc")
854 {
855 }
856 
857 //-------------------------------------------------
858 //  apollo_ni - destructor
859 //-------------------------------------------------
860 
~apollo_ni()861 apollo_ni::~apollo_ni()
862 {
863 }
864 
865 //-------------------------------------------------
866 //  device_start - device-specific startup
867 //-------------------------------------------------
868 
device_start()869 void apollo_ni::device_start()
870 {
871 	CLOG1(("apollo_ni::device_start"));
872 	set_node_id(DEFAULT_NODE_ID);
873 }
874 
875 //-------------------------------------------------
876 //  device_reset - device-specific reset
877 //-------------------------------------------------
878 
device_reset()879 void apollo_ni::device_reset()
880 {
881 	CLOG1(("apollo_ni::device_reset"));
882 }
883 
884 //-------------------------------------------------
885 //  set node ID
886 //-------------------------------------------------
887 
set_node_id(uint32_t node_id)888 void apollo_ni::set_node_id(uint32_t node_id)
889 {
890 	m_node_id = node_id;
891 	CLOG1(("apollo_ni::set_node_id: node ID is %x", node_id));
892 }
893 
894 //-------------------------------------------------
895 //  read/write
896 //-------------------------------------------------
897 
write(offs_t offset,uint16_t data,uint16_t mem_mask)898 void apollo_ni::write(offs_t offset, uint16_t data, uint16_t mem_mask)
899 {
900 	CLOG1(("Error: writing node id ROM at offset %02x = %04x & %04x", offset, data, mem_mask));
901 }
902 
read(offs_t offset,uint16_t mem_mask)903 uint16_t apollo_ni::read(offs_t offset, uint16_t mem_mask)
904 {
905 	uint16_t data = 0;
906 	switch (offset & 0x0f)
907 	{
908 	case 1: // msb
909 		data = (m_node_id >> 16) & 0xff;
910 		break;
911 	case 2:
912 		data = (m_node_id >> 8) & 0xff;
913 		break;
914 	case 3: // lsb
915 		data = m_node_id & 0xff;
916 		break;
917 	case 15: // checksum
918 		data = ((m_node_id >> 16) + (m_node_id >> 8) + m_node_id) & 0xff;
919 		break;
920 	default:
921 		data = 0;
922 		break;
923 	}
924 	data <<= 8;
925 	CLOG2(("reading node id ROM at offset %02x = %04x & %04x", offset, data, mem_mask));
926 	return data;
927 }
928 
929 /*-------------------------------------------------
930  DEVICE_IMAGE_LOAD( rom )
931  -------------------------------------------------*/
call_load()932 image_init_result apollo_ni::call_load()
933 {
934 	CLOG1(("apollo_ni::call_load: %s", filename()));
935 
936 	uint64_t size = length();
937 		if (size != 32)
938 	{
939 		CLOG(("apollo_ni::call_load: %s has unexpected file size %d", filename(), size));
940 	}
941 	else
942 	{
943 		uint8_t data[32];
944 		fread(data, sizeof(data));
945 
946 		uint8_t checksum = data[2] + data[4] + data[6];
947 		if (checksum != data[30])
948 		{
949 			CLOG(("apollo_ni::call_load: checksum is %02x - should be %02x", checksum, data[30]));
950 		}
951 		else
952 		{
953 			m_node_id = (((data[2] << 8) | data[4]) << 8) | (data[6]);
954 			CLOG1(("apollo_ni::call_load: node ID is %x", m_node_id));
955 			return image_init_result::PASS;
956 		}
957 	}
958 	return image_init_result::FAIL;
959 }
960 
961 /*-------------------------------------------------
962  DEVICE_IMAGE_CREATE( rom )
963  -------------------------------------------------*/
964 
call_create(int format_type,util::option_resolution * format_options)965 image_init_result apollo_ni::call_create(int format_type, util::option_resolution *format_options)
966 {
967 	CLOG1(("apollo_ni::call_create:"));
968 
969 	if (length() > 0)
970 	{
971 		CLOG(("apollo_ni::call_create: %s already exists", filename()));
972 	}
973 	else
974 	{
975 		uint32_t node_id = 0;
976 		sscanf(basename_noext(), "%x", &node_id);
977 		if (node_id == 0 || node_id > 0xfffff)
978 		{
979 			CLOG(("apollo_ni::call_create: filename %s is no valid node ID", basename()));
980 		}
981 		else
982 		{
983 			uint8_t data[32];
984 			memset(data, 0, sizeof(data));
985 			data[2] = node_id >> 16;
986 			data[4] = node_id >> 8;
987 			data[6] = node_id;
988 			data[30] = data[2] + data[4] + data[6];
989 			fwrite(data, sizeof(data));
990 			CLOG(("apollo_ni::call_create: created %s with node ID %x", filename(), node_id));
991 			set_node_id(node_id);
992 			return image_init_result::PASS;
993 		}
994 	}
995 	return image_init_result::FAIL;
996 }
997 
998 /*-------------------------------------------------
999  DEVICE_IMAGE_UNLOAD( rom )
1000  -------------------------------------------------*/
call_unload()1001 void apollo_ni::call_unload()
1002 {
1003 	CLOG1(("apollo_ni::call_unload:"));
1004 }
1005 
1006 //-------------------------------------------------
1007 //  set node ID from disk
1008 //-------------------------------------------------
1009 
set_node_id_from_disk()1010 void apollo_ni::set_node_id_from_disk()
1011 {
1012 	uint8_t db[0x50];
1013 
1014 	// check label of physical volume and get sector data of logical volume 1
1015 	// Note: sector data starts with 32 byte block header
1016 	// set node ID from UID of logical volume 1 of logical unit 0
1017 	if (m_wdc
1018 			&& m_wdc->get_sector(0, db, sizeof(db), 0) == sizeof(db)
1019 			&& memcmp(db + 0x22, "APOLLO", 6) == 0)
1020 	{
1021 		uint16_t sector1 = apollo_is_dn5500() ? 4 : 1;
1022 
1023 		if (m_wdc->get_sector(sector1, db, sizeof(db), 0) == sizeof(db))
1024 		{
1025 			// set node_id from UID of logical volume 1 of logical unit 0
1026 			m_node_id = (((db[0x49] << 8) | db[0x4a]) << 8) | db[0x4b];
1027 			CLOG1(("apollo_ni::set_node_id_from_disk: node ID is %x", m_node_id));
1028 		}
1029 	}
1030 }
1031 
1032 //##########################################################################
1033 // machine/apollo.c - APOLLO DS3500 CPU Board
1034 //##########################################################################
1035 
1036 #undef VERBOSE
1037 #define VERBOSE 0
1038 
1039 DEVICE_INPUT_DEFAULTS_START(3c505)
1040 	DEVICE_INPUT_DEFAULTS("IO_BASE",  0x3f0, 0x300) // I/O address 0x300
1041 	DEVICE_INPUT_DEFAULTS("IRQ_DRQ",  0x0f, 0x0a)   // IRQ 10
1042 	DEVICE_INPUT_DEFAULTS("IRQ_DRQ",  0x70, 0x60)   // DRQ 6
1043 	DEVICE_INPUT_DEFAULTS("ROM_OPTS", 0x01, 0x01)   // host ROM enabled
1044 	DEVICE_INPUT_DEFAULTS("ROM_OPTS", 0xfe, 0x00)   // host ROM address 0x00000
1045 DEVICE_INPUT_DEFAULTS_END
1046 
apollo_isa_cards(device_slot_interface & device)1047 static void apollo_isa_cards(device_slot_interface &device)
1048 {
1049 	device.option_add("wdc", ISA16_OMTI8621_APOLLO);    // Combo ESDI/AT floppy controller
1050 	device.option_add("ctape", ISA8_SC499);             // Archive SC499 cartridge tape
1051 	device.option_add("3c505", ISA16_3C505).default_bios("apollo"); // 3Com 3C505 Ethernet card
1052 	device.set_option_device_input_defaults("3c505", DEVICE_INPUT_DEFAULTS_NAME(3c505));
1053 }
1054 
common(machine_config & config)1055 void apollo_state::common(machine_config &config)
1056 {
1057 	// configuration MUST be reset first !
1058 	APOLLO_CONF(config, APOLLO_CONF_TAG, 0);
1059 
1060 	AM9517A(config, m_dma8237_1, 14.318181_MHz_XTAL / 3);
1061 	m_dma8237_1->out_hreq_callback().set(FUNC(apollo_state::apollo_dma_1_hrq_changed));
1062 	m_dma8237_1->out_eop_callback().set(FUNC(apollo_state::apollo_dma8237_out_eop));
1063 	m_dma8237_1->in_memr_callback().set(FUNC(apollo_state::apollo_dma_read_byte));
1064 	m_dma8237_1->out_memw_callback().set(FUNC(apollo_state::apollo_dma_write_byte));
1065 	m_dma8237_1->in_ior_callback<0>().set(FUNC(apollo_state::pc_dma8237_0_dack_r));
1066 	m_dma8237_1->in_ior_callback<1>().set(FUNC(apollo_state::pc_dma8237_1_dack_r));
1067 	m_dma8237_1->in_ior_callback<2>().set(FUNC(apollo_state::pc_dma8237_2_dack_r));
1068 	m_dma8237_1->in_ior_callback<3>().set(FUNC(apollo_state::pc_dma8237_3_dack_r));
1069 	m_dma8237_1->out_iow_callback<0>().set(FUNC(apollo_state::pc_dma8237_0_dack_w));
1070 	m_dma8237_1->out_iow_callback<1>().set(FUNC(apollo_state::pc_dma8237_1_dack_w));
1071 	m_dma8237_1->out_iow_callback<2>().set(FUNC(apollo_state::pc_dma8237_2_dack_w));
1072 	m_dma8237_1->out_iow_callback<3>().set(FUNC(apollo_state::pc_dma8237_3_dack_w));
1073 	m_dma8237_1->out_dack_callback<0>().set(FUNC(apollo_state::pc_dack0_w));
1074 	m_dma8237_1->out_dack_callback<1>().set(FUNC(apollo_state::pc_dack1_w));
1075 	m_dma8237_1->out_dack_callback<2>().set(FUNC(apollo_state::pc_dack2_w));
1076 	m_dma8237_1->out_dack_callback<3>().set(FUNC(apollo_state::pc_dack3_w));
1077 
1078 	AM9517A(config, m_dma8237_2, 14.318181_MHz_XTAL / 3);
1079 	m_dma8237_2->out_hreq_callback().set(FUNC(apollo_state::apollo_dma_2_hrq_changed));
1080 	m_dma8237_2->in_memr_callback().set(FUNC(apollo_state::apollo_dma_read_word));
1081 	m_dma8237_2->out_memw_callback().set(FUNC(apollo_state::apollo_dma_write_word));
1082 	m_dma8237_2->in_ior_callback<1>().set(FUNC(apollo_state::pc_dma8237_5_dack_r));
1083 	m_dma8237_2->in_ior_callback<2>().set(FUNC(apollo_state::pc_dma8237_6_dack_r));
1084 	m_dma8237_2->in_ior_callback<3>().set(FUNC(apollo_state::pc_dma8237_7_dack_r));
1085 	m_dma8237_2->out_iow_callback<1>().set(FUNC(apollo_state::pc_dma8237_5_dack_w));
1086 	m_dma8237_2->out_iow_callback<2>().set(FUNC(apollo_state::pc_dma8237_6_dack_w));
1087 	m_dma8237_2->out_iow_callback<3>().set(FUNC(apollo_state::pc_dma8237_7_dack_w));
1088 	m_dma8237_2->out_dack_callback<0>().set(FUNC(apollo_state::pc_dack4_w));
1089 	m_dma8237_2->out_dack_callback<1>().set(FUNC(apollo_state::pc_dack5_w));
1090 	m_dma8237_2->out_dack_callback<2>().set(FUNC(apollo_state::pc_dack6_w));
1091 	m_dma8237_2->out_dack_callback<3>().set(FUNC(apollo_state::pc_dack7_w));
1092 
1093 	PIC8259(config, m_pic8259_master, 0);
1094 	m_pic8259_master->out_int_callback().set(FUNC(apollo_state::apollo_pic8259_master_set_int_line));
1095 	m_pic8259_master->in_sp_callback().set_constant(1);
1096 	m_pic8259_master->read_slave_ack_callback().set(FUNC(apollo_state::apollo_pic8259_get_slave_ack));
1097 
1098 	PIC8259(config, m_pic8259_slave, 0);
1099 	m_pic8259_slave->out_int_callback().set(FUNC(apollo_state::apollo_pic8259_slave_set_int_line));
1100 	m_pic8259_slave->in_sp_callback().set_constant(0);
1101 
1102 	PTM6840(config, m_ptm, 0);
1103 	m_ptm->set_external_clocks(250000, 125000, 62500);
1104 	m_ptm->irq_callback().set(FUNC(apollo_state::apollo_ptm_irq_function));
1105 
1106 	clock_device &ptmclock(CLOCK(config, "ptmclock", 250000));
1107 	ptmclock.signal_handler().set(FUNC(apollo_state::apollo_ptm_timer_tick));
1108 
1109 	MC146818(config, m_rtc, 32.768_kHz_XTAL);
1110 	// FIXME: is this interrupt really only connected on DN3000?
1111 	//m_rtc->irq().set(FUNC(apollo_state::apollo_rtc_irq_function));
1112 	m_rtc->set_use_utc(true);
1113 	m_rtc->set_binary(false);
1114 	m_rtc->set_24hrs(false);
1115 	m_rtc->set_epoch(0);
1116 
1117 	APOLLO_NI(config, m_node_id, 0);
1118 
1119 	APOLLO_SIO(config, m_sio2, 3.6864_MHz_XTAL);
1120 	m_sio2->irq_cb().set(FUNC(apollo_state::sio2_irq_handler));
1121 
1122 	ISA16(config, m_isa, 0);
1123 	m_isa->set_custom_spaces();
1124 	m_isa->irq2_callback().set(m_pic8259_slave, FUNC(pic8259_device::ir2_w)); // in place of irq 2 on at irq 9 is used
1125 	m_isa->irq3_callback().set(m_pic8259_master, FUNC(pic8259_device::ir3_w));
1126 	m_isa->irq4_callback().set(m_pic8259_master, FUNC(pic8259_device::ir4_w));
1127 	m_isa->irq5_callback().set(m_pic8259_master, FUNC(pic8259_device::ir5_w));
1128 	m_isa->irq6_callback().set(m_pic8259_master, FUNC(pic8259_device::ir6_w));
1129 	m_isa->irq7_callback().set(m_pic8259_master, FUNC(pic8259_device::ir7_w));
1130 	m_isa->irq10_callback().set(m_pic8259_slave, FUNC(pic8259_device::ir2_w));
1131 	m_isa->irq11_callback().set(m_pic8259_slave, FUNC(pic8259_device::ir3_w));
1132 	m_isa->irq12_callback().set(m_pic8259_slave, FUNC(pic8259_device::ir4_w));
1133 	m_isa->irq14_callback().set(m_pic8259_slave, FUNC(pic8259_device::ir6_w));
1134 	m_isa->irq15_callback().set(m_pic8259_slave, FUNC(pic8259_device::ir7_w));
1135 	m_isa->drq0_callback().set(m_dma8237_1, FUNC(am9517a_device::dreq0_w));
1136 	m_isa->drq1_callback().set(m_dma8237_1, FUNC(am9517a_device::dreq1_w));
1137 	m_isa->drq2_callback().set(m_dma8237_1, FUNC(am9517a_device::dreq2_w));
1138 	m_isa->drq3_callback().set(m_dma8237_1, FUNC(am9517a_device::dreq3_w));
1139 	m_isa->drq5_callback().set(m_dma8237_2, FUNC(am9517a_device::dreq1_w));
1140 	m_isa->drq6_callback().set(m_dma8237_2, FUNC(am9517a_device::dreq2_w));
1141 	m_isa->drq7_callback().set(m_dma8237_2, FUNC(am9517a_device::dreq3_w));
1142 
1143 	ISA16_SLOT(config, "isa1", 0, APOLLO_ISA_TAG, apollo_isa_cards, "wdc", false); // FIXME: determine ISA bus clock
1144 	ISA16_SLOT(config, "isa2", 0, APOLLO_ISA_TAG, apollo_isa_cards, "ctape", false);
1145 	ISA16_SLOT(config, "isa3", 0, APOLLO_ISA_TAG, apollo_isa_cards, "3c505", false);
1146 	ISA16_SLOT(config, "isa4", 0, APOLLO_ISA_TAG, apollo_isa_cards, nullptr, false);
1147 	ISA16_SLOT(config, "isa5", 0, APOLLO_ISA_TAG, apollo_isa_cards, nullptr, false);
1148 	ISA16_SLOT(config, "isa6", 0, APOLLO_ISA_TAG, apollo_isa_cards, nullptr, false);
1149 	ISA16_SLOT(config, "isa7", 0, APOLLO_ISA_TAG, apollo_isa_cards, nullptr, false);
1150 
1151 	SOFTWARE_LIST(config, "ctape_list").set_original("apollo_ctape");
1152 }
1153 
1154 // for machines with the keyboard and a graphics head
apollo(machine_config & config)1155 void apollo_state::apollo(machine_config &config)
1156 {
1157 	common(config);
1158 	APOLLO_SIO(config, m_sio, 3.6864_MHz_XTAL);
1159 	m_sio->irq_cb().set(FUNC(apollo_state::sio_irq_handler));
1160 	m_sio->outport_cb().set(FUNC(apollo_state::sio_output));
1161 	m_sio->a_tx_cb().set(m_keyboard, FUNC(apollo_kbd_device::rx_w));
1162 
1163 #ifdef APOLLO_XXL
1164 	m_sio->b_tx_cb().set(APOLLO_STDIO_TAG, FUNC(apollo_stdio_device::rx_w));
1165 #endif
1166 }
1167 
1168 static DEVICE_INPUT_DEFAULTS_START( apollo_terminal )
1169 	DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 )
1170 	DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 )
1171 	DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
1172 	DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
1173 	DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
1174 	DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
1175 DEVICE_INPUT_DEFAULTS_END
1176 
1177 // for headless machines using a serial console
apollo_terminal(machine_config & config)1178 void apollo_state::apollo_terminal(machine_config &config)
1179 {
1180 	common(config);
1181 	APOLLO_SIO(config, m_sio, 3.6864_MHz_XTAL);
1182 	m_sio->irq_cb().set(FUNC(apollo_state::sio_irq_handler));
1183 	m_sio->outport_cb().set(FUNC(apollo_state::sio_output));
1184 	m_sio->b_tx_cb().set("rs232", FUNC(rs232_port_device::write_txd));
1185 
1186 	rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal"));
1187 	rs232.rxd_handler().set(m_sio, FUNC(apollo_sio::rx_b_w));
1188 	rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(apollo_terminal));
1189 }
1190 
init_apollo()1191 void apollo_state::init_apollo()
1192 {
1193 	MLOG1(("driver_init_apollo"));
1194 }
1195 
MACHINE_START_MEMBER(apollo_state,apollo)1196 MACHINE_START_MEMBER(apollo_state,apollo)
1197 {
1198 	MLOG1(("machine_start_apollo"));
1199 
1200 	m_dma_channel = -1;
1201 	m_cur_eop = false;
1202 
1203 	m_internal_leds.resolve();
1204 	m_external_leds.resolve();
1205 }
1206 
MACHINE_RESET_MEMBER(apollo_state,apollo)1207 MACHINE_RESET_MEMBER(apollo_state,apollo)
1208 {
1209 	uint8_t year = apollo_rtc_r(9);
1210 
1211 	MLOG1(("machine_reset_apollo"));
1212 
1213 	// set configuration
1214 	apollo_csr_set_servicemode(apollo_config(APOLLO_CONF_SERVICE_MODE));
1215 
1216 	// change year according to configuration settings
1217 	if (year < 25 && apollo_config(APOLLO_CONF_25_YEARS_AGO))
1218 	{
1219 		year += 75;
1220 		apollo_rtc_w(9, year);
1221 	}
1222 	else if (year < 30 && apollo_config(APOLLO_CONF_30_YEARS_AGO))
1223 	{
1224 		year += 70;
1225 		apollo_rtc_w(9, year);
1226 	}
1227 	else if (year >= 70 && !apollo_config(APOLLO_CONF_30_YEARS_AGO)
1228 			&& !apollo_config(APOLLO_CONF_25_YEARS_AGO))
1229 	{
1230 		year -= 70;
1231 		apollo_rtc_w(9, year);
1232 	}
1233 
1234 	ptm_counter = 0;
1235 	sio_output_data = 0xff;
1236 }
1237 
1238 #ifdef APOLLO_XXL
1239 
1240 //##########################################################################
1241 // machine/apollo_stdio.c - stdio terminal for mess
1242 //##########################################################################
1243 
1244 #undef VERBOSE
1245 #define VERBOSE 0
1246 
1247 #if defined(__linux__)
1248 #include <fcntl.h>
1249 #include <unistd.h>
1250 #endif
1251 
1252 /***************************************************************************
1253  IMPLEMENTATION
1254  ***************************************************************************/
1255 
1256 // device type definition
1257 DEFINE_DEVICE_TYPE(APOLLO_STDIO, apollo_stdio_device, "apollo_stdio", "Apollo STDIO")
1258 
1259 //-------------------------------------------------
1260 // apollo_stdio_device - constructor
1261 //-------------------------------------------------
1262 
apollo_stdio_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1263 apollo_stdio_device::apollo_stdio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1264 	device_t(mconfig, APOLLO_STDIO, tag, owner, clock),
1265 	device_serial_interface(mconfig, *this),
1266 	m_tx_w(*this)
1267 {
1268 }
1269 
1270 //-------------------------------------------------
1271 //  device_start - device-specific startup
1272 //-------------------------------------------------
1273 
device_start()1274 void apollo_stdio_device::device_start()
1275 {
1276 	CLOG1(("device_start"));
1277 
1278 	m_tx_w.resolve_safe();
1279 
1280 	m_poll_timer = machine().scheduler().timer_alloc(timer_expired_delegate(
1281 			FUNC(apollo_stdio_device::poll_timer), this));
1282 }
1283 
1284 //-------------------------------------------------
1285 //  device_reset - device-specific reset
1286 //-------------------------------------------------
1287 
device_reset()1288 void apollo_stdio_device::device_reset()
1289 {
1290 	CLOG1(("device_reset"));
1291 
1292 	// comms is at 8N1, 9600 baud
1293 	set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
1294 	set_rcv_rate(9600);
1295 	set_tra_rate(9600);
1296 
1297 	m_tx_busy = false;
1298 	m_xmit_read = m_xmit_write = 0;
1299 
1300 #if defined(__linux__)
1301 	// FIXME: unavailable in mingw
1302 	// set stdin to nonblocking to allow polling
1303 	fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK);
1304 #endif
1305 
1306 	// start timer
1307 	m_poll_timer->adjust(attotime::zero, 0, attotime::from_msec(1)); // every 1ms
1308 }
1309 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)1310 void apollo_stdio_device::device_timer(emu_timer &timer, device_timer_id id,
1311 		int param, void *ptr)
1312 {
1313 //  FIXME?
1314 //  device_serial_interface::device_timer(timer, id, param, ptr);
1315 }
1316 
rcv_complete()1317 void apollo_stdio_device::rcv_complete() // Rx completed receiving byte
1318 {
1319 	receive_register_extract();
1320 	uint8_t data = get_received_char();
1321 
1322 	// output data to stdout (FIXME: '\r' may confuse ceterm)
1323 	if (data != '\r')
1324 	{
1325 		::putchar(data);
1326 		::fflush(stdout);
1327 	}
1328 	CLOG1(("rcv_complete %02x - %c", data, data));
1329 }
1330 
tra_complete()1331 void apollo_stdio_device::tra_complete() // Tx completed sending byte
1332 {
1333 	// is there more waiting to send?
1334 	if (m_xmit_read != m_xmit_write)
1335 	{
1336 		transmit_register_setup(m_xmitring[m_xmit_read++]);
1337 		if (m_xmit_read >= XMIT_RING_SIZE)
1338 		{
1339 			m_xmit_read = 0;
1340 		}
1341 	}
1342 	else
1343 	{
1344 		m_tx_busy = false;
1345 	}
1346 }
1347 
tra_callback()1348 void apollo_stdio_device::tra_callback() // Tx send bit
1349 {
1350 	int bit = transmit_register_get_data_bit();
1351 	m_tx_w(bit);
1352 
1353 	CLOG2(("tra_callback %02x", bit));
1354 }
1355 
TIMER_CALLBACK_MEMBER(apollo_stdio_device::poll_timer)1356 TIMER_CALLBACK_MEMBER(apollo_stdio_device::poll_timer)
1357 {
1358 #if defined(__linux__)
1359 	uint8_t data;
1360 	while (::read(STDIN_FILENO, &data, 1) == 1)
1361 	{
1362 		xmit_char(data == '\n' ? '\r' : data);
1363 	}
1364 #endif
1365 }
1366 
xmit_char(uint8_t data)1367 void apollo_stdio_device::xmit_char(uint8_t data)
1368 {
1369 	CLOG1(("xmit_char %02x - %c", data, data));
1370 
1371 	// if tx is busy it'll pick this up automatically when it completes
1372 	if (!m_tx_busy)
1373 	{
1374 		m_tx_busy = true;
1375 		transmit_register_setup(data);
1376 	}
1377 	else
1378 	{
1379 		// tx is busy, it'll pick this up next time
1380 		m_xmitring[m_xmit_write++] = data;
1381 		if (m_xmit_write >= XMIT_RING_SIZE)
1382 		{
1383 			m_xmit_write = 0;
1384 		}
1385 	}
1386 }
1387 #endif
1388