mame/src/mess/machine/bebox.c
2012-10-03 14:36:54 +00:00

1110 lines
30 KiB
C

/***************************************************************************
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 "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
INLINE UINT16 read16be_with_read8_handler(read8_space_func handler, address_space &space, offs_t offset, UINT16 mem_mask)
{
UINT16 result = 0;
if (ACCESSING_BITS_8_15)
result |= ((UINT16)(*handler)(space, offset * 2 + 0, mem_mask >> 8)) << 8;
if (ACCESSING_BITS_0_7)
result |= ((UINT16)(*handler)(space, offset * 2 + 1, mem_mask >> 0)) << 0;
return result;
}
INLINE void write16be_with_write8_handler(write8_space_func handler, address_space &space, offs_t offset, UINT16 data, UINT16 mem_mask)
{
if (ACCESSING_BITS_8_15)
(*handler)(space, offset * 2 + 0, data >> 8, mem_mask >> 8);
if (ACCESSING_BITS_0_7)
(*handler)(space, offset * 2 + 1, data >> 0, mem_mask >> 0);
}
INLINE UINT32 read32be_with_read8_handler(read8_space_func handler, address_space &space, offs_t offset, UINT32 mem_mask)
{
UINT32 result = 0;
if (ACCESSING_BITS_16_31)
result |= read16be_with_read8_handler(handler, space, offset * 2 + 0, mem_mask >> 16) << 16;
if (ACCESSING_BITS_0_15)
result |= read16be_with_read8_handler(handler, space, offset * 2 + 1, mem_mask) << 0;
return result;
}
INLINE void write32be_with_write8_handler(write8_space_func handler, address_space &space, offs_t offset, UINT32 data, UINT32 mem_mask)
{
if (ACCESSING_BITS_16_31)
write16be_with_write8_handler(handler, space, offset * 2 + 0, data >> 16, mem_mask >> 16);
if (ACCESSING_BITS_0_15)
write16be_with_write8_handler(handler, space, offset * 2 + 1, data, mem_mask);
}
INLINE UINT64 read64be_with_read8_handler(read8_space_func handler, address_space &space, offs_t offset, UINT64 mem_mask)
{
UINT64 result = 0;
if (ACCESSING_BITS_32_63)
result |= (UINT64)read32be_with_read8_handler(handler, space, offset * 2 + 0, mem_mask >> 32) << 32;
if (ACCESSING_BITS_0_31)
result |= (UINT64)read32be_with_read8_handler(handler, space, offset * 2 + 1, mem_mask) << 0;
return result;
}
INLINE void write64be_with_write8_handler(write8_space_func handler, address_space &space, offs_t offset, UINT64 data, UINT64 mem_mask)
{
if (ACCESSING_BITS_32_63)
write32be_with_write8_handler(handler, space, offset * 2 + 0, data >> 32, mem_mask >> 32);
if (ACCESSING_BITS_0_31)
write32be_with_write8_handler(handler, space, offset * 2 + 1, data, mem_mask);
}
/*************************************
*
* 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_MEMBER(bebox_state::bebox_cpu0_imask_r )
{
return ((UINT64) m_cpu_imask[0]) << 32;
}
READ64_MEMBER(bebox_state::bebox_cpu1_imask_r )
{
return ((UINT64) m_cpu_imask[1]) << 32;
}
READ64_MEMBER(bebox_state::bebox_interrupt_sources_r )
{
return ((UINT64) m_interrupts) << 32;
}
WRITE64_MEMBER(bebox_state::bebox_cpu0_imask_w )
{
UINT32 old_imask = m_cpu_imask[0];
bebox_mbreg32_w(&m_cpu_imask[0], data, mem_mask);
if (old_imask != m_cpu_imask[0])
{
if (LOG_CPUIMASK)
{
logerror("BeBox CPU #0 pc=0x%08X imask=0x%08x\n",
(unsigned) space.device().safe_pc( ), m_cpu_imask[0]);
}
bebox_update_interrupts(space.machine());
}
}
WRITE64_MEMBER(bebox_state::bebox_cpu1_imask_w )
{
UINT32 old_imask = m_cpu_imask[1];
bebox_mbreg32_w(&m_cpu_imask[1], data, mem_mask);
if (old_imask != m_cpu_imask[1])
{
if (LOG_CPUIMASK)
{
logerror("BeBox CPU #1 pc=0x%08X imask=0x%08x\n",
(unsigned) space.device() .safe_pc( ), m_cpu_imask[1]);
}
bebox_update_interrupts(space.machine());
}
}
READ64_MEMBER(bebox_state::bebox_crossproc_interrupts_r )
{
UINT32 result;
result = 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_MEMBER(bebox_state::bebox_crossproc_interrupts_w )
{
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 = m_crossproc_interrupts;
static const char *const cputags[] = { "ppc1", "ppc2" };
bebox_mbreg32_w(&m_crossproc_interrupts, data, mem_mask);
for (i = 0; i < ARRAY_LENGTH(crossproc_map); i++)
{
if ((old_crossproc_interrupts ^ m_crossproc_interrupts) & crossproc_map[i].mask)
{
if (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");
*/
}
space.machine().device(cputags[crossproc_map[i].cpunum])->execute().set_input_line(crossproc_map[i].inputline, line);
}
}
}
WRITE64_MEMBER(bebox_state::bebox_processor_resets_w )
{
UINT8 b = (UINT8) (data >> 56);
if (b & 0x20)
{
space.machine().device("ppc2")->execute().set_input_line(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");
}
machine.device(cputags[cpunum])->execute().set_input_line(INPUT_LINE_IRQ0, interrupt ? ASSERT_LINE : CLEAR_LINE);
}
}
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) machine.device("ppc1")->safe_pc(),
(unsigned) machine.device("ppc2")->safe_pc(),
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_MEMBER(bebox_state::bebox_interrupt_ack_r )
{
int result;
result = pic8259_acknowledge( m_devices.pic8259_master );
bebox_set_irq_bit(space.machine(), 5, 0); /* HACK */
return ((UINT64) result) << 56;
}
/*************************************************************
*
* pic8259 configuration
*
*************************************************************/
WRITE_LINE_MEMBER(bebox_state::bebox_pic8259_master_set_int_line)
{
bebox_set_irq_bit(machine(), 5, state);
}
WRITE_LINE_MEMBER(bebox_state::bebox_pic8259_slave_set_int_line)
{
if (m_devices.pic8259_master)
pic8259_ir2_w(m_devices.pic8259_master, state);
}
READ8_MEMBER(bebox_state::get_slave_ack)
{
if (offset==2) { // IRQ = 2
return pic8259_acknowledge(m_devices.pic8259_slave);
}
return 0x00;
}
const struct pic8259_interface bebox_pic8259_master_config =
{
DEVCB_DRIVER_LINE_MEMBER(bebox_state,bebox_pic8259_master_set_int_line),
DEVCB_LINE_VCC,
DEVCB_DRIVER_MEMBER(bebox_state,get_slave_ack)
};
const struct pic8259_interface bebox_pic8259_slave_config =
{
DEVCB_DRIVER_LINE_MEMBER(bebox_state,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_MEMBER(bebox_state::bebox_800001F0_r ) { return ide_controller_r(ide_device(space.machine()), offset + 0x1F0, 1); }
WRITE8_MEMBER(bebox_state::bebox_800001F0_w ) { ide_controller_w(ide_device(space.machine()), offset + 0x1F0, 1, data); }
READ64_MEMBER(bebox_state::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_MEMBER(bebox_state::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_MEMBER(bebox_state::bebox_video_r )
{
UINT64 result = 0;
mem_mask = FLIPENDIAN_INT64(mem_mask);
if (ACCESSING_BITS_0_7)
result |= (UINT64)vga_mem_linear_r(space, offset * 8 + 0, mem_mask >> 0) << 0;
if (ACCESSING_BITS_8_15)
result |= (UINT64)vga_mem_linear_r(space, offset * 8 + 1, mem_mask >> 8) << 8;
if (ACCESSING_BITS_16_23)
result |= (UINT64)vga_mem_linear_r(space, offset * 8 + 2, mem_mask >> 16) << 16;
if (ACCESSING_BITS_24_31)
result |= (UINT64)vga_mem_linear_r(space, offset * 8 + 3, mem_mask >> 24) << 24;
if (ACCESSING_BITS_32_39)
result |= (UINT64)vga_mem_linear_r(space, offset * 8 + 4, mem_mask >> 32) << 32;
if (ACCESSING_BITS_40_47)
result |= (UINT64)vga_mem_linear_r(space, offset * 8 + 5, mem_mask >> 40) << 40;
if (ACCESSING_BITS_48_55)
result |= (UINT64)vga_mem_linear_r(space, offset * 8 + 6, mem_mask >> 48) << 48;
if (ACCESSING_BITS_56_63)
result |= (UINT64)vga_mem_linear_r(space, offset * 8 + 7, mem_mask >> 56) << 56;
return FLIPENDIAN_INT64(result);
}
static WRITE64_MEMBER(bebox_state::bebox_video_w )
{
data = FLIPENDIAN_INT64(data);
mem_mask = FLIPENDIAN_INT64(mem_mask);
if (ACCESSING_BITS_0_7)
vga_mem_linear_w(space, offset * 8 + 0, data >> 0 , mem_mask >> 0);
if (ACCESSING_BITS_8_15)
vga_mem_linear_w(space, offset * 8 + 1, data >> 8 , mem_mask >> 8);
if (ACCESSING_BITS_16_23)
vga_mem_linear_w(space, offset * 8 + 2, data >> 16, mem_mask >> 16);
if (ACCESSING_BITS_24_31)
vga_mem_linear_w(space, offset * 8 + 3, data >> 24, mem_mask >> 24);
if (ACCESSING_BITS_32_39)
vga_mem_linear_w(space, offset * 8 + 4, data >> 32, mem_mask >> 32);
if (ACCESSING_BITS_40_47)
vga_mem_linear_w(space, offset * 8 + 5, data >> 40, mem_mask >> 40);
if (ACCESSING_BITS_48_55)
vga_mem_linear_w(space, offset * 8 + 6, data >> 48, mem_mask >> 48);
if (ACCESSING_BITS_56_63)
vga_mem_linear_w(space, offset * 8 + 7, data >> 56, mem_mask >> 56);
}
*/
/*************************************
*
* 8237 DMA
*
*************************************/
READ8_MEMBER(bebox_state::bebox_page_r)
{
UINT8 data = m_at_pages[offset % 0x10];
switch(offset % 8)
{
case 1:
data = m_dma_offset[(offset / 8) & 1][2];
break;
case 2:
data = m_dma_offset[(offset / 8) & 1][3];
break;
case 3:
data = m_dma_offset[(offset / 8) & 1][1];
break;
case 7:
data = m_dma_offset[(offset / 8) & 1][0];
break;
}
return data;
}
WRITE8_MEMBER(bebox_state::bebox_page_w)
{
m_at_pages[offset % 0x10] = data;
switch(offset % 8)
{
case 1:
m_dma_offset[(offset / 8) & 1][2] &= 0xFF00;
m_dma_offset[(offset / 8) & 1][2] |= ((UINT16 ) data) << 0;
break;
case 2:
m_dma_offset[(offset / 8) & 1][3] &= 0xFF00;
m_dma_offset[(offset / 8) & 1][3] |= ((UINT16 ) data) << 0;
break;
case 3:
m_dma_offset[(offset / 8) & 1][1] &= 0xFF00;
m_dma_offset[(offset / 8) & 1][1] |= ((UINT16 ) data) << 0;
break;
case 7:
m_dma_offset[(offset / 8) & 1][0] &= 0xFF00;
m_dma_offset[(offset / 8) & 1][0] |= ((UINT16 ) data) << 0;
break;
}
}
WRITE8_MEMBER(bebox_state::bebox_80000480_w)
{
switch(offset % 8)
{
case 1:
m_dma_offset[(offset / 8) & 1][2] &= 0x00FF;
m_dma_offset[(offset / 8) & 1][2] |= ((UINT16 ) data) << 8;
break;
case 2:
m_dma_offset[(offset / 8) & 1][3] &= 0x00FF;
m_dma_offset[(offset / 8) & 1][3] |= ((UINT16 ) data) << 8;
break;
case 3:
m_dma_offset[(offset / 8) & 1][1] &= 0x00FF;
m_dma_offset[(offset / 8) & 1][1] |= ((UINT16 ) data) << 8;
break;
case 7:
m_dma_offset[(offset / 8) & 1][0] &= 0x00FF;
m_dma_offset[(offset / 8) & 1][0] |= ((UINT16 ) data) << 8;
break;
}
}
READ8_MEMBER(bebox_state::bebox_80000480_r)
{
fatalerror("NYI\n");
}
WRITE_LINE_MEMBER(bebox_state::bebox_dma_hrq_changed)
{
machine().device("ppc1")->execute().set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
/* Assert HLDA */
i8237_hlda_w( machine().device("dma8237_1"), state );
}
READ8_MEMBER(bebox_state::bebox_dma_read_byte )
{
address_space& prog_space = machine().device<cpu_device>("ppc1")->space(AS_PROGRAM); // get the right address space
offs_t page_offset = (((offs_t) m_dma_offset[0][m_dma_channel]) << 16)
& 0x7FFF0000;
return prog_space.read_byte(page_offset + offset);
}
WRITE8_MEMBER(bebox_state::bebox_dma_write_byte )
{
address_space& prog_space = machine().device<cpu_device>("ppc1")->space(AS_PROGRAM); // get the right address space
offs_t page_offset = (((offs_t) m_dma_offset[0][m_dma_channel]) << 16)
& 0x7FFF0000;
prog_space.write_byte(page_offset + offset, data);
}
READ8_MEMBER(bebox_state::bebox_dma8237_fdc_dack_r){
return pc_fdc_dack_r(machine(),space);
}
WRITE8_MEMBER(bebox_state::bebox_dma8237_fdc_dack_w){
pc_fdc_dack_w( machine(), space, data );
}
WRITE_LINE_MEMBER(bebox_state::bebox_dma8237_out_eop){
pc_fdc_set_tc_state( machine(), state );
}
static void set_dma_channel(running_machine &machine, int channel, int state)
{
bebox_state *drvstate = machine.driver_data<bebox_state>();
if (!state) drvstate->m_dma_channel = channel;
}
WRITE_LINE_MEMBER(bebox_state::pc_dack0_w){ set_dma_channel(machine(), 0, state); }
WRITE_LINE_MEMBER(bebox_state::pc_dack1_w){ set_dma_channel(machine(), 1, state); }
WRITE_LINE_MEMBER(bebox_state::pc_dack2_w){ set_dma_channel(machine(), 2, state); }
WRITE_LINE_MEMBER(bebox_state::pc_dack3_w){ set_dma_channel(machine(), 3, state); }
I8237_INTERFACE( bebox_dma8237_1_config )
{
DEVCB_DRIVER_LINE_MEMBER(bebox_state,bebox_dma_hrq_changed),
DEVCB_DRIVER_LINE_MEMBER(bebox_state,bebox_dma8237_out_eop),
DEVCB_DRIVER_MEMBER(bebox_state, bebox_dma_read_byte),
DEVCB_DRIVER_MEMBER(bebox_state, bebox_dma_write_byte),
{ DEVCB_NULL, DEVCB_NULL, DEVCB_DRIVER_MEMBER(bebox_state,bebox_dma8237_fdc_dack_r), DEVCB_NULL },
{ DEVCB_NULL, DEVCB_NULL, DEVCB_DRIVER_MEMBER(bebox_state,bebox_dma8237_fdc_dack_w), DEVCB_NULL },
{ DEVCB_DRIVER_LINE_MEMBER(bebox_state,pc_dack0_w), DEVCB_DRIVER_LINE_MEMBER(bebox_state,pc_dack1_w), DEVCB_DRIVER_LINE_MEMBER(bebox_state,pc_dack2_w), DEVCB_DRIVER_LINE_MEMBER(bebox_state,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
*
*************************************/
WRITE_LINE_MEMBER(bebox_state::bebox_timer0_w)
{
if (m_devices.pic8259_master)
pic8259_ir0_w(m_devices.pic8259_master, state);
}
const struct pit8253_config bebox_pit8254_config =
{
{
{
4772720/4, /* heartbeat IRQ */
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(bebox_state,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_MEMBER(bebox_state::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_MEMBER(bebox_state::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
*
*************************************/
READ64_MEMBER(bebox_state::scsi53c810_r )
{
int reg = offset*8;
UINT64 r = 0;
if (!(mem_mask & U64(0xff00000000000000))) {
r |= (UINT64)m_lsi53c810->lsi53c810_reg_r(reg+0) << 56;
}
if (!(mem_mask & U64(0x00ff000000000000))) {
r |= (UINT64)m_lsi53c810->lsi53c810_reg_r(reg+1) << 48;
}
if (!(mem_mask & U64(0x0000ff0000000000))) {
r |= (UINT64)m_lsi53c810->lsi53c810_reg_r(reg+2) << 40;
}
if (!(mem_mask & U64(0x000000ff00000000))) {
r |= (UINT64)m_lsi53c810->lsi53c810_reg_r(reg+3) << 32;
}
if (!(mem_mask & U64(0x00000000ff000000))) {
r |= (UINT64)m_lsi53c810->lsi53c810_reg_r(reg+4) << 24;
}
if (!(mem_mask & U64(0x0000000000ff0000))) {
r |= (UINT64)m_lsi53c810->lsi53c810_reg_r(reg+5) << 16;
}
if (!(mem_mask & U64(0x000000000000ff00))) {
r |= (UINT64)m_lsi53c810->lsi53c810_reg_r(reg+6) << 8;
}
if (!(mem_mask & U64(0x00000000000000ff))) {
r |= (UINT64)m_lsi53c810->lsi53c810_reg_r(reg+7) << 0;
}
return r;
}
WRITE64_MEMBER(bebox_state::scsi53c810_w )
{
int reg = offset*8;
if (!(mem_mask & U64(0xff00000000000000))) {
m_lsi53c810->lsi53c810_reg_w(reg+0, data >> 56);
}
if (!(mem_mask & U64(0x00ff000000000000))) {
m_lsi53c810->lsi53c810_reg_w(reg+1, data >> 48);
}
if (!(mem_mask & U64(0x0000ff0000000000))) {
m_lsi53c810->lsi53c810_reg_w(reg+2, data >> 40);
}
if (!(mem_mask & U64(0x000000ff00000000))) {
m_lsi53c810->lsi53c810_reg_w(reg+3, data >> 32);
}
if (!(mem_mask & U64(0x00000000ff000000))) {
m_lsi53c810->lsi53c810_reg_w(reg+4, data >> 24);
}
if (!(mem_mask & U64(0x0000000000ff0000))) {
m_lsi53c810->lsi53c810_reg_w(reg+5, data >> 16);
}
if (!(mem_mask & U64(0x000000000000ff00))) {
m_lsi53c810->lsi53c810_reg_w(reg+6, data >> 8);
}
if (!(mem_mask & U64(0x00000000000000ff))) {
m_lsi53c810->lsi53c810_reg_w(reg+7, data >> 0);
}
}
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_readwrite_handler(addr, addr + 0xFF, read64_delegate(FUNC(bebox_state::scsi53c810_r),state), write64_delegate(FUNC(bebox_state::scsi53c810_w),state));
}
}
break;
}
}
}
TIMER_CALLBACK_MEMBER(bebox_state::bebox_get_devices){
m_devices.pic8259_master = machine().device("pic8259_master");
m_devices.pic8259_slave = machine().device("pic8259_slave");
m_devices.dma8237_1 = machine().device("dma8237_1");
m_devices.dma8237_2 = machine().device("dma8237_2");
}
/*************************************
*
* Driver main
*
*************************************/
void bebox_state::machine_reset()
{
m_devices.pic8259_master = NULL;
m_devices.pic8259_slave = NULL;
m_devices.dma8237_1 = NULL;
m_devices.dma8237_2 = NULL;
machine().scheduler().timer_set(attotime::zero, timer_expired_delegate(FUNC(bebox_state::bebox_get_devices),this));
machine().device("ppc1")->execute().set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
machine().device("ppc2")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
memcpy(machine().device<fujitsu_29f016a_device>("flash")->space().get_read_ptr(0),memregion("user1")->base(),0x200000);
}
void bebox_state::machine_start()
{
pc_fdc_init(machine(), &bebox_fdc_interface);
}
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);
/* 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);
/* 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);
}
}