From 6af0958209d2609fa9e34d0a27c02c4962100bce Mon Sep 17 00:00:00 2001 From: Bill Beech Date: Wed, 16 Oct 2019 13:41:27 -0700 Subject: [PATCH] Intel-Systems: Update and cleanup components --- Intel-Systems/common/i3214.c | 275 ++ Intel-Systems/common/i8080.c | 174 +- Intel-Systems/common/i8237.c | 452 ++-- Intel-Systems/common/i8251.c | 171 +- Intel-Systems/common/i8253.c | 155 +- Intel-Systems/common/i8255.c | 170 +- Intel-Systems/common/i8259.c | 188 +- Intel-Systems/common/i8272.c | 844 +++++- Intel-Systems/common/ieprom.c | 74 +- Intel-Systems/common/ieprom1.c | 150 ++ Intel-Systems/common/ioc-cont.c | 122 +- Intel-Systems/common/ipb.c | 181 ++ Intel-Systems/common/ipbmultibus.c | 373 +++ Intel-Systems/common/ipc-cont.c | 44 +- Intel-Systems/{imds-225 => common}/ipc.c | 105 +- Intel-Systems/common/ipcmultibus.c | 132 +- Intel-Systems/common/iram8.c | 59 +- Intel-Systems/common/isbc064.c | 132 +- Intel-Systems/common/isbc201.c | 466 ++-- Intel-Systems/common/isbc202.c | 491 ++-- Intel-Systems/common/isbc206.c | 605 +++++ Intel-Systems/common/isbc208.c | 3096 ++++++++++------------ Intel-Systems/common/isbc464.c | 175 ++ Intel-Systems/common/m800multibus.c | 373 +++ Intel-Systems/common/multibus.c | 201 +- Intel-Systems/common/zx200a.c | 596 +++-- Intel-Systems/imds-210/imds-210_sys.c | 98 + Intel-Systems/imds-210/system_defs.h | 156 ++ Intel-Systems/imds-220/imds-220_sys.c | 85 + Intel-Systems/imds-220/system_defs.h | 156 ++ Intel-Systems/imds-225/imds-225_sys.c | 2 + Intel-Systems/imds-225/system_defs.h | 41 +- Intel-Systems/imds-230/imds-230_sys.c | 87 + Intel-Systems/imds-230/system_defs.h | 155 ++ Intel-Systems/imds-800/cpu.c | 142 + Intel-Systems/imds-800/front_panel.c | 64 + Intel-Systems/imds-800/imds-800_sys.c | 84 + Intel-Systems/imds-800/monitor.c | 77 + Intel-Systems/imds-800/system_defs.h | 140 + Intel-Systems/imds-810/cpu.c | 142 + Intel-Systems/imds-810/front_panel.c | 68 + Intel-Systems/imds-810/imds-810_sys.c | 84 + Intel-Systems/imds-810/monitor.c | 83 + Intel-Systems/imds-810/system_defs.h | 140 + Intel-Systems/isys8010/isbc8010.c | 75 +- Intel-Systems/isys8010/isys8010_sys.c | 9 +- Intel-Systems/isys8010/system_defs.h | 36 +- Intel-Systems/isys8020/isbc8020.c | 92 +- Intel-Systems/isys8020/isys8020_sys.c | 4 + Intel-Systems/isys8020/system_defs.h | 35 +- Intel-Systems/isys8024/isbc8024.c | 80 +- Intel-Systems/isys8024/system_defs.h | 27 +- Intel-Systems/isys8030/isbc8030.c | 76 +- Intel-Systems/isys8030/system_defs.h | 25 +- Intel-Systems/isys80XX/isys80XX_sys.c | 92 + Intel-Systems/isys80XX/system_defs.h | 150 ++ Visual Studio Projects/Simh.sln | 30 + Visual Studio Projects/imds-210.vcproj | 377 +++ Visual Studio Projects/imds-220.vcproj | 381 +++ Visual Studio Projects/imds-225.vcproj | 18 +- Visual Studio Projects/imds-230.vcproj | 381 +++ Visual Studio Projects/imds-800.vcproj | 373 +++ Visual Studio Projects/imds-810.vcproj | 373 +++ Visual Studio Projects/isys8010.vcproj | 8 + Visual Studio Projects/isys8020.vcproj | 12 + Visual Studio Projects/isys8024.vcproj | 8 + Visual Studio Projects/isys8030.vcproj | 8 + makefile | 142 +- 68 files changed, 10662 insertions(+), 3758 deletions(-) create mode 100644 Intel-Systems/common/i3214.c create mode 100644 Intel-Systems/common/ieprom1.c create mode 100644 Intel-Systems/common/ipb.c create mode 100644 Intel-Systems/common/ipbmultibus.c rename Intel-Systems/{imds-225 => common}/ipc.c (64%) create mode 100644 Intel-Systems/common/isbc206.c create mode 100644 Intel-Systems/common/isbc464.c create mode 100644 Intel-Systems/common/m800multibus.c create mode 100644 Intel-Systems/imds-210/imds-210_sys.c create mode 100644 Intel-Systems/imds-210/system_defs.h create mode 100644 Intel-Systems/imds-220/imds-220_sys.c create mode 100644 Intel-Systems/imds-220/system_defs.h create mode 100644 Intel-Systems/imds-230/imds-230_sys.c create mode 100644 Intel-Systems/imds-230/system_defs.h create mode 100644 Intel-Systems/imds-800/cpu.c create mode 100644 Intel-Systems/imds-800/front_panel.c create mode 100644 Intel-Systems/imds-800/imds-800_sys.c create mode 100644 Intel-Systems/imds-800/monitor.c create mode 100644 Intel-Systems/imds-800/system_defs.h create mode 100644 Intel-Systems/imds-810/cpu.c create mode 100644 Intel-Systems/imds-810/front_panel.c create mode 100644 Intel-Systems/imds-810/imds-810_sys.c create mode 100644 Intel-Systems/imds-810/monitor.c create mode 100644 Intel-Systems/imds-810/system_defs.h create mode 100644 Intel-Systems/isys80XX/isys80XX_sys.c create mode 100644 Intel-Systems/isys80XX/system_defs.h create mode 100644 Visual Studio Projects/imds-210.vcproj create mode 100644 Visual Studio Projects/imds-220.vcproj create mode 100644 Visual Studio Projects/imds-230.vcproj create mode 100644 Visual Studio Projects/imds-800.vcproj create mode 100644 Visual Studio Projects/imds-810.vcproj diff --git a/Intel-Systems/common/i3214.c b/Intel-Systems/common/i3214.c new file mode 100644 index 00000000..8396ffe9 --- /dev/null +++ b/Intel-Systems/common/i3214.c @@ -0,0 +1,275 @@ +/* i3214.c: Intel i3214 PICU adapter + + Copyright (c) 2019, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + 12 OCT 19 - Original file. + + NOTES: + + These functions support a simulated i3214 interface device on an iSBC. + The device had three physical I/O port which could be connected + as needed. This device was replaced by the 8259. + + All I/O is via programmed I/O. The i3214 has a status port + and two data port. + +save for now! + + A write to the status port can select some options for the device: + + Asynchronous Mode Instruction + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | S2 S1 EP PEN L2 L1 B2 B1| + +---+---+---+---+---+---+---+---+ + + Baud Rate Factor + B2 0 1 0 1 + B1 0 0 1 1 + sync 1X 16X 64X + mode + + Character Length + L2 0 1 0 1 + L1 0 0 1 1 + 5 6 7 8 + bits bits bits bits + + EP - A 1 in this bit position selects even parity. + PEN - A 1 in this bit position enables parity. + + Number of Stop Bits + S2 0 1 0 1 + S1 0 0 1 1 + invalid 1 1.5 2 + bit bits bits + + Command Instruction Format + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | EH IR RTS ER SBRK RxE DTR TxE| + +---+---+---+---+---+---+---+---+ + + TxE - A 1 in this bit position enables transmit. + DTR - A 1 in this bit position forces *DTR to zero. + RxE - A 1 in this bit position enables receive. + SBRK - A 1 in this bit position forces TxD to zero. + ER - A 1 in this bit position resets the error bits + RTS - A 1 in this bit position forces *RTS to zero. + IR - A 1 in this bit position returns the 8251 to Mode Instruction Format. + EH - A 1 in this bit position enables search for sync characters. + + A read of the status port gets the port status: + + Status Read Format + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + |DSR SD FE OE PE TxE RxR TxR| + +---+---+---+---+---+---+---+---+ + + TxR - A 1 in this bit position signals transmit ready to receive a character. + RxR - A 1 in this bit position signals receiver has a character. + TxE - A 1 in this bit position signals transmitter has no more characters to transmit. + PE - A 1 in this bit signals a parity error. + OE - A 1 in this bit signals an transmit overrun error. + FE - A 1 in this bit signals a framing error. + SD - A 1 in this bit position returns the 8251 to Mode Instruction Format. + DSR - A 1 in this bit position signals *DSR is at zero. + + A read from the data port gets the typed character, a write + to the data port writes the character to the device. +*/ + +#include "system_defs.h" + +// 3214 status bits + +/* external globals */ + +/* external function prototypes */ + +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); + +/* globals */ + +uint8 i3214_mask = 0; +uint8 i3214_cnt = 0; +uint8 i3214_ram[16]; +uint8 EPROM_enable = 1; +uint8 BUS_OVERRIDE = 0; +uint8 monitor_boot = 0x00; + +/* function prototypes */ + +t_stat i3214_cfg(uint8 base, uint8 devnum); +t_stat i3214_reset (DEVICE *dptr); +t_stat i3214_reset_dev (uint8 devnum); +t_stat i3214_svc (UNIT *uptr); +uint8 i3214_do_mask(t_bool io, uint8 data, uint8 devnum); +uint8 i3214_do_status(t_bool io, uint8 data, uint8 devnum); +uint8 i3214_cpu_bus_override(t_bool io, uint8 data, uint8 devnum); +uint8 i3214_monitor_do_boot(t_bool io, uint8 data, uint8 devnum); + +/* i3214 Standard I/O Data Structures */ +/* 1 i3214 device */ + +UNIT i3214_unit[] = { + { UDATA (&i3214_svc, 0, 0), KBD_POLL_WAIT } +}; + +REG i3214_reg[] = { + { HRDATA (MASK0, i3214_mask, 8) }, + { HRDATA (CNT0, i3214_cnt, 8) }, + { HRDATA (RAM0, i3214_ram, 8) }, + { NULL } +}; + +DEBTAB i3214_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +MTAB i3214_mod[] = { + { 0 } +}; + +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + +DEVICE i3214_dev = { + "I3214", //name + i3214_unit, //units + i3214_reg, //registers + i3214_mod, //modifiers + I3214_NUM, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + i3214_reset, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + i3214_debug, //debflags + NULL, //msize + NULL //lname +}; + +// i3214 configuration + +t_stat i3214_cfg(uint8 base, uint8 devnum) +{ + sim_printf(" i3214[%d]: at base port 0%02XH\n", + devnum, base & 0xFF); + reg_dev(i3214_do_mask, base, devnum); + reg_dev(i3214_do_status, base + 1, devnum); + reg_dev(i3214_cpu_bus_override, base + 2, devnum); + reg_dev(i3214_monitor_do_boot, base + 3, devnum); + return SCPE_OK; +} + +/* Service routines to handle simulator functions */ + +/* i3214_svc - actually gets char & places in buffer */ + +t_stat i3214_svc (UNIT *uptr) +{ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i3214_reset (DEVICE *dptr) +{ + uint8 devnum; + + for (devnum=0; devnumflags & UNIT_8085) - sim_printf("CPU = 8085\n"); - else - sim_printf("CPU = 8080\n"); + + if (onetime++ == 0) { + if (uptr->flags & UNIT_8085) + sim_printf("CPU = 8085\n"); + else + sim_printf("CPU = 8080\n"); + sim_printf(" i8080:\n"); + } + /* Main instruction fetch/decode loop */ while (reason == 0) { /* loop until halted */ @@ -437,9 +450,11 @@ int32 sim_instr (void) } } else { /* 8080 */ if (IM & IE) { /* enabled? */ - push_word(PC); /* do an RST 7 */ - PC = 0x0038; - int_req &= ~INT_R; + INTA = 1; + push_word(PC); /* do an RST 2 */ + PC = 0x0010; + int_req = 0; +// sim_printf("8080 Interrupt\n"); } } } /* end interrupt */ @@ -450,20 +465,22 @@ int32 sim_instr (void) break; } - sim_interval--; /* countdown clock */ - PCX = PC; - if (uptr->flags & UNIT_TRACE) { dumpregs(); - sim_printf("\n"); +// sim_printf("\n"); } + + sim_interval--; /* countdown clock */ + PCY = PCX = PC; + IR = OP = fetch_byte(0); /* instruction fetch */ - if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */ + if (GET_XACK(1) == 0) { // no XACK for instruction fetch // reason = STOP_XACK; - sim_printf("Stopped for XACK-1 PC=%04X\n", PC); + if (uptr->flags & UNIT_XACK) + sim_printf("Failed XACK for Instruction Fetch from %04X\n", PCX); // continue; - } + } // first instruction decode if (OP == 0x76) { /* HLT Instruction*/ @@ -509,6 +526,7 @@ int32 sim_instr (void) DAR = A; DAR -= getreg(OP & 0x07); setarith(DAR); + A &= BYTE_R; //required *** goto loop_end; } @@ -589,6 +607,7 @@ int32 sim_instr (void) DAR = getreg((OP >> 3) & 0x07); DAR++; setinc(DAR); + DAR &= BYTE_R; //required putreg((OP >> 3) & 0x07, DAR); goto loop_end; } @@ -597,6 +616,7 @@ int32 sim_instr (void) DAR = getreg((OP >> 3) & 0x07); DAR--; setinc(DAR); + DAR &= BYTE_R; //required putreg((OP >> 3) & 0x07, DAR); goto loop_end; } @@ -604,6 +624,7 @@ int32 sim_instr (void) if ((OP & 0xCF) == 0x03) { /* INX */ DAR = getpair((OP >> 4) & 0x03); DAR++; + DAR &= WORD_R; //required putpair((OP >> 4) & 0x03, DAR); goto loop_end; } @@ -611,6 +632,7 @@ int32 sim_instr (void) if ((OP & 0xCF) == 0x0B) { /* DCX */ DAR = getpair((OP >> 4) & 0x03); DAR--; + DAR &= WORD_R; //required putpair((OP >> 4) & 0x03, DAR); goto loop_end; } @@ -767,7 +789,6 @@ int32 sim_instr (void) if (GET_FLAG(CF)) A--; A &= BYTE_R; //required - A &= BYTE_R; break; case 0x27: /* DAA */ @@ -788,41 +809,47 @@ int32 sim_instr (void) COND_SET_FLAG(DAR & 0x10, CF); COND_SET_FLAG(A & 0x80, SF); COND_SET_FLAG((A & 0xFF) == 0, ZF); + A &= BYTE_R; //required parity(A); break; case 0x07: /* RLC */ COND_SET_FLAG(A & 0x80, CF); - A = (A << 1) & 0xFF; + A = A << 1; if (GET_FLAG(CF)) A |= 0x01; + A &= BYTE_R; //required break; case 0x0F: /* RRC */ COND_SET_FLAG(A & 0x01, CF); - A = (A >> 1) & 0xFF; + A = A >> 1; if (GET_FLAG(CF)) A |= 0x80; + A &= BYTE_R; //required break; case 0x17: /* RAL */ DAR = GET_FLAG(CF); COND_SET_FLAG(A & 0x80, CF); - A = (A << 1) & 0xFF; + A = A << 1; if (DAR) A |= 0x01; + A &= BYTE_R; //required break; case 0x1F: /* RAR */ DAR = GET_FLAG(CF); COND_SET_FLAG(A & 0x01, CF); - A = (A >> 1) & 0xFF; + A = A >> 1; if (DAR) A |= 0x80; + A &= BYTE_R; //required break; case 0x2F: /* CMA */ A = ~A; + A &= BYTE_R; //required break; case 0x3F: /* CMC */ @@ -857,15 +884,13 @@ int32 sim_instr (void) break; case 0xDB: /* IN */ - DAR = fetch_byte(1); - port = DAR; - A = dev_table[DAR].routine(0, 0); + port = fetch_byte(1); + A = dev_table[port].routine(0, 0, dev_table[port].devnum); break; case 0xD3: /* OUT */ - DAR = fetch_byte(1); - port = DAR; - dev_table[DAR].routine(1, A); + port = fetch_byte(1); + dev_table[port].routine(1, A, dev_table[port].devnum); break; default: /* undefined opcode */ @@ -876,10 +901,17 @@ int32 sim_instr (void) break; } loop_end: - if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */ + + if (GET_XACK(1) == 0) { // no XACK for operand fetch // reason = STOP_XACK; -// sim_printf("Stopped for XACK-2 PC=%04X\n", PC); + if (OP == 0xD3 || OP == 0xDB) { + if (uptr->flags & UNIT_XACK) + sim_printf("Failed XACK for Port %02X Fetch from %04X\n", port, PCX); + } else { + if (uptr->flags & UNIT_XACK) + sim_printf("Failed XACK for Operand %04X Fetch from %04X\n", addr, PCX); // continue; + } } } @@ -892,33 +924,25 @@ loop_end: /* dump the registers */ void dumpregs(void) { - sim_printf(" A=%02X BC=%04X DE=%04X HL=%04X SP=%04X IM=%02X XACK=%d\n", - A, BC, DE, HL, SP, IM, xack); - sim_printf(" CF=%d ZF=%d AF=%d SF=%d PF=%d\n", + sim_printf(" PC=%04X A=%02X BC=%04X DE=%04X HL=%04X SP=%04X IM=%02X XACK=%d", + PCY, A, BC, DE, HL, SP, IM, xack); + sim_printf(" IR=%02X addr=%04X", IR, addr); + sim_printf(" CF=%d ZF=%d AF=%d SF=%d PF=%d\n", GET_FLAG(CF) ? 1 : 0, GET_FLAG(ZF) ? 1 : 0, GET_FLAG(AF) ? 1 : 0, GET_FLAG(SF) ? 1 : 0, GET_FLAG(PF) ? 1 : 0); } + /* fetch an instruction or byte */ int32 fetch_byte(int32 flag) { uint32 val; val = get_mbyte(PC) & 0xFF; /* fetch byte */ - if (i8080_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) { /* display source code */ - switch (flag) { - case 0: /* opcode fetch */ - sim_printf("OP=%02X %04X %s", val, PC, opcode[val]); - break; - case 1: /* byte operand fetch */ - sim_printf("0%02XH", val); - break; - } - } PC = (PC + 1) & ADDRMASK; /* increment PC */ - val &= BYTE_R; + addr = val & 0xff; return val; } @@ -929,10 +953,11 @@ int32 fetch_word(void) val = get_mbyte(PC) & BYTE_R; /* fetch low byte */ val |= get_mbyte(PC + 1) << 8; /* fetch high byte */ - if (i8080_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) /* display source code */ - sim_printf("0%04XH", val); +// if (i8080_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) /* display source code */ +// sim_printf("0%04XH", val); PC = (PC + 2) & ADDRMASK; /* increment PC */ val &= WORD_R; + addr = val; return val; } @@ -1039,7 +1064,7 @@ void parity(int32 reg) SET_FLAG(PF); } -/* Set the ign, ero amd

arity flags following +/* Set the ign, ero and

arity flags following an INR/DCR operation on 'reg'. */ @@ -1156,7 +1181,7 @@ int32 getpush(int32 reg) /* Place data into the indicated register pair, in PUSH - format where 3 means A& flags, not SP */ + format where 3 means A & flags, not SP */ void putpush(int32 reg, int32 data) { switch (reg) { @@ -1210,8 +1235,8 @@ t_stat i8080_reset (DEVICE *dptr) saved_PC = 0; int_req = 0; IM = 0; + INTA = 0; sim_brk_types = sim_brk_dflt = SWMASK ('E'); - sim_printf(" 8080: Reset\n"); return SCPE_OK; } @@ -1245,14 +1270,25 @@ int32 sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) { int32 i, addr = 0, cnt = 0; - if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; - addr = saved_PC; - while ((i = getc (fileref)) != EOF) { - put_mbyte(addr, i); - addr++; - cnt++; - } /* end while */ - sim_printf ("%d Bytes loaded.\n", cnt); + if ((*cptr != 0)) return SCPE_ARG; + if (flag == 0) { //load +// addr = saved_PC; + while ((i = getc (fileref)) != EOF) { + put_mbyte(addr, i); + addr++; + cnt++; + } /* end while */ + sim_printf ("%d Bytes loaded.\n", cnt); + return (SCPE_OK); + } else { //dump +// addr = saved_PC; + while (addr <= 0xffff) { + i = get_mbyte(addr); + putc(i, fileref); + addr++; + cnt++; + } + } return (SCPE_OK); } diff --git a/Intel-Systems/common/i8237.c b/Intel-Systems/common/i8237.c index 49d13cf9..c443bb9f 100644 --- a/Intel-Systems/common/i8237.c +++ b/Intel-Systems/common/i8237.c @@ -239,11 +239,6 @@ extern uint16 port; //port called in dev_table[port] -/* globals */ - -int32 i8237_devnum = 0; //actual number of 8253 instances + 1 -uint16 i8237_port[4]; //base port registered to each instance - /* internal function prototypes */ t_stat i8237_svc (UNIT *uptr); @@ -271,32 +266,37 @@ uint8 i8237_rFx(t_bool io, uint8 data); extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); +/* globals */ + +int32 i8237_devnum = 0; //actual number of 8253 instances + 1 +uint16 i8237_port[4]; //base port registered to each instance + /* 8237 physical register definitions */ -uint16 i8237_r0; // 8237 ch 0 address register -uint16 i8237_r1; // 8237 ch 0 count register -uint16 i8237_r2; // 8237 ch 1 address register -uint16 i8237_r3; // 8237 ch 1 count register -uint16 i8237_r4; // 8237 ch 2 address register -uint16 i8237_r5; // 8237 ch 2 count register -uint16 i8237_r6; // 8237 ch 3 address register -uint16 i8237_r7; // 8237 ch 3 count register -uint8 i8237_r8; // 8237 status register -uint8 i8237_r9; // 8237 command register -uint8 i8237_rA; // 8237 mode register -uint8 i8237_rB; // 8237 mask register -uint8 i8237_rC; // 8237 request register -uint8 i8237_rD; // 8237 first/last ff -uint8 i8237_rE; // 8237 -uint8 i8237_rF; // 8237 +uint16 i8237_r0[4]; // 8237 ch 0 address register +uint16 i8237_r1[4]; // 8237 ch 0 count register +uint16 i8237_r2[4]; // 8237 ch 1 address register +uint16 i8237_r3[4]; // 8237 ch 1 count register +uint16 i8237_r4[4]; // 8237 ch 2 address register +uint16 i8237_r5[4]; // 8237 ch 2 count register +uint16 i8237_r6[4]; // 8237 ch 3 address register +uint16 i8237_r7[4]; // 8237 ch 3 count register +uint8 i8237_r8[4]; // 8237 status register +uint8 i8237_r9[4]; // 8237 command register +uint8 i8237_rA[4]; // 8237 mode register +uint8 i8237_rB[4]; // 8237 mask register +uint8 i8237_rC[4]; // 8237 request register +uint8 i8237_rD[4]; // 8237 first/last ff +uint8 i8237_rE[4]; // 8237 +uint8 i8237_rF[4]; // 8237 /* i8237 physical register definitions */ -uint16 i8237_sr; // isbc-208 segment register -uint8 i8237_i; // iSBC-208 interrupt register -uint8 i8237_a; // iSBC-208 auxillary port register +uint16 i8237_sr[4]; // 8237 segment register +uint8 i8237_i[4]; // 8237 interrupt register +uint8 i8237_a[4]; // 8237 auxillary port register -/* i8237 Standard SIMH Device Data Structures - 1 unit */ +/* i8237 Standard SIMH Device Data Structures - 4 units */ UNIT i8237_unit[] = { { UDATA (0, 0, 0) ,20 }, /* i8237 0 */ @@ -305,25 +305,75 @@ UNIT i8237_unit[] = { { UDATA (0, 0, 0) ,20 } /* i8237 3 */ }; - REG i8237_reg[] = { - { HRDATA (CH0ADR, i8237_r0, 16) }, - { HRDATA (CH0CNT, i8237_r1, 16) }, - { HRDATA (CH1ADR, i8237_r2, 16) }, - { HRDATA (CH1CNT, i8237_r3, 16) }, - { HRDATA (CH2ADR, i8237_r4, 16) }, - { HRDATA (CH2CNT, i8237_r5, 16) }, - { HRDATA (CH3ADR, i8237_r6, 16) }, - { HRDATA (CH3CNT, i8237_r7, 16) }, - { HRDATA (STAT37, i8237_r8, 8) }, - { HRDATA (CMD37, i8237_r9, 8) }, - { HRDATA (MODE, i8237_rA, 8) }, - { HRDATA (MASK, i8237_rB, 8) }, - { HRDATA (REQ, i8237_rC, 8) }, - { HRDATA (FF, i8237_rD, 8) }, - { HRDATA (SEGREG, i8237_sr, 8) }, - { HRDATA (AUX, i8237_a, 8) }, - { HRDATA (INT, i8237_i, 8) }, + { HRDATA (CH0ADR0, i8237_r0[0], 16) }, /* i8237 0 */ + { HRDATA (CH0CNT0, i8237_r1[0], 16) }, + { HRDATA (CH1ADR0, i8237_r2[0], 16) }, + { HRDATA (CH1CNT0, i8237_r3[0], 16) }, + { HRDATA (CH2ADR0, i8237_r4[0], 16) }, + { HRDATA (CH2CNT0, i8237_r5[0], 16) }, + { HRDATA (CH3ADR0, i8237_r6[0], 16) }, + { HRDATA (CH3CNT0, i8237_r7[0], 16) }, + { HRDATA (STAT370, i8237_r8[0], 8) }, + { HRDATA (CMD370, i8237_r9[0], 8) }, + { HRDATA (MODE0, i8237_rA[0], 8) }, + { HRDATA (MASK0, i8237_rB[0], 8) }, + { HRDATA (REQ0, i8237_rC[0], 8) }, + { HRDATA (FF0, i8237_rD[0], 8) }, + { HRDATA (SEGREG0, i8237_sr[0], 8) }, + { HRDATA (AUX0, i8237_a[0], 8) }, + { HRDATA (INT0, i8237_i[0], 8) }, + { HRDATA (CH0ADR1, i8237_r0[1], 16) }, /* i8237 1 */ + { HRDATA (CH0CNT1, i8237_r1[1], 16) }, + { HRDATA (CH1ADR1, i8237_r2[1], 16) }, + { HRDATA (CH1CNT1, i8237_r3[1], 16) }, + { HRDATA (CH2ADR1, i8237_r4[1], 16) }, + { HRDATA (CH2CNT1, i8237_r5[1], 16) }, + { HRDATA (CH3ADR1, i8237_r6[1], 16) }, + { HRDATA (CH3CNT1, i8237_r7[1], 16) }, + { HRDATA (STAT371, i8237_r8[1], 8) }, + { HRDATA (CMD371, i8237_r9[1], 8) }, + { HRDATA (MODE1, i8237_rA[1], 8) }, + { HRDATA (MASK1, i8237_rB[1], 8) }, + { HRDATA (REQ1, i8237_rC[1], 8) }, + { HRDATA (FF1, i8237_rD[1], 8) }, + { HRDATA (SEGREG1, i8237_sr[1], 8) }, + { HRDATA (AUX1, i8237_a[1], 8) }, + { HRDATA (INT1, i8237_i[1], 8) }, + { HRDATA (CH0ADR2, i8237_r0[2], 16) }, /* i8237 2 */ + { HRDATA (CH0CNT2, i8237_r1[2], 16) }, + { HRDATA (CH1ADR2, i8237_r2[2], 16) }, + { HRDATA (CH1CNT2, i8237_r3[2], 16) }, + { HRDATA (CH2ADR2, i8237_r4[2], 16) }, + { HRDATA (CH2CNT2, i8237_r5[2], 16) }, + { HRDATA (CH3ADR2, i8237_r6[2], 16) }, + { HRDATA (CH3CNT2, i8237_r7[2], 16) }, + { HRDATA (STAT372, i8237_r8[2], 8) }, + { HRDATA (CMD372, i8237_r9[2], 8) }, + { HRDATA (MODE2, i8237_rA[2], 8) }, + { HRDATA (MASK2, i8237_rB[2], 8) }, + { HRDATA (REQ2, i8237_rC[2], 8) }, + { HRDATA (FF2, i8237_rD[2], 8) }, + { HRDATA (SEGREG2, i8237_sr[2], 8) }, + { HRDATA (AUX2, i8237_a[2], 8) }, + { HRDATA (INT2, i8237_i[2], 8) }, + { HRDATA (CH0ADR3, i8237_r0[3], 16) }, /* i8237 3 */ + { HRDATA (CH0CNT3, i8237_r1[3], 16) }, + { HRDATA (CH1ADR3, i8237_r2[3], 16) }, + { HRDATA (CH1CNT3, i8237_r3[3], 16) }, + { HRDATA (CH2ADR3, i8237_r4[3], 16) }, + { HRDATA (CH2CNT3, i8237_r5[3], 16) }, + { HRDATA (CH3ADR3, i8237_r6[3], 16) }, + { HRDATA (CH3CNT3, i8237_r7[3], 16) }, + { HRDATA (STAT373, i8237_r8[3], 8) }, + { HRDATA (CMD373, i8237_r9[3], 8) }, + { HRDATA (MODE3, i8237_rA[3], 8) }, + { HRDATA (MASK3, i8237_rB[3], 8) }, + { HRDATA (REQ3, i8237_rC[3], 8) }, + { HRDATA (FF3, i8237_rD[3], 8) }, + { HRDATA (SEGREG3, i8237_sr[3], 8) }, + { HRDATA (AUX3, i8237_a[3], 8) }, + { HRDATA (INT3, i8237_i[3], 8) }, { NULL } }; @@ -343,11 +393,11 @@ DEBTAB i8237_debug[] = { }; DEVICE i8237_dev = { - "8237", //name - i8237_unit, //units - i8237_reg, //registers - i8237_mod, //modifiers - 1, //numunits + "8237", //name + i8237_unit, //units + i8237_reg, //registers + i8237_mod, //modifiers + I8237_NUM, //numunits 16, //aradix 32, //awidth 1, //aincr @@ -355,16 +405,14 @@ DEVICE i8237_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// &i8237_reset, //deposit - NULL, //reset + NULL, //reset NULL, //boot - NULL, //attach + NULL, //attach NULL, //detach NULL, //ctxt - DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags + 0, //flags 0, //dctrl -// DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl - i8237_debug, //debflags + i8237_debug, //debflags NULL, //msize NULL //lname }; @@ -428,6 +476,7 @@ void i8237_reset1(void) int32 i; UNIT *uptr; static int flag = 1; + uint8 devnum; for (i = 0; i < 1; i++) { /* handle all units */ uptr = i8237_dev.units + i; @@ -448,11 +497,12 @@ void i8237_reset1(void) // sim_printf(" SBC208%d: Configured, Attached to %s\n", i, uptr->filename); } } - i8237_r8 = 0; /* status */ - i8237_r9 = 0; /* command */ - i8237_rB = 0x0F; /* mask */ - i8237_rC = 0; /* request */ - i8237_rD = 0; /* first/last FF */ + devnum = uptr->u6; + i8237_r8[devnum] = 0; /* status */ + i8237_r9[devnum] = 0; /* command */ + i8237_rB[devnum] = 0x0F; /* mask */ + i8237_rC[devnum] = 0; /* request */ + i8237_rD[devnum] = 0; /* first/last FF */ } @@ -481,24 +531,24 @@ uint8 i8237_r0x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(H) read as %04X\n", i8237_r0); - return (i8237_r0 >> 8); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[devnum](H) read as %04X\n", i8237_r0[devnum]); + return (i8237_r0[devnum] >> 8); } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) read as %04X\n", i8237_r0); - return (i8237_r0 & 0xFF); + i8237_rD[devnum]++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[devnum](L) read as %04X\n", i8237_r0[devnum]); + return (i8237_r0[devnum] & 0xFF); } } else { /* write base & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r0 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(H) set to %04X\n", i8237_r0); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + i8237_r0[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[devnum](H) set to %04X\n", i8237_r0[devnum]); } else { /* low byte */ - i8237_rD++; - i8237_r0 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) set to %04X\n", i8237_r0); + i8237_rD[devnum]++; + i8237_r0[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[devnum](L) set to %04X\n", i8237_r0[devnum]); } return 0; } @@ -512,24 +562,24 @@ uint8 i8237_r1x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read current word count CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(H) read as %04X\n", i8237_r1); - return (i8237_r1 >> 8); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[devnum](H) read as %04X\n", i8237_r1[devnum]); + return (i8237_r1[devnum] >> 8); } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) read as %04X\n", i8237_r1); - return (i8237_r1 & 0xFF); + i8237_rD[devnum]++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[devnum](L) read as %04X\n", i8237_r1[devnum]); + return (i8237_r1[devnum] & 0xFF); } } else { /* write base & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r1 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(H) set to %04X\n", i8237_r1); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + i8237_r1[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[devnum](H) set to %04X\n", i8237_r1[devnum]); } else { /* low byte */ - i8237_rD++; - i8237_r1 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) set to %04X\n", i8237_r1); + i8237_rD[devnum]++; + i8237_r1[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[devnum](L) set to %04X\n", i8237_r1[devnum]); } return 0; } @@ -543,24 +593,24 @@ uint8 i8237_r2x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(H) read as %04X\n", i8237_r2); - return (i8237_r2 >> 8); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[devnum](H) read as %04X\n", i8237_r2[devnum]); + return (i8237_r2[devnum] >> 8); } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) read as %04X\n", i8237_r2); - return (i8237_r2 & 0xFF); + i8237_rD[devnum]++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[devnum](L) read as %04X\n", i8237_r2[devnum]); + return (i8237_r2[devnum] & 0xFF); } } else { /* write base & current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r2 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(H) set to %04X\n", i8237_r2); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + i8237_r2[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[devnum](H) set to %04X\n", i8237_r2[devnum]); } else { /* low byte */ - i8237_rD++; - i8237_r2 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) set to %04X\n", i8237_r2); + i8237_rD[devnum]++; + i8237_r2[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[devnum](L) set to %04X\n", i8237_r2[devnum]); } return 0; } @@ -574,24 +624,24 @@ uint8 i8237_r3x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read current word count CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(H) read as %04X\n", i8237_r3); - return (i8237_r3 >> 8); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3[devnum](H) read as %04X\n", i8237_r3[devnum]); + return (i8237_r3[devnum] >> 8); } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) read as %04X\n", i8237_r3); - return (i8237_r3 & 0xFF); + i8237_rD[devnum]++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3[devnum](L) read as %04X\n", i8237_r3[devnum]); + return (i8237_r3[devnum] & 0xFF); } } else { /* write base & current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r3 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(H) set to %04X\n", i8237_r3); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + i8237_r3[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3[devnum](H) set to %04X\n", i8237_r3[devnum]); } else { /* low byte */ - i8237_rD++; - i8237_r3 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) set to %04X\n", i8237_r3); + i8237_rD[devnum]++; + i8237_r3[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3[devnum](L) set to %04X\n", i8237_r3[devnum]); } return 0; } @@ -605,24 +655,24 @@ uint8 i8237_r4x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read current address CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(H) read as %04X\n", i8237_r4); - return (i8237_r4 >> 8); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4[devnum](H) read as %04X\n", i8237_r4[devnum]); + return (i8237_r4[devnum] >> 8); } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) read as %04X\n", i8237_r4); - return (i8237_r4 & 0xFF); + i8237_rD[devnum]++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4[devnum](L) read as %04X\n", i8237_r4[devnum]); + return (i8237_r4[devnum] & 0xFF); } } else { /* write base & current address CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r4 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(H) set to %04X\n", i8237_r4); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + i8237_r4[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4[devnum](H) set to %04X\n", i8237_r4[devnum]); } else { /* low byte */ - i8237_rD++; - i8237_r4 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) set to %04X\n", i8237_r4); + i8237_rD[devnum]++; + i8237_r4[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4[devnum](L) set to %04X\n", i8237_r4[devnum]); } return 0; } @@ -636,24 +686,24 @@ uint8 i8237_r5x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read current word count CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(H) read as %04X\n", i8237_r5); - return (i8237_r5 >> 8); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5[devnum](H) read as %04X\n", i8237_r5[devnum]); + return (i8237_r5[devnum] >> 8); } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) read as %04X\n", i8237_r5); - return (i8237_r5 & 0xFF); + i8237_rD[devnum]++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5[devnum](L) read as %04X\n", i8237_r5[devnum]); + return (i8237_r5[devnum] & 0xFF); } } else { /* write base & current address CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r5 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(H) set to %04X\n", i8237_r5); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + i8237_r5[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5[devnum](H) set to %04X\n", i8237_r5[devnum]); } else { /* low byte */ - i8237_rD++; - i8237_r5 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) set to %04X\n", i8237_r5); + i8237_rD[devnum]++; + i8237_r5[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5[devnum](L) set to %04X\n", i8237_r5[devnum]); } return 0; } @@ -667,24 +717,24 @@ uint8 i8237_r6x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read current address CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(H) read as %04X\n", i8237_r6); - return (i8237_r6 >> 8); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6[devnum](H) read as %04X\n", i8237_r6[devnum]); + return (i8237_r6[devnum] >> 8); } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) read as %04X\n", i8237_r6); - return (i8237_r6 & 0xFF); + i8237_rD[devnum]++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6[devnum](L) read as %04X\n", i8237_r6[devnum]); + return (i8237_r6[devnum] & 0xFF); } } else { /* write base & current address CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r6 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(H) set to %04X\n", i8237_r6); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + i8237_r6[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6[devnum](H) set to %04X\n", i8237_r6[devnum]); } else { /* low byte */ - i8237_rD++; - i8237_r6 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) set to %04X\n", i8237_r6); + i8237_rD[devnum]++; + i8237_r6[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6[devnum](L) set to %04X\n", i8237_r6[devnum]); } return 0; } @@ -698,24 +748,24 @@ uint8 i8237_r7x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read current word count CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(H) read as %04X\n", i8237_r7); - return (i8237_r7 >> 8); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7[devnum](H) read as %04X\n", i8237_r7[devnum]); + return (i8237_r7[devnum] >> 8); } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) read as %04X\n", i8237_r7); - return (i8237_r7 & 0xFF); + i8237_rD[devnum]++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7[devnum](L) read as %04X\n", i8237_r7[devnum]); + return (i8237_r7[devnum] & 0xFF); } } else { /* write base & current address CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r7 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(H) set to %04X\n", i8237_r7); + if (i8237_rD[devnum]) { /* high byte */ + i8237_rD[devnum] = 0; + i8237_r7[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7[devnum](H) set to %04X\n", i8237_r7[devnum]); } else { /* low byte */ - i8237_rD++; - i8237_r7 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) set to %04X\n", i8237_r7); + i8237_rD[devnum]++; + i8237_r7[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7[devnum](L) set to %04X\n", i8237_r7[devnum]); } return 0; } @@ -729,11 +779,11 @@ uint8 i8237_r8x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read status register */ - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r8 (status) read as %02X\n", i8237_r8); - return (i8237_r8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r8[devnum] (status) read as %02X\n", i8237_r8[devnum]); + return (i8237_r8[devnum]); } else { /* write command register */ - i8237_r9 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r9 (command) set to %02X\n", i8237_r9); + i8237_r9[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r9[devnum] (command) set to %02X\n", i8237_r9[devnum]); return 0; } } @@ -746,11 +796,11 @@ uint8 i8237_r9x(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_r9\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_r9[devnum]\n"); return 0; } else { /* write request register */ - i8237_rC = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rC (request) set to %02X\n", i8237_rC); + i8237_rC[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rC[devnum] (request) set to %02X\n", i8237_rC[devnum]); return 0; } } @@ -763,36 +813,36 @@ uint8 i8237_rAx(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rA\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rA[devnum]\n"); return 0; } else { /* write single mask register */ switch(data & 0x03) { case 0: if (data & 0x04) - i8237_rB |= 1; + i8237_rB[devnum] |= 1; else - i8237_rB &= ~1; + i8237_rB[devnum] &= ~1; break; case 1: if (data & 0x04) - i8237_rB |= 2; + i8237_rB[devnum] |= 2; else - i8237_rB &= ~2; + i8237_rB[devnum] &= ~2; break; case 2: if (data & 0x04) - i8237_rB |= 4; + i8237_rB[devnum] |= 4; else - i8237_rB &= ~4; + i8237_rB[devnum] &= ~4; break; case 3: if (data & 0x04) - i8237_rB |= 8; + i8237_rB[devnum] |= 8; else - i8237_rB &= ~8; + i8237_rB[devnum] &= ~8; break; } - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB[devnum] (mask) set to %02X\n", i8237_rB[devnum]); return 0; } } @@ -805,11 +855,11 @@ uint8 i8237_rBx(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rB\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rB[devnum]\n"); return 0; } else { /* write mode register */ - i8237_rA = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rA (mode) set to %02X\n", i8237_rA); + i8237_rA[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rA[devnum] (mode) set to %02X\n", i8237_rA[devnum]); return 0; } } @@ -822,11 +872,11 @@ uint8 i8237_rCx(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rC\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rC[devnum]\n"); return 0; } else { /* clear byte pointer FF */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rD (FF) cleared\n"); + i8237_rD[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rD[devnum] (FF) cleared\n"); return 0; } } @@ -839,7 +889,7 @@ uint8 i8237_rDx(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { /* read temporary register */ - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rD\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rD[devnum]\n"); return 0; } else { /* master clear */ i8237_reset1(); @@ -856,11 +906,11 @@ uint8 i8237_rEx(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rE\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rE[devnum]\n"); return 0; } else { /* clear mask register */ - i8237_rB = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) cleared\n"); + i8237_rB[devnum] = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB[devnum] (mask) cleared\n"); return 0; } } @@ -873,11 +923,11 @@ uint8 i8237_rFx(t_bool io, uint8 data) if ((devnum = i8237_get_dn()) != 0xFF) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rF\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rF[devnum]\n"); return 0; } else { /* write all mask register bits */ - i8237_rB = data & 0x0F; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); + i8237_rB[devnum] = data & 0x0F; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB[devnum] (mask) set to %02X\n", i8237_rB[devnum]); return 0; } } diff --git a/Intel-Systems/common/i8251.c b/Intel-Systems/common/i8251.c index 828a3194..756cd49b 100644 --- a/Intel-Systems/common/i8251.c +++ b/Intel-Systems/common/i8251.c @@ -111,50 +111,60 @@ #include "system_defs.h" -#define DEBUG 0 - -/* external globals */ - -extern uint16 port; //port called in dev_table[port] - #define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ #define UNIT_ANSI (1 << UNIT_V_ANSI) +// 8251 status bits + #define TXR 0x01 #define RXR 0x02 #define TXE 0x04 #define SD 0x40 +/* external globals */ + /* external function prototypes */ -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); /* globals */ -int32 i8251_devnum = 0; //actual number of 8251 instances + 1 -uint16 i8251_port[4]; //baseport port registered to each instance - /* function prototypes */ +t_stat i8251_cfg(uint8 base, uint8 devnum); t_stat i8251_svc (UNIT *uptr); -t_stat i8251_reset (DEVICE *dptr, uint16 baseport); -uint8 i8251_get_dn(void); -uint8 i8251s(t_bool io, uint8 data); -uint8 i8251d(t_bool io, uint8 data); -void i8251_reset1(uint8 devnum); +t_stat i8251_reset (DEVICE *dptr); +uint8 i8251s(t_bool io, uint8 data, uint8 devnum); +uint8 i8251d(t_bool io, uint8 data, uint8 devnum); +void i8251_reset_dev(uint8 devnum); /* i8251 Standard I/O Data Structures */ -/* up to 1 i8251 devices */ +/* up to 4 i8251 devices */ -UNIT i8251_unit = { - UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT +UNIT i8251_unit[4] = { + { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT } }; REG i8251_reg[] = { - { HRDATA (DATA, i8251_unit.buf, 8) }, - { HRDATA (STAT, i8251_unit.u3, 8) }, - { HRDATA (MODE, i8251_unit.u4, 8) }, - { HRDATA (CMD, i8251_unit.u5, 8) }, + { HRDATA (DATA0, i8251_unit[0].buf, 8) }, + { HRDATA (STAT0, i8251_unit[0].u3, 8) }, + { HRDATA (MODE0, i8251_unit[0].u4, 8) }, + { HRDATA (CMD0, i8251_unit[0].u5, 8) }, + { HRDATA (DATA1, i8251_unit[1].buf, 8) }, + { HRDATA (STAT1, i8251_unit[1].u3, 8) }, + { HRDATA (MODE1, i8251_unit[1].u4, 8) }, + { HRDATA (CMD1, i8251_unit[1].u5, 8) }, + { HRDATA (DATA2, i8251_unit[2].buf, 8) }, + { HRDATA (STAT2, i8251_unit[2].u3, 8) }, + { HRDATA (MODE2, i8251_unit[2].u4, 8) }, + { HRDATA (CMD2, i8251_unit[2].u5, 8) }, + { HRDATA (DATA3, i8251_unit[3].buf, 8) }, + { HRDATA (STAT3, i8251_unit[3].u3, 8) }, + { HRDATA (MODE3, i8251_unit[3].u4, 8) }, + { HRDATA (CMD3, i8251_unit[3].u5, 8) }, { NULL } }; @@ -179,10 +189,10 @@ MTAB i8251_mod[] = { DEVICE i8251_dev = { "I8251", //name - &i8251_unit, //units + i8251_unit, //units i8251_reg, //registers i8251_mod, //modifiers - 1, //numunits + I8251_NUM, //numunits 16, //aradix 16, //awidth 1, //aincr @@ -190,8 +200,7 @@ DEVICE i8251_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// &i8251_reset, //reset - NULL, //reset + &i8251_reset, //reset NULL, //boot NULL, //attach NULL, //detach @@ -203,6 +212,17 @@ DEVICE i8251_dev = { NULL //lname }; +// i8251 configuration + +t_stat i8251_cfg(uint8 base, uint8 devnum) +{ + sim_printf(" i8251[%d]: at base port 0%02XH\n", + devnum, base & 0xFF); + reg_dev(i8251d, base, devnum); + reg_dev(i8251s, base + 1, devnum); + return SCPE_OK; +} + /* Service routines to handle simulator functions */ /* i8251_svc - actually gets char & places in buffer */ @@ -211,100 +231,69 @@ t_stat i8251_svc (UNIT *uptr) { int32 temp; - sim_activate (&i8251_unit, i8251_unit.wait); /* continue poll */ + sim_activate (uptr, uptr->wait); /* continue poll */ if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ - i8251_unit.buf = temp & 0xFF; /* Save char */ - i8251_unit.u3 |= RXR; /* Set status */ + uptr->buf = temp & 0xFF; /* Save char */ + uptr->u3 |= RXR; /* Set status */ /* Do any special character handling here */ - i8251_unit.pos++; + uptr->pos++; return SCPE_OK; } /* Reset routine */ -t_stat i8251_reset (DEVICE *dptr, uint16 baseport) +t_stat i8251_reset (DEVICE *dptr) { - if (i8251_devnum >= I8251_NUM) { - sim_printf("i8251_reset: too many devices!\n"); - return SCPE_MEM; + uint8 devnum; + + for (devnum=0; devnum= i8251_port[i] && port <= i8251_port[i] + 1) - return i; - sim_printf("i8251_get_dn: port %04X not in 8251 device table\n", port); - return 0xFF; + i8251_unit[devnum].u3 = TXR + TXE; /* status */ + i8251_unit[devnum].u4 = 0; /* mode instruction */ + i8251_unit[devnum].u5 = 0; /* command instruction */ + i8251_unit[devnum].u6 = 0; + i8251_unit[devnum].buf = 0; + i8251_unit[devnum].pos = 0; } /* I/O instruction handlers, called from the CPU module when an IN or OUT instruction is issued. */ -uint8 i8251s(t_bool io, uint8 data) +uint8 i8251s(t_bool io, uint8 data, uint8 devnum) { - uint8 devnum; - - if ((devnum = i8251_get_dn()) != 0xFF) { - // sim_printf("\nio=%d data=%04X\n", io, data); - if (io == 0) { /* read status port */ - return i8251_unit.u3; - } else { /* write status port */ - if (i8251_unit.u6) { /* if mode, set cmd */ - i8251_unit.u5 = data; - if (DEBUG) - sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); - if (data & SD) /* reset port! */ - i8251_reset1(devnum); - } else { /* set mode */ - i8251_unit.u4 = data; - if (DEBUG) - sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); - i8251_unit.u6 = 1; /* set cmd received */ - } + if (io == 0) { /* read status port */ + return i8251_unit[devnum].u3; + } else { /* write status port */ + if (i8251_unit[devnum].u4) { /* if mode, set cmd */ + i8251_unit[devnum].u5 = data; + if (data & SD) /* reset port! */ + i8251_reset_dev(devnum); + } else { /* set mode */ + i8251_unit[devnum].u4 = data; + i8251_unit[devnum].u6 = 1; /* set cmd received */ } } return 0; } -uint8 i8251d(t_bool io, uint8 data) +uint8 i8251d(t_bool io, uint8 data, uint8 devnum) { - uint8 devnum; - - if ((devnum = i8251_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - i8251_unit.u3 &= ~RXR; - return (i8251_unit.buf); - } else { /* write data port */ - sim_putchar(data); - } + if (io == 0) { /* read data port */ + i8251_unit[devnum].u3 &= ~RXR; + return (i8251_unit[devnum].buf); + } else { /* write data port */ + sim_putchar(data); } return 0; } diff --git a/Intel-Systems/common/i8253.c b/Intel-Systems/common/i8253.c index 37dcb12d..5c0ec31e 100644 --- a/Intel-Systems/common/i8253.c +++ b/Intel-Systems/common/i8253.c @@ -35,30 +35,23 @@ #include "system_defs.h" -#define DEBUG 0 - /* external globals */ -extern uint16 port; //port called in dev_table[port] - /* external function prototypes */ -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); /* globals */ -int32 i8253_devnum = 0; //actual number of 8253 instances + 1 -uint16 i8253_port[4]; //baseport port registered to each instance - /* function prototypes */ +t_stat i8253_cfg(uint8 base, uint8 devnum); t_stat i8253_svc (UNIT *uptr); -t_stat i8253_reset (DEVICE *dptr, uint16 baseport); -uint8 i8253_get_dn(void); -uint8 i8253t0(t_bool io, uint8 data); -uint8 i8253t1(t_bool io, uint8 data); -uint8 i8253t2(t_bool io, uint8 data); -uint8 i8253c(t_bool io, uint8 data); +t_stat i8253_reset (DEVICE *dptr); +uint8 i8253t0(t_bool io, uint8 data, uint8 devnum); +uint8 i8253t1(t_bool io, uint8 data, uint8 devnum); +uint8 i8253t2(t_bool io, uint8 data, uint8 devnum); +uint8 i8253c(t_bool io, uint8 data, uint8 devnum); /* i8253 Standard I/O Data Structures */ /* up to 4 i8253 devices */ @@ -99,20 +92,19 @@ MTAB i8253_mod[] = { /* address width is set to 16 bits to use devices in 8086/8088 implementations */ DEVICE i8253_dev = { - "I8251", //name - i8253_unit, //units + "I8253", //name + i8253_unit, //units i8253_reg, //registers i8253_mod, //modifiers - 1, //numunits + I8253_NUM, //numunits 16, //aradix - 16, //awidth + 16, //awidth 1, //aincr 16, //dradix 8, //dwidth NULL, //examine NULL, //deposit -// &i8253_reset, //reset - NULL, //reset + i8253_reset, //reset NULL, //boot NULL, //attach NULL, //detach @@ -126,6 +118,19 @@ DEVICE i8253_dev = { /* Service routines to handle simulator functions */ +// i8253 configuration + +t_stat i8253_cfg(uint8 base, uint8 devnum) +{ + sim_printf(" i8253[%d]: at base port 0%02XH\n", + devnum, base & 0xFF); + reg_dev(i8253t0, base, devnum); + reg_dev(i8253t1, base + 1, devnum); + reg_dev(i8253t2, base + 2, devnum); + reg_dev(i8253c, base + 3, devnum); + return SCPE_OK; +} + /* i8253_svc - actually gets char & places in buffer */ t_stat i8253_svc (UNIT *uptr) @@ -136,57 +141,31 @@ t_stat i8253_svc (UNIT *uptr) /* Reset routine */ -t_stat i8253_reset (DEVICE *dptr, uint16 baseport) +t_stat i8253_reset (DEVICE *dptr) { - if (i8253_devnum > I8253_NUM) { - sim_printf("i8253_reset: too many devices!\n"); - return SCPE_MEM; + uint8 devnum; + + for (devnum=0; devnum= i8253_port[i] && port <= i8253_port[i] + 3) - return i; - sim_printf("i8253_get_dn: port %04X not in 8253 device table\n", port); - return 0xFF; -} - /* I/O instruction handlers, called from the CPU module when an IN or OUT instruction is issued. */ -uint8 i8253t0(t_bool io, uint8 data) +uint8 i8253t0(t_bool io, uint8 data, uint8 devnum) { - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return i8253_unit[devnum].u3; - } else { /* write data port */ - if (DEBUG) - sim_printf(" 8253-%d: Timer 0=%02X\n", devnum, data); - i8253_unit[devnum].u3 = data; - //sim_activate_after (&i8253_unit[devnum], ); - return 0; - } + if (io == 0) { /* read data port */ + return i8253_unit[devnum].u3; + } else { /* write data port */ + i8253_unit[devnum].u3 = data; + //sim_activate_after (&i8253_unit[devnum], ); + return 0; } return 0; } @@ -194,53 +173,35 @@ uint8 i8253t0(t_bool io, uint8 data) //read routine: //sim_activate_time(&i8253_unit[devnum])/sim_inst_per_second() -uint8 i8253t1(t_bool io, uint8 data) +uint8 i8253t1(t_bool io, uint8 data, uint8 devnum) { - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return i8253_unit[devnum].u4; - } else { /* write data port */ - if (DEBUG) - sim_printf(" 8253-%d: Timer 1=%02X\n", devnum, data); - i8253_unit[devnum].u4 = data; - return 0; - } + if (io == 0) { /* read data port */ + return i8253_unit[devnum].u4; + } else { /* write data port */ + i8253_unit[devnum].u4 = data; + return 0; } return 0; } -uint8 i8253t2(t_bool io, uint8 data) +uint8 i8253t2(t_bool io, uint8 data, uint8 devnum) { - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return i8253_unit[devnum].u5; - } else { /* write data port */ - if (DEBUG) - sim_printf(" 8253-%d: Timer 2=%02X\n", devnum, data); - i8253_unit[devnum].u5 = data; - return 0; - } + if (io == 0) { /* read data port */ + return i8253_unit[devnum].u5; + } else { /* write data port */ + i8253_unit[devnum].u5 = data; + return 0; } return 0; } -uint8 i8253c(t_bool io, uint8 data) +uint8 i8253c(t_bool io, uint8 data, uint8 devnum) { - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read status port */ - return i8253_unit[devnum].u6; - } else { /* write data port */ - i8253_unit[devnum].u6 = data; - if (DEBUG) - sim_printf(" 8253-%d: Mode Instruction=%02X\n", devnum, data); - return 0; - } + if (io == 0) { /* read status port */ + return i8253_unit[devnum].u6; + } else { /* write data port */ + i8253_unit[devnum].u6 = data; + return 0; } return 0; } diff --git a/Intel-Systems/common/i8255.c b/Intel-Systems/common/i8255.c index fb64895c..8ccb6084 100644 --- a/Intel-Systems/common/i8255.c +++ b/Intel-Systems/common/i8255.c @@ -77,36 +77,29 @@ #include "system_defs.h" /* system header in system dir */ -#define DEBUG 0 - -/* external globals */ - -extern uint16 port; //port called in dev_table[port] - /* internal function prototypes */ -t_stat i8255_reset (DEVICE *dptr, uint16 baseport); -uint8 i8255_get_dn(void); -uint8 i8255a(t_bool io, uint8 data); -uint8 i8255b(t_bool io, uint8 data); -uint8 i8255c(t_bool io, uint8 data); -uint8 i8255s(t_bool io, uint8 data); +t_stat i8255_cfg(uint8 base, uint8 devnum); +t_stat i8255_reset (DEVICE *dptr); +uint8 i8255a(t_bool io, uint8 data, uint8 devnum); +uint8 i8255b(t_bool io, uint8 data, uint8 devnum); +uint8 i8255c(t_bool io, uint8 data, uint8 devnum); +uint8 i8255s(t_bool io, uint8 data, uint8 devnum); /* external function prototypes */ -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); /* globals */ -int32 i8255_devnum = 0; //actual number of 8255 instances + 1 -uint16 i8255_port[4]; //baseport port registered to each instance - /* these bytes represent the input and output to/from a port instance */ uint8 i8255_A[4]; //port A byte I/O uint8 i8255_B[4]; //port B byte I/O uint8 i8255_C[4]; //port C byte I/O +/* external globals */ + /* i8255 Standard I/O Data Structures */ /* up to 4 i8255 devices */ @@ -162,8 +155,7 @@ DEVICE i8255_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// i8255_reset2(), //reset - NULL, //reset + i8255_reset, //reset NULL, //boot NULL, //attach NULL, //detach @@ -175,38 +167,32 @@ DEVICE i8255_dev = { NULL //lname }; -/* Reset routine */ +// i8255 configuration -t_stat i8255_reset (DEVICE *dptr, uint16 baseport) +t_stat i8255_cfg(uint8 base, uint8 devnum) { - if (i8255_devnum > I8255_NUM) { - sim_printf("i8255_reset: too many devices!\n"); - return SCPE_MEM; - } - sim_printf(" 8255-%d: Reset\n", i8255_devnum); - sim_printf(" 8255-%d: Registered at %04X\n", i8255_devnum, baseport); - i8255_port[i8255_devnum] = baseport; - reg_dev(i8255a, baseport, i8255_devnum); - reg_dev(i8255b, baseport + 1, i8255_devnum); - reg_dev(i8255c, baseport + 2, i8255_devnum); - reg_dev(i8255s, baseport + 3, i8255_devnum); - i8255_unit[i8255_devnum].u3 = 0x9B; /* control */ - i8255_A[i8255_devnum] = 0xFF; /* Port A */ - i8255_B[i8255_devnum] = 0xFF; /* Port B */ - i8255_C[i8255_devnum] = 0xFF; /* Port C */ - i8255_devnum++; + reg_dev(i8255a, base, devnum); + reg_dev(i8255b, base + 1, devnum); + reg_dev(i8255c, base + 2, devnum); + reg_dev(i8255s, base + 3, devnum); + sim_printf(" i8255[%d]: at base port 0%02XH\n", + devnum, base & 0xFF); return SCPE_OK; } -uint8 i8255_get_dn(void) -{ - int i; +/* Reset routine */ - for (i=0; i=i8255_port[i] && port <= i8255_port[i] + 3) - return i; - sim_printf("i8255_get_dn: port %04X not in 8255 device table\n", port); - return 0xFF; +t_stat i8255_reset (DEVICE *dptr) +{ + uint8 devnum; + + for (devnum = 0; devnum < I8255_NUM; devnum++) { + i8255_unit[devnum].u3 = 0x9B; /* control */ + i8255_A[devnum] = 0xFF; /* Port A */ + i8255_B[devnum] = 0xFF; /* Port B */ + i8255_C[devnum] = 0xFF; /* Port C */ + } + return SCPE_OK; } /* I/O instruction handlers, called from the CPU module when an @@ -215,79 +201,69 @@ uint8 i8255_get_dn(void) /* i8255 functions */ -uint8 i8255s(t_bool io, uint8 data) +uint8 i8255s(t_bool io, uint8 data, uint8 devnum) { uint8 bit; - uint8 devnum; - - if ((devnum = i8255_get_dn()) != 0xFF) { - if (io == 0) { /* read status port */ - return 0xFF; //undefined - } else { /* write status port */ - if (data & 0x80) { /* mode instruction */ - i8255_unit[devnum].u3 = data; - if (DEBUG) - sim_printf(" 8255-%d: Mode Instruction=%02X\n", devnum, data); - if (data & 0x64) - sim_printf(" Mode 1 and 2 not yet implemented\n"); - } else { /* bit set */ - bit = (data & 0x0E) >> 1; /* get bit number */ - if (data & 0x01) { /* set bit */ - i8255_C[devnum] |= (0x01 << bit); - } else { /* reset bit */ - i8255_C[devnum] &= ~(0x01 << bit); - } + + if (io == 0) { /* read status port */ + return 0xFF; //undefined + } else { /* write status port */ + if (data & 0x80) { /* mode instruction */ + i8255_unit[devnum].u3 = data; + if (data & 0x64) + sim_printf(" Mode 1 and 2 not yet implemented\n"); + } else { /* bit set */ + bit = (data & 0x0E) >> 1; /* get bit number */ + if (data & 0x01) { /* set bit */ + i8255_C[devnum] |= (0x01 << bit); + } else { /* reset bit */ + i8255_C[devnum] &= ~(0x01 << bit); } } } return 0; } -uint8 i8255a(t_bool io, uint8 data) +uint8 i8255a(t_bool io, uint8 data, uint8 devnum) { - uint8 devnum; - - if ((devnum = i8255_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - //return (i8255_unit[devnum].u4); - return (i8255_A[devnum]); - } else { /* write data port */ - i8255_A[devnum] = data; - if (DEBUG) - sim_printf(" 8255-%d: Port A = %02X\n", devnum, data); - } + if (io == 0) { /* read data port */ + return (i8255_A[devnum]); + } else { /* write data port */ + i8255_A[devnum] = data; } return 0; } -uint8 i8255b(t_bool io, uint8 data) +uint8 i8255b(t_bool io, uint8 data, uint8 devnum) { - uint8 devnum; - - if ((devnum = i8255_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return (i8255_B[devnum]); - } else { /* write data port */ - i8255_B[devnum] = data; - if (DEBUG) - sim_printf(" 8255-%d: Port B = %02X\n", devnum, data); - } + if (io == 0) { /* read data port */ + return (i8255_B[devnum]); + } else { /* write data port */ + i8255_B[devnum] = data; } return 0; } -uint8 i8255c(t_bool io, uint8 data) +uint8 i8255c(t_bool io, uint8 data, uint8 devnum) { - uint8 devnum; - - if ((devnum = i8255_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return (i8255_C[devnum]); - } else { /* write data port */ - i8255_C[devnum] = data; - if (DEBUG) - sim_printf(" 8255-%d: Port C = %02X\n", devnum, data); + if (io == 0) { /* read data port */ + return (i8255_C[devnum]); + } else { /* write data port */ + if (devnum == 0) { + if((i8255_C[devnum] & 0x80) != (data & 0x80)) { //change in ROM enable + if (data & 0x80) + sim_printf("Onboard EPROM: Enabled\n"); + else + sim_printf("Onboard EPROM: Disabled\n"); + } + if((i8255_C[devnum] & 0x20) != (data & 0x20)) { //change in RAM enable + if (data & 0x20) + sim_printf("Onboard RAM: Enabled\n"); + else + sim_printf("Onboard RAM: Disabled\n"); + } } + i8255_C[devnum] = data; } return 0; } diff --git a/Intel-Systems/common/i8259.c b/Intel-Systems/common/i8259.c index 2a1e4729..f12bf72e 100644 --- a/Intel-Systems/common/i8259.c +++ b/Intel-Systems/common/i8259.c @@ -35,29 +35,22 @@ #include "system_defs.h" /* system header in system dir */ -#define DEBUG 0 - /* function prototypes */ -uint8 i8259a(t_bool io, uint8 data); -uint8 i8259b(t_bool io, uint8 data); +t_stat i8259_cfg(uint8 base, uint8 devnum); +uint8 i8259a(t_bool io, uint8 data, uint8 devnum); +uint8 i8259b(t_bool io, uint8 data, uint8 devnum); void i8259_dump(uint8 devnum); -t_stat i8259_reset (DEVICE *dptr, uint16 baseport); -uint8 i8259_get_dn(void); +t_stat i8259_reset (DEVICE *dptr); /* external globals */ -extern uint16 port; //port called in dev_table[port] - /* external function prototypes */ -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); /* globals */ -int32 i8259_devnum = 0; //actual number of 8259 instances + 1 -uint16 i8259_port[4]; //baseport port registered to each instance - /* these bytes represent the input and output to/from a port instance */ uint8 i8259_IR[4]; //interrupt inputs (bits 0-7) @@ -113,11 +106,11 @@ DEBTAB i8259_debug[] = { /* address width is set to 16 bits to use devices in 8086/8088 implementations */ DEVICE i8259_dev = { - "I8259", //name + "I8259", //name i8259_unit, //units i8259_reg, //registers NULL, //modifiers - 1, //numunits + I8259_NUM, //numunits 16, //aradix 16, //awidth 1, //aincr @@ -125,8 +118,7 @@ DEVICE i8259_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// &i8259_reset, //reset - NULL, //reset + i8259_reset, //reset NULL, //boot NULL, //attach NULL, //detach @@ -142,116 +134,98 @@ DEVICE i8259_dev = { IN or OUT instruction is issued. */ -/* Reset routine */ +// i8259 configuration -t_stat i8259_reset (DEVICE *dptr, uint16 baseport) +t_stat i8259_cfg(uint8 base, uint8 devnum) { - if (i8259_devnum >= I8259_NUM) { - sim_printf("i8255_reset: too many devices!\n"); - return SCPE_MEM; - } - sim_printf(" 8259-%d: Reset\n", i8259_devnum); - sim_printf(" 8259-%d: Registered at %04X\n", i8259_devnum, baseport); - i8259_port[i8259_devnum] = baseport; - reg_dev(i8259a, baseport, i8259_devnum); - reg_dev(i8259b, baseport + 1, i8259_devnum); - i8259_unit[i8259_devnum].u3 = 0x00; /* IRR */ - i8259_unit[i8259_devnum].u4 = 0x00; /* ISR */ - i8259_unit[i8259_devnum].u5 = 0x00; /* IMR */ - i8259_devnum++; + reg_dev(i8259a, base, devnum); + reg_dev(i8259b, base + 1, devnum); + sim_printf(" i8259[%d]: at base port 0%02XH\n", + devnum, base & 0xFF); return SCPE_OK; } -uint8 i8259_get_dn(void) -{ - int i; +/* Reset routine */ - for (i=0; i= i8259_port[i] && port <= i8259_port[i] + 1) - return i; - sim_printf("i8259_get_dn: port %04X not in 8259 device table\n", port); - return 0xFF; +t_stat i8259_reset (DEVICE *dptr) +{ + uint8 devnum; + + for (devnum=0; devnumu6], i8272_unit[uptr->u6].wait); /* continue poll */ - if (uptr->u6 >= i8272_devnum) return SCPE_OK; - if ((temp = sim_poll_kbd()) < SCPE_KFLAG) - return temp; /* no char or error? */ - //sim_printf("i8272_svc: received character temp=%04X devnum=%d\n", temp, uptr->u6); - i8272_unit[uptr->u6].buf = temp & 0xFF; /* Save char */ - i8272_unit[uptr->u6].u3 |= RXR; /* Set status */ + devnum = uptr->u5; //get FDC instance + if ((i8272_msr[devnum] & CB) && cmd[devnum] && (uptr->u6 == drv[devnum])) { /* execution phase */ + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: Entered execution phase\n"); + switch (cmd[devnum]) { + case READ: /* 0x06 */ +// sim_printf("READ-e: fddst72=%02X", fddst72[devnum][uptr->u6]); + h[devnum] = i8272_w3[devnum]; // h = 0 or 1 + hed[devnum] = i8272_w3[devnum] << 2; // hed = 0 or 4 [h << 2] + sec[devnum] = i8272_w4[devnum]; // sector number (1-XX) + secn[devnum] = i8272_w5[devnum]; // N (0-5) + spt[devnum] = i8272_w6[devnum]; // sectors/track + ssize[devnum] = 128 << secn[devnum]; // size of sector (bytes) + bpt = ssize[devnum] * spt[devnum]; // bytes/track + bpc = bpt * 2; // bytes/cylinder +// sim_printf(" d=%d h=%d c=%d s=%d\n", drv[devnum], h[devnum], cyl[devnum], sec[devnum]); + sim_debug (DEBUG_flow, &i8272_dev, + "8272_svc: FDC read: h=%d, hed=%d, sec=%d, secn=%d, spt=%d, ssize=%04X, bpt=%04X, bpc=%04X\n", + h[devnum], hed[devnum], sec[devnum], secn[devnum], spt[devnum], ssize[devnum], bpt, bpc); + sim_debug (DEBUG_flow, &i8272_dev, + "8272_svc: FDC read: d=%d h=%d c=%d s=%d N=%d spt=%d fddst72=%02X\n", + drv[devnum], h[devnum], cyl[devnum], sec[devnum], secn[devnum], spt[devnum], fddst72[devnum][uptr->u6]); + sim_debug (DEBUG_read, &i8272_dev, "8272_svc: FDC read of d=%d h=%d c=%d s=%d\n", + drv[devnum], h[devnum], cyl[devnum], sec[devnum]); + if ((fddst72[devnum][uptr->u6] & RDY) == 0) { // drive not ready + i8272_r0[devnum] = IC_ABNORM + NR + hed[devnum] + drv[devnum]; /* command done - Not ready error*/ + i8272_r3[devnum] = fddst72[devnum][uptr->u6]; + i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: FDC read: Not Ready\n"); + } else { // get image addr for this d, h, c, s + imgadr = (cyl[devnum] * bpc) + (h[devnum] * bpt) + ((sec[devnum] - 1) * ssize[devnum]); +// sim_debug (DEBUG_read, &i8272_dev, +// "8272_svc: FDC read: DMA addr=%04X cnt=%04X imgadr=%04X\n", +// i8237_r0, i8237_r1, imgadr); + for (i=0; i<=ssize[devnum]; i++) { /* copy selected sector to memory */ + data = *(i8272_buf[devnum][uptr->u6] + (imgadr + i)); +// multibus_put_mbyte(i8237_r0 + i, data); + } +//*** need to step return results IAW table 3-11 in 143078-001 + i8272_w4[devnum] = ++sec[devnum]; /* next sector */ + i8272_r0[devnum] = hed[devnum] + drv[devnum]; /* command done - no error */ + i8272_r3[devnum] = fddst72[devnum][uptr->u6]; + } + i8272_r1[devnum] = 0; + i8272_r2[devnum] = 0; + i8272_w2[devnum] = cyl[devnum]; /* generate a current address mark */ + i8272_w3[devnum] = h[devnum]; + if (i8272_w4[devnum] > i8272_w6[devnum]) { // beyond last sector of track? + i8272_w4[devnum] = 1; // yes, set to sector 1; + if (h[devnum]) { // on head one? + i8272_w2[devnum]++; // yes, step cylinder + h[devnum] = 0; // back to head 0 + } + } + i8272_w5[devnum] = secn[devnum]; + i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ +// set_irq(I8272_INT); /* set interrupt */ +// sim_printf("READ-x: fddst72=%02X\n", fddst72[devnum][uptr->u6]); + break; + case WRITE: /* 0x05 */ +// sim_printf("WRITE-e: fddst72=%02X\n", fddst72[devnum][uptr->u6]); + h[devnum] = i8272_w3[devnum]; // h = 0 or 1 + hed[devnum] = i8272_w3[devnum] << 2; // hed = 0 or 4 [h << 2] + sec[devnum] = i8272_w4[devnum]; // sector number (1-XX) + secn[devnum] = i8272_w5[devnum]; // N (0-5) + spt[devnum] = i8272_w6[devnum]; // sectors/track + ssize[devnum] = 128 << secn[devnum]; // size of sector (bytes) + bpt = ssize[devnum] * spt[devnum]; // bytes/track + bpc = bpt * 2; // bytes/cylinder + sim_debug (DEBUG_flow, &i8272_dev, + "8272_svc: FDC write: hed=%d, sec=%d, secn=%d, spt=%d, ssize=%04X, bpt=%04X, bpc=%04X\n", + hed[devnum], sec[devnum], secn[devnum], spt[devnum], ssize[devnum], bpt, bpc); + sim_debug (DEBUG_flow, &i8272_dev, + "8272_svc: FDC write: d=%d h=%d c=%d s=%d N=%d spt=%d fddst72=%02X\n", + drv[devnum], h[devnum], cyl[devnum], sec[devnum], secn[devnum], spt[devnum], fddst72[devnum][uptr->u6]); + sim_debug (DEBUG_write, &i8272_dev, "8272_svc: FDC write of d=%d h=%d c=%d s=%d\n", + drv[devnum], h[devnum], cyl[devnum], sec[devnum]); + i8272_r1[devnum] = 0; // clear ST1 + i8272_r2[devnum] = 0; // clear ST2 + if ((fddst72[devnum][uptr->u6] & RDY) == 0) { + i8272_r0[devnum] = IC_ABNORM + NR + hed[devnum] + drv[devnum]; /* Not ready error*/ + i8272_r3[devnum] = fddst72[devnum][uptr->u6]; + i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: FDC write: Not Ready\n"); +// } else if (fddst72[devnum][uptr->u6] & WP) { +// i8272_r0[devnum] = IC_ABNORM + hed[devnum] + drv[devnum]; /* write protect error */ +// i8272_r1[devnum] = NW; // set not writable in ST1 +// i8272_r3[devnum] = fddst72[devnum][uptr->u6] + WP; +// i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ +// sim_printf("\nWrite Protected fddst72[%d]=%02X\n", uptr->u6, fddst72[devnum][uptr->u6]); +// if (i8272_dev.dctrl & DEBUG_flow) +// sim_printf("8272_svc: FDC write: Write Protected\n"); + } else { // get image addr for this d, h, c, s + imgadr = (cyl[devnum] * bpc) + (h[devnum] * bpt) + ((sec[devnum] - 1) * ssize[devnum]); +// sim_debug (DEBUG_write, &i8272_dev, +// "8272_svc: FDC write: DMA adr=%04X cnt=%04X imgadr=%04X\n", +// i8237_r0, i8237_r1, imgadr); + for (i=0; i<=ssize[devnum]; i++) { /* copy selected memory to image */ +// data = multibus_get_mbyte(i8237_r0 + i); + *(i8272_buf[devnum][uptr->u6] + (imgadr + i)) = data; + } + //*** quick fix. Needs more thought! +// fp = fopen(uptr->filename, "wb"); // write out modified image +// for (i=0; icapac; i++) { +// c = *(i8272_buf[devnum][uptr->u6] + i) & 0xFF; +// fputc(c, fp); +// } +// fclose(fp); +//*** need to step return results IAW table 3-11 in 143078-001 + i8272_w2[devnum] = cyl[devnum]; /* generate a current address mark */ + i8272_w3[devnum] = hed[devnum] >> 2; + i8272_w4[devnum] = ++sec[devnum]; /* next sector */ + i8272_w5[devnum] = secn[devnum]; + i8272_r0[devnum] = hed[devnum] + drv[devnum]; /* command done - no error */ + i8272_r3[devnum] = fddst72[devnum][uptr->u6]; + i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ + } + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ +// set_irq(I8272_INT); /* set interrupt */ +// sim_printf("WRITE-x: fddst72=%02X\n", fddst72[devnum][uptr->u6]); + break; + case FMTTRK: /* 0x0D */ + if ((fddst72[devnum][uptr->u6] & RDY) == 0) { + i8272_r0[devnum] = IC_ABNORM + NR + hed[devnum] + drv[devnum]; /* Not ready error*/ + i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: Not Ready\n"); + } else if (fddst72[devnum][uptr->u6] & WP) { + i8272_r0[devnum] = IC_ABNORM + hed[devnum] + drv[devnum]; /* write protect error*/ + i8272_r3[devnum] = fddst72[devnum][uptr->u6] + WP; + i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: Write Protected\n"); + } else { + ; /* do nothing for now */ + i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ + } + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ +// set_irq(I8272_INT); /* set interrupt */ + break; + case SENINT: /* 0x08 */ + i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ + i8272_r0[devnum] = hed[devnum] + drv[devnum]; /* command done - no error */ + i8272_r1[devnum] = 0; + i8272_r2[devnum] = 0; + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ +// clr_irq(I8272_INT); /* clear interrupt */ + break; + case SENDRV: /* 0x04 */ + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: FDC sense drive: d=%d fddst72=%02X\n", + drv[devnum], fddst72[devnum][uptr->u6]); + i8272_msr[devnum] |= (RQM + DIO + CB); /* enter result phase */ + i8272_r0[devnum] = hed[devnum] + drv[devnum]; /* command done - no error */ + i8272_r1[devnum] = 0; + i8272_r2[devnum] = 0; + i8272_r3[devnum] = fddst72[devnum][drv[devnum]]; /* drv status */ + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ + break; + case HOME: /* 0x07 */ +// sim_printf("HOME-e: fddst72=%02X\n", fddst72[devnum][uptr->u6]); + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: FDC home: d=%d fddst72=%02X\n", + drv[devnum], fddst72[devnum][uptr->u6]); + if ((fddst72[devnum][uptr->u6] & RDY) == 0) { + i8272_r0[devnum] = IC_ABNORM + NR + hed[devnum] + drv[devnum]; /* Not ready error*/ + i8272_r3[devnum] = fddst72[devnum][uptr->u6]; + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: Not Ready\n"); + } else { + cyl[devnum] = 0; /* now on cylinder 0 */ + fddst72[devnum][drv[devnum]] |= T0; /* set status flag */ + i8272_r0[devnum] = SE + hed[devnum] + drv[devnum]; /* seek end - no error */ + } + i8272_r1[devnum] = 0; + i8272_r2[devnum] = 0; + i8272_msr[devnum] &= ~(RQM + DIO + CB + hed[devnum] + drv[devnum]); /* execution phase done*/ + i8272_msr[devnum] |= RQM; /* enter COMMAND phase */ + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ +// set_irq(I8272_INT); /* set interrupt */ +// sim_printf("HOME-x: fddst72=%02X\n", fddst72[devnum][uptr->u6]); + break; + case SPEC: /* 0x03 */ + fddst72[devnum][0] |= TS; //*** bad, bad, bad! + fddst72[devnum][1] |= TS; + fddst72[devnum][2] |= TS; + fddst72[devnum][3] |= TS; +// sim_printf("SPEC-e: fddst72[%d]=%02X\n", uptr->u6, fddst72[devnum][uptr->u6]); + sim_debug (DEBUG_flow, &i8272_dev, + "8272_svc: FDC specify: SRT=%d ms HUT=%d ms HLT=%d ms ND=%d\n", + 16 - (drv[devnum] >> 4), 16 * (drv[devnum] & 0x0f), i8272_w2[devnum] & 0xfe, nd[devnum]); + i8272_r0[devnum] = hed[devnum] + drv[devnum]; /* command done - no error */ + i8272_r1[devnum] = 0; + i8272_r2[devnum] = 0; +// i8272_msr[devnum] &= ~(RQM + DIO + CB); /* execution phase done*/ + i8272_msr[devnum] = 0; // force 0 for now, where does 0x07 come from? + i8272_msr[devnum] |= RQM + (nd[devnum] ? ND : 0); /* enter command phase */ + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ +// sim_printf("SPEC-x: fddst72[%d]=%02X\n", uptr->u6, fddst72[devnum][uptr->u6]); + break; + case READID: /* 0x0A */ + if ((fddst72[devnum][uptr->u6] & RDY) == 0) { + i8272_r0[devnum] = IC_RC + NR + hed[devnum] + drv[devnum]; /* Not ready error*/ + i8272_r3[devnum] = fddst72[devnum][uptr->u6]; + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: Not Ready\n"); + } else { + i8272_w2[devnum] = cyl[devnum]; /* generate a valid address mark */ + i8272_w3[devnum] = hed[devnum] >> 2; + i8272_w4[devnum] = 1; /* always sector 1 */ + i8272_w5[devnum] = secn[devnum]; + i8272_r0[devnum] = hed[devnum] + drv[devnum]; /* command done - no error */ + i8272_msr[devnum] &= ~(RQM + DIO + CB); /* execution phase done*/ + i8272_msr[devnum] |= RQM; /* enter command phase */ + } + i8272_r1[devnum] = 0; + i8272_r2[devnum] = 0; + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ + break; + case SEEK: /* 0x0F */ +// sim_printf("SEEK-e: fddst72=%02X\n", fddst72[devnum][uptr->u6]); + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: FDC seek: d=%d c=%d fddst72=%02X\n", + drv[devnum], i8272_w2, fddst72[devnum][uptr->u6]); + if ((fddst72[devnum][uptr->u6] & RDY) == 0) { /* Not ready? */ + i8272_r0[devnum] = IC_ABNORM + NR + hed[devnum] + drv[devnum]; /* error*/ + i8272_r3[devnum] = fddst72[devnum][uptr->u6]; + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: FDC seek: Not Ready\n"); + } else if (i8272_w2[devnum] >= maxcyl72[devnum][uptr->u6]) { + i8272_r0[devnum] = IC_ABNORM + RDY + hed[devnum] + drv[devnum]; /* seek error*/ + sim_debug (DEBUG_flow, &i8272_dev, "8272_svc: FDC seek: Invalid Cylinder %d\n", i8272_w2); + } else { + i8272_r0[devnum] |= SE + hed[devnum] + drv[devnum]; /* command done - no error */ + cyl[devnum] = i8272_w2[devnum]; /* new cylinder number */ + if (cyl[devnum] == 0) { /* if cyl 0, set flag */ + fddst72[devnum][drv[devnum]] |= T0; /* set T0 status flag */ + i8272_r3[devnum] |= T0; + } else { + fddst72[devnum][drv[devnum]] &= ~T0; /* clear T0 status flag */ + i8272_r3[devnum] &= ~T0; + } + } + i8272_r1[devnum] = 0; + i8272_r2[devnum] = 0; + i8272_msr[devnum] &= ~(RQM + DIO + CB + hed[devnum] + drv[devnum]); /* execution phase done*/ + i8272_msr[devnum] |= RQM; /* enter command phase */ + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ +// set_irq(I8272_INT); /* set interrupt */ +// sim_printf("SEEK-x: fddst72=%02X\n", fddst72[devnum][uptr->u6]); + break; + default: + i8272_msr[devnum] &= ~(RQM + DIO + CB); /* execution phase done*/ + i8272_msr[devnum] |= RQM; /* enter command phase */ + i8272_r0[devnum] = IC_INVC + hed[devnum] + drv[devnum]; /* set bad command error */ + i8272_r1[devnum] = 0; + i8272_r2[devnum] = 0; + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ + break; + } + pcmd[devnum] = cmd[devnum]; /* save for result phase */ + cmd[devnum] = 0; /* reset command */ + sim_debug (DEBUG_flow, &i8272_dev, + "8272_svc: Exit: msr=%02X ST0=%02X ST1=%02X ST2=%02X ST3=%02X\n", + i8272_msr[devnum], i8272_r0[devnum], i8272_r1[devnum], i8272_r2[devnum], i8272_r3); + } + sim_activate (&i8272_unit[uptr->u6], i8272_unit[uptr->u6].wait); return SCPE_OK; } -/* Reset routine */ +/* i8272 hardware reset routine */ t_stat i8272_reset(DEVICE *dptr, uint16 base) { - if (i8272_devnum >= i8272_NUM) { - sim_printf("8251_reset: too many devices!\n"); + if (i8272_devnum >= I8272_NUM) { + sim_printf("8272_reset: too many devices!\n"); return 0; } - i8272_reset1(i8272_devnum); - sim_printf(" 8251-%d: Registered at %03X\n", i8272_devnum, base); - i8272_port[i8272_devnum] = reg_dev(i8251d, base); - reg_dev(i8251s, base + 1); - i8272_unit[i8272_devnum].u6 = i8272_devnum; - sim_activate(&i8272_unit[i8272_devnum], i8272_unit[i8272_devnum].wait); /* activate unit */ - i8272_devnum++; + if (I8272_NUM) { + sim_printf(" I8272-%d: Hardware Reset\n", i8272_devnum); + sim_printf(" I8272-%d: Registered at %04X\n", i8272_devnum, base); + i8272_port[i8272_devnum] = reg_dev(i8272_r00, I8272_BASE + 0); + reg_dev(i8272_r01, I8272_BASE + 1); + if ((i8272_dev.flags & DEV_DIS) == 0) + i8272_reset1(i8272_devnum); + i8272_devnum++; + } else { + sim_printf(" No isbc208 installed\n"); + } return SCPE_OK; } +/* i8272 software reset routine */ + void i8272_reset1(uint8 devnum) { - i8272_unit[devnum].u3 = TXR + TXE; /* status */ - i8272_unit[devnum].u4 = 0; /* mode instruction */ - i8272_unit[devnum].u5 = 0; /* command instruction */ - i8272_unit[devnum].buf = 0; - i8272_unit[devnum].pos = 0; - sim_printf(" 8251-%d: Reset\n", devnum); + int32 i; + UNIT *uptr; + static int flag = 1; + + if (flag) sim_printf("I8272: Initializing\n"); + for (i = 0; i < FDD_NUM; i++) { /* handle all units */ + uptr = i8272_dev.units + i; + if (uptr->capac == 0) { /* if not configured */ +// sim_printf(" i8272%d: Not configured\n", i); +// if (flag) { +// sim_printf(" ALL: \"set isbc208 en\"\n"); +// sim_printf(" EPROM: \"att isbc2080 \"\n"); +// flag = 0; +// } + uptr->capac = 0; /* initialize unit */ + uptr->u3 = 0; + uptr->u4 = 0; + uptr->u5 = devnum; // i8272 device instance - only set here! + uptr->u6 = i; /* FDD number - only set here! */ + fddst72[devnum][i] = WP + T0 + i; /* initial drive status */ + uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */ + sim_activate (&i8272_unit[uptr->u6], i8272_unit[uptr->u6].wait); + } else { + fddst72[devnum][i] = RDY + WP + T0 + i; /* initial attach drive status */ +// sim_printf(" i8272%d: Configured, Attached to %s\n", i, uptr->filename); + } + } + i8272_msr[devnum] = RQM; /* 8272 ready for start of command */ + rsp72[devnum] = wsp72[devnum] = 0; /* reset indexes */ + cmd[devnum] = 0; /* clear command */ + sim_printf(" i8272-%d: Software Reset\n", i8272_devnum); + if (flag) { + sim_printf(" 8272 Reset\n"); + } + flag = 0; } uint8 i8272_get_dn(void) { int i; - for (i=0; i=i8272_port[i] && port <= i8272_port[i] + 1) + for (i=0; i= i8272_port[i] && port <= i8272_port[i] + 1) return i; - sim_printf("i8272_get_dn: port %03X not in 8251 device table\n", port); + sim_printf("i8272_get_dn: port %03X not in 8272 device table\n", port); return 0xFF; } +/* i8272 attach - attach an .IMG file to an FDD on a FDC */ + +t_stat i8272_attach (UNIT *uptr, CONST char *cptr) +{ + t_stat r; + uint8 fdcnum, fddnum, devnum; + int i; + long flen; + + sim_debug (DEBUG_flow, &i8272_dev, " i8272_attach: Entered with cptr=%s\n", cptr); + if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { + sim_printf(" i8272_attach: Attach error\n"); + return r; + } + devnum = fdcnum = uptr->u5; + fddnum = uptr->u6; + flen = uptr->capac; + fddst72[devnum][uptr->u6] |= RDY; /* set unit ready */ + for (i=0; iu6] = 40; + fddst72[devnum][uptr->u6] |= TS; // two sided + } + else if (flen == 737280) { /* 5" 720K DSQD / 3.5" 720K DSDD */ + maxcyl72[devnum][uptr->u6] = 80; + fddst72[devnum][uptr->u6] |= TS; // two sided + } + else if (flen == 1228800) { /* 5" 1.2M DSHD */ + maxcyl72[devnum][uptr->u6] = 80; + fddst72[devnum][uptr->u6] |= TS; // two sided + } + else if (flen == 1474560) { /* 3.5" 1.44M DSHD */ + maxcyl72[devnum][uptr->u6] = 80; + fddst72[devnum][uptr->u6] |= TS; // two sided + } + sim_printf(" Drive-%d: %d bytes of disk image %s loaded, fddst72=%02X\n", + uptr->u6, i, uptr->filename, fddst72[devnum][uptr->u6]); + } + sim_debug (DEBUG_flow, &i8272_dev, " i8272_attach: Done\n"); + return SCPE_OK; +} + +/* i8272 set mode */ +/* Handle write protect */ + +t_stat i8272_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + uint8 devnum; + + sim_debug (DEBUG_flow, &i8272_dev, " i8272_set_mode: Entered with val=%08XH uptr->flags=%08X\n", + val, uptr->flags); + devnum = uptr->u5; + if (val & UNIT_WPMODE) { /* write protect */ + fddst72[devnum][uptr->u6] |= WP; + uptr->flags |= val; + } else { /* read write */ + fddst72[devnum][uptr->u6] &= ~WP; + uptr->flags &= ~val; + } +// sim_printf("fddst72[%d]=%02XH uptr->flags=%08X\n", uptr->u6, fddst72[devnum][uptr->u6], uptr->flags); + sim_debug (DEBUG_flow, &i8272_dev, " i8272_set_mode: Done\n"); + return SCPE_OK; +} /* I/O instruction handlers, called from the CPU module when an IN or OUT instruction is issued. */ -uint8 i8251s(t_bool io, uint8 data) +uint8 i8272_r00(t_bool io, uint8 data) { uint8 devnum; if ((devnum = i8272_get_dn()) != 0xFF) { - if (io == 0) { /* read status port */ - return i8272_unit[devnum].u3; - } else { /* write status port */ - if (i8272_unit[devnum].u6) { /* if mode, set cmd */ - i8272_unit[devnum].u5 = data; - sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); - if (data & SD) /* reset port! */ - i8272_reset1(devnum); - } else { /* set mode */ - i8272_unit[devnum].u4 = data; - sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); - i8272_unit[devnum].u6 = 1; /* set cmd received */ + if (io == 0) { /* read FDC status register */ + sim_debug (DEBUG_reg, &i8272_dev, "i8272_msr read as %02X\n", i8272_msr[devnum]); + return i8272_msr[devnum]; + } else { + sim_debug (DEBUG_reg, &i8272_dev, "Illegal write to i8272_r0\n"); + return 0; + } + } + return 0; +} + +// read/write FDC data register stack + +uint8 i8272_r01(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8272_get_dn()) != 0xFF) { + if (io == 0) { /* read FDC data register */ + wsp72[devnum] = 0; /* clear write stack index */ + switch (rsp72[devnum]) { /* read from next stack register */ + case 0: + sim_debug (DEBUG_reg, &i8272_dev, "i8272_r1 read as %02X\n", i8272_r1[devnum]); + sim_debug (DEBUG_reg, &i8272_dev, "i8272_r3 read as %02X\n", i8272_r3[devnum]); + rsp72[devnum]++; /* step read stack index */ +// clr_irq(I8272_INT); /* clear interrupt */ + if (pcmd[devnum] == SENDRV) { + i8272_msr[devnum] = RQM; /* result phase SENDRV done */ + return i8272_r1[devnum]; // SENDRV return ST1 + } + return i8272_r0[devnum]; /* ST0 */ + case 1: + sim_debug (DEBUG_reg, &i8272_dev, "i8272_r2 read as %02X\n", i8272_r2[devnum]); + rsp72[devnum]++; /* step read stack index */ + if (pcmd[devnum] == SENINT) { + i8272_msr[devnum] = RQM; /* result phase SENINT done */ + return cyl[devnum]; // SENINT return current cylinder + } + return i8272_r1[devnum]; /* ST1 */ + case 2: + sim_debug (DEBUG_reg, &i8272_dev, "i8272_r3 read as %02X\n", i8272_r3[devnum]); + rsp72[devnum]++; /* step read stack index */ + return i8272_r2[devnum]; /* ST2 */ + case 3: + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w2 read as %02X\n", i8272_w2); + rsp72[devnum]++; /* step read stack index */ + return i8272_w2[devnum]; /* C - cylinder */ + case 4: + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w3 read as %02X\n", i8272_w3[devnum]); + rsp72[devnum]++; /* step read stack index */ + return i8272_w3[devnum]; /* H - head */ + case 5: + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w4 read as %02X\n", i8272_w4[devnum]); + rsp72[devnum]++; /* step read stack index */ + return i8272_w4[devnum]; /* R - sector */ + case 6: + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w5 read as %02X\n", i8272_w5[devnum]); + i8272_msr[devnum] = RQM; /* result phase ALL OTHERS done */ + return i8272_w5[devnum]; /* N - sector size*/ + } + } else { /* write FDC data register */ + rsp72[devnum] = 0; /* clear read stack index */ + switch (wsp72[devnum]) { /* write to next stack register */ + case 0: + i8272_w0[devnum] = data; /* rws = MT + MFM + SK + cmd */ + cmd[devnum] = data & 0x1F; /* save the current command */ + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w0 set to %02X\n", data); + if (cmd[devnum] == SENINT) { + i8272_msr[devnum] = CB; /* command phase SENINT done */ + return 0; + } + wsp72[devnum]++; /* step write stack index */ + break; + case 1: + i8272_w1[devnum] = data; /* rws = hed + drv */ + if (cmd[devnum] != SPEC) + drv[devnum] = data & 0x03; + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w1 set to %02X\n", data); + if (cmd[devnum] == HOME || cmd[devnum] == SENDRV || cmd[devnum] == READID) { + i8272_msr[devnum] = CB + hed[devnum] + drv[devnum]; /* command phase HOME, READID and SENDRV done */ + return 0; + } + wsp72[devnum]++; /* step write stack index */ + break; + case 2: + i8272_w2[devnum] = data; /* rws = C */ + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w2 set to %02X\n", data); + if (cmd[devnum] == SPEC || cmd[devnum] == SEEK) { + i8272_msr[devnum] = CB + hed[devnum] + drv[devnum]; /* command phase SPECIFY and SEEK done */ + return 0; + } + wsp72[devnum]++; /* step write stack index */ + break; + case 3: + i8272_w3[devnum] = data; /* rw = H */ + hed[devnum] = data; + wsp72[devnum]++; /* step write stack index */ + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w3 set to %02X\n", data); + break; + case 4: + i8272_w4[devnum] = data; /* rw = R */ + sec[devnum] = data; + wsp72[devnum]++; /* step write stack index */ + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w4 set to %02X\n", data); + break; + case 5: + i8272_w5[devnum] = data; /* rw = N */ + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w5 set to %02X\n", data); + if (cmd[devnum] == FMTTRK) { + i8272_msr[devnum] = CB + hed[devnum] + drv[devnum]; /* command phase FMTTRK done */ + return 0; + } + wsp72[devnum]++; /* step write stack index */ + break; + case 6: + i8272_w6[devnum] = data; /* rw = last sector number */ + wsp72[devnum]++; /* step write stack index */ + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w6 set to %02X\n", data); + break; + case 7: + i8272_w7[devnum] = data; /* rw = gap length */ + wsp72[devnum]++; /* step write stack index */ + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w7 set to %02X\n", data); + break; + case 8: + i8272_w8[devnum] = data; /* rw = bytes to transfer */ + sim_debug (DEBUG_reg, &i8272_dev, "i8272_w8 set to %02X\n", data); + if (cmd[devnum] == READ || cmd[devnum] == WRITE) + i8272_msr[devnum] = CB + hed[devnum] + drv[devnum]; /* command phase all others done */ + break; } } } return 0; } -uint8 i8251d(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8272_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - i8272_unit[devnum].u3 &= ~RXR; - return (i8272_unit[devnum].buf); - } else { /* write data port */ - sim_putchar(data); - } - } - return 0; -} - /* end of i8272.c */ diff --git a/Intel-Systems/common/ieprom.c b/Intel-Systems/common/ieprom.c index 0b570ebc..ff5a5ec4 100644 --- a/Intel-Systems/common/ieprom.c +++ b/Intel-Systems/common/ieprom.c @@ -26,36 +26,37 @@ MODIFICATIONS: ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. - 24 Apr 15 -- Modified to use simh_debug NOTES: These functions support a simulated ROM devices on an iSBC-80/XX SBCs. This allows the attachment of the device to a binary file containing the EPROM code image. Unit will support a single 2708, 2716, 2732, or 2764 type EPROM. - These functions also support bit 1 of 8255 number 1, port B, to enable/ + These functions also support bit 0x80 of 8255 number 0, port C, to enable/ disable the onboard ROM. */ #include "system_defs.h" -#define DEBUG 0 - /* function prototypes */ +t_stat EPROM_cfg(uint16 base, uint16 size); t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); -t_stat EPROM_reset (DEVICE *dptr, uint16 size); +t_stat EPROM_reset (DEVICE *dptr); uint8 EPROM_get_mbyte(uint16 addr); /* external function prototypes */ -//extern uint8 i8255_C[4]; //port c byte I/O -extern uint8 xack; /* XACK signal */ +/* external globals */ + +extern uint8 xack; /* XACK signal */ +extern uint8 i8255_C[4]; //port C byte I/O + +/* globals */ /* SIMH EPROM Standard I/O Data Structures */ -UNIT EPROM_unit = { +UNIT EPROM_unit[] = { UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO+UNIT_BUFABLE+UNIT_MUSTBUF, 0), 0 }; @@ -72,7 +73,7 @@ DEBTAB EPROM_debug[] = { DEVICE EPROM_dev = { "EPROM", //name - &EPROM_unit, //units + EPROM_unit, //units NULL, //registers NULL, //modifiers 1, //numunits @@ -83,8 +84,7 @@ DEVICE EPROM_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// &EPROM_reset, //reset - NULL, //reset + EPROM_reset, //reset NULL, //boot &EPROM_attach, //attach NULL, //detach @@ -96,62 +96,54 @@ DEVICE EPROM_dev = { NULL //lname }; -/* global variables */ - /* EPROM functions */ +// EPROM configuration + +t_stat EPROM_cfg(uint16 base, uint16 size) +{ + EPROM_unit->capac = size; /* set EPROM size */ + EPROM_unit->u3 = base & 0xFFFF; /* set EPROM base */ + sim_printf(" EPROM: 0%04XH bytes at base 0%04XH\n", + EPROM_unit->capac, EPROM_unit->u3); + return SCPE_OK; +} + /* EPROM reset */ -t_stat EPROM_reset (DEVICE *dptr, uint16 size) +t_stat EPROM_reset (DEVICE *dptr) { - sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=0000 size=%04X\n", size); - if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */ - EPROM_unit.capac = size; /* set EPROM size to 0 */ - sim_printf(" EPROM: Configured, Not attached\n"); - sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n"); - } else { - sim_printf(" EPROM: Configured %d bytes, Attached to %s\n", - EPROM_unit.capac, EPROM_unit.filename); - } - sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n"); return SCPE_OK; } /* EPROM attach */ -t_stat EPROM_attach (UNIT *uptr, CONST char *cptr) +t_stat EPROM_attach (UNIT *uptr, CONST char *cptr) { t_stat r; - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: cptr=%s\n", cptr); if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Error\n"); + sim_printf ("EPROM_attach: Error %d\n", r); return r; } - sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n"); - sim_printf(" EPROM: Configured %d bytes, Attached to %s\n", - EPROM_unit.capac, EPROM_unit.filename); - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n"); return SCPE_OK; } -/* get a byte from memory */ +/* get a byte from memory */ uint8 EPROM_get_mbyte(uint16 addr) { uint8 val; - sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr); - if (addr < EPROM_unit.capac) { + if ((addr >= EPROM_unit->u3) && ((uint32) addr <= (EPROM_unit->u3 + EPROM_unit->capac))) { SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)EPROM_unit.filebuf + addr); - sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val); - return (val & 0xFF); + val = *((uint8 *)EPROM_unit->filebuf + (addr - EPROM_unit->u3)); + val &= 0xFF; + return val; } else { - sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n"); - return 0; + sim_printf("EPROM: Out of range\n"); } + return 0; } /* end of iEPROM.c */ diff --git a/Intel-Systems/common/ieprom1.c b/Intel-Systems/common/ieprom1.c new file mode 100644 index 00000000..af9917e2 --- /dev/null +++ b/Intel-Systems/common/ieprom1.c @@ -0,0 +1,150 @@ +/* iEPROM1.c: Intel EPROM simulator for 8-bit SBCs + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + ?? ??? 10 - Original file. + + NOTES: + + These functions support a simulated ROM devices on an iSBC-80/XX SBCs. + This allows the attachment of the device to a binary file containing the EPROM + code image. Unit will support a single 2708, 2716, 2732, or 2764 type EPROM. + These functions also support bit 1 of 8255 number 1, port B, to enable/ + disable the onboard ROM. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat EPROM1_cfg(uint16 base, uint16 size); +t_stat EPROM1_attach (UNIT *uptr, CONST char *cptr); +t_stat EPROM1_reset (DEVICE *dptr); +uint8 EPROM1_get_mbyte(uint16 addr); + +/* external function prototypes */ + +extern void multibus_put_mbyte(uint16 addr, uint8 val); + +/* external globals */ + +extern uint8 xack; /* XACK signal */ + +/* globals */ + +/* SIMH EPROM Standard I/O Data Structures */ + +UNIT EPROM1_unit[] = { + UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO+UNIT_BUFABLE+UNIT_MUSTBUF, 0), 0 +}; + +DEBTAB EPROM1_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE EPROM1_dev = { + "EPROM1", //name + EPROM1_unit, //units + NULL, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + NULL, //reset + NULL, //boot + &EPROM1_attach, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + EPROM1_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* EPROM functions */ + +// EPROM configuration + +t_stat EPROM1_cfg(uint16 base, uint16 size) +{ + EPROM1_unit->capac = size; /* set EPROM size */ + EPROM1_unit->u3 = base & 0xFFFF; /* set EPROM base */ + sim_printf(" EPROM1: 0%04XH bytes at base 0%04XH\n", + EPROM1_unit->capac, EPROM1_unit->u3); + return SCPE_OK; +} + +/* EPROM reset */ + +t_stat EPROM1_reset (DEVICE *dptr) +{ + return SCPE_OK; +} + +/* EPROM attach */ + +t_stat EPROM1_attach (UNIT *uptr, CONST char *cptr) +{ + t_stat r; + + if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { + sim_printf("EPROM1_attach: Error %d\n", r); + return r; + } + return SCPE_OK; +} + +/* get a byte from memory */ + +uint8 EPROM1_get_mbyte(uint16 addr) +{ + uint8 val; + + if ((addr >= EPROM1_unit->u3) && ((uint32) addr <= (EPROM1_unit->u3 + EPROM1_unit->capac))) { + SET_XACK(1); /* good memory address */ + val = *((uint8 *)EPROM1_unit->filebuf + (addr - EPROM1_unit->u3)); + val &= 0xFF; + return val; + } else { + sim_printf("EPROM1: Out of range\n"); + } + return 0; +} + +/* end of iEPROM1.c */ diff --git a/Intel-Systems/common/ioc-cont.c b/Intel-Systems/common/ioc-cont.c index 46835588..d075fe20 100644 --- a/Intel-Systems/common/ioc-cont.c +++ b/Intel-Systems/common/ioc-cont.c @@ -34,14 +34,18 @@ #include "system_defs.h" /* system header in system dir */ -#define DEBUG 0 - //dbb status flag bits #define OBF 1 #define IBF 2 #define F0 4 #define CD 8 +//system status bits +#define IIM 16 //illegal interrupt mask +#define IDT 32 //illegal data transfer +#define IC 64 //illegal command +#define DE 128 //device error + //dbb command codes #define PACIFY 0x00 //Resets IOC and its devices #define ERESET 0x01 //Resets device-generated error (not used by standard devices) @@ -67,19 +71,18 @@ /* external globals */ -extern uint16 port; //port called in dev_table[port] extern int32 PCX; /* function prototypes */ -uint8 ioc_cont0(t_bool io, uint8 data); /* ioc_cont*/ -uint8 ioc_cont1(t_bool io, uint8 data); /* ioc_cont*/ -t_stat ioc_cont_reset (DEVICE *dptr, uint16 baseport); +t_stat ioc_cont_cfg(uint8 base, uint8 devnum); +t_stat ioc_cont_reset (DEVICE *dptr); +uint8 ioc_cont0(t_bool io, uint8 data, uint8 devnum); /* ioc_cont*/ +uint8 ioc_cont1(t_bool io, uint8 data, uint8 devnum); /* ioc_cont*/ /* external function prototypes */ -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); -extern uint32 saved_PC; /* program counter */ +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); /* globals */ @@ -123,27 +126,33 @@ DEVICE ioc_cont_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// &ioc_cont_reset, //reset - NULL, //reset + ioc_cont_reset, //reset NULL, //boot NULL, //attach NULL, //detach NULL, //ctxt 0, //flags 0, //dctrl - ioc_cont_debug, //debflags + ioc_cont_debug, //debflags NULL, //msize NULL //lname }; +// ioc_cont configuration + +t_stat ioc_cont_cfg(uint8 base, uint8 devnum) +{ + sim_printf(" ioc-cont[%d]: at base 0%02XH\n", + devnum, base & 0xFF); + reg_dev(ioc_cont0, base, devnum); + reg_dev(ioc_cont1, base + 1, devnum); + return SCPE_OK; +} + /* Reset routine */ -t_stat ioc_cont_reset(DEVICE *dptr, uint16 baseport) +t_stat ioc_cont_reset(DEVICE *dptr) { - sim_printf(" ioc_cont[%d]: Reset\n", 0); - sim_printf(" ioc_cont[%d]: Registered at %04X\n", 0, baseport); - reg_dev(ioc_cont0, baseport, 0); - reg_dev(ioc_cont1, baseport + 1, 0); dbb_stat = 0x00; /* clear DBB status */ return SCPE_OK; } @@ -152,80 +161,97 @@ t_stat ioc_cont_reset(DEVICE *dptr, uint16 baseport) IN or OUT instruction is issued. */ -/* IOC control port functions */ +/* IOC data port functions */ -uint8 ioc_cont0(t_bool io, uint8 data) +uint8 ioc_cont0(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read data port */ - if (DEBUG) - sim_printf("\n ioc_cont0: read data returned %02X PCX=%04X", dbb_out, PCX); + dbb_stat &= ~OBF; //reset OBF flag return dbb_out; } else { /* write data port */ dbb_in = data; dbb_stat |= IBF; - if (DEBUG) - sim_printf("\n ioc_cont0: write data=%02X port=%02X PCX=%04X", dbb_in, port, PCX); return 0; } } -uint8 ioc_cont1(t_bool io, uint8 data) +/* IOC control port functions */ + +uint8 ioc_cont1(t_bool io, uint8 data, uint8 devnum) { int temp; if (io == 0) { /* read status port */ if ((dbb_stat & F0) && (dbb_stat & IBF)) { - temp = dbb_stat; - if (DEBUG) - sim_printf("\n ioc_cont1: DBB status read 1 data=%02X PCX=%04X", dbb_stat, PCX); - dbb_stat &= ~IBF; //reset IBF flag - return temp; + return dbb_stat; } if ((dbb_stat & F0) && (dbb_stat & OBF)) { temp = dbb_stat; - if (DEBUG) - sim_printf("\n ioc_cont1: DBB status read 2 data=%02X PCX=%04X", dbb_stat, PCX); dbb_stat &= ~OBF; //reset OBF flag return temp; } if (dbb_stat & F0) { - temp = dbb_stat; - if (DEBUG) - sim_printf("\n ioc_cont1: DBB status read 3 data=%02X PCX=%04X", dbb_stat, PCX); - dbb_stat &= ~F0; //reset F0 flag - return temp; + return dbb_stat; } -// if (DEBUG) -// sim_printf(" ioc_cont1: DBB status read 4 data=%02X PCX=%04X\n", dbb_stat, PCX); return dbb_stat; } else { /* write command port */ + dbb_stat |= F0; dbb_cmd = data; switch(dbb_cmd){ - case PACIFY: //should delay 100 ms + case PACIFY: //reset IOC and its devices dbb_stat = 0; break; - case SYSTAT: + case ERESET: //reset device-generated error(not used by std devices) + break; + case SYSTAT: //returns subsystem status byte to master dbb_out = 0; dbb_stat |= OBF; dbb_stat &= ~CD; break; - case CRTS: + case DSTAT: //returns device status to master + break; + case SRQDAK: //enables input of device int ack mask from master + break; + case SRQACK: //clears IOC subsystem int req + break; + case SRQ: //tests ability of IOC to forward an int req to master + break; + case DECHO: //tests ability of IOC to echo data byte sent by master + break; + case CSMEM: //requests IOC to checksum onboard ROM + break; + case TRAM: //requests IOC to test onboard RAM + break; + case SINT: //enables specified device int from IOC + break; + case CRTC: //requests data byte output to CRT + break; + case CRTS: //return CRT status byte to master dbb_out = 0; dbb_stat |= F0; break; - case KSTC: - dbb_out = 0; - dbb_stat |= F0; + case KEYC: //request data byte from KBD break; - case RDSTS: + case KSTC: //return KBD status byte to master + dbb_out = 0; + break; + case WPBC: //enables input of first 5 bytes of IOPB + break; + case WPBCC: //enables input of 4 bytes that follow WPDC + break; + case WDBC: //enables input of diskette write bytes from master + break; + case RDBC: //enables output of diskette read bytes to master. + break; + case RRSTS: //returns diskette result byte to master + break; + case RDSTS: //returns diskette device status byte to master dbb_out = 0x80; //not ready - dbb_stat |= (F0 | IBF); + dbb_stat |= IBF; break; default: - sim_printf("\n ioc_cont1: Unknown command %02X PCX=%04X", dbb_cmd, PCX); + sim_printf(" IOC-CONT: Unknown command %02X PCX=%04X\n", dbb_cmd, PCX); } - if (DEBUG) - sim_printf("\n ioc_cont1: DBB command write data=%02X PCX=%04X", dbb_cmd, PCX); return 0; } } diff --git a/Intel-Systems/common/ipb.c b/Intel-Systems/common/ipb.c new file mode 100644 index 00000000..93837f69 --- /dev/null +++ b/Intel-Systems/common/ipb.c @@ -0,0 +1,181 @@ +/* ipb.c: Intel IPB Processor simulator + + Copyright (c) 2017, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + 01 Mar 18 - Original file. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +uint8 get_mbyte(uint16 addr); +uint16 get_mword(uint16 addr); +void put_mbyte(uint16 addr, uint8 val); +void put_mword(uint16 addr, uint16 val); +t_stat SBC_reset (DEVICE *dptr); + +/* external function prototypes */ + +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +extern uint8 multibus_get_mbyte(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern uint8 EPROM_get_mbyte(uint16 addr); +extern uint8 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16 addr, uint8 val); +extern t_stat i8251_cfg(uint8 base, uint8 devnum); +extern t_stat i8251_reset(DEVICE *dptr); +extern t_stat i8253_cfg(uint8 base, uint8 devnum); +extern t_stat i8253_reset(DEVICE *dptr); +extern t_stat i8255_cfg(uint8 base, uint8 devnum); +extern t_stat i8255_reset(DEVICE *dptr); +extern t_stat i8259_cfg(uint8 base, uint8 devnum); +extern t_stat i8259_reset(DEVICE *dptr); +extern t_stat EPROM_reset(DEVICE *dptr); +extern t_stat RAM_reset(DEVICE *dptr); +extern t_stat ipc_cont_reset(DEVICE *dptr); +extern t_stat ipc_cont_cfg(uint8 base, uint8 devnum); +extern t_stat ioc_cont_reset(DEVICE *dptr); +extern t_stat ioc_cont_cfg(uint8 base, uint8 devnum); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern t_stat EPROM_cfg(uint16 base, uint16 size); +extern t_stat RAM_cfg(uint16 base, uint16 size); +extern t_stat multibus_cfg(); + +/* globals */ + +int onetime = 0; + +/* extern globals */ + +extern uint32 PCX; /* program counter */ +extern UNIT i8255_unit; +extern UNIT EPROM_unit; +extern UNIT RAM_unit; +extern UNIT ipc_cont_unit; +extern UNIT ioc_cont_unit; +extern DEVICE *i8080_dev; +extern DEVICE *i8251_dev; +extern DEVICE *i8253_dev; +extern DEVICE *i8255_dev; +extern DEVICE *i8259_dev; +extern DEVICE *ipc_cont_dev; +extern DEVICE *ioc_cont_dev; + +t_stat SBC_config(void) +{ + sim_printf("Configuring IPB SBC\n Onboard Devices:\n"); + i8251_cfg(I8251_BASE_0, 0); + i8251_cfg(I8251_BASE_1, 1); + i8253_cfg(I8253_BASE, 0); + i8255_cfg(I8255_BASE_0, 0); + i8255_cfg(I8255_BASE_1, 1); + i8259_cfg(I8259_BASE_0, 0); + i8259_cfg(I8259_BASE_1, 0); + ipc_cont_cfg(ICONT_BASE, 0); + ioc_cont_cfg(DBB_BASE, 0); + EPROM_cfg(ROM_BASE, ROM_SIZE); + RAM_cfg(RAM_BASE, RAM_SIZE); + return SCPE_OK; +} + +/* CPU reset routine + put here to cause a reset of the entire IPC system */ + +t_stat SBC_reset (DEVICE *dptr) +{ + if (onetime == 0) { + SBC_config(); + multibus_cfg(); + onetime++; + } + i8080_reset(i8080_dev); + i8251_reset(i8251_dev); + i8253_reset(i8253_dev); + i8255_reset(i8255_dev); + i8259_reset(i8259_dev); + ipc_cont_reset(ipc_cont_dev); + ioc_cont_reset(ioc_cont_dev); + return SCPE_OK; +} + +/* get a byte from memory - handle RAM, ROM and Multibus memory */ + +uint8 get_mbyte(uint16 addr) +{ + if (addr >= 0xF800) { //monitor ROM - always there + return EPROM_get_mbyte(addr - 0xF000); //top half of EPROM + } + if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup + return EPROM_get_mbyte(addr); //top half of EPROM for boot + } + if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM + return EPROM_get_mbyte(addr - 0xE800); //bottom half of EPROM + } + if (addr < 0x8000) //IPB RAM + return RAM_get_mbyte(addr); + else + return multibus_get_mbyte(addr); //check multibus cards +} + +/* get a word from memory */ + +uint16 get_mword(uint16 addr) +{ + uint16 val; + + val = get_mbyte(addr); + val |= (get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory - handle RAM, ROM and Multibus memory */ + +void put_mbyte(uint16 addr, uint8 val) +{ + if (addr >= 0xF800) { //monitor ROM - always there + return; + } + if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup + return; + } + if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM + return; + } + if (addr < 0x8000) { + RAM_put_mbyte(addr, val); //IPB RAM + return; + } + multibus_put_mbyte(addr, val); //check multibus cards +} + +/* put a word to memory */ + +void put_mword(uint16 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of ipb.c */ diff --git a/Intel-Systems/common/ipbmultibus.c b/Intel-Systems/common/ipbmultibus.c new file mode 100644 index 00000000..03eeeb77 --- /dev/null +++ b/Intel-Systems/common/ipbmultibus.c @@ -0,0 +1,373 @@ +/* ipcmultibus.c: Multibus I simulator + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + 01 Mar 18 - Original file. + + NOTES: + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + +*/ + +#include "system_defs.h" + +int32 mbirq = 0; /* set no multibus interrupts */ + +/* function prototypes */ + +t_stat multibus_cfg(void); +t_stat multibus_svc(UNIT *uptr); +t_stat multibus_reset(DEVICE *dptr); +void set_irq(int32 int_num); +void clr_irq(int32 int_num); +uint8 nulldev(t_bool io, uint8 data, uint8 devnum); +t_stat multibus_reset (DEVICE *dptr); +uint8 multibus_get_mbyte(uint16 addr); +uint16 multibus_get_mword(uint16 addr); +void multibus_put_mbyte(uint16 addr, uint8 val); +void multibus_put_mword(uint16 addr, uint16 val); + +/* external function prototypes */ + +extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */ +extern void set_cpuint(int32 int_num); +extern t_stat zx200a_reset(DEVICE *dptr); +extern t_stat isbc201_reset (DEVICE *dptr); +extern t_stat isbc202_reset (DEVICE *dptr); +extern t_stat isbc206_reset (DEVICE *dptr); +extern t_stat isbc464_reset (DEVICE *dptr); +extern t_stat isbc064_reset (DEVICE *dptr); +extern uint8 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16 addr, uint8 val); +extern uint8 isbc064_get_mbyte(uint16 addr); +extern void isbc064_put_mbyte(uint16 addr, uint8 val); +extern uint8 isbc464_get_mbyte(uint16 addr); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern t_stat isbc064_cfg(uint16 base, uint16 size); +extern t_stat isbc464_cfg(uint16 base, uint16 size); +extern t_stat isbc201_cfg(uint8 base); +extern t_stat isbc202_cfg(uint8 base); +extern t_stat isbc206_cfg(uint8 base); +extern t_stat zx200a_cfg(uint8 base); +extern t_stat RAM_cfg(uint16 base, uint16 size); +extern t_stat EPROM_cfg(uint16 base, uint16 size); + +/* external globals */ + +extern uint8 xack; /* XACK signal */ +extern int32 int_req; /* i8080 INT signal */ +extern DEVICE isbc464_dev; +extern DEVICE isbc064_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE isbc206_dev; +extern DEVICE zx200a_dev; + +/* multibus Standard SIMH Device Data Structures */ + +UNIT multibus_unit = { + UDATA (&multibus_svc, 0, 0), 20 +}; + +REG multibus_reg[] = { + { HRDATA (MBIRQ, mbirq, 32) }, + { HRDATA (XACK, xack, 8) }, + { NULL } +}; + +DEBTAB multibus_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE multibus_dev = { + "MBIRQ", //name + &multibus_unit, //units + multibus_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + &multibus_reset, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + multibus_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +// multibus_cfg + +t_stat multibus_cfg(void) +{ + sim_printf("Configuring Multibus Devices\n"); + if (SBC064_NUM) isbc064_cfg(SBC064_BASE, SBC064_SIZE); + if (SBC464_NUM) isbc464_cfg(SBC464_BASE, SBC464_SIZE); + if (SBC201_NUM) isbc201_cfg(SBC201_BASE); + if (SBC202_NUM) isbc202_cfg(SBC202_BASE); + if (SBC206_NUM) isbc206_cfg(SBC206_BASE); + if (ZX200A_NUM) zx200a_cfg(ZX200A_BASE); + return SCPE_OK; +} +/* service routine - actually does the simulated interrupts */ + +t_stat multibus_svc(UNIT *uptr) +{ + switch (mbirq) { + case INT_1: + set_cpuint(INT_R); +#if NIPC + clr_irq(SBC202_INT); /***** bad, bad, bad! */ +#endif +// sim_printf("multibus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req); + break; + default: +// sim_printf("multibus_svc: default mbirq=%04X\n", mbirq); + break; + } + sim_activate (&multibus_unit, multibus_unit.wait); /* continue poll */ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat multibus_reset(DEVICE *dptr) +{ + if (SBC_reset(NULL) == 0) { + sim_printf(" Multibus: Reset\n"); + if (SBC064_NUM) { //device installed + isbc064_reset(&isbc064_dev); + sim_printf(" Multibus: SBC064 reset\n"); + } + if (SBC464_NUM) { //unit enabled + isbc464_reset(&isbc464_dev); + sim_printf(" Multibus: SBC464 reset\n"); + } + if (SBC201_NUM) { //unit enabled + isbc201_reset(&isbc201_dev); + sim_printf(" Multibus: SBC201 reset\n"); + } + if (SBC202_NUM) { //unit enabled + isbc202_reset(&isbc202_dev); + sim_printf(" Multibus: SBC202 reset\n"); + } + if (SBC206_NUM) { //unit enabled + isbc206_reset(&isbc206_dev); + sim_printf(" Multibus: SBC206 reset\n"); + } + if (ZX200A_NUM) { //unit enabled + zx200a_reset(&zx200a_dev); + sim_printf(" Multibus: ZX200A reset\n"); + } + sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ + return SCPE_OK; + } else { + sim_printf(" Multibus: SBC not selected\n"); + return SCPE_OK; + } +} + +void set_irq(int32 int_num) +{ + mbirq |= int_num; +// sim_printf("set_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); +} + +void clr_irq(int32 int_num) +{ + mbirq &= ~int_num; +// sim_printf("clr_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); +} + +/* This is the I/O configuration table. There are 256 possible +device addresses, if a device is plugged to a port it's routine +address is here, 'nulldev' means no device has been registered. +*/ +struct idev { + uint8 (*routine)(t_bool io, uint8 data, uint8 devnum); + uint8 port; + uint8 devnum; +}; + +struct idev dev_table[256] = { +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 000H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 004H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 008H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 00CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 010H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 014H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 018H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 01CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 020H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 024H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 028H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 02CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 030H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 034H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 038H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 03CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 040H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 044H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 048H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 04CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 050H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 054H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 058H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 05CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 060H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 064H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 068H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 06CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 070H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 074H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 078H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 07CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 080H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 084H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 088H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 08CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 090H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 094H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 098H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 09CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0CCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0DCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0ECH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */ +}; + +uint8 nulldev(t_bool flag, uint8 data, uint8 devnum) +{ + SET_XACK(0); /* set no XACK */ + return 0; //should be 0xff, but ISIS won't boot if not 0! +} + +uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint8 port, uint8 devnum) +{ + if (dev_table[port].routine != &nulldev) { /* port already assigned */ + if (dev_table[port].routine != routine) { /* different device? */ + sim_printf(" Multibus: I/O Port %04X is already assigned to different device\n", port); + return 1; + } else + return 0; + } else { + dev_table[port].routine = routine; + dev_table[port].devnum = devnum; + } + return 0; +} + +/* get a byte from memory */ + +uint8 multibus_get_mbyte(uint16 addr) +{ + uint8 val = 0; + + SET_XACK(0); /* set no XACK */ + if ((isbc464_dev.flags & DEV_DIS) == 0) { //ROM is enabled + if (addr >= SBC464_BASE && addr <= (SBC464_BASE + SBC464_SIZE - 1)) + return(isbc464_get_mbyte(addr)); + } + if ((isbc064_dev.flags & DEV_DIS) == 0) { //RAM is enabled + if (addr >= SBC064_BASE && addr <= (SBC064_BASE + SBC064_SIZE - 1)) + val = isbc064_get_mbyte(addr); + } + if (xack == 0) + val = RAM_get_mbyte(addr); + return val; +} + +/* get a word from memory */ + +uint16 multibus_get_mword(uint16 addr) +{ + uint16 val; + + val = multibus_get_mbyte(addr); + val |= (multibus_get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory */ + +void multibus_put_mbyte(uint16 addr, uint8 val) +{ + SET_XACK(0); /* set no XACK */ + if ((isbc064_dev.flags & DEV_DIS) == 0) { //RAM is enabled + if (addr >= SBC064_BASE && addr <= (SBC064_BASE + SBC064_SIZE - 1)) + isbc064_put_mbyte(addr, val); + } + RAM_put_mbyte(addr, val); +} + +/* put a word to memory */ + +void multibus_put_mword(uint16 addr, uint16 val) +{ + multibus_put_mbyte(addr, val & 0xff); + multibus_put_mbyte(addr+1, val >> 8); +} + +/* end of ipbmultibus.c */ + diff --git a/Intel-Systems/common/ipc-cont.c b/Intel-Systems/common/ipc-cont.c index 82d22205..21438c0c 100644 --- a/Intel-Systems/common/ipc-cont.c +++ b/Intel-Systems/common/ipc-cont.c @@ -33,16 +33,15 @@ #include "system_defs.h" /* system header in system dir */ -#define DEBUG 0 - /* function prototypes */ -uint8 ipc_cont(t_bool io, uint8 data); /* ipc_cont*/ -t_stat ipc_cont_reset (DEVICE *dptr, uint16 baseport); +t_stat ipc_cont_cfg(uint8 base, uint8 devnum); +uint8 ipc_cont(t_bool io, uint8 data, uint8 devnum); /* ipc_cont*/ +t_stat ipc_cont_reset (DEVICE *dptr); /* external function prototypes */ -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); /* globals */ @@ -69,9 +68,9 @@ DEBTAB ipc_cont_debug[] = { /* address width is set to 16 bits to use devices in 8086/8088 implementations */ DEVICE ipc_cont_dev = { - "IPC-CONT", //name - ipc_cont_unit, //units - ipc_cont_reg, //registers + "IPC-CONT", //name + ipc_cont_unit, //units + ipc_cont_reg, //registers NULL, //modifiers 1, //numunits 16, //aradix @@ -81,27 +80,33 @@ DEVICE ipc_cont_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// &ipc_cont_reset, //reset - NULL, //reset + NULL, //reset NULL, //boot NULL, //attach NULL, //detach NULL, //ctxt 0, //flags 0, //dctrl - ipc_cont_debug, //debflags + ipc_cont_debug, //debflags NULL, //msize NULL //lname }; +// ipc_cont configuration + +t_stat ipc_cont_cfg(uint8 base, uint8 devnum) +{ + sim_printf(" ipc-cont[%d]: at base 0%02XH\n", + devnum, base & 0xFF); + reg_dev(ipc_cont, base, devnum); + return SCPE_OK; +} + /* Reset routine */ -t_stat ipc_cont_reset(DEVICE *dptr, uint16 baseport) +t_stat ipc_cont_reset(DEVICE *dptr) { - sim_printf(" ipc_cont[%d]: Reset\n", 0); - sim_printf(" ipc_cont[%d]: Registered at %04X\n", 0, baseport); - reg_dev(ipc_cont, baseport, 0); - ipc_cont_unit[0].u3 = 0x00; /* ipc reset */ + ipc_cont_unit[0].u3 = 0x00; /* ipc reset */ return SCPE_OK; } @@ -111,12 +116,9 @@ t_stat ipc_cont_reset(DEVICE *dptr, uint16 baseport) /* IPC control port functions */ -uint8 ipc_cont(t_bool io, uint8 data) +uint8 ipc_cont(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read status port */ - if (DEBUG) - sim_printf(" ipc_cont: read data=%02X ipc_cont_unit[%d].u3=%02X\n", - ipc_cont_unit[0].u3, 0, ipc_cont_unit[0].u3); return ipc_cont_unit[0].u3; } else { /* write control port */ //this simulates an 74LS259 register @@ -155,8 +157,6 @@ uint8 ipc_cont(t_bool io, uint8 data) default: break; } - if (DEBUG) - sim_printf(" ipc_cont: write data=%02X ipc_cont_unit[%d].u3=%02X\n", data, 0, ipc_cont_unit[0].u3); } return 0; } diff --git a/Intel-Systems/imds-225/ipc.c b/Intel-Systems/common/ipc.c similarity index 64% rename from Intel-Systems/imds-225/ipc.c rename to Intel-Systems/common/ipc.c index 79d82199..fb42e7b8 100644 --- a/Intel-Systems/imds-225/ipc.c +++ b/Intel-Systems/common/ipc.c @@ -31,10 +31,9 @@ #include "system_defs.h" -#define DEBUG 0 - /* function prototypes */ +t_stat SBC_config(void); uint8 get_mbyte(uint16 addr); uint16 get_mword(uint16 addr); void put_mbyte(uint16 addr, uint8 val); @@ -44,52 +43,82 @@ t_stat SBC_reset (DEVICE *dptr); /* external function prototypes */ extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -//extern uint8 multibus_get_mbyte(uint16 addr); -//extern void multibus_put_mbyte(uint16 addr, uint8 val); extern uint8 EPROM_get_mbyte(uint16 addr); extern uint8 RAM_get_mbyte(uint16 addr); extern void RAM_put_mbyte(uint16 addr, uint8 val); +extern t_stat i8251_cfg(uint8 base, uint8 devnum); +extern t_stat i8251_reset(DEVICE *dptr); +extern t_stat i8253_cfg(uint8 base, uint8 devnum); +extern t_stat i8253_reset(DEVICE *dptr); +extern t_stat i8255_cfg(uint8 base, uint8 devnum); +extern t_stat i8255_reset(DEVICE *dptr); +extern t_stat i8259_cfg(uint8 base, uint8 devnum); +extern t_stat i8259_reset(DEVICE *dptr); +extern t_stat EPROM_reset(DEVICE *dptr); +extern t_stat RAM_reset(DEVICE *dptr); +extern t_stat ipc_cont_reset(DEVICE *dptr); +extern t_stat ipc_cont_cfg(uint8 base, uint8 devnum); +extern t_stat ioc_cont_reset(DEVICE *dptr); +extern t_stat ioc_cont_cfg(uint8 base, uint8 devnum); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern t_stat EPROM_cfg(uint16 base, uint16 size); +extern t_stat RAM_cfg(uint16 base, uint16 size); +extern t_stat multibus_cfg(); + +/* external globals */ + +extern uint32 PCX; /* program counter */ extern UNIT i8255_unit; extern UNIT EPROM_unit; extern UNIT RAM_unit; extern UNIT ipc_cont_unit; extern UNIT ioc_cont_unit; -extern int32 i8251_devnum; -extern t_stat i8251_reset(DEVICE *dptr, uint16 base); -extern int32 i8253_devnum; -extern t_stat i8253_reset(DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset(DEVICE *dptr, uint16 base); -extern int32 i8259_devnum; -extern t_stat i8259_reset(DEVICE *dptr, uint16 base); -extern t_stat EPROM_reset(DEVICE *dptr, uint16 size); -extern t_stat RAM_reset(DEVICE *dptr, uint16 base, uint16 size); -extern t_stat ipc_cont_reset(DEVICE *dptr, uint16 base); -extern t_stat ioc_cont_reset(DEVICE *dptr, uint16 base); -extern uint32 PCX; /* program counter */ +extern DEVICE *i8080_dev; +extern DEVICE *i8251_dev; +extern DEVICE *i8253_dev; +extern DEVICE *i8255_dev; +extern DEVICE *i8259_dev; +extern DEVICE *ipc_cont_dev; +extern DEVICE *ioc_cont_dev; + +/* globals */ + +int onetime = 0; + +t_stat SBC_config(void) +{ + sim_printf("Configuring IPC SBC\n Onboard Devices:\n"); + i8251_cfg(I8251_BASE_0, 0); + i8251_cfg(I8251_BASE_1, 1); + i8253_cfg(I8253_BASE, 0); + i8255_cfg(I8255_BASE_0, 0); + i8255_cfg(I8255_BASE_1, 1); + i8259_cfg(I8259_BASE_0, 0); + i8259_cfg(I8259_BASE_1, 0); + ipc_cont_cfg(ICONT_BASE, 0); + ioc_cont_cfg(DBB_BASE, 0); + EPROM_cfg(ROM_BASE, ROM_SIZE); + RAM_cfg(RAM_BASE, RAM_SIZE); + return SCPE_OK; +} /* CPU reset routine put here to cause a reset of the entire IPC system */ t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing MDS-225\n Onboard Devices:\n"); - i8080_reset(NULL); - i8251_devnum = 0; - i8251_reset(NULL, I8251_BASE_0); - i8251_reset(NULL, I8251_BASE_1); - i8253_devnum = 0; - i8253_reset(NULL, I8253_BASE); - i8255_devnum = 0; - i8255_reset(NULL, I8255_BASE_0); - i8255_reset(NULL, I8255_BASE_1); - i8259_devnum = 0; - i8259_reset(NULL, I8259_BASE_0); - i8259_reset(NULL, I8259_BASE_1); - EPROM_reset(NULL, ROM_SIZE); - RAM_reset(NULL, RAM_BASE, RAM_SIZE); - ipc_cont_reset(NULL, ICONT_BASE); - ioc_cont_reset(NULL, DBB_BASE); +{ + if (onetime == 0) { + SBC_config(); + multibus_cfg(); + onetime++; + } + i8080_reset(i8080_dev); + i8251_reset(i8251_dev); + i8253_reset(i8253_dev); + i8255_reset(i8255_dev); + i8259_reset(i8259_dev); + ipc_cont_reset(ipc_cont_dev); + ioc_cont_reset(ioc_cont_dev); return SCPE_OK; } @@ -125,18 +154,12 @@ uint16 get_mword(uint16 addr) void put_mbyte(uint16 addr, uint8 val) { if (addr >= 0xF800) { //monitor ROM - always there - if (DEBUG) - sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); return; } if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup - if (DEBUG) - sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); return; } if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM - if (DEBUG) - sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); return; } RAM_put_mbyte(addr, val); diff --git a/Intel-Systems/common/ipcmultibus.c b/Intel-Systems/common/ipcmultibus.c index 93b1e55a..10300e1f 100644 --- a/Intel-Systems/common/ipcmultibus.c +++ b/Intel-Systems/common/ipcmultibus.c @@ -26,7 +26,6 @@ MODIFICATIONS: ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. 24 Apr 15 -- Modified to use simh_debug NOTES: @@ -41,15 +40,16 @@ #define SET_XACK(VAL) (xack = VAL) int32 mbirq = 0; /* set no multibus interrupts */ +int32 flag = 0; /* function prototypes */ +t_stat multibus_cfg(void); t_stat multibus_svc(UNIT *uptr); t_stat multibus_reset(DEVICE *dptr); void set_irq(int32 int_num); void clr_irq(int32 int_num); -uint8 nulldev(t_bool io, uint8 data); -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +uint8 nulldev(t_bool flag, uint8 data, uint8 devnum); t_stat multibus_reset (DEVICE *dptr); uint8 multibus_get_mbyte(uint16 addr); uint16 multibus_get_mword(uint16 addr); @@ -60,19 +60,38 @@ void multibus_put_mword(uint16 addr, uint16 val); extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */ extern void set_cpuint(int32 int_num); -extern t_stat zx200a_reset(DEVICE *dptr, uint16 base); -extern t_stat isbc201_reset (DEVICE *dptr, uint16); -extern t_stat isbc202_reset (DEVICE *dptr, uint16); +extern t_stat isbc064_reset (DEVICE *dptr); +extern t_stat isbc464_reset (DEVICE *dptr); +extern t_stat zx200a_reset(DEVICE *dptr); +extern t_stat isbc201_reset (DEVICE *dptr); +extern t_stat isbc202_reset (DEVICE *dptr); +extern t_stat isbc206_reset (DEVICE *dptr); +extern t_stat isbc208_reset (DEVICE *dptr); extern uint8 RAM_get_mbyte(uint16 addr); extern void RAM_put_mbyte(uint16 addr, uint8 val); +extern uint8 isbc464_get_mbyte(uint16 addr); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern t_stat isbc064_cfg(uint16 base, uint16 size); +extern t_stat isbc464_cfg(uint16 base, uint16 size); +extern t_stat isbc201_cfg(uint8 base); +extern t_stat isbc202_cfg(uint8 base); +extern t_stat isbc206_cfg(uint8 base); +extern t_stat isbc208_cfg(uint8 base); +extern t_stat zx200a_cfg(uint8 base); +extern t_stat RAM_cfg(uint16 base, uint16 size); +extern t_stat EPROM_cfg(uint16 base, uint16 size); /* external globals */ extern uint8 xack; /* XACK signal */ extern int32 int_req; /* i8080 INT signal */ -extern int32 isbc201_fdcnum; -extern int32 isbc202_fdcnum; -extern int32 zx200a_fdcnum; +extern DEVICE isbc064_dev; +extern DEVICE isbc464_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE isbc206_dev; +extern DEVICE isbc208_dev; +extern DEVICE zx200a_dev; /* multibus Standard SIMH Device Data Structures */ @@ -82,7 +101,8 @@ UNIT multibus_unit = { REG multibus_reg[] = { { HRDATA (MBIRQ, mbirq, 32) }, - { HRDATA (XACK, xack, 8) } + { HRDATA (XACK, xack, 8) }, + { NULL } }; DEBTAB multibus_debug[] = { @@ -122,6 +142,21 @@ DEVICE multibus_dev = { /* Service routines to handle simulator functions */ +// multibus_cfg + +t_stat multibus_cfg(void) +{ + sim_printf("Configuring Multibus Devices\n"); + if (SBC064_NUM) isbc064_cfg(SBC064_BASE, SBC064_SIZE); + if (SBC464_NUM) isbc464_cfg(SBC464_BASE, SBC464_SIZE); + if (SBC201_NUM) isbc201_cfg(SBC201_BASE); + if (SBC202_NUM) isbc202_cfg(SBC202_BASE); + if (SBC206_NUM) isbc206_cfg(SBC206_BASE); + if (SBC208_NUM) isbc208_cfg(SBC208_BASE); + if (ZX200A_NUM) zx200a_cfg(ZX200A_BASE); + return SCPE_OK; +} + /* service routine - actually does the simulated interrupts */ t_stat multibus_svc(UNIT *uptr) @@ -146,16 +181,42 @@ t_stat multibus_svc(UNIT *uptr) t_stat multibus_reset(DEVICE *dptr) { - SBC_reset(NULL); - sim_printf(" Multibus: Reset\n"); - zx200a_fdcnum = 0; - zx200a_reset(NULL, ZX200A_BASE); - isbc201_fdcnum = 0; - isbc201_reset(NULL, SBC201_BASE); - isbc202_fdcnum = 0; - isbc202_reset(NULL, SBC202_BASE); - sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ - return SCPE_OK; + if (SBC_reset(NULL) == 0) { + sim_printf(" Multibus: Reset\n"); + if (SBC064_NUM) { //device installed + isbc064_reset(&isbc064_dev); + sim_printf(" Multibus: SBC064 reset\n"); + } + if (SBC464_NUM) { //unit enabled + isbc464_reset(&isbc464_dev); + sim_printf(" Multibus: SBC464 reset\n"); + } + if (SBC201_NUM) { //unit enabled + isbc201_reset(&isbc201_dev); + sim_printf(" Multibus: SBC201 reset\n"); + } + if (SBC202_NUM) { //unit enabled + isbc202_reset(&isbc202_dev); + sim_printf(" Multibus: SBC202 reset\n"); + } + if (SBC206_NUM) { //unit enabled + isbc206_reset(&isbc206_dev); + sim_printf(" Multibus: SBC206 reset\n"); + } + if (SBC208_NUM) { //unit enabled + isbc208_reset(&isbc208_dev); + sim_printf(" Multibus: SBC208 reset\n"); + } + if (ZX200A_NUM) { //unit enabled + zx200a_reset(&zx200a_dev); + sim_printf(" Multibus: ZX200A reset\n"); + } + sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ + return SCPE_OK; + } else { + sim_printf(" Multibus: SBC not selected\n"); + return SCPE_OK; + } } void set_irq(int32 int_num) @@ -167,7 +228,6 @@ void set_irq(int32 int_num) void clr_irq(int32 int_num) { mbirq &= ~int_num; -// sim_printf("clr_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); } /* This is the I/O configuration table. There are 256 possible @@ -175,7 +235,8 @@ device addresses, if a device is plugged to a port it's routine address is here, 'nulldev' means no device has been registered. */ struct idev { - uint8 (*routine)(t_bool io, uint8 data); + uint8 (*routine)(t_bool io, uint8 data, uint8 devnum); + uint8 port; uint8 devnum; }; @@ -246,19 +307,21 @@ struct idev dev_table[256] = { {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */ }; -uint8 nulldev(t_bool flag, uint8 data) +uint8 nulldev(t_bool flag, uint8 data, uint8 devnum) { SET_XACK(0); /* set no XACK */ -// return 0xFF; - return 0; + return 0; //should be 0xff, but ISIS won't boot if not 0! } -uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnum) +uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint8 port, uint8 devnum) { if (dev_table[port].routine != &nulldev) { /* port already assigned */ - sim_printf(" Multibus: I/O Port %04X is already assigned\n", port); + if (dev_table[port].routine != routine) { /* different device? */ + sim_printf(" Multibus: I/O Port %02X is already assigned to different device\n", port); + return 1; + } else + return 0; } else { - sim_printf(" Port %04X is assigned\n", port); dev_table[port].routine = routine; dev_table[port].devnum = devnum; } @@ -269,9 +332,16 @@ uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnu uint8 multibus_get_mbyte(uint16 addr) { + uint8 val = 0; + SET_XACK(0); /* set no XACK */ -// sim_printf("multibus_get_mbyte: Cleared XACK for %04X\n", addr); - return RAM_get_mbyte(addr); + if ((isbc464_dev.flags & DEV_DIS) == 0) { //ROM is enabled + if (addr >= SBC464_BASE && addr <= (SBC464_BASE + SBC464_SIZE)) + return(isbc464_get_mbyte(addr)); + } + if (xack == 0) + val = RAM_get_mbyte(addr); + return val; } /* get a word from memory */ @@ -290,9 +360,7 @@ uint16 multibus_get_mword(uint16 addr) void multibus_put_mbyte(uint16 addr, uint8 val) { SET_XACK(0); /* set no XACK */ -// sim_printf("multibus_put_mbyte: Cleared XACK for %04X\n", addr); RAM_put_mbyte(addr, val); -// sim_printf("multibus_put_mbyte: Done XACK=%dX\n", XACK); } /* put a word to memory */ diff --git a/Intel-Systems/common/iram8.c b/Intel-Systems/common/iram8.c index 5ae08a4c..87014b6b 100644 --- a/Intel-Systems/common/iram8.c +++ b/Intel-Systems/common/iram8.c @@ -26,8 +26,6 @@ MODIFICATIONS: ?? ??? 11 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. - 24 Apr 15 -- Modified to use simh_debug NOTES: @@ -38,17 +36,15 @@ #include "system_defs.h" -#define DEBUG 0 - /* function prototypes */ -t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); +t_stat RAM_cfg(uint16 base, uint16 size); +t_stat RAM_reset (DEVICE *dptr); uint8 RAM_get_mbyte(uint16 addr); void RAM_put_mbyte(uint16 addr, uint8 val); -/* external function prototypes */ +/* external globals */ -extern uint8 i8255_B[4]; //port B byte I/O extern uint8 xack; /* XACK signal */ /* SIMH RAM Standard I/O Data Structures */ @@ -79,8 +75,7 @@ DEVICE RAM_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// &RAM_reset, //reset - NULL, //reset + RAM_reset, //reset NULL, //boot NULL, //attach NULL, //detach @@ -94,27 +89,26 @@ DEVICE RAM_dev = { /* RAM functions */ +// RAM configuration + +t_stat RAM_cfg(uint16 base, uint16 size) +{ + RAM_unit.capac = size & 0xFFFF; /* set RAM size */ + RAM_unit.u3 = base & 0xFFFF; /* set RAM base */ + RAM_unit.filebuf = (uint8 *)malloc(size * sizeof(uint8)); + if (RAM_unit.filebuf == NULL) { + sim_printf (" RAM: Malloc error\n"); + return SCPE_MEM; + } + sim_printf(" RAM: 0%04XH bytes at base 0%04XH\n", + size, base & 0xFFFF); + return SCPE_OK; +} + /* RAM reset */ -t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size) +t_stat RAM_reset (DEVICE *dptr) { - sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%04X size=%04X\n", base, size-1); - if (RAM_unit.capac == 0) { /* if undefined */ - RAM_unit.capac = size; - RAM_unit.u3 = base; - } - if (RAM_unit.filebuf == NULL) { /* no buffer allocated */ - RAM_unit.filebuf = malloc(RAM_unit.capac); - if (RAM_unit.filebuf == NULL) { - sim_debug (DEBUG_flow, &RAM_dev, "RAM_set_size: Malloc error\n"); - return SCPE_MEM; - } - } - if (DEBUG) - sim_printf(" RAM: Available [%04X-%04XH]\n", - RAM_unit.u3, - RAM_unit.u3 + RAM_unit.capac - 1); - sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n"); return SCPE_OK; } @@ -124,33 +118,26 @@ uint8 RAM_get_mbyte(uint16 addr) { uint8 val; - sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr); if ((addr >= RAM_unit.u3) && ((uint32) addr < (RAM_unit.u3 + RAM_unit.capac))) { SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr); val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); - sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); return (val & 0xFF); } else { - sim_debug (DEBUG_read, &RAM_dev, " Out of range\n"); return 0xFF; } } -/* put a byte to memory */ +/* put a byte into memory */ void RAM_put_mbyte(uint16 addr, uint8 val) { - sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val); if ((addr >= RAM_unit.u3) && ((uint32)addr < RAM_unit.u3 + RAM_unit.capac)) { SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr); *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; - sim_debug (DEBUG_write, &RAM_dev, "\n"); return; } else { - sim_debug (DEBUG_write, &RAM_dev, " Out of range\n"); return; + } } diff --git a/Intel-Systems/common/isbc064.c b/Intel-Systems/common/isbc064.c index 87ea71e5..cc17913d 100644 --- a/Intel-Systems/common/isbc064.c +++ b/Intel-Systems/common/isbc064.c @@ -25,8 +25,8 @@ MODIFICATIONS: - ?? ??? 11 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + ?? ??? 11 -- Original file. + 16 Dec 12 -- Modified to use isbc_80_10.cfg file to set base and size. 24 Apr 15 -- Modified to use simh_debug NOTES: @@ -37,22 +37,42 @@ #include "system_defs.h" +#define UNIT_V_MSIZE (UNIT_V_UF+2) /* Memory Size */ +#define UNIT_MSIZE (1 << UNIT_V_MSIZE) + #define SET_XACK(VAL) (xack = VAL) /* prototypes */ -t_stat isbc064_reset (DEVICE *dptr); +t_stat isbc064_cfg(uint16 base, uint16 size); +t_stat isbc064_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat isbc064_reset(DEVICE *dptr); uint8 isbc064_get_mbyte(uint16 addr); void isbc064_put_mbyte(uint16 addr, uint8 val); -extern uint8 xack; /* XACK signal */ +/* external function prototypes */ -/* isbc064 Standard I/O Data Structures */ +/* local globals */ + +/* external globals */ + +extern uint32 PCX; /* program counter */ +extern uint8 xack; + +/* isbc064 Standard SIMH Device Data Structures */ UNIT isbc064_unit = { UDATA (NULL, UNIT_FIX+UNIT_DISABLE+UNIT_BINK, 65536), KBD_POLL_WAIT }; +MTAB isbc064_mod[] = { + { UNIT_MSIZE, 16384, "16K", "16K", &isbc064_set_size }, + { UNIT_MSIZE, 32768, "32K", "32K", &isbc064_set_size }, + { UNIT_MSIZE, 49152, "48K", "48K", &isbc064_set_size }, + { UNIT_MSIZE, 65536, "64K", "64K", &isbc064_set_size }, + { 0 } +}; + DEBTAB isbc064_debug[] = { { "ALL", DEBUG_all }, { "FLOW", DEBUG_flow }, @@ -68,7 +88,7 @@ DEVICE isbc064_dev = { "SBC064", //name &isbc064_unit, //units NULL, //registers - NULL, //modifiers + isbc064_mod, //modifiers 1, //numunits 16, //aradix 16, //awidth @@ -76,8 +96,7 @@ DEVICE isbc064_dev = { 16, //dradix 8, //dwidth NULL, //examine - NULL, //deposite -// &isbc064_reset, //reset + NULL, //deposit NULL, //reset NULL, //boot NULL, //attach @@ -90,29 +109,40 @@ DEVICE isbc064_dev = { NULL //lname }; -/* iSBC064 globals */ +/* Service routines to handle simulator functions */ + +// configuration routine + +t_stat isbc064_cfg(uint16 base, uint16 size) +{ + sim_printf(" sbc064: 0%04XH bytes at base 0%04XH\n", + size, base); + isbc064_unit.capac = size; //set size + isbc064_unit.u3 = base; //and base + isbc064_unit.filebuf = (uint8 *)calloc(size, sizeof(uint8)); + if (isbc064_unit.filebuf == NULL) { + sim_printf (" sbc064: Malloc error\n"); + return SCPE_MEM; + } + return SCPE_OK; +} + +t_stat isbc064_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + if ((val <= 0) || (val > MAXMEMSIZE)) { + sim_printf("Memory size error - val=%d\n", val); + return SCPE_ARG; + } + isbc064_reset(&isbc064_dev); + isbc064_unit.capac = val; + sim_printf("SBC064: Size set to %04X\n", val); + return SCPE_OK; +} /* Reset routine */ t_stat isbc064_reset (DEVICE *dptr) { - sim_debug (DEBUG_flow, &isbc064_dev, "isbc064_reset: "); - if ((isbc064_dev.flags & DEV_DIS) == 0) { - isbc064_unit.capac = SBC064_SIZE; - isbc064_unit.u3 = SBC064_BASE; - sim_printf("Initializing iSBC-064 RAM Board\n"); - sim_printf(" Available[%04X-%04XH]\n", - isbc064_unit.u3, - isbc064_unit.u3 + isbc064_unit.capac - 1); - } - if (isbc064_unit.filebuf == NULL) { - isbc064_unit.filebuf = (uint8 *)malloc(isbc064_unit.capac); - if (isbc064_unit.filebuf == NULL) { - sim_debug (DEBUG_flow, &isbc064_dev, "isbc064_reset: Malloc error\n"); - return SCPE_MEM; - } - } - sim_debug (DEBUG_flow, &isbc064_dev, "isbc064_reset: Done\n"); return SCPE_OK; } @@ -120,55 +150,37 @@ t_stat isbc064_reset (DEVICE *dptr) uint8 isbc064_get_mbyte(uint16 addr) { - uint32 val, org, len; + uint32 val; - if ((isbc064_dev.flags & DEV_DIS) == 0) { - org = isbc064_unit.u3; - len = isbc064_unit.capac; - sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: addr=%04X", addr); - sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: org=%04X, len=%04X\n", org, len); - if ((addr >= org) && (addr < (org + len))) { + if ((isbc064_dev.flags & DEV_DIS) == 0) { //device is enabled + if ((addr >= isbc064_unit.u3) && (addr <= (isbc064_unit.u3 + isbc064_unit.capac))) { SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &isbc064_dev, "isbc064_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)isbc064_unit.filebuf + (addr - org)); - sim_debug (DEBUG_read, &isbc064_dev, " val=%04X\n", val); -// sim_printf ("isbc064_get_mbyte: addr=%04X, val=%02X\n", addr, val); - return (val & 0xFF); + val = *((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.u3)); + return (val & 0xFF); } else { - sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Out of range\n"); - return 0; /* multibus has active high pullups and inversion */ + sim_printf("isbc064_get_mbyte: Read-Enabled Out of range addr=%04X PC=%04X\n", addr, PCX); + return 0xff; /* multibus has active high pullups and inversion */ } - } - sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Disabled\n"); -// sim_printf ("isbc064_get_mbyte: Disabled\n"); - return 0; /* multibus has active high pullups and inversion */ + } //device is disabled/not installed + sim_printf ("isbc064_get_mbyte: Read-Disabled addr=%04X PC=%04X\n", addr, PCX); + return 0xff; /* multibus has active high pullups and inversion */ } /* put a byte into memory */ void isbc064_put_mbyte(uint16 addr, uint8 val) { - uint32 org, len; - - if ((isbc064_dev.flags & DEV_DIS) == 0) { - org = isbc064_unit.u3; - len = isbc064_unit.capac; -// sim_printf ("isbc064_put_mbyte: addr=%04X, val=%02X\n", addr, val); - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: addr=%04X, val=%02X\n", addr, val); - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: org=%04X, len=%04X\n", org, len); - if ((addr >= org) && (addr < (org + len))) { + if ((isbc064_dev.flags & DEV_DIS) == 0) { //device is enabled + if ((addr >= isbc064_unit.u3) && (addr < (isbc064_unit.u3 + isbc064_unit.capac))) { SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Set XACK for %04X\n", addr); - *((uint8 *)isbc064_unit.filebuf + (addr - org)) = val & 0xFF; - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Return\n"); + *((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.u3)) = val & 0xFF; return; } else { - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Out of range\n"); + sim_printf("isbc064_put_mbyte: Write Out of range addr=%04X PC=%04X\n", addr, PCX); return; } - } - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Disabled\n"); -// sim_printf ("isbc064_put_mbyte: Disabled\n"); + } //device is disabled/not installed + sim_printf ("isbc064_put_mbyte: Write-Disabled addr=%04X PC=%04X\n", addr, PCX); } /* end of isbc064.c */ diff --git a/Intel-Systems/common/isbc201.c b/Intel-Systems/common/isbc201.c index 5c5d605d..fd9af33f 100644 --- a/Intel-Systems/common/isbc201.c +++ b/Intel-Systems/common/isbc201.c @@ -34,7 +34,7 @@ Registers: - 078H - Read - Subsystem status + 088H - Read - Subsystem status bit 0 - ready status of drive 0 bit 1 - ready status of drive 1 bit 2 - state of channel's interrupt FF @@ -44,16 +44,16 @@ bit 6 - zero bit 7 - zero - 079H - Read - Read result type (bits 2-7 are zero) + 089H - Read - Read result type (bits 2-7 are zero) 00 - I/O complete with error(unlinked) 01 - I/O complete with error(linked)(hi 6-bits are block num) 10 - Result byte contains diskette ready status 11 - Reserved - 079H - Write - IOPB address low byte. + 089H - Write - IOPB address low byte. - 07AH - Write - IOPB address high byte and start operation. + 08AH - Write - IOPB address high byte and start operation. - 07BH - Read - Read result byte + 08BH - Read - Read result byte If result type is 00H bit 0 - deleted record bit 1 - CRC error @@ -74,7 +74,7 @@ bit 7 - drive 1 ready else return 0 - 07FH - Write - Reset diskette system. + 08FH - Write - Reset diskette system. Operations: NOP - 0x00 @@ -136,19 +136,35 @@ u3 - u4 - - u5 - fdc number (board instance number). + u5 - u6 - fdd number. + SSSD - Bootable + This is actually an IBM 3740 format disk. It has 77 tracks of 26 SD + sectors of 128 bytes each for a total of 2002 sectors. The disk layout + of the first 6 tracks of the SSSD 256256 byte disk image is as follows: + + File Link Blk Addr Data Blk Addr + From To + Trk Sec Trk Sec Trk Sec + ISIS.T0 000h 018h 000h 001h 000h 017h bin file 0B80 0000 0B00 + ISIS.DIR 001h 001h 001h 002h 001h 01Ah 0D00 0D80 1980 + ISIS.MAP 002h 001h 002h 002h 002h 003h 1A00 1A80 1B00 + ISIS.LAB 000h 019h 000h 01Ah 000h 01Ah 0C00 0C80 0C80 + ISIS.BIN 002h 004h 002h 005h 004h 00Eh pkd file 1B80 1C00 3A80 + 004h 00Fh 004h 010h 005h 013h 3B00 3B80 4A00 + ISIS.CLI 005h 014h 005h 015h 006h 00Dh reg file 4A80 4B00 5480 + NEXT BLK 006h 00Eh 5500 + */ #include "system_defs.h" /* system header in system dir */ -#define DEBUG 0 - #define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ #define UNIT_WPMODE (1 << UNIT_V_WPMODE) #define FDD_NUM 2 +#define SECSIZ 128 //disk controoler operations #define DNOP 0x00 //disk no operation @@ -166,10 +182,10 @@ #define FDCPRE 0x08 //FDC board present //result type -#define RERR 0x00 //FDC returned error -#define ROK 0x02 //FDC returned ok +#define ROK 0x00 //FDC OK OR ERROR +#define RCHG 0x02 //FDC DISK CHANGED -// If result type is RERR then rbyte is +// If result type is ROK then rbyte is #define RB0DR 0x01 //deleted record #define RB0CRC 0x02 //CRC error #define RB0SEK 0x04 //seek error @@ -179,57 +195,47 @@ #define RB0WE 0x40 //write error #define RB0NR 0x80 //not ready -// If result type is ROK then rbyte is +// If result type is RCHG then rbyte is #define RB1RD0 0x40 //drive 0 ready #define RB1RD1 0x80 //drive 1 ready //disk geometry values #define MDSSD 256256 //single density FDD size -#define MDSDD 512512 //double density FDD size #define MAXSECSD 26 //single density last sector -#define MAXSECDD 52 //double density last sector #define MAXTRK 76 //last track /* external globals */ -extern uint16 port; //port called in dev_table[port] extern int32 PCX; /* external function prototypes */ -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); extern uint8 multibus_get_mbyte(uint16 addr); -extern uint16 multibus_get_mword(uint16 addr); extern void multibus_put_mbyte(uint16 addr, uint8 val); -extern uint8 multibus_put_mword(uint16 addr, uint16 val); /* function prototypes */ -t_stat isbc201_reset(DEVICE *dptr, uint16 base); -void isbc201_reset1(uint8 fdcnum); +t_stat isbc201_cfg(uint8 base); +t_stat isbc201_reset(DEVICE *dptr); +void isbc201_reset1(void); t_stat isbc201_attach (UNIT *uptr, CONST char *cptr); t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -uint8 isbc201_get_dn(void); -uint8 isbc2010(t_bool io, uint8 data); /* isbc201 0 */ -uint8 isbc2011(t_bool io, uint8 data); /* isbc201 1 */ -uint8 isbc2012(t_bool io, uint8 data); /* isbc201 2 */ -uint8 isbc2013(t_bool io, uint8 data); /* isbc201 3 */ -uint8 isbc2017(t_bool io, uint8 data); /* isbc201 7 */ -void isbc201_diskio(uint8 fdcnum); //do actual disk i/o +uint8 isbc201r0(t_bool io, uint8 data, uint8 devnum); /* isbc201 0 */ +uint8 isbc201r1(t_bool io, uint8 data, uint8 devnum); /* isbc201 1 */ +uint8 isbc201r2(t_bool io, uint8 data, uint8 devnum); /* isbc201 2 */ +uint8 isbc201r3(t_bool io, uint8 data, uint8 devnum); /* isbc201 3 */ +uint8 isbc201r7(t_bool io, uint8 data, uint8 devnum); /* isbc201 7 */ +void isbc201_diskio(void); //do actual disk i/o /* globals */ -int32 isbc201_fdcnum = 0; //actual number of SBC-201 instances + 1 - typedef struct { //FDD definition - int t0; - int rdy; uint8 sec; uint8 cyl; } FDDDEF; typedef struct { //FDC definition - uint16 baseport; //FDC base port uint16 iopb; //FDC IOPB uint8 stat; //FDC status uint8 rdychg; //FDC ready changed @@ -240,36 +246,21 @@ typedef struct { //FDC definition FDDDEF fdd[FDD_NUM]; //indexed by the FDD number } FDCDEF; -FDCDEF fdc201[4]; //indexed by the isbc-201 instance number +FDCDEF fdc201; -UNIT isbc201_unit[] = { - { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD), 20 }, - { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD), 20 }, - { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD), 20 }, - { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD), 20 } +/* isbc201 Standard I/O Data Structures */ + +UNIT isbc201_unit[] = { //2 FDDs + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD) }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD) } }; REG isbc201_reg[] = { - { HRDATA (STAT0, fdc201[0].stat, 8) }, /* fdc201 0 status */ - { HRDATA (RTYP0, fdc201[0].rtype, 8) }, /* fdc201 0 result type */ - { HRDATA (RBYT0A, fdc201[0].rbyte0, 8) }, /* fdc201 0 result byte 0 */ - { HRDATA (RBYT0B, fdc201[0].rbyte1, 8) }, /* fdc201 0 result byte 1 */ - { HRDATA (INTFF0, fdc201[0].intff, 8) }, /* fdc201 0 interrupt f/f */ - { HRDATA (STAT1, fdc201[1].stat, 8) }, /* fdc201 1 status */ - { HRDATA (RTYP1, fdc201[1].rtype, 8) }, /* fdc201 1 result type */ - { HRDATA (RBYT1A, fdc201[1].rbyte0, 8) }, /* fdc201 1 result byte 0 */ - { HRDATA (RBYT1B, fdc201[1].rbyte1, 8) }, /* fdc201 1 result byte 1 */ - { HRDATA (INTFF1, fdc201[1].intff, 8) }, /* fdc201 1 interrupt f/f */ - { HRDATA (STAT2, fdc201[2].stat, 8) }, /* fdc201 2 status */ - { HRDATA (RTYP2, fdc201[2].rtype, 8) }, /* fdc201 2 result type */ - { HRDATA (RBYT2A, fdc201[2].rbyte0, 8) }, /* fdc201 2 result byte 0 */ - { HRDATA (RBYT2B, fdc201[2].rbyte1, 8) }, /* fdc201 2 result byte 1 */ - { HRDATA (INTFF2, fdc201[2].intff, 8) }, /* fdc201 2 interrupt f/f */ - { HRDATA (STAT3, fdc201[3].stat, 8) }, /* fdc201 3 status */ - { HRDATA (RTYP3, fdc201[3].rtype, 8) }, /* fdc201 3 result type */ - { HRDATA (RBYT3A, fdc201[3].rbyte0, 8) }, /* fdc201 3 result byte 0 */ - { HRDATA (RBYT3B, fdc201[3].rbyte1, 8) }, /* fdc201 3 result byte 1 */ - { HRDATA (INTFF3, fdc201[3].intff, 8) }, /* fdc201 3 interrupt f/f */ + { HRDATA (STAT0, fdc201.stat, 8) }, //fdc201 0 status + { HRDATA (RTYP0, fdc201.rtype, 8) }, //fdc201 0 result type + { HRDATA (RBYT0A, fdc201.rbyte0, 8) }, //fdc201 0 result byte 0 + { HRDATA (RBYT0B, fdc201.rbyte1, 8) }, //fdc201 0 result byte 1 + { HRDATA (INTFF0, fdc201.intff, 8) }, //fdc201 0 interrupt f/f { NULL } }; @@ -305,81 +296,72 @@ DEVICE isbc201_dev = { 8, //dwidth NULL, //examine NULL, //deposit - NULL, //reset + isbc201_reset, //reset NULL, //boot &isbc201_attach, //attach NULL, //detach NULL, //ctxt DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags - DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl + 0, //dctrl isbc201_debug, //debflags NULL, //msize NULL //lname }; -/* Hardware reset routine */ +// configuration routine -t_stat isbc201_reset(DEVICE *dptr, uint16 base) +t_stat isbc201_cfg(uint8 base) { int32 i; UNIT *uptr; - sim_printf(" iSBC-201 FDC Board"); - if (SBC201_NUM) { - sim_printf(" - Found\n"); - sim_printf(" isbc201-%d: Hardware Reset\n", isbc201_fdcnum); - sim_printf(" isbc201-%d: Registered at %04X\n", isbc201_fdcnum, base); - //register base port address for this FDC instance - fdc201[isbc201_fdcnum].baseport = base; - //register I/O port addresses for each function - reg_dev(isbc2010, base, isbc201_fdcnum); //read status - reg_dev(isbc2011, base + 1, isbc201_fdcnum); //read rslt type/write IOPB addr-l - reg_dev(isbc2012, base + 2, isbc201_fdcnum); //write IOPB addr-h and start - reg_dev(isbc2013, base + 3, isbc201_fdcnum); //read rstl byte - reg_dev(isbc2017, base + 7, isbc201_fdcnum); //write reset fdc201 - // one-time initialization for all FDDs for this FDC instance - for (i = 0; i < FDD_NUM; i++) { - uptr = isbc201_dev.units + i; - uptr->u5 = isbc201_fdcnum; //fdc device number - uptr->u6 = i; //fdd unit number - uptr->flags |= UNIT_WPMODE; //set WP in unit flags - } - isbc201_reset1(isbc201_fdcnum); - isbc201_fdcnum++; - } else - sim_printf(" - Not Found\n"); + sim_printf(" sbc201: at base 0%02XH\n", + base); + reg_dev(isbc201r0, base, 0); //read status + reg_dev(isbc201r1, base + 1, 0); //read rslt type/write IOPB addr-l + reg_dev(isbc201r2, base + 2, 0); //write IOPB addr-h and start + reg_dev(isbc201r3, base + 3, 0); //read rstl byte + reg_dev(isbc201r7, base + 7, 0); //write reset fdc201 + // one-time initialization for all FDDs for this FDC instance + for (i = 0; i < FDD_NUM; i++) { + uptr = isbc201_dev.units + i; + uptr->u6 = i; //fdd unit number + } + return SCPE_OK; +} +/* Hardware reset routine */ + +t_stat isbc201_reset(DEVICE *dptr) +{ + isbc201_reset1(); return SCPE_OK; } /* Software reset routine */ -void isbc201_reset1(uint8 fdcnum) +void isbc201_reset1(void) { int32 i; UNIT *uptr; - sim_printf(" isbc201-%d: Software Reset\n", fdcnum); - fdc201[fdcnum].stat = 0; //clear status + fdc201.stat = 0; //clear status for (i = 0; i < FDD_NUM; i++) { /* handle all units */ uptr = isbc201_dev.units + i; - fdc201[fdcnum].stat |= FDCPRE; //set the FDC status - fdc201[fdcnum].rtype = ROK; - if (uptr->capac == 0) { /* if not configured */ - sim_printf(" isbc201-%d: Configured, Status=%02X Not attached\n", i, fdc201[fdcnum].stat); - } else { + fdc201.stat |= FDCPRE; //set the FDC status + fdc201.rtype = ROK; + fdc201.rbyte0 = 0; //set no error + if (uptr->flags & UNIT_ATT) { /* if attached */ switch(i){ case 0: - fdc201[fdcnum].stat |= RDY0; //set FDD 0 ready - fdc201[fdcnum].rbyte1 |= RB1RD0; + fdc201.stat |= RDY0; //set FDD 0 ready + fdc201.rbyte1 |= RB1RD0; break; case 1: - fdc201[fdcnum].stat |= RDY1; //set FDD 1 ready - fdc201[fdcnum].rbyte1 |= RB1RD1; + fdc201.stat |= RDY1; //set FDD 1 ready + fdc201.rbyte1 |= RB1RD1; break; } - fdc201[fdcnum].rdychg = 0; - sim_printf(" isbc201-%d: Configured, Status=%02X Attached to %s\n", - i, fdc201[fdcnum].stat, uptr->filename); + fdc201.rdychg = 0; } } } @@ -389,29 +371,25 @@ void isbc201_reset1(uint8 fdcnum) t_stat isbc201_attach (UNIT *uptr, CONST char *cptr) { t_stat r; - uint8 fdcnum, fddnum; + uint8 fddnum; - sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_attach: Entered with cptr=%s\n", cptr); if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - sim_printf(" isbc201_attach: Attach error\n"); + sim_printf(" SBC201_attach: Attach error %d\n", r); return r; } - fdcnum = uptr->u5; fddnum = uptr->u6; switch(fddnum){ case 0: - fdc201[fdcnum].stat |= RDY0; //set FDD 0 ready - fdc201[fdcnum].rbyte1 |= RB1RD0; + fdc201.stat |= RDY0; //set FDD 0 ready + fdc201.rbyte1 |= RB1RD0; break; case 1: - fdc201[fdcnum].stat |= RDY1; //set FDD 1 ready - fdc201[fdcnum].rbyte1 |= RB1RD1; + fdc201.stat |= RDY1; //set FDD 1 ready + fdc201.rbyte1 |= RB1RD1; break; } - fdc201[fdcnum].rtype = ROK; - sim_printf(" iSBC-201%d: FDD %d Configured %d bytes, Attached to %s\n", - fdcnum, fddnum, uptr->capac, uptr->filename); - sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_attach: Done\n"); + fdc201.rtype = ROK; + fdc201.rbyte0 = 0; return SCPE_OK; } @@ -419,139 +397,86 @@ t_stat isbc201_attach (UNIT *uptr, CONST char *cptr) t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { -// sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_set_mode: Entered with val=%08XH uptr->flags=%08X\n", -// val, uptr->flags); + if (uptr->flags & UNIT_ATT) + return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename); if (val & UNIT_WPMODE) { /* write protect */ uptr->flags |= val; } else { /* read write */ uptr->flags &= ~val; } -// sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_set_mode: Done\n"); return SCPE_OK; } -uint8 isbc201_get_dn(void) -{ - int i; - - for (i=0; i= fdc201[i].baseport && port <= fdc201[i].baseport + 7) - return i; - sim_printf("isbc201_get_dn: port %04X not in fdc201 device table\n", port); - return 0xFF; -} - /* I/O instruction handlers, called from the CPU module when an IN or OUT instruction is issued. */ /* ISBC201 control port functions */ -uint8 isbc2010(t_bool io, uint8 data) +uint8 isbc201r0(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc201_get_dn()) != 0xFF) { - if (io == 0) { /* read ststus*/ - if (DEBUG) - sim_printf("\n isbc201-%d: 0x78 returned status=%02X PCX=%04X", - fdcnum, fdc201[fdcnum].stat, PCX); - return fdc201[fdcnum].stat; + if (io == 0) { /* read status*/ + return fdc201.stat; } - } return 0; } -uint8 isbc2011(t_bool io, uint8 data) +uint8 isbc201r1(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc201_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - fdc201[fdcnum].intff = 0; //clear interrupt FF - fdc201[fdcnum].stat &= ~FDCINT; - if (DEBUG) - sim_printf("\n isbc201-%d: 0x79 returned rtype=%02X intff=%02X status=%02X PCX=%04X", - fdcnum, fdc201[fdcnum].rtype, fdc201[fdcnum].intff, fdc201[fdcnum].stat, PCX); - return fdc201[fdcnum].rtype; - } else { /* write data port */ - fdc201[fdcnum].iopb = data; - if (DEBUG) - sim_printf("\n isbc201-%d: 0x79 IOPB low=%02X PCX=%04X", - fdcnum, data, PCX); + if (io == 0) { /* read data port */ + fdc201.intff = 0; //clear interrupt FF + fdc201.stat &= ~FDCINT; + return fdc201.rtype; + } else { /* write data port */ + fdc201.iopb = data; } - } return 0; } -uint8 isbc2012(t_bool io, uint8 data) +uint8 isbc201r2(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc201_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - fdc201[fdcnum].iopb |= (data << 8); - if (DEBUG) - sim_printf("\n isbc201-%d: 0x7A IOPB=%04X PCX=%04X", - fdcnum, fdc201[fdcnum].iopb, PCX); - isbc201_diskio(fdcnum); - if (fdc201[fdcnum].intff) - fdc201[fdcnum].stat |= FDCINT; + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + fdc201.iopb |= (data << 8); + isbc201_diskio(); + if (fdc201.intff) + fdc201.stat |= FDCINT; } - } return 0; } -uint8 isbc2013(t_bool io, uint8 data) +uint8 isbc201r3(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc201_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - if (fdc201[fdcnum].rtype == 0) { - if (DEBUG) - sim_printf("\n isbc201-%d: 0x7B returned rbyte0=%02X PCX=%04X", - fdcnum, fdc201[fdcnum].rbyte0, PCX); - return fdc201[fdcnum].rbyte0; + if (io == 0) { /* read data port */ + if (fdc201.rtype == ROK) { + return fdc201.rbyte0; + } else { + if (fdc201.rdychg) { + return fdc201.rbyte1; } else { - if (fdc201[fdcnum].rdychg) { - if (DEBUG) - sim_printf("\n isbc201-%d: 0x7B returned rbyte1=%02X PCX=%04X", - fdcnum, fdc201[fdcnum].rbyte1, PCX); - return fdc201[fdcnum].rbyte1; - } else { - if (DEBUG) - sim_printf("\n isbc201-%d: 0x7B returned rbytex=%02X PCX=%04X", - fdcnum, 0, PCX); - return 0; - } + return fdc201.rbyte0; } - } else { /* write data port */ - ; //stop diskette operation } + } else { /* write data port */ + ; //stop diskette operation } return 0; } -uint8 isbc2017(t_bool io, uint8 data) +uint8 isbc201r7(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc201_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - isbc201_reset1(fdcnum); - } + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + isbc201_reset1(); } return 0; } // perform the actual disk I/O operation -void isbc201_diskio(uint8 fdcnum) +void isbc201_diskio(void) { uint8 cw, di, nr, ta, sa, bn, data, nrptr; uint16 ba, ni; @@ -562,40 +487,36 @@ void isbc201_diskio(uint8 fdcnum) uint8 *fbuf; //parse the IOPB - cw = multibus_get_mbyte(fdc201[fdcnum].iopb); - di = multibus_get_mbyte(fdc201[fdcnum].iopb + 1); - nr = multibus_get_mbyte(fdc201[fdcnum].iopb + 2); - ta = multibus_get_mbyte(fdc201[fdcnum].iopb + 3); - sa = multibus_get_mbyte(fdc201[fdcnum].iopb + 4); - ba = multibus_get_mword(fdc201[fdcnum].iopb + 5); - bn = multibus_get_mbyte(fdc201[fdcnum].iopb + 7); - ni = multibus_get_mword(fdc201[fdcnum].iopb + 8); - fddnum = (di & 0x30) >> 4; + cw = multibus_get_mbyte(fdc201.iopb); + di = multibus_get_mbyte(fdc201.iopb + 1); + nr = multibus_get_mbyte(fdc201.iopb + 2); + ta = multibus_get_mbyte(fdc201.iopb + 3); + sa = multibus_get_mbyte(fdc201.iopb + 4) & 0x1f; + ba = multibus_get_mbyte(fdc201.iopb + 5); + ba |= (multibus_get_mbyte(fdc201.iopb + 6) << 8); + bn = multibus_get_mbyte(fdc201.iopb + 7); + ni = multibus_get_mbyte(fdc201.iopb + 8); + ni |= (multibus_get_mbyte(fdc201.iopb + 9) << 8); + fddnum = (di & 0x10) >> 4; uptr = isbc201_dev.units + fddnum; fbuf = (uint8 *) (isbc201_dev.units + fddnum)->filebuf; - if (DEBUG) { - sim_printf("\n isbc201-%d: isbc201_diskio IOPB=%04X FDD=%02X STAT=%02X", - fdcnum, fdc201[fdcnum].iopb, fddnum, fdc201[fdcnum].stat); - sim_printf("\n isbc201-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X", - fdcnum, cw, di, nr, ta, sa, ba, bn, ni); - } //check for not ready - switch(fddnum) { + switch(fddnum) { case 0: - if ((fdc201[fdcnum].stat & RDY0) == 0) { - fdc201[fdcnum].rtype = RERR; - fdc201[fdcnum].rbyte0 = RB0NR; - fdc201[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc201-%d: Ready error on drive %d", fdcnum, fddnum); + if ((fdc201.stat & RDY0) == 0) { + fdc201.rtype = ROK; + fdc201.rbyte0 = RB0NR; + fdc201.intff = 1; //set interrupt FF + sim_printf("\n SBC201: FDD %d - Ready error", fddnum); return; } break; case 1: - if ((fdc201[fdcnum].stat & RDY1) == 0) { - fdc201[fdcnum].rtype = RERR; - fdc201[fdcnum].rbyte0 = RB0NR; - fdc201[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc201-%d: Ready error on drive %d", fdcnum, fddnum); + if ((fdc201.stat & RDY1) == 0) { + fdc201.rtype = ROK; + fdc201.rbyte0 = RB0NR; + fdc201.intff = 1; //set interrupt FF + sim_printf("\n SBC201: FDD %d - Ready error", fddnum); return; } break; @@ -608,61 +529,63 @@ void isbc201_diskio(uint8 fdcnum) (sa == 0) || (ta > MAXTRK) )) { - fdc201[fdcnum].rtype = RERR; - fdc201[fdcnum].rbyte0 = RB0ADR; - fdc201[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc201-%d: Address error on drive %d", fdcnum, fddnum); + fdc201.rtype = ROK; + fdc201.rbyte0 = RB0ADR; + fdc201.intff = 1; //set interrupt FF + sim_printf("\n SBC201: FDD %d - Address error at %04X", fddnum, PCX); return; } switch (di & 0x07) { case DNOP: - fdc201[fdcnum].rtype = ROK; - fdc201[fdcnum].intff = 1; //set interrupt FF + fdc201.rtype = ROK; + fdc201.rbyte0 = 0; + fdc201.intff = 1; //set interrupt FF break; case DSEEK: - fdc201[fdcnum].fdd[fddnum].sec = sa; - fdc201[fdcnum].fdd[fddnum].cyl = ta; - fdc201[fdcnum].rtype = ROK; - fdc201[fdcnum].intff = 1; //set interrupt FF + fdc201.fdd[fddnum].sec = sa; + fdc201.fdd[fddnum].cyl = ta; + fdc201.rtype = ROK; + fdc201.rbyte0 = 0; + fdc201.intff = 1; //set interrupt FF break; case DHOME: - fdc201[fdcnum].fdd[fddnum].sec = sa; - fdc201[fdcnum].fdd[fddnum].cyl = 0; - fdc201[fdcnum].rtype = ROK; - fdc201[fdcnum].intff = 1; //set interrupt FF + fdc201.fdd[fddnum].sec = sa; + fdc201.fdd[fddnum].cyl = 0; + fdc201.rtype = ROK; + fdc201.rbyte0 = 0; + fdc201.intff = 1; //set interrupt FF break; case DVCRC: - fdc201[fdcnum].rtype = ROK; - fdc201[fdcnum].intff = 1; //set interrupt FF + fdc201.rtype = ROK; + fdc201.rbyte0 = 0; + fdc201.intff = 1; //set interrupt FF break; case DFMT: //check for WP if(uptr->flags & UNIT_WPMODE) { - fdc201[fdcnum].rtype = RERR; - fdc201[fdcnum].rbyte0 = RB0WP; - fdc201[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc202-%d: Write protect error 1 on drive %d", fdcnum, fddnum); + fdc201.rtype = ROK; + fdc201.rbyte0 = RB0WP; + fdc201.intff = 1; //set interrupt FF + sim_printf("\n SBC201: FDD %d - Write protect error 1", fddnum); return; } fmtb = multibus_get_mbyte(ba); //get the format byte //calculate offset into disk image - dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128; - for(i=0; i<=((uint32)(MAXSECDD) * 128); i++) { + dskoff = ((ta * MAXSECSD) + (sa - 1)) * SECSIZ; + for(i=0; i<=((uint32)(MAXSECSD) * SECSIZ); i++) { *(fbuf + (dskoff + i)) = fmtb; } - fdc201[fdcnum].rtype = ROK; - fdc201[fdcnum].intff = 1; //set interrupt FF + fdc201.rtype = ROK; + fdc201.rbyte0 = 0; + fdc201.intff = 1; //set interrupt FF break; case DREAD: nrptr = 0; while(nrptr < nr) { //calculate offset into disk image - dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128; - if (DEBUG) - sim_printf("\n isbc201-%d: DREAD cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X dskoff=%06X", - fdcnum, cw, di, nr, ta, sa, ba, bn, ni, dskoff); + dskoff = ((ta * MAXSECSD) + (sa - 1)) * SECSIZ; //copy sector from image to RAM - for (i=0; i<128; i++) { + for (i=0; iflags & UNIT_WPMODE) { - fdc201[fdcnum].rtype = RERR; - fdc201[fdcnum].rbyte0 = RB0WP; - fdc201[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc201-%d: Write protect error on drive %d", fdcnum, fddnum); + fdc201.rtype = ROK; + fdc201.rbyte0 = RB0WP; + fdc201.intff = 1; //set interrupt FF + sim_printf("\n SBC201: FDD %d - Write protect error 2", fddnum); return; } nrptr = 0; while(nrptr < nr) { //calculate offset into disk image - dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128; - if (DEBUG) - sim_printf("\n isbc201-%d: DWRITE cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X dskoff=%06X", - fdcnum, cw, di, nr, ta, sa, ba, bn, ni, dskoff); - for (i=0; i<128; i++) { //copy sector from image to RAM + dskoff = ((ta * MAXSECSD) + (sa - 1)) * SECSIZ; + for (i=0; iu5 = isbc202_fdcnum; //fdc device number - uptr->u6 = i; //fdd unit number - uptr->flags |= UNIT_WPMODE; //set WP in unit flags - } - isbc202_reset1(isbc202_fdcnum); //software reset - isbc202_reset1(isbc202_fdcnum); - isbc202_fdcnum++; - } else - sim_printf(" - Not Found\n"); + sim_printf(" sbc202: at base 0%02XH\n", + base); + reg_dev(isbc202r0, base, 0); //read status + reg_dev(isbc202r1, base + 1, 0); //read rslt type/write IOPB addr-l + reg_dev(isbc202r2, base + 2, 0); //write IOPB addr-h and start + reg_dev(isbc202r3, base + 3, 0); //read rstl byte + reg_dev(isbc202r7, base + 7, 0); //write reset fdc201 + // one-time initialization for all FDDs for this FDC instance + for (i = 0; i < FDD_NUM; i++) { + uptr = isbc202_dev.units + i; + uptr->u6 = i; //fdd unit number + } + return SCPE_OK; +} + +/* Hardware reset routine */ + +t_stat isbc202_reset(DEVICE *dptr) +{ + isbc202_reset_dev(); //software reset return SCPE_OK; } /* Software reset routine */ -void isbc202_reset1(uint8 fdcnum) +void isbc202_reset_dev(void) { int32 i; UNIT *uptr; - sim_printf(" isbc202-%d: Software Reset\n", fdcnum); - fdc202[fdcnum].stat = 0; //clear status + fdc202.stat = 0; //clear status for (i = 0; i < FDD_NUM; i++) { /* handle all units */ uptr = isbc202_dev.units + i; - fdc202[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status - fdc202[fdcnum].rtype = ROK; - if (uptr->capac == 0) { /* if not configured */ - sim_printf(" SBC202%d: Configured, Status=%02X Not attached\n", i, fdc202[fdcnum].stat); - } else { + fdc202.stat |= FDCPRE | FDCDD; //set the FDC status + fdc202.rtype = ROK; + fdc202.rbyte0 = 0; //set no error + if (uptr->flags & UNIT_ATT) { /* if attached */ switch(i){ case 0: - fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready - fdc202[fdcnum].rbyte1 |= RB1RD0; + fdc202.stat |= RDY0; //set FDD 0 ready + fdc202.rbyte1 |= RB1RD0; break; case 1: - fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready - fdc202[fdcnum].rbyte1 |= RB1RD1; + fdc202.stat |= RDY1; //set FDD 1 ready + fdc202.rbyte1 |= RB1RD1; break; case 2: - fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready - fdc202[fdcnum].rbyte1 |= RB1RD2; + fdc202.stat |= RDY2; //set FDD 2 ready + fdc202.rbyte1 |= RB1RD2; break; case 3: - fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready - fdc202[fdcnum].rbyte1 |= RB1RD3; + fdc202.stat |= RDY3; //set FDD 3 ready + fdc202.rbyte1 |= RB1RD3; break; } - fdc202[fdcnum].rdychg = 0; - sim_printf(" SBC202%d: Configured, Status=%02X Attached to %s\n", - i, fdc202[fdcnum].stat, uptr->filename); + fdc202.rdychg = 0; } } } -/* isbc202 attach - attach an .IMG file to a FDD */ +/* isbc202 attach - attach an .IMG file to an FDD */ t_stat isbc202_attach (UNIT *uptr, CONST char *cptr) { t_stat r; - uint8 fdcnum, fddnum; + uint8 fddnum; - sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Entered with cptr=%s\n", cptr); -// sim_printf(" isbc202_attach: Entered with cptr=%s\n", cptr); if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - sim_printf(" isbc202_attach: Attach error\n"); + sim_printf(" isbc202_attach: Attach error %d\n", r); return r; } - fdcnum = uptr->u5; fddnum = uptr->u6; switch(fddnum){ case 0: - fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready - fdc202[fdcnum].rbyte1 |= RB1RD0; + fdc202.stat |= RDY0; //set FDD 0 ready + fdc202.rbyte1 |= RB1RD0; break; case 1: - fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready - fdc202[fdcnum].rbyte1 |= RB1RD1; + fdc202.stat |= RDY1; //set FDD 1 ready + fdc202.rbyte1 |= RB1RD1; break; case 2: - fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready - fdc202[fdcnum].rbyte1 |= RB1RD2; + fdc202.stat |= RDY2; //set FDD 2 ready + fdc202.rbyte1 |= RB1RD2; break; case 3: - fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready - fdc202[fdcnum].rbyte1 |= RB1RD3; + fdc202.stat |= RDY3; //set FDD 3 ready + fdc202.rbyte1 |= RB1RD3; break; } - fdc202[fdcnum].rtype = ROK; - sim_printf(" iSBC-202%d: FDD %d Configured %d bytes, Attached to %s\n", - fdcnum, fddnum, uptr->capac, uptr->filename); - sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Done\n"); + fdc202.rtype = ROK; + fdc202.rbyte0 = 0; //set no error return SCPE_OK; } @@ -432,135 +396,88 @@ t_stat isbc202_attach (UNIT *uptr, CONST char *cptr) t_stat isbc202_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { -// sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_set_mode: Entered with val=%08XH uptr->flags=%08X\n", -// val, uptr->flags); + if (uptr->flags & UNIT_ATT) + return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename); if (val & UNIT_WPMODE) { /* write protect */ uptr->flags |= val; } else { /* read write */ uptr->flags &= ~val; } -// sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_set_mode: Done\n"); return SCPE_OK; } -uint8 isbc202_get_dn(void) -{ - int i; - - for (i=0; i= fdc202[i].baseport && port <= fdc202[i].baseport + 7) - return i; - sim_printf("isbc202_get_dn: port %04X not in isbc202 device table\n", port); - return 0xFF; -} - /* iSBC202 control port functions */ -uint8 isbc2020(t_bool io, uint8 data) +uint8 isbc202r0(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc202_get_dn()) != 0xFF) { - if (io == 0) { /* read ststus*/ - if (DEBUG) - sim_printf("\n isbc202-%d: 0x78 returned status=%02X PCX=%04X", - fdcnum, fdc202[fdcnum].stat, PCX); - return fdc202[fdcnum].stat; - } + if (io == 0) { /* read ststus*/ + return fdc202.stat; } return 0; } -uint8 isbc2021(t_bool io, uint8 data) +uint8 isbc202r1(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc202_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - fdc202[fdcnum].intff = 0; //clear interrupt FF - fdc202[fdcnum].stat &= ~FDCINT; - if (DEBUG) - sim_printf("\n isbc202-%d: 0x79 returned rtype=%02X intff=%02X status=%02X PCX=%04X", - fdcnum, fdc202[fdcnum].rtype, fdc202[fdcnum].intff, fdc202[fdcnum].stat, PCX); - return fdc202[fdcnum].rtype; - } else { /* write data port */ - fdc202[fdcnum].iopb = data; - if (DEBUG) - sim_printf("\n isbc202-%d: 0x79 IOPB low=%02X PCX=%04X", - fdcnum, data, PCX); + if (io == 0) { /* read data port */ + fdc202.intff = 0; //clear interrupt FF + fdc202.stat &= ~FDCINT; + if (fdc202.rdychg) { + fdc202.rtype = ROK; + return fdc202.rtype; + } else { + fdc202.rtype = ROK; + return fdc202.rtype; } + } else { /* write data port */ + fdc202.iopb = data; } return 0; } -uint8 isbc2022(t_bool io, uint8 data) +uint8 isbc202r2(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc202_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - fdc202[fdcnum].iopb |= (data << 8); - if (DEBUG) - sim_printf("\n isbc202-%d: 0x7A IOPB=%04X PCX=%04X", - fdcnum, fdc202[fdcnum].iopb, PCX); - isbc202_diskio(fdcnum); - if (fdc202[fdcnum].intff) - fdc202[fdcnum].stat |= FDCINT; - } + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + fdc202.iopb |= (data << 8); + isbc202_diskio(); + if (fdc202.intff) + fdc202.stat |= FDCINT; } return 0; } -uint8 isbc2023(t_bool io, uint8 data) +uint8 isbc202r3(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc202_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - if (fdc202[fdcnum].rtype == 0) { - if (DEBUG) - sim_printf("\n isbc202-%d: 0x7B returned rbyte0=%02X PCX=%04X", - fdcnum, fdc202[fdcnum].rbyte0, PCX); - return fdc202[fdcnum].rbyte0; + if (io == 0) { /* read data port */ + if (fdc202.rtype == ROK) { + return fdc202.rbyte0; + } else { + if (fdc202.rdychg) { + return fdc202.rbyte1; } else { - if (fdc202[fdcnum].rdychg) { - if (DEBUG) - sim_printf("\n isbc202-%d: 0x7B returned rbyte1=%02X PCX=%04X", - fdcnum, fdc202[fdcnum].rbyte1, PCX); - return fdc202[fdcnum].rbyte1; - } else { - if (DEBUG) - sim_printf("\n isbc202-%d: 0x7B returned rbytex=%02X PCX=%04X", - fdcnum, 0, PCX); - return 0; - } + return fdc202.rbyte0; } - } else { /* write data port */ - ; //stop diskette operation } + } else { /* write data port */ + ; //stop diskette operation } return 0; } -uint8 isbc2027(t_bool io, uint8 data) +uint8 isbc202r7(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = isbc202_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - isbc202_reset1(fdcnum); - } + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + isbc202_reset_dev(); } return 0; } // perform the actual disk I/O operation -void isbc202_diskio(uint8 fdcnum) +void isbc202_diskio(void) { uint8 cw, di, nr, ta, sa, data, nrptr; uint16 ba; @@ -571,56 +488,51 @@ void isbc202_diskio(uint8 fdcnum) uint8 *fbuf; //parse the IOPB - cw = multibus_get_mbyte(fdc202[fdcnum].iopb); - di = multibus_get_mbyte(fdc202[fdcnum].iopb + 1); - nr = multibus_get_mbyte(fdc202[fdcnum].iopb + 2); - ta = multibus_get_mbyte(fdc202[fdcnum].iopb + 3); - sa = multibus_get_mbyte(fdc202[fdcnum].iopb + 4); - ba = multibus_get_mword(fdc202[fdcnum].iopb + 5); + cw = multibus_get_mbyte(fdc202.iopb); + di = multibus_get_mbyte(fdc202.iopb + 1); + nr = multibus_get_mbyte(fdc202.iopb + 2); + ta = multibus_get_mbyte(fdc202.iopb + 3); + sa = multibus_get_mbyte(fdc202.iopb + 4); + ba = multibus_get_mbyte(fdc202.iopb + 5); + ba |= (multibus_get_mbyte(fdc202.iopb + 6) << 8); fddnum = (di & 0x30) >> 4; uptr = isbc202_dev.units + fddnum; - fbuf = (uint8 *) (isbc202_dev.units + fddnum)->filebuf; - if (DEBUG) { - sim_printf("\n isbc202-%d: isbc202_diskio IOPB=%04X FDD=%02X STAT=%02X", - fdcnum, fdc202[fdcnum].iopb, fddnum, fdc202[fdcnum].stat); - sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X", - fdcnum, cw, di, nr, ta, sa, ba); - } + fbuf = (uint8 *) uptr->filebuf; //check for not ready switch(fddnum) { case 0: - if ((fdc202[fdcnum].stat & RDY0) == 0) { - fdc202[fdcnum].rtype = RERR; - fdc202[fdcnum].rbyte0 = RB0NR; - fdc202[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum); + if ((fdc202.stat & RDY0) == 0) { + fdc202.rtype = ROK; + fdc202.rbyte0 = RB0NR; + fdc202.intff = 1; //set interrupt FF + sim_printf("\n SBC202: FDD %d - Ready error", fddnum); return; } break; case 1: - if ((fdc202[fdcnum].stat & RDY1) == 0) { - fdc202[fdcnum].rtype = RERR; - fdc202[fdcnum].rbyte0 = RB0NR; - fdc202[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum); + if ((fdc202.stat & RDY1) == 0) { + fdc202.rtype = ROK; + fdc202.rbyte0 = RB0NR; + fdc202.intff = 1; //set interrupt FF + sim_printf("\n SBC202: FDD %d - Ready error", fddnum); return; } break; case 2: - if ((fdc202[fdcnum].stat & RDY2) == 0) { - fdc202[fdcnum].rtype = RERR; - fdc202[fdcnum].rbyte0 = RB0NR; - fdc202[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum); + if ((fdc202.stat & RDY2) == 0) { + fdc202.rtype = ROK; + fdc202.rbyte0 = RB0NR; + fdc202.intff = 1; //set interrupt FF + sim_printf("\n SBC202: FDD %d - Ready error", fddnum); return; } break; case 3: - if ((fdc202[fdcnum].stat & RDY3) == 0) { - fdc202[fdcnum].rtype = RERR; - fdc202[fdcnum].rbyte0 = RB0NR; - fdc202[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum); + if ((fdc202.stat & RDY3) == 0) { + fdc202.rtype = ROK; + fdc202.rbyte0 = RB0NR; + fdc202.intff = 1; //set interrupt FF + sim_printf("\n SBC202: FDD %d - Ready error", fddnum); return; } break; @@ -633,61 +545,64 @@ void isbc202_diskio(uint8 fdcnum) (sa == 0) || (ta > MAXTRK) )) { - fdc202[fdcnum].rtype = RERR; - fdc202[fdcnum].rbyte0 = RB0ADR; - fdc202[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc202-%d: Address error on drive %d", fdcnum, fddnum); - return; + fdc202.rtype = ROK; + fdc202.rbyte0 = RB0ADR; + fdc202.intff = 1; //set interrupt FF + sim_printf("\n SBC202: FDD %d - Address error sa=%02X nr=%02X ta=%02X PCX=%04X", + fddnum, sa, nr, ta, PCX); + return; } switch (di & 0x07) { case DNOP: - fdc202[fdcnum].rtype = ROK; - fdc202[fdcnum].intff = 1; //set interrupt FF + fdc202.rtype = ROK; + fdc202.rbyte0 = 0; //set no error + fdc202.intff = 1; //set interrupt FF break; case DSEEK: - fdc202[fdcnum].fdd[fddnum].sec = sa; - fdc202[fdcnum].fdd[fddnum].cyl = ta; - fdc202[fdcnum].rtype = ROK; - fdc202[fdcnum].intff = 1; //set interrupt FF + fdc202.fdd[fddnum].sec = sa; + fdc202.fdd[fddnum].cyl = ta; + fdc202.rtype = ROK; + fdc202.rbyte0 = 0; //set no error + fdc202.intff = 1; //set interrupt FF break; case DHOME: - fdc202[fdcnum].fdd[fddnum].sec = sa; - fdc202[fdcnum].fdd[fddnum].cyl = 0; - fdc202[fdcnum].rtype = ROK; - fdc202[fdcnum].intff = 1; //set interrupt FF + fdc202.fdd[fddnum].sec = sa; + fdc202.fdd[fddnum].cyl = 0; + fdc202.rtype = ROK; + fdc202.rbyte0 = 0; //set no error + fdc202.intff = 1; //set interrupt FF break; case DVCRC: - fdc202[fdcnum].rtype = ROK; - fdc202[fdcnum].intff = 1; //set interrupt FF + fdc202.rtype = ROK; + fdc202.rbyte0 = 0; //set no error + fdc202.intff = 1; //set interrupt FF break; case DFMT: //check for WP if(uptr->flags & UNIT_WPMODE) { - fdc202[fdcnum].rtype = RERR; - fdc202[fdcnum].rbyte0 = RB0WP; - fdc202[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc202-%d: Write protect error 1 on drive %d", fdcnum, fddnum); + fdc202.rtype = ROK; + fdc202.rbyte0 = RB0WP; + fdc202.intff = 1; //set interrupt FF + sim_printf("\n SBC202: FDD %d - Write protect error DFMT", fddnum); return; } fmtb = multibus_get_mbyte(ba); //get the format byte //calculate offset into disk image - dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128; - for(i=0; i<=((uint32)(MAXSECDD) * 128); i++) { + dskoff = ((ta * MAXSECDD) + (sa - 1)) * SECSIZ; + for(i=0; i<=((uint32)(MAXSECDD) * SECSIZ); i++) { *(fbuf + (dskoff + i)) = fmtb; } - fdc202[fdcnum].rtype = ROK; - fdc202[fdcnum].intff = 1; //set interrupt FF + fdc202.rtype = ROK; + fdc202.rbyte0 = 0; //set no error + fdc202.intff = 1; //set interrupt FF break; case DREAD: nrptr = 0; while(nrptr < nr) { //calculate offset into disk image - dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128; - if (DEBUG) - sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X", - fdcnum, cw, di, nr, ta, sa, ba, dskoff); - //copy sector from image to RAM - for (i=0; i<128; i++) { + dskoff = ((ta * MAXSECDD) + (sa - 1)) * SECSIZ; + //copy sector from disk image to RAM + for (i=0; iflags & UNIT_WPMODE) { - fdc202[fdcnum].rtype = RERR; - fdc202[fdcnum].rbyte0 = RB0WP; - fdc202[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n isbc202-%d: Write protect error 2 on drive %d", fdcnum, fddnum); + fdc202.rtype = ROK; + fdc202.rbyte0 = RB0WP; + fdc202.intff = 1; //set interrupt FF + sim_printf("\n SBC202: FDD %d - Write protect error DWRITE", fddnum); return; } nrptr = 0; while(nrptr < nr) { //calculate offset into disk image - dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128; - if (DEBUG) - sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X", - fdcnum, cw, di, nr, ta, sa, ba, dskoff); - for (i=0; i<128; i++) { //copy sector from image to RAM + dskoff = ((ta * MAXSECDD) + (sa - 1)) * SECSIZ; + //copy sector from RAM to disk image + for (i=0; iu6 = i; //fdd unit number + } + return SCPE_OK; +} + +/* Hardware reset routine */ + +t_stat isbc206_reset(DEVICE *dptr) +{ + isbc206_reset1(); //software reset + return SCPE_OK; +} + +/* Software reset routine */ + +void isbc206_reset1(void) +{ + int32 i; + UNIT *uptr; + + hdc206.stat = 0; //clear status + for (i = 0; i < HD_NUM; i++) { /* handle all units */ + uptr = isbc206_dev.units + i; + hdc206.stat |= (HDCPRE + 0x80); //set the HDC status + hdc206.rtype = ROK; + hdc206.rbyte0 = 0; //set no error + if (uptr->flags & UNIT_ATT) { /* if attached */ + switch(i){ + case 0: + hdc206.stat |= RDY0; //set HDD 0 ready + hdc206.rbyte1 |= RB1RD0; + break; + case 1: + hdc206.stat |= RDY1; //set HDD 1 ready + hdc206.rbyte1 |= RB1RD1; + break; + } + hdc206.rdychg = 0; + } + } +} + +/* isbc206 attach - attach an .IMG file to a HDD */ + +t_stat isbc206_attach (UNIT *uptr, CONST char *cptr) +{ + t_stat r; + uint8 hddnum; + + if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { + sim_printf(" isbc206_attach: Attach error %d\n", r); + return r; + } + hddnum = uptr->u6; + switch(hddnum){ + case 0: + hdc206.stat |= RDY0; //set HDD 0 ready + hdc206.rbyte1 |= RB1RD0; + break; + case 1: + hdc206.stat |= RDY1; //set HDD 1 ready + hdc206.rbyte1 |= RB1RD1; + break; + } + hdc206.rtype = ROK; + hdc206.rbyte0 = 0; //set no error + return SCPE_OK; +} + +/* isbc206 set mode = Write protect */ + +t_stat isbc206_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + if (uptr->flags & UNIT_ATT) + return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename); + if (val & UNIT_WPMODE) { /* write protect */ + uptr->flags |= val; + } else { /* read write */ + uptr->flags &= ~val; + } + return SCPE_OK; +} + +/* iSBC206 control port functions */ + +uint8 isbc206r0(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read status*/ + return hdc206.stat; + } + return 0; +} + +uint8 isbc206r1(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read data port */ + hdc206.intff = 0; //clear interrupt FF + hdc206.stat &= ~(HDCINT + 0x80); + if (hdc206.rdychg) { + hdc206.rtype = ROK; + return hdc206.rtype; + } else { + hdc206.rtype = ROK; + return hdc206.rtype; + } + } else { /* write data port */ + hdc206.iopb = data; + } + return 0; +} + +uint8 isbc206r2(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + hdc206.iopb |= (data << 8); + isbc206_diskio(); + if (hdc206.intff) + hdc206.stat |= HDCINT; + } + return 0; +} + +uint8 isbc206r3(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read data port */ + if (hdc206.rtype == ROK) { + return hdc206.rbyte0; + } else { + if (hdc206.rdychg) { + return hdc206.rbyte1; + } else { + return hdc206.rbyte0; + } + } + } else { /* write data port */ + ; //stop diskette operation + } + return 0; +} + + +uint8 isbc206r7(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + isbc206_reset1(); + } + return 0; +} + +// perform the actual disk I/O operation + +void isbc206_diskio(void) +{ + uint8 cw, di, nr, ta, sa, data, nrptr; + uint16 ba; + uint32 dskoff; + uint8 hddnum, fmtb; + uint32 i; + UNIT *uptr; + uint8 *fbuf; + + //parse the IOPB + cw = multibus_get_mbyte(hdc206.iopb); + di = multibus_get_mbyte(hdc206.iopb + 1); + nr = multibus_get_mbyte(hdc206.iopb + 2); + ta = multibus_get_mbyte(hdc206.iopb + 3); + sa = multibus_get_mbyte(hdc206.iopb + 4); + ba = multibus_get_mbyte(hdc206.iopb + 5); + hddnum = (di & 0x30) >> 4; + uptr = isbc206_dev.units + hddnum; + fbuf = (uint8 *) (isbc206_dev.units + hddnum)->filebuf; + //check for not ready + switch(hddnum) { + case 0: + if ((hdc206.stat & RDY0) == 0) { + hdc206.rtype = ROK; + hdc206.rbyte0 = RB0NR; + hdc206.intff = 1; //set interrupt FF + sim_printf("\n SBC206: HDD %d - Ready error", hddnum); + return; + } + break; + case 1: + if ((hdc206.stat & RDY1) == 0) { + hdc206.rtype = ROK; + hdc206.rbyte0 = RB0NR; + hdc206.intff = 1; //set interrupt FF + sim_printf("\n SBC206: HDD %d - Ready error", hddnum); + return; + } + break; + } + //check for address error + if ( + ((di & 0x07) != DHOME) && ( + (sa > MAXSECHD) || + ((sa + nr) > (MAXSECHD + 1)) || + (sa == 0) || + (ta > MAXTRKHD) + )) { + hdc206.rtype = ROK; + hdc206.rbyte0 = RB0ADR; + hdc206.intff = 1; //set interrupt FF + sim_printf("\n SBC206: FDD %d - Address error sa=%02X nr=%02X ta=%02X PCX=%04X", + hddnum, sa, nr, ta, PCX); + return; + } + switch (di & 0x07) { + case DNOP: + hdc206.rtype = ROK; + hdc206.rbyte0 = 0; //set no error + hdc206.intff = 1; //set interrupt FF + break; + case DSEEK: + hdc206.hd[hddnum].sec = sa; + hdc206.hd[hddnum].cyl = ta; + hdc206.rtype = ROK; + hdc206.rbyte0 = 0; //set no error + hdc206.intff = 1; //set interrupt FF + break; + case DHOME: + hdc206.hd[hddnum].sec = sa; + hdc206.hd[hddnum].cyl = 0; + hdc206.rtype = ROK; + hdc206.rbyte0 = 0; //set no error + hdc206.intff = 1; //set interrupt FF + break; + case DVCRC: + hdc206.rtype = ROK; + hdc206.rbyte0 = 0; //set no error + hdc206.intff = 1; //set interrupt FF + break; + case DFMT: + //check for WP + if(uptr->flags & UNIT_WPMODE) { + hdc206.rtype = ROK; + hdc206.rbyte0 = RB0WP; + hdc206.intff = 1; //set interrupt FF + sim_printf("\n SBC206: HDD %d - Write protect error DFMT", hddnum); + return; + } + fmtb = multibus_get_mbyte(ba); //get the format byte + //calculate offset into disk image + dskoff = ((ta * MAXSECHD) + (sa - 1)) * 128; + for(i=0; i<=((uint32)(MAXSECHD) * 128); i++) { + *(fbuf + (dskoff + i)) = fmtb; + } + hdc206.rtype = ROK; + hdc206.rbyte0 = 0; //set no error + hdc206.intff = 1; //set interrupt FF + break; + case DREAD: + nrptr = 0; + while(nrptr < nr) { + //calculate offset into disk image + dskoff = ((ta * MAXSECHD) + (sa - 1)) * 128; + //copy sector from image to RAM + for (i=0; i<128; i++) { + data = *(fbuf + (dskoff + i)); + multibus_put_mbyte(ba + i, data); + } + sa++; + ba+=0x80; + nrptr++; + } + hdc206.rtype = ROK; + hdc206.rbyte0 = 0; //set no error + hdc206.intff = 1; //set interrupt FF + break; + case DWRITE: + //check for WP + if(uptr->flags & UNIT_WPMODE) { + hdc206.rtype = ROK; + hdc206.rbyte0 = RB0WP; + hdc206.intff = 1; //set interrupt FF + sim_printf("\n SBC206: HDD %d - Write protect error DWRITE", hddnum); + return; + } + nrptr = 0; + while(nrptr < nr) { + //calculate offset into disk image + dskoff = ((ta * MAXSECHD) + (sa - 1)) * 128; + //copy sector from image to RAM + for (i=0; i<128; i++) { + data = multibus_get_mbyte(ba + i); + *(fbuf + (dskoff + i)) = data; + } + sa++; + ba+=0x80; + nrptr++; + } + hdc206.rtype = ROK; + hdc206.rbyte0 = 0; //set no error + hdc206.intff = 1; //set interrupt FF + break; + default: + sim_printf("\n SBC206: HDD %d - isbc206_diskio bad di=%02X", hddnum, di & 0x07); + break; + } +} + +/* end of isbc206.c */ diff --git a/Intel-Systems/common/isbc208.c b/Intel-Systems/common/isbc208.c index 6f8c9fa9..cd803bc9 100644 --- a/Intel-Systems/common/isbc208.c +++ b/Intel-Systems/common/isbc208.c @@ -1,1035 +1,741 @@ -/* isbc208.c: Intel iSBC208 Floppy Disk adapter - - Copyright (c) 2011, William A. Beech - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of William A. Beech shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from William A. Beech. - - MODIFICATIONS: - - ?? ??? 11 - Original file. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - These functions support a simulated iSBC208 interface to 4 each 8-, 5 1/4-, or - 3 1/2-inch floppy disk drives. Commands are setup with programmed I/O to the - simulated ports of an i8237 DMA controller and an i8272 FDC. Data transfer - to/from the simulated disks is performed directly with the multibus memory. - - The iSBC-208 can be configured for 8- or 16-bit addresses. It defaults to 8-bit - addresses for the 8080/8085 processors. It can be configured for I/O port - addresses with 3-bits (8-bit address) or 11-bits (16-bit address). Default is - 3-bits set to 0. This defines the port offset to be used to determine the actual - port address. Bus priority can be configured for parallel or serial mode. Default is - serial. The multibus interface interrupt can be configured for interrupt 0-7. - Default is none. Since all channel registers in the i8237 are 16-bit, transfers - are done as two 8-bit operations, low- then high-byte. - - Port addressing is as follows (Port offset = 0): - - Port Mode Command Function - - 00 Write Load DMAC Channel 0 Base and Current Address Regsiters - Read Read DMAC Channel 0 Current Address Register - 01 Write Load DMAC Channel 0 Base and Current Word Count Registers - Read Read DMAC Channel 0 Current Word Count Register - 04 Write Load DMAC Channel 2 Base and Current Address Regsiters - Read Read DMAC Channel 2 Current Address Register - 05 Write Load DMAC Channel 2 Base and Current Word Count Registers - Read Read DMAC Channel 2 Current Word Count Register - 06 Write Load DMAC Channel 3 Base and Current Address Regsiters - Read Read DMAC Channel 3 Current Address Register - 07 Write Load DMAC Channel 3 Base and Current Word Count Registers - Read Read DMAC Channel 3 Current Word Count Register - 08 Write Load DMAC Command Register - Read Read DMAC Status Register - 09 Write Load DMAC Request Register - OA Write Set/Reset DMAC Mask Register - OB Write Load DMAC Mode Register - OC Write Clear DMAC First/Last Flip-Flop - 0D Write DMAC Master Clear - OF Write Load DMAC Mask Register - 10 Read Read FDC Status Register - 11 Write Load FDC Data Register - Read Read FDC Data Register - 12 Write Load Controller Auxiliary Port - Read Poll Interrupt Status - 13 Write Controller Reset - 14 Write Load Controller Low-Byte Segment Address Register - 15 Write Load Controller High-Byte Segment Address Register - 20-2F Read/Write Reserved for iSBX Multimodule Board - - Register usage is defined in the following paragraphs. - - Read/Write DMAC Address Registers - - Used to simultaneously load a channel's current-address register and base-address - register with the memory address of the first byte to be transferred. (The Channel - 0 current/base address register must be loaded prior to initiating a diskette read - or write operation.) Since each channel's address registers are 16 bits in length - (64K address range), two "write address register" commands must be executed in - order to load the complete current/base address registers for any channel. - - Read/Write DMAC Word Count Registers - - The Write DMAC Word Count Register command is used to simultaneously load a - channel's current and base word-count registers with the number of bytes - to be transferred during a subsequent DMA operation. Since the word-count - registers are 16-bits in length, two commands must be executed to load both - halves of the registers. - - Write DMAC Command Register - - The Write DMAC Command Register command loads an 8-bit byte into the - DMAC's command register to define the operating characteristics of the - DMAC. The functions of the individual bits in the command register are - defined in the following diagram. Note that only two bits within the - register are applicable to the controller; the remaining bits select - functions that are not supported and, accordingly, must always be set - to zero. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | 0 0 0 0 0 0 | - +---+---+---+---+---+---+---+---+ - | | - | +---------- 0 CONTROLLER ENABLE - | 1 CONTROLLER DISABLE - | - +------------------ 0 FIXED PRIORITY - 1 ROTATING PRIORITY - - Read DMAC Status Register Command - - The Read DMAC Status Register command accesses an 8-bit status byte that - identifies the DMA channels that have reached terminal count or that - have a pending DMA request. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | 0 0 | - +---+---+---+---+---+---+---+---+ - | | | | | | - | | | | | +-- CHANNEL 0 TC - | | | | +---------- CHANNEL 2 TC - | | | +-------------- CHANNEL 3 TC - | | +------------------ CHANNEL 0 DMA REQUEST - | +-------------------------- CHANNEL 2 DMA REQUEST - +------------------------------ CHANNEL 3 DMA REQUEST - - Write DMAC Request Register - - The data byte associated with the Write DMAC Request Register command - sets or resets a channel's associated request bit within the DMAC's - internal 4-bit request register. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | X X X X X | - +---+---+---+---+---+---+---+---+ - | | | - | +---+-- 00 SELECT CHANNEL 0 - | 01 SELECT CHANNEL 1 - | 10 SELECT CHANNEL 2 - | 11 SELECT CHANNEL 3 - | - +---------- 0 RESET REQUEST BIT - 1 SET REQUEST BIT - - Set/Reset DMAC Mask Register - - Prior to a DREQ-initiated DMA transfer, the channel's mask bit must - be reset to enable recognition of the DREQ input. When the transfer - is complete (terminal count reached or external EOP applied) and - the channel is not programmed to autoinitialize, the channel's - mask bit is automatically set (disabling DREQ) and must be reset - prior to a subsequent DMA transfer. All four bits of the mask - register are set (disabling the DREQ inputs) by a DMAC master - clear or controller reset. Additionally, all four bits can be - set/reset by a single Write DMAC Mask Register command. - - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | X X X X X | - +---+---+---+---+---+---+---+---+ - | | | - | +---+-- 00 SELECT CHANNEL 0 - | 01 SELECT CHANNEL 1 - | 10 SELECT CHANNEL 2 - | 11 SELECT CHANNEL 3 - | - +---------- 0 RESET REQUEST BIT - 1 SET REQUEST BIT - - Write DMAC Mode Register - - The Write DMAC Mode Register command is used to define the - operating mode characteristics for each DMA channel. Each - channel has an internal 6-bit mode register; the high-order - six bits of the associated data byte are written into the - mode register addressed by the two low-order bits. - - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | | - +---+---+---+---+---+---+---+---+ - | | | | | | | | - | | | | | | +---+-- 00 SELECT CHANNEL 0 - | | | | | | 01 SELECT CHANNEL 1 - | | | | | | 10 SELECT CHANNEL 2 - | | | | | | 11 SELECT CHANNEL 3 - | | | | | | - | | | | +---+---------- 00 VERIFY TRANSFER - | | | | 01 WRITE TRANSFER - | | | | 10 READ TRANSFER - | | | | - | | | +------------------ 0 AUTOINITIALIZE DISABLE - | | | 1 AUTOINITIALIZE ENABLE - | | | - | | +---------------------- 0 ADDRESS INCREMENT - | | 1 ADDRESS DECREMENT - | | - +---+-------------------------- 00 DEMAND MODE - 01 SINGLE MODE - 10 BLOCK MODE - - Clear DMAC First/Last Flip-Flop - - The Clear DMAC First/Last Flip-Flop command initializes - the DMAC's internal first/last flip-flop so that the - next byte written to or re~d from the 16-bit address - or word-count registers is the low-order byte. The - flip-flop is toggled with each register access so that - a second register read or write command accesses the - high-order byte. - - DMAC Master Clear - - The DMAC Master Clear command clears the DMAC's command, status, - request, and temporary registers to zero, initializes the - first/last flip-flop, and sets the four channel mask bits in - the mask register to disable all DMA requests (i.e., the DMAC - is placed in an idle state). - - Write DMAC Mask Register - - The Write DMAC Mask Register command allows all four bits of the - DMAC's mask register to be written with a single command. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | X X X X X | - +---+---+---+---+---+---+---+---+ - | | | - | | +-- 0 CLEAR CHANNEL 0 MASK BIT - | | 1 SET CHANNEL 0 MASK BIT - | | - | +---------- 0 CLEAR CHANNEL 2 MASK BIT - | 1 SET CHANNEL 2 MASK BIT - | - +-------------- 0 CLEAR CHANNEL 3 MASK BIT - 1 SET CHANNEL 3 MASK BIT - - Read FDC Status Register - - The Read FDC Status Register command accesses the FDC's main - status register. The individual status register bits are as - follows: - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | | - +---+---+---+---+---+---+---+---+ - | | | | | | | | - | | | | | | | +-- FDD 0 BUSY - | | | | | | +------ FDD 1 BUSY - | | | | | +---------- FDD 2 BUSY - | | | | +-------------- FDD 3 BUSY - | | | +------------------ FDC BUSY - | | +---------------------- NON-DMA MODE - | +-------------------------- DATA INPUT/OUTPUT - +------------------------------ REQUEST FOR MASTER - - Read/Write FDC Data Register - - The Read and Write FDC Data Register commands are used to write - command and parameter bytes to the FDC in order to specify the - operation to be performed (referred to as the "command phase") - and to read status bytes from the FDC following the operation - (referred to as the "result phase"). During the command and - result phases, the 8-bit data register is actually a series of - 8-bit registers in a stack. Each register is accessed in - sequence; the number of registers accessed and the individual - register contents are defined by the specific disk command. - - Write Controller Auxiliary Port - - The Write Controller Auxiliary Port command is used to set or - clear individual bits within the controller's auxiliary port. - The four low-order port bits are dedicated to auxiliary drive - control functions (jumper links are required to connect the - desired port bit to an available pin on the drive interface - connectors). The most common application for these bits is - the "Motor-On" control function for mini-sized drives. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | | - +---+---+---+---+---+---+---+---+ - | | | | | | | | - | | | | +---+---+---+-- DRIVE CONTROL - | | | +------------------ ADDR 20 - | | +---------------------- ADDR 21 - | +-------------------------- ADDR 22 - +------------------------------ ADDR 23 - - Poll Interrupt Status - - The Poll Interrupt Status command presents the interrupt - status of the controller and the two interrupt status - lines dedicated to the iSBX Multimodule board. - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | X X X X X | - +---+---+---+---+---+---+---+---+ - | | | - | | +-- CONTROLLER INTERRUPT - | +------ MULTIMODULE BOARD INTERRUPT 0 - +---------- MULTIMODULE BOARD INTERRUPT 1 - - Controller Reset - - The Controller Reset command is the software reset for the - controller. This command clears the controller's auxiliary - port and segment address register, provides a reset signal - to the iSBX Multimodule board and initializes the bus - controller (releases the bus), the DMAC (clears the internal - registers and masks the DREQ inputs), and the FDC (places - the FDC in an idle state and disables the output control - lines to the diskette drive). - - Write Controller Low- And High-Byte Segment Address Registers - - The Write Controller Low- and High-Byte Address Registers - commands are required when the controller uses 20-bit - addressing (memory address range from 0 to OFFFFFH). These - commands are issued prior to initiating a diskette read or - write operation to specify the 16-bit segment address. - - FDC Commands - - The 8272/D765 is capable of performing 15 different - commands. Each command is initiated by a multibyte transfer - from the processor, and the result after execution of the - command may also be a multibyte transfer back to the processor. - Because of this multibyte interchange of information between - the FDC and the processor, it is convenient to consider each - command as consisting of three phases: - - Command Phase: The FDC receives all information required to - perform a particular operation from the processor. - - Execution Phase: The FDC performs the operation it was - instructed to do. - - Result Phase: After completion of the operation, status - and other housekeeping information are made available - to the processor. - - Not all the FDC commands are supported by this emulation. Only the subset - of commands required to build an operable CP/M BIOS are supported. They are: - - Read - Read specified data from the selected FDD. - - Write - Write specified data to the selected FDD. - - Seek - Move the R/W head to the specified cylinder on the specified FDD. - - Specify - Set the characteristics for all the FDDs. - - Sense Interrupt - Sense change in FDD Ready line or and of Seek/Recalibrate - command. - - Sense Drive - Returns status of all the FDDs. - - Recalibrate - Move the R/W head to cylinder 0 on the specified FDD. - - Format Track - Format the current track on the specified FDD. - - Read ID - Reads the first address mark it finds. - - Simulated Floppy Disk Drives - - The units in this device simulate an 8- or 5 1/4- or 3 1/2 inch drives. The - drives can emulate SSSD, SSDD, and DSDD. Drives can be attached to files up - to 1.44MB in size. Drive configuration is selected when a disk is logged onto - the system. An identity sector or identity byte contains information to - configure the OS drivers for the type of drive to emulate. - - uptr->u3 - - uptr->u4 - - uptr->u5 - - uptr->u6 - unit number (0-FDD_NUM) -*/ - -#include "system_defs.h" - -#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ -#define UNIT_WPMODE (1 << UNIT_V_WPMODE) - -/* master status register definitions */ - -#define RQM 0x80 /* Request for master */ -#define DIO 0x40 /* Data I/O Direction 0=W, 1=R */ -#define NDM 0x20 /* Non-DMA mode */ -#define CB 0x10 /* FDC busy */ -#define D3B 0x08 /* FDD 3 busy */` -#define D2B 0x04 /* FDD 2 busy */` -#define D1B 0x02 /* FDD 1 busy */` -#define D0B 0x01 /* FDD 0 busy */` - -/* status register 0 definitions */ - -#define IC 0xC0 /* Interrupt code */ -#define IC_NORM 0x00 /* normal completion */ -#define IC_ABNORM 0x40 /* abnormal completion */ -#define IC_INVC 0x80 /* invalid command */ -#define IC_RC 0xC0 /* drive not ready */ -#define SE 0x20 /* Seek end */ -#define EC 0x10 /* Equipment check */ -#define NR 0x08 /* Not ready */ -#define HD 0x04 /* Head selected */ -#define US 0x03 /* Unit selected */ -#define US_0 0x00 /* Unit 0 */ -#define US_1 0x01 /* Unit 1 */ -#define US_2 0x02 /* Unit 2 */ -#define US_3 0x03 /* Unit 3 */ - -/* status register 1 definitions */ - -#define EN 0x80 /* End of cylinder */ -#define DE 0x20 /* Data error */ -#define OR 0x10 /* Overrun */ -#define ND 0x04 /* No data */ -#define NW 0x02 /* Not writable */ -#define MA 0x01 /* Missing address mark */ - -/* status register 2 definitions */ - -#define CM 0x40 /* Control mark */ -#define DD 0x20 /* Data error in data field */ -#define WC 0x10 /* Wrong cylinder */ -#define BC 0x02 /* Bad cylinder */ -#define MD 0x01 /* Missing address mark in data field */ - -/* status register 3/fddst definitions */ - -#define FT 0x80 /* Fault */ -#define WP 0x40 /* Write protect */ -#define RDY 0x20 /* Ready */ -#define T0 0x10 /* Track 0 */ -#define TS 0x08 /* Two sided */ -//#define HD 0x04 /* Head selected */ -//#define US 0x03 /* Unit selected */ - -/* FDC command definitions */ - -#define READTRK 0x02 -#define SPEC 0x03 -#define SENDRV 0x04 -#define WRITE 0x05 -#define READ 0x06 -#define HOME 0x07 -#define SENINT 0x08 -#define WRITEDEL 0x09 -#define READID 0x0A -#define READDEL 0x0C -#define FMTTRK 0x0D -#define SEEK 0x0F -#define SCANEQ 0x11 -#define SCANLOEQ 0x19 -#define SCANHIEQ 0x1D - -#define FDD_NUM 4 - -int32 sbc208_devnum = 0; //actual number of 8255 instances + 1 -uint16 sbc208_port[4]; //base port registered to each instance - -/* internal function prototypes */ - -t_stat isbc208_svc (UNIT *uptr); -t_stat isbc208_reset (DEVICE *dptr, uint16 base); -void isbc208_reset1 (void); -t_stat isbc208_attach (UNIT *uptr, CONST char *cptr); -t_stat isbc208_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -uint8 isbc208_r0(t_bool io, uint8 data); -uint8 isbc208_r1(t_bool io, uint8 data); -uint8 isbc208_r2(t_bool io, uint8 data); -uint8 isbc208_r3(t_bool io, uint8 data); -uint8 isbc208_r4(t_bool io, uint8 data); -uint8 isbc208_r5(t_bool io, uint8 data); -uint8 isbc208_r6(t_bool io, uint8 data); -uint8 isbc208_r7(t_bool io, uint8 data); -uint8 isbc208_r8(t_bool io, uint8 data); -uint8 isbc208_r9(t_bool io, uint8 data); -uint8 isbc208_rA(t_bool io, uint8 data); -uint8 isbc208_rB(t_bool io, uint8 data); -uint8 isbc208_rC(t_bool io, uint8 data); -uint8 isbc208_rD(t_bool io, uint8 data); -uint8 isbc208_rE(t_bool io, uint8 data); -uint8 isbc208_rF(t_bool io, uint8 data); -uint8 isbc208_r10(t_bool io, uint8 data); -uint8 isbc208_r11(t_bool io, uint8 data); -uint8 isbc208_r12(t_bool io, uint8 data); -uint8 isbc208_r13(t_bool io, uint8 data); -uint8 isbc208_r14(t_bool io, uint8 data); -uint8 isbc208_r15(t_bool io, uint8 data); - -/* external function prototypes */ - -extern void set_irq(int32 int_num); -extern void clr_irq(int32 int_num); -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); -extern void multibus_put_mbyte(uint16 addr, uint8 val); -extern uint8 multibus_get_mbyte(uint16 addr); - -/* 8237 physical register definitions */ - -uint16 i8237_r0; // 8237 ch 0 address register -uint16 i8237_r1; // 8237 ch 0 count register -uint16 i8237_r2; // 8237 ch 1 address register -uint16 i8237_r3; // 8237 ch 1 count register -uint16 i8237_r4; // 8237 ch 2 address register -uint16 i8237_r5; // 8237 ch 2 count register -uint16 i8237_r6; // 8237 ch 3 address register -uint16 i8237_r7; // 8237 ch 3 count register -uint8 i8237_r8; // 8237 status register -uint8 i8237_r9; // 8237 command register -uint8 i8237_rA; // 8237 mode register -uint8 i8237_rB; // 8237 mask register -uint8 i8237_rC; // 8237 request register -uint8 i8237_rD; // 8237 first/last ff -uint8 i8237_rE; // 8237 -uint8 i8237_rF; // 8237 - -/* 8272 physical register definitions */ -/* 8272 command register stack*/ - -uint8 i8272_w0; // MT+MFM+SK+command -uint8 i8272_w1; // HDS [HDS=H << 2] + DS1 + DS0 -uint8 i8272_w2; // cylinder # (0-XX) -uint8 i8272_w3; // head # (0 or 1) -uint8 i8272_w4; // sector # (1-XX) -uint8 i8272_w5; // number of bytes (128 << N) -uint8 i8272_w6; // End of track (last sector # on cylinder) -uint8 i8272_w7; // Gap length -uint8 i8272_w8; // Data length (when N=0, size to read or write) - -/* 8272 status register stack */ - -uint8 i8272_msr; // main status -uint8 i8272_r0; // ST 0 -uint8 i8272_r1; // ST 1 -uint8 i8272_r2; // ST 2 -uint8 i8272_r3; // ST 3 - -/* iSBC-208 physical register definitions */ - -uint16 isbc208_sr; // isbc-208 segment register -uint8 isbc208_i; // iSBC-208 interrupt register -uint8 isbc208_a; // iSBC-208 auxillary port register - -/* data obtained from analyzing command registers/attached file length */ - -int32 wsp = 0, rsp = 0; // indexes to write and read stacks (8272 data) -int32 cyl; // current cylinder -int32 hed; // current head [ h << 2] -int32 h; // current head -int32 sec; // current sector -int32 drv; // current drive -uint8 cmd, pcmd; // current command -int32 secn; // N 0-128, 1-256, etc -int32 spt; // sectors per track -int32 ssize; // sector size (128 << N) - -uint8 *isbc208_buf[FDD_NUM] = { /* FDD buffer pointers */ - NULL, - NULL, - NULL, - NULL -}; - -int32 fddst[FDD_NUM] = { // in ST3 format - 0, // status of FDD 0 - 0, // status of FDD 1 - 0, // status of FDD 2 - 0 // status of FDD 3 -}; - -int8 maxcyl[FDD_NUM] = { - 0, // last cylinder + 1 of FDD 0 - 0, // last cylinder + 1 of FDD 1 - 0, // last cylinder + 1 of FDD 2 - 0 // last cylinder + 1 of FDD 3 -}; - -/* isbc208 Standard SIMH Device Data Structures - 4 units */ - -UNIT isbc208_unit[] = { - { UDATA (&isbc208_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, - { UDATA (&isbc208_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, - { UDATA (&isbc208_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, - { UDATA (&isbc208_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 } -}; - -REG isbc208_reg[] = { - { HRDATA (CH0ADR, i8237_r0, 16) }, - { HRDATA (CH0CNT, i8237_r1, 16) }, - { HRDATA (CH1ADR, i8237_r2, 16) }, - { HRDATA (CH1CNT, i8237_r3, 16) }, - { HRDATA (CH2ADR, i8237_r4, 16) }, - { HRDATA (CH2CNT, i8237_r5, 16) }, - { HRDATA (CH3ADR, i8237_r6, 16) }, - { HRDATA (CH3CNT, i8237_r7, 16) }, - { HRDATA (STAT37, i8237_r8, 8) }, - { HRDATA (CMD37, i8237_r9, 8) }, - { HRDATA (MODE, i8237_rA, 8) }, - { HRDATA (MASK, i8237_rB, 8) }, - { HRDATA (REQ, i8237_rC, 8) }, - { HRDATA (FF, i8237_rD, 8) }, - { HRDATA (STAT72, i8272_msr, 8) }, - { HRDATA (STAT720, i8272_r0, 8) }, - { HRDATA (STAT721, i8272_r1, 8) }, - { HRDATA (STAT722, i8272_r2, 8) }, - { HRDATA (STAT723, i8272_r3, 8) }, - { HRDATA (CMD720, i8272_w0, 8) }, - { HRDATA (CMD721, i8272_w1, 8) }, - { HRDATA (CMD722, i8272_w2, 8) }, - { HRDATA (CMD723, i8272_w3, 8) }, - { HRDATA (CMD724, i8272_w4, 8) }, - { HRDATA (CMD725, i8272_w5, 8) }, - { HRDATA (CMD726, i8272_w6, 8) }, - { HRDATA (CMD727, i8272_w7, 8) }, - { HRDATA (CMD728, i8272_w8, 8) }, - { HRDATA (FDD0, fddst[0], 8) }, - { HRDATA (FDD1, fddst[1], 8) }, - { HRDATA (FDD2, fddst[2], 8) }, - { HRDATA (FDD3, fddst[3], 8) }, - { HRDATA (SEGREG, isbc208_sr, 8) }, - { HRDATA (AUX, isbc208_a, 8) }, - { HRDATA (INT, isbc208_i, 8) }, - { NULL } -}; - -MTAB isbc208_mod[] = { - { UNIT_WPMODE, 0, "RW", "RW", &isbc208_set_mode }, - { UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc208_set_mode }, - { 0 } -}; - -DEBTAB isbc208_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { "REG", DEBUG_reg }, - { NULL } -}; - -DEVICE isbc208_dev = { - "SBC208", //name - isbc208_unit, //units - isbc208_reg, //registers - isbc208_mod, //modifiers - FDD_NUM, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &isbc208_reset, //deposit - NULL, //deposit - NULL, //boot - &isbc208_attach, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags -// 0, //dctrl - DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl - isbc208_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Service routines to handle simulator functions */ - -/* service routine - actually does the simulated disk I/O */ - -t_stat isbc208_svc (UNIT *uptr) -{ - uint32 i; - int32 imgadr, data; - int c; - int32 bpt, bpc; - FILE *fp; - - if ((i8272_msr & CB) && cmd && (uptr->u6 == drv)) { /* execution phase */ - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: Entered execution phase\n"); - switch (cmd) { - case READ: /* 0x06 */ -// sim_printf("READ-e: fddst=%02X", fddst[uptr->u6]); - h = i8272_w3; // h = 0 or 1 - hed = i8272_w3 << 2; // hed = 0 or 4 [h << 2] - sec = i8272_w4; // sector number (1-XX) - secn = i8272_w5; // N (0-5) - spt = i8272_w6; // sectors/track - ssize = 128 << secn; // size of sector (bytes) - bpt = ssize * spt; // bytes/track - bpc = bpt * 2; // bytes/cylinder -// sim_printf(" d=%d h=%d c=%d s=%d\n", drv, h, cyl, sec); - sim_debug (DEBUG_flow, &isbc208_dev, - "208_svc: FDC read: h=%d, hed=%d, sec=%d, secn=%d, spt=%d, ssize=%04X, bpt=%04X, bpc=%04X\n", - h, hed, sec, secn, spt, ssize, bpt, bpc); - sim_debug (DEBUG_flow, &isbc208_dev, - "208_svc: FDC read: d=%d h=%d c=%d s=%d N=%d spt=%d fddst=%02X\n", - drv, h, cyl, sec, secn, spt, fddst[uptr->u6]); - sim_debug (DEBUG_read, &isbc208_dev, "208_svc: FDC read of d=%d h=%d c=%d s=%d\n", - drv, h, cyl, sec); - if ((fddst[uptr->u6] & RDY) == 0) { // drive not ready - i8272_r0 = IC_ABNORM + NR + hed + drv; /* command done - Not ready error*/ - i8272_r3 = fddst[uptr->u6]; - i8272_msr |= (RQM + DIO + CB); /* enter result phase */ - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: FDC read: Not Ready\n"); - } else { // get image addr for this d, h, c, s - imgadr = (cyl * bpc) + (h * bpt) + ((sec - 1) * ssize); - sim_debug (DEBUG_read, &isbc208_dev, - "208_svc: FDC read: DMA addr=%04X cnt=%04X imgadr=%04X\n", - i8237_r0, i8237_r1, imgadr); - for (i=0; i<=i8237_r1; i++) { /* copy selected sector to memory */ - data = *(isbc208_buf[uptr->u6] + (imgadr + i)); - multibus_put_mbyte(i8237_r0 + i, data); - } -//*** need to step return results IAW table 3-11 in 143078-001 - i8272_w4 = ++sec; /* next sector */ - i8272_r0 = hed + drv; /* command done - no error */ - i8272_r3 = fddst[uptr->u6]; - } - i8272_r1 = 0; - i8272_r2 = 0; - i8272_w2 = cyl; /* generate a current address mark */ - i8272_w3 = h; - if (i8272_w4 > i8272_w6) { // beyond last sector of track? - i8272_w4 = 1; // yes, set to sector 1; - if (h) { // on head one? - i8272_w2++; // yes, step cylinder - h = 0; // back to head 0 - } - } - i8272_w5 = secn; - i8272_msr |= (RQM + DIO + CB); /* enter result phase */ - rsp = wsp = 0; /* reset indexes */ - set_irq(SBC208_INT); /* set interrupt */ -// sim_printf("READ-x: fddst=%02X\n", fddst[uptr->u6]); - break; - case WRITE: /* 0x05 */ -// sim_printf("WRITE-e: fddst=%02X\n", fddst[uptr->u6]); - h = i8272_w3; // h = 0 or 1 - hed = i8272_w3 << 2; // hed = 0 or 4 [h << 2] - sec = i8272_w4; // sector number (1-XX) - secn = i8272_w5; // N (0-5) - spt = i8272_w6; // sectors/track - ssize = 128 << secn; // size of sector (bytes) - bpt = ssize * spt; // bytes/track - bpc = bpt * 2; // bytes/cylinder - sim_debug (DEBUG_flow, &isbc208_dev, - "208_svc: FDC write: hed=%d, sec=%d, secn=%d, spt=%d, ssize=%04X, bpt=%04X, bpc=%04X\n", - hed, sec, secn, spt, ssize, bpt, bpc); - sim_debug (DEBUG_flow, &isbc208_dev, - "208_svc: FDC write: d=%d h=%d c=%d s=%d N=%d spt=%d fddst=%02X\n", - drv, h, cyl, sec, secn, spt, fddst[uptr->u6]); - sim_debug (DEBUG_write, &isbc208_dev, "208_svc: FDC write of d=%d h=%d c=%d s=%d\n", - drv, h, cyl, sec); - i8272_r1 = 0; // clear ST1 - i8272_r2 = 0; // clear ST2 - if ((fddst[uptr->u6] & RDY) == 0) { - i8272_r0 = IC_ABNORM + NR + hed + drv; /* Not ready error*/ - i8272_r3 = fddst[uptr->u6]; - i8272_msr |= (RQM + DIO + CB); /* enter result phase */ - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: FDC write: Not Ready\n"); -// } else if (fddst[uptr->u6] & WP) { -// i8272_r0 = IC_ABNORM + hed + drv; /* write protect error*/ -// i8272_r1 = NW; // set not writable in ST1 -// i8272_r3 = fddst[uptr->u6] + WP; -// i8272_msr |= (RQM + DIO + CB); /* enter result phase */ -// sim_printf("\nWrite Protected fddst[%d]=%02X\n", uptr->u6, fddst[uptr->u6]); -// if (isbc208_dev.dctrl & DEBUG_flow) -// sim_printf("208_svc: FDC write: Write Protected\n"); - } else { // get image addr for this d, h, c, s - imgadr = (cyl * bpc) + (h * bpt) + ((sec - 1) * ssize); - sim_debug (DEBUG_write, &isbc208_dev, - "208_svc: FDC write: DMA adr=%04X cnt=%04X imgadr=%04X\n", - i8237_r0, i8237_r1, imgadr); - for (i=0; i<=i8237_r1; i++) { /* copy selected memory to image */ - data = multibus_get_mbyte(i8237_r0 + i); - *(isbc208_buf[uptr->u6] + (imgadr + i)) = data; - } - //*** quick fix. Needs more thought! - fp = fopen(uptr->filename, "wb"); // write out modified image - if (fp) { - for (i=0; icapac; i++) { - c = *(isbc208_buf[uptr->u6] + i) & 0xFF; - fputc(c, fp); - } - fclose(fp); - } -//*** need to step return results IAW table 3-11 in 143078-001 - i8272_w2 = cyl; /* generate a current address mark */ - i8272_w3 = hed >> 2; - i8272_w4 = ++sec; /* next sector */ - i8272_w5 = secn; - i8272_r0 = hed + drv; /* command done - no error */ - i8272_r3 = fddst[uptr->u6]; - i8272_msr |= (RQM + DIO + CB); /* enter result phase */ - } - rsp = wsp = 0; /* reset indexes */ - set_irq(SBC208_INT); /* set interrupt */ -// sim_printf("WRITE-x: fddst=%02X\n", fddst[uptr->u6]); - break; - case FMTTRK: /* 0x0D */ - if ((fddst[uptr->u6] & RDY) == 0) { - i8272_r0 = IC_ABNORM + NR + hed + drv; /* Not ready error*/ - i8272_msr |= (RQM + DIO + CB); /* enter result phase */ - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: Not Ready\n"); - } else if (fddst[uptr->u6] & WP) { - i8272_r0 = IC_ABNORM + hed + drv; /* write protect error*/ - i8272_r3 = fddst[uptr->u6] + WP; - i8272_msr |= (RQM + DIO + CB); /* enter result phase */ - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: Write Protected\n"); - } else { - ; /* do nothing for now */ - i8272_msr |= (RQM + DIO + CB); /* enter result phase */ - } - rsp = wsp = 0; /* reset indexes */ - set_irq(SBC208_INT); /* set interrupt */ - break; - case SENINT: /* 0x08 */ - i8272_msr |= (RQM + DIO + CB); /* enter result phase */ - i8272_r0 = hed + drv; /* command done - no error */ - i8272_r1 = 0; - i8272_r2 = 0; - rsp = wsp = 0; /* reset indexes */ - clr_irq(SBC208_INT); /* clear interrupt */ - break; - case SENDRV: /* 0x04 */ - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: FDC sense drive: d=%d fddst=%02X\n", - drv, fddst[uptr->u6]); - i8272_msr |= (RQM + DIO + CB); /* enter result phase */ - i8272_r0 = hed + drv; /* command done - no error */ - i8272_r1 = 0; - i8272_r2 = 0; - i8272_r3 = fddst[drv]; /* drv status */ - rsp = wsp = 0; /* reset indexes */ - break; - case HOME: /* 0x07 */ -// sim_printf("HOME-e: fddst=%02X\n", fddst[uptr->u6]); - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: FDC home: d=%d fddst=%02X\n", - drv, fddst[uptr->u6]); - if ((fddst[uptr->u6] & RDY) == 0) { - i8272_r0 = IC_ABNORM + NR + hed + drv; /* Not ready error*/ - i8272_r3 = fddst[uptr->u6]; - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: Not Ready\n"); - } else { - cyl = 0; /* now on cylinder 0 */ - fddst[drv] |= T0; /* set status flag */ - i8272_r0 = SE + hed + drv; /* seek end - no error */ - } - i8272_r1 = 0; - i8272_r2 = 0; - i8272_msr &= ~(RQM + DIO + CB + hed + drv); /* execution phase done*/ - i8272_msr |= RQM; /* enter COMMAND phase */ - rsp = wsp = 0; /* reset indexes */ - set_irq(SBC208_INT); /* set interrupt */ -// sim_printf("HOME-x: fddst=%02X\n", fddst[uptr->u6]); - break; - case SPEC: /* 0x03 */ - fddst[0] |= TS; //*** bad, bad, bad! - fddst[1] |= TS; - fddst[2] |= TS; - fddst[3] |= TS; -// sim_printf("SPEC-e: fddst[%d]=%02X\n", uptr->u6, fddst[uptr->u6]); - sim_debug (DEBUG_flow, &isbc208_dev, - "208_svc: FDC specify: SRT=%d ms HUT=%d ms HLT=%d ms \n", - 16 - (drv >> 4), 16 * (drv & 0x0f), i8272_w2 & 0xfe); - i8272_r0 = hed + drv; /* command done - no error */ - i8272_r1 = 0; - i8272_r2 = 0; -// i8272_msr &= ~(RQM + DIO + CB); /* execution phase done*/ - i8272_msr = 0; // force 0 for now, where does 0x07 come from? - i8272_msr |= RQM; /* enter command phase */ - rsp = wsp = 0; /* reset indexes */ -// sim_printf("SPEC-x: fddst[%d]=%02X\n", uptr->u6, fddst[uptr->u6]); - break; - case READID: /* 0x0A */ - if ((fddst[uptr->u6] & RDY) == 0) { - i8272_r0 = IC_RC + NR + hed + drv; /* Not ready error*/ - i8272_r3 = fddst[uptr->u6]; - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: Not Ready\n"); - } else { - i8272_w2 = cyl; /* generate a valid address mark */ - i8272_w3 = hed >> 2; - i8272_w4 = 1; /* always sector 1 */ - i8272_w5 = secn; - i8272_r0 = hed + drv; /* command done - no error */ - i8272_msr &= ~(RQM + DIO + CB); /* execution phase done*/ - i8272_msr |= RQM; /* enter command phase */ - } - i8272_r1 = 0; - i8272_r2 = 0; - rsp = wsp = 0; /* reset indexes */ - break; - case SEEK: /* 0x0F */ -// sim_printf("SEEK-e: fddst=%02X\n", fddst[uptr->u6]); - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: FDC seek: d=%d c=%d fddst=%02X\n", - drv, i8272_w2, fddst[uptr->u6]); - if ((fddst[uptr->u6] & RDY) == 0) { /* Not ready? */ - i8272_r0 = IC_ABNORM + NR + hed + drv; /* error*/ - i8272_r3 = fddst[uptr->u6]; - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: FDC seek: Not Ready\n"); - } else if (i8272_w2 >= maxcyl[uptr->u6]) { - i8272_r0 = IC_ABNORM + RDY + hed + drv; /* seek error*/ - sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: FDC seek: Invalid Cylinder %d\n", i8272_w2); - } else { - i8272_r0 |= SE + hed + drv; /* command done - no error */ - cyl = i8272_w2; /* new cylinder number */ - if (cyl == 0) { /* if cyl 0, set flag */ - fddst[drv] |= T0; /* set T0 status flag */ - i8272_r3 |= T0; - } else { - fddst[drv] &= ~T0; /* clear T0 status flag */ - i8272_r3 &= ~T0; - } - } - i8272_r1 = 0; - i8272_r2 = 0; - i8272_msr &= ~(RQM + DIO + CB + hed + drv); /* execution phase done*/ - i8272_msr |= RQM; /* enter command phase */ - rsp = wsp = 0; /* reset indexes */ -// set_irq(SBC208_INT); /* set interrupt */ -// sim_printf("SEEK-x: fddst=%02X\n", fddst[uptr->u6]); - break; - default: - i8272_msr &= ~(RQM + DIO + CB); /* execution phase done*/ - i8272_msr |= RQM; /* enter command phase */ - i8272_r0 = IC_INVC + hed + drv; /* set bad command error */ - i8272_r1 = 0; - i8272_r2 = 0; - rsp = wsp = 0; /* reset indexes */ - break; - } - pcmd = cmd; /* save for result phase */ - cmd = 0; /* reset command */ - sim_debug (DEBUG_flow, &isbc208_dev, - "208_svc: Exit: msr=%02X ST0=%02X ST1=%02X ST2=%02X ST3=%02X\n", - i8272_msr, i8272_r0, i8272_r1, i8272_r2, i8272_r3); - } - sim_activate (&isbc208_unit[uptr->u6], isbc208_unit[uptr->u6].wait); - return SCPE_OK; -} - -/* Reset routine */ - -t_stat isbc208_reset (DEVICE *dptr, uint16 base) -{ - if (sbc208_devnum > SBC208_NUM) { - sim_printf("sbc208_reset: too many devices!\n"); - return SCPE_MEM; - } - if (SBC202_NUM) { - sim_printf(" SBC208-%d: Hardware Reset\n", sbc208_devnum); - sim_printf(" SBC208-%d: Registered at %04X\n", sbc208_devnum, base); - sbc208_port[sbc208_devnum] = reg_dev(isbc208_r0, SBC208_BASE + 0, sbc208_devnum); - reg_dev(isbc208_r1, SBC208_BASE + 1, sbc208_devnum); - reg_dev(isbc208_r2, SBC208_BASE + 2, sbc208_devnum); - reg_dev(isbc208_r3, SBC208_BASE + 3, sbc208_devnum); - reg_dev(isbc208_r4, SBC208_BASE + 4, sbc208_devnum); - reg_dev(isbc208_r5, SBC208_BASE + 5, sbc208_devnum); - reg_dev(isbc208_r6, SBC208_BASE + 6, sbc208_devnum); - reg_dev(isbc208_r7, SBC208_BASE + 7, sbc208_devnum); - reg_dev(isbc208_r8, SBC208_BASE + 8, sbc208_devnum); - reg_dev(isbc208_r9, SBC208_BASE + 9, sbc208_devnum); - reg_dev(isbc208_rA, SBC208_BASE + 10, sbc208_devnum); - reg_dev(isbc208_rB, SBC208_BASE + 11, sbc208_devnum); - reg_dev(isbc208_rC, SBC208_BASE + 12, sbc208_devnum); - reg_dev(isbc208_rD, SBC208_BASE + 13, sbc208_devnum); - reg_dev(isbc208_rE, SBC208_BASE + 14, sbc208_devnum); - reg_dev(isbc208_rF, SBC208_BASE + 15, sbc208_devnum); - reg_dev(isbc208_r10, SBC208_BASE + 16, sbc208_devnum); - reg_dev(isbc208_r11, SBC208_BASE + 17, sbc208_devnum); - reg_dev(isbc208_r12, SBC208_BASE + 18, sbc208_devnum); - reg_dev(isbc208_r13, SBC208_BASE + 19, sbc208_devnum); - reg_dev(isbc208_r14, SBC208_BASE + 20, sbc208_devnum); - reg_dev(isbc208_r15, SBC208_BASE + 21, sbc208_devnum); - if ((isbc208_dev.flags & DEV_DIS) == 0) - isbc208_reset1(); - sbc208_devnum++; - } else { - sim_printf(" No isbc208 installed\n"); - } - return SCPE_OK; -} - -void isbc208_reset1 (void) +/* isbc208.c: Intel iSBC208 Floppy Disk adapter + 05-03-15 version + + Copyright (c) 2011, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + ?? ??? 11 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + These functions support a simulated iSBC208 interface to 4 each 8-, 5 1/4-, or + 3 1/2-inch floppy disk drives. Commands are setup with programmed I/O to the + simulated ports of an i8237 DMA controller and an i8272 FDC. Data transfer + to/from the simulated disks is performed directly with the multibus memory. + + The iSBC-208 can be configured for 8- or 16-bit addresses. It defaults to 8-bit + addresses for the 8080/8085 processors. It can be configured for I/O port + addresses with 3-bits (8-bit address) or 11-bits (16-bit address). Default is + 3-bits set to 0. This defines the port offset to be used to determine the actual + port address. Bus priority can be configured for parallel or serial mode. Default is + serial. The multibus interface interrupt can be configured for interrupt 0-7. + Default is none. Since all channel registers in the i8237 are 16-bit, transfers + are done as two 8-bit operations, low- then high-byte. + + Port addressing is as follows (Port offset = 0): + + Port Mode Command Function + + 00 Write Load DMAC Channel 0 Base and Current Address Regsiters + Read Read DMAC Channel 0 Current Address Register + 01 Write Load DMAC Channel 0 Base and Current Word Count Registers + Read Read DMAC Channel 0 Current Word Count Register + 04 Write Load DMAC Channel 2 Base and Current Address Regsiters + Read Read DMAC Channel 2 Current Address Register + 05 Write Load DMAC Channel 2 Base and Current Word Count Registers + Read Read DMAC Channel 2 Current Word Count Register + 06 Write Load DMAC Channel 3 Base and Current Address Regsiters + Read Read DMAC Channel 3 Current Address Register + 07 Write Load DMAC Channel 3 Base and Current Word Count Registers + Read Read DMAC Channel 3 Current Word Count Register + 08 Write Load DMAC Command Register + Read Read DMAC Status Register + 09 Write Load DMAC Request Register + OA Write Set/Reset DMAC Mask Register + OB Write Load DMAC Mode Register + OC Write Clear DMAC First/Last Flip-Flop + 0D Write DMAC Master Clear + OF Write Load DMAC Mask Register + 10 Read Read FDC Status Register + 11 Write Load FDC Data Register + Read Read FDC Data Register + 12 Write Load Controller Auxiliary Port + Read Poll Interrupt Status + 13 Write Controller Reset + 14 Write Load Controller Low-Byte Segment Address Register + 15 Write Load Controller High-Byte Segment Address Register + 20-2F Read/Write Reserved for iSBX Multimodule Board + + Register usage is defined in the following paragraphs. + + Read/Write DMAC Address Registers + + Used to simultaneously load a channel's current-address register and base-address + register with the memory address of the first byte to be transferred. (The Channel + 0 current/base address register must be loaded prior to initiating a diskette read + or write operation.) Since each channel's address registers are 16 bits in length + (64K address range), two "write address register" commands must be executed in + order to load the complete current/base address registers for any channel. + + Read/Write DMAC Word Count Registers + + The Write DMAC Word Count Register command is used to simultaneously load a + channel's current and base word-count registers with the number of bytes + to be transferred during a subsequent DMA operation. Since the word-count + registers are 16-bits in length, two commands must be executed to load both + halves of the registers. + + Write DMAC Command Register + + The Write DMAC Command Register command loads an 8-bit byte into the + DMAC's command register to define the operating characteristics of the + DMAC. The functions of the individual bits in the command register are + defined in the following diagram. Note that only two bits within the + register are applicable to the controller; the remaining bits select + functions that are not supported and, accordingly, must always be set + to zero. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | 0 0 0 0 0 0 | + +---+---+---+---+---+---+---+---+ + | | + | +---------- 0 CONTROLLER ENABLE + | 1 CONTROLLER DISABLE + | + +------------------ 0 FIXED PRIORITY + 1 ROTATING PRIORITY + + Read DMAC Status Register Command + + The Read DMAC Status Register command accesses an 8-bit status byte that + identifies the DMA channels that have reached terminal count or that + have a pending DMA request. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | 0 0 | + +---+---+---+---+---+---+---+---+ + | | | | | | + | | | | | +-- CHANNEL 0 TC + | | | | +---------- CHANNEL 2 TC + | | | +-------------- CHANNEL 3 TC + | | +------------------ CHANNEL 0 DMA REQUEST + | +-------------------------- CHANNEL 2 DMA REQUEST + +------------------------------ CHANNEL 3 DMA REQUEST + + Write DMAC Request Register + + The data byte associated with the Write DMAC Request Register command + sets or resets a channel's associated request bit within the DMAC's + internal 4-bit request register. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | +---+-- 00 SELECT CHANNEL 0 + | 01 SELECT CHANNEL 1 + | 10 SELECT CHANNEL 2 + | 11 SELECT CHANNEL 3 + | + +---------- 0 RESET REQUEST BIT + 1 SET REQUEST BIT + + Set/Reset DMAC Mask Register + + Prior to a DREQ-initiated DMA transfer, the channel's mask bit must + be reset to enable recognition of the DREQ input. When the transfer + is complete (terminal count reached or external EOP applied) and + the channel is not programmed to autoinitialize, the channel's + mask bit is automatically set (disabling DREQ) and must be reset + prior to a subsequent DMA transfer. All four bits of the mask + register are set (disabling the DREQ inputs) by a DMAC master + clear or controller reset. Additionally, all four bits can be + set/reset by a single Write DMAC Mask Register command. + + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | +---+-- 00 SELECT CHANNEL 0 + | 01 SELECT CHANNEL 1 + | 10 SELECT CHANNEL 2 + | 11 SELECT CHANNEL 3 + | + +---------- 0 RESET REQUEST BIT + 1 SET REQUEST BIT + + Write DMAC Mode Register + + The Write DMAC Mode Register command is used to define the + operating mode characteristics for each DMA channel. Each + channel has an internal 6-bit mode register; the high-order + six bits of the associated data byte are written into the + mode register addressed by the two low-order bits. + + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | | + +---+---+---+---+---+---+---+---+ + | | | | | | | | + | | | | | | +---+-- 00 SELECT CHANNEL 0 + | | | | | | 01 SELECT CHANNEL 1 + | | | | | | 10 SELECT CHANNEL 2 + | | | | | | 11 SELECT CHANNEL 3 + | | | | | | + | | | | +---+---------- 00 VERIFY TRANSFER + | | | | 01 WRITE TRANSFER + | | | | 10 READ TRANSFER + | | | | + | | | +------------------ 0 AUTOINITIALIZE DISABLE + | | | 1 AUTOINITIALIZE ENABLE + | | | + | | +---------------------- 0 ADDRESS INCREMENT + | | 1 ADDRESS DECREMENT + | | + +---+-------------------------- 00 DEMAND MODE + 01 SINGLE MODE + 10 BLOCK MODE + + Clear DMAC First/Last Flip-Flop + + The Clear DMAC First/Last Flip-Flop command initializes + the DMAC's internal first/last flip-flop so that the + next byte written to or re~d from the 16-bit address + or word-count registers is the low-order byte. The + flip-flop is toggled with each register access so that + a second register read or write command accesses the + high-order byte. + + DMAC Master Clear + + The DMAC Master Clear command clears the DMAC's command, status, + request, and temporary registers to zero, initializes the + first/last flip-flop, and sets the four channel mask bits in + the mask register to disable all DMA requests (i.e., the DMAC + is placed in an idle state). + + Write DMAC Mask Register + + The Write DMAC Mask Register command allows all four bits of the + DMAC's mask register to be written with a single command. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | | +-- 0 CLEAR CHANNEL 0 MASK BIT + | | 1 SET CHANNEL 0 MASK BIT + | | + | +---------- 0 CLEAR CHANNEL 2 MASK BIT + | 1 SET CHANNEL 2 MASK BIT + | + +-------------- 0 CLEAR CHANNEL 3 MASK BIT + 1 SET CHANNEL 3 MASK BIT + + Read FDC Status Register + + The Read FDC Status Register command accesses the FDC's main + status register. The individual status register bits are as + follows: + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | | + +---+---+---+---+---+---+---+---+ + | | | | | | | | + | | | | | | | +-- FDD 0 BUSY + | | | | | | +------ FDD 1 BUSY + | | | | | +---------- FDD 2 BUSY + | | | | +-------------- FDD 3 BUSY + | | | +------------------ FDC BUSY + | | +---------------------- NON-DMA MODE + | +-------------------------- DATA INPUT/OUTPUT + +------------------------------ REQUEST FOR MASTER + + Read/Write FDC Data Register + + The Read and Write FDC Data Register commands are used to write + command and parameter bytes to the FDC in order to specify the + operation to be performed (referred to as the "command phase") + and to read status bytes from the FDC following the operation + (referred to as the "result phase"). During the command and + result phases, the 8-bit data register is actually a series of + 8-bit registers in a stack. Each register is accessed in + sequence; the number of registers accessed and the individual + register contents are defined by the specific disk command. + + Write Controller Auxiliary Port + + The Write Controller Auxiliary Port command is used to set or + clear individual bits within the controller's auxiliary port. + The four low-order port bits are dedicated to auxiliary drive + control functions (jumper links are required to connect the + desired port bit to an available pin on the drive interface + connectors). The most common application for these bits is + the "Motor-On" control function for mini-sized drives. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | | + +---+---+---+---+---+---+---+---+ + | | | | | | | | + | | | | +---+---+---+-- DRIVE CONTROL + | | | +------------------ ADDR 20 + | | +---------------------- ADDR 21 + | +-------------------------- ADDR 22 + +------------------------------ ADDR 23 + + Poll Interrupt Status + + The Poll Interrupt Status command presents the interrupt + status of the controller and the two interrupt status + lines dedicated to the iSBX Multimodule board. + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | | +-- CONTROLLER INTERRUPT + | +------ MULTIMODULE BOARD INTERRUPT 0 + +---------- MULTIMODULE BOARD INTERRUPT 1 + + Controller Reset + + The Controller Reset command is the software reset for the + controller. This command clears the controller's auxiliary + port and segment address register, provides a reset signal + to the iSBX Multimodule board and initializes the bus + controller (releases the bus), the DMAC (clears the internal + registers and masks the DREQ inputs), and the FDC (places + the FDC in an idle state and disables the output control + lines to the diskette drive). + + Write Controller Low- And High-Byte Segment Address Registers + + The Write Controller Low- and High-Byte Address Registers + commands are required when the controller uses 20-bit + addressing (memory address range from 0 to OFFFFFH). These + commands are issued prior to initiating a diskette read or + write operation to specify the 16-bit segment address. + + FDC Commands + + The 8272/D765 is capable of performing 15 different + commands. Each command is initiated by a multibyte transfer + from the processor, and the result after execution of the + command may also be a multibyte transfer back to the processor. + Because of this multibyte interchange of information between + the FDC and the processor, it is convenient to consider each + command as consisting of three phases: + + Command Phase: The FDC receives all information required to + perform a particular operation from the processor. + + Execution Phase: The FDC performs the operation it was + instructed to do. + + Result Phase: After completion of the operation, status + and other housekeeping information are made available + to the processor. + + Not all the FDC commands are supported by this emulation. Only the subset + of commands required to build an operable CP/M BIOS are supported. They are: + + Read - Read specified data from the selected FDD. + + Write - Write specified data to the selected FDD. + + Seek - Move the R/W head to the specified cylinder on the specified FDD. + + Specify - Set the characteristics for all the FDDs. + + Sense Interrupt - Sense change in FDD Ready line or end of Seek/Recalibrate + command. + + Sense Drive - Returns status of all the FDDs. + + Recalibrate - Move the R/W head to cylinder 0 on the specified FDD. + + Format Track - Format the current track on the specified FDD. + + Read ID - Reads the first address mark it finds. + + Simulated Floppy Disk Drives + + The units in this device simulate an 8- or 5 1/4- or 3 1/2 inch drives. The + drives can emulate SSSD, SSDD, and DSDD. Drives can be attached to files up + to 1.44MB in size. Drive configuration is selected when a disk is logged onto + the system. An identity sector or identity byte contains information to + configure the OS drivers for the type of drive to emulate. + + uptr->u3 - + uptr->u4 - + uptr->u5 - + uptr->u6 - unit number (0-FDD_NUM) +*/ + +#include "system_defs.h" + +#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ +#define UNIT_WPMODE (1 << UNIT_V_WPMODE) + +/* master status register definitions */ +#define RQM 0x80 /* Request for master */ +#define DIO 0x40 /* Data I/O Direction 0=W, 1=R */ +#define NDM 0x20 /* Non-DMA mode */ +#define CB 0x10 /* FDC busy */ +#define D3B 0x08 /* FDD 3 busy */` +#define D2B 0x04 /* FDD 2 busy */` +#define D1B 0x02 /* FDD 1 busy */` +#define D0B 0x01 /* FDD 0 busy */` + +/* status register 0 definitions */ +#define IC 0xC0 /* Interrupt code */ +#define IC_NORM 0x00 /* normal completion */ +#define IC_ABNORM 0x40 /* abnormal completion */ +#define IC_INVC 0x80 /* invalid command */ +#define IC_RC 0xC0 /* drive not ready */ +#define SE 0x20 /* Seek end */ +#define EC 0x10 /* Equipment check */ +#define NR 0x08 /* Not ready */ +#define HD 0x04 /* Head selected */ +#define US 0x03 /* Unit selected */ +#define US_0 0x00 /* Unit 0 */ +#define US_1 0x01 /* Unit 1 */ +#define US_2 0x02 /* Unit 2 */ +#define US_3 0x03 /* Unit 3 */ + +/* status register 1 definitions */ +#define EN 0x80 /* End of cylinder */ +#define DE 0x20 /* Data error */ +#define OR 0x10 /* Overrun */ +#define ND 0x04 /* No data */ +#define NW 0x02 /* Not writable */ +#define MA 0x01 /* Missing address mark */ + +/* status register 2 definitions */ +#define CM 0x40 /* Control mark */ +#define DD 0x20 /* Data error in data field */ +#define WC 0x10 /* Wrong cylinder */ +#define BC 0x02 /* Bad cylinder */ +#define MD 0x01 /* Missing address mark in data field */ + +/* status register 3/fddst definitions */ +#define FT 0x80 /* Fault */ +#define WP 0x40 /* Write protect */ +#define RDY 0x20 /* Ready */ +#define T0 0x10 /* Track 0 */ +#define TS 0x08 /* Two sided */ +//#define HD 0x04 /* Head selected */ +//#define US 0x03 /* Unit selected */ + +/* FDC command definitions */ +#define READTRK 0x02 +#define SPEC 0x03 +#define SENDRV 0x04 +#define WRITE 0x05 +#define READ 0x06 +#define HOME 0x07 +#define SENINT 0x08 +#define WRITEDEL 0x09 +#define READID 0x0A +#define READDEL 0x0C +#define FMTTRK 0x0D +#define SEEK 0x0F +#define SCANEQ 0x11 +#define SCANLOEQ 0x19 +#define SCANHIEQ 0x1D + +#define FDD_NUM 4 + +/* internal function prototypes */ + +t_stat isbc208_cfg(uint8 base); +t_stat isbc208_reset (DEVICE *dptr); +void isbc208_reset1 (void); +t_stat isbc208_attach (UNIT *uptr, const char *cptr); +t_stat isbc208_set_mode (UNIT *uptr, int32 val, const char *cptr, void *desc); +t_stat isbc208_svc (UNIT *uptr); +uint8 isbc208_r0(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r1(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r2(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r3(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r4(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r5(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r6(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r7(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r8(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r9(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_rA(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_rB(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_rC(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_rD(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_rE(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_rF(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r10(t_bool io, uint8 dat, uint8 devnum); +uint8 isbc208_r11(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r12(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r13(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r14(t_bool io, uint8 data, uint8 devnum); +uint8 isbc208_r15(t_bool io, uint8 data, uint8 devnum); + +/* external function prototypes */ + +extern void set_irq(int32 int_num); +extern void clr_irq(int32 int_num); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern int32 multibus_get_mbyte(uint16 addr); + +/* external globals */ + +extern int32 PCX; + +/* 8237 physical register definitions */ +uint16 i8237_r0; // 8237 ch 0 address register +uint16 i8237_r1; // 8237 ch 0 count register +uint16 i8237_r2; // 8237 ch 1 address register +uint16 i8237_r3; // 8237 ch 1 count register +uint16 i8237_r4; // 8237 ch 2 address register +uint16 i8237_r5; // 8237 ch 2 count register +uint16 i8237_r6; // 8237 ch 3 address register +uint16 i8237_r7; // 8237 ch 3 count register +uint8 i8237_r8; // 8237 status register +uint8 i8237_r9; // 8237 command register +uint8 i8237_rA; // 8237 mode register +uint8 i8237_rB; // 8237 mask register +uint8 i8237_rC; // 8237 request register +uint8 i8237_rD; // 8237 first/last ff + +/* 8272 physical register definitions */ +/* 8272 command register stack*/ +uint8 i8272_w0; // MT+MFM+SK+command +uint8 i8272_w1; // HDS [HDS=H << 2] + DS1 + DS0 +uint8 i8272_w2; // cylinder # (0-XX) +uint8 i8272_w3; // head # (0 or 1) +uint8 i8272_w4; // sector # (1-XX) +uint8 i8272_w5; // number of bytes (128 << N) +uint8 i8272_w6; // End of track (last sector # on cylinder) +uint8 i8272_w7; // Gap length +uint8 i8272_w8; // Data length (when N=0, size to read or write) + +/* 8272 status register stack */ +uint8 i8272_msr; // main status +uint8 i8272_r0; // ST 0 +uint8 i8272_r1; // ST 1 +uint8 i8272_r2; // ST 2 +uint8 i8272_r3; // ST 3 + +/* iSBC-208 physical register definitions */ +uint16 isbc208_sr; // isbc-208 segment register +uint8 isbc208_i; // iSBC-208 interrupt register +uint8 isbc208_a; // iSBC-208 auxillary port register + +/* data obtained from analyzing command registers/attached file length */ +int32 wsp = 0, rsp = 0; // indexes to write and read stacks (8272 data) +int32 cyl; // current cylinder +int32 hed; // current head [ h << 2] +int32 h; // current head +int32 sec; // current sector +int32 drv; // current drive +uint8 cmd, pcmd; // current command +int32 secn; // N 0-128, 1-256, etc +int32 spt; // sectors per track +int32 ssize; // sector size (128 << N) + +int32 fddst[FDD_NUM] = { // in ST3 format + 0, // status of FDD 0 + 0, // status of FDD 1 + 0, // status of FDD 2 + 0 // status of FDD 3 +}; + +int8 maxcyl[FDD_NUM] = { + 0, // last cylinder + 1 of FDD 0 + 0, // last cylinder + 1 of FDD 1 + 0, // last cylinder + 1 of FDD 2 + 0 // last cylinder + 1 of FDD 3 +}; + +/* isbc208 Standard SIMH Device Data Structures - 4 units */ +UNIT isbc208_unit[] = { + { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 }, + { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 }, + { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 }, + { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 } +}; + +REG isbc208_reg[] = { + { HRDATA (CH0ADR, i8237_r0, 16) }, + { HRDATA (CH0CNT, i8237_r1, 16) }, + { HRDATA (CH1ADR, i8237_r2, 16) }, + { HRDATA (CH1CNT, i8237_r3, 16) }, + { HRDATA (CH2ADR, i8237_r4, 16) }, + { HRDATA (CH2CNT, i8237_r5, 16) }, + { HRDATA (CH3ADR, i8237_r6, 16) }, + { HRDATA (CH3CNT, i8237_r7, 16) }, + { HRDATA (STAT37, i8237_r8, 8) }, + { HRDATA (CMD37, i8237_r9, 8) }, + { HRDATA (MODE, i8237_rA, 8) }, + { HRDATA (MASK, i8237_rB, 8) }, + { HRDATA (REQ, i8237_rC, 8) }, + { HRDATA (FF, i8237_rD, 8) }, + { HRDATA (STAT72, i8272_msr, 8) }, + { HRDATA (STAT720, i8272_r0, 8) }, + { HRDATA (STAT721, i8272_r1, 8) }, + { HRDATA (STAT722, i8272_r2, 8) }, + { HRDATA (STAT723, i8272_r3, 8) }, + { HRDATA (CMD720, i8272_w0, 8) }, + { HRDATA (CMD721, i8272_w1, 8) }, + { HRDATA (CMD722, i8272_w2, 8) }, + { HRDATA (CMD723, i8272_w3, 8) }, + { HRDATA (CMD724, i8272_w4, 8) }, + { HRDATA (CMD725, i8272_w5, 8) }, + { HRDATA (CMD726, i8272_w6, 8) }, + { HRDATA (CMD727, i8272_w7, 8) }, + { HRDATA (CMD728, i8272_w8, 8) }, + { HRDATA (FDD0, fddst[0], 8) }, + { HRDATA (FDD1, fddst[1], 8) }, + { HRDATA (FDD2, fddst[2], 8) }, + { HRDATA (FDD3, fddst[3], 8) }, + { HRDATA (SEGREG, isbc208_sr, 8) }, + { HRDATA (AUX, isbc208_a, 8) }, + { HRDATA (INT, isbc208_i, 8) }, + { NULL } +}; + +MTAB isbc208_mod[] = { + { UNIT_WPMODE, 0, "RW", "RW", &isbc208_set_mode }, + { UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc208_set_mode }, + { 0 } +}; + +DEBTAB isbc208_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { "REG", DEBUG_reg }, + { NULL } +}; + +DEVICE isbc208_dev = { + "SBC208", //name + isbc208_unit, //units + isbc208_reg, //registers + isbc208_mod, //modifiers + FDD_NUM, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + &isbc208_reset, //reset + NULL, //boot + &isbc208_attach, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG|DEV_DISABLE|DEV_DIS, //flags + 0, //dctrl + isbc208_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +// configuration routine + +t_stat isbc208_cfg(uint8 base) { int32 i; UNIT *uptr; - static int flag = 1; - if (flag) sim_printf("iSBC 208: Initializing\n"); + sim_printf(" sbc208: at base 0%02XH\n", + base); + reg_dev(isbc208_r0, base + 0, 0); //8237 registers + reg_dev(isbc208_r1, base + 1, 0); + reg_dev(isbc208_r2, base + 2, 0); + reg_dev(isbc208_r3, base + 3, 0); + reg_dev(isbc208_r4, base + 4, 0); + reg_dev(isbc208_r5, base + 5, 0); + reg_dev(isbc208_r6, base + 6, 0); + reg_dev(isbc208_r7, base + 7, 0); + reg_dev(isbc208_r8, base + 8, 0); + reg_dev(isbc208_r9, base + 9, 0); + reg_dev(isbc208_rA, base + 10, 0); + reg_dev(isbc208_rB, base + 11, 0); + reg_dev(isbc208_rC, base + 12, 0); + reg_dev(isbc208_rD, base + 13, 0); + reg_dev(isbc208_rE, base + 14, 0); + reg_dev(isbc208_rF, base + 15, 0); + reg_dev(isbc208_r10, base + 16, 0); //8272 registers + reg_dev(isbc208_r11, base + 17, 0); + reg_dev(isbc208_r12, base + 18, 0); //devices on iSBC 208 + reg_dev(isbc208_r13, base + 19, 0); + reg_dev(isbc208_r14, base + 20, 0); + reg_dev(isbc208_r15, base + 21, 0); + // one-time initialization for all FDDs + for (i = 0; i < FDD_NUM; i++) { + uptr = isbc208_dev.units + i; + uptr->u3 = 0; + uptr->u4 = 0; + uptr->u5 = 0; + uptr->u6 = i; //fdd unit number + fddst[i] = WP | T0 | i; /* initial drive status */ + uptr->flags |= UNIT_WPMODE; //set WP in unit flags + } + return SCPE_OK; +} + +/* Reset routine */ + +t_stat isbc208_reset (DEVICE *dptr) +{ + isbc208_reset1(); + return SCPE_OK; +} + +void isbc208_reset1 (void) +{ + int32 i; + UNIT *uptr; + for (i = 0; i < FDD_NUM; i++) { /* handle all units */ uptr = isbc208_dev.units + i; - if (uptr->capac == 0) { /* if not configured */ -// sim_printf(" SBC208%d: Not configured\n", i); -// if (flag) { -// sim_printf(" ALL: \"set isbc208 en\"\n"); -// sim_printf(" EPROM: \"att isbc2080 \"\n"); -// flag = 0; -// } - uptr->capac = 0; /* initialize unit */ - uptr->u3 = 0; - uptr->u4 = 0; - uptr->u5 = 0; - uptr->u6 = i; /* unit number - only set here! */ - fddst[i] = WP + T0 + i; /* initial drive status */ - uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */ + if ((uptr->flags & UNIT_ATT) == 0) { // unattached +// sim_printf(" SBC208: FDD %d - Configured, Status=%02X, No disk image attached\n", +// i, fddst[i]); + } else { /* attached */ + fddst[i] |= RDY; /* drive ready */ +// sim_printf(" SBC208: FDD %d - Configured, Status=%02X, Attached to disk image %s\n", +// i, fddst[i], uptr->filename); sim_activate (&isbc208_unit[uptr->u6], isbc208_unit[uptr->u6].wait); - } else { - fddst[i] = RDY + WP + T0 + i; /* initial attach drive status */ -// sim_printf(" SBC208%d: Configured, Attached to %s\n", i, uptr->filename); } } i8237_r8 = 0; /* status */ @@ -1037,619 +743,745 @@ void isbc208_reset1 (void) i8237_rB = 0x0F; /* mask */ i8237_rC = 0; /* request */ i8237_rD = 0; /* first/last FF */ - i8272_msr = RQM; /* 8272 ready for start of command */ rsp = wsp = 0; /* reset indexes */ cmd = 0; /* clear command */ - sim_printf(" SBC208-%d: Software Reset\n", sbc208_devnum); - if (flag) { - sim_printf(" 8237 Reset\n"); - sim_printf(" 8272 Reset\n"); - } - flag = 0; -} - -/* isbc208 attach - attach an .IMG file to a FDD */ - -t_stat isbc208_attach (UNIT *uptr, CONST char *cptr) -{ + i8272_msr = RQM; /* 8272 ready for start of command */ +// sim_printf(" 8237 Reset\n"); +// sim_printf(" 8272 Reset\n"); +} + +/* isbc208 attach - attach an .IMG file to a FDD */ + +t_stat isbc208_attach (UNIT *uptr, const char *cptr) +{ t_stat r; - FILE *fp; - int32 i, c = 0; - long flen; + int32 c = 0; + long len; + uint8 fddnum; - sim_debug (DEBUG_flow, &isbc208_dev, " isbc208_attach: Entered with cptr=%s\n", cptr); if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - sim_printf(" isbc208_attach: Attach error\n"); + sim_printf(" isbc208_attach: Attach error %d\n", r); return r; } - fp = fopen(uptr->filename, "rb"); - if (fp == NULL) { - sim_printf(" Unable to open disk img file %s\n", uptr->filename); - sim_printf(" No disk image loaded!!!\n"); - } else { - sim_printf("iSBC 208: Attach\n"); - fseek(fp, 0, SEEK_END); /* size disk image */ - flen = ftell(fp); - fseek(fp, 0, SEEK_SET); - if (flen == -1) { - sim_printf(" isbc208_attach: File error\n"); - fclose(fp); - return SCPE_IOERR; - } - if (isbc208_buf[uptr->u6] == NULL) { /* no buffer allocated */ - isbc208_buf[uptr->u6] = (uint8 *)malloc(flen); - if (isbc208_buf[uptr->u6] == NULL) { - sim_printf(" iSBC208_attach: Malloc error\n"); - fclose(fp); - return SCPE_MEM; - } - } - uptr->capac = flen; - i = 0; - c = fgetc(fp); // copy disk image into buffer - while (c != EOF) { - *(isbc208_buf[uptr->u6] + i++) = c & 0xFF; - c = fgetc(fp); - } - fclose(fp); - fddst[uptr->u6] |= RDY; /* set unit ready */ - if (flen == 368640) { /* 5" 360K DSDD */ - maxcyl[uptr->u6] = 40; - fddst[uptr->u6] |= TS; // two sided - } - else if (flen == 737280) { /* 5" 720K DSQD / 3.5" 720K DSDD */ - maxcyl[uptr->u6] = 80; - fddst[uptr->u6] |= TS; // two sided - } - else if (flen == 1228800) { /* 5" 1.2M DSHD */ - maxcyl[uptr->u6] = 80; - fddst[uptr->u6] |= TS; // two sided - } - else if (flen == 1474560) { /* 3.5" 1.44M DSHD */ - maxcyl[uptr->u6] = 80; - fddst[uptr->u6] |= TS; // two sided - } - sim_printf(" Drive-%d: %d bytes of disk image %s loaded, fddst=%02X\n", - uptr->u6, i, uptr->filename, fddst[uptr->u6]); + len = sim_fsize (uptr->fileref); + fddnum = uptr->u6; + fddst[fddnum] |= RDY; /* set unit ready */ + if (len == 368640) { /* 5" 360K DSDD */ + maxcyl[fddnum] = 40; + fddst[fddnum] |= TS; // two sided } - sim_debug (DEBUG_flow, &isbc208_dev, " iSBC208_attach: Done\n"); + else if (len == 512512) { /* 8" 512K SSDD */ + maxcyl[fddnum] = 77; + } + else if (len == 737280) { /* 5" 720K DSQD */ + maxcyl[fddnum] = 80; + fddst[fddnum] |= TS; // two sided + } + else if (len == 1228800) { /* 5" 1.2M DSHD */ + maxcyl[fddnum] = 80; + fddst[fddnum] |= TS; // two sided + } + else if (len == 1474560) { /* 3.5" 1.44M DSHD */ + maxcyl[fddnum] = 80; + fddst[fddnum] |= TS; // two sided + } + uptr->capac = len; + detach_unit (uptr); + attach_unit (uptr, cptr); + sim_printf(" SBC208: FDD %d - %ld bytes of disk image %s loaded, fddst=%02X\n", + fddnum, len, uptr->filename, fddst[fddnum]); + sim_activate (&isbc208_unit[fddnum], isbc208_unit[fddnum].wait); +// sim_printf( " iSBC208_attach: Done\n"); return SCPE_OK; -} - -/* isbc208 set mode = 8- or 16-bit data bus */ -/* always 8-bit mode for current simulators */ - -t_stat isbc208_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - sim_debug (DEBUG_flow, &isbc208_dev, " isbc208_set_mode: Entered with val=%08XH uptr->flags=%08X\n", - val, uptr->flags); - if (val & UNIT_WPMODE) { /* write protect */ - fddst[uptr->u6] |= WP; - uptr->flags |= val; - } else { /* read write */ - fddst[uptr->u6] &= ~WP; - uptr->flags &= ~val; - } -// sim_printf("fddst[%d]=%02XH uptr->flags=%08X\n", uptr->u6, fddst[uptr->u6], uptr->flags); - sim_debug (DEBUG_flow, &isbc208_dev, " isbc208_set_mode: Done\n"); - return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. -*/ - -uint8 isbc208_r0(t_bool io, uint8 data) -{ - if (io == 0) { /* read current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r0(H) read as %04X\n", i8237_r0); - return (i8237_r0 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r0(L) read as %04X\n", i8237_r0); - return (i8237_r0 & 0xFF); - } - } else { /* write base & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r0 |= (data << 8); - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r0(H) set to %04X\n", i8237_r0); - } else { /* low byte */ - i8237_rD++; - i8237_r0 = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r0(L) set to %04X\n", i8237_r0); - } - return 0; - } -} - -uint8 isbc208_r1(t_bool io, uint8 data) -{ - if (io == 0) { /* read current word count CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r1(H) read as %04X\n", i8237_r1); - return (i8237_r1 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r1(L) read as %04X\n", i8237_r1); - return (i8237_r1 & 0xFF); - } - } else { /* write base & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r1 |= (data << 8); - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r1(H) set to %04X\n", i8237_r1); - } else { /* low byte */ - i8237_rD++; - i8237_r1 = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r1(L) set to %04X\n", i8237_r1); - } - return 0; - } -} - -uint8 isbc208_r2(t_bool io, uint8 data) -{ - if (io == 0) { /* read current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r2(H) read as %04X\n", i8237_r2); - return (i8237_r2 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r2(L) read as %04X\n", i8237_r2); - return (i8237_r2 & 0xFF); - } - } else { /* write base & current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r2 |= (data << 8); - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r2(H) set to %04X\n", i8237_r2); - } else { /* low byte */ - i8237_rD++; - i8237_r2 = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r2(L) set to %04X\n", i8237_r2); - } - return 0; - } -} - -uint8 isbc208_r3(t_bool io, uint8 data) -{ - if (io == 0) { /* read current word count CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r3(H) read as %04X\n", i8237_r3); - return (i8237_r3 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r3(L) read as %04X\n", i8237_r3); - return (i8237_r3 & 0xFF); - } - } else { /* write base & current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r3 |= (data << 8); - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r3(H) set to %04X\n", i8237_r3); - } else { /* low byte */ - i8237_rD++; - i8237_r3 = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r3(L) set to %04X\n", i8237_r3); - } - return 0; - } -} - -uint8 isbc208_r4(t_bool io, uint8 data) -{ - if (io == 0) { /* read current address CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r4(H) read as %04X\n", i8237_r4); - return (i8237_r4 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r4(L) read as %04X\n", i8237_r4); - return (i8237_r4 & 0xFF); - } - } else { /* write base & current address CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r4 |= (data << 8); - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r4(H) set to %04X\n", i8237_r4); - } else { /* low byte */ - i8237_rD++; - i8237_r4 = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r4(L) set to %04X\n", i8237_r4); - } - return 0; - } -} - -uint8 isbc208_r5(t_bool io, uint8 data) -{ - if (io == 0) { /* read current word count CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r5(H) read as %04X\n", i8237_r5); - return (i8237_r5 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r5(L) read as %04X\n", i8237_r5); - return (i8237_r5 & 0xFF); - } - } else { /* write base & current address CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r5 |= (data << 8); - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r5(H) set to %04X\n", i8237_r5); - } else { /* low byte */ - i8237_rD++; - i8237_r5 = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r5(L) set to %04X\n", i8237_r5); - } - return 0; - } -} - -uint8 isbc208_r6(t_bool io, uint8 data) -{ - if (io == 0) { /* read current address CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r6(H) read as %04X\n", i8237_r6); - return (i8237_r6 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r6(L) read as %04X\n", i8237_r6); - return (i8237_r6 & 0xFF); - } - } else { /* write base & current address CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r6 |= (data << 8); - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r6(H) set to %04X\n", i8237_r6); - } else { /* low byte */ - i8237_rD++; - i8237_r6 = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r6(L) set to %04X\n", i8237_r6); - } - return 0; - } -} - -uint8 isbc208_r7(t_bool io, uint8 data) -{ - if (io == 0) { /* read current word count CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r7(H) read as %04X\n", i8237_r7); - return (i8237_r7 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r7(L) read as %04X\n", i8237_r7); - return (i8237_r7 & 0xFF); - } - } else { /* write base & current address CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r7 |= (data << 8); - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r7(H) set to %04X\n", i8237_r7); - } else { /* low byte */ - i8237_rD++; - i8237_r7 = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r7(L) set to %04X\n", i8237_r7); - } - return 0; - } -} - -uint8 isbc208_r8(t_bool io, uint8 data) -{ - if (io == 0) { /* read status register */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r8 (status) read as %02X\n", i8237_r8); - return (i8237_r8); - } else { /* write command register */ - i8237_r9 = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r9 (command) set to %02X\n", i8237_r9); - return 0; - } -} - -uint8 isbc208_r9(t_bool io, uint8 data) -{ - if (io == 0) { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r9\n"); - return 0; - } else { /* write request register */ - i8237_rC = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_rC (request) set to %02X\n", i8237_rC); - return 0; - } -} - -uint8 isbc208_rA(t_bool io, uint8 data) -{ - if (io == 0) { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rA\n"); - return 0; - } else { /* write single mask register */ - switch(data & 0x03) { - case 0: - if (data & 0x04) - i8237_rB |= 1; - else - i8237_rB &= ~1; - break; - case 1: - if (data & 0x04) - i8237_rB |= 2; - else - i8237_rB &= ~2; - break; - case 2: - if (data & 0x04) - i8237_rB |= 4; - else - i8237_rB &= ~4; - break; - case 3: - if (data & 0x04) - i8237_rB |= 8; - else - i8237_rB &= ~8; - break; - } - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); - return 0; - } -} - -uint8 isbc208_rB(t_bool io, uint8 data) -{ - if (io == 0) { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rB\n"); - return 0; - } else { /* write mode register */ - i8237_rA = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_rA (mode) set to %02X\n", i8237_rA); - return 0; - } -} - -uint8 isbc208_rC(t_bool io, uint8 data) -{ - if (io == 0) { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rC\n"); - return 0; - } else { /* clear byte pointer FF */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_rD (FF) cleared\n"); - return 0; - } -} - -uint8 isbc208_rD(t_bool io, uint8 data) -{ - if (io == 0) { /* read temporary register */ - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rD\n"); - return 0; - } else { /* master clear */ - isbc208_reset1(); - sim_debug (DEBUG_reg, &isbc208_dev, "i8237 master clear\n"); - return 0; - } -} - -uint8 isbc208_rE(t_bool io, uint8 data) -{ - if (io == 0) { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rE\n"); - return 0; - } else { /* clear mask register */ - i8237_rB = 0; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_rB (mask) cleared\n"); - return 0; - } -} - -uint8 isbc208_rF(t_bool io, uint8 data) -{ - if (io == 0) { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rF\n"); - return 0; - } else { /* write all mask register bits */ - i8237_rB = data & 0x0F; - sim_debug (DEBUG_reg, &isbc208_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); - return 0; - } -} - -uint8 isbc208_r10(t_bool io, uint8 data) -{ - if (io == 0) { /* read FDC status register */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_msr read as %02X\n", i8272_msr); - return i8272_msr; - } else { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal write to isbc208_r10\n"); - return 0; - } -} - -// read/write FDC data register -uint8 isbc208_r11(t_bool io, uint8 data) -{ - if (io == 0) { /* read FDC data register */ - wsp = 0; /* clear write stack index */ - switch (rsp) { /* read from next stack register */ - case 0: - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_r1 read as %02X\n", i8272_r1); - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_r3 read as %02X\n", i8272_r3); - rsp++; /* step read stack index */ - clr_irq(SBC208_INT); /* clear interrupt */ - if (pcmd == SENDRV) { - i8272_msr = RQM; /* result phase SENDRV done */ - return i8272_r1; // SENDRV return ST1 - } - return i8272_r0; /* ST0 */ - case 1: - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_r2 read as %02X\n", i8272_r2); - rsp++; /* step read stack index */ - if (pcmd == SENINT) { - i8272_msr = RQM; /* result phase SENINT done */ - return cyl; // SENINT return current cylinder - } - return i8272_r1; /* ST1 */ - case 2: - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_r3 read as %02X\n", i8272_r3); - rsp++; /* step read stack index */ - return i8272_r2; /* ST2 */ - case 3: - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w2 read as %02X\n", i8272_w2); - rsp++; /* step read stack index */ - return i8272_w2; /* C - cylinder */ - case 4: - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w3 read as %02X\n", i8272_w3); - rsp++; /* step read stack index */ - return i8272_w3; /* H - head */ - case 5: - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w4 read as %02X\n", i8272_w4); - rsp++; /* step read stack index */ - return i8272_w4; /* R - sector */ - case 6: - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w5 read as %02X\n", i8272_w5); - i8272_msr = RQM; /* result phase ALL OTHERS done */ - return i8272_w5; /* N - sector size*/ - } - } else { /* write FDC data register */ - rsp = 0; /* clear read stack index */ - switch (wsp) { /* write to next stack register */ - case 0: - i8272_w0 = data; /* rws = MT + MFM + SK + cmd */ - cmd = data & 0x1F; /* save the current command */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w0 set to %02X\n", data); - if (cmd == SENINT) { - i8272_msr = CB; /* command phase SENINT done */ - return 0; - } - wsp++; /* step write stack index */ - break; - case 1: - i8272_w1 = data; /* rws = hed + drv */ - if (cmd != SPEC) - drv = data & 0x03; - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w1 set to %02X\n", data); - if (cmd == HOME || cmd == SENDRV || cmd == READID) { - i8272_msr = CB + hed + drv; /* command phase HOME, READID and SENDRV done */ - return 0; - } - wsp++; /* step write stack index */ - break; - case 2: - i8272_w2 = data; /* rws = C */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w2 set to %02X\n", data); - if (cmd == SPEC || cmd == SEEK) { - i8272_msr = CB + hed + drv; /* command phase SPECIFY and SEEK done */ - return 0; - } - wsp++; /* step write stack index */ - break; - case 3: - i8272_w3 = data; /* rw = H */ - hed = data; - wsp++; /* step write stack index */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w3 set to %02X\n", data); - break; - case 4: - i8272_w4 = data; /* rw = R */ - sec = data; - wsp++; /* step write stack index */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w4 set to %02X\n", data); - break; - case 5: - i8272_w5 = data; /* rw = N */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w5 set to %02X\n", data); - if (cmd == FMTTRK) { - i8272_msr = CB + hed + drv; /* command phase FMTTRK done */ - return 0; - } - wsp++; /* step write stack index */ - break; - case 6: - i8272_w6 = data; /* rw = last sector number */ - wsp++; /* step write stack index */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w6 set to %02X\n", data); - break; - case 7: - i8272_w7 = data; /* rw = gap length */ - wsp++; /* step write stack index */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w7 set to %02X\n", data); - break; - case 8: - i8272_w8 = data; /* rw = bytes to transfer */ - sim_debug (DEBUG_reg, &isbc208_dev, "i8272_w8 set to %02X\n", data); - if (cmd == READ || cmd == WRITE) - i8272_msr = CB + hed + drv; /* command phase all others done */ - break; - } - } - return 0; -} - -uint8 isbc208_r12(t_bool io, uint8 data) -{ - if (io == 0) { /* read interrupt status */ - sim_debug (DEBUG_reg, &isbc208_dev, "isbc208_r12 read as %02X\n", isbc208_i); - return (isbc208_i); - } else { /* write controller auxillary port */ - isbc208_a = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "isbc208_r12 set to %02X\n", isbc208_a); - return 0; - } -} - -uint8 isbc208_r13(t_bool io, uint8 data) -{ - if (io == 0) { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r13\n"); - return 0; - } else { /* reset controller */ - isbc208_reset1(); - sim_debug (DEBUG_reg, &isbc208_dev, "isbc208_r13 controller reset\n"); - return 0; - } -} - -uint8 isbc208_r14(t_bool io, uint8 data) -{ - if (io == 0) { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r14\n"); - return 0; - } else { /* Low-Byte Segment Address Register */ - isbc208_sr = data & 0xFF; - sim_debug (DEBUG_reg, &isbc208_dev, "isbc208_sr(L) set to %02X\n", data & 0xFF); - return 0; - } -} - -uint8 isbc208_r15(t_bool io, uint8 data) -{ - if (io == 0) { - sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r15\n"); - return 0; - } else { /* High-Byte Segment Address Register */ - isbc208_sr |= data << 8; - sim_debug (DEBUG_reg, &isbc208_dev, "isbc208_sr(H) set to %02X\n", data); - return 0; - } -} - -/* end of isbc208.c */ +} + +/* isbc208 set mode = WP or RW */ + +t_stat isbc208_set_mode (UNIT *uptr, int32 val, const char *cptr, void *desc) +{ + if (uptr->flags & UNIT_ATT) + return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename); + if (val & UNIT_WPMODE) { /* write protect */ + fddst[uptr->u6] |= WP; + uptr->flags |= val; + } else { /* read write */ + fddst[uptr->u6] &= ~WP; + uptr->flags &= ~val; + } + return SCPE_OK; +} + +/* service routine - actually does the simulated disk I/O */ + +t_stat isbc208_svc (UNIT *uptr) +{ + int32 i, imgadr, data; + int32 bpt, bpc; + uint8 *fbuf; + + if ((i8272_msr & CB) && cmd && (uptr->u6 == drv)) { /* execution phase */ + fbuf = (uint8 *) uptr->filebuf; + switch (cmd) { + case READ: /* 0x06 */ + h = i8272_w3; // h = 0 or 1 + hed = i8272_w3 << 2; // hed = 0 or 4 [h << 2] + sec = i8272_w4; // sector number (1-XX) + secn = i8272_w5; // N (0-5) + spt = i8272_w6; // sectors/track + ssize = 128 << secn; // size of sector (bytes) + bpt = ssize * spt; // bytes/track + bpc = bpt * 2; // bytes/cylinder +// sim_printf("208 Read: FDD=%d h=%d s=%d t=%d n=%d secsiz=%d spt=%d PCX=%04X\n", +// drv, h, sec, cyl, secn, ssize, spt, PCX); + if ((fddst[uptr->u6] & RDY) == 0) { // drive not ready + i8272_r0 = IC_ABNORM | NR | hed | drv; /* command done - Not ready error*/ + i8272_r3 = fddst[uptr->u6]; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } else { // get image addr for this d, h, c, s + if (fddst[uptr->u6] & TS) + imgadr = (cyl * bpc) /*+ (h * bpt)*/ + ((sec - 1) * ssize); + else + imgadr = (cyl * bpt) + ((sec - 1) * ssize); + for (i=0; i<=i8237_r1; i++) { /* copy selected sector to memory */ + data = *(fbuf + (imgadr + i)); + multibus_put_mbyte(i8237_r0 + i, data); + } +//*** need to step return results IAW table 3-11 in 143078-001 + i8272_w4 = ++sec; /* next sector */ + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r3 = fddst[uptr->u6]; + } + i8272_r1 = 0; + i8272_r2 = 0; + i8272_w2 = cyl; /* generate a current address mark */ + i8272_w3 = h; + if (i8272_w4 > i8272_w6) { // beyond last sector of track? + i8272_w4 = 1; // yes, set to sector 1; + if (h) { // on head one? + i8272_w2++; // yes, step cylinder + h = 0; // back to head 0 + } + } + i8272_w5 = secn; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + case WRITE: /* 0x05 */ + h = i8272_w3; // h = 0 or 1 + hed = i8272_w3 << 2; // hed = 0 or 4 [h << 2] + sec = i8272_w4; // sector number (1-XX) + secn = i8272_w5; // N (0-5) + spt = i8272_w6; // sectors/track + ssize = 128 << secn; // size of sector (bytes) + bpt = ssize * spt; // bytes/track + bpc = bpt * 2; // bytes/cylinder + i8272_r1 = 0; // clear ST1 + i8272_r2 = 0; // clear ST2 +// sim_printf("208 Read: FDD=%d h=%d s=%d t=%d n=%d secsiz=%d spt=%d PCX=%04X\n", +// drv, h, sec, cyl, secn, ssize, spt, PCX); + if ((fddst[uptr->u6] & RDY) == 0) { + i8272_r0 = IC_ABNORM | NR | hed | drv; /* Not ready error*/ + i8272_r3 = fddst[uptr->u6]; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } else if (fddst[uptr->u6] & WP) { + i8272_r0 = IC_ABNORM | hed | drv; /* write protect error*/ + i8272_r1 = NW; // set not writable in ST1 + i8272_r3 = fddst[uptr->u6] | WP; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + sim_printf("\nWrite Protected fddst[%d]=%02X\n", uptr->u6, fddst[uptr->u6]); + } else { // get image addr for this d, h, c, s + if (fddst[uptr->u6] == TS) + imgadr = (cyl * bpc) /*+ (h * bpt)*/ + ((sec - 1) * ssize); + else + imgadr = (cyl * bpt) + ((sec - 1) * ssize); + for (i=0; i<=i8237_r1; i++) { /* copy selected memory to image */ + data = multibus_get_mbyte(i8237_r0 + i); + *(fbuf + (imgadr + i)) = data; + } + //*** quick fix. Needs more thought! + /* + fp = fopen(uptr->filename, "wb"); // write out modified image + for (i=0; icapac; i++) { + c = *(isbc208_buf[uptr->u6] + i) & 0xFF; + fputc(c, fp); + } + fclose(fp); + */ +//*** need to step return results IAW table 3-11 in 143078-001 + i8272_w2 = cyl; /* generate a current address mark */ + i8272_w3 = hed >> 2; + i8272_w4 = ++sec; /* next sector */ + i8272_w5 = secn; + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r3 = fddst[uptr->u6]; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + case FMTTRK: /* 0x0D */ + if ((fddst[uptr->u6] & RDY) == 0) { + i8272_r0 = IC_ABNORM | NR | hed | drv; /* Not ready error*/ + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } else if (fddst[uptr->u6] & WP) { + i8272_r0 = IC_ABNORM | hed | drv; /* write protect error*/ + i8272_r3 = fddst[uptr->u6] | WP; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } else { + ; /* do nothing for now */ + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + case SENINT: /* 0x08 */ + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r1 = 0; + i8272_r2 = 0; + rsp = wsp = 0; /* reset indexes */ + clr_irq(SBC208_INT); /* clear interrupt */ + break; + case SENDRV: /* 0x04 */ + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r1 = 0; + i8272_r2 = 0; + i8272_r3 = fddst[drv]; /* drv status */ + rsp = wsp = 0; /* reset indexes */ + break; + case HOME: /* 0x07 */ + if ((fddst[uptr->u6] & RDY) == 0) { + i8272_r0 = IC_ABNORM | NR | hed | drv; /* Not ready error*/ + i8272_r3 = fddst[uptr->u6]; + } else { + cyl = 0; /* now on cylinder 0 */ + fddst[drv] |= T0; /* set status flag */ + i8272_r0 = SE | hed | drv; /* seek end - no error */ + } + i8272_r1 = 0; + i8272_r2 = 0; + i8272_msr &= ~(RQM | DIO | CB | hed | drv); /* execution phase done*/ + i8272_msr |= RQM; /* enter COMMAND phase */ + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + case SPEC: /* 0x03 */ + fddst[0] |= TS; //*** bad, bad, bad! + fddst[1] |= TS; + fddst[2] |= TS; + fddst[3] |= TS; + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r1 = 0; + i8272_r2 = 0; + i8272_msr &= ~(RQM | DIO | CB); /* execution phase done*/ +// i8272_msr = 0; // force 0 for now, where does 0x07 come from? + i8272_msr |= RQM; /* enter command phase */ + rsp = wsp = 0; /* reset indexes */ + break; + case READID: /* 0x0A */ + if ((fddst[uptr->u6] & RDY) == 0) { + i8272_r0 = IC_RC | NR | hed | drv; /* Not ready error*/ + i8272_r3 = fddst[uptr->u6]; + } else { + i8272_w2 = cyl; /* generate a valid address mark */ + i8272_w3 = hed >> 2; + i8272_w4 = 1; /* always sector 1 */ + i8272_w5 = secn; + i8272_r0 = hed | drv; /* command done - no error */ + i8272_msr &= ~(RQM | DIO | CB); /* execution phase done*/ + i8272_msr |= RQM; /* enter command phase */ + } + i8272_r1 = 0; + i8272_r2 = 0; + rsp = wsp = 0; /* reset indexes */ + break; + case SEEK: /* 0x0F */ + if ((fddst[uptr->u6] & RDY) == 0) { /* Not ready? */ + i8272_r0 = IC_ABNORM | NR | hed | drv; /* error*/ + i8272_r3 = fddst[uptr->u6]; + } else if (i8272_w2 >= maxcyl[uptr->u6]) { // too many steps + i8272_r0 = IC_ABNORM | RDY | hed | drv; /* seek error*/ + } else { +// i8272_r0 |= SE | hed | drv; /* command done - no error */ + i8272_r0 = SE | hed | drv; /* command done - no error */ + cyl = i8272_w2; /* new cylinder number */ + if (cyl == 0) { /* if cyl 0, set flag */ + fddst[drv] |= T0; /* set T0 status flag */ + i8272_r3 |= T0; + } else { + fddst[drv] &= ~T0; /* clear T0 status flag */ + i8272_r3 &= ~T0; + } + } + i8272_r1 = 0; + i8272_r2 = 0; + i8272_msr &= ~(RQM | DIO | CB | hed | drv); /* execution phase done*/ + i8272_msr |= RQM; /* enter command phase */ + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + default: + i8272_msr &= ~(RQM | DIO | CB); /* execution phase done*/ + i8272_msr |= RQM; /* enter command phase */ + i8272_r0 = IC_INVC | hed | drv; /* set bad command error */ + i8272_r1 = 0; + i8272_r2 = 0; + rsp = wsp = 0; /* reset indexes */ + break; + } + pcmd = cmd; /* save for result phase */ + cmd = 0; /* reset command */ + } + sim_activate (&isbc208_unit[uptr->u6], isbc208_unit[uptr->u6].wait); + return SCPE_OK; +} + +// read/write FDC data register stack +uint8 isbc208_r11(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read FDC data register */ +// sim_printf("208 R11: Read data=%02X pcmd=%02X rsp=%d PCX=%04X\nA", data, pcmd, rsp, PCX); + wsp = 0; /* clear write stack index */ + switch (rsp) { /* read from next stack register */ + case 0: + rsp++; /* step read stack index */ + clr_irq(SBC208_INT); /* clear interrupt */ + if (pcmd == SENDRV) { + i8272_msr = RQM; /* result phase SENDRV done */ + return i8272_r1; // SENDRV return ST1 + } + return i8272_r0; /* ST0 */ + case 1: + rsp++; /* step read stack index */ + if (pcmd == SENINT) { + i8272_msr = RQM; /* result phase SENINT done */ + return cyl; // SENINT return current cylinder + } + return i8272_r1; /* ST1 */ + case 2: + rsp++; /* step read stack index */ + return i8272_r2; /* ST2 */ + case 3: + rsp++; /* step read stack index */ + return i8272_w2; /* C - cylinder */ + case 4: + rsp++; /* step read stack index */ + return i8272_w3; /* H - head */ + case 5: + rsp++; /* step read stack index */ + return i8272_w4; /* R - sector */ + case 6: + i8272_msr = RQM; /* result phase ALL OTHERS done */ + return i8272_w5; /* N - sector size*/ + } + } else { /* write FDC data register */ +// sim_printf("208 R11: Write data=%02X cmd=%02X wsp=%d PCX=%04X\nA", data, cmd, wsp, PCX); + rsp = 0; /* clear read stack index */ + switch (wsp) { /* write to next stack register */ + case 0: + i8272_w0 = data; /* rws = MT + MFM + SK + cmd */ + cmd = data & 0x1F; /* save the current command */ + if (cmd == SENINT) { + i8272_msr = CB; /* command phase SENINT done */ + return 0; + } + wsp++; /* step write stack index */ + break; + case 1: + i8272_w1 = data; /* rws = hed + drv */ + if (cmd != SPEC) + drv = data & 0x03; + if (cmd == HOME || cmd == SENDRV || cmd == READID) { + i8272_msr = CB | hed | drv; /* command phase HOME, READID and SENDRV done */ + return 0; + } + wsp++; /* step write stack index */ + break; + case 2: + i8272_w2 = data; /* rws = C */ + if (cmd == SPEC || cmd == SEEK) { + i8272_msr = CB | hed | drv; /* command phase SPECIFY and SEEK done */ + return 0; + } + wsp++; /* step write stack index */ + break; + case 3: + i8272_w3 = data; /* rw = H */ + hed = data; + wsp++; /* step write stack index */ + break; + case 4: + i8272_w4 = data; /* rw = R */ + sec = data; + wsp++; /* step write stack index */ + break; + case 5: + i8272_w5 = data; /* rw = N */ + if (cmd == FMTTRK) { + i8272_msr = CB | hed | drv; /* command phase FMTTRK done */ + return 0; + } + wsp++; /* step write stack index */ + break; + case 6: + i8272_w6 = data; /* rw = last sector number */ + wsp++; /* step write stack index */ + break; + case 7: + i8272_w7 = data; /* rw = gap length */ + wsp++; /* step write stack index */ + break; + case 8: + i8272_w8 = data; /* rw = bytes to transfer */ + if (cmd == READ || cmd == WRITE) + i8272_msr = CB | hed | drv; /* command phase all others done */ + break; + } + } + return 0; +} + + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. + + Each function is passed an 'io' flag, where 0 means a read from + the port, and 1 means a write to the port. On input, the actual + input is passed as the return value, on output, 'data' is written + to the device. +*/ + +uint8 isbc208_r0(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r0 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r0 & 0xFF); + } + } else { /* write base & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r0 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r0 = data & 0xFF; + } + return 0; + } +} + +uint8 isbc208_r1(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current word count CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r1 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r1 & 0xFF); + } + } else { /* write base & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r1 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r1 = data & 0xFF; + } + return 0; + } +} + +uint8 isbc208_r2(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r2 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r2 & 0xFF); + } + } else { /* write base & current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r2 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r2 = data & 0xFF; + } + return 0; + } +} + +uint8 isbc208_r3(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current word count CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r3 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r3 & 0xFF); + } + } else { /* write base & current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r3 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r3 = data & 0xFF; + } + return 0; + } +} + +uint8 isbc208_r4(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current address CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r4 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r4 & 0xFF); + } + } else { /* write base & current address CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r4 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r4 = data & 0xFF; + } + return 0; + } +} + +uint8 isbc208_r5(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current word count CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r5 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r5 & 0xFF); + } + } else { /* write base & current address CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r5 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r5 = data & 0xFF; + } + return 0; + } +} + +uint8 isbc208_r6(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current address CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r6 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r6 & 0xFF); + } + } else { /* write base & current address CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r6 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r6 = data & 0xFF; + } + return 0; + } +} + +uint8 isbc208_r7(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current word count CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r7 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r7 & 0xFF); + } + } else { /* write base & current address CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r7 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r7 = data & 0xFF; + } + return 0; + } +} + +uint8 isbc208_r8(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read status register */ + return (i8237_r8); + } else { /* write command register */ + i8237_r9 = data & 0xFF; + return 0; + } +} + +uint8 isbc208_r9(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* write request register */ + i8237_rC = data & 0xFF; + return 0; + } +} + +uint8 isbc208_rA(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* write single mask register */ + switch(data & 0x03) { + case 0: + if (data & 0x04) + i8237_rB |= 1; + else + i8237_rB &= ~1; + break; + case 1: + if (data & 0x04) + i8237_rB |= 2; + else + i8237_rB &= ~2; + break; + case 2: + if (data & 0x04) + i8237_rB |= 4; + else + i8237_rB &= ~4; + break; + case 3: + if (data & 0x04) + i8237_rB |= 8; + else + i8237_rB &= ~8; + break; + } + return 0; + } +} + +uint8 isbc208_rB(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* write mode register */ + i8237_rA = data & 0xFF; + return 0; + } +} + +uint8 isbc208_rC(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* clear byte pointer FF */ + i8237_rD = 0; + return 0; + } +} + +uint8 isbc208_rD(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read temporary register */ + return 0; + } else { /* master clear */ + isbc208_reset1(); + return 0; + } +} + +uint8 isbc208_rE(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* clear mask register */ + i8237_rB = 0; + return 0; + } +} + +uint8 isbc208_rF(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* write all mask register bits */ + i8237_rB = data & 0x0F; + return 0; + } +} + +uint8 isbc208_r10(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read FDC status register */ +// sim_printf("FDC Status=%02X PCX=%04X\n", i8272_msr, PCX); + return i8272_msr; + } else { + return 0; + } +} + +uint8 isbc208_r12(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read interrupt status */ + return (isbc208_i); + } else { /* write controller auxillary port */ + isbc208_a = data & 0xFF; + return 0; + } +} + +uint8 isbc208_r13(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* reset controller */ + isbc208_reset1(); + return 0; + } +} + +uint8 isbc208_r14(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* Low-Byte Segment Address Register */ + isbc208_sr = data & 0xFF; + return 0; + } +} + +uint8 isbc208_r15(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* High-Byte Segment Address Register */ + isbc208_sr |= data << 8; + return 0; + } +} + +/* end of isbc208.c */ \ No newline at end of file diff --git a/Intel-Systems/common/isbc464.c b/Intel-Systems/common/isbc464.c new file mode 100644 index 00000000..673ffd98 --- /dev/null +++ b/Intel-Systems/common/isbc464.c @@ -0,0 +1,175 @@ +/* isbc464.c: Intel iSBC 464 32K Byte ROM Card + + Copyright (c) 2011, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + 29 Oct 17 - Original file. + + NOTES: + +*/ + +#include "system_defs.h" + +#define SET_XACK(VAL) (xack = VAL) + +/* prototypes */ + +t_stat isbc064_cfg(uint16 base, uint16 size); +t_stat isbc464_reset (DEVICE *dptr); +t_stat isbc464_attach (UNIT *uptr, CONST char *cptr); +uint8 isbc464_get_mbyte(uint16 addr); +void isbc464_put_mbyte(uint16 addr, uint8 val); + +/* external function prototypes */ + +/* external globals */ + +extern uint8 xack; /* XACK signal */ + +/* local globals */ + +/* isbc464 Standard I/O Data Structures */ + +UNIT isbc464_unit[] = { + UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO+UNIT_BUFABLE+UNIT_MUSTBUF, 0), 0 +}; + +DEBTAB isbc464_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE isbc464_dev = { + "SBC464", //name + isbc464_unit, //units + NULL, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposite + NULL, //reset + NULL, //boot + isbc464_attach, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags + 0, //dctrl + isbc464_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* isbc464 globals */ + +// configuration routine + +t_stat isbc464_cfg(uint16 base, uint16 size) +{ + sim_printf(" sbc464: 0%04XH bytes at base 0%04XH\n", + size, base); + isbc464_unit->capac = size; //set size + isbc464_unit->u3 = base; //and base + return SCPE_OK; +} + +/* Reset routine */ + +t_stat isbc464_reset (DEVICE *dptr) +{ + return SCPE_OK; +} + +/* isbc464 attach */ + +t_stat isbc464_attach (UNIT *uptr, CONST char *cptr) +{ + t_stat r; + + isbc464_reset(NULL); //odd fix, but it works + if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { + sim_printf ("isbc464_attach: Error %d\n", r); + return r; + } + return SCPE_OK; +} + +/* get a byte from memory */ + +uint8 isbc464_get_mbyte(uint16 addr) +{ + uint32 val, org, len; + uint8 *fbuf; + + if ((isbc464_dev.flags & DEV_DIS) == 0) { + org = isbc464_unit->u3; + len = isbc464_unit->capac; + fbuf = (uint8 *) isbc464_unit->filebuf; + if ((addr >= org) && (addr < (org + len))) { + SET_XACK(1); /* good memory address */ + val = *(fbuf + (addr - org)); + return (val & 0xFF); + } else { + sim_printf("isbc464_get_mbyte: Out of range\n"); + return 0; /* multibus has active high pullups and inversion */ + } + } + sim_printf ("isbc464_put_mbyte: Write-Disabled addr=%04X\n", addr); + return 0; /* multibus has active high pullups and inversion */ +} + +/* put a byte into memory */ + +void isbc464_put_mbyte(uint16 addr, uint8 val) +{ + uint32 org, len; + + if ((isbc464_dev.flags & DEV_DIS) == 0) { + org = isbc464_unit->u3; + len = isbc464_unit->capac; + if ((addr >= org) && (addr < (org + len))) { +// SET_XACK(1); /* good memory address */ + sim_printf ("isbc464_put_mbyte: Read-only Memory\n"); + return; + } else { + sim_printf ("isbc464_put_mbyte: Out of range\n"); + return; + } + } + sim_printf ("isbc464_put_mbyte: Disabled\n"); +} + +/* end of isbc464.c */ diff --git a/Intel-Systems/common/m800multibus.c b/Intel-Systems/common/m800multibus.c new file mode 100644 index 00000000..f3b97390 --- /dev/null +++ b/Intel-Systems/common/m800multibus.c @@ -0,0 +1,373 @@ +/* m800multibus.c: Multibus I simulator for M800/810 + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + +*/ + +#include "system_defs.h" + +#define SET_XACK(VAL) (xack = VAL) + +int32 mbirq = 0; /* set no multibus interrupts */ + +/* function prototypes */ + +t_stat multibus_cfg(void); +t_stat multibus_svc(UNIT *uptr); +t_stat multibus_reset(DEVICE *dptr); +void set_irq(int32 int_num); +void clr_irq(int32 int_num); +uint8 nulldev(t_bool io, uint8 data, uint8 devnum); +uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint8 port, uint8 devnum); +t_stat multibus_reset (DEVICE *dptr); +uint8 multibus_get_mbyte(uint16 addr); +uint16 multibus_get_mword(uint16 addr); +void multibus_put_mbyte(uint16 addr, uint8 val); +void multibus_put_mword(uint16 addr, uint16 val); + +/* external function prototypes */ + +extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */ +extern void set_cpuint(int32 int_num); +extern t_stat zx200a_reset(DEVICE *dptr); +extern t_stat isbc201_reset (DEVICE *dptr); +extern t_stat isbc202_reset (DEVICE *dptr); +extern t_stat isbc206_reset (DEVICE *dptr); +extern t_stat isbc208_reset (DEVICE *dptr); +extern t_stat isbc464_reset (DEVICE *dptr); +extern t_stat isbc064_reset (DEVICE *dptr); +extern uint8 isbc064_get_mbyte(uint16 addr); +extern void isbc064_put_mbyte(uint16 addr, uint8 val); +extern uint8 isbc464_get_mbyte(uint16 addr); +extern t_stat isbc064_cfg(uint16 base, uint16 size); +extern t_stat isbc464_cfg(uint16 base, uint16 size); +extern t_stat isbc201_cfg(uint8 base); +extern t_stat isbc202_cfg(uint8 base); +extern t_stat isbc206_cfg(uint8 base); +extern t_stat isbc208_cfg(uint8 base); +extern t_stat zx200a_cfg(uint8 base); + +/* external globals */ + +extern uint8 xack; /* XACK signal */ +extern int32 int_req; /* i8080 INT signal */ +extern DEVICE isbc064_dev; +extern DEVICE isbc464_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE isbc206_dev; +extern DEVICE isbc208_dev; +extern DEVICE zx200a_dev; + +/* multibus Standard SIMH Device Data Structures */ + +UNIT multibus_unit = { + UDATA (&multibus_svc, 0, 0), 20 +}; + +REG multibus_reg[] = { + { HRDATA (MBIRQ, mbirq, 32) }, + { HRDATA (XACK, xack, 8) }, + { NULL } +}; + +DEBTAB multibus_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE multibus_dev = { + "MBIRQ", //name + &multibus_unit, //units + multibus_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + &multibus_reset, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + multibus_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +// multibus_cfg + +t_stat multibus_cfg(void) +{ + sim_printf("Configuring Multibus Devices\n"); + if (SBC064_NUM) isbc064_cfg(SBC064_BASE, SBC064_SIZE); + if (SBC464_NUM) isbc464_cfg(SBC464_BASE, SBC464_SIZE); + if (SBC201_NUM) isbc201_cfg(SBC201_BASE); + if (SBC202_NUM) isbc202_cfg(SBC202_BASE); + if (SBC206_NUM) isbc206_cfg(SBC206_BASE); + if (SBC208_NUM) isbc208_cfg(SBC208_BASE); + if (ZX200A_NUM) zx200a_cfg(ZX200A_BASE); + return SCPE_OK; +} + +/* service routine - actually does the simulated interrupts */ + +t_stat multibus_svc(UNIT *uptr) +{ + switch (mbirq) { + case INT_1: + set_cpuint(INT_R); +#if NIPC + clr_irq(SBC202_INT); /***** bad, bad, bad! */ +#endif +// sim_printf("multibus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req); + break; + default: +// sim_printf("multibus_svc: default mbirq=%04X\n", mbirq); + break; + } + sim_activate (&multibus_unit, multibus_unit.wait); /* continue poll */ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat multibus_reset(DEVICE *dptr) +{ + if (SBC_reset(NULL) == 0) { + sim_printf(" Multibus: Reset\n"); + if (SBC064_NUM) { //device installed + isbc064_reset(&isbc064_dev); + sim_printf(" Multibus: SBC064 reset\n"); + } + if (SBC464_NUM) { //unit enabled + isbc464_reset(&isbc464_dev); + sim_printf(" Multibus: SBC464 reset\n"); + } + if (SBC201_NUM) { //unit enabled + isbc201_reset(&isbc201_dev); + sim_printf(" Multibus: SBC201 reset\n"); + } + if (SBC202_NUM) { //unit enabled + isbc202_reset(&isbc202_dev); + sim_printf(" Multibus: SBC202 reset\n"); + } + if (SBC206_NUM) { //unit enabled + isbc206_reset(&isbc206_dev); + sim_printf(" Multibus: SBC206 reset\n"); + } + if (SBC208_NUM) { //unit enabled + isbc208_reset(&isbc208_dev); + sim_printf(" Multibus: SBC208 reset\n"); + } + if (ZX200A_NUM) { //unit enabled + zx200a_reset(&zx200a_dev); + sim_printf(" Multibus: ZX200A reset\n"); + } + sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ + return SCPE_OK; + } else { + sim_printf(" Multibus: SBC not selected\n"); + return SCPE_OK; + } +} + +void set_irq(int32 int_num) +{ + mbirq |= int_num; +// sim_printf("set_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); +} + +void clr_irq(int32 int_num) +{ + mbirq &= ~int_num; +// sim_printf("clr_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); +} + +/* This is the I/O configuration table. There are 256 possible +device addresses, if a device is plugged to a port it's routine +address is here, 'nulldev' means no device has been registered. +*/ +struct idev { + uint8 (*routine)(t_bool io, uint8 data, uint8 devnum); + uint8 port; + uint8 devnum; +}; + +struct idev dev_table[256] = { +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 000H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 004H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 008H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 00CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 010H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 014H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 018H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 01CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 020H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 024H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 028H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 02CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 030H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 034H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 038H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 03CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 040H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 044H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 048H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 04CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 050H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 054H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 058H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 05CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 060H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 064H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 068H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 06CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 070H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 074H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 078H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 07CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 080H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 084H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 088H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 08CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 090H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 094H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 098H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 09CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0CCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0DCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0ECH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */ +}; + +uint8 nulldev(t_bool flag, uint8 data, uint8 devnum) +{ + SET_XACK(0); /* set no XACK */ + return 0; //should be 0xff, but ISIS won't boot if not 0! +} + +uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint8 port, uint8 devnum) +{ + if (dev_table[port].routine != &nulldev) { /* port already assigned */ + sim_printf(" Multibus: I/O Port %04X is already assigned\n", port); + } else { + dev_table[port].routine = routine; + dev_table[port].devnum = devnum; + } + return 0; +} + +/* get a byte from memory */ + +uint8 multibus_get_mbyte(uint16 addr) +{ + uint8 val = 0; + + SET_XACK(0); /* set no XACK */ +// sim_printf("multibus_get_mbyte: Cleared XACK for %04X\n", addr); + if ((isbc464_dev.flags & DEV_DIS) == 0) { //ROM is enabled + if (addr >= SBC464_BASE && addr <= (SBC464_BASE + SBC464_SIZE)) + return(isbc464_get_mbyte(addr)); + } + if (xack == 0) + val = isbc064_get_mbyte(addr); + return val; +} + +/* get a word from memory */ + +uint16 multibus_get_mword(uint16 addr) +{ + uint16 val; + + val = multibus_get_mbyte(addr); + val |= (multibus_get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory */ + +void multibus_put_mbyte(uint16 addr, uint8 val) +{ + SET_XACK(0); /* set no XACK */ +// sim_printf("multibus_put_mbyte: Cleared XACK for %04X\n", addr); + isbc064_put_mbyte(addr, val); +// sim_printf("multibus_put_mbyte: Done XACK=%dX\n", XACK); +} + +/* put a word to memory */ + +void multibus_put_mword(uint16 addr, uint16 val) +{ + multibus_put_mbyte(addr, val & 0xff); + multibus_put_mbyte(addr+1, val >> 8); +} + +/* end of m800multibus.c */ + diff --git a/Intel-Systems/common/multibus.c b/Intel-Systems/common/multibus.c index 40c5ef76..9d073c55 100644 --- a/Intel-Systems/common/multibus.c +++ b/Intel-Systems/common/multibus.c @@ -26,51 +26,67 @@ MODIFICATIONS: ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. 24 Apr 15 -- Modified to use simh_debug NOTES: - This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus - Computer Systems. - */ #include "system_defs.h" -int32 mbirq = 0; /* set no multibus interrupts */ - /* function prototypes */ +t_stat multibus_cfg(void); t_stat multibus_svc(UNIT *uptr); t_stat multibus_reset(DEVICE *dptr); void set_irq(int32 int_num); void clr_irq(int32 int_num); -uint8 nulldev(t_bool io, uint8 data); -uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnum); +uint8 nulldev(t_bool io, uint8 port, uint8 devnum); +uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); t_stat multibus_reset (DEVICE *dptr); uint8 multibus_get_mbyte(uint16 addr); void multibus_put_mbyte(uint16 addr, uint8 val); /* external function prototypes */ -extern t_stat SBC_reset(DEVICE *dptr); /* reset the iSBC80/10 emulator */ +extern t_stat SBC_reset(DEVICE *dptr); /* reset the iSBC80/10 emulator */ extern uint8 isbc064_get_mbyte(uint16 addr); extern void isbc064_put_mbyte(uint16 addr, uint8 val); +extern uint8 isbc464_get_mbyte(uint16 addr); extern void set_cpuint(int32 int_num); -extern t_stat SBC_reset (DEVICE *dptr); -extern t_stat isbc064_reset (DEVICE *dptr); -extern t_stat isbc201_reset (DEVICE *dptr, uint16); -extern t_stat isbc202_reset (DEVICE *dptr, uint16); -extern t_stat zx200a_reset(DEVICE *dptr, uint16 base); +extern t_stat isbc064_reset (DEVICE *); +extern t_stat isbc464_reset (DEVICE *); +extern t_stat isbc201_reset (DEVICE *); +extern t_stat isbc202_reset (DEVICE *); +extern t_stat isbc206_reset (DEVICE *); +extern t_stat isbc208_reset (DEVICE *); +extern t_stat zx200a_reset(DEVICE *); +extern t_stat isbc064_cfg(uint16 base, uint16 size); +extern t_stat isbc464_cfg(uint16 base, uint16 size); +extern t_stat isbc201_cfg(uint8 base); +extern t_stat isbc202_cfg(uint8 base); +extern t_stat isbc206_cfg(uint8 base); +extern t_stat isbc208_cfg(uint8 base); +extern t_stat zx200a_cfg(uint8 base); + +/* local globals */ + +int32 mbirq = 0; /* set no multibus interrupts */ /* external globals */ -extern uint8 xack; /* XACK signal */ -extern int32 int_req; /* i8080 INT signal */ -extern int32 isbc201_fdcnum; -extern int32 isbc202_fdcnum; -extern int32 zx200a_fdcnum; +extern uint8 xack; /* XACK signal */ +extern int32 int_req; /* i8080 INT signal */ +extern int32 PCX; +extern DEVICE isbc064_dev; +extern DEVICE isbc464_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE isbc206_dev; +extern DEVICE isbc208_dev; +extern DEVICE zx200a_dev; +extern UNIT isbc064_unit; +extern UNIT isbc464_unit; /* multibus Standard SIMH Device Data Structures */ @@ -80,7 +96,8 @@ UNIT multibus_unit = { REG multibus_reg[] = { { HRDATA (MBIRQ, mbirq, 32) }, - { HRDATA (XACK, xack, 8) } + { HRDATA (XACK, xack, 8) }, + { NULL } }; DEBTAB multibus_debug[] = { @@ -120,21 +137,18 @@ DEVICE multibus_dev = { /* Service routines to handle simulator functions */ -/* service routine - actually does the simulated interrupts */ +// multibus_cfg -t_stat multibus_svc(UNIT *uptr) +t_stat multibus_cfg(void) { - switch (mbirq) { - case INT_1: - set_cpuint(INT_R); - clr_irq(SBC202_INT); /***** bad, bad, bad! */ -// sim_printf("multibus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req); - break; - default: -// sim_printf("multibus_svc: default mbirq=%04X\n", mbirq); - break; - } - sim_activate (&multibus_unit, multibus_unit.wait); /* continue poll */ + sim_printf("Configuring Multibus Devices\n"); + if (SBC064_NUM) isbc064_cfg(SBC064_BASE, SBC064_SIZE); + if (SBC464_NUM) isbc464_cfg(SBC464_BASE, SBC464_SIZE); + if (SBC201_NUM) isbc201_cfg(SBC201_BASE); + if (SBC202_NUM) isbc202_cfg(SBC202_BASE); + if (SBC206_NUM) isbc206_cfg(SBC206_BASE); + if (SBC208_NUM) isbc208_cfg(SBC208_BASE); + if (ZX200A_NUM) zx200a_cfg(ZX200A_BASE); return SCPE_OK; } @@ -142,29 +156,67 @@ t_stat multibus_svc(UNIT *uptr) t_stat multibus_reset(DEVICE *dptr) { - SBC_reset(NULL); - sim_printf(" Multibus: Reset\n"); - isbc064_reset(NULL); - isbc201_fdcnum = 0; - isbc201_reset(NULL, SBC201_BASE); - isbc202_fdcnum = 0; - isbc202_reset(NULL, SBC202_BASE); - zx200a_fdcnum = 0; - zx200a_reset(NULL, ZX200A_BASE); - sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ + if (SBC_reset(NULL) == 0) { + sim_printf(" Multibus: Reset\n"); + if (SBC064_NUM) { //device installed + isbc064_reset(&isbc064_dev); + sim_printf(" Multibus: SBC064 reset\n"); + } + if (SBC464_NUM) { //unit enabled + isbc464_reset(&isbc464_dev); + sim_printf(" Multibus: SBC464 reset\n"); + } + if (SBC201_NUM) { //unit enabled + isbc201_reset(&isbc201_dev); + sim_printf(" Multibus: SBC201 reset\n"); + } + if (SBC202_NUM) { //unit enabled + isbc202_reset(&isbc202_dev); + sim_printf(" Multibus: SBC202 reset\n"); + } + if (SBC206_NUM) { //unit enabled + isbc206_reset(&isbc206_dev); + sim_printf(" Multibus: SBC206 reset\n"); + } + if (SBC208_NUM) { //unit enabled + isbc208_reset(&isbc208_dev); + sim_printf(" Multibus: SBC208 reset\n"); + } + if (ZX200A_NUM) { //unit enabled + zx200a_reset(&zx200a_dev); + sim_printf(" Multibus: ZX200A reset\n"); + } + sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ + return SCPE_OK; + } else { + sim_printf(" Multibus: SBC not selected\n"); + return SCPE_OK; + } +} + +/* service routine - actually does the simulated interrupts */ + +t_stat multibus_svc(UNIT *uptr) +{ + switch (mbirq) { + case INT_2: + set_cpuint(INT_R); + break; + default: + break; + } + sim_activate (&multibus_unit, multibus_unit.wait); /* continue poll */ return SCPE_OK; } void set_irq(int32 int_num) { mbirq |= int_num; -// sim_printf("set_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); } void clr_irq(int32 int_num) { mbirq &= ~int_num; -// sim_printf("clr_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); } /* This is the I/O configuration table. There are 256 possible @@ -172,8 +224,8 @@ device addresses, if a device is plugged to a port it's routine address is here, 'nulldev' means no device has been registered. */ struct idev { - uint8 (*routine)(t_bool io, uint8 data); - uint16 port; + uint8 (*routine)(t_bool io, uint8 data, uint8 devnum); + uint8 port; uint8 devnum; }; @@ -244,21 +296,18 @@ struct idev dev_table[256] = { {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */ }; -//uint8 nulldev(t_bool flag, uint8 data, uint8 devnum) -uint8 nulldev(t_bool flag, uint8 data) +uint8 nulldev(t_bool io, uint8 data, uint8 devnum) { SET_XACK(0); /* set no XACK */ - return 0xFF; + return 0xff; /* multibus has active high pullups and inversion */ } -//uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint16 port, uint8 devnum) -uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnum) +uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint8 port, uint8 devnum) { - if (dev_table[port].routine != &nulldev) { /* port already assigned */ + if (dev_table[port].routine != &nulldev) { /* port already assigned */ if (dev_table[port].routine != routine) - sim_printf(" I/O Port %04X is already assigned\n", port); + sim_printf(" I/O Port %02X is already assigned\n", port); } else { - sim_printf(" Port %04X is assigned to dev %04X\n", port, devnum); dev_table[port].routine = routine; dev_table[port].devnum = devnum; } @@ -270,38 +319,26 @@ uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnum uint8 multibus_get_mbyte(uint16 addr) { SET_XACK(0); /* set no XACK */ -// sim_printf("multibus_get_mbyte: Cleared XACK for %04X\n", addr); - return isbc064_get_mbyte(addr); + if ((isbc464_dev.flags & DEV_DIS) == 0) { //ROM is enabled + if (addr >= isbc464_unit.u3 && addr < (isbc464_unit.u3 + isbc464_unit.capac)) + return(isbc464_get_mbyte(addr)); + } + if ((isbc064_dev.flags & DEV_DIS) == 0) { //RAM is enabled + if (addr >= isbc064_unit.u3 && addr < (isbc064_unit.u3 + isbc064_unit.capac)) + return (isbc064_get_mbyte(addr)); + } + return 0; } -/* get a word from memory */ - -uint16 multibus_get_mword(uint16 addr) -{ - uint16 val; - - val = multibus_get_mbyte(addr); - val |= (multibus_get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte to memory */ - void multibus_put_mbyte(uint16 addr, uint8 val) { SET_XACK(0); /* set no XACK */ -// sim_printf("multibus_put_mbyte: Cleared XACK for %04X\n", addr); - isbc064_put_mbyte(addr, val); -// sim_printf("multibus_put_mbyte: Done XACK=%dX\n", XACK); -} - -/* put a word to memory */ - -void multibus_put_mword(uint16 addr, uint16 val) -{ - multibus_put_mbyte(addr, val & 0xff); - multibus_put_mbyte(addr+1, val >> 8); + if ((isbc064_dev.flags & DEV_DIS) == 0) { //device is enabled + if (addr >= SBC064_BASE && addr <= (SBC064_BASE + SBC064_SIZE - 1)) + isbc064_put_mbyte(addr, val); + } else { + return; + } } /* end of multibus.c */ - diff --git a/Intel-Systems/common/zx200a.c b/Intel-Systems/common/zx200a.c index 3a6722bf..446ca791 100644 --- a/Intel-Systems/common/zx200a.c +++ b/Intel-Systems/common/zx200a.c @@ -1,4 +1,4 @@ -/* zx-200a.c: Intel double density disk adapter adapter +/* zx-200a.c: ZENDEX single/double density disk adapter Copyright (c) 2010, William A. Beech @@ -127,7 +127,7 @@ u3 - u4 - - u5 - fdc number (board instance number). + u5 - u6 - fdd number. The ZX-200A appears to the multibus system as if there were an iSBC-201 @@ -139,12 +139,11 @@ #include "system_defs.h" /* system header in system dir */ -#define DEBUG 0 #define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ #define UNIT_WPMODE (1 << UNIT_V_WPMODE) -#define FDD_NUM 4 +#define FDD_NUM 6 //disk controoler operations #define DNOP 0x00 //disk no operation @@ -165,10 +164,10 @@ #define RDY3 0x40 //FDD 3 ready //result type -#define RERR 0x00 //FDC returned error -#define ROK 0x02 //FDC returned ok +#define ROK 0x00 //FDC error +#define RCHG 0x02 //FDC OK OR disk changed -// If result type is RERR then rbyte is +// If result type is ROK then rbyte is #define RB0DR 0x01 //deleted record #define RB0CRC 0x02 //CRC error #define RB0SEK 0x04 //seek error @@ -178,7 +177,7 @@ #define RB0WE 0x40 //write error #define RB0NR 0x80 //not ready -// If result type is ROK then rbyte is +// If result type is RCHG then rbyte is #define RB1RD2 0x10 //drive 2 ready #define RB1RD3 0x20 //drive 3 ready #define RB1RD0 0x40 //drive 0 ready @@ -193,38 +192,37 @@ /* external function prototypes */ -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); extern uint8 multibus_get_mbyte(uint16 addr); -extern uint16 multibus_get_mword(uint16 addr); extern void multibus_put_mbyte(uint16 addr, uint8 val); -extern uint8 multibus_put_mword(uint16 addr, uint16 val); /* external globals */ -extern uint16 port; //port called in dev_table[port] extern int32 PCX; /* internal function prototypes */ -t_stat zx200a_reset(DEVICE *dptr, uint16 base); -void zx200a_reset1(uint8); +t_stat isbc064_cfg(uint16 base); +t_stat zx200a_reset(DEVICE *dptr); +void zx200a_reset1(void); t_stat zx200a_attach (UNIT *uptr, CONST char *cptr); t_stat zx200a_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -uint8 zx200a0(t_bool io, uint8 data); -uint8 zx200a1(t_bool io, uint8 data); -uint8 zx200a2(t_bool io, uint8 data); -uint8 zx200a3(t_bool io, uint8 data); -uint8 zx200a7(t_bool io, uint8 data); -void zx200a_diskio(uint8 fdcnum); +uint8 zx200ar0SD(t_bool io, uint8 data, uint8 devnum); +uint8 zx200ar0DD(t_bool io, uint8 data, uint8 devnum); +uint8 zx200ar1SD(t_bool io, uint8 data, uint8 devnum); +uint8 zx200ar1DD(t_bool io, uint8 data, uint8 devnum); +uint8 zx200ar2SD(t_bool io, uint8 data, uint8 devnum); +uint8 zx200ar2DD(t_bool io, uint8 data, uint8 devnum); +uint8 zx200ar3(t_bool io, uint8 data, uint8 devnum); +uint8 zx200ar7(t_bool io, uint8 data, uint8 devnum); +void zx200a_diskio(void); /* globals */ -int32 zx200a_fdcnum = 0; //actual number of ZX-200A instances + 1 - typedef struct { //FDD definition // uint8 *buf; - int t0; - int rdy; +// int t0; +// int rdy; uint8 sec; uint8 cyl; uint8 dd; @@ -235,7 +233,8 @@ typedef struct { //FDD definition typedef struct { //FDC definition uint16 baseport; //FDC base port uint16 iopb; //FDC IOPB - uint8 stat; //FDC status + uint8 DDstat; //FDC DD status + uint8 SDstat; //FDC SD status uint8 rdychg; //FDC ready change uint8 rtype; //FDC result type uint8 rbyte0; //FDC result byte for type 00 @@ -244,36 +243,26 @@ typedef struct { //FDC definition FDDDEF fdd[FDD_NUM]; //indexed by the FDD number } FDCDEF; -FDCDEF zx200a[4]; //indexed by the zx200a instance number +FDCDEF zx200a; + +/* ZX-200A Standard I/O Data Structures */ UNIT zx200a_unit[] = { - { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 }, - { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 }, - { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 }, - { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSDD), 20 } + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSSD), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSSD), 20 }, }; REG zx200a_reg[] = { - { HRDATA (STAT0, zx200a[0].stat, 8) }, /* zx200a 0 status */ - { HRDATA (RTYP0, zx200a[0].rtype, 8) }, /* zx200a 0 result type */ - { HRDATA (RBYT0A, zx200a[0].rbyte0, 8) }, /* zx200a 0 result byte 0 */ - { HRDATA (RBYT0B, zx200a[0].rbyte1, 8) }, /* zx200a 0 result byte 1 */ - { HRDATA (INTFF0, zx200a[0].intff, 8) }, /* zx200a 0 interrupt f/f */ - { HRDATA (STAT1, zx200a[1].stat, 8) }, /* zx200a 1 status */ - { HRDATA (RTYP1, zx200a[1].rtype, 8) }, /* zx200a 1 result type */ - { HRDATA (RBYT1A, zx200a[1].rbyte0, 8) }, /* zx200a 1 result byte 0 */ - { HRDATA (RBYT1B, zx200a[1].rbyte1, 8) }, /* zx200a 1 result byte 1 */ - { HRDATA (INTFF1, zx200a[1].intff, 8) }, /* zx200a 1 interrupt f/f */ - { HRDATA (STAT2, zx200a[2].stat, 8) }, /* zx200a 2 status */ - { HRDATA (RTYP2, zx200a[2].rtype, 8) }, /* zx200a 2 result type */ - { HRDATA (RBYT2A, zx200a[2].rbyte0, 8) }, /* zx200a 2 result byte 0 */ - { HRDATA (RBYT2B, zx200a[2].rbyte1, 8) }, /* zx200a 2 result byte 1 */ - { HRDATA (INTFF2, zx200a[2].intff, 8) }, /* zx200a 2 interrupt f/f */ - { HRDATA (STAT3, zx200a[3].stat, 8) }, /* zx200a 3 status */ - { HRDATA (RTYP3, zx200a[3].rtype, 8) }, /* zx200a 3 result type */ - { HRDATA (RBYT3A, zx200a[3].rbyte0, 8) }, /* zx200a 3 result byte 0 */ - { HRDATA (RBYT3B, zx200a[3].rbyte1, 8) }, /* zx200a 3 result byte 1 */ - { HRDATA (INTFF3, zx200a[3].intff, 8) }, /* zx200a 3 interrupt f/f */ + { HRDATA (STAT0, zx200a.SDstat, 8) }, /* zx200a 0 SD status */ + { HRDATA (STAT0, zx200a.DDstat, 8) }, /* zx200a 0 DD status */ + { HRDATA (RTYP0, zx200a.rtype, 8) }, /* zx200a 0 result type */ + { HRDATA (RBYT0A, zx200a.rbyte0, 8) }, /* zx200a 0 result byte 0 */ + { HRDATA (RBYT0B, zx200a.rbyte1, 8) }, /* zx200a 0 result byte 1 */ + { HRDATA (INTFF0, zx200a.intff, 8) }, /* zx200a 0 interrupt f/f */ { NULL } }; @@ -309,14 +298,15 @@ DEVICE zx200a_dev = { 8, //dwidth NULL, //examine NULL, //deposit - NULL, //reset + zx200a_reset, //reset NULL, //boot &zx200a_attach, //attach NULL, //detach NULL, //ctxt DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags - DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl - zx200a_debug, //debflags +// DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl + 0, //dctrl + zx200a_debug, //debflags NULL, //msize NULL //lname }; @@ -327,81 +317,90 @@ DEVICE zx200a_dev = { /* Service routines to handle simulator functions */ -/* Reset routine */ +// configuration routine -t_stat zx200a_reset(DEVICE *dptr, uint16 base) +t_stat zx200a_cfg(uint8 base) { int32 i; UNIT *uptr; - sim_printf(" ZX-200A FDC Board"); - if (ZX200A_NUM) { - sim_printf(" - Found on Port %02X\n", base); - sim_printf(" ZX200A-%d: Hardware Reset\n", zx200a_fdcnum); - sim_printf(" ZX200A-%d: Registered at %04X\n", zx200a_fdcnum, base); - //register base port address for this FDC instance - zx200a[zx200a_fdcnum].baseport = base; - //register I/O port addresses for each function - reg_dev(zx200a0, base, zx200a_fdcnum); - reg_dev(zx200a1, base + 1, zx200a_fdcnum); - reg_dev(zx200a2, base + 2, zx200a_fdcnum); - reg_dev(zx200a3, base + 3, zx200a_fdcnum); - reg_dev(zx200a7, base + 7, zx200a_fdcnum); - reg_dev(zx200a0, base+16, zx200a_fdcnum); - reg_dev(zx200a1, base+16 + 1, zx200a_fdcnum); - reg_dev(zx200a2, base+16 + 2, zx200a_fdcnum); - reg_dev(zx200a3, base+16 + 3, zx200a_fdcnum); - reg_dev(zx200a7, base+16 + 7, zx200a_fdcnum); - // one-time initialization for all FDDs for this FDC instance - for (i = 0; i < FDD_NUM; i++) { - uptr = zx200a_dev.units + i; - uptr->u5 = zx200a_fdcnum; //fdc device number - uptr->u6 = i; //fdd unit number - uptr->flags |= UNIT_WPMODE; //set WP in unit flags - } - zx200a_reset1(zx200a_fdcnum); - zx200a_fdcnum++; - } else - sim_printf(" - Not Found\n"); + sim_printf(" zx200a: at base 0%02XH\n", + base); + //register I/O port addresses for each function + reg_dev(zx200ar0DD, base, 0); //read status + reg_dev(zx200ar1DD, base + 1, 0); //read rslt type/write IOPB addr-l + reg_dev(zx200ar2DD, base + 2, 0); //write IOPB addr-h and start + reg_dev(zx200ar3, base + 3, 0); //read rstl byte + reg_dev(zx200ar7, base + 7, 0); //write reset zx200a + reg_dev(zx200ar0SD, base + 16, 0); //read status + reg_dev(zx200ar1SD, base + 17, 0); //read rslt type/write IOPB addr-l + reg_dev(zx200ar2SD, base + 18, 0); //write IOPB addr-h and start + reg_dev(zx200ar3, base + 19, 0); //read rstl byte + reg_dev(zx200ar7, base + 23, 0); //write reset zx200a + // one-time initialization for all FDDs + for (i = 0; i < FDD_NUM; i++) { + uptr = zx200a_dev.units + i; + uptr->u6 = i; //fdd unit number + } return SCPE_OK; } + +/* Reset routine */ + +t_stat zx200a_reset(DEVICE *dptr) +{ + zx200a_reset1(); //software reset + return SCPE_OK; +} + /* Software reset routine */ -void zx200a_reset1(uint8 fdcnum) +void zx200a_reset1(void) { int32 i; UNIT *uptr; - sim_printf(" ZX-200A-%d: Initializing\n", fdcnum); - zx200a[fdcnum].stat = 0; //clear status + zx200a.DDstat = 0; //clear the FDC DD status + zx200a.SDstat = 0; //clear the FDC SD status for (i = 0; i < FDD_NUM; i++) { /* handle all units */ uptr = zx200a_dev.units + i; - zx200a[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status - zx200a[fdcnum].rtype = ROK; - if (uptr->capac == 0) { /* if not configured */ - sim_printf(" ZX-200A%d: Configured, Status=%02X Not attached\n", i, zx200a[fdcnum].stat); + zx200a.DDstat |= FDCPRE | FDCDD; //set the FDC DD status + zx200a.SDstat |= FDCPRE; //set the FDC SD status + if (i <= 3 ) { //first 4 are DD, last 2 are SD + zx200a.fdd[i].dd = 1; //set double density } else { + zx200a.fdd[i].dd = 0; //set single density + } + zx200a.rtype = ROK; + zx200a.rbyte0 = 0; //set no error + if (uptr->flags & UNIT_ATT) { /* if attached */ switch(i){ case 0: - zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready - zx200a[fdcnum].rbyte1 |= RB1RD0; + zx200a.DDstat |= RDY0; //set FDD 0 ready + zx200a.rbyte1 |= RB1RD0; break; case 1: - zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready - zx200a[fdcnum].rbyte1 |= RB1RD1; + zx200a.DDstat |= RDY1; //set FDD 1 ready + zx200a.rbyte1 |= RB1RD1; break; case 2: - zx200a[fdcnum].stat |= RDY2; //set FDD 2 ready - zx200a[fdcnum].rbyte1 |= RB1RD2; + zx200a.DDstat |= RDY2; //set FDD 2 ready + zx200a.rbyte1 |= RB1RD2; break; case 3: - zx200a[fdcnum].stat |= RDY3; //set FDD 3 ready - zx200a[fdcnum].rbyte1 |= RB1RD3; + zx200a.DDstat |= RDY3; //set FDD 3 ready + zx200a.rbyte1 |= RB1RD3; + break; + case 4: + zx200a.SDstat |= RDY0; //set FDD 0 ready + zx200a.rbyte1 |= RB1RD0; + break; + case 5: + zx200a.SDstat |= RDY1; //set FDD 1 ready + zx200a.rbyte1 |= RB1RD1; break; } - zx200a[fdcnum].rdychg = 0; - sim_printf(" ZX-200A%d: Configured, Status=%02X Attached to %s\n", - i, zx200a[fdcnum].stat, uptr->filename); + zx200a.rdychg = 0; } } } @@ -411,52 +410,42 @@ void zx200a_reset1(uint8 fdcnum) t_stat zx200a_attach (UNIT *uptr, CONST char *cptr) { t_stat r; - uint8 fdcnum, fddnum; + uint8 fddnum; sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_attach: Entered with cptr=%s\n", cptr); if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - sim_printf(" zx200a_attach: Attach error\n"); + sim_printf(" zx200a_attach: Attach error %d\n", r); return r; } - fdcnum = uptr->u5; fddnum = uptr->u6; switch(fddnum){ case 0: - zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready - zx200a[fdcnum].rbyte1 |= RB1RD0; + zx200a.DDstat |= RDY0; //set FDD 0 ready + zx200a.rbyte1 |= RB1RD0; break; case 1: - zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready - zx200a[fdcnum].rbyte1 |= RB1RD1; + zx200a.DDstat |= RDY1; //set FDD 1 ready + zx200a.rbyte1 |= RB1RD1; break; case 2: - zx200a[fdcnum].stat |= RDY2; //set FDD 2 ready - zx200a[fdcnum].rbyte1 |= RB1RD2; + zx200a.DDstat |= RDY2; //set FDD 2 ready + zx200a.rbyte1 |= RB1RD2; break; case 3: - zx200a[fdcnum].stat |= RDY3; //set FDD 3 ready - zx200a[fdcnum].rbyte1 |= RB1RD3; + zx200a.DDstat |= RDY3; //set FDD 3 ready + zx200a.rbyte1 |= RB1RD3; + break; + case 4: + zx200a.SDstat |= RDY0; //set FDD 0 ready + zx200a.rbyte1 |= RB1RD0; + break; + case 5: + zx200a.SDstat |= RDY1; //set FDD 1 ready + zx200a.rbyte1 |= RB1RD1; break; } - zx200a[fdcnum].rtype = ROK; - if (uptr->capac == 256256 && (fddnum == 2 || fddnum == 3)) { /* 8" 256K SSSD */ - zx200a[fdcnum].fdd[fddnum].dd = 0; -// zx200a[fdcnum].fdd[fddnum].maxcyl = 77; -// zx200a[fdcnum].fdd[fddnum].maxsec = 26; - zx200a[fdcnum].fdd[fddnum].sec = 1; - zx200a[fdcnum].fdd[fddnum].cyl = 0; - } - else if (uptr->capac == 512512) { /* 8" 512K SSDD */ - zx200a[fdcnum].fdd[fddnum].dd = 1; -// zx200a[fdcnum].fdd[fddnum].maxcyl = 77; -// zx200a[fdcnum].fdd[fddnum].maxsec = 52; - zx200a[fdcnum].fdd[fddnum].sec = 1; - zx200a[fdcnum].fdd[fddnum].cyl = 0; - } else - sim_printf(" ZX-200A-%d: Invalid disk image or SD on drive 0 or 1\n", fdcnum); - sim_printf(" ZX-200A-%d: Configured %d bytes, Attached to %s\n", - fdcnum, uptr->capac, uptr->filename); - sim_debug (DEBUG_flow, &zx200a_dev, " ZX-200A_attach: Done\n"); + zx200a.rtype = ROK; + zx200a.rbyte0 = 0; //set no error return SCPE_OK; } @@ -464,141 +453,134 @@ t_stat zx200a_attach (UNIT *uptr, CONST char *cptr) t_stat zx200a_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { -// sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_set_mode: Entered with val=%08XH uptr->flags=%08X\n", -// val, uptr->flags); + if (uptr->flags & UNIT_ATT) + return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename); if (val & UNIT_WPMODE) { /* write protect */ uptr->flags |= val; } else { /* read write */ uptr->flags &= ~val; } -// sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_set_mode: Done\n"); return SCPE_OK; } -uint8 zx200_get_dn(void) -{ - int i; - - for (i=0; i= zx200a[i].baseport && port <= zx200a[i].baseport + 7) || - (port >= zx200a[i].baseport+16 && port <= zx200a[i].baseport+16 + 7)) - return i; - sim_printf("zx200_get_dn: port %04X not in zx200 device table\n", port); - return 0xFF; -} - /* I/O instruction handlers, called from the CPU module when an IN or OUT instruction is issued. */ /* zx200a control port functions */ -uint8 zx200a0(t_bool io, uint8 data) +uint8 zx200ar0SD(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = zx200_get_dn()) != 0xFF) { - if (io == 0) { /* read ststus*/ - if (DEBUG) - sim_printf("\n zx-200a0-%d: 0x78/88 returned status=%02X PCX=%04X", - fdcnum, zx200a[fdcnum].stat, PCX); - return zx200a[fdcnum].stat; - } + if (io == 0) { /* read ststus*/ + return zx200a.SDstat; } return 0; } -uint8 zx200a1(t_bool io, uint8 data) +uint8 zx200ar0DD(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = zx200_get_dn()) != 0xFF) { - if (io == 0) { /* read operation */ - zx200a[fdcnum].intff = 0; //clear interrupt FF - zx200a[fdcnum].stat &= ~FDCINT; - if (DEBUG) - sim_printf("\n zx-200a1-%d: 0x79/89 returned rtype=%02X intff=%02X status=%02X PCX=%04X", - fdcnum, zx200a[fdcnum].rtype, zx200a[fdcnum].intff, zx200a[fdcnum].stat, PCX); - return zx200a[fdcnum].rtype; - } else { /* write control port */ - zx200a[fdcnum].iopb = data; - if (DEBUG) - sim_printf("\n zx-200a1-%d: 0x79/88 IOPB low=%02X PCX=%04X", - fdcnum, data, PCX); - } + if (io == 0) { /* read ststus*/ + return zx200a.DDstat; } return 0; } -uint8 zx200a2(t_bool io, uint8 data) +uint8 zx200ar1SD(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = zx200_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - zx200a[fdcnum].iopb |= (data << 8); - if (DEBUG) - sim_printf("\n zx-200a2-%d: 0x7A/8A IOPB=%04X PCX=%04X", - fdcnum, zx200a[fdcnum].iopb, PCX); - zx200a_diskio(fdcnum); - if (zx200a[fdcnum].intff) - zx200a[fdcnum].stat |= FDCINT; + if (io == 0) { /* read operation */ + zx200a.intff = 0; //clear interrupt FF + if (zx200a.intff) + zx200a.SDstat &= ~FDCINT; + if (zx200a.rdychg) { + zx200a.rtype = ROK; + return zx200a.rtype; + } else { + zx200a.rtype = ROK; + return zx200a.rtype; } + } else { /* write control port */ + zx200a.iopb = data; } return 0; } -uint8 zx200a3(t_bool io, uint8 data) +uint8 zx200ar1DD(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; + if (io == 0) { /* read operation */ + zx200a.intff = 0; //clear interrupt FF + if (zx200a.intff) + zx200a.DDstat &= ~FDCINT; + if (zx200a.rdychg) { + zx200a.rtype = ROK; + return zx200a.rtype; + } else { + zx200a.rtype = ROK; + return zx200a.rtype; + } + } else { /* write control port */ + zx200a.iopb = data; + } + return 0; +} - if ((fdcnum = zx200_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - if (zx200a[fdcnum].rtype == 0) { - if (DEBUG) - sim_printf("\n zx200a3-%d: 0x7B/8B returned rbyte0=%02X PCX=%04X", - fdcnum, zx200a[fdcnum].rbyte0, PCX); - return zx200a[fdcnum].rbyte0; +uint8 zx200ar2SD(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + zx200a.iopb |= (data << 8); + zx200a_diskio(); + if (zx200a.intff) + zx200a.SDstat |= FDCINT; + } + return 0; +} + +uint8 zx200ar2DD(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + zx200a.iopb |= (data << 8); + zx200a_diskio(); + if (zx200a.intff) + zx200a.DDstat |= FDCINT; + } + return 0; +} + +uint8 zx200ar3(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read data port */ + if (zx200a.rtype == 0) { + return zx200a.rbyte0; + } else { + if (zx200a.rdychg) { + return zx200a.rbyte1; } else { - if (zx200a[fdcnum].rdychg) { - if (DEBUG) - sim_printf("\n zx200a3-%d: 0x7B/8B returned rbyte1=%02X PCX=%04X", - fdcnum, zx200a[fdcnum].rbyte1, PCX); - return zx200a[fdcnum].rbyte1; - } else { - if (DEBUG) - sim_printf("\n zx200a3-%d: 0x7B/8B returned rbytex=%02X PCX=%04X", - fdcnum, 0, PCX); - return 0; - } + return zx200a.rbyte0; } - } else { /* write data port */ - ; //stop diskette operation } + } else { /* write data port */ + ; //stop diskette operation } return 0; } /* reset ZX-200A */ -uint8 zx200a7(t_bool io, uint8 data) +uint8 zx200ar7(t_bool io, uint8 data, uint8 devnum) { - uint8 fdcnum; - - if ((fdcnum = zx200_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - zx200a_reset1(fdcnum); - } + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + zx200a_reset1(); } return 0; } // perform the actual disk I/O operation -void zx200a_diskio(uint8 fdcnum) +void zx200a_diskio(void) { uint8 cw, di, nr, ta, sa, data, nrptr; uint16 ba; @@ -609,62 +591,75 @@ void zx200a_diskio(uint8 fdcnum) uint8 *fbuf; //parse the IOPB - cw = multibus_get_mbyte(zx200a[fdcnum].iopb); - di = multibus_get_mbyte(zx200a[fdcnum].iopb + 1); - nr = multibus_get_mbyte(zx200a[fdcnum].iopb + 2); - ta = multibus_get_mbyte(zx200a[fdcnum].iopb + 3); - sa = multibus_get_mbyte(zx200a[fdcnum].iopb + 4); - ba = multibus_get_mword(zx200a[fdcnum].iopb + 5); + cw = multibus_get_mbyte(zx200a.iopb); + di = multibus_get_mbyte(zx200a.iopb + 1); + nr = multibus_get_mbyte(zx200a.iopb + 2); + ta = multibus_get_mbyte(zx200a.iopb + 3); + sa = multibus_get_mbyte(zx200a.iopb + 4); + ba = multibus_get_mbyte(zx200a.iopb + 5); + ba |= (multibus_get_mbyte(zx200a.iopb + 6) << 8); fddnum = (di & 0x30) >> 4; uptr = zx200a_dev.units + fddnum; - fbuf = (uint8 *) (zx200a_dev.units + fddnum)->filebuf; - if (DEBUG) { - sim_printf("\n zx200a-%d: zx200a_diskio IOPB=%04X FDD=%02X STAT=%02X", - fdcnum, zx200a[fdcnum].iopb, fddnum, zx200a[fdcnum].stat); - sim_printf("\n zx200a-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X", - fdcnum, cw, di, nr, ta, sa, ba); - } + fbuf = (uint8 *) uptr->filebuf; //check for not ready switch(fddnum) { case 0: - if ((zx200a[fdcnum].stat & RDY0) == 0) { - zx200a[fdcnum].rtype = RERR; - zx200a[fdcnum].rbyte0 = RB0NR; - zx200a[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n zx200a-%d: Ready error on drive %d", fdcnum, fddnum); + if ((zx200a.DDstat & RDY0) == 0) { + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0NR; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } break; case 1: - if ((zx200a[fdcnum].stat & RDY1) == 0) { - zx200a[fdcnum].rtype = RERR; - zx200a[fdcnum].rbyte0 = RB0NR; - zx200a[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n zx200a-%d: Ready error on drive %d", fdcnum, fddnum); + if ((zx200a.DDstat & RDY1) == 0) { + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0NR; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } break; case 2: - if ((zx200a[fdcnum].stat & RDY2) == 0) { - zx200a[fdcnum].rtype = RERR; - zx200a[fdcnum].rbyte0 = RB0NR; - zx200a[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n zx200a-%d: Ready error on drive %d", fdcnum, fddnum); + if ((zx200a.DDstat & RDY2) == 0) { + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0NR; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } break; case 3: - if ((zx200a[fdcnum].stat & RDY3) == 0) { - zx200a[fdcnum].rtype = RERR; - zx200a[fdcnum].rbyte0 = RB0NR; - zx200a[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n zx200a-%d: Ready error on drive %d", fdcnum, fddnum); + if ((zx200a.DDstat & RDY3) == 0) { + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0NR; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n zx200a: Ready error on drive %d", fddnum); + return; + } + break; + case 4: + if ((zx200a.SDstat & RDY0) == 0) { + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0NR; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n zx200a: Ready error on drive %d", fddnum); + return; + } + break; + case 5: + if ((zx200a.SDstat & RDY1) == 0) { + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0NR; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } break; } //check for address error - if (zx200a[fdcnum].fdd[fddnum].dd == 1) { + if (zx200a.fdd[fddnum].dd == 1) { if ( ((di & 0x07) != DHOME) && ( (sa > MAXSECDD) || @@ -672,13 +667,14 @@ void zx200a_diskio(uint8 fdcnum) (sa == 0) || (ta > MAXTRK) )) { - zx200a[fdcnum].rtype = RERR; - zx200a[fdcnum].rbyte0 = RB0ADR; - zx200a[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n zx200a-%d: Address error on drive %d", fdcnum, fddnum); + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0ADR; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n ZX200A: FDD %d - Address error sa=%02X nr=%02X ta=%02X PCX=%04X", + fddnum, sa, nr, ta, PCX); return; } - } else if (zx200a[fdcnum].fdd[fddnum].dd == 0) { + } else { if ( ((di & 0x07) != DHOME) && ( (sa > MAXSECSD) || @@ -686,45 +682,50 @@ void zx200a_diskio(uint8 fdcnum) (sa == 0) || (ta > MAXTRK) )) { - zx200a[fdcnum].rtype = RERR; - zx200a[fdcnum].rbyte0 = RB0ADR; - zx200a[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n zx200a-%d: Address error on drive %d", fdcnum, fddnum); + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0ADR; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n ZX200A: FDD %d - Address error sa=%02X nr=%02X ta=%02X PCX=%04X", + fddnum, sa, nr, ta, PCX); return; } } switch (di & 0x07) { case DNOP: - zx200a[fdcnum].rtype = ROK; - zx200a[fdcnum].intff = 1; //set interrupt FF + zx200a.rtype = ROK; + zx200a.rbyte0 = 0; //set no error + zx200a.intff = 1; //set interrupt FF break; case DSEEK: - zx200a[fdcnum].fdd[fddnum].sec = sa; - zx200a[fdcnum].fdd[fddnum].cyl = ta; - zx200a[fdcnum].rtype = ROK; - zx200a[fdcnum].intff = 1; //set interrupt FF + zx200a.fdd[fddnum].sec = sa; + zx200a.fdd[fddnum].cyl = ta; + zx200a.rtype = ROK; + zx200a.rbyte0 = 0; //set no error + zx200a.intff = 1; //set interrupt FF break; case DHOME: - zx200a[fdcnum].fdd[fddnum].sec = sa; - zx200a[fdcnum].fdd[fddnum].cyl = 0; - zx200a[fdcnum].rtype = ROK; - zx200a[fdcnum].intff = 1; //set interrupt FF + zx200a.fdd[fddnum].sec = sa; + zx200a.fdd[fddnum].cyl = 0; + zx200a.rtype = ROK; + zx200a.rbyte0 = 0; //set no error + zx200a.intff = 1; //set interrupt FF break; case DVCRC: - zx200a[fdcnum].rtype = ROK; - zx200a[fdcnum].intff = 1; //set interrupt FF + zx200a.rtype = ROK; + zx200a.rbyte0 = 0; //set no error + zx200a.intff = 1; //set interrupt FF break; case DFMT: //check for WP if(uptr->flags & UNIT_WPMODE) { - zx200a[fdcnum].rtype = RERR; - zx200a[fdcnum].rbyte0 = RB0WP; - zx200a[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n zx200a-%d: Write protect error 1 on drive %d", fdcnum, fddnum); + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0WP; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n zx200a: Write protect error 1 on drive %d", fddnum); return; } fmtb = multibus_get_mbyte(ba); //get the format byte - if (zx200a[fdcnum].fdd[fddnum].dd == 1) { + if (zx200a.fdd[fddnum].dd == 1) { //calculate offset into DD disk image dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128; for(i=0; i<=((uint32)(MAXSECDD) * 128); i++) { @@ -737,21 +738,19 @@ void zx200a_diskio(uint8 fdcnum) *(fbuf + (dskoff + i)) = fmtb; } } - zx200a[fdcnum].rtype = ROK; - zx200a[fdcnum].intff = 1; //set interrupt FF + zx200a.rtype = ROK; + zx200a.rbyte0 = 0; //set no error + zx200a.intff = 1; //set interrupt FF break; case DREAD: nrptr = 0; while(nrptr < nr) { //calculate offset into disk image - if (zx200a[fdcnum].fdd[fddnum].dd == 1) { + if (zx200a.fdd[fddnum].dd == 1) { dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128; } else { dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128; } - if (DEBUG) - sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X", - fdcnum, cw, di, nr, ta, sa, ba, dskoff); //copy sector from image to RAM for (i=0; i<128; i++) { data = *(fbuf + (dskoff + i)); @@ -761,29 +760,27 @@ void zx200a_diskio(uint8 fdcnum) ba+=0x80; nrptr++; } - zx200a[fdcnum].rtype = ROK; - zx200a[fdcnum].intff = 1; //set interrupt FF + zx200a.rtype = ROK; + zx200a.rbyte0 = 0; //set no error + zx200a.intff = 1; //set interrupt FF break; case DWRITE: //check for WP if(uptr->flags & UNIT_WPMODE) { - zx200a[fdcnum].rtype = RERR; - zx200a[fdcnum].rbyte0 = RB0WP; - zx200a[fdcnum].intff = 1; //set interrupt FF - sim_printf("\n zx200a-%d: Write protect error 2 on drive %d", fdcnum, fddnum); + zx200a.rtype = ROK; + zx200a.rbyte0 = RB0WP; + zx200a.intff = 1; //set interrupt FF + sim_printf("\n zx200a: Write protect error 2 on drive %d", fddnum); return; } nrptr = 0; while(nrptr < nr) { //calculate offset into disk image - if (zx200a[fdcnum].fdd[fddnum].dd == 1) { + if (zx200a.fdd[fddnum].dd == 1) { dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128; } else { dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128; } - if (DEBUG) - sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X", - fdcnum, cw, di, nr, ta, sa, ba, dskoff); for (i=0; i<128; i++) { //copy sector from image to RAM data = multibus_get_mbyte(ba + i); *(fbuf + (dskoff + i)) = data; @@ -792,11 +789,12 @@ void zx200a_diskio(uint8 fdcnum) ba+=0x80; nrptr++; } - zx200a[fdcnum].rtype = ROK; - zx200a[fdcnum].intff = 1; //set interrupt FF + zx200a.rtype = ROK; + zx200a.rbyte0 = 0; //set no error + zx200a.intff = 1; //set interrupt FF break; default: - sim_printf("\n zx200a-%d: zx200a_diskio bad di=%02X", fdcnum, di & 0x07); + sim_printf("\n zx200a: zx200a_diskio bad di=%02X", di & 0x07); break; } } diff --git a/Intel-Systems/imds-210/imds-210_sys.c b/Intel-Systems/imds-210/imds-210_sys.c new file mode 100644 index 00000000..03074804 --- /dev/null +++ b/Intel-Systems/imds-210/imds-210_sys.c @@ -0,0 +1,98 @@ +/* mds210_sys.c: multibus system interface + + Copyright (c) 2017, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + 28 Oct 17 - Original file. + + 18 May 19 - Equipment Emulated: + Model 210 chassis. + Integrated processor board (IPB). + Parallel I/O board (PIO). + ROM-resident system monitor. + Auxiliary ROM board with MCS-80/MCS-85 assembler + and text editor. + +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE i8253_dev; +extern DEVICE i8255_dev; +extern DEVICE i8259_dev; +extern DEVICE EPROM_dev; +extern DEVICE RAM_dev; +extern DEVICE ipc_cont_dev; +extern DEVICE multibus_dev; +//extern DEVICE isbc201_dev; +//extern DEVICE isbc202_dev; +//extern DEVICE isbc206_dev; +//extern DEVICE zx200a_dev; +extern DEVICE isbc464_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel MDS-210"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &EPROM_dev, + &RAM_dev, + &i8251_dev, + &i8253_dev, + &i8255_dev, + &i8259_dev, + &ipc_cont_dev, + &multibus_dev, +// &isbc201_dev, +// &isbc202_dev, +// &isbc206_dev, +// &zx200a_dev, + &isbc464_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + diff --git a/Intel-Systems/imds-210/system_defs.h b/Intel-Systems/imds-210/system_defs.h new file mode 100644 index 00000000..df2fc486 --- /dev/null +++ b/Intel-Systems/imds-210/system_defs.h @@ -0,0 +1,156 @@ +/* system_defs.h: Intel iSBC simulator definitions + + Copyright (c) 2017, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + 28 Oct 17 - Original file. +*/ + +#include +#include +#include "sim_defs.h" /* simulator defns */ + +#define IPC 0 +#define SET_XACK(VAL) (xack = VAL) + +/* set the base for the DBB ports */ +#define DBB_BASE 0xC0 + +/* set the base I/O address for the 8255 */ +#define I8255_BASE_0 0xE4 +#define I8255_BASE_1 0xE8 +#define I8255_NUM 2 + +/* set the base I/O address for the 8253 */ +#define I8253_BASE 0xF0 +#define I8253_NUM 1 + +/* set the base I/O address for the 8251 */ +#define I8251_BASE_0 0xF4 +#define I8251_BASE_1 0xF6 +#define I8251_NUM 2 + +/* set the base I/O address for the 8259 */ +#define I8259_BASE_0 0xFA +#define I8259_BASE_1 0xFC +#define I8259_NUM 2 + +/* set the base I/O address for the IPC control port */ +#define ICONT_BASE 0xFF + +/* set the base and size for the EPROM on the MDS 210 */ +#define ROM_BASE 0x0000 +#define ROM_SIZE 0x0FFF +#define ROM_DISABLE 1 +#define EPROM_NUM 1 + +/* set the base and size for the RAM on the MDS 210 */ +#define RAM_BASE 0x0000 +#define RAM_SIZE 0x7FFF + +//board definitions for the multibus +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x78 +#define SBC201_INT INT_1 +#define SBC201_NUM 0 + +/* set the base I/O address for the iSBC 202 */ +#define SBC202_BASE 0x78 +#define SBC202_INT INT_1 +#define SBC202_NUM 1 + +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_1 +#define SBC206_NUM 0 + +/* set the base I/O address for the iSBC 208 */ +#define SBC208_BASE 0x40 +#define SBC208_INT INT_1 +#define SBC208_NUM 0 + +/* set the base for the zx-200a disk controller */ +#define ZX200A_BASE 0x78 +#define ZX200A_INT INT_1 +#define ZX200A_NUM 0 + +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x4800 +#define SBC464_NUM 1 + +/* set the base and size for the iSBC 064 RAM */ +#define SBC064_BASE 0x8000 +#define SBC064_SIZE 0x7FFF +#define SBC064_NUM 1 + +/* set INTR for CPU */ +#define INTR INT_1 + +/* multibus interrupt definitions */ + +#define INT_0 0x01 +#define INT_1 0x02 +#define INT_2 0x04 +#define INT_3 0x08 +#define INT_4 0x10 +#define INT_5 0x20 +#define INT_6 0x40 +#define INT_7 0x80 + +/* CPU interrupts definitions */ + +#define INT_R 0x200 +#define I75 0x40 +#define I65 0x20 +#define I55 0x10 + +/* Memory */ + +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) + +/* debug definitions */ + +#define DEBUG_flow 0x0001 +#define DEBUG_read 0x0002 +#define DEBUG_write 0x0004 +#define DEBUG_level1 0x0008 +#define DEBUG_level2 0x0010 +#define DEBUG_reg 0x0020 +#define DEBUG_asm 0x0040 +#define DEBUG_xack 0x0080 +#define DEBUG_all 0xFFFF + +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ + diff --git a/Intel-Systems/imds-220/imds-220_sys.c b/Intel-Systems/imds-220/imds-220_sys.c new file mode 100644 index 00000000..d6965f82 --- /dev/null +++ b/Intel-Systems/imds-220/imds-220_sys.c @@ -0,0 +1,85 @@ +/* mds220_sys.c: multibus system interface + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + 01 Mar 18 - Original file. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE i8253_dev; +extern DEVICE i8255_dev; +extern DEVICE i8259_dev; +extern DEVICE EPROM_dev; +extern DEVICE RAM_dev; +extern DEVICE ipc_cont_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE zx200a_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel MDS-220"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &EPROM_dev, + &RAM_dev, + &i8251_dev, + &i8253_dev, + &i8255_dev, + &i8259_dev, + &ipc_cont_dev, + &multibus_dev, + &isbc201_dev, + &isbc202_dev, + &zx200a_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + diff --git a/Intel-Systems/imds-220/system_defs.h b/Intel-Systems/imds-220/system_defs.h new file mode 100644 index 00000000..93a719be --- /dev/null +++ b/Intel-Systems/imds-220/system_defs.h @@ -0,0 +1,156 @@ +/* system_defs.h: Intel iSBC simulator definitions + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + ?? ??? 10 - Original file. +*/ + +#include +#include +#include "sim_defs.h" /* simulator defns */ + +#define IPC 0 +#define SET_XACK(VAL) (xack = VAL) + +/* set the base for the DBB ports */ +#define DBB_BASE 0xC0 + +/* set the base I/O address for the 8255 */ +#define I8255_BASE_0 0xE4 +#define I8255_BASE_1 0xE8 +#define I8255_NUM 2 + +/* set the base I/O address for the 8253 */ +#define I8253_BASE 0xF0 +#define I8253_NUM 1 + +/* set the base I/O address for the 8251 */ +#define I8251_BASE_0 0xF4 +#define I8251_BASE_1 0xF6 +#define I8251_NUM 2 + +/* set the base I/O address for the 8259 */ +#define I8259_BASE_0 0xFA +#define I8259_BASE_1 0xFC +#define I8259_NUM 2 + +/* set the base I/O address for the IPC control port */ +#define ICONT_BASE 0xFF + +/* set the base and size for the EPROM on the MDS 220 */ +#define ROM_BASE 0x0000 +#define ROM_SIZE 0x1000 +#define ROM_DISABLE 1 +#define EPROM_NUM 1 + +/* set the base and size for the RAM on the MDS 220 */ +#define RAM_BASE 0x0000 +#define RAM_SIZE 0x8000 + +//board definitions for the multibus +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x78 +#define SBC201_INT INT_2 +#define SBC201_NUM 0 + +/* set the base I/O address for the iSBC 202 */ +#define SBC202_BASE 0x78 +#define SBC202_INT INT_2 +#define SBC202_NUM 1 + +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_1 +#define SBC206_NUM 0 + +/* set the base I/O address for the iSBC 208 */ +#define SBC208_BASE 0x40 +#define SBC208_INT INT_2 +#define SBC208_NUM 0 + +/* set the base for the zx-200a disk controller */ +#define ZX200A_BASE 0x78 +#define ZX200A_INT INT_2 +#define ZX200A_NUM 1 + +/* set the base and size for the iSBC 064 RAM*/ +#define SBC064_BASE 0x8000 +#define SBC064_SIZE 0x8000 +#define SBC064_NUM 1 + +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x4800 +#define SBC464_NUM 0 + +/* set INTR for CPU */ +#define INTR INT_2 + +/* multibus interrupt definitions */ + +#define INT_0 0x01 +#define INT_1 0x02 +#define INT_2 0x04 +#define INT_3 0x08 +#define INT_4 0x10 +#define INT_5 0x20 +#define INT_6 0x40 +#define INT_7 0x80 + +/* CPU interrupts definitions */ + +#define INT_R 0x200 +#define I75 0x40 +#define I65 0x20 +#define I55 0x10 + +/* Memory */ + +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) + +/* debug definitions */ + +#define DEBUG_flow 0x0001 +#define DEBUG_read 0x0002 +#define DEBUG_write 0x0004 +#define DEBUG_level1 0x0008 +#define DEBUG_level2 0x0010 +#define DEBUG_reg 0x0020 +#define DEBUG_asm 0x0040 +#define DEBUG_xack 0x0080 +#define DEBUG_all 0xFFFF + +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ + diff --git a/Intel-Systems/imds-225/imds-225_sys.c b/Intel-Systems/imds-225/imds-225_sys.c index 6a77f530..18ae3e57 100644 --- a/Intel-Systems/imds-225/imds-225_sys.c +++ b/Intel-Systems/imds-225/imds-225_sys.c @@ -40,6 +40,7 @@ extern DEVICE ipc_cont_dev; extern DEVICE multibus_dev; extern DEVICE isbc201_dev; extern DEVICE isbc202_dev; +extern DEVICE isbc206_dev; extern DEVICE zx200a_dev; /* SCP data structures @@ -69,6 +70,7 @@ DEVICE *sim_devices[] = { &multibus_dev, &isbc201_dev, &isbc202_dev, + &isbc206_dev, &zx200a_dev, NULL }; diff --git a/Intel-Systems/imds-225/system_defs.h b/Intel-Systems/imds-225/system_defs.h index f7483e63..9c545892 100644 --- a/Intel-Systems/imds-225/system_defs.h +++ b/Intel-Systems/imds-225/system_defs.h @@ -30,8 +30,7 @@ #include #include "sim_defs.h" /* simulator defns */ -#define IPC 0 -#define SET_XACK(VAL) (xack = VAL) +#define SET_XACK(VAL) (xack = VAL) /* set the base for the DBB ports */ #define DBB_BASE 0xC0 @@ -60,35 +59,53 @@ /* set the base and size for the EPROM on the MDS 225 */ #define ROM_BASE 0x0000 -#define ROM_SIZE 0x1000 +#define ROM_SIZE 0x0FFF #define ROM_DISABLE 1 +#define EPROM_NUM 1 /* set the base and size for the RAM on the MDS 225 */ #define RAM_BASE 0x0000 -#define RAM_SIZE 0xF800 +#define RAM_SIZE 0xFFFF +#define RAM_DISABLE 0 //board definitions for the multibus -/* set the base I/O address for the iSBC 201 */ -#define SBC201_BASE 0x78 -#define SBC201_INT INT_1 -#define SBC201_NUM 0 - /* set the base I/O address for the iSBC 202 */ #define SBC202_BASE 0x78 -#define SBC202_INT INT_1 +#define SBC202_INT INT_2 #define SBC202_NUM 1 +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x88 +#define SBC201_INT INT_2 +#define SBC201_NUM 1 + +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_1 +#define SBC206_NUM 0 + /* set the base I/O address for the iSBC 208 */ #define SBC208_BASE 0x40 -#define SBC208_INT INT_1 +#define SBC208_INT INT_2 #define SBC208_NUM 0 /* set the base for the zx-200a disk controller */ #define ZX200A_BASE 0x78 +#define ZX200A_INT INT_2 #define ZX200A_NUM 0 +/* set the base and size for the iSBC 064 RAM*/ +#define SBC064_BASE 0x0000 +#define SBC064_SIZE 0xFFFF +#define SBC064_NUM 0 + +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x4800 +#define SBC464_NUM 0 + /* set INTR for CPU */ -#define INTR INT_1 +#define INTR INT_2 /* multibus interrupt definitions */ diff --git a/Intel-Systems/imds-230/imds-230_sys.c b/Intel-Systems/imds-230/imds-230_sys.c new file mode 100644 index 00000000..01271118 --- /dev/null +++ b/Intel-Systems/imds-230/imds-230_sys.c @@ -0,0 +1,87 @@ +/* mds220_sys.c: multibus system interface + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + 01 Mar 18 - Original file. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE i8253_dev; +extern DEVICE i8255_dev; +extern DEVICE i8259_dev; +extern DEVICE EPROM_dev; +extern DEVICE RAM_dev; +extern DEVICE ipc_cont_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE zx200a_dev; +extern DEVICE isbc064_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel MDS-230"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &EPROM_dev, + &RAM_dev, + &i8251_dev, + &i8253_dev, + &i8255_dev, + &i8259_dev, + &ipc_cont_dev, + &multibus_dev, + &isbc201_dev, + &isbc202_dev, + &zx200a_dev, + &isbc064_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + diff --git a/Intel-Systems/imds-230/system_defs.h b/Intel-Systems/imds-230/system_defs.h new file mode 100644 index 00000000..b10abadb --- /dev/null +++ b/Intel-Systems/imds-230/system_defs.h @@ -0,0 +1,155 @@ +/* system_defs.h: Intel iSBC simulator definitions + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + ?? ??? 10 - Original file. +*/ + +#include +#include +#include "sim_defs.h" /* simulator defns */ + +#define SET_XACK(VAL) (xack = VAL) + +/* set the base for the DBB ports */ +#define DBB_BASE 0xC0 + +/* set the base I/O address for the 8255 */ +#define I8255_BASE_0 0xE4 +#define I8255_BASE_1 0xE8 +#define I8255_NUM 2 + +/* set the base I/O address for the 8253 */ +#define I8253_BASE 0xF0 +#define I8253_NUM 1 + +/* set the base I/O address for the 8251 */ +#define I8251_BASE_0 0xF4 +#define I8251_BASE_1 0xF6 +#define I8251_NUM 2 + +/* set the base I/O address for the 8259 */ +#define I8259_BASE_0 0xFA +#define I8259_BASE_1 0xFC +#define I8259_NUM 2 + +/* set the base I/O address for the IPC control port */ +#define ICONT_BASE 0xFF + +/* set the base and size for the EPROM on the MDS 220 */ +#define ROM_BASE 0x0000 +#define ROM_SIZE 0x0FFF +#define ROM_DISABLE 1 +#define EPROM_NUM 1 + +/* set the base and size for the RAM on the MDS 220 */ +#define RAM_BASE 0x0000 +#define RAM_SIZE 0x7FFF + +//board definitions for the multibus +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x78 +#define SBC201_INT INT_2 +#define SBC201_NUM 1 + +/* set the base I/O address for the iSBC 202 */ +#define SBC202_BASE 0x78 +#define SBC202_INT INT_2 +#define SBC202_NUM 1 + +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_1 +#define SBC206_NUM 0 + +/* set the base I/O address for the iSBC 208 */ +#define SBC208_BASE 0x40 +#define SBC208_INT INT_2 +#define SBC208_NUM 0 + +/* set the base for the zx-200a disk controller */ +#define ZX200A_BASE 0x78 +#define ZX200A_INT INT_2 +#define ZX200A_NUM 1 + +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x4800 +#define SBC464_NUM 0 + +/* set the base and size for the iSBC 064 RAM */ +#define SBC064_BASE 0x08000 +#define SBC064_SIZE 0x7FFF +#define SBC064_NUM 1 + +/* set INTR for CPU */ +#define INTR INT_2 + +/* multibus interrupt definitions */ + +#define INT_0 0x01 +#define INT_1 0x02 +#define INT_2 0x04 +#define INT_3 0x08 +#define INT_4 0x10 +#define INT_5 0x20 +#define INT_6 0x40 +#define INT_7 0x80 + +/* CPU interrupts definitions */ + +#define INT_R 0x200 +#define I75 0x40 +#define I65 0x20 +#define I55 0x10 + +/* Memory */ + +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) + +/* debug definitions */ + +#define DEBUG_flow 0x0001 +#define DEBUG_read 0x0002 +#define DEBUG_write 0x0004 +#define DEBUG_level1 0x0008 +#define DEBUG_level2 0x0010 +#define DEBUG_reg 0x0020 +#define DEBUG_asm 0x0040 +#define DEBUG_xack 0x0080 +#define DEBUG_all 0xFFFF + +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ + diff --git a/Intel-Systems/imds-800/cpu.c b/Intel-Systems/imds-800/cpu.c new file mode 100644 index 00000000..66467834 --- /dev/null +++ b/Intel-Systems/imds-800/cpu.c @@ -0,0 +1,142 @@ +/* cpu.c: Intel MDS-800 CPU Module simulator + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + + 5 October 2017 - Original file. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat SBC_reset (DEVICE *dptr); +uint8 get_mbyte(uint16 addr); +uint16 get_mword(uint16 addr); +void put_mbyte(uint16 addr, uint8 val); +void put_mword(uint16 addr, uint16 val); +t_stat SBC_config(void); + +// globals + +int onetime = 0; + +/* external function prototypes */ + +extern t_stat monitor_reset (void); +extern t_stat monitor_cfg(void); +extern t_stat fp_reset (void); +extern t_stat fp_cfg(void); +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +extern uint8 EPROM_get_mbyte(uint16 addr); +extern uint8 EPROM1_get_mbyte(uint16 addr); +extern t_stat multibus_cfg(void); +extern uint8 multibus_get_mbyte(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern t_stat i3214_cfg(uint8 base, uint8 devnum); + +// external globals + +extern uint8 monitor_boot; +extern DEVICE i8080_dev; +extern uint8 i3214_mask; +extern uint8 EPROM_enable; +extern uint8 i3214_cnt; +extern uint8 i3214_ram[16]; +extern uint8 BUS_OVERRIDE; + +t_stat SBC_config(void) +{ + sim_printf("Configuring MDS-800 CPU Card\n Onboard Devices:\n"); + i3214_cfg(I3214_BASE, 0); + fp_cfg(); + monitor_cfg(); + return SCPE_OK; +} + +/* SBC reset routine + put here to cause a reset of the entire MDS-800 system */ + +t_stat SBC_reset (DEVICE *dptr) +{ + if (onetime == 0) { + SBC_config(); + multibus_cfg(); + onetime++; + } + i8080_reset(&i8080_dev); + EPROM_enable = 1; + BUS_OVERRIDE = 0; + fp_reset(); + monitor_reset(); + return SCPE_OK; +} + +// memory operations + +/* get a byte from memory - handle RAM, ROM and Multibus memory */ + +uint8 get_mbyte(uint16 addr) +{ + uint8 val; + + if (((monitor_boot & 0x04) == 0) && (addr >= ROM0_BASE && addr <= ROM0_BASE + ROM0_SIZE)) + val = EPROM_get_mbyte(addr); + else if (ROM1_SIZE && addr >= ROM1_BASE && addr <= ROM1_BASE + ROM1_SIZE) + val = EPROM1_get_mbyte(addr); + else val = multibus_get_mbyte(addr); + val &= 0xFF; + return(val); +} + +/* get a word from memory */ + +uint16 get_mword(uint16 addr) +{ + uint16 val; + + val = get_mbyte(addr); + val |= (get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory - handle RAM, ROM and Multibus memory */ + +void put_mbyte(uint16 addr, uint8 val) +{ + multibus_put_mbyte(addr, val); +} + +/* put a word to memory */ + +void put_mword(uint16 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of cpu.c */ diff --git a/Intel-Systems/imds-800/front_panel.c b/Intel-Systems/imds-800/front_panel.c new file mode 100644 index 00000000..d3dfe492 --- /dev/null +++ b/Intel-Systems/imds-800/front_panel.c @@ -0,0 +1,64 @@ +/* front_panel.c: Intel MDS-800 Front Panel Module simulator + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + + 5 October 2017 - Original file. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat fp_reset (void); +t_stat fp_cfg(void); + +/* external function prototypes */ + +extern t_stat EPROM_reset(DEVICE *dptr); +extern t_stat EPROM_cfg(uint16 base, uint16 size); + +/* external globals */ + +extern DEVICE *EPROM_dev; + +t_stat fp_cfg(void) +{ + sim_printf("Configuring MDS-800 Front Panel Card\n Onboard Devices:\n"); + EPROM_cfg(ROM0_BASE, ROM0_SIZE); + return SCPE_OK; +} + +/* CPU reset routine + put here to cause a reset of the entire IPC system */ + +t_stat fp_reset (void) +{ + EPROM_reset(EPROM_dev); + return SCPE_OK; +} + +/* end of front_panel.c */ diff --git a/Intel-Systems/imds-800/imds-800_sys.c b/Intel-Systems/imds-800/imds-800_sys.c new file mode 100644 index 00000000..93f0ba2b --- /dev/null +++ b/Intel-Systems/imds-800/imds-800_sys.c @@ -0,0 +1,84 @@ +/* mds-800_sys.c: multibus system interface + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + 5 October 2017 - Original file. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE i3214_dev; +extern DEVICE EPROM_dev; +extern DEVICE EPROM1_dev; +extern DEVICE RAM_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE zx200a_dev; +extern DEVICE isbc064_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel MDS-800"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &EPROM_dev, + &EPROM1_dev, + &i8251_dev, + &i3214_dev, + &multibus_dev, + &isbc064_dev, + &isbc201_dev, + &isbc202_dev, + &zx200a_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + +/* end of mds-800_sys.c */ + diff --git a/Intel-Systems/imds-800/monitor.c b/Intel-Systems/imds-800/monitor.c new file mode 100644 index 00000000..8384a942 --- /dev/null +++ b/Intel-Systems/imds-800/monitor.c @@ -0,0 +1,77 @@ +/* monitor.c: Intel MDS-800 Monitor Module simulator + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + + 5 October 2017 - Original file. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat monitor_cfg(void); +t_stat monitor_reset (void); + +/* external function prototypes */ + +extern t_stat i8251_reset(DEVICE *dptr); +extern t_stat i8251_cfg(uint8 base, uint8 devnum); +extern t_stat EPROM1_reset(DEVICE *dptr); +extern t_stat EPROM1_cfg(uint16 base, uint16 size); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern uint8 i3214_monitor_do_boot(t_bool io, uint8 data, uint8 devnum); + +// external globals + +extern uint32 PCX; /* program counter */ +extern DEVICE *i8251_dev; +extern DEVICE *EPROM1_dev; +extern uint8 monitor_boot; + +// globals + +t_stat monitor_cfg(void) +{ + sim_printf("Configuring MDS-800 Monitor Card\n Onboard Devices:\n"); + EPROM1_cfg(ROM1_BASE, ROM1_SIZE); + i8251_cfg(I8251_BASE_0, 0); + i8251_cfg(I8251_BASE_1, 1); + return SCPE_OK; +} + +/* Monitor reset routine + put here to cause a reset of the entire IPC system */ + +t_stat monitor_reset (void) +{ + monitor_boot = 0x00; + i8251_reset(i8251_dev); + EPROM1_reset(EPROM1_dev); + return SCPE_OK; +} + +/* end of monitor.c */ diff --git a/Intel-Systems/imds-800/system_defs.h b/Intel-Systems/imds-800/system_defs.h new file mode 100644 index 00000000..d12f48ee --- /dev/null +++ b/Intel-Systems/imds-800/system_defs.h @@ -0,0 +1,140 @@ +/* system_defs.h: Intel iSBC simulator definitions + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + 5 October 2017 - Original file. +*/ + +#include +#include +#include "sim_defs.h" /* simulator defns */ + +#define SET_XACK(VAL) (xack = VAL) + +/* set the base I/O address for the 8251 */ +#define I8251_BASE_0 0xF4 //TTY +#define I8251_BASE_1 0xF6 //CRT +#define I8251_NUM 2 + +// set the base I/O address for the 3214 +#define I3214_BASE 0xFC +#define I3214_NUM 1 + +/* set the base and size for the EPROM0 on the Monitor Module */ +#define ROM0_BASE 0x0000 +#define ROM0_SIZE 0x00FF +#define ROM0_DISABLE 1 + +/* set the base and size for the EPROM1 on the Front Panel Module */ +#define ROM1_BASE 0xF800 +#define ROM1_SIZE 0x07FF +#define ROM1_DISABLE 0 + +//board definitions for the multibus +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x88 +#define SBC201_INT INT_3 +#define SBC201_NUM 1 + +/* set the base I/O address for the iSBC 202 */ +#define SBC202_BASE 0x78 +#define SBC202_INT INT_3 +#define SBC202_NUM 1 + +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_1 +#define SBC206_NUM 0 + +/* set the base I/O address for the iSBC 208 */ +#define SBC208_BASE 0x40 +#define SBC208_INT INT_1 +#define SBC208_NUM 0 + +/* set the base for the ZX-200a disk controller */ +#define ZX200A_BASE 0x78 +#define ZX200A_INT INT_2 +#define ZX200A_NUM 0 + +/* set the base and size for the iSBC 064 */ +#define SBC064_BASE 0x0000 +#define SBC064_SIZE 0xF7FF +#define SBC064_NUM 1 + +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x47FF +#define SBC464_NUM 0 + +/* set INTR for CPU */ +#define INTR INT_2 + +/* multibus interrupt definitions */ + +#define INT_0 0x01 +#define INT_1 0x02 +#define INT_2 0x04 +#define INT_3 0x08 +#define INT_4 0x10 +#define INT_5 0x20 +#define INT_6 0x40 +#define INT_7 0x80 + +/* CPU interrupt definitions */ + +#define INT_R 0x200 +#define I75 0x40 +#define I65 0x20 +#define I55 0x10 + +/* Memory */ + +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) + +/* debug definitions */ + +#define DEBUG_flow 0x0001 +#define DEBUG_read 0x0002 +#define DEBUG_write 0x0004 +#define DEBUG_level1 0x0008 +#define DEBUG_level2 0x0010 +#define DEBUG_reg 0x0020 +#define DEBUG_asm 0x0040 +#define DEBUG_xack 0x0080 +#define DEBUG_all 0xFFFF + +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ + +/* end of system_defs.h */ diff --git a/Intel-Systems/imds-810/cpu.c b/Intel-Systems/imds-810/cpu.c new file mode 100644 index 00000000..e7614fa0 --- /dev/null +++ b/Intel-Systems/imds-810/cpu.c @@ -0,0 +1,142 @@ +/* cpu.c: Intel MDS-810 CPU Module simulator + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + + 5 October 2017 - Original file. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat SBC_config(void); +t_stat SBC_reset (DEVICE *dptr); +uint8 get_mbyte(uint16 addr); +uint16 get_mword(uint16 addr); +void put_mbyte(uint16 addr, uint8 val); +void put_mword(uint16 addr, uint16 val); + +// globals + +int onetime = 0; + +/* external function prototypes */ + +extern t_stat monitor_reset (void); +extern t_stat fp_reset (void); +extern t_stat i3214_reset (DEVICE *dptr); +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +extern uint8 EPROM_get_mbyte(uint16 addr); +extern uint8 EPROM1_get_mbyte(uint16 addr); +extern uint8 multibus_get_mbyte(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern t_stat i3214_cfg(uint8 base, uint8 devnum); +extern t_stat fp_cfg(void); +extern t_stat monitor_cfg(void); +extern t_stat multibus_cfg(void); + +// external globals + +extern uint32 PCX; /* program counter */ +extern DEVICE i3214_dev; +extern DEVICE i8080_dev; +extern uint8 EPROM_enable; +extern uint8 BUS_OVERRIDE; + +t_stat SBC_config(void) +{ + sim_printf("Configuring MDS-800 CPU Module\n Onboard Devices:\n"); + i3214_cfg(I3214_BASE, 0); + fp_cfg(); + monitor_cfg(); + return SCPE_OK; +} + +/* SBC reset routine + put here to cause a reset of the entire MDS-800 system */ + +t_stat SBC_reset (DEVICE *dptr) +{ + if (onetime == 0) { + SBC_config(); + multibus_cfg(); + onetime++; + } + EPROM_enable = 1; + BUS_OVERRIDE = 0; + i8080_reset(&i8080_dev); + i3214_reset(&i3214_dev); + fp_reset(); + monitor_reset(); + return SCPE_OK; +} + +// memory operations + +/* get a byte from memory - handle RAM, ROM and Multibus memory */ + +uint8 get_mbyte(uint16 addr) +{ + uint8 val; + + if (EPROM_enable && (addr >= ROM0_BASE && addr <= ROM0_BASE + ROM0_SIZE)) + val = EPROM_get_mbyte(addr); + else if (ROM1_SIZE && addr >= ROM1_BASE && addr <= ROM1_BASE + ROM1_SIZE) + val = EPROM1_get_mbyte(addr); + else val = multibus_get_mbyte(addr); + val &= 0xFF; + return(val); +} + +/* get a word from memory */ + +uint16 get_mword(uint16 addr) +{ + uint16 val; + + val = get_mbyte(addr); + val |= (get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory - handle RAM, ROM and Multibus memory */ + +void put_mbyte(uint16 addr, uint8 val) +{ + multibus_put_mbyte(addr, val); +} + +/* put a word to memory */ + +void put_mword(uint16 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of cpu.c */ diff --git a/Intel-Systems/imds-810/front_panel.c b/Intel-Systems/imds-810/front_panel.c new file mode 100644 index 00000000..e4b4d87a --- /dev/null +++ b/Intel-Systems/imds-810/front_panel.c @@ -0,0 +1,68 @@ +/* front_panel.c: Intel MDS-800 Front Panel Module simulator + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + + 5 October 2017 - Original file. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat fp_reset (void); +t_stat fp_cfg(void); + +/* external function prototypes */ + +extern uint8 EPROM_get_mbyte(uint16 addr); +extern t_stat EPROM_reset(DEVICE *dptr); +extern t_stat EPROM_cfg(uint16 base, uint16 size); + +// external globals + +extern UNIT EPROM_unit; //1702 EPROM +extern uint32 PCX; /* program counter */ + +// fp configuration + +t_stat fp_cfg(void) +{ + sim_printf("Configuring MDS-800 Front Panel Module\n Onboard Devices:\n"); + EPROM_cfg(ROM0_BASE, ROM0_SIZE); + return SCPE_OK; +} + +/* CPU reset routine + put here to cause a reset of the entire IPC system */ + +t_stat fp_reset (void) +{ + return SCPE_OK; +} + + +/* end of front_panel.c */ diff --git a/Intel-Systems/imds-810/imds-810_sys.c b/Intel-Systems/imds-810/imds-810_sys.c new file mode 100644 index 00000000..b3d33360 --- /dev/null +++ b/Intel-Systems/imds-810/imds-810_sys.c @@ -0,0 +1,84 @@ +/* mds-810_sys.c: multibus system interface + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + 5 October 2017 - Original file. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE EPROM_dev; +extern DEVICE i3214_dev; +extern DEVICE EPROM1_dev; +extern DEVICE RAM_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE zx200a_dev; +extern DEVICE isbc064_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel MDS-810"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &EPROM_dev, + &EPROM1_dev, + &i8251_dev, + &i3214_dev, + &multibus_dev, + &isbc064_dev, + &isbc201_dev, + &isbc202_dev, + &zx200a_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + +/* end of mds-800_sys.c */ + diff --git a/Intel-Systems/imds-810/monitor.c b/Intel-Systems/imds-810/monitor.c new file mode 100644 index 00000000..de18ea30 --- /dev/null +++ b/Intel-Systems/imds-810/monitor.c @@ -0,0 +1,83 @@ +/* monitor.c: Intel MDS-800 Monitor Module simulator + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + + 5 October 2017 - Original file. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat monitor_cfg(void); +t_stat monitor_reset (void); + +/* external function prototypes */ + +extern uint8 monitor_do_boot(t_bool io, uint8 data); +extern uint8 EPROM1_get_mbyte(uint16 addr); +extern t_stat i3214_reset(DEVICE *dptr); +extern t_stat EPROM1_reset(DEVICE *dptr); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern t_stat EPROM1_cfg(uint16 base, uint16 size); +extern t_stat i8251_reset (DEVICE *dptr); +extern t_stat i8251_cfg(uint8 base, uint8 size); + +// external globals + +extern uint32 PCX; /* program counter */ +extern UNIT EPROM1_unit; //8316 PROM +extern DEVICE *i8251_dev; +extern DEVICE *EPROM1_dev; + +// globals + +extern uint8 monitor_boot; + +// fp configuration + +t_stat monitor_cfg(void) +{ + sim_printf("Initializing MDS-800 Monitor Module\n Onboard Devices:\n"); + EPROM1_cfg(ROM1_BASE, ROM1_SIZE); + i8251_cfg(I8251_BASE_0, 0); + i8251_cfg(I8251_BASE_1, 1); + return SCPE_OK; +} + +/* Monitor reset routine + put here to cause a reset of the entire IPC system */ + +t_stat monitor_reset (void) +{ + monitor_boot = 0x00; + i8251_reset(i8251_dev); + EPROM1_reset(EPROM1_dev); + return SCPE_OK; +} + +/* end of monitor.c */ diff --git a/Intel-Systems/imds-810/system_defs.h b/Intel-Systems/imds-810/system_defs.h new file mode 100644 index 00000000..eccff4be --- /dev/null +++ b/Intel-Systems/imds-810/system_defs.h @@ -0,0 +1,140 @@ +/* system_defs.h: Intel iSBC simulator definitions + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + 5 October 2017 - Original file. +*/ + +#include +#include +#include "sim_defs.h" /* simulator defns */ + +#define SET_XACK(VAL) (xack = VAL) + +/* set the base I/O address for the 8251 */ +#define I8251_BASE_0 0xF4 //TTY +#define I8251_BASE_1 0xF6 //CRT +#define I8251_NUM 2 + +// set the base I/O address for the 3214 +#define I3214_BASE 0xFC +#define I3214_NUM 1 + +/* set the base and size for the EPROM0 on the Monitor Module */ +#define ROM0_BASE 0x0000 +#define ROM0_SIZE 0x00FF +#define ROM0_DISABLE 1 + +/* set the base and size for the EPROM1 on the Front Panel Module */ +#define ROM1_BASE 0xF800 +#define ROM1_SIZE 0x07FF +#define ROM1_DISABLE 1 + +//board definitions for the multibus +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x88 +#define SBC201_INT INT_3 +#define SBC201_NUM 1 + +/* set the base I/O address for the iSBC 202 */ +#define SBC202_BASE 0x78 +#define SBC202_INT INT_3 +#define SBC202_NUM 1 + +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_1 +#define SBC206_NUM 0 + +/* set the base I/O address for the iSBC 208 */ +#define SBC208_BASE 0x40 +#define SBC208_INT INT_2 +#define SBC208_NUM 0 + +/* set the base for the ZX-200a disk controller */ +#define ZX200A_BASE 0x78 +#define ZX200A_INT INT_2 +#define ZX200A_NUM 0 + +/* set the base and size for the iSBC 064 */ +#define SBC064_BASE 0x0000 +#define SBC064_SIZE 0xFFFF +#define SBC064_NUM 1 + +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x47FF +#define SBC464_NUM 0 + +/* set INTR for CPU */ +#define INTR INT_3 + +/* multibus interrupt definitions */ + +#define INT_0 0x01 +#define INT_1 0x02 +#define INT_2 0x04 +#define INT_3 0x08 +#define INT_4 0x10 +#define INT_5 0x20 +#define INT_6 0x40 +#define INT_7 0x80 + +/* CPU interrupt definitions */ + +#define INT_R 0x200 +#define I75 0x40 +#define I65 0x20 +#define I55 0x10 + +/* Memory */ + +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) + +/* debug definitions */ + +#define DEBUG_flow 0x0001 +#define DEBUG_read 0x0002 +#define DEBUG_write 0x0004 +#define DEBUG_level1 0x0008 +#define DEBUG_level2 0x0010 +#define DEBUG_reg 0x0020 +#define DEBUG_asm 0x0040 +#define DEBUG_xack 0x0080 +#define DEBUG_all 0xFFFF + +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ + +/* end of system_defs.h */ diff --git a/Intel-Systems/isys8010/isbc8010.c b/Intel-Systems/isys8010/isbc8010.c index 78f04246..d0e348e5 100644 --- a/Intel-Systems/isys8010/isbc8010.c +++ b/Intel-Systems/isys8010/isbc8010.c @@ -1,4 +1,4 @@ -/* iSBC80-10.c: Intel iSBC 80/10 Processor simulator +/* iSBC8010.c: Intel iSBC 80/10 Processor simulator Copyright (c) 2010, William A. Beech @@ -38,15 +38,23 @@ /* function prototypes */ +t_stat SBC_config(void); +t_stat SBC_reset (DEVICE *dptr); uint8 get_mbyte(uint16 addr); uint16 get_mword(uint16 addr); void put_mbyte(uint16 addr, uint8 val); void put_mword(uint16 addr, uint16 val); -t_stat SBC_reset (DEVICE *dptr); /* external globals */ extern uint8 i8255_C[4]; //port C byte I/O +extern DEVICE *i8080_dev; +extern DEVICE *i8251_dev; +extern DEVICE *i8255_dev; +extern DEVICE *EPROM_dev; +extern UNIT EPROM_unit; +extern DEVICE *RAM_dev; +extern UNIT RAM_unit; /* external function prototypes */ @@ -56,28 +64,44 @@ extern uint8 EPROM_get_mbyte(uint16 addr); extern uint8 RAM_get_mbyte(uint16 addr); extern void RAM_put_mbyte(uint16 addr, uint8 val); extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 i8251_devnum; -extern t_stat i8251_reset (DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern UNIT EPROM_unit; -extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); -extern UNIT RAM_unit; -extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); +extern t_stat i8251_reset (DEVICE *dptr); +extern t_stat i8255_reset (DEVICE *dptr); +extern t_stat EPROM_reset (DEVICE *dptr); +extern t_stat RAM_reset (DEVICE *dptr); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern t_stat i8251_cfg(uint8 base, uint8 devnum); +extern t_stat i8255_cfg(uint8 base, uint8 devnum); +extern t_stat RAM_cfg(uint16 base, uint16 size); +extern t_stat EPROM_cfg(uint16 base, uint16 size); +extern t_stat multibus_cfg(); + +/* globals */ + +int onetime = 0; + +t_stat SBC_config(void) +{ + sim_printf("Configuring iSBC-80/10 SBC\n Onboard Devices:\n"); + i8251_cfg(I8251_BASE, 0); + i8255_cfg(I8255_BASE_0, 0); + i8255_cfg(I8255_BASE_1, 1); + EPROM_cfg(ROM_BASE, ROM_SIZE); + RAM_cfg(RAM_BASE, RAM_SIZE); + return SCPE_OK; +} /* SBC reset routine */ t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing iSBC-80/10 SBC\n Onboard Devices:\n"); - i8080_reset (NULL); - i8251_devnum = 0; - i8251_reset (NULL, I8251_BASE); - i8255_devnum = 0; - i8255_reset (NULL, I8255_BASE_0); - i8255_reset (NULL, I8255_BASE_1); - EPROM_reset (NULL, ROM_SIZE); - RAM_reset (NULL, RAM_BASE, RAM_SIZE); +{ + if (onetime == 0) { + SBC_config(); + multibus_cfg(); + onetime++; + } + i8080_reset(i8080_dev); + i8251_reset(i8251_dev); + i8255_reset(i8255_dev); return SCPE_OK; } @@ -86,7 +110,7 @@ t_stat SBC_reset (DEVICE *dptr) uint8 get_mbyte(uint16 addr) { /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((ROM_DISABLE && (i8255_C[0] & 0x80)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { return EPROM_get_mbyte(addr); } @@ -115,14 +139,14 @@ uint16 get_mword(uint16 addr) void put_mbyte(uint16 addr, uint8 val) { /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { + if ((ROM_DISABLE && (i8255_C[0] & 0x80)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { sim_printf("Write to R/O memory address %04X - ignored\n", addr); return; } } /* if local RAM handle it */ if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { + if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { RAM_put_mbyte(addr, val); return; } @@ -131,11 +155,10 @@ void put_mbyte(uint16 addr, uint8 val) } /* put a word to memory */ - void put_mword(uint16 addr, uint16 val) { put_mbyte(addr, val & 0xff); put_mbyte(addr+1, val >> 8); } -/* end of iSBC80-10.c */ +/* end of iSBC8010.c */ diff --git a/Intel-Systems/isys8010/isys8010_sys.c b/Intel-Systems/isys8010/isys8010_sys.c index 6d5247ee..e95c9d30 100644 --- a/Intel-Systems/isys8010/isys8010_sys.c +++ b/Intel-Systems/isys8010/isys8010_sys.c @@ -38,8 +38,11 @@ extern DEVICE RAM_dev; extern DEVICE multibus_dev; extern DEVICE isbc201_dev; extern DEVICE isbc202_dev; +extern DEVICE isbc206_dev; +extern DEVICE isbc208_dev; extern DEVICE zx200a_dev; extern DEVICE isbc064_dev; +extern DEVICE isbc464_dev; /* SCP data structures @@ -64,8 +67,11 @@ DEVICE *sim_devices[] = { &i8255_dev, &multibus_dev, &isbc064_dev, + &isbc464_dev, &isbc201_dev, &isbc202_dev, + &isbc206_dev, + &isbc208_dev, &zx200a_dev, NULL }; @@ -77,6 +83,7 @@ const char *sim_stop_messages[] = { "Breakpoint", "Invalid Opcode", "Invalid Memory", - "XACK Error" + "XACK Error", + NULL }; diff --git a/Intel-Systems/isys8010/system_defs.h b/Intel-Systems/isys8010/system_defs.h index ad982e89..171cae14 100644 --- a/Intel-Systems/isys8010/system_defs.h +++ b/Intel-Systems/isys8010/system_defs.h @@ -28,12 +28,13 @@ #include #include +#include #include "sim_defs.h" /* simulator defns */ #define SET_XACK(VAL) (xack = VAL) //chip definitions for the iSBC-80/10 -/* set the base I/O address and device count for the 8251s */ +/* set the base I/O address and device count for the 8251 */ #define I8251_BASE 0xEC #define I8251_NUM 1 @@ -44,43 +45,54 @@ /* set the base and size for the EPROM on the iSBC 80/10 */ #define ROM_BASE 0x0000 -#define ROM_SIZE 0x1000 +#define ROM_SIZE 0x0FFF #define ROM_DISABLE 1 +#define EPROM_NUM 1 /* set the base and size for the RAM on the iSBC 80/10 */ #define RAM_BASE 0x3C00 -#define RAM_SIZE 0x0400 +#define RAM_SIZE 0x03FF #define RAM_DISABLE 1 /* set INTR for CPU on the iSBC 80/10 */ -#define INTR INT_1 +#define INTR INT_2 //board definitions for the multibus /* set the base I/O address for the iSBC 201 */ #define SBC201_BASE 0x88 -#define SBC201_INT INT_1 -#define SBC201_NUM 0 +#define SBC201_INT INT_2 +#define SBC201_NUM 1 /* set the base I/O address for the iSBC 202 */ #define SBC202_BASE 0x78 -#define SBC202_INT INT_1 +#define SBC202_INT INT_2 #define SBC202_NUM 1 +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_2 +#define SBC206_NUM 0 + /* set the base I/O address for the iSBC 208 */ #define SBC208_BASE 0x40 -#define SBC208_INT INT_1 -#define SBC208_NUM 0 +#define SBC208_INT INT_2 +#define SBC208_NUM 1 /* set the base for the zx-200a disk controller */ #define ZX200A_BASE 0x78 -#define ZX200A_INT INT_1 +#define ZX200A_INT INT_2 #define ZX200A_NUM 0 -/* set the base and size for the iSBC 064 */ +/* set the base and size for the iSBC 064 RAM*/ #define SBC064_BASE 0x0000 -#define SBC064_SIZE 0x10000 +#define SBC064_SIZE 0xFFFF #define SBC064_NUM 1 +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x4800 +#define SBC464_NUM 0 + /* multibus interrupt definitions */ #define INT_0 0x01 diff --git a/Intel-Systems/isys8020/isbc8020.c b/Intel-Systems/isys8020/isbc8020.c index 1dd917eb..95cd1b99 100644 --- a/Intel-Systems/isys8020/isbc8020.c +++ b/Intel-Systems/isys8020/isbc8020.c @@ -1,4 +1,4 @@ -/* iSBC80-20.c: Intel iSBC 80/20 Processor simulator +/* iSBC8020.c: Intel iSBC 80/20 Processor simulator Copyright (c) 2010, William A. Beech @@ -31,8 +31,11 @@ #include "system_defs.h" +int flag = 1; + /* function prototypes */ +t_stat SBC_config(void); uint8 get_mbyte(uint16 addr); uint16 get_mword(uint16 addr); void put_mbyte(uint16 addr, uint8 val); @@ -48,33 +51,76 @@ extern uint8 i8255_C[4]; //port C byte I/O extern uint8 multibus_get_mbyte(uint16 addr); extern void multibus_put_mbyte(uint16 addr, uint8 val); extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 i8251_devnum; -extern t_stat i8251_reset (DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern int32 i8259_devnum; -extern t_stat i8259_reset (DEVICE *dptr, uint16 base); +extern DEVICE *i8080_dev; +extern t_stat i8251_reset (DEVICE *dptr); +extern uint8 i8251s(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8251d(t_bool io, uint8 data, uint8 devnum); +extern DEVICE *i8251_dev; +extern t_stat i8253_reset (DEVICE *dptr); +extern uint8 i8253t0(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8253t1(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8253t2(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8253c(t_bool io, uint8 data, uint8 devnum); +extern DEVICE *i8253_dev; +extern t_stat i8255_reset (DEVICE *dptr); +extern uint8 i8255a(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8255b(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8255c(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8255s(t_bool io, uint8 data, uint8 devnum); +extern DEVICE *i8255_dev; +extern t_stat i8259_reset (DEVICE *dptr); +extern uint8 i8259a(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8259b(t_bool io, uint8 data, uint8 devnum); +extern DEVICE *i8259_dev; extern uint8 EPROM_get_mbyte(uint16 addr); extern UNIT EPROM_unit; -extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); +extern t_stat EPROM_reset (DEVICE *dptr); extern uint8 RAM_get_mbyte(uint16 addr); extern void RAM_put_mbyte(uint16 addr, uint8 val); extern UNIT RAM_unit; -extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); +extern t_stat RAM_reset (DEVICE *dptr); +extern t_stat i8251_cfg(uint8 base, uint8 devnum); +extern t_stat i8253_cfg(uint8 base, uint8 devnum); +extern t_stat i8255_cfg(uint8 base, uint8 devnum); +extern t_stat i8259_cfg(uint8 base, uint8 devnum); +extern t_stat RAM_cfg(uint16 base, uint16 size); +extern t_stat EPROM_cfg(uint16 base, uint16 size); +extern t_stat multibus_cfg(); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); + +// globals + +int onetime = 0; + +t_stat SBC_config(void) +{ + sim_printf("Configuring iSBC-80/20 SBC\n Onboard Devices:\n"); + i8251_cfg(I8251_BASE, 0); + i8253_cfg(I8253_BASE, 0); + i8255_cfg(I8255_BASE_0, 0); + i8255_cfg(I8255_BASE_1, 1); + i8259_cfg(I8259_BASE, 0); + EPROM_cfg(ROM_BASE, ROM_SIZE); + RAM_cfg(RAM_BASE, RAM_SIZE); + return SCPE_OK; +} /* CPU reset routine put here to cause a reset of the entire iSBC system */ t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing iSBC-80/20\n"); - i8080_reset(NULL); - i8251_reset(NULL, I8251_BASE); - i8255_reset(NULL, I8255_BASE_0); - i8255_reset(NULL, I8255_BASE_1); - i8259_reset(NULL, I8259_BASE); - EPROM_reset(NULL, ROM_SIZE); - RAM_reset(NULL, RAM_BASE, RAM_SIZE); +{ + if (onetime == 0) { + SBC_config(); + multibus_cfg(); + onetime++; + } + i8080_reset(i8080_dev); + i8251_reset(i8251_dev); + i8253_reset(i8253_dev); + i8255_reset(i8255_dev); + i8255_reset(i8255_dev); + i8259_reset(i8259_dev); return SCPE_OK; } @@ -84,11 +130,11 @@ uint8 get_mbyte(uint16 addr) { /* if local EPROM handle it */ if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && (addr < (EPROM_unit.u3 + EPROM_unit.capac))) + if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) return EPROM_get_mbyte(addr); } /* if local RAM handle it */ if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && (addr < (RAM_unit.u3 + RAM_unit.capac))) + if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) return RAM_get_mbyte(addr); } /* otherwise, try the multibus */ return multibus_get_mbyte(addr); @@ -111,13 +157,13 @@ void put_mbyte(uint16 addr, uint8 val) { /* if local EPROM handle it */ if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && (addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { + if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { sim_printf("Write to R/O memory address %04X - ignored\n", addr); return; } } /* if local RAM handle it */ if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && (addr <= (RAM_unit.u3 + RAM_unit.capac))) { + if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { RAM_put_mbyte(addr, val); return; } @@ -133,4 +179,4 @@ void put_mword(uint16 addr, uint16 val) put_mbyte(addr+1, val >> 8); } -/* end of iSBC80-20.c */ +/* end of iSBC8020.c */ diff --git a/Intel-Systems/isys8020/isys8020_sys.c b/Intel-Systems/isys8020/isys8020_sys.c index 7e24718c..9577074e 100644 --- a/Intel-Systems/isys8020/isys8020_sys.c +++ b/Intel-Systems/isys8020/isys8020_sys.c @@ -33,12 +33,14 @@ extern DEVICE i8080_dev; extern REG i8080_reg[]; extern DEVICE i8259_dev; extern DEVICE i8251_dev; +extern DEVICE i8253_dev; extern DEVICE i8255_dev; extern DEVICE EPROM_dev; extern DEVICE RAM_dev; extern DEVICE multibus_dev; extern DEVICE isbc201_dev; extern DEVICE isbc202_dev; +extern DEVICE isbc208_dev; extern DEVICE isbc064_dev; /* SCP data structures @@ -62,11 +64,13 @@ DEVICE *sim_devices[] = { &RAM_dev, &i8259_dev, &i8251_dev, + &i8253_dev, &i8255_dev, &multibus_dev, &isbc064_dev, &isbc201_dev, &isbc202_dev, + &isbc208_dev, NULL }; diff --git a/Intel-Systems/isys8020/system_defs.h b/Intel-Systems/isys8020/system_defs.h index e1943944..8cf38a6b 100644 --- a/Intel-Systems/isys8020/system_defs.h +++ b/Intel-Systems/isys8020/system_defs.h @@ -30,13 +30,17 @@ #include #include "sim_defs.h" /* simulator defns */ -#define SET_XACK(VAL) (xack = VAL) +#define SET_XACK(VAL) (xack = VAL) //chip definitions for the iSBC-80/20 /* set the base I/O address for the 8251 */ #define I8251_BASE 0xEC #define I8251_NUM 1 +/* set the base I/O address for the 8253/8254 */ +#define I8253_BASE 0xDC +#define I8253_NUM 1 + /* set the base I/O address for the 8255 */ #define I8255_BASE_0 0xE4 #define I8255_BASE_1 0xE8 @@ -48,43 +52,54 @@ /* set the base and size for the EPROM on the iSBC 80/20 */ #define ROM_BASE 0x0000 -#define ROM_SIZE 0x1000 +#define ROM_SIZE 0x0FFF #define ROM_DISABLE 1 +#define EPROM_NUM 1 /* set the base and size for the RAM on the iSBC 80/20 */ -#define RAM_BASE 0x3C00 -#define RAM_SIZE 0x0400 +#define RAM_BASE 0x3000 +#define RAM_SIZE 0x0FFF #define RAM_DISABLE 1 /* set INTR for CPU */ -#define INTR INT_1 +#define INTR INT_2 //board definitions for the multibus /* set the base I/O address for the iSBC 201 */ #define SBC201_BASE 0x78 -#define SBC201_INT INT_1 +#define SBC201_INT INT_2 #define SBC201_NUM 0 /* set the base I/O address for the iSBC 202 */ #define SBC202_BASE 0x78 -#define SBC202_INT INT_1 +#define SBC202_INT INT_2 #define SBC202_NUM 1 +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_2 +#define SBC206_NUM 0 + /* set the base I/O address for the iSBC 208 */ #define SBC208_BASE 0x40 -#define SBC208_INT INT_1 +#define SBC208_INT INT_2 #define SBC208_NUM 0 /* set the base for the zx-200a disk controller */ #define ZX200A_BASE 0x78 -#define ZX200A_INT INT_1 +#define ZX200A_INT INT_2 #define ZX200A_NUM 0 /* set the base and size for the iSBC 064 */ #define SBC064_BASE 0x0000 -#define SBC064_SIZE 0x10000 +#define SBC064_SIZE 0xFFFF #define SBC064_NUM 1 +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x4800 +#define SBC464_NUM 0 + /* multibus interrupt definitions */ #define INT_0 0x01 diff --git a/Intel-Systems/isys8024/isbc8024.c b/Intel-Systems/isys8024/isbc8024.c index fb7c63cf..5689f41f 100644 --- a/Intel-Systems/isys8024/isbc8024.c +++ b/Intel-Systems/isys8024/isbc8024.c @@ -37,6 +37,7 @@ /* function prototypes */ +t_stat SBC_config(void); uint8 get_mbyte(uint16 addr); uint16 get_mword(uint16 addr); void put_mbyte(uint16 addr, uint8 val); @@ -53,39 +54,74 @@ extern int32 PCX; /* External view of PC */ extern uint8 multibus_get_mbyte(uint16 addr); extern void multibus_put_mbyte(uint16 addr, uint8 val); extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 i8251_devnum; -extern t_stat i8251_reset (DEVICE *dptr, uint16 base); -extern int32 i8253_devnum; -extern t_stat i8253_reset (DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern int32 i8259_devnum; -extern t_stat i8259_reset (DEVICE *dptr, uint16 base); +extern DEVICE *i8080_dev; +extern t_stat i8251_reset (DEVICE *dptr); +extern uint8 i8251s(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8251d(t_bool io, uint8 data, uint8 devnum); +extern DEVICE *i8251_dev; +extern t_stat i8253_reset (DEVICE *dptr); +extern uint8 i8253t0(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8253t1(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8253t2(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8253c(t_bool io, uint8 data, uint8 devnum); +extern DEVICE *i8253_dev; +extern t_stat i8255_reset (DEVICE *dptr); +extern uint8 i8255a(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8255b(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8255c(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8255s(t_bool io, uint8 data, uint8 devnum); +extern DEVICE *i8255_dev; +extern t_stat i8259_reset (DEVICE *dptr); +extern uint8 i8259a(t_bool io, uint8 data, uint8 devnum); +extern uint8 i8259b(t_bool io, uint8 data, uint8 devnum); +extern DEVICE *i8259_dev; extern uint8 EPROM_get_mbyte(uint16 addr); extern UNIT EPROM_unit; -extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); +extern t_stat EPROM_reset (DEVICE *dptr, uint16 base, uint16 size); extern uint8 RAM_get_mbyte(uint16 addr); extern void RAM_put_mbyte(uint16 addr, uint8 val); extern UNIT RAM_unit; extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); +extern t_stat i8251_cfg(uint8 base, uint8 devnum); +extern t_stat i8253_cfg(uint8 base, uint8 devnum); +extern t_stat i8255_cfg(uint8 base, uint8 devnum); +extern t_stat i8259_cfg(uint8 base, uint8 devnum); +extern t_stat RAM_cfg(uint16 base, uint16 size); +extern t_stat EPROM_cfg(uint16 base, uint16 size); +extern t_stat multibus_cfg(); + +// globals + +int onetime = 0; + +t_stat SBC_config(void) +{ + sim_printf("Configuring iSBC-80/24 SBC\n Onboard Devices:\n"); + i8251_cfg(I8251_BASE, 0); + i8253_cfg(I8253_BASE, 0); + i8255_cfg(I8255_BASE_0, 0); + i8255_cfg(I8255_BASE_1, 1); + i8259_cfg(I8259_BASE, 0); + EPROM_cfg(ROM_BASE, ROM_SIZE); + RAM_cfg(RAM_BASE, RAM_SIZE); + return SCPE_OK; +} /* SBC reset routine */ t_stat SBC_reset (DEVICE *dptr) { - sim_printf("Initializing iSBC-80/24 SBC\n Onboard Devices:\n"); - i8080_reset (NULL); - i8251_devnum = 0; - i8251_reset (NULL, I8251_BASE); - i8253_devnum = 0; - i8253_reset (NULL, I8253_BASE); - i8255_devnum = 0; - i8255_reset (NULL, I8255_BASE_0); - i8255_reset (NULL, I8255_BASE_1); - i8259_devnum = 0; - i8259_reset (NULL, I8259_BASE); - EPROM_reset (NULL, ROM_SIZE); - RAM_reset (NULL, RAM_BASE, RAM_SIZE); + if (onetime == 0) { + SBC_config(); + multibus_cfg(); + onetime++; + } + i8080_reset(i8080_dev); + i8251_reset(i8251_dev); + i8253_reset(i8253_dev); + i8255_reset(i8255_dev); + i8255_reset(i8255_dev); + i8259_reset(i8259_dev); return SCPE_OK; } diff --git a/Intel-Systems/isys8024/system_defs.h b/Intel-Systems/isys8024/system_defs.h index 2850be4a..b433b1c4 100644 --- a/Intel-Systems/isys8024/system_defs.h +++ b/Intel-Systems/isys8024/system_defs.h @@ -52,12 +52,13 @@ /* set the base and size for the EPROM on the iSBC 80/10 */ #define ROM_BASE 0x0000 -#define ROM_SIZE 0x1000 +#define ROM_SIZE 0x0FFF #define ROM_DISABLE 1 +#define EPROM_NUM 1 /* set the base and size for the RAM on the iSBC 80/10 */ #define RAM_BASE 0xF000 -#define RAM_SIZE 0x1000 +#define RAM_SIZE 0x0FFF #define RAM_DISABLE 0 /* set INTR for CPU on the iSBC 80/10 */ @@ -74,21 +75,39 @@ #define SBC202_INT INT_1 #define SBC202_NUM 1 +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_2 +#define SBC206_NUM 0 + /* set the base for the zx-200a disk controller */ #define ZX200A_BASE 0x78 #define ZX200A_INT INT_1 #define ZX200A_NUM 0 +/* set the base I/O address for the iSBX 218 */ +#define SBC208_BASE 0x40 +#define SBC208_INT INT_1 +#define SBC208_NUM 0 +#define I8272_BASE 0xF0 +#define I8272_NUM 1 +#define I8272_INT INT_1 + /* set the base I/O address for the iSBC 208 */ -#define SBC208_BASE 0x40 +#define SBC208_BASE 0x40 #define SBC208_INT INT_1 #define SBC208_NUM 0 /* set the base and size for the iSBC 064 */ #define SBC064_BASE 0x0000 -#define SBC064_SIZE 0x10000 +#define SBC064_SIZE 0xFFFF #define SBC064_NUM 1 +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x4800 +#define SBC464_NUM 0 + /* multibus interrupt definitions */ #define INT_0 0x01 diff --git a/Intel-Systems/isys8030/isbc8030.c b/Intel-Systems/isys8030/isbc8030.c index 32421b7a..f3bb4649 100644 --- a/Intel-Systems/isys8030/isbc8030.c +++ b/Intel-Systems/isys8030/isbc8030.c @@ -37,6 +37,7 @@ /* function prototypes */ +t_stat SBC_config(void); uint8 get_mbyte(uint16 addr); uint16 get_mword(uint16 addr); void put_mbyte(uint16 addr, uint8 val); @@ -46,44 +47,67 @@ t_stat SBC_reset (DEVICE *dptr); /* external globals */ extern uint8 i8255_C[4]; //port C byte I/O +extern int32 PCX; /* external function prototypes */ extern uint8 multibus_get_mbyte(uint16 addr); extern void multibus_put_mbyte(uint16 addr, uint8 val); extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 i8251_devnum; -extern t_stat i8251_reset (DEVICE *dptr, uint16 base); -extern int32 i8253_devnum; -extern t_stat i8253_reset (DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern int32 i8259_devnum; -extern t_stat i8259_reset (DEVICE *dptr, uint16 base); +extern DEVICE *i8080_dev; +extern t_stat i8251_reset (DEVICE *dptr); +extern DEVICE *i8251_dev; +extern t_stat i8253_reset (DEVICE *dptr); +extern DEVICE *i8253_dev; +extern t_stat i8255_reset (DEVICE *dptr); +extern DEVICE *i8255_dev; +extern t_stat i8259_reset (DEVICE *dptr); +extern DEVICE *i8259_dev; extern uint8 EPROM_get_mbyte(uint16 addr); extern UNIT EPROM_unit; -extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); +extern t_stat EPROM_reset (DEVICE *dptr, uint16 base, uint16 size); extern uint8 RAM_get_mbyte(uint16 addr); extern void RAM_put_mbyte(uint16 addr, uint8 val); extern UNIT RAM_unit; extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); +extern t_stat i8251_cfg(uint8 base, uint8 devnum); +extern t_stat i8253_cfg(uint8 base, uint8 devnum); +extern t_stat i8255_cfg(uint8 base, uint8 devnum); +extern t_stat i8259_cfg(uint8 base, uint8 devnum); +extern t_stat RAM_cfg(uint16 base, uint16 size); +extern t_stat EPROM_cfg(uint16 base, uint16 size); +extern t_stat multibus_cfg(); + +// globals + +int onetime = 0; + +t_stat SBC_config(void) +{ + sim_printf("Configuring iSBC-80/30 SBC\n Onboard Devices:\n"); + i8251_cfg(I8251_BASE, 0); + i8253_cfg(I8253_BASE, 0); + i8255_cfg(I8255_BASE, 0); + i8259_cfg(I8259_BASE, 0); + EPROM_cfg(ROM_BASE, ROM_SIZE); + RAM_cfg(RAM_BASE, RAM_SIZE); + return SCPE_OK; +} /* SBC reset routine */ t_stat SBC_reset (DEVICE *dptr) { - sim_printf("Initializing iSBC-80/24:\n"); - i8080_reset (NULL); - i8251_devnum = 0; - i8251_reset (NULL, I8251_BASE); - i8253_devnum = 0; - i8253_reset (NULL, I8253_BASE); - i8255_devnum = 0; - i8255_reset (NULL, I8255_BASE); - i8259_devnum = 0; - i8259_reset (NULL, I8259_BASE); - EPROM_reset (NULL, ROM_SIZE); - RAM_reset (NULL, RAM_BASE, RAM_SIZE); + if (onetime == 0) { + SBC_config(); + multibus_cfg(); + onetime++; + } + i8080_reset(i8080_dev); + i8251_reset(i8251_dev); + i8253_reset(i8253_dev); + i8255_reset(i8255_dev); + i8259_reset(i8259_dev); return SCPE_OK; } @@ -92,12 +116,12 @@ t_stat SBC_reset (DEVICE *dptr) uint8 get_mbyte(uint16 addr) { /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((ROM_DISABLE && (i8255_C[0] & 0x80)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { return EPROM_get_mbyte(addr); } } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { return RAM_get_mbyte(addr); } @@ -121,13 +145,13 @@ uint16 get_mword(uint16 addr) void put_mbyte(uint16 addr, uint8 val) { /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((ROM_DISABLE && (i8255_C[0] & 0x80)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { - sim_printf("Write to R/O memory address %04X - ignored\n", addr); + sim_printf("Write to R/O memory address %04X from %04X - ignored\n", addr, PCX); return; } } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { RAM_put_mbyte(addr, val); return; diff --git a/Intel-Systems/isys8030/system_defs.h b/Intel-Systems/isys8030/system_defs.h index 717477d6..1daf48bc 100644 --- a/Intel-Systems/isys8030/system_defs.h +++ b/Intel-Systems/isys8030/system_defs.h @@ -55,12 +55,13 @@ /* set the base and size for the EPROM on the iSBC 80/30 */ #define ROM_BASE 0x0000 -#define ROM_SIZE 0x1000 +#define ROM_SIZE 0x0FFF #define ROM_DISABLE 1 +#define EPROM_NUM 1 /* set the base and size for the RAM on the iSBC 80/30 */ #define RAM_BASE 0xF000 -#define RAM_SIZE 0x1000 +#define RAM_SIZE 0x0FFF #define RAM_DISABLE 0 /* set INTR for CPU on the iSBC 80/30 */ @@ -77,21 +78,31 @@ #define SBC202_INT INT_1 #define SBC202_NUM 1 -/* set the base for the zx-200a disk controller */ -#define ZX200A_BASE 0x78 -#define ZX200A_INT INT_1 -#define ZX200A_NUM 0 +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_1 +#define SBC206_NUM 0 /* set the base I/O address for the iSBC 208 */ #define SBC208_BASE 0x40 #define SBC208_INT INT_1 #define SBC208_NUM 0 +/* set the base for the zx-200a disk controller */ +#define ZX200A_BASE 0x78 +#define ZX200A_INT INT_1 +#define ZX200A_NUM 0 + /* set the base and size for the iSBC 064 */ #define SBC064_BASE 0x0000 -#define SBC064_SIZE 0x10000 +#define SBC064_SIZE 0xFFFF #define SBC064_NUM 1 +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x4800 +#define SBC464_NUM 0 + /* multibus interrupt definitions */ #define INT_0 0x01 diff --git a/Intel-Systems/isys80XX/isys80XX_sys.c b/Intel-Systems/isys80XX/isys80XX_sys.c new file mode 100644 index 00000000..2eb3fc15 --- /dev/null +++ b/Intel-Systems/isys80XX/isys80XX_sys.c @@ -0,0 +1,92 @@ +/* 1sys80XX_sys.c: multibus system interface + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + ?? ??? 10 - Original file. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE i8253_dev; +extern DEVICE i8255_dev; +extern DEVICE i8259_dev; +extern DEVICE EPROM_dev; +extern DEVICE sbc_dev; +extern DEVICE RAM_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE isbc206_dev; +extern DEVICE zx200a_dev; +extern DEVICE isbc064_dev; +extern DEVICE isbc464_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel OEM SBC System"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &EPROM_dev, + &RAM_dev, + &i8251_dev, + &i8253_dev, + &i8255_dev, + &i8259_dev, + &sbc_dev, + &multibus_dev, + &isbc064_dev, + &isbc464_dev, + &isbc201_dev, + &isbc202_dev, + &isbc206_dev, + &zx200a_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error", + NULL +}; + diff --git a/Intel-Systems/isys80XX/system_defs.h b/Intel-Systems/isys80XX/system_defs.h new file mode 100644 index 00000000..8256e461 --- /dev/null +++ b/Intel-Systems/isys80XX/system_defs.h @@ -0,0 +1,150 @@ +/* system_defs.h: Intel iSBC simulator definitions + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + ?? ??? 10 - Original file. +*/ + +#include +#include +#include +#include "sim_defs.h" /* simulator defns */ + +#define SET_XACK(VAL) (xack = VAL) + +//chip definitions for the iSBC-80/10 +/* set the base I/O address and device count for the 8251s */ +#define I8251_BASE 0xEC +#define I8251_NUM 1 + +/* set the base I/O address for the 8253/8254 */ +#define I8253_BASE 0xDC +#define I8253_NUM 1 + +/* set the base I/O address and device count for the 8255s */ +#define I8255_BASE_0 0xE4 +#define I8255_BASE_1 0xE8 +#define I8255_NUM 2 + +/* set the base I/O address for the 8259 */ +#define I8259_BASE 0xDA +#define I8259_NUM 1 + +/* set the base and size for the EPROM on the iSBC 80/10 */ +#define ROM_BASE 0x0000 +#define ROM_SIZE 0x1000 +#define ROM_DISABLE 1 +#define EPROM_NUM 1 + +/* set the base and size for the RAM on the iSBC 80/10 */ +#define RAM_BASE 0x3C00 +#define RAM_SIZE 0x0400 +#define RAM_DISABLE 1 + +/* set INTR for CPU on the iSBC 80/10 */ +#define INTR INT_1 + +//board definitions for the multibus +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x88 +#define SBC201_INT INT_1 +#define SBC201_NUM 1 + +/* set the base I/O address for the iSBC 202 */ +#define SBC202_BASE 0x78 +#define SBC202_INT INT_1 +#define SBC202_NUM 1 + +/* set the base I/O address for the iSBC 206 */ +#define SBC206_BASE 0x68 +#define SBC206_INT INT_1 +#define SBC206_NUM 1 + +/* set the base I/O address for the iSBC 208 */ +#define SBC208_BASE 0x40 +#define SBC208_INT INT_1 +#define SBC208_NUM 0 + +/* set the base for the zx-200a disk controller */ +#define ZX200A_BASE 0x78 +#define ZX200A_INT INT_1 +#define ZX200A_NUM 1 + +/* set the base and size for the iSBC 064 RAM*/ +#define SBC064_BASE 0x0000 +#define SBC064_SIZE 0x10000 +#define SBC064_NUM 1 + +/* set the base and size for the iSBC 464 ROM */ +#define SBC464_BASE 0xA800 +#define SBC464_SIZE 0x4800 +#define SBC464_NUM 1 + +/* multibus interrupt definitions */ + +#define INT_0 0x01 +#define INT_1 0x02 +#define INT_2 0x04 +#define INT_3 0x08 +#define INT_4 0x10 +#define INT_5 0x20 +#define INT_6 0x40 +#define INT_7 0x80 + +/* CPU interrupts definitions */ + +#define INT_R 0x200 +#define I75 0x40 +#define I65 0x20 +#define I55 0x10 + +/* Memory */ + +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) + +/* debug definitions */ + +#define DEBUG_flow 0x0001 +#define DEBUG_read 0x0002 +#define DEBUG_write 0x0004 +#define DEBUG_level1 0x0008 +#define DEBUG_level2 0x0010 +#define DEBUG_reg 0x0020 +#define DEBUG_asm 0x0040 +#define DEBUG_xack 0x0080 +#define DEBUG_all 0xFFFF + +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ + diff --git a/Visual Studio Projects/Simh.sln b/Visual Studio Projects/Simh.sln index 32995061..19972ee8 100644 --- a/Visual Studio Projects/Simh.sln +++ b/Visual Studio Projects/Simh.sln @@ -383,6 +383,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PDP10-KI", "PDP10-KI.vcproj {D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imds-210", "imds-210.vcproj", "{1BCAB163-8041-48C3-9A5C-73649D69ED5C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imds-220", "imds-220.vcproj", "{2532CA88-7206-44F0-97EB-927F7E7820F2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imds-230", "imds-230.vcproj", "{C81A7EA9-8043-45F9-AFBB-578A6DB98174}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imds-800", "imds-800.vcproj", "{17ADE01C-7EDC-4F11-974D-52A9F90FE1D8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imds-810", "imds-810.vcproj", "{0720F164-692E-4C07-BE69-41C4302062E5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -697,6 +707,26 @@ Global {0BA63EC5-BD4F-44FB-AE89-7DD2C84CB1D9}.Debug|Win32.Build.0 = Debug|Win32 {0BA63EC5-BD4F-44FB-AE89-7DD2C84CB1D9}.Release|Win32.ActiveCfg = Release|Win32 {0BA63EC5-BD4F-44FB-AE89-7DD2C84CB1D9}.Release|Win32.Build.0 = Release|Win32 + {1BCAB163-8041-48C3-9A5C-73649D69ED5C}.Debug|Win32.ActiveCfg = Debug|Win32 + {1BCAB163-8041-48C3-9A5C-73649D69ED5C}.Debug|Win32.Build.0 = Debug|Win32 + {1BCAB163-8041-48C3-9A5C-73649D69ED5C}.Release|Win32.ActiveCfg = Release|Win32 + {1BCAB163-8041-48C3-9A5C-73649D69ED5C}.Release|Win32.Build.0 = Release|Win32 + {2532CA88-7206-44F0-97EB-927F7E7820F2}.Debug|Win32.ActiveCfg = Debug|Win32 + {2532CA88-7206-44F0-97EB-927F7E7820F2}.Debug|Win32.Build.0 = Debug|Win32 + {2532CA88-7206-44F0-97EB-927F7E7820F2}.Release|Win32.ActiveCfg = Release|Win32 + {2532CA88-7206-44F0-97EB-927F7E7820F2}.Release|Win32.Build.0 = Release|Win32 + {C81A7EA9-8043-45F9-AFBB-578A6DB98174}.Debug|Win32.ActiveCfg = Debug|Win32 + {C81A7EA9-8043-45F9-AFBB-578A6DB98174}.Debug|Win32.Build.0 = Debug|Win32 + {C81A7EA9-8043-45F9-AFBB-578A6DB98174}.Release|Win32.ActiveCfg = Release|Win32 + {C81A7EA9-8043-45F9-AFBB-578A6DB98174}.Release|Win32.Build.0 = Release|Win32 + {17ADE01C-7EDC-4F11-974D-52A9F90FE1D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {17ADE01C-7EDC-4F11-974D-52A9F90FE1D8}.Debug|Win32.Build.0 = Debug|Win32 + {17ADE01C-7EDC-4F11-974D-52A9F90FE1D8}.Release|Win32.ActiveCfg = Release|Win32 + {17ADE01C-7EDC-4F11-974D-52A9F90FE1D8}.Release|Win32.Build.0 = Release|Win32 + {0720F164-692E-4C07-BE69-41C4302062E5}.Debug|Win32.ActiveCfg = Debug|Win32 + {0720F164-692E-4C07-BE69-41C4302062E5}.Debug|Win32.Build.0 = Debug|Win32 + {0720F164-692E-4C07-BE69-41C4302062E5}.Release|Win32.ActiveCfg = Release|Win32 + {0720F164-692E-4C07-BE69-41C4302062E5}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Visual Studio Projects/imds-210.vcproj b/Visual Studio Projects/imds-210.vcproj new file mode 100644 index 00000000..82f59662 --- /dev/null +++ b/Visual Studio Projects/imds-210.vcproj @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Visual Studio Projects/imds-220.vcproj b/Visual Studio Projects/imds-220.vcproj new file mode 100644 index 00000000..24f39c68 --- /dev/null +++ b/Visual Studio Projects/imds-220.vcproj @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Visual Studio Projects/imds-225.vcproj b/Visual Studio Projects/imds-225.vcproj index 09b4eab9..1d31e49d 100644 --- a/Visual Studio Projects/imds-225.vcproj +++ b/Visual Studio Projects/imds-225.vcproj @@ -228,7 +228,7 @@ > + + @@ -247,6 +251,18 @@ RelativePath="..\Intel-Systems\common\isbc202.c" > + + + + + + diff --git a/Visual Studio Projects/imds-230.vcproj b/Visual Studio Projects/imds-230.vcproj new file mode 100644 index 00000000..68a6b742 --- /dev/null +++ b/Visual Studio Projects/imds-230.vcproj @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Visual Studio Projects/imds-800.vcproj b/Visual Studio Projects/imds-800.vcproj new file mode 100644 index 00000000..2389fc7d --- /dev/null +++ b/Visual Studio Projects/imds-800.vcproj @@ -0,0 +1,373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Visual Studio Projects/imds-810.vcproj b/Visual Studio Projects/imds-810.vcproj new file mode 100644 index 00000000..6266fd2b --- /dev/null +++ b/Visual Studio Projects/imds-810.vcproj @@ -0,0 +1,373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Visual Studio Projects/isys8010.vcproj b/Visual Studio Projects/isys8010.vcproj index 40f06a6c..6eb0836a 100644 --- a/Visual Studio Projects/isys8010.vcproj +++ b/Visual Studio Projects/isys8010.vcproj @@ -223,10 +223,18 @@ RelativePath="..\Intel-Systems\common\isbc202.c" > + + + + diff --git a/Visual Studio Projects/isys8020.vcproj b/Visual Studio Projects/isys8020.vcproj index ac59853c..75842bb3 100644 --- a/Visual Studio Projects/isys8020.vcproj +++ b/Visual Studio Projects/isys8020.vcproj @@ -199,6 +199,10 @@ RelativePath="..\Intel-Systems\common\i8251.c" > + + @@ -227,10 +231,18 @@ RelativePath="..\Intel-Systems\common\isbc202.c" > + + + + diff --git a/Visual Studio Projects/isys8024.vcproj b/Visual Studio Projects/isys8024.vcproj index 8b485aa1..24cd0d5d 100644 --- a/Visual Studio Projects/isys8024.vcproj +++ b/Visual Studio Projects/isys8024.vcproj @@ -231,10 +231,18 @@ RelativePath="..\Intel-Systems\common\isbc202.c" > + + + + diff --git a/Visual Studio Projects/isys8030.vcproj b/Visual Studio Projects/isys8030.vcproj index 1f2aa6a6..839c92c9 100644 --- a/Visual Studio Projects/isys8030.vcproj +++ b/Visual Studio Projects/isys8030.vcproj @@ -231,10 +231,18 @@ RelativePath="..\Intel-Systems\common\isbc202.c" > + + + + diff --git a/makefile b/makefile index 18a890f2..ba1d9c76 100644 --- a/makefile +++ b/makefile @@ -1731,7 +1731,9 @@ ISYS8010 = ${ISYS8010C}/i8080.c ${ISYS8010D}/isys8010_sys.c \ ${ISYS8010C}/ieprom.c ${ISYS8010C}/iram8.c \ ${ISYS8010C}/multibus.c ${ISYS8010D}/isbc8010.c \ ${ISYS8010C}/isbc064.c ${ISYS8010C}/isbc202.c \ - ${ISYS8010C}/isbc201.c ${ISYS8010C}/zx200a.c + ${ISYS8010C}/isbc201.c ${ISYS8010C}/zx200a.c \ + ${ISYS8010C}/isbc206.c ${ISYS8010C}/isbc464.c \ + ${ISYS8010C}/isbc208.c ISYS8010_OPT = -I ${ISYS8010D} @@ -1742,8 +1744,10 @@ ISYS8020 = ${ISYS8020C}/i8080.c ${ISYS8020D}/isys8020_sys.c \ ${ISYS8020C}/ieprom.c ${ISYS8020C}/iram8.c \ ${ISYS8020C}/multibus.c ${ISYS8020D}/isbc8020.c \ ${ISYS8020C}/isbc064.c ${ISYS8020C}/i8259.c \ - ${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \ - ${ISYS8010C}/zx200a.c + ${ISYS8020C}/isbc202.c ${ISYS8020C}/isbc201.c \ + ${ISYS8020C}/isbc206.c ${ISYS8020C}/isbc464.c \ + ${ISYS8020C}/zx200a.c ${ISYS8020C}/i8253.c \ + ${ISYS8020C}/isbc208.c ISYS8020_OPT = -I ${ISYS8020D} @@ -1755,8 +1759,9 @@ ISYS8024 = ${ISYS8024C}/i8080.c ${ISYS8024D}/isys8024_sys.c \ ${ISYS8024C}/ieprom.c ${ISYS8024C}/iram8.c \ ${ISYS8024C}/multibus.c ${ISYS8024D}/isbc8024.c \ ${ISYS8024C}/isbc064.c ${ISYS8024C}/isbc208.c \ - ${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \ - ${ISYS8010C}/zx200a.c + ${ISYS8024C}/isbc202.c ${ISYS8024C}/isbc201.c \ + ${ISYS8024C}/isbc206.c ${ISYS8024C}/isbc464.c \ + ${ISYS8024C}/zx200a.c ISYS8024_OPT = -I ${ISYS8024D} @@ -1767,24 +1772,95 @@ ISYS8030 = ${ISYS8030C}/i8080.c ${ISYS8030D}/isys8030_sys.c \ ${ISYS8030C}/i8259.c ${ISYS8030C}/i8253.c \ ${ISYS8030C}/ieprom.c ${ISYS8030C}/iram8.c \ ${ISYS8030C}/multibus.c ${ISYS8030D}/isbc8030.c \ - ${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \ - ${ISYS8030C}/isbc064.c ${ISYS8010C}/zx200a.c + ${ISYS8030C}/isbc202.c ${ISYS8030C}/isbc201.c \ + ${ISYS8030C}/isbc206.c ${ISYS8030C}/isbc464.c \ + ${ISYS8030C}/isbc064.c ${ISYS8030C}/zx200a.c \ + ${ISYS8010C}/isbc208.c ISYS8030_OPT = -I ${ISYS8030D} +IMDS-210D = Intel-Systems/imds-210 +IMDS-210C = Intel-Systems/common +IMDS-210 = ${IMDS-210C}/i8080.c ${IMDS-210D}/imds-210_sys.c \ + ${IMDS-210C}/i8251.c ${IMDS-210C}/i8255.c \ + ${IMDS-210C}/i8259.c ${IMDS-210C}/i8253.c \ + ${IMDS-210C}/ieprom.c ${IMDS-210C}/iram8.c \ + ${IMDS-210C}/ipbmultibus.c ${IMDS-210C}/ipb.c \ + ${IMDS-210C}/ipc-cont.c ${IMDS-210C}/ioc-cont.c \ + ${IMDS-210C}/isbc202.c ${IMDS-210C}/isbc201.c \ + ${IMDS-210C}/isbc206.c ${IMDS-210C}/isbc464.c \ + ${IMDS-210C}/zx200a.c ${IMDS-210C}/isbc064.c +IMDS-210_OPT = -I ${IMDS-210D} + + +IMDS-220D = Intel-Systems/imds-220 +IMDS-220C = Intel-Systems/common +IMDS-220 = ${IMDS-220C}/i8080.c ${IMDS-220D}/imds-220_sys.c \ + ${IMDS-220C}/i8251.c ${IMDS-220C}/i8255.c \ + ${IMDS-220C}/i8259.c ${IMDS-220C}/i8253.c \ + ${IMDS-220C}/ieprom.c ${IMDS-220C}/iram8.c \ + ${IMDS-220C}/ipbmultibus.c ${IMDS-220C}/ipb.c \ + ${IMDS-220C}/ipc-cont.c ${IMDS-220C}/ioc-cont.c \ + ${IMDS-220C}/isbc202.c ${IMDS-220C}/isbc201.c \ + ${IMDS-220C}/isbc206.c ${IMDS-220C}/isbc464.c \ + ${IMDS-220C}/zx200a.c ${IMDS-220C}/isbc064.c +IMDS-220_OPT = -I ${IMDS-220D} + + IMDS-225D = Intel-Systems/imds-225 IMDS-225C = Intel-Systems/common IMDS-225 = ${IMDS-225C}/i8080.c ${IMDS-225D}/imds-225_sys.c \ ${IMDS-225C}/i8251.c ${IMDS-225C}/i8255.c \ ${IMDS-225C}/i8259.c ${IMDS-225C}/i8253.c \ ${IMDS-225C}/ieprom.c ${IMDS-225C}/iram8.c \ - ${IMDS-225C}/ipcmultibus.c ${IMDS-225D}/ipc.c \ + ${IMDS-225C}/ipcmultibus.c ${IMDS-225C}/ipc.c \ ${IMDS-225C}/ipc-cont.c ${IMDS-225C}/ioc-cont.c \ ${IMDS-225C}/isbc202.c ${IMDS-225C}/isbc201.c \ - ${IMDS-225C}/zx200a.c + ${IMDS-225C}/zx200a.c ${IMDS-225C}/isbc464.c \ + ${IMDS-225C}/isbc206.c IMDS-225_OPT = -I ${IMDS-225D} +IMDS-230D = Intel-Systems/imds-230 +IMDS-230C = Intel-Systems/common +IMDS-230 = ${IMDS-230C}/i8080.c ${IMDS-230D}/imds-230_sys.c \ + ${IMDS-230C}/i8251.c ${IMDS-230C}/i8255.c \ + ${IMDS-230C}/i8259.c ${IMDS-230C}/i8253.c \ + ${IMDS-230C}/ieprom.c ${IMDS-230C}/iram8.c \ + ${IMDS-230C}/ipbmultibus.c ${IMDS-230C}/ipb.c \ + ${IMDS-230C}/ipc-cont.c ${IMDS-230C}/ioc-cont.c \ + ${IMDS-230C}/isbc202.c ${IMDS-230C}/isbc201.c \ + ${IMDS-230C}/isbc206.c ${IMDS-230C}/isbc464.c \ + ${IMDS-230C}/zx200a.c ${IMDS-230C}/isbc064.c +IMDS-230_OPT = -I ${IMDS-230D} + + +IMDS-800D = Intel-Systems/imds-800 +IMDS-800C = Intel-Systems/common +IMDS-800 = ${IMDS-800C}/i8080.c ${IMDS-800D}/imds-800_sys.c \ + ${IMDS-800D}/cpu.c ${IMDS-800D}/front_panel.c \ + ${IMDS-800D}/monitor.c ${IMDS-800C}/ieprom1.c \ + ${IMDS-800C}/i8251.c ${IMDS-800C}/ieprom.c \ + ${IMDS-800C}/m800multibus.c ${IMDS-800C}/isbc064.c \ + ${IMDS-800C}/isbc202.c ${IMDS-800C}/isbc201.c \ + ${IMDS-800C}/zx200a.c ${IMDS-800C}/isbc464.c \ + ${IMDS-800C}/isbc206.c ${IMDS-800C}/i3214.c +IMDS-800_OPT = -I ${IMDS-800D} + + +IMDS-810D = Intel-Systems/imds-810 +IMDS-810C = Intel-Systems/common +IMDS-810 = ${IMDS-800C}/i8080.c ${IMDS-810D}/imds-810_sys.c \ + ${IMDS-810D}/cpu.c ${IMDS-810D}/front_panel.c \ + ${IMDS-810D}/monitor.c ${IMDS-810C}/ieprom1.c \ + ${IMDS-810C}/i8251.c ${IMDS-810C}/ieprom.c \ + ${IMDS-810C}/m800multibus.c ${IMDS-810C}/isbc064.c \ + ${IMDS-810C}/isbc202.c ${IMDS-810C}/isbc201.c \ + ${IMDS-810C}/zx200a.c ${IMDS-810C}/isbc464.c \ + ${IMDS-810C}/isbc206.c ${IMDS-800C}/i3214.c +IMDS-810_OPT = -I ${IMDS-810D} + + IBMPCD = Intel-Systems/ibmpc IBMPCC = Intel-Systems/common IBMPC = ${IBMPCC}/i8255.c ${IBMPCD}/ibmpc.c \ @@ -2022,7 +2098,8 @@ ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \ nova eclipse hp2100 hp3000 i1401 i1620 s3 altair altairz80 gri \ i7094 ibm1130 id16 id32 sds lgp h316 cdc1700 \ swtp6800mp-a swtp6800mp-a2 tx-0 ssem b5500 isys8010 isys8020 \ - isys8030 isys8024 imds-225 scelbi 3b2 i701 i704 i7010 i7070 i7080 i7090 \ + isys8030 isys8024 imds-210 imds-220 imds-225 imds-230 imds-800 imds-810 \ + scelbi 3b2 i701 i704 i7010 i7070 i7080 i7090 \ sigma uc15 pdp10-ka pdp10-ki pdp6 all : ${ALL} @@ -2516,6 +2593,24 @@ ifneq (,$(call find_test,${ISYS8030D},isys8030)) $@ $(call find_test,${ISYS8030D},isys8030) $(TEST_ARG) endif +imds-210: ${BIN}imds-210${EXE} + +${BIN}imds-210${EXE} : ${IMDS-210} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS-210} ${SIM} ${IMDS-210_OPT} $(CC_OUTSPEC) ${LDFLAGS} +ifneq (,$(call find_test,${IMDS-210D},imds-210)) + $@ $(call find_test,${IMDS-210D},imds-210) $(TEST_ARG) +endif + +imds-220: ${BIN}imds-220${EXE} + +${BIN}imds-220${EXE} : ${IMDS-220} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS-220} ${SIM} ${IMDS-220_OPT} $(CC_OUTSPEC) ${LDFLAGS} +ifneq (,$(call find_test,${IMDS-220D},imds-220)) + $@ $(call find_test,${IMDS-220D},imds-220) $(TEST_ARG) +endif + imds-225: ${BIN}imds-225${EXE} ${BIN}imds-225${EXE} : ${IMDS-225} ${SIM} ${BUILD_ROMS} @@ -2525,6 +2620,33 @@ ifneq (,$(call find_test,${IMDS-225D},imds-225)) $@ $(call find_test,${IMDS-225D},imds-225) $(TEST_ARG) endif +imds-230: ${BIN}imds-230${EXE} + +${BIN}imds-230${EXE} : ${IMDS-230} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS-230} ${SIM} ${IMDS-230_OPT} $(CC_OUTSPEC) ${LDFLAGS} +ifneq (,$(call find_test,${IMDS-230D},imds-230)) + $@ $(call find_test,${IMDS-230D},imds-230) $(TEST_ARG) +endif + +imds-800: ${BIN}imds-800${EXE} + +${BIN}imds-800${EXE} : ${IMDS-800} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS-800} ${SIM} ${IMDS-800_OPT} $(CC_OUTSPEC) ${LDFLAGS} +ifneq (,$(call find_test,${IMDS-800D},imds-800)) + $@ $(call find_test,${IMDS-800D},imds-800) $(TEST_ARG) +endif + +imds-810: ${BIN}imds-810${EXE} + +${BIN}imds-810${EXE} : ${IMDS-810} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS-810} ${SIM} ${IMDS-810_OPT} $(CC_OUTSPEC) ${LDFLAGS} +ifneq (,$(call find_test,${IMDS-810D},imds-810)) + $@ $(call find_test,${IMDS-810D},imds-810) $(TEST_ARG) +endif + ibmpc: ${BIN}ibmpc${EXE} ${BIN}ibmpc${EXE} : ${IBMPC} ${SIM} ${BUILD_ROMS}