diff --git a/IBMPC-Systems/common/i8255.c b/IBMPC-Systems/common/i8255.c index d3545cbe..bb0851e9 100644 --- a/IBMPC-Systems/common/i8255.c +++ b/IBMPC-Systems/common/i8255.c @@ -26,7 +26,7 @@ MODIFICATIONS: ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set baseport and size. 24 Apr 15 -- Modified to use simh_debug NOTES: @@ -83,7 +83,7 @@ extern uint16 port; //port called in dev_table[port] /* function prototypes */ -t_stat i8255_reset (DEVICE *dptr, uint16 base); +t_stat i8255_reset (DEVICE *dptr, uint16 baseport); uint8 i8255_get_dn(void); uint8 i8255s(t_bool io, uint8 data); uint8 i8255a(t_bool io, uint8 data); @@ -92,12 +92,12 @@ uint8 i8255c(t_bool io, uint8 data); /* external function prototypes */ -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); /* globals */ int32 i8255_devnum = 0; //actual number of 8255 instances + 1 -uint16 i8255_port[4]; //base port registered to each instance +uint16 i8255_port[4]; //baseport port registered to each instance /* these bytes represent the input and output to/from a port instance */ @@ -175,22 +175,23 @@ DEVICE i8255_dev = { /* Reset routine */ -t_stat i8255_reset (DEVICE *dptr, uint16 base) +t_stat i8255_reset (DEVICE *dptr, uint16 baseport) { if (i8255_devnum > I8255_NUM) { sim_printf("i8255_reset: too many devices!\n"); return SCPE_MEM; } - i8255_port[i8255_devnum] = reg_dev(i8255a, base); - reg_dev(i8255b, base + 1); - reg_dev(i8255c, base + 2); - reg_dev(i8255s, base + 3); + sim_printf(" 8255-%d: Reset\n", i8255_devnum); + sim_printf(" 8255-%d: Registered at %04X\n", i8255_devnum, baseport); + i8255_port[i8255_devnum] = baseport; + reg_dev(i8255a, baseport, i8255_devnum); + reg_dev(i8255b, baseport + 1, i8255_devnum); + reg_dev(i8255c, baseport + 2, i8255_devnum); + reg_dev(i8255s, baseport + 3, i8255_devnum); i8255_unit[i8255_devnum].u3 = 0x9B; /* control */ i8255_A[i8255_devnum] = 0xFF; /* Port A */ i8255_B[i8255_devnum] = 0xFF; /* Port B */ i8255_C[i8255_devnum] = 0xFF; /* Port C */ - sim_printf(" 8255-%d: Reset\n", i8255_devnum); - sim_printf(" 8255-%d: Registered at %03X\n", i8255_devnum, base); i8255_devnum++; return SCPE_OK; } @@ -202,7 +203,7 @@ uint8 i8255_get_dn(void) for (i=0; i=i8255_port[i] && port <= i8255_port[i] + 3) return i; - sim_printf("i8255_get_dn: port %03X not in 8255 device table\n", port); + sim_printf("i8255_get_dn: port %04X not in 8255 device table\n", port); return 0xFF; } diff --git a/Intel-Systems/common/i8008.c b/Intel-Systems/common/i8008.c index 56025d08..05a07727 100644 --- a/Intel-Systems/common/i8008.c +++ b/Intel-Systems/common/i8008.c @@ -196,7 +196,7 @@ DEBTAB i8008_debug[] = { }; DEVICE i8008_dev = { - "CPU", //name + "I8008", //name &i8008_unit, //units i8008_reg, //registers i8008_mod, //modifiers diff --git a/Intel-Systems/common/i8080.c b/Intel-Systems/common/i8080.c index 5b017e7b..474c67a6 100644 --- a/Intel-Systems/common/i8080.c +++ b/Intel-Systems/common/i8080.c @@ -171,6 +171,7 @@ uint32 int_req = 0; /* Interrupt request */ int32 PCX; /* External view of PC */ int32 PC; UNIT *uptr; +uint32 port; //port used in any IN/OUT /* function prototypes */ void set_cpuint(int32 int_num); @@ -206,7 +207,8 @@ extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ struct idev { - uint8 (*routine)(t_bool, uint8, uint8); + uint8 (*routine)(t_bool, uint8); + uint16 port; uint8 devnum; }; @@ -265,7 +267,7 @@ DEBTAB i8080_debug[] = { }; DEVICE i8080_dev = { - "CPU", //name + "I8080", //name &i8080_unit, //units i8080_reg, //registers i8080_mod, //modifiers @@ -393,12 +395,10 @@ int32 sim_instr (void) reason = 0; uptr = i8080_dev.units; - if (i8080_dev.dctrl & DEBUG_flow) { - if (uptr->flags & UNIT_8085) - sim_printf("CPU = 8085\n"); - else - sim_printf("CPU = 8080\n"); - } + if (uptr->flags & UNIT_8085) + sim_printf("CPU = 8085\n"); + else + sim_printf("CPU = 8080\n"); /* Main instruction fetch/decode loop */ while (reason == 0) { /* loop until halted */ @@ -472,9 +472,9 @@ int32 sim_instr (void) IR = OP = fetch_byte(0); /* instruction fetch */ if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */ - reason = STOP_XACK; - sim_printf("Stopped for XACK-1 PC=%04X\n", --PC); - continue; +// reason = STOP_XACK; + sim_printf("Stopped for XACK-1 PC=%04X\n", PC); +// continue; } if (OP == 0x76) { /* HLT Instruction*/ @@ -890,14 +890,18 @@ int32 sim_instr (void) case 0xDB: /* IN */ DAR = fetch_byte(1); - A = dev_table[DAR].routine(0, 0, dev_table[DAR].devnum); + port = DAR; + //A = dev_table[DAR].routine(0, 0, dev_table[DAR].devnum); + A = dev_table[DAR].routine(0, 0); 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].devnum); + port = DAR; + //dev_table[DAR].routine(1, A, dev_table[DAR].devnum); + dev_table[DAR].routine(1, A); // sim_printf("\n%04X\tOUT\t%02X\t;devnum=%d", PC - 1, DAR, dev_table[DAR].devnum); break; @@ -909,12 +913,12 @@ int32 sim_instr (void) break; } loop_end: - if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */ - reason = STOP_XACK; - sim_printf("Stopped for XACK-2 PC=%04X\n", --PC); - continue; - } - +// if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */ +// reason = STOP_XACK; +// sim_printf("Stopped for XACK-2 PC=%04X\n", PC); +// continue; +// } + ; } /* Simulation halted */ @@ -1296,7 +1300,7 @@ int32 sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) return (SCPE_OK); } -/* Symbolic output +/* Symbolic output - working Inputs: *of = output stream @@ -1329,17 +1333,17 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, inst = val[0]; fprintf (of, "%s", opcode[inst]); if (oplen[inst] == 2) { - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); +// if (strchr(opcode[inst], ' ') != NULL) +// fprintf (of, ","); +// else fprintf (of, " "); fprintf (of, "%02X", val[1]); } if (oplen[inst] == 3) { adr = val[1] & 0xFF; adr |= (val[2] << 8) & 0xff00; - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); +// if (strchr(opcode[inst], ' ') != NULL) +// fprintf (of, ","); +// else fprintf (of, " "); fprintf (of, "%04X", adr); } return -(oplen[inst] - 1); diff --git a/Intel-Systems/common/i8088.c b/Intel-Systems/common/i8088.c index 934b2d07..c5387494 100644 --- a/Intel-Systems/common/i8088.c +++ b/Intel-Systems/common/i8088.c @@ -449,7 +449,7 @@ DEBTAB i8088_debug[] = { }; DEVICE i8088_dev = { - "CPU", //name + "I8088", //name &i8088_unit, //units i8088_reg, //registers i8088_mod, //modifiers diff --git a/Intel-Systems/common/i8237.c b/Intel-Systems/common/i8237.c new file mode 100644 index 00000000..fbbcaffb --- /dev/null +++ b/Intel-Systems/common/i8237.c @@ -0,0 +1,867 @@ +/* i8237.c: Intel 8237 DMA adapter + + Copyright (c) 2016, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + 11 Jul 16 - Original file. + + NOTES: + + + Default is none. Since all channel registers in the i8237 are 16-bit, transfers + are done as two 8-bit operations, low- then high-byte. + + Port addressing is as follows (Port offset = 0): + + Port Mode Command Function + + 00 Write Load DMAC Channel 0 Base and Current Address Regsiters + Read Read DMAC Channel 0 Current Address Register + 01 Write Load DMAC Channel 0 Base and Current Word Count Registers + Read Read DMAC Channel 0 Current Word Count Register + 02 Write Load DMAC Channel 1 Base and Current Address Regsiters + Read Read DMAC Channel 1 Current Address Register + 03 Write Load DMAC Channel 1 Base and Current Word Count Registers + Read Read DMAC Channel 1 Current Word Count Register + 04 Write Load DMAC Channel 2 Base and Current Address Regsiters + Read Read DMAC Channel 2 Current Address Register + 05 Write Load DMAC Channel 2 Base and Current Word Count Registers + Read Read DMAC Channel 2 Current Word Count Register + 06 Write Load DMAC Channel 3 Base and Current Address Regsiters + Read Read DMAC Channel 3 Current Address Register + 07 Write Load DMAC Channel 3 Base and Current Word Count Registers + Read Read DMAC Channel 3 Current Word Count Register + 08 Write Load DMAC Command Register + Read Read DMAC Status Register + 09 Write Load DMAC Request Register + 0A Write Set/Reset DMAC Mask Register + 0B Write Load DMAC Mode Register + 0C Write Clear DMAC First/Last Flip-Flop + 0D Write DMAC Master Clear + 0F Write Load DMAC Mask Register + + Register usage is defined in the following paragraphs. + + Read/Write DMAC Address Registers + + Used to simultaneously load a channel's current-address register and base-address + register with the memory address of the first byte to be transferred. (The Channel + 0 current/base address register must be loaded prior to initiating a diskette read + or write operation.) Since each channel's address registers are 16 bits in length + (64K address range), two "write address register" commands must be executed in + order to load the complete current/base address registers for any channel. + + Read/Write DMAC Word Count Registers + + The Write DMAC Word Count Register command is used to simultaneously load a + channel's current and base word-count registers with the number of bytes + to be transferred during a subsequent DMA operation. Since the word-count + registers are 16-bits in length, two commands must be executed to load both + halves of the registers. + + Write DMAC Command Register + + The Write DMAC Command Register command loads an 8-bit byte into the + DMAC's command register to define the operating characteristics of the + DMAC. The functions of the individual bits in the command register are + defined in the following diagram. Note that only two bits within the + register are applicable to the controller; the remaining bits select + functions that are not supported and, accordingly, must always be set + to zero. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | 0 0 0 0 0 0 | + +---+---+---+---+---+---+---+---+ + | | + | +---------- 0 CONTROLLER ENABLE + | 1 CONTROLLER DISABLE + | + +------------------ 0 FIXED PRIORITY + 1 ROTATING PRIORITY + + Read DMAC Status Register Command + + The Read DMAC Status Register command accesses an 8-bit status byte that + identifies the DMA channels that have reached terminal count or that + have a pending DMA request. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | 0 0 | + +---+---+---+---+---+---+---+---+ + | | | | | | + | | | | | +-- CHANNEL 0 TC + | | | | +---------- CHANNEL 2 TC + | | | +-------------- CHANNEL 3 TC + | | +------------------ CHANNEL 0 DMA REQUEST + | +-------------------------- CHANNEL 2 DMA REQUEST + +------------------------------ CHANNEL 3 DMA REQUEST + + Write DMAC Request Register + + The data byte associated with the Write DMAC Request Register command + sets or resets a channel's associated request bit within the DMAC's + internal 4-bit request register. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | +---+-- 00 SELECT CHANNEL 0 + | 01 SELECT CHANNEL 1 + | 10 SELECT CHANNEL 2 + | 11 SELECT CHANNEL 3 + | + +---------- 0 RESET REQUEST BIT + 1 SET REQUEST BIT + + Set/Reset DMAC Mask Register + + Prior to a DREQ-initiated DMA transfer, the channel's mask bit must + be reset to enable recognition of the DREQ input. When the transfer + is complete (terminal count reached or external EOP applied) and + the channel is not programmed to autoinitialize, the channel's + mask bit is automatically set (disabling DREQ) and must be reset + prior to a subsequent DMA transfer. All four bits of the mask + register are set (disabling the DREQ inputs) by a DMAC master + clear or controller reset. Additionally, all four bits can be + set/reset by a single Write DMAC Mask Register command. + + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | +---+-- 00 SELECT CHANNEL 0 + | 01 SELECT CHANNEL 1 + | 10 SELECT CHANNEL 2 + | 11 SELECT CHANNEL 3 + | + +---------- 0 RESET REQUEST BIT + 1 SET REQUEST BIT + + Write DMAC Mode Register + + The Write DMAC Mode Register command is used to define the + operating mode characteristics for each DMA channel. Each + channel has an internal 6-bit mode register; the high-order + six bits of the associated data byte are written into the + mode register addressed by the two low-order bits. + + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | | + +---+---+---+---+---+---+---+---+ + | | | | | | | | + | | | | | | +---+-- 00 SELECT CHANNEL 0 + | | | | | | 01 SELECT CHANNEL 1 + | | | | | | 10 SELECT CHANNEL 2 + | | | | | | 11 SELECT CHANNEL 3 + | | | | | | + | | | | +---+---------- 00 VERIFY TRANSFER + | | | | 01 WRITE TRANSFER + | | | | 10 READ TRANSFER + | | | | + | | | +------------------ 0 AUTOINITIALIZE DISABLE + | | | 1 AUTOINITIALIZE ENABLE + | | | + | | +---------------------- 0 ADDRESS INCREMENT + | | 1 ADDRESS DECREMENT + | | + +---+-------------------------- 00 DEMAND MODE + 01 SINGLE MODE + 10 BLOCK MODE + + Clear DMAC First/Last Flip-Flop + + The Clear DMAC First/Last Flip-Flop command initializes + the DMAC's internal first/last flip-flop so that the + next byte written to or re~d from the 16-bit address + or word-count registers is the low-order byte. The + flip-flop is toggled with each register access so that + a second register read or write command accesses the + high-order byte. + + DMAC Master Clear + + The DMAC Master Clear command clears the DMAC's command, status, + request, and temporary registers to zero, initializes the + first/last flip-flop, and sets the four channel mask bits in + the mask register to disable all DMA requests (i.e., the DMAC + is placed in an idle state). + + Write DMAC Mask Register + + The Write DMAC Mask Register command allows all four bits of the + DMAC's mask register to be written with a single command. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | | +-- 0 CLEAR CHANNEL 0 MASK BIT + | | 1 SET CHANNEL 0 MASK BIT + | | + | +---------- 0 CLEAR CHANNEL 2 MASK BIT + | 1 SET CHANNEL 2 MASK BIT + | + +-------------- 0 CLEAR CHANNEL 3 MASK BIT + 1 SET CHANNEL 3 MASK BIT + +*/ + +#include "system_defs.h" + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* globals */ + +int32 i8237_devnum = 0; //actual number of 8253 instances + 1 +uint16 i8237_port[4]; //base port registered to each instance + +/* function prototypes */ + +t_stat i8237_svc(UNIT *uptr); +t_stat i8237_reset(DEVICE *dptr, uint16 base); +void i8237_reset1(int32 devnum); +t_stat i8237_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +uint8 i8237_r0x(t_bool io, uint8 data); +uint8 i8237_r1x(t_bool io, uint8 data); +uint8 i8237_r2x(t_bool io, uint8 data); +uint8 i8237_r3x(t_bool io, uint8 data); +uint8 i8237_r4x(t_bool io, uint8 data); +uint8 i8237_r5x(t_bool io, uint8 data); +uint8 i8237_r6x(t_bool io, uint8 data); +uint8 i8237_r7x(t_bool io, uint8 data); +uint8 i8237_r8x(t_bool io, uint8 data); +uint8 i8237_r9x(t_bool io, uint8 data); +uint8 i8237_rAx(t_bool io, uint8 data); +uint8 i8237_rBx(t_bool io, uint8 data); +uint8 i8237_rCx(t_bool io, uint8 data); +uint8 i8237_rDx(t_bool io, uint8 data); +uint8 i8237_rEx(t_bool io, uint8 data); +uint8 i8237_rFx(t_bool io, uint8 data); + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); + +/* 8237 physical register definitions */ + +uint16 i8237_r0[4]; // 8237 ch 0 address register +uint16 i8237_r1[4]; // 8237 ch 0 count register +uint16 i8237_r2[4]; // 8237 ch 1 address register +uint16 i8237_r3[4]; // 8237 ch 1 count register +uint16 i8237_r4[4]; // 8237 ch 2 address register +uint16 i8237_r5[4]; // 8237 ch 2 count register +uint16 i8237_r6[4]; // 8237 ch 3 address register +uint16 i8237_r7[4]; // 8237 ch 3 count register +uint8 i8237_r8[4]; // 8237 status register +uint8 i8237_r9[4]; // 8237 command register +uint8 i8237_rA[4]; // 8237 mode register +uint8 i8237_rB[4]; // 8237 mask register +uint8 i8237_rC[4]; // 8237 request register +uint8 i8237_rD[4]; // 8237 first/last ff +uint8 i8237_rE[4]; // 8237 +uint8 i8237_rF[4]; // 8237 + +/* i8237 physical register definitions */ + +uint16 i8237_sr[4]; // isbc-208 segment register +uint8 i8237_i[4]; // iSBC-208 interrupt register +uint8 i8237_a[4]; // iSBC-208 auxillary port register + +/* i8237 Standard SIMH Device Data Structures - 1 unit */ + +UNIT i8237_unit[] = { + { UDATA (0, 0, 0) ,20 }, /* i8237 0 */ + { UDATA (0, 0, 0) ,20 }, /* i8237 1 */ + { UDATA (0, 0, 0) ,20 }, /* i8237 2 */ + { UDATA (0, 0, 0) ,20 } /* i8237 3 */ +}; + + +REG i8237_reg[] = { + { HRDATA (CH0ADR, i8237_r0[devnum], 16) }, + { HRDATA (CH0CNT, i8237_r1[devnum], 16) }, + { HRDATA (CH1ADR, i8237_r2[devnum], 16) }, + { HRDATA (CH1CNT, i8237_r3, 16) }, + { HRDATA (CH2ADR, i8237_r4, 16) }, + { HRDATA (CH2CNT, i8237_r5, 16) }, + { HRDATA (CH3ADR, i8237_r6, 16) }, + { HRDATA (CH3CNT, i8237_r7, 16) }, + { HRDATA (STAT37, i8237_r8, 8) }, + { HRDATA (CMD37, i8237_r9, 8) }, + { HRDATA (MODE, i8237_rA, 8) }, + { HRDATA (MASK, i8237_rB, 8) }, + { HRDATA (REQ, i8237_rC, 8) }, + { HRDATA (FF, i8237_rD, 8) }, + { HRDATA (SEGREG, i8237_sr, 8) }, + { HRDATA (AUX, i8237_a, 8) }, + { HRDATA (INT, i8237_i, 8) }, + { NULL } +}; + +MTAB i8237_mod[] = { + { 0 } +}; + +DEBTAB i8237_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { "REG", DEBUG_reg }, + { NULL } +}; + +DEVICE i8237_dev = { + "I8237", //name + i8237_unit, //units + i8237_reg, //registers + i8237_mod, //modifiers + 1, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &i8237_reset, //deposit + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags + 0, //dctrl +// DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl + i8237_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* service routine - actually does the simulated DMA */ + +t_stat i8237_svc(UNIT *uptr) +{ + sim_printf("uptr=%08X\n", uptr); + sim_activate (&i8237_unit[uptr->u6], i8237_unit[uptr->u6].wait); + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i8237_reset(DEVICE *dptr, uint16 base) +{ + if (i8237_devnum > I8237_NUM) { + sim_printf("i8237_reset: too many devices!\n"); + return SCPE_MEM; + } + sim_printf(" 8237 Reset\n"); + sim_printf(" 8237: Registered at %03X\n", base); + i8237_port[i8237_devnum] = reg_dev(i8237_r0x, base); + reg_dev(i8237_r1x, base + 1); + reg_dev(i8237_r2x, base + 2); + reg_dev(i8237_r3x, base + 3); + reg_dev(i8237_r4x, base + 4); + reg_dev(i8237_r5x, base + 5); + reg_dev(i8237_r6x, base + 6); + reg_dev(i8237_r7x, base + 7); + reg_dev(i8237_r8x, base + 8); + reg_dev(i8237_r9x, base + 9); + reg_dev(i8237_rAx, base + 10); + reg_dev(i8237_rBx, base + 11); + reg_dev(i8237_rCx, base + 12); + reg_dev(i8237_rDx, base + 13); + reg_dev(i8237_rEx, base + 14); + reg_dev(i8237_rFx, base + 15); + sim_printf(" 8237 Reset\n"); + sim_printf(" 8237: Registered at %03X\n", base); + sim_activate (&i8237_unit[i8237_devnum], i8237_unit[i8237_devnum].wait); /* activate unit */ + if ((i8237_dev.flags & DEV_DIS) == 0) + i8237_reset1(i8237_devnum); + i8237_devnum++; + return SCPE_OK; +} + +uint8 i8237_get_dn(void) +{ + int i; + + for (i=0; i=i8237_port[i] && port <= i8237_port[i] + 16) + return i; + sim_printf("i8237_get_dn: port %03X not in 8237 device table\n", port); + return 0xFF; +} + +void i8237_reset1(int32 devnum) +{ + int32 i; + UNIT *uptr; + + uptr = i8237_dev[devnum].units; + if (uptr->capac == 0) { /* if not configured */ + uptr->capac = 0; /* initialize unit */ + uptr->u3 = 0; + uptr->u4 = 0; + uptr->u5 = 0; + uptr->u6 = i; /* unit number - only set here! */ + sim_activate (&i8237_unit[devnum], i8237_unit[devnum].wait); + } + i8237_r8[devnum] = 0; /* status */ + i8237_r9[devnum] = 0; /* command */ + i8237_rB[devnum] = 0x0F; /* mask */ + i8237_rC[devnum] = 0; /* request */ + i8237_rD[devnum] = 0; /* first/last FF */ +} + + +/* i8237 set mode = 8- or 16-bit data bus */ +/* always 8-bit mode for current simulators */ + +t_stat i8237_set_mode(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + sim_debug (DEBUG_flow, &i8237_dev, " i8237_set_mode: Entered with val=%08XH uptr->flags=%08X\n", val, uptr->flags); + sim_debug (DEBUG_flow, &i8237_dev, " i8237_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 i8237_r0x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](H) read as %04X\n", devnum, i8237_r0[devnum]); + return (i8237_r0[devnum] >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](L) read as %04X\n", devnum, i8237_r0[devnum]); + return (i8237_r0[devnum] & 0xFF); + } + } else { /* write base & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r0[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](H) set to %04X\n", devnum, i8237_r0[devnum]); + } else { /* low byte */ + i8237_rD++; + i8237_r0[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](L) set to %04X\n"devnum, , i8237_r0[devnum]); + } + return 0; + } + } +} + +uint8 i8237_r1x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current word count CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](H) read as %04X\n", devnum, i8237_r1[devnum]); + return (i8237_r1[devnum][devnum] >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](L) read as %04X\n", devnum, i8237_r1[devnum]); + return (i8237_r1[devnum] & 0xFF); + } + } else { /* write base & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r1[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](H) set to %04X\n", devnum, i8237_r1[devnum]); + } else { /* low byte */ + i8237_rD++; + i8237_r1[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](L) set to %04X\n", devnum, i8237_r1[devnum]); + } + return 0; + } + } +} + +uint8 i8237_r2x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](H) read as %04X\n", devnum, i8237_r2[devnum]); + return (i8237_r2[devnum] >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](L) read as %04X\n", devnum, i8237_r2[devnum]); + return (i8237_r2[devnum] & 0xFF); + } + } else { /* write base & current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r2[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](H) set to %04X\n", devnum, i8237_r2[devnum]); + } else { /* low byte */ + i8237_rD++; + i8237_r2[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](L) set to %04X\n", devnum, i8237_r2[devnum]); + } + return 0; + } + } +} + +uint8 i8237_r3x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current word count CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(H) read as %04X\n", i8237_r3); + return (i8237_r3 >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_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, &i8237_dev, "i8237_r3(H) set to %04X\n", i8237_r3); + } else { /* low byte */ + i8237_rD++; + i8237_r3 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) set to %04X\n", i8237_r3); + } + return 0; + } + } +} + +uint8 i8237_r4x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current address CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(H) read as %04X\n", i8237_r4); + return (i8237_r4 >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_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, &i8237_dev, "i8237_r4(H) set to %04X\n", i8237_r4); + } else { /* low byte */ + i8237_rD++; + i8237_r4 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) set to %04X\n", i8237_r4); + } + return 0; + } + } +} + +uint8 i8237_r5x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current word count CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(H) read as %04X\n", i8237_r5); + return (i8237_r5 >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_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, &i8237_dev, "i8237_r5(H) set to %04X\n", i8237_r5); + } else { /* low byte */ + i8237_rD++; + i8237_r5 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) set to %04X\n", i8237_r5); + } + return 0; + } + } +} + +uint8 i8237_r6x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current address CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(H) read as %04X\n", i8237_r6); + return (i8237_r6 >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_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, &i8237_dev, "i8237_r6(H) set to %04X\n", i8237_r6); + } else { /* low byte */ + i8237_rD++; + i8237_r6 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) set to %04X\n", i8237_r6); + } + return 0; + } + } +} + +uint8 i8237_r7x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current word count CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(H) read as %04X\n", i8237_r7); + return (i8237_r7 >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_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, &i8237_dev, "i8237_r7(H) set to %04X\n", i8237_r7); + } else { /* low byte */ + i8237_rD++; + i8237_r7 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) set to %04X\n", i8237_r7); + } + return 0; + } + } +} + +uint8 i8237_r8x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read status register */ + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r8 (status) read as %02X\n", i8237_r8); + return (i8237_r8); + } else { /* write command register */ + i8237_r9 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r9 (command) set to %02X\n", i8237_r9); + return 0; + } + } +} + +uint8 i8237_r9x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_r9\n"); + return 0; + } else { /* write request register */ + i8237_rC = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rC (request) set to %02X\n", i8237_rC); + return 0; + } + } +} + +uint8 i8237_rAx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_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, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); + return 0; + } + } +} + +uint8 i8237_rBx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rB\n"); + return 0; + } else { /* write mode register */ + i8237_rA = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rA (mode) set to %02X\n", i8237_rA); + return 0; + } + } +} + +uint8 i8237_rCx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rC\n"); + return 0; + } else { /* clear byte pointer FF */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rD (FF) cleared\n"); + return 0; + } + } +} + +uint8 i8237_rDx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read temporary register */ + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rD\n"); + return 0; + } else { /* master clear */ + i8237_reset1(); + sim_debug (DEBUG_reg, &i8237_dev, "i8237 master clear\n"); + return 0; + } + } +} + +uint8 i8237_rEx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rE\n"); + return 0; + } else { /* clear mask register */ + i8237_rB = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) cleared\n"); + return 0; + } + } +} + +uint8 i8237_rFx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rF\n"); + return 0; + } else { /* write all mask register bits */ + i8237_rB = data & 0x0F; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); + return 0; + } + } +} + +/* end of i8237.c */ diff --git a/Intel-Systems/common/i8251.c b/Intel-Systems/common/i8251.c index b414b43e..00d50c14 100644 --- a/Intel-Systems/common/i8251.c +++ b/Intel-Systems/common/i8251.c @@ -26,7 +26,7 @@ MODIFICATIONS: ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set baseport and size. 24 Apr 15 -- Modified to use simh_debug NOTES: @@ -111,6 +111,10 @@ #include "system_defs.h" +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + #define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ #define UNIT_ANSI (1 << UNIT_V_ANSI) @@ -119,14 +123,22 @@ #define TXE 0x04 #define SD 0x40 -extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16, uint8); +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); + +/* globals */ + +int32 i8251_devnum = 0; //actual number of 8251 instances + 1 +uint16 i8251_port[4]; //baseport port registered to each instance /* function prototypes */ t_stat i8251_svc (UNIT *uptr); -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); +t_stat i8251_reset (DEVICE *dptr, uint16 baseport); +uint8 i8251_get_dn(void); +uint8 i8251s(t_bool io, uint8 data); +uint8 i8251d(t_bool io, uint8 data); void i8251_reset1(uint8 devnum); /* i8251 Standard I/O Data Structures */ @@ -164,20 +176,20 @@ MTAB i8251_mod[] = { /* address width is set to 16 bits to use devices in 8086/8088 implementations */ DEVICE i8251_dev = { - "8251", //name + "I8251", //name &i8251_unit, //units i8251_reg, //registers i8251_mod, //modifiers 1, //numunits 16, //aradix - 16, //awidth + 16, //awidth 1, //aincr 16, //dradix 8, //dwidth NULL, //examine NULL, //deposit // &i8251_reset, //reset - NULL, //reset + NULL, //reset NULL, //boot NULL, //attach NULL, //detach @@ -211,65 +223,23 @@ t_stat i8251_svc (UNIT *uptr) /* Reset routine */ -t_stat i8251_reset (DEVICE *dptr, uint16 base, uint8 devnum) +t_stat i8251_reset (DEVICE *dptr, uint16 baseport) { - if (devnum >= I8251_NUM) { - sim_printf("8251_reset: Illegal Device Number %d\n", devnum); + if (i8251_devnum >= I8251_NUM) { + sim_printf("8251_reset: Illegal Device Number %d\n", i8251_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_printf(" 8251-%d: Hardware Reset\n", i8251_devnum); + sim_printf(" 8251-%d: Registered at %04X\n", i8251_devnum, baseport); + i8251_port[i8251_devnum] = baseport; + reg_dev(i8251d, baseport, i8251_devnum); + reg_dev(i8251s, baseport + 1, i8251_devnum); + i8251_reset1(i8251_devnum); sim_activate (&i8251_unit, i8251_unit.wait); /* activate unit */ + i8251_devnum++; return SCPE_OK; } -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - -uint8 i8251s(t_bool io, uint8 data, uint8 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-%d: Command Instruction=%02X\n", devnum, data); - if (data & SD) /* reset port! */ - i8251_reset1(devnum); - } else { /* set mode */ - i8251_unit.u4 = data; - sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); - i8251_unit.u6 = 1; /* set cmd received */ - } - return (0); - } -} - -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); - } else { /* write data port */ - sim_putchar(data); - } - return 0; -} - void i8251_reset1(uint8 devnum) { i8251_unit.u3 = TXR + TXE; /* status */ @@ -278,7 +248,61 @@ void i8251_reset1(uint8 devnum) i8251_unit.u6 = 0; i8251_unit.buf = 0; i8251_unit.pos = 0; - sim_printf(" 8251-%d: Reset\n", devnum); + sim_printf(" 8251-%d: Software Reset\n", devnum); +} + +uint8 i8251_get_dn(void) +{ + int i; + + for (i=0; i= i8251_port[i] && port <= i8251_port[i] + 1) + return i; + sim_printf("i8251_get_dn: port %04X not in 8251 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +uint8 i8251s(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8251_get_dn()) != 0xFF) { + // sim_printf("\nio=%d data=%04X\n", io, data); + if (io == 0) { /* read status port */ + return i8251_unit.u3; + } else { /* write status port */ + if (i8251_unit.u6) { /* if mode, set cmd */ + i8251_unit.u5 = data; + sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); + if (data & SD) /* reset port! */ + i8251_reset1(devnum); + } else { /* set mode */ + i8251_unit.u4 = data; + sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); + i8251_unit.u6 = 1; /* set cmd received */ + } + } + } + return 0; +} + +uint8 i8251d(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8251_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + i8251_unit.u3 &= ~RXR; + return (i8251_unit.buf); + } else { /* write data port */ + sim_putchar(data); + } + } + return 0; } /* end of i8251.c */ diff --git a/Intel-Systems/common/i8253.c b/Intel-Systems/common/i8253.c new file mode 100644 index 00000000..79170392 --- /dev/null +++ b/Intel-Systems/common/i8253.c @@ -0,0 +1,238 @@ +/* i8253.c: Intel i8253 PIT adapter + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set baseport and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + +*/ + +#include "system_defs.h" + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); + +/* globals */ + +int32 i8253_devnum = 0; //actual number of 8253 instances + 1 +uint16 i8253_port[4]; //baseport port registered to each instance + +/* function prototypes */ + +t_stat i8253_svc (UNIT *uptr); +t_stat i8253_reset (DEVICE *dptr, uint16 baseport); +uint8 i8253_get_dn(void); +uint8 i8253t0(t_bool io, uint8 data); +uint8 i8253t1(t_bool io, uint8 data); +uint8 i8253t2(t_bool io, uint8 data); +uint8 i8253c(t_bool io, uint8 data); + +/* i8253 Standard I/O Data Structures */ +/* up to 4 i8253 devices */ + +UNIT i8253_unit[] = { + { UDATA (&i8253_svc, 0, 0), 20 }, + { UDATA (&i8253_svc, 0, 0), 20 }, + { UDATA (&i8253_svc, 0, 0), 20 }, + { UDATA (&i8253_svc, 0, 0), 20 } +}; + +REG i8253_reg[] = { + { HRDATA (T0, i8253_unit[0].u3, 8) }, + { HRDATA (T1, i8253_unit[0].u4, 8) }, + { HRDATA (T2, i8253_unit[0].u5, 8) }, + { HRDATA (CMD, i8253_unit[0].u6, 8) }, + { HRDATA (T0, i8253_unit[1].u3, 8) }, + { HRDATA (T1, i8253_unit[1].u4, 8) }, + { HRDATA (T2, i8253_unit[1].u5, 8) }, + { HRDATA (CMD, i8253_unit[1].u6, 8) }, + { NULL } +}; + +DEBTAB i8253_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +MTAB i8253_mod[] = { + { 0 } +}; + +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + +DEVICE i8253_dev = { + "I8251", //name + i8253_unit, //units + i8253_reg, //registers + i8253_mod, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &i8253_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + i8253_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* i8253_svc - actually gets char & places in buffer */ + +t_stat i8253_svc (UNIT *uptr) +{ + sim_activate (&i8253_unit[0], i8253_unit[0].wait); /* continue poll */ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i8253_reset (DEVICE *dptr, uint16 baseport) +{ + if (i8253_devnum > I8253_NUM) { + sim_printf("i8253_reset: too many devices!\n"); + return SCPE_MEM; + } + sim_printf(" 8253-%d: Reset\n", i8253_devnum); + sim_printf(" 8253-%d: Registered at %04X\n", i8253_devnum, baseport); + i8253_port[i8253_devnum] = baseport; + reg_dev(i8253t0, baseport, i8253_devnum); + reg_dev(i8253t1, baseport + 1, i8253_devnum); + reg_dev(i8253t2, baseport + 2, i8253_devnum); + reg_dev(i8253c, baseport + 3, i8253_devnum); + i8253_unit[i8253_devnum].u3 = 0; /* status */ + i8253_unit[i8253_devnum].u4 = 0; /* mode instruction */ + i8253_unit[i8253_devnum].u5 = 0; /* command instruction */ + i8253_unit[i8253_devnum].u6 = 0; +// sim_activate (&i8253_unit[i8253_devnum], i8253_unit[i8253_devnum].wait); /* activate unit */ + i8253_devnum++; + return SCPE_OK; +} + +uint8 i8253_get_dn(void) +{ + int i; + + for (i=0; i= i8253_port[i] && port <= i8253_port[i] + 3) + return i; + sim_printf("i8253_get_dn: port %04X not in 8253 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +uint8 i8253t0(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return i8253_unit[devnum].u3; + } else { /* write data port */ + sim_printf(" 8253-%d: Timer 0=%02X\n", devnum, data); + i8253_unit[devnum].u3 = data; + return 0; + } + } + return 0; +} + +uint8 i8253t1(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return i8253_unit[devnum].u4; + } else { /* write data port */ + sim_printf(" 8253-%d: Timer 1=%02X\n", devnum, data); + i8253_unit[devnum].u4 = data; + return 0; + } + } + return 0; +} + +uint8 i8253t2(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return i8253_unit[devnum].u5; + } else { /* write data port */ + sim_printf(" 8253-%d: Timer 2=%02X\n", devnum, data); + i8253_unit[devnum].u5 = data; + return 0; + } + } + return 0; +} + +uint8 i8253c(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read status port */ + return i8253_unit[devnum].u6; + } else { /* write data port */ + i8253_unit[devnum].u6 = data; + sim_printf(" 8253-%d: Mode Instruction=%02X\n", devnum, data); + return 0; + } + } + return 0; +} + +/* end of i8253.c */ diff --git a/Intel-Systems/common/i8255.c b/Intel-Systems/common/i8255.c index 9ee57c0c..6b85d0b9 100644 --- a/Intel-Systems/common/i8255.c +++ b/Intel-Systems/common/i8255.c @@ -26,7 +26,7 @@ MODIFICATIONS: ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set baseport and size. 24 Apr 15 -- Modified to use simh_debug NOTES: @@ -77,20 +77,34 @@ #include "system_defs.h" /* system header in system dir */ +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + /* function prototypes */ -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); +t_stat i8255_reset (DEVICE *dptr, uint16 baseport); +uint8 i8255_get_dn(void); +uint8 i8255s(t_bool io, uint8 data); +uint8 i8255a(t_bool io, uint8 data); +uint8 i8255b(t_bool io, uint8 data); +uint8 i8255c(t_bool io, uint8 data); /* external function prototypes */ -extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); /* globals */ +int32 i8255_devnum = 0; //actual number of 8255 instances + 1 +uint16 i8255_port[4]; //baseport port registered to each instance + +/* these bytes represent the input and output to/from a port instance */ + +uint8 i8255_A[4]; //port A byte I/O +uint8 i8255_B[4]; //port B byte I/O +uint8 i8255_C[4]; //port C byte I/O + /* i8255 Standard I/O Data Structures */ /* up to 4 i8255 devices */ @@ -102,22 +116,22 @@ UNIT i8255_unit[] = { }; REG i8255_reg[] = { - { HRDATA (CONTROL0, i8255_unit[0].u3, 8) }, /* i8255 0 */ - { HRDATA (PORTA0, i8255_unit[0].u4, 8) }, - { HRDATA (PORTB0, i8255_unit[0].u5, 8) }, - { HRDATA (PORTC0, i8255_unit[0].u6, 8) }, - { HRDATA (CONTROL1, i8255_unit[1].u3, 8) }, /* i8255 1 */ - { HRDATA (PORTA1, i8255_unit[1].u4, 8) }, - { HRDATA (PORTB1, i8255_unit[1].u5, 8) }, - { HRDATA (PORTC1, i8255_unit[1].u6, 8) }, - { HRDATA (CONTROL1, i8255_unit[2].u3, 8) }, /* i8255 2 */ - { HRDATA (PORTA1, i8255_unit[2].u4, 8) }, - { HRDATA (PORTB1, i8255_unit[2].u5, 8) }, - { HRDATA (PORTC1, i8255_unit[2].u6, 8) }, - { HRDATA (CONTROL1, i8255_unit[3].u3, 8) }, /* i8255 3 */ - { HRDATA (PORTA1, i8255_unit[3].u4, 8) }, - { HRDATA (PORTB1, i8255_unit[3].u5, 8) }, - { HRDATA (PORTC1, i8255_unit[3].u6, 8) }, + { HRDATA (CS0, i8255_unit[0].u3, 8) }, /* i8255 0 */ + { HRDATA (A0, i8255_A[0], 8) }, + { HRDATA (B0, i8255_B[0], 8) }, + { HRDATA (C0, i8255_C[0], 8) }, + { HRDATA (CS1, i8255_unit[1].u3, 8) }, /* i8255 1 */ + { HRDATA (A1, i8255_A[1], 8) }, + { HRDATA (B1, i8255_B[1], 8) }, + { HRDATA (C1, i8255_C[1], 8) }, + { HRDATA (CS2, i8255_unit[2].u3, 8) }, /* i8255 2 */ + { HRDATA (A2, i8255_A[2], 8) }, + { HRDATA (B2, i8255_B[2], 8) }, + { HRDATA (C2, i8255_C[2], 8) }, + { HRDATA (CS3, i8255_unit[3].u3, 8) }, /* i8255 3 */ + { HRDATA (A3, i8255_A[3], 8) }, + { HRDATA (B3, i8255_B[3], 8) }, + { HRDATA (C3, i8255_C[3], 8) }, { NULL } }; @@ -126,7 +140,6 @@ DEBTAB i8255_debug[] = { { "FLOW", DEBUG_flow }, { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, { "LEV1", DEBUG_level1 }, { "LEV2", DEBUG_level2 }, { NULL } @@ -135,7 +148,7 @@ DEBTAB i8255_debug[] = { /* address width is set to 16 bits to use devices in 8086/8088 implementations */ DEVICE i8255_dev = { - "8255", //name + "I8255", //name i8255_unit, //units i8255_reg, //registers NULL, //modifiers @@ -147,7 +160,7 @@ DEVICE i8255_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// &i8255_reset, //reset +// i8255_reset2(), //reset NULL, //reset NULL, //boot NULL, //attach @@ -160,104 +173,117 @@ DEVICE i8255_dev = { NULL //lname }; +/* Reset routine */ + +t_stat i8255_reset (DEVICE *dptr, uint16 baseport) +{ + if (i8255_devnum > I8255_NUM) { + sim_printf("i8255_reset: too many devices!\n"); + return SCPE_MEM; + } + sim_printf(" 8255-%d: Reset\n", i8255_devnum); + sim_printf(" 8255-%d: Registered at %04X\n", i8255_devnum, baseport); + i8255_port[i8255_devnum] = baseport; + reg_dev(i8255a, baseport, i8255_devnum); + reg_dev(i8255b, baseport + 1, i8255_devnum); + reg_dev(i8255c, baseport + 2, i8255_devnum); + reg_dev(i8255s, baseport + 3, i8255_devnum); + i8255_unit[i8255_devnum].u3 = 0x9B; /* control */ + i8255_A[i8255_devnum] = 0xFF; /* Port A */ + i8255_B[i8255_devnum] = 0xFF; /* Port B */ + i8255_C[i8255_devnum] = 0xFF; /* Port C */ + i8255_devnum++; + return SCPE_OK; +} + +uint8 i8255_get_dn(void) +{ + int i; + + for (i=0; i=i8255_port[i] && port <= i8255_port[i] + 3) + return i; + sim_printf("i8255_get_dn: port %04X not in 8255 device table\n", port); + return 0xFF; +} + /* I/O instruction handlers, called from the CPU module when an IN or OUT instruction is issued. */ /* i8255 functions */ -uint8 i8255s(t_bool io, uint8 data, uint8 devnum) +uint8 i8255s(t_bool io, uint8 data) { uint8 bit; + uint8 devnum; - if (devnum >= I8255_NUM) { - sim_printf("8255s: Illegal Device Number %d\n", devnum); - return 0; - } - if (io == 0) { /* read status port */ - return i8255_unit[devnum].u3; - } else { /* write status port */ - if (data & 0x80) { /* mode instruction */ - i8255_unit[0].u3 = 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[devnum].u6 |= (0x01 << bit); - } else { /* reset bit */ - i8255_unit[devnum].u6 &= ~(0x01 << bit); + if ((devnum = i8255_get_dn()) != 0xFF) { + if (io == 0) { /* read status port */ + return i8255_unit[devnum].u3; + } else { /* write status port */ + if (data & 0x80) { /* mode instruction */ + i8255_unit[devnum].u3 = 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_C[devnum] |= (0x01 << bit); + } else { /* reset bit */ + i8255_C[devnum] &= ~(0x01 << bit); + } } } } return 0; } -uint8 i8255a(t_bool io, uint8 data, uint8 devnum) +uint8 i8255a(t_bool io, uint8 data) { - if (devnum >= I8255_NUM) { - sim_printf("8255a: Illegal Device Number %d\n", devnum); - return 0; - } - if (io == 0) { /* read data port */ - return (i8255_unit[devnum].u4); - } else { /* write data port */ - i8255_unit[devnum].u4 = data; - sim_printf(" 8255-%d: Port A = %02X\n", devnum, data); + uint8 devnum; + + if ((devnum = i8255_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + //return (i8255_unit[devnum].u4); + return (i8255_A[devnum]); + } else { /* write data port */ + i8255_A[devnum] = data; + sim_printf(" 8255-%d: Port A = %02X\n", devnum, data); + } } return 0; } -uint8 i8255b(t_bool io, uint8 data, uint8 devnum) +uint8 i8255b(t_bool io, uint8 data) { - if (devnum >= I8255_NUM) { - sim_printf("8255b: Illegal Device Number %d\n", devnum); - return 0; - } - if (io == 0) { /* read data port */ - return (i8255_unit[devnum].u5); - } else { /* write data port */ - i8255_unit[devnum].u5 = data; - sim_printf(" 8255-%d: Port B = %02X\n", devnum, data); + uint8 devnum; + + if ((devnum = i8255_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return (i8255_B[devnum]); + } else { /* write data port */ + i8255_B[devnum] = data; + sim_printf(" 8255-%d: Port B = %02X\n", devnum, data); + } } return 0; } -uint8 i8255c(t_bool io, uint8 data, uint8 devnum) +uint8 i8255c(t_bool io, uint8 data) { - if (devnum >= I8255_NUM) { - sim_printf("8255c: Illegal Device Number %d\n", devnum); - return 0; - } - if (io == 0) { /* read data port */ - return (i8255_unit[devnum].u6); - } else { /* write data port */ - i8255_unit[devnum].u6 = data; - sim_printf(" 8255-%d: Port C = %02X\n", devnum, data); + uint8 devnum; + + if ((devnum = i8255_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return (i8255_C[devnum]); + } else { /* write data port */ + i8255_C[devnum] = data; + sim_printf(" 8255-%d: Port C = %02X\n", devnum, data); + } } return 0; } -/* Reset routine */ - -t_stat i8255_reset (DEVICE *dptr, uint16 base, uint8 devnum) -{ - if (devnum >= I8255_NUM) { - sim_printf("8255_reset: Illegal Device Number %d\n", devnum); - return 0; - } - 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; -} - /* end of i8255.c */ diff --git a/Intel-Systems/common/i8259.c b/Intel-Systems/common/i8259.c index 309d6418..e13223d4 100644 --- a/Intel-Systems/common/i8259.c +++ b/Intel-Systems/common/i8259.c @@ -37,17 +37,25 @@ /* function prototypes */ -uint8 i8259a(t_bool io, uint8 data, uint8 devnum); -uint8 i8259b(t_bool io, uint8 data, uint8 devnum); +uint8 i8259a(t_bool io, uint8 data); +uint8 i8259b(t_bool io, uint8 data); void i8259_dump(uint8 devnum); -t_stat i8259_reset (DEVICE *dptr, uint16 base, uint8 devnum); +t_stat i8259_reset (DEVICE *dptr, uint16 baseport); +uint8 i8259_get_dn(void); + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] /* external function prototypes */ -extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); /* globals */ +int32 i8259_devnum = 0; //actual number of 8259 instances + 1 +uint16 i8259_port[4]; //baseport port registered to each instance + uint8 i8259_base[I8259_NUM]; uint8 i8259_icw1[I8259_NUM]; uint8 i8259_icw2[I8259_NUM]; @@ -58,21 +66,29 @@ uint8 i8259_ocw2[I8259_NUM]; uint8 i8259_ocw3[I8259_NUM]; uint8 icw_num0 = 1, icw_num1 = 1; -/* i8255 Standard I/O Data Structures */ +/* i8259 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 */ + { UDATA (0, 0, 0) }, /* i8259 1 */ + { UDATA (0, 0, 0) }, /* i8259 2 */ + { UDATA (0, 0, 0) } /* i8259 3 */ }; 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 (IRR1, i8259_unit[1].u3, 8) }, /* i8259 1 */ { HRDATA (ISR1, i8259_unit[1].u4, 8) }, { HRDATA (IMR1, i8259_unit[1].u5, 8) }, + { HRDATA (IRR1, i8259_unit[2].u3, 8) }, /* i8259 2 */ + { HRDATA (ISR1, i8259_unit[2].u4, 8) }, + { HRDATA (IMR1, i8259_unit[2].u5, 8) }, + { HRDATA (IRR1, i8259_unit[3].u3, 8) }, /* i8259 3 */ + { HRDATA (ISR1, i8259_unit[3].u4, 8) }, + { HRDATA (IMR1, i8259_unit[3].u5, 8) }, { NULL } }; @@ -90,7 +106,7 @@ DEBTAB i8259_debug[] = { /* address width is set to 16 bits to use devices in 8086/8088 implementations */ DEVICE i8259_dev = { - "8259", //name + "I8259", //name i8259_unit, //units i8259_reg, //registers NULL, //modifiers @@ -119,117 +135,130 @@ DEVICE i8259_dev = { IN or OUT instruction is issued. */ -/* i8259 functions */ +/* Reset routine */ -uint8 i8259a(t_bool io, uint8 data, uint8 devnum) +t_stat i8259_reset (DEVICE *dptr, uint16 baseport) { - if (devnum >= I8259_NUM) { - sim_printf("8259a: Illegal Device Number %d\n", devnum); + if (i8259_devnum >= I8259_NUM) { + sim_printf("8259_reset: Illegal Device Number %d\n", i8259_devnum); return 0; } - if (io == 0) { /* read data port */ - 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[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[devnum] = data; - break; - case 8: /* OCW3 */ - i8259_ocw3[devnum] = data; - break; - default: - sim_printf("8259a-%d: OCW Error %02X\n", devnum, data); - break; + sim_printf(" 8259-%d: Reset\n", i8259_devnum); + sim_printf(" 8259-%d: Registered at %04X\n", i8259_devnum, baseport); + i8259_port[i8259_devnum] = baseport; + reg_dev(i8259a, baseport, i8259_devnum); + reg_dev(i8259b, baseport + 1, i8259_devnum); + i8259_unit[i8259_devnum].u3 = 0x00; /* IRR */ + i8259_unit[i8259_devnum].u4 = 0x00; /* ISR */ + i8259_unit[i8259_devnum].u5 = 0x00; /* IMR */ + i8259_devnum++; + return SCPE_OK; +} + +uint8 i8259_get_dn(void) +{ + int i; + + for (i=0; i= i8259_port[i] && port <= i8259_port[i] + 1) + return i; + sim_printf("i8259_get_dn: port %04X not in 8259 device table\n", port); + return 0xFF; +} + +/* i8259 functions */ + +uint8 i8259a(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8259_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + 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[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[devnum] = data; + break; + case 8: /* OCW3 */ + i8259_ocw3[devnum] = data; + break; + default: + sim_printf("8259a-%d: OCW Error %02X\n", devnum, data); + break; + } + } + sim_printf(" 8259-%d: A data = %02X\n", devnum, data); + icw_num0++; /* step ICW number */ } - sim_printf("8259a-%d: data = %02X\n", devnum, data); - icw_num0++; /* step ICW number */ +// i8259_dump(devnum); } - i8259_dump(devnum); return 0; } -uint8 i8259b(t_bool io, uint8 data, uint8 devnum) +uint8 i8259b(t_bool io, uint8 data) { - if (devnum >= I8259_NUM) { - sim_printf("8259b: Illegal Device Number %d\n", devnum); - return 0; - } - if (io == 0) { /* read data port */ - 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[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[devnum] = data; - break; - case 8: /* OCW3 */ - i8259_ocw3[devnum] = data; - break; - default: - sim_printf("8259b-%d: OCW Error %02X\n", devnum, data); - break; + uint8 devnum; + + if ((devnum = i8259_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + 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[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[devnum] = data; + break; + case 8: /* OCW3 */ + i8259_ocw3[devnum] = data; + break; + default: + sim_printf("8259b-%d: OCW Error %02X\n", devnum, data); + break; + } + } + sim_printf(" 8259-%d: B data = %02X\n", devnum, data); + icw_num1++; /* step ICW number */ } - sim_printf("8259b-%d: data = %02X\n", devnum, data); - icw_num1++; /* step ICW number */ +// i8259_dump(devnum); } - i8259_dump(devnum); return 0; } void i8259_dump(uint8 devnum) { - 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, uint16 base, uint8 devnum) -{ - if (devnum >= I8259_NUM) { - sim_printf("8259_reset: Illegal Device Number %d\n", devnum); - return 0; - } - 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; + sim_printf("Device %d", devnum); + sim_printf(" IRR=%02X", i8259_unit[devnum].u3); + sim_printf(" ISR=%02X", i8259_unit[devnum].u4); + sim_printf(" IMR=%02X", i8259_unit[devnum].u5); + sim_printf(" ICW1=%02X", i8259_icw1[devnum]); + sim_printf(" ICW2=%02X", i8259_icw2[devnum]); + sim_printf(" ICW3=%02X", i8259_icw3[devnum]); + sim_printf(" ICW4=%02X", i8259_icw4[devnum]); + sim_printf(" OCW1=%02X", i8259_ocw1[devnum]); + sim_printf(" OCW2=%02X", i8259_ocw2[devnum]); + sim_printf(" OCW3=%02X\n", i8259_ocw3[devnum]); } /* end of i8259.c */ diff --git a/Intel-Systems/common/i8272.c b/Intel-Systems/common/i8272.c new file mode 100644 index 00000000..512995d1 --- /dev/null +++ b/Intel-Systems/common/i8272.c @@ -0,0 +1,228 @@ +/* i8272.c: Intel 8272 FDC adapter + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + u6 - unit number/device number +*/ + +#include "system_defs.h" + +/* external globals */ + +extern uint16 port; + +#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ +#define UNIT_ANSI (1 << UNIT_V_ANSI) + +#define TXR 0x01 +#define RXR 0x02 +#define TXE 0x04 +#define SD 0x40 + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); + +/* function prototypes */ + +t_stat i8272_svc (UNIT *uptr); +t_stat i8272_reset (DEVICE *dptr, uint16 base); +void i8272_reset1(uint8 devnum); +uint8 i8272_get_dn(void); +uint8 i8251s(t_bool io, uint8 data); +uint8 i8251d(t_bool io, uint8 data); + +/* globals */ + +int32 i8272_devnum = 0; //initially, no 8251 instances +uint16 i8272_port[4]; //base port assigned to each 8251 instance + +/* i8251 Standard I/O Data Structures */ +/* up to 1 i8251 devices */ + +UNIT i8272_unit[4] = { + { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT } +}; + +REG i8272_reg[4] = { + { HRDATA (DATA, i8272_unit[0].buf, 8) }, + { HRDATA (STAT, i8272_unit[0].u3, 8) }, + { HRDATA (MODE, i8272_unit[0].u4, 8) }, + { HRDATA (CMD, i8272_unit[0].u5, 8) } +}; + +DEBTAB i8272_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +MTAB i8272_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 i8272_dev = { + "I8272", //name + i8272_unit, //units + i8272_reg, //registers + i8272_mod, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &i8272_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + i8272_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* i8272_svc - actually gets char & places in buffer */ + +t_stat i8272_svc(UNIT *uptr) +{ + int32 temp; + + sim_activate(&i8272_unit[uptr->u6], i8272_unit[uptr->u6].wait); /* continue poll */ + if (uptr->u6 >= i8272_devnum) return SCPE_OK; + if ((temp = sim_poll_kbd()) < SCPE_KFLAG) + return temp; /* no char or error? */ + //sim_printf("i8272_svc: received character temp=%04X devnum=%d\n", temp, uptr->u6); + i8272_unit[uptr->u6].buf = temp & 0xFF; /* Save char */ + i8272_unit[uptr->u6].u3 |= RXR; /* Set status */ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i8272_reset(DEVICE *dptr, uint16 base) +{ + if (i8272_devnum >= i8272_NUM) { + sim_printf("8251_reset: too many devices!\n"); + return 0; + } + i8272_reset1(i8272_devnum); + sim_printf(" 8251-%d: Registered at %03X\n", i8272_devnum, base); + i8272_port[i8272_devnum] = reg_dev(i8251d, base); + reg_dev(i8251s, base + 1); + i8272_unit[i8272_devnum].u6 = i8272_devnum; + sim_activate(&i8272_unit[i8272_devnum], i8272_unit[i8272_devnum].wait); /* activate unit */ + i8272_devnum++; + return SCPE_OK; +} + +void i8272_reset1(uint8 devnum) +{ + i8272_unit[devnum].u3 = TXR + TXE; /* status */ + i8272_unit[devnum].u4 = 0; /* mode instruction */ + i8272_unit[devnum].u5 = 0; /* command instruction */ + i8272_unit[devnum].buf = 0; + i8272_unit[devnum].pos = 0; + sim_printf(" 8251-%d: Reset\n", devnum); +} + +uint8 i8272_get_dn(void) +{ + int i; + + for (i=0; i=i8272_port[i] && port <= i8272_port[i] + 1) + return i; + sim_printf("i8272_get_dn: port %03X not in 8251 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +uint8 i8251s(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8272_get_dn()) != 0xFF) { + if (io == 0) { /* read status port */ + return i8272_unit[devnum].u3; + } else { /* write status port */ + if (i8272_unit[devnum].u6) { /* if mode, set cmd */ + i8272_unit[devnum].u5 = data; + sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); + if (data & SD) /* reset port! */ + i8272_reset1(devnum); + } else { /* set mode */ + i8272_unit[devnum].u4 = data; + sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); + i8272_unit[devnum].u6 = 1; /* set cmd received */ + } + } + } + return 0; +} + +uint8 i8251d(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8272_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + i8272_unit[devnum].u3 &= ~RXR; + return (i8272_unit[devnum].buf); + } else { /* write data port */ + sim_putchar(data); + } + } + return 0; +} + +/* end of i8251.c */ diff --git a/Intel-Systems/common/i8273.c b/Intel-Systems/common/i8273.c index aa91fcf4..421e0ebd 100644 --- a/Intel-Systems/common/i8273.c +++ b/Intel-Systems/common/i8273.c @@ -159,7 +159,7 @@ DEBTAB i8273_debug[] = { }; DEVICE i8273_dev = { - "8273", //name + "I8273", //name &i8273_unit, //units i8273_reg, //registers i8273_mod, //modifiers diff --git a/Intel-Systems/common/i8274.c b/Intel-Systems/common/i8274.c index 357352f3..930a165c 100644 --- a/Intel-Systems/common/i8274.c +++ b/Intel-Systems/common/i8274.c @@ -189,7 +189,7 @@ DEBTAB i8274_debug[] = { }; DEVICE i8274_dev = { - "8274", //name + "I8274", //name &i8274_unit, //units i8274_reg, //registers i8274_mod, //modifiers diff --git a/Intel-Systems/common/ieprom.c b/Intel-Systems/common/ieprom.c index da8e190e..e15b9e50 100644 --- a/Intel-Systems/common/ieprom.c +++ b/Intel-Systems/common/ieprom.c @@ -40,8 +40,6 @@ #include "system_defs.h" -#define SET_XACK(VAL) (xack = VAL) - /* function prototypes */ t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); @@ -50,8 +48,8 @@ uint8 EPROM_get_mbyte(uint16 addr); /* external function prototypes */ -extern UNIT i8255_unit[]; -extern uint8 xack; /* XACK signal */ +extern uint8 i8255_C[4]; //port c byte I/O +extern uint8 xack; /* XACK signal */ /* SIMH EPROM Standard I/O Data Structures */ @@ -90,7 +88,8 @@ DEVICE EPROM_dev = { NULL, //detach NULL, //ctxt DEV_DEBUG, //flags - 0, //dctrl + DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl +// 0, //dctrl EPROM_debug, //debflags NULL, //msize NULL //lname @@ -142,7 +141,8 @@ t_stat EPROM_attach (UNIT *uptr, CONST char *cptr) } sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n"); fclose(fp); - sim_printf("EPROM: %d bytes of ROM image %s loaded\n", j, EPROM_unit.filename); + sim_printf(" EPROM: Configured %d bytes, Attached to %s\n", + EPROM_unit.capac, EPROM_unit.filename); sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n"); return SCPE_OK; } @@ -151,16 +151,14 @@ t_stat EPROM_attach (UNIT *uptr, CONST char *cptr) t_stat EPROM_reset (DEVICE *dptr, uint16 size) { -// sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=0000 size=%04X\n", size); + sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=0000 size=%04X\n", size); if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */ EPROM_unit.capac = size; /* set EPROM size to 0 */ + sim_printf(" EPROM: Configured, Not attached\n"); sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n"); -// sim_printf(" EPROM: Available [%04X-%04XH]\n", -// 0, EPROM_unit.capac - 1); - return SCPE_OK; - } - if ((EPROM_unit.flags & UNIT_ATT) == 0) { - sim_printf("EPROM: No file attached\n"); + } else { + sim_printf(" EPROM: Configured %d bytes, Attached to %s\n", + EPROM_unit.capac, EPROM_unit.filename); } sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n"); return SCPE_OK; @@ -172,20 +170,17 @@ uint8 EPROM_get_mbyte(uint16 addr) { uint8 val; - 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 */ - sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)EPROM_unit.filebuf + addr); - sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val); - return (val & 0xFF); - } + sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr); + if (addr < EPROM_unit.capac) { + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr); + val = *((uint8 *)EPROM_unit.filebuf + addr); + sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val); + return (val & 0xFF); + } else { sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n"); - return 0xFF; + return 0; } - sim_debug (DEBUG_read, &EPROM_dev, " EPROM Disabled\n"); - return 0xFF; } /* end of iEPROM.c */ diff --git a/Intel-Systems/common/ioc-cont.c b/Intel-Systems/common/ioc-cont.c index 5915d76d..81c8bb2b 100644 --- a/Intel-Systems/common/ioc-cont.c +++ b/Intel-Systems/common/ioc-cont.c @@ -36,12 +36,12 @@ /* function prototypes */ -uint8 ioc_cont(t_bool io, uint8 data, uint8 devnum); /* ioc_cont*/ -t_stat ioc_cont_reset (DEVICE *dptr, uint16 base, uint8 devnum); +uint8 ioc_cont(t_bool io, uint8 data); /* ioc_cont*/ +t_stat ioc_cont_reset (DEVICE *dptr, uint16 baseport); /* external function prototypes */ -extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); extern uint32 saved_PC; /* program counter */ /* globals */ @@ -98,28 +98,28 @@ DEVICE ioc_cont_dev = { IN or OUT instruction is issued. */ -/* IOC control port functions */ - -uint8 ioc_cont(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read status port */ - sim_printf(" ioc_cont: read data=%02X port=%02X returned 0x00 from PC=%04X\n", data, devnum, saved_PC); - return 0x00; - } else { /* write control port */ - sim_printf(" ioc_cont: data=%02X port=%02X\n", data, devnum); - } -} - /* Reset routine */ -t_stat ioc_cont_reset(DEVICE *dptr, uint16 base, uint8 devnum) +t_stat ioc_cont_reset(DEVICE *dptr, uint16 baseport) { - reg_dev(ioc_cont, base, devnum); - reg_dev(ioc_cont, base + 1, devnum); - ioc_cont_unit[devnum].u3 = 0x00; /* ipc reset */ - sim_printf(" ioc_cont[%d]: Reset\n", devnum); - sim_printf(" ioc_cont[%d]: Registered at %04X\n", devnum, base); + sim_printf(" ioc_cont[%d]: Reset\n", 0); + sim_printf(" ioc_cont[%d]: Registered at %04X\n", 0, baseport); + reg_dev(ioc_cont, baseport, 0); + reg_dev(ioc_cont, baseport + 1, 0); + ioc_cont_unit[0].u3 = 0x00; /* ipc reset */ return SCPE_OK; } +/* IOC control port functions */ + +uint8 ioc_cont(t_bool io, uint8 data) +{ + if (io == 0) { /* read status port */ + sim_printf(" ioc_cont: read data=%02X port=%02X returned 0x00 from PC=%04X\n", data, 0, saved_PC); + return 0x00; + } else { /* write control port */ + sim_printf(" ioc_cont: data=%02X port=%02X\n", data, 0); + } +} + /* end of ioc-cont.c */ diff --git a/Intel-Systems/common/ipc-cont.c b/Intel-Systems/common/ipc-cont.c index 0e3391b4..1601b350 100644 --- a/Intel-Systems/common/ipc-cont.c +++ b/Intel-Systems/common/ipc-cont.c @@ -29,19 +29,18 @@ NOTES: - */ #include "system_defs.h" /* system header in system dir */ /* function prototypes */ -uint8 ipc_cont(t_bool io, uint8 data, uint8 devnum); /* ipc_cont*/ -t_stat ipc_cont_reset (DEVICE *dptr, uint16 base, uint8 devnum); +uint8 ipc_cont(t_bool io, uint8 data); /* ipc_cont*/ +t_stat ipc_cont_reset (DEVICE *dptr, uint16 baseport); /* external function prototypes */ -extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); /* globals */ @@ -93,68 +92,69 @@ DEVICE ipc_cont_dev = { NULL //lname }; +/* Reset routine */ + +t_stat ipc_cont_reset(DEVICE *dptr, uint16 baseport) +{ + sim_printf(" ipc_cont[%d]: Reset\n", 0); + sim_printf(" ipc_cont[%d]: Registered at %04X\n", 0, baseport); + reg_dev(ipc_cont, baseport, 0); + ipc_cont_unit[0].u3 = 0x00; /* ipc reset */ + return SCPE_OK; +} + /* I/O instruction handlers, called from the CPU module when an IN or OUT instruction is issued. */ /* IPC control port functions */ -uint8 ipc_cont(t_bool io, uint8 data, uint8 devnum) +uint8 ipc_cont(t_bool io, uint8 data) { if (io == 0) { /* read status port */ - sim_printf(" ipc_cont: read data=%02X port=%02X returned 0xFF\n", ipc_cont_unit[devnum].u3, devnum); - return ipc_cont_unit[devnum].u3; + sim_printf(" ipc_cont: read data=%02X ipc_cont_unit[%d].u3=%02X\n", + ipc_cont_unit[0].u3, 0, ipc_cont_unit[0].u3); + return ipc_cont_unit[0].u3; } else { /* write control port */ - //this simulates an 74ls259 register - //d0-d2 address the reg(in reverse order!), d3 is the data to be latched + //this simulates an 74LS259 register + //d0-d2 address the reg(in reverse order!), d3 is the data to be latched (inverted) switch(data & 0x07) { - case 5: //interrupt enable - if(data & 0x08) //bit high - ipc_cont_unit[0].u3 |= 0x10; - else //bit low + case 5: //interrupt enable 8085 INTR + if(data & 0x08) //bit low + ipc_cont_unit[0].u3 &= 0xBF; + else //bit high + ipc_cont_unit[0].u3 |= 0x20; + break; + case 4: //*selboot ROM @ 0E800h + if(data & 0x08) //bit low ipc_cont_unit[0].u3 &= 0xEF; + else //bit high + ipc_cont_unit[0].u3 |= 0x10; break; - case 4: //*selboot - if(data & 0x08) //bit high - ipc_cont_unit[0].u3 |= 0x08; - else //bit low - ipc_cont_unit[0].u3 &= 0xF7; - break; - case 2: //*startup - if(data & 0x08) //bit high - ipc_cont_unit[0].u3 |= 0x04; - else //bit low + case 2: //*startup ROM @ 00000h + if(data & 0x08) //bit low ipc_cont_unit[0].u3 &= 0xFB; + else //bit high + ipc_cont_unit[0].u3 |= 0x04; break; - case 1: //over ride - if(data & 0x08) //bit high - ipc_cont_unit[0].u3 |= 0x02; - else //bit low + case 1: //override inhibit other multibus users + if(data & 0x08) //bit low ipc_cont_unit[0].u3 &= 0xFD; + else //bit high + ipc_cont_unit[0].u3 |= 0x02; break; case 0: //aux prom enable - if(data & 0x08) //bit high - ipc_cont_unit[0].u3 |= 0x01; - else //bit low + if(data & 0x08) //bit low ipc_cont_unit[0].u3 &= 0xFE; + else //bit high + ipc_cont_unit[0].u3 |= 0x01; break; default: break; } - sim_printf(" ipc_cont: data=%02X ipc_cont[%d]=%02X\n", data, devnum, ipc_cont_unit[0].u3); + sim_printf(" ipc_cont: write data=%02X ipc_cont_unit[%d].u3=%02X\n", data, 0, ipc_cont_unit[0].u3); } return 0; } -/* Reset routine */ - -t_stat ipc_cont_reset(DEVICE *dptr, uint16 base, uint8 devnum) -{ - reg_dev(ipc_cont, base, devnum); - ipc_cont_unit[devnum].u3 = 0x00; /* ipc reset */ - sim_printf(" ipc_cont[%d]: Reset\n", devnum); - sim_printf(" ipc_cont[%d]: Registered at %04X\n", devnum, base); - return SCPE_OK; -} - /* end of ipc-cont.c */ diff --git a/Intel-Systems/common/ipceprom.c b/Intel-Systems/common/ipceprom.c index ef87c08d..f997a249 100644 --- a/Intel-Systems/common/ipceprom.c +++ b/Intel-Systems/common/ipceprom.c @@ -1,4 +1,4 @@ -/* iEPROM.c: Intel EPROM simulator for 8-bit SBCs +/* ipcEPROM.c: Intel EPROM simulator for 8-bit SBCs Copyright (c) 2010, William A. Beech @@ -40,8 +40,6 @@ #include "system_defs.h" -#define SET_XACK(VAL) (xack = VAL) - /* function prototypes */ t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); @@ -51,6 +49,7 @@ uint8 EPROM_get_mbyte(uint16 addr); /* external function prototypes */ extern uint8 xack; /* XACK signal */ +extern UNIT ipc_cont_unit[]; /* SIMH EPROM Standard I/O Data Structures */ @@ -184,4 +183,4 @@ uint8 EPROM_get_mbyte(uint16 addr) return 0xFF; } -/* end of iEPROM.c */ +/* end of ipcEPROM.c */ diff --git a/Intel-Systems/common/ipcmultibus.c b/Intel-Systems/common/ipcmultibus.c index 5e8a7c8e..fe69a754 100644 --- a/Intel-Systems/common/ipcmultibus.c +++ b/Intel-Systems/common/ipcmultibus.c @@ -48,23 +48,32 @@ t_stat multibus_svc(UNIT *uptr); t_stat multibus_reset(DEVICE *dptr); void set_irq(int32 int_num); void clr_irq(int32 int_num); -uint8 nulldev(t_bool io, uint8 data, uint8 devnum); -uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint16 port, uint8 devnum); +uint8 nulldev(t_bool io, uint8 data); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); t_stat multibus_reset (DEVICE *dptr); uint8 multibus_get_mbyte(uint16 addr); +uint16 multibus_get_mword(uint16 addr); void multibus_put_mbyte(uint16 addr, uint8 val); +void multibus_put_mword(uint16 addr, uint16 val); /* external function prototypes */ extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */ extern void set_cpuint(int32 int_num); extern UNIT zx200a_unit; -extern t_stat zx200a_reset(DEVICE *dptr, uint16 base, uint8 devnum); +extern t_stat zx200a_reset(DEVICE *dptr, uint16 base); +extern t_stat isbc201_reset (DEVICE *dptr, uint16); +extern t_stat isbc202_reset (DEVICE *dptr, uint16); +extern uint8 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16 addr, uint8 val); /* external globals */ extern uint8 xack; /* XACK signal */ extern int32 int_req; /* i8080 INT signal */ +extern int32 isbc201_fdcnum; +extern int32 isbc202_fdcnum; +extern int32 zx200a_fdcnum; /* multibus Standard SIMH Device Data Structures */ @@ -139,9 +148,14 @@ t_stat multibus_svc(UNIT *uptr) t_stat multibus_reset(DEVICE *dptr) { SBC_reset(NULL); - zx200a_reset(NULL, ZX200A_BASE_DD, 0); - zx200a_reset(NULL, ZX200A_BASE_SD, 0); sim_printf(" Multibus: Reset\n"); + zx200a_fdcnum = 0; + zx200a_reset(NULL, ZX200A_BASE_DD); + zx200a_reset(NULL, ZX200A_BASE_SD); + isbc201_fdcnum = 0; + isbc201_reset(NULL, SBC201_BASE); + isbc202_fdcnum = 0; + isbc202_reset(NULL, SBC202_BASE); sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ return SCPE_OK; } @@ -163,7 +177,7 @@ device addresses, if a device is plugged to a port it's routine address is here, 'nulldev' means no device has been registered. */ struct idev { - uint8 (*routine)(t_bool io, uint8 data, uint8 devnum); + uint8 (*routine)(t_bool io, uint8 data); uint8 devnum; }; @@ -234,7 +248,7 @@ struct idev dev_table[256] = { {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */ }; -uint8 nulldev(t_bool flag, uint8 data, uint8 devnum) +uint8 nulldev(t_bool flag, uint8 data) { SET_XACK(0); /* set no XACK */ if (flag == 0) /* if we got here, no valid I/O device */ @@ -242,17 +256,55 @@ uint8 nulldev(t_bool flag, uint8 data, uint8 devnum) return 0; } -uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint16 port, uint8 devnum) +uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), 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); + sim_printf("Multibus: I/O Port %04X is already assigned\n", port); } else { -// sim_printf("Port %02X is assigned\n", port); + sim_printf("Port %04X is assigned\n", port); dev_table[port].routine = routine; dev_table[port].devnum = devnum; } return 0; } +/* get a byte from memory */ + +uint8 multibus_get_mbyte(uint16 addr) +{ + SET_XACK(0); /* set no XACK */ +// sim_printf("multibus_get_mbyte: Cleared XACK for %04X\n", addr); + return RAM_get_mbyte(addr); +} + +/* get a word from memory */ + +uint16 multibus_get_mword(uint16 addr) +{ + uint16 val; + + val = multibus_get_mbyte(addr); + val |= (multibus_get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory */ + +void multibus_put_mbyte(uint16 addr, uint8 val) +{ + SET_XACK(0); /* set no XACK */ +// sim_printf("multibus_put_mbyte: Cleared XACK for %04X\n", addr); + RAM_put_mbyte(addr, val); +// sim_printf("multibus_put_mbyte: Done XACK=%dX\n", XACK); +} + +/* put a word to memory */ + +void multibus_put_mword(uint16 addr, uint16 val) +{ + multibus_put_mbyte(addr, val & 0xff); + multibus_put_mbyte(addr+1, val >> 8); +} + /* end of ipcmultibus.c */ diff --git a/Intel-Systems/common/ipcram8.c b/Intel-Systems/common/ipcram8.c index f0202d37..57c55fa8 100644 --- a/Intel-Systems/common/ipcram8.c +++ b/Intel-Systems/common/ipcram8.c @@ -1,4 +1,4 @@ -/* iRAM8.c: Intel RAM simulator for 8-bit SBCs +/* ipcRAM8.c: Intel RAM simulator for 8-bit SBCs Copyright (c) 2011, William A. Beech @@ -38,8 +38,6 @@ #include "system_defs.h" -#define SET_XACK(VAL) (xack = VAL) - /* function prototypes */ t_stat RAM_svc (UNIT *uptr); @@ -49,7 +47,6 @@ void RAM_put_mbyte(uint16 addr, uint8 val); /* external function prototypes */ -extern UNIT i8255_unit[]; extern uint8 xack; /* XACK signal */ /* SIMH RAM Standard I/O Data Structures */ @@ -126,39 +123,23 @@ uint8 RAM_get_mbyte(uint16 addr) { uint8 val; - 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 */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); - sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); - return (val & 0xFF); - } - sim_debug (DEBUG_read, &RAM_dev, " Out of range\n"); - return 0xFF; - } - sim_debug (DEBUG_read, &RAM_dev, " RAM disabled\n"); - return 0xFF; + sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr); + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr); + val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); + sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); + return (val & 0xFF); } /* put a byte to memory */ void RAM_put_mbyte(uint16 addr, uint8 val) { - 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 */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr); - *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; - sim_debug (DEBUG_write, &RAM_dev, "\n"); - return; - } - sim_debug (DEBUG_write, &RAM_dev, " Out of range\n"); - return; - } - sim_debug (DEBUG_write, &RAM_dev, " RAM disabled\n"); + sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val); + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr); + *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; + sim_debug (DEBUG_write, &RAM_dev, "\n"); } -/* end of iRAM8.c */ +/* end of ipcRAM8.c */ diff --git a/Intel-Systems/common/iram8.c b/Intel-Systems/common/iram8.c index f0202d37..130b8f6c 100644 --- a/Intel-Systems/common/iram8.c +++ b/Intel-Systems/common/iram8.c @@ -38,19 +38,16 @@ #include "system_defs.h" -#define SET_XACK(VAL) (xack = VAL) - /* function prototypes */ -t_stat RAM_svc (UNIT *uptr); t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); uint8 RAM_get_mbyte(uint16 addr); void RAM_put_mbyte(uint16 addr, uint8 val); /* external function prototypes */ -extern UNIT i8255_unit[]; -extern uint8 xack; /* XACK signal */ +extern uint8 i8255_B[4]; //port B byte I/O +extern uint8 xack; /* XACK signal */ /* SIMH RAM Standard I/O Data Structures */ @@ -93,8 +90,6 @@ DEVICE RAM_dev = { NULL //lname }; -/* global variables */ - /* RAM functions */ /* RAM reset */ @@ -113,9 +108,9 @@ t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size) return SCPE_MEM; } } -// sim_printf(" RAM: Available [%04X-%04XH]\n", -// RAM_unit.u3, -// RAM_unit.u3 + RAM_unit.capac - 1); + sim_printf(" RAM: Available [%04X-%04XH]\n", + RAM_unit.u3, + RAM_unit.u3 + RAM_unit.capac - 1); sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n"); return SCPE_OK; } @@ -126,39 +121,34 @@ uint8 RAM_get_mbyte(uint16 addr) { uint8 val; - 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 */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); - sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); - return (val & 0xFF); - } + sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr); + if ((addr >= RAM_unit.u3) && ((uint32) addr < (RAM_unit.u3 + RAM_unit.capac))) { + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr); + val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); + sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); + return (val & 0xFF); + } else { sim_debug (DEBUG_read, &RAM_dev, " Out of range\n"); return 0xFF; } - sim_debug (DEBUG_read, &RAM_dev, " RAM disabled\n"); - return 0xFF; } /* put a byte to memory */ void RAM_put_mbyte(uint16 addr, uint8 val) { - 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 */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr); - *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; - sim_debug (DEBUG_write, &RAM_dev, "\n"); - return; - } + sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val); + if ((addr >= RAM_unit.u3) && ((uint32)addr < RAM_unit.u3 + RAM_unit.capac)) { + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr); + *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; + sim_debug (DEBUG_write, &RAM_dev, "\n"); + return; + } else { sim_debug (DEBUG_write, &RAM_dev, " Out of range\n"); return; } - sim_debug (DEBUG_write, &RAM_dev, " RAM disabled\n"); } /* end of iRAM8.c */ diff --git a/Intel-Systems/common/isbc064.c b/Intel-Systems/common/isbc064.c index c9b43ad0..77959f5d 100644 --- a/Intel-Systems/common/isbc064.c +++ b/Intel-Systems/common/isbc064.c @@ -77,7 +77,8 @@ DEVICE isbc064_dev = { 8, //dwidth NULL, //examine NULL, //deposite - &isbc064_reset, //reset +// &isbc064_reset, //reset + NULL, //reset NULL, //boot NULL, //attach NULL, //detach @@ -99,7 +100,8 @@ t_stat isbc064_reset (DEVICE *dptr) if ((isbc064_dev.flags & DEV_DIS) == 0) { isbc064_unit.capac = SBC064_SIZE; isbc064_unit.u3 = SBC064_BASE; - sim_printf("iSBC 064: Available[%04X-%04XH]\n", + sim_printf("Initializing iSBC-064 RAM Board\n"); + sim_printf(" Available[%04X-%04XH]\n", isbc064_unit.u3, isbc064_unit.u3 + isbc064_unit.capac - 1); } @@ -119,7 +121,6 @@ t_stat isbc064_reset (DEVICE *dptr) uint8 isbc064_get_mbyte(uint16 addr) { uint32 val, org, len; - int i = 0; if ((isbc064_dev.flags & DEV_DIS) == 0) { org = isbc064_unit.u3; @@ -131,14 +132,16 @@ uint8 isbc064_get_mbyte(uint16 addr) sim_debug (DEBUG_xack, &isbc064_dev, "isbc064_get_mbyte: Set XACK for %04X\n", addr); val = *((uint8 *)isbc064_unit.filebuf + (addr - org)); sim_debug (DEBUG_read, &isbc064_dev, " val=%04X\n", val); +// sim_printf ("isbc064_get_mbyte: addr=%04X, val=%02X\n", addr, val); return (val & 0xFF); } else { - sim_debug (DEBUG_read, &isbc064_dev, " Out of range\n"); - return 0xFF; /* multibus has active high pullups */ + sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Out of range\n"); + return 0; /* multibus has active high pullups and inversion */ } } - sim_debug (DEBUG_read, &isbc064_dev, " Disabled\n"); - return 0xFF; /* multibus has active high pullups */ + sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Disabled\n"); +// sim_printf ("isbc064_get_mbyte: Disabled\n"); + return 0; /* multibus has active high pullups and inversion */ } /* put a byte into memory */ @@ -146,11 +149,11 @@ uint8 isbc064_get_mbyte(uint16 addr) void isbc064_put_mbyte(uint16 addr, uint8 val) { uint32 org, len; - int i = 0; if ((isbc064_dev.flags & DEV_DIS) == 0) { org = isbc064_unit.u3; len = isbc064_unit.capac; +// sim_printf ("isbc064_put_mbyte: addr=%04X, val=%02X\n", addr, val); sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: addr=%04X, val=%02X\n", addr, val); sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: org=%04X, len=%04X\n", org, len); if ((addr >= org) && (addr < (org + len))) { @@ -160,11 +163,12 @@ void isbc064_put_mbyte(uint16 addr, uint8 val) sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Return\n"); return; } else { - sim_debug (DEBUG_write, &isbc064_dev, " Out of range\n"); + sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Out of range\n"); return; } } sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Disabled\n"); +// sim_printf ("isbc064_put_mbyte: Disabled\n"); } /* end of isbc064.c */ diff --git a/Intel-Systems/common/isbc201.c b/Intel-Systems/common/isbc201.c new file mode 100644 index 00000000..812c740d --- /dev/null +++ b/Intel-Systems/common/isbc201.c @@ -0,0 +1,681 @@ +/* isbc201.c: Intel single density disk adapter adapter + + Copyright (c) 2010, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + 31 Oct 16 - Original file. + + NOTES: + + This controller will mount 2 SD disk images on drives :F0: and :F1: addressed + at ports 088H to 08FH. + + Registers: + + 078H - Read - Subsystem status + bit 0 - ready status of drive 0 + bit 1 - ready status of drive 1 + bit 2 - state of channel's interrupt FF + bit 3 - controller presence indicator + bit 4 - zero + bit 5 - zero + bit 6 - zero + bit 7 - zero + + 079H - Read - Read result type (bits 2-7 are zero) + 00 - I/O complete with error(unlinked) + 01 - I/O complete with error(linked)(hi 6-bits are block num) + 10 - Result byte contains diskette ready status + 11 - Reserved + 079H - Write - IOPB address low byte. + + 07AH - Write - IOPB address high byte and start operation. + + 07BH - Read - Read result byte + If result type is 00H + bit 0 - deleted record + bit 1 - CRC error + bit 2 - seek error + bit 3 - address error + bit 4 - data overrun/underrun + bit 5 - write protect + bit 6 - write error + bit 7 - not ready + If result type is 10H + bit 0 - zero + bit 1 - zero + bit 2 - zero + bit 3 - zero + bit 4 - zero + bit 5 - zero + bit 6 - drive 0 ready + bit 7 - drive 1 ready + + 07FH - Write - Reset diskette system. + + Operations: + Recalibrate - + Seek - + Format Track - + Write Data - + Write Deleted Data - + Read Data - + Verify CRC - + + IOPB - I/O Parameter Block + Byte 0 - Channel Word + bit 0 - wait + bit 1 - branch on wait + bit 2 - successor bit + bit 3 - data word length (=8-bit, 1=16-bit) + bit 4-5 - interrupt control + 00 - I/O complete interrupt to be issued + 01 - I/O complete interrupts are disabled + 10 - illegal code + 11 - illegal code + bit 6 - randon format sequence + bit 7 - lock override + + Byte 1 - Diskette Instruction + bit 0-2 - operation code + 000 - no operation + 001 - seek + 010 - format track + 011 - recalibrate + 100 - read data + 101 - verify CRC + 110 - write data + 111 - write deleted data + bit 3 - data word length ( same as byte-0, bit-3) + bit 4-5 - unit select + 00 - drive 0 + 01 - drive 1 + 10 - drive 2 + 11 - drive 3 + bit 6-7 - reserved (zero) + + Byte 2 - Number of Records + + Byte 3 - Track Address + + Byte 4 - Sector Address + + Byte 5 - Buffer Low Address + + Byte 6 - Buffer High Address + + Byte 8 - Block Number + + Byte 9 - Next IOPB Lower Address + + Byte 10 - Next IOPB Upper Address + + u3 - + u4 - + u5 - fdc number + u6 - fdd number. + +*/ + +#include "system_defs.h" /* system header in system dir */ + +#define DEBUG 0 + +#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ +#define UNIT_WPMODE (1 << UNIT_V_WPMODE) + +#define FDD_NUM 2 + +//disk controoler operations +#define DNOP 0x00 //disk no operation +#define DSEEK 0x01 //disk seek +#define DFMT 0x02 //disk format +#define DHOME 0x03 //disk home +#define DREAD 0x04 //disk read +#define DVCRC 0x05 //disk verify CRC +#define DWRITE 0x06 //disk write + +//status +#define RDY0 0x01 //FDD 0 ready +#define RDY1 0x02 //FDD 1 ready +#define FDCINT 0x04 //FDC interrupt flag +#define FDCPRE 0x08 //FDC board present + +//result type +#define RERR 0x00 //FDC returned error +#define ROK 0x02 //FDC returned ok + +// If result type is RERR then rbyte is +#define RB0DR 0x01 //deleted record +#define RB0CRC 0x02 //CRC error +#define RB0SEK 0x04 //seek error +#define RB0ADR 0x08 //address error +#define RB0OU 0x10 //data overrun/underrun +#define RB0WP 0x20 //write protect +#define RB0WE 0x40 //write error +#define RB0NR 0x80 //not ready + +// If result type is ROK then rbyte is +#define RB1RD0 0x40 //drive 0 ready +#define RB1RD1 0x80 //drive 1 ready + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 multibus_get_mbyte(uint16 addr); +extern uint16 multibus_get_mword(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern uint8 multibus_put_mword(uint16 addr, uint16 val); + +/* function prototypes */ + +t_stat isbc201_reset(DEVICE *dptr, uint16 base); +void isbc201_reset1(uint8 fdcnum); +t_stat isbc201_attach (UNIT *uptr, CONST char *cptr); +t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +uint8 isbc201_get_dn(void); +uint8 isbc2010(t_bool io, uint8 data); /* isbc201 0 */ +uint8 isbc2011(t_bool io, uint8 data); /* isbc201 1 */ +uint8 isbc2012(t_bool io, uint8 data); /* isbc201 2 */ +uint8 isbc2013(t_bool io, uint8 data); /* isbc201 3 */ +uint8 isbc2017(t_bool io, uint8 data); /* isbc201 7 */ +void isbc201_diskio(uint8 fdcnum); //do actual disk i/o + +/* globals */ + +int32 isbc201_fdcnum = 0; //actual number of SBC-201 instances + 1 + +typedef struct { //FDD definition + uint8 *buf; + int t0; + int rdy; + uint8 maxsec; + uint8 maxcyl; + } FDDDEF; + +typedef struct { //FDC definition + uint16 baseport; //FDC base port + uint16 iopb; //FDC IOPB + uint8 stat; //FDC status + uint8 rtype; //FDC result type + uint8 rbyte0; //FDC result byte for type 00 + uint8 rbyte1; //FDC result byte for type 10 + uint8 intff; //fdc interrupt FF + FDDDEF fdd[FDD_NUM]; //indexed by the FDD number + } FDCDEF; + +FDCDEF fdc201[4]; //indexed by the isbc-201 instance number + +UNIT isbc201_unit[] = { + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 } +}; + +REG isbc201_reg[] = { + { HRDATA (STATUS0, isbc201_unit[0].u3, 8) }, /* isbc201 0 status */ + { HRDATA (RTYP0, isbc201_unit[0].u4, 8) }, /* isbc201 0 result type */ + { HRDATA (RBYT0, isbc201_unit[0].u5, 8) }, /* isbc201 0 result byte */ + { HRDATA (STATUS1, isbc201_unit[1].u3, 8) }, /* isbc201 1 status */ + { HRDATA (RTYP1, isbc201_unit[1].u4, 8) }, /* isbc201 0 result type */ + { HRDATA (RBYT1, isbc201_unit[1].u5, 8) }, /* isbc201 0 result byte */ + { HRDATA (STATUS2, isbc201_unit[2].u3, 8) }, /* isbc201 2 status */ + { HRDATA (RTYP2, isbc201_unit[0].u4, 8) }, /* isbc201 0 result type */ + { HRDATA (R$BYT2, isbc201_unit[2].u5, 8) }, /* isbc201 0 result byte */ + { HRDATA (STATUS3, isbc201_unit[3].u3, 8) }, /* isbc201 3 status */ + { HRDATA (RTYP3, isbc201_unit[3].u4, 8) }, /* isbc201 0 result type */ + { HRDATA (RBYT3, isbc201_unit[3].u5, 8) }, /* isbc201 0 result byte */ + { NULL } +}; + +MTAB isbc201_mod[] = { + { UNIT_WPMODE, 0, "RW", "RW", &isbc201_set_mode }, + { UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc201_set_mode }, + { 0 } +}; + +DEBTAB isbc201_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 isbc201_dev = { + "SBC201", //name + isbc201_unit, //units + isbc201_reg, //registers + isbc201_mod, //modifiers + FDD_NUM, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + NULL, //reset + NULL, //boot + &isbc201_attach, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags + DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl + isbc201_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Hardware reset routine */ + +t_stat isbc201_reset(DEVICE *dptr, uint16 base) +{ + sim_printf("Initializing iSBC-201 FDC Board\n"); + if (SBC201_NUM) { + sim_printf(" isbc201-%d: Hardware Reset\n", isbc201_fdcnum); + sim_printf(" isbc201-%d: Registered at %04X\n", isbc201_fdcnum, base); + fdc201[isbc201_fdcnum].baseport = base; + reg_dev(isbc2010, base, isbc201_fdcnum); //read status + reg_dev(isbc2011, base + 1, isbc201_fdcnum); //read rslt type/write IOPB addr-l + reg_dev(isbc2012, base + 2, isbc201_fdcnum); //write IOPB addr-h and start + reg_dev(isbc2013, base + 3, isbc201_fdcnum); //read rstl byte + reg_dev(isbc2017 , base + 7, isbc201_fdcnum); //write reset isbc202 + isbc201_reset1(isbc201_fdcnum); + isbc201_fdcnum++; + } else { + sim_printf(" No isbc201 installed\n"); + } + return SCPE_OK; +} + +/* Software reset routine */ + +void isbc201_reset1(uint8 fdcnum) +{ + int32 i; + UNIT *uptr; + + sim_printf(" isbc201-%d: Software Reset\n", fdcnum); + fdc201[fdcnum].stat = 0; //clear status + for (i = 0; i < FDD_NUM; i++) { /* handle all units */ + uptr = isbc201_dev.units + i; + fdc201[fdcnum].stat |= FDCPRE; //set the FDC status + fdc201[fdcnum].rtype = ROK; + if (uptr->capac == 0) { /* if not configured */ + uptr->capac = 0; /* initialize unit */ + uptr->u5 = fdcnum; //fdc device number + uptr->u6 = i; //fdd unit number + uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */ + sim_printf(" isbc201-%d: Configured, Status=%02X Not attached\n", i, fdc201[fdcnum].stat); + } else { + switch(i){ + case 0: + fdc201[fdcnum].stat |= RDY0; //set FDD 0 ready + fdc201[fdcnum].rbyte1 |= RB1RD0; + break; + case 1: + fdc201[fdcnum].stat |= RDY1; //set FDD 1 ready + fdc201[fdcnum].rbyte1 |= RB1RD1; + break; + } + sim_printf(" isbc201-%d: Configured, Status=%02X Attached to %s\n", + i, fdc201[fdcnum].stat, uptr->filename); + } + } +} + +/* isbc202 attach - attach an .IMG file to a FDD */ + +t_stat isbc201_attach (UNIT *uptr, CONST char *cptr) +{ + t_stat r; + FILE *fp; + int32 i, c = 0; + long flen; + uint8 fdcnum, fddnum; + + sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_attach: Entered with cptr=%s\n", cptr); + if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { + sim_printf(" isbc201_attach: Attach error\n"); + return r; + } + fdcnum = uptr->u5; + fddnum = uptr->u6; + fp = fopen(uptr->filename, "rb"); + if (fp == NULL) { + sim_printf(" Unable to open disk image file %s\n", uptr->filename); + sim_printf(" No disk image loaded!!!\n"); + } else { + sim_printf("isbc202: Attach\n"); + fseek(fp, 0, SEEK_END); /* size disk image */ + flen = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (fdc201[fdcnum].fdd[fddnum].buf == NULL) { /* no buffer allocated */ + fdc201[fdcnum].fdd[fddnum].buf = (uint8 *)malloc(flen); + if (fdc201[fdcnum].fdd[fddnum].buf == NULL) { + sim_printf(" isbc201_attach: Malloc error\n"); + return SCPE_MEM; + } + } + uptr->capac = flen; + i = 0; + c = fgetc(fp); // copy disk image into buffer + while (c != EOF) { + *(fdc201[fdcnum].fdd[fddnum].buf + i++) = c & 0xFF; + c = fgetc(fp); + } + fclose(fp); + switch(fddnum){ + case 0: + fdc201[fdcnum].stat |= RDY0; //set FDD 0 ready + fdc201[fdcnum].rtype = ROK; + fdc201[fdcnum].rbyte1 |= RB1RD0; + break; + case 1: + fdc201[fdcnum].stat |= RDY1; //set FDD 1 ready + fdc201[fdcnum].rtype = ROK; + fdc201[fdcnum].rbyte1 |= RB1RD1; + break; + } + if (flen == 256256) { /* 8" 256K SSSD */ + fdc201[fdcnum].fdd[fddnum].maxcyl = 77; + fdc201[fdcnum].fdd[fddnum].maxsec = 26; + } + sim_printf(" iSBC-201%d: Configured %d bytes, Attached to %s\n", + fdcnum, uptr->capac, uptr->filename); + } + sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_attach: Done\n"); + return SCPE_OK; +} + +/* isbc202 set mode = Write protect */ + +t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ +// sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_set_mode: Entered with val=%08XH uptr->flags=%08X\n", +// val, uptr->flags); + if (val & UNIT_WPMODE) { /* write protect */ + uptr->flags |= val; + } else { /* read write */ + uptr->flags &= ~val; + } +// sim_debug (DEBUG_flow, &isbc201_dev, " isbc201_set_mode: Done\n"); + return SCPE_OK; +} + +uint8 isbc201_get_dn(void) +{ + int i; + + for (i=0; i= fdc201[i].baseport && port <= fdc201[i].baseport + 7) + return i; + sim_printf("isbc201_get_dn: port %04X not in isbc202 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +/* ISBC201 control port functions */ + +uint8 isbc2010(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = isbc201_get_dn()) != 0xFF) { + if (io == 0) { /* read ststus*/ + if (DEBUG) + sim_printf("\n isbc201-%d: returned status=%02X", + fdcnum, fdc201[fdcnum].stat); + return fdc201[fdcnum].stat; + } + } + return 0; +} + +uint8 isbc2011(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = isbc201_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + fdc201[fdcnum].intff = 0; //clear interrupt FF + fdc201[fdcnum].stat &= ~FDCINT; + if (DEBUG) + sim_printf("\n isbc201-%d: returned rtype=%02X intff=%02X status=%02X", + fdcnum, fdc201[fdcnum].rtype, fdc201[fdcnum].intff, fdc201[fdcnum].stat); + return fdc201[fdcnum].rtype; + } else { /* write data port */ + fdc201[fdcnum].iopb = data; + if (DEBUG) + sim_printf("\n isbc201-%d: IOPB low=%02X", fdcnum, data); + } + } + return 0; +} + +uint8 isbc2012(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = isbc201_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + fdc201[fdcnum].iopb |= (data << 8); + if (DEBUG) + sim_printf("\n isbc201-%d: data=%02X IOPB=%04X", fdcnum, data, fdc201[fdcnum].iopb); + isbc201_diskio(fdcnum); + if (fdc201[fdcnum].intff) + fdc201[fdcnum].stat |= FDCINT; + } + } + return 0; +} + +uint8 isbc2013(t_bool io, uint8 data) +{ + uint8 fdcnum, rslt; + + if ((fdcnum = isbc201_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + switch(fdc201[fdcnum].rtype) { + case 0x00: + rslt = fdc201[fdcnum].rbyte0; + break; + case 0x02: + rslt = fdc201[fdcnum].rbyte1; + break; + } + if (DEBUG) + sim_printf("\n isbc201-%d: returned result byte=%02X", fdcnum, rslt); + return rslt; + } else { /* write data port */ + ; //stop diskette operation + } + } + return 0; +} + +uint8 isbc2017(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = isbc201_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + isbc201_reset1(fdcnum); + } + } + return 0; +} + +// perform the actual disk I/O operation + +void isbc201_diskio(uint8 fdcnum) +{ + uint8 cw, di, nr, ta, sa, bn, data, nrptr, c; + uint16 ba, ni; + uint32 dskoff; + uint8 fddnum; + uint32 i; + UNIT *uptr; + FILE *fp; + + //parse the IOPB + cw = multibus_get_mbyte(fdc201[fdcnum].iopb); + di = multibus_get_mbyte(fdc201[fdcnum].iopb + 1); + nr = multibus_get_mbyte(fdc201[fdcnum].iopb + 2); + ta = multibus_get_mbyte(fdc201[fdcnum].iopb + 3); + sa = multibus_get_mbyte(fdc201[fdcnum].iopb + 4); + ba = multibus_get_mword(fdc201[fdcnum].iopb + 5); + bn = multibus_get_mbyte(fdc201[fdcnum].iopb + 7); + ni = multibus_get_mword(fdc201[fdcnum].iopb + 8); + fddnum = (di & 0x30) >> 4; + uptr = isbc201_dev.units + fddnum; + if (DEBUG) { + sim_printf("\n isbc201-%d: isbc201_diskio IOPB=%04X FDD=%02X STAT=%02X", + fdcnum, fdc201[fdcnum].iopb, fddnum, fdc201[fdcnum].stat); + sim_printf("\n isbc201-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X", + fdcnum, cw, di, nr, ta, sa, ba, bn, ni); + } + //check for not ready + switch(fddnum) { + case 0: + if ((fdc201[fdcnum].stat & RDY0) == 0) { + fdc201[fdcnum].rtype = RERR; + fdc201[fdcnum].rbyte0 = RB0NR; + fdc201[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc201-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + case 1: + if ((fdc201[fdcnum].stat & RDY1) == 0) { + fdc201[fdcnum].rtype = RERR; + fdc201[fdcnum].rbyte0 = RB0NR; + fdc201[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc201-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + } + //check for address error + if ( + (sa > fdc201[fdcnum].fdd[fddnum].maxsec) || + ((sa + nr) > (fdc201[fdcnum].fdd[fddnum].maxsec + 1)) || + (sa == 0) || + (ta > fdc201[fdcnum].fdd[fddnum].maxcyl) + ) { +// sim_printf("\n isbc201-%d: maxsec=%02X maxcyl=%02X", +// fdcnum, fdc201[fdcnum].fdd[fddnum].maxsec, fdc201[fdcnum].fdd[fddnum].maxcyl); + fdc201[fdcnum].rtype = RERR; + fdc201[fdcnum].rbyte0 = RB0ADR; + fdc201[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc201-%d: Address error on drive %d", fdcnum, fddnum); + return; + } + switch (di & 0x07) { + case DNOP: + case DSEEK: + case DHOME: + case DVCRC: + fdc201[fdcnum].rtype = ROK; + fdc201[fdcnum].intff = 1; //set interrupt FF + break; + case DREAD: + nrptr = 0; + while(nrptr < nr) { + //calculate offset into disk image + dskoff = ((ta * fdc201[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128; + if (DEBUG) + sim_printf("\n isbc201-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X dskoff=%06X", + fdcnum, cw, di, nr, ta, sa, ba, bn, ni, dskoff); + for (i=0; i<128; i++) { //copy sector from image to RAM + data = *(fdc201[fdcnum].fdd[fddnum].buf + (dskoff + i)); + multibus_put_mbyte(ba + i, data); + } + sa++; + ba+=0x80; + nrptr++; + } + fdc201[fdcnum].rtype = ROK; + fdc201[fdcnum].intff = 1; //set interrupt FF + break; + case DWRITE: + //check for WP + if(uptr->flags & UNIT_WPMODE) { + fdc201[fdcnum].rtype = RERR; + fdc201[fdcnum].rbyte0 = RB0WP; + fdc201[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc201-%d: Write protect error on drive %d", fdcnum, fddnum); + return; + } + nrptr = 0; + while(nrptr < nr) { + //calculate offset into disk image + dskoff = ((ta * fdc201[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128; + if (DEBUG) + sim_printf("\n isbc201-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X bn=%02X ni=%04X dskoff=%06X", + fdcnum, cw, di, nr, ta, sa, ba, bn, ni, dskoff); + for (i=0; i<128; i++) { //copy sector from image to RAM + data = multibus_get_mbyte(ba + i); + *(fdc201[fdcnum].fdd[fddnum].buf + (dskoff + i)) = data; + } + sa++; + ba+=0x80; + nrptr++; + } + //*** quick fix. Needs more thought! + fp = fopen(uptr->filename, "wb"); // write out modified image + for (i=0; icapac; i++) { + c = *(fdc201[fdcnum].fdd[fddnum].buf + i); + fputc(c, fp); + } + fclose(fp); + fdc201[fdcnum].rtype = ROK; + fdc201[fdcnum].intff = 1; //set interrupt FF + break; + default: + sim_printf("\n isbc201-%d: isbc201_diskio bad di=%02X", fdcnum, di & 0x07); + break; + } +} + +/* end of isbc201.c */ diff --git a/Intel-Systems/common/isbc202.c b/Intel-Systems/common/isbc202.c index aafd9611..628cf3f1 100644 --- a/Intel-Systems/common/isbc202.c +++ b/Intel-Systems/common/isbc202.c @@ -29,31 +29,241 @@ NOTES: + This controller will mount 4 DD disk images on drives :F0: thru :F3: addressed + at ports 078H to 07FH. + + Registers: + + 078H - Read - Subsystem status + bit 0 - ready status of drive 0 + bit 1 - ready status of drive 1 + bit 2 - state of channel's interrupt FF + bit 3 - controller presence indicator + bit 4 - DD controller presence indicator + bit 5 - ready status of drive 2 + bit 6 - ready status of drive 3 + bit 7 - zero + + 079H - Read - Read result type (bits 2-7 are zero) + 00 - I/O complete with error + 01 - Reserved + 10 - Result byte contains diskette ready status + 11 - Reserved + 079H - Write - IOPB address low byte. + + 07AH - Write - IOPB address high byte and start operation. + + 07BH - Read - Read result byte + If result type is 00H + bit 0 - deleted record + bit 1 - CRC error + bit 2 - seek error + bit 3 - address error + bit 4 - data overrun/underrun + bit 5 - write protect + bit 6 - write error + bit 7 - not ready + If result type is 10H + bit 0 - zero + bit 1 - zero + bit 2 - zero + bit 3 - zero + bit 4 - drive 2 ready + bit 5 - drive 3 ready + bit 6 - drive 0 ready + bit 7 - drive 1 ready + + 07FH - Write - Reset diskette system. + + Operations: + Recalibrate - + Seek - + Format Track - + Write Data - + Write Deleted Data - + Read Data - + Verify CRC - + + IOPB - I/O Parameter Block + Byte 0 - Channel Word + bit 3 - data word length (=8-bit, 1=16-bit) + bit 4-5 - interrupt control + 00 - I/O complete interrupt to be issued + 01 - I/O complete interrupts are disabled + 10 - illegal code + 11 - illegal code + bit 6- randon format sequence + + Byte 1 - Diskette Instruction + bit 0-2 - operation code + 000 - no operation + 001 - seek + 010 - format track + 011 - recalibrate + 100 - read data + 101 - verify CRC + 110 - write data + 111 - write deleted data + bit 3 - data word length ( same as byte-0, bit-3) + bit 4-5 - unit select + 00 - drive 0 + 01 - drive 1 + 10 - drive 2 + 11 - drive 3 + bit 6-7 - reserved (zero) + + Byte 2 - Number of Records + + Byte 4 - Track Address + + Byte 5 - Sector Address + + Byte 6 - Buffer Low Address + + Byte 7 - Buffer High Address + + u3 - + u4 - + u5 - + u6 - fdd number. */ #include "system_defs.h" /* system header in system dir */ -/* function prototypes */ +#define DEBUG 0 -uint8 isbc202(t_bool io, uint8 data, uint8 devnum); /* isbc202*/ -t_stat isbc202_reset(DEVICE *dptr, uint16 base, uint8 devnum); +#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ +#define UNIT_WPMODE (1 << UNIT_V_WPMODE) + +#define FDD_NUM 4 + +//disk controoler operations +#define DNOP 0x00 //disk no operation +#define DSEEK 0x01 //disk seek +#define DFMT 0x02 //disk format +#define DHOME 0x03 //disk home +#define DREAD 0x04 //disk read +#define DVCRC 0x05 //disk verify CRC +#define DWRITE 0x06 //disk write + +//status +#define RDY0 0x01 //FDD 0 ready +#define RDY1 0x02 //FDD 1 ready +#define FDCINT 0x04 //FDC interrupt flag +#define FDCPRE 0x08 //FDC board present +#define FDCDD 0x10 //fdc is DD +#define RDY2 0x20 //FDD 2 ready +#define RDY3 0x40 //FDD 3 ready + +//result type +#define RERR 0x00 //FDC returned error +#define ROK 0x02 //FDC returned ok + +// If result type is RERR then rbyte is +#define RB0DR 0x01 //deleted record +#define RB0CRC 0x02 //CRC error +#define RB0SEK 0x04 //seek error +#define RB0ADR 0x08 //address error +#define RB0OU 0x10 //data overrun/underrun +#define RB0WP 0x20 //write protect +#define RB0WE 0x40 //write error +#define RB0NR 0x80 //not ready + +// If result type is ROK then rbyte is +#define RB1RD2 0x10 //drive 2 ready +#define RB1RD3 0x20 //drive 3 ready +#define RB1RD0 0x40 //drive 0 ready +#define RB1RD1 0x80 //drive 1 ready + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] /* external function prototypes */ -extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 multibus_get_mbyte(uint16 addr); +extern uint16 multibus_get_mword(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern uint8 multibus_put_mword(uint16 addr, uint16 val); + +/* function prototypes */ + +t_stat isbc202_reset(DEVICE *dptr, uint16 base); +void isbc202_reset1(uint8 fdcnum); +t_stat isbc202_attach (UNIT *uptr, CONST char *cptr); +t_stat isbc202_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +uint8 isbc202_get_dn(void); +uint8 isbc2020(t_bool io, uint8 data); /* isbc202 0 */ +uint8 isbc2021(t_bool io, uint8 data); /* isbc202 1 */ +uint8 isbc2022(t_bool io, uint8 data); /* isbc202 2 */ +uint8 isbc2023(t_bool io, uint8 data); /* isbc202 3 */ +uint8 isbc2027(t_bool io, uint8 data); /* isbc202 7 */ +void isbc202_diskio(uint8 fdcnum); //do actual disk i/o /* globals */ +int32 isbc202_fdcnum = 0; //actual number of SBC-202 instances + 1 + +typedef struct { //FDD definition + uint8 *buf; + int t0; + int rdy; + uint8 maxsec; + uint8 maxcyl; + } FDDDEF; + +typedef struct { //FDC definition + uint16 baseport; //FDC base port + uint16 iopb; //FDC IOPB + uint8 stat; //FDC status + uint8 rtype; //FDC result type + uint8 rbyte0; //FDC result byte for type 00 + uint8 rbyte1; //FDC result byte for type 10 + uint8 intff; //fdc interrupt FF + FDDDEF fdd[FDD_NUM]; //indexed by the FDD number + } FDCDEF; + +FDCDEF fdc202[4]; //indexed by the isbc-202 instance number + UNIT isbc202_unit[] = { - { UDATA (0, 0, 0) }, /* isbc202*/ + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 } }; REG isbc202_reg[] = { - { HRDATA (CONTROL0, isbc202_unit[0].u3, 8) }, /* isbc202 */ + { HRDATA (STAT0, fdc202[0].stat, 8) }, /* isbc202 0 status */ + { HRDATA (RTYP0, fdc202[0].rtype, 8) }, /* isbc202 0 result type */ + { HRDATA (RBYT0A, fdc202[0].rbyte0, 8) }, /* isbc202 0 result byte 0 */ + { HRDATA (RBYT0B, fdc202[0].rbyte1, 8) }, /* isbc202 0 result byte 1 */ + { HRDATA (INTFF0, fdc202[0].intff, 8) }, /* isbc202 0 interrupt f/f */ + { HRDATA (STAT1, fdc202[1].stat, 8) }, /* isbc202 1 status */ + { HRDATA (RTYP1, fdc202[1].rtype, 8) }, /* isbc202 1 result type */ + { HRDATA (RBYT1A, fdc202[1].rbyte0, 8) }, /* isbc202 1 result byte 0 */ + { HRDATA (RBYT1B, fdc202[1].rbyte1, 8) }, /* isbc202 1 result byte 1 */ + { HRDATA (INTFF1, fdc202[1].intff, 8) }, /* isbc202 1 interrupt f/f */ + { HRDATA (STAT2, fdc202[2].stat, 8) }, /* isbc202 2 status */ + { HRDATA (RTYP2, fdc202[2].rtype, 8) }, /* isbc202 2 result type */ + { HRDATA (RBYT2A, fdc202[2].rbyte0, 8) }, /* isbc202 2 result byte 0 */ + { HRDATA (RBYT2B, fdc202[0].rbyte1, 8) }, /* isbc202 2 result byte 1 */ + { HRDATA (INTFF2, fdc202[2].intff, 8) }, /* isbc202 2 interrupt f/f */ + { HRDATA (STAT3, fdc202[3].stat, 8) }, /* isbc202 3 status */ + { HRDATA (RTYP3, fdc202[3].rtype, 8) }, /* isbc202 3 result type */ + { HRDATA (RBYT3A, fdc202[3].rbyte0, 8) }, /* isbc202 3 result byte 0 */ + { HRDATA (RBYT3B, fdc202[3].rbyte1, 8) }, /* isbc202 3 result byte 1 */ + { HRDATA (INTFF3, fdc202[0].intff, 8) }, /* isbc202 3 interrupt f/f */ { NULL } }; +MTAB isbc202_mod[] = { + { UNIT_WPMODE, 0, "RW", "RW", &isbc202_set_mode }, + { UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc202_set_mode }, + { 0 } +}; + DEBTAB isbc202_debug[] = { { "ALL", DEBUG_all }, { "FLOW", DEBUG_flow }, @@ -68,11 +278,11 @@ DEBTAB isbc202_debug[] = { /* address width is set to 16 bits to use devices in 8086/8088 implementations */ DEVICE isbc202_dev = { - "ISBC202", //name - isbc202_unit, //units - isbc202_reg, //registers - NULL, //modifiers - 1, //numunits + "SBC202", //name + isbc202_unit, //units + isbc202_reg, //registers + isbc202_mod, //modifiers + FDD_NUM, //numunits 16, //aradix 16, //awidth 1, //aincr @@ -80,51 +290,449 @@ DEVICE isbc202_dev = { 8, //dwidth NULL, //examine NULL, //deposit -// &isbc202_reset, //reset - NULL, //reset + NULL, //reset NULL, //boot - NULL, //attach + &isbc202_attach, //attach NULL, //detach NULL, //ctxt - 0, //flags - 0, //dctrl - isbc202_debug, //debflags + DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags + DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl + isbc202_debug, //debflags NULL, //msize NULL //lname }; -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ +/* Hardware reset routine */ -/* ISBC202 control port functions */ - -uint8 isbc202(t_bool io, uint8 data, uint8 devnum) +t_stat isbc202_reset(DEVICE *dptr, uint16 base) { - if (io == 0) { /* always return 0 */ - sim_printf(" isbc202: read data=%02X port=%02X returned 0\n", data, devnum); - return 0x00; - } else { /* write control port */ - sim_printf(" isbc202: data=%02X port=%02X\n", data, devnum); - } -} - -/* Reset routine */ - -t_stat isbc202_reset(DEVICE *dptr, uint16 base, uint8 devnum) -{ - reg_dev(isbc202, base, devnum); - reg_dev(isbc202, base + 1, devnum); - reg_dev(isbc202, base + 2, devnum); - reg_dev(isbc202, base + 3, devnum); - reg_dev(isbc202, base + 4, devnum); - reg_dev(isbc202, base + 5, devnum); - reg_dev(isbc202, base + 6, devnum); - reg_dev(isbc202, base + 7, devnum); - isbc202_unit[devnum].u3 = 0x00; /* ipc reset */ - sim_printf(" isbc202-%d: Reset\n", devnum); - sim_printf(" isbc202-%d: Registered at %04X\n", devnum, base); + sim_printf("Initializing iSBC-202 FDC Board\n"); + if (SBC202_NUM) { + sim_printf(" isbc202-%d: Hardware Reset\n", isbc202_fdcnum); + sim_printf(" isbc202-%d: Registered at %04X\n", isbc202_fdcnum, base); + fdc202[isbc202_fdcnum].baseport = base; + reg_dev(isbc2020, base, isbc202_fdcnum); //read status + reg_dev(isbc2021, base + 1, isbc202_fdcnum); //read rslt type/write IOPB addr-l + reg_dev(isbc2022, base + 2, isbc202_fdcnum); //write IOPB addr-h and start + reg_dev(isbc2023, base + 3, isbc202_fdcnum); //read rstl byte + reg_dev(isbc2027, base + 7, isbc202_fdcnum); //write reset isbc202 + isbc202_reset1(isbc202_fdcnum); + isbc202_fdcnum++; + } else + sim_printf(" No isbc202 installed\n"); return SCPE_OK; } +/* Software reset routine */ + +void isbc202_reset1(uint8 fdcnum) +{ + int32 i; + UNIT *uptr; + + sim_printf(" isbc202-%d: Software Reset\n", fdcnum); + fdc202[fdcnum].stat = 0; //clear status + for (i = 0; i < FDD_NUM; i++) { /* handle all units */ + uptr = isbc202_dev.units + i; + fdc202[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status + fdc202[fdcnum].rtype = ROK; + if (uptr->capac == 0) { /* if not configured */ + uptr->u5 = fdcnum; //fdc device number + uptr->u6 = i; //fdd unit number + uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */ + sim_printf(" SBC202%d: Configured, Status=%02X Not attached\n", i, fdc202[fdcnum].stat); + } else { + switch(i){ + case 0: + fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready + fdc202[fdcnum].rbyte1 |= RB1RD0; + break; + case 1: + fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready + fdc202[fdcnum].rbyte1 |= RB1RD1; + break; + case 2: + fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready + fdc202[fdcnum].rbyte1 |= RB1RD2; + break; + case 3: + fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready + fdc202[fdcnum].rbyte1 |= RB1RD3; + break; + } + sim_printf(" SBC202%d: Configured, Status=%02X Attached to %s\n", + i, fdc202[fdcnum].stat, uptr->filename); + } + } +} + +/* isbc202 attach - attach an .IMG file to a FDD */ + +t_stat isbc202_attach (UNIT *uptr, CONST char *cptr) +{ + t_stat r; + FILE *fp; + int32 i, c = 0; + long flen; + uint8 fdcnum, fddnum; + + sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Entered with cptr=%s\n", cptr); + if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { + sim_printf(" isbc202_attach: Attach error\n"); + return r; + } + fdcnum = uptr->u5; + fddnum = uptr->u6; + fp = fopen(uptr->filename, "rb"); + if (fp == NULL) { + sim_printf(" Unable to open disk image file %s\n", uptr->filename); + sim_printf(" No disk image loaded!!!\n"); + } else { + sim_printf("isbc202: Attach\n"); + fseek(fp, 0, SEEK_END); /* size disk image */ + flen = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (fdc202[fdcnum].fdd[fddnum].buf == NULL) { /* no buffer allocated */ + fdc202[fdcnum].fdd[fddnum].buf = (uint8 *)malloc(flen); + if (fdc202[fdcnum].fdd[fddnum].buf == NULL) { + sim_printf(" isbc202_attach: Malloc error\n"); + return SCPE_MEM; + } + } + uptr->capac = flen; + i = 0; + c = fgetc(fp); // copy disk image into buffer + while (c != EOF) { + *(fdc202[fdcnum].fdd[fddnum].buf + i++) = c & 0xFF; + c = fgetc(fp); + } + fclose(fp); + switch(fddnum){ + case 0: + fdc202[fdcnum].stat |= RDY0; //set FDD 0 ready + fdc202[fdcnum].rtype = ROK; + fdc202[fdcnum].rbyte1 |= RB1RD0; + break; + case 1: + fdc202[fdcnum].stat |= RDY1; //set FDD 1 ready + fdc202[fdcnum].rtype = ROK; + fdc202[fdcnum].rbyte1 |= RB1RD1; + break; + case 2: + fdc202[fdcnum].stat |= RDY2; //set FDD 2 ready + fdc202[fdcnum].rtype = ROK; + fdc202[fdcnum].rbyte1 |= RB1RD2; + break; + case 3: + fdc202[fdcnum].stat |= RDY3; //set FDD 3 ready + fdc202[fdcnum].rtype = ROK; + fdc202[fdcnum].rbyte1 |= RB1RD3; + break; + } + if (flen == 512512) { /* 8" 512K SSDD */ + fdc202[fdcnum].fdd[fddnum].maxcyl = 77; + fdc202[fdcnum].fdd[fddnum].maxsec = 52; + } else + sim_printf(" iSBC-202-%d: Not a DD disk image\n", fdcnum); + + sim_printf(" iSBC-202%d: Configured %d bytes, Attached to %s\n", + fdcnum, uptr->capac, uptr->filename); + } + sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_attach: Done\n"); + return SCPE_OK; +} + +/* isbc202 set mode = Write protect */ + +t_stat isbc202_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ +// sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_set_mode: Entered with val=%08XH uptr->flags=%08X\n", +// val, uptr->flags); + if (val & UNIT_WPMODE) { /* write protect */ + uptr->flags |= val; + } else { /* read write */ + uptr->flags &= ~val; + } +// sim_debug (DEBUG_flow, &isbc202_dev, " isbc202_set_mode: Done\n"); + return SCPE_OK; +} + +uint8 isbc202_get_dn(void) +{ + int i; + + for (i=0; i= fdc202[i].baseport && port <= fdc202[i].baseport + 7) + return i; + sim_printf("isbc202_get_dn: port %04X not in isbc202 device table\n", port); + return 0xFF; +} + +/* ISBC202 control port functions */ + +uint8 isbc2020(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = isbc202_get_dn()) != 0xFF) { + if (io == 0) { /* read ststus*/ + if (DEBUG) + sim_printf("\n isbc202-%d: returned status=%02X", fdcnum, fdc202[fdcnum].stat); + return fdc202[fdcnum].stat; + } + } + return 0; +} + +uint8 isbc2021(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = isbc202_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + fdc202[fdcnum].intff = 0; //clear interrupt FF + fdc202[fdcnum].stat &= ~FDCINT; + if (DEBUG) + sim_printf("\n isbc202-%d: returned rtype=%02X intff=%02X status=%02X", + fdcnum, fdc202[fdcnum].rtype, fdc202[fdcnum].intff, fdc202[fdcnum].stat); + return fdc202[fdcnum].rtype; + } else { /* write data port */ + fdc202[fdcnum].iopb = data; + if (DEBUG) + sim_printf("\n isbc202-%d: IOPB low=%02X", fdcnum, data); + } + } + return 0; +} + +uint8 isbc2022(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = isbc202_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + fdc202[fdcnum].iopb |= (data << 8); + if (DEBUG) + sim_printf("\n isbc202-%d: IOPB=%04X", fdcnum, fdc202[fdcnum].iopb); + isbc202_diskio(fdcnum); + if (fdc202[fdcnum].intff) + fdc202[fdcnum].stat |= FDCINT; + } + } + return 0; +} + +uint8 isbc2023(t_bool io, uint8 data) +{ + uint8 fdcnum, rslt; + + if ((fdcnum = isbc202_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + switch(fdc202[fdcnum].rtype) { + case 0x00: + rslt = fdc202[fdcnum].rbyte0; + break; + case 0x02: + rslt = fdc202[fdcnum].rbyte1; + break; + } + if (DEBUG) + sim_printf("\n isbc202-%d: returned result byte=%02X", fdcnum, rslt); + return rslt; + } else { /* write data port */ + ; //stop diskette operation + } + } + return 0; +} + +uint8 isbc2027(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = isbc202_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + isbc202_reset1(fdcnum); + } + } + return 0; +} + +// perform the actual disk I/O operation + +void isbc202_diskio(uint8 fdcnum) +{ + uint8 cw, di, nr, ta, sa, data, nrptr, c; + uint16 ba; + uint32 dskoff; + uint8 fddnum, fmtb; + uint32 i; + UNIT *uptr; + FILE *fp; + //parse the IOPB + cw = multibus_get_mbyte(fdc202[fdcnum].iopb); + di = multibus_get_mbyte(fdc202[fdcnum].iopb + 1); + nr = multibus_get_mbyte(fdc202[fdcnum].iopb + 2); + ta = multibus_get_mbyte(fdc202[fdcnum].iopb + 3); + sa = multibus_get_mbyte(fdc202[fdcnum].iopb + 4); + ba = multibus_get_mword(fdc202[fdcnum].iopb + 5); + fddnum = (di & 0x30) >> 4; + uptr = isbc202_dev.units + fddnum; + if (DEBUG) { + sim_printf("\n isbc202-%d: isbc202_diskio IOPB=%04X FDD=%02X STAT=%02X", + fdcnum, fdc202[fdcnum].iopb, fddnum, fdc202[fdcnum].stat); + sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X", + fdcnum, cw, di, nr, ta, sa, ba); + sim_printf("\n isbc202-%d: maxsec=%02X maxcyl=%02X", + fdcnum, fdc202[fdcnum].fdd[fddnum].maxsec, fdc202[fdcnum].fdd[fddnum].maxcyl); + } + //check for not ready + switch(fddnum) { + case 0: + if ((fdc202[fdcnum].stat & RDY0) == 0) { + fdc202[fdcnum].rtype = RERR; + fdc202[fdcnum].rbyte0 = RB0NR; + fdc202[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + case 1: + if ((fdc202[fdcnum].stat & RDY1) == 0) { + fdc202[fdcnum].rtype = RERR; + fdc202[fdcnum].rbyte0 = RB0NR; + fdc202[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + case 2: + if ((fdc202[fdcnum].stat & RDY2) == 0) { + fdc202[fdcnum].rtype = RERR; + fdc202[fdcnum].rbyte0 = RB0NR; + fdc202[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + case 3: + if ((fdc202[fdcnum].stat & RDY3) == 0) { + fdc202[fdcnum].rtype = RERR; + fdc202[fdcnum].rbyte0 = RB0NR; + fdc202[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc202-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + } + //check for address error + if ( + (sa > fdc202[fdcnum].fdd[fddnum].maxsec) || + ((sa + nr) > (fdc202[fdcnum].fdd[fddnum].maxsec + 1)) || + (sa == 0) || + (ta > fdc202[fdcnum].fdd[fddnum].maxcyl) + ) { + if (DEBUG) + sim_printf("\n isbc202-%d: maxsec=%02X maxcyl=%02X", + fdcnum, fdc202[fdcnum].fdd[fddnum].maxsec, fdc202[fdcnum].fdd[fddnum].maxcyl); + fdc202[fdcnum].rtype = RERR; + fdc202[fdcnum].rbyte0 = RB0ADR; + fdc202[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc202-%d: Address error on drive %d", fdcnum, fddnum); + return; + } + switch (di & 0x07) { + case DNOP: + case DSEEK: + case DHOME: + case DVCRC: + fdc202[fdcnum].rtype = ROK; + fdc202[fdcnum].intff = 1; //set interrupt FF + break; + case DFMT: + //check for WP + if(uptr->flags & UNIT_WPMODE) { + fdc202[fdcnum].rtype = RERR; + fdc202[fdcnum].rbyte0 = RB0WP; + fdc202[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc202-%d: Write protect error 1 on drive %d", fdcnum, fddnum); + return; + } + fmtb = multibus_get_mbyte(ba); //get the format byte + //calculate offset into disk image + dskoff = ((ta * (uint32)(fdc202[fdcnum].fdd[fddnum].maxsec)) + (sa - 1)) * 128; + for(i=0; i<=((uint32)(fdc202[fdcnum].fdd[fddnum].maxsec) * 128); i++) { + *(fdc202[fdcnum].fdd[fddnum].buf + (dskoff + i)) = fmtb; + } + //*** quick fix. Needs more thought! + fp = fopen(uptr->filename, "wb"); // write out modified image + for (i=0; icapac; i++) { + c = *(fdc202[fdcnum].fdd[fddnum].buf + i); + fputc(c, fp); + } + fclose(fp); + fdc202[fdcnum].rtype = ROK; + fdc202[fdcnum].intff = 1; //set interrupt FF + break; + case DREAD: + nrptr = 0; + while(nrptr < nr) { + //calculate offset into disk image + dskoff = ((ta * fdc202[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128; +// sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X", +// fdcnum, cw, di, nr, ta, sa, ba, dskoff); + for (i=0; i<128; i++) { //copy sector from image to RAM + data = *(fdc202[fdcnum].fdd[fddnum].buf + (dskoff + i)); + multibus_put_mbyte(ba + i, data); + } + sa++; + ba+=0x80; + nrptr++; + } + fdc202[fdcnum].rtype = ROK; + fdc202[fdcnum].intff = 1; //set interrupt FF + break; + case DWRITE: + //check for WP + if(uptr->flags & UNIT_WPMODE) { + fdc202[fdcnum].rtype = RERR; + fdc202[fdcnum].rbyte0 = RB0WP; + fdc202[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n isbc202-%d: Write protect error 2 on drive %d", fdcnum, fddnum); + return; + } + nrptr = 0; + while(nrptr < nr) { + //calculate offset into disk image + dskoff = ((ta * fdc202[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128; + // sim_printf("\n isbc202-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X", + // fdcnum, cw, di, nr, ta, sa, ba, dskoff); + for (i=0; i<128; i++) { //copy sector from image to RAM + data = multibus_get_mbyte(ba + i); + *(fdc202[fdcnum].fdd[fddnum].buf + (dskoff + i)) = data; + } + sa++; + ba+=0x80; + nrptr++; + } + //*** quick fix. Needs more thought! + fp = fopen(uptr->filename, "wb"); // write out modified image + for (i=0; icapac; i++) { + c = *(fdc202[fdcnum].fdd[fddnum].buf + i); + fputc(c, fp); + } + fclose(fp); + fdc202[fdcnum].rtype = ROK; + fdc202[fdcnum].intff = 1; //set interrupt FF + break; + default: + sim_printf("\n isbc202-%d: isbc202_diskio bad di=%02X", fdcnum, di & 0x07); + break; + } +} + /* end of isbc202.c */ diff --git a/Intel-Systems/common/isbc208.c b/Intel-Systems/common/isbc208.c index 616fc87b..e2bcc529 100644 --- a/Intel-Systems/common/isbc208.c +++ b/Intel-Systems/common/isbc208.c @@ -473,41 +473,44 @@ #define FDD_NUM 4 +int32 sbc208_devnum = 0; //actual number of 8255 instances + 1 +uint16 sbc208_port[4]; //base port registered to each instance + /* internal function prototypes */ t_stat isbc208_svc (UNIT *uptr); -t_stat isbc208_reset (DEVICE *dptr); +t_stat isbc208_reset (DEVICE *dptr, uint16 base); void isbc208_reset1 (void); t_stat isbc208_attach (UNIT *uptr, CONST char *cptr); t_stat isbc208_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -uint8 isbc208_r0(t_bool io, uint8 data, uint8 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); +uint8 isbc208_r0(t_bool io, uint8 data); +uint8 isbc208_r1(t_bool io, uint8 data); +uint8 isbc208_r2(t_bool io, uint8 data); +uint8 isbc208_r3(t_bool io, uint8 data); +uint8 isbc208_r4(t_bool io, uint8 data); +uint8 isbc208_r5(t_bool io, uint8 data); +uint8 isbc208_r6(t_bool io, uint8 data); +uint8 isbc208_r7(t_bool io, uint8 data); +uint8 isbc208_r8(t_bool io, uint8 data); +uint8 isbc208_r9(t_bool io, uint8 data); +uint8 isbc208_rA(t_bool io, uint8 data); +uint8 isbc208_rB(t_bool io, uint8 data); +uint8 isbc208_rC(t_bool io, uint8 data); +uint8 isbc208_rD(t_bool io, uint8 data); +uint8 isbc208_rE(t_bool io, uint8 data); +uint8 isbc208_rF(t_bool io, uint8 data); +uint8 isbc208_r10(t_bool io, uint8 data); +uint8 isbc208_r11(t_bool io, uint8 data); +uint8 isbc208_r12(t_bool io, uint8 data); +uint8 isbc208_r13(t_bool io, uint8 data); +uint8 isbc208_r14(t_bool io, uint8 data); +uint8 isbc208_r15(t_bool io, uint8 data); /* external function prototypes */ extern void set_irq(int32 int_num); extern void clr_irq(int32 int_num); -extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); extern void multibus_put_mbyte(uint16 addr, uint8 val); extern uint8 multibus_get_mbyte(uint16 addr); @@ -669,14 +672,15 @@ DEVICE isbc208_dev = { 8, //dwidth NULL, //examine NULL, //deposit - &isbc208_reset, //deposit +// &isbc208_reset, //deposit + NULL, //deposit NULL, //boot &isbc208_attach, //attach NULL, //detach NULL, //ctxt DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags - 0, //dctrl -// DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl +// 0, //dctrl + DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl isbc208_debug, //debflags NULL, //msize NULL //lname @@ -957,32 +961,43 @@ t_stat isbc208_svc (UNIT *uptr) /* Reset routine */ -t_stat isbc208_reset (DEVICE *dptr) +t_stat isbc208_reset (DEVICE *dptr, uint16 base) { - 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(); + if (sbc208_devnum > SBC208_NUM) { + sim_printf("sbc208_reset: too many devices!\n"); + return SCPE_MEM; + } + if (SBC202_NUM) { + sim_printf(" SBC208-%d: Hardware Reset\n", sbc208_devnum); + sim_printf(" SBC208-%d: Registered at %04X\n", sbc208_devnum, base); + sbc208_port[sbc208_devnum] = reg_dev(isbc208_r0, SBC208_BASE + 0, sbc208_devnum); + reg_dev(isbc208_r1, SBC208_BASE + 1, sbc208_devnum); + reg_dev(isbc208_r2, SBC208_BASE + 2, sbc208_devnum); + reg_dev(isbc208_r3, SBC208_BASE + 3, sbc208_devnum); + reg_dev(isbc208_r4, SBC208_BASE + 4, sbc208_devnum); + reg_dev(isbc208_r5, SBC208_BASE + 5, sbc208_devnum); + reg_dev(isbc208_r6, SBC208_BASE + 6, sbc208_devnum); + reg_dev(isbc208_r7, SBC208_BASE + 7, sbc208_devnum); + reg_dev(isbc208_r8, SBC208_BASE + 8, sbc208_devnum); + reg_dev(isbc208_r9, SBC208_BASE + 9, sbc208_devnum); + reg_dev(isbc208_rA, SBC208_BASE + 10, sbc208_devnum); + reg_dev(isbc208_rB, SBC208_BASE + 11, sbc208_devnum); + reg_dev(isbc208_rC, SBC208_BASE + 12, sbc208_devnum); + reg_dev(isbc208_rD, SBC208_BASE + 13, sbc208_devnum); + reg_dev(isbc208_rE, SBC208_BASE + 14, sbc208_devnum); + reg_dev(isbc208_rF, SBC208_BASE + 15, sbc208_devnum); + reg_dev(isbc208_r10, SBC208_BASE + 16, sbc208_devnum); + reg_dev(isbc208_r11, SBC208_BASE + 17, sbc208_devnum); + reg_dev(isbc208_r12, SBC208_BASE + 18, sbc208_devnum); + reg_dev(isbc208_r13, SBC208_BASE + 19, sbc208_devnum); + reg_dev(isbc208_r14, SBC208_BASE + 20, sbc208_devnum); + reg_dev(isbc208_r15, SBC208_BASE + 21, sbc208_devnum); + if ((isbc208_dev.flags & DEV_DIS) == 0) + isbc208_reset1(); + sbc208_devnum++; + } else { + sim_printf(" No isbc208 installed\n"); + } return SCPE_OK; } @@ -1023,6 +1038,7 @@ void isbc208_reset1 (void) i8272_msr = RQM; /* 8272 ready for start of command */ rsp = wsp = 0; /* reset indexes */ cmd = 0; /* clear command */ + sim_printf(" SBC208-%d: Software Reset\n", sbc208_devnum); if (flag) { sim_printf(" 8237 Reset\n"); sim_printf(" 8272 Reset\n"); @@ -1120,7 +1136,7 @@ t_stat isbc208_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) to the device. */ -uint8 isbc208_r0(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r0(t_bool io, uint8 data) { if (io == 0) { /* read current address CH 0 */ if (i8237_rD) { /* high byte */ @@ -1146,7 +1162,7 @@ uint8 isbc208_r0(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r1(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r1(t_bool io, uint8 data) { if (io == 0) { /* read current word count CH 0 */ if (i8237_rD) { /* high byte */ @@ -1172,7 +1188,7 @@ uint8 isbc208_r1(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r2(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r2(t_bool io, uint8 data) { if (io == 0) { /* read current address CH 1 */ if (i8237_rD) { /* high byte */ @@ -1198,7 +1214,7 @@ uint8 isbc208_r2(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r3(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r3(t_bool io, uint8 data) { if (io == 0) { /* read current word count CH 1 */ if (i8237_rD) { /* high byte */ @@ -1224,7 +1240,7 @@ uint8 isbc208_r3(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r4(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r4(t_bool io, uint8 data) { if (io == 0) { /* read current address CH 2 */ if (i8237_rD) { /* high byte */ @@ -1250,7 +1266,7 @@ uint8 isbc208_r4(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r5(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r5(t_bool io, uint8 data) { if (io == 0) { /* read current word count CH 2 */ if (i8237_rD) { /* high byte */ @@ -1276,7 +1292,7 @@ uint8 isbc208_r5(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r6(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r6(t_bool io, uint8 data) { if (io == 0) { /* read current address CH 3 */ if (i8237_rD) { /* high byte */ @@ -1302,7 +1318,7 @@ uint8 isbc208_r6(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r7(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r7(t_bool io, uint8 data) { if (io == 0) { /* read current word count CH 3 */ if (i8237_rD) { /* high byte */ @@ -1328,7 +1344,7 @@ uint8 isbc208_r7(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r8(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r8(t_bool io, uint8 data) { if (io == 0) { /* read status register */ sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r8 (status) read as %02X\n", i8237_r8); @@ -1340,7 +1356,7 @@ uint8 isbc208_r8(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r9(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r9(t_bool io, uint8 data) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r9\n"); @@ -1352,7 +1368,7 @@ uint8 isbc208_r9(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_rA(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_rA(t_bool io, uint8 data) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rA\n"); @@ -1389,7 +1405,7 @@ uint8 isbc208_rA(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_rB(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_rB(t_bool io, uint8 data) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rB\n"); @@ -1401,7 +1417,7 @@ uint8 isbc208_rB(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_rC(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_rC(t_bool io, uint8 data) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rC\n"); @@ -1413,7 +1429,7 @@ uint8 isbc208_rC(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_rD(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_rD(t_bool io, uint8 data) { if (io == 0) { /* read temporary register */ sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rD\n"); @@ -1425,7 +1441,7 @@ uint8 isbc208_rD(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_rE(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_rE(t_bool io, uint8 data) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rE\n"); @@ -1437,7 +1453,7 @@ uint8 isbc208_rE(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_rF(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_rF(t_bool io, uint8 data) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rF\n"); @@ -1449,7 +1465,7 @@ uint8 isbc208_rF(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r10(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r10(t_bool io, uint8 data) { if (io == 0) { /* read FDC status register */ sim_debug (DEBUG_reg, &isbc208_dev, "i8272_msr read as %02X\n", i8272_msr); @@ -1461,7 +1477,7 @@ uint8 isbc208_r10(t_bool io, uint8 data, uint8 devnum) } // read/write FDC data register -uint8 isbc208_r11(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r11(t_bool io, uint8 data) { if (io == 0) { /* read FDC data register */ wsp = 0; /* clear write stack index */ @@ -1580,7 +1596,7 @@ uint8 isbc208_r11(t_bool io, uint8 data, uint8 devnum) return 0; } -uint8 isbc208_r12(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r12(t_bool io, uint8 data) { if (io == 0) { /* read interrupt status */ sim_debug (DEBUG_reg, &isbc208_dev, "isbc208_r12 read as %02X\n", isbc208_i); @@ -1592,7 +1608,7 @@ uint8 isbc208_r12(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r13(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r13(t_bool io, uint8 data) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r13\n"); @@ -1604,7 +1620,7 @@ uint8 isbc208_r13(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r14(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r14(t_bool io, uint8 data) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r14\n"); @@ -1616,7 +1632,7 @@ uint8 isbc208_r14(t_bool io, uint8 data, uint8 devnum) } } -uint8 isbc208_r15(t_bool io, uint8 data, uint8 devnum) +uint8 isbc208_r15(t_bool io, uint8 data) { if (io == 0) { sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r15\n"); diff --git a/Intel-Systems/common/multibus.c b/Intel-Systems/common/multibus.c index e183a670..3db3f04a 100644 --- a/Intel-Systems/common/multibus.c +++ b/Intel-Systems/common/multibus.c @@ -38,8 +38,6 @@ #include "system_defs.h" -#define SET_XACK(VAL) (xack = VAL) - int32 mbirq = 0; /* set no multibus interrupts */ /* function prototypes */ @@ -48,8 +46,8 @@ t_stat multibus_svc(UNIT *uptr); t_stat multibus_reset(DEVICE *dptr); void set_irq(int32 int_num); void clr_irq(int32 int_num); -uint8 nulldev(t_bool io, uint8 data, uint8 devnum); -uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint16 port, uint8 devnum); +uint8 nulldev(t_bool io, uint8 data); +uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnum); t_stat multibus_reset (DEVICE *dptr); uint8 multibus_get_mbyte(uint16 addr); void multibus_put_mbyte(uint16 addr, uint8 val); @@ -62,12 +60,15 @@ 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); -extern t_stat isbc208_reset (DEVICE *dptr); +extern t_stat isbc201_reset (DEVICE *dptr, uint16); +extern t_stat isbc202_reset (DEVICE *dptr, uint16); /* external globals */ extern uint8 xack; /* XACK signal */ extern int32 int_req; /* i8080 INT signal */ +extern int32 isbc201_fdcnum; +extern int32 isbc202_fdcnum; /* multibus Standard SIMH Device Data Structures */ @@ -124,7 +125,7 @@ t_stat multibus_svc(UNIT *uptr) switch (mbirq) { case INT_1: set_cpuint(INT_R); - clr_irq(SBC208_INT); /***** bad, bad, bad! */ + clr_irq(SBC202_INT); /***** bad, bad, bad! */ // sim_printf("multibus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req); break; default: @@ -140,9 +141,12 @@ t_stat multibus_svc(UNIT *uptr) t_stat multibus_reset(DEVICE *dptr) { SBC_reset(NULL); - isbc064_reset(NULL); - isbc208_reset(NULL); - sim_printf(" Multibus: Reset\n"); + sim_printf("Initializing Multibus Boards\n Multibus Boards:\n"); + isbc064_reset(NULL); + isbc201_fdcnum = 0; + isbc201_reset(NULL, SBC201_BASE); + isbc202_fdcnum = 0; + isbc202_reset(NULL, SBC202_BASE); sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ return SCPE_OK; } @@ -164,7 +168,8 @@ device addresses, if a device is plugged to a port it's routine address is here, 'nulldev' means no device has been registered. */ struct idev { - uint8 (*routine)(t_bool io, uint8 data, uint8 devnum); + uint8 (*routine)(t_bool io, uint8 data); + uint16 port; uint8 devnum; }; @@ -235,24 +240,27 @@ struct idev dev_table[256] = { {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */ }; -uint8 nulldev(t_bool flag, uint8 data, uint8 devnum) +//uint8 nulldev(t_bool flag, uint8 data, uint8 devnum) +uint8 nulldev(t_bool flag, uint8 data) { SET_XACK(0); /* set no XACK */ - if (flag == 0) /* if we got here, no valid I/O device */ - return (0xFF); +// if (flag == 0) /* if we got here, no valid I/O device */ +// return (0xFF); return 0; } -uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint16 port, uint8 devnum) +//uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint16 port, uint8 devnum) +uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data), 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); + if (dev_table[port].routine != routine) + sim_printf(" I/O Port %04X is already assigned\n", port); } else { -// sim_printf("Port %02X is assigned\n", port); + sim_printf(" Port %04X is assigned to dev %04X\n", port, devnum); dev_table[port].routine = routine; dev_table[port].devnum = devnum; } - return 0; + return 0; } /* get a byte from memory */ @@ -264,6 +272,17 @@ uint8 multibus_get_mbyte(uint16 addr) return isbc064_get_mbyte(addr); } +/* get a word from memory */ + +uint16 multibus_get_mword(uint16 addr) +{ + uint16 val; + + val = multibus_get_mbyte(addr); + val |= (multibus_get_mbyte(addr+1) << 8); + return val; +} + /* put a byte to memory */ void multibus_put_mbyte(uint16 addr, uint8 val) @@ -274,5 +293,13 @@ void multibus_put_mbyte(uint16 addr, uint8 val) // sim_printf("multibus_put_mbyte: Done XACK=%dX\n", XACK); } +/* put a word to memory */ + +void multibus_put_mword(uint16 addr, uint16 val) +{ + multibus_put_mbyte(addr, val & 0xff); + multibus_put_mbyte(addr+1, val >> 8); +} + /* end of multibus.c */ diff --git a/Intel-Systems/common/zx200a.c b/Intel-Systems/common/zx200a.c index ae5994a6..f75d9885 100644 --- a/Intel-Systems/common/zx200a.c +++ b/Intel-Systems/common/zx200a.c @@ -131,80 +131,138 @@ #include "system_defs.h" /* system header in system dir */ +#define DEBUG 1 + #define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ #define UNIT_WPMODE (1 << UNIT_V_WPMODE) #define FDD_NUM 4 -#define WP 0x40 /* Write protect */ -#define RDY 0x20 /* Ready */ -#define T0 0x10 /* Track 0 */ -#define TS 0x08 /* Two sided */ +//disk controoler operations +#define DNOP 0x00 //disk no operation +#define DSEEK 0x01 //disk seek +#define DFMT 0x02 //disk format +#define DHOME 0x03 //disk home +#define DREAD 0x04 //disk read +#define DVCRC 0x05 //disk verify CRC +#define DWRITE 0x06 //disk write -/* internal function prototypes */ +//status +#define RDY0 0x01 //FDD 0 ready +#define RDY1 0x02 //FDD 1 ready +#define FDCINT 0x04 //FDC interrupt flag +#define FDCPRE 0x08 //FDC board present +#define FDCDD 0x10 //fdc is DD +#define RDY2 0x20 //FDD 2 ready +#define RDY3 0x40 //FDD 3 ready -t_stat zx200a_svc (UNIT *uptr); -uint8 zx200a0(t_bool io, uint8 data, uint8 devnum); -uint8 zx200a1(t_bool io, uint8 data, uint8 devnum); -uint8 zx200a2(t_bool io, uint8 data, uint8 devnum); -uint8 zx200a3(t_bool io, uint8 data, uint8 devnum); -uint8 zx200a7(t_bool io, uint8 data, uint8 devnum); -t_stat zx200a_attach (UNIT *uptr, CONST char *cptr); -t_stat zx200a_reset(DEVICE *dptr, uint16 base, uint8 devnum); -void zx200a_reset1(void); +//result type +#define RERR 0x00 //FDC returned error +#define ROK 0x02 //FDC returned ok + +// If result type is RERR then rbyte is +#define RB0DR 0x01 //deleted record +#define RB0CRC 0x02 //CRC error +#define RB0SEK 0x04 //seek error +#define RB0ADR 0x08 //address error +#define RB0OU 0x10 //data overrun/underrun +#define RB0WP 0x20 //write protect +#define RB0WE 0x40 //write error +#define RB0NR 0x80 //not ready + +// If result type is ROK then rbyte is +#define RB1RD2 0x10 //drive 2 ready +#define RB1RD3 0x20 //drive 3 ready +#define RB1RD0 0x40 //drive 0 ready +#define RB1RD1 0x80 //drive 1 ready /* external function prototypes */ -extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16 port, uint8 devnum); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +extern uint8 multibus_get_mbyte(uint16 addr); +extern uint16 multibus_get_mword(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern uint8 multibus_put_mword(uint16 addr, uint16 val); + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* internal function prototypes */ + +t_stat zx200a_reset(DEVICE *dptr, uint16 base); +void zx200a_reset1(uint8); +t_stat zx200a_attach (UNIT *uptr, CONST char *cptr); +t_stat zx200a_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +uint8 zx200a0(t_bool io, uint8 data); +uint8 zx200a1(t_bool io, uint8 data); +uint8 zx200a2(t_bool io, uint8 data); +uint8 zx200a3(t_bool io, uint8 data); +uint8 zx200a7(t_bool io, uint8 data); +void zx200a_diskio(uint8 fdcnum); /* globals */ -uint16 iopb; -uint8 syssta = 0, rsttyp = 0, rstbyt1 = 0, rstbyt2 = 0, cmd = 0; +int32 zx200a_fdcnum = 0; //actual number of SBC-202 instances + 1 -uint8 *zx200a_buf[FDD_NUM] = { /* FDD buffer pointers */ - NULL, - NULL, - NULL, - NULL -}; +typedef struct { //FDD definition + uint8 *buf; + int t0; + int rdy; + uint8 maxsec; + uint8 maxcyl; + } FDDDEF; -int32 fddst[FDD_NUM] = { // fdd status - 0, // status of FDD 0 - 0, // status of FDD 1 - 0, // status of FDD 2 - 0 // status of FDD 3 -}; +typedef struct { //FDC definition + uint16 baseport; //FDC base port + uint16 iopb; //FDC IOPB + uint8 stat; //FDC status + uint8 rtype; //FDC result type + uint8 rbyte0; //FDC result byte for type 00 + uint8 rbyte1; //FDC result byte for type 10 + uint8 intff; //fdc interrupt FF + FDDDEF fdd[FDD_NUM]; //indexed by the FDD number + } FDCDEF; -int32 maxsec[FDD_NUM] = { // last sector - 0, // status of FDD 0 - 0, // status of FDD 1 - 0, // status of FDD 2 - 0 // status of FDD 3 -}; - -int8 maxcyl[FDD_NUM] = { - 0, // last cylinder + 1 of FDD 0 - 0, // last cylinder + 1 of FDD 1 - 0, // last cylinder + 1 of FDD 2 - 0 // last cylinder + 1 of FDD 3 -}; +FDCDEF zx200a[4]; //indexed by the isbc-202 instance number UNIT zx200a_unit[] = { - { UDATA (&zx200a_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, - { UDATA (&zx200a_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, - { UDATA (&zx200a_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, - { UDATA (&zx200a_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 } + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }, + { UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 } }; REG zx200a_reg[] = { - { HRDATA (SUBSYSSTA, zx200a_unit[0].u3, 8) }, /* subsytem status */ - { HRDATA (RSTTYP, zx200a_unit[0].u4, 8) }, /* result type */ - { HRDATA (RSTBYT0, zx200a_unit[0].u5, 8) }, /* result byte 0 RSTTYP = 0*/ - { HRDATA (RSTBYT1, zx200a_unit[0].u6, 8) }, /* result byte 1 RSTTYP = 10*/ + { HRDATA (STAT0, zx200a[0].stat, 8) }, /* zx200a 0 status */ + { HRDATA (RTYP0, zx200a[0].rtype, 8) }, /* zx200a 0 result type */ + { HRDATA (RBYT0A, zx200a[0].rbyte0, 8) }, /* zx200a 0 result byte 0 */ + { HRDATA (RBYT0B, zx200a[0].rbyte1, 8) }, /* zx200a 0 result byte 1 */ + { HRDATA (INTFF0, zx200a[0].intff, 8) }, /* zx200a 0 interrupt f/f */ + { HRDATA (STAT1, zx200a[1].stat, 8) }, /* zx200a 1 status */ + { HRDATA (RTYP1, zx200a[1].rtype, 8) }, /* zx200a 1 result type */ + { HRDATA (RBYT1A, zx200a[1].rbyte0, 8) }, /* zx200a 1 result byte 0 */ + { HRDATA (RBYT1B, zx200a[1].rbyte1, 8) }, /* zx200a 1 result byte 1 */ + { HRDATA (INTFF1, zx200a[1].intff, 8) }, /* zx200a 1 interrupt f/f */ + { HRDATA (STAT2, zx200a[2].stat, 8) }, /* zx200a 2 status */ + { HRDATA (RTYP2, zx200a[2].rtype, 8) }, /* zx200a 2 result type */ + { HRDATA (RBYT2A, zx200a[2].rbyte0, 8) }, /* zx200a 2 result byte 0 */ + { HRDATA (RBYT2B, zx200a[0].rbyte1, 8) }, /* zx200a 2 result byte 1 */ + { HRDATA (INTFF2, zx200a[2].intff, 8) }, /* zx200a 2 interrupt f/f */ + { HRDATA (STAT3, zx200a[3].stat, 8) }, /* zx200a 3 status */ + { HRDATA (RTYP3, zx200a[3].rtype, 8) }, /* zx200a 3 result type */ + { HRDATA (RBYT3A, zx200a[3].rbyte0, 8) }, /* zx200a 3 result byte 0 */ + { HRDATA (RBYT3B, zx200a[3].rbyte1, 8) }, /* zx200a 3 result byte 1 */ + { HRDATA (INTFF3, zx200a[0].intff, 8) }, /* zx200a 3 interrupt f/f */ { NULL } }; +MTAB zx200a_mod[] = { + { UNIT_WPMODE, 0, "RW", "RW", &zx200a_set_mode }, + { UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &zx200a_set_mode }, + { 0 } +}; + DEBTAB zx200a_debug[] = { { "ALL", DEBUG_all }, { "FLOW", DEBUG_flow }, @@ -234,12 +292,12 @@ DEVICE zx200a_dev = { // &zx200a_reset, //reset NULL, //reset NULL, //boot - NULL, //attach + &zx200a_attach, //attach NULL, //detach NULL, //ctxt - 0, //flags - 0, //dctrl - zx200a_debug, //debflags + DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags + DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl + zx200a_debug, //debflags NULL, //msize NULL //lname }; @@ -250,79 +308,68 @@ DEVICE zx200a_dev = { /* Service routines to handle simulator functions */ -/* service routine - actually does the simulated disk I/O */ +/* Reset routine */ -t_stat zx200a_svc (UNIT *uptr) +t_stat zx200a_reset(DEVICE *dptr, uint16 base) { - sim_activate(&zx200a_unit[uptr->u6], zx200a_unit[uptr->u6].wait); + sim_printf("Initializing ZX-200A FDC Board\n"); + if (ZX200A_NUM) { + sim_printf(" ZX200A-%d: Hardware Reset\n", zx200a_fdcnum); + sim_printf(" ZX200A-%d: Registered at %04X\n", zx200a_fdcnum, base); + zx200a[zx200a_fdcnum].baseport = base; + reg_dev(zx200a0, base, zx200a_fdcnum); + reg_dev(zx200a1, base + 1, zx200a_fdcnum); + reg_dev(zx200a2, base + 2, zx200a_fdcnum); + reg_dev(zx200a3, base + 3, zx200a_fdcnum); + reg_dev(zx200a7, base + 7, zx200a_fdcnum); + zx200a_unit[zx200a_fdcnum].u3 = 0x00; /* ipc reset */ + zx200a_reset1(zx200a_fdcnum); + zx200a_fdcnum++; + } else + sim_printf(" No ZX-200A installed\n"); return SCPE_OK; } -/* zx200a control port functions */ - -uint8 zx200a0(t_bool io, uint8 data, uint8 devnum) +void zx200a_reset1(uint8 fdcnum) { - int val; + int32 i; + UNIT *uptr; - if (io == 0) { /* read operation */ - val = zx200a_unit[0].u3; - sim_printf(" zx200a0: read data=%02X devnum=%02X val=%02X\n", data, devnum, val); - return val; - } else { /* write control port */ - sim_printf(" zx200a0: write data=%02X port=%02X\n", data, devnum); - } -} - -uint8 zx200a1(t_bool io, uint8 data, uint8 devnum) -{ - int val; - - if (io == 0) { /* read operation */ - val = zx200a_unit[0].u4; - sim_printf(" zx200a1: read data=%02X devnum=%02X val=%02X\n", data, devnum, val); - return val; - } else { /* write control port */ - iopb = data; - sim_printf(" zx200a1: write data=%02X port=%02X iopb=%04X\n", data, devnum, iopb); - } -} - -uint8 zx200a2(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read operation */ - sim_printf(" zx200a2: read data=%02X devnum=%02X\n", data, devnum); - return 0x00; - } else { /* write control port */ - iopb |= (data << 8); - sim_printf(" zx200a2: write data=%02X port=%02X iopb=%04X\n", data, devnum, iopb); - } -} - -uint8 zx200a3(t_bool io, uint8 data, uint8 devnum) -{ - int val; - - if (io == 0) { /* read operation */ - if (zx200a_unit[0].u4) - val = zx200a_unit[0].u5; - else - val = zx200a_unit[0].u6; - sim_printf(" zx200a3: read data=%02X devnum=%02X val=%02X\n", data, devnum, val); - return val; - } else { /* write control port */ - sim_printf(" zx200a3: write data=%02X port=%02X\n", data, devnum); - } -} - -/* reset ZX-200A */ -uint8 zx200a7(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read operation */ - sim_printf(" zx200a7: read data=%02X devnum=%02X\n", data, devnum); - return 0x00; - } else { /* write control port */ - sim_printf(" zx200a7: write data=%02X port=%02X\n", data, devnum); - zx200a_reset(NULL, ZX200A_BASE_DD, 0); //for now + sim_printf(" ZX-200A-%d: Initializing\n", fdcnum); + zx200a[fdcnum].stat = 0; //clear status + for (i = 0; i < FDD_NUM; i++) { /* handle all units */ + uptr = zx200a_dev.units + i; + zx200a[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status + zx200a[fdcnum].rtype = ROK; + if (uptr->capac == 0) { /* if not configured */ + uptr->capac = 0; /* initialize unit */ + uptr->u4 = 0; + uptr->u5 = fdcnum; //fdc device number + uptr->u6 = i; /* unit number - only set here! */ + uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */ + sim_printf(" ZX-200A%d: Configured, Status=%02X Not attached\n", i, zx200a[fdcnum].stat); + } else { + switch(i){ + case 0: + zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready + zx200a[fdcnum].rbyte1 |= RB1RD0; + break; + case 1: + zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready + zx200a[fdcnum].rbyte1 |= RB1RD1; + break; + case 2: + zx200a[fdcnum].stat |= RDY2; //set FDD 2 ready + zx200a[fdcnum].rbyte1 |= RB1RD2; + break; + case 3: + zx200a[fdcnum].stat |= RDY3; //set FDD 3 ready + zx200a[fdcnum].rbyte1 |= RB1RD3; + break; + } + sim_printf(" ZX-200A%d: Configured, Status=%02X Attached to %s\n", + i, zx200a[fdcnum].stat, uptr->filename); + } } } @@ -334,12 +381,15 @@ t_stat zx200a_attach (UNIT *uptr, CONST char *cptr) FILE *fp; int32 i, c = 0; long flen; + uint8 fdcnum, fddnum; - sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_attach: Entered with uptr=%08X cptr=%s\n", uptr, cptr); + sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_attach: Entered with cptr=%s\n", cptr); if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { sim_printf(" zx200a_attach: Attach error\n"); return r; } + fdcnum = uptr->u5; + fddnum = uptr->u6; fp = fopen(uptr->filename, "rb"); if (fp == NULL) { sim_printf(" Unable to open disk image file %s\n", uptr->filename); @@ -349,9 +399,9 @@ t_stat zx200a_attach (UNIT *uptr, CONST char *cptr) fseek(fp, 0, SEEK_END); /* size disk image */ flen = ftell(fp); fseek(fp, 0, SEEK_SET); - if (zx200a_buf[uptr->u6] == NULL) { /* no buffer allocated */ - zx200a_buf[uptr->u6] = (uint8 *)malloc(flen); - if (zx200a_buf[uptr->u6] == NULL) { + if (zx200a[fdcnum].fdd[fddnum].buf == NULL) { /* no buffer allocated */ + zx200a[fdcnum].fdd[fddnum].buf = (uint8 *)malloc(flen); + if (zx200a[fdcnum].fdd[fddnum].buf == NULL) { sim_printf(" zx200a_attach: Malloc error\n"); return SCPE_MEM; } @@ -360,85 +410,343 @@ t_stat zx200a_attach (UNIT *uptr, CONST char *cptr) i = 0; c = fgetc(fp); // copy disk image into buffer while (c != EOF) { - *(zx200a_buf[uptr->u6] + i++) = c & 0xFF; + *(zx200a[fdcnum].fdd[fddnum].buf + i++) = c & 0xFF; c = fgetc(fp); } fclose(fp); - switch(uptr->u6){ - case 0: - fddst[uptr->u6] |= 0x01; /* set unit ready */ - break; - case 1: - fddst[uptr->u6] |= 0x02; /* set unit ready */ - break; - case 2: - fddst[uptr->u6] |= 0x20; /* set unit ready */ - break; - case 3: - fddst[uptr->u6] |= 0x40; /* set unit ready */ - break; - } + switch(fddnum){ + case 0: + zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready + zx200a[fdcnum].rtype = ROK; + zx200a[fdcnum].rbyte1 |= RB1RD0; + break; + case 1: + zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready + zx200a[fdcnum].rtype = ROK; + zx200a[fdcnum].rbyte1 |= RB1RD1; + break; + case 2: + zx200a[fdcnum].stat |= RDY2; //set FDD 2 ready + zx200a[fdcnum].rtype = ROK; + zx200a[fdcnum].rbyte1 |= RB1RD2; + break; + case 3: + zx200a[fdcnum].stat |= RDY3; //set FDD 3 ready + zx200a[fdcnum].rtype = ROK; + zx200a[fdcnum].rbyte1 |= RB1RD3; + break; + } if (flen == 256256) { /* 8" 256K SSSD */ - maxcyl[uptr->u6] = 77; - maxsec[uptr->u6] = 26; + zx200a[fdcnum].fdd[fddnum].maxcyl = 77; + zx200a[fdcnum].fdd[fddnum].maxsec = 26; } else if (flen == 512512) { /* 8" 512K SSDD */ - maxcyl[uptr->u6] = 77; - maxsec[uptr->u6] = 52; - } - sim_printf(" Drive-%d: %d bytes of disk image %s loaded, fddst=%02X\n", - uptr->u6, i, uptr->filename, fddst[uptr->u6]); + zx200a[fdcnum].fdd[fddnum].maxcyl = 77; + zx200a[fdcnum].fdd[fddnum].maxsec = 52; + } else + sim_printf(" ZX-200A-%d: Not a known ISIS-II disk image\n", fdcnum); + sim_printf(" ZX-200A-%d: Configured %d bytes, Attached to %s\n", + fdcnum, uptr->capac, uptr->filename); } - sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_attach: Done\n"); - return SCPE_OK; -} -/* Reset routine */ - -t_stat zx200a_reset(DEVICE *dptr, uint16 base, uint8 devnum) -{ - reg_dev(zx200a0, base, devnum); - reg_dev(zx200a1, base + 1, devnum); - reg_dev(zx200a2, base + 2, devnum); - reg_dev(zx200a3, base + 3, devnum); - reg_dev(zx200a7, base + 7, devnum); - zx200a_unit[devnum].u3 = 0x00; /* ipc reset */ - sim_printf(" zx200a-%d: Reset\n", devnum); - sim_printf(" zx200a-%d: Registered at %04X\n", devnum, base); - if ((zx200a_dev.flags & DEV_DIS) == 0) - zx200a_reset1(); + sim_debug (DEBUG_flow, &zx200a_dev, " ZX-200A_attach: Done\n"); return SCPE_OK; } -void zx200a_reset1(void) +/* zx200a set mode = Write protect */ + +t_stat zx200a_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { - int32 i; +// sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_set_mode: Entered with val=%08XH uptr->flags=%08X\n", +// val, uptr->flags); + if (val & UNIT_WPMODE) { /* write protect */ + uptr->flags |= val; + } else { /* read write */ + uptr->flags &= ~val; + } +// sim_debug (DEBUG_flow, &zx200a_dev, " zx200a_set_mode: Done\n"); + return SCPE_OK; +} + +uint8 zx200_get_dn(void) +{ + int i; + + for (i=0; i= zx200a[i].baseport && port <= zx200a[i].baseport + 7) + return i; + sim_printf("zx200_get_dn: port %04X not in zx200 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +/* zx200a control port functions */ + +uint8 zx200a0(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = zx200_get_dn()) != 0xFF) { + if (io == 0) { /* read ststus*/ +// sim_printf("\n ZX200A-%d: returned status=%02X", fdcnum, zx200a[fdcnum].stat); + return zx200a[fdcnum].stat; + } + } + return 0; +} + +uint8 zx200a1(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = zx200_get_dn()) != 0xFF) { + if (io == 0) { /* read operation */ + zx200a[fdcnum].intff = 0; //clear interrupt FF + zx200a[fdcnum].stat &= ~FDCINT; + if (DEBUG) + sim_printf("\n ZX-200A1-%d: returned rtype=%02X intff=%02X status=%02X", + fdcnum, zx200a[fdcnum].rtype, zx200a[fdcnum].intff, zx200a[fdcnum].stat); + return zx200a[fdcnum].rtype; + } else { /* write control port */ + zx200a[fdcnum].iopb = data; + if (DEBUG) + sim_printf("\n ZX-200A1-%d: IOPB low=%02X", fdcnum, data); + } + } + return 0; +} + +uint8 zx200a2(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = zx200_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + zx200a[fdcnum].iopb |= (data << 8); + if (DEBUG) + sim_printf("\n zx200a-%d: IOPB=%04X", fdcnum, zx200a[fdcnum].iopb); + zx200a_diskio(fdcnum); + if (zx200a[fdcnum].intff) + zx200a[fdcnum].stat |= FDCINT; + } + } + return 0; +} + +uint8 zx200a3(t_bool io, uint8 data) +{ + uint8 fdcnum, rslt; + + if ((fdcnum = zx200_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + switch(zx200a[fdcnum].rtype) { + case 0x00: + rslt = zx200a[fdcnum].rbyte0; + break; + case 0x02: + rslt = zx200a[fdcnum].rbyte1; + break; + } + if (DEBUG) + sim_printf("\n zx200a-%d: returned result byte=%02X", fdcnum, rslt); + return rslt; + } else { /* write data port */ + ; //stop diskette operation + } + } + return 0; +} + +/* reset ZX-200A */ +uint8 zx200a7(t_bool io, uint8 data) +{ + uint8 fdcnum; + + if ((fdcnum = zx200_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + zx200a_reset1(fdcnum); + } + } + return 0; +} + +// perform the actual disk I/O operation + +void zx200a_diskio(uint8 fdcnum) +{ + uint8 cw, di, nr, ta, sa, data, nrptr, c; + uint16 ba; + uint32 dskoff; + uint8 fddnum, fmtb; + uint32 i; UNIT *uptr; - static int flag = 1; - - if (flag) sim_printf("ZX-200A: Initializing\n"); - for (i = 0; i < FDD_NUM; i++) { /* handle all units */ - uptr = zx200a_dev.units + i; - if (uptr->capac == 0) { /* if not configured */ -// sim_printf(" ZX-200A%d: Not configured\n", i); -// if (flag) { -// sim_printf(" ALL: \"set ZX-200A en\"\n"); -// sim_printf(" EPROM: \"att ZX-200A0 \"\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 (&zx200a_unit[uptr->u6], zx200a_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); - } + FILE *fp; + //parse the IOPB + cw = multibus_get_mbyte(zx200a[fdcnum].iopb); + di = multibus_get_mbyte(zx200a[fdcnum].iopb + 1); + nr = multibus_get_mbyte(zx200a[fdcnum].iopb + 2); + ta = multibus_get_mbyte(zx200a[fdcnum].iopb + 3); + sa = multibus_get_mbyte(zx200a[fdcnum].iopb + 4); + ba = multibus_get_mword(zx200a[fdcnum].iopb + 5); + fddnum = (di & 0x30) >> 4; + uptr = zx200a_dev.units + fddnum; + if (DEBUG) { + sim_printf("\n zx200a-%d: zx200a_diskio IOPB=%04X FDD=%02X STAT=%02X", + fdcnum, zx200a[fdcnum].iopb, fddnum, zx200a[fdcnum].stat); + sim_printf("\n zx200a-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X", + fdcnum, cw, di, nr, ta, sa, ba); + sim_printf("\n zx200a-%d: maxsec=%02X maxcyl=%02X", + fdcnum, zx200a[fdcnum].fdd[fddnum].maxsec, zx200a[fdcnum].fdd[fddnum].maxcyl); + } + //check for not ready + switch(fddnum) { + case 0: + if ((zx200a[fdcnum].stat & RDY0) == 0) { + zx200a[fdcnum].rtype = RERR; + zx200a[fdcnum].rbyte0 = RB0NR; + zx200a[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n zx200a-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + case 1: + if ((zx200a[fdcnum].stat & RDY1) == 0) { + zx200a[fdcnum].rtype = RERR; + zx200a[fdcnum].rbyte0 = RB0NR; + zx200a[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n zx200a-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + case 2: + if ((zx200a[fdcnum].stat & RDY2) == 0) { + zx200a[fdcnum].rtype = RERR; + zx200a[fdcnum].rbyte0 = RB0NR; + zx200a[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n zx200a-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + case 3: + if ((zx200a[fdcnum].stat & RDY3) == 0) { + zx200a[fdcnum].rtype = RERR; + zx200a[fdcnum].rbyte0 = RB0NR; + zx200a[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n zx200a-%d: Ready error on drive %d", fdcnum, fddnum); + return; + } + break; + } + //check for address error + if ( + (sa > zx200a[fdcnum].fdd[fddnum].maxsec) || + ((sa + nr) > (zx200a[fdcnum].fdd[fddnum].maxsec + 1)) || + (sa == 0) || + (ta > zx200a[fdcnum].fdd[fddnum].maxcyl) + ) { + if (DEBUG) + sim_printf("\n zx200a-%d: maxsec=%02X maxcyl=%02X", + fdcnum, zx200a[fdcnum].fdd[fddnum].maxsec, zx200a[fdcnum].fdd[fddnum].maxcyl); + zx200a[fdcnum].rtype = RERR; + zx200a[fdcnum].rbyte0 = RB0ADR; + zx200a[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n zx200a-%d: Address error on drive %d", fdcnum, fddnum); + return; + } + switch (di & 0x07) { + case DNOP: + case DSEEK: + case DHOME: + case DVCRC: + zx200a[fdcnum].rtype = ROK; + zx200a[fdcnum].intff = 1; //set interrupt FF + break; + case DFMT: + //check for WP + if(uptr->flags & UNIT_WPMODE) { + zx200a[fdcnum].rtype = RERR; + zx200a[fdcnum].rbyte0 = RB0WP; + zx200a[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n zx200a-%d: Write protect error 1 on drive %d", fdcnum, fddnum); + return; + } + fmtb = multibus_get_mbyte(ba); //get the format byte + //calculate offset into disk image + dskoff = ((ta * (uint32)(zx200a[fdcnum].fdd[fddnum].maxsec)) + (sa - 1)) * 128; + for(i=0; i<=((uint32)(zx200a[fdcnum].fdd[fddnum].maxsec) * 128); i++) { + *(zx200a[fdcnum].fdd[fddnum].buf + (dskoff + i)) = fmtb; + } + //*** quick fix. Needs more thought! + fp = fopen(uptr->filename, "wb"); // write out modified image + for (i=0; icapac; i++) { + c = *(zx200a[fdcnum].fdd[fddnum].buf + i); + fputc(c, fp); + } + fclose(fp); + zx200a[fdcnum].rtype = ROK; + zx200a[fdcnum].intff = 1; //set interrupt FF + break; + case DREAD: + nrptr = 0; + while(nrptr < nr) { + //calculate offset into disk image + dskoff = ((ta * zx200a[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128; +// sim_printf("\n zx200a-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X", +// fdcnum, cw, di, nr, ta, sa, ba, dskoff); + for (i=0; i<128; i++) { //copy sector from image to RAM + data = *(zx200a[fdcnum].fdd[fddnum].buf + (dskoff + i)); + multibus_put_mbyte(ba + i, data); + } + sa++; + ba+=0x80; + nrptr++; + } + zx200a[fdcnum].rtype = ROK; + zx200a[fdcnum].intff = 1; //set interrupt FF + break; + case DWRITE: + //check for WP + if(uptr->flags & UNIT_WPMODE) { + zx200a[fdcnum].rtype = RERR; + zx200a[fdcnum].rbyte0 = RB0WP; + zx200a[fdcnum].intff = 1; //set interrupt FF + sim_printf("\n zx200a-%d: Write protect error 2 on drive %d", fdcnum, fddnum); + return; + } + nrptr = 0; + while(nrptr < nr) { + //calculate offset into disk image + dskoff = ((ta * zx200a[fdcnum].fdd[fddnum].maxsec) + (sa - 1)) * 128; + // sim_printf("\n zx200a-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X dskoff=%06X", + // fdcnum, cw, di, nr, ta, sa, ba, dskoff); + for (i=0; i<128; i++) { //copy sector from image to RAM + data = multibus_get_mbyte(ba + i); + *(zx200a[fdcnum].fdd[fddnum].buf + (dskoff + i)) = data; + } + sa++; + ba+=0x80; + nrptr++; + } + //*** quick fix. Needs more thought! + fp = fopen(uptr->filename, "wb"); // write out modified image + for (i=0; icapac; i++) { + c = *(zx200a[fdcnum].fdd[fddnum].buf + i); + fputc(c, fp); + } + fclose(fp); + zx200a[fdcnum].rtype = ROK; + zx200a[fdcnum].intff = 1; //set interrupt FF + break; + default: + sim_printf("\n zx200a-%d: zx200a_diskio bad di=%02X", fdcnum, di & 0x07); + break; } - cmd = 0; /* clear command */ - flag = 0; } + /* end of zx-200a.c */ diff --git a/Intel-Systems/isys8010/isbc80-10.c b/Intel-Systems/isys8010/isbc8010.c similarity index 71% rename from Intel-Systems/isys8010/isbc80-10.c rename to Intel-Systems/isys8010/isbc8010.c index 1c6f085c..189c2b6f 100644 --- a/Intel-Systems/isys8010/isbc80-10.c +++ b/Intel-Systems/isys8010/isbc8010.c @@ -44,32 +44,38 @@ void put_mbyte(uint16 addr, uint8 val); void put_mword(uint16 addr, uint16 val); t_stat SBC_reset (DEVICE *dptr); +/* external globals */ + +extern uint8 i8255_C[4]; //port C byte I/O + /* external function prototypes */ -extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ extern uint8 multibus_get_mbyte(uint16 addr); extern void multibus_put_mbyte(uint16 addr, uint8 val); extern uint8 EPROM_get_mbyte(uint16 addr); extern uint8 RAM_get_mbyte(uint16 addr); extern void RAM_put_mbyte(uint16 addr, uint8 val); -extern UNIT i8255_unit[]; +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +extern int32 i8251_devnum; +extern t_stat i8251_reset (DEVICE *dptr, uint16 base); +extern int32 i8255_devnum; +extern t_stat i8255_reset (DEVICE *dptr, uint16 base); extern UNIT EPROM_unit; -extern UNIT RAM_unit; -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 UNIT RAM_unit; extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); /* SBC reset routine */ t_stat SBC_reset (DEVICE *dptr) { - sim_printf("Initializing iSBC-80/10:\n"); + sim_printf("Initializing iSBC-80/10 SBC\n Onboard Devices:\n"); i8080_reset (NULL); - i8255_reset (NULL, I8255_BASE_0, 0); - i8255_reset (NULL, I8255_BASE_1, 1); - i8251_reset (NULL, I8251_BASE, 0); + i8251_devnum = 0; + i8251_reset (NULL, I8251_BASE); + i8255_devnum = 0; + i8255_reset (NULL, I8255_BASE_0); + i8255_reset (NULL, I8255_BASE_1); EPROM_reset (NULL, ROM_SIZE); RAM_reset (NULL, RAM_BASE, RAM_SIZE); return SCPE_OK; @@ -80,15 +86,15 @@ t_stat SBC_reset (DEVICE *dptr) uint8 get_mbyte(uint16 addr) { /* if local EPROM handle it */ - 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 ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { + return EPROM_get_mbyte(addr); + } } /* if local RAM handle it */ - if (i8255_unit[0].u5 & 0x02) { - if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { - return RAM_get_mbyte(addr); - } + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { + return RAM_get_mbyte(addr); + } } /* otherwise, try the multibus */ return multibus_get_mbyte(addr); } @@ -109,13 +115,17 @@ uint16 get_mword(uint16 addr) void put_mbyte(uint16 addr, uint8 val) { /* if local EPROM handle it */ - 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); + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { + sim_printf("Write to R/O memory address %04X - ignored\n", addr); return; + } } /* if local RAM handle it */ - if ((i8255_unit[0].u5 & 0x02) && (addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { - RAM_put_mbyte(addr, val); + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { + RAM_put_mbyte(addr, val); return; + } } /* otherwise, try the multibus */ multibus_put_mbyte(addr, val); } diff --git a/Intel-Systems/isys8010/isys8010_sys.c b/Intel-Systems/isys8010/isys8010_sys.c index 69d7e8b7..703762f5 100644 --- a/Intel-Systems/isys8010/isys8010_sys.c +++ b/Intel-Systems/isys8010/isys8010_sys.c @@ -36,7 +36,8 @@ extern DEVICE i8255_dev; extern DEVICE EPROM_dev; extern DEVICE RAM_dev; extern DEVICE multibus_dev; -extern DEVICE isbc208_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; extern DEVICE isbc064_dev; /* SCP data structures @@ -62,7 +63,8 @@ DEVICE *sim_devices[] = { &i8255_dev, &multibus_dev, &isbc064_dev, - &isbc208_dev, + &isbc201_dev, + &isbc202_dev, NULL }; diff --git a/Intel-Systems/isys8010/system_defs.h b/Intel-Systems/isys8010/system_defs.h index adb9c911..b70d65f5 100644 --- a/Intel-Systems/isys8010/system_defs.h +++ b/Intel-Systems/isys8010/system_defs.h @@ -28,38 +28,58 @@ #include #include -//#include "isys8010_cfg.h" /* Intel System 80/10 configuration */ #include "sim_defs.h" /* simulator defns */ +#define SET_XACK(VAL) (xack = VAL) + +//chip definitions for the iSBC-80/10 +/* set the base I/O address and device count for the 8251s */ +#define I8251_BASE 0xEC +#define I8251_NUM 1 + /* set the base I/O address 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 +#define ROM_DISABLE 1 /* set the base and size for the RAM on the iSBC 80/10 */ #define RAM_BASE 0x3C00 #define RAM_SIZE 0x0400 +#define RAM_DISABLE 1 /* set INTR for CPU on the iSBC 80/10 */ #define INTR INT_1 +//board definitions for the multibus +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x78 +#define SBC201_INT INT_1 +#define SBC201_NUM 0 + +/* set the base I/O address for the iSBC 202 */ +#define SBC202_BASE 0x78 +#define SBC202_INT INT_1 +#define SBC202_NUM 1 + /* set the base I/O address for the iSBC 208 */ #define SBC208_BASE 0x40 - -/* configure interrupt request line */ #define SBC208_INT INT_1 +#define SBC208_NUM 0 + +/* set the base for the zx-200a disk controller */ +#define ZX200A_BASE_DD 0x78 +#define ZX200A_BASE_SD 0x88 +#define ZX200A_NUM 0 /* set the base and size for the iSBC 064 */ #define SBC064_BASE 0x0000 #define SBC064_SIZE 0x10000 +#define SBC064_NUM 1 /* multibus interrupt definitions */ diff --git a/Intel-Systems/isys8020/isbc80-20.c b/Intel-Systems/isys8020/isbc8020.c similarity index 71% rename from Intel-Systems/isys8020/isbc80-20.c rename to Intel-Systems/isys8020/isbc8020.c index 4848a962..72372305 100644 --- a/Intel-Systems/isys8020/isbc80-20.c +++ b/Intel-Systems/isys8020/isbc8020.c @@ -39,22 +39,27 @@ void put_mbyte(uint16 addr, uint8 val); void put_mword(uint16 addr, uint16 val); t_stat SBC_reset (DEVICE *dptr); +/* external globals */ + +extern uint8 i8255_C[4]; //port C byte I/O + /* external function prototypes */ -extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ extern uint8 multibus_get_mbyte(uint16 addr); extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +extern int32 i8251_devnum; +extern t_stat i8251_reset (DEVICE *dptr, uint16 base); +extern int32 i8255_devnum; +extern t_stat i8255_reset (DEVICE *dptr, uint16 base); +extern int32 i8259_devnum; +extern t_stat i8259_reset (DEVICE *dptr, uint16 base); extern uint8 EPROM_get_mbyte(uint16 addr); +extern UNIT EPROM_unit; +extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); 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, 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 @@ -64,10 +69,10 @@ t_stat SBC_reset (DEVICE *dptr) { sim_printf("Initializing iSBC-80/20\n"); i8080_reset(NULL); - 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); + i8251_reset(NULL, I8251_BASE); + i8255_reset(NULL, I8255_BASE_0); + i8255_reset(NULL, I8255_BASE_1); + i8259_reset(NULL, I8259_BASE); EPROM_reset(NULL, ROM_SIZE); RAM_reset(NULL, RAM_BASE, RAM_SIZE); return SCPE_OK; @@ -78,13 +83,13 @@ t_stat SBC_reset (DEVICE *dptr) uint8 get_mbyte(uint16 addr) { /* if local EPROM handle it */ - if ((i8255_unit.u5 & 0x01) && /* EPROM enabled? */ - (addr >= EPROM_unit.u3) && (addr < (EPROM_unit.u3 + EPROM_unit.capac))) { - return EPROM_get_mbyte(addr); + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((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) && /* local RAM enabled? */ - (addr >= RAM_unit.u3) && (addr < (RAM_unit.u3 + RAM_unit.capac))) { - return RAM_get_mbyte(addr); + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((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); } @@ -105,15 +110,17 @@ uint16 get_mword(uint16 addr) void put_mbyte(uint16 addr, uint8 val) { /* if local EPROM handle it */ - if ((i8255_unit.u5 & 0x01) && /* EPROM enabled? */ - (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 ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((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) && /* local RAM enabled? */ - (addr >= RAM_unit.u3) && (addr <= (RAM_unit.u3 + RAM_unit.capac))) { - RAM_put_mbyte(addr, val); - return; + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((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); } diff --git a/Intel-Systems/isys8020/isys8020_sys.c b/Intel-Systems/isys8020/isys8020_sys.c index f7209805..a539d225 100644 --- a/Intel-Systems/isys8020/isys8020_sys.c +++ b/Intel-Systems/isys8020/isys8020_sys.c @@ -37,7 +37,8 @@ extern DEVICE i8255_dev; extern DEVICE EPROM_dev; extern DEVICE RAM_dev; extern DEVICE multibus_dev; -extern DEVICE isbc208_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; extern DEVICE isbc064_dev; /* SCP data structures @@ -64,7 +65,8 @@ DEVICE *sim_devices[] = { &i8255_dev, &multibus_dev, &isbc064_dev, - &isbc208_dev, + &isbc201_dev, + &isbc202_dev, NULL }; diff --git a/Intel-Systems/isys8020/system_defs.h b/Intel-Systems/isys8020/system_defs.h index d432a214..ce8734d1 100644 --- a/Intel-Systems/isys8020/system_defs.h +++ b/Intel-Systems/isys8020/system_defs.h @@ -30,39 +30,60 @@ #include #include "sim_defs.h" /* simulator defns */ -/* set the base I/O address for the 8259 */ -#define I8259_BASE 0xD8 -#define I8259_NUM 1 +#define SET_XACK(VAL) (xack = VAL) + +//chip definitions for the iSBC-80/20 +/* set the base I/O address for the 8251 */ +#define I8251_BASE 0xEC +#define I8251_NUM 1 /* set the base I/O address for the 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 I/O address for the 8259 */ +#define I8259_BASE 0xD8 +#define I8259_NUM 1 /* set the base and size for the EPROM on the iSBC 80/20 */ #define ROM_BASE 0x0000 #define ROM_SIZE 0x1000 +#define ROM_DISABLE 1 /* set the base and size for the RAM on the iSBC 80/20 */ #define RAM_BASE 0x3C00 #define RAM_SIZE 0x0400 +#define RAM_DISABLE 1 /* set INTR for CPU */ #define INTR INT_1 +//board definitions for the multibus +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x78 +#define SBC201_INT INT_1 +#define SBC201_NUM 0 + +/* set the base I/O address for the iSBC 202 */ +#define SBC202_BASE 0x78 +#define SBC202_INT INT_1 +#define SBC202_NUM 1 + /* set the base I/O address for the iSBC 208 */ #define SBC208_BASE 0x40 - -/* configure interrupt request line */ #define SBC208_INT INT_1 +#define SBC208_NUM 0 + +/* set the base for the zx-200a disk controller */ +#define ZX200A_BASE_DD 0x78 +#define ZX200A_BASE_SD 0x88 +#define ZX200A_NUM 0 /* set the base and size for the iSBC 064 */ #define SBC064_BASE 0x0000 #define SBC064_SIZE 0x10000 +#define SBC064_NUM 1 /* multibus interrupt definitions */ diff --git a/Visual Studio Projects/isys8010.vcproj b/Visual Studio Projects/isys8010.vcproj index a0bfc76e..5fa1ad92 100644 --- a/Visual Studio Projects/isys8010.vcproj +++ b/Visual Studio Projects/isys8010.vcproj @@ -35,6 +35,9 @@ + @@ -116,6 +119,9 @@ + @@ -212,12 +218,20 @@ RelativePath="..\Intel-Systems\common\isbc064.c" > + + + + + + + @@ -116,6 +119,9 @@ + @@ -216,12 +222,20 @@ RelativePath="..\Intel-Systems\common\isbc064.c" > + + + + + +