summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/vme/sys68k_iscsi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/vme/sys68k_iscsi.cpp')
-rw-r--r--src/devices/bus/vme/sys68k_iscsi.cpp489
1 files changed, 489 insertions, 0 deletions
diff --git a/src/devices/bus/vme/sys68k_iscsi.cpp b/src/devices/bus/vme/sys68k_iscsi.cpp
new file mode 100644
index 00000000000..184cc5d0643
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_iscsi.cpp
@@ -0,0 +1,489 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ * Interrupt scheme and dmac hookup shamelessly based on esq5505.cpp
+ *
+ * 11/04/2016
+ * Force SYS68K ISCSI-1 driver - This driver will be converted into a slot device once the VME bus driver exists.
+ * The ISCSI-1 board is a VME slave board that reads command and returns results through dual ported RAM to the VME bus.
+ *
+ * http://bitsavers.trailing-edge.com/pdf/forceComputers/800114_Force_Introduction_to_the_SYS68K_ISCSI-1_Oct86.pdf
+ *
+ * ||
+ * || ||
+ * ||||--||
+ * ||||--||
+ * || ||__________________________________________________________ ___
+ * || |_| |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | |VME|
+ * || | | |
+ * || | |P1 |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || |_| |
+ * || |___|
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |
+ * || |___
+ * || _| |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | |VME|
+ * || | | |
+ * || | |P2 |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || |_| |
+ * || |___|
+ * || ||------------------------------------------------------------+-+
+ * ||||--||
+ * ||||--||
+ * ||
+ *
+ * History of Force Computers
+ *------------------------------------------------------------------------
+ * See fccpu30.cpp
+ *
+ * Description from datasheet etc
+ * ------------------------------
+ * - 68010 CPU for local control (10MHz)
+ * - 68450 DMA Controller for local transfers (10MHz)
+ * - Dual Ported l28Kbyte 0 wait state static RAM between the VMEbus and the local CPU
+ * - SCSlbus interface built with the NCR 5386S SCSlbus controller.
+ * o Programmable as an initiator or target
+ * o Transfer rate up to 1.5Mbyte/s
+ * - SHUGART compatible floppy interface with the WD1772 FDC. Up to 4 floppy drives can be
+ * controlled independent of the SCSlbus
+ * - All I/O signals available on P2 connector 4 different interrupt request signals to the VMEbus. Each
+ * channel contains a software programmable IRQ level (1 to 7) and vector
+ * - Local parallel interface for controlling and monitoring board functions
+ * - VMEbus Rev.C/IEEE P10l4 compatible interface A24:D16, D8, SYSFAIL (jumper)
+ * - Watchdog timer controlling correct functions of on-board hard and software
+ * - Status and control LEDs for monitoring local activities
+ * - High level handling firmware for communication, self test, data caching/hashing and control
+ *
+ * Address Map
+ * ----------------------------------------------------------
+ * Address Range Description
+ * ----------------------------------------------------------
+ * 000000 - 000007 Initialisation vectors from system EPROM
+ * 000008 - 001FFF Local SRAM
+ * 002000 - 01FFFF Dynamic Dual Port RAM VME bus accessible
+ * C40000 - C4001F SCSIbus controller
+ * C80000 - C800FF DMAC
+ * CC0000 - CC0007 FDC
+ * CC0009 - CC0009 Control Register
+ * D00000 - D0003F PI/T
+ * E00000 - E70000 EPROMs
+ * ----------------------------------------------------------
+ *
+ * VME side A24 address map - Dual ported RAM
+ * ----------------------------------------------------------
+ * Default Range Description
+ * ----------------------------------------------------------
+ * A00000 - A00000 Status word Bits 8:RESET 9:HALT 10:WD
+ * A00001 - A0000F BIM - See below
+ * A01001 - A01001 Read generates local interrupt
+ * A01801 - A01801 Read generates local reset
+ * A02000 - A1FFFF Dynamic Dual Port RAM
+ * ----------------------------------------------------------
+ *
+ * BIM Ctrl Vect Req Toggle PI/T Status PI/T
+ * ch adr adr pin write pin rea
+ * ----------------------------------------------------------
+ * 0 A00001 A00009 PA0 PA4
+ * 1 A00003 A0000B PA1 PA5
+ * 2 A00005 A0000D PA2 PA6
+ * 3 A00007 A0000F PA3 PA7
+ * ----------------------------------------------------------
+ *
+ * Interrupt sources
+ * ----------------------------------------------------------
+ * Description Device Lvl IRQ VME board
+ * /Board Vector Address
+ * ----------------------------------------------------------
+ * On board Sources
+ * ABORT P3 p13 1 AV1
+ * DMA controller 68450 2 DMAC/AV2
+ * SCSI bus controller NCR 5386S 3 AV3
+ * Floppy Disk controller WD 1772 4 AV4
+ * Parallel interface and timer 68230 5 PIT timer
+ * --- 6 ---
+ * Parallel interface and timer 68230 7 PIT port
+ * ----------------------------------------------------------
+ *
+ * TODO:
+ * - Write and attach a NCR5386S SCSI device
+ * - Find a floppy image and present it to the WD1772 floppy controller
+ * - Add VME bus driver
+ * - Let a controller CPU board (eg CPU-1 or CPU-30) boot from floppy or SCSI disk
+ *
+ ****************************************************************************/
+#include "emu.h"
+#include "sys68k_iscsi.h"
+
+#include "cpu/m68000/m68010.h"
+#include "machine/68230pit.h"
+#include "machine/wd_fdc.h"
+#include "machine/hd63450.h" // compatible with MC68450
+#include "machine/clock.h"
+
+#define VERBOSE (0) // (LOG_GENERAL)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+#define TODO "Driver for SCSI NCR5386s device needed\n"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(VME_SYS68K_ISCSI1, vme_sys68k_iscsi1_card_device, "sys68k_iscsi1", "Force Computers SYS68K/ISCSI-1")
+
+#define CPU_CRYSTAL 20_MHz_XTAL /* Jauch */
+#define PIT_CRYSTAL 16_MHz_XTAL /* Jauch */
+
+void vme_sys68k_iscsi1_card_device::fcscsi1_mem(address_map &map)
+{
+ map.unmap_value_high();
+
+ map(0x000000, 0x01ffff).ram(); /* SRAM */
+ map(0xe00000, 0xe1ffff).rom().region("eprom", 0); /* System EPROM Area 32Kb DEBUGGER supplied */
+ map(0xd00000, 0xd0003f).rw("pit", FUNC(pit68230_device::read), FUNC(pit68230_device::write)).umask16(0x00ff);
+// map(0xc40000, 0xc4001f).rw("scsi", FUNC(ncr5386_device::read), FUNC(ncr5386_device::write)).umask16(0x00ff); /* SCSI Controller interface - device support not yet available*/
+ map(0xc40000, 0xc4001f).rw(FUNC(vme_sys68k_iscsi1_card_device::scsi_r), FUNC(vme_sys68k_iscsi1_card_device::scsi_w)).umask16(0x00ff);
+ map(0xc80000, 0xc800ff).rw("mc68450", FUNC(hd63450_device::read), FUNC(hd63450_device::write)); /* DMA Controller interface */
+ map(0xcc0000, 0xcc0007).rw("fdc", FUNC(wd1772_device::read), FUNC(wd1772_device::write)).umask16(0x00ff); /* Floppy Controller interface */
+ map(0xcc0009, 0xcc0009).rw(FUNC(vme_sys68k_iscsi1_card_device::tcr_r), FUNC(vme_sys68k_iscsi1_card_device::tcr_w)); /* The Control Register, SCSI ID and FD drive select bits */
+}
+
+/*
+----------------------------------------------------
+ IRQ IRQ
+Level Source B4l inserted B4l removed (Def)
+-----------------------------------------------------
+ 1 P3 Pin #13 AV1 Autovector AV1 Autovector
+ 2 DMAC DMAC AV2 Autovector
+ 3 SCSIBC AV3 Autovector AV3 Autovector
+ 4 FDC AV4 Autovector AV4 Autovector
+ 5 PI/T Timer PI/T Timer Vect PI/T Timer Vect
+ 6 -- -- --
+ 7 PI/T Port PI/T Port Vect PI/T Port Vect
+------------------------------------------------------
+Default configuration: B41 jumper removed
+
+The PI/T port interrupt can be used under software control to
+cause non-maskable (Level 7) interrupts if the watchdog timer
+elapses and/or if the VMEbus interrupt trigger call occurs.
+*/
+
+/* TODO: Add configurable B41 jumper */
+#define B41 0
+
+void vme_sys68k_iscsi1_card_device::update_irq_to_maincpu() {
+ if (fdc_irq_state) {
+ m_maincpu->set_input_line(M68K_IRQ_3, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_2, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_1, CLEAR_LINE);
+ } else if (dmac_irq_state) {
+ m_maincpu->set_input_line(M68K_IRQ_3, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_1, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_2, ASSERT_LINE);
+ } else {
+ m_maincpu->set_input_line(M68K_IRQ_3, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_2, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_1, CLEAR_LINE);
+ }
+}
+
+void vme_sys68k_iscsi1_card_device::cpu_space_map(address_map &map)
+{
+ map(0xfffff0, 0xffffff).m(m_maincpu, FUNC(m68000_base_device::autovectors_map));
+ map(0xfffff5, 0xfffff5).r(FUNC(vme_sys68k_iscsi1_card_device::dma_iack));
+}
+
+static void fcscsi_floppies(device_slot_interface &device)
+{
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+
+/* ROM definitions */
+ROM_START (sys68k_iscsi1)
+ ROM_REGION16_BE (0x20000, "eprom", 0)
+
+ /* Besta ROM:s - apparantly patched Force ROM:s */
+ ROM_SYSTEM_BIOS(0, "besta88", "Besta 88")
+ ROMX_LOAD ("besta88_scsi_lower.rom", 0x00001, 0x4000, CRC (fb3ab364) SHA1 (d79112100f1c4beaf358e006efd4dde5e300b0ba), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD ("besta88_scsi_upper.rom", 0x00000, 0x4000, CRC (41f9cdf4) SHA1 (66b998bbf9459f0a613718260e05e97749532073), ROM_SKIP(1) | ROM_BIOS(0))
+
+ /* Force ROM:s */
+ ROM_SYSTEM_BIOS(1, "iscsi-1_v3.7", "Force Computer SYS68K/ISCSI-1 firmware v3.7")
+ ROMX_LOAD ("iscsi-1_v3.7_l.bin", 0x00001, 0x4000, CRC (83d95ab7) SHA1 (bf249910bcb6cb0b04dda2a95a38a0f90b553352), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD ("iscsi-1_v3.7_u.bin", 0x00000, 0x4000, CRC (58815831) SHA1 (074085ef96e1fe2a551938bdeee6a9cab40ff09c), ROM_SKIP(1) | ROM_BIOS(1))
+
+ROM_END
+
+
+void vme_sys68k_iscsi1_card_device::device_add_mconfig(machine_config &config)
+{
+ /* basic machine hardware */
+ M68010(config, m_maincpu, CPU_CRYSTAL / 2); /* 7474 based frequency divide by 2 */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_iscsi1_card_device::fcscsi1_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_sys68k_iscsi1_card_device::cpu_space_map);
+
+ /* FDC */
+ WD1772(config, m_fdc, PIT_CRYSTAL / 2);
+ m_fdc->intrq_wr_callback().set(FUNC(vme_sys68k_iscsi1_card_device::fdc_irq));
+ m_fdc->drq_wr_callback().set("mc68450", FUNC(hd63450_device::drq1_w));
+ FLOPPY_CONNECTOR(config, "fdc:0", fcscsi_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:1", fcscsi_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:2", fcscsi_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:3", fcscsi_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+
+ /* PIT Parallel Interface and Timer device */
+ PIT68230(config, m_pit, PIT_CRYSTAL / 2); /* 7474 based frequency divide by 2 */
+ m_pit->pb_out_callback().set(FUNC(vme_sys68k_iscsi1_card_device::led_w));
+
+ /* DMAC it is really a M68450 but the HD63850 is upwards compatible */
+ HD63450(config, m_dmac, CPU_CRYSTAL / 2, "maincpu"); // MC68450 compatible
+ m_dmac->set_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_usec(4), attotime::from_hz(15625/2));
+ m_dmac->set_burst_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_nsec(50), attotime::from_nsec(50));
+ m_dmac->irq_callback().set(FUNC(vme_sys68k_iscsi1_card_device::dma_irq));
+ //m_dmac->dma_read<0>().set(FUNC(vme_sys68k_iscsi1_card_device::scsi_read_byte)); // ch 0 = SCSI
+ //m_dmac->dma_write<0>().set(FUNC(vme_sys68k_iscsi1_card_device::scsi_write_byte));
+ m_dmac->dma_read<1>().set(FUNC(vme_sys68k_iscsi1_card_device::fdc_read_byte)); // ch 1 = fdc
+ m_dmac->dma_write<1>().set(FUNC(vme_sys68k_iscsi1_card_device::fdc_write_byte));
+}
+
+const tiny_rom_entry *vme_sys68k_iscsi1_card_device::device_rom_region() const
+{
+ LOG("%s\n", FUNCNAME);
+ return ROM_NAME(sys68k_iscsi1);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+vme_sys68k_iscsi1_card_device::vme_sys68k_iscsi1_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_fdc(*this, "fdc")
+ , m_pit(*this, "pit")
+ , m_dmac(*this, "mc68450")
+ , m_eprom(*this, "eprom")
+ , m_ram(*this, "ram")
+ , m_tcr(0)
+{
+ LOG("%s\n", FUNCNAME);
+}
+
+vme_sys68k_iscsi1_card_device::vme_sys68k_iscsi1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_iscsi1_card_device(mconfig, VME_SYS68K_ISCSI1, tag, owner, clock)
+{
+}
+
+/* Start it up */
+void vme_sys68k_iscsi1_card_device::device_start()
+{
+ LOG("%s\n", FUNCNAME);
+
+#if 0 // TODO: Setup VME access handlers for shared memory area
+ uint32_t base = 0x00A00000;
+ m_vme->install_device(base + 0, base + 1, // Channel B - Data
+ read8_delegate(FUNC(z80sio_device::db_r), subdevice<z80sio_device>("pit")), write8_delegate(FUNC(z80sio_device::db_w), subdevice<z80sio_device>("pit")), 0x00ff);
+ m_vme->install_device(base + 2, base + 3, // Channel B - Control
+ read8_delegate(FUNC(z80sio_device::cb_r), subdevice<z80sio_device>("pit")), write8_delegate(FUNC(z80sio_device::cb_w), subdevice<z80sio_device>("pit")), 0x00ff);
+#endif
+
+}
+
+void vme_sys68k_iscsi1_card_device::device_reset()
+{
+ LOG("%s\n", FUNCNAME);
+
+ m_maincpu->space(AS_PROGRAM).install_rom(0, m_eprom->bytes() - 1, m_eprom->base());
+
+ m_boot_mph = m_maincpu->space(AS_PROGRAM).install_read_tap(0x000006, 0x000007, "boot",
+ [this](offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ if (!machine().side_effects_disabled() && ACCESSING_BITS_0_7)
+ {
+ m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram.bytes() - 1, m_ram.target());
+ m_boot_mph.remove();
+ }
+ });
+}
+
+/* The Control Register - discretely implemented on the PCB
+Bit #: 7 6 5 4 3 2 1 0
+ \ \ \ \ \ \ \ \ Floppy Disk Side Select
+ \ \ \ \ \ \ \ Floppy Disk Drive Select 0
+ \ \ \ \ \ \ Floppy Disk Drive Select 1
+ \ \ \ \ \ Floppy Disk Drive Select 2
+ \ \ \ \ Floppy Disk Drive Select 3
+ \ \ \ ISCSI-l I.D. Bit #0
+ \ \ ISCSI-l I.D. Bit #1
+ \ ISCSI-l 1.D. Bit #2
+*/
+
+uint8_t vme_sys68k_iscsi1_card_device::tcr_r(){
+ LOG("%s\n", FUNCNAME);
+ return (uint8_t) m_tcr;
+}
+
+void vme_sys68k_iscsi1_card_device::tcr_w(uint8_t data){
+ floppy_image_device *floppy0 = m_fdc->subdevice<floppy_connector>("0")->get_device();
+ floppy_image_device *floppy1 = m_fdc->subdevice<floppy_connector>("1")->get_device();
+ floppy_image_device *floppy2 = m_fdc->subdevice<floppy_connector>("2")->get_device();
+ floppy_image_device *floppy3 = m_fdc->subdevice<floppy_connector>("3")->get_device();
+ floppy_image_device *floppy = nullptr;
+
+ if (!BIT(data, 1)) floppy = floppy0;
+ else
+ if (!BIT(data, 2)) floppy = floppy1;
+ else
+ if (!BIT(data, 3)) floppy = floppy2;
+ else
+ if (!BIT(data, 4)) floppy = floppy3;
+
+ if (floppy) {
+ m_fdc->set_floppy(floppy);
+ floppy->ss_w(!BIT(data, 0));
+ floppy->mon_w(0);
+ } else {
+ floppy0->mon_w(1);
+ floppy1->mon_w(1);
+ floppy2->mon_w(1);
+ floppy3->mon_w(1);
+ }
+
+ LOG("%s [%02x]\n", FUNCNAME, data);
+ m_tcr = data;
+ return;
+}
+
+void vme_sys68k_iscsi1_card_device::led_w(uint8_t data) {
+ LOG("%s [%02x]\n", FUNCNAME, data);
+
+ m_fdc->dden_w(BIT(data, 7));
+
+ return;
+}
+
+void vme_sys68k_iscsi1_card_device::dma_irq(int state)
+{
+ if(state != CLEAR_LINE)
+ {
+ logerror("DMAC IRQ, vector = %x\n", m_dmac->iack());
+ dmac_irq_state = 1;
+ }
+ else
+ {
+ dmac_irq_state = 0;
+ }
+
+ update_irq_to_maincpu();
+}
+
+uint8_t vme_sys68k_iscsi1_card_device::dma_iack()
+{
+ if (B41)
+ return m_dmac->iack();
+ else
+ return m68000_base_device::autovector(2);
+}
+
+void vme_sys68k_iscsi1_card_device::fdc_irq(int state)
+{
+ if (state != 0)
+ {
+ fdc_irq_state = 1;
+ }
+ else
+ {
+ fdc_irq_state = 0;
+ }
+ update_irq_to_maincpu();
+}
+
+uint8_t vme_sys68k_iscsi1_card_device::fdc_read_byte()
+{
+ return m_fdc->data_r();
+}
+
+void vme_sys68k_iscsi1_card_device::fdc_write_byte(uint8_t data)
+{
+ m_fdc->data_w(data & 0xff);
+}
+
+uint8_t vme_sys68k_iscsi1_card_device::scsi_r(offs_t offset)
+{
+ uint8_t data = 0;
+
+ // fake diag status
+ if (offset == 9)
+ data = 0x80;
+
+ LOG("scsi R %02x == %02x\n", offset, data);
+
+ return data;
+}
+
+void vme_sys68k_iscsi1_card_device::scsi_w(offs_t offset, uint8_t data)
+{
+ LOG("scsi W %02x <- %02x\n", offset, data);
+}
+
+uint8_t vme_sys68k_iscsi1_card_device::not_implemented_r(){
+ static int been_here = 0;
+ if (!been_here++){
+ logerror(TODO);
+ printf(TODO);
+ }
+ return (uint8_t) 0;
+}
+
+void vme_sys68k_iscsi1_card_device::not_implemented_w(uint8_t data){
+ static int been_here = 0;
+ if (!been_here++){
+ logerror(TODO);
+ printf(TODO);
+ }
+ return;
+}
+
+// This info isn't kept in a card driver atm so storing it as a comment for later use
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
+//COMP( 1986, fcscsi1, 0, 0, fcscsi1, fcscsi1, driver_device, 0, "Force Computers Gmbh", "SYS68K/SCSI-1", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )