ISYS8010, ISYS8020: Latest update

This commit is contained in:
Bill Beech 2016-12-05 12:54:15 -07:00
parent 0ef87fac53
commit 2947c39ffe
34 changed files with 4084 additions and 897 deletions

View file

@ -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_NUM; i++)
if (port >=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;
}

View file

@ -196,7 +196,7 @@ DEBTAB i8008_debug[] = {
};
DEVICE i8008_dev = {
"CPU", //name
"I8008", //name
&i8008_unit, //units
i8008_reg, //registers
i8008_mod, //modifiers

View file

@ -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);

View file

@ -449,7 +449,7 @@ DEBTAB i8088_debug[] = {
};
DEVICE i8088_dev = {
"CPU", //name
"I8088", //name
&i8088_unit, //units
i8088_reg, //registers
i8088_mod, //modifiers

View file

@ -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_NUM; i++)
if (port >=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 */

View file

@ -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_NUM; i++)
if (port >= 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 */

View file

@ -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_NUM; i++)
if (port >= 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 */

View file

@ -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_NUM; i++)
if (port >=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 */

View file

@ -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_NUM; i++)
if (port >= 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 */

View file

@ -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_NUM; i++)
if (port >=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 */

View file

@ -159,7 +159,7 @@ DEBTAB i8273_debug[] = {
};
DEVICE i8273_dev = {
"8273", //name
"I8273", //name
&i8273_unit, //units
i8273_reg, //registers
i8273_mod, //modifiers

View file

@ -189,7 +189,7 @@ DEBTAB i8274_debug[] = {
};
DEVICE i8274_dev = {
"8274", //name
"I8274", //name
&i8274_unit, //units
i8274_reg, //registers
i8274_mod, //modifiers

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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<SBC201_NUM; i++)
if (port >= 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; i<uptr->capac; 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 */

View file

@ -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<SBC202_NUM; i++)
if (port >= 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; i<uptr->capac; 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; i<uptr->capac; 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 */

View file

@ -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");

View file

@ -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);
sim_printf("Initializing Multibus Boards\n Multibus Boards:\n");
isbc064_reset(NULL);
isbc208_reset(NULL);
sim_printf(" Multibus: Reset\n");
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 */

View file

@ -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_NUM; i++)
if (port >= 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 <filename>\"\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; i<uptr->capac; 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; i<uptr->capac; 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 */

View file

@ -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);
}

View file

@ -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
};

View file

@ -28,38 +28,58 @@
#include <stdio.h>
#include <ctype.h>
//#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 */

View file

@ -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);
}

View file

@ -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
};

View file

@ -30,39 +30,60 @@
#include <ctype.h>
#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 */

View file

@ -35,6 +35,9 @@
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
@ -116,6 +119,9 @@
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
@ -212,12 +218,20 @@
RelativePath="..\Intel-Systems\common\isbc064.c"
>
</File>
<File
RelativePath="..\Intel-Systems\common\isbc201.c"
>
</File>
<File
RelativePath="..\Intel-Systems\common\isbc202.c"
>
</File>
<File
RelativePath="..\Intel-Systems\common\isbc208.c"
>
</File>
<File
RelativePath="..\Intel-Systems\isys8010\isbc80-10.c"
RelativePath="..\Intel-Systems\isys8010\isbc8010.c"
>
</File>
<File
@ -272,6 +286,10 @@
RelativePath="..\sim_video.c"
>
</File>
<File
RelativePath="..\Intel-Systems\common\zx200a.c"
>
</File>
</Filter>
<Filter
Name="Header Files"

View file

@ -35,6 +35,9 @@
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
@ -116,6 +119,9 @@
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
@ -216,12 +222,20 @@
RelativePath="..\Intel-Systems\common\isbc064.c"
>
</File>
<File
RelativePath="..\Intel-Systems\common\isbc201.c"
>
</File>
<File
RelativePath="..\Intel-Systems\common\isbc202.c"
>
</File>
<File
RelativePath="..\Intel-Systems\common\isbc208.c"
>
</File>
<File
RelativePath="..\Intel-Systems\isys8020\isbc80-20.c"
RelativePath="..\Intel-Systems\isys8020\isbc8020.c"
>
</File>
<File
@ -276,6 +290,10 @@
RelativePath="..\sim_video.c"
>
</File>
<File
RelativePath="..\Intel-Systems\common\zx200a.c"
>
</File>
</Filter>
<Filter
Name="Header Files"

View file

@ -331,7 +331,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
ifeq (X11R7,$(shell if $(TEST) -d /usr/X11R7/lib; then echo X11R7; fi))
LIBPATH += /usr/X11R7/lib
INCPATH += /usr/X11R7/include
OS_LDFLAGS += -L/usr/X11R7/lib -Wl,-R/usr/X11R7/lib
OS_LDFLAGS += -L/usr/X11R7/lib -R/usr/X11R7/lib
OS_CCDEFS += -I/usr/X11R7/include
endif
ifeq (/usr/local/lib,$(findstring /usr/local/lib,$(LIBPATH)))
@ -480,7 +480,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c
DISPLAYVT = ${DISPLAYD}/vt11.c
DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS)
$(info using libSDL2: $(call find_lib,SDL2) $(call find_include,SDL2/SDL))
$(info using libSDL2: $(call find_include,SDL2/SDL))
ifeq (Darwin,$(OSTYPE))
VIDEO_CCDEFS += -DSDL_MAIN_AVAILABLE
endif
@ -812,13 +812,9 @@ else
ifneq (,$(VIDEO_USEFUL))
SDL_INCLUDE = $(word 1,$(shell dir /b /s ..\windows-build\libSDL\SDL.h))
ifeq (SDL.h,$(findstring SDL.h,$(SDL_INCLUDE)))
$(info using libSDL2: $(abspath $(SDL_INCLUDE)))
VIDEO_CCDEFS += -DHAVE_LIBSDL -DUSE_SIM_VIDEO -I$(abspath $(dir $(SDL_INCLUDE)))
VIDEO_CCDEFS += -DHAVE_LIBSDL -I$(abspath $(dir $(SDL_INCLUDE)))
VIDEO_LDFLAGS += -lSDL2 -L$(abspath $(dir $(SDL_INCLUDE))\..\lib)
VIDEO_FEATURES = - video capabilities provided by libSDL2 (Simple Directmedia Layer)
DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c
DISPLAYVT = ${DISPLAYD}/vt11.c
DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS)
else
$(info ***********************************************************************)
$(info ***********************************************************************)
@ -1339,8 +1335,9 @@ ISYS8010C = Intel-Systems/common
ISYS8010 = ${ISYS8010C}/i8080.c ${ISYS8010D}/isys8010_sys.c \
${ISYS8010C}/i8251.c ${ISYS8010C}/i8255.c \
${ISYS8010C}/ieprom.c ${ISYS8010C}/iram8.c \
${ISYS8010C}/multibus.c ${ISYS8010D}/isbc80-10.c \
${ISYS8010C}/isbc064.c ${ISYS8010C}/isbc208.c
${ISYS8010C}/multibus.c ${ISYS8010D}/isbc8010.c \
${ISYS8010C}/isbc064.c ${ISYS8010C}/isbc202.c \
${ISYS8010C}/isbc201.c ${ISYS8010C}/zx200a.c
ISYS8010_OPT = -I ${ISYS8010D}
@ -1349,20 +1346,35 @@ ISYS8020C = Intel-Systems/common
ISYS8020 = ${ISYS8020C}/i8080.c ${ISYS8020D}/isys8020_sys.c \
${ISYS8020C}/i8251.c ${ISYS8020C}/i8255.c \
${ISYS8020C}/ieprom.c ${ISYS8020C}/iram8.c \
${ISYS8020C}/multibus.c ${ISYS8020D}/isbc80-20.c \
${ISYS8020C}/isbc064.c ${ISYS8020C}/isbc208.c \
${ISYS8020C}/i8259.c
${ISYS8020C}/multibus.c ${ISYS8020D}/isbc8020.c \
${ISYS8020C}/isbc064.c ${ISYS8020C}/i8259.c \
${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \
${ISYS8010C}/zx200a.c
ISYS8020_OPT = -I ${ISYS8020D}
ISYS8024D = Intel-Systems/isys8024
ISYS8024C = Intel-Systems/common
ISYS8024 = ${ISYS8024C}/i8080.c ${ISYS8024D}/isys8024_sys.c \
${ISYS8024C}/i8251.c ${ISYS8024C}/i8253.c \
${ISYS8024C}/i8255.c ${ISYS8024C}/i8259.c \
${ISYS8024C}/ieprom.c ${ISYS8024C}/iram8.c \
${ISYS8024C}/multibus.c ${ISYS8024D}/isbc8024.c \
${ISYS8024C}/isbc064.c ${ISYS8024C}/isbc208.c \
${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \
${ISYS8010C}/zx200a.c
ISYS8024_OPT = -I ${ISYS8024D}
ISYS8030D = Intel-Systems/isys8030
ISYS8030C = Intel-Systems/common
ISYS8030 = ${ISYS8030C}/i8080.c ${ISYS8030D}/isys8030_sys.c \
${ISYS8030C}/i8251.c ${ISYS8030C}/i8255.c \
${ISYS8030C}/i8259.c ${ISYS8030C}/i8253.c \
${ISYS8030C}/ieprom.c ${ISYS8030C}/iram8.c \
${ISYS8030C}/multibus.c ${ISYS8030D}/isbc80-30.c \
${ISYS8030C}/isbc064.c ${ISYS8030C}/isbc208.c
${ISYS8030C}/multibus.c ${ISYS8030D}/isbc8030.c \
${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \
${ISYS8030C}/isbc064.c ${ISYS8010C}/zx200a.c
ISYS8030_OPT = -I ${ISYS8030D}
@ -1374,15 +1386,16 @@ IMDS-225 = ${IMDS-225C}/i8080.c ${IMDS-225D}/imds-225_sys.c \
${IMDS-225C}/ipceprom.c ${IMDS-225C}/ipcram8.c \
${IMDS-225C}/ipcmultibus.c ${IMDS-225D}/ipc.c \
${IMDS-225C}/ipc-cont.c ${IMDS-225C}/ioc-cont.c \
${IMDS-225C}/isbc202.c ${IMDS-225C}/isbc201.c \
${IMDS-225C}/zx200a.c
IMDS-225_OPT = -I ${IMDS-225D}
IBMPCD = IBMPC-Systems/ibmpc
IBMPCC = IBMPC-Systems/common
IBMPC = ${IBMPCC}/i8088.c ${IBMPCD}/ibmpc_sys.c \
IBMPC = ${IBMPCC}/i8255.c ${IBMPCD}/ibmpc.c \
${IBMPCC}/i8088.c ${IBMPCD}/ibmpc_sys.c \
${IBMPCC}/i8253.c ${IBMPCC}/i8259.c \
${IBMPCC}/i8255.c ${IBMPCD}/ibmpc.c \
${IBMPCC}/pceprom.c ${IBMPCC}/pcram8.c \
${IBMPCC}/i8237.c ${IBMPCC}/pcbus.c
IBMPC_OPT = -I ${IBMPCD}
@ -1400,7 +1413,7 @@ IBMPCXT_OPT = -I ${IBMPCXTD}
TX0D = TX-0
TX0 = ${TX0D}/tx0_cpu.c ${TX0D}/tx0_dpy.c ${TX0D}/tx0_stddev.c \
${TX0D}/tx0_sys.c ${TX0D}/tx0_sys_orig.c ${DISPLAYL}
${TX0D}/tx0_sys.c ${TX0D}/tx0_sys_orig.c ${DISPLAYL}
TX0_OPT = -I ${TX0D} $(DISPLAY_OPT)
@ -1514,8 +1527,8 @@ ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \
vax microvax3900 microvax1 rtvax1000 microvax2 vax730 vax750 vax780 vax8600 \
nova eclipse hp2100 hp3000 i1401 i1620 s3 altair altairz80 gri \
i7094 ibm1130 id16 id32 sds lgp h316 cdc1700 \
swtp6800mp-a swtp6800mp-a2 tx-0 ssem isys8010 isys8020 \
b5500
swtp6800mp-a swtp6800mp-a2 tx-0 ssem \
b5500 imds-225 imbpc ibmpcxt
all : ${ALL}
@ -1795,25 +1808,23 @@ ${BIN}isys8020${EXE} : ${ISYS8020} ${SIM} ${BUILD_ROMS}
${MKDIRBIN}
${CC} ${ISYS8020} ${SIM} ${ISYS8020_OPT} $(CC_OUTSPEC) ${LDFLAGS}
isys8024: ${BIN}isys8024${EXE}
${BIN}isys8024${EXE} : ${ISYS8024} ${SIM} ${BUILD_ROMS}
${MKDIRBIN}
${CC} ${ISYS8024} ${SIM} ${ISYS8024_OPT} $(CC_OUTSPEC) ${LDFLAGS}
isys8030: ${BIN}isys8030${EXE}
${BIN}isys8030${EXE} : ${ISYS8030} ${SIM} ${BUILD_ROMS}
ifneq (1,$(CPP_BUILD)$(CPP_FORCE))
${MKDIRBIN}
${CC} ${ISYS8030} ${SIM} ${ISYS8030_OPT} $(CC_OUTSPEC) ${LDFLAGS}
else
$(info isys8030 can't be built using C++)
endif
imds-225: ${BIN}imds-225${EXE}
${BIN}imds-225${EXE} : ${IMDS-225} ${SIM} ${BUILD_ROMS}
ifneq (1,$(CPP_BUILD)$(CPP_FORCE))
${MKDIRBIN}
${CC} ${IMDS-225} ${SIM} ${IMDS-225_OPT} $(CC_OUTSPEC) ${LDFLAGS}
else
$(info imds-225 can't be built using C++)
endif
ibmpc: ${BIN}ibmpc${EXE}