IBMPC: Initial check in of new experimental simulator for the IBM PC (5150)

This commit is contained in:
Bill Beech 2016-07-15 13:07:07 -07:00 committed by Mark Pizzolato
parent 5f1ee6ed67
commit 89a8c87e87
18 changed files with 12380 additions and 0 deletions

2002
IBMPC-Systems/common/i8008.c Normal file

File diff suppressed because it is too large Load diff

1445
IBMPC-Systems/common/i8080.c Normal file

File diff suppressed because it is too large Load diff

4750
IBMPC-Systems/common/i8088.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,872 @@
/* 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
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
/* internal function prototypes */
t_stat i8237_svc (UNIT *uptr);
t_stat i8237_reset (DEVICE *dptr, uint16 base);
void i8237_reset1 (void);
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; // 8237 ch 0 address register
uint16 i8237_r1; // 8237 ch 0 count register
uint16 i8237_r2; // 8237 ch 1 address register
uint16 i8237_r3; // 8237 ch 1 count register
uint16 i8237_r4; // 8237 ch 2 address register
uint16 i8237_r5; // 8237 ch 2 count register
uint16 i8237_r6; // 8237 ch 3 address register
uint16 i8237_r7; // 8237 ch 3 count register
uint8 i8237_r8; // 8237 status register
uint8 i8237_r9; // 8237 command register
uint8 i8237_rA; // 8237 mode register
uint8 i8237_rB; // 8237 mask register
uint8 i8237_rC; // 8237 request register
uint8 i8237_rD; // 8237 first/last ff
uint8 i8237_rE; // 8237
uint8 i8237_rF; // 8237
/* i8237 physical register definitions */
uint16 i8237_sr; // isbc-208 segment register
uint8 i8237_i; // iSBC-208 interrupt register
uint8 i8237_a; // iSBC-208 auxillary port register
/* 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, 16) },
{ HRDATA (CH0CNT, i8237_r1, 16) },
{ HRDATA (CH1ADR, i8237_r2, 16) },
{ HRDATA (CH1CNT, i8237_r3, 16) },
{ HRDATA (CH2ADR, i8237_r4, 16) },
{ HRDATA (CH2CNT, i8237_r5, 16) },
{ HRDATA (CH3ADR, i8237_r6, 16) },
{ HRDATA (CH3CNT, i8237_r7, 16) },
{ HRDATA (STAT37, i8237_r8, 8) },
{ HRDATA (CMD37, i8237_r9, 8) },
{ HRDATA (MODE, i8237_rA, 8) },
{ HRDATA (MASK, i8237_rB, 8) },
{ HRDATA (REQ, i8237_rC, 8) },
{ HRDATA (FF, i8237_rD, 8) },
{ HRDATA (SEGREG, i8237_sr, 8) },
{ HRDATA (AUX, i8237_a, 8) },
{ HRDATA (INT, i8237_i, 8) },
{ 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 = {
"8237", //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;
}
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++;
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(void)
{
int32 i;
UNIT *uptr;
static int flag = 1;
for (i = 0; i < 1; i++) { /* handle all units */
uptr = i8237_dev.units + i;
if (uptr->capac == 0) { /* if not configured */
// sim_printf(" SBC208%d: Not configured\n", i);
// if (flag) {
// sim_printf(" ALL: \"set isbc208 en\"\n");
// sim_printf(" EPROM: \"att isbc2080 <filename>\"\n");
// flag = 0;
// }
uptr->capac = 0; /* initialize unit */
uptr->u3 = 0;
uptr->u4 = 0;
uptr->u5 = 0;
uptr->u6 = i; /* unit number - only set here! */
sim_activate (&i8237_unit[uptr->u6], i8237_unit[uptr->u6].wait);
} else {
// sim_printf(" SBC208%d: Configured, Attached to %s\n", i, uptr->filename);
}
}
i8237_r8 = 0; /* status */
i8237_r9 = 0; /* command */
i8237_rB = 0x0F; /* mask */
i8237_rC = 0; /* request */
i8237_rD = 0; /* first/last FF */
}
/* 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(H) read as %04X\n", i8237_r0);
return (i8237_r0 >> 8);
} else { /* low byte */
i8237_rD++;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) read as %04X\n", i8237_r0);
return (i8237_r0 & 0xFF);
}
} else { /* write base & current address CH 0 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
i8237_r0 |= (data << 8);
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(H) set to %04X\n", i8237_r0);
} else { /* low byte */
i8237_rD++;
i8237_r0 = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) set to %04X\n", i8237_r0);
}
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(H) read as %04X\n", i8237_r1);
return (i8237_r1 >> 8);
} else { /* low byte */
i8237_rD++;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) read as %04X\n", i8237_r1);
return (i8237_r1 & 0xFF);
}
} else { /* write base & current address CH 0 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
i8237_r1 |= (data << 8);
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(H) set to %04X\n", i8237_r1);
} else { /* low byte */
i8237_rD++;
i8237_r1 = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) set to %04X\n", i8237_r1);
}
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(H) read as %04X\n", i8237_r2);
return (i8237_r2 >> 8);
} else { /* low byte */
i8237_rD++;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) read as %04X\n", i8237_r2);
return (i8237_r2 & 0xFF);
}
} else { /* write base & current address CH 1 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
i8237_r2 |= (data << 8);
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(H) set to %04X\n", i8237_r2);
} else { /* low byte */
i8237_rD++;
i8237_r2 = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) set to %04X\n", i8237_r2);
}
return 0;
}
}
}
uint8 i8237_r3x(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) { /* read current word count CH 1 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(H) read as %04X\n", i8237_r3);
return (i8237_r3 >> 8);
} else { /* low byte */
i8237_rD++;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) read as %04X\n", i8237_r3);
return (i8237_r3 & 0xFF);
}
} else { /* write base & current address CH 1 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
i8237_r3 |= (data << 8);
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(H) set to %04X\n", i8237_r3);
} else { /* low byte */
i8237_rD++;
i8237_r3 = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) set to %04X\n", i8237_r3);
}
return 0;
}
}
}
uint8 i8237_r4x(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) { /* read current address CH 2 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(H) read as %04X\n", i8237_r4);
return (i8237_r4 >> 8);
} else { /* low byte */
i8237_rD++;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) read as %04X\n", i8237_r4);
return (i8237_r4 & 0xFF);
}
} else { /* write base & current address CH 2 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
i8237_r4 |= (data << 8);
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(H) set to %04X\n", i8237_r4);
} else { /* low byte */
i8237_rD++;
i8237_r4 = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) set to %04X\n", i8237_r4);
}
return 0;
}
}
}
uint8 i8237_r5x(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) { /* read current word count CH 2 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(H) read as %04X\n", i8237_r5);
return (i8237_r5 >> 8);
} else { /* low byte */
i8237_rD++;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) read as %04X\n", i8237_r5);
return (i8237_r5 & 0xFF);
}
} else { /* write base & current address CH 2 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
i8237_r5 |= (data << 8);
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(H) set to %04X\n", i8237_r5);
} else { /* low byte */
i8237_rD++;
i8237_r5 = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) set to %04X\n", i8237_r5);
}
return 0;
}
}
}
uint8 i8237_r6x(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) { /* read current address CH 3 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(H) read as %04X\n", i8237_r6);
return (i8237_r6 >> 8);
} else { /* low byte */
i8237_rD++;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) read as %04X\n", i8237_r6);
return (i8237_r6 & 0xFF);
}
} else { /* write base & current address CH 3 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
i8237_r6 |= (data << 8);
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(H) set to %04X\n", i8237_r6);
} else { /* low byte */
i8237_rD++;
i8237_r6 = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) set to %04X\n", i8237_r6);
}
return 0;
}
}
}
uint8 i8237_r7x(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) { /* read current word count CH 3 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(H) read as %04X\n", i8237_r7);
return (i8237_r7 >> 8);
} else { /* low byte */
i8237_rD++;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) read as %04X\n", i8237_r7);
return (i8237_r7 & 0xFF);
}
} else { /* write base & current address CH 3 */
if (i8237_rD) { /* high byte */
i8237_rD = 0;
i8237_r7 |= (data << 8);
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(H) set to %04X\n", i8237_r7);
} else { /* low byte */
i8237_rD++;
i8237_r7 = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) set to %04X\n", i8237_r7);
}
return 0;
}
}
}
uint8 i8237_r8x(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) { /* read status register */
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r8 (status) read as %02X\n", i8237_r8);
return (i8237_r8);
} else { /* write command register */
i8237_r9 = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_r9 (command) set to %02X\n", i8237_r9);
return 0;
}
}
}
uint8 i8237_r9x(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) {
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_r9\n");
return 0;
} else { /* write request register */
i8237_rC = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rC (request) set to %02X\n", i8237_rC);
return 0;
}
}
}
uint8 i8237_rAx(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) {
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rA\n");
return 0;
} else { /* write single mask register */
switch(data & 0x03) {
case 0:
if (data & 0x04)
i8237_rB |= 1;
else
i8237_rB &= ~1;
break;
case 1:
if (data & 0x04)
i8237_rB |= 2;
else
i8237_rB &= ~2;
break;
case 2:
if (data & 0x04)
i8237_rB |= 4;
else
i8237_rB &= ~4;
break;
case 3:
if (data & 0x04)
i8237_rB |= 8;
else
i8237_rB &= ~8;
break;
}
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB);
return 0;
}
}
}
uint8 i8237_rBx(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) {
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rB\n");
return 0;
} else { /* write mode register */
i8237_rA = data & 0xFF;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rA (mode) set to %02X\n", i8237_rA);
return 0;
}
}
}
uint8 i8237_rCx(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) {
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rC\n");
return 0;
} else { /* clear byte pointer FF */
i8237_rD = 0;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rD (FF) cleared\n");
return 0;
}
}
}
uint8 i8237_rDx(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) { /* read temporary register */
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rD\n");
return 0;
} else { /* master clear */
i8237_reset1();
sim_debug (DEBUG_reg, &i8237_dev, "i8237 master clear\n");
return 0;
}
}
}
uint8 i8237_rEx(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) {
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rE\n");
return 0;
} else { /* clear mask register */
i8237_rB = 0;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) cleared\n");
return 0;
}
}
}
uint8 i8237_rFx(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8237_get_dn()) != 0xFF) {
if (io == 0) {
sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rF\n");
return 0;
} else { /* write all mask register bits */
i8237_rB = data & 0x0F;
sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB);
return 0;
}
}
}
/* end of i8237.c */

View file

@ -0,0 +1,318 @@
/* i8251.c: Intel 8251 UART 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:
These functions support a simulated i8251 interface device on an iSBC.
The device had one physical I/O port which could be connected
to any serial I/O device that would connect to a current loop,
RS232, or TTY interface. Available baud rates were jumper
selectable for each port from 110 to 9600.
All I/O is via programmed I/O. The i8251 has a status port
and a data port.
The simulated device does not support synchronous mode. The simulated device
supports a select from I/O space and one address line. The data port is at the
lower address and the status/command port is at the higher.
A write to the status port can select some options for the device:
Asynchronous Mode Instruction
7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+
| S2 S1 EP PEN L2 L1 B2 B1|
+---+---+---+---+---+---+---+---+
Baud Rate Factor
B2 0 1 0 1
B1 0 0 1 1
sync 1X 16X 64X
mode
Character Length
L2 0 1 0 1
L1 0 0 1 1
5 6 7 8
bits bits bits bits
EP - A 1 in this bit position selects even parity.
PEN - A 1 in this bit position enables parity.
Number of Stop Bits
S2 0 1 0 1
S1 0 0 1 1
invalid 1 1.5 2
bit bits bits
Command Instruction Format
7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+
| EH IR RTS ER SBRK RxE DTR TxE|
+---+---+---+---+---+---+---+---+
TxE - A 1 in this bit position enables transmit.
DTR - A 1 in this bit position forces *DTR to zero.
RxE - A 1 in this bit position enables receive.
SBRK - A 1 in this bit position forces TxD to zero.
ER - A 1 in this bit position resets the error bits
RTS - A 1 in this bit position forces *RTS to zero.
IR - A 1 in this bit position returns the 8251 to Mode Instruction Format.
EH - A 1 in this bit position enables search for sync characters.
A read of the status port gets the port status:
Status Read Format
7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+
|DSR SD FE OE PE TxE RxR TxR|
+---+---+---+---+---+---+---+---+
TxR - A 1 in this bit position signals transmit ready to receive a character.
RxR - A 1 in this bit position signals receiver has a character.
TxE - A 1 in this bit position signals transmitter has no more characters to transmit.
PE - A 1 in this bit signals a parity error.
OE - A 1 in this bit signals an transmit overrun error.
FE - A 1 in this bit signals a framing error.
SD - A 1 in this bit position returns the 8251 to Mode Instruction Format.
DSR - A 1 in this bit position signals *DSR is at zero.
A read from the data port gets the typed character, a write
to the data port writes the character to the device.
*/
#include "system_defs.h"
/* 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 i8251_svc (UNIT *uptr);
t_stat i8251_reset (DEVICE *dptr, uint16 base);
void i8251_reset1(uint8 devnum);
uint8 i8251_get_dn(void);
uint8 i8251s(t_bool io, uint8 data);
uint8 i8251d(t_bool io, uint8 data);
/* globals */
int32 i8251_devnum = 0; //initially, no 8251 instances
uint16 i8251_port[4]; //base port assigned to each 8251 instance
/* i8251 Standard I/O Data Structures */
/* up to 1 i8251 devices */
UNIT i8251_unit = {
{ UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT },
{ UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT },
{ UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT },
{ UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }
};
REG i8251_reg[4] = {
{ HRDATA (DATA0, i8251_unit[0].buf, 8) },
{ HRDATA (STAT0, i8251_unit[0].u3, 8) },
{ HRDATA (MODE0, i8251_unit[0].u4, 8) },
{ HRDATA (CMD0, i8251_unit[0].u5, 8) },
{ HRDATA (DATA1, i8251_unit[1].buf, 8) },
{ HRDATA (STAT1, i8251_unit[1].u3, 8) },
{ HRDATA (MODE1, i8251_unit[1].u4, 8) },
{ HRDATA (CMD1, i8251_unit[1].u5, 8) },
{ HRDATA (DATA2, i8251_unit[2].buf, 8) },
{ HRDATA (STAT2, i8251_unit[2].u3, 8) },
{ HRDATA (MODE2, i8251_unit[2].u4, 8) },
{ HRDATA (CMD2, i8251_unit[2].u5, 8) },
{ HRDATA (DATA3, i8251_unit[3].buf, 8) },
{ HRDATA (STAT3, i8251_unit[3].u3, 8) },
{ HRDATA (MOD3E, i8251_unit[3].u4, 8) },
{ HRDATA (CMD3, i8251_unit[3].u5, 8) },
{ NULL }
};
DEBTAB i8251_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "XACK", DEBUG_xack },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
MTAB i8251_mod[] = {
{ UNIT_ANSI, 0, "TTY", "TTY", NULL },
{ UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL },
{ 0 }
};
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
DEVICE i8251_dev = {
"8251", //name
i8251_unit, //units
i8251_reg, //registers
i8251_mod, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
// &i8251_reset, //reset
NULL, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
0, //flags
0, //dctrl
i8251_debug, //debflags
NULL, //msize
NULL //lname
};
/* Service routines to handle simulator functions */
/* i8251_svc - actually gets char & places in buffer */
t_stat i8251_svc (UNIT *uptr)
{
int32 temp;
sim_activate (&i8251_unit, i8251_unit.wait); /* continue poll */
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG)
return temp; /* no char or error? */
i8251_unit.buf = temp & 0xFF; /* Save char */
i8251_unit.u3 |= RXR; /* Set status */
/* Do any special character handling here */
i8251_unit.pos++;
return SCPE_OK;
}
/* Reset routine */
t_stat i8251_reset (DEVICE *dptr, uint16 base)
{
if (i8251_devnum >= I8251_NUM) {
sim_printf("8251_reset: too many devices!\n");
return 0;
}
i8251_port[i8251_devnum] = reg_dev(i8251d, base);
reg_dev(i8251s, base + 1);
i8251_reset1(i8251_devnum);
sim_printf(" 8251-%d: Registered at %04X\n", i8251_devnum, base);
sim_activate (&i8251_unit[i8251_devnum], i8251_unit[i8251_devnum].wait); /* activate unit */
i8259_devnum++;
return SCPE_OK;
}
void i8251_reset1(uint8 devnum)
{
i8251_unit.u3 = TXR + TXE; /* status */
i8251_unit.u4 = 0; /* mode instruction */
i8251_unit.u5 = 0; /* command instruction */
i8251_unit.u6 = 0;
i8251_unit.buf = 0;
i8251_unit.pos = 0;
sim_printf(" 8251-%d: 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 %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 = i8259_get_dn()) != 0xFF) {
if (io == 0) { /* read status port */
return i8251_unit[devnum].u3;
} else { /* write status port */
if (i8251_unit[devnum].u6) { /* if mode, set cmd */
i8251_unit[devnum].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[devnum].u4 = data;
sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data);
i8251_unit[devnum].u6 = 1; /* set cmd received */
}
}
}
return 0;
}
uint8 i8251d(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8259_get_dn()) != 0xFF) {
if (io == 0) { /* read data port */
i8251_unit[devnum].u3 &= ~RXR;
return (i8251_unit[devnum].buf);
} else { /* write data port */
sim_putchar(data);
}
}
return 0;
}
/* end of i8251.c */

View file

@ -0,0 +1,235 @@
/* 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 base and size.
24 Apr 15 -- Modified to use simh_debug
NOTES:
*/
#include "system_defs.h"
/* external function prototypes */
extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16);
/* external globals */
extern uint16 port; //port called in dev_table[port]
/* globals */
int32 i8253_devnum = 0; //actual number of 8253 instances + 1
uint16 i8253_port[4]; //base port registered to each instance
/* function prototypes */
t_stat i8253_svc (UNIT *uptr);
t_stat i8253_reset (DEVICE *dptr, uint16 base);
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 = {
"8251", //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)
{
int32 temp;
sim_activate (&i8253_unit[0], i8253_unit[0].wait); /* continue poll */
return SCPE_OK;
}
/* Reset routine */
t_stat i8253_reset (DEVICE *dptr, uint16 port)
{
if (i8253_devnum > I8253_NUM) {
sim_printf("i8253_reset: too many devices!\n");
return SCPE_MEM;
}
i8253_port[i8253_devnum] = reg_dev(i8253t0, port);
reg_dev(i8253t1, port + 1);
reg_dev(i8253t2, port + 2);
reg_dev(i8253c, port + 3);
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_printf(" 8253-%d: Reset\n", i8253_devnum);
sim_printf(" 8253-%d: Registered at %03X\n", i8253_devnum, port);
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 %03X 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 */
i8253_unit[devnum].u3 = data;
return 0;
} else { /* write data port */
return i8253_unit[devnum].u3;
}
}
return 0;
}
uint8 i8253t1(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8253_get_dn()) != 0xFF) {
if (io == 0) { /* read data port */
i8253_unit[devnum].u4 = data;
return 0;
} else { /* write data port */
return i8253_unit[devnum].u4;
}
}
return 0;
}
uint8 i8253t2(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8253_get_dn()) != 0xFF) {
if (io == 0) { /* read data port */
i8253_unit[devnum].u5 = data;
return 0;
} else { /* write data port */
return i8253_unit[devnum].u5;
}
}
return 0;
}
uint8 i8253c(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8253_get_dn()) != 0xFF) {
if (io == 0) { /* read status port */
i8253_unit[devnum].u6 = data;
return 0;
} else { /* write data port */
return i8253_unit[devnum].u6;
}
}
return 0;
}
/* end of i8253.c */

View file

@ -0,0 +1,288 @@
/* i8255.c: Intel i8255 PIO 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:
These functions support a simulated i8255 interface device on an iSBC.
The device has threee physical 8-bit I/O ports which could be connected
to any parallel I/O device.
All I/O is via programmed I/O. The i8255 has a control port (PIOS)
and three data ports (PIOA, PIOB, and PIOC).
The simulated device supports a select from I/O space and two address lines.
The data ports are at the lower addresses and the control port is at
the highest.
A write to the control port can configure the device:
Control Word
+---+---+---+---+---+---+---+---+
| D7 D6 D5 D4 D3 D2 D1 D0|
+---+---+---+---+---+---+---+---+
Group B
D0 Port C (lower) 1-Input, 0-Output
D1 Port B 1-Input, 0-Output
D2 Mode Selection 0-Mode 0, 1-Mode 1
Group A
D3 Port C (upper) 1-Input, 0-Output
D4 Port A 1-Input, 0-Output
D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2
D7 Mode Set Flag 1=Active, 0=Bit Set
Mode 0 - Basic Input/Output
Mode 1 - Strobed Input/Output
Mode 2 - Bidirectional Bus
Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset
A read to the data ports gets the current port value, a write
to the data ports writes the character to the device.
This program simulates up to 4 i8255 devices. It handles 2 i8255
devices on the iSBC 80/10 SBC. Other devices could be on other
multibus boards in the simulated system.
*/
#include "system_defs.h" /* system header in system dir */
/* external globals */
extern uint16 port; //port called in dev_table[port]
/* function prototypes */
t_stat i8255_reset (DEVICE *dptr, uint16 base);
uint8 i8255_get_dn(void);
uint8 i8255s(t_bool io, uint8 data);
uint8 i8255a(t_bool io, uint8 data);
uint8 i8255b(t_bool io, uint8 data);
uint8 i8255c(t_bool io, uint8 data);
/* external function prototypes */
extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16);
/* globals */
int32 i8255_devnum = 0; //actual number of 8255 instances + 1
uint16 i8255_port[4]; //base port registered to each instance
/* these bytes represent the input and output to/from a port instance */
uint8 i8255_A[4]; //port A byte I/O
uint8 i8255_B[4]; //port B byte I/O
uint8 i8255_C[4]; //port C byte I/O
/* i8255 Standard I/O Data Structures */
/* up to 4 i8255 devices */
UNIT i8255_unit[] = {
{ UDATA (0, 0, 0) }, /* i8255 0 */
{ UDATA (0, 0, 0) }, /* i8255 1 */
{ UDATA (0, 0, 0) }, /* i8255 2 */
{ UDATA (0, 0, 0) } /* i8255 3 */
};
REG i8255_reg[] = {
{ HRDATA (CS0, i8255_unit[0].u3, 8) }, /* i8255 0 */
{ HRDATA (A0, i8255_A[0], 8) },
{ HRDATA (B0, i8255_B[0], 8) },
{ HRDATA (C0, i8255_C[0], 8) },
{ HRDATA (CS1, i8255_unit[1].u3, 8) }, /* i8255 1 */
{ HRDATA (A1, i8255_A[1], 8) },
{ HRDATA (B1, i8255_B[1], 8) },
{ HRDATA (C1, i8255_C[1], 8) },
{ HRDATA (CS2, i8255_unit[2].u3, 8) }, /* i8255 2 */
{ HRDATA (A2, i8255_A[2], 8) },
{ HRDATA (B2, i8255_B[2], 8) },
{ HRDATA (C2, i8255_C[2], 8) },
{ HRDATA (CS3, i8255_unit[3].u3, 8) }, /* i8255 3 */
{ HRDATA (A3, i8255_A[3], 8) },
{ HRDATA (B3, i8255_B[3], 8) },
{ HRDATA (C3, i8255_C[3], 8) },
{ NULL }
};
DEBTAB i8255_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
DEVICE i8255_dev = {
"8255", //name
i8255_unit, //units
i8255_reg, //registers
NULL, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
// &i8255_reset, //reset
NULL, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
0, //flags
0, //dctrl
i8255_debug, //debflags
NULL, //msize
NULL //lname
};
/* Reset routine */
t_stat i8255_reset (DEVICE *dptr, uint16 base)
{
if (i8255_devnum > I8255_NUM) {
sim_printf("i8255_reset: too many devices!\n");
return SCPE_MEM;
}
i8255_port[i8255_devnum] = reg_dev(i8255a, base);
reg_dev(i8255b, base + 1);
reg_dev(i8255c, base + 2);
reg_dev(i8255s, base + 3);
i8255_unit[i8255_devnum].u3 = 0x9B; /* control */
i8255_A[i8255_devnum] = 0xFF; /* Port A */
i8255_B[i8255_devnum] = 0xFF; /* Port B */
i8255_C[i8255_devnum] = 0xFF; /* Port C */
sim_printf(" 8255-%d: Reset\n", i8255_devnum);
sim_printf(" 8255-%d: Registered at %03X\n", i8255_devnum, base);
i8255_devnum++;
return SCPE_OK;
}
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 %03X not in 8255 device table\n", port);
return 0xFF;
}
/* I/O instruction handlers, called from the CPU module when an
IN or OUT instruction is issued.
*/
/* i8255 functions */
uint8 i8255s(t_bool io, uint8 data)
{
uint8 bit;
uint8 devnum;
if ((devnum = i8255_get_dn()) != 0xFF) {
if (io == 0) { /* read status port */
return i8255_unit[devnum].u3;
} else { /* write status port */
if (data & 0x80) { /* mode instruction */
i8255_unit[devnum].u3 = data;
sim_printf(" 8255-%d: Mode Instruction=%02X\n", devnum, data);
if (data & 0x64)
sim_printf(" Mode 1 and 2 not yet implemented\n");
} else { /* bit set */
bit = (data & 0x0E) >> 1; /* get bit number */
if (data & 0x01) { /* set bit */
i8255_C[devnum] |= (0x01 << bit);
} else { /* reset bit */
i8255_C[devnum] &= ~(0x01 << bit);
}
}
}
}
return 0;
}
uint8 i8255a(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8255_get_dn()) != 0xFF) {
if (io == 0) { /* read data port */
//return (i8255_unit[devnum].u4);
return (i8255_A[devnum]);
} else { /* write data port */
i8255_A[devnum] = data;
sim_printf(" 8255-%d: Port A = %02X\n", devnum, data);
}
}
return 0;
}
uint8 i8255b(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8255_get_dn()) != 0xFF) {
if (io == 0) { /* read data port */
return (i8255_B[devnum]);
} else { /* write data port */
i8255_B[devnum] = data;
sim_printf(" 8255-%d: Port B = %02X\n", devnum, data);
}
}
return 0;
}
uint8 i8255c(t_bool io, uint8 data)
{
uint8 devnum;
if ((devnum = i8255_get_dn()) != 0xFF) {
if (io == 0) { /* read data port */
return (i8255_C[devnum]);
} else { /* write data port */
i8255_C[devnum] = data;
sim_printf(" 8255-%d: Port C = %02X\n", devnum, data);
}
}
return 0;
}
/* end of i8255.c */

View file

@ -0,0 +1,263 @@
/* i8259.c: Intel i8259 PIC 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.
NOTES:
This software was written by Bill Beech, 24 Jan 13, to allow emulation of
more complex Computer Systems.
This program simulates up to 4 i8259 devices.
u3 = IRR
u4 = ISR
u5 = IMR
*/
#include "system_defs.h" /* system header in system dir */
/* external globals */
extern uint16 port; //port called in dev_table[port]
/* function prototypes */
void i8259_dump(uint8 devnum);
t_stat i8259_reset (DEVICE *dptr, uint16 base);
uint8 i8259_get_dn(void);
uint8 i8259a(t_bool io, uint8 data);
uint8 i8259b(t_bool io, uint8 data);
/* external function prototypes */
extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16);
/* globals */
int32 i8259_devnum = 0; //initially, no 8259 instances
uint16 i8259_port[4]; //base port assigned to each 8259 instance
uint8 i8259_ints[4]; //8 interrupt inputs for each 8259 instance
uint8 i8259_icw1[4];
uint8 i8259_icw2[4];
uint8 i8259_icw3[4];
uint8 i8259_icw4[4];
uint8 i8259_ocw1[4];
uint8 i8259_ocw2[4];
uint8 i8259_ocw3[4];
uint8 icw_num0 = 1, icw_num1 = 1;
/* i8259 Standard I/O Data Structures */
/* up to 4 i8259 devices */
UNIT i8259_unit[] = {
{ UDATA (0, 0, 0) }, /* i8259 0 */
{ UDATA (0, 0, 0) }, /* i8259 1 */
{ UDATA (0, 0, 0) }, /* i8259 2 */
{ UDATA (0, 0, 0) } /* i8259 3 */
};
REG i8259_reg[] = {
{ HRDATA (IRR0, i8259_unit[0].u3, 8) }, /* i8259 0 */
{ HRDATA (ISR0, i8259_unit[0].u4, 8) },
{ HRDATA (IMR0, i8259_unit[0].u5, 8) },
{ HRDATA (IRR1, i8259_unit[1].u3, 8) }, /* i8259 0 */
{ HRDATA (ISR1, i8259_unit[1].u4, 8) },
{ HRDATA (IMR1, i8259_unit[1].u5, 8) },
{ HRDATA (IRR2, i8259_unit[2].u3, 8) }, /* i8259 2 */
{ HRDATA (ISR2, i8259_unit[2].u4, 8) },
{ HRDATA (IMR2, i8259_unit[2].u5, 8) },
{ HRDATA (IRR3, i8259_unit[3].u3, 8) }, /* i8259 3 */
{ HRDATA (ISR3, i8259_unit[3].u4, 8) },
{ HRDATA (IMR3, i8259_unit[3].u5, 8) },
{ NULL }
};
DEBTAB i8259_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
/* address width is set to 16 bits to use devices in 8086/8088 implementations */
DEVICE i8259_dev = {
"8259", //name
i8259_unit, //units
i8259_reg, //registers
NULL, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
// &i8259_reset, //reset
NULL, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
0, //flags
0, //dctrl
i8259_debug, //debflags
NULL, //msize
NULL //lname
};
void i8259_dump(uint8 devnum)
{
sim_printf("Device %d\n", devnum);
sim_printf(" IRR = %02X\n", i8259_unit[devnum].u3);
sim_printf(" ISR = %02X\n", i8259_unit[devnum].u4);
sim_printf(" IMR = %02X\n", i8259_unit[devnum].u5);
sim_printf(" ICW1 = %02X\n", i8259_icw1[devnum]);
sim_printf(" ICW2 = %02X\n", i8259_icw2[devnum]);
sim_printf(" ICW3 = %02X\n", i8259_icw3[devnum]);
sim_printf(" ICW4 = %02X\n", i8259_icw4[devnum]);
sim_printf(" OCW1 = %02X\n", i8259_ocw1[devnum]);
sim_printf(" OCW2 = %02X\n", i8259_ocw2[devnum]);
sim_printf(" OCW3 = %02X\n", i8259_ocw3[devnum]);
}
/* Reset routine */
t_stat i8259_reset (DEVICE *dptr, uint16 base)
{
if (i8259_devnum > I8259_NUM) {
sim_printf("i8259_reset: too many devices!\n");
return SCPE_MEM;
}
i8259_port[i8259_devnum] = reg_dev(i8259a, base);
reg_dev(i8259b, base + 1);
i8259_unit[i8259_devnum].u3 = 0x00; /* IRR */
i8259_unit[i8259_devnum].u4 = 0x00; /* ISR */
i8259_unit[i8259_devnum].u5 = 0x00; /* IMR */
sim_printf(" 8259-%d: Reset\n", i8259_devnum);
sim_printf(" 8259-%d: Registered at %03X\n", i8259_devnum, base);
i8259_devnum++;
return SCPE_OK;
}
uint8 i8259_get_dn(void)
{
int i;
for (i=0; i<I8259_NUM; i++)
if (port >=i8259_port[i] && port <= i8259_port[i] + 2)
return i;
sim_printf("i8259_get_dn: port %03X not in 8259 device table\n", port);
return 0xFF;
}
/* I/O instruction handlers, called from the CPU module when an
IN or OUT instruction is issued.
*/
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("8259a-%d: data = %02X\n", devnum, data);
icw_num0++; /* step ICW number */
}
}
//i8259_dump(devnum);
return 0;
}
uint8 i8259b(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_num1 = 1;
}
if (icw_num1 == 1) {
i8259_icw1[devnum] = data; /* ICW1 */
i8259_unit[devnum].u5 = 0x00; /* clear IMR */
i8259_ocw3[devnum] = 0x02; /* clear OCW3, Sel IRR */
} else {
switch (data & 0x18) {
case 0: /* OCW2 */
i8259_ocw2[devnum] = data;
break;
case 8: /* OCW3 */
i8259_ocw3[devnum] = data;
break;
default:
sim_printf("8259b-%d: OCW Error %02X\n", devnum, data);
break;
}
}
sim_printf("8259b-%d: data = %02X\n", devnum, data);
icw_num1++; /* step ICW number */
}
}
//i8259_dump(devnum);
return 0;
}
/* end of i8259.c */

View file

@ -0,0 +1,252 @@
/* i8273.c: Intel i8273 UART adapter
Copyright (c) 2011, William A. Beech
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of William A. Beech shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from William A. Beech.
These functions support a simulated i8273 interface device on an iSBC.
The device had one physical I/O port which could be connected
to any serial I/O device that would connect to a current loop,
RS232, or TTY interface. Available baud rates were jumper
selectable for each port from 110 to 9600.
All I/O is via programmed I/O. The i8273 has a status port
and a data port.
The simulated device does not support synchronous mode. The simulated device
supports a select from I/O space and one address line. The data port is at the
lower address and the status/command port is at the higher.
A write to the status port can select some options for the device:
Asynchronous Mode Instruction
+---+---+---+---+---+---+---+---+
| S2 S1 EP PEN L2 L1 B2 B1|
+---+---+---+---+---+---+---+---+
Baud Rate Factor
B2 0 1 0 1
B1 0 0 1 1
sync 1X 16X 64X
mode
Character Length
L2 0 1 0 1
L1 0 0 1 1
5 6 7 8
bits bits bits bits
EP - A 1 in this bit position selects even parity.
PEN - A 1 in this bit position enables parity.
Number of Stop Bits
S2 0 1 0 1
S1 0 0 1 1
invalid 1 1.5 2
bit bits bits
Command Instruction Format
+---+---+---+---+---+---+---+---+
| EH IR RTS ER SBRK RxE DTR TxE|
+---+---+---+---+---+---+---+---+
TxE - A 1 in this bit position enables transmit.
DTR - A 1 in this bit position forces *DTR to zero.
RxE - A 1 in this bit position enables receive.
SBRK - A 1 in this bit position forces TxD to zero.
ER - A 1 in this bit position resets the error bits
RTS - A 1 in this bit position forces *RTS to zero.
IR - A 1 in this bit position returns the 8251 to Mode Instruction Format.
EH - A 1 in this bit position enables search for sync characters.
A read of the status port gets the port status:
Status Read Format
+---+---+---+---+---+---+---+---+
|DSR SD FE OE PE TxE RxR TxR|
+---+---+---+---+---+---+---+---+
TxR - A 1 in this bit position signals transmit ready to receive a character.
RxR - A 1 in this bit position signals receiver has a character.
TxE - A 1 in this bit position signals transmitter has no more characters to transmit.
PE - A 1 in this bit signals a parity error.
OE - A 1 in this bit signals an transmit overrun error.
FE - A 1 in this bit signals a framing error.
SD - A 1 in this bit position returns the 8251 to Mode Instruction Format.
DSR - A 1 in this bit position signals *DSR is at zero.
A read to the data port gets the buffered character, a write
to the data port writes the character to the device.
*/
#include <stdio.h>
#include "multibus_defs.h"
#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */
#define UNIT_ANSI (1 << UNIT_V_ANSI)
uint8
wr0 = 0, /* command register */
wr1 = 0, /* enable register */
wr2 = 0, /* CH A mode register */
/* CH B interrups vector */
wr3 = 0, /* configuration register 1 */
wr4 = 0, /* configuration register 2 */
wr5 = 0, /* configuration register 3 */
wr6 = 0, /* sync low byte */
wr7 = 0, /* sync high byte */
rr0 = 0, /* status register */
rr1 = 0, /* error register */
rr2 = 0; /* read interrupt vector */
/* function prototypes */
t_stat i8273_reset (DEVICE *dptr);
/* i8273 Standard I/O Data Structures */
UNIT i8273_unit = { UDATA (NULL, 0, 0), KBD_POLL_WAIT };
REG i8273_reg[] = {
{ HRDATA (WR0, wr0, 8) },
{ HRDATA (WR1, wr1, 8) },
{ HRDATA (WR2, wr2, 8) },
{ HRDATA (WR3, wr3, 8) },
{ HRDATA (WR4, wr4, 8) },
{ HRDATA (WR5, wr5, 8) },
{ HRDATA (WR6, wr6, 8) },
{ HRDATA (WR7, wr7, 8) },
{ HRDATA (RR0, rr0, 8) },
{ HRDATA (RR0, rr1, 8) },
{ HRDATA (RR0, rr2, 8) },
{ NULL }
};
MTAB i8273_mod[] = {
{ UNIT_ANSI, 0, "TTY", "TTY", NULL },
{ UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL },
{ 0 }
};
DEBTAB i8273_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE i8273_dev = {
"8273", //name
&i8273_unit, //units
i8273_reg, //registers
i8273_mod, //modifiers
1, //numunits
16, //aradix
32, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
i8273_reset, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
i8273_debug, //debflags
NULL, //msize
NULL //lname
};
/* Service routines to handle simulator functions */
/* Reset routine */
t_stat i8273_reset (DEVICE *dptr)
{
wr0 = 0; /* command register */
wr1 = 0; /* enable register */
wr2 = 0; /* CH A mode register */
/* CH B interrups vector */
wr3 = 0; /* configuration register 1 */
wr4 = 0; /* configuration register 2 */
wr5 = 0; /* configuration register 3 */
wr6 = 0; /* sync low byte */
wr7 = 0; /* sync high byte */
rr0 = 0; /* status register */
rr1 = 0; /* error register */
rr2 = 0; /* read interrupt vector */
sim_printf(" 8273 Reset\n");
return SCPE_OK;
}
/* I/O instruction handlers, called from the CPU module when an
IN or OUT instruction is issued.
Each function is passed an 'io' flag, where 0 means a read from
the port, and 1 means a write to the port. On input, the actual
input is passed as the return value, on output, 'data' is written
to the device.
*/
int32 i8273s(int32 io, int32 data)
{
if (io == 0) { /* read status port */
return i8273_unit.u3;
} else { /* write status port */
if (data == 0x40) { /* reset port! */
i8273_unit.u3 = 0x05; /* status */
i8273_unit.u4 = 0; /* mode instruction */
i8273_unit.u5 = 0; /* command instruction */
i8273_unit.u6 = 0;
i8273_unit.buf = 0;
i8273_unit.pos = 0;
sim_printf("8273 Reset\n");
} else if (i8273_unit.u6) {
i8273_unit.u5 = data;
sim_printf("8273 Command Instruction=%02X\n", data);
} else {
i8273_unit.u4 = data;
sim_printf("8273 Mode Instruction=%02X\n", data);
i8273_unit.u6++;
}
return (0);
}
}
int32 i8273d(int32 io, int32 data)
{
if (io == 0) { /* read data port */
i8273_unit.u3 &= 0xFD;
return (i8273_unit.buf);
} else { /* write data port */
sim_putchar(data);
}
return 0;
}

View file

@ -0,0 +1,351 @@
/* i8274.c: Intel i8274 MPSC adapter
Copyright (c) 2011, William A. Beech
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of William A. Beech shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from William A. Beech.
These functions support a simulated i8274 interface device on an iSBC.
The device had two physical I/O ports which could be connected
to any serial I/O device that would connect to an RS232 interface.
All I/O is via programmed I/O. The i8274 has a status port
and a data port.
The simulated device does not support synchronous mode. The simulated device
supports a select from I/O space and two address lines. The data port is at the
lower address and the status/command port is at the higher address for each
channel.
Minimum simulation is provided for this device. Channel A is used as a
console port for the iSBC-88/45
A write to the status port can select some options for the device:
Asynchronous Mode Instruction
+---+---+---+---+---+---+---+---+
| S2 S1 EP PEN L2 L1 B2 B1|
+---+---+---+---+---+---+---+---+
Baud Rate Factor
B2 0 1 0 1
B1 0 0 1 1
sync 1X 16X 64X
mode
Character Length
L2 0 1 0 1
L1 0 0 1 1
5 6 7 8
bits bits bits bits
EP - A 1 in this bit position selects even parity.
PEN - A 1 in this bit position enables parity.
Number of Stop Bits
S2 0 1 0 1
S1 0 0 1 1
invalid 1 1.5 2
bit bits bits
Command Instruction Format
+---+---+---+---+---+---+---+---+
| EH IR RTS ER SBRK RxE DTR TxE|
+---+---+---+---+---+---+---+---+
TxE - A 1 in this bit position enables transmit.
DTR - A 1 in this bit position forces *DTR to zero.
RxE - A 1 in this bit position enables receive.
SBRK - A 1 in this bit position forces TxD to zero.
ER - A 1 in this bit position resets the error bits
RTS - A 1 in this bit position forces *RTS to zero.
IR - A 1 in this bit position returns the 8251 to Mode Instruction Format.
EH - A 1 in this bit position enables search for sync characters.
A read of the status port gets the port status:
Status Read Format
+---+---+---+---+---+---+---+---+
|DSR SD FE OE PE TxE RxR TxR|
+---+---+---+---+---+---+---+---+
TxR - A 1 in this bit position signals transmit ready to receive a character.
RxR - A 1 in this bit position signals receiver has a character.
TxE - A 1 in this bit position signals transmitter has no more characters to transmit.
PE - A 1 in this bit signals a parity error.
OE - A 1 in this bit signals an transmit overrun error.
FE - A 1 in this bit signals a framing error.
SD - A 1 in this bit position returns the 8251 to Mode Instruction Format.
DSR - A 1 in this bit position signals *DSR is at zero.
A read to the data port gets the buffered character, a write
to the data port writes the character to the device.
*/
#include <stdio.h>
#include "multibus_defs.h"
#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */
#define UNIT_ANSI (1 << UNIT_V_ANSI)
/* register definitions */
/* channel A */
uint8 wr0a = 0, /* command register */
wr1a = 0, /* enable register */
wr2a = 0, /* mode register */
wr3a = 0, /* configuration register 1 */
wr4a = 0, /* configuration register 2 */
wr5a = 0, /* configuration register 3 */
wr6a = 0, /* sync low byte */
wr7a = 0, /* sync high byte */
rr0a = 0, /* status register */
rr1a = 0, /* error register */
rr2a = 0; /* read interrupt vector */
/* channel B */
uint8 wr0b = 0, /* command register */
wr1b = 0, /* enable register */
wr2b = 0, /* CH B interrups vector */
wr3b = 0, /* configuration register 1 */
wr4b = 0, /* configuration register 2 */
wr5b = 0, /* configuration register 3 */
wr6b = 0, /* sync low byte */
wr7b = 0, /* sync high byte */
rr0b = 0, /* status register */
rr1b = 0, /* error register */
rr2b = 0; /* read interrupt vector */
/* function prototypes */
t_stat i8274_svc (UNIT *uptr);
t_stat i8274_reset (DEVICE *dptr);
int32 i8274As(int32 io, int32 data);
int32 i8274Ad(int32 io, int32 data);
int32 i8274Bs(int32 io, int32 data);
int32 i8274Bd(int32 io, int32 data);
/* i8274 Standard I/O Data Structures */
UNIT i8274_unit = { UDATA (NULL, 0, 0), KBD_POLL_WAIT };
REG i8274_reg[] = {
{ HRDATA (WR0A, wr0a, 8) },
{ HRDATA (WR1A, wr1a, 8) },
{ HRDATA (WR2A, wr2a, 8) },
{ HRDATA (WR3A, wr3a, 8) },
{ HRDATA (WR4A, wr4a, 8) },
{ HRDATA (WR5A, wr5a, 8) },
{ HRDATA (WR6A, wr6a, 8) },
{ HRDATA (WR7A, wr7a, 8) },
{ HRDATA (RR0A, rr0a, 8) },
{ HRDATA (RR0A, rr1a, 8) },
{ HRDATA (RR0A, rr2a, 8) },
{ HRDATA (WR0B, wr0b, 8) },
{ HRDATA (WR1B, wr1b, 8) },
{ HRDATA (WR2B, wr2b, 8) },
{ HRDATA (WR3B, wr3b, 8) },
{ HRDATA (WR4B, wr4b, 8) },
{ HRDATA (WR5B, wr5b, 8) },
{ HRDATA (WR6B, wr6b, 8) },
{ HRDATA (WR7B, wr7b, 8) },
{ HRDATA (RR0B, rr0b, 8) },
{ HRDATA (RR0B, rr1b, 8) },
{ HRDATA (RR0B, rr2b, 8) },
{ NULL }
};
MTAB i8274_mod[] = {
{ UNIT_ANSI, 0, "TTY", "TTY", NULL },
{ UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL },
{ 0 }
};
DEBTAB i8274_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE i8274_dev = {
"8274", //name
&i8274_unit, //units
i8274_reg, //registers
i8274_mod, //modifiers
1, //numunits
16, //aradix
32, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
i8274_reset, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
i8274_debug, //debflags
NULL, //msize
NULL //lname
};
/* Service routines to handle simulator functions */
/* service routine - actually gets char & places in buffer in CH A*/
t_stat i8274_svc (UNIT *uptr)
{
int32 temp;
sim_activate (&i8274_unit, i8274_unit.wait); /* continue poll */
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG)
return temp; /* no char or error? */
i8274_unit.buf = temp & 0xFF; /* Save char */
rr0a |= 0x01; /* Set rx char ready */
/* Do any special character handling here */
i8274_unit.pos++;
return SCPE_OK;
}
/* Reset routine */
t_stat i8274_reset (DEVICE *dptr)
{
wr0a = wr1a = wr2a = wr3a = wr4a = wr5a = wr6a = wr7a = rr0a = rr1a = rr2a = 0;
wr0b = wr1b = wr2b = wr3b = wr4b = wr5b = wr6b = wr7b = rr0b = rr1b = rr2b = 0;
sim_printf(" 8274 Reset\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.
The 8274 contains 2 separate channels, A and B.
*/
/* channel A command/status */
int32 i8274As(int32 io, int32 data)
{
if (io == 0) { /* read status port */
switch(wr0a & 0x7) {
case 0: /* rr0a */
return rr0a;
case 1: /* rr1a */
return rr1a;
case 2: /* rr1a */
return rr2a;
}
return 0; /* bad register select */
} else { /* write status port */
switch(wr0a & 0x7) {
case 0: /* wr0a */
wr0a = data;
if ((wr0a & 0x38) == 0x18) { /* channel reset */
wr0a = wr1a = wr2a = wr3a = wr4a = wr5a = 0;
wr6a = wr7a = rr0a = rr1a = rr2a = 0;
sim_printf("8274 Channel A reset\n");
}
break;
case 1: /* wr1a */
wr1a = data;
break;
case 2: /* wr2a */
wr2a = data;
break;
case 3: /* wr3a */
wr3a = data;
break;
case 4: /* wr4a */
wr4a = data;
break;
case 5: /* wr5a */
wr5a = data;
break;
case 6: /* wr6a */
wr6a = data;
break;
case 7: /* wr7a */
wr7a = data;
break;
}
sim_printf("8274 Command WR%dA=%02X\n", wr0a & 0x7, data);
return 0;
}
}
/* channel A data */
int32 i8274Ad(int32 io, int32 data)
{
if (io == 0) { /* read data port */
rr0a &= 0xFE;
return (i8274_unit.buf);
} else { /* write data port */
sim_putchar(data);
}
return 0;
}
/* channel B command/status */
int32 i8274Bs(int32 io, int32 data)
{
if (io == 0) { /* read status port */
return i8274_unit.u3;
} else { /* write status port */
if (data == 0x40) { /* reset port! */
sim_printf("8274 Reset\n");
} else if (i8274_unit.u6) {
i8274_unit.u5 = data;
sim_printf("8274 Command Instruction=%02X\n", data);
} else {
i8274_unit.u4 = data;
sim_printf("8274 Mode Instruction=%02X\n", data);
i8274_unit.u6++;
}
return (0);
}
}
/* channel B data */
int32 i8274Bd(int32 io, int32 data)
{
if (io == 0) { /* read data port */
i8274_unit.u3 &= 0xFD;
return (i8274_unit.buf);
} else { /* write data port */
sim_putchar(data);
}
return 0;
}
/* end of i8274.c */

View file

@ -0,0 +1,206 @@
/* iPATA.c: Intel i8255 PIO adapter for PATA HD
Copyright (c) 2015, William A. Beech
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of William A. Beech shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from William A. Beech.
NOTES:
These functions support a simulated i8255 interface device on an iSBC.
The device has threee physical 8-bit I/O ports which could be connected
to any parallel I/O device. This is an extension of the i8255.c file to support
an emulated PATA IDE Hard Disk Drive.
All I/O is via programmed I/O. The i8255 has a control port (PIOS)
and three data ports (PIOA, PIOB, and PIOC).
The simulated device supports a select from I/O space and two address lines.
The data ports are at the lower addresses and the control port is at
the highest.
A write to the control port can configure the device:
Control Word
+---+---+---+---+---+---+---+---+
| D7 D6 D5 D4 D3 D2 D1 D0|
+---+---+---+---+---+---+---+---+
Group B
D0 Port C (lower) 1-Input, 0-Output
D1 Port B 1-Input, 0-Output
D2 Mode Selection 0-Mode 0, 1-Mode 1
Group A
D3 Port C (upper) 1-Input, 0-Output
D4 Port A 1-Input, 0-Output
D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2
D7 Mode Set Flag 1=Active, 0=Bit Set
Mode 0 - Basic Input/Output
Mode 1 - Strobed Input/Output
Mode 2 - Bidirectional Bus
Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset
A read to the data ports gets the current port value, a write
to the data ports writes the character to the device.
The Second 8255 on the iSBC 80/10 is used to connect to the IDE PATA
Hard Disk Drive. Pins are defined as shown below:
PA[0..7] High data byte
PB[0..7] Low data byte
PC[0..2] Register select
PC[3..4] CSFX select
PC[5] Read register
PC[6] Write register
*/
#include "system_defs.h"
extern int32 reg_dev(int32 (*routine)(), int32 port);
/* function prototypes */
t_stat pata_reset (DEVICE *dptr, int32 base);
/* i8255 Standard I/O Data Structures */
UNIT pata_unit[] = {
{ UDATA (0, 0, 0) }
};
REG pata_reg[] = {
{ HRDATA (CONTROL0, pata_unit[0].u3, 8) },
{ HRDATA (PORTA0, pata_unit[0].u4, 8) },
{ HRDATA (PORTB0, pata_unit[0].u5, 8) },
{ HRDATA (PORTC0, pata_unit[0].u6, 8) },
{ NULL }
};
DEVICE pata_dev = {
"PATA", //name
pata_unit, //units
pata_reg, //registers
NULL, //modifiers
1, //numunits
16, //aradix
32, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
// &pata_reset, //reset
NULL, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
0, //flags
0, //dctrl
NULL, //debflags
NULL, //msize
NULL //lname
};
/* I/O instruction handlers, called from the CPU module when an
IN or OUT instruction is issued.
*/
int32 patas(int32 io, int32 data)
{
int32 bit;
if (io == 0) { /* read status port */
return pata_unit[0].u3;
} else { /* write status port */
if (data & 0x80) { /* mode instruction */
pata_unit[0].u3 = data;
sim_printf("PATA: 8255 Mode Instruction=%02X\n", data);
if (data & 0x64)
sim_printf(" Mode 1 and 2 not yet implemented\n");
} else { /* bit set */
bit = (data & 0x0E) >> 1; /* get bit number */
if (data & 0x01) { /* set bit */
pata_unit[0].u6 |= (0x01 << bit);
} else { /* reset bit */
pata_unit[0].u6 &= ~(0x01 << bit);
}
}
}
return 0;
}
int32 pataa(int32 io, int32 data)
{
if (io == 0) { /* read data port */
sim_printf("PATA: 8255 Read Port A = %02X\n", pata_unit[0].u4);
return (pata_unit[0].u4);
} else { /* write data port */
pata_unit[0].u4 = data;
sim_printf("PATA: 8255 Write Port A = %02X\n", data);
}
return 0;
}
int32 patab(int32 io, int32 data)
{
if (io == 0) { /* read data port */
sim_printf("PATA: 8255 Read Port B = %02X\n", pata_unit[0].u5);
return (pata_unit[0].u5);
} else { /* write data port */
pata_unit[0].u5 = data;
sim_printf("PATA: 8255 Write Port B = %02X\n", data);
}
return 0;
}
int32 patac(int32 io, int32 data)
{
if (io == 0) { /* read data port */
sim_printf("PATA: 8255 Read Port C = %02X\n", pata_unit[0].u6);
return (pata_unit[0].u6);
} else { /* write data port */
pata_unit[0].u6 = data;
sim_printf("PATA: 8255 Write Port C = %02X\n", data);
}
return 0;
}
/* Reset routine */
t_stat pata_reset (DEVICE *dptr, int32 base)
{
pata_unit[0].u3 = 0x9B; /* control */
pata_unit[0].u4 = 0xFF; /* Port A */
pata_unit[0].u5 = 0xFF; /* Port B */
pata_unit[0].u6 = 0xFF; /* Port C */
reg_dev(pataa, base);
reg_dev(patab, base + 1);
reg_dev(patac, base + 2);
reg_dev(patas, base + 3);
sim_printf(" PATA: Reset\n");
return SCPE_OK;
}

193
IBMPC-Systems/common/pata.c Normal file
View file

@ -0,0 +1,193 @@
/* i8255.c: Intel i8255 PIO 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.
These functions support a simulated i8255 interface device on an iSBC.
The device has threee physical 8-bit I/O ports which could be connected
to any parallel I/O device.
All I/O is via programmed I/O. The i8255 has a control port (PIOS)
and three data ports (PIOA, PIOB, and PIOC).
The simulated device supports a select from I/O space and two address lines.
The data ports are at the lower addresses and the control port is at
the highest.
A write to the control port can configure the device:
Control Word
+---+---+---+---+---+---+---+---+
| D7 D6 D5 D4 D3 D2 D1 D0|
+---+---+---+---+---+---+---+---+
Group B
D0 Port C (lower) 1-Input, 0-Output
D1 Port B 1-Input, 0-Output
D2 Mode Selection 0-Mode 0, 1-Mode 1
Group A
D3 Port C (upper) 1-Input, 0-Output
D4 Port A 1-Input, 0-Output
D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2
D7 Mode Set Flag 1=Active, 0=Bit Set
Mode 0 - Basic Input/Output
Mode 1 - Strobed Input/Output
Mode 2 - Bidirectional Bus
Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset
A read to the data ports gets the current port value, a write
to the data ports writes the character to the device.
?? ??? 10 - Original file.
16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size.
*/
#include "system_defs.h"
extern int32 reg_dev(int32 (*routine)(int32, int32), int32 port);
/* function prototypes */
t_stat pata_reset (DEVICE *dptr, int32 base);
/* i8255 Standard I/O Data Structures */
UNIT pata_unit[] = {
{ UDATA (0, 0, 0) }
};
REG pata_reg[] = {
{ HRDATA (CONTROL0, pata_unit[0].u3, 8) },
{ HRDATA (PORTA0, pata_unit[0].u4, 8) },
{ HRDATA (PORTB0, pata_unit[0].u5, 8) },
{ HRDATA (PORTC0, pata_unit[0].u6, 8) },
{ NULL }
};
DEVICE pata_dev = {
"PATA", //name
pata_unit, //units
pata_reg, //registers
NULL, //modifiers
1, //numunits
16, //aradix
32, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
// &pata_reset, //reset
NULL, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
0, //flags
0, //dctrl
NULL, //debflags
NULL, //msize
NULL //lname
};
/* I/O instruction handlers, called from the CPU module when an
IN or OUT instruction is issued.
*/
int32 patas(int32 io, int32 data)
{
int32 bit;
if (io == 0) { /* read status port */
return pata_unit[0].u3;
} else { /* write status port */
if (data & 0x80) { /* mode instruction */
pata_unit[0].u3 = data;
sim_printf("PATA: 8255 Mode Instruction=%02X\n", data);
if (data & 0x64)
sim_printf(" Mode 1 and 2 not yet implemented\n");
} else { /* bit set */
bit = (data & 0x0E) >> 1; /* get bit number */
if (data & 0x01) { /* set bit */
pata_unit[0].u6 |= (0x01 << bit);
} else { /* reset bit */
pata_unit[0].u6 &= ~(0x01 << bit);
}
}
}
return 0;
}
int32 pataa(int32 io, int32 data)
{
if (io == 0) { /* read data port */
return (pata_unit[0].u4);
} else { /* write data port */
pata_unit[0].u4 = data;
sim_printf("PATA: 8255 Port A = %02X\n", data);
}
return 0;
}
int32 patab(int32 io, int32 data)
{
if (io == 0) { /* read data port */
return (pata_unit[0].u5);
} else { /* write data port */
pata_unit[0].u5 = data;
sim_printf("PATA: 8255 Port B = %02X\n", data);
}
return 0;
}
int32 patac(int32 io, int32 data)
{
if (io == 0) { /* read data port */
return (pata_unit[0].u6);
} else { /* write data port */
pata_unit[0].u6 = data;
sim_printf("PATA: 8255 Port C = %02X\n", data);
}
return 0;
}
/* Reset routine */
t_stat pata_reset (DEVICE *dptr, int32 base)
{
pata_unit[0].u3 = 0x9B; /* control */
pata_unit[0].u4 = 0xFF; /* Port A */
pata_unit[0].u5 = 0xFF; /* Port B */
pata_unit[0].u6 = 0xFF; /* Port C */
reg_dev(pataa, base);
reg_dev(patab, base + 1);
reg_dev(patac, base + 2);
reg_dev(patas, base + 3);
sim_printf(" PATA: Reset\n");
return SCPE_OK;
}

View file

@ -0,0 +1,465 @@
/* pcbus.c: PC bus simulator
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:
This software was written by Bill Beech, Jul 2016, to allow emulation of PC XT
Computer Systems.
*/
#include "system_defs.h"
int32 mbirq = 0; /* set no interrupts */
/* function prototypes */
t_stat xtbus_svc(UNIT *uptr);
t_stat xtbus_reset(DEVICE *dptr);
void set_irq(int32 int_num);
void clr_irq(int32 int_num);
uint8 nulldev(t_bool io, uint8 data);
uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port);
void dump_dev_table(void);
t_stat xtbus_reset (DEVICE *dptr);
uint8 xtbus_get_mbyte(uint32 addr);
void xtbus_put_mbyte(uint32 addr, uint8 val);
/* external function prototypes */
extern t_stat SBC_reset(DEVICE *dptr); /* reset the PC XT simulator */
extern void set_cpuint(int32 int_num);
/* external globals */
extern int32 int_req; /* i8088 INT signal */
extern uint16 port; //port called in dev_table[port]
/* Standard SIMH Device Data Structures */
UNIT xtbus_unit = {
UDATA (&xtbus_svc, 0, 0), 20
};
REG xtbus_reg[] = {
{ HRDATA (MBIRQ, mbirq, 32) },
};
DEBTAB xtbus_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE xtbus_dev = {
"PCBUS", //name
&xtbus_unit, //units
xtbus_reg, //registers
NULL, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
&xtbus_reset, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
xtbus_debug, //debflags
NULL, //msize
NULL //lname
};
/* Service routines to handle simulator functions */
/* service routine - actually does the simulated interrupts */
t_stat xtbus_svc(UNIT *uptr)
{
switch (mbirq) {
case INT_1:
set_cpuint(INT_R);
sim_printf("xtbus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req);
break;
default:
//sim_printf("xtbus_svc: default mbirq=%04X\n", mbirq);
break;
}
sim_activate (&xtbus_unit, xtbus_unit.wait); /* continue poll */
return SCPE_OK;
}
/* Reset routine */
t_stat xtbus_reset(DEVICE *dptr)
{
SBC_reset(NULL);
sim_printf(" Xtbus: Reset\n");
sim_activate (&xtbus_unit, xtbus_unit.wait); /* activate unit */
return SCPE_OK;
}
void set_irq(int32 int_num)
{
mbirq |= int_num;
sim_printf("set_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq);
}
void clr_irq(int32 int_num)
{
mbirq &= ~int_num;
sim_printf("clr_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq);
}
/* This is the I/O configuration table. There are 1024 possible
device addresses, if a device is plugged to a port it's routine
address is here, 'nulldev' means no device has been registered.
The actual 808X can address 65,536 I/O ports but the IBM only uses
the first 1024. */
struct idev {
uint8 (*routine)(t_bool io, uint8 data);
};
struct idev dev_table[1024] = {
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 000H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 004H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 008H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 00CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 010H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 014H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 018H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 01CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 020H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 024H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 028H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 02CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 030H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 034H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 038H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 03CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 040H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 044H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 048H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 04CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 050H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 054H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 058H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 05CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 060H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 064H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 068H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 06CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 070H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 074H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 078H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 07CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 080H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 084H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 088H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 08CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 090H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 094H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 098H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 09CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0CCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0DCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0ECH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0FCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 100H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 104H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 108H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 10CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 110H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 114H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 118H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 11CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 120H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 124H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 128H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 12CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 130H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 134H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 138H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 13CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 140H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 144H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 148H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 14CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 150H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 154H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 158H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 15CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 160H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 164H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 168H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 16CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 170H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 174H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 178H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 17CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 180H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 184H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 188H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 18CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 190H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 194H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 198H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 19CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1CCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1D0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1D4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1D8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1DCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1E0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1E4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1E8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1ECH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1F0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1F4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1F8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1FCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 200H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 204H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 208H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 20CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 210H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 214H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 218H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 21CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 220H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 224H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 228H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 22CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 230H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 234H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 238H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 23CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 240H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 244H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 248H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 24CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 250H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 254H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 258H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 25CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 260H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 264H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 268H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 26CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 270H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 274H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 278H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 27CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 280H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 284H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 288H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 28CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 290H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 294H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 298H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 29CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2CCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2D0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2D4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2D8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2DCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2E0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2E4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2E8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2ECH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2F0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2F4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2F8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2FCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 300H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 304H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 308H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 30CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 310H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 314H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 318H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 31CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 320H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 324H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 328H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 32CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 330H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 334H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 338H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 33CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 340H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 344H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 348H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 34CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 350H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 354H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 358H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 35CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 360H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 364H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 368H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 36CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 370H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 374H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 378H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 37CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 380H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 384H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 388H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 38CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 390H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 394H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 398H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 39CH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3CCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3D0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3D4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3D8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3DCH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3E0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3E4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3E8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3ECH */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3F0H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3F4H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3F8H */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 3FCH */
};
uint8 nulldev(t_bool flag, uint8 data)
{
sim_printf("xtbus: I/O Port %03X is not assigned io=%d data=%02X\n",
port, flag, data);
if (flag == 0) /* if we got here, no valid I/O device */
return 0xFF;
}
uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port)
{
if (dev_table[port].routine != &nulldev) { /* port already assigned */
sim_printf("xtbus: I/O Port %03X is already assigned\n", port);
} else {
sim_printf("Port %03X is assigned\n", port);
dev_table[port].routine = routine;
}
//dump_dev_table();
return port;
}
void dump_dev_table(void)
{
int i;
for (i=0; i<1024; i++) {
if (dev_table[i].routine != &nulldev) { /* assigned port */
sim_printf("Port %03X is assigned\n", i);
}
}
}
/* get a byte from bus */
uint8 xtbus_get_mbyte(uint32 addr)
{
return 0xFF;
}
/* put a byte to bus */
void xtbus_put_mbyte(uint32 addr, uint8 val)
{
;
}
/* end of pcbus.c */

View file

@ -0,0 +1,177 @@
/* pceprom.c: Intel EPROM simulator for 8-bit SBCs
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:
These functions support a simulated ROM devices on aPC XT SBC.
This allows the attachment of the device to a binary file containing the EPROM
code image. Unit will support a single 2764, 27128, 27256, or 27512 type EPROM.
*/
#include "system_defs.h"
/* function prototypes */
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr);
t_stat EPROM_reset (DEVICE *dptr, uint32 base, uint32 size);
uint8 EPROM_get_mbyte(uint32 addr);
/* external function prototypes */
/* SIMH EPROM Standard I/O Data Structures */
UNIT EPROM_unit = {
UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0), 0
};
DEBTAB EPROM_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE EPROM_dev = {
"EPROM", //name
&EPROM_unit, //units
NULL, //registers
NULL, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
// &EPROM_reset, //reset
NULL, //reset
NULL, //boot
&EPROM_attach, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
EPROM_debug, //debflags
NULL, //msize
NULL //lname
};
/* global variables */
/* EPROM functions */
/* EPROM attach */
t_stat EPROM_attach (UNIT *uptr, CONST char *cptr)
{
uint16 j;
int c;
FILE *fp;
t_stat r;
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: cptr=%s\n", cptr);
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Error\n");
return r;
}
sim_debug (DEBUG_read, &EPROM_dev, "\tAllocate buffer\n");
if (EPROM_unit.filebuf == NULL) { /* no buffer allocated */
EPROM_unit.filebuf = malloc(EPROM_unit.capac); /* allocate EPROM buffer */
if (EPROM_unit.filebuf == NULL) {
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Malloc error\n");
return SCPE_MEM;
}
}
sim_debug (DEBUG_read, &EPROM_dev, "\tOpen file %s\n", EPROM_unit.filename);
fp = fopen(EPROM_unit.filename, "rb"); /* open EPROM file */
if (fp == NULL) {
sim_printf("EPROM: Unable to open ROM file %s\n", EPROM_unit.filename);
sim_printf("\tNo ROM image loaded!!!\n");
return SCPE_OK;
}
sim_debug (DEBUG_read, &EPROM_dev, "\tRead file\n");
j = 0; /* load EPROM file */
c = fgetc(fp);
while (c != EOF) {
*((uint8 *)EPROM_unit.filebuf + j++) = c & 0xFF;
c = fgetc(fp);
if (j > EPROM_unit.capac) {
sim_printf("\tImage is too large - Load truncated!!!\n");
break;
}
}
sim_printf("\tImage size=%05X unit_capac=%05X\n", j, EPROM_unit.capac);
sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n");
fclose(fp);
sim_printf("EPROM: %d bytes of ROM image %s loaded\n", j, EPROM_unit.filename);
sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n");
return SCPE_OK;
}
/* EPROM reset */
t_stat EPROM_reset (DEVICE *dptr, uint32 base, uint32 size)
{
sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=%05X size=%05X\n", base, size);
if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */
EPROM_unit.capac = size; /* set EPROM size */
EPROM_unit.u3 = base; /* set EPROM base addr */
sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n");
sim_printf(" EPROM: Available [%05X-%05XH]\n",
base, size);
return SCPE_OK;
} else
sim_printf("EPROM: No file attached\n");
sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n");
return SCPE_OK;
}
/* get a byte from memory */
uint8 EPROM_get_mbyte(uint32 addr)
{
uint8 val;
uint32 romoff;
romoff = addr - EPROM_unit.u3;
sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%05X romoff=%05X\n", addr, romoff);
if (romoff < EPROM_unit.capac) {
val = *((uint8 *)EPROM_unit.filebuf + romoff);
sim_debug (DEBUG_read, &EPROM_dev, " val=%02X\n", val);
return (val & 0xFF);
}
sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n");
return 0xFF;
}
/* end of pceprom.c */

View file

@ -0,0 +1,152 @@
/* pcram8.c: Intel RAM simulator for 8-bit SBCs
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:
These functions support a simulated RAM devices on a PC XT SBC.
*/
#include "system_defs.h"
/* function prototypes */
t_stat RAM_svc (UNIT *uptr);
t_stat RAM_reset (DEVICE *dptr, uint32 base, uint32 size);
uint8 RAM_get_mbyte(uint32 addr);
void RAM_put_mbyte(uint32 addr, uint8 val);
/* external function prototypes */
extern UNIT i8255_unit[];
/* SIMH RAM Standard I/O Data Structures */
UNIT RAM_unit = { UDATA (NULL, UNIT_BINK, 0), KBD_POLL_WAIT };
DEBTAB RAM_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE RAM_dev = {
"RAM", //name
&RAM_unit, //units
NULL, //registers
NULL, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
// &RAM_reset, //reset
NULL, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
RAM_debug, //debflags
NULL, //msize
NULL //lname
};
/* global variables */
/* RAM functions */
/* RAM reset */
t_stat RAM_reset (DEVICE *dptr, uint32 base, uint32 size)
{
sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%05X size=%05X\n", base, size-1);
if (RAM_unit.capac == 0) { /* if undefined */
RAM_unit.capac = size;
RAM_unit.u3 = base;
}
if (RAM_unit.filebuf == NULL) { /* no buffer allocated */
RAM_unit.filebuf = malloc(RAM_unit.capac);
if (RAM_unit.filebuf == NULL) {
sim_debug (DEBUG_flow, &RAM_dev, "RAM_set_size: Malloc error\n");
return SCPE_MEM;
}
}
sim_printf(" RAM: Available [%05X-%05XH]\n",
RAM_unit.u3,
RAM_unit.u3 + RAM_unit.capac - 1);
sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n");
return SCPE_OK;
}
/* get a byte from memory */
uint8 RAM_get_mbyte(uint32 addr)
{
uint8 val;
if (i8255_unit[0].u5 & 0x02) { /* enable RAM */
sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr);
if ((addr >= RAM_unit.u3) && ((uint32) addr < (RAM_unit.u3 + RAM_unit.capac))) {
val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3));
sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val);
return (val & 0xFF);
}
sim_debug (DEBUG_read, &RAM_dev, " Out of range\n");
return 0xFF;
}
sim_debug (DEBUG_read, &RAM_dev, " RAM disabled\n");
return 0xFF;
}
/* put a byte to memory */
void RAM_put_mbyte(uint32 addr, uint8 val)
{
if (i8255_unit[0].u5 & 0x02) { /* enable RAM */
sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val);
if ((addr >= RAM_unit.u3) && ((uint32)addr < RAM_unit.u3 + RAM_unit.capac)) {
*((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 pcram8.c */

203
IBMPC-Systems/ibmpc/ibmpc.c Normal file
View file

@ -0,0 +1,203 @@
/* ibmpcxt.c: IBM PC Processor simulator
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:
This software was written by Bill Beech, Jul 2016, to allow emulation of IBM PC
Computer Systems.
*/
#include "system_defs.h"
int32 nmiflg = 0; //mask NMI off
uint8 dmapagreg0, dmapagreg1, dmapagreg2, dmapagreg3;
extern uint16 port; //port called in dev_table[port]
/* function prototypes */
uint8 get_mbyte(uint32 addr);
uint16 get_mword(uint32 addr);
void put_mbyte(uint32 addr, uint8 val);
void put_mword(uint32 addr, uint16 val);
t_stat SBC_reset (DEVICE *dptr, uint16 base);
uint8 enbnmi(t_bool io, uint8 data);
uint8 dmapag(t_bool io, uint8 data);
uint8 dmapag0(t_bool io, uint8 data);
uint8 dmapag1(t_bool io, uint8 data);
uint8 dmapag2(t_bool io, uint8 data);
uint8 dmapag3(t_bool io, uint8 data);
/* external function prototypes */
extern t_stat i8088_reset (DEVICE *dptr); /* reset the 8088 emulator */
extern uint8 xtbus_get_mbyte(uint32 addr);
extern void xtbus_put_mbyte(uint32 addr, uint8 val);
extern uint8 EPROM_get_mbyte(uint32 addr);
extern uint8 RAM_get_mbyte(uint32 addr);
extern void RAM_put_mbyte(uint32 addr, uint8 val);
extern UNIT i8255_unit[];
extern UNIT EPROM_unit;
extern UNIT RAM_unit;
extern t_stat i8237_reset (DEVICE *dptr, uint16 base);
extern t_stat i8253_reset (DEVICE *dptr, uint16 base);
extern t_stat i8255_reset (DEVICE *dptr, uint16 base);
extern t_stat i8259_reset (DEVICE *dptr, uint16 base);
extern t_stat EPROM_reset (DEVICE *dptr, uint32 base, uint32 size);
extern t_stat RAM_reset (DEVICE *dptr, uint32 base, uint32 size);
extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16);
/* SBC reset routine */
t_stat SBC_reset (DEVICE *dptr, uint16 base)
{
sim_printf("Initializing IBM PC:\n");
i8088_reset (NULL);
i8237_reset (NULL, I8237_BASE_0);
i8253_reset (NULL, I8253_BASE_0);
i8255_reset (NULL, I8255_BASE_0);
i8259_reset (NULL, I8259_BASE_0);
EPROM_reset (NULL, ROM_BASE, ROM_SIZE);
RAM_reset (NULL, RAM_BASE, RAM_SIZE);
reg_dev(enbnmi, NMI_BASE);
reg_dev(dmapag0, DMAPAG_BASE_0);
reg_dev(dmapag1, DMAPAG_BASE_1);
reg_dev(dmapag2, DMAPAG_BASE_2);
reg_dev(dmapag3, DMAPAG_BASE_3);
return SCPE_OK;
}
uint8 dmapag0(t_bool io, uint8 data)
{
if (io == 0) { /* read data port */
;
} else { /* write data port */
dmapagreg0 = data;
//sim_printf("dmapag0: dmapagreg0=%04X\n", data);
}
}
uint8 dmapag1(t_bool io, uint8 data)
{
if (io == 0) { /* read data port */
;
} else { /* write data port */
dmapagreg1 = data;
//sim_printf("dmapag1: dmapagreg1=%04X\n", data);
}
}
uint8 dmapag2(t_bool io, uint8 data)
{
if (io == 0) { /* read data port */
;
} else { /* write data port */
dmapagreg2 = data;
//sim_printf("dmapag2: dmapagreg2=%04X\n", data);
}
}
uint8 dmapag3(t_bool io, uint8 data)
{
//sim_printf("dmapag3: entered\n");
if (io == 0) { /* read data port */
;
} else { /* write data port */
dmapagreg3 = data;
//sim_printf("dmapag3: dmapagreg3=%04X\n", data);
}
}
uint8 enbnmi(t_bool io, uint8 data)
{
if (io == 0) { /* read data port */
;
} else { /* write data port */
if (data & 0x80) {
nmiflg = 1;
//sim_printf("enbnmi: NMI enabled\n");
} else {
nmiflg = 0;
//sim_printf("enbnmi: NMI disabled\n");
}
}
}
/* get a byte from memory - handle RAM, ROM, I/O, and pcbus memory */
uint8 get_mbyte(uint32 addr)
{
/* if local EPROM handle it */
if ((addr >= EPROM_unit.u3) && ((uint32)addr < (EPROM_unit.u3 + EPROM_unit.capac))) {
sim_printf("Write to R/O memory address %05X - ignored\n", addr);
return EPROM_get_mbyte(addr);
}
/* if local RAM handle it */
if ((addr >= RAM_unit.u3) && ((uint32)addr < (RAM_unit.u3 + RAM_unit.capac))) {
return RAM_get_mbyte(addr);
}
/* otherwise, try the pcbus */
return xtbus_get_mbyte(addr);
}
/* get a word from memory - handle RAM, ROM, I/O, and pcbus memory */
uint16 get_mword(uint32 addr)
{
uint16 val;
val = get_mbyte(addr);
val |= (get_mbyte(addr+1) << 8);
return val;
}
/* put a byte to memory - handle RAM, ROM, I/O, and pcbus memory */
void put_mbyte(uint32 addr, uint8 val)
{
/* if local EPROM handle it */
if ((addr >= EPROM_unit.u3) && ((uint32)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) {
sim_printf("Write to R/O memory address %04X - ignored\n", addr);
return;
} /* if local RAM handle it */
if ((i8255_unit[0].u5 & 0x02) && (addr >= RAM_unit.u3) && ((uint32)addr <= (RAM_unit.u3 + RAM_unit.capac))) {
RAM_put_mbyte(addr, val);
return;
} /* otherwise, try the pcbus */
xtbus_put_mbyte(addr, val);
}
/* put a word to memory - handle RAM, ROM, I/O, and pcbus memory */
void put_mword(uint32 addr, uint16 val)
{
put_mbyte(addr, val & 0xff);
put_mbyte(addr+1, val >> 8);
}
/* end of ibmpc.c */

View file

@ -0,0 +1,97 @@
/* ibmpcxt_sys.c: IBM 5160 simulator
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.
11 Jul 16 - Original file.
*/
#include "system_defs.h"
extern DEVICE i8088_dev;
extern REG i8088_reg[];
extern DEVICE i8237_dev;
extern DEVICE i8253_dev;
extern DEVICE i8255_dev;
extern DEVICE i8259_dev;
extern DEVICE EPROM_dev;
extern DEVICE RAM_dev;
extern DEVICE xtbus_dev;
/* bit patterns to manipulate 8-bit ports */
#define i82XX_bit_0 0x01 //bit 0 of a port
#define i82XX_bit_1 0x02 //bit 1 of a port
#define i82XX_bit_2 0x04 //bit 2 of a port
#define i82XX_bit_3 0x08 //bit 3 of a port
#define i82XX_bit_4 0x10 //bit 4 of a port
#define i82XX_bit_5 0x20 //bit 5 of a port
#define i82XX_bit_6 0x40 //bit 6 of a port
#define i82XX_bit_7 0x80 //bit 7 of a port
#define i82XX_nbit_0 ~i8255_bit_0 //bit 0 of a port
#define i82XX_nbit_1 ~i8255_bit_1 //bit 1 of a port
#define i82XX_nbit_2 ~i8255_bit_3 //bit 2 of a port
#define i82XX_nbit_3 ~i8255_bit_3 //bit 3 of a port
#define i82XX_nbit_4 ~i8255_bit_4 //bit 4 of a port
#define i82XX_nbit_5 ~i8255_bit_5 //bit 5 of a port
#define i82XX_nbit_6 ~i8255_bit_6 //bit 6 of a port
#define i82XX_nbit_7 ~i8255_bit_7 //bit 7 of a port
/* SCP data structures
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax number of words needed for examine
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
*/
char sim_name[] = "IBM PC";
REG *sim_PC = &i8088_reg[0];
int32 sim_emax = 4;
DEVICE *sim_devices[] = {
&i8088_dev,
&EPROM_dev,
&RAM_dev,
&i8237_dev,
&i8253_dev,
&i8255_dev,
&i8259_dev,
&xtbus_dev,
NULL
};
const char *sim_stop_messages[] = {
"Unknown error",
"Unknown I/O Instruction",
"HALT instruction",
"Breakpoint",
"Invalid Opcode",
"Invalid Memory",
"XACK Error"
};

View file

@ -0,0 +1,111 @@
/* system_defs.h: IBM PC simulator definitions
Copyright (c) 2010, William A. Beech
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
William A. Beech BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of William A. Beech shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from William A. Beech.
11 Jul 16 - Original file.
*/
#include <stdio.h>
#include <ctype.h>
#include "sim_defs.h" /* simulator defns */
/* set the base I/O address and device count for the 8237 */
#define I8237_BASE_0 0x000
#define I8237_NUM 1
/* set the base I/O address and device count for the 8253 */
#define I8253_BASE_0 0x040
#define I8253_BASE_1 0x100
#define I8253_NUM 2
/* set the base I/O address and device count for the 8255 */
#define I8255_BASE_0 0x060
#define I8255_NUM 1
/* set the base I/O address and device count for the 8259 */
#define I8259_BASE_0 0x020
#define I8259_NUM 1
/* set the base I/O address for the NMI mask */
#define NMI_BASE 0x0A0
/* set the base I/O address and device count for the DMA page registers */
#define DMAPAG_BASE_0 0x080
#define DMAPAG_BASE_1 0x081
#define DMAPAG_BASE_2 0x082
#define DMAPAG_BASE_3 0x083
#define DMAPAG_NUM 4
/* set the base and size for the EPROM on the IBM PC */
#define ROM_BASE 0xFE000
#define ROM_SIZE 0x02000
/* set the base and size for the RAM on the IBM PC */
#define RAM_BASE 0x00000
#define RAM_SIZE 0x40000
/* set INTR for CPU on the 8088 */
#define INT_R INT_1
/* xtbus interrupt definitions */
#define INT_0 0x01
#define INT_1 0x02
#define INT_2 0x04
#define INT_3 0x08
#define INT_4 0x10
#define INT_5 0x20
#define INT_6 0x40
#define INT_7 0x80
/* Memory */
#define ADDRMASK16 0xFFFF
#define ADDRMASK20 0xFFFFF
#define MAXMEMSIZE20 0xFFFFF /* 8080 max memory size */
#define MEMSIZE (i8088_unit.capac) /* 8088 actual memory size */
#define ADDRMASK (MAXMEMSIZE - 1) /* 8088 address mask */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* debug definitions */
#define DEBUG_flow 0x0001
#define DEBUG_read 0x0002
#define DEBUG_write 0x0004
#define DEBUG_level1 0x0008
#define DEBUG_level2 0x0010
#define DEBUG_reg 0x0020
#define DEBUG_asm 0x0040
#define DEBUG_all 0xFFFF
/* Simulator stop codes */
#define STOP_RSRV 1 /* must be 1 */
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint */
#define STOP_OPCODE 4 /* Invalid Opcode */
#define STOP_IO 5 /* I/O error */
#define STOP_MEM 6 /* Memory error */