From cbdcaec1622c04124436da6d2a0b989836763c54 Mon Sep 17 00:00:00 2001 From: Bill Beech Date: Mon, 23 May 2016 14:28:19 -0700 Subject: [PATCH] ISYS8010, ISYS8020: Cleanup Build issues for gcc and clang and g++ and clang++ Corrected declaration sizes to match for consistency across different modules. --- Intel-Systems/common/i8080.c | 21 +- Intel-Systems/common/i8251.c | 71 +- Intel-Systems/common/i8255.c | 350 +---- Intel-Systems/common/i8259.c | 245 ++-- Intel-Systems/common/i8273.c | 2 +- Intel-Systems/common/ieprom.c | 26 +- Intel-Systems/common/ipata.c | 206 +++ Intel-Systems/common/iram8.c | 28 +- Intel-Systems/common/isbc064.c | 35 +- Intel-Systems/common/isbc064b.c | 256 ---- Intel-Systems/common/isbc064x.c | 205 --- Intel-Systems/common/isbc208.c | 1140 +++++++++-------- Intel-Systems/common/isbc80-10.c | 75 +- Intel-Systems/common/isbc80-20.c | 80 +- Intel-Systems/common/isbc80-30.c | 86 +- Intel-Systems/common/mds-800.c | 143 --- Intel-Systems/common/multibus.c | 49 +- Intel-Systems/isys8010/System_80-10.vsd | Bin 57856 -> 0 bytes .../isys8010/functional description.vsd | Bin 57344 -> 0 bytes Intel-Systems/isys8010/isys8010.txt | 211 --- Intel-Systems/isys8010/isys8010_cfg.h | 41 - Intel-Systems/isys8010/system_defs.h | 33 +- Intel-Systems/isys8020/system_defs.h | 36 +- .../isys8030_cfg.h} | 0 Visual Studio Projects/isys8020.vcproj | 2 +- 25 files changed, 1224 insertions(+), 2117 deletions(-) create mode 100644 Intel-Systems/common/ipata.c delete mode 100644 Intel-Systems/common/isbc064b.c delete mode 100644 Intel-Systems/common/isbc064x.c delete mode 100644 Intel-Systems/common/mds-800.c delete mode 100644 Intel-Systems/isys8010/System_80-10.vsd delete mode 100644 Intel-Systems/isys8010/functional description.vsd delete mode 100644 Intel-Systems/isys8010/isys8010.txt delete mode 100644 Intel-Systems/isys8010/isys8010_cfg.h rename Intel-Systems/{isys8020/isys8020_cfg.h => isys8030/isys8030_cfg.h} (100%) diff --git a/Intel-Systems/common/i8080.c b/Intel-Systems/common/i8080.c index 3a979222..065436e0 100644 --- a/Intel-Systems/common/i8080.c +++ b/Intel-Systems/common/i8080.c @@ -165,7 +165,7 @@ uint32 HL = 0; /* HL register pair */ uint32 SP = 0; /* Stack pointer */ uint32 saved_PC = 0; /* program counter */ uint32 IM = 0; /* Interrupt Mask Register */ -uint32 xack = 0; /* XACK signal */ +uint8 xack = 0; /* XACK signal */ uint32 int_req = 0; /* Interrupt request */ int32 PCX; /* External view of PC */ @@ -197,16 +197,17 @@ t_stat i8080_reset (DEVICE *dptr); /* external function prototypes */ extern t_stat i8080_reset (DEVICE *dptr); -extern int32 get_mbyte(int32 addr); -extern int32 get_mword(int32 addr); -extern void put_mbyte(int32 addr, int32 val); -extern void put_mword(int32 addr, int32 val); +extern uint8 get_mbyte(uint16 addr); +extern uint16 get_mword(uint16 addr); +extern void put_mbyte(uint16 addr, uint8 val); +extern void put_mword(uint16 addr, uint16 val); extern int32 sim_int_char; extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ struct idev { - int32 (*routine)(int32, int32); + uint8 (*routine)(t_bool, uint8, uint8); + uint8 devnum; }; /* This is the I/O configuration table. There are 256 possible @@ -889,13 +890,15 @@ int32 sim_instr (void) case 0xDB: /* IN */ DAR = fetch_byte(1); - A = dev_table[DAR].routine(0, 0); + A = dev_table[DAR].routine(0, 0, dev_table[DAR].devnum); A &= BYTE_R; +// sim_printf("\n%04X\tIN\t%02X\t;devnum=%d", PC - 1, DAR, dev_table[DAR].devnum); break; case 0xD3: /* OUT */ DAR = fetch_byte(1); - dev_table[DAR].routine(1, A); + dev_table[DAR].routine(1, A, dev_table[DAR].devnum); +// sim_printf("\n%04X\tOUT\t%02X\t;devnum=%d", PC - 1, DAR, dev_table[DAR].devnum); break; default: /* undefined opcode */ @@ -906,7 +909,7 @@ 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 instruction fetch */ reason = STOP_XACK; sim_printf("Stopped for XACK-2 PC=%04X\n", --PC); continue; diff --git a/Intel-Systems/common/i8251.c b/Intel-Systems/common/i8251.c index fbc19bb2..b414b43e 100644 --- a/Intel-Systems/common/i8251.c +++ b/Intel-Systems/common/i8251.c @@ -119,16 +119,18 @@ #define TXE 0x04 #define SD 0x40 -extern int32 reg_dev(int32 (*routine)(int32, int32), int32 port); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16, uint8); /* function prototypes */ t_stat i8251_svc (UNIT *uptr); -t_stat i8251_reset (DEVICE *dptr, int32 base); -int32 i8251s(int32 io, int32 data); -int32 i8251d(int32 io, int32 data); -void i8251_reset1(void); +t_stat i8251_reset (DEVICE *dptr, uint16 base, uint8 devnum); +uint8 i8251s(t_bool io, uint8 data, uint8 devnum); +uint8 i8251d(t_bool io, uint8 data, uint8 devnum); +void i8251_reset1(uint8 devnum); + /* i8251 Standard I/O Data Structures */ +/* up to 1 i8251 devices */ UNIT i8251_unit = { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT @@ -142,20 +144,33 @@ REG i8251_reg[] = { { NULL } }; +DEBTAB i8251_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + MTAB i8251_mod[] = { { UNIT_ANSI, 0, "TTY", "TTY", NULL }, { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, { 0 } }; +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + DEVICE i8251_dev = { "8251", //name &i8251_unit, //units i8251_reg, //registers i8251_mod, //modifiers 1, //numunits - 10, //aradix - 31, //awidth + 16, //aradix + 16, //awidth 1, //aincr 16, //dradix 8, //dwidth @@ -169,7 +184,7 @@ DEVICE i8251_dev = { NULL, //ctxt 0, //flags 0, //dctrl - NULL, //debflags + i8251_debug, //debflags NULL, //msize NULL //lname }; @@ -196,14 +211,18 @@ t_stat i8251_svc (UNIT *uptr) /* Reset routine */ -t_stat i8251_reset (DEVICE *dptr, int32 base) +t_stat i8251_reset (DEVICE *dptr, uint16 base, uint8 devnum) { - reg_dev(i8251d, base); - reg_dev(i8251s, base + 1); - reg_dev(i8251d, base + 2); - reg_dev(i8251s, base + 3); - i8251_reset1(); - sim_printf(" 8251: Registered at %02X\n", base); + if (devnum >= I8251_NUM) { + sim_printf("8251_reset: Illegal Device Number %d\n", devnum); + return 0; + } + reg_dev(i8251d, base, devnum); + reg_dev(i8251s, base + 1, devnum); + reg_dev(i8251d, base + 2, devnum); + reg_dev(i8251s, base + 3, devnum); + i8251_reset1(devnum); + sim_printf(" 8251-%d: Registered at %04X\n", devnum, base); sim_activate (&i8251_unit, i8251_unit.wait); /* activate unit */ return SCPE_OK; } @@ -212,28 +231,36 @@ t_stat i8251_reset (DEVICE *dptr, int32 base) IN or OUT instruction is issued. */ -int32 i8251s(int32 io, int32 data) +uint8 i8251s(t_bool io, uint8 data, uint8 devnum) { + if (devnum >= I8251_NUM) { + sim_printf("8251s: Illegal Device Number %d\n", devnum); + return 0; + } // 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; - sim_printf("8251: Command Instruction=%02X\n", data); + sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); if (data & SD) /* reset port! */ - i8251_reset1(); + i8251_reset1(devnum); } else { /* set mode */ i8251_unit.u4 = data; - sim_printf("8251: Mode Instruction=%02X\n", data); + sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); i8251_unit.u6 = 1; /* set cmd received */ } return (0); } } -int32 i8251d(int32 io, int32 data) +uint8 i8251d(t_bool io, uint8 data, uint8 devnum) { + if (devnum >= I8251_NUM) { + sim_printf("8251d: Illegal Device Number %d\n", devnum); + return 0; + } if (io == 0) { /* read data port */ i8251_unit.u3 &= ~RXR; return (i8251_unit.buf); @@ -243,7 +270,7 @@ int32 i8251d(int32 io, int32 data) return 0; } -void i8251_reset1(void) +void i8251_reset1(uint8 devnum) { i8251_unit.u3 = TXR + TXE; /* status */ i8251_unit.u4 = 0; /* mode instruction */ @@ -251,7 +278,7 @@ void i8251_reset1(void) i8251_unit.u6 = 0; i8251_unit.buf = 0; i8251_unit.pos = 0; - sim_printf(" 8251: Reset\n"); + sim_printf(" 8251-%d: Reset\n", devnum); } /* end of i8251.c */ diff --git a/Intel-Systems/common/i8255.c b/Intel-Systems/common/i8255.c index 51a03b43..9ee57c0c 100644 --- a/Intel-Systems/common/i8255.c +++ b/Intel-Systems/common/i8255.c @@ -76,38 +76,23 @@ */ #include "system_defs.h" /* system header in system dir */ -#define i8255_DEV 4 /* number of devices */ /* function prototypes */ -int32 i8255s0(int32 io, int32 data); /* i8255 0 */ -int32 i8255a0(int32 io, int32 data); -int32 i8255b0(int32 io, int32 data); -int32 i8255c0(int32 io, int32 data); -int32 i8255s1(int32 io, int32 data); /* i8255 1 */ -int32 i8255a1(int32 io, int32 data); -int32 i8255b1(int32 io, int32 data); -int32 i8255c1(int32 io, int32 data); -int32 i8255s2(int32 io, int32 data); /* i8255 2 */ -int32 i8255a2(int32 io, int32 data); -int32 i8255b2(int32 io, int32 data); -int32 i8255c2(int32 io, int32 data); -int32 i8255s3(int32 io, int32 data); /* i8255 3 */ -int32 i8255a3(int32 io, int32 data); -int32 i8255b3(int32 io, int32 data); -int32 i8255c3(int32 io, int32 data); -t_stat i8255_reset (DEVICE *dptr, int32 base); +uint8 i8255s0(t_bool io, uint8 data, uint8 devnum); /* i8255*/ +uint8 i8255a0(t_bool io, uint8 data, uint8 devnum); +uint8 i8255b0(t_bool io, uint8 data, uint8 devnum); +uint8 i8255c0(t_bool io, uint8 data, uint8 devnum); +t_stat i8255_reset (DEVICE *dptr, uint16 base, uint8 devnum); /* external function prototypes */ -extern int32 reg_dev(int32 (*routine)(int32, int32), int32 port); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); /* globals */ -int32 i8255_cnt = 0; -uint8 i8255_base[i8255_DEV]; - /* i8255 Standard I/O Data Structures */ +/* up to 4 i8255 devices */ UNIT i8255_unit[] = { { UDATA (0, 0, 0) }, /* i8255 0 */ @@ -116,17 +101,6 @@ UNIT i8255_unit[] = { { UDATA (0, 0, 0) } /* i8255 3 */ }; -DEBTAB i8255_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - REG i8255_reg[] = { { HRDATA (CONTROL0, i8255_unit[0].u3, 8) }, /* i8255 0 */ { HRDATA (PORTA0, i8255_unit[0].u4, 8) }, @@ -147,6 +121,19 @@ REG i8255_reg[] = { { NULL } }; +DEBTAB i8255_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + DEVICE i8255_dev = { "8255", //name i8255_unit, //units @@ -154,7 +141,7 @@ DEVICE i8255_dev = { NULL, //modifiers 1, //numunits 16, //aradix - 32, //awidth + 16, //awidth 1, //aincr 16, //dradix 8, //dwidth @@ -177,296 +164,99 @@ DEVICE i8255_dev = { IN or OUT instruction is issued. */ -/* i8255 0 functions */ +/* i8255 functions */ -int32 i8255s0(int32 io, int32 data) +uint8 i8255s(t_bool io, uint8 data, uint8 devnum) { - int32 bit; + uint8 bit; + if (devnum >= I8255_NUM) { + sim_printf("8255s: Illegal Device Number %d\n", devnum); + return 0; + } if (io == 0) { /* read status port */ - return i8255_unit[0].u3; + return i8255_unit[devnum].u3; } else { /* write status port */ if (data & 0x80) { /* mode instruction */ i8255_unit[0].u3 = data; - sim_printf("8255-0: Mode Instruction=%02X\n", data); + 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_unit[0].u6 |= (0x01 << bit); + i8255_unit[devnum].u6 |= (0x01 << bit); } else { /* reset bit */ - i8255_unit[0].u6 &= ~(0x01 << bit); + i8255_unit[devnum].u6 &= ~(0x01 << bit); } } } return 0; } -int32 i8255a0(int32 io, int32 data) +uint8 i8255a(t_bool io, uint8 data, uint8 devnum) { + if (devnum >= I8255_NUM) { + sim_printf("8255a: Illegal Device Number %d\n", devnum); + return 0; + } if (io == 0) { /* read data port */ - return (i8255_unit[0].u4); + return (i8255_unit[devnum].u4); } else { /* write data port */ - i8255_unit[0].u4 = data; - sim_printf("8255-0: Port A = %02X\n", data); + i8255_unit[devnum].u4 = data; + sim_printf(" 8255-%d: Port A = %02X\n", devnum, data); } return 0; } -int32 i8255b0(int32 io, int32 data) +uint8 i8255b(t_bool io, uint8 data, uint8 devnum) { + if (devnum >= I8255_NUM) { + sim_printf("8255b: Illegal Device Number %d\n", devnum); + return 0; + } if (io == 0) { /* read data port */ - return (i8255_unit[0].u5); + return (i8255_unit[devnum].u5); } else { /* write data port */ - i8255_unit[0].u5 = data; - sim_printf("8255-0: Port B = %02X\n", data); + i8255_unit[devnum].u5 = data; + sim_printf(" 8255-%d: Port B = %02X\n", devnum, data); } return 0; } -int32 i8255c0(int32 io, int32 data) +uint8 i8255c(t_bool io, uint8 data, uint8 devnum) { + if (devnum >= I8255_NUM) { + sim_printf("8255c: Illegal Device Number %d\n", devnum); + return 0; + } if (io == 0) { /* read data port */ - return (i8255_unit[0].u6); + return (i8255_unit[devnum].u6); } else { /* write data port */ - i8255_unit[0].u6 = data; - sim_printf("8255-0: Port C = %02X\n", data); - } - return 0; -} - -/* i8255 1 functions */ - -int32 i8255s1(int32 io, int32 data) -{ - int32 bit; - - if (io == 0) { /* read status port */ - return i8255_unit[1].u3; - } else { /* write status port */ - if (data & 0x80) { /* mode instruction */ - i8255_unit[1].u3 = data; - sim_printf("8255-1: Mode Instruction=%02X\n", 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_unit[1].u6 |= (0x01 << bit); - } else { /* reset bit */ - i8255_unit[1].u6 &= ~(0x01 << bit); - } - } - } - return 0; -} - -int32 i8255a1(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8255_unit[1].u4); - } else { /* write data port */ - i8255_unit[1].u4 = data; - sim_printf("8255-1: Port A = %02X\n", data); - } - return 0; -} - -int32 i8255b1(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8255_unit[1].u5); - } else { /* write data port */ - i8255_unit[1].u5 = data; - sim_printf("8255-1: Port B = %02X\n", data); - } - return 0; -} - -int32 i8255c1(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8255_unit[1].u6); - } else { /* write data port */ - i8255_unit[1].u6 = data; - sim_printf("8255-1: Port C = %02X\n", data); - } - return 0; -} - -/* i8255 2 functions */ - -int32 i8255s2(int32 io, int32 data) -{ - int32 bit; - - if (io == 0) { /* read status port */ - return i8255_unit[2].u3; - } else { /* write status port */ - if (data & 0x80) { /* mode instruction */ - i8255_unit[2].u3 = data; - sim_printf("8255-2: Mode Instruction=%02X\n", 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_unit[2].u6 |= (0x01 << bit); - } else { /* reset bit */ - i8255_unit[2].u6 &= ~(0x01 << bit); - } - } - } - return 0; -} - -int32 i8255a2(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8255_unit[2].u4); - } else { /* write data port */ - i8255_unit[2].u4 = data; - sim_printf("8255-2: Port A = %02X\n", data); - } - return 0; -} - -int32 i8255b2(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8255_unit[2].u5); - } else { /* write data port */ - i8255_unit[2].u5 = data; - sim_printf("8255-2: Port B = %02X\n", data); - } - return 0; -} - -int32 i8255c2(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8255_unit[2].u6); - } else { /* write data port */ - i8255_unit[2].u6 = data; - sim_printf("8255-2: Port C = %02X\n", data); - } - return 0; -} - -/* i8255 3 functions */ - -int32 i8255s3(int32 io, int32 data) -{ - int32 bit; - - if (io == 0) { /* read status port */ - return i8255_unit[3].u3; - } else { /* write status port */ - if (data & 0x80) { /* mode instruction */ - i8255_unit[3].u3 = data; - sim_printf("8255-3: Mode Instruction=%02X\n", data); - if (data & 0x64) - sim_printf("\n Mode 1 and 2 not yet implemented\n"); - } else { /* bit set */ - bit = (data & 0x0E) >> 1; /* get bit number */ - if (data & 0x01) { /* set bit */ - i8255_unit[3].u6 |= (0x01 << bit); - } else { /* reset bit */ - i8255_unit[3].u6 &= ~(0x01 << bit); - } - } - } - return 0; -} - -int32 i8255a3(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8255_unit[3].u4); - } else { /* write data port */ - i8255_unit[3].u4 = data; - sim_printf("8255-3: Port A = %02X\n", data); - } - return 0; -} - -int32 i8255b3(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8255_unit[3].u5); - } else { /* write data port */ - i8255_unit[3].u5 = data; - sim_printf("8255-3: Port B = %02X\n", data); - } - return 0; -} - -int32 i8255c3(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8255_unit[3].u6); - } else { /* write data port */ - i8255_unit[3].u6 = data; - sim_printf("8255-3: Port C = %02X\n", data); + i8255_unit[devnum].u6 = data; + sim_printf(" 8255-%d: Port C = %02X\n", devnum, data); } return 0; } /* Reset routine */ -t_stat i8255_reset (DEVICE *dptr, int32 base) +t_stat i8255_reset (DEVICE *dptr, uint16 base, uint8 devnum) { - switch (i8255_cnt) { - case 0: - reg_dev(i8255a0, base); - reg_dev(i8255b0, base + 1); - reg_dev(i8255c0, base + 2); - reg_dev(i8255s0, base + 3); - i8255_unit[0].u3 = 0x9B; /* control */ - i8255_unit[0].u4 = 0xFF; /* Port A */ - i8255_unit[0].u5 = 0xFF; /* Port B */ - i8255_unit[0].u6 = 0xFF; /* Port C */ - sim_printf(" 8255-0: Reset\n"); - break; - case 1: - reg_dev(i8255a1, base); - reg_dev(i8255b1, base + 1); - reg_dev(i8255c1, base + 2); - reg_dev(i8255s1, base + 3); - i8255_unit[1].u3 = 0x9B; /* control */ - i8255_unit[1].u4 = 0xFF; /* Port A */ - i8255_unit[1].u5 = 0xFF; /* Port B */ - i8255_unit[1].u6 = 0xFF; /* Port C */ - sim_printf(" 8255-1: Reset\n"); - break; - case 2: - reg_dev(i8255a2, base); - reg_dev(i8255b2, base + 1); - reg_dev(i8255c2, base + 2); - reg_dev(i8255s2, base + 3); - i8255_unit[2].u3 = 0x9B; /* control */ - i8255_unit[2].u4 = 0xFF; /* Port A */ - i8255_unit[2].u5 = 0xFF; /* Port B */ - i8255_unit[2].u6 = 0xFF; /* Port C */ - sim_printf(" 8255-2: Reset\n"); - break; - case 3: - reg_dev(i8255a3, base); - reg_dev(i8255b3, base + 1); - reg_dev(i8255c3, base + 2); - reg_dev(i8255s3, base + 3); - i8255_unit[3].u3 = 0x9B; /* control */ - i8255_unit[3].u4 = 0xFF; /* Port A */ - i8255_unit[3].u5 = 0xFF; /* Port B */ - i8255_unit[3].u6 = 0xFF; /* Port C */ - sim_printf(" 8255-3: Reset\n"); - break; - default: - sim_printf(" 8255: Bad device\n"); + if (devnum >= I8255_NUM) { + sim_printf("8255_reset: Illegal Device Number %d\n", devnum); + return 0; } - sim_printf(" 8255-%d: Registered at %02X\n", i8255_cnt, base); - i8255_cnt++; + reg_dev(i8255a, base, devnum); + reg_dev(i8255b, base + 1, devnum); + reg_dev(i8255c, base + 2, devnum); + reg_dev(i8255s, base + 3, devnum); + i8255_unit[devnum].u3 = 0x9B; /* control */ + i8255_unit[devnum].u4 = 0xFF; /* Port A */ + i8255_unit[devnum].u5 = 0xFF; /* Port B */ + i8255_unit[devnum].u6 = 0xFF; /* Port C */ + sim_printf(" 8255-%d: Reset\n", devnum); + sim_printf(" 8255-%d: Registered at %04X\n", devnum, base); return SCPE_OK; } diff --git a/Intel-Systems/common/i8259.c b/Intel-Systems/common/i8259.c index 2b73d000..309d6418 100644 --- a/Intel-Systems/common/i8259.c +++ b/Intel-Systems/common/i8259.c @@ -34,41 +34,48 @@ */ #include "system_defs.h" /* system header in system dir */ -#define i8259_DEV 2 /* number of devices */ /* function prototypes */ -int32 i8259a0(int32 io, int32 data); -int32 i8259b0(int32 io, int32 data); -int32 i8259a1(int32 io, int32 data); -int32 i8259b1(int32 io, int32 data); -void i8259_dump(int32 dev); -t_stat i8259_reset (DEVICE *dptr, int32 base); +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 base, uint8 devnum); /* external function prototypes */ -extern int32 reg_dev(int32 (*routine)(int32, int32), int32 port); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); /* globals */ -int32 i8259_cnt = 0; -uint8 i8259_base[i8259_DEV]; -uint8 i8259_icw1[i8259_DEV]; -uint8 i8259_icw2[i8259_DEV]; -uint8 i8259_icw3[i8259_DEV]; -uint8 i8259_icw4[i8259_DEV]; -uint8 i8259_ocw1[i8259_DEV]; -uint8 i8259_ocw2[i8259_DEV]; -uint8 i8259_ocw3[i8259_DEV]; -int32 icw_num0 = 1, icw_num1 = 1; +uint8 i8259_base[I8259_NUM]; +uint8 i8259_icw1[I8259_NUM]; +uint8 i8259_icw2[I8259_NUM]; +uint8 i8259_icw3[I8259_NUM]; +uint8 i8259_icw4[I8259_NUM]; +uint8 i8259_ocw1[I8259_NUM]; +uint8 i8259_ocw2[I8259_NUM]; +uint8 i8259_ocw3[I8259_NUM]; +uint8 icw_num0 = 1, icw_num1 = 1; /* i8255 Standard I/O Data Structures */ +/* up to 2 i8259 devices */ UNIT i8259_unit[] = { { UDATA (0, 0, 0) }, /* i8259 0 */ { UDATA (0, 0, 0) } /* i8259 1 */ }; +REG i8259_reg[] = { + { HRDATA (IRR0, i8259_unit[0].u3, 8) }, /* i8259 0 */ + { HRDATA (ISR0, i8259_unit[0].u4, 8) }, + { HRDATA (IMR0, i8259_unit[0].u5, 8) }, + { HRDATA (IRR1, i8259_unit[1].u3, 8) }, /* i8259 0 */ + { HRDATA (ISR1, i8259_unit[1].u4, 8) }, + { HRDATA (IMR1, i8259_unit[1].u5, 8) }, + { NULL } +}; + DEBTAB i8259_debug[] = { { "ALL", DEBUG_all }, { "FLOW", DEBUG_flow }, @@ -80,15 +87,7 @@ DEBTAB i8259_debug[] = { { NULL } }; -REG i8259_reg[] = { - { HRDATA (IRR0, i8259_unit[0].u3, 8) }, /* i8259 0 */ - { HRDATA (ISR0, i8259_unit[0].u4, 8) }, - { HRDATA (IMR0, i8259_unit[0].u5, 8) }, - { HRDATA (IRR1, i8259_unit[1].u3, 8) }, /* i8259 0 */ - { HRDATA (ISR1, i8259_unit[1].u4, 8) }, - { HRDATA (IMR1, i8259_unit[1].u5, 8) }, - { NULL } -}; +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ DEVICE i8259_dev = { "8259", //name @@ -97,7 +96,7 @@ DEVICE i8259_dev = { NULL, //modifiers 1, //numunits 16, //aradix - 32, //awidth + 16, //awidth 1, //aincr 16, //dradix 8, //dwidth @@ -120,190 +119,116 @@ DEVICE i8259_dev = { IN or OUT instruction is issued. */ -/* i8259 0 functions */ +/* i8259 functions */ -int32 i8259a0(int32 io, int32 data) +uint8 i8259a(t_bool io, uint8 data, uint8 devnum) { + if (devnum >= I8259_NUM) { + sim_printf("8259a: Illegal Device Number %d\n", devnum); + return 0; + } if (io == 0) { /* read data port */ - if ((i8259_ocw3[0] & 0x03) == 0x02) - return (i8259_unit[0].u3); /* IRR */ - if ((i8259_ocw3[0] & 0x03) == 0x03) - return (i8259_unit[0].u4); /* ISR */ + if ((i8259_ocw3[devnum] & 0x03) == 0x02) + return (i8259_unit[devnum].u3); /* IRR */ + if ((i8259_ocw3[devnum] & 0x03) == 0x03) + return (i8259_unit[devnum].u4); /* ISR */ } else { /* write data port */ if (data & 0x10) { icw_num0 = 1; } if (icw_num0 == 1) { - i8259_icw1[0] = data; /* ICW1 */ - i8259_unit[0].u5 = 0x00; /* clear IMR */ - i8259_ocw3[0] = 0x02; /* clear OCW3, Sel IRR */ + i8259_icw1[devnum] = data; /* ICW1 */ + i8259_unit[devnum].u5 = 0x00; /* clear IMR */ + i8259_ocw3[devnum] = 0x02; /* clear OCW3, Sel IRR */ } else { switch (data & 0x18) { case 0: /* OCW2 */ - i8259_ocw2[0] = data; + i8259_ocw2[devnum] = data; break; case 8: /* OCW3 */ - i8259_ocw3[0] = data; + i8259_ocw3[devnum] = data; break; default: - sim_printf("8259b-0: OCW Error %02X\n", data); + sim_printf("8259a-%d: OCW Error %02X\n", devnum, data); break; } } - sim_printf("8259a-0: data = %02X\n", data); + sim_printf("8259a-%d: data = %02X\n", devnum, data); icw_num0++; /* step ICW number */ } - i8259_dump(0); + i8259_dump(devnum); return 0; } -int32 i8259a1(int32 io, int32 data) +uint8 i8259b(t_bool io, uint8 data, uint8 devnum) { + if (devnum >= I8259_NUM) { + sim_printf("8259b: Illegal Device Number %d\n", devnum); + return 0; + } if (io == 0) { /* read data port */ - if ((i8259_ocw3[1] & 0x03) == 0x02) - return (i8259_unit[1].u3); /* IRR */ - if ((i8259_ocw3[1] & 0x03) == 0x03) - return (i8259_unit[1].u4); /* ISR */ + if ((i8259_ocw3[devnum] & 0x03) == 0x02) + return (i8259_unit[devnum].u3); /* IRR */ + if ((i8259_ocw3[devnum] & 0x03) == 0x03) + return (i8259_unit[devnum].u4); /* ISR */ } else { /* write data port */ if (data & 0x10) { icw_num1 = 1; } if (icw_num1 == 1) { - i8259_icw1[1] = data; /* ICW1 */ - i8259_unit[1].u5 = 0x00; /* clear IMR */ - i8259_ocw3[1] = 0x02; /* clear OCW3, Sel IRR */ + i8259_icw1[devnum] = data; /* ICW1 */ + i8259_unit[devnum].u5 = 0x00; /* clear IMR */ + i8259_ocw3[devnum] = 0x02; /* clear OCW3, Sel IRR */ } else { switch (data & 0x18) { case 0: /* OCW2 */ - i8259_ocw2[1] = data; + i8259_ocw2[devnum] = data; break; case 8: /* OCW3 */ - i8259_ocw3[1] = data; + i8259_ocw3[devnum] = data; break; default: - sim_printf("8259b-1: OCW Error %02X\n", data); + sim_printf("8259b-%d: OCW Error %02X\n", devnum, data); break; } } - sim_printf("8259a-1: data = %02X\n", data); + sim_printf("8259b-%d: data = %02X\n", devnum, data); icw_num1++; /* step ICW number */ } - i8259_dump(1); + i8259_dump(devnum); return 0; } -/* i8259 1 functions */ - -int32 i8259b0(int32 io, int32 data) +void i8259_dump(uint8 devnum) { - if (io == 0) { /* read data port */ - return (i8259_unit[0].u5); /* IMR */ - } else { /* write data port */ - if (icw_num0 >= 2 && icw_num0 < 5) { /* ICW mode */ - switch (icw_num0) { - case 2: /* ICW2 */ - i8259_icw2[0] = data; - break; - case 3: /* ICW3 */ - i8259_icw3[0] = data; - break; - case 4: /* ICW4 */ - if (i8259_icw1[0] & 0x01) - i8259_icw4[0] = data; - else - sim_printf("8259b-0: ICW4 not enabled - data=%02X\n", data); - break; - default: - sim_printf("8259b-0: ICW Error %02X\n", data); - break; - } - icw_num0++; - } else { - i8259_ocw1[0] = data; /* OCW0 */ - } - } - i8259_dump(0); - return 0; -} - -int32 i8259b1(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (i8259_unit[1].u5); /* IMR */ - } else { /* write data port */ - if (icw_num1 >= 2 && icw_num1 < 5) { /* ICW mode */ - switch (icw_num1) { - case 2: /* ICW2 */ - i8259_icw2[1] = data; - break; - case 3: /* ICW3 */ - i8259_icw3[1] = data; - break; - case 4: /* ICW4 */ - if (i8259_icw1[1] & 0x01) - i8259_icw4[1] = data; - else - sim_printf("8259b-1: ICW4 not enabled - data=%02X\n", data); - break; - default: - sim_printf("8259b-1: ICW Error %02X\n", data); - break; - } - icw_num1++; - } else { - i8259_ocw1[1] = data; /* OCW0 */ - } - } - i8259_dump(1); - return 0; -} - -void i8259_dump(int32 dev) -{ - sim_printf("Device %d\n", dev); - sim_printf(" IRR = %02X\n", i8259_unit[dev].u3); - sim_printf(" ISR = %02X\n", i8259_unit[dev].u4); - sim_printf(" IMR = %02X\n", i8259_unit[dev].u5); - sim_printf(" ICW1 = %02X\n", i8259_icw1[dev]); - sim_printf(" ICW2 = %02X\n", i8259_icw2[dev]); - sim_printf(" ICW3 = %02X\n", i8259_icw3[dev]); - sim_printf(" ICW4 = %02X\n", i8259_icw4[dev]); - sim_printf(" OCW1 = %02X\n", i8259_ocw1[dev]); - sim_printf(" OCW2 = %02X\n", i8259_ocw2[dev]); - sim_printf(" OCW3 = %02X\n", i8259_ocw3[dev]); + sim_printf("Device %d\n", devnum); + sim_printf(" IRR = %02X\n", i8259_unit[devnum].u3); + sim_printf(" ISR = %02X\n", i8259_unit[devnum].u4); + sim_printf(" IMR = %02X\n", i8259_unit[devnum].u5); + sim_printf(" ICW1 = %02X\n", i8259_icw1[devnum]); + sim_printf(" ICW2 = %02X\n", i8259_icw2[devnum]); + sim_printf(" ICW3 = %02X\n", i8259_icw3[devnum]); + sim_printf(" ICW4 = %02X\n", i8259_icw4[devnum]); + sim_printf(" OCW1 = %02X\n", i8259_ocw1[devnum]); + sim_printf(" OCW2 = %02X\n", i8259_ocw2[devnum]); + sim_printf(" OCW3 = %02X\n", i8259_ocw3[devnum]); } /* Reset routine */ -t_stat i8259_reset (DEVICE *dptr, int32 base) +t_stat i8259_reset (DEVICE *dptr, uint16 base, uint8 devnum) { - switch (i8259_cnt) { - case 0: - reg_dev(i8259a0, base); - reg_dev(i8259b0, base + 1); - reg_dev(i8259a0, base + 2); - reg_dev(i8259b0, base + 3); - i8259_unit[0].u3 = 0x00; /* IRR */ - i8259_unit[0].u4 = 0x00; /* ISR */ - i8259_unit[0].u5 = 0x00; /* IMR */ - sim_printf(" 8259-0: Reset\n"); - break; - case 1: - reg_dev(i8259a1, base); - reg_dev(i8259b1, base + 1); - reg_dev(i8259a1, base + 2); - reg_dev(i8259b1, base + 3); - i8259_unit[1].u3 = 0x00; /* IRR */ - i8259_unit[1].u4 = 0x00; /* ISR */ - i8259_unit[1].u5 = 0x00; /* IMR */ - sim_printf(" 8259-1: Reset\n"); - break; - default: - sim_printf(" 8259: Bad device\n"); - break; + if (devnum >= I8259_NUM) { + sim_printf("8259_reset: Illegal Device Number %d\n", devnum); + return 0; } - sim_printf(" 8259-%d: Registered at %02X\n", i8259_cnt, base); - i8259_cnt++; + reg_dev(i8259a, base, devnum); + reg_dev(i8259b, base + 1, devnum); + i8259_unit[devnum].u3 = 0x00; /* IRR */ + i8259_unit[devnum].u4 = 0x00; /* ISR */ + i8259_unit[devnum].u5 = 0x00; /* IMR */ + sim_printf(" 8259-%d: Reset\n", devnum); + sim_printf(" 8259-%d: Registered at %04X\n", devnum, base); return SCPE_OK; } diff --git a/Intel-Systems/common/i8273.c b/Intel-Systems/common/i8273.c index 03b4dd3f..aa91fcf4 100644 --- a/Intel-Systems/common/i8273.c +++ b/Intel-Systems/common/i8273.c @@ -159,7 +159,7 @@ DEBTAB i8273_debug[] = { }; DEVICE i8273_dev = { - "8251", //name + "8273", //name &i8273_unit, //units i8273_reg, //registers i8273_mod, //modifiers diff --git a/Intel-Systems/common/ieprom.c b/Intel-Systems/common/ieprom.c index a5730426..da8e190e 100644 --- a/Intel-Systems/common/ieprom.c +++ b/Intel-Systems/common/ieprom.c @@ -31,11 +31,11 @@ NOTES: - These functions support a simulated i2732 EPROM device on an Intel iSBC 80/XX. + 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 and 2764 type EPROMs. + 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" @@ -45,10 +45,12 @@ /* function prototypes */ t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); -t_stat EPROM_reset (DEVICE *dptr, int32 size); -int32 EPROM_get_mbyte(uint32 addr); +t_stat EPROM_reset (DEVICE *dptr, uint16 size); +uint8 EPROM_get_mbyte(uint16 addr); -extern UNIT i8255_unit; +/* external function prototypes */ + +extern UNIT i8255_unit[]; extern uint8 xack; /* XACK signal */ /* SIMH EPROM Standard I/O Data Structures */ @@ -75,7 +77,7 @@ DEVICE EPROM_dev = { NULL, //modifiers 1, //numunits 16, //aradix - 32, //awidth + 16, //awidth 1, //aincr 16, //dradix 8, //dwidth @@ -147,7 +149,7 @@ t_stat EPROM_attach (UNIT *uptr, CONST char *cptr) /* EPROM reset */ -t_stat EPROM_reset (DEVICE *dptr, int32 size) +t_stat EPROM_reset (DEVICE *dptr, uint16 size) { // sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=0000 size=%04X\n", size); if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */ @@ -166,11 +168,11 @@ t_stat EPROM_reset (DEVICE *dptr, int32 size) /* get a byte from memory */ -int32 EPROM_get_mbyte(uint32 addr) +uint8 EPROM_get_mbyte(uint16 addr) { - int32 val; + uint8 val; - if (i8255_unit.u5 & 0x01) { /* EPROM enabled */ + if (i8255_unit[0].u5 & 0x01) { /* EPROM enabled */ sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr); if (addr < EPROM_unit.capac) { SET_XACK(1); /* good memory address */ diff --git a/Intel-Systems/common/ipata.c b/Intel-Systems/common/ipata.c new file mode 100644 index 00000000..715f61f4 --- /dev/null +++ b/Intel-Systems/common/ipata.c @@ -0,0 +1,206 @@ +/* iPATA.c: Intel i8255 PIO adapter for PATA HD + + Copyright (c) 2015, 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. + + NOTES: + + These functions support a simulated i8255 interface device on an iSBC. + The device has threee physical 8-bit I/O ports which could be connected + to any parallel I/O device. This is an extension of the i8255.c file to support + an emulated PATA IDE Hard Disk Drive. + + All I/O is via programmed I/O. The i8255 has a control port (PIOS) + and three data ports (PIOA, PIOB, and PIOC). + + The simulated device supports a select from I/O space and two address lines. + The data ports are at the lower addresses and the control port is at + the highest. + + A write to the control port can configure the device: + + Control Word + +---+---+---+---+---+---+---+---+ + | D7 D6 D5 D4 D3 D2 D1 D0| + +---+---+---+---+---+---+---+---+ + + Group B + D0 Port C (lower) 1-Input, 0-Output + D1 Port B 1-Input, 0-Output + D2 Mode Selection 0-Mode 0, 1-Mode 1 + + Group A + D3 Port C (upper) 1-Input, 0-Output + D4 Port A 1-Input, 0-Output + D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2 + + D7 Mode Set Flag 1=Active, 0=Bit Set + + Mode 0 - Basic Input/Output + Mode 1 - Strobed Input/Output + Mode 2 - Bidirectional Bus + + Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset + + A read to the data ports gets the current port value, a write + to the data ports writes the character to the device. + + The Second 8255 on the iSBC 80/10 is used to connect to the IDE PATA + Hard Disk Drive. Pins are defined as shown below: + + PA[0..7] High data byte + PB[0..7] Low data byte + PC[0..2] Register select + PC[3..4] CSFX select + PC[5] Read register + PC[6] Write register +*/ + +#include "system_defs.h" + +extern int32 reg_dev(int32 (*routine)(), int32 port); + +/* function prototypes */ + +t_stat pata_reset (DEVICE *dptr, int32 base); + +/* i8255 Standard I/O Data Structures */ + +UNIT pata_unit[] = { + { UDATA (0, 0, 0) } +}; + +REG pata_reg[] = { + { HRDATA (CONTROL0, pata_unit[0].u3, 8) }, + { HRDATA (PORTA0, pata_unit[0].u4, 8) }, + { HRDATA (PORTB0, pata_unit[0].u5, 8) }, + { HRDATA (PORTC0, pata_unit[0].u6, 8) }, + { NULL } +}; + +DEVICE pata_dev = { + "PATA", //name + pata_unit, //units + pata_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &pata_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + NULL, //debflags + NULL, //msize + NULL //lname +}; + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +int32 patas(int32 io, int32 data) +{ + int32 bit; + + if (io == 0) { /* read status port */ + return pata_unit[0].u3; + } else { /* write status port */ + if (data & 0x80) { /* mode instruction */ + pata_unit[0].u3 = data; + sim_printf("PATA: 8255 Mode Instruction=%02X\n", 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 */ + pata_unit[0].u6 |= (0x01 << bit); + } else { /* reset bit */ + pata_unit[0].u6 &= ~(0x01 << bit); + } + } + } + return 0; +} + +int32 pataa(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + sim_printf("PATA: 8255 Read Port A = %02X\n", pata_unit[0].u4); + return (pata_unit[0].u4); + } else { /* write data port */ + pata_unit[0].u4 = data; + sim_printf("PATA: 8255 Write Port A = %02X\n", data); + } + return 0; +} + +int32 patab(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + sim_printf("PATA: 8255 Read Port B = %02X\n", pata_unit[0].u5); + return (pata_unit[0].u5); + } else { /* write data port */ + pata_unit[0].u5 = data; + sim_printf("PATA: 8255 Write Port B = %02X\n", data); + } + return 0; +} + +int32 patac(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + sim_printf("PATA: 8255 Read Port C = %02X\n", pata_unit[0].u6); + return (pata_unit[0].u6); + } else { /* write data port */ + pata_unit[0].u6 = data; + sim_printf("PATA: 8255 Write Port C = %02X\n", data); + } + return 0; +} + +/* Reset routine */ + +t_stat pata_reset (DEVICE *dptr, int32 base) +{ + pata_unit[0].u3 = 0x9B; /* control */ + pata_unit[0].u4 = 0xFF; /* Port A */ + pata_unit[0].u5 = 0xFF; /* Port B */ + pata_unit[0].u6 = 0xFF; /* Port C */ + reg_dev(pataa, base); + reg_dev(patab, base + 1); + reg_dev(patac, base + 2); + reg_dev(patas, base + 3); + sim_printf(" PATA: Reset\n"); + return SCPE_OK; +} + diff --git a/Intel-Systems/common/iram8.c b/Intel-Systems/common/iram8.c index 9c5f9a98..f0202d37 100644 --- a/Intel-Systems/common/iram8.c +++ b/Intel-Systems/common/iram8.c @@ -31,7 +31,9 @@ NOTES: - These functions support a simulated i8111 or i8102 RAM devices on an iSBC-80/XX. + These functions support a simulated RAM devices on an iSBC-80/XX SBCs. + These functions also support bit 2 of 8255 number 1, port B, to enable/ + disable the onboard RAM. */ #include "system_defs.h" @@ -41,11 +43,13 @@ /* function prototypes */ t_stat RAM_svc (UNIT *uptr); -t_stat RAM_reset (DEVICE *dptr, int32 base, int32 size); -int32 RAM_get_mbyte(int32 addr); -void RAM_put_mbyte(int32 addr, int32 val); +t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); +uint8 RAM_get_mbyte(uint16 addr); +void RAM_put_mbyte(uint16 addr, uint8 val); -extern UNIT i8255_unit; +/* external function prototypes */ + +extern UNIT i8255_unit[]; extern uint8 xack; /* XACK signal */ /* SIMH RAM Standard I/O Data Structures */ @@ -70,7 +74,7 @@ DEVICE RAM_dev = { NULL, //modifiers 1, //numunits 16, //aradix - 32, //awidth + 16, //awidth 1, //aincr 16, //dradix 8, //dwidth @@ -95,7 +99,7 @@ DEVICE RAM_dev = { /* RAM reset */ -t_stat RAM_reset (DEVICE *dptr, int32 base, int32 size) +t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size) { sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%04X size=%04X\n", base, size-1); if (RAM_unit.capac == 0) { /* if undefined */ @@ -118,11 +122,11 @@ t_stat RAM_reset (DEVICE *dptr, int32 base, int32 size) /* get a byte from memory */ -int32 RAM_get_mbyte(int32 addr) +uint8 RAM_get_mbyte(uint16 addr) { - int32 val; + uint8 val; - if (i8255_unit.u5 & 0x02) { /* enable RAM */ + if (i8255_unit[0].u5 & 0x02) { /* enable RAM */ 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 */ @@ -140,9 +144,9 @@ int32 RAM_get_mbyte(int32 addr) /* put a byte to memory */ -void RAM_put_mbyte(int32 addr, int32 val) +void RAM_put_mbyte(uint16 addr, uint8 val) { - if (i8255_unit.u5 & 0x02) { /* enable RAM */ + if (i8255_unit[0].u5 & 0x02) { /* enable RAM */ 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 */ diff --git a/Intel-Systems/common/isbc064.c b/Intel-Systems/common/isbc064.c index 28bf9cee..c9b43ad0 100644 --- a/Intel-Systems/common/isbc064.c +++ b/Intel-Systems/common/isbc064.c @@ -42,10 +42,8 @@ /* prototypes */ t_stat isbc064_reset (DEVICE *dptr); -int32 isbc064_get_mbyte(int32 addr); -int32 isbc064_get_mword(int32 addr); -void isbc064_put_mbyte(int32 addr, int32 val); -void isbc064_put_mword(int32 addr, int32 val); +uint8 isbc064_get_mbyte(uint16 addr); +void isbc064_put_mbyte(uint16 addr, uint8 val); extern uint8 xack; /* XACK signal */ @@ -73,7 +71,7 @@ DEVICE isbc064_dev = { NULL, //modifiers 1, //numunits 16, //aradix - 8, //awidth + 16, //awidth 1, //aincr 16, //dradix 8, //dwidth @@ -118,9 +116,9 @@ t_stat isbc064_reset (DEVICE *dptr) /* get a byte from memory */ -int32 isbc064_get_mbyte(int32 addr) +uint8 isbc064_get_mbyte(uint16 addr) { - int32 val, org, len; + uint32 val, org, len; int i = 0; if ((isbc064_dev.flags & DEV_DIS) == 0) { @@ -143,22 +141,11 @@ int32 isbc064_get_mbyte(int32 addr) return 0xFF; /* multibus has active high pullups */ } -/* get a word from memory */ - -int32 isbc064_get_mword(int32 addr) -{ - int32 val; - - val = isbc064_get_mbyte(addr); - val |= (isbc064_get_mbyte(addr+1) << 8); - return val; -} - /* put a byte into memory */ -void isbc064_put_mbyte(int32 addr, int32 val) +void isbc064_put_mbyte(uint16 addr, uint8 val) { - int32 org, len; + uint32 org, len; int i = 0; if ((isbc064_dev.flags & DEV_DIS) == 0) { @@ -180,12 +167,4 @@ void isbc064_put_mbyte(int32 addr, int32 val) sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Disabled\n"); } -/* put a word into memory */ - -void isbc064_put_mword(int32 addr, int32 val) -{ - isbc064_put_mbyte(addr, val); - isbc064_put_mbyte(addr+1, val << 8); -} - /* end of isbc064.c */ diff --git a/Intel-Systems/common/isbc064b.c b/Intel-Systems/common/isbc064b.c deleted file mode 100644 index 4fdd8b95..00000000 --- a/Intel-Systems/common/isbc064b.c +++ /dev/null @@ -1,256 +0,0 @@ -/* isbc064.c: Intel iSBC064 64K Byte Memory 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. - - These functions support a simulated isbc016, isbc032, isbc048 and isbc064 memory card - on an Intel multibus system. - - */ - -#include - -#include "multibus_defs.h" - -#define UNIT_V_MSIZE (UNIT_V_UF) /* Memory Size */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) -#define UNIT_V_MBASE (UNIT_V_UF+1) /* Memory Base */ -#define UNIT_MBASE (1 << UNIT_V_MBASE) - -/* prototypes */ - -t_stat isbc064_reset (DEVICE *dptr); -t_stat isbc064_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat isbc064_set_base (UNIT *uptr, int32 val, char *cptr, void *desc); -int32 isbc064_get_mbyte(int32 addr); -int32 isbc064_get_mword(int32 addr); -void isbc064_put_mbyte(int32 addr, int32 val); -void isbc064_put_mword(int32 addr, int32 val); - -/* isbc064 Standard I/O Data Structures */ - -UNIT isbc064_unit = { UDATA (NULL, UNIT_FIX+UNIT_DISABLE+UNIT_BINK, 65536), KBD_POLL_WAIT }; - -MTAB isbc064_mod[] = { - { UNIT_MSIZE, 16384, NULL, "16K", &isbc064_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &isbc064_set_size }, - { UNIT_MSIZE, 49152, NULL, "48K", &isbc064_set_size }, - { UNIT_MSIZE, 65535, NULL, "64K", &isbc064_set_size }, - { UNIT_MBASE, 0, NULL, "B0K", &isbc064_set_base }, - { UNIT_MBASE, 16384, NULL, "B16K", &isbc064_set_base }, - { UNIT_MBASE, 32768, NULL, "B32K", &isbc064_set_base }, - { UNIT_MBASE, 49152, NULL, "B48K", &isbc064_set_base }, - { 0 } -}; - -DEBTAB isbc064_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE isbc064_dev = { - "SBC064", //name - &isbc064_unit, //units - NULL, //registers - isbc064_mod, //modifiers - 1, //numunits - 16, //aradix - 8, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposite - &isbc064_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags - 0, //dctrl - isbc064_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* iSBC064 globals */ - -uint8 *MB_buf = NULL; //pointer to memory buffer - -/* Set memory size routine */ - -t_stat isbc064_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ - int32 mc = 0; - uint32 i; - - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_set_size: val=%04X\n", val); - if ((val <= 0) || (val > MAXMEMSIZE)) { - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_set_size: Memory size error\n"); - return SCPE_ARG; - } - isbc064_unit.capac = val; - for (i = isbc064_unit.capac; i < MAXMEMSIZE; i++) - isbc064_put_mbyte(i, 0); - isbc064_unit.capac = val; - isbc064_unit.u3 = 0; - if (MB_buf) { - free (MB_buf); - MB_buf = NULL; - } - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_set_size: Done\n"); - return SCPE_OK; -} - -/* Set memory base address routine */ - -t_stat isbc064_set_base (UNIT *uptr, int32 val, char *cptr, void *desc) -{ - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_set_base: val=%04X\n", val); - if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) { - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_set_base: Base address error\n"); - return SCPE_ARG; - } - isbc064_unit.u3 = val; - if (MB_buf) { - free (MB_buf); - MB_buf = NULL; - } - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_set_base: Done\n"); - return (isbc064_reset (NULL)); -} - -/* Reset routine */ - -t_stat isbc064_reset (DEVICE *dptr) -{ - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_reset: \n"); - if ((isbc064_dev.flags & DEV_DIS) == 0) { - sim_printf("Initializing %s [%04X-%04XH]\n", "iSBC-064", - isbc064_unit.u3, - isbc064_unit.u3 + isbc064_unit.capac - 1); - if (MB_buf == NULL) { - MB_buf = malloc(isbc064_unit.capac); - if (MB_buf == NULL) { - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_reset: Malloc error\n"); - return SCPE_MEM; - } - } - } - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_reset: Done\n"); - return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - external memory read or write is issued. -*/ - -/* get a byte from memory */ - -int32 isbc064_get_mbyte(int32 addr) -{ - int32 val, org, len; - int i = 0; - - if ((isbc064_dev.flags & DEV_DIS) == 0) { - org = isbc064_unit.u3; - len = isbc064_unit.capac - 1; - if (isbc064_dev.dctrl & DEBUG_read) - sim_printf("isbc064_get_mbyte: addr=%04X", addr); - if ((addr >= org) && (addr <= org + len)) { - val = *(MB_buf + (addr - org)); - if (isbc064_dev.dctrl & DEBUG_read) - sim_printf(" val=%04X\n", val); - return (val & 0xFF); - } else { - if (isbc064_dev.dctrl & DEBUG_read) - sim_printf(" Out of range\n"); - return 0xFF; /* multibus has active high pullups */ - } - } - if (isbc064_dev.dctrl & DEBUG_read) - sim_printf(" Disabled\n"); - return 0xFF; /* multibus has active high pullups */ -} - -/* get a word from memory */ - -int32 isbc064_get_mword(int32 addr) -{ - int32 val; - - val = isbc064_get_mbyte(addr); - val |= (isbc064_get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte into memory */ - -void isbc064_put_mbyte(int32 addr, int32 val) -{ - int32 org, len, type; - int i = 0; - - if ((isbc064_dev.flags & DEV_DIS) == 0) { - org = isbc064_unit.u3; - len = isbc064_unit.capac - 1; - if (isbc064_dev.dctrl & DEBUG_write) - sim_printf("isbc064_put_mbyte: addr=%04X, val=%02X", addr, val); - if ((addr >= org) && (addr < org + len)) { - *(MB_buf + (addr - org)) = val & 0xFF; - if (isbc064_dev.dctrl & DEBUG_write) - sim_printf("\n"); - return; - } else { - if (isbc064_dev.dctrl & DEBUG_write) - sim_printf(" Out of range\n"); - return; - } - } - if (isbc064_dev.dctrl & DEBUG_write) - sim_printf("isbc064_put_mbyte: Disabled\n"); -} - -/* put a word into memory */ - -void isbc064_put_mword(int32 addr, int32 val) -{ - isbc064_put_mbyte(addr, val); - isbc064_put_mbyte(addr+1, val << 8); -} - -/* end of isbc064.c */ diff --git a/Intel-Systems/common/isbc064x.c b/Intel-Systems/common/isbc064x.c deleted file mode 100644 index 753e7e83..00000000 --- a/Intel-Systems/common/isbc064x.c +++ /dev/null @@ -1,205 +0,0 @@ -/* isbc064.c: Intel iSBC064 64K Byte Memory 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. - - These functions support a simulated isbc016, isbc032, isbc048 and isbc064 - memory card on an Intel multibus system. - - ?? ??? 11 - Original file. - 16 Dec 12 - Modified to use system_80_10.cfg file to set base and size. - -*/ - -#include -#include "multibus_defs.h" - -#define SET_XACK(VAL) (XACK = VAL) - -/* prototypes */ - -t_stat isbc064_reset (DEVICE *dptr); -int32 isbc064_get_mbyte(int32 addr); -int32 isbc064_get_mword(int32 addr); -void isbc064_put_mbyte(int32 addr, int32 val); -void isbc064_put_mword(int32 addr, int32 val); - -extern uint8 XACK; /* XACK signal */ - -/* isbc064 Standard I/O Data Structures */ - -UNIT isbc064_unit = { - UDATA (NULL, UNIT_FIX+UNIT_DISABLE+UNIT_BINK, 65536), KBD_POLL_WAIT -}; - -DEBTAB isbc064_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE isbc064_dev = { - "SBC064", //name - &isbc064_unit, //units - NULL, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 8, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposite - &isbc064_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags - 0, //dctrl - isbc064_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* iSBC064 globals */ - -/* Reset routine */ - -t_stat isbc064_reset (DEVICE *dptr) -{ - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_reset: \n"); - if ((isbc064_dev.flags & DEV_DIS) == 0) { - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_reset: Size=%04X\n", isbc064_unit.capac - 1); - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_reset: Base address=%04X\n", isbc064_unit.u3); - sim_printf("iSBC 064: Available[%04X-%04XH]\n", - isbc064_unit.u3, - isbc064_unit.u3 + isbc064_unit.capac - 1); - } - if (isbc064_unit.filebuf == NULL) { - isbc064_unit.filebuf = malloc(isbc064_unit.capac); - if (isbc064_unit.filebuf == NULL) { - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_reset: Malloc error\n"); - return SCPE_MEM; - } - } - if (isbc064_dev.dctrl & DEBUG_flow) - sim_printf("isbc064_reset: Done\n"); - return SCPE_OK; -} - -/* get a byte from memory */ - -int32 isbc064_get_mbyte(int32 addr) -{ - int32 val, org, len; - int i = 0; - - if ((isbc064_dev.flags & DEV_DIS) == 0) { - org = isbc064_unit.u3; - len = isbc064_unit.capac; - if (isbc064_dev.dctrl & DEBUG_read) - sim_printf("isbc064_get_mbyte: addr=%04X", addr); - if (isbc064_dev.dctrl & DEBUG_read) - sim_printf("isbc064_put_mbyte: org=%04X, len=%04X\n", org, len); - if ((addr >= org) && (addr < (org + len))) { - SET_XACK(1); /* good memory address */ - if (isbc064_dev.dctrl & DEBUG_xack) - sim_printf("isbc064_get_mbyte: Set XACK for %04X\n", addr); - val = *(uint8 *)(isbc064_unit.filebuf + (addr - org)); - if (isbc064_dev.dctrl & DEBUG_read) - sim_printf(" val=%04X\n", val); - return (val & 0xFF); - } else { - if (isbc064_dev.dctrl & DEBUG_read) - sim_printf(" Out of range\n"); - return 0xFF; /* multibus has active high pullups */ - } - } - if (isbc064_dev.dctrl & DEBUG_read) - sim_printf(" Disabled\n"); - return 0xFF; /* multibus has active high pullups */ -} - -/* get a word from memory */ - -int32 isbc064_get_mword(int32 addr) -{ - int32 val; - - val = isbc064_get_mbyte(addr); - val |= (isbc064_get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte into memory */ - -void isbc064_put_mbyte(int32 addr, int32 val) -{ - int32 org, len; - int i = 0; - - if ((isbc064_dev.flags & DEV_DIS) == 0) { - org = isbc064_unit.u3; - len = isbc064_unit.capac; - if (isbc064_dev.dctrl & DEBUG_write) - sim_printf("isbc064_put_mbyte: addr=%04X, val=%02X\n", addr, val); - if (isbc064_dev.dctrl & DEBUG_write) - sim_printf("isbc064_put_mbyte: org=%04X, len=%04X\n", org, len); - if ((addr >= org) && (addr < (org + len))) { - SET_XACK(1); /* good memory address */ - if (isbc064_dev.dctrl & DEBUG_xack) - sim_printf("isbc064_put_mbyte: Set XACK for %04X\n", addr); - *(uint8 *)(isbc064_unit.filebuf + (addr - org)) = val & 0xFF; - if (isbc064_dev.dctrl & DEBUG_xack) - sim_printf("isbc064_put_mbyte: Return\n"); - return; - } else { - if (isbc064_dev.dctrl & DEBUG_write) - sim_printf(" Out of range\n"); - return; - } - } - if (isbc064_dev.dctrl & DEBUG_write) - sim_printf("isbc064_put_mbyte: Disabled\n"); -} - -/* put a word into memory */ - -void isbc064_put_mword(int32 addr, int32 val) -{ - isbc064_put_mbyte(addr, val); - isbc064_put_mbyte(addr+1, val << 8); -} - -/* end of isbc064.c */ diff --git a/Intel-Systems/common/isbc208.c b/Intel-Systems/common/isbc208.c index 7ab2da88..616fc87b 100644 --- a/Intel-Systems/common/isbc208.c +++ b/Intel-Systems/common/isbc208.c @@ -26,7 +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: @@ -396,10 +395,11 @@ #include "system_defs.h" -#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ +#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 */ @@ -410,6 +410,7 @@ #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 */ @@ -426,6 +427,7 @@ #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 */ @@ -434,6 +436,7 @@ #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 */ @@ -441,6 +444,7 @@ #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 */ @@ -450,6 +454,7 @@ //#define US 0x03 /* Unit selected */ /* FDC command definitions */ + #define READTRK 0x02 #define SPEC 0x03 #define SENDRV 0x04 @@ -475,38 +480,39 @@ 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); -int32 isbc208_r0(int32 io, int32 data); -int32 isbc208_r1(int32 io, int32 data); -int32 isbc208_r2(int32 io, int32 data); -int32 isbc208_r3(int32 io, int32 data); -int32 isbc208_r4(int32 io, int32 data); -int32 isbc208_r5(int32 io, int32 data); -int32 isbc208_r6(int32 io, int32 data); -int32 isbc208_r7(int32 io, int32 data); -int32 isbc208_r8(int32 io, int32 data); -int32 isbc208_r9(int32 io, int32 data); -int32 isbc208_rA(int32 io, int32 data); -int32 isbc208_rB(int32 io, int32 data); -int32 isbc208_rC(int32 io, int32 data); -int32 isbc208_rD(int32 io, int32 data); -int32 isbc208_rE(int32 io, int32 data); -int32 isbc208_rF(int32 io, int32 data); -int32 isbc208_r10(int32 io, int32 data); -int32 isbc208_r11(int32 io, int32 data); -int32 isbc208_r12(int32 io, int32 data); -int32 isbc208_r13(int32 io, int32 data); -int32 isbc208_r14(int32 io, int32 data); -int32 isbc208_r15(int32 io, int32 data); +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 data, 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 int32 reg_dev(int32 (*routine)(int32, int32), int32 port); -extern void multibus_put_mbyte(int32 addr, int32 val); -extern int32 multibus_get_mbyte(int32 addr); +extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); +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 @@ -521,9 +527,12 @@ 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) @@ -535,6 +544,7 @@ 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 @@ -542,11 +552,13 @@ 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] @@ -580,6 +592,7 @@ int8 maxcyl[FDD_NUM] = { }; /* 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 }, @@ -682,10 +695,10 @@ t_stat isbc208_svc (UNIT *uptr) FILE *fp; if ((i8272_msr & CB) && cmd && (uptr->u6 == drv)) { /* execution phase */ - sim_debug (DEBUG_flow, &isbc208_dev, "isbc208_svc: Entered execution phase\n"); + 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]); +// 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) @@ -694,24 +707,24 @@ t_stat isbc208_svc (UNIT *uptr) 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_printf(" d=%d h=%d c=%d s=%d\n", drv, h, cyl, sec); sim_debug (DEBUG_flow, &isbc208_dev, - "isbc208_svc: FDC read: h=%d, hed=%d, sec=%d, secn=%d, spt=%d, ssize=%04X, bpt=%04X, bpc=%04X\n", + "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, - "isbc208_svc: FDC read: d=%d h=%d c=%d s=%d N=%d spt=%d fddst=%02X\n", + "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_flow, &isbc208_dev, "\nFDC read of d=%d h=%d c=%d s=%d", + 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, "isbc208_svc: FDC read: Not Ready\n"); + 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_flow, &isbc208_dev, - "isbc208_svc: FDC read: DMA addr=%04X cnt=%04X imgadr=%04X\n", + 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)); @@ -750,18 +763,20 @@ t_stat isbc208_svc (UNIT *uptr) bpt = ssize * spt; // bytes/track bpc = bpt * 2; // bytes/cylinder sim_debug (DEBUG_flow, &isbc208_dev, - "isbc208_svc: FDC write: hed=%d, sec=%d, secn=%d, spt=%d, ssize=%04X, bpt=%04X, bpc=%04X\n", + "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, - "isbc208_svc: FDC write: d=%d h=%d c=%d s=%d N=%d spt=%d fddst=%02X\n", + "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, "isbc208_svc: FDC write: Not Ready\n"); + 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 @@ -769,11 +784,11 @@ t_stat isbc208_svc (UNIT *uptr) // 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("isbc208_svc: FDC write: Write Protected\n"); +// 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_flow, &isbc208_dev, - "isbc208_svc: FDC write: DMA adr=%04X cnt=%04X imgadr=%04X\n", + 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); @@ -803,12 +818,12 @@ t_stat isbc208_svc (UNIT *uptr) 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, "isbc208_svc: Not Ready\n"); + 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, "isbc208_svc: Write Protected\n"); + sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: Write Protected\n"); } else { ; /* do nothing for now */ i8272_msr |= (RQM + DIO + CB); /* enter result phase */ @@ -825,7 +840,7 @@ t_stat isbc208_svc (UNIT *uptr) clr_irq(SBC208_INT); /* clear interrupt */ break; case SENDRV: /* 0x04 */ - sim_debug (DEBUG_flow, &isbc208_dev, "isbc208_svc: FDC sense drive of disk=%d fddst=%02X\n", + 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 */ @@ -836,12 +851,12 @@ t_stat isbc208_svc (UNIT *uptr) break; case HOME: /* 0x07 */ // sim_printf("HOME-e: fddst=%02X\n", fddst[uptr->u6]); - sim_debug (DEBUG_flow, &isbc208_dev, "isbc208_svc: FDC home: disk=%d fddst=%02X\n", + 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, "isbc208_svc: Not Ready\n"); + sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: Not Ready\n"); } else { cyl = 0; /* now on cylinder 0 */ fddst[drv] |= T0; /* set status flag */ @@ -862,7 +877,7 @@ t_stat isbc208_svc (UNIT *uptr) fddst[3] |= TS; // sim_printf("SPEC-e: fddst[%d]=%02X\n", uptr->u6, fddst[uptr->u6]); sim_debug (DEBUG_flow, &isbc208_dev, - "isbc208_svc: FDC specify SRT=%d ms HUT=%d ms HLT=%d ms \n", + "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; @@ -877,7 +892,7 @@ t_stat isbc208_svc (UNIT *uptr) 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, "isbc208_svc: Not Ready\n"); + sim_debug (DEBUG_flow, &isbc208_dev, "208_svc: Not Ready\n"); } else { i8272_w2 = cyl; /* generate a valid address mark */ i8272_w3 = hed >> 2; @@ -893,15 +908,15 @@ t_stat isbc208_svc (UNIT *uptr) break; case SEEK: /* 0x0F */ // sim_printf("SEEK-e: fddst=%02X\n", fddst[uptr->u6]); - sim_debug (DEBUG_flow, &isbc208_dev, "isbc208_svc: FDC seek: disk=%d cyl=%d fddst=%02X\n", + 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, "isbc208_svc: FDC seek: Not Ready\n"); + 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, "isbc208_svc: FDC seek: Invalid Cylinder %d\n", i8272_w2); + 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 */ @@ -933,15 +948,520 @@ t_stat isbc208_svc (UNIT *uptr) pcmd = cmd; /* save for result phase */ cmd = 0; /* reset command */ sim_debug (DEBUG_flow, &isbc208_dev, - "isbc208_svc: Exit: RSLT0 msr=%02X ST0=%02X ST1=%02X ST2=%02X ST3=%02X\n", + "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) +{ + reg_dev(isbc208_r0, SBC208_BASE + 0, 0); + reg_dev(isbc208_r1, SBC208_BASE + 1, 0); + reg_dev(isbc208_r2, SBC208_BASE + 2, 0); + reg_dev(isbc208_r3, SBC208_BASE + 3, 0); + reg_dev(isbc208_r4, SBC208_BASE + 4, 0); + reg_dev(isbc208_r5, SBC208_BASE + 5, 0); + reg_dev(isbc208_r6, SBC208_BASE + 6, 0); + reg_dev(isbc208_r7, SBC208_BASE + 7, 0); + reg_dev(isbc208_r8, SBC208_BASE + 8, 0); + reg_dev(isbc208_r9, SBC208_BASE + 9, 0); + reg_dev(isbc208_rA, SBC208_BASE + 10, 0); + reg_dev(isbc208_rB, SBC208_BASE + 11, 0); + reg_dev(isbc208_rC, SBC208_BASE + 12, 0); + reg_dev(isbc208_rD, SBC208_BASE + 13, 0); + reg_dev(isbc208_rE, SBC208_BASE + 14, 0); + reg_dev(isbc208_rF, SBC208_BASE + 15, 0); + reg_dev(isbc208_r10, SBC208_BASE + 16, 0); + reg_dev(isbc208_r11, SBC208_BASE + 17, 0); + reg_dev(isbc208_r12, SBC208_BASE + 18, 0); + reg_dev(isbc208_r13, SBC208_BASE + 19, 0); + reg_dev(isbc208_r14, SBC208_BASE + 20, 0); + reg_dev(isbc208_r15, SBC208_BASE + 21, 0); + if ((isbc208_dev.flags & DEV_DIS) == 0) + isbc208_reset1(); + return SCPE_OK; +} + +void isbc208_reset1 (void) +{ + int32 i; + UNIT *uptr; + static int flag = 1; + + if (flag) sim_printf("iSBC 208: Initializing\n"); + 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 */ + 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 */ + i8237_r9 = 0; /* command */ + 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 */ + 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) +{ + t_stat r; + FILE *fp; + int32 i, c = 0; + long flen; + + 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"); + 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 (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"); + 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]); + } + sim_debug (DEBUG_flow, &isbc208_dev, " 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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, uint8 devnum) +{ + 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 -int32 isbc208_r11(int32 io, int32 data) +uint8 isbc208_r11(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read FDC data register */ wsp = 0; /* clear write stack index */ @@ -1060,511 +1580,7 @@ int32 isbc208_r11(int32 io, int32 data) return 0; } -/* Reset routine */ - -t_stat isbc208_reset (DEVICE *dptr) -{ - reg_dev(isbc208_r0, SBC208_BASE + 0); - reg_dev(isbc208_r1, SBC208_BASE + 1); - reg_dev(isbc208_r2, SBC208_BASE + 2); - reg_dev(isbc208_r3, SBC208_BASE + 3); - reg_dev(isbc208_r4, SBC208_BASE + 4); - reg_dev(isbc208_r5, SBC208_BASE + 5); - reg_dev(isbc208_r6, SBC208_BASE + 6); - reg_dev(isbc208_r7, SBC208_BASE + 7); - reg_dev(isbc208_r8, SBC208_BASE + 8); - reg_dev(isbc208_r9, SBC208_BASE + 9); - reg_dev(isbc208_rA, SBC208_BASE + 10); - reg_dev(isbc208_rB, SBC208_BASE + 11); - reg_dev(isbc208_rC, SBC208_BASE + 12); - reg_dev(isbc208_rD, SBC208_BASE + 13); - reg_dev(isbc208_rE, SBC208_BASE + 14); - reg_dev(isbc208_rF, SBC208_BASE + 15); - reg_dev(isbc208_r10, SBC208_BASE + 16); - reg_dev(isbc208_r11, SBC208_BASE + 17); - reg_dev(isbc208_r12, SBC208_BASE + 18); - reg_dev(isbc208_r13, SBC208_BASE + 19); - reg_dev(isbc208_r14, SBC208_BASE + 20); - reg_dev(isbc208_r15, SBC208_BASE + 21); - if ((isbc208_dev.flags & DEV_DIS) == 0) - isbc208_reset1(); - return SCPE_OK; -} - -void isbc208_reset1 (void) -{ - int32 i; - UNIT *uptr; - static int flag = 1; - - if (flag) sim_printf("iSBC 208: Initializing\n"); - 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 */ - 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 */ - i8237_r9 = 0; /* command */ - 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 */ - 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) -{ - t_stat r; - FILE *fp; - int32 i, c = 0; - long flen; - - 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"); - 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 (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"); - 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]); - } - sim_debug (DEBUG_flow, &isbc208_dev, " iSBC208_attach: Done\n"); - return SCPE_OK; -} - -/* isbc208 set mode = 8- or 16-bit data bus */ - -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. -*/ - -int32 isbc208_r0(int32 io, int32 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; - } -} - -int32 isbc208_r1(int32 io, int32 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; - } -} - -int32 isbc208_r2(int32 io, int32 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; - } -} - -int32 isbc208_r3(int32 io, int32 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; - } -} - -int32 isbc208_r4(int32 io, int32 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; - } -} - -int32 isbc208_r5(int32 io, int32 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; - } -} - -int32 isbc208_r6(int32 io, int32 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; - } -} - -int32 isbc208_r7(int32 io, int32 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; - } -} - -int32 isbc208_r8(int32 io, int32 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; - } -} - -int32 isbc208_r9(int32 io, int32 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; - } -} - -int32 isbc208_rA(int32 io, int32 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; - } -} - -int32 isbc208_rB(int32 io, int32 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; - } -} - -int32 isbc208_rC(int32 io, int32 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; - } -} - -int32 isbc208_rD(int32 io, int32 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; - } -} - -int32 isbc208_rE(int32 io, int32 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; - } -} - -int32 isbc208_rF(int32 io, int32 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; - } -} - -int32 isbc208_r10(int32 io, int32 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; - } -} - -int32 isbc208_r12(int32 io, int32 data) +uint8 isbc208_r12(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read interrupt status */ sim_debug (DEBUG_reg, &isbc208_dev, "isbc208_r12 read as %02X\n", isbc208_i); @@ -1576,7 +1592,7 @@ int32 isbc208_r12(int32 io, int32 data) } } -int32 isbc208_r13(int32 io, int32 data) +uint8 isbc208_r13(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r13\n"); @@ -1588,7 +1604,7 @@ int32 isbc208_r13(int32 io, int32 data) } } -int32 isbc208_r14(int32 io, int32 data) +uint8 isbc208_r14(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r14\n"); @@ -1600,7 +1616,7 @@ int32 isbc208_r14(int32 io, int32 data) } } -int32 isbc208_r15(int32 io, int32 data) +uint8 isbc208_r15(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r15\n"); diff --git a/Intel-Systems/common/isbc80-10.c b/Intel-Systems/common/isbc80-10.c index eef42d94..1c6f085c 100644 --- a/Intel-Systems/common/isbc80-10.c +++ b/Intel-Systems/common/isbc80-10.c @@ -36,49 +36,30 @@ #include "system_defs.h" -/* set the base I/O address for the first 8255 */ -#define I8255_BASE_0 0xE4 - -/* set the base I/O address for the second 8255 */ -#define I8255_BASE_1 0xE8 - -/* set the base I/O address for the 8251 */ -#define I8251_BASE 0xEC - -/* set the base and size for the EPROM on the iSBC 80/10 */ -#define ROM_SIZE 0x1000 - -/* set the base and size for the RAM on the iSBC 80/10 */ -#define RAM_BASE 0x3C00 -#define RAM_SIZE 0x0400 - -/* set INTR for CPU */ -#define INTR INT_1 - /* function prototypes */ -int32 get_mbyte(int32 addr); -int32 get_mword(int32 addr); -void put_mbyte(int32 addr, int32 val); -void put_mword(int32 addr, int32 val); +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 int32 multibus_get_mbyte(int32 addr); -extern void multibus_put_mbyte(int32 addr, int32 val); -extern int32 EPROM_get_mbyte(int32 addr); -extern int32 RAM_get_mbyte(int32 addr); -extern void RAM_put_mbyte(int32 addr, int32 val); -extern UNIT i8255_unit; +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 UNIT i8255_unit[]; extern UNIT EPROM_unit; extern UNIT RAM_unit; -extern t_stat i8255_reset (DEVICE *dptr, int32 base); -extern t_stat i8251_reset (DEVICE *dptr, int32 base); -extern t_stat pata_reset (DEVICE *dptr, int32 base); -extern t_stat EPROM_reset (DEVICE *dptr, int32 size); -extern t_stat RAM_reset (DEVICE *dptr, int32 base, int32 size); +extern t_stat i8255_reset (DEVICE *dptr, uint16 base, uint8 devnum); +extern t_stat i8251_reset (DEVICE *dptr, uint16 base, uint8 devnum); +extern t_stat pata_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); /* SBC reset routine */ @@ -86,9 +67,9 @@ t_stat SBC_reset (DEVICE *dptr) { sim_printf("Initializing iSBC-80/10:\n"); i8080_reset (NULL); - i8255_reset (NULL, I8255_BASE_0); - i8255_reset (NULL, I8255_BASE_1); - i8251_reset (NULL, I8251_BASE); + i8255_reset (NULL, I8255_BASE_0, 0); + i8255_reset (NULL, I8255_BASE_1, 1); + i8251_reset (NULL, I8251_BASE, 0); EPROM_reset (NULL, ROM_SIZE); RAM_reset (NULL, RAM_BASE, RAM_SIZE); return SCPE_OK; @@ -96,15 +77,15 @@ t_stat SBC_reset (DEVICE *dptr) /* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ -int32 get_mbyte(int32 addr) +uint8 get_mbyte(uint16 addr) { /* if local EPROM handle it */ - if (i8255_unit.u5 & 0x01) { + if (i8255_unit[0].u5 & 0x01) { if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { return EPROM_get_mbyte(addr); } } /* if local RAM handle it */ - if (i8255_unit.u5 & 0x02) { + if (i8255_unit[0].u5 & 0x02) { if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { return RAM_get_mbyte(addr); } @@ -114,9 +95,9 @@ int32 get_mbyte(int32 addr) /* get a word from memory */ -int32 get_mword(int32 addr) +uint16 get_mword(uint16 addr) { - int32 val; + uint16 val; val = get_mbyte(addr); val |= (get_mbyte(addr+1) << 8); @@ -125,14 +106,14 @@ int32 get_mword(int32 addr) /* put a byte to memory - handle RAM, ROM, I/O, and Multibus memory */ -void put_mbyte(int32 addr, int32 val) +void put_mbyte(uint16 addr, uint8 val) { /* if local EPROM handle it */ - if ((i8255_unit.u5 & 0x01) && (addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { + if ((i8255_unit[0].u5 & 0x01) && (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 ((i8255_unit.u5 & 0x02) && (addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { + if ((i8255_unit[0].u5 & 0x02) && (addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { RAM_put_mbyte(addr, val); return; } /* otherwise, try the multibus */ @@ -141,9 +122,9 @@ void put_mbyte(int32 addr, int32 val) /* put a word to memory */ -void put_mword(int32 addr, int32 val) +void put_mword(uint16 addr, uint16 val) { - put_mbyte(addr, val); + put_mbyte(addr, val & 0xff); put_mbyte(addr+1, val >> 8); } diff --git a/Intel-Systems/common/isbc80-20.c b/Intel-Systems/common/isbc80-20.c index 78dc260a..4848a962 100644 --- a/Intel-Systems/common/isbc80-20.c +++ b/Intel-Systems/common/isbc80-20.c @@ -23,61 +23,39 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from William A. Beech. - NOTES: - This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus Computer Systems. + + ?? ??? 10 - Original file. */ #include "system_defs.h" -/* set the base I/O address for the 8259 */ -#define I8259_BASE 0xD8 - -/* set the base I/O address for the first 8255 */ -#define I8255_BASE_0 0xE4 - -/* set the base I/O address for the second 8255 */ -#define I8255_BASE_1 0xE8 - -/* set the base I/O address for the 8251 */ -#define I8251_BASE 0xEC - -/* set the base and size for the EPROM on the iSBC 80/20 */ -#define ROM_SIZE 0x1000 - -/* set the base and size for the RAM on the iSBC 80/20 */ -#define RAM_BASE 0x3C00 -#define RAM_SIZE 0x0400 - -/* set INTR for CPU */ -#define INTR INT_1 - /* function prototypes */ -int32 get_mbyte(int32 addr); -int32 get_mword(int32 addr); -void put_mbyte(int32 addr, int32 val); -void put_mword(int32 addr, int32 val); -t_stat i80_10_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 function prototypes */ extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 multibus_get_mbyte(int32 addr); -extern void multibus_put_mbyte(int32 addr, int32 val); -extern int32 EPROM_get_mbyte(int32 addr); -extern int32 RAM_get_mbyte(int32 addr); -extern void RAM_put_mbyte(int32 addr, int32 val); +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 UNIT i8255_unit; extern UNIT EPROM_unit; extern UNIT RAM_unit; -extern t_stat i8251_reset (DEVICE *dptr, int32 base); -extern t_stat i8255_reset (DEVICE *dptr, int32 base); -extern t_stat i8259_reset (DEVICE *dptr, int32 base); -extern t_stat pata_reset (DEVICE *dptr, int32 base); -extern t_stat EPROM_reset (DEVICE *dptr, int32 size); -extern t_stat RAM_reset (DEVICE *dptr, int32 base, int32 size); +extern t_stat i8255_reset (DEVICE *dptr, uint16 base, uint8 devnum); +extern t_stat i8251_reset (DEVICE *dptr, uint16 base, uint8 devnum); +extern t_stat i8259_reset (DEVICE *dptr, uint16 base, uint8 devnum); +extern t_stat pata_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); /* CPU reset routine put here to cause a reset of the entire iSBC system */ @@ -86,10 +64,10 @@ t_stat SBC_reset (DEVICE *dptr) { sim_printf("Initializing iSBC-80/20\n"); i8080_reset(NULL); - i8259_reset(NULL, I8259_BASE); - i8255_reset(NULL, I8255_BASE_0); - i8255_reset(NULL, I8255_BASE_1); - i8251_reset(NULL, I8251_BASE); + i8259_reset(NULL, I8259_BASE, 0); + i8255_reset(NULL, I8255_BASE_0, 0); + i8255_reset(NULL, I8255_BASE_1, 1); + i8251_reset(NULL, I8251_BASE, 0); EPROM_reset(NULL, ROM_SIZE); RAM_reset(NULL, RAM_BASE, RAM_SIZE); return SCPE_OK; @@ -97,10 +75,8 @@ t_stat SBC_reset (DEVICE *dptr) /* get a byte from memory - handle RAM, ROM and Multibus memory */ -int32 get_mbyte(int32 addr) +uint8 get_mbyte(uint16 addr) { - int32 val, org, len; - /* if local EPROM handle it */ if ((i8255_unit.u5 & 0x01) && /* EPROM enabled? */ (addr >= EPROM_unit.u3) && (addr < (EPROM_unit.u3 + EPROM_unit.capac))) { @@ -115,9 +91,9 @@ int32 get_mbyte(int32 addr) /* get a word from memory */ -int32 get_mword(int32 addr) +uint16 get_mword(uint16 addr) { - int32 val; + uint16 val; val = get_mbyte(addr); val |= (get_mbyte(addr+1) << 8); @@ -126,7 +102,7 @@ int32 get_mword(int32 addr) /* put a byte to memory - handle RAM, ROM and Multibus memory */ -void put_mbyte(int32 addr, int32 val) +void put_mbyte(uint16 addr, uint8 val) { /* if local EPROM handle it */ if ((i8255_unit.u5 & 0x01) && /* EPROM enabled? */ @@ -144,9 +120,9 @@ void put_mbyte(int32 addr, int32 val) /* put a word to memory */ -void put_mword(int32 addr, int32 val) +void put_mword(uint16 addr, uint16 val) { - put_mbyte(addr, val); + put_mbyte(addr, val & 0xff); put_mbyte(addr+1, val >> 8); } diff --git a/Intel-Systems/common/isbc80-30.c b/Intel-Systems/common/isbc80-30.c index 6362f863..89a2ca8e 100644 --- a/Intel-Systems/common/isbc80-30.c +++ b/Intel-Systems/common/isbc80-30.c @@ -27,77 +27,89 @@ Computer Systems. ?? ??? 10 - Original file. + 17 May 16 - Modified for the iSBC 80/30 Processor Card. */ #include "system_defs.h" /* set the base I/O address for the 8259 */ -#define I8259_BASE 0xD8 +#define I8259_BASE 0xD8 +#define I8259_NUM 1 -/* set the base I/O address for the first 8255 */ +/* set the base I/O address for the 8253 */ +#define I8253_BASE 0xDC +#define I8253_NUM 1 + +/* set the base I/O address for the 8255 */ #define I8255_BASE_0 0xE4 - -/* set the base I/O address for the second 8255 */ #define I8255_BASE_1 0xE8 +#define I8255_NUM 2 /* set the base I/O address for the 8251 */ -#define I8251_BASE 0xEC +#define I8251_BASE 0xEC +#define I8251_NUM 1 -/* set the base and size for the EPROM on the iSBC 80/20 */ +/* set the base and size for the EPROM */ +#define ROM_BASE 0x0000 #define ROM_SIZE 0x1000 -/* set the base and size for the RAM on the iSBC 80/20 */ -#define RAM_BASE 0x3C00 -#define RAM_SIZE 0x0400 +/* set the base and size for the RAM */ +#define RAM_BASE 0x4000 +#define RAM_SIZE 0x2000 /* set INTR for CPU */ #define INTR INT_1 /* function prototypes */ -int32 get_mbyte(int32 addr); -int32 get_mword(int32 addr); -void put_mbyte(int32 addr, int32 val); -void put_mword(int32 addr, int32 val); +uint16 get_mbyte(uint16 addr); +uint8 get_mword(uint16 addr); +void put_mbyte(uint16 addr, uint8 val); +void put_mword(uint16 addr, uint16 val); t_stat i80_10_reset (DEVICE *dptr); /* external function prototypes */ -extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 multibus_get_mbyte(int32 addr); -extern void multibus_put_mbyte(int32 addr, int32 val); -extern int32 EPROM_get_mbyte(int32 addr); -extern int32 RAM_get_mbyte(int32 addr); -extern void RAM_put_mbyte(int32 addr, int32 val); +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8085 emulator */ +extern int32 multibus_get_mbyte(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern int32 EPROM_get_mbyte(uint16 addr); +extern int32 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16, uint8 val); +extern UNIT i8251_unit; +extern UNIT i8253_unit; extern UNIT i8255_unit; +extern UNIT i8259_unit; extern UNIT EPROM_unit; extern UNIT RAM_unit; -extern t_stat i8251_reset (DEVICE *dptr, int32 base); -extern t_stat i8255_reset (DEVICE *dptr, int32 base); -extern t_stat i8259_reset (DEVICE *dptr, int32 base); -extern t_stat pata_reset (DEVICE *dptr, int32 base); -extern t_stat EPROM_reset (DEVICE *dptr, int32 size); -extern t_stat RAM_reset (DEVICE *dptr, int32 base, int32 size); +extern t_stat i8259_reset (DEVICE *dptr, uint16 base); +extern t_stat i8253_reset (DEVICE *dptr, uint16 base); +extern t_stat i8255_reset (DEVICE *dptr, uint16 base); +extern t_stat i8251_reset (DEVICE *dptr, uint16 base); +extern t_stat pata_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); /* 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"); + sim_printf("Initializing iSBC-80/30\n"); i8080_reset(NULL); - i8259_reset(NULL, I8259_BASE); - i8255_reset(NULL, I8255_BASE_0); - i8255_reset(NULL, I8255_BASE_1); - i8251_reset(NULL, I8251_BASE); - EPROM_reset(NULL, ROM_SIZE); - RAM_reset(NULL, RAM_BASE, RAM_SIZE); + i8259_reset(NULL, I8259_BASE); + i8253_reset(NULL, I8253_BASE); + i8255_reset(NULL, I8255_BASE_0); + i8255_reset(NULL, I8255_BASE_1); + i8251_reset(NULL, I8251_BASE); + EPROM_reset(NULL, ROM_SIZE); + RAM_reset(NULL, RAM_BASE, RAM_SIZE); return SCPE_OK; } /* get a byte from memory - handle RAM, ROM and Multibus memory */ -int32 get_mbyte(int32 addr) +uint8 get_mbyte(uint16 addr) { int32 val, org, len; @@ -113,7 +125,7 @@ int32 get_mbyte(int32 addr) /* get a word from memory */ -int32 get_mword(int32 addr) +uint16 get_mword(uint16 addr) { int32 val; @@ -124,7 +136,7 @@ int32 get_mword(int32 addr) /* put a byte to memory - handle RAM, ROM and Multibus memory */ -void put_mbyte(int32 addr, int32 val) +void put_mbyte(uint16 addr, uint8 val) { /* if local EPROM handle it */ if ((i8255_unit.u6 & 0x01) && (addr >= EPROM_unit.u3) && (addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { @@ -140,10 +152,10 @@ void put_mbyte(int32 addr, int32 val) /* put a word to memory */ -void put_mword(int32 addr, int32 val) +void put_mword(uint16 addr, uint16 val) { put_mbyte(addr, val); put_mbyte(addr+1, val >> 8); } -/* end of iSBC80-10.c */ +/* end of iSBC80-30.c */ diff --git a/Intel-Systems/common/mds-800.c b/Intel-Systems/common/mds-800.c deleted file mode 100644 index d5e35a12..00000000 --- a/Intel-Systems/common/mds-800.c +++ /dev/null @@ -1,143 +0,0 @@ -/* iSBC80-10.c: Intel iSBC 80/10 Processor 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. - - ?? ??? 10 - Original file. -*/ - -#include "system_defs.h" - -/* set the base I/O address for the first 8255 */ -#define I8255_BASE_0 0xE4 - -/* set the base I/O address for the second 8255 */ -#define I8255_BASE_1 0xE8 - -/* set the base I/O address for the 8251 */ -#define I8251_BASE 0xEC - -/* set the base and size for the EPROM on the iSBC 80/10 */ -#define ROM_SIZE 0x1000 - -/* set the base and size for the RAM on the iSBC 80/10 */ -#define RAM_BASE 0x3C00 -#define RAM_SIZE 0x0400 - -/* set INTR for CPU */ -#define INTR INT_1 - -/* function prototypes */ - -int32 get_mbyte(int32 addr); -int32 get_mword(int32 addr); -void put_mbyte(int32 addr, int32 val); -void put_mword(int32 addr, int32 val); -t_stat SBC_reset (DEVICE *dptr); - -/* external function prototypes */ - -extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 multibus_get_mbyte(int32 addr); -extern void multibus_put_mbyte(int32 addr, int32 val); -extern int32 EPROM_get_mbyte(int32 addr); -extern int32 RAM_get_mbyte(int32 addr); -extern void RAM_put_mbyte(int32 addr, int32 val); -extern UNIT i8255_unit; -extern UNIT EPROM_unit; -extern UNIT RAM_unit; -extern t_stat i8255_reset (DEVICE *dptr, int32 base); -extern t_stat i8251_reset (DEVICE *dptr, int32 base); -extern t_stat pata_reset (DEVICE *dptr, int32 base); -extern t_stat EPROM_reset (DEVICE *dptr, int32 size); -extern t_stat RAM_reset (DEVICE *dptr, int32 base, int32 size); - -/* SBC reset routine */ - -t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing iSBC-80/10:\n"); - i8080_reset (NULL); - i8255_reset (NULL, I8255_BASE_0); - i8255_reset (NULL, I8255_BASE_1); - i8251_reset (NULL, I8251_BASE); - EPROM_reset (NULL, ROM_SIZE); - RAM_reset (NULL, RAM_BASE, RAM_SIZE); - return SCPE_OK; -} - -/* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ - -int32 get_mbyte(int32 addr) -{ - int32 val, org, len; - - /* if local EPROM handle it */ - if ((i8255_unit.u5 & 0x01) && (addr >= EPROM_unit.u3) && (addr < (EPROM_unit.u3 + EPROM_unit.capac))) { - return EPROM_get_mbyte(addr); - } /* if local RAM handle it */ - if ((i8255_unit.u5 & 0x02) && (addr >= RAM_unit.u3) && (addr < (RAM_unit.u3 + RAM_unit.capac))) { - return RAM_get_mbyte(addr); - } /* otherwise, try the multibus */ - return multibus_get_mbyte(addr); -} - -/* get a word from memory */ - -int32 get_mword(int32 addr) -{ - int32 val; - - val = get_mbyte(addr); - val |= (get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte to memory - handle RAM, ROM, I/O, and Multibus memory */ - -void put_mbyte(int32 addr, int32 val) -{ - /* if local EPROM handle it */ - if ((i8255_unit.u5 & 0x01) && (addr >= EPROM_unit.u3) && (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 ((i8255_unit.u5 & 0x02) && (addr >= RAM_unit.u3) && (addr <= (RAM_unit.u3 + RAM_unit.capac))) { - RAM_put_mbyte(addr, val); - return; - } /* otherwise, try the multibus */ - multibus_put_mbyte(addr, val); -} - -/* put a word to memory */ - -void put_mword(int32 addr, int32 val) -{ - put_mbyte(addr, val); - put_mbyte(addr+1, val >> 8); -} - -/* end of iSBC80-10.c */ diff --git a/Intel-Systems/common/multibus.c b/Intel-Systems/common/multibus.c index 159967a3..e183a670 100644 --- a/Intel-Systems/common/multibus.c +++ b/Intel-Systems/common/multibus.c @@ -48,19 +48,17 @@ t_stat multibus_svc(UNIT *uptr); t_stat multibus_reset(DEVICE *dptr); void set_irq(int32 int_num); void clr_irq(int32 int_num); -int32 nulldev(int32 io, int32 data); -int32 reg_dev(int32 (*routine)(int32, int32), int32 port); +uint8 nulldev(t_bool io, uint8 data, uint8 devnum); +uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint16 port, uint8 devnum); t_stat multibus_reset (DEVICE *dptr); -int32 multibus_get_mbyte(int32 addr); -int32 multibus_get_mword(int32 addr); -void multibus_put_mbyte(int32 addr, int32 val); -void multibus_put_mword(int32 addr, int32 val); +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 int32 isbc064_get_mbyte(int32 addr); -extern void isbc064_put_mbyte(int32 addr, int32 val); +extern uint8 isbc064_get_mbyte(uint16 addr); +extern void isbc064_put_mbyte(uint16 addr, uint8 val); extern void set_cpuint(int32 int_num); extern t_stat SBC_reset (DEVICE *dptr); extern t_stat isbc064_reset (DEVICE *dptr); @@ -99,7 +97,7 @@ DEVICE multibus_dev = { NULL, //modifiers 1, //numunits 16, //aradix - 32, //awidth + 16, //awidth 1, //aincr 16, //dradix 8, //dwidth @@ -163,10 +161,11 @@ void clr_irq(int32 int_num) /* 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 is available +address is here, 'nulldev' means no device has been registered. */ struct idev { - int32 (*routine)(int32, int32); + uint8 (*routine)(t_bool io, uint8 data, uint8 devnum); + uint8 devnum; }; struct idev dev_table[256] = { @@ -236,7 +235,7 @@ struct idev dev_table[256] = { {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */ }; -int32 nulldev(int32 flag, int32 data) +uint8 nulldev(t_bool flag, uint8 data, uint8 devnum) { SET_XACK(0); /* set no XACK */ if (flag == 0) /* if we got here, no valid I/O device */ @@ -244,40 +243,30 @@ int32 nulldev(int32 flag, int32 data) return 0; } -int32 reg_dev(int32 (*routine)(int32, int32), int32 port) +uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint16 port, uint8 devnum) { if (dev_table[port].routine != &nulldev) { /* port already assigned */ // sim_printf("Multibus: I/O Port %02X is already assigned\n", port); } else { // sim_printf("Port %02X is assigned\n", port); dev_table[port].routine = routine; + dev_table[port].devnum = devnum; } return 0; } /* get a byte from memory */ -int32 multibus_get_mbyte(int32 addr) +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); } -/* get a word from memory */ - -int32 multibus_get_mword(int32 addr) -{ - int32 val; - - val = multibus_get_mbyte(addr); - val |= (multibus_get_mbyte(addr+1) << 8); - return val; -} - /* put a byte to memory */ -void multibus_put_mbyte(int32 addr, int32 val) +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); @@ -285,13 +274,5 @@ void multibus_put_mbyte(int32 addr, int32 val) // sim_printf("multibus_put_mbyte: Done XACK=%dX\n", XACK); } -/* put a word to memory */ - -void multibus_put_mword(int32 addr, int32 val) -{ - multibus_put_mbyte(addr, val); - multibus_put_mbyte(addr+1, val << 8); -} - /* end of multibus.c */ diff --git a/Intel-Systems/isys8010/System_80-10.vsd b/Intel-Systems/isys8010/System_80-10.vsd deleted file mode 100644 index 7f4a87f5e1bf3e8376296fde8c24359e909055c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57856 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 diff --git a/Intel-Systems/isys8010/isys8010.txt b/Intel-Systems/isys8010/isys8010.txt deleted file mode 100644 index e63bdd6e..00000000 --- a/Intel-Systems/isys8010/isys8010.txt +++ /dev/null @@ -1,211 +0,0 @@ -Altair 8800 Simulator -===================== - -1. Background. - - The MITS (Micro Instrumentation and Telemetry Systems) Altair 8800 -was announced on the January 1975 cover of Popular Electronics, which -boasted you could buy and build this powerful computer kit for only $397. -The kit consisted at that time of only the parts to build a case, power -supply, card cage (18 slots), CPU card, and memory card with 256 *bytes* of -memory. Still, thousands were ordered within the first few months after the -announcement, starting the personal computer revolution as we know it today. - - Many laugh at the small size of the that first kit, noting there -were no peripherals and the 256 byte memory size. But the computer was an -open system, and by 1977 MITS and many other small startups had added many -expansion cards to make the Altair quite a respectable little computer. The -"Altair Bus" that made this possible was soon called the S-100 Bus, later -adopted as an industry standard, and eventually became the IEE-696 Bus. - -2. Hardware - - We are simulating a fairly "loaded" Altair 8800 from about 1977, -with the following configuration: - - device simulates - name(s) - - CPU Altair 8800 with Intel 8080 CPU board, 62KB - of RAM, 2K of EPROM with start boot ROM. - 2SIO MITS 88-2SIO Dual Serial Interface Board. Port 1 - is assumed to be connected to a serial "glass - TTY" that is your terminal running the Simulator. - PTR Paper Tape Reader attached to port 2 of the - 2SIO board. - PTP Paper Tape Punch attached to port 2 of the - 2SIO board. This also doubles as a printer - port. - DSK MITS 88-DISK Floppy Disk controller with up - to eight drives. - -2.1 CPU - - We have 2 CPU options that were not present on the original -machine but are useful in the simulator. We also allow you to select -memory sizes, but be aware that some sample software requires the full -64K (i.e. CP/M) and the MITS Disk Basic and Altair DOS require about -a minimum of 24K. - - SET CPU 8080 Simulates the 8080 CPU (normal) - SET CPU Z80 Simulates the later Z80 CPU [At the present time - this is not fully implemented and is not to be - trusted with real Z80 software] - SET CPU ITRAP Causes the simulator to halt if an invalid 8080 - Opcode is detected. - SET CPU NOITRAP Does not stop on an invalid Opcode. This is - how the real 8080 works. - SET CPU 4K - SET CPU 8K - SET CPU 12K - SET CPU 16K - ...... - SET CPU 64K All these set various CPU memory configurations. - The 2K EPROM at the high end of memory is always - present and will always boot. - -The BOOT EPROM card starts at address 177400. Jumping to this address -will always boot drive 0 of the floppy controller. If no valid bootable -software is present there the machine crashes. This is historically -accurate behavior. - -The real 8080, on receiving a HLT (Halt) instruction, freezes the processor -and only an interrupt or CPU hardware reset will restore it. The simulator -is alot nicer, it will halt but send you back to the simulator command line. - -CPU Registers include the following: - - name size comments - - PC 16 The Program Counter - A 8 The accumulator - BC 16 The BC register pair. Register B is the high - 8 bits, C is the lower 8 bits - DE 16 The DE register pair. D is the top 8 bits, E is - the bottom. - HL 16 The HL register pair. H is top, L is bottom. - C 1 Carry flag. - Z 1 Zero Flag. - AC 1 Auxillary Carry flag. - P 1 Parity flag. - S 1 Sign flag. - SR 16 The front panel switches. - BREAK 16 Breakpoint address (377777 to disable). - WRU 8 The interrupt character. This starts as 005 - (ctrl-E) but some Altair software uses this - keystroke so best to change this to something - exotic such as 035 (which is Ctl-]). - - -2.2 The Serial I/O Card (2SIO) - - This simple programmed I/O device provides 2 serial ports to the -outside world, which could be hardware jumpered to support RS-232 plugs or a -TTY current loop interface. The standard I/O addresses assigned by MITS -was 20-21 (octal) for the first port, and 22-23 (octal) for the second. -We follow this standard in the Simulator. - - The simulator directs I/O to/from the first port to the screen. The -second port reads from an attachable "tape reader" file on input, and writes -to an attachable "punch file" on output. These files are considered a -simple stream of 8-bit bytes. - -2.3 The 88-DISK controller. - - The MITS 88-DISK is a simple programmed I/O interface to the MITS -8-inch floppy drive, which was basically a Pertec FD-400 with a power -supply and buffer board builtin. The controller supports neither interrupts -nor DMA, so floppy access required the sustained attention of the CPU. -The standard I/O addresses were 10, 11, and 12 (octal), and we follow the -standard. Details on controlling this hardware are in the altair_dsk.c -source file. - - -3. Sample Software - - Running an Altair in 1977 you would be running either MITS Disk -Extended BASIC, or the brand new and sexy CP/M Operating System from Digital -Research. Or possibly, you ordered Altair DOS back when it was promised in -1975, and are still waiting for it to be delivered in early 1977. - - We have samples of all three for you to check out. We can't go into -the details of how they work, but we'll give you a few hints. - - -3.1 CP/M Version 2.2 - - This version is my own port of the standard CP/M to the Altair. -There were some "official" versions but I don't have them. None were -endorsed or sold by MITS to my knowledge, however. - To boot CP/M: - - sim> attach dsk0 altcpm.dsk - sim> go 177400 - 62K CP/M VERSION 2.2 (ALTAIR 8800) - A>DIR - - CP/M feels like DOS, sort of. DIR will work. I have included all -the standard CP/M utilities, plus a few common public-domain ones. I also -include the sources to the customized BIOS and some other small programs. -TYPE will print an ASCII file. DUMP will dump a binary one. LS is a better -DIR than DIR. ASM will assemble .ASM files to Hex, LOAD will "load" them to -binary format (.COM). ED is a simple editor, #A command will bring the -source file to the buffer, T command will "type" lines, L will move lines, -E exits the editor. 20L20T will move down 20 lines, and type 20. Very -DECish. DDT is the debugger, SUBMIT is a batch-type command processor. -A sample batch file that will assemble and write out the bootable CP/M -image (on drive A) is "SYSGEN.SUB". To run it, type "SUBMIT SYSGEN". - - -3.2 MITS Disk Extended BASIC Version 4.1 - - This was the commonly used software for serious users of the Altair -computer. It is a powerful (but slow) BASIC with some extended commands to -allow it to access and manage the disk. There was no operating system it -ran under. To boot: - - sim> attach dsk0 mbasic.dsk - sim> go 177400 - - MEMORY SIZE? [return] - LINEPRINTER? C [return] - HIGHEST DISK NUMBER? 0 [return] (3 here = 4 drive system) - NUMBER OF FILES? 3 [return] - NUMBER OF RANDOM FILES? 2 [return] - - 44297 BYTES FREE - ALTAIR BASIC REV. 4.1 - [DISK EXTENDED VERSION] - COPYRIGHT 1977 BY MITS INC. - OK - mount 0 - OK - files - - -3.3 Altair DOS Version 1.0 - - This was long promised but not delivered until it was almost -irrelevant. A short attempted tour will reveal it to be a dog, far inferior -to CP/M. To boot: - - sim> attach dsk0 altdos.dsk - sim> go 177400 - - MEMORY SIZE? 64 [return] - INTERRUPTS? N [return] - HIGHEST DISK NUMBER? 0 [return] (3 here = 4 drive system) - HOW MANY DISK FILES? 3 [return] - HOW MANY RANDOM FILES? 2 [return] - - 056769 BYTES AVAILABLE - DOS MONITOR VER 1.0 - COPYRIGHT 1977 BY MITS INC - .mnt 0 - - .dir 0 - - - - - diff --git a/Intel-Systems/isys8010/isys8010_cfg.h b/Intel-Systems/isys8010/isys8010_cfg.h deleted file mode 100644 index d38d3529..00000000 --- a/Intel-Systems/isys8010/isys8010_cfg.h +++ /dev/null @@ -1,41 +0,0 @@ -/* system_80_10.cfg: Intel System 80/10 simulator definitions - - This file holds the configuration for the System 80/10 - boards I/O and Memory. - - 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. - - 16 Dec 12 - Original file -*/ - -/* set the base I/O address for the iSBC 208 */ -#define SBC208_BASE 0x40 - -/* configure interrupt request line */ -#define SBC208_INT INT_1 - -/* set the base and size for the iSBC 064 */ -#define SBC064_BASE 0x0000 -#define SBC064_SIZE 0x10000 - diff --git a/Intel-Systems/isys8010/system_defs.h b/Intel-Systems/isys8010/system_defs.h index a00e72a1..adb9c911 100644 --- a/Intel-Systems/isys8010/system_defs.h +++ b/Intel-Systems/isys8010/system_defs.h @@ -24,14 +24,43 @@ in this Software without prior written authorization from William A. Beech. ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. */ #include #include -#include "isys8010_cfg.h" /* Intel System 80/10 configuration */ +//#include "isys8010_cfg.h" /* Intel System 80/10 configuration */ #include "sim_defs.h" /* simulator defns */ +/* 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 and device count for the 8251s */ +#define I8251_BASE 0xEC +#define I8251_NUM 1 + +/* set the base and size for the EPROM on the iSBC 80/10 */ +#define ROM_BASE 0x0000 +#define ROM_SIZE 0x1000 + +/* set the base and size for the RAM on the iSBC 80/10 */ +#define RAM_BASE 0x3C00 +#define RAM_SIZE 0x0400 + +/* set INTR for CPU on the iSBC 80/10 */ +#define INTR INT_1 + +/* set the base I/O address for the iSBC 208 */ +#define SBC208_BASE 0x40 + +/* configure interrupt request line */ +#define SBC208_INT INT_1 + +/* set the base and size for the iSBC 064 */ +#define SBC064_BASE 0x0000 +#define SBC064_SIZE 0x10000 + /* multibus interrupt definitions */ #define INT_0 0x01 diff --git a/Intel-Systems/isys8020/system_defs.h b/Intel-Systems/isys8020/system_defs.h index 6a9a6b27..d432a214 100644 --- a/Intel-Systems/isys8020/system_defs.h +++ b/Intel-Systems/isys8020/system_defs.h @@ -24,14 +24,46 @@ in this Software without prior written authorization from William A. Beech. ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. */ #include #include -#include "isys8020_cfg.h" /* Intel System 80/20 configuration */ #include "sim_defs.h" /* simulator defns */ +/* set the base I/O address for the 8259 */ +#define I8259_BASE 0xD8 +#define I8259_NUM 1 + +/* 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 8251 */ +#define I8251_BASE 0xEC +#define I8251_NUM 1 + +/* set the base and size for the EPROM on the iSBC 80/20 */ +#define ROM_BASE 0x0000 +#define ROM_SIZE 0x1000 + +/* set the base and size for the RAM on the iSBC 80/20 */ +#define RAM_BASE 0x3C00 +#define RAM_SIZE 0x0400 + +/* set INTR for CPU */ +#define INTR INT_1 + +/* set the base I/O address for the iSBC 208 */ +#define SBC208_BASE 0x40 + +/* configure interrupt request line */ +#define SBC208_INT INT_1 + +/* set the base and size for the iSBC 064 */ +#define SBC064_BASE 0x0000 +#define SBC064_SIZE 0x10000 + /* multibus interrupt definitions */ #define INT_0 0x01 diff --git a/Intel-Systems/isys8020/isys8020_cfg.h b/Intel-Systems/isys8030/isys8030_cfg.h similarity index 100% rename from Intel-Systems/isys8020/isys8020_cfg.h rename to Intel-Systems/isys8030/isys8030_cfg.h diff --git a/Visual Studio Projects/isys8020.vcproj b/Visual Studio Projects/isys8020.vcproj index 391a762d..8697ff65 100644 --- a/Visual Studio Projects/isys8020.vcproj +++ b/Visual Studio Projects/isys8020.vcproj @@ -221,7 +221,7 @@ >