summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/bebox.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/bebox.c')
-rw-r--r--src/mess/machine/bebox.c1093
1 files changed, 1093 insertions, 0 deletions
diff --git a/src/mess/machine/bebox.c b/src/mess/machine/bebox.c
new file mode 100644
index 00000000000..3e7200e17c0
--- /dev/null
+++ b/src/mess/machine/bebox.c
@@ -0,0 +1,1093 @@
+/***************************************************************************
+
+ machine/bebox.c
+
+ BeBox
+
+ Memory map:
+
+ 00000000 - 3FFFFFFF Physical RAM
+ 40000000 - 7FFFFFFF Motherboard glue registers
+ 80000000 - 807FFFFF ISA I/O
+ 81000000 - BF7FFFFF PCI I/O
+ BFFFFFF0 - BFFFFFFF PCI/ISA interrupt acknowledge
+ FF000000 - FFFFFFFF ROM/flash
+
+ In ISA space, peripherals are generally in similar places as they are on
+ standard PC hardware (e.g. - the keyboard is 80000060 and 80000064). The
+ following table shows more:
+
+ Keyboard/Mouse (Intel 8242) 80000060, 80000064
+ Real Time Clock (BQ3285) 80000070, 80000074
+ IDE ATA Interface 800001F0-F7, 800003F6-7
+ COM2 800002F8-F
+ GeekPort A/D Control 80000360-1
+ GeekPort A/D Data 80000362-3
+ GeekPort A/D Rate 80000364
+ GeekPort OE 80000366
+ Infrared Interface 80000368-A
+ COM3 80000380-7
+ COM4 80000388-F
+ GeekPort D/A 80000390-3
+ GeekPort GPA/GPB 80000394
+ Joystick Buttons 80000397
+ SuperIO Config (PReP standard) 80000398-9
+ MIDI Port 1 800003A0-7
+ MIDI Port 2 800003A8-F
+ Parallel 800003BC-E
+ Floppy 800003F0-7
+ COM1 800003F8-F
+ AD1848 80000830-4
+
+
+ Interrupt bit masks:
+
+ bit 31 - N/A (used to set/clear masks)
+ bit 30 - SMI interrupt to CPU 0 (CPU 0 only)
+ bit 29 - SMI interrupt to CPU 1 (CPU 1 only)
+ bit 28 - Unused
+ bit 27 - COM1 (PC IRQ #4)
+ bit 26 - COM2 (PC IRQ #3)
+ bit 25 - COM3
+ bit 24 - COM4
+ bit 23 - MIDI1
+ bit 22 - MIDI2
+ bit 21 - SCSI
+ bit 20 - PCI Slot #1
+ bit 19 - PCI Slot #2
+ bit 18 - PCI Slot #3
+ bit 17 - Sound
+ bit 16 - Keyboard (PC IRQ #1)
+ bit 15 - Real Time Clock (PC IRQ #8)
+ bit 14 - PC IRQ #5
+ bit 13 - Floppy Disk (PC IRQ #6)
+ bit 12 - Parallel Port (PC IRQ #7)
+ bit 11 - PC IRQ #9
+ bit 10 - PC IRQ #10
+ bit 9 - PC IRQ #11
+ bit 8 - Mouse (PC IRQ #12)
+ bit 7 - IDE (PC IRQ #14)
+ bit 6 - PC IRQ #15
+ bit 5 - PIC8259
+ bit 4 - Infrared Controller
+ bit 3 - Analog To Digital
+ bit 2 - GeekPort
+ bit 1 - Unused
+ bit 0 - Unused
+
+ Be documentation uses PowerPC bit numbering conventions (i.e. - bit #0 is
+ the most significant bit)
+
+ PCI Devices:
+ #0 Motorola MPC105
+ #11 Intel 82378 PCI/ISA bridge
+ #12 NCR 53C810 SCSI
+
+ More hardware information at http://www.netbsd.org/Ports/bebox/hardware.html
+
+***************************************************************************/
+
+/* Core includes */
+#include "emu.h"
+#include "memconv.h"
+#include "includes/bebox.h"
+
+/* Components */
+#include "video/pc_vga.h"
+#include "video/cirrus.h"
+#include "cpu/powerpc/ppc.h"
+#include "machine/ins8250.h"
+#include "machine/pc_fdc.h"
+#include "machine/mc146818.h"
+#include "machine/pic8259.h"
+#include "machine/pit8253.h"
+#include "machine/8237dma.h"
+#include "machine/idectrl.h"
+#include "machine/pci.h"
+#include "machine/intelfsh.h"
+#include "machine/8042kbdc.h"
+#include "machine/53c810.h"
+#include "machine/ram.h"
+
+#define LOG_CPUIMASK 1
+#define LOG_UART 1
+#define LOG_INTERRUPTS 1
+
+
+
+/*************************************
+ *
+ * Interrupts and Motherboard Registers
+ *
+ *************************************/
+
+static void bebox_update_interrupts(running_machine &machine);
+
+static void bebox_mbreg32_w(UINT32 *target, UINT64 data, UINT64 mem_mask)
+{
+ int i;
+
+ for (i = 1; i < 32; i++)
+ {
+ if ((data >> (63 - i)) & 1)
+ {
+ if ((data >> 63) & 1)
+ *target |= 0x80000000 >> i;
+ else
+ *target &= ~(0x80000000 >> i);
+ }
+ }
+}
+
+
+READ64_HANDLER( bebox_cpu0_imask_r )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ return ((UINT64) state->m_cpu_imask[0]) << 32;
+}
+
+READ64_HANDLER( bebox_cpu1_imask_r )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ return ((UINT64) state->m_cpu_imask[1]) << 32;
+}
+
+READ64_HANDLER( bebox_interrupt_sources_r )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ return ((UINT64) state->m_interrupts) << 32;
+}
+
+WRITE64_HANDLER( bebox_cpu0_imask_w )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ UINT32 old_imask = state->m_cpu_imask[0];
+
+ bebox_mbreg32_w(&state->m_cpu_imask[0], data, mem_mask);
+
+ if (old_imask != state->m_cpu_imask[0])
+ {
+ if (LOG_CPUIMASK)
+ {
+ logerror("BeBox CPU #0 pc=0x%08X imask=0x%08x\n",
+ (unsigned) cpu_get_pc( &space->device()), state->m_cpu_imask[0]);
+ }
+ bebox_update_interrupts(space->machine());
+ }
+}
+
+WRITE64_HANDLER( bebox_cpu1_imask_w )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ UINT32 old_imask = state->m_cpu_imask[1];
+
+ bebox_mbreg32_w(&state->m_cpu_imask[1], data, mem_mask);
+
+ if (old_imask != state->m_cpu_imask[1])
+ {
+ if (LOG_CPUIMASK)
+ {
+ logerror("BeBox CPU #1 pc=0x%08X imask=0x%08x\n",
+ (unsigned) cpu_get_pc( &space->device() ), state->m_cpu_imask[1]);
+ }
+ bebox_update_interrupts(space->machine());
+ }
+}
+
+READ64_HANDLER( bebox_crossproc_interrupts_r )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ UINT32 result;
+ result = state->m_crossproc_interrupts;
+
+ /* return a different result depending on which CPU is accessing this handler */
+ if (space != space->machine().device("ppc1")->memory().space(AS_PROGRAM))
+ result |= 0x02000000;
+ else
+ result &= ~0x02000000;
+
+ return ((UINT64) result) << 32;
+}
+
+WRITE64_HANDLER( bebox_crossproc_interrupts_w )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ static const struct
+ {
+ UINT32 mask;
+ int cpunum;
+ int active_high;
+ int inputline;
+ } crossproc_map[] =
+ {
+ { 0x40000000, 0, 1, 0/*PPC_INPUT_LINE_SMI*/ },
+ { 0x20000000, 1, 1, 0/*PPC_INPUT_LINE_SMI*/ },
+ { 0x08000000, 0, 0, 0/*PPC_INPUT_LINE_TLBISYNC*/ },
+ { 0x04000000, 1, 0, 0/*PPC_INPUT_LINE_TLBISYNC*/ }
+ };
+ int i, line;
+ UINT32 old_crossproc_interrupts = state->m_crossproc_interrupts;
+ static const char *const cputags[] = { "ppc1", "ppc2" };
+
+ bebox_mbreg32_w(&state->m_crossproc_interrupts, data, mem_mask);
+
+ for (i = 0; i < ARRAY_LENGTH(crossproc_map); i++)
+ {
+ if ((old_crossproc_interrupts ^ state->m_crossproc_interrupts) & crossproc_map[i].mask)
+ {
+ if (state->m_crossproc_interrupts & crossproc_map[i].mask)
+ line = crossproc_map[i].active_high ? ASSERT_LINE : CLEAR_LINE;
+ else
+ line = crossproc_map[i].active_high ? CLEAR_LINE : ASSERT_LINE;
+
+ if (LOG_INTERRUPTS)
+ {
+/*
+ logerror("bebox_crossproc_interrupts_w(): CPU #%d %s %s\n",
+ crossproc_map[i].cpunum, line ? "Asserting" : "Clearing",
+ (crossproc_map[i].inputline == PPC_INPUT_LINE_SMI) ? "SMI" : "TLBISYNC");
+ */
+ }
+
+ cputag_set_input_line(space->machine(), cputags[crossproc_map[i].cpunum], crossproc_map[i].inputline, line);
+ }
+ }
+}
+
+WRITE64_HANDLER( bebox_processor_resets_w )
+{
+ UINT8 b = (UINT8) (data >> 56);
+
+ if (b & 0x20)
+ {
+ cputag_set_input_line(space->machine(), "ppc2", INPUT_LINE_RESET, (b & 0x80) ? CLEAR_LINE : ASSERT_LINE);
+ }
+}
+
+
+static void bebox_update_interrupts(running_machine &machine)
+{
+ bebox_state *state = machine.driver_data<bebox_state>();
+ int cpunum;
+ UINT32 interrupt;
+ static const char *const cputags[] = { "ppc1", "ppc2" };
+
+ for (cpunum = 0; cpunum < 2; cpunum++)
+ {
+ interrupt = state->m_interrupts & state->m_cpu_imask[cpunum];
+
+ if (LOG_INTERRUPTS)
+ {
+ logerror("\tbebox_update_interrupts(): CPU #%d [%08X|%08X] IRQ %s\n", cpunum,
+ state->m_interrupts, state->m_cpu_imask[cpunum], interrupt ? "on" : "off");
+ }
+
+ cputag_set_input_line(machine, cputags[cpunum], INPUT_LINE_IRQ0, interrupt ? ASSERT_LINE : CLEAR_LINE);
+ }
+}
+
+
+static void bebox_set_irq_bit(running_machine &machine, unsigned int interrupt_bit, int val)
+{
+ bebox_state *state = machine.driver_data<bebox_state>();
+ static const char *const interrupt_names[32] =
+ {
+ NULL,
+ NULL,
+ "GEEKPORT",
+ "ADC",
+ "IR",
+ "PIC8259",
+ "PCIRQ 15",
+ "IDE",
+ "MOUSE",
+ "PCIRQ 11",
+ "PCIRQ 10",
+ "PCIRQ 9",
+ "PARALLEL",
+ "FLOPPY",
+ "PCIRQ 5",
+ "RTC",
+ "KEYBOARD",
+ "SOUND",
+ "PCI3",
+ "PCI2",
+ "PCI1",
+ "SCSI",
+ "MIDI2",
+ "MIDI1",
+ "COM4",
+ "COM3",
+ "COM2",
+ "COM1",
+ NULL,
+ "SMI1",
+ "SMI0",
+ NULL
+ };
+ UINT32 old_interrupts;
+
+ if (LOG_INTERRUPTS)
+ {
+ /* make sure that we don't shoot ourself in the foot */
+ assert_always((interrupt_bit < ARRAY_LENGTH(interrupt_names)) && (interrupt_names[interrupt_bit] != NULL), "Raising invalid interrupt");
+
+ logerror("bebox_set_irq_bit(): pc[0]=0x%08x pc[1]=0x%08x %s interrupt #%u (%s)\n",
+ (unsigned) cpu_get_reg(machine.device("ppc1"), STATE_GENPC),
+ (unsigned) cpu_get_reg(machine.device("ppc2"), STATE_GENPC),
+ val ? "Asserting" : "Clearing",
+ interrupt_bit, interrupt_names[interrupt_bit]);
+ }
+
+ old_interrupts = state->m_interrupts;
+ if (val)
+ state->m_interrupts |= 1 << interrupt_bit;
+ else
+ state->m_interrupts &= ~(1 << interrupt_bit);
+
+ /* if interrupt values have changed, update the lines */
+ if (state->m_interrupts != old_interrupts)
+ bebox_update_interrupts(machine);
+}
+
+
+/*************************************
+ *
+ * COM ports
+ *
+ *************************************/
+
+const ins8250_interface bebox_uart_inteface_0 =
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+const ins8250_interface bebox_uart_inteface_1 =
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+const ins8250_interface bebox_uart_inteface_2 =
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+const ins8250_interface bebox_uart_inteface_3 =
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+
+/*************************************
+ *
+ * Floppy Disk Controller
+ *
+ *************************************/
+
+static void bebox_fdc_interrupt(running_machine &machine, int state)
+{
+ bebox_state *drvstate = machine.driver_data<bebox_state>();
+ bebox_set_irq_bit(machine, 13, state);
+ if ( drvstate->m_devices.pic8259_master ) {
+ pic8259_ir6_w(drvstate->m_devices.pic8259_master, state);
+ }
+}
+
+
+static void bebox_fdc_dma_drq(running_machine &machine, int state)
+{
+ bebox_state *drvstate = machine.driver_data<bebox_state>();
+ if ( drvstate->m_devices.dma8237_1 ) {
+ i8237_dreq2_w(drvstate->m_devices.dma8237_1, state);
+ }
+}
+
+
+static device_t *bebox_fdc_get_image(running_machine &machine, int floppy_index)
+{
+ /* the BeBox boot ROM seems to query for floppy #1 when it should be
+ * querying for floppy #0 */
+ return floppy_get_device(machine, 0);
+}
+
+static device_t * bebox_get_device(running_machine &machine )
+{
+ return machine.device("smc37c78");
+}
+
+
+static const struct pc_fdc_interface bebox_fdc_interface =
+{
+ bebox_fdc_interrupt,
+ bebox_fdc_dma_drq,
+ bebox_fdc_get_image,
+ bebox_get_device
+};
+
+
+/*************************************
+ *
+ * 8259 PIC
+ *
+ *************************************/
+
+READ64_HANDLER( bebox_interrupt_ack_r )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ int result;
+ result = pic8259_acknowledge( state->m_devices.pic8259_master );
+ bebox_set_irq_bit(space->machine(), 5, 0); /* HACK */
+ return ((UINT64) result) << 56;
+}
+
+
+/*************************************************************
+ *
+ * pic8259 configuration
+ *
+ *************************************************************/
+
+static WRITE_LINE_DEVICE_HANDLER( bebox_pic8259_master_set_int_line )
+{
+ bebox_set_irq_bit(device->machine(), 5, state);
+}
+
+static WRITE_LINE_DEVICE_HANDLER( bebox_pic8259_slave_set_int_line )
+{
+ bebox_state *drvstate = device->machine().driver_data<bebox_state>();
+ if (drvstate->m_devices.pic8259_master)
+ pic8259_ir2_w(drvstate->m_devices.pic8259_master, state);
+}
+
+static READ8_DEVICE_HANDLER( get_slave_ack )
+{
+ bebox_state *state = device->machine().driver_data<bebox_state>();
+ if (offset==2) { // IRQ = 2
+ return pic8259_acknowledge(state->m_devices.pic8259_slave);
+ }
+ return 0x00;
+}
+
+const struct pic8259_interface bebox_pic8259_master_config =
+{
+ DEVCB_LINE(bebox_pic8259_master_set_int_line),
+ DEVCB_LINE_VCC,
+ DEVCB_HANDLER(get_slave_ack)
+};
+
+const struct pic8259_interface bebox_pic8259_slave_config =
+{
+ DEVCB_LINE(bebox_pic8259_slave_set_int_line),
+ DEVCB_LINE_GND,
+ DEVCB_NULL
+};
+
+
+/*************************************
+ *
+ * Floppy/IDE/ATA
+ *
+ *************************************/
+
+static device_t *ide_device(running_machine &machine)
+{
+ return machine.device("ide");
+}
+
+READ8_HANDLER( bebox_800001F0_r ) { return ide_controller_r(ide_device(space->machine()), offset + 0x1F0, 1); }
+WRITE8_HANDLER( bebox_800001F0_w ) { ide_controller_w(ide_device(space->machine()), offset + 0x1F0, 1, data); }
+
+READ64_HANDLER( bebox_800003F0_r )
+{
+ UINT64 result = read64be_with_read8_handler(pc_fdc_r, space, offset, mem_mask | 0xFFFF);
+
+ if (((mem_mask >> 8) & 0xFF) == 0)
+ {
+ result &= ~(0xFF << 8);
+ result |= ide_controller_r(ide_device(space->machine()), 0x3F6, 1) << 8;
+ }
+
+ if (((mem_mask >> 0) & 0xFF) == 0)
+ {
+ result &= ~(0xFF << 0);
+ result |= ide_controller_r(ide_device(space->machine()), 0x3F7, 1) << 0;
+ }
+ return result;
+}
+
+
+WRITE64_HANDLER( bebox_800003F0_w )
+{
+ write64be_with_write8_handler(pc_fdc_w, space, offset, data, mem_mask | 0xFFFF);
+
+ if (((mem_mask >> 8) & 0xFF) == 0)
+ ide_controller_w(ide_device(space->machine()), 0x3F6, 1, (data >> 8) & 0xFF);
+
+ if (((mem_mask >> 0) & 0xFF) == 0)
+ ide_controller_w(ide_device(space->machine()), 0x3F7, 1, (data >> 0) & 0xFF);
+}
+
+
+void bebox_ide_interrupt(device_t *device, int state)
+{
+ bebox_state *drvstate = device->machine().driver_data<bebox_state>();
+ bebox_set_irq_bit(device->machine(), 7, state);
+ if ( drvstate->m_devices.pic8259_master ) {
+ pic8259_ir6_w(drvstate->m_devices.pic8259_master, state);
+ }
+}
+
+
+/*************************************
+ *
+ * Video card (Cirrus Logic CL-GD5430)
+ *
+ *************************************/
+
+static READ64_HANDLER( bebox_video_r )
+{
+ const UINT64 *mem = (const UINT64 *) pc_vga_memory();
+ return BIG_ENDIANIZE_INT64(mem[offset]);
+}
+
+
+static WRITE64_HANDLER( bebox_video_w )
+{
+ UINT64 *mem = (UINT64 *) pc_vga_memory();
+ data = BIG_ENDIANIZE_INT64(data);
+ mem_mask = BIG_ENDIANIZE_INT64(mem_mask);
+ COMBINE_DATA(&mem[offset]);
+}
+
+/*************************************
+ *
+ * 8237 DMA
+ *
+ *************************************/
+
+
+READ8_HANDLER(bebox_page_r)
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ UINT8 data = state->m_at_pages[offset % 0x10];
+
+ switch(offset % 8)
+ {
+ case 1:
+ data = state->m_dma_offset[(offset / 8) & 1][2];
+ break;
+ case 2:
+ data = state->m_dma_offset[(offset / 8) & 1][3];
+ break;
+ case 3:
+ data = state->m_dma_offset[(offset / 8) & 1][1];
+ break;
+ case 7:
+ data = state->m_dma_offset[(offset / 8) & 1][0];
+ break;
+ }
+ return data;
+}
+
+
+WRITE8_HANDLER(bebox_page_w)
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ state->m_at_pages[offset % 0x10] = data;
+
+ switch(offset % 8)
+ {
+ case 1:
+ state->m_dma_offset[(offset / 8) & 1][2] &= 0xFF00;
+ state->m_dma_offset[(offset / 8) & 1][2] |= ((UINT16 ) data) << 0;
+ break;
+ case 2:
+ state->m_dma_offset[(offset / 8) & 1][3] &= 0xFF00;
+ state->m_dma_offset[(offset / 8) & 1][3] |= ((UINT16 ) data) << 0;
+ break;
+ case 3:
+ state->m_dma_offset[(offset / 8) & 1][1] &= 0xFF00;
+ state->m_dma_offset[(offset / 8) & 1][1] |= ((UINT16 ) data) << 0;
+ break;
+ case 7:
+ state->m_dma_offset[(offset / 8) & 1][0] &= 0xFF00;
+ state->m_dma_offset[(offset / 8) & 1][0] |= ((UINT16 ) data) << 0;
+ break;
+ }
+}
+
+
+WRITE8_HANDLER(bebox_80000480_w)
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ switch(offset % 8)
+ {
+ case 1:
+ state->m_dma_offset[(offset / 8) & 1][2] &= 0x00FF;
+ state->m_dma_offset[(offset / 8) & 1][2] |= ((UINT16 ) data) << 8;
+ break;
+ case 2:
+ state->m_dma_offset[(offset / 8) & 1][3] &= 0x00FF;
+ state->m_dma_offset[(offset / 8) & 1][3] |= ((UINT16 ) data) << 8;
+ break;
+ case 3:
+ state->m_dma_offset[(offset / 8) & 1][1] &= 0x00FF;
+ state->m_dma_offset[(offset / 8) & 1][1] |= ((UINT16 ) data) << 8;
+ break;
+ case 7:
+ state->m_dma_offset[(offset / 8) & 1][0] &= 0x00FF;
+ state->m_dma_offset[(offset / 8) & 1][0] |= ((UINT16 ) data) << 8;
+ break;
+ }
+}
+
+
+READ8_HANDLER(bebox_80000480_r)
+{
+ fatalerror("NYI");
+}
+
+
+static WRITE_LINE_DEVICE_HANDLER( bebox_dma_hrq_changed )
+{
+ cputag_set_input_line(device->machine(), "ppc1", INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
+
+ /* Assert HLDA */
+ i8237_hlda_w( device, state );
+}
+
+
+static READ8_HANDLER( bebox_dma_read_byte )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ offs_t page_offset = (((offs_t) state->m_dma_offset[0][state->m_dma_channel]) << 16)
+ & 0x7FFF0000;
+ return space->read_byte(page_offset + offset);
+}
+
+
+static WRITE8_HANDLER( bebox_dma_write_byte )
+{
+ bebox_state *state = space->machine().driver_data<bebox_state>();
+ offs_t page_offset = (((offs_t) state->m_dma_offset[0][state->m_dma_channel]) << 16)
+ & 0x7FFF0000;
+ space->write_byte(page_offset + offset, data);
+}
+
+
+static READ8_DEVICE_HANDLER( bebox_dma8237_fdc_dack_r ) {
+ return pc_fdc_dack_r(device->machine());
+}
+
+
+static WRITE8_DEVICE_HANDLER( bebox_dma8237_fdc_dack_w ) {
+ pc_fdc_dack_w( device->machine(), data );
+}
+
+
+static WRITE_LINE_DEVICE_HANDLER( bebox_dma8237_out_eop ) {
+ pc_fdc_set_tc_state( device->machine(), state );
+}
+
+static void set_dma_channel(device_t *device, int channel, int state)
+{
+ bebox_state *drvstate = device->machine().driver_data<bebox_state>();
+ if (!state) drvstate->m_dma_channel = channel;
+}
+
+static WRITE_LINE_DEVICE_HANDLER( pc_dack0_w ) { set_dma_channel(device, 0, state); }
+static WRITE_LINE_DEVICE_HANDLER( pc_dack1_w ) { set_dma_channel(device, 1, state); }
+static WRITE_LINE_DEVICE_HANDLER( pc_dack2_w ) { set_dma_channel(device, 2, state); }
+static WRITE_LINE_DEVICE_HANDLER( pc_dack3_w ) { set_dma_channel(device, 3, state); }
+
+
+I8237_INTERFACE( bebox_dma8237_1_config )
+{
+ DEVCB_LINE(bebox_dma_hrq_changed),
+ DEVCB_LINE(bebox_dma8237_out_eop),
+ DEVCB_MEMORY_HANDLER("ppc1", PROGRAM, bebox_dma_read_byte),
+ DEVCB_MEMORY_HANDLER("ppc1", PROGRAM, bebox_dma_write_byte),
+ { DEVCB_NULL, DEVCB_NULL, DEVCB_HANDLER(bebox_dma8237_fdc_dack_r), DEVCB_NULL },
+ { DEVCB_NULL, DEVCB_NULL, DEVCB_HANDLER(bebox_dma8237_fdc_dack_w), DEVCB_NULL },
+ { DEVCB_LINE(pc_dack0_w), DEVCB_LINE(pc_dack1_w), DEVCB_LINE(pc_dack2_w), DEVCB_LINE(pc_dack3_w) }
+};
+
+
+I8237_INTERFACE( bebox_dma8237_2_config )
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ { DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL },
+ { DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL },
+ { DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL }
+};
+
+
+/*************************************
+ *
+ * 8254 PIT
+ *
+ *************************************/
+
+static WRITE_LINE_DEVICE_HANDLER( bebox_timer0_w )
+{
+ bebox_state *drvstate = device->machine().driver_data<bebox_state>();
+ if (drvstate->m_devices.pic8259_master)
+ pic8259_ir0_w(drvstate->m_devices.pic8259_master, state);
+}
+
+
+const struct pit8253_config bebox_pit8254_config =
+{
+ {
+ {
+ 4772720/4, /* heartbeat IRQ */
+ DEVCB_NULL,
+ DEVCB_LINE(bebox_timer0_w)
+ },
+ {
+ 4772720/4, /* dram refresh */
+ DEVCB_NULL,
+ DEVCB_NULL
+ },
+ {
+ 4772720/4, /* pio port c pin 4, and speaker polling enough */
+ DEVCB_NULL,
+ DEVCB_NULL
+ }
+ }
+};
+
+
+/*************************************
+ *
+ * Flash ROM
+ *
+ *************************************/
+
+READ8_HANDLER( bebox_flash_r )
+{
+ fujitsu_29f016a_device *flash = space->machine().device<fujitsu_29f016a_device>("flash");
+ offset = (offset & ~7) | (7 - (offset & 7));
+ return flash->read(offset);
+}
+
+
+WRITE8_HANDLER( bebox_flash_w )
+{
+ fujitsu_29f016a_device *flash = space->machine().device<fujitsu_29f016a_device>("flash");
+ offset = (offset & ~7) | (7 - (offset & 7));
+ flash->write(offset, data);
+}
+
+/*************************************
+ *
+ * Keyboard
+ *
+ *************************************/
+
+static void bebox_keyboard_interrupt(running_machine &machine,int state)
+{
+ bebox_state *drvstate = machine.driver_data<bebox_state>();
+ bebox_set_irq_bit(machine, 16, state);
+ if ( drvstate->m_devices.pic8259_master ) {
+ pic8259_ir1_w(drvstate->m_devices.pic8259_master, state);
+ }
+}
+
+static int bebox_get_out2(running_machine &machine) {
+ return pit8253_get_output(machine.device("pit8254"), 2 );
+}
+
+static const struct kbdc8042_interface bebox_8042_interface =
+{
+ KBDC8042_STANDARD,
+ NULL,
+ bebox_keyboard_interrupt,
+ NULL,
+ bebox_get_out2
+};
+
+
+/*************************************
+ *
+ * SCSI
+ *
+ *************************************/
+
+
+static READ64_HANDLER( scsi53c810_r )
+{
+ int reg = offset*8;
+ UINT64 r = 0;
+ if (!(mem_mask & U64(0xff00000000000000))) {
+ r |= (UINT64)lsi53c810_reg_r(space, reg+0) << 56;
+ }
+ if (!(mem_mask & U64(0x00ff000000000000))) {
+ r |= (UINT64)lsi53c810_reg_r(space, reg+1) << 48;
+ }
+ if (!(mem_mask & U64(0x0000ff0000000000))) {
+ r |= (UINT64)lsi53c810_reg_r(space, reg+2) << 40;
+ }
+ if (!(mem_mask & U64(0x000000ff00000000))) {
+ r |= (UINT64)lsi53c810_reg_r(space, reg+3) << 32;
+ }
+ if (!(mem_mask & U64(0x00000000ff000000))) {
+ r |= (UINT64)lsi53c810_reg_r(space, reg+4) << 24;
+ }
+ if (!(mem_mask & U64(0x0000000000ff0000))) {
+ r |= (UINT64)lsi53c810_reg_r(space, reg+5) << 16;
+ }
+ if (!(mem_mask & U64(0x000000000000ff00))) {
+ r |= (UINT64)lsi53c810_reg_r(space, reg+6) << 8;
+ }
+ if (!(mem_mask & U64(0x00000000000000ff))) {
+ r |= (UINT64)lsi53c810_reg_r(space, reg+7) << 0;
+ }
+
+ return r;
+}
+
+
+static WRITE64_HANDLER( scsi53c810_w )
+{
+ int reg = offset*8;
+ if (!(mem_mask & U64(0xff00000000000000))) {
+ lsi53c810_reg_w(space, reg+0, data >> 56);
+ }
+ if (!(mem_mask & U64(0x00ff000000000000))) {
+ lsi53c810_reg_w(space, reg+1, data >> 48);
+ }
+ if (!(mem_mask & U64(0x0000ff0000000000))) {
+ lsi53c810_reg_w(space, reg+2, data >> 40);
+ }
+ if (!(mem_mask & U64(0x000000ff00000000))) {
+ lsi53c810_reg_w(space, reg+3, data >> 32);
+ }
+ if (!(mem_mask & U64(0x00000000ff000000))) {
+ lsi53c810_reg_w(space, reg+4, data >> 24);
+ }
+ if (!(mem_mask & U64(0x0000000000ff0000))) {
+ lsi53c810_reg_w(space, reg+5, data >> 16);
+ }
+ if (!(mem_mask & U64(0x000000000000ff00))) {
+ lsi53c810_reg_w(space, reg+6, data >> 8);
+ }
+ if (!(mem_mask & U64(0x00000000000000ff))) {
+ lsi53c810_reg_w(space, reg+7, data >> 0);
+ }
+}
+
+
+#define BYTE_REVERSE32(x) (((x >> 24) & 0xff) | \
+ ((x >> 8) & 0xff00) | \
+ ((x << 8) & 0xff0000) | \
+ ((x << 24) & 0xff000000))
+
+static UINT32 scsi53c810_fetch(running_machine &machine, UINT32 dsp)
+{
+ UINT32 result;
+ result = machine.device("ppc1")->memory().space(AS_PROGRAM)->read_dword(dsp & 0x7FFFFFFF);
+ return BYTE_REVERSE32(result);
+}
+
+
+static void scsi53c810_irq_callback(running_machine &machine, int value)
+{
+ bebox_set_irq_bit(machine, 21, value);
+}
+
+
+static void scsi53c810_dma_callback(running_machine &machine, UINT32 src, UINT32 dst, int length, int byteswap)
+{
+}
+
+
+UINT32 scsi53c810_pci_read(device_t *busdevice, device_t *device, int function, int offset, UINT32 mem_mask)
+{
+ bebox_state *state = device->machine().driver_data<bebox_state>();
+ UINT32 result = 0;
+
+ if (function == 0)
+ {
+ switch(offset)
+ {
+ case 0x00: /* vendor/device ID */
+ result = 0x00011000;
+ break;
+
+ case 0x08:
+ result = 0x01000000;
+ break;
+
+ default:
+ result = state->m_scsi53c810_data[offset / 4];
+ break;
+ }
+ }
+ return result;
+}
+
+
+void scsi53c810_pci_write(device_t *busdevice, device_t *device, int function, int offset, UINT32 data, UINT32 mem_mask)
+{
+ bebox_state *state = device->machine().driver_data<bebox_state>();
+ offs_t addr;
+
+ if (function == 0)
+ {
+ state->m_scsi53c810_data[offset / 4] = data;
+
+ switch(offset)
+ {
+ case 0x04:
+ /* command
+ *
+ * bit 8: SERR/ Enable
+ * bit 6: Enable Parity Response
+ * bit 4: Write and Invalidate Mode
+ * bit 2: Enable Bus Mastering
+ * bit 1: Enable Memory Space
+ * bit 0: Enable IO Space
+ */
+ if (data & 0x02)
+ {
+ /* brutal ugly hack; at some point the PCI code should be handling this stuff */
+ if (state->m_scsi53c810_data[5] != 0xFFFFFFF0)
+ {
+ address_space *space = device->machine().device("ppc1")->memory().space(AS_PROGRAM);
+
+ addr = (state->m_scsi53c810_data[5] | 0xC0000000) & ~0xFF;
+ space->install_legacy_read_handler(addr, addr + 0xFF, FUNC(scsi53c810_r));
+ space->install_legacy_write_handler(addr, addr + 0xFF, FUNC(scsi53c810_w));
+ }
+ }
+ break;
+ }
+ }
+}
+
+
+static const SCSIConfigTable dev_table =
+{
+ 2, /* 2 SCSI devices */
+ {
+ { SCSI_ID_0, "harddisk1" }, /* SCSI ID 0, using HD 0, HD */
+ { SCSI_ID_3, "cdrom" } /* SCSI ID 3, using CHD 0, CD-ROM */
+ }
+};
+
+static const struct LSI53C810interface scsi53c810_intf =
+{
+ &dev_table, /* SCSI device table */
+ &scsi53c810_irq_callback,
+ &scsi53c810_dma_callback,
+ &scsi53c810_fetch,
+};
+
+
+static TIMER_CALLBACK( bebox_get_devices ) {
+ bebox_state *state = machine.driver_data<bebox_state>();
+ state->m_devices.pic8259_master = machine.device("pic8259_master");
+ state->m_devices.pic8259_slave = machine.device("pic8259_slave");
+ state->m_devices.dma8237_1 = machine.device("dma8237_1");
+ state->m_devices.dma8237_2 = machine.device("dma8237_2");
+}
+
+
+/*************************************
+ *
+ * Driver main
+ *
+ *************************************/
+
+MACHINE_RESET( bebox )
+{
+ bebox_state *state = machine.driver_data<bebox_state>();
+ state->m_devices.pic8259_master = NULL;
+ state->m_devices.pic8259_slave = NULL;
+ state->m_devices.dma8237_1 = NULL;
+ state->m_devices.dma8237_2 = NULL;
+
+ machine.scheduler().timer_set(attotime::zero, FUNC(bebox_get_devices));
+
+ cputag_set_input_line(machine, "ppc1", INPUT_LINE_RESET, CLEAR_LINE);
+ cputag_set_input_line(machine, "ppc2", INPUT_LINE_RESET, ASSERT_LINE);
+
+ memcpy(machine.device<fujitsu_29f016a_device>("flash")->space()->get_read_ptr(0),state->memregion("user1")->base(),0x200000);
+}
+
+MACHINE_START( bebox )
+{
+ pc_fdc_init(machine, &bebox_fdc_interface);
+ /* SCSI */
+ lsi53c810_init(machine, &scsi53c810_intf);
+}
+
+DRIVER_INIT_MEMBER(bebox_state,bebox)
+{
+ address_space *space_0 = machine().device("ppc1")->memory().space(AS_PROGRAM);
+ address_space *space_1 = machine().device("ppc2")->memory().space(AS_PROGRAM);
+ offs_t vram_begin;
+ offs_t vram_end;
+
+ /* set up boot and flash ROM */
+ membank("bank2")->set_base(machine().root_device().memregion("user2")->base());
+
+ /* install MESS managed RAM */
+ space_0->install_readwrite_bank(0, machine().device<ram_device>(RAM_TAG)->size() - 1, 0, 0x02000000, "bank3");
+ space_1->install_readwrite_bank(0, machine().device<ram_device>(RAM_TAG)->size() - 1, 0, 0x02000000, "bank3");
+ membank("bank3")->set_base(machine().device<ram_device>(RAM_TAG)->pointer());
+
+ kbdc8042_init(machine(), &bebox_8042_interface);
+
+ /* install VGA memory */
+ vram_begin = 0xC1000000;
+ vram_end = vram_begin + pc_vga_memory_size() - 1;
+ space_0->install_legacy_readwrite_handler(vram_begin, vram_end, FUNC(bebox_video_r), FUNC(bebox_video_w));
+ space_1->install_legacy_readwrite_handler(vram_begin, vram_end, FUNC(bebox_video_r), FUNC(bebox_video_w));
+
+ /* The following is a verrrry ugly hack put in to support NetBSD for
+ * NetBSD. When NetBSD/bebox it does most of its work on CPU #0 and then
+ * lets CPU #1 go. However, it seems that CPU #1 jumps into never-never
+ * land, crashes, and then goes into NetBSD's crash handler which catches
+ * it. The current PowerPC core cannot catch this trip into never-never
+ * land properly, and MESS crashes. In the interim, this "mitten" catches
+ * the crash
+ */
+ {
+ static UINT64 ops[2] =
+ {
+ /* li r0, 0x0700 */
+ /* mtspr ctr, r0 */
+ U64(0x380007007C0903A6),
+
+ /* bcctr 0x14, 0 */
+ U64(0x4E80042000000000)
+ };
+ space_1->install_read_bank(0x9421FFF0, 0x9421FFFF, "bank1");
+ membank("bank1")->set_base(ops);
+ }
+}