ISYS8010, ISYS8020: Latest update
This commit is contained in:
parent
0ef87fac53
commit
2947c39ffe
34 changed files with 4084 additions and 897 deletions
|
@ -26,7 +26,7 @@
|
||||||
MODIFICATIONS:
|
MODIFICATIONS:
|
||||||
|
|
||||||
?? ??? 10 - Original file.
|
?? ??? 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
|
24 Apr 15 -- Modified to use simh_debug
|
||||||
|
|
||||||
NOTES:
|
NOTES:
|
||||||
|
@ -83,7 +83,7 @@ extern uint16 port; //port called in dev_table[port]
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
t_stat i8255_reset (DEVICE *dptr, uint16 base);
|
t_stat i8255_reset (DEVICE *dptr, uint16 baseport);
|
||||||
uint8 i8255_get_dn(void);
|
uint8 i8255_get_dn(void);
|
||||||
uint8 i8255s(t_bool io, uint8 data);
|
uint8 i8255s(t_bool io, uint8 data);
|
||||||
uint8 i8255a(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 */
|
/* 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 */
|
/* globals */
|
||||||
|
|
||||||
int32 i8255_devnum = 0; //actual number of 8255 instances + 1
|
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 */
|
/* these bytes represent the input and output to/from a port instance */
|
||||||
|
|
||||||
|
@ -175,22 +175,23 @@ DEVICE i8255_dev = {
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
||||||
t_stat i8255_reset (DEVICE *dptr, uint16 base)
|
t_stat i8255_reset (DEVICE *dptr, uint16 baseport)
|
||||||
{
|
{
|
||||||
if (i8255_devnum > I8255_NUM) {
|
if (i8255_devnum > I8255_NUM) {
|
||||||
sim_printf("i8255_reset: too many devices!\n");
|
sim_printf("i8255_reset: too many devices!\n");
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
}
|
}
|
||||||
i8255_port[i8255_devnum] = reg_dev(i8255a, base);
|
sim_printf(" 8255-%d: Reset\n", i8255_devnum);
|
||||||
reg_dev(i8255b, base + 1);
|
sim_printf(" 8255-%d: Registered at %04X\n", i8255_devnum, baseport);
|
||||||
reg_dev(i8255c, base + 2);
|
i8255_port[i8255_devnum] = baseport;
|
||||||
reg_dev(i8255s, base + 3);
|
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_unit[i8255_devnum].u3 = 0x9B; /* control */
|
||||||
i8255_A[i8255_devnum] = 0xFF; /* Port A */
|
i8255_A[i8255_devnum] = 0xFF; /* Port A */
|
||||||
i8255_B[i8255_devnum] = 0xFF; /* Port B */
|
i8255_B[i8255_devnum] = 0xFF; /* Port B */
|
||||||
i8255_C[i8255_devnum] = 0xFF; /* Port C */
|
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++;
|
i8255_devnum++;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +203,7 @@ uint8 i8255_get_dn(void)
|
||||||
for (i=0; i<I8255_NUM; i++)
|
for (i=0; i<I8255_NUM; i++)
|
||||||
if (port >=i8255_port[i] && port <= i8255_port[i] + 3)
|
if (port >=i8255_port[i] && port <= i8255_port[i] + 3)
|
||||||
return i;
|
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;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ DEBTAB i8008_debug[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE i8008_dev = {
|
DEVICE i8008_dev = {
|
||||||
"CPU", //name
|
"I8008", //name
|
||||||
&i8008_unit, //units
|
&i8008_unit, //units
|
||||||
i8008_reg, //registers
|
i8008_reg, //registers
|
||||||
i8008_mod, //modifiers
|
i8008_mod, //modifiers
|
||||||
|
|
|
@ -171,6 +171,7 @@ uint32 int_req = 0; /* Interrupt request */
|
||||||
int32 PCX; /* External view of PC */
|
int32 PCX; /* External view of PC */
|
||||||
int32 PC;
|
int32 PC;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
uint32 port; //port used in any IN/OUT
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
void set_cpuint(int32 int_num);
|
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 {
|
struct idev {
|
||||||
uint8 (*routine)(t_bool, uint8, uint8);
|
uint8 (*routine)(t_bool, uint8);
|
||||||
|
uint16 port;
|
||||||
uint8 devnum;
|
uint8 devnum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -265,7 +267,7 @@ DEBTAB i8080_debug[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE i8080_dev = {
|
DEVICE i8080_dev = {
|
||||||
"CPU", //name
|
"I8080", //name
|
||||||
&i8080_unit, //units
|
&i8080_unit, //units
|
||||||
i8080_reg, //registers
|
i8080_reg, //registers
|
||||||
i8080_mod, //modifiers
|
i8080_mod, //modifiers
|
||||||
|
@ -393,12 +395,10 @@ int32 sim_instr (void)
|
||||||
reason = 0;
|
reason = 0;
|
||||||
|
|
||||||
uptr = i8080_dev.units;
|
uptr = i8080_dev.units;
|
||||||
if (i8080_dev.dctrl & DEBUG_flow) {
|
if (uptr->flags & UNIT_8085)
|
||||||
if (uptr->flags & UNIT_8085)
|
sim_printf("CPU = 8085\n");
|
||||||
sim_printf("CPU = 8085\n");
|
else
|
||||||
else
|
sim_printf("CPU = 8080\n");
|
||||||
sim_printf("CPU = 8080\n");
|
|
||||||
}
|
|
||||||
/* Main instruction fetch/decode loop */
|
/* Main instruction fetch/decode loop */
|
||||||
|
|
||||||
while (reason == 0) { /* loop until halted */
|
while (reason == 0) { /* loop until halted */
|
||||||
|
@ -472,9 +472,9 @@ int32 sim_instr (void)
|
||||||
IR = OP = fetch_byte(0); /* instruction fetch */
|
IR = OP = fetch_byte(0); /* instruction fetch */
|
||||||
|
|
||||||
if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */
|
if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */
|
||||||
reason = STOP_XACK;
|
// reason = STOP_XACK;
|
||||||
sim_printf("Stopped for XACK-1 PC=%04X\n", --PC);
|
sim_printf("Stopped for XACK-1 PC=%04X\n", PC);
|
||||||
continue;
|
// continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OP == 0x76) { /* HLT Instruction*/
|
if (OP == 0x76) { /* HLT Instruction*/
|
||||||
|
@ -890,14 +890,18 @@ int32 sim_instr (void)
|
||||||
|
|
||||||
case 0xDB: /* IN */
|
case 0xDB: /* IN */
|
||||||
DAR = fetch_byte(1);
|
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;
|
A &= BYTE_R;
|
||||||
// sim_printf("\n%04X\tIN\t%02X\t;devnum=%d", PC - 1, DAR, dev_table[DAR].devnum);
|
// sim_printf("\n%04X\tIN\t%02X\t;devnum=%d", PC - 1, DAR, dev_table[DAR].devnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD3: /* OUT */
|
case 0xD3: /* OUT */
|
||||||
DAR = fetch_byte(1);
|
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);
|
// sim_printf("\n%04X\tOUT\t%02X\t;devnum=%d", PC - 1, DAR, dev_table[DAR].devnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -909,12 +913,12 @@ int32 sim_instr (void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
loop_end:
|
loop_end:
|
||||||
if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */
|
// if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */
|
||||||
reason = STOP_XACK;
|
// reason = STOP_XACK;
|
||||||
sim_printf("Stopped for XACK-2 PC=%04X\n", --PC);
|
// sim_printf("Stopped for XACK-2 PC=%04X\n", PC);
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simulation halted */
|
/* Simulation halted */
|
||||||
|
@ -1296,7 +1300,7 @@ int32 sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
|
||||||
return (SCPE_OK);
|
return (SCPE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Symbolic output
|
/* Symbolic output - working
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
*of = output stream
|
*of = output stream
|
||||||
|
@ -1329,17 +1333,17 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||||
inst = val[0];
|
inst = val[0];
|
||||||
fprintf (of, "%s", opcode[inst]);
|
fprintf (of, "%s", opcode[inst]);
|
||||||
if (oplen[inst] == 2) {
|
if (oplen[inst] == 2) {
|
||||||
if (strchr(opcode[inst], ' ') != NULL)
|
// if (strchr(opcode[inst], ' ') != NULL)
|
||||||
fprintf (of, ",");
|
// fprintf (of, ",");
|
||||||
else fprintf (of, " ");
|
// else fprintf (of, " ");
|
||||||
fprintf (of, "%02X", val[1]);
|
fprintf (of, "%02X", val[1]);
|
||||||
}
|
}
|
||||||
if (oplen[inst] == 3) {
|
if (oplen[inst] == 3) {
|
||||||
adr = val[1] & 0xFF;
|
adr = val[1] & 0xFF;
|
||||||
adr |= (val[2] << 8) & 0xff00;
|
adr |= (val[2] << 8) & 0xff00;
|
||||||
if (strchr(opcode[inst], ' ') != NULL)
|
// if (strchr(opcode[inst], ' ') != NULL)
|
||||||
fprintf (of, ",");
|
// fprintf (of, ",");
|
||||||
else fprintf (of, " ");
|
// else fprintf (of, " ");
|
||||||
fprintf (of, "%04X", adr);
|
fprintf (of, "%04X", adr);
|
||||||
}
|
}
|
||||||
return -(oplen[inst] - 1);
|
return -(oplen[inst] - 1);
|
||||||
|
|
|
@ -449,7 +449,7 @@ DEBTAB i8088_debug[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE i8088_dev = {
|
DEVICE i8088_dev = {
|
||||||
"CPU", //name
|
"I8088", //name
|
||||||
&i8088_unit, //units
|
&i8088_unit, //units
|
||||||
i8088_reg, //registers
|
i8088_reg, //registers
|
||||||
i8088_mod, //modifiers
|
i8088_mod, //modifiers
|
||||||
|
|
867
Intel-Systems/common/i8237.c
Normal file
867
Intel-Systems/common/i8237.c
Normal 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 */
|
|
@ -26,7 +26,7 @@
|
||||||
MODIFICATIONS:
|
MODIFICATIONS:
|
||||||
|
|
||||||
?? ??? 10 - Original file.
|
?? ??? 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
|
24 Apr 15 -- Modified to use simh_debug
|
||||||
|
|
||||||
NOTES:
|
NOTES:
|
||||||
|
@ -111,6 +111,10 @@
|
||||||
|
|
||||||
#include "system_defs.h"
|
#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_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */
|
||||||
#define UNIT_ANSI (1 << UNIT_V_ANSI)
|
#define UNIT_ANSI (1 << UNIT_V_ANSI)
|
||||||
|
|
||||||
|
@ -119,14 +123,22 @@
|
||||||
#define TXE 0x04
|
#define TXE 0x04
|
||||||
#define SD 0x40
|
#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 */
|
/* function prototypes */
|
||||||
|
|
||||||
t_stat i8251_svc (UNIT *uptr);
|
t_stat i8251_svc (UNIT *uptr);
|
||||||
t_stat i8251_reset (DEVICE *dptr, uint16 base, uint8 devnum);
|
t_stat i8251_reset (DEVICE *dptr, uint16 baseport);
|
||||||
uint8 i8251s(t_bool io, uint8 data, uint8 devnum);
|
uint8 i8251_get_dn(void);
|
||||||
uint8 i8251d(t_bool io, uint8 data, uint8 devnum);
|
uint8 i8251s(t_bool io, uint8 data);
|
||||||
|
uint8 i8251d(t_bool io, uint8 data);
|
||||||
void i8251_reset1(uint8 devnum);
|
void i8251_reset1(uint8 devnum);
|
||||||
|
|
||||||
/* i8251 Standard I/O Data Structures */
|
/* 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 */
|
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
|
||||||
|
|
||||||
DEVICE i8251_dev = {
|
DEVICE i8251_dev = {
|
||||||
"8251", //name
|
"I8251", //name
|
||||||
&i8251_unit, //units
|
&i8251_unit, //units
|
||||||
i8251_reg, //registers
|
i8251_reg, //registers
|
||||||
i8251_mod, //modifiers
|
i8251_mod, //modifiers
|
||||||
1, //numunits
|
1, //numunits
|
||||||
16, //aradix
|
16, //aradix
|
||||||
16, //awidth
|
16, //awidth
|
||||||
1, //aincr
|
1, //aincr
|
||||||
16, //dradix
|
16, //dradix
|
||||||
8, //dwidth
|
8, //dwidth
|
||||||
NULL, //examine
|
NULL, //examine
|
||||||
NULL, //deposit
|
NULL, //deposit
|
||||||
// &i8251_reset, //reset
|
// &i8251_reset, //reset
|
||||||
NULL, //reset
|
NULL, //reset
|
||||||
NULL, //boot
|
NULL, //boot
|
||||||
NULL, //attach
|
NULL, //attach
|
||||||
NULL, //detach
|
NULL, //detach
|
||||||
|
@ -211,65 +223,23 @@ t_stat i8251_svc (UNIT *uptr)
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
||||||
t_stat i8251_reset (DEVICE *dptr, uint16 base, uint8 devnum)
|
t_stat i8251_reset (DEVICE *dptr, uint16 baseport)
|
||||||
{
|
{
|
||||||
if (devnum >= I8251_NUM) {
|
if (i8251_devnum >= I8251_NUM) {
|
||||||
sim_printf("8251_reset: Illegal Device Number %d\n", devnum);
|
sim_printf("8251_reset: Illegal Device Number %d\n", i8251_devnum);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
reg_dev(i8251d, base, devnum);
|
sim_printf(" 8251-%d: Hardware Reset\n", i8251_devnum);
|
||||||
reg_dev(i8251s, base + 1, devnum);
|
sim_printf(" 8251-%d: Registered at %04X\n", i8251_devnum, baseport);
|
||||||
reg_dev(i8251d, base + 2, devnum);
|
i8251_port[i8251_devnum] = baseport;
|
||||||
reg_dev(i8251s, base + 3, devnum);
|
reg_dev(i8251d, baseport, i8251_devnum);
|
||||||
i8251_reset1(devnum);
|
reg_dev(i8251s, baseport + 1, i8251_devnum);
|
||||||
sim_printf(" 8251-%d: Registered at %04X\n", devnum, base);
|
i8251_reset1(i8251_devnum);
|
||||||
sim_activate (&i8251_unit, i8251_unit.wait); /* activate unit */
|
sim_activate (&i8251_unit, i8251_unit.wait); /* activate unit */
|
||||||
|
i8251_devnum++;
|
||||||
return SCPE_OK;
|
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)
|
void i8251_reset1(uint8 devnum)
|
||||||
{
|
{
|
||||||
i8251_unit.u3 = TXR + TXE; /* status */
|
i8251_unit.u3 = TXR + TXE; /* status */
|
||||||
|
@ -278,7 +248,61 @@ void i8251_reset1(uint8 devnum)
|
||||||
i8251_unit.u6 = 0;
|
i8251_unit.u6 = 0;
|
||||||
i8251_unit.buf = 0;
|
i8251_unit.buf = 0;
|
||||||
i8251_unit.pos = 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 */
|
/* end of i8251.c */
|
||||||
|
|
238
Intel-Systems/common/i8253.c
Normal file
238
Intel-Systems/common/i8253.c
Normal 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 */
|
|
@ -26,7 +26,7 @@
|
||||||
MODIFICATIONS:
|
MODIFICATIONS:
|
||||||
|
|
||||||
?? ??? 10 - Original file.
|
?? ??? 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
|
24 Apr 15 -- Modified to use simh_debug
|
||||||
|
|
||||||
NOTES:
|
NOTES:
|
||||||
|
@ -77,20 +77,34 @@
|
||||||
|
|
||||||
#include "system_defs.h" /* system header in system dir */
|
#include "system_defs.h" /* system header in system dir */
|
||||||
|
|
||||||
|
/* external globals */
|
||||||
|
|
||||||
|
extern uint16 port; //port called in dev_table[port]
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
uint8 i8255s0(t_bool io, uint8 data, uint8 devnum); /* i8255*/
|
t_stat i8255_reset (DEVICE *dptr, uint16 baseport);
|
||||||
uint8 i8255a0(t_bool io, uint8 data, uint8 devnum);
|
uint8 i8255_get_dn(void);
|
||||||
uint8 i8255b0(t_bool io, uint8 data, uint8 devnum);
|
uint8 i8255s(t_bool io, uint8 data);
|
||||||
uint8 i8255c0(t_bool io, uint8 data, uint8 devnum);
|
uint8 i8255a(t_bool io, uint8 data);
|
||||||
t_stat i8255_reset (DEVICE *dptr, uint16 base, uint8 devnum);
|
uint8 i8255b(t_bool io, uint8 data);
|
||||||
|
uint8 i8255c(t_bool io, uint8 data);
|
||||||
|
|
||||||
/* external function prototypes */
|
/* 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 */
|
/* 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 */
|
/* i8255 Standard I/O Data Structures */
|
||||||
/* up to 4 i8255 devices */
|
/* up to 4 i8255 devices */
|
||||||
|
|
||||||
|
@ -102,22 +116,22 @@ UNIT i8255_unit[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
REG i8255_reg[] = {
|
REG i8255_reg[] = {
|
||||||
{ HRDATA (CONTROL0, i8255_unit[0].u3, 8) }, /* i8255 0 */
|
{ HRDATA (CS0, i8255_unit[0].u3, 8) }, /* i8255 0 */
|
||||||
{ HRDATA (PORTA0, i8255_unit[0].u4, 8) },
|
{ HRDATA (A0, i8255_A[0], 8) },
|
||||||
{ HRDATA (PORTB0, i8255_unit[0].u5, 8) },
|
{ HRDATA (B0, i8255_B[0], 8) },
|
||||||
{ HRDATA (PORTC0, i8255_unit[0].u6, 8) },
|
{ HRDATA (C0, i8255_C[0], 8) },
|
||||||
{ HRDATA (CONTROL1, i8255_unit[1].u3, 8) }, /* i8255 1 */
|
{ HRDATA (CS1, i8255_unit[1].u3, 8) }, /* i8255 1 */
|
||||||
{ HRDATA (PORTA1, i8255_unit[1].u4, 8) },
|
{ HRDATA (A1, i8255_A[1], 8) },
|
||||||
{ HRDATA (PORTB1, i8255_unit[1].u5, 8) },
|
{ HRDATA (B1, i8255_B[1], 8) },
|
||||||
{ HRDATA (PORTC1, i8255_unit[1].u6, 8) },
|
{ HRDATA (C1, i8255_C[1], 8) },
|
||||||
{ HRDATA (CONTROL1, i8255_unit[2].u3, 8) }, /* i8255 2 */
|
{ HRDATA (CS2, i8255_unit[2].u3, 8) }, /* i8255 2 */
|
||||||
{ HRDATA (PORTA1, i8255_unit[2].u4, 8) },
|
{ HRDATA (A2, i8255_A[2], 8) },
|
||||||
{ HRDATA (PORTB1, i8255_unit[2].u5, 8) },
|
{ HRDATA (B2, i8255_B[2], 8) },
|
||||||
{ HRDATA (PORTC1, i8255_unit[2].u6, 8) },
|
{ HRDATA (C2, i8255_C[2], 8) },
|
||||||
{ HRDATA (CONTROL1, i8255_unit[3].u3, 8) }, /* i8255 3 */
|
{ HRDATA (CS3, i8255_unit[3].u3, 8) }, /* i8255 3 */
|
||||||
{ HRDATA (PORTA1, i8255_unit[3].u4, 8) },
|
{ HRDATA (A3, i8255_A[3], 8) },
|
||||||
{ HRDATA (PORTB1, i8255_unit[3].u5, 8) },
|
{ HRDATA (B3, i8255_B[3], 8) },
|
||||||
{ HRDATA (PORTC1, i8255_unit[3].u6, 8) },
|
{ HRDATA (C3, i8255_C[3], 8) },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,7 +140,6 @@ DEBTAB i8255_debug[] = {
|
||||||
{ "FLOW", DEBUG_flow },
|
{ "FLOW", DEBUG_flow },
|
||||||
{ "READ", DEBUG_read },
|
{ "READ", DEBUG_read },
|
||||||
{ "WRITE", DEBUG_write },
|
{ "WRITE", DEBUG_write },
|
||||||
{ "XACK", DEBUG_xack },
|
|
||||||
{ "LEV1", DEBUG_level1 },
|
{ "LEV1", DEBUG_level1 },
|
||||||
{ "LEV2", DEBUG_level2 },
|
{ "LEV2", DEBUG_level2 },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
|
@ -135,7 +148,7 @@ DEBTAB i8255_debug[] = {
|
||||||
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
|
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
|
||||||
|
|
||||||
DEVICE i8255_dev = {
|
DEVICE i8255_dev = {
|
||||||
"8255", //name
|
"I8255", //name
|
||||||
i8255_unit, //units
|
i8255_unit, //units
|
||||||
i8255_reg, //registers
|
i8255_reg, //registers
|
||||||
NULL, //modifiers
|
NULL, //modifiers
|
||||||
|
@ -147,7 +160,7 @@ DEVICE i8255_dev = {
|
||||||
8, //dwidth
|
8, //dwidth
|
||||||
NULL, //examine
|
NULL, //examine
|
||||||
NULL, //deposit
|
NULL, //deposit
|
||||||
// &i8255_reset, //reset
|
// i8255_reset2(), //reset
|
||||||
NULL, //reset
|
NULL, //reset
|
||||||
NULL, //boot
|
NULL, //boot
|
||||||
NULL, //attach
|
NULL, //attach
|
||||||
|
@ -160,104 +173,117 @@ DEVICE i8255_dev = {
|
||||||
NULL //lname
|
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
|
/* I/O instruction handlers, called from the CPU module when an
|
||||||
IN or OUT instruction is issued.
|
IN or OUT instruction is issued.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* i8255 functions */
|
/* i8255 functions */
|
||||||
|
|
||||||
uint8 i8255s(t_bool io, uint8 data, uint8 devnum)
|
uint8 i8255s(t_bool io, uint8 data)
|
||||||
{
|
{
|
||||||
uint8 bit;
|
uint8 bit;
|
||||||
|
uint8 devnum;
|
||||||
|
|
||||||
if (devnum >= I8255_NUM) {
|
if ((devnum = i8255_get_dn()) != 0xFF) {
|
||||||
sim_printf("8255s: Illegal Device Number %d\n", devnum);
|
if (io == 0) { /* read status port */
|
||||||
return 0;
|
return i8255_unit[devnum].u3;
|
||||||
}
|
} else { /* write status port */
|
||||||
if (io == 0) { /* read status port */
|
if (data & 0x80) { /* mode instruction */
|
||||||
return i8255_unit[devnum].u3;
|
i8255_unit[devnum].u3 = data;
|
||||||
} else { /* write status port */
|
sim_printf(" 8255-%d: Mode Instruction=%02X\n", devnum, data);
|
||||||
if (data & 0x80) { /* mode instruction */
|
if (data & 0x64)
|
||||||
i8255_unit[0].u3 = data;
|
sim_printf(" Mode 1 and 2 not yet implemented\n");
|
||||||
sim_printf(" 8255-%d: Mode Instruction=%02X\n", devnum, data);
|
} else { /* bit set */
|
||||||
if (data & 0x64)
|
bit = (data & 0x0E) >> 1; /* get bit number */
|
||||||
sim_printf(" Mode 1 and 2 not yet implemented\n");
|
if (data & 0x01) { /* set bit */
|
||||||
} else { /* bit set */
|
i8255_C[devnum] |= (0x01 << bit);
|
||||||
bit = (data & 0x0E) >> 1; /* get bit number */
|
} else { /* reset bit */
|
||||||
if (data & 0x01) { /* set bit */
|
i8255_C[devnum] &= ~(0x01 << bit);
|
||||||
i8255_unit[devnum].u6 |= (0x01 << bit);
|
}
|
||||||
} else { /* reset bit */
|
|
||||||
i8255_unit[devnum].u6 &= ~(0x01 << bit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 i8255a(t_bool io, uint8 data, uint8 devnum)
|
uint8 i8255a(t_bool io, uint8 data)
|
||||||
{
|
{
|
||||||
if (devnum >= I8255_NUM) {
|
uint8 devnum;
|
||||||
sim_printf("8255a: Illegal Device Number %d\n", devnum);
|
|
||||||
return 0;
|
if ((devnum = i8255_get_dn()) != 0xFF) {
|
||||||
}
|
if (io == 0) { /* read data port */
|
||||||
if (io == 0) { /* read data port */
|
//return (i8255_unit[devnum].u4);
|
||||||
return (i8255_unit[devnum].u4);
|
return (i8255_A[devnum]);
|
||||||
} else { /* write data port */
|
} else { /* write data port */
|
||||||
i8255_unit[devnum].u4 = data;
|
i8255_A[devnum] = data;
|
||||||
sim_printf(" 8255-%d: Port A = %02X\n", devnum, data);
|
sim_printf(" 8255-%d: Port A = %02X\n", devnum, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 i8255b(t_bool io, uint8 data, uint8 devnum)
|
uint8 i8255b(t_bool io, uint8 data)
|
||||||
{
|
{
|
||||||
if (devnum >= I8255_NUM) {
|
uint8 devnum;
|
||||||
sim_printf("8255b: Illegal Device Number %d\n", devnum);
|
|
||||||
return 0;
|
if ((devnum = i8255_get_dn()) != 0xFF) {
|
||||||
}
|
if (io == 0) { /* read data port */
|
||||||
if (io == 0) { /* read data port */
|
return (i8255_B[devnum]);
|
||||||
return (i8255_unit[devnum].u5);
|
} else { /* write data port */
|
||||||
} else { /* write data port */
|
i8255_B[devnum] = data;
|
||||||
i8255_unit[devnum].u5 = data;
|
sim_printf(" 8255-%d: Port B = %02X\n", devnum, data);
|
||||||
sim_printf(" 8255-%d: Port B = %02X\n", devnum, data);
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 i8255c(t_bool io, uint8 data, uint8 devnum)
|
uint8 i8255c(t_bool io, uint8 data)
|
||||||
{
|
{
|
||||||
if (devnum >= I8255_NUM) {
|
uint8 devnum;
|
||||||
sim_printf("8255c: Illegal Device Number %d\n", devnum);
|
|
||||||
return 0;
|
if ((devnum = i8255_get_dn()) != 0xFF) {
|
||||||
}
|
if (io == 0) { /* read data port */
|
||||||
if (io == 0) { /* read data port */
|
return (i8255_C[devnum]);
|
||||||
return (i8255_unit[devnum].u6);
|
} else { /* write data port */
|
||||||
} else { /* write data port */
|
i8255_C[devnum] = data;
|
||||||
i8255_unit[devnum].u6 = data;
|
sim_printf(" 8255-%d: Port C = %02X\n", devnum, data);
|
||||||
sim_printf(" 8255-%d: Port C = %02X\n", devnum, data);
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
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 */
|
/* end of i8255.c */
|
||||||
|
|
|
@ -37,17 +37,25 @@
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
uint8 i8259a(t_bool io, uint8 data, uint8 devnum);
|
uint8 i8259a(t_bool io, uint8 data);
|
||||||
uint8 i8259b(t_bool io, uint8 data, uint8 devnum);
|
uint8 i8259b(t_bool io, uint8 data);
|
||||||
void i8259_dump(uint8 devnum);
|
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 */
|
/* 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 */
|
/* 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_base[I8259_NUM];
|
||||||
uint8 i8259_icw1[I8259_NUM];
|
uint8 i8259_icw1[I8259_NUM];
|
||||||
uint8 i8259_icw2[I8259_NUM];
|
uint8 i8259_icw2[I8259_NUM];
|
||||||
|
@ -58,21 +66,29 @@ uint8 i8259_ocw2[I8259_NUM];
|
||||||
uint8 i8259_ocw3[I8259_NUM];
|
uint8 i8259_ocw3[I8259_NUM];
|
||||||
uint8 icw_num0 = 1, icw_num1 = 1;
|
uint8 icw_num0 = 1, icw_num1 = 1;
|
||||||
|
|
||||||
/* i8255 Standard I/O Data Structures */
|
/* i8259 Standard I/O Data Structures */
|
||||||
/* up to 2 i8259 devices */
|
/* up to 2 i8259 devices */
|
||||||
|
|
||||||
UNIT i8259_unit[] = {
|
UNIT i8259_unit[] = {
|
||||||
{ UDATA (0, 0, 0) }, /* i8259 0 */
|
{ 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[] = {
|
REG i8259_reg[] = {
|
||||||
{ HRDATA (IRR0, i8259_unit[0].u3, 8) }, /* i8259 0 */
|
{ HRDATA (IRR0, i8259_unit[0].u3, 8) }, /* i8259 0 */
|
||||||
{ HRDATA (ISR0, i8259_unit[0].u4, 8) },
|
{ HRDATA (ISR0, i8259_unit[0].u4, 8) },
|
||||||
{ HRDATA (IMR0, i8259_unit[0].u5, 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 (ISR1, i8259_unit[1].u4, 8) },
|
||||||
{ HRDATA (IMR1, i8259_unit[1].u5, 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 }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,7 +106,7 @@ DEBTAB i8259_debug[] = {
|
||||||
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
|
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
|
||||||
|
|
||||||
DEVICE i8259_dev = {
|
DEVICE i8259_dev = {
|
||||||
"8259", //name
|
"I8259", //name
|
||||||
i8259_unit, //units
|
i8259_unit, //units
|
||||||
i8259_reg, //registers
|
i8259_reg, //registers
|
||||||
NULL, //modifiers
|
NULL, //modifiers
|
||||||
|
@ -119,117 +135,130 @@ DEVICE i8259_dev = {
|
||||||
IN or OUT instruction is issued.
|
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) {
|
if (i8259_devnum >= I8259_NUM) {
|
||||||
sim_printf("8259a: Illegal Device Number %d\n", devnum);
|
sim_printf("8259_reset: Illegal Device Number %d\n", i8259_devnum);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (io == 0) { /* read data port */
|
sim_printf(" 8259-%d: Reset\n", i8259_devnum);
|
||||||
if ((i8259_ocw3[devnum] & 0x03) == 0x02)
|
sim_printf(" 8259-%d: Registered at %04X\n", i8259_devnum, baseport);
|
||||||
return (i8259_unit[devnum].u3); /* IRR */
|
i8259_port[i8259_devnum] = baseport;
|
||||||
if ((i8259_ocw3[devnum] & 0x03) == 0x03)
|
reg_dev(i8259a, baseport, i8259_devnum);
|
||||||
return (i8259_unit[devnum].u4); /* ISR */
|
reg_dev(i8259b, baseport + 1, i8259_devnum);
|
||||||
} else { /* write data port */
|
i8259_unit[i8259_devnum].u3 = 0x00; /* IRR */
|
||||||
if (data & 0x10) {
|
i8259_unit[i8259_devnum].u4 = 0x00; /* ISR */
|
||||||
icw_num0 = 1;
|
i8259_unit[i8259_devnum].u5 = 0x00; /* IMR */
|
||||||
}
|
i8259_devnum++;
|
||||||
if (icw_num0 == 1) {
|
return SCPE_OK;
|
||||||
i8259_icw1[devnum] = data; /* ICW1 */
|
}
|
||||||
i8259_unit[devnum].u5 = 0x00; /* clear IMR */
|
|
||||||
i8259_ocw3[devnum] = 0x02; /* clear OCW3, Sel IRR */
|
uint8 i8259_get_dn(void)
|
||||||
} else {
|
{
|
||||||
switch (data & 0x18) {
|
int i;
|
||||||
case 0: /* OCW2 */
|
|
||||||
i8259_ocw2[devnum] = data;
|
for (i=0; i<I8259_NUM; i++)
|
||||||
break;
|
if (port >= i8259_port[i] && port <= i8259_port[i] + 1)
|
||||||
case 8: /* OCW3 */
|
return i;
|
||||||
i8259_ocw3[devnum] = data;
|
sim_printf("i8259_get_dn: port %04X not in 8259 device table\n", port);
|
||||||
break;
|
return 0xFF;
|
||||||
default:
|
}
|
||||||
sim_printf("8259a-%d: OCW Error %02X\n", devnum, data);
|
|
||||||
break;
|
/* 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);
|
// i8259_dump(devnum);
|
||||||
icw_num0++; /* step ICW number */
|
|
||||||
}
|
}
|
||||||
i8259_dump(devnum);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 i8259b(t_bool io, uint8 data, uint8 devnum)
|
uint8 i8259b(t_bool io, uint8 data)
|
||||||
{
|
{
|
||||||
if (devnum >= I8259_NUM) {
|
uint8 devnum;
|
||||||
sim_printf("8259b: Illegal Device Number %d\n", devnum);
|
|
||||||
return 0;
|
if ((devnum = i8259_get_dn()) != 0xFF) {
|
||||||
}
|
if (io == 0) { /* read data port */
|
||||||
if (io == 0) { /* read data port */
|
if ((i8259_ocw3[devnum] & 0x03) == 0x02)
|
||||||
if ((i8259_ocw3[devnum] & 0x03) == 0x02)
|
return (i8259_unit[devnum].u3); /* IRR */
|
||||||
return (i8259_unit[devnum].u3); /* IRR */
|
if ((i8259_ocw3[devnum] & 0x03) == 0x03)
|
||||||
if ((i8259_ocw3[devnum] & 0x03) == 0x03)
|
return (i8259_unit[devnum].u4); /* ISR */
|
||||||
return (i8259_unit[devnum].u4); /* ISR */
|
} else { /* write data port */
|
||||||
} else { /* write data port */
|
if (data & 0x10) {
|
||||||
if (data & 0x10) {
|
icw_num1 = 1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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);
|
// i8259_dump(devnum);
|
||||||
icw_num1++; /* step ICW number */
|
|
||||||
}
|
}
|
||||||
i8259_dump(devnum);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i8259_dump(uint8 devnum)
|
void i8259_dump(uint8 devnum)
|
||||||
{
|
{
|
||||||
sim_printf("Device %d\n", devnum);
|
sim_printf("Device %d", devnum);
|
||||||
sim_printf(" IRR = %02X\n", i8259_unit[devnum].u3);
|
sim_printf(" IRR=%02X", i8259_unit[devnum].u3);
|
||||||
sim_printf(" ISR = %02X\n", i8259_unit[devnum].u4);
|
sim_printf(" ISR=%02X", i8259_unit[devnum].u4);
|
||||||
sim_printf(" IMR = %02X\n", i8259_unit[devnum].u5);
|
sim_printf(" IMR=%02X", i8259_unit[devnum].u5);
|
||||||
sim_printf(" ICW1 = %02X\n", i8259_icw1[devnum]);
|
sim_printf(" ICW1=%02X", i8259_icw1[devnum]);
|
||||||
sim_printf(" ICW2 = %02X\n", i8259_icw2[devnum]);
|
sim_printf(" ICW2=%02X", i8259_icw2[devnum]);
|
||||||
sim_printf(" ICW3 = %02X\n", i8259_icw3[devnum]);
|
sim_printf(" ICW3=%02X", i8259_icw3[devnum]);
|
||||||
sim_printf(" ICW4 = %02X\n", i8259_icw4[devnum]);
|
sim_printf(" ICW4=%02X", i8259_icw4[devnum]);
|
||||||
sim_printf(" OCW1 = %02X\n", i8259_ocw1[devnum]);
|
sim_printf(" OCW1=%02X", i8259_ocw1[devnum]);
|
||||||
sim_printf(" OCW2 = %02X\n", i8259_ocw2[devnum]);
|
sim_printf(" OCW2=%02X", i8259_ocw2[devnum]);
|
||||||
sim_printf(" OCW3 = %02X\n", i8259_ocw3[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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of i8259.c */
|
/* end of i8259.c */
|
||||||
|
|
228
Intel-Systems/common/i8272.c
Normal file
228
Intel-Systems/common/i8272.c
Normal 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 */
|
|
@ -159,7 +159,7 @@ DEBTAB i8273_debug[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE i8273_dev = {
|
DEVICE i8273_dev = {
|
||||||
"8273", //name
|
"I8273", //name
|
||||||
&i8273_unit, //units
|
&i8273_unit, //units
|
||||||
i8273_reg, //registers
|
i8273_reg, //registers
|
||||||
i8273_mod, //modifiers
|
i8273_mod, //modifiers
|
||||||
|
|
|
@ -189,7 +189,7 @@ DEBTAB i8274_debug[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE i8274_dev = {
|
DEVICE i8274_dev = {
|
||||||
"8274", //name
|
"I8274", //name
|
||||||
&i8274_unit, //units
|
&i8274_unit, //units
|
||||||
i8274_reg, //registers
|
i8274_reg, //registers
|
||||||
i8274_mod, //modifiers
|
i8274_mod, //modifiers
|
||||||
|
|
|
@ -40,8 +40,6 @@
|
||||||
|
|
||||||
#include "system_defs.h"
|
#include "system_defs.h"
|
||||||
|
|
||||||
#define SET_XACK(VAL) (xack = VAL)
|
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr);
|
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr);
|
||||||
|
@ -50,8 +48,8 @@ uint8 EPROM_get_mbyte(uint16 addr);
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern UNIT i8255_unit[];
|
extern uint8 i8255_C[4]; //port c byte I/O
|
||||||
extern uint8 xack; /* XACK signal */
|
extern uint8 xack; /* XACK signal */
|
||||||
|
|
||||||
/* SIMH EPROM Standard I/O Data Structures */
|
/* SIMH EPROM Standard I/O Data Structures */
|
||||||
|
|
||||||
|
@ -90,7 +88,8 @@ DEVICE EPROM_dev = {
|
||||||
NULL, //detach
|
NULL, //detach
|
||||||
NULL, //ctxt
|
NULL, //ctxt
|
||||||
DEV_DEBUG, //flags
|
DEV_DEBUG, //flags
|
||||||
0, //dctrl
|
DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl
|
||||||
|
// 0, //dctrl
|
||||||
EPROM_debug, //debflags
|
EPROM_debug, //debflags
|
||||||
NULL, //msize
|
NULL, //msize
|
||||||
NULL //lname
|
NULL //lname
|
||||||
|
@ -142,7 +141,8 @@ t_stat EPROM_attach (UNIT *uptr, CONST char *cptr)
|
||||||
}
|
}
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n");
|
sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n");
|
||||||
fclose(fp);
|
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");
|
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -151,16 +151,14 @@ t_stat EPROM_attach (UNIT *uptr, CONST char *cptr)
|
||||||
|
|
||||||
t_stat EPROM_reset (DEVICE *dptr, uint16 size)
|
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 */
|
if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */
|
||||||
EPROM_unit.capac = size; /* set EPROM size to 0 */
|
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_debug (DEBUG_flow, &EPROM_dev, "Done1\n");
|
||||||
// sim_printf(" EPROM: Available [%04X-%04XH]\n",
|
} else {
|
||||||
// 0, EPROM_unit.capac - 1);
|
sim_printf(" EPROM: Configured %d bytes, Attached to %s\n",
|
||||||
return SCPE_OK;
|
EPROM_unit.capac, EPROM_unit.filename);
|
||||||
}
|
|
||||||
if ((EPROM_unit.flags & UNIT_ATT) == 0) {
|
|
||||||
sim_printf("EPROM: No file attached\n");
|
|
||||||
}
|
}
|
||||||
sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n");
|
sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -172,20 +170,17 @@ uint8 EPROM_get_mbyte(uint16 addr)
|
||||||
{
|
{
|
||||||
uint8 val;
|
uint8 val;
|
||||||
|
|
||||||
if (i8255_unit[0].u5 & 0x01) { /* EPROM enabled */
|
sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr);
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr);
|
if (addr < EPROM_unit.capac) {
|
||||||
if (addr < EPROM_unit.capac) {
|
SET_XACK(1); /* good memory address */
|
||||||
SET_XACK(1); /* good memory address */
|
sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr);
|
||||||
sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr);
|
val = *((uint8 *)EPROM_unit.filebuf + addr);
|
||||||
val = *((uint8 *)EPROM_unit.filebuf + addr);
|
sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val);
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val);
|
return (val & 0xFF);
|
||||||
return (val & 0xFF);
|
} else {
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n");
|
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 */
|
/* end of iEPROM.c */
|
||||||
|
|
|
@ -36,12 +36,12 @@
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
uint8 ioc_cont(t_bool io, uint8 data, uint8 devnum); /* ioc_cont*/
|
uint8 ioc_cont(t_bool io, uint8 data); /* ioc_cont*/
|
||||||
t_stat ioc_cont_reset (DEVICE *dptr, uint16 base, uint8 devnum);
|
t_stat ioc_cont_reset (DEVICE *dptr, uint16 baseport);
|
||||||
|
|
||||||
/* external function prototypes */
|
/* 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 */
|
extern uint32 saved_PC; /* program counter */
|
||||||
|
|
||||||
/* globals */
|
/* globals */
|
||||||
|
@ -98,28 +98,28 @@ DEVICE ioc_cont_dev = {
|
||||||
IN or OUT instruction is issued.
|
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 */
|
/* 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);
|
sim_printf(" ioc_cont[%d]: Reset\n", 0);
|
||||||
reg_dev(ioc_cont, base + 1, devnum);
|
sim_printf(" ioc_cont[%d]: Registered at %04X\n", 0, baseport);
|
||||||
ioc_cont_unit[devnum].u3 = 0x00; /* ipc reset */
|
reg_dev(ioc_cont, baseport, 0);
|
||||||
sim_printf(" ioc_cont[%d]: Reset\n", devnum);
|
reg_dev(ioc_cont, baseport + 1, 0);
|
||||||
sim_printf(" ioc_cont[%d]: Registered at %04X\n", devnum, base);
|
ioc_cont_unit[0].u3 = 0x00; /* ipc reset */
|
||||||
return SCPE_OK;
|
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 */
|
/* end of ioc-cont.c */
|
||||||
|
|
|
@ -29,19 +29,18 @@
|
||||||
|
|
||||||
NOTES:
|
NOTES:
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "system_defs.h" /* system header in system dir */
|
#include "system_defs.h" /* system header in system dir */
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
uint8 ipc_cont(t_bool io, uint8 data, uint8 devnum); /* ipc_cont*/
|
uint8 ipc_cont(t_bool io, uint8 data); /* ipc_cont*/
|
||||||
t_stat ipc_cont_reset (DEVICE *dptr, uint16 base, uint8 devnum);
|
t_stat ipc_cont_reset (DEVICE *dptr, uint16 baseport);
|
||||||
|
|
||||||
/* external function prototypes */
|
/* 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 */
|
/* globals */
|
||||||
|
|
||||||
|
@ -93,68 +92,69 @@ DEVICE ipc_cont_dev = {
|
||||||
NULL //lname
|
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
|
/* I/O instruction handlers, called from the CPU module when an
|
||||||
IN or OUT instruction is issued.
|
IN or OUT instruction is issued.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* IPC control port functions */
|
/* 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 */
|
if (io == 0) { /* read status port */
|
||||||
sim_printf(" ipc_cont: read data=%02X port=%02X returned 0xFF\n", ipc_cont_unit[devnum].u3, devnum);
|
sim_printf(" ipc_cont: read data=%02X ipc_cont_unit[%d].u3=%02X\n",
|
||||||
return ipc_cont_unit[devnum].u3;
|
ipc_cont_unit[0].u3, 0, ipc_cont_unit[0].u3);
|
||||||
|
return ipc_cont_unit[0].u3;
|
||||||
} else { /* write control port */
|
} else { /* write control port */
|
||||||
//this simulates an 74ls259 register
|
//this simulates an 74LS259 register
|
||||||
//d0-d2 address the reg(in reverse order!), d3 is the data to be latched
|
//d0-d2 address the reg(in reverse order!), d3 is the data to be latched (inverted)
|
||||||
switch(data & 0x07) {
|
switch(data & 0x07) {
|
||||||
case 5: //interrupt enable
|
case 5: //interrupt enable 8085 INTR
|
||||||
if(data & 0x08) //bit high
|
if(data & 0x08) //bit low
|
||||||
ipc_cont_unit[0].u3 |= 0x10;
|
ipc_cont_unit[0].u3 &= 0xBF;
|
||||||
else //bit low
|
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;
|
ipc_cont_unit[0].u3 &= 0xEF;
|
||||||
|
else //bit high
|
||||||
|
ipc_cont_unit[0].u3 |= 0x10;
|
||||||
break;
|
break;
|
||||||
case 4: //*selboot
|
case 2: //*startup ROM @ 00000h
|
||||||
if(data & 0x08) //bit high
|
if(data & 0x08) //bit low
|
||||||
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
|
|
||||||
ipc_cont_unit[0].u3 &= 0xFB;
|
ipc_cont_unit[0].u3 &= 0xFB;
|
||||||
|
else //bit high
|
||||||
|
ipc_cont_unit[0].u3 |= 0x04;
|
||||||
break;
|
break;
|
||||||
case 1: //over ride
|
case 1: //override inhibit other multibus users
|
||||||
if(data & 0x08) //bit high
|
if(data & 0x08) //bit low
|
||||||
ipc_cont_unit[0].u3 |= 0x02;
|
|
||||||
else //bit low
|
|
||||||
ipc_cont_unit[0].u3 &= 0xFD;
|
ipc_cont_unit[0].u3 &= 0xFD;
|
||||||
|
else //bit high
|
||||||
|
ipc_cont_unit[0].u3 |= 0x02;
|
||||||
break;
|
break;
|
||||||
case 0: //aux prom enable
|
case 0: //aux prom enable
|
||||||
if(data & 0x08) //bit high
|
if(data & 0x08) //bit low
|
||||||
ipc_cont_unit[0].u3 |= 0x01;
|
|
||||||
else //bit low
|
|
||||||
ipc_cont_unit[0].u3 &= 0xFE;
|
ipc_cont_unit[0].u3 &= 0xFE;
|
||||||
|
else //bit high
|
||||||
|
ipc_cont_unit[0].u3 |= 0x01;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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;
|
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 */
|
/* end of ipc-cont.c */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* iEPROM.c: Intel EPROM simulator for 8-bit SBCs
|
/* ipcEPROM.c: Intel EPROM simulator for 8-bit SBCs
|
||||||
|
|
||||||
Copyright (c) 2010, William A. Beech
|
Copyright (c) 2010, William A. Beech
|
||||||
|
|
||||||
|
@ -40,8 +40,6 @@
|
||||||
|
|
||||||
#include "system_defs.h"
|
#include "system_defs.h"
|
||||||
|
|
||||||
#define SET_XACK(VAL) (xack = VAL)
|
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr);
|
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr);
|
||||||
|
@ -51,6 +49,7 @@ uint8 EPROM_get_mbyte(uint16 addr);
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern uint8 xack; /* XACK signal */
|
extern uint8 xack; /* XACK signal */
|
||||||
|
extern UNIT ipc_cont_unit[];
|
||||||
|
|
||||||
/* SIMH EPROM Standard I/O Data Structures */
|
/* SIMH EPROM Standard I/O Data Structures */
|
||||||
|
|
||||||
|
@ -184,4 +183,4 @@ uint8 EPROM_get_mbyte(uint16 addr)
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of iEPROM.c */
|
/* end of ipcEPROM.c */
|
||||||
|
|
|
@ -48,23 +48,32 @@ t_stat multibus_svc(UNIT *uptr);
|
||||||
t_stat multibus_reset(DEVICE *dptr);
|
t_stat multibus_reset(DEVICE *dptr);
|
||||||
void set_irq(int32 int_num);
|
void set_irq(int32 int_num);
|
||||||
void clr_irq(int32 int_num);
|
void clr_irq(int32 int_num);
|
||||||
uint8 nulldev(t_bool io, uint8 data, uint8 devnum);
|
uint8 nulldev(t_bool io, uint8 data);
|
||||||
uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint16 port, uint8 devnum);
|
extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8);
|
||||||
t_stat multibus_reset (DEVICE *dptr);
|
t_stat multibus_reset (DEVICE *dptr);
|
||||||
uint8 multibus_get_mbyte(uint16 addr);
|
uint8 multibus_get_mbyte(uint16 addr);
|
||||||
|
uint16 multibus_get_mword(uint16 addr);
|
||||||
void multibus_put_mbyte(uint16 addr, uint8 val);
|
void multibus_put_mbyte(uint16 addr, uint8 val);
|
||||||
|
void multibus_put_mword(uint16 addr, uint16 val);
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */
|
extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */
|
||||||
extern void set_cpuint(int32 int_num);
|
extern void set_cpuint(int32 int_num);
|
||||||
extern UNIT zx200a_unit;
|
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 */
|
/* external globals */
|
||||||
|
|
||||||
extern uint8 xack; /* XACK signal */
|
extern uint8 xack; /* XACK signal */
|
||||||
extern int32 int_req; /* i8080 INT 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 */
|
/* multibus Standard SIMH Device Data Structures */
|
||||||
|
|
||||||
|
@ -139,9 +148,14 @@ t_stat multibus_svc(UNIT *uptr)
|
||||||
t_stat multibus_reset(DEVICE *dptr)
|
t_stat multibus_reset(DEVICE *dptr)
|
||||||
{
|
{
|
||||||
SBC_reset(NULL);
|
SBC_reset(NULL);
|
||||||
zx200a_reset(NULL, ZX200A_BASE_DD, 0);
|
|
||||||
zx200a_reset(NULL, ZX200A_BASE_SD, 0);
|
|
||||||
sim_printf(" Multibus: Reset\n");
|
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 */
|
sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
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.
|
address is here, 'nulldev' means no device has been registered.
|
||||||
*/
|
*/
|
||||||
struct idev {
|
struct idev {
|
||||||
uint8 (*routine)(t_bool io, uint8 data, uint8 devnum);
|
uint8 (*routine)(t_bool io, uint8 data);
|
||||||
uint8 devnum;
|
uint8 devnum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -234,7 +248,7 @@ struct idev dev_table[256] = {
|
||||||
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */
|
{&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 */
|
SET_XACK(0); /* set no XACK */
|
||||||
if (flag == 0) /* if we got here, no valid I/O device */
|
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;
|
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 */
|
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 {
|
} 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].routine = routine;
|
||||||
dev_table[port].devnum = devnum;
|
dev_table[port].devnum = devnum;
|
||||||
}
|
}
|
||||||
return 0;
|
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 */
|
/* end of ipcmultibus.c */
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* iRAM8.c: Intel RAM simulator for 8-bit SBCs
|
/* ipcRAM8.c: Intel RAM simulator for 8-bit SBCs
|
||||||
|
|
||||||
Copyright (c) 2011, William A. Beech
|
Copyright (c) 2011, William A. Beech
|
||||||
|
|
||||||
|
@ -38,8 +38,6 @@
|
||||||
|
|
||||||
#include "system_defs.h"
|
#include "system_defs.h"
|
||||||
|
|
||||||
#define SET_XACK(VAL) (xack = VAL)
|
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
t_stat RAM_svc (UNIT *uptr);
|
t_stat RAM_svc (UNIT *uptr);
|
||||||
|
@ -49,7 +47,6 @@ void RAM_put_mbyte(uint16 addr, uint8 val);
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern UNIT i8255_unit[];
|
|
||||||
extern uint8 xack; /* XACK signal */
|
extern uint8 xack; /* XACK signal */
|
||||||
|
|
||||||
/* SIMH RAM Standard I/O Data Structures */
|
/* SIMH RAM Standard I/O Data Structures */
|
||||||
|
@ -126,39 +123,23 @@ uint8 RAM_get_mbyte(uint16 addr)
|
||||||
{
|
{
|
||||||
uint8 val;
|
uint8 val;
|
||||||
|
|
||||||
if (i8255_unit[0].u5 & 0x02) { /* enable RAM */
|
sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr);
|
||||||
sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr);
|
SET_XACK(1); /* good memory address */
|
||||||
if ((addr >= RAM_unit.u3) && ((uint32) addr < (RAM_unit.u3 + RAM_unit.capac))) {
|
sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr);
|
||||||
SET_XACK(1); /* good memory address */
|
val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3));
|
||||||
sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr);
|
sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val);
|
||||||
val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3));
|
return (val & 0xFF);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put a byte to memory */
|
/* put a byte to memory */
|
||||||
|
|
||||||
void RAM_put_mbyte(uint16 addr, uint8 val)
|
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);
|
||||||
sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val);
|
SET_XACK(1); /* good memory address */
|
||||||
if ((addr >= RAM_unit.u3) && ((uint32)addr < RAM_unit.u3 + RAM_unit.capac)) {
|
sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr);
|
||||||
SET_XACK(1); /* good memory address */
|
*((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF;
|
||||||
sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr);
|
sim_debug (DEBUG_write, &RAM_dev, "\n");
|
||||||
*((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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of iRAM8.c */
|
/* end of ipcRAM8.c */
|
||||||
|
|
|
@ -38,19 +38,16 @@
|
||||||
|
|
||||||
#include "system_defs.h"
|
#include "system_defs.h"
|
||||||
|
|
||||||
#define SET_XACK(VAL) (xack = VAL)
|
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
t_stat RAM_svc (UNIT *uptr);
|
|
||||||
t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size);
|
t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size);
|
||||||
uint8 RAM_get_mbyte(uint16 addr);
|
uint8 RAM_get_mbyte(uint16 addr);
|
||||||
void RAM_put_mbyte(uint16 addr, uint8 val);
|
void RAM_put_mbyte(uint16 addr, uint8 val);
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern UNIT i8255_unit[];
|
extern uint8 i8255_B[4]; //port B byte I/O
|
||||||
extern uint8 xack; /* XACK signal */
|
extern uint8 xack; /* XACK signal */
|
||||||
|
|
||||||
/* SIMH RAM Standard I/O Data Structures */
|
/* SIMH RAM Standard I/O Data Structures */
|
||||||
|
|
||||||
|
@ -93,8 +90,6 @@ DEVICE RAM_dev = {
|
||||||
NULL //lname
|
NULL //lname
|
||||||
};
|
};
|
||||||
|
|
||||||
/* global variables */
|
|
||||||
|
|
||||||
/* RAM functions */
|
/* RAM functions */
|
||||||
|
|
||||||
/* RAM reset */
|
/* RAM reset */
|
||||||
|
@ -113,9 +108,9 @@ t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size)
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// sim_printf(" RAM: Available [%04X-%04XH]\n",
|
sim_printf(" RAM: Available [%04X-%04XH]\n",
|
||||||
// RAM_unit.u3,
|
RAM_unit.u3,
|
||||||
// RAM_unit.u3 + RAM_unit.capac - 1);
|
RAM_unit.u3 + RAM_unit.capac - 1);
|
||||||
sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n");
|
sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -126,39 +121,34 @@ uint8 RAM_get_mbyte(uint16 addr)
|
||||||
{
|
{
|
||||||
uint8 val;
|
uint8 val;
|
||||||
|
|
||||||
if (i8255_unit[0].u5 & 0x02) { /* enable RAM */
|
sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr);
|
||||||
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))) {
|
||||||
if ((addr >= RAM_unit.u3) && ((uint32) addr < (RAM_unit.u3 + RAM_unit.capac))) {
|
SET_XACK(1); /* good memory address */
|
||||||
SET_XACK(1); /* good memory address */
|
sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr);
|
||||||
sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr);
|
val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3));
|
||||||
val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3));
|
sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val);
|
||||||
sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val);
|
return (val & 0xFF);
|
||||||
return (val & 0xFF);
|
} else {
|
||||||
}
|
|
||||||
sim_debug (DEBUG_read, &RAM_dev, " Out of range\n");
|
sim_debug (DEBUG_read, &RAM_dev, " Out of range\n");
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
sim_debug (DEBUG_read, &RAM_dev, " RAM disabled\n");
|
|
||||||
return 0xFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put a byte to memory */
|
/* put a byte to memory */
|
||||||
|
|
||||||
void RAM_put_mbyte(uint16 addr, uint8 val)
|
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);
|
||||||
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)) {
|
||||||
if ((addr >= RAM_unit.u3) && ((uint32)addr < RAM_unit.u3 + RAM_unit.capac)) {
|
SET_XACK(1); /* good memory address */
|
||||||
SET_XACK(1); /* good memory address */
|
sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr);
|
||||||
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;
|
||||||
*((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF;
|
sim_debug (DEBUG_write, &RAM_dev, "\n");
|
||||||
sim_debug (DEBUG_write, &RAM_dev, "\n");
|
return;
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
sim_debug (DEBUG_write, &RAM_dev, " Out of range\n");
|
sim_debug (DEBUG_write, &RAM_dev, " Out of range\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sim_debug (DEBUG_write, &RAM_dev, " RAM disabled\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of iRAM8.c */
|
/* end of iRAM8.c */
|
||||||
|
|
|
@ -77,7 +77,8 @@ DEVICE isbc064_dev = {
|
||||||
8, //dwidth
|
8, //dwidth
|
||||||
NULL, //examine
|
NULL, //examine
|
||||||
NULL, //deposite
|
NULL, //deposite
|
||||||
&isbc064_reset, //reset
|
// &isbc064_reset, //reset
|
||||||
|
NULL, //reset
|
||||||
NULL, //boot
|
NULL, //boot
|
||||||
NULL, //attach
|
NULL, //attach
|
||||||
NULL, //detach
|
NULL, //detach
|
||||||
|
@ -99,7 +100,8 @@ t_stat isbc064_reset (DEVICE *dptr)
|
||||||
if ((isbc064_dev.flags & DEV_DIS) == 0) {
|
if ((isbc064_dev.flags & DEV_DIS) == 0) {
|
||||||
isbc064_unit.capac = SBC064_SIZE;
|
isbc064_unit.capac = SBC064_SIZE;
|
||||||
isbc064_unit.u3 = SBC064_BASE;
|
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.u3 + isbc064_unit.capac - 1);
|
isbc064_unit.u3 + isbc064_unit.capac - 1);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +121,6 @@ t_stat isbc064_reset (DEVICE *dptr)
|
||||||
uint8 isbc064_get_mbyte(uint16 addr)
|
uint8 isbc064_get_mbyte(uint16 addr)
|
||||||
{
|
{
|
||||||
uint32 val, org, len;
|
uint32 val, org, len;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if ((isbc064_dev.flags & DEV_DIS) == 0) {
|
if ((isbc064_dev.flags & DEV_DIS) == 0) {
|
||||||
org = isbc064_unit.u3;
|
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);
|
sim_debug (DEBUG_xack, &isbc064_dev, "isbc064_get_mbyte: Set XACK for %04X\n", addr);
|
||||||
val = *((uint8 *)isbc064_unit.filebuf + (addr - org));
|
val = *((uint8 *)isbc064_unit.filebuf + (addr - org));
|
||||||
sim_debug (DEBUG_read, &isbc064_dev, " val=%04X\n", val);
|
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);
|
return (val & 0xFF);
|
||||||
} else {
|
} else {
|
||||||
sim_debug (DEBUG_read, &isbc064_dev, " Out of range\n");
|
sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Out of range\n");
|
||||||
return 0xFF; /* multibus has active high pullups */
|
return 0; /* multibus has active high pullups and inversion */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sim_debug (DEBUG_read, &isbc064_dev, " Disabled\n");
|
sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Disabled\n");
|
||||||
return 0xFF; /* multibus has active high pullups */
|
// sim_printf ("isbc064_get_mbyte: Disabled\n");
|
||||||
|
return 0; /* multibus has active high pullups and inversion */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put a byte into memory */
|
/* put a byte into memory */
|
||||||
|
@ -146,11 +149,11 @@ uint8 isbc064_get_mbyte(uint16 addr)
|
||||||
void isbc064_put_mbyte(uint16 addr, uint8 val)
|
void isbc064_put_mbyte(uint16 addr, uint8 val)
|
||||||
{
|
{
|
||||||
uint32 org, len;
|
uint32 org, len;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if ((isbc064_dev.flags & DEV_DIS) == 0) {
|
if ((isbc064_dev.flags & DEV_DIS) == 0) {
|
||||||
org = isbc064_unit.u3;
|
org = isbc064_unit.u3;
|
||||||
len = isbc064_unit.capac;
|
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: addr=%04X, val=%02X\n", addr, val);
|
||||||
sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: org=%04X, len=%04X\n", org, len);
|
sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: org=%04X, len=%04X\n", org, len);
|
||||||
if ((addr >= org) && (addr < (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");
|
sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Return\n");
|
||||||
return;
|
return;
|
||||||
} else {
|
} 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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Disabled\n");
|
sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Disabled\n");
|
||||||
|
// sim_printf ("isbc064_put_mbyte: Disabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of isbc064.c */
|
/* end of isbc064.c */
|
||||||
|
|
681
Intel-Systems/common/isbc201.c
Normal file
681
Intel-Systems/common/isbc201.c
Normal 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 */
|
|
@ -29,31 +29,241 @@
|
||||||
|
|
||||||
NOTES:
|
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 */
|
#include "system_defs.h" /* system header in system dir */
|
||||||
|
|
||||||
/* function prototypes */
|
#define DEBUG 0
|
||||||
|
|
||||||
uint8 isbc202(t_bool io, uint8 data, uint8 devnum); /* isbc202*/
|
#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */
|
||||||
t_stat isbc202_reset(DEVICE *dptr, uint16 base, uint8 devnum);
|
#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 */
|
/* 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 */
|
/* 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[] = {
|
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[] = {
|
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 }
|
{ 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[] = {
|
DEBTAB isbc202_debug[] = {
|
||||||
{ "ALL", DEBUG_all },
|
{ "ALL", DEBUG_all },
|
||||||
{ "FLOW", DEBUG_flow },
|
{ "FLOW", DEBUG_flow },
|
||||||
|
@ -68,11 +278,11 @@ DEBTAB isbc202_debug[] = {
|
||||||
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
|
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
|
||||||
|
|
||||||
DEVICE isbc202_dev = {
|
DEVICE isbc202_dev = {
|
||||||
"ISBC202", //name
|
"SBC202", //name
|
||||||
isbc202_unit, //units
|
isbc202_unit, //units
|
||||||
isbc202_reg, //registers
|
isbc202_reg, //registers
|
||||||
NULL, //modifiers
|
isbc202_mod, //modifiers
|
||||||
1, //numunits
|
FDD_NUM, //numunits
|
||||||
16, //aradix
|
16, //aradix
|
||||||
16, //awidth
|
16, //awidth
|
||||||
1, //aincr
|
1, //aincr
|
||||||
|
@ -80,51 +290,449 @@ DEVICE isbc202_dev = {
|
||||||
8, //dwidth
|
8, //dwidth
|
||||||
NULL, //examine
|
NULL, //examine
|
||||||
NULL, //deposit
|
NULL, //deposit
|
||||||
// &isbc202_reset, //reset
|
NULL, //reset
|
||||||
NULL, //reset
|
|
||||||
NULL, //boot
|
NULL, //boot
|
||||||
NULL, //attach
|
&isbc202_attach, //attach
|
||||||
NULL, //detach
|
NULL, //detach
|
||||||
NULL, //ctxt
|
NULL, //ctxt
|
||||||
0, //flags
|
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
|
||||||
0, //dctrl
|
DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl
|
||||||
isbc202_debug, //debflags
|
isbc202_debug, //debflags
|
||||||
NULL, //msize
|
NULL, //msize
|
||||||
NULL //lname
|
NULL //lname
|
||||||
};
|
};
|
||||||
|
|
||||||
/* I/O instruction handlers, called from the CPU module when an
|
/* Hardware reset routine */
|
||||||
IN or OUT instruction is issued.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ISBC202 control port functions */
|
t_stat isbc202_reset(DEVICE *dptr, uint16 base)
|
||||||
|
|
||||||
uint8 isbc202(t_bool io, uint8 data, uint8 devnum)
|
|
||||||
{
|
{
|
||||||
if (io == 0) { /* always return 0 */
|
sim_printf("Initializing iSBC-202 FDC Board\n");
|
||||||
sim_printf(" isbc202: read data=%02X port=%02X returned 0\n", data, devnum);
|
if (SBC202_NUM) {
|
||||||
return 0x00;
|
sim_printf(" isbc202-%d: Hardware Reset\n", isbc202_fdcnum);
|
||||||
} else { /* write control port */
|
sim_printf(" isbc202-%d: Registered at %04X\n", isbc202_fdcnum, base);
|
||||||
sim_printf(" isbc202: data=%02X port=%02X\n", data, devnum);
|
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
|
||||||
/* Reset routine */
|
reg_dev(isbc2023, base + 3, isbc202_fdcnum); //read rstl byte
|
||||||
|
reg_dev(isbc2027, base + 7, isbc202_fdcnum); //write reset isbc202
|
||||||
t_stat isbc202_reset(DEVICE *dptr, uint16 base, uint8 devnum)
|
isbc202_reset1(isbc202_fdcnum);
|
||||||
{
|
isbc202_fdcnum++;
|
||||||
reg_dev(isbc202, base, devnum);
|
} else
|
||||||
reg_dev(isbc202, base + 1, devnum);
|
sim_printf(" No isbc202 installed\n");
|
||||||
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);
|
|
||||||
return SCPE_OK;
|
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 */
|
/* end of isbc202.c */
|
||||||
|
|
|
@ -473,41 +473,44 @@
|
||||||
|
|
||||||
#define FDD_NUM 4
|
#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 */
|
/* internal function prototypes */
|
||||||
|
|
||||||
t_stat isbc208_svc (UNIT *uptr);
|
t_stat isbc208_svc (UNIT *uptr);
|
||||||
t_stat isbc208_reset (DEVICE *dptr);
|
t_stat isbc208_reset (DEVICE *dptr, uint16 base);
|
||||||
void isbc208_reset1 (void);
|
void isbc208_reset1 (void);
|
||||||
t_stat isbc208_attach (UNIT *uptr, CONST char *cptr);
|
t_stat isbc208_attach (UNIT *uptr, CONST char *cptr);
|
||||||
t_stat isbc208_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
t_stat isbc208_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
uint8 isbc208_r0(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r0(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r1(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r1(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r2(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r2(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r3(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r3(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r4(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r4(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r5(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r5(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r6(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r6(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r7(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r7(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r8(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r8(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r9(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r9(t_bool io, uint8 data);
|
||||||
uint8 isbc208_rA(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_rA(t_bool io, uint8 data);
|
||||||
uint8 isbc208_rB(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_rB(t_bool io, uint8 data);
|
||||||
uint8 isbc208_rC(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_rC(t_bool io, uint8 data);
|
||||||
uint8 isbc208_rD(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_rD(t_bool io, uint8 data);
|
||||||
uint8 isbc208_rE(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_rE(t_bool io, uint8 data);
|
||||||
uint8 isbc208_rF(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_rF(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r10(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r10(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r11(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r11(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r12(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r12(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r13(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r13(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r14(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r14(t_bool io, uint8 data);
|
||||||
uint8 isbc208_r15(t_bool io, uint8 data, uint8 devnum);
|
uint8 isbc208_r15(t_bool io, uint8 data);
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern void set_irq(int32 int_num);
|
extern void set_irq(int32 int_num);
|
||||||
extern void clr_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 void multibus_put_mbyte(uint16 addr, uint8 val);
|
||||||
extern uint8 multibus_get_mbyte(uint16 addr);
|
extern uint8 multibus_get_mbyte(uint16 addr);
|
||||||
|
|
||||||
|
@ -669,14 +672,15 @@ DEVICE isbc208_dev = {
|
||||||
8, //dwidth
|
8, //dwidth
|
||||||
NULL, //examine
|
NULL, //examine
|
||||||
NULL, //deposit
|
NULL, //deposit
|
||||||
&isbc208_reset, //deposit
|
// &isbc208_reset, //deposit
|
||||||
|
NULL, //deposit
|
||||||
NULL, //boot
|
NULL, //boot
|
||||||
&isbc208_attach, //attach
|
&isbc208_attach, //attach
|
||||||
NULL, //detach
|
NULL, //detach
|
||||||
NULL, //ctxt
|
NULL, //ctxt
|
||||||
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
|
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
|
||||||
0, //dctrl
|
// 0, //dctrl
|
||||||
// DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl
|
DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl
|
||||||
isbc208_debug, //debflags
|
isbc208_debug, //debflags
|
||||||
NULL, //msize
|
NULL, //msize
|
||||||
NULL //lname
|
NULL //lname
|
||||||
|
@ -957,32 +961,43 @@ t_stat isbc208_svc (UNIT *uptr)
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
||||||
t_stat isbc208_reset (DEVICE *dptr)
|
t_stat isbc208_reset (DEVICE *dptr, uint16 base)
|
||||||
{
|
{
|
||||||
reg_dev(isbc208_r0, SBC208_BASE + 0, 0);
|
if (sbc208_devnum > SBC208_NUM) {
|
||||||
reg_dev(isbc208_r1, SBC208_BASE + 1, 0);
|
sim_printf("sbc208_reset: too many devices!\n");
|
||||||
reg_dev(isbc208_r2, SBC208_BASE + 2, 0);
|
return SCPE_MEM;
|
||||||
reg_dev(isbc208_r3, SBC208_BASE + 3, 0);
|
}
|
||||||
reg_dev(isbc208_r4, SBC208_BASE + 4, 0);
|
if (SBC202_NUM) {
|
||||||
reg_dev(isbc208_r5, SBC208_BASE + 5, 0);
|
sim_printf(" SBC208-%d: Hardware Reset\n", sbc208_devnum);
|
||||||
reg_dev(isbc208_r6, SBC208_BASE + 6, 0);
|
sim_printf(" SBC208-%d: Registered at %04X\n", sbc208_devnum, base);
|
||||||
reg_dev(isbc208_r7, SBC208_BASE + 7, 0);
|
sbc208_port[sbc208_devnum] = reg_dev(isbc208_r0, SBC208_BASE + 0, sbc208_devnum);
|
||||||
reg_dev(isbc208_r8, SBC208_BASE + 8, 0);
|
reg_dev(isbc208_r1, SBC208_BASE + 1, sbc208_devnum);
|
||||||
reg_dev(isbc208_r9, SBC208_BASE + 9, 0);
|
reg_dev(isbc208_r2, SBC208_BASE + 2, sbc208_devnum);
|
||||||
reg_dev(isbc208_rA, SBC208_BASE + 10, 0);
|
reg_dev(isbc208_r3, SBC208_BASE + 3, sbc208_devnum);
|
||||||
reg_dev(isbc208_rB, SBC208_BASE + 11, 0);
|
reg_dev(isbc208_r4, SBC208_BASE + 4, sbc208_devnum);
|
||||||
reg_dev(isbc208_rC, SBC208_BASE + 12, 0);
|
reg_dev(isbc208_r5, SBC208_BASE + 5, sbc208_devnum);
|
||||||
reg_dev(isbc208_rD, SBC208_BASE + 13, 0);
|
reg_dev(isbc208_r6, SBC208_BASE + 6, sbc208_devnum);
|
||||||
reg_dev(isbc208_rE, SBC208_BASE + 14, 0);
|
reg_dev(isbc208_r7, SBC208_BASE + 7, sbc208_devnum);
|
||||||
reg_dev(isbc208_rF, SBC208_BASE + 15, 0);
|
reg_dev(isbc208_r8, SBC208_BASE + 8, sbc208_devnum);
|
||||||
reg_dev(isbc208_r10, SBC208_BASE + 16, 0);
|
reg_dev(isbc208_r9, SBC208_BASE + 9, sbc208_devnum);
|
||||||
reg_dev(isbc208_r11, SBC208_BASE + 17, 0);
|
reg_dev(isbc208_rA, SBC208_BASE + 10, sbc208_devnum);
|
||||||
reg_dev(isbc208_r12, SBC208_BASE + 18, 0);
|
reg_dev(isbc208_rB, SBC208_BASE + 11, sbc208_devnum);
|
||||||
reg_dev(isbc208_r13, SBC208_BASE + 19, 0);
|
reg_dev(isbc208_rC, SBC208_BASE + 12, sbc208_devnum);
|
||||||
reg_dev(isbc208_r14, SBC208_BASE + 20, 0);
|
reg_dev(isbc208_rD, SBC208_BASE + 13, sbc208_devnum);
|
||||||
reg_dev(isbc208_r15, SBC208_BASE + 21, 0);
|
reg_dev(isbc208_rE, SBC208_BASE + 14, sbc208_devnum);
|
||||||
if ((isbc208_dev.flags & DEV_DIS) == 0)
|
reg_dev(isbc208_rF, SBC208_BASE + 15, sbc208_devnum);
|
||||||
isbc208_reset1();
|
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;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1023,6 +1038,7 @@ void isbc208_reset1 (void)
|
||||||
i8272_msr = RQM; /* 8272 ready for start of command */
|
i8272_msr = RQM; /* 8272 ready for start of command */
|
||||||
rsp = wsp = 0; /* reset indexes */
|
rsp = wsp = 0; /* reset indexes */
|
||||||
cmd = 0; /* clear command */
|
cmd = 0; /* clear command */
|
||||||
|
sim_printf(" SBC208-%d: Software Reset\n", sbc208_devnum);
|
||||||
if (flag) {
|
if (flag) {
|
||||||
sim_printf(" 8237 Reset\n");
|
sim_printf(" 8237 Reset\n");
|
||||||
sim_printf(" 8272 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.
|
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 (io == 0) { /* read current address CH 0 */
|
||||||
if (i8237_rD) { /* high byte */
|
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 (io == 0) { /* read current word count CH 0 */
|
||||||
if (i8237_rD) { /* high byte */
|
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 (io == 0) { /* read current address CH 1 */
|
||||||
if (i8237_rD) { /* high byte */
|
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 (io == 0) { /* read current word count CH 1 */
|
||||||
if (i8237_rD) { /* high byte */
|
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 (io == 0) { /* read current address CH 2 */
|
||||||
if (i8237_rD) { /* high byte */
|
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 (io == 0) { /* read current word count CH 2 */
|
||||||
if (i8237_rD) { /* high byte */
|
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 (io == 0) { /* read current address CH 3 */
|
||||||
if (i8237_rD) { /* high byte */
|
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 (io == 0) { /* read current word count CH 3 */
|
||||||
if (i8237_rD) { /* high byte */
|
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 */
|
if (io == 0) { /* read status register */
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "i8237_r8 (status) read as %02X\n", i8237_r8);
|
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) {
|
if (io == 0) {
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r9\n");
|
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) {
|
if (io == 0) {
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rA\n");
|
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) {
|
if (io == 0) {
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rB\n");
|
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) {
|
if (io == 0) {
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rC\n");
|
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 */
|
if (io == 0) { /* read temporary register */
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rD\n");
|
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) {
|
if (io == 0) {
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rE\n");
|
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) {
|
if (io == 0) {
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_rF\n");
|
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 */
|
if (io == 0) { /* read FDC status register */
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "i8272_msr read as %02X\n", i8272_msr);
|
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
|
// 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 */
|
if (io == 0) { /* read FDC data register */
|
||||||
wsp = 0; /* clear write stack index */
|
wsp = 0; /* clear write stack index */
|
||||||
|
@ -1580,7 +1596,7 @@ uint8 isbc208_r11(t_bool io, uint8 data, uint8 devnum)
|
||||||
return 0;
|
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 */
|
if (io == 0) { /* read interrupt status */
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "isbc208_r12 read as %02X\n", isbc208_i);
|
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) {
|
if (io == 0) {
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r13\n");
|
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) {
|
if (io == 0) {
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r14\n");
|
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) {
|
if (io == 0) {
|
||||||
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r15\n");
|
sim_debug (DEBUG_reg, &isbc208_dev, "Illegal read of isbc208_r15\n");
|
||||||
|
|
|
@ -38,8 +38,6 @@
|
||||||
|
|
||||||
#include "system_defs.h"
|
#include "system_defs.h"
|
||||||
|
|
||||||
#define SET_XACK(VAL) (xack = VAL)
|
|
||||||
|
|
||||||
int32 mbirq = 0; /* set no multibus interrupts */
|
int32 mbirq = 0; /* set no multibus interrupts */
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
@ -48,8 +46,8 @@ t_stat multibus_svc(UNIT *uptr);
|
||||||
t_stat multibus_reset(DEVICE *dptr);
|
t_stat multibus_reset(DEVICE *dptr);
|
||||||
void set_irq(int32 int_num);
|
void set_irq(int32 int_num);
|
||||||
void clr_irq(int32 int_num);
|
void clr_irq(int32 int_num);
|
||||||
uint8 nulldev(t_bool io, uint8 data, uint8 devnum);
|
uint8 nulldev(t_bool io, uint8 data);
|
||||||
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);
|
||||||
t_stat multibus_reset (DEVICE *dptr);
|
t_stat multibus_reset (DEVICE *dptr);
|
||||||
uint8 multibus_get_mbyte(uint16 addr);
|
uint8 multibus_get_mbyte(uint16 addr);
|
||||||
void multibus_put_mbyte(uint16 addr, uint8 val);
|
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 void set_cpuint(int32 int_num);
|
||||||
extern t_stat SBC_reset (DEVICE *dptr);
|
extern t_stat SBC_reset (DEVICE *dptr);
|
||||||
extern t_stat isbc064_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 */
|
/* external globals */
|
||||||
|
|
||||||
extern uint8 xack; /* XACK signal */
|
extern uint8 xack; /* XACK signal */
|
||||||
extern int32 int_req; /* i8080 INT signal */
|
extern int32 int_req; /* i8080 INT signal */
|
||||||
|
extern int32 isbc201_fdcnum;
|
||||||
|
extern int32 isbc202_fdcnum;
|
||||||
|
|
||||||
/* multibus Standard SIMH Device Data Structures */
|
/* multibus Standard SIMH Device Data Structures */
|
||||||
|
|
||||||
|
@ -124,7 +125,7 @@ t_stat multibus_svc(UNIT *uptr)
|
||||||
switch (mbirq) {
|
switch (mbirq) {
|
||||||
case INT_1:
|
case INT_1:
|
||||||
set_cpuint(INT_R);
|
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);
|
// sim_printf("multibus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -140,9 +141,12 @@ t_stat multibus_svc(UNIT *uptr)
|
||||||
t_stat multibus_reset(DEVICE *dptr)
|
t_stat multibus_reset(DEVICE *dptr)
|
||||||
{
|
{
|
||||||
SBC_reset(NULL);
|
SBC_reset(NULL);
|
||||||
isbc064_reset(NULL);
|
sim_printf("Initializing Multibus Boards\n Multibus Boards:\n");
|
||||||
isbc208_reset(NULL);
|
isbc064_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 */
|
sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
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.
|
address is here, 'nulldev' means no device has been registered.
|
||||||
*/
|
*/
|
||||||
struct idev {
|
struct idev {
|
||||||
uint8 (*routine)(t_bool io, uint8 data, uint8 devnum);
|
uint8 (*routine)(t_bool io, uint8 data);
|
||||||
|
uint16 port;
|
||||||
uint8 devnum;
|
uint8 devnum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -235,24 +240,27 @@ struct idev dev_table[256] = {
|
||||||
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */
|
{&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 */
|
SET_XACK(0); /* set no XACK */
|
||||||
if (flag == 0) /* if we got here, no valid I/O device */
|
// if (flag == 0) /* if we got here, no valid I/O device */
|
||||||
return (0xFF);
|
// return (0xFF);
|
||||||
return 0;
|
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 */
|
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 {
|
} 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].routine = routine;
|
||||||
dev_table[port].devnum = devnum;
|
dev_table[port].devnum = devnum;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get a byte from memory */
|
/* get a byte from memory */
|
||||||
|
@ -264,6 +272,17 @@ uint8 multibus_get_mbyte(uint16 addr)
|
||||||
return isbc064_get_mbyte(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 */
|
/* put a byte to memory */
|
||||||
|
|
||||||
void multibus_put_mbyte(uint16 addr, uint8 val)
|
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);
|
// 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 */
|
/* end of multibus.c */
|
||||||
|
|
||||||
|
|
|
@ -131,80 +131,138 @@
|
||||||
|
|
||||||
#include "system_defs.h" /* system header in system dir */
|
#include "system_defs.h" /* system header in system dir */
|
||||||
|
|
||||||
|
#define DEBUG 1
|
||||||
|
|
||||||
#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */
|
#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */
|
||||||
#define UNIT_WPMODE (1 << UNIT_V_WPMODE)
|
#define UNIT_WPMODE (1 << UNIT_V_WPMODE)
|
||||||
|
|
||||||
#define FDD_NUM 4
|
#define FDD_NUM 4
|
||||||
|
|
||||||
#define WP 0x40 /* Write protect */
|
//disk controoler operations
|
||||||
#define RDY 0x20 /* Ready */
|
#define DNOP 0x00 //disk no operation
|
||||||
#define T0 0x10 /* Track 0 */
|
#define DSEEK 0x01 //disk seek
|
||||||
#define TS 0x08 /* Two sided */
|
#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);
|
//result type
|
||||||
uint8 zx200a0(t_bool io, uint8 data, uint8 devnum);
|
#define RERR 0x00 //FDC returned error
|
||||||
uint8 zx200a1(t_bool io, uint8 data, uint8 devnum);
|
#define ROK 0x02 //FDC returned ok
|
||||||
uint8 zx200a2(t_bool io, uint8 data, uint8 devnum);
|
|
||||||
uint8 zx200a3(t_bool io, uint8 data, uint8 devnum);
|
// If result type is RERR then rbyte is
|
||||||
uint8 zx200a7(t_bool io, uint8 data, uint8 devnum);
|
#define RB0DR 0x01 //deleted record
|
||||||
t_stat zx200a_attach (UNIT *uptr, CONST char *cptr);
|
#define RB0CRC 0x02 //CRC error
|
||||||
t_stat zx200a_reset(DEVICE *dptr, uint16 base, uint8 devnum);
|
#define RB0SEK 0x04 //seek error
|
||||||
void zx200a_reset1(void);
|
#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 */
|
/* 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 */
|
/* globals */
|
||||||
|
|
||||||
uint16 iopb;
|
int32 zx200a_fdcnum = 0; //actual number of SBC-202 instances + 1
|
||||||
uint8 syssta = 0, rsttyp = 0, rstbyt1 = 0, rstbyt2 = 0, cmd = 0;
|
|
||||||
|
|
||||||
uint8 *zx200a_buf[FDD_NUM] = { /* FDD buffer pointers */
|
typedef struct { //FDD definition
|
||||||
NULL,
|
uint8 *buf;
|
||||||
NULL,
|
int t0;
|
||||||
NULL,
|
int rdy;
|
||||||
NULL
|
uint8 maxsec;
|
||||||
};
|
uint8 maxcyl;
|
||||||
|
} FDDDEF;
|
||||||
|
|
||||||
int32 fddst[FDD_NUM] = { // fdd status
|
typedef struct { //FDC definition
|
||||||
0, // status of FDD 0
|
uint16 baseport; //FDC base port
|
||||||
0, // status of FDD 1
|
uint16 iopb; //FDC IOPB
|
||||||
0, // status of FDD 2
|
uint8 stat; //FDC status
|
||||||
0 // status of FDD 3
|
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
|
FDCDEF zx200a[4]; //indexed by the isbc-202 instance number
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
UNIT zx200a_unit[] = {
|
UNIT zx200a_unit[] = {
|
||||||
{ UDATA (&zx200a_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
||||||
{ UDATA (&zx200a_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
||||||
{ UDATA (&zx200a_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 },
|
||||||
{ UDATA (&zx200a_svc, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }
|
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE, 0), 20 }
|
||||||
};
|
};
|
||||||
|
|
||||||
REG zx200a_reg[] = {
|
REG zx200a_reg[] = {
|
||||||
{ HRDATA (SUBSYSSTA, zx200a_unit[0].u3, 8) }, /* subsytem status */
|
{ HRDATA (STAT0, zx200a[0].stat, 8) }, /* zx200a 0 status */
|
||||||
{ HRDATA (RSTTYP, zx200a_unit[0].u4, 8) }, /* result type */
|
{ HRDATA (RTYP0, zx200a[0].rtype, 8) }, /* zx200a 0 result type */
|
||||||
{ HRDATA (RSTBYT0, zx200a_unit[0].u5, 8) }, /* result byte 0 RSTTYP = 0*/
|
{ HRDATA (RBYT0A, zx200a[0].rbyte0, 8) }, /* zx200a 0 result byte 0 */
|
||||||
{ HRDATA (RSTBYT1, zx200a_unit[0].u6, 8) }, /* result byte 1 RSTTYP = 10*/
|
{ 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 }
|
{ 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[] = {
|
DEBTAB zx200a_debug[] = {
|
||||||
{ "ALL", DEBUG_all },
|
{ "ALL", DEBUG_all },
|
||||||
{ "FLOW", DEBUG_flow },
|
{ "FLOW", DEBUG_flow },
|
||||||
|
@ -234,12 +292,12 @@ DEVICE zx200a_dev = {
|
||||||
// &zx200a_reset, //reset
|
// &zx200a_reset, //reset
|
||||||
NULL, //reset
|
NULL, //reset
|
||||||
NULL, //boot
|
NULL, //boot
|
||||||
NULL, //attach
|
&zx200a_attach, //attach
|
||||||
NULL, //detach
|
NULL, //detach
|
||||||
NULL, //ctxt
|
NULL, //ctxt
|
||||||
0, //flags
|
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
|
||||||
0, //dctrl
|
DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl
|
||||||
zx200a_debug, //debflags
|
zx200a_debug, //debflags
|
||||||
NULL, //msize
|
NULL, //msize
|
||||||
NULL //lname
|
NULL //lname
|
||||||
};
|
};
|
||||||
|
@ -250,79 +308,68 @@ DEVICE zx200a_dev = {
|
||||||
|
|
||||||
/* Service routines to handle simulator functions */
|
/* 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;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* zx200a control port functions */
|
void zx200a_reset1(uint8 fdcnum)
|
||||||
|
|
||||||
uint8 zx200a0(t_bool io, uint8 data, uint8 devnum)
|
|
||||||
{
|
{
|
||||||
int val;
|
int32 i;
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
if (io == 0) { /* read operation */
|
sim_printf(" ZX-200A-%d: Initializing\n", fdcnum);
|
||||||
val = zx200a_unit[0].u3;
|
zx200a[fdcnum].stat = 0; //clear status
|
||||||
sim_printf(" zx200a0: read data=%02X devnum=%02X val=%02X\n", data, devnum, val);
|
for (i = 0; i < FDD_NUM; i++) { /* handle all units */
|
||||||
return val;
|
uptr = zx200a_dev.units + i;
|
||||||
} else { /* write control port */
|
zx200a[fdcnum].stat |= FDCPRE | FDCDD; //set the FDC status
|
||||||
sim_printf(" zx200a0: write data=%02X port=%02X\n", data, devnum);
|
zx200a[fdcnum].rtype = ROK;
|
||||||
}
|
if (uptr->capac == 0) { /* if not configured */
|
||||||
}
|
uptr->capac = 0; /* initialize unit */
|
||||||
|
uptr->u4 = 0;
|
||||||
uint8 zx200a1(t_bool io, uint8 data, uint8 devnum)
|
uptr->u5 = fdcnum; //fdc device number
|
||||||
{
|
uptr->u6 = i; /* unit number - only set here! */
|
||||||
int val;
|
uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */
|
||||||
|
sim_printf(" ZX-200A%d: Configured, Status=%02X Not attached\n", i, zx200a[fdcnum].stat);
|
||||||
if (io == 0) { /* read operation */
|
} else {
|
||||||
val = zx200a_unit[0].u4;
|
switch(i){
|
||||||
sim_printf(" zx200a1: read data=%02X devnum=%02X val=%02X\n", data, devnum, val);
|
case 0:
|
||||||
return val;
|
zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready
|
||||||
} else { /* write control port */
|
zx200a[fdcnum].rbyte1 |= RB1RD0;
|
||||||
iopb = data;
|
break;
|
||||||
sim_printf(" zx200a1: write data=%02X port=%02X iopb=%04X\n", data, devnum, iopb);
|
case 1:
|
||||||
}
|
zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready
|
||||||
}
|
zx200a[fdcnum].rbyte1 |= RB1RD1;
|
||||||
|
break;
|
||||||
uint8 zx200a2(t_bool io, uint8 data, uint8 devnum)
|
case 2:
|
||||||
{
|
zx200a[fdcnum].stat |= RDY2; //set FDD 2 ready
|
||||||
if (io == 0) { /* read operation */
|
zx200a[fdcnum].rbyte1 |= RB1RD2;
|
||||||
sim_printf(" zx200a2: read data=%02X devnum=%02X\n", data, devnum);
|
break;
|
||||||
return 0x00;
|
case 3:
|
||||||
} else { /* write control port */
|
zx200a[fdcnum].stat |= RDY3; //set FDD 3 ready
|
||||||
iopb |= (data << 8);
|
zx200a[fdcnum].rbyte1 |= RB1RD3;
|
||||||
sim_printf(" zx200a2: write data=%02X port=%02X iopb=%04X\n", data, devnum, iopb);
|
break;
|
||||||
}
|
}
|
||||||
}
|
sim_printf(" ZX-200A%d: Configured, Status=%02X Attached to %s\n",
|
||||||
|
i, zx200a[fdcnum].stat, uptr->filename);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,12 +381,15 @@ t_stat zx200a_attach (UNIT *uptr, CONST char *cptr)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int32 i, c = 0;
|
int32 i, c = 0;
|
||||||
long flen;
|
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) {
|
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
||||||
sim_printf(" zx200a_attach: Attach error\n");
|
sim_printf(" zx200a_attach: Attach error\n");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
fdcnum = uptr->u5;
|
||||||
|
fddnum = uptr->u6;
|
||||||
fp = fopen(uptr->filename, "rb");
|
fp = fopen(uptr->filename, "rb");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
sim_printf(" Unable to open disk image file %s\n", uptr->filename);
|
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 */
|
fseek(fp, 0, SEEK_END); /* size disk image */
|
||||||
flen = ftell(fp);
|
flen = ftell(fp);
|
||||||
fseek(fp, 0, SEEK_SET);
|
fseek(fp, 0, SEEK_SET);
|
||||||
if (zx200a_buf[uptr->u6] == NULL) { /* no buffer allocated */
|
if (zx200a[fdcnum].fdd[fddnum].buf == NULL) { /* no buffer allocated */
|
||||||
zx200a_buf[uptr->u6] = (uint8 *)malloc(flen);
|
zx200a[fdcnum].fdd[fddnum].buf = (uint8 *)malloc(flen);
|
||||||
if (zx200a_buf[uptr->u6] == NULL) {
|
if (zx200a[fdcnum].fdd[fddnum].buf == NULL) {
|
||||||
sim_printf(" zx200a_attach: Malloc error\n");
|
sim_printf(" zx200a_attach: Malloc error\n");
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
}
|
}
|
||||||
|
@ -360,85 +410,343 @@ t_stat zx200a_attach (UNIT *uptr, CONST char *cptr)
|
||||||
i = 0;
|
i = 0;
|
||||||
c = fgetc(fp); // copy disk image into buffer
|
c = fgetc(fp); // copy disk image into buffer
|
||||||
while (c != EOF) {
|
while (c != EOF) {
|
||||||
*(zx200a_buf[uptr->u6] + i++) = c & 0xFF;
|
*(zx200a[fdcnum].fdd[fddnum].buf + i++) = c & 0xFF;
|
||||||
c = fgetc(fp);
|
c = fgetc(fp);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
switch(uptr->u6){
|
switch(fddnum){
|
||||||
case 0:
|
case 0:
|
||||||
fddst[uptr->u6] |= 0x01; /* set unit ready */
|
zx200a[fdcnum].stat |= RDY0; //set FDD 0 ready
|
||||||
break;
|
zx200a[fdcnum].rtype = ROK;
|
||||||
case 1:
|
zx200a[fdcnum].rbyte1 |= RB1RD0;
|
||||||
fddst[uptr->u6] |= 0x02; /* set unit ready */
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 2:
|
zx200a[fdcnum].stat |= RDY1; //set FDD 1 ready
|
||||||
fddst[uptr->u6] |= 0x20; /* set unit ready */
|
zx200a[fdcnum].rtype = ROK;
|
||||||
break;
|
zx200a[fdcnum].rbyte1 |= RB1RD1;
|
||||||
case 3:
|
break;
|
||||||
fddst[uptr->u6] |= 0x40; /* set unit ready */
|
case 2:
|
||||||
break;
|
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 */
|
if (flen == 256256) { /* 8" 256K SSSD */
|
||||||
maxcyl[uptr->u6] = 77;
|
zx200a[fdcnum].fdd[fddnum].maxcyl = 77;
|
||||||
maxsec[uptr->u6] = 26;
|
zx200a[fdcnum].fdd[fddnum].maxsec = 26;
|
||||||
}
|
}
|
||||||
else if (flen == 512512) { /* 8" 512K SSDD */
|
else if (flen == 512512) { /* 8" 512K SSDD */
|
||||||
maxcyl[uptr->u6] = 77;
|
zx200a[fdcnum].fdd[fddnum].maxcyl = 77;
|
||||||
maxsec[uptr->u6] = 52;
|
zx200a[fdcnum].fdd[fddnum].maxsec = 52;
|
||||||
}
|
} else
|
||||||
sim_printf(" Drive-%d: %d bytes of disk image %s loaded, fddst=%02X\n",
|
sim_printf(" ZX-200A-%d: Not a known ISIS-II disk image\n", fdcnum);
|
||||||
uptr->u6, i, uptr->filename, fddst[uptr->u6]);
|
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");
|
sim_debug (DEBUG_flow, &zx200a_dev, " ZX-200A_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();
|
|
||||||
return SCPE_OK;
|
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;
|
UNIT *uptr;
|
||||||
static int flag = 1;
|
FILE *fp;
|
||||||
|
//parse the IOPB
|
||||||
if (flag) sim_printf("ZX-200A: Initializing\n");
|
cw = multibus_get_mbyte(zx200a[fdcnum].iopb);
|
||||||
for (i = 0; i < FDD_NUM; i++) { /* handle all units */
|
di = multibus_get_mbyte(zx200a[fdcnum].iopb + 1);
|
||||||
uptr = zx200a_dev.units + i;
|
nr = multibus_get_mbyte(zx200a[fdcnum].iopb + 2);
|
||||||
if (uptr->capac == 0) { /* if not configured */
|
ta = multibus_get_mbyte(zx200a[fdcnum].iopb + 3);
|
||||||
// sim_printf(" ZX-200A%d: Not configured\n", i);
|
sa = multibus_get_mbyte(zx200a[fdcnum].iopb + 4);
|
||||||
// if (flag) {
|
ba = multibus_get_mword(zx200a[fdcnum].iopb + 5);
|
||||||
// sim_printf(" ALL: \"set ZX-200A en\"\n");
|
fddnum = (di & 0x30) >> 4;
|
||||||
// sim_printf(" EPROM: \"att ZX-200A0 <filename>\"\n");
|
uptr = zx200a_dev.units + fddnum;
|
||||||
// flag = 0;
|
if (DEBUG) {
|
||||||
// }
|
sim_printf("\n zx200a-%d: zx200a_diskio IOPB=%04X FDD=%02X STAT=%02X",
|
||||||
uptr->capac = 0; /* initialize unit */
|
fdcnum, zx200a[fdcnum].iopb, fddnum, zx200a[fdcnum].stat);
|
||||||
uptr->u3 = 0;
|
sim_printf("\n zx200a-%d: cw=%02X di=%02X nr=%02X ta=%02X sa=%02X ba=%04X",
|
||||||
uptr->u4 = 0;
|
fdcnum, cw, di, nr, ta, sa, ba);
|
||||||
uptr->u5 = 0;
|
sim_printf("\n zx200a-%d: maxsec=%02X maxcyl=%02X",
|
||||||
uptr->u6 = i; /* unit number - only set here! */
|
fdcnum, zx200a[fdcnum].fdd[fddnum].maxsec, zx200a[fdcnum].fdd[fddnum].maxcyl);
|
||||||
fddst[i] = WP + T0 + i; /* initial drive status */
|
}
|
||||||
uptr->flags |= UNIT_WPMODE; /* set WP in unit flags */
|
//check for not ready
|
||||||
sim_activate (&zx200a_unit[uptr->u6], zx200a_unit[uptr->u6].wait);
|
switch(fddnum) {
|
||||||
} else {
|
case 0:
|
||||||
fddst[i] = RDY + WP + T0 + i; /* initial attach drive status */
|
if ((zx200a[fdcnum].stat & RDY0) == 0) {
|
||||||
// sim_printf(" SBC208%d: Configured, Attached to %s\n", i, uptr->filename);
|
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 */
|
/* end of zx-200a.c */
|
||||||
|
|
|
@ -44,32 +44,38 @@ void put_mbyte(uint16 addr, uint8 val);
|
||||||
void put_mword(uint16 addr, uint16 val);
|
void put_mword(uint16 addr, uint16 val);
|
||||||
t_stat SBC_reset (DEVICE *dptr);
|
t_stat SBC_reset (DEVICE *dptr);
|
||||||
|
|
||||||
|
/* external globals */
|
||||||
|
|
||||||
|
extern uint8 i8255_C[4]; //port C byte I/O
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */
|
|
||||||
extern uint8 multibus_get_mbyte(uint16 addr);
|
extern uint8 multibus_get_mbyte(uint16 addr);
|
||||||
extern void multibus_put_mbyte(uint16 addr, uint8 val);
|
extern void multibus_put_mbyte(uint16 addr, uint8 val);
|
||||||
extern uint8 EPROM_get_mbyte(uint16 addr);
|
extern uint8 EPROM_get_mbyte(uint16 addr);
|
||||||
extern uint8 RAM_get_mbyte(uint16 addr);
|
extern uint8 RAM_get_mbyte(uint16 addr);
|
||||||
extern void RAM_put_mbyte(uint16 addr, uint8 val);
|
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 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 t_stat EPROM_reset (DEVICE *dptr, uint16 size);
|
||||||
|
extern UNIT RAM_unit;
|
||||||
extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size);
|
extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size);
|
||||||
|
|
||||||
/* SBC reset routine */
|
/* SBC reset routine */
|
||||||
|
|
||||||
t_stat SBC_reset (DEVICE *dptr)
|
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);
|
i8080_reset (NULL);
|
||||||
i8255_reset (NULL, I8255_BASE_0, 0);
|
i8251_devnum = 0;
|
||||||
i8255_reset (NULL, I8255_BASE_1, 1);
|
i8251_reset (NULL, I8251_BASE);
|
||||||
i8251_reset (NULL, I8251_BASE, 0);
|
i8255_devnum = 0;
|
||||||
|
i8255_reset (NULL, I8255_BASE_0);
|
||||||
|
i8255_reset (NULL, I8255_BASE_1);
|
||||||
EPROM_reset (NULL, ROM_SIZE);
|
EPROM_reset (NULL, ROM_SIZE);
|
||||||
RAM_reset (NULL, RAM_BASE, RAM_SIZE);
|
RAM_reset (NULL, RAM_BASE, RAM_SIZE);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -80,15 +86,15 @@ t_stat SBC_reset (DEVICE *dptr)
|
||||||
uint8 get_mbyte(uint16 addr)
|
uint8 get_mbyte(uint16 addr)
|
||||||
{
|
{
|
||||||
/* if local EPROM handle it */
|
/* if local EPROM handle it */
|
||||||
if (i8255_unit[0].u5 & 0x01) {
|
if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */
|
||||||
if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) {
|
if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) {
|
||||||
return EPROM_get_mbyte(addr);
|
return EPROM_get_mbyte(addr);
|
||||||
}
|
}
|
||||||
} /* if local RAM handle it */
|
} /* if local RAM handle it */
|
||||||
if (i8255_unit[0].u5 & 0x02) {
|
if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */
|
||||||
if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) {
|
if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) {
|
||||||
return RAM_get_mbyte(addr);
|
return RAM_get_mbyte(addr);
|
||||||
}
|
}
|
||||||
} /* otherwise, try the multibus */
|
} /* otherwise, try the multibus */
|
||||||
return multibus_get_mbyte(addr);
|
return multibus_get_mbyte(addr);
|
||||||
}
|
}
|
||||||
|
@ -109,13 +115,17 @@ uint16 get_mword(uint16 addr)
|
||||||
void put_mbyte(uint16 addr, uint8 val)
|
void put_mbyte(uint16 addr, uint8 val)
|
||||||
{
|
{
|
||||||
/* if local EPROM handle it */
|
/* if local EPROM handle it */
|
||||||
if ((i8255_unit[0].u5 & 0x01) && (addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) {
|
if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */
|
||||||
sim_printf("Write to R/O memory address %04X - ignored\n", addr);
|
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;
|
return;
|
||||||
|
}
|
||||||
} /* if local RAM handle it */
|
} /* if local RAM handle it */
|
||||||
if ((i8255_unit[0].u5 & 0x02) && (addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) {
|
if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */
|
||||||
RAM_put_mbyte(addr, val);
|
if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) {
|
||||||
|
RAM_put_mbyte(addr, val);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
} /* otherwise, try the multibus */
|
} /* otherwise, try the multibus */
|
||||||
multibus_put_mbyte(addr, val);
|
multibus_put_mbyte(addr, val);
|
||||||
}
|
}
|
|
@ -36,7 +36,8 @@ extern DEVICE i8255_dev;
|
||||||
extern DEVICE EPROM_dev;
|
extern DEVICE EPROM_dev;
|
||||||
extern DEVICE RAM_dev;
|
extern DEVICE RAM_dev;
|
||||||
extern DEVICE multibus_dev;
|
extern DEVICE multibus_dev;
|
||||||
extern DEVICE isbc208_dev;
|
extern DEVICE isbc201_dev;
|
||||||
|
extern DEVICE isbc202_dev;
|
||||||
extern DEVICE isbc064_dev;
|
extern DEVICE isbc064_dev;
|
||||||
|
|
||||||
/* SCP data structures
|
/* SCP data structures
|
||||||
|
@ -62,7 +63,8 @@ DEVICE *sim_devices[] = {
|
||||||
&i8255_dev,
|
&i8255_dev,
|
||||||
&multibus_dev,
|
&multibus_dev,
|
||||||
&isbc064_dev,
|
&isbc064_dev,
|
||||||
&isbc208_dev,
|
&isbc201_dev,
|
||||||
|
&isbc202_dev,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,38 +28,58 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
//#include "isys8010_cfg.h" /* Intel System 80/10 configuration */
|
|
||||||
#include "sim_defs.h" /* simulator defns */
|
#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 */
|
/* set the base I/O address and device count for the 8255s */
|
||||||
#define I8255_BASE_0 0xE4
|
#define I8255_BASE_0 0xE4
|
||||||
#define I8255_BASE_1 0xE8
|
#define I8255_BASE_1 0xE8
|
||||||
#define I8255_NUM 2
|
#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 */
|
/* set the base and size for the EPROM on the iSBC 80/10 */
|
||||||
#define ROM_BASE 0x0000
|
#define ROM_BASE 0x0000
|
||||||
#define ROM_SIZE 0x1000
|
#define ROM_SIZE 0x1000
|
||||||
|
#define ROM_DISABLE 1
|
||||||
|
|
||||||
/* set the base and size for the RAM on the iSBC 80/10 */
|
/* set the base and size for the RAM on the iSBC 80/10 */
|
||||||
#define RAM_BASE 0x3C00
|
#define RAM_BASE 0x3C00
|
||||||
#define RAM_SIZE 0x0400
|
#define RAM_SIZE 0x0400
|
||||||
|
#define RAM_DISABLE 1
|
||||||
|
|
||||||
/* set INTR for CPU on the iSBC 80/10 */
|
/* set INTR for CPU on the iSBC 80/10 */
|
||||||
#define INTR INT_1
|
#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 */
|
/* set the base I/O address for the iSBC 208 */
|
||||||
#define SBC208_BASE 0x40
|
#define SBC208_BASE 0x40
|
||||||
|
|
||||||
/* configure interrupt request line */
|
|
||||||
#define SBC208_INT INT_1
|
#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 */
|
/* set the base and size for the iSBC 064 */
|
||||||
#define SBC064_BASE 0x0000
|
#define SBC064_BASE 0x0000
|
||||||
#define SBC064_SIZE 0x10000
|
#define SBC064_SIZE 0x10000
|
||||||
|
#define SBC064_NUM 1
|
||||||
|
|
||||||
/* multibus interrupt definitions */
|
/* multibus interrupt definitions */
|
||||||
|
|
||||||
|
|
|
@ -39,22 +39,27 @@ void put_mbyte(uint16 addr, uint8 val);
|
||||||
void put_mword(uint16 addr, uint16 val);
|
void put_mword(uint16 addr, uint16 val);
|
||||||
t_stat SBC_reset (DEVICE *dptr);
|
t_stat SBC_reset (DEVICE *dptr);
|
||||||
|
|
||||||
|
/* external globals */
|
||||||
|
|
||||||
|
extern uint8 i8255_C[4]; //port C byte I/O
|
||||||
|
|
||||||
/* external function prototypes */
|
/* external function prototypes */
|
||||||
|
|
||||||
extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */
|
|
||||||
extern uint8 multibus_get_mbyte(uint16 addr);
|
extern uint8 multibus_get_mbyte(uint16 addr);
|
||||||
extern void multibus_put_mbyte(uint16 addr, uint8 val);
|
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 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 uint8 RAM_get_mbyte(uint16 addr);
|
||||||
extern void RAM_put_mbyte(uint16 addr, uint8 val);
|
extern void RAM_put_mbyte(uint16 addr, uint8 val);
|
||||||
extern UNIT i8255_unit;
|
|
||||||
extern UNIT EPROM_unit;
|
|
||||||
extern UNIT RAM_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);
|
extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size);
|
||||||
|
|
||||||
/* CPU reset routine
|
/* CPU reset routine
|
||||||
|
@ -64,10 +69,10 @@ t_stat SBC_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
sim_printf("Initializing iSBC-80/20\n");
|
sim_printf("Initializing iSBC-80/20\n");
|
||||||
i8080_reset(NULL);
|
i8080_reset(NULL);
|
||||||
i8259_reset(NULL, I8259_BASE, 0);
|
i8251_reset(NULL, I8251_BASE);
|
||||||
i8255_reset(NULL, I8255_BASE_0, 0);
|
i8255_reset(NULL, I8255_BASE_0);
|
||||||
i8255_reset(NULL, I8255_BASE_1, 1);
|
i8255_reset(NULL, I8255_BASE_1);
|
||||||
i8251_reset(NULL, I8251_BASE, 0);
|
i8259_reset(NULL, I8259_BASE);
|
||||||
EPROM_reset(NULL, ROM_SIZE);
|
EPROM_reset(NULL, ROM_SIZE);
|
||||||
RAM_reset(NULL, RAM_BASE, RAM_SIZE);
|
RAM_reset(NULL, RAM_BASE, RAM_SIZE);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -78,13 +83,13 @@ t_stat SBC_reset (DEVICE *dptr)
|
||||||
uint8 get_mbyte(uint16 addr)
|
uint8 get_mbyte(uint16 addr)
|
||||||
{
|
{
|
||||||
/* if local EPROM handle it */
|
/* if local EPROM handle it */
|
||||||
if ((i8255_unit.u5 & 0x01) && /* EPROM enabled? */
|
if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */
|
||||||
(addr >= EPROM_unit.u3) && (addr < (EPROM_unit.u3 + EPROM_unit.capac))) {
|
if ((addr >= EPROM_unit.u3) && (addr < (EPROM_unit.u3 + EPROM_unit.capac)))
|
||||||
return EPROM_get_mbyte(addr);
|
return EPROM_get_mbyte(addr);
|
||||||
} /* if local RAM handle it */
|
} /* if local RAM handle it */
|
||||||
if ((i8255_unit.u5 & 0x02) && /* local RAM enabled? */
|
if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */
|
||||||
(addr >= RAM_unit.u3) && (addr < (RAM_unit.u3 + RAM_unit.capac))) {
|
if ((addr >= RAM_unit.u3) && (addr < (RAM_unit.u3 + RAM_unit.capac)))
|
||||||
return RAM_get_mbyte(addr);
|
return RAM_get_mbyte(addr);
|
||||||
} /* otherwise, try the multibus */
|
} /* otherwise, try the multibus */
|
||||||
return multibus_get_mbyte(addr);
|
return multibus_get_mbyte(addr);
|
||||||
}
|
}
|
||||||
|
@ -105,15 +110,17 @@ uint16 get_mword(uint16 addr)
|
||||||
void put_mbyte(uint16 addr, uint8 val)
|
void put_mbyte(uint16 addr, uint8 val)
|
||||||
{
|
{
|
||||||
/* if local EPROM handle it */
|
/* if local EPROM handle it */
|
||||||
if ((i8255_unit.u5 & 0x01) && /* EPROM enabled? */
|
if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */
|
||||||
(addr >= EPROM_unit.u3) && (addr <= (EPROM_unit.u3 + EPROM_unit.capac))) {
|
if ((addr >= EPROM_unit.u3) && (addr <= (EPROM_unit.u3 + EPROM_unit.capac))) {
|
||||||
sim_printf("Write to R/O memory address %04X - ignored\n", addr);
|
sim_printf("Write to R/O memory address %04X - ignored\n", addr);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
} /* if local RAM handle it */
|
} /* if local RAM handle it */
|
||||||
if ((i8255_unit.u5 & 0x02) && /* local RAM enabled? */
|
if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */
|
||||||
(addr >= RAM_unit.u3) && (addr <= (RAM_unit.u3 + RAM_unit.capac))) {
|
if ((addr >= RAM_unit.u3) && (addr <= (RAM_unit.u3 + RAM_unit.capac))) {
|
||||||
RAM_put_mbyte(addr, val);
|
RAM_put_mbyte(addr, val);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
} /* otherwise, try the multibus */
|
} /* otherwise, try the multibus */
|
||||||
multibus_put_mbyte(addr, val);
|
multibus_put_mbyte(addr, val);
|
||||||
}
|
}
|
|
@ -37,7 +37,8 @@ extern DEVICE i8255_dev;
|
||||||
extern DEVICE EPROM_dev;
|
extern DEVICE EPROM_dev;
|
||||||
extern DEVICE RAM_dev;
|
extern DEVICE RAM_dev;
|
||||||
extern DEVICE multibus_dev;
|
extern DEVICE multibus_dev;
|
||||||
extern DEVICE isbc208_dev;
|
extern DEVICE isbc201_dev;
|
||||||
|
extern DEVICE isbc202_dev;
|
||||||
extern DEVICE isbc064_dev;
|
extern DEVICE isbc064_dev;
|
||||||
|
|
||||||
/* SCP data structures
|
/* SCP data structures
|
||||||
|
@ -64,7 +65,8 @@ DEVICE *sim_devices[] = {
|
||||||
&i8255_dev,
|
&i8255_dev,
|
||||||
&multibus_dev,
|
&multibus_dev,
|
||||||
&isbc064_dev,
|
&isbc064_dev,
|
||||||
&isbc208_dev,
|
&isbc201_dev,
|
||||||
|
&isbc202_dev,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,39 +30,60 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "sim_defs.h" /* simulator defns */
|
#include "sim_defs.h" /* simulator defns */
|
||||||
|
|
||||||
/* set the base I/O address for the 8259 */
|
#define SET_XACK(VAL) (xack = VAL)
|
||||||
#define I8259_BASE 0xD8
|
|
||||||
#define I8259_NUM 1
|
//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 */
|
/* set the base I/O address for the 8255 */
|
||||||
#define I8255_BASE_0 0xE4
|
#define I8255_BASE_0 0xE4
|
||||||
#define I8255_BASE_1 0xE8
|
#define I8255_BASE_1 0xE8
|
||||||
#define I8255_NUM 2
|
#define I8255_NUM 2
|
||||||
|
|
||||||
/* set the base I/O address for the 8251 */
|
/* set the base I/O address for the 8259 */
|
||||||
#define I8251_BASE 0xEC
|
#define I8259_BASE 0xD8
|
||||||
#define I8251_NUM 1
|
#define I8259_NUM 1
|
||||||
|
|
||||||
/* set the base and size for the EPROM on the iSBC 80/20 */
|
/* set the base and size for the EPROM on the iSBC 80/20 */
|
||||||
#define ROM_BASE 0x0000
|
#define ROM_BASE 0x0000
|
||||||
#define ROM_SIZE 0x1000
|
#define ROM_SIZE 0x1000
|
||||||
|
#define ROM_DISABLE 1
|
||||||
|
|
||||||
/* set the base and size for the RAM on the iSBC 80/20 */
|
/* set the base and size for the RAM on the iSBC 80/20 */
|
||||||
#define RAM_BASE 0x3C00
|
#define RAM_BASE 0x3C00
|
||||||
#define RAM_SIZE 0x0400
|
#define RAM_SIZE 0x0400
|
||||||
|
#define RAM_DISABLE 1
|
||||||
|
|
||||||
/* set INTR for CPU */
|
/* set INTR for CPU */
|
||||||
#define INTR INT_1
|
#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 */
|
/* set the base I/O address for the iSBC 208 */
|
||||||
#define SBC208_BASE 0x40
|
#define SBC208_BASE 0x40
|
||||||
|
|
||||||
/* configure interrupt request line */
|
|
||||||
#define SBC208_INT INT_1
|
#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 */
|
/* set the base and size for the iSBC 064 */
|
||||||
#define SBC064_BASE 0x0000
|
#define SBC064_BASE 0x0000
|
||||||
#define SBC064_SIZE 0x10000
|
#define SBC064_SIZE 0x10000
|
||||||
|
#define SBC064_NUM 1
|
||||||
|
|
||||||
/* multibus interrupt definitions */
|
/* multibus interrupt definitions */
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXMLDataGeneratorTool"
|
Name="VCXMLDataGeneratorTool"
|
||||||
/>
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCMIDLTool"
|
Name="VCMIDLTool"
|
||||||
/>
|
/>
|
||||||
|
@ -116,6 +119,9 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXMLDataGeneratorTool"
|
Name="VCXMLDataGeneratorTool"
|
||||||
/>
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCMIDLTool"
|
Name="VCMIDLTool"
|
||||||
/>
|
/>
|
||||||
|
@ -212,12 +218,20 @@
|
||||||
RelativePath="..\Intel-Systems\common\isbc064.c"
|
RelativePath="..\Intel-Systems\common\isbc064.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\Intel-Systems\common\isbc201.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\Intel-Systems\common\isbc202.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Intel-Systems\common\isbc208.c"
|
RelativePath="..\Intel-Systems\common\isbc208.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Intel-Systems\isys8010\isbc80-10.c"
|
RelativePath="..\Intel-Systems\isys8010\isbc8010.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
|
@ -272,6 +286,10 @@
|
||||||
RelativePath="..\sim_video.c"
|
RelativePath="..\sim_video.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\Intel-Systems\common\zx200a.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header Files"
|
Name="Header Files"
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXMLDataGeneratorTool"
|
Name="VCXMLDataGeneratorTool"
|
||||||
/>
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCMIDLTool"
|
Name="VCMIDLTool"
|
||||||
/>
|
/>
|
||||||
|
@ -116,6 +119,9 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXMLDataGeneratorTool"
|
Name="VCXMLDataGeneratorTool"
|
||||||
/>
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCMIDLTool"
|
Name="VCMIDLTool"
|
||||||
/>
|
/>
|
||||||
|
@ -216,12 +222,20 @@
|
||||||
RelativePath="..\Intel-Systems\common\isbc064.c"
|
RelativePath="..\Intel-Systems\common\isbc064.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\Intel-Systems\common\isbc201.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\Intel-Systems\common\isbc202.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Intel-Systems\common\isbc208.c"
|
RelativePath="..\Intel-Systems\common\isbc208.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Intel-Systems\isys8020\isbc80-20.c"
|
RelativePath="..\Intel-Systems\isys8020\isbc8020.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
|
@ -276,6 +290,10 @@
|
||||||
RelativePath="..\sim_video.c"
|
RelativePath="..\sim_video.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\Intel-Systems\common\zx200a.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header Files"
|
Name="Header Files"
|
||||||
|
|
65
makefile
65
makefile
|
@ -331,7 +331,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
|
||||||
ifeq (X11R7,$(shell if $(TEST) -d /usr/X11R7/lib; then echo X11R7; fi))
|
ifeq (X11R7,$(shell if $(TEST) -d /usr/X11R7/lib; then echo X11R7; fi))
|
||||||
LIBPATH += /usr/X11R7/lib
|
LIBPATH += /usr/X11R7/lib
|
||||||
INCPATH += /usr/X11R7/include
|
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
|
OS_CCDEFS += -I/usr/X11R7/include
|
||||||
endif
|
endif
|
||||||
ifeq (/usr/local/lib,$(findstring /usr/local/lib,$(LIBPATH)))
|
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
|
DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c
|
||||||
DISPLAYVT = ${DISPLAYD}/vt11.c
|
DISPLAYVT = ${DISPLAYD}/vt11.c
|
||||||
DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS)
|
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))
|
ifeq (Darwin,$(OSTYPE))
|
||||||
VIDEO_CCDEFS += -DSDL_MAIN_AVAILABLE
|
VIDEO_CCDEFS += -DSDL_MAIN_AVAILABLE
|
||||||
endif
|
endif
|
||||||
|
@ -812,13 +812,9 @@ else
|
||||||
ifneq (,$(VIDEO_USEFUL))
|
ifneq (,$(VIDEO_USEFUL))
|
||||||
SDL_INCLUDE = $(word 1,$(shell dir /b /s ..\windows-build\libSDL\SDL.h))
|
SDL_INCLUDE = $(word 1,$(shell dir /b /s ..\windows-build\libSDL\SDL.h))
|
||||||
ifeq (SDL.h,$(findstring SDL.h,$(SDL_INCLUDE)))
|
ifeq (SDL.h,$(findstring SDL.h,$(SDL_INCLUDE)))
|
||||||
$(info using libSDL2: $(abspath $(SDL_INCLUDE)))
|
VIDEO_CCDEFS += -DHAVE_LIBSDL -I$(abspath $(dir $(SDL_INCLUDE)))
|
||||||
VIDEO_CCDEFS += -DHAVE_LIBSDL -DUSE_SIM_VIDEO -I$(abspath $(dir $(SDL_INCLUDE)))
|
|
||||||
VIDEO_LDFLAGS += -lSDL2 -L$(abspath $(dir $(SDL_INCLUDE))\..\lib)
|
VIDEO_LDFLAGS += -lSDL2 -L$(abspath $(dir $(SDL_INCLUDE))\..\lib)
|
||||||
VIDEO_FEATURES = - video capabilities provided by libSDL2 (Simple Directmedia Layer)
|
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
|
else
|
||||||
$(info ***********************************************************************)
|
$(info ***********************************************************************)
|
||||||
$(info ***********************************************************************)
|
$(info ***********************************************************************)
|
||||||
|
@ -1339,8 +1335,9 @@ ISYS8010C = Intel-Systems/common
|
||||||
ISYS8010 = ${ISYS8010C}/i8080.c ${ISYS8010D}/isys8010_sys.c \
|
ISYS8010 = ${ISYS8010C}/i8080.c ${ISYS8010D}/isys8010_sys.c \
|
||||||
${ISYS8010C}/i8251.c ${ISYS8010C}/i8255.c \
|
${ISYS8010C}/i8251.c ${ISYS8010C}/i8255.c \
|
||||||
${ISYS8010C}/ieprom.c ${ISYS8010C}/iram8.c \
|
${ISYS8010C}/ieprom.c ${ISYS8010C}/iram8.c \
|
||||||
${ISYS8010C}/multibus.c ${ISYS8010D}/isbc80-10.c \
|
${ISYS8010C}/multibus.c ${ISYS8010D}/isbc8010.c \
|
||||||
${ISYS8010C}/isbc064.c ${ISYS8010C}/isbc208.c
|
${ISYS8010C}/isbc064.c ${ISYS8010C}/isbc202.c \
|
||||||
|
${ISYS8010C}/isbc201.c ${ISYS8010C}/zx200a.c
|
||||||
ISYS8010_OPT = -I ${ISYS8010D}
|
ISYS8010_OPT = -I ${ISYS8010D}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1349,20 +1346,35 @@ ISYS8020C = Intel-Systems/common
|
||||||
ISYS8020 = ${ISYS8020C}/i8080.c ${ISYS8020D}/isys8020_sys.c \
|
ISYS8020 = ${ISYS8020C}/i8080.c ${ISYS8020D}/isys8020_sys.c \
|
||||||
${ISYS8020C}/i8251.c ${ISYS8020C}/i8255.c \
|
${ISYS8020C}/i8251.c ${ISYS8020C}/i8255.c \
|
||||||
${ISYS8020C}/ieprom.c ${ISYS8020C}/iram8.c \
|
${ISYS8020C}/ieprom.c ${ISYS8020C}/iram8.c \
|
||||||
${ISYS8020C}/multibus.c ${ISYS8020D}/isbc80-20.c \
|
${ISYS8020C}/multibus.c ${ISYS8020D}/isbc8020.c \
|
||||||
${ISYS8020C}/isbc064.c ${ISYS8020C}/isbc208.c \
|
${ISYS8020C}/isbc064.c ${ISYS8020C}/i8259.c \
|
||||||
${ISYS8020C}/i8259.c
|
${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \
|
||||||
|
${ISYS8010C}/zx200a.c
|
||||||
ISYS8020_OPT = -I ${ISYS8020D}
|
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
|
ISYS8030D = Intel-Systems/isys8030
|
||||||
ISYS8030C = Intel-Systems/common
|
ISYS8030C = Intel-Systems/common
|
||||||
ISYS8030 = ${ISYS8030C}/i8080.c ${ISYS8030D}/isys8030_sys.c \
|
ISYS8030 = ${ISYS8030C}/i8080.c ${ISYS8030D}/isys8030_sys.c \
|
||||||
${ISYS8030C}/i8251.c ${ISYS8030C}/i8255.c \
|
${ISYS8030C}/i8251.c ${ISYS8030C}/i8255.c \
|
||||||
${ISYS8030C}/i8259.c ${ISYS8030C}/i8253.c \
|
${ISYS8030C}/i8259.c ${ISYS8030C}/i8253.c \
|
||||||
${ISYS8030C}/ieprom.c ${ISYS8030C}/iram8.c \
|
${ISYS8030C}/ieprom.c ${ISYS8030C}/iram8.c \
|
||||||
${ISYS8030C}/multibus.c ${ISYS8030D}/isbc80-30.c \
|
${ISYS8030C}/multibus.c ${ISYS8030D}/isbc8030.c \
|
||||||
${ISYS8030C}/isbc064.c ${ISYS8030C}/isbc208.c
|
${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \
|
||||||
|
${ISYS8030C}/isbc064.c ${ISYS8010C}/zx200a.c
|
||||||
ISYS8030_OPT = -I ${ISYS8030D}
|
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}/ipceprom.c ${IMDS-225C}/ipcram8.c \
|
||||||
${IMDS-225C}/ipcmultibus.c ${IMDS-225D}/ipc.c \
|
${IMDS-225C}/ipcmultibus.c ${IMDS-225D}/ipc.c \
|
||||||
${IMDS-225C}/ipc-cont.c ${IMDS-225C}/ioc-cont.c \
|
${IMDS-225C}/ipc-cont.c ${IMDS-225C}/ioc-cont.c \
|
||||||
|
${IMDS-225C}/isbc202.c ${IMDS-225C}/isbc201.c \
|
||||||
${IMDS-225C}/zx200a.c
|
${IMDS-225C}/zx200a.c
|
||||||
IMDS-225_OPT = -I ${IMDS-225D}
|
IMDS-225_OPT = -I ${IMDS-225D}
|
||||||
|
|
||||||
|
|
||||||
IBMPCD = IBMPC-Systems/ibmpc
|
IBMPCD = IBMPC-Systems/ibmpc
|
||||||
IBMPCC = IBMPC-Systems/common
|
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}/i8253.c ${IBMPCC}/i8259.c \
|
||||||
${IBMPCC}/i8255.c ${IBMPCD}/ibmpc.c \
|
|
||||||
${IBMPCC}/pceprom.c ${IBMPCC}/pcram8.c \
|
${IBMPCC}/pceprom.c ${IBMPCC}/pcram8.c \
|
||||||
${IBMPCC}/i8237.c ${IBMPCC}/pcbus.c
|
${IBMPCC}/i8237.c ${IBMPCC}/pcbus.c
|
||||||
IBMPC_OPT = -I ${IBMPCD}
|
IBMPC_OPT = -I ${IBMPCD}
|
||||||
|
@ -1400,7 +1413,7 @@ IBMPCXT_OPT = -I ${IBMPCXTD}
|
||||||
|
|
||||||
TX0D = TX-0
|
TX0D = TX-0
|
||||||
TX0 = ${TX0D}/tx0_cpu.c ${TX0D}/tx0_dpy.c ${TX0D}/tx0_stddev.c \
|
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)
|
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 \
|
vax microvax3900 microvax1 rtvax1000 microvax2 vax730 vax750 vax780 vax8600 \
|
||||||
nova eclipse hp2100 hp3000 i1401 i1620 s3 altair altairz80 gri \
|
nova eclipse hp2100 hp3000 i1401 i1620 s3 altair altairz80 gri \
|
||||||
i7094 ibm1130 id16 id32 sds lgp h316 cdc1700 \
|
i7094 ibm1130 id16 id32 sds lgp h316 cdc1700 \
|
||||||
swtp6800mp-a swtp6800mp-a2 tx-0 ssem isys8010 isys8020 \
|
swtp6800mp-a swtp6800mp-a2 tx-0 ssem \
|
||||||
b5500
|
b5500 imds-225 imbpc ibmpcxt
|
||||||
|
|
||||||
all : ${ALL}
|
all : ${ALL}
|
||||||
|
|
||||||
|
@ -1795,25 +1808,23 @@ ${BIN}isys8020${EXE} : ${ISYS8020} ${SIM} ${BUILD_ROMS}
|
||||||
${MKDIRBIN}
|
${MKDIRBIN}
|
||||||
${CC} ${ISYS8020} ${SIM} ${ISYS8020_OPT} $(CC_OUTSPEC) ${LDFLAGS}
|
${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}
|
isys8030: ${BIN}isys8030${EXE}
|
||||||
|
|
||||||
${BIN}isys8030${EXE} : ${ISYS8030} ${SIM} ${BUILD_ROMS}
|
${BIN}isys8030${EXE} : ${ISYS8030} ${SIM} ${BUILD_ROMS}
|
||||||
ifneq (1,$(CPP_BUILD)$(CPP_FORCE))
|
|
||||||
${MKDIRBIN}
|
${MKDIRBIN}
|
||||||
${CC} ${ISYS8030} ${SIM} ${ISYS8030_OPT} $(CC_OUTSPEC) ${LDFLAGS}
|
${CC} ${ISYS8030} ${SIM} ${ISYS8030_OPT} $(CC_OUTSPEC) ${LDFLAGS}
|
||||||
else
|
|
||||||
$(info isys8030 can't be built using C++)
|
|
||||||
endif
|
|
||||||
|
|
||||||
imds-225: ${BIN}imds-225${EXE}
|
imds-225: ${BIN}imds-225${EXE}
|
||||||
|
|
||||||
${BIN}imds-225${EXE} : ${IMDS-225} ${SIM} ${BUILD_ROMS}
|
${BIN}imds-225${EXE} : ${IMDS-225} ${SIM} ${BUILD_ROMS}
|
||||||
ifneq (1,$(CPP_BUILD)$(CPP_FORCE))
|
|
||||||
${MKDIRBIN}
|
${MKDIRBIN}
|
||||||
${CC} ${IMDS-225} ${SIM} ${IMDS-225_OPT} $(CC_OUTSPEC) ${LDFLAGS}
|
${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}
|
ibmpc: ${BIN}ibmpc${EXE}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue