Changes to replace the SWTP V1 code with the V2 code

This commit is contained in:
Bill Beech 2012-07-05 14:14:49 -07:00
parent eb60957366
commit 567a304c37
27 changed files with 4757 additions and 3666 deletions

View file

@ -18,3 +18,4 @@ if not exist BIN mkdir BIN
gcc -v 1>NUL 2>NUL
if ERRORLEVEL 1 echo "MinGW Environment Unavailable"
mingw32-make WIN32=1 -f makefile %1 %2 %3 %4
pause

View file

@ -588,10 +588,15 @@ SDS = ${SDSD}/sds_cpu.c ${SDSD}/sds_drm.c ${SDSD}/sds_dsk.c ${SDSD}/sds_io.c \
${SDSD}/sds_stddev.c ${SDSD}/sds_sys.c
SDS_OPT = -I ${SDSD}
SWTPD = swtp
SWTP = ${SWTPD}/swtp_cpu.c ${SWTPD}/swtp_dsk.c ${SWTPD}/swtp_sio.c \
${SWTPD}/swtp_sys.c
SWTP_OPT = -I ${SWTPD}
SWTP6800D = swtp6800/swtp6800
SWTP6800C = swtp6800/common
SWTP6800MP-A = ${SWTP6800C}/mp-a.c ${SWTP6800C}/m6800.c ${SWTP6800C}/m6810.c \
${SWTP6800C}/bootrom.c ${SWTP6800C}/dc-4.c ${SWTP6800C}/mp-s.c ${SWTP6800D}/mp-a_sys.c \
${SWTP6800C}/mp-b2.c ${SWTP6800C}/mp-8m.c
SWTP6800MP-A2 = ${SWTP6800C}/mp-a2.c ${SWTP6800C}/m6800.c ${SWTP6800C}/m6810.c \
${SWTP6800C}/bootrom.c ${SWTP6800C}/dc-4.c ${SWTP6800C}/mp-s.c ${SWTP6800D}/mp-a2_sys.c \
${SWTP6800C}/mp-b2.c ${SWTP6800C}/mp-8m.c ${SWTP6800C}/i2716.c
SWTP6800_OPT = -I ${SWTP6800D}
#
@ -600,7 +605,7 @@ SWTP_OPT = -I ${SWTPD}
ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \
vax vax780 nova eclipse hp2100 i1401 i1620 s3 \
altair altairz80 gri i7094 ibm1130 id16 \
id32 sds lgp h316 swtp
id32 sds lgp h316 swtp6800mp-a swtp6800mp-a2
all : ${ALL}
@ -789,8 +794,15 @@ ${BIN}sds${EXE} : ${SDS} ${SIM}
${MKDIRBIN}
${CC} ${SDS} ${SIM} ${SDS_OPT} -o $@ ${LDFLAGS}
swtp : ${BIN}swtp${EXE}
swtp6800mp-a : ${BIN}swtp6800mp-a${EXE}
${BIN}swtp${EXE} : ${SWTP} ${SIM}
${BIN}swtp6800mp-a${EXE} : ${SWTP6800MP-A} ${SIM}
${MKDIRBIN}
${CC} ${SWTP} ${SIM} ${SWTP_OPT} -o $@ ${LDFLAGS}
${CC} ${SWTP6800MP-A} ${SIM} ${SWTP6800_OPT} -o $@ ${LDFLAGS}
swtp6800mp-a2 : ${BIN}swtp6800mp-a2${EXE}
${BIN}swtp6800mp-a2${EXE} : ${SWTP6800MP-A2} ${SIM}
${MKDIRBIN}
${CC} ${SWTP6800MP-A2} ${SIM} ${SWTP6800_OPT} -o $@ ${LDFLAGS}

Binary file not shown.

Binary file not shown.

BIN
swtp/swtp

Binary file not shown.

View file

@ -1,100 +0,0 @@
SWTP 6800 Emulator
=====================
1. Background.
The Southwest Technical Products (SWTP) SWTP 6800 was announced 1n the 1976 SWTP Catalog, which boasted you could buy and build this powerful computer kit for only $395. The kit consisted at that time of only the parts to build a case, power supply, mother board, CPU card, serial card with RS-232 or 20 ma loop interface, and memory card with 2048 *bytes* of static memory.
2. Hardware
We are simulating a fairly "loaded" SWTP 6800 from about 1978, with the following configuration:
device simulates
name(s)
CPU SWTP MP-A with Motorola 6080 CPU board, 62KB of RAM, 2K of EPROM with start boot ROM.
SIO SWTP MP-S Dual Serial Interface Board. Port 1 is assumed to be connected to a serial "glass TTY" that is your terminal running the Simulator.
PTR Second serial port of SIO is assumed to be connected to the paper tap reader/punch.
PTP Second serial port of SIO is assumed to be connected to the paper tap reader/punch.
DSK SWTP DC-4 Floppy Disk controller with up to four drives.
2.1 The CPU Card (MP-A)
We allow you to select memory sizes, but be aware that some sample software requires the full 32K (i.e. FLEX). We emulate the SWTP SWTBUG boot rom.
SET CPU ITRAP Causes the simulator to halt if an invalid 8080 Opcode is detected.
SET CPU NOITRAP Does not stop on an invalid Opcode. This is how the real 6800 operates.
SET CPU MTRAP Causes the simulator to halt if an invalid address is accessed.
SET CPU NOMTRAP Does not stop on invalid address access. This is how a real 6800 operates.
SET CPU 4K
SET CPU 8K
SET CPU 12K
SET CPU 16K
......
SET CPU 32K All these set various CPU memory configurations.
The 2K EPROM at the high end of memory is always present and will always boot.
SET CPU MA000 Enable 8 K bytes of memory at $A000-$BFFF. Otherwise, only 128 bytes re available at $A000.
SET CPU NOMA000 Enable only 128 bytes of memory at $A000.
The SWTBUG EPROM maps to both addresses $E000-E3FF and $FC00-FFFF.
The real 6800, on receiving a HLT (Halt) instruction, freezes the processor and only an interrupt or CPU hardware reset will restore it. The simulator is a lot nicer, it will halt but send you back to the simulator command line.
CPU Registers include the following:
name size comments
PC 16 Program Counter
A 8 Accumulator A
B 8 Accumulator B
IX 16 Index Register
C 1 Carry flag
Z 1 Zero Flag
H 1 Half-Carry flag
I 1 Interrupt flag
N 1 Negative flag
V 1 Overflao Flag
2.2 The Serial I/O Card (MP-S)
This simple programmed I/O device provides 2 serial ports to the outside world, which could be hardware jumpered to support RS-232 plugs or a TTY current loop interface. The standard I/O addresses assigned by SWTP was $8004-8005 for the first port, and $8006-8007 for the second. We follow this standard in the Simulator.
The simulator directs I/O to/from the first port to the screen. The second port reads from an attachable "tape reader" file on input, and writes to an attachable "punch file" on output. These files are considered a simple stream of 8-bit bytes.
2.3 The Floppy Disk controller (DC4)
The SWTP DC4 is a simple programmed I/O interface to the SWTP MF-68 5-inch dual floppy drive, which was basically a pair of Shugart SA-400s with a power supply and buffer board builtin. The controller supports neither interrupts nor DMA, so floppy access required the sustained attention of the CPU. The standard I/O addresses were $8018-801B, and we follow the standard. Details on controlling this hardware are in the swtp_dsk.c source file.
3. Sample Software
Running an SWTP 6800 in 1978 you would be running the FLEX Version 2.0 Operating System from Technical Systems Consultants, Inc.
3.1 CP/M Version 2.2
This version is a port of the standard FLEX Version 2.0 to the SWTP 6800.
To boot FLEX:
sim> set cpu hex
sim> set cpu itrap
sim> set cpu mtrap
sim> att dsk 6800boot.dsk
sim> att dsk1 6800work.dsk
sim> set cpu MA000
sim> set dsk1 rw
sim> go
$D ; Capital D causes SWTBUG to boot Flex
FLEX 2.0
DATE (MM,DD,YY)? 03,09,99 ; Must enter a date from last century!
+++ ;Flex prompt!

View file

@ -1,9 +0,0 @@
reset
set cpu hex
set cpu itrap
set cpu mtrap
att dsk 6800boot.dsk
att dsk1 6800work.dsk
set cpu MA000
set dsk1 rw
g

File diff suppressed because it is too large Load diff

View file

@ -1,506 +0,0 @@
/* swtp_dc4_dsk.c: SWTP DC-4 DISK Simulator
Copyright (c) 2005, 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
ROBERT M SUPNIK 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.
Based on work by Charles E Owen (c) 1997 and Peter Schorn (c) 2002-2005
The DC-4 is a 5-inch floppy controller which can control up
to 4 daisy-chained 5-inch floppy drives. The controller is based on
the Western Digital 1797 Floppy Disk Controller (FDC) chip. This
file only emulates the minimum DC-4 functionality to interface with
the virtual disk file.
The floppy controller is interfaced to the CPU by use of 5 memory
addreses. These are device numbers 5 and 6 (0x8014-0x801B).
Address Mode Function
------- ---- --------
0x8014 Read Returns FDC interrupt status
0x8014 Write Selects the drive/head/motor control
0x8018 Read Returns status of FDC
0x8018 Write FDC command register
0x8019 Read Returns FDC track register
0x8019 Write Set FDC track register
0x801A Read Returns FDC sector register
0x801A Write Set FDC sector register
0x801B Read Read data
0x801B Write Write data
Drive Select Read (0x8014):
+---+---+---+---+---+---+---+---+
| I | D | X | X | X | X | X | X |
+---+---+---+---+---+---+---+---+
I = Set indicates an interrupt request from the FDC pending.
D = DRQ pending - same as bit 1 of FDC status register.
Drive Select Write (0x8014):
+---+---+---+---+---+---+---+---+
| M | S | X | X | X | X | Device|
+---+---+---+---+---+---+---+---+
M = If this bit is 1, the one-shot is triggered/retriggered to
start/keep the motors on.
S = Side select. If set, side one is selected otherwise side zero
is selected.
X = not used
Device = value 0 thru 3, selects drive 0-3 to be controlled.
Drive Status Read (0x8018):
+---+---+---+---+---+---+---+---+
| R | P | H | S | C | L | D | B |
+---+---+---+---+---+---+---+---+
B - When 1, the controller is busy.
D - When 1, index mark detected (type I) or data request - read data
ready/write data empty (type II or III).
H - When 1, track 0 (type I) or lost data (type II or III).
C - When 1, crc error detected.
S - When 1, seek (type I) or RNF (type II or III) error.
H - When 1, head is currently loaded (type I) or record type/
write fault (type II or III).
P - When 1, indicates that diskette is write-protected.
R - When 1, drive is not ready.
Drive Control Write (0x8018) for type I commands:
+---+---+---+---+---+---+---+---+
| 0 | S2| S1| S0| H | V | R1| R0|
+---+---+---+---+---+---+---+---+
R0/R1 - Selects the step rate.
V - When 1, verify on destination track.
H - When 1, loads head to drive surface.
S0/S1/S2 = 000 - home.
001 - seek track in data register.
010 - step without updating track register.
011 - step and update track register.
100 - step in without updating track register.
101 - step in and update track register.
110 - step out without updating track register.
111 - step out and update track register.
Drive Control Write (0x8018) for type II commands:
+---+---+---+---+---+---+---+---+
| 1 | 0 | T | M | S | E | B | A |
+---+---+---+---+---+---+---+---+
A - Zero for read, 1 on write deleted data mark else data mark.
B - When 1, shifts sector length field definitions one place.
E - When, delay operation 15 ms, 0 no delay.
S - When 1, select side 1, 0 select side 0.
M - When 1, multiple records, 0 for single record.
T - When 1, write command, 0 for read.
Drive Control Write (0x8018) for type III commands:
+---+---+---+---+---+---+---+---+
| 1 | 1 | T0| T1| 0 | E | 0 | 0 |
+---+---+---+---+---+---+---+---+
E - When, delay operation 15 ms, 0 no delay.
T0/T1 - 00 - read address command.
10 - read track command.
11 - write track command.
Tracks are numbered from 0 up to one minus the last track in the 1797!
Track Register Read (0x8019):
+---+---+---+---+---+---+---+---+
| Track Number |
+---+---+---+---+---+---+---+---+
Reads the current 8-bit value from the track position.
Track Register Write (0x8019):
+---+---+---+---+---+---+---+---+
| Track Number |
+---+---+---+---+---+---+---+---+
Writes the 8-bit value to the track register.
Sectors are numbers from 1 up to the last sector in the 1797!
Sector Register Read (0x801A):
+---+---+---+---+---+---+---+---+
| Sector Number |
+---+---+---+---+---+---+---+---+
Reads the current 8-bit value from the sector position.
Sector Register Write (0x801A):
+---+---+---+---+---+---+---+---+
| Sector Number |
+---+---+---+---+---+---+---+---+
Writes the 8-bit value to the sector register.
Data Register Read (0x801B):
+---+---+---+---+---+---+---+---+
| Data |
+---+---+---+---+---+---+---+---+
Reads the current 8-bit value from the data register.
Data Register Write (0x801B):
+---+---+---+---+---+---+---+---+
| Data |
+---+---+---+---+---+---+---+---+
Writes the 8-bit value to the data register.
A FLEX disk is defined as follows:
Track Sector Use
0 1 Boot sector
0 2 Boot sector (cont)
0 3 Unused
0 4 System Identity Record (explained below)
0 5 Unused
0 6-last Directory - 10 entries/sector (explained below)
1 1 First available data sector
last-1 last Last available data sector
System Identity Record
Byte Use
0x10 Volume ID (8 bytes)
0x18 ???
0x19 ???
0x1A ???
0x1B Volume number (2 bytes)
0x1D First free sector (2 bytes)
0x1F Last track minus one (byte)
0x20 Last sector (byte)
0x21 Total sectors on disk (2 bytes)
0x23 Month (byte
0x24 Day (byte)
0x25 Year (byte)
0x26 Last track minus one (byte)
0x27 Last sector (byte)
*/
#include <stdio.h>
#include "swtp_defs.h"
#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */
#define UNIT_ENABLE (1 << UNIT_V_ENABLE)
/* emulate a SS FLEX disk with 72 sectors and 80 tracks */
#define NUM_DISK 4 /* standard 1797 maximum */
#define SECT_SIZE 256 /* standard FLEX sector */
#define NUM_SECT 72 /* sectors/track */
#define TRAK_SIZE (SECT_SIZE * NUM_SECT)
#define HEADS 1 /* handle as SS with twice the sectors */
#define NUM_CYL 80 /* maximum tracks */
#define DSK_SIZE (NUM_SECT * HEADS * NUM_CYL * SECT_SIZE)
/* 1797 status bits */
#define BUSY 0x01
#define DRQ 0x02
#define WRPROT 0x40
#define NOTRDY 0x80
/* debug prints */
#define DEBUG 0
/* prototypes */
t_stat dsk_svc (UNIT *uptr);
t_stat dsk_reset (DEVICE *dptr);
int32 fdcdrv(int32 io, int32 data);
int32 fdccmd(int32 io, int32 data);
int32 fdctrk(int32 io, int32 data);
int32 fdcsec(int32 io, int32 data);
int32 fdcdata(int32 io, int32 data);
/* Global data on status */
int32 cur_dsk = NUM_DISK; /* Currently selected drive */
int32 cur_trk[NUM_DISK] = {0, 0, 0, 0};
int32 cur_sec[NUM_DISK] = {0, 0, 0, 0};
int32 cur_byt[NUM_DISK] = {0, 0, 0, 0};
int32 cur_flg[NUM_DISK] = {NOTRDY, NOTRDY, NOTRDY, NOTRDY};
/* Variables */
uint8 dskbuf[SECT_SIZE]; /* Data Buffer */
UNIT *dptr = NULL; /* fileref to write dirty buffer to */
int32 fdcbyte;
int32 intrq = 0; /* interrupt request flag */
/* DC-4 Simh Device Data Structures */
UNIT dsk_unit[] = {
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) } };
REG dsk_reg[] = {
{ HRDATA (DISK, cur_dsk, 4) },
{ NULL } };
MTAB dsk_mod[] = {
{ UNIT_ENABLE, UNIT_ENABLE, "RW", "RW", NULL },
{ UNIT_ENABLE, 0, "RO", "RO", NULL },
{ 0 } };
DEVICE dsk_dev = {
"DSK", dsk_unit, dsk_reg, dsk_mod,
NUM_DISK, 16, 16, 1, 16, 8,
NULL, NULL, &dsk_reset,
NULL, NULL, NULL };
/* service routines to handle simlulator functions */
/* service routine - actually gets char & places in buffer */
t_stat dsk_svc (UNIT *uptr)
{
return SCPE_OK;
}
/* Reset routine */
t_stat dsk_reset (DEVICE *dptr)
{
cur_dsk = 0;
return SCPE_OK;
}
/* I/O instruction handlers, called from the CPU module when an
memory read or write to the proper addresses 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.
*/
/* DC-4 drive select register routine - this register is not part of the 1797
*/
int32 fdcdrv(int32 io, int32 data)
{
/* **** probably need to grab the parameters from the SIR and set the limits */
if (io) { /* write to DC-4 drive register */
cur_dsk = data & 0x03; /* only 2 drive select bits */
#if DEBUG > 0
printf("Drive set to %d\n\r", cur_dsk);
#endif
if ((dsk_unit[cur_dsk].flags & UNIT_ENABLE) == 0)
cur_flg[cur_dsk] |= WRPROT; /* set WPROT */
return 0;
} else { /* read from DC-4 drive register */
#if DEBUG > 0
printf("Drive read as %02X\n\r", intrq);
#endif
return intrq;
}
}
/* WD 1797 FDC command register routine */
int32 fdccmd(int32 io, int32 data)
{
static int32 val = 0, val1 = NOTRDY, i;
static long pos;
UNIT *uptr;
if ((dsk_unit[cur_dsk].flags & UNIT_ATT) == 0) { /* not attached */
cur_flg[cur_dsk] |= NOTRDY; /* set not ready flag */
printf("Drive %d is not attached\n\r", cur_dsk);
return 0;
} else {
cur_flg[cur_dsk] &= ~NOTRDY; /* clear not ready flag */
}
uptr = dsk_dev.units + cur_dsk; /* get virtual drive address */
if (io) { /* write command to fdc */
switch(data) {
case 0x8C: /* read command */
case 0x9C:
#if DEBUG > 0
printf("Read of disk %d, track %d, sector %d\n\r",
cur_dsk, cur_trk[cur_dsk], cur_sec[cur_dsk]);
#endif
pos = TRAK_SIZE * cur_trk[cur_dsk]; /* calculate file offset */
pos += SECT_SIZE * (cur_sec[cur_dsk] - 1);
#if DEBUG > 0
printf("Read pos = %ld ($%04X)\n\r", pos, pos);
#endif
sim_fseek(uptr -> fileref, pos, 0); /* seek to offset */
sim_fread(dskbuf, 256, 1, uptr -> fileref); /* read in buffer */
cur_flg[cur_dsk] |= BUSY | DRQ; /* set DRQ & BUSY */
i = cur_byt[cur_dsk] = 0; /* clear counter */
break;
case 0xAC: /* write command */
#if DEBUG > 0
printf("Write of disk %d, track %d, sector %d\n\r",
cur_dsk, cur_trk[cur_dsk], cur_sec[cur_dsk]);
#endif
if (cur_flg[cur_dsk] & WRPROT) {
printf("Drive %d is write-protected\n\r", cur_dsk);
} else {
pos = TRAK_SIZE * cur_trk[cur_dsk]; /* calculate file offset */
pos += SECT_SIZE * (cur_sec[cur_dsk] - 1);
#if DEBUG > 1
printf("Write pos = %ld ($%04X)\n\r", pos, pos);
#endif
sim_fseek(uptr -> fileref, pos, 0); /* seek to offset */
dptr = uptr; /* save pointer for actual write */
cur_flg[cur_dsk] |= BUSY | DRQ;/* set DRQ & BUSY */
i = cur_byt[cur_dsk] = 0; /* clear counter */
}
break;
case 0x18: /* seek command */
case 0x1B:
cur_trk[cur_dsk] = fdcbyte; /* set track */
cur_flg[cur_dsk] &= ~(BUSY | DRQ); /* clear flags */
#if DEBUG > 0
printf("Seek of disk %d, track %d\n\r", cur_dsk, fdcbyte);
#endif
break;
case 0x0B: /* restore command */
cur_trk[cur_dsk] = 0; /* home the drive */
cur_flg[cur_dsk] &= ~(BUSY | DRQ); /* clear flags */
#if DEBUG > 0
printf("Drive %d homed\n\r", cur_dsk);
#endif
break;
default:
printf("Unknown FDC command %02XH\n\r", data);
}
} else { /* read status from fdc */
val = cur_flg[cur_dsk]; /* set return value */
if (val1 == 0 && val == 0x03) /* delay BUSY going high */
val = 0x02; /* set DRQ first */
if (val != val1) { /* now allow BUSY after on read */
val1 = val;
#if DEBUG > 0
printf("Drive %d status=%02X\n\r", cur_dsk, cur_flg[cur_dsk]);
#endif
}
}
return val;
}
/* WD 1797 FDC track register routine */
int32 fdctrk(int32 io, int32 data)
{
if (io) {
cur_trk[cur_dsk] = data & 0xFF;
#if DEBUG > 1
printf("Drive %d track set to %d\n\r", cur_dsk, data);
#endif
} else
;
#if DEBUG > 1
printf("Drive %d track read as %d\n\r", cur_dsk, cur_trk[cur_dsk]);
#endif
return cur_trk[cur_dsk];
}
/* WD 1797 FDC sector register routine */
int32 fdcsec(int32 io, int32 data)
{
if (io) {
cur_sec[cur_dsk] = data & 0xFF;
if (cur_sec[cur_dsk] == 0) /* fix for swtp boot! */
cur_sec[cur_dsk] = 1;
#if DEBUG > 1
printf("Drive %d sector set to %d\n\r", cur_dsk, data);
#endif
} else
;
#if DEBUG > 1
printf("Drive %d sector read as %d\n\r", cur_dsk, cur_sec[cur_dsk]);
#endif
return cur_sec[cur_dsk];
}
/* WD 1797 FDC data register routine */
int32 fdcdata(int32 io, int32 data)
{
int32 i;
if (io) { /* write byte to fdc */
fdcbyte = data; /* save for seek */
if ((i = cur_byt[cur_dsk]) < SECT_SIZE) { /* copy bytes to buffer */
#if DEBUG > 3
printf("Writing byte %d of %02X\n\r", cur_byt[cur_dsk], data);
#endif
cur_byt[cur_dsk]++; /* step counter */
dskbuf[i] = data; /* byte into buffer */
if (cur_byt[cur_dsk] == SECT_SIZE) {
cur_flg[cur_dsk] &= ~(BUSY | DRQ);
if (dptr) { /* if initiated by FDC write command */
sim_fwrite(dskbuf, 256, 1, dptr -> fileref); /* write it */
dptr = NULL;
}
#if DEBUG > 0
printf("Sector write complete\n\r");
#endif
}
}
return 0;
} else { /* read byte from fdc */
if ((i = cur_byt[cur_dsk]) < SECT_SIZE) { /* copy bytes from buffer */
#if DEBUG > 1
printf("Reading byte %d\n\r", cur_byt[cur_dsk]);
#endif
cur_byt[cur_dsk]++; /* step counter */
if (cur_byt[cur_dsk] == SECT_SIZE) { /* done? */
cur_flg[cur_dsk] &= ~(BUSY | DRQ); /* clear flags */
#if DEBUG > 0
printf("Sector read complete\n\r");
#endif
}
return (dskbuf[i] & 0xFF);
} else
return 0;
}
}

View file

@ -1,312 +0,0 @@
/* swtp_sio: SWTP serial I/O card
Copyright (c) 2005, William 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
Willaim 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.
Based on work by Charles E Owen (c) 1997 and Peter Schorn (c) 2002-2005
These functions support a simulated SWTP MP-S interface card.
The card had two physical I/O ports which could be connected
to any serial I/O device that would connect to a current loop
or RS232 interface. Available baud rates were jumper selectable
for each port from 110 to 9600. The ports appear at all 4 addresses.
This fact is used by SWTBUG to determine the presence of the MP-S vice
MP-C serial card.
All I/O is via either programmed I/O or interrupt controlled I/O.
It has a status port and a data port. A write to the status port
can select some options for the device (0x03 will reset the port).
A read of the status port gets the port status:
+---+---+---+---+---+---+---+---+
| I | P | O | F |CTS|DCD|TXE|RXF|
+---+---+---+---+---+---+---+---+
RXF - A 1 in this bit position means a character has been received
on the data port and is ready to be read.
TXE - A 1 in this bit means the port is ready to receive a character
on the data port and transmit it out over the serial line.
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 <ctype.h>
#include "swtp_defs.h"
#define UNIT_V_ANSI (UNIT_V_UF + 0) // ANSI mode
#define UNIT_ANSI (1 << UNIT_V_ANSI)
t_stat sio_svc (UNIT *uptr);
t_stat sio_reset (DEVICE *dptr);
t_stat ptr_svc (UNIT *uptr);
t_stat ptr_reset (DEVICE *dptr);
t_stat ptp_svc (UNIT *uptr);
t_stat ptp_reset (DEVICE *dptr);
int32 ptr_stopioe = 0, ptp_stopioe = 0; // stop on error
// MP-S Standard I/O Data Structures
UNIT sio_unit = { UDATA (&sio_svc, 0, 0),
KBD_POLL_WAIT };
REG sio_reg[] = {
{ ORDATA (DATA, sio_unit.buf, 8) },
{ ORDATA (STAT, sio_unit.u3, 8) },
{ NULL } };
MTAB sio_mod[] = {
{ UNIT_ANSI, 0, "TTY", "TTY", NULL },
{ 0 } };
DEVICE sio_dev = {
"MP-S", &sio_unit, sio_reg, sio_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &sio_reset,
NULL, NULL, NULL };
UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE, 0),
KBD_POLL_WAIT };
DEVICE ptr_dev = {
"PTR", &ptr_unit, NULL, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptr_reset,
NULL, NULL, NULL };
UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0),
KBD_POLL_WAIT };
DEVICE ptp_dev = {
"PTP", &ptp_unit, NULL, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptp_reset,
NULL, NULL, NULL };
/* Service routines to handle simulator functions */
/* service routine - actually gets char & places in buffer */
int32 ptp_rdr(int32 io, int32 data);
int32 ptp_flag = 0, ptr_flag = 0;
/* console input service routine */
t_stat sio_svc (UNIT *uptr)
{
int32 temp;
sim_activate (&sio_unit, sio_unit.wait); // continue poll
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG)
return temp; // no char or error?
sio_unit.buf = temp & 0xFF; // Save char
sio_unit.u3 |= 0x01; // Set RXF flag
/* Do any special character handling here */
sio_unit.pos++; // step character count
return SCPE_OK;
}
/* paper tape reader input service routine */
t_stat ptr_svc (UNIT *uptr)
{
return SCPE_OK;
}
/* paper tape punch output service routine */
t_stat ptp_svc (UNIT *uptr)
{
return SCPE_OK;
}
/* Reset console */
t_stat sio_reset (DEVICE *dptr)
{
sio_unit.buf = 0; // Data buffer
sio_unit.u3 = 0x02; // Status buffer
sim_activate (&sio_unit, sio_unit.wait); // activate unit
return SCPE_OK;
}
/* Reset paper tape reader */
t_stat ptr_reset (DEVICE *dptr)
{
ptr_unit.buf = 0;
ptr_unit.u3 = 0x02;
sim_cancel (&ptr_unit); // deactivate unit
return SCPE_OK;
}
/* Reset paper tape punch */
t_stat ptp_reset (DEVICE *dptr)
{
ptp_unit.buf = 0;
ptp_unit.u3 = 0x02;
sim_cancel (&ptp_unit); // deactivate unit
return SCPE_OK;
}
/* I/O instruction handlers, called from the CPU module when a
read or write occur to addresses 0x8000-0x801F.
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.
This code emulates a SWTP MP-S Serial Card with a Model 33 Teletype
attached. The Model 33 uses DC1-DC4 codes to enable or disable the
paper tape reader and punch. Those devices are defined in this module,
and the code built to emulate those functions if the PTP and/or PTR
are attached in the simulator.
*/
/* Port 1 (0x8004-0x8007) controls the Model 33 Teletype */
int32 ptr_flg1 = 0;
int32 odata, status;
int32 sio0s(int32 io, int32 data)
{
UNIT *uptr;
if (io == 0) { // control register read
if (ptr_flag) { // reader enabled?
if ((ptr_unit.flags & UNIT_ATT) == 0) // attached?
ptr_unit.u3 &= 0xFE; // no, clear RXF flag
else {
uptr = ptr_dev.units;// not EOF?
if (feof(uptr -> fileref))
ptr_unit.u3 &= 0xFE;
else
ptr_unit.u3 |= 0x01;
}
return (status = ptr_unit.u3); // no - done
} else {
return (status = sio_unit.u3); // return console status
}
} else { // control register write
if (data == 0x03) { // reset port!
sio_unit.u3 = 0x02; // reset console
sio_unit.buf = 0;
sio_unit.pos = 0;
ptr_unit.u3 = 0x02; // reset reader
ptr_unit.buf = 0;
ptr_unit.pos = 0;
ptp_unit.u3 = 0x02; // reset punch
ptp_unit.buf = 0;
ptp_unit.pos = 0;
}
return (status = 0); // invalid io
}
}
int32 sio0d(int32 io, int32 data)
{
UNIT *uptr;
if (io == 0) { // data register read
if (ptr_flag) { // RDR enabled?
if ((ptr_unit.flags & UNIT_ATT) == 0) // attached?
return 0; // no, done
// printf("ptr_unit.u3=%02X\n", ptr_unit.u3);
if ((ptr_unit.u3 & 0x01) == 0) { // yes, more data?
// printf("Returning old %02X\n", odata); // no, return previous byte
return (odata & 0xFF);
}
uptr = ptr_dev.units; // get data byte
if ((odata = getc(uptr -> fileref)) == EOF) { // end of file?
// printf("Got EOF\n");
ptr_unit.u3 &= 0xFE; // clear RXF flag
return (odata = 0); // no data
}
// printf("Returning new %02X\n", odata);
ptr_unit.pos++; // step character count
ptr_unit.u3 &= 0xFE; // clear RXF flag
return (odata & 0xFF); // return character
} else {
sio_unit.u3 &= 0xFE; // clear RXF flag
return (odata = sio_unit.buf); // return next char
}
} else { // data register write
if (isprint(data) || data == '\r' || data == '\n') { // printable?
sim_putchar(data); // print character on console
if (ptp_flag && ptp_unit.flags & UNIT_ATT) { // PTP enabled & attached?
uptr = ptp_dev.units; // punch character to file
putc(data, uptr -> fileref);
ptp_unit.pos++; // step character counter
}
} else { // DC1-DC4 control Reader/Punch
switch (data) {
case 0x11: // RDR on
ptr_flag = 1;
ptr_flg1 = 0;
ptr_unit.u3 |= 0x01;
// printf("Reader on\r\n");
break;
case 0x12: // PTP on
ptp_flag = 1;
ptp_unit.u3 |= 0x02;
// printf("Punch on\r\n");
break;
case 0x13: // RDR off
ptr_flag = 0;
// printf("Reader off-%d bytes read\r\n", ptr_unit.pos);
break;
case 0x14: // PTP off
ptp_flag = 0;
// printf("Punch off-%d bytes written\r\n", ptp_unit.pos);
break;
default: // ignore all other characters
break;
}
}
}
return (odata = 0);
}
/* because each port appears at 2 addresses and this fact is used
to determine if it is a MP-C or MP-S repeatedly in the SWTBUG
monitor, this code assures that reads of the high ports return
the same data as was read the last time on the low ports.
*/
int32 sio1s(int32 io, int32 data)
{
return status;
}
int32 sio1d(int32 io, int32 data)
{
return odata;
}

View file

@ -1,425 +0,0 @@
/* swtp_sys.c: SWTP 6800 system interface
Copyright (c) 2005, William 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.
Based on work by Charles E Owen (c) 1997 and Peter Schorn (c) 2002-2005
*/
#include <ctype.h>
#include <string.h>
#include "swtp_defs.h"
/* externals */
extern DEVICE cpu_dev;
extern DEVICE dsk_dev;
extern UNIT cpu_unit;
extern REG cpu_reg[];
extern DEVICE sio_dev;
extern DEVICE ptr_dev;
extern DEVICE ptp_dev;
extern DEVICE lpt_dev;
extern unsigned char M[];
extern int32 saved_PC;
extern int32 sim_switches;
//extern int32 (*sim_vm_fprint_addr)(FILE*, DEVICE*,t_addr);
/* prototypes */
int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag);
int32 fprint_sym (FILE *of, int32 addr, uint32 *val,
UNIT *uptr, int32 sw);
t_addr fprint_addr(FILE *stream, DEVICE *dptr, t_addr addr);
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw);
void sim_special_init (void);
/* links into scp */
void (*sim_vm_init)(void) = &sim_special_init;
/* 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
sim_load binary loader
*/
char sim_name[] = "SWTP 6800";
REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 16;
DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptp_dev, &ptr_dev, &dsk_dev, NULL };
const char *sim_stop_messages[] = {
"Unknown error",
"Unknown I/O Instruction",
"HALT instruction",
"Breakpoint",
"Invalid Opcode",
"Invalid Memory" };
static const char *opcode[] = {
"???", "NOP", "???", "???", //0x00
"???", "???", "TAP", "TPA",
"INX", "DEX", "CLV", "SEV",
"CLC", "SEC", "CLI", "SEI",
"SBA", "CBA", "???", "???", //0x10
"???", "???", "TAB", "TBA",
"???", "DAA", "???", "ABA",
"???", "???", "???", "???",
"BRA", "???", "BHI", "BLS", //0x20
"BCC", "BCS", "BNE", "BEQ",
"BVC", "BVS", "BPL", "BMI",
"BGE", "BLT", "BGT", "BLE",
"TSX", "INS", "PULA", "PULB", //0x30
"DES", "TXS", "PSHA", "PSHB",
"???", "RTS", "???", "RTI",
"???", "???", "WAI", "SWI",
"NEGA", "???", "???", "COMA", //0x40
"LSRA", "???", "RORA", "ASRA",
"ASLA", "ROLA", "DECA", "???",
"INCA", "TSTA", "???", "CLRA",
"NEGB", "???", "???", "COMB", //0x50
"LSRB", "???", "RORB", "ASRB",
"ASLB", "ROLB", "DECB", "???",
"INCB", "TSTB", "???", "CLRB",
"NEG", "???", "???", "COM", //0x60
"LSR", "???", "ROR", "ASR",
"ASL", "ROL", "DEC", "???",
"INC", "TST", "JMP", "CLR",
"NEG", "???", "???", "COM", //0x70
"LSR", "???", "ROR", "ASR",
"ASL", "ROL", "DEC", "???",
"INC", "TST", "JMP", "CLR",
"SUBA", "CMPA", "SBCA", "???", //0x80
"ANDA", "BITA", "LDAA", "???",
"EORA", "ADCA", "ORAA", "ADDA",
"CPX", "BSR", "LDS", "???",
"SUBA", "CMPA", "SBCA", "???", //0x90
"ANDA", "BITA", "LDAA", "STAA",
"EORA", "ADCA", "ORAA", "ADDA",
"CPX", "???", "LDS", "STS",
"SUBA", "CMPA", "SBCA", "???", //0xA0
"ANDA", "BITA", "LDAA", "STAA",
"EORA", "ADCA", "ORAA", "ADDA",
"CPX X", "JSR X", "LDS X", "STS X",
"SUBA", "CMPA", "SBCA", "???", //0xB0
"ANDA", "BITA", "LDAA", "STAA",
"EORA", "ADCA", "ORAA", "ADDA",
"CPX", "JSR", "LDS", "STS",
"SUBB", "CMPB", "SBCB", "???", //0xC0
"ANDB", "BITB", "LDAB", "???",
"EORB", "ADCB", "ORAB", "ADDB",
"???", "???", "LDX", "???",
"SUBB", "CMPB", "SBCB", "???", //0xD0
"ANDB", "BITB", "LDAB", "STAB",
"EORB", "ADCB", "ORAB", "ADDB",
"???", "???", "LDX", "STX",
"SUBB", "CMPB", "SBCB", "???", //0xE0
"ANDB", "BITB", "LDAB", "STAB",
"EORB", "ADCB", "ORAB", "ADDB",
"???", "???", "LDX", "STX",
"SUBB", "CMPB", "SBCB", "???", //0xF0
"ANDB", "BITB", "LDAB", "STAB",
"EORB", "ADCB", "ORAB", "ADDB",
"???", "???", "LDX", "STX",
};
int32 oplen[256] = {
0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1, //0x00
1,1,0,0,0,0,1,1,0,1,0,1,0,0,0,0,
2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
1,1,1,1,1,1,1,1,0,1,0,1,0,0,1,1,
1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1, //0x40
1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1,
2,0,0,2,2,0,2,2,2,2,2,0,2,2,2,2,
3,0,0,3,3,0,3,3,3,3,3,0,3,3,3,3,
2,2,2,0,2,2,2,0,2,2,2,2,3,2,3,0, //0x80
2,2,2,0,2,2,2,2,2,2,2,2,2,0,2,2,
2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,0,3,3,3,3,3,3,3,3,3,3,3,3,
2,2,2,0,2,2,2,0,2,2,2,2,0,0,3,0, //0xC0
2,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2,
2,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2,
3,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3 };
/* This is the dumper/loader. This command uses the -h to signify a
hex dump/load vice a binary one. If no address is given to load, it
takes the address from the hex record or the current PC for binary.
*/
int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
{
int32 i, cnt = 0, addr = 0, start = 0x10000, end = 0, bytecnt,
cksum1, cksum, bytes[250];
char buffer[256];
sscanf(cptr," %x-%x", &start, &end);
if (flag) { // dump
if (start == 0x10000) // no address parameter
return SCPE_2FARG;
if (sim_switches & 0x80) { // hex dump
addr = start;
while (addr <= end) { // more records to write
if ((addr + 16) <= end) // how many bytes this record
bytecnt = 16 + 3;
else
bytecnt = end - addr + 4;
cksum = -1 - (bytecnt) - (addr >> 8) - (addr & 0xFF); //init cksum
fprintf(fileref, "S1%02X%02X%02X", bytecnt, addr>>8, addr&0xFF); //header
for (i=0; i<bytecnt-3; i++, addr++, cnt++) { // data
fprintf(fileref, "%02X", M[addr]);
cksum -= M[addr];
}
fprintf(fileref, "%02X\r\n", cksum & 0xff); // eor
}
fprintf(fileref, "S9\r\n"); // eof
} else { // binary dump
for (addr = start; addr <= end; addr++, cnt++) {
putc(M[addr], fileref);
}
}
printf ("%d Bytes dumped starting at %04X\n", cnt, start);
} else { // load
if (sim_switches & 0x80) { // hex load
while ((fgets(buffer, 255, fileref)) != NULL) {
if (buffer[0] != 'S')
printf("Not a Motorola hex format file\n");
else {
if (buffer[0] == '0') // name record
printf("Name record found and ignored\n");
else if (buffer[1] == '1') { // another record
sscanf(buffer+2,"%2x%4x", &bytecnt, &addr);
if (start == 0x10000)
start = addr;
for (i=0; i < bytecnt-3; i++)
sscanf(buffer+8+(2*i), "%2x", &bytes[i]);
sscanf(buffer+8+(2*i), "%2x", &cksum1);
cksum = -1 - (bytecnt) - (addr >> 8) - (addr & 0xFF); //init cksum
for (i=0; i < bytecnt-3; i++)
cksum -= bytes[i];
cksum &= 0xFF;
if (cksum != cksum1)
printf("Checksum error\n");
else {
for (i=0; i < bytecnt-3; i++) {
M[addr++] = bytes[i];
cnt++;
}
}
} else if (buffer[1] == '9') // end of file
printf("End of file\n");
}
}
} else { // binary load
if (start == 0x10000) // no starting address
addr = saved_PC;
else
addr = start;
start = addr;
while ((i = getc (fileref)) != EOF) {
M[addr] = i;
addr++;
cnt++;
}
}
printf ("%d Bytes loaded starting at %04X\n", cnt, start);
}
return (SCPE_OK);
}
/* Symbolic output
Inputs:
*of = output stream
addr = current PC
*val = pointer to values
*uptr = pointer to unit
sw = switches
Outputs:
status = error code
*/
int32 fprint_sym (FILE *of, int32 addr, uint32 *val,
UNIT *uptr, int32 sw)
{
int32 i, inst, inst1;
if (sw & SWMASK ('D')) { // dump memory
for (i=0; i<16; i++)
fprintf(of, "%02X ", val[i]);
fprintf(of, " ");
for (i=0; i<16; i++)
if (isprint(val[i]))
fprintf(of, "%c", val[i]);
else
fprintf(of, ".");
return -15;
} else if (sw & SWMASK ('M')) { // dump instruction mnemonic
inst = val[0];
if (!oplen[inst]) { // invalid opcode
fprintf(of, "%02X", inst);
return 0;
}
inst1 = inst & 0xF0;
fprintf (of, "%s", opcode[inst]); // mnemonic
if (strlen(opcode[inst]) == 3)
fprintf(of, " ");
if (inst1 == 0x20 || inst == 0x8D) { // rel operand
inst1 = val[1];
if (val[1] & 0x80)
inst1 |= 0xFF00;
fprintf(of, " $%04X", (addr + inst1 + 2) & ADDRMASK);
} else if (inst1 == 0x80 || inst1 == 0xC0) { // imm operand
if ((inst & 0x0F) < 0x0C)
fprintf(of, " #$%02X", val[1]);
else
fprintf(of, " #$%02X%02X", val[1], val[2]);
} else if (inst1 == 0x60 || inst1 == 0xA0 || inst1 == 0xE0) // ind operand
fprintf(of, " %d,X", val[1]);
else if (inst1 == 0x70 || inst1 == 0xb0 || inst1 == 0xF0) // ext operand
fprintf(of, " $%02X%02X", val[1], val[2]);
return (-(oplen[inst] - 1));
} else
return SCPE_ARG;
}
/* address output routine */
t_addr fprint_addr(FILE *of, DEVICE *dptr, t_addr addr)
{
fprintf(of, "%04X", addr);
return 0;
}
/* Symbolic input
Inputs:
*cptr = pointer to input string
addr = current PC
*uptr = pointer to unit
*val = pointer to output values
sw = switches
Outputs:
status = error status
*/
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw)
{
int32 cflag, i = 0, j, r;
char gbuf[CBUFSIZE];
cflag = (uptr == NULL) || (uptr == &cpu_unit);
while (isspace (*cptr)) cptr++; /* absorb spaces */
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
if (cptr[0] == 0)
return SCPE_ARG; /* must have 1 char */
val[0] = (uint32) cptr[0];
return SCPE_OK;
}
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
if (cptr[0] == 0)
return SCPE_ARG; /* must have 1 char */
val[0] = ((uint32) cptr[0] << 8) + (uint32) cptr[1];
return SCPE_OK;
}
/* An instruction: get opcode (all characters until null, comma,
or numeric (including spaces).
*/
while (1) {
if (*cptr == ',' || *cptr == '\0' ||
isdigit(*cptr))
break;
gbuf[i] = toupper(*cptr);
cptr++;
i++;
}
/* Allow for RST which has numeric as part of opcode */
if (toupper(gbuf[0]) == 'R' &&
toupper(gbuf[1]) == 'S' &&
toupper(gbuf[2]) == 'T') {
gbuf[i] = toupper(*cptr);
cptr++;
i++;
}
/* Allow for 'MOV' which is only opcode that has comma in it. */
if (toupper(gbuf[0]) == 'M' &&
toupper(gbuf[1]) == 'O' &&
toupper(gbuf[2]) == 'V') {
gbuf[i] = toupper(*cptr);
cptr++;
i++;
gbuf[i] = toupper(*cptr);
cptr++;
i++;
}
/* kill trailing spaces if any */
gbuf[i] = '\0';
for (j = i - 1; gbuf[j] == ' '; j--) {
gbuf[j] = '\0';
}
/* find opcode in table */
for (j = 0; j < 256; j++) {
if (strcmp(gbuf, opcode[j]) == 0)
break;
}
if (j > 255) /* not found */
return SCPE_ARG;
val[0] = j; /* store opcode */
if (oplen[j] < 2) /* if 1-byter we are done */
return SCPE_OK;
if (*cptr == ',') cptr++;
cptr = get_glyph(cptr, gbuf, 0); /* get address */
sscanf(gbuf, "%o", &r);
if (oplen[j] == 2) {
val[1] = r & 0xFF;
return (-1);
}
val[1] = r & 0xFF;
val[2] = (r >> 8) & 0xFF;
return (-2);
}
/* initialize optional interfaces */
void sim_special_init (void)
{
// *sim_vm_fprint_addr = &fprint_addr;
}

231
swtp6800/common/bootrom.c Normal file
View file

@ -0,0 +1,231 @@
/* bootrom.c: Boot ROM simulator for Motorola processors
Copyright (c) 2010-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 single simulated 2704 to 2764 EPROM device on
an 8-bit computer system.. This device allows the the device buffer to
be loaded from a binary file containing the emulated EPROM code.
These functions support a simulated 2704, 2708, 2716, 2732 or 2764 EPROM
device on a CPU board. The byte get and put routines use an offset into
the boot EPROM image to locate the proper byte. This allows another device
to set the base address for the boot EPROM. The device type is stored as
a binary number in the first three unit flag bits.
This device uses a dynamically allocated buffer to hold the EPROM image.
A call to BOOTROM_config will free the current buffer. A call to
BOOTROM_reset will allocate a new buffer of BOOTROM_unit.capac bytes. A
call to BOOTROM_attach will load the buffer with the EPROM image.
*/
#include <stdio.h>
#include "swtp_defs.h"
#define UNIT_V_MSIZE (UNIT_V_UF) /* ROM Size */
#define UNIT_MSIZE (0x7 << UNIT_V_MSIZE)
#define UNIT_NONE (0 << UNIT_V_MSIZE) /* No EPROM */
#define UNIT_2704 (1 << UNIT_V_MSIZE) /* 2704 mode */
#define UNIT_2708 (2 << UNIT_V_MSIZE) /* 2708 mode */
#define UNIT_2716 (3 << UNIT_V_MSIZE) /* 2716 mode */
#define UNIT_2732 (4 << UNIT_V_MSIZE) /* 2732 mode */
#define UNIT_2764 (5 << UNIT_V_MSIZE) /* 2764 mode */
/* function prototypes */
t_stat BOOTROM_svc (UNIT *uptr);
t_stat BOOTROM_config (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat BOOTROM_attach (UNIT *uptr, char *cptr);
t_stat BOOTROM_reset (DEVICE *dptr);
int32 BOOTROM_get_mbyte(int32 offset);
/* SIMH Standard I/O Data Structures */
UNIT BOOTROM_unit = { UDATA (NULL,
UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),
KBD_POLL_WAIT };
MTAB BOOTROM_mod[] = {
{ UNIT_MSIZE, UNIT_NONE, "None", "NONE", &BOOTROM_config },
{ UNIT_MSIZE, UNIT_2704, "2704", "2704", &BOOTROM_config },
{ UNIT_MSIZE, UNIT_2708, "2708", "2708", &BOOTROM_config },
{ UNIT_MSIZE, UNIT_2716, "2716", "2716", &BOOTROM_config },
{ UNIT_MSIZE, UNIT_2732, "2732", "2732", &BOOTROM_config },
{ UNIT_MSIZE, UNIT_2764, "2764", "2764", &BOOTROM_config },
{ 0 }
};
DEBTAB BOOTROM_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE BOOTROM_dev = {
"BOOTROM", /* name */
&BOOTROM_unit, /* units */
NULL, /* registers */
BOOTROM_mod, /* modifiers */
1, /* numunits */
16, /* aradix */
32, /* awidth */
1, /* aincr */
16, /* dradix */
8, /* dwidth */
NULL, /* examine */
NULL, /* deposit */
&BOOTROM_reset, /* reset */
NULL, /* boot */
&BOOTROM_attach, /* attach */
NULL, /* detach */
NULL, /* ctxt */
DEV_DEBUG, /* flags */
0, /* dctrl */
BOOTROM_debug, /* debflags */
NULL, /* msize */
NULL /* lname */
};
/* global variables */
/* BOOTROM_attach - attach file to EPROM unit */
t_stat BOOTROM_attach (UNIT *uptr, char *cptr)
{
t_stat r;
if (BOOTROM_dev.dctrl & DEBUG_flow)
printf("BOOTROM_attach: cptr=%s\n", cptr);
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
if (BOOTROM_dev.dctrl & DEBUG_flow)
printf("BOOTROM_attach: Error\n");
return r;
}
if (BOOTROM_dev.dctrl & DEBUG_flow)
printf("BOOTROM_attach: Done\n");
return (BOOTROM_reset (NULL));
}
/* BOOTROM_config = None, 2704, 2708, 2716, 2732 or 2764 */
t_stat BOOTROM_config (UNIT *uptr, int32 val, char *cptr, void *desc)
{
if (BOOTROM_dev.dctrl & DEBUG_flow) /* entry message */
printf("BOOTROM_config: val=%d\n", val);
if ((val < UNIT_NONE) || (val > UNIT_2764)) { /* valid param? */
if (BOOTROM_dev.dctrl & DEBUG_flow) /* No */
printf("BOOTROM_config: Parameter error\n");
return SCPE_ARG;
}
if (val == UNIT_NONE)
BOOTROM_unit.capac = 0; /* set EPROM size */
else
BOOTROM_unit.capac = 0x200 << (val >> UNIT_V_MSIZE) - 1; /* set EPROM size */
if (BOOTROM_unit.filebuf) { /* free buffer */
free (BOOTROM_unit.filebuf);
BOOTROM_unit.filebuf = NULL;
}
if (BOOTROM_dev.dctrl & DEBUG_flow) /* status message */
printf("BOOTROM_config: BOOTROM_unit.capac=%d\n",
BOOTROM_unit.capac);
if (BOOTROM_dev.dctrl & DEBUG_flow) /* exit message */
printf("BOOTROM_config: Done\n");
return SCPE_OK;
}
/* EPROM reset */
t_stat BOOTROM_reset (DEVICE *dptr)
{
int j, c;
FILE *fp;
t_stat r;
if (BOOTROM_dev.dctrl & DEBUG_flow)
printf("BOOTROM_reset: \n");
if ((BOOTROM_unit.flags & UNIT_MSIZE) == 0) { /* if none selected */
// printf(" EPROM: Defaulted to None\n");
// printf(" \"set eprom NONE | 2704 | 2708 | 2716 | 2732 | 2764\"\n");
// printf(" \"att eprom <filename>\"\n");
BOOTROM_unit.capac = 0; /* set EPROM size to 0 */
if (BOOTROM_dev.dctrl & DEBUG_flow)
printf("BOOTROM_reset: Done1\n");
return SCPE_OK;
} /* if attached */
// printf(" EPROM: Initializing [%04X-%04XH]\n",
// 0xE000, 0xE000 + BOOTROM_unit.capac - 1);
if (BOOTROM_unit.filebuf == NULL) { /* no buffer allocated */
BOOTROM_unit.filebuf = malloc(BOOTROM_unit.capac); /* allocate EPROM buffer */
if (BOOTROM_unit.filebuf == NULL) {
if (BOOTROM_dev.dctrl & DEBUG_flow)
printf("BOOTROM_reset: Malloc error\n");
return SCPE_MEM;
}
}
fp = fopen(BOOTROM_unit.filename, "rb"); /* open EPROM file */
if (fp == NULL) {
printf("\tUnable to open ROM file %s\n",BOOTROM_unit.filename);
printf("\tNo ROM image loaded!!!\n");
return SCPE_OK;
}
j = 0; /* load EPROM file */
c = fgetc(fp);
while (c != EOF) {
*(uint8 *)(BOOTROM_unit.filebuf + j++) = c & 0xFF;
c = fgetc(fp);
if (j > BOOTROM_unit.capac) {
printf("\tImage is too large - Load truncated!!!\n");
break;
}
}
fclose(fp);
// printf("\t%d bytes of ROM image %s loaded\n", j, BOOTROM_unit.filename);
if (BOOTROM_dev.dctrl & DEBUG_flow)
printf("BOOTROM_reset: Done2\n");
return SCPE_OK;
}
/* get a byte from memory - byte offset of image */
int32 BOOTROM_get_mbyte(int32 offset)
{
int32 val;
if (BOOTROM_unit.filebuf == NULL) {
if (BOOTROM_dev.dctrl & DEBUG_read)
printf("BOOTROM_get_mbyte: EPROM not configured\n");
return 0xFF;
}
if (BOOTROM_dev.dctrl & DEBUG_read)
printf("BOOTROM_get_mbyte: offset=%04X\n", offset);
val = *(uint8 *)(BOOTROM_unit.filebuf + offset) & 0xFF;
if (BOOTROM_dev.dctrl & DEBUG_read)
printf("BOOTROM_get_mbyte: Normal val=%02X\n", val);
return val;
}
/* end of bootrom.c */

571
swtp6800/common/dc-4.c Normal file
View file

@ -0,0 +1,571 @@
/* dc4.c: SWTP DC-4 FDC Simulator
Copyright (c) 2005-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.
The DC-4 is a 5-inch floppy controller which can control up
to 4 daisy-chained 5-inch floppy drives. The controller is based on
the Western Digital 1797 Floppy Disk Controller (FDC) chip. This
file only emulates the minimum DC-4 functionality to interface with
the virtual disk file.
The floppy controller is interfaced to the CPU by use of 5 memory
addreses. These are SS-30 slot numbers 5 and 6 (0x8014-0x801B).
Address Mode Function
------- ---- --------
0x8014 Read Returns FDC interrupt status
0x8014 Write Selects the drive/head/motor control
0x8018 Read Returns status of FDC
0x8018 Write FDC command register
0x8019 Read Returns FDC track register
0x8019 Write Set FDC track register
0x801A Read Returns FDC sector register
0x801A Write Set FDC sector register
0x801B Read Read data
0x801B Write Write data
Drive Select Read (0x8014):
+---+---+---+---+---+---+---+---+
| I | D | X | X | X | X | X | X |
+---+---+---+---+---+---+---+---+
I = Set indicates an interrupt request from the FDC pending.
D = DRQ pending - same as bit 1 of FDC status register.
Drive Select Write (0x8014):
+---+---+---+---+---+---+---+---+
| M | S | X | X | X | X | Device|
+---+---+---+---+---+---+---+---+
M = If this bit is 1, the one-shot is triggered/retriggered to
start/keep the motors on.
S = Side select. If set, side one is selected otherwise side zero
is selected.
X = not used
Device = value 0 thru 3, selects drive 0-3 to be controlled.
Drive Status Read (0x8018):
+---+---+---+---+---+---+---+---+
| R | P | H | S | C | L | D | B |
+---+---+---+---+---+---+---+---+
B - When 1, the controller is busy.
D - When 1, index mark detected (type I) or data request - read data
ready/write data empty (type II or III).
H - When 1, track 0 (type I) or lost data (type II or III).
C - When 1, crc error detected.
S - When 1, seek (type I) or RNF (type II or III) error.
H - When 1, head is currently loaded (type I) or record type/
write fault (type II or III).
P - When 1, indicates that diskette is write-protected.
R - When 1, drive is not ready.
Drive Control Write (0x8018) for type I commands:
+---+---+---+---+---+---+---+---+
| 0 | S2| S1| S0| H | V | R1| R0|
+---+---+---+---+---+---+---+---+
R0/R1 - Selects the step rate.
V - When 1, verify on destination track.
H - When 1, loads head to drive surface.
S0/S1/S2 = 000 - home.
001 - seek track in data register.
010 - step without updating track register.
011 - step and update track register.
100 - step in without updating track register.
101 - step in and update track register.
110 - step out without updating track register.
111 - step out and update track register.
Drive Control Write (0x8018) for type II commands:
+---+---+---+---+---+---+---+---+
| 1 | 0 | T | M | S | E | B | A |
+---+---+---+---+---+---+---+---+
A - Zero for read, 1 on write deleted data mark else data mark.
B - When 1, shifts sector length field definitions one place.
E - When, delay operation 15 ms, 0 no delay.
S - When 1, select side 1, 0 select side 0.
M - When 1, multiple records, 0 for single record.
T - When 1, write command, 0 for read.
Drive Control Write (0x8018) for type III commands:
+---+---+---+---+---+---+---+---+
| 1 | 1 | T0| T1| 0 | E | 0 | 0 |
+---+---+---+---+---+---+---+---+
E - When, delay operation 15 ms, 0 no delay.
T0/T1 - 00 - read address command.
10 - read track command.
11 - write track command.
Tracks are numbered from 0 up to one minus the last track in the 1797!
Track Register Read (0x8019):
+---+---+---+---+---+---+---+---+
| Track Number |
+---+---+---+---+---+---+---+---+
Reads the current 8-bit value from the track position.
Track Register Write (0x8019):
+---+---+---+---+---+---+---+---+
| Track Number |
+---+---+---+---+---+---+---+---+
Writes the 8-bit value to the track register.
Sectors are numbers from 1 up to the last sector in the 1797!
Sector Register Read (0x801A):
+---+---+---+---+---+---+---+---+
| Sector Number |
+---+---+---+---+---+---+---+---+
Reads the current 8-bit value from the sector position.
Sector Register Write (0x801A):
+---+---+---+---+---+---+---+---+
| Sector Number |
+---+---+---+---+---+---+---+---+
Writes the 8-bit value to the sector register.
Data Register Read (0x801B):
+---+---+---+---+---+---+---+---+
| Data |
+---+---+---+---+---+---+---+---+
Reads the current 8-bit value from the data register.
Data Register Write (0x801B):
+---+---+---+---+---+---+---+---+
| Data |
+---+---+---+---+---+---+---+---+
Writes the 8-bit value to the data register.
A FLEX disk is defined as follows:
Track Sector Use
0 1 Boot sector
0 2 Boot sector (cont)
0 3 Unused
0 4 System Identity Record (explained below)
0 5 Unused
0 6-last Directory - 10 entries/sector (explained below)
1 1 First available data sector
last-1 last Last available data sector
System Identity Record
Byte Use
0x00 Two bytes of zeroes (Clears forward link)
0x10 Volume name in ASCII(11 bytes)
0x1B Volume number in binary (2 bytes)
0x1D Address of first free data sector (Track-Sector) (2 bytes)
0x1F Address of last free data sector (Track-Sector) (2 bytes)
0x21 Total number of data sectors in binary (2 bytes)
0x23 Current date (Month-Day-Year) in binary
0x26 Highest track number on disk in binary (byte)
0x27 Highest sector number on a track in binary (byte)
The following unit registers are used by this controller emulation:
dsk_unit[cur_drv].u3 unit current flags
dsk_unit[cur_drv].u4 unit current track
dsk_unit[cur_drv].u5 unit current sector
dsk_unit[cur_drv].pos unit current sector byte index into buffer
dsk_unit[cur_drv].filebuf unit current sector buffer
dsk_unit[cur_drv].fileref unit current attached file reference
*/
#include <stdio.h>
#include "swtp_defs.h"
#define DEBUG 0
#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */
#define UNIT_ENABLE (1 << UNIT_V_ENABLE)
/* emulate a SS FLEX disk with 72 sectors and 80 tracks */
#define NUM_DISK 4 /* standard 1797 maximum */
#define SECT_SIZE 256 /* standard FLEX sector */
#define NUM_SECT 72 /* sectors/track */
#define TRAK_SIZE (SECT_SIZE * NUM_SECT) /* trk size (bytes) */
#define HEADS 1 /* handle as SS with twice the sectors */
#define NUM_CYL 80 /* maximum tracks */
#define DSK_SIZE (NUM_SECT * HEADS * NUM_CYL * SECT_SIZE) /* dsk size (bytes) */
#define SECSIZ 256 /* standard FLEX sector */
/* SIR offsets */
#define MAXCYL 0x26 /* last cylinder # */
#define MAXSEC 0x27 /* last sector # */
/* 1797 status bits */
#define BUSY 0x01
#define DRQ 0x02
#define WRPROT 0x40
#define NOTRDY 0x80
/* function prototypes */
t_stat dsk_reset (DEVICE *dptr);
/* SS-50 I/O address space functions */
int32 fdcdrv(int32 io, int32 data);
int32 fdccmd(int32 io, int32 data);
int32 fdctrk(int32 io, int32 data);
int32 fdcsec(int32 io, int32 data);
int32 fdcdata(int32 io, int32 data);
/* Local Variables */
int32 fdcbyte;
int32 intrq = 0; /* interrupt request flag */
int32 cur_dsk; /* Currently selected drive */
int32 wrt_flag = 0; /* FDC write flag */
int32 spt; /* sectors/track */
int32 trksiz; /* trk size (bytes) */
int32 heds; /* number of heads */
int32 cpd; /* cylinders/disk */
int32 dsksiz; /* dsk size (bytes) */
/* Floppy Disk Controller data structures
dsk_dev Mother Board device descriptor
dsk_unit Mother Board unit descriptor
dsk_reg Mother Board register list
dsk_mod Mother Board modifiers list
*/
UNIT dsk_unit[] = {
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) },
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) },
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) },
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) }
};
REG dsk_reg[] = {
{ HRDATA (DISK, cur_dsk, 4) },
{ NULL }
};
MTAB dsk_mod[] = {
{ UNIT_ENABLE, UNIT_ENABLE, "RW", "RW", NULL },
{ UNIT_ENABLE, 0, "RO", "RO", NULL },
{ 0 }
};
DEBTAB dsk_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE dsk_dev = {
"DC-4", //name
dsk_unit, //units
dsk_reg, //registers
dsk_mod, //modifiers
4, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
&dsk_reset, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
dsk_debug, /* debflags */
NULL, //msize
NULL //lname
};
/* Reset routine */
t_stat dsk_reset (DEVICE *dptr)
{
int i;
cur_dsk = 5; /* force initial SIR read */
for (i=0; i<NUM_DISK; i++) {
dsk_unit[i].u3 = 0; /* clear current flags */
dsk_unit[i].u4 = 0; /* clear current cylinder # */
dsk_unit[i].u5 = 0; /* clear current sector # */
dsk_unit[i].pos = 0; /* clear current byte ptr */
if (dsk_unit[i].filebuf == NULL) {
dsk_unit[i].filebuf = malloc(256); /* allocate buffer */
if (dsk_unit[i].filebuf == NULL) {
printf("dc-4_reset: Malloc error\n");
return SCPE_MEM;
}
}
}
spt = 0;
trksiz = 0;
heds = 0;
cpd = 0;
dsksiz = 0;
return SCPE_OK;
}
/* I/O instruction handlers, called from the MP-B2 module when a
read or write occur to addresses 0x8004-0x8007. */
/* DC-4 drive select register routine - this register is not part of the 1797
*/
int32 fdcdrv(int32 io, int32 data)
{
static long pos;
char buf[128];
if (io) { /* write to DC-4 drive register */
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdcdrv: Drive selected %d cur_dsk=%d", data & 0x03, cur_dsk);
if (cur_dsk == (data & 0x03))
return 0; /* already selected */
cur_dsk = data & 0x03; /* only 2 drive select bits */
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdcdrv: Drive set to %d", cur_dsk);
if ((dsk_unit[cur_dsk].flags & UNIT_ENABLE) == 0) {
dsk_unit[cur_dsk].u3 |= WRPROT; /* set 1797 WPROT */
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdcdrv: Drive write protected");
} else {
dsk_unit[cur_dsk].u3 &= ~WRPROT; /* set 1797 not WPROT */
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdcdrv: Drive NOT write protected");
}
pos = 0x200; /* Read in SIR */
if (dsk_dev.dctrl & DEBUG_read)
printf("\nfdcdrv: Read pos = %ld ($%04X)", pos, (unsigned int) pos);
sim_fseek(dsk_unit[cur_dsk].fileref, pos, 0); /* seek to offset */
sim_fread(dsk_unit[cur_dsk].filebuf, SECSIZ, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
dsk_unit[cur_dsk].u3 |= BUSY | DRQ; /* set DRQ & BUSY */
dsk_unit[cur_dsk].pos = 0; /* clear counter */
spt = *(uint8 *)(dsk_unit[cur_dsk].filebuf + MAXSEC) & 0xFF;
heds = 0;
cpd = *(uint8 *)(dsk_unit[cur_dsk].filebuf + MAXCYL) & 0xFF;
trksiz = spt * SECSIZ;
dsksiz = trksiz * cpd;
if (dsk_dev.dctrl & DEBUG_read)
printf("\nfdcdrv: spt=%d heds=%d cpd=%d trksiz=%d dsksiz=%d flags=%08X u3=%08X",
spt, heds, cpd, trksiz, dsksiz, dsk_unit[cur_dsk].flags, dsk_unit[cur_dsk].u3);
return 0;
} else { /* read from DC-4 drive register */
if (dsk_dev.dctrl & DEBUG_read)
printf("\nfdcdrv: Drive read as %02X", intrq);
return intrq;
}
}
/* WD 1797 FDC command register routine */
int32 fdccmd(int32 io, int32 data)
{
static int32 val = 0, val1 = NOTRDY;
static long pos;
if ((dsk_unit[cur_dsk].flags & UNIT_ATT) == 0) { /* not attached */
dsk_unit[cur_dsk].u3 |= NOTRDY; /* set not ready flag */
if (dsk_dev.dctrl & DEBUG_flow)
printf("\nfdccmd: Drive %d is not attached", cur_dsk);
return 0;
} else {
dsk_unit[cur_dsk].u3 &= ~NOTRDY; /* clear not ready flag */
}
if (io) { /* write command to fdc */
switch(data) {
case 0x8C: /* read command */
case 0x9C:
if (dsk_dev.dctrl & DEBUG_read)
printf("\nfdccmd: Read of disk %d, track %d, sector %d",
cur_dsk, dsk_unit[cur_dsk].u4, dsk_unit[cur_dsk].u5);
pos = trksiz * dsk_unit[cur_dsk].u4; /* calculate file offset */
pos += SECSIZ * (dsk_unit[cur_dsk].u5 - 1);
if (dsk_dev.dctrl & DEBUG_read)
printf("\nfdccmd: Read pos = %ld ($%08X)", pos, (unsigned int) pos);
sim_fseek(dsk_unit[cur_dsk].fileref, pos, 0); /* seek to offset */
sim_fread(dsk_unit[cur_dsk].filebuf, SECSIZ, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
dsk_unit[cur_dsk].u3 |= BUSY | DRQ; /* set DRQ & BUSY */
dsk_unit[cur_dsk].pos = 0; /* clear counter */
break;
case 0xAC: /* write command */
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdccmd: Write of disk %d, track %d, sector %d",
cur_dsk, dsk_unit[cur_dsk].u4, dsk_unit[cur_dsk].u5);
if (dsk_unit[cur_dsk].u3 & WRPROT) {
printf("\nfdccmd: Drive %d is write-protected", cur_dsk);
} else {
pos = trksiz * dsk_unit[cur_dsk].u4; /* calculate file offset */
pos += SECSIZ * (dsk_unit[cur_dsk].u5 - 1);
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdccmd: Write pos = %ld ($%08X)", pos, (unsigned int) pos);
sim_fseek(dsk_unit[cur_dsk].fileref, pos, 0); /* seek to offset */
wrt_flag = 1; /* set write flag */
dsk_unit[cur_dsk].u3 |= BUSY | DRQ;/* set DRQ & BUSY */
dsk_unit[cur_dsk].pos = 0; /* clear counter */
}
break;
case 0x18: /* seek command */
case 0x1B:
dsk_unit[cur_dsk].u4 = fdcbyte; /* set track */
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
if (dsk_dev.dctrl & DEBUG_flow)
printf("\nfdccmd: Seek of disk %d, track %d", cur_dsk, fdcbyte);
break;
case 0x0B: /* restore command */
dsk_unit[cur_dsk].u4 = 0; /* home the drive */
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
if (dsk_dev.dctrl & DEBUG_flow)
printf("\nfdccmd: Drive %d homed", cur_dsk);
break;
case 0xF0: /* write track command */
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdccmd: Write track command for drive %d", cur_dsk);
break;
default:
printf("Unknown FDC command %02XH\n\r", data);
}
} else { /* read status from fdc */
val = dsk_unit[cur_dsk].u3; /* set return value */
/* either print below will force the val to 0x43 forever. timing problem in
the 6800 disk driver software? */
// if (dsk_dev.dctrl & DEBUG_flow)
// printf("\nfdccmd: Exit Drive %d status=%02X", cur_dsk, val);
// printf("\n%02X", val); //even this short fails it!
if (val1 == 0 && ((val & (BUSY + DRQ)) == (BUSY + DRQ))) /* delay BUSY going high */
val &= ~BUSY;
if (val != val1) /* now allow BUSY after one read */
val1 = val;
if (dsk_dev.dctrl & DEBUG_flow)
printf("\nfdccmd: Exit Drive %d status=%02X", cur_dsk, val);
}
return val;
}
/* WD 1797 FDC track register routine */
int32 fdctrk(int32 io, int32 data)
{
if (io) {
dsk_unit[cur_dsk].u4 = data & 0xFF;
if (dsk_dev.dctrl & DEBUG_read)
printf("\nfdctrk: Drive %d track set to %d", cur_dsk, dsk_unit[cur_dsk].u4);
} else
;
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdctrk: Drive %d track read as %d", cur_dsk, dsk_unit[cur_dsk].u4);
return dsk_unit[cur_dsk].u4;
}
/* WD 1797 FDC sector register routine */
int32 fdcsec(int32 io, int32 data)
{
if (io) {
dsk_unit[cur_dsk].u5 = data & 0xFF;
if (dsk_unit[cur_dsk].u5 == 0) /* fix for swtp boot! */
dsk_unit[cur_dsk].u5 = 1;
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdcsec: Drive %d sector set to %d", cur_dsk, dsk_unit[cur_dsk].u5);
} else
;
if (dsk_dev.dctrl & DEBUG_read)
printf("\nfdcsec: Drive %d sector read as %d", cur_dsk, dsk_unit[cur_dsk].u5);
return dsk_unit[cur_dsk].u5;
}
/* WD 1797 FDC data register routine */
int32 fdcdata(int32 io, int32 data)
{
int32 val;
if (io) { /* write byte to fdc */
fdcbyte = data; /* save for seek */
if (dsk_unit[cur_dsk].pos < SECSIZ) { /* copy bytes to buffer */
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdcdata: Writing byte %d of %02X", dsk_unit[cur_dsk].pos, data);
*(uint8 *)(dsk_unit[cur_dsk].filebuf + dsk_unit[cur_dsk].pos) = data; /* byte into buffer */
dsk_unit[cur_dsk].pos++; /* step counter */
if (dsk_unit[cur_dsk].pos == SECSIZ) {
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ);
if (wrt_flag) { /* if initiated by FDC write command */
sim_fwrite(dsk_unit[cur_dsk].filebuf, SECSIZ, 1, dsk_unit[cur_dsk].fileref); /* write it */
wrt_flag = 0; /* clear write flag */
}
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdcdata: Sector write complete");
}
}
return 0;
} else { /* read byte from fdc */
if (dsk_unit[cur_dsk].pos < SECSIZ) { /* copy bytes from buffer */
if (dsk_dev.dctrl & DEBUG_read)
printf("\nfdcdata: Reading byte %d u3=%02X", dsk_unit[cur_dsk].pos, dsk_unit[cur_dsk].u3);
val = *(uint8 *)(dsk_unit[cur_dsk].filebuf + dsk_unit[cur_dsk].pos) & 0xFF;
dsk_unit[cur_dsk].pos++; /* step counter */
if (dsk_unit[cur_dsk].pos == SECSIZ) { /* done? */
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
if (dsk_dev.dctrl & DEBUG_write)
printf("\nfdcdata: Sector read complete");
}
return val;
} else
return 0;
}
}
/* end of dc-4.c */

222
swtp6800/common/i2716.c Normal file
View file

@ -0,0 +1,222 @@
/* i2716.c: Intel 2716 EPROM simulator for 8-bit processors
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 2704 to 2764 EPROMs device on an 8-bit
computer system. This device allows the attachment of the device to a binary file
containing the EPROM code.
These functions support emulation of 0 to 4 2716 EPROM devices on a CPU board.
The byte get and put routines use an offset into the boot EPROM image to locate
the proper byte. This allows another device to set the base address for each
EPROM.
This device uses a dynamically allocated buffer to hold each EPROM image.
A call to BOOTROM_config will free the current buffer. A call to
i2716_reset will allocate a new buffer of 2048 bytes. A
call to BOOTROM_attach will load the buffer with the EPROM image.
*/
#include <stdio.h>
#include "swtp_defs.h"
#define I2716_NUM 4 /* number of 2716 EPROMS */
extern int32 get_base(void);
/* function prototypes */
t_stat i2716_attach (UNIT *uptr, char *cptr);
t_stat i2716_reset (DEVICE *dptr);
int32 i2716_get_mbyte(int32 offset);
/* SIMH EPROM Standard I/O Data Structures */
UNIT i2716_unit[] = {
{ UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 },
{ UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 },
{ UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 },
{ UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 }
};
MTAB i2716_mod[] = {
{ 0 }
};
DEBTAB i2716_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE i2716_dev = {
"I2716", /* name */
i2716_unit, /* units */
NULL, /* registers */
i2716_mod, /* modifiers */
I2716_NUM, /* numunits */
16, /* aradix */
32, /* awidth */
1, /* aincr */
16, /* dradix */
8, /* dwidth */
NULL, /* examine */
NULL, /* deposit */
&i2716_reset, /* reset */
NULL, /* boot */
&i2716_attach, /* attach */
NULL, /* detach */
NULL, /* ctxt */
DEV_DEBUG, /* flags */
0, /* dctrl */
i2716_debug, /* debflags */
NULL, /* msize */
NULL /* lname */
};
/* global variables */
/* i2716_attach - attach file to EPROM unit
force EPROM reset at completion */
t_stat i2716_attach (UNIT *uptr, char *cptr)
{
int32 j, c;
t_stat r;
FILE *fp;
if (i2716_dev.dctrl & DEBUG_flow)
printf("i2716_attach: cptr=%s\n", cptr);
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
if (i2716_dev.dctrl & DEBUG_flow)
printf("i2716_attach: Error\n");
return r;
}
if (i2716_dev.dctrl & DEBUG_read)
printf("\tOpen file\n");
fp = fopen(uptr->filename, "rb"); /* open EPROM file */
if (fp == NULL) {
printf("i2716%d: Unable to open ROM file %s\n", uptr - i2716_dev.units, uptr->filename);
printf("\tNo ROM image loaded!!!\n");
return SCPE_OK;
}
if (i2716_dev.dctrl & DEBUG_read)
printf("\tRead file\n");
j = 0; /* load EPROM file */
c = fgetc(fp);
while (c != EOF) {
*(uint8 *)(uptr->filebuf + j++) = c & 0xFF;
c = fgetc(fp);
if (j > 2048) {
printf("\tImage is too large - Load truncated!!!\n");
break;
}
}
if (i2716_dev.dctrl & DEBUG_read)
printf("\tClose file\n");
fclose(fp);
// printf("i2716%d: %d bytes of ROM image %s loaded\n",uptr - i2716_dev.units, j, uptr->filename);
if (i2716_dev.dctrl & DEBUG_flow)
printf("i2716_attach: Done\n");
return SCPE_OK;
}
/* EPROM reset */
t_stat i2716_reset (DEVICE *dptr)
{
int32 i, j, c, base;
t_stat r;
UNIT *uptr;
if (i2716_dev.dctrl & DEBUG_flow)
printf("i2716_reset: \n");
for (i = 0; i < I2716_NUM; i++) { /* init all units */
uptr = i2716_dev.units + i;
if (i2716_dev.dctrl & DEBUG_flow)
printf("i2716 %d unit.flags=%08X\n", i, uptr->flags);
uptr->capac = 2048;
uptr->u3 = 2048 * i;
base = get_base();
if (uptr->filebuf == NULL) { /* no buffer allocated */
uptr->filebuf = malloc(2048); /* allocate EPROM buffer */
if (uptr->filebuf == NULL) {
if (i2716_dev.dctrl & DEBUG_flow)
printf("i2716_reset: Malloc error\n");
return SCPE_MEM;
}
}
if (base == 0) {
// printf("i2716%d: Not enabled on MP-A2\n", i);
continue;
}
// printf("i2716%d: Initializing [%04X-%04XH]\n",
// i, base+uptr->u3, base+uptr->u3 + uptr->capac);
// if ((uptr->flags & UNIT_ATT) == 0) {
// printf("i2716%d: No file attached\n", i);
// }
}
if (i2716_dev.dctrl & DEBUG_flow)
printf("i2716_reset: Done\n");
return SCPE_OK;
}
/* I/O instruction handlers, called from the CPU module when an
EPROM memory read or write is issued.
*/
/* get a byte from memory */
int32 i2716_get_mbyte(int32 offset)
{
int32 i, val, org, len;
UNIT *uptr;
for (i = 0; i < I2716_NUM; i++) { /* find addressed unit */
uptr = i2716_dev.units + i;
org = uptr->u3;
len = uptr->capac - 1;
if ((offset >= org) && (offset < (org + len))) {
if (uptr->filebuf == NULL) {
if (i2716_dev.dctrl & DEBUG_read)
printf("i2716_get_mbyte: EPROM not configured\n");
return 0xFF;
} else {
val = *(uint8 *)(uptr->filebuf + (offset - org));
if (i2716_dev.dctrl & DEBUG_read)
printf(" val=%04X\n", val);
return (val & 0xFF);
}
}
}
if (i2716_dev.dctrl & DEBUG_read)
printf("i2716_get_mbyte: Out of range\n");
return 0xFF;
}
/* end of i2716.c */

2020
swtp6800/common/m6800.c Normal file

File diff suppressed because it is too large Load diff

146
swtp6800/common/m6810.c Normal file
View file

@ -0,0 +1,146 @@
/* m6810.c: Motorola m6810 RAM emulator
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 m6810 RAM device on a CPU board. The
byte get and put routines use an offset into the RAM image to locate the
proper byte. This allows another device to set the base address for the
M6810.
*/
#include <stdio.h>
#include "swtp_defs.h"
/* function prototypes */
t_stat m6810_reset (DEVICE *dptr);
int32 m6810_get_mbyte(int32 offset);
void m6810_put_mbyte(int32 offset, int32 val);
/* SIMH RAM Standard I/O Data Structures */
UNIT m6810_unit = { UDATA (NULL, UNIT_BINK, 128),
0 };
MTAB m6810_mod[] = {
{ 0 }
};
DEBTAB m6810_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE m6810_dev = {
"M6810", //name
&m6810_unit, //units
NULL, //registers
m6810_mod, //modifiers
1, //numunits
16, //aradix
32, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
&m6810_reset, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
m6810_debug, //debflags
NULL, //msize
NULL //lname
};
/* global variables */
/* m6810_reset */
t_stat m6810_reset (DEVICE *dptr)
{
if (m6810_dev.dctrl & DEBUG_flow)
printf("m6810_reset: \n");
if (m6810_unit.filebuf == NULL) {
m6810_unit.filebuf = malloc(128);
if (m6810_unit.filebuf == NULL) {
printf("m6810_reset: Malloc error\n");
return SCPE_MEM;
}
m6810_unit.capac = 128;
}
if (m6810_dev.dctrl & DEBUG_flow)
printf("m6810_reset: Done\n");
return SCPE_OK;
}
/* I/O instruction handlers, called from the CPU module when an
RAM memory read or write is issued.
*/
/* get a byte from memory - from offset from start of RAM*/
int32 m6810_get_mbyte(int32 offset)
{
int32 val, org, len;
if (m6810_dev.dctrl & DEBUG_read)
printf("m6810_get_mbyte: offset=%04X\n", offset);
if (offset < m6810_unit.capac) {
val = *(uint8 *)(m6810_unit.filebuf + offset) & 0xFF;
if (m6810_dev.dctrl & DEBUG_read)
printf("val=%04X\n", val);
return val;
} else {
if (m6810_dev.dctrl & DEBUG_read)
printf("m6810_get_mbyte: out of range\n");
return 0xFF;
}
}
/* put a byte to memory */
void m6810_put_mbyte(int32 offset, int32 val)
{
if (m6810_dev.dctrl & DEBUG_write)
printf("m6810_put_mbyte: offset=%04X, val=%02X\n", offset, val);
if (offset < m6810_unit.capac) {
*(uint8 *)(m6810_unit.filebuf + offset) = val & 0xFF;
return;
} else {
if (m6810_dev.dctrl & DEBUG_write)
printf("m6810_put_mbyte: out of range\n");
return;
}
}
/* end of m6810.c */

209
swtp6800/common/mp-8m.c Normal file
View file

@ -0,0 +1,209 @@
/* mp-8m.c: SWTP 8K Byte Memory Card emulator
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 6 simulated MP-8M memory cards on an SS-50 system.
Each unit uses a dynamically allocated 8192 byte buffer to hold the data.
Each unit contains the base address in mp_8m_unit.u3. The unit capacity is
held in mp_8m_unit.capac. Each unit can be enabled or disabled to reconfigure
the RAM for the system.
*/
#include <stdio.h>
#include "swtp_defs.h"
#define MP_8M_NUM 6 /* number of MP-*m boards */
/* prototypes */
t_stat mp_8m_reset (DEVICE *dptr);
int32 mp_8m_get_mbyte(int32 addr);
int32 mp_8m_get_mword(int32 addr);
void mp_8m_put_mbyte(int32 addr, int32 val);
void mp_8m_put_mword(int32 addr, int32 val);
/* isbc064 Standard I/O Data Structures */
UNIT mp_8m_unit[] = {
{ UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
{ UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
{ UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
{ UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
{ UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 },
{ UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 }
};
MTAB mp_8m_mod[] = {
{ 0 }
};
DEBTAB mp_8m_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE mp_8m_dev = {
"MP-8M", //name
mp_8m_unit, //units
NULL, //registers
mp_8m_mod, //modifiers
MP_8M_NUM, //numunits
16, //aradix
8, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposite
&mp_8m_reset, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
mp_8m_debug, //debflags
NULL, //msize
NULL //lname
};
/* Reset routine */
t_stat mp_8m_reset (DEVICE *dptr)
{
int32 i, j, val;
UNIT *uptr;
if (mp_8m_dev.dctrl & DEBUG_flow)
printf("mp_8m_reset: \n");
for (i = 0; i < MP_8M_NUM; i++) { /* init all units */
uptr = mp_8m_dev.units + i;
if (mp_8m_dev.dctrl & DEBUG_flow)
printf("MP-8M %d unit.flags=%08X\n", i, uptr->flags);
uptr->capac = 0x2000;
if (i < 4)
uptr->u3 = 0x2000 * i;
else
uptr->u3 = 0x2000 * (i + 1);
if (uptr->filebuf == NULL) {
uptr->filebuf = malloc(0x2000);
if (uptr->filebuf == NULL) {
printf("mp_8m_reset: Malloc error\n");
return SCPE_MEM;
}
for (j=0; j<8192; j++) { /* fill pattern for testing */
val = (0xA0 | i);
*(uint8 *)(uptr->filebuf + j) = val & 0xFF;
}
}
if (mp_8m_dev.dctrl & DEBUG_flow)
printf("MP-8M %d initialized at [%04X-%04XH]\n", i, uptr->u3,
uptr->u3 + uptr->capac - 1);
}
if (mp_8m_dev.dctrl & DEBUG_flow)
printf("mp_8m_reset: Done\n");
return SCPE_OK;
}
/* I/O instruction handlers, called from the mp-b2 module when an
external memory read or write is issued.
*/
/* get a byte from memory */
int32 mp_8m_get_mbyte(int32 addr)
{
int32 val, org, len;
int32 i;
UNIT *uptr;
if (mp_8m_dev.dctrl & DEBUG_read)
printf("mp_8m_get_mbyte: addr=%04X", addr);
for (i = 0; i < MP_8M_NUM; i++) { /* find addressed unit */
uptr = mp_8m_dev.units + i;
org = uptr->u3;
len = uptr->capac - 1;
if ((addr >= org) && (addr <= org + len)) {
val = *(uint8 *)(uptr->filebuf + (addr - org));
if (mp_8m_dev.dctrl & DEBUG_read)
printf(" val=%04X\n", val);
return (val & 0xFF);
}
}
if (mp_8m_dev.dctrl & DEBUG_read)
printf("mp_8m_get_mbyte: Out of range\n");
return 0xFF; /* multibus has active high pullups */
}
/* get a word from memory */
int32 mp_8m_get_mword(int32 addr)
{
int32 val;
val = (mp_8m_get_mbyte(addr) << 8);
val |= mp_8m_get_mbyte(addr+1);
return val;
}
/* put a byte into memory */
void mp_8m_put_mbyte(int32 addr, int32 val)
{
int32 org, len, type;
int32 i;
UNIT *uptr;
if (mp_8m_dev.dctrl & DEBUG_write)
printf("mp_8m_put_mbyte: addr=%04X, val=%02X", addr, val);
for (i = 0; i < MP_8M_NUM; i++) { /* find addressed unit */
uptr = mp_8m_dev.units + i;
org = uptr->u3;
len = uptr->capac - 1;
if ((addr >= org) && (addr < org + len)) {
*(uint8 *)(uptr->filebuf + (addr - org)) = val & 0xFF;
if (mp_8m_dev.dctrl & DEBUG_write)
printf("\n");
return;
}
}
if (mp_8m_dev.dctrl & DEBUG_write)
printf("mp_8m_put_mbyte: Out of range\n");
}
/* put a word into memory */
void mp_8m_put_mword(int32 addr, int32 val)
{
mp_8m_put_mbyte(addr, val >> 8);
mp_8m_put_mbyte(addr+1, val);
}
/* end of mp-8m.c */

211
swtp6800/common/mp-a.c Normal file
View file

@ -0,0 +1,211 @@
/* mp-a.c: SWTP MP-A M6800 CPU simulator
Copyright (c) 2011, William 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.
The MP-A CPU Board contains the following devices [mp-a.c]:
M6800 processor [m6800.c].
M6810 128 byte RAM at 0xA000 [m6810.c].
M6830, SWTBUG, or custom boot ROM at 0xE000 [bootrom.c].
Interface to the SS-50 bus and the MP-B2 Mother Board for I/O
and memory boards [mp-b2.c].
Note: The file names of the emulator source programs for each device are
contained in "[]".
*/
#include <stdio.h>
#include "swtp_defs.h"
#define UNIT_V_SWT (UNIT_V_UF) /* on SWTBUG, off MIKBUG */
#define UNIT_SWT (1 << UNIT_V_SWT)
#define UNIT_V_RAM (UNIT_V_UF+1) /* off disables 6810 RAM */
#define UNIT_RAM (1 << UNIT_V_RAM)
/* local global variables */
/* function prototypes */
int32 CPU_BD_get_mbyte(int32 addr);
int32 CPU_BD_get_mword(int32 addr);
void CPU_BD_put_mbyte(int32 addr, int32 val);
void CPU_BD_put_mword(int32 addr, int32 val);
/* external routines */
/* MP-B2 bus routines */
extern int32 MB_get_mbyte(int32 addr);
extern int32 MB_get_mword(int32 addr);
extern void MB_put_mbyte(int32 addr, int32 val);
extern void MB_put_mword(int32 addr, int32 val);
/* M6810 bus routines */
extern int32 m6810_get_mbyte(int32 addr);
extern void m6810_put_mbyte(int32 addr, int32 val);
/* BOOTROM bus routines */
extern UNIT BOOTROM_unit;
extern int32 BOOTROM_get_mbyte(int32 offset);
/* MP-A data structures
CPU_BD_dev MP-A2 device descriptor
CPU_BD_unit MP-A2 unit descriptor
CPU_BD_reg MP-A2 register list
CPU_BD_mod MP-A2 modifiers list */
UNIT CPU_BD_unit = { UDATA (NULL, 0, 0) };
REG CPU_BD_reg[] = {
{ NULL }
};
MTAB CPU_BD_mod[] = {
{ UNIT_SWT, UNIT_SWT, "SWT", "SWT", NULL },
{ UNIT_SWT, 0, "NOSWT", "NOSWT", NULL },
{ UNIT_RAM, UNIT_RAM, "RAM", "RAM", NULL },
{ UNIT_RAM, 0, "NORAM", "NORAM", NULL },
{ 0 }
};
DEBTAB CPU_BD_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE CPU_BD_dev = {
"MP-A", //name
&CPU_BD_unit, //units
CPU_BD_reg, //registers
CPU_BD_mod, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
NULL, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
CPU_BD_debug, /* debflags */
NULL, //msize
NULL //lname
};
/* get a byte from memory */
int32 CPU_BD_get_mbyte(int32 addr)
{
int32 val;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: addr=%04X\n", addr);
switch(addr & 0xF000) {
case 0xA000:
if (CPU_BD_unit.flags & UNIT_RAM) {
val = m6810_get_mbyte(addr - 0xA000) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: m6810 val=%02X\n", val);
return val;
} else {
val = MB_get_mbyte(addr) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: m6810 val=%02X\n", val);
return val;
}
case 0xE000:
val = BOOTROM_get_mbyte(addr - 0xE000) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: EPROM=%02X\n", val);
return val;
case 0xF000:
val = BOOTROM_get_mbyte(addr - (0x10000 - BOOTROM_unit.capac)) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: EPROM=%02X\n", val);
return val;
default:
val = MB_get_mbyte(addr) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: mp_b2 val=%02X\n", val);
return val;
}
}
/* get a word from memory */
int32 CPU_BD_get_mword(int32 addr)
{
int32 val;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mword: addr=%04X\n", addr);
val = (CPU_BD_get_mbyte(addr) << 8);
val |= CPU_BD_get_mbyte(addr+1);
val &= 0xFFFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mword: val=%04X\n", val);
return val;
}
/* put a byte to memory */
void CPU_BD_put_mbyte(int32 addr, int32 val)
{
if (CPU_BD_dev.dctrl & DEBUG_write)
printf("CPU_BD_put_mbyte: addr=%04X, val=%02X\n", addr, val);
switch(addr & 0xF000) {
case 0xA000:
if (CPU_BD_unit.flags & UNIT_RAM) {
m6810_put_mbyte(addr - 0xA000, val);
return;
} else {
MB_put_mbyte(addr, val);
return;
}
default:
MB_put_mbyte(addr, val);
return;
}
}
/* put a word to memory */
void CPU_BD_put_mword(int32 addr, int32 val)
{
if (CPU_BD_dev.dctrl & DEBUG_write)
printf("CPU_BD_put_mword: addr=%04X, val=%04X\n", addr, val);
CPU_BD_put_mbyte(addr, val >> 8);
CPU_BD_put_mbyte(addr+1, val);
}
/* end of mp-a.c */

263
swtp6800/common/mp-a2.c Normal file
View file

@ -0,0 +1,263 @@
/* mp-a2.c: SWTP MP-A2 M6800 CPU simulator
Copyright (c) 2011, William 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.
The MP-A2 CPU Board contains the following devices [mp-a2.c]:
M6800 processor [m6800.c].
M6810 128 byte RAM at 0xA000 [m6810.c].
M6830, SWTBUG, or custom boot ROM at 0xE000 [bootrom.c].
4 ea 2716 EPROMs at either 0xC000, 0xC800, 0xD000 and 0xD800 (LO_PROM)or
0xE000, 0xE800, 0xF000 and 0xF800 (HI_PROM) [eprom.c].
Interface to the SS-50 bus and the MP-B2 Mother Board for I/O
and memory boards [mp-b2.c].
Note: The file names of the emulator source programs for each device are
contained in "[]".
*/
#include <stdio.h>
#include "swtp_defs.h"
#define UNIT_V_USER_D (UNIT_V_UF) /* user defined switch */
#define UNIT_USER_D (1 << UNIT_V_USER_D)
#define UNIT_V_4K_8K (UNIT_V_UF+1) /* off if HI_PROM and only 2K EPROM */
#define UNIT_4K_8K (1 << UNIT_V_4K_8K)
#define UNIT_V_SWT (UNIT_V_UF+2) /* on SWTBUG, off MIKBUG */
#define UNIT_SWT (1 << UNIT_V_SWT)
#define UNIT_V_8K (UNIT_V_UF+3) /* off if HI_PROM and only 2K or 4k EPROM */
#define UNIT_8K (1 << UNIT_V_8K)
#define UNIT_V_RAM (UNIT_V_UF+4) /* off disables 6810 RAM */
#define UNIT_RAM (1 << UNIT_V_RAM)
#define UNIT_V_LO_PROM (UNIT_V_UF+5) /* on EPROMS @ C000-CFFFH, off no EPROMS */
#define UNIT_LO_PROM (1 << UNIT_V_LO_PROM)
#define UNIT_V_HI_PROM (UNIT_V_UF+6) /* on EPROMS @ F000-FFFFH, off fo LO_PROM, MON, or no EPROMS */
#define UNIT_HI_PROM (1 << UNIT_V_HI_PROM)
#define UNIT_V_MON (UNIT_V_UF+7) /* on for monitor vectors in high memory */
#define UNIT_MON (1 << UNIT_V_MON)
/* local global variables */
/* function prototypes */
int32 get_base(void);
int32 CPU_BD_get_mbyte(int32 addr);
int32 CPU_BD_get_mword(int32 addr);
void CPU_BD_put_mbyte(int32 addr, int32 val);
void CPU_BD_put_mword(int32 addr, int32 val);
/* external routines */
/* MP-B2 bus routines */
extern int32 MB_get_mbyte(int32 addr);
extern int32 MB_get_mword(int32 addr);
extern void MB_put_mbyte(int32 addr, int32 val);
extern void MB_put_mword(int32 addr, int32 val);
/* M6810 bus routines */
extern int32 m6810_get_mbyte(int32 addr);
extern void m6810_put_mbyte(int32 addr, int32 val);
/* BOOTROM bus routines */
extern UNIT BOOTROM_unit;
extern int32 BOOTROM_get_mbyte(int32 offset);
/* I2716 bus routines */
extern int32 i2716_get_mbyte(int32 offset);
/* MP-A2 data structures
CPU_BD_dev MP-A2 device descriptor
CPU_BD_unit MP-A2 unit descriptor
CPU_BD_reg MP-A2 register list
CPU_BD_mod MP-A2 modifiers list */
UNIT CPU_BD_unit = { UDATA (NULL, 0, 0) };
REG CPU_BD_reg[] = {
{ NULL }
};
MTAB CPU_BD_mod[] = {
{ UNIT_USER_D, UNIT_USER_D, "USER_D", "USER_D", NULL },
{ UNIT_USER_D, 0, "NOUSER_D", "NOUSER_D", NULL },
{ UNIT_4K_8K, UNIT_4K_8K, "4K_8K", "4K_8K", NULL },
{ UNIT_4K_8K, 0, "NO4K_8K", "NO4K_8K", NULL },
{ UNIT_SWT, UNIT_SWT, "SWT", "SWT", NULL },
{ UNIT_SWT, 0, "NOSWT", "NOSWT", NULL },
{ UNIT_8K, UNIT_8K, "8K", "8K", NULL },
{ UNIT_8K, 0, "NO8K", "NO8K", NULL },
{ UNIT_RAM, UNIT_RAM, "RAM", "RAM", NULL },
{ UNIT_RAM, 0, "NORAM", "NORAM", NULL },
{ UNIT_LO_PROM, UNIT_LO_PROM, "LO_PROM", "LO_PROM", NULL },
{ UNIT_LO_PROM, 0, "NOLO_PROM", "NOLO_PROM", NULL },
{ UNIT_HI_PROM, UNIT_HI_PROM, "HI_PROM", "HI_PROM", NULL },
{ UNIT_HI_PROM, 0, "NOHI_PROM", "NOHI_PROM", NULL },
{ UNIT_MON, UNIT_MON, "MON", "MON", NULL },
{ UNIT_MON, 0, "NOMON", "NOMON", NULL },
{ 0 }
};
DEBTAB CPU_BD_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE CPU_BD_dev = {
"MP-A2", //name
&CPU_BD_unit, //units
CPU_BD_reg, //registers
CPU_BD_mod, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
NULL, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
CPU_BD_debug, /* debflags */
NULL, //msize
NULL //lname
};
/* get base address of 2716's */
int32 get_base(void)
{
if (CPU_BD_unit.flags & UNIT_LO_PROM)
return 0xC000;
else if (CPU_BD_unit.flags & UNIT_HI_PROM)
return 0xF000;
return 0;
}
/* get a byte from memory */
int32 CPU_BD_get_mbyte(int32 addr)
{
int32 val;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: addr=%04X\n", addr);
switch(addr & 0xF000) {
case 0xA000:
if (CPU_BD_unit.flags & UNIT_RAM) {
val = m6810_get_mbyte(addr - 0xA000) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: m6810 val=%02X\n", val);
return val;
} else {
val = MB_get_mbyte(addr) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: m6810 val=%02X\n", val);
return val;
}
case 0xC000:
if (CPU_BD_unit.flags & UNIT_LO_PROM) {
val = i2716_get_mbyte(addr - 0xC000) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: 2716=%02X\n", val);
return val;
} else
return 0xFF;
break;
case 0xE000:
val = BOOTROM_get_mbyte(addr - 0xE000) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: EPROM=%02X\n", val);
return val;
case 0xF000:
if (CPU_BD_unit.flags & UNIT_MON) {
val = BOOTROM_get_mbyte(addr - (0x10000 - BOOTROM_unit.capac)) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: EPROM=%02X\n", val);
return val;
}
default:
val = MB_get_mbyte(addr) & 0xFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mbyte: mp_b2 val=%02X\n", val);
return val;
}
}
/* get a word from memory */
int32 CPU_BD_get_mword(int32 addr)
{
int32 val;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mword: addr=%04X\n", addr);
val = (CPU_BD_get_mbyte(addr) << 8);
val |= CPU_BD_get_mbyte(addr+1);
val &= 0xFFFF;
if (CPU_BD_dev.dctrl & DEBUG_read)
printf("CPU_BD_get_mword: val=%04X\n", val);
return val;
}
/* put a byte to memory */
void CPU_BD_put_mbyte(int32 addr, int32 val)
{
if (CPU_BD_dev.dctrl & DEBUG_write)
printf("CPU_BD_put_mbyte: addr=%04X, val=%02X\n", addr, val);
switch(addr & 0xF000) {
case 0xA000:
if (CPU_BD_unit.flags & UNIT_RAM) {
m6810_put_mbyte(addr - 0xA000, val);
return;
} else {
MB_put_mbyte(addr, val);
return;
}
default:
MB_put_mbyte(addr, val);
return;
}
}
/* put a word to memory */
void CPU_BD_put_mword(int32 addr, int32 val)
{
if (CPU_BD_dev.dctrl & DEBUG_write)
printf("CPU_BD_put_mword: addr=%04X, val=%04X\n", addr, val);
CPU_BD_put_mbyte(addr, val >> 8);
CPU_BD_put_mbyte(addr+1, val);
}
/* end of mp-a2.c */

322
swtp6800/common/mp-b2.c Normal file
View file

@ -0,0 +1,322 @@
/* mp-b2.c: SWTP SS-50/SS-30 MP-B2 Mother Board
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.
*/
#include <stdio.h>
#include "swtp_defs.h"
#define UNIT_V_RAM_0000 (UNIT_V_UF) /* MP-8M board 0 enable */
#define UNIT_RAM_0000 (1 << UNIT_V_RAM_0000)
#define UNIT_V_RAM_2000 (UNIT_V_UF+1) /* MP-8M board 1 enable */
#define UNIT_RAM_2000 (1 << UNIT_V_RAM_2000)
#define UNIT_V_RAM_4000 (UNIT_V_UF+2) /* MP-8M board 2 enable */
#define UNIT_RAM_4000 (1 << UNIT_V_RAM_4000)
#define UNIT_V_RAM_6000 (UNIT_V_UF+3) /* MP-8M board 3 enable */
#define UNIT_RAM_6000 (1 << UNIT_V_RAM_6000)
#define UNIT_V_RAM_A000 (UNIT_V_UF+4) /* MP-8M board 4 enable */
#define UNIT_RAM_A000 (1 << UNIT_V_RAM_A000)
#define UNIT_V_RAM_C000 (UNIT_V_UF+5) /* MP-8M board 5 enable */
#define UNIT_RAM_C000 (1 << UNIT_V_RAM_C000)
/* function prototypes */
/* empty I/O device routine */
int32 nulldev(int32 io, int32 data);
/* SS-50 bus routines */
int32 MB_get_mbyte(int32 addr);
int32 MB_get_mword(int32 addr);
void MB_put_mbyte(int32 addr, int32 val);
void MB_put_mword(int32 addr, int32 val);
/* MP-8M bus routines */
extern int32 mp_8m_get_mbyte(int32 addr);
extern void mp_8m_put_mbyte(int32 addr, int32 val);
/* SS-50 I/O address space functions */
/* MP-S serial I/O routines */
extern int32 sio0s(int32 io, int32 data);
extern int32 sio0d(int32 io, int32 data);
extern int32 sio1s(int32 io, int32 data);
extern int32 sio1d(int32 io, int32 data);
/* DC-4 FDC I/O routines */
extern int32 fdcdrv(int32 io, int32 data);
extern int32 fdccmd(int32 io, int32 data);
extern int32 fdctrk(int32 io, int32 data);
extern int32 fdcsec(int32 io, int32 data);
extern int32 fdcdata(int32 io, int32 data);
/* This is the I/O configuration table. There are 32 possible
device addresses, if a device is plugged into a port it's routine
address is here, 'nulldev' means no device is available
*/
struct idev {
int32 (*routine)();
};
struct idev dev_table[32] = {
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 0 8000-8003 */
{&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /*Port 1 8004-8007 */
/* sio1x routines just return the last value read on the matching
sio0x routine. SWTBUG tests for the MP-C with most port reads! */
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 2 8008-800B*/
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 3 800C-800F*/
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 4 8010-8013*/
{&fdcdrv}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 5 8014-8017*/
{&fdccmd}, {&fdctrk}, {&fdcsec}, {&fdcdata}, /*Port 6 8018-801B*/
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /*Port 7 801C-801F*/
};
/* dummy i/o device */
int32 nulldev(int32 io, int32 data)
{
if (io == 0)
return (0xFF);
return 0;
}
/* Mother Board data structures
MB_dev Mother Board device descriptor
MB_unit Mother Board unit descriptor
MB_reg Mother Board register list
MB_mod Mother Board modifiers list
*/
UNIT MB_unit = {
UDATA (NULL, 0, 0)
};
REG MB_reg[] = {
{ NULL }
};
MTAB MB_mod[] = {
{ UNIT_RAM_0000, UNIT_RAM_0000, "BD0 On", "BD0", NULL },
{ UNIT_RAM_0000, 0, "BD0 Off", "NOBD0", NULL },
{ UNIT_RAM_2000, UNIT_RAM_2000, "BD1 On", "BD1", NULL },
{ UNIT_RAM_2000, 0, "BD1 Off", "NOBD1", NULL },
{ UNIT_RAM_4000, UNIT_RAM_4000, "BD2 On", "BD2", NULL },
{ UNIT_RAM_4000, 0, "BD2 Off", "NOBD2", NULL },
{ UNIT_RAM_6000, UNIT_RAM_6000, "BD3 On", "BD3", NULL },
{ UNIT_RAM_6000, 0, "BD3 Off", "NOBD3", NULL },
{ UNIT_RAM_A000, UNIT_RAM_A000, "BD4 On", "BD4", NULL },
{ UNIT_RAM_A000, 0, "BD4 Off", "NOBD4", NULL },
{ UNIT_RAM_C000, UNIT_RAM_C000, "BD5 On", "BD5", NULL },
{ UNIT_RAM_C000, 0, "BD5 Off", "NOBD5", NULL },
{ 0 }
};
DEBTAB MB_debug[] = {
{ "ALL", DEBUG_all },
{ "FLOW", DEBUG_flow },
{ "READ", DEBUG_read },
{ "WRITE", DEBUG_write },
{ "LEV1", DEBUG_level1 },
{ "LEV2", DEBUG_level2 },
{ NULL }
};
DEVICE MB_dev = {
"MP-B2", //name
&MB_unit, //units
MB_reg, //registers
MB_mod, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
NULL, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
MB_debug, /* debflags */
NULL, //msize
NULL //lname
};
/* get a byte from memory */
int32 MB_get_mbyte(int32 addr)
{
int32 val;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mbyte: addr=%04X\n", addr);
switch(addr & 0xF000) {
case 0x0000:
case 0x1000:
if (MB_unit.flags & UNIT_RAM_0000) {
val = mp_8m_get_mbyte(addr) & 0xFF;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mbyte: mp_8m val=%02X\n", val);
return val;
} else
return 0xFF;
case 0x2000:
case 0x3000:
if (MB_unit.flags & UNIT_RAM_2000) {
val = mp_8m_get_mbyte(addr) & 0xFF;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mbyte: mp_8m val=%02X\n", val);
return val;
} else
return 0xFF;
case 0x4000:
case 0x5000:
if (MB_unit.flags & UNIT_RAM_4000) {
val = mp_8m_get_mbyte(addr) & 0xFF;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mbyte: mp_8m val=%02X\n", val);
return val;
} else
return 0xFF;
case 0x6000:
case 0x7000:
if (MB_unit.flags & UNIT_RAM_6000) {
val = mp_8m_get_mbyte(addr) & 0xFF;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mbyte: mp_8m val=%02X\n", val);
return val;
} else
return 0xFF;
case 0x8000:
val = (dev_table[addr - 0x8000].routine(0, 0)) & 0xFF;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mbyte: I/O addr=%04X val=%02X\n", addr, val);
return val;
case 0xA000:
case 0xB000:
if (MB_unit.flags & UNIT_RAM_A000) {
val = mp_8m_get_mbyte(addr) & 0xFF;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mbyte: mp_8m val=%02X\n", val);
return val;
} else
return 0xFF;
case 0xC000:
case 0xD000:
if (MB_unit.flags & UNIT_RAM_C000) {
val = mp_8m_get_mbyte(addr) & 0xFF;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mbyte: mp_8m val=%02X\n", val);
return val;
} else
return 0xFF;
default:
return 0xFF;
}
}
/* get a word from memory */
int32 MB_get_mword(int32 addr)
{
int32 val;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mword: addr=%04X\n", addr);
val = (MB_get_mbyte(addr) << 8);
val |= MB_get_mbyte(addr+1);
val &= 0xFFFF;
if (MB_dev.dctrl & DEBUG_read)
printf("MB_get_mword: val=%04X\n", val);
return val;
}
/* put a byte to memory */
void MB_put_mbyte(int32 addr, int32 val)
{
if (MB_dev.dctrl & DEBUG_write)
printf("MB_put_mbyte: addr=%04X, val=%02X\n", addr, val);
switch(addr & 0xF000) {
case 0x0000:
case 0x1000:
if (MB_unit.flags & UNIT_RAM_0000) {
mp_8m_put_mbyte(addr, val);
return;
}
case 0x2000:
case 0x3000:
if (MB_unit.flags & UNIT_RAM_2000) {
mp_8m_put_mbyte(addr, val);
return;
}
case 0x4000:
case 0x5000:
if (MB_unit.flags & UNIT_RAM_4000) {
mp_8m_put_mbyte(addr, val);
return;
}
case 0x6000:
case 0x7000:
if (MB_unit.flags & UNIT_RAM_6000) {
mp_8m_put_mbyte(addr, val);
return;
}
case 0x8000:
dev_table[addr - 0x8000].routine(1, val);
return;
case 0xA000:
case 0xB000:
if (MB_unit.flags & UNIT_RAM_A000) {
mp_8m_put_mbyte(addr, val);
return;
}
case 0xC000:
case 0xD000:
if (MB_unit.flags & UNIT_RAM_C000) {
mp_8m_put_mbyte(addr, val);
return;
}
default:
return;
}
}
/* put a word to memory */
void MB_put_mword(int32 addr, int32 val)
{
if (MB_dev.dctrl & DEBUG_write)
printf("MB_ptt_mword: addr=%04X, val=%04X\n", addr, val);
MB_put_mbyte(addr, val >> 8);
MB_put_mbyte(addr+1, val);
}
/* end of mp-b2.c */

330
swtp6800/common/mp-s.c Normal file
View file

@ -0,0 +1,330 @@
/* mp-s.c: SWTP MP-S serial I/O card emulator
Copyright (c) 2005-2011, William 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
Willaim 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 SWTP MP-S interface card.
The card contains one M6850 ACIA. The ACIA implements one complete
serial port. It provides 7 or 8-bit ASCII RS-232 interface to Terminals
or 20 mA current loop interface to a model 33 or 37 Teletype. It is not
compatible with baudot Teletypes. Baud rates from 110 to 1200 are
switch selectable from S! on the MP-S. The ACIA ports appear at all
4 addresses. This fact is used by SWTBUG to determine the presence of the
MP-S vice MP-C serial card. The ACIA interrupt request line can be connected
to the IRQ or NMI interrupt lines by a jumper on the MP-S.
All I/O is via either programmed I/O or interrupt controlled I/O.
It has a status port and a data port. A write to the status port
can select some options for the device (0x03 will reset the port).
A read of the status port gets the port status:
+---+---+---+---+---+---+---+---+
| I | P | O | F |CTS|DCD|TXE|RXF|
+---+---+---+---+---+---+---+---+
RXF - A 1 in this bit position means a character has been received
on the data port and is ready to be read.
TXE - A 1 in this bit means the port is ready to receive a character
on the data port and transmit it out over the serial line.
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 <ctype.h>
#include "swtp_defs.h"
#define UNIT_V_TTY (UNIT_V_UF) // TTY or ANSI mode
#define UNIT_TTY (1 << UNIT_V_TTY)
/* local global variables */
int32 ptr_stopioe = 0; // stop on error
int32 ptp_stopioe = 0; // stop on error
int32 odata;
int32 status;
int32 ptp_flag = 0;
int32 ptr_flag = 0;
/* function prototypes */
t_stat sio_svc (UNIT *uptr);
t_stat ptr_svc (UNIT *uptr);
t_stat ptp_svc (UNIT *uptr);
t_stat sio_reset (DEVICE *dptr);
t_stat ptr_reset (DEVICE *dptr);
t_stat ptp_reset (DEVICE *dptr);
int32 sio0s(int32 io, int32 data);
int32 sio0d(int32 io, int32 data);
int32 sio1s(int32 io, int32 data);
int32 sio1d(int32 io, int32 data);
/* sio data structures
sio_dev SIO device descriptor
sio_unit SIO unit descriptor
sio_reg SIO register list
sio_mod SIO modifiers list */
UNIT sio_unit = { UDATA (&sio_svc, 0, 0), KBD_POLL_WAIT
};
REG sio_reg[] = {
{ ORDATA (DATA, sio_unit.buf, 8) },
{ ORDATA (STAT, sio_unit.u3, 8) },
{ NULL }
};
MTAB sio_mod[] = {
{ UNIT_TTY, UNIT_TTY, "TTY", "TTY", NULL },
{ UNIT_TTY, 0, "ANSI", "ANSI", NULL },
{ 0 }
};
DEVICE sio_dev = {
"MP-S", &sio_unit, sio_reg, sio_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &sio_reset,
NULL, NULL, NULL
};
/* paper tape reader data structures
ptr_dev PTR device descriptor
ptr_unit PTR unit descriptor
ptr_reg PTR register list
ptr_mod PTR modifiers list */
UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE, 0), KBD_POLL_WAIT
};
DEVICE ptr_dev = {
"PTR", &ptr_unit, NULL, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptr_reset,
NULL, NULL, NULL
};
/* paper tape punch data structures
ptp_dev PTP device descriptor
ptp_unit PTP unit descriptor
ptp_reg PTP register list
ptp_mod PTP modifiers list */
UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0), KBD_POLL_WAIT
};
DEVICE ptp_dev = {
"PTP", &ptp_unit, NULL, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptp_reset,
NULL, NULL, NULL
};
/* console input service routine */
int32 sio_svc (UNIT *uptr)
{
int32 temp;
sim_activate (&sio_unit, sio_unit.wait); // continue poll
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG)
return temp; // no char or error?
sio_unit.buf = temp & 0xFF; // Save char
sio_unit.u3 |= 0x01; // Set RXF flag
/* Do any special character handling here */
sio_unit.pos++; // step character count
return SCPE_OK;
}
/* paper tape reader input service routine */
int32 ptr_svc (UNIT *uptr)
{
int32 temp;
sim_activate (&ptr_unit, ptr_unit.wait); // continue poll
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG)
return temp; // no char or error?
ptr_unit.buf = temp & 0xFF; // Save char
ptr_unit.u3 |= 0x01; // Set RXF flag
/* Do any special character handling here */
ptr_unit.pos++; // step character count
return SCPE_OK;
}
/* paper tape punch output service routine */
int32 ptp_svc (UNIT *uptr)
{
return SCPE_OK;
}
/* Reset console */
int32 sio_reset (DEVICE *dptr)
{
sio_unit.buf = 0; // Data buffer
sio_unit.u3 = 0x02; // Status buffer
sim_activate (&sio_unit, sio_unit.wait); // activate unit
return SCPE_OK;
}
/* Reset paper tape reader */
int32 ptr_reset (DEVICE *dptr)
{
ptr_unit.buf = 0;
ptr_unit.u3 = 0x02;
sim_activate (&ptr_unit, ptr_unit.wait); // activate unit
// sim_cancel (&ptr_unit); // deactivate unit
return SCPE_OK;
}
/* Reset paper tape punch */
int32 ptp_reset (DEVICE *dptr)
{
ptp_unit.buf = 0;
ptp_unit.u3 = 0x02;
sim_activate (&ptp_unit, ptp_unit.wait); // activate unit
// sim_cancel (&ptp_unit); // deactivate unit
return SCPE_OK;
}
/* I/O instruction handlers, called from the MP-B2 module when a
read or write occur to addresses 0x8004-0x8007. */
int32 sio0s(int32 io, int32 data)
{
if (io == 0) { // control register read
if (ptr_flag) { // reader enabled?
if ((ptr_unit.flags & UNIT_ATT) == 0) { // attached?
ptr_unit.u3 &= 0xFE; // no, clear RXF flag
ptr_flag = 0; // clear reader flag
printf("Reader not attached to file\n");
} else { // attached
if (feof(ptr_unit.fileref)) { // EOF
ptr_unit.u3 &= 0xFE; // clear RXF flag
ptr_flag = 0; // clear reader flag
} else // not EOF
ptr_unit.u3 |= 0x01; // set ready
}
return (status = ptr_unit.u3); // return ptr status
} else {
return (status = sio_unit.u3); // return console status
}
} else { // control register write
if (data == 0x03) { // reset port!
sio_unit.u3 = 0x02; // reset console
sio_unit.buf = 0;
sio_unit.pos = 0;
ptr_unit.u3 = 0x02; // reset reader
ptr_unit.buf = 0;
ptr_unit.pos = 0;
ptp_unit.u3 = 0x02; // reset punch
ptp_unit.buf = 0;
ptp_unit.pos = 0;
}
return (status = 0); // invalid io
}
}
int32 sio0d(int32 io, int32 data)
{
if (io == 0) { // data register read
if (ptr_flag) { // RDR enabled?
if ((ptr_unit.flags & UNIT_ATT) == 0) // attached?
return 0; // no, done
// printf("ptr_unit.u3=%02X\n", ptr_unit.u3);
if ((ptr_unit.u3 & 0x01) == 0) { // yes, more data?
// printf("Returning old %02X\n", odata); // no, return previous byte
return (odata & 0xFF);
}
if ((odata = getc(ptr_unit.fileref)) == EOF) { // end of file?
// printf("Got EOF\n");
ptr_unit.u3 &= 0xFE; // clear RXF flag
return (odata = 0); // no data
}
// printf("Returning new %02X\n", odata);
ptr_unit.pos++; // step character count
ptr_unit.u3 &= 0xFE; // clear RXF flag
return (odata & 0xFF); // return character
} else {
sio_unit.u3 &= 0xFE; // clear RXF flag
return (odata = sio_unit.buf); // return next char
}
} else { // data register write
if (isprint(data) || data == '\r' || data == '\n') { // printable?
sim_putchar(data); // print character on console
if (ptp_flag && ptp_unit.flags & UNIT_ATT) { // PTP enabled & attached?
putc(data, ptp_unit.fileref);
ptp_unit.pos++; // step character counter
}
} else { // DC1-DC4 control Reader/Punch
switch (data) {
case 0x11: // PTR on
ptr_flag = 1;
ptr_unit.u3 |= 0x01;
// printf("Reader on\n");
break;
case 0x12: // PTP on
ptp_flag = 1;
ptp_unit.u3 |= 0x02;
// printf("Punch on\n");
break;
case 0x13: // PTR off
ptr_flag = 0;
// printf("Reader off-%d bytes read\n", ptr_unit.pos);
break;
case 0x14: // PTP off
ptp_flag = 0;
// printf("Punch off-%d bytes written\n", ptp_unit.pos);
break;
default: // ignore all other characters
break;
}
}
}
return (odata = 0);
}
/* because each port appears at 2 addresses and this fact is used
to determine if it is a MP-C or MP-S repeatedly in the SWTBUG
monitor, this code assures that reads of the high ports return
the same data as was read the last time on the low ports.
*/
int32 sio1s(int32 io, int32 data)
{
return status;
}
int32 sio1d(int32 io, int32 data)
{
return odata;
}
/* end of mp-s.c */

View file

@ -0,0 +1,87 @@
/* mp-a_sys.c: SWTP 6800 system interface
Copyright (c) 2005, William 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.
*/
#include <ctype.h>
#include <string.h>
#include "swtp_defs.h"
/* externals */
extern DEVICE CPU_BD_dev;
extern DEVICE m6800_dev;
extern REG m6800_reg[];
extern DEVICE BOOTROM_dev;
extern DEVICE m6810_dev;
extern DEVICE i2716_dev;
extern DEVICE MB_dev;
extern DEVICE sio_dev;
extern DEVICE ptr_dev;
extern DEVICE ptp_dev;
extern DEVICE mp_8m_dev;
extern DEVICE dsk_dev;
/* 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
sim_load binary loader
*/
char sim_name[] = "SWTP 6800, V2, MP-A2 CPU Board";
REG *sim_PC = &m6800_reg[0];
int32 sim_emax = 4;
DEVICE *sim_devices[] = {
&CPU_BD_dev,
&m6800_dev,
&BOOTROM_dev,
&m6810_dev,
&i2716_dev,
&MB_dev,
&sio_dev,
&ptr_dev,
&ptp_dev,
&mp_8m_dev,
&dsk_dev,
NULL
};
const char *sim_stop_messages[] = {
"Unknown error",
"Unknown I/O Instruction",
"HALT instruction",
"Breakpoint",
"Invalid Opcode",
"Invalid Memory"
};
/* end of mp-a_sys.c */

View file

@ -0,0 +1,85 @@
/* mp-a_sys.c: SWTP 6800 system interface
Copyright (c) 2005, William 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.
*/
#include <ctype.h>
#include <string.h>
#include "swtp_defs.h"
/* externals */
extern DEVICE CPU_BD_dev;
extern DEVICE m6800_dev;
extern REG m6800_reg[];
extern DEVICE BOOTROM_dev;
extern DEVICE m6810_dev;
extern DEVICE MB_dev;
extern DEVICE sio_dev;
extern DEVICE ptr_dev;
extern DEVICE ptp_dev;
extern DEVICE mp_8m_dev;
extern DEVICE dsk_dev;
/* 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
sim_load binary loader
*/
char sim_name[] = "SWTP 6800, V2, MP-A CPU Board";
REG *sim_PC = &m6800_reg[0];
int32 sim_emax = 4;
DEVICE *sim_devices[] = {
&CPU_BD_dev,
&m6800_dev,
&BOOTROM_dev,
&m6810_dev,
&MB_dev,
&sio_dev,
&ptr_dev,
&ptp_dev,
&mp_8m_dev,
&dsk_dev,
NULL
};
const char *sim_stop_messages[] = {
"Unknown error",
"Unknown I/O Instruction",
"HALT instruction",
"Breakpoint",
"Invalid Opcode",
"Invalid Memory"
};
/* end of mp-a_sys.c */

Binary file not shown.

View file

@ -0,0 +1,8 @@
set bootrom 2708
attach bootrom swtbug.bin
set cpu hex
set cpu itrap
set cpu mtrap
reset
set mp-b2 bd0, bd1, bd2, bd3, bd4, bd5
g

View file

@ -0,0 +1,9 @@
set bootrom 2708
attach bootrom swtbug.bin
set mp-a2 mon, lo_prom
set cpu hex
set cpu itrap
set cpu mtrap
reset
set mp-b2 bd0, bd1, bd2, bd3, bd4, bd5
g

View file

@ -1,6 +1,6 @@
/* swtp_defs.h: SWTP 6800 simulator definitions
Copyright (c) 2005, 2007, William Beech
Copyright (c) 2005-2012, William Beech
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -22,25 +22,34 @@ Copyright (c) 2005, 2007, William Beech
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.
Based on work by Charles E Owen (c) 1997 and Peter Schorn (c) 2002-2005
*/
#include "sim_defs.h" // simulator defs
#include <ctype.h>
#include "../../sim_defs.h" // simulator defs
/* Memory */
#define MAXMEMSIZE 65536 // max memory size
#define MEMSIZE (cpu_unit.capac)// actual memory size
#define ADDRMASK (MAXMEMSIZE - 1)// address mask
#define MAXMEMSIZE 65536 // max memory size
#define MEMSIZE (m6800_unit.capac) // actual memory size
#define ADDRMASK (MAXMEMSIZE - 1) // 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-really WAI
#define STOP_IBKPT 3 // breakpoint
#define STOP_OPCODE 4 // invalid opcode
#define STOP_MEMORY 5 // invalid memory address
#define STOP_RSRV 1 // must be 1
#define STOP_HALT 2 // HALT-really WAI
#define STOP_IBKPT 3 // breakpoint
#define STOP_OPCODE 4 // invalid opcode
#define STOP_MEMORY 5 // invalid memory address