1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /*
4 
5     Wang Professional Computer
6 
7     http://www.seasip.info/VintagePC/wangpc.html
8 
9     chdman -createblankhd q540.chd 512 8 17 512
10 
11 */
12 
13 /*
14 
15     TODO:
16 
17     - with quantum perfect cpu gets stuck @ 49c3 mov ss,cs:[52ah]
18     - hard disk
19 
20 */
21 
22 #include "emu.h"
23 #include "softlist.h"
24 #include "bus/centronics/ctronics.h"
25 #include "bus/rs232/rs232.h"
26 #include "bus/wangpc/wangpc.h"
27 #include "cpu/i86/i86.h"
28 #include "formats/pc_dsk.h"
29 #include "imagedev/floppy.h"
30 #include "machine/am9517a.h"
31 #include "machine/i8255.h"
32 #include "machine/im6402.h"
33 #include "machine/pit8253.h"
34 #include "machine/pic8259.h"
35 #include "machine/scn_pci.h"
36 #include "machine/ram.h"
37 #include "machine/upd765.h"
38 #include "machine/wangpckb.h"
39 
40 #define I8086_TAG       "i8086"
41 #define AM9517A_TAG     "am9517a"
42 #define I8259A_TAG      "i8259"
43 #define I8255A_TAG      "i8255a"
44 #define I8253_TAG       "i8253"
45 #define IM6402_TAG      "im6402"
46 #define SCN2661_TAG     "scn2661"
47 #define UPD765_TAG      "upd765"
48 #define CENTRONICS_TAG  "centronics"
49 #define RS232_TAG       "rs232"
50 #define WANGPC_KEYBOARD_TAG "wangpckb"
51 #define LED_DIAGNOSTIC  "led0"
52 
53 class wangpc_state : public driver_device
54 {
55 public:
56 	// constructor
wangpc_state(const machine_config & mconfig,device_type type,const char * tag)57 	wangpc_state(const machine_config &mconfig, device_type type, const char *tag) :
58 		driver_device(mconfig, type, tag),
59 		m_maincpu(*this, I8086_TAG),
60 		m_dmac(*this, AM9517A_TAG),
61 		m_pic(*this, I8259A_TAG),
62 		m_ppi(*this, I8255A_TAG),
63 		m_pit(*this, I8253_TAG),
64 		m_uart(*this, IM6402_TAG),
65 		m_epci(*this, SCN2661_TAG),
66 		m_fdc(*this, UPD765_TAG),
67 		m_ram(*this, RAM_TAG),
68 		m_floppy0(*this, UPD765_TAG ":0:525dd"),
69 		m_floppy1(*this, UPD765_TAG ":1:525dd"),
70 		m_centronics(*this, CENTRONICS_TAG),
71 		m_cent_data_in(*this, "cent_data_in"),
72 		m_cent_data_out(*this, "cent_data_out"),
73 		m_bus(*this, "wangpcbus"),
74 		m_sw(*this, "SW"),
75 		m_led_diagnostic(*this, LED_DIAGNOSTIC),
76 		m_timer2_irq(1),
77 		m_centronics_ack(1),
78 		m_dav(1),
79 		m_dma_eop(1),
80 		m_uart_dr(0),
81 		m_uart_tbre(0),
82 		m_fpu_irq(0),
83 		m_bus_irq2(0),
84 		m_enable_eop(0),
85 		m_disable_dreq2(0),
86 		m_fdc_drq(0),
87 		m_fdc_dd0(0),
88 		m_fdc_dd1(0),
89 		m_fdc_tc(0),
90 		m_ds1(false),
91 		m_ds2(false)
92 	{
93 	}
94 
95 	void wangpc(machine_config &config);
96 
97 private:
98 	required_device<cpu_device> m_maincpu;
99 	required_device<am9517a_device> m_dmac;
100 	required_device<pic8259_device> m_pic;
101 	required_device<i8255_device> m_ppi;
102 	required_device<pit8253_device> m_pit;
103 	required_device<im6402_device> m_uart;
104 	required_device<scn_pci_device> m_epci;
105 	required_device<upd765a_device> m_fdc;
106 	required_device<ram_device> m_ram;
107 	required_device<floppy_image_device> m_floppy0;
108 	required_device<floppy_image_device> m_floppy1;
109 	required_device<centronics_device> m_centronics;
110 	required_device<input_buffer_device> m_cent_data_in;
111 	required_device<output_latch_device> m_cent_data_out;
112 	required_device<wangpcbus_device> m_bus;
113 	required_ioport m_sw;
114 	output_finder<> m_led_diagnostic;
115 
116 	virtual void machine_start() override;
117 	virtual void machine_reset() override;
118 
119 	void select_drive();
120 	void check_level1_interrupts();
121 	void check_level2_interrupts();
122 	void update_fdc_drq();
123 	void update_fdc_tc();
124 
125 	void fdc_ctrl_w(uint8_t data);
126 	uint8_t deselect_drive1_r();
127 	void deselect_drive1_w(uint8_t data);
128 	uint8_t select_drive1_r();
129 	void select_drive1_w(uint8_t data);
130 	uint8_t deselect_drive2_r();
131 	void deselect_drive2_w(uint8_t data);
132 	uint8_t select_drive2_r();
133 	void select_drive2_w(uint8_t data);
134 	uint8_t motor1_off_r();
135 	void motor1_off_w(uint8_t data);
136 	uint8_t motor1_on_r();
137 	void motor1_on_w(uint8_t data);
138 	uint8_t motor2_off_r();
139 	void motor2_off_w(uint8_t data);
140 	uint8_t motor2_on_r();
141 	void motor2_on_w(uint8_t data);
142 	uint8_t fdc_reset_r();
143 	void fdc_reset_w(uint8_t data);
144 	uint8_t fdc_tc_r();
145 	void fdc_tc_w(uint8_t data);
146 	void dma_page_w(offs_t offset, uint8_t data);
147 	uint8_t status_r();
148 	void timer0_irq_clr_w(uint8_t data);
149 	uint8_t timer2_irq_clr_r();
150 	void nmi_mask_w(uint8_t data);
151 	uint8_t led_on_r();
152 	void fpu_mask_w(uint8_t data);
153 	uint8_t dma_eop_clr_r();
154 	void uart_tbre_clr_w(uint8_t data);
155 	uint8_t uart_r();
156 	void uart_w(uint8_t data);
157 	uint8_t centronics_r();
158 	void centronics_w(uint8_t data);
159 	uint8_t busy_clr_r();
160 	void acknlg_clr_w(uint8_t data);
161 	uint8_t led_off_r();
162 	void parity_nmi_clr_w(uint8_t data);
163 	uint8_t option_id_r();
164 
165 	DECLARE_WRITE_LINE_MEMBER( hrq_w );
166 	DECLARE_WRITE_LINE_MEMBER( eop_w );
167 	uint8_t memr_r(offs_t offset);
168 	void memw_w(offs_t offset, uint8_t data);
169 	uint8_t ior2_r();
170 	void iow2_w(uint8_t data);
171 	DECLARE_WRITE_LINE_MEMBER( dack0_w );
172 	DECLARE_WRITE_LINE_MEMBER( dack1_w );
173 	DECLARE_WRITE_LINE_MEMBER( dack2_w );
174 	DECLARE_WRITE_LINE_MEMBER( dack3_w );
175 	uint8_t ppi_pa_r();
176 	uint8_t ppi_pb_r();
177 	uint8_t ppi_pc_r();
178 	void ppi_pc_w(uint8_t data);
179 	DECLARE_WRITE_LINE_MEMBER( pit2_w );
180 	DECLARE_WRITE_LINE_MEMBER( uart_dr_w );
181 	DECLARE_WRITE_LINE_MEMBER( uart_tbre_w );
182 	DECLARE_WRITE_LINE_MEMBER( epci_irq_w );
183 	DECLARE_WRITE_LINE_MEMBER( write_centronics_ack );
184 	DECLARE_WRITE_LINE_MEMBER( write_centronics_busy );
185 	DECLARE_WRITE_LINE_MEMBER( write_centronics_fault );
186 	DECLARE_WRITE_LINE_MEMBER( write_centronics_perror );
187 	DECLARE_WRITE_LINE_MEMBER( bus_irq2_w );
188 
189 	DECLARE_FLOPPY_FORMATS( floppy_formats );
190 
191 	DECLARE_WRITE_LINE_MEMBER( fdc_irq );
192 	DECLARE_WRITE_LINE_MEMBER( fdc_drq );
193 
194 	image_init_result on_disk0_load(floppy_image_device *image);
195 	void on_disk0_unload(floppy_image_device *image);
196 	image_init_result on_disk1_load(floppy_image_device *image);
197 	void on_disk1_unload(floppy_image_device *image);
198 
199 	void wangpc_io(address_map &map);
200 	void wangpc_mem(address_map &map);
201 
202 	uint8_t m_dma_page[4];
203 	int m_dack;
204 
205 	int m_timer2_irq;
206 	int m_centronics_ack;
207 	int m_centronics_busy;
208 	int m_centronics_fault;
209 	int m_centronics_perror;
210 	int m_dav;
211 	int m_dma_eop;
212 	int m_uart_dr;
213 	int m_uart_tbre;
214 	int m_fpu_irq;
215 	int m_bus_irq2;
216 
217 	int m_enable_eop;
218 	int m_disable_dreq2;
219 	int m_fdc_drq;
220 	int m_fdc_dd0;
221 	int m_fdc_dd1;
222 	int m_fdc_tc;
223 	int m_ds1;
224 	int m_ds2;
225 
226 	int m_led[6];
227 };
228 
229 
230 
231 //**************************************************************************
232 //  MACROS/CONSTANTS
233 //**************************************************************************
234 
235 #define LOG 0
236 
237 
238 
239 //**************************************************************************
240 //  IMPLEMENTATION
241 //**************************************************************************
242 
select_drive()243 void wangpc_state::select_drive()
244 {
245 	floppy_image_device *floppy = nullptr;
246 
247 	if (m_ds1) floppy = m_floppy0;
248 	if (m_ds2) floppy = m_floppy1;
249 
250 	m_fdc->set_floppy(floppy);
251 }
252 
fdc_ctrl_w(uint8_t data)253 void wangpc_state::fdc_ctrl_w(uint8_t data)
254 {
255 	/*
256 
257 	    bit     description
258 
259 	    0       Enable /EOP
260 	    1       Disable /DREQ2
261 	    2       Clear drive 1 door disturbed interrupt
262 	    3       Clear drive 2 door disturbed interrupt
263 	    4
264 	    5
265 	    6
266 	    7
267 
268 	*/
269 
270 	m_enable_eop = BIT(data, 0);
271 	m_disable_dreq2 = BIT(data, 1);
272 
273 	if (BIT(data, 2)) m_fdc_dd0 = 0;
274 	if (BIT(data, 3)) m_fdc_dd1 = 0;
275 
276 	if (LOG)
277 	{
278 		logerror("%s: Enable /EOP %u\n", machine().describe_context(), m_enable_eop);
279 		logerror("%s: Disable /DREQ2 %u\n", machine().describe_context(), m_disable_dreq2);
280 	}
281 
282 	update_fdc_tc();
283 	update_fdc_drq();
284 }
285 
286 
deselect_drive1_r()287 uint8_t wangpc_state::deselect_drive1_r()
288 {
289 	m_ds1 = false;
290 	select_drive();
291 
292 	return 0xff;
293 }
294 
deselect_drive1_w(uint8_t data)295 void wangpc_state::deselect_drive1_w(uint8_t data)
296 {
297 	deselect_drive1_r();
298 }
299 
select_drive1_r()300 uint8_t wangpc_state::select_drive1_r()
301 {
302 	m_ds1 = true;
303 	select_drive();
304 
305 	return 0xff;
306 }
307 
select_drive1_w(uint8_t data)308 void wangpc_state::select_drive1_w(uint8_t data)
309 {
310 	select_drive1_r();
311 }
312 
deselect_drive2_r()313 uint8_t wangpc_state::deselect_drive2_r()
314 {
315 	m_ds2 = false;
316 	select_drive();
317 
318 	return 0xff;
319 }
320 
deselect_drive2_w(uint8_t data)321 void wangpc_state::deselect_drive2_w(uint8_t data)
322 {
323 	deselect_drive2_r();
324 }
325 
select_drive2_r()326 uint8_t wangpc_state::select_drive2_r()
327 {
328 	m_ds2 = true;
329 	select_drive();
330 
331 	return 0xff;
332 }
333 
select_drive2_w(uint8_t data)334 void wangpc_state::select_drive2_w(uint8_t data)
335 {
336 	select_drive2_r();
337 }
338 
motor1_off_r()339 uint8_t wangpc_state::motor1_off_r()
340 {
341 	if (LOG) logerror("%s: Drive 1 motor OFF\n", machine().describe_context());
342 
343 	m_floppy0->mon_w(1);
344 
345 	return 0xff;
346 }
347 
motor1_off_w(uint8_t data)348 void wangpc_state::motor1_off_w(uint8_t data)
349 {
350 	motor1_off_r();
351 }
352 
motor1_on_r()353 uint8_t wangpc_state::motor1_on_r()
354 {
355 	if (LOG) logerror("%s: Drive 1 motor ON\n", machine().describe_context());
356 
357 	m_floppy0->mon_w(0);
358 
359 	return 0xff;
360 }
361 
motor1_on_w(uint8_t data)362 void wangpc_state::motor1_on_w(uint8_t data)
363 {
364 	motor1_on_r();
365 }
366 
motor2_off_r()367 uint8_t wangpc_state::motor2_off_r()
368 {
369 	if (LOG) logerror("%s: Drive 2 motor OFF\n", machine().describe_context());
370 
371 	m_floppy1->mon_w(1);
372 
373 	return 0xff;
374 }
375 
motor2_off_w(uint8_t data)376 void wangpc_state::motor2_off_w(uint8_t data)
377 {
378 	motor2_off_r();
379 }
380 
motor2_on_r()381 uint8_t wangpc_state::motor2_on_r()
382 {
383 	if (LOG) logerror("%s: Drive 2 motor ON\n", machine().describe_context());
384 
385 	m_floppy1->mon_w(0);
386 
387 	return 0xff;
388 }
389 
motor2_on_w(uint8_t data)390 void wangpc_state::motor2_on_w(uint8_t data)
391 {
392 	motor2_on_r();
393 }
394 
fdc_reset_r()395 uint8_t wangpc_state::fdc_reset_r()
396 {
397 	if (LOG) logerror("%s: FDC reset\n", machine().describe_context());
398 
399 	m_fdc->reset();
400 
401 	return 0xff;
402 }
403 
fdc_reset_w(uint8_t data)404 void wangpc_state::fdc_reset_w(uint8_t data)
405 {
406 	fdc_reset_r();
407 }
408 
fdc_tc_r()409 uint8_t wangpc_state::fdc_tc_r()
410 {
411 	if (LOG) logerror("%s: FDC TC\n", machine().describe_context());
412 
413 	m_fdc->tc_w(1);
414 	m_fdc->tc_w(0);
415 
416 	return 0xff;
417 }
418 
fdc_tc_w(uint8_t data)419 void wangpc_state::fdc_tc_w(uint8_t data)
420 {
421 	fdc_tc_r();
422 }
423 
424 
425 //-------------------------------------------------
426 //  dma_page_w -
427 //-------------------------------------------------
428 
dma_page_w(offs_t offset,uint8_t data)429 void wangpc_state::dma_page_w(offs_t offset, uint8_t data)
430 {
431 	if (LOG) logerror("%s: DMA page %u: %06x\n", machine().describe_context(), offset + 1, (data & 0x0f) << 16);
432 
433 	m_dma_page[offset + 1] = data & 0x0f;
434 }
435 
436 
437 //-------------------------------------------------
438 //  status_r -
439 //-------------------------------------------------
440 
status_r()441 uint8_t wangpc_state::status_r()
442 {
443 	/*
444 
445 	    bit     description
446 
447 	    0       Memory Parity Flag
448 	    1       I/O Error Flag
449 	    2       Unassigned
450 	    3       FDC Interrupt Flag
451 	    4       Door disturbed on drive 1
452 	    5       Door disturbed on drive 2
453 	    6       Door open on drive 1
454 	    7       Door open on drive 2
455 
456 	*/
457 
458 	uint8_t data = 0x03;
459 
460 	// floppy interrupts
461 	data |= m_fdc->get_irq() << 3;
462 	data |= m_fdc_dd0 << 4;
463 	data |= m_fdc_dd1 << 5;
464 	data |= m_floppy0->exists() ? 0 : 0x40;
465 	data |= m_floppy1->exists() ? 0 : 0x80;
466 
467 	return data;
468 }
469 
470 
471 //-------------------------------------------------
472 //  timer0_int_clr_w -
473 //-------------------------------------------------
474 
timer0_irq_clr_w(uint8_t data)475 void wangpc_state::timer0_irq_clr_w(uint8_t data)
476 {
477 	//if (LOG) logerror("%s: Timer 0 IRQ clear\n", machine().describe_context());
478 
479 	m_pic->ir0_w(CLEAR_LINE);
480 }
481 
482 
483 //-------------------------------------------------
484 //  timer2_irq_clr_r -
485 //-------------------------------------------------
486 
timer2_irq_clr_r()487 uint8_t wangpc_state::timer2_irq_clr_r()
488 {
489 	//if (LOG) logerror("%s: Timer 2 IRQ clear\n", machine().describe_context());
490 
491 	m_timer2_irq = 1;
492 	check_level1_interrupts();
493 
494 	return 0xff;
495 }
496 
497 
498 //-------------------------------------------------
499 //  nmi_mask_w -
500 //-------------------------------------------------
501 
nmi_mask_w(uint8_t data)502 void wangpc_state::nmi_mask_w(uint8_t data)
503 {
504 	if (LOG) logerror("%s: NMI mask %02x\n", machine().describe_context(), data);
505 }
506 
507 
508 //-------------------------------------------------
509 //  led_on_r -
510 //-------------------------------------------------
511 
led_on_r()512 uint8_t wangpc_state::led_on_r()
513 {
514 	if (LOG) logerror("%s: Diagnostic LED on\n", machine().describe_context());
515 
516 	m_led_diagnostic = 1;
517 
518 	return 0xff;
519 }
520 
521 
522 //-------------------------------------------------
523 //  fpu_mask_w -
524 //-------------------------------------------------
525 
fpu_mask_w(uint8_t data)526 void wangpc_state::fpu_mask_w(uint8_t data)
527 {
528 	if (LOG) logerror("%s: FPU mask %02x\n", machine().describe_context(), data);
529 }
530 
531 
532 //-------------------------------------------------
533 //  dma_eop_clr_r -
534 //-------------------------------------------------
535 
dma_eop_clr_r()536 uint8_t wangpc_state::dma_eop_clr_r()
537 {
538 	if (LOG) logerror("%s: EOP clear\n", machine().describe_context());
539 
540 	m_dma_eop = 1;
541 
542 	check_level2_interrupts();
543 
544 	return 0xff;
545 }
546 
547 
548 //-------------------------------------------------
549 //  uart_tbre_clr_w -
550 //-------------------------------------------------
551 
uart_tbre_clr_w(uint8_t data)552 void wangpc_state::uart_tbre_clr_w(uint8_t data)
553 {
554 	if (LOG) logerror("%s: TBRE clear\n", machine().describe_context());
555 
556 	m_uart_tbre = 0;
557 
558 	check_level2_interrupts();
559 }
560 
561 
562 //-------------------------------------------------
563 //  uart_r -
564 //-------------------------------------------------
565 
uart_r()566 uint8_t wangpc_state::uart_r()
567 {
568 	m_uart_dr = 0;
569 
570 	check_level2_interrupts();
571 
572 	uint8_t data = m_uart->read();
573 
574 	if (LOG) logerror("%s: UART read %02x\n", machine().describe_context(), data);
575 
576 	return data;
577 }
578 
579 
580 //-------------------------------------------------
581 //  uart_w -
582 //-------------------------------------------------
583 
uart_w(uint8_t data)584 void wangpc_state::uart_w(uint8_t data)
585 {
586 	if (LOG) logerror("%s: UART write %02x\n", machine().describe_context(), data);
587 
588 	switch (data)
589 	{
590 	case 0x10: m_led[0] = 1; break;
591 	case 0x11: m_led[0] = 0; break;
592 	case 0x12: m_led[1] = 1; break;
593 	case 0x13: m_led[1] = 0; break;
594 	case 0x14: m_led[2] = 1; break;
595 	case 0x15: m_led[2] = 0; break;
596 	case 0x16: m_led[3] = 1; break;
597 	case 0x17: m_led[3] = 0; break;
598 	case 0x18: m_led[4] = 1; break;
599 	case 0x19: m_led[4] = 0; break;
600 	case 0x1a: m_led[5] = 1; break;
601 	case 0x1b: m_led[5] = 0; break;
602 	case 0x1c: m_led[0] = m_led[1] = m_led[2] = m_led[3] = m_led[4] = m_led[5] = 1; break;
603 	case 0x1d: m_led[0] = m_led[1] = m_led[2] = m_led[3] = m_led[4] = m_led[5] = 0; break;
604 	}
605 
606 	if (LOG) popmessage("%u%u%u%u%u%u", m_led[0], m_led[1], m_led[2], m_led[3], m_led[4], m_led[5]);
607 
608 	m_uart_tbre = 0;
609 	check_level2_interrupts();
610 
611 	m_uart->write(data);
612 }
613 
614 
615 //-------------------------------------------------
616 //  centronics_r -
617 //-------------------------------------------------
618 
centronics_r()619 uint8_t wangpc_state::centronics_r()
620 {
621 	m_dav = 1;
622 	check_level1_interrupts();
623 
624 	return m_cent_data_in->read();
625 }
626 
627 
628 //-------------------------------------------------
629 //  centronics_w -
630 //-------------------------------------------------
631 
centronics_w(uint8_t data)632 void wangpc_state::centronics_w(uint8_t data)
633 {
634 	m_centronics_ack = 1;
635 	check_level1_interrupts();
636 
637 	m_cent_data_out->write(data);
638 
639 	m_centronics->write_strobe(0);
640 	m_centronics->write_strobe(1);
641 }
642 
643 
644 //-------------------------------------------------
645 //  busy_clr_r -
646 //-------------------------------------------------
647 
busy_clr_r()648 uint8_t wangpc_state::busy_clr_r()
649 {
650 	if (LOG) logerror("%s: BUSY clear\n", machine().describe_context());
651 
652 	m_centronics_busy = 0;
653 	check_level1_interrupts();
654 
655 	return 0xff;
656 }
657 
658 
659 //-------------------------------------------------
660 //  acknlg_clr_w -
661 //-------------------------------------------------
662 
acknlg_clr_w(uint8_t data)663 void wangpc_state::acknlg_clr_w(uint8_t data)
664 {
665 	if (LOG) logerror("%s: ACKNLG clear\n", machine().describe_context());
666 
667 	m_centronics_ack = 1;
668 	check_level1_interrupts();
669 }
670 
671 
672 //-------------------------------------------------
673 //  led_off_r -
674 //-------------------------------------------------
675 
led_off_r()676 uint8_t wangpc_state::led_off_r()
677 {
678 	if (LOG) logerror("%s: Diagnostic LED off\n", machine().describe_context());
679 
680 	m_led_diagnostic = 0;
681 
682 	return 0xff;
683 }
684 
685 
686 //-------------------------------------------------
687 //  parity_nmi_clr_w -
688 //-------------------------------------------------
689 
parity_nmi_clr_w(uint8_t data)690 void wangpc_state::parity_nmi_clr_w(uint8_t data)
691 {
692 	if (LOG) logerror("%s: Parity NMI clear\n", machine().describe_context());
693 }
694 
695 
696 //-------------------------------------------------
697 //  option_id_r -
698 //-------------------------------------------------
699 
option_id_r()700 uint8_t wangpc_state::option_id_r()
701 {
702 	/*
703 
704 	    bit     description
705 
706 	    0
707 	    1
708 	    2
709 	    3
710 	    4
711 	    5
712 	    6
713 	    7       FDC Interrupt Flag
714 
715 	*/
716 
717 	uint8_t data = 0;
718 
719 	// FDC interrupt
720 	data |= (m_fdc_dd0 || m_fdc_dd1 || (int) m_fdc->get_irq()) << 7;
721 
722 	return data;
723 }
724 
725 
726 
727 //**************************************************************************
728 //  ADDRESS MAPS
729 //**************************************************************************
730 
731 //-------------------------------------------------
732 //  ADDRESS_MAP( wangpc_mem )
733 //-------------------------------------------------
734 
wangpc_mem(address_map & map)735 void wangpc_state::wangpc_mem(address_map &map)
736 {
737 	map.unmap_value_high();
738 	map(0x00000, 0x1ffff).ram();
739 	map(0x40000, 0xf3fff).rw(m_bus, FUNC(wangpcbus_device::mrdc_r), FUNC(wangpcbus_device::amwc_w));
740 	map(0xfc000, 0xfffff).rom().region(I8086_TAG, 0);
741 }
742 
743 
744 //-------------------------------------------------
745 //  ADDRESS_MAP( wangpc_io )
746 //-------------------------------------------------
747 
wangpc_io(address_map & map)748 void wangpc_state::wangpc_io(address_map &map)
749 {
750 	map.unmap_value_high();
751 	map(0x1000, 0x1000).w(FUNC(wangpc_state::fdc_ctrl_w));
752 	map(0x1004, 0x1004).rw(FUNC(wangpc_state::deselect_drive1_r), FUNC(wangpc_state::deselect_drive1_w));
753 	map(0x1006, 0x1006).rw(FUNC(wangpc_state::select_drive1_r), FUNC(wangpc_state::select_drive1_w));
754 	map(0x1008, 0x1008).rw(FUNC(wangpc_state::deselect_drive2_r), FUNC(wangpc_state::deselect_drive2_w));
755 	map(0x100a, 0x100a).rw(FUNC(wangpc_state::select_drive2_r), FUNC(wangpc_state::select_drive2_w));
756 	map(0x100c, 0x100c).rw(FUNC(wangpc_state::motor1_off_r), FUNC(wangpc_state::motor1_off_w));
757 	map(0x100e, 0x100e).rw(FUNC(wangpc_state::motor1_on_r), FUNC(wangpc_state::motor1_on_w));
758 	map(0x1010, 0x1010).rw(FUNC(wangpc_state::motor2_off_r), FUNC(wangpc_state::motor2_off_w));
759 	map(0x1012, 0x1012).rw(FUNC(wangpc_state::motor2_on_r), FUNC(wangpc_state::motor2_on_w));
760 	map(0x1014, 0x1017).m(m_fdc, FUNC(upd765a_device::map)).umask16(0x00ff);
761 	map(0x1018, 0x1018).mirror(0x0002).rw(FUNC(wangpc_state::fdc_reset_r), FUNC(wangpc_state::fdc_reset_w));
762 	map(0x101c, 0x101c).mirror(0x0002).rw(FUNC(wangpc_state::fdc_tc_r), FUNC(wangpc_state::fdc_tc_w));
763 	map(0x1020, 0x1027).rw(m_ppi, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff);
764 	map(0x1028, 0x1029); //.w(FUNC(wangpc_state::)); (?)
765 	map(0x1040, 0x1047).rw(m_pit, FUNC(pit8253_device::read), FUNC(pit8253_device::write)).umask16(0x00ff);
766 	map(0x1060, 0x1063).rw(m_pic, FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff);
767 	map(0x1080, 0x1087).r(m_epci, FUNC(scn_pci_device::read)).umask16(0x00ff);
768 	map(0x1088, 0x108f).w(m_epci, FUNC(scn_pci_device::write)).umask16(0x00ff);
769 	map(0x10a0, 0x10bf).rw(m_dmac, FUNC(am9517a_device::read), FUNC(am9517a_device::write)).umask16(0x00ff);
770 	map(0x10c2, 0x10c7).w(FUNC(wangpc_state::dma_page_w)).umask16(0x00ff);
771 	map(0x10e0, 0x10e0).rw(FUNC(wangpc_state::status_r), FUNC(wangpc_state::timer0_irq_clr_w));
772 	map(0x10e2, 0x10e2).rw(FUNC(wangpc_state::timer2_irq_clr_r), FUNC(wangpc_state::nmi_mask_w));
773 	map(0x10e4, 0x10e4).rw(FUNC(wangpc_state::led_on_r), FUNC(wangpc_state::fpu_mask_w));
774 	map(0x10e6, 0x10e6).rw(FUNC(wangpc_state::dma_eop_clr_r), FUNC(wangpc_state::uart_tbre_clr_w));
775 	map(0x10e8, 0x10e8).rw(FUNC(wangpc_state::uart_r), FUNC(wangpc_state::uart_w));
776 	map(0x10ea, 0x10ea).rw(FUNC(wangpc_state::centronics_r), FUNC(wangpc_state::centronics_w));
777 	map(0x10ec, 0x10ec).rw(FUNC(wangpc_state::busy_clr_r), FUNC(wangpc_state::acknlg_clr_w));
778 	map(0x10ee, 0x10ee).rw(FUNC(wangpc_state::led_off_r), FUNC(wangpc_state::parity_nmi_clr_w));
779 	map(0x10fe, 0x10fe).r(FUNC(wangpc_state::option_id_r));
780 	map(0x1100, 0x1fff).rw(m_bus, FUNC(wangpcbus_device::sad_r), FUNC(wangpcbus_device::sad_w));
781 }
782 
783 
784 
785 //**************************************************************************
786 //  INPUT PORTS
787 //**************************************************************************
788 
789 //-------------------------------------------------
790 //  INPUT_PORTS( wangpc )
791 //-------------------------------------------------
792 
793 static INPUT_PORTS_START( wangpc )
794 	// keyboard defined in machine/wangpckb.c
795 
796 	PORT_START("SW")
797 	PORT_DIPNAME( 0x0f, 0x0f, "CPU Baud Rate" ) PORT_DIPLOCATION("SW:1,2,3,4")
798 	PORT_DIPSETTING(    0x0f, "19200" )
799 	PORT_DIPSETTING(    0x0e, "9600" )
800 	PORT_DIPSETTING(    0x0d, "7200" )
801 	PORT_DIPSETTING(    0x0c, "4800" )
802 	PORT_DIPSETTING(    0x0b, "3600" )
803 	PORT_DIPSETTING(    0x0a, "2400" )
804 	PORT_DIPSETTING(    0x09, "2000" )
805 	PORT_DIPSETTING(    0x08, "1800" )
806 	PORT_DIPSETTING(    0x07, "1200" )
807 	PORT_DIPSETTING(    0x06, "600" )
808 	PORT_DIPSETTING(    0x05, "300" )
809 	PORT_DIPSETTING(    0x04, "150" )
810 	PORT_DIPSETTING(    0x03, "134.5" )
811 	PORT_DIPSETTING(    0x02, "110" )
812 	PORT_DIPSETTING(    0x01, "75" )
813 	PORT_DIPSETTING(    0x00, "50 (Loop on Power-Up)" )
814 INPUT_PORTS_END
815 
816 
817 
818 //**************************************************************************
819 //  DEVICE CONFIGURATION
820 //**************************************************************************
821 
822 //-------------------------------------------------
823 //  I8237
824 //-------------------------------------------------
825 
update_fdc_tc()826 void wangpc_state::update_fdc_tc()
827 {
828 	if (m_enable_eop)
829 		m_fdc->tc_w(m_fdc_tc);
830 	else
831 		m_fdc->tc_w(0);
832 }
833 
WRITE_LINE_MEMBER(wangpc_state::hrq_w)834 WRITE_LINE_MEMBER( wangpc_state::hrq_w )
835 {
836 	m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
837 
838 	m_dmac->hack_w(state);
839 }
840 
WRITE_LINE_MEMBER(wangpc_state::eop_w)841 WRITE_LINE_MEMBER( wangpc_state::eop_w )
842 {
843 	if (m_dack == 2)
844 	{
845 		m_fdc_tc = state;
846 		update_fdc_tc();
847 	}
848 
849 	if (state)
850 	{
851 		if (LOG) logerror("EOP set\n");
852 
853 		m_dma_eop = 0;
854 		check_level2_interrupts();
855 	}
856 
857 	m_bus->tc_w(state);
858 }
859 
memr_r(offs_t offset)860 uint8_t wangpc_state::memr_r(offs_t offset)
861 {
862 	address_space &program = m_maincpu->space(AS_PROGRAM);
863 	offs_t addr = (m_dma_page[m_dack] << 16) | offset;
864 
865 	return program.read_byte(addr);
866 }
867 
memw_w(offs_t offset,uint8_t data)868 void wangpc_state::memw_w(offs_t offset, uint8_t data)
869 {
870 	address_space &program = m_maincpu->space(AS_PROGRAM);
871 	offs_t addr = (m_dma_page[m_dack] << 16) | offset;
872 
873 	program.write_byte(addr, data);
874 }
875 
ior2_r()876 uint8_t wangpc_state::ior2_r()
877 {
878 	if (m_disable_dreq2)
879 		return m_bus->dack_r(2);
880 	else
881 		return m_fdc->dma_r();
882 }
883 
iow2_w(uint8_t data)884 void wangpc_state::iow2_w(uint8_t data)
885 {
886 	if (m_disable_dreq2)
887 		m_bus->dack_w(2, data);
888 	else
889 		m_fdc->dma_w(data);
890 }
891 
WRITE_LINE_MEMBER(wangpc_state::dack0_w)892 WRITE_LINE_MEMBER( wangpc_state::dack0_w )
893 {
894 	if (!state) m_dack = 0;
895 }
896 
WRITE_LINE_MEMBER(wangpc_state::dack1_w)897 WRITE_LINE_MEMBER( wangpc_state::dack1_w )
898 {
899 	if (!state) m_dack = 1;
900 }
901 
WRITE_LINE_MEMBER(wangpc_state::dack2_w)902 WRITE_LINE_MEMBER( wangpc_state::dack2_w )
903 {
904 	if (!state) m_dack = 2;
905 }
906 
WRITE_LINE_MEMBER(wangpc_state::dack3_w)907 WRITE_LINE_MEMBER( wangpc_state::dack3_w )
908 {
909 	if (!state) m_dack = 3;
910 }
911 
912 //-------------------------------------------------
913 //  pic8259_interface pic_intf
914 //-------------------------------------------------
915 
check_level1_interrupts()916 void wangpc_state::check_level1_interrupts()
917 {
918 	int state = !m_timer2_irq || !m_epci->rxrdy_r() || !m_epci->txemt_dschg_r() || !m_centronics_ack || !m_dav || m_centronics_busy;
919 
920 	m_pic->ir1_w(state);
921 }
922 
check_level2_interrupts()923 void wangpc_state::check_level2_interrupts()
924 {
925 	int state = !m_dma_eop || m_uart_dr || m_uart_tbre || m_fdc_dd0 || m_fdc_dd1 || m_fdc->get_irq() || m_fpu_irq || m_bus_irq2;
926 
927 	m_pic->ir2_w(state);
928 }
929 
930 //-------------------------------------------------
931 //  I8255A INTERFACE
932 //-------------------------------------------------
933 
ppi_pa_r()934 uint8_t wangpc_state::ppi_pa_r()
935 {
936 	/*
937 
938 	    bit     description
939 
940 	    0       /POWER ON
941 	    1       /SMART
942 	    2       /DATA AVAILABLE
943 	    3       SLCT
944 	    4       BUSY
945 	    5       /FAULT
946 	    6       PE
947 	    7       ACKNOWLEDGE
948 
949 	*/
950 
951 	uint8_t data = 0x08 | 0x02 | 0x01;
952 
953 	data |= m_dav << 2;
954 	data |= m_centronics_busy << 4;
955 	data |= m_centronics_fault << 5;
956 	data |= m_centronics_perror << 6;
957 	data |= m_centronics_ack << 7;
958 
959 	return data;
960 }
961 
ppi_pb_r()962 uint8_t wangpc_state::ppi_pb_r()
963 {
964 	/*
965 
966 	    bit     description
967 
968 	    0       /TIMER 2 INTERRUPT
969 	    1       /SERIAL INTERRUPT
970 	    2       /PARALLEL PORT INTERRUPT
971 	    3       /DMA INTERRUPT
972 	    4       KBD INTERRUPT TRANSMIT
973 	    5       KBD INTERRUPT RECEIVE
974 	    6       FLOPPY DISK INTERRUPT
975 	    7       8087 INTERRUPT
976 
977 	*/
978 
979 	uint8_t data = 0;
980 
981 	// timer 2 interrupt
982 	data |= m_timer2_irq;
983 
984 	// serial interrupt
985 	data |= (m_epci->rxrdy_r() & m_epci->txemt_dschg_r()) << 1;
986 
987 	// parallel port interrupt
988 	data |= m_centronics_ack << 2;
989 
990 	// DMA interrupt
991 	data |= m_dma_eop << 3;
992 
993 	// keyboard interrupt
994 	data |= m_uart_tbre << 4;
995 	data |= m_uart_dr << 5;
996 
997 	// FDC interrupt
998 	data |= m_fdc->get_irq() << 6;
999 
1000 	// 8087 interrupt
1001 	data |= m_fpu_irq << 7;
1002 
1003 	return data;
1004 }
1005 
ppi_pc_r()1006 uint8_t wangpc_state::ppi_pc_r()
1007 {
1008 	/*
1009 
1010 	    bit     description
1011 
1012 	    0
1013 	    1
1014 	    2
1015 	    3
1016 	    4       SW1
1017 	    5       SW2
1018 	    6       SW3
1019 	    7       SW4
1020 
1021 	*/
1022 
1023 	return m_sw->read() << 4;
1024 }
1025 
ppi_pc_w(uint8_t data)1026 void wangpc_state::ppi_pc_w(uint8_t data)
1027 {
1028 	/*
1029 
1030 	    bit     description
1031 
1032 	    0       /USR0 (pin 14)
1033 	    1       /USR1 (pin 36)
1034 	    2       /RESET (pin 31)
1035 	    3       Unassigned
1036 	    4
1037 	    5
1038 	    6
1039 	    7
1040 
1041 	*/
1042 
1043 	m_centronics->write_autofd(BIT(data, 0));
1044 	m_centronics->write_select_in(BIT(data, 1));
1045 	m_centronics->write_init(BIT(data, 2));
1046 }
1047 
WRITE_LINE_MEMBER(wangpc_state::pit2_w)1048 WRITE_LINE_MEMBER( wangpc_state::pit2_w )
1049 {
1050 	if (state)
1051 	{
1052 		m_timer2_irq = 0;
1053 		check_level1_interrupts();
1054 	}
1055 }
1056 
1057 //-------------------------------------------------
1058 //  IM6402_INTERFACE( uart_intf )
1059 //-------------------------------------------------
1060 
WRITE_LINE_MEMBER(wangpc_state::uart_dr_w)1061 WRITE_LINE_MEMBER( wangpc_state::uart_dr_w )
1062 {
1063 	if (state)
1064 	{
1065 		if (LOG) logerror("DR set\n");
1066 
1067 		m_uart_dr = 1;
1068 		check_level2_interrupts();
1069 	}
1070 }
1071 
WRITE_LINE_MEMBER(wangpc_state::uart_tbre_w)1072 WRITE_LINE_MEMBER( wangpc_state::uart_tbre_w )
1073 {
1074 	if (state)
1075 	{
1076 		if (LOG) logerror("TBRE set\n");
1077 
1078 		m_uart_tbre = 1;
1079 		check_level2_interrupts();
1080 	}
1081 }
1082 
1083 
1084 //-------------------------------------------------
1085 //  SCN2661_INTERFACE( epci_intf )
1086 //-------------------------------------------------
1087 
WRITE_LINE_MEMBER(wangpc_state::epci_irq_w)1088 WRITE_LINE_MEMBER( wangpc_state::epci_irq_w )
1089 {
1090 	check_level1_interrupts();
1091 }
1092 
1093 
1094 //-------------------------------------------------
1095 //  upd765_interface fdc_intf
1096 //-------------------------------------------------
1097 
wangpc_floppies(device_slot_interface & device)1098 static void wangpc_floppies(device_slot_interface &device)
1099 {
1100 	device.option_add("525dd", FLOPPY_525_DD);
1101 }
1102 
FLOPPY_FORMATS_MEMBER(wangpc_state::floppy_formats)1103 FLOPPY_FORMATS_MEMBER( wangpc_state::floppy_formats )
1104 	FLOPPY_PC_FORMAT
1105 FLOPPY_FORMATS_END
1106 
1107 WRITE_LINE_MEMBER( wangpc_state::fdc_irq )
1108 {
1109 	if (LOG) logerror("FDC INT %u\n", state);
1110 
1111 	check_level2_interrupts();
1112 }
1113 
WRITE_LINE_MEMBER(wangpc_state::fdc_drq)1114 WRITE_LINE_MEMBER( wangpc_state::fdc_drq )
1115 {
1116 	if (LOG) logerror("FDC DRQ %u\n", state);
1117 
1118 	m_fdc_drq = state;
1119 	update_fdc_drq();
1120 }
1121 
update_fdc_drq()1122 void wangpc_state::update_fdc_drq()
1123 {
1124 	if (m_disable_dreq2)
1125 		m_dmac->dreq2_w(1);
1126 	else
1127 		m_dmac->dreq2_w(!m_fdc_drq);
1128 }
1129 
1130 
1131 //-------------------------------------------------
1132 //  centronics_interface centronics_intf
1133 //-------------------------------------------------
1134 
WRITE_LINE_MEMBER(wangpc_state::write_centronics_ack)1135 WRITE_LINE_MEMBER( wangpc_state::write_centronics_ack )
1136 {
1137 	if (LOG) logerror("ACKNLG %u\n", state);
1138 
1139 	m_centronics_ack = state;
1140 
1141 	check_level1_interrupts();
1142 }
1143 
WRITE_LINE_MEMBER(wangpc_state::write_centronics_busy)1144 WRITE_LINE_MEMBER( wangpc_state::write_centronics_busy )
1145 {
1146 	if (LOG) logerror("BUSY %u\n", state);
1147 
1148 	m_centronics_busy = state;
1149 
1150 	check_level1_interrupts();
1151 }
1152 
WRITE_LINE_MEMBER(wangpc_state::write_centronics_fault)1153 WRITE_LINE_MEMBER( wangpc_state::write_centronics_fault )
1154 {
1155 	m_centronics_fault = state;
1156 }
1157 
WRITE_LINE_MEMBER(wangpc_state::write_centronics_perror)1158 WRITE_LINE_MEMBER( wangpc_state::write_centronics_perror )
1159 {
1160 	m_centronics_perror = state;
1161 }
1162 
1163 //-------------------------------------------------
1164 //  WANGPC_BUS_INTERFACE( kb_intf )
1165 //-------------------------------------------------
1166 
WRITE_LINE_MEMBER(wangpc_state::bus_irq2_w)1167 WRITE_LINE_MEMBER( wangpc_state::bus_irq2_w )
1168 {
1169 	if (LOG) logerror("Bus IRQ2 %u\n", state);
1170 
1171 	m_bus_irq2 = state;
1172 
1173 	check_level2_interrupts();
1174 }
1175 
1176 
1177 
1178 //**************************************************************************
1179 //  MACHINE INITIALIZATION
1180 //**************************************************************************
1181 
1182 //-------------------------------------------------
1183 //  MACHINE_START( wangpc )
1184 //-------------------------------------------------
1185 
machine_start()1186 void wangpc_state::machine_start()
1187 {
1188 	// connect floppy callbacks
1189 	m_floppy0->setup_load_cb(floppy_image_device::load_cb(&wangpc_state::on_disk0_load, this));
1190 	m_floppy0->setup_unload_cb(floppy_image_device::unload_cb(&wangpc_state::on_disk0_unload, this));
1191 	m_floppy1->setup_load_cb(floppy_image_device::load_cb(&wangpc_state::on_disk1_load, this));
1192 	m_floppy1->setup_unload_cb(floppy_image_device::unload_cb(&wangpc_state::on_disk1_unload, this));
1193 
1194 	m_led_diagnostic.resolve();
1195 
1196 	// state saving
1197 	save_item(NAME(m_dma_page));
1198 	save_item(NAME(m_dack));
1199 	save_item(NAME(m_timer2_irq));
1200 	save_item(NAME(m_centronics_ack));
1201 	save_item(NAME(m_centronics_busy));
1202 	save_item(NAME(m_centronics_fault));
1203 	save_item(NAME(m_centronics_perror));
1204 	save_item(NAME(m_dav));
1205 	save_item(NAME(m_dma_eop));
1206 	save_item(NAME(m_uart_dr));
1207 	save_item(NAME(m_uart_tbre));
1208 	save_item(NAME(m_fpu_irq));
1209 	save_item(NAME(m_bus_irq2));
1210 	save_item(NAME(m_enable_eop));
1211 	save_item(NAME(m_disable_dreq2));
1212 	save_item(NAME(m_fdc_drq));
1213 	save_item(NAME(m_ds1));
1214 	save_item(NAME(m_ds2));
1215 }
1216 
1217 
machine_reset()1218 void wangpc_state::machine_reset()
1219 {
1220 	// initialize UART
1221 	m_uart->cls1_w(1);
1222 	m_uart->cls2_w(1);
1223 	m_uart->pi_w(1);
1224 	m_uart->sbs_w(1);
1225 	m_uart->crl_w(1);
1226 }
1227 
1228 
1229 //-------------------------------------------------
1230 //  on_disk0_change -
1231 //-------------------------------------------------
1232 
on_disk0_load(floppy_image_device * image)1233 image_init_result wangpc_state::on_disk0_load(floppy_image_device *image)
1234 {
1235 	on_disk0_unload(image);
1236 
1237 	return image_init_result::PASS;
1238 }
1239 
on_disk0_unload(floppy_image_device * image)1240 void wangpc_state::on_disk0_unload(floppy_image_device *image)
1241 {
1242 	if (LOG) logerror("Door 1 disturbed\n");
1243 
1244 	m_fdc_dd0 = 1;
1245 	check_level2_interrupts();
1246 }
1247 
1248 
1249 //-------------------------------------------------
1250 //  on_disk1_change -
1251 //-------------------------------------------------
1252 
on_disk1_load(floppy_image_device * image)1253 image_init_result wangpc_state::on_disk1_load(floppy_image_device *image)
1254 {
1255 	on_disk1_unload(image);
1256 
1257 	return image_init_result::PASS;
1258 }
1259 
on_disk1_unload(floppy_image_device * image)1260 void wangpc_state::on_disk1_unload(floppy_image_device *image)
1261 {
1262 	if (LOG) logerror("Door 2 disturbed\n");
1263 
1264 	m_fdc_dd1 = 1;
1265 	check_level2_interrupts();
1266 }
1267 
1268 
1269 
1270 //**************************************************************************
1271 //  MACHINE DRIVERS
1272 //**************************************************************************
1273 
1274 //-------------------------------------------------
1275 //  machine_config( wangpc )
1276 //-------------------------------------------------
1277 
wangpc(machine_config & config)1278 void wangpc_state::wangpc(machine_config &config)
1279 {
1280 	I8086(config, m_maincpu, 8000000);
1281 	m_maincpu->set_addrmap(AS_PROGRAM, &wangpc_state::wangpc_mem);
1282 	m_maincpu->set_addrmap(AS_IO, &wangpc_state::wangpc_io);
1283 	m_maincpu->set_irq_acknowledge_callback(I8259A_TAG, FUNC(pic8259_device::inta_cb));
1284 	//config.m_perfect_cpu_quantum = subtag(I8086_TAG);
1285 
1286 	// devices
1287 	AM9517A(config, m_dmac, 4000000);
1288 	m_dmac->out_hreq_callback().set(FUNC(wangpc_state::hrq_w));
1289 	m_dmac->out_eop_callback().set(FUNC(wangpc_state::eop_w));
1290 	m_dmac->in_memr_callback().set(FUNC(wangpc_state::memr_r));
1291 	m_dmac->out_memw_callback().set(FUNC(wangpc_state::memw_w));
1292 	m_dmac->in_ior_callback<1>().set(m_bus, FUNC(wangpcbus_device::dack1_r));
1293 	m_dmac->in_ior_callback<2>().set(FUNC(wangpc_state::ior2_r));
1294 	m_dmac->in_ior_callback<3>().set(m_bus, FUNC(wangpcbus_device::dack3_r));
1295 	m_dmac->out_iow_callback<1>().set(m_bus, FUNC(wangpcbus_device::dack1_w));
1296 	m_dmac->out_iow_callback<2>().set(FUNC(wangpc_state::iow2_w));
1297 	m_dmac->out_iow_callback<3>().set(m_bus, FUNC(wangpcbus_device::dack3_w));
1298 	m_dmac->out_dack_callback<0>().set(FUNC(wangpc_state::dack0_w));
1299 	m_dmac->out_dack_callback<1>().set(FUNC(wangpc_state::dack1_w));
1300 	m_dmac->out_dack_callback<2>().set(FUNC(wangpc_state::dack2_w));
1301 	m_dmac->out_dack_callback<3>().set(FUNC(wangpc_state::dack3_w));
1302 
1303 	PIC8259(config, m_pic, 0);
1304 	m_pic->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
1305 
1306 	I8255A(config, m_ppi, 0);
1307 	m_ppi->in_pa_callback().set(FUNC(wangpc_state::ppi_pa_r));
1308 	m_ppi->in_pb_callback().set(FUNC(wangpc_state::ppi_pb_r));
1309 	m_ppi->in_pc_callback().set(FUNC(wangpc_state::ppi_pc_r));
1310 	m_ppi->out_pc_callback().set(FUNC(wangpc_state::ppi_pc_w));
1311 
1312 	PIT8253(config, m_pit, 0);
1313 	m_pit->set_clk<0>(500000);
1314 	m_pit->out_handler<0>().set(m_pic, FUNC(pic8259_device::ir0_w));
1315 	m_pit->set_clk<1>(2000000);
1316 	m_pit->set_clk<2>(500000);
1317 	m_pit->out_handler<2>().set(FUNC(wangpc_state::pit2_w));
1318 
1319 	IM6402(config, m_uart, 62500*16, 62500*16);
1320 	m_uart->tro_callback().set("wangpckb", FUNC(wangpc_keyboard_device::write_rxd));
1321 	m_uart->dr_callback().set(FUNC(wangpc_state::uart_dr_w));
1322 	m_uart->tbre_callback().set(FUNC(wangpc_state::uart_tbre_w));
1323 
1324 	SCN2661C(config, m_epci, 5'068'800);
1325 	m_epci->txd_handler().set(RS232_TAG, FUNC(rs232_port_device::write_txd));
1326 	m_epci->rxrdy_handler().set(FUNC(wangpc_state::epci_irq_w));
1327 	m_epci->rts_handler().set(RS232_TAG, FUNC(rs232_port_device::write_rts));
1328 	m_epci->dtr_handler().set(RS232_TAG, FUNC(rs232_port_device::write_dtr));
1329 	m_epci->txemt_dschg_handler().set(FUNC(wangpc_state::epci_irq_w));
1330 
1331 	UPD765A(config, m_fdc, 8'000'000, false, false);
1332 	m_fdc->intrq_wr_callback().set(FUNC(wangpc_state::fdc_irq));
1333 	m_fdc->drq_wr_callback().set(FUNC(wangpc_state::fdc_drq));
1334 	FLOPPY_CONNECTOR(config, UPD765_TAG ":0", wangpc_floppies, "525dd", wangpc_state::floppy_formats);
1335 	FLOPPY_CONNECTOR(config, UPD765_TAG ":1", wangpc_floppies, "525dd", wangpc_state::floppy_formats);
1336 
1337 	CENTRONICS(config, m_centronics, centronics_devices, "printer");
1338 	m_centronics->set_data_input_buffer(m_cent_data_in);
1339 	m_centronics->ack_handler().set(FUNC(wangpc_state::write_centronics_ack));
1340 	m_centronics->busy_handler().set(FUNC(wangpc_state::write_centronics_busy));
1341 	m_centronics->fault_handler().set(FUNC(wangpc_state::write_centronics_fault));
1342 	m_centronics->perror_handler().set(FUNC(wangpc_state::write_centronics_perror));
1343 
1344 	INPUT_BUFFER(config, m_cent_data_in);
1345 
1346 	OUTPUT_LATCH(config, m_cent_data_out);
1347 	m_centronics->set_output_latch(*m_cent_data_out);
1348 
1349 	rs232_port_device &rs232(RS232_PORT(config, RS232_TAG, default_rs232_devices, nullptr));
1350 	rs232.rxd_handler().set(m_epci, FUNC(scn_pci_device::rxd_w));
1351 	rs232.cts_handler().set(m_epci, FUNC(scn_pci_device::cts_w));
1352 	rs232.dsr_handler().set(m_epci, FUNC(scn_pci_device::dsr_w));
1353 	rs232.dcd_handler().set(m_epci, FUNC(scn_pci_device::dcd_w));
1354 
1355 	WANGPC_KEYBOARD(config, "wangpckb").txd_handler().set(m_uart, FUNC(im6402_device::write_rri));
1356 
1357 	// bus
1358 	WANGPC_BUS(config, m_bus, 0);
1359 	m_bus->irq2_wr_callback().set(FUNC(wangpc_state::bus_irq2_w));
1360 	m_bus->irq3_wr_callback().set(m_pic, FUNC(pic8259_device::ir3_w));
1361 	m_bus->irq4_wr_callback().set(m_pic, FUNC(pic8259_device::ir4_w));
1362 	m_bus->irq5_wr_callback().set(m_pic, FUNC(pic8259_device::ir5_w));
1363 	m_bus->irq6_wr_callback().set(m_pic, FUNC(pic8259_device::ir6_w));
1364 	m_bus->irq7_wr_callback().set(m_pic, FUNC(pic8259_device::ir7_w));
1365 	m_bus->drq1_wr_callback().set(m_dmac, FUNC(am9517a_device::dreq1_w));
1366 	m_bus->drq2_wr_callback().set(m_dmac, FUNC(am9517a_device::dreq2_w));
1367 	m_bus->drq3_wr_callback().set(m_dmac, FUNC(am9517a_device::dreq3_w));
1368 	m_bus->ioerror_wr_callback().set_inputline(m_maincpu, INPUT_LINE_NMI);
1369 	WANGPC_BUS_SLOT(config, "slot1", m_bus, wangpc_cards, nullptr, 1);
1370 	WANGPC_BUS_SLOT(config, "slot2", m_bus, wangpc_cards, "mvc", 2);
1371 	WANGPC_BUS_SLOT(config, "slot3", m_bus, wangpc_cards, nullptr, 3);
1372 	WANGPC_BUS_SLOT(config, "slot4", m_bus, wangpc_cards, nullptr, 4);
1373 	WANGPC_BUS_SLOT(config, "slot5", m_bus, wangpc_cards, nullptr, 5);
1374 
1375 	// internal ram
1376 	RAM(config, RAM_TAG).set_default_size("128K");
1377 
1378 	// software list
1379 	SOFTWARE_LIST(config, "flop_list").set_original("wangpc");
1380 }
1381 
1382 
1383 
1384 //**************************************************************************
1385 //  ROM DEFINITIONS
1386 //**************************************************************************
1387 
1388 //-------------------------------------------------
1389 //  ROM( wangpc )
1390 //-------------------------------------------------
1391 
1392 ROM_START( wangpc )
1393 	ROM_REGION16_LE( 0x4000, I8086_TAG, 0)
1394 	ROM_LOAD16_BYTE( "0001 r2.l94", 0x0001, 0x2000, CRC(f9f41304) SHA1(1815295809ef11573d724ede47446f9ac7aee713) )
1395 	ROM_LOAD16_BYTE( "379-0000 r2.l115", 0x0000, 0x2000, CRC(67b37684) SHA1(70d9f68eb88cc2bc9f53f949cc77411c09a4266e) )
1396 ROM_END
1397 
1398 
1399 
1400 //**************************************************************************
1401 //  GAME DRIVERS
1402 //**************************************************************************
1403 
1404 COMP( 1985, wangpc, 0, 0, wangpc, wangpc, wangpc_state, empty_init, "Wang Laboratories", "Wang Professional Computer", MACHINE_SUPPORTS_SAVE )
1405