Changes to replace the SWTP V1 code with the V2 code
This commit is contained in:
parent
eb60957366
commit
567a304c37
27 changed files with 4757 additions and 3666 deletions
|
@ -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
|
||||
|
|
28
makefile
28
makefile
|
@ -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
BIN
swtp/swtp
Binary file not shown.
100
swtp/swtp.txt
100
swtp/swtp.txt
|
@ -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!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
2293
swtp/swtp_cpu.c
2293
swtp/swtp_cpu.c
File diff suppressed because it is too large
Load diff
506
swtp/swtp_dsk.c
506
swtp/swtp_dsk.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
312
swtp/swtp_sio.c
312
swtp/swtp_sio.c
|
@ -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;
|
||||
}
|
||||
|
425
swtp/swtp_sys.c
425
swtp/swtp_sys.c
|
@ -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
231
swtp6800/common/bootrom.c
Normal 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
571
swtp6800/common/dc-4.c
Normal 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
222
swtp6800/common/i2716.c
Normal 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
2020
swtp6800/common/m6800.c
Normal file
File diff suppressed because it is too large
Load diff
146
swtp6800/common/m6810.c
Normal file
146
swtp6800/common/m6810.c
Normal 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
209
swtp6800/common/mp-8m.c
Normal 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
211
swtp6800/common/mp-a.c
Normal 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
263
swtp6800/common/mp-a2.c
Normal 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
322
swtp6800/common/mp-b2.c
Normal 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
330
swtp6800/common/mp-s.c
Normal 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 */
|
87
swtp6800/swtp6800/mp-a2_sys.c
Normal file
87
swtp6800/swtp6800/mp-a2_sys.c
Normal 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 */
|
85
swtp6800/swtp6800/mp-a_sys.c
Normal file
85
swtp6800/swtp6800/mp-a_sys.c
Normal 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 */
|
BIN
swtp6800/swtp6800/swtbug.bin
Normal file
BIN
swtp6800/swtp6800/swtbug.bin
Normal file
Binary file not shown.
8
swtp6800/swtp6800/swtp6800mp-a.ini
Normal file
8
swtp6800/swtp6800/swtp6800mp-a.ini
Normal 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
|
9
swtp6800/swtp6800/swtp6800mp-a2.ini
Normal file
9
swtp6800/swtp6800/swtp6800mp-a2.ini
Normal 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
|
|
@ -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
|
||||
|
Loading…
Add table
Reference in a new issue