summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/pcshare.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/pcshare.c')
-rw-r--r--src/mame/machine/pcshare.c572
1 files changed, 572 insertions, 0 deletions
diff --git a/src/mame/machine/pcshare.c b/src/mame/machine/pcshare.c
new file mode 100644
index 00000000000..da3fa1d02bb
--- /dev/null
+++ b/src/mame/machine/pcshare.c
@@ -0,0 +1,572 @@
+/***************************************************************************
+
+ machine/pc.c
+
+ Functions to emulate general aspects of the machine
+ (RAM, ROM, interrupts, I/O ports)
+
+ The information herein is heavily based on
+ 'Ralph Browns Interrupt List'
+ Release 52, Last Change 20oct96
+
+ TODO:
+ clean up (maybe split) the different pieces of hardware
+ PIC, PIT, DMA... add support for LPT, COM (almost done)
+ emulation of a serial mouse on a COM port (almost done)
+ support for Game Controller port at 0x0201
+ support for XT harddisk (under the way, see machine/pc_hdc.c)
+ whatever 'hardware' comes to mind,
+ maybe SoundBlaster? EGA? VGA?
+
+***************************************************************************/
+
+#include "driver.h"
+#include "memconv.h"
+#include "machine/8255ppi.h"
+
+#include "machine/pic8259.h"
+#include "machine/pit8253.h"
+#include "machine/mc146818.h"
+#include "machine/pcshare.h"
+
+#include "machine/8237dma.h"
+#include "machine/pckeybrd.h"
+
+#ifdef MESS
+#include "machine/uart8250.h"
+#include "video/pc_vga.h"
+#include "video/pc_cga.h"
+#include "video/pc_mda.h"
+#include "video/pc_aga.h"
+
+#include "includes/pc_mouse.h"
+#include "machine/pc_fdc.h"
+
+#include "includes/pclpt.h"
+#include "includes/centroni.h"
+
+#include "machine/pc_hdc.h"
+#include "machine/nec765.h"
+#include "audio/pc.h"
+
+#include "mscommon.h"
+#endif /* MESS */
+
+#define VERBOSE_DBG 0 /* general debug messages */
+#if VERBOSE_DBG
+#define DBG_LOG(N,M,A) \
+ if(VERBOSE_DBG>=N){ if( M )logerror("%11.6f: %-24s",attotime_to_double(timer_get_time()),(char*)M ); logerror A; }
+#else
+#define DBG_LOG(n,m,a)
+#endif
+
+#define VERBOSE_JOY 0 /* JOY (joystick port) */
+
+#if VERBOSE_JOY
+#define LOG(LEVEL,N,M,A) \
+#define JOY_LOG(N,M,A) \
+ if(VERBOSE_JOY>=N){ if( M )logerror("%11.6f: %-24s",attotime_to_double(timer_get_time()),(char*)M ); logerror A; }
+#else
+#define JOY_LOG(n,m,a)
+#endif
+
+#define FDC_DMA 2
+
+
+static emu_timer *pc_keyboard_timer;
+
+static TIMER_CALLBACK( pc_keyb_timer );
+
+#define LOG_PORT80 0
+
+
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef MESS
+/* called when a interrupt is set/cleared from com hardware */
+static void pc_com_interrupt(int nr, int state)
+{
+ static const int irq[4] = {4, 3, 4, 3};
+
+ /* issue COM1/3 IRQ4, COM2/4 IRQ3 */
+ pic8259_set_irq_line(0, irq[nr], state);
+}
+
+/* called when com registers read/written - used to update peripherals that
+are connected */
+static void pc_com_refresh_connected(int n, int data)
+{
+ /* mouse connected to this port? */
+ if (readinputport(3) & (0x80>>n))
+ pc_mouse_handshake_in(n,data);
+}
+
+/* PC interface to PC-com hardware. Done this way because PCW16 also
+uses PC-com hardware and doesn't have the same setup! */
+static uart8250_interface com_interface[4]=
+{
+ {
+ TYPE8250,
+ 1843200,
+ pc_com_interrupt,
+ NULL,
+ pc_com_refresh_connected
+ },
+ {
+ TYPE8250,
+ 1843200,
+ pc_com_interrupt,
+ NULL,
+ pc_com_refresh_connected
+ },
+ {
+ TYPE8250,
+ 1843200,
+ pc_com_interrupt,
+ NULL,
+ pc_com_refresh_connected
+ },
+ {
+ TYPE8250,
+ 1843200,
+ pc_com_interrupt,
+ NULL,
+ pc_com_refresh_connected
+ }
+};
+#endif /* MESS */
+
+
+
+static void pc_timer0_w(int state)
+{
+ pic8259_set_irq_line(0, 0, state);
+}
+
+
+
+/*
+ * timer0 heartbeat IRQ
+ * timer1 DRAM refresh (ignored)
+ * timer2 PIO port C pin 4 and speaker polling
+ */
+static const struct pit8253_config pc_pit8253_config =
+{
+ TYPE8253,
+ {
+ {
+ 4772720/4, /* heartbeat IRQ */
+ pc_timer0_w,
+ NULL
+ }, {
+ 4772720/4, /* dram refresh */
+ NULL,
+ NULL
+ }, {
+ 4772720/4, /* pio port c pin 4, and speaker polling enough */
+ NULL,
+#ifdef MESS
+ pc_sh_speaker_change_clock
+#else
+ NULL //pc_sh_speaker_change_clock
+#endif /* MESS */
+ }
+ }
+};
+
+static const struct pit8253_config pc_pit8254_config =
+{
+ TYPE8254,
+ {
+ {
+ 4772720/4, /* heartbeat IRQ */
+ pc_timer0_w,
+ NULL
+ }, {
+ 4772720/4, /* dram refresh */
+ NULL,
+ NULL
+ }, {
+ 4772720/4, /* pio port c pin 4, and speaker polling enough */
+ NULL,
+#ifdef MESS
+ pc_sh_speaker_change_clock
+#else
+ NULL //pc_sh_speaker_change_clock
+#endif /* MESS */
+ }
+ }
+};
+
+
+#ifdef MESS
+static PC_LPT_CONFIG lpt_config[3]={
+ {
+ 1,
+ LPT_UNIDIRECTIONAL,
+ NULL
+ },
+ {
+ 1,
+ LPT_UNIDIRECTIONAL,
+ NULL
+ },
+ {
+ 1,
+ LPT_UNIDIRECTIONAL,
+ NULL
+ }
+};
+
+static CENTRONICS_CONFIG cent_config[3]={
+ {
+ PRINTER_IBM,
+ pc_lpt_handshake_in
+ },
+ {
+ PRINTER_IBM,
+ pc_lpt_handshake_in
+ },
+ {
+ PRINTER_IBM,
+ pc_lpt_handshake_in
+ }
+};
+#endif
+
+
+
+/*************************************************************************
+ *
+ * PC DMA stuff
+ *
+ *************************************************************************/
+
+static UINT8 dma_offset[2][4];
+static UINT8 at_pages[0x10];
+static offs_t pc_page_offset_mask;
+
+
+
+READ8_HANDLER(pc_page_r)
+{
+ return 0xFF;
+}
+
+
+
+WRITE8_HANDLER(pc_page_w)
+{
+ switch(offset % 4) {
+ case 1:
+ dma_offset[0][2] = data;
+ break;
+ case 2:
+ dma_offset[0][3] = data;
+ break;
+ case 3:
+ dma_offset[0][0] = dma_offset[0][1] = data;
+ break;
+ }
+}
+
+
+
+READ16_HANDLER(pc_page16le_r) { return read16le_with_read8_handler(pc_page_r, offset, mem_mask); }
+WRITE16_HANDLER(pc_page16le_w) { write16le_with_write8_handler(pc_page_w, offset, data, mem_mask); }
+
+
+
+READ8_HANDLER(at_page8_r)
+{
+ UINT8 data = at_pages[offset % 0x10];
+
+ switch(offset % 8) {
+ case 1:
+ data = dma_offset[(offset / 8) & 1][2];
+ break;
+ case 2:
+ data = dma_offset[(offset / 8) & 1][3];
+ break;
+ case 3:
+ data = dma_offset[(offset / 8) & 1][1];
+ break;
+ case 7:
+ data = dma_offset[(offset / 8) & 1][0];
+ break;
+ }
+ return data;
+}
+
+
+
+WRITE8_HANDLER(at_page8_w)
+{
+ at_pages[offset % 0x10] = data;
+
+ if (LOG_PORT80 && (offset == 0))
+ logerror(" at_page8_w(): Port 80h <== 0x%02x (PC=0x%08x)\n", data, (unsigned) activecpu_get_reg(REG_PC));
+
+ switch(offset % 8) {
+ case 1:
+ dma_offset[(offset / 8) & 1][2] = data;
+ break;
+ case 2:
+ dma_offset[(offset / 8) & 1][3] = data;
+ break;
+ case 3:
+ dma_offset[(offset / 8) & 1][1] = data;
+ break;
+ case 7:
+ dma_offset[(offset / 8) & 1][0] = data;
+ break;
+ }
+}
+
+
+
+READ32_HANDLER(at_page32_r)
+{
+ return read32le_with_read8_handler(at_page8_r, offset, mem_mask);
+}
+
+
+
+WRITE32_HANDLER(at_page32_w)
+{
+ write32le_with_write8_handler(at_page8_w, offset, data, mem_mask);
+}
+
+
+
+static UINT8 pc_dma_read_byte(int channel, offs_t offset)
+{
+ UINT8 result;
+ offs_t page_offset = (((offs_t) dma_offset[0][channel]) << 16)
+ & pc_page_offset_mask;
+
+ cpuintrf_push_context(0);
+ result = program_read_byte(page_offset + offset);
+ cpuintrf_pop_context();
+
+ return result;
+}
+
+
+
+static void pc_dma_write_byte(int channel, offs_t offset, UINT8 data)
+{
+ offs_t page_offset = (((offs_t) dma_offset[0][channel]) << 16)
+ & pc_page_offset_mask;
+
+ cpuintrf_push_context(0);
+ program_write_byte(page_offset + offset, data);
+ cpuintrf_pop_context();
+}
+
+
+
+static struct dma8237_interface pc_dma =
+{
+ 0,
+ 1.0e-6, // 1us
+
+ pc_dma_read_byte,
+ pc_dma_write_byte,
+
+#ifdef MESS
+ { 0, 0, pc_fdc_dack_r, pc_hdc_dack_r },
+ { 0, 0, pc_fdc_dack_w, pc_hdc_dack_w },
+ pc_fdc_set_tc_state
+#else
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ 0
+#endif
+};
+
+
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef MESS
+static void pc_fdc_interrupt(int state)
+{
+ pic8259_set_irq_line(0, 6, state);
+}
+
+
+
+static void pc_fdc_dma_drq(int state, int read_)
+{
+ dma8237_drq_write(0, FDC_DMA, state);
+}
+
+
+
+static const struct pc_fdc_interface fdc_interface =
+{
+ NEC765A,
+ pc_fdc_interrupt,
+ pc_fdc_dma_drq,
+};
+#endif /* MESS */
+
+
+
+/* ----------------------------------------------------------------------- */
+
+static void pc_pic_set_int_line(int which, int interrupt)
+{
+ switch(which)
+ {
+ case 0:
+ /* Master */
+ cpunum_set_input_line(0, 0, interrupt ? HOLD_LINE : CLEAR_LINE);
+ break;
+
+ case 1:
+ /* Slave */
+ pic8259_set_irq_line(0, 2, interrupt);
+ break;
+ }
+}
+
+
+
+void init_pc_common(UINT32 flags)
+{
+#ifdef MESS
+ /* MESS managed RAM */
+ if (mess_ram)
+ memory_set_bankptr(10, mess_ram);
+#endif /* MESS */
+
+ /* PIT */
+ if (flags & PCCOMMON_TIMER_8254)
+ pit8253_init(1, &pc_pit8254_config);
+ else if (flags & PCCOMMON_TIMER_8253)
+ pit8253_init(1, &pc_pit8253_config);
+
+#ifdef MESS
+ /* FDC/HDC hardware */
+ pc_fdc_init(&fdc_interface);
+ pc_hdc_setup();
+
+ /* com hardware */
+ uart8250_init(0, com_interface);
+ uart8250_reset(0);
+ uart8250_init(1, com_interface+1);
+ uart8250_reset(1);
+ uart8250_init(2, com_interface+2);
+ uart8250_reset(2);
+ uart8250_init(3, com_interface+3);
+ uart8250_reset(3);
+
+ pc_lpt_config(0, lpt_config);
+ centronics_config(0, cent_config);
+ pc_lpt_set_device(0, &CENTRONICS_PRINTER_DEVICE);
+ pc_lpt_config(1, lpt_config+1);
+ centronics_config(1, cent_config+1);
+ pc_lpt_set_device(1, &CENTRONICS_PRINTER_DEVICE);
+ pc_lpt_config(2, lpt_config+2);
+ centronics_config(2, cent_config+2);
+ pc_lpt_set_device(2, &CENTRONICS_PRINTER_DEVICE);
+
+ /* serial mouse */
+ pc_mouse_set_serial_port(0);
+ pc_mouse_initialise();
+#endif /* MESS */
+
+ /* PC-XT keyboard */
+ if (flags & PCCOMMON_KEYBOARD_AT)
+ at_keyboard_init(AT_KEYBOARD_TYPE_AT);
+ else
+ at_keyboard_init(AT_KEYBOARD_TYPE_PC);
+ at_keyboard_set_scan_code_set(1);
+
+ /* PIC */
+ pic8259_init(2, pc_pic_set_int_line);
+
+ /* DMA */
+ if (flags & PCCOMMON_DMA8237_AT)
+ {
+ dma8237_init(2);
+ dma8237_config(0, &pc_dma);
+ pc_page_offset_mask = 0xFF0000;
+ }
+ else
+ {
+ dma8237_init(1);
+ dma8237_config(0, &pc_dma);
+ pc_page_offset_mask = 0x0F0000;
+ }
+
+ pc_keyboard_timer = timer_alloc(pc_keyb_timer);
+}
+
+/*
+ keyboard seams to permanently sent data clocked by the mainboard
+ clock line low for longer means "resync", keyboard sends 0xaa as answer
+ will become automatically 0x00 after a while
+*/
+
+static struct {
+ UINT8 data;
+ int on;
+} pc_keyb= { 0 };
+
+UINT8 pc_keyb_read(void)
+{
+ return pc_keyb.data;
+}
+
+
+
+static TIMER_CALLBACK( pc_keyb_timer )
+{
+ at_keyboard_reset();
+ pc_keyboard();
+}
+
+
+
+void pc_keyb_set_clock(int on)
+{
+ attotime keyb_delay = STATIC_ATTOTIME_IN_MSEC(5);
+
+ on = on ? 1 : 0;
+
+ if (pc_keyb.on != on)
+ {
+ if (on)
+ timer_adjust(pc_keyboard_timer, keyb_delay, 0, attotime_zero);
+ else
+ timer_reset(pc_keyboard_timer, attotime_never);
+
+ pc_keyb.on = on;
+ }
+}
+
+void pc_keyb_clear(void)
+{
+ pc_keyb.data = 0;
+}
+
+void pc_keyboard(void)
+{
+ int data;
+
+ at_keyboard_polling();
+
+ if (pc_keyb.on)
+ {
+ if ( (data=at_keyboard_read())!=-1) {
+ pc_keyb.data = data;
+ DBG_LOG(1,"KB_scancode",("$%02x\n", pc_keyb.data));
+ pic8259_set_irq_line(0, 1, 1);
+ pic8259_set_irq_line(0, 1, 0);
+ }
+ }
+}