SWTP6800: Update to simulators
- General cleanup of codebase - Fixed condition codes m6800.c from Roberto Sancho Villa - Add additional FDC lfd-400 from Roberto Sancho Villa - Add additional OS's (FLEX 1.0, FDOS 1.0, DOS68, MiniDOS, and MiniDOS-MPX) to software support - Add additional disk formats to software support dc-4.c from Roberto Sancho Villa - Add CPU history - Fix LOAD/DUMP to support binary and hex - Fix fprintf_sym to disassemble 6800 code correctly - Add EXAMINE/DEPOSIT to CPU Memory - Fixed disasm to space the register - Add SET_FLAG(IF) to IRQ – fixed error in handling IRQ from Roberto Sancho Villa
This commit is contained in:
parent
087e0c7bc8
commit
44428e53b6
17 changed files with 1410 additions and 695 deletions
|
@ -199,6 +199,10 @@
|
|||
RelativePath="..\swtp6800\common\dc-4.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\swtp6800\common\fd400.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\swtp6800\common\m6800.c"
|
||||
>
|
||||
|
|
|
@ -199,6 +199,10 @@
|
|||
RelativePath="..\swtp6800\common\dc-4.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\swtp6800\common\fd400.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\swtp6800\common\i2716.c"
|
||||
>
|
||||
|
|
|
@ -739,7 +739,7 @@ SWTP6800MP_A_LIB = $(LIB_DIR)SWTP6800MP-A-$(ARCH).OLB
|
|||
SWTP6800MP_A_SOURCE = $(SWTP6800MP_A_COMMON)mp-a.c,$(SWTP6800MP_A_COMMON)m6800.c,\
|
||||
$(SWTP6800MP_A_COMMON)m6810.c,$(SWTP6800MP_A_COMMON)bootrom.c,$(SWTP6800MP_A_COMMON)dc-4.c,\
|
||||
$(SWTP6800MP_A_COMMON)mp-s.c,$(SWTP6800MP_A_DIR)mp-a_sys.c,$(SWTP6800MP_A_COMMON)mp-b2.c,\
|
||||
$(SWTP6800MP_A_COMMON)mp-8m.c
|
||||
$(SWTP6800MP_A_COMMON)mp-8m.c,$(SWTP6800MP_A_COMMON)fd400.c
|
||||
SWTP6800MP_A_OPTIONS = /INCL=($(SIMH_DIR),$(SWTP6800MP_A_DIR))/DEF=($(CC_DEFS))
|
||||
|
||||
#
|
||||
|
@ -751,7 +751,7 @@ SWTP6800MP_A2_LIB = $(LIB_DIR)SWTP6800MP-A2-$(ARCH).OLB
|
|||
SWTP6800MP_A2_SOURCE = $(SWTP6800MP_A2_COMMON)mp-a2.c,$(SWTP6800MP_A2_COMMON)m6800.c,\
|
||||
$(SWTP6800MP_A2_COMMON)m6810.c,$(SWTP6800MP_A2_COMMON)bootrom.c,$(SWTP6800MP_A2_COMMON)dc-4.c,\
|
||||
$(SWTP6800MP_A2_COMMON)mp-s.c,$(SWTP6800MP_A2_DIR)mp-a2_sys.c,$(SWTP6800MP_A2_COMMON)mp-b2.c,\
|
||||
$(SWTP6800MP_A2_COMMON)mp-8m.c,$(SWTP6800MP_A2_COMMON)i2716.c
|
||||
$(SWTP6800MP_A2_COMMON)mp-8m.c,$(SWTP6800MP_A2_COMMON)i2716.c,,$(SWTP6800MP_A_COMMON)fd400.c
|
||||
SWTP6800MP_A2_OPTIONS = /INCL=($(SIMH_DIR),$(SWTP6800MP_A2_DIR))/DEF=($(CC_DEFS))
|
||||
|
||||
#
|
||||
|
|
Binary file not shown.
10
makefile
10
makefile
|
@ -1806,11 +1806,13 @@ SDS_OPT = -I ${SDSD} -DUSE_SIM_CARD
|
|||
SWTP6800D = ${SIMHD}/swtp6800/swtp6800
|
||||
SWTP6800C = ${SIMHD}/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
|
||||
${SWTP6800C}/bootrom.c ${SWTP6800C}/dc-4.c ${SWTP6800D}/mp-a_sys.c \
|
||||
${SWTP6800C}/mp-8m.c ${SWTP6800C}/fd400.c ${SWTP6800C}/mp-b2.c \
|
||||
${SWTP6800C}/mp-s.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
|
||||
${SWTP6800C}/bootrom.c ${SWTP6800C}/dc-4.c ${SWTP6800D}/mp-a2_sys.c \
|
||||
${SWTP6800C}/mp-8m.c ${SWTP6800C}/i2716.c ${SWTP6800C}/fd400.c \
|
||||
${SWTP6800C}/mp-s.c ${SWTP6800C}/mp-b2.c
|
||||
SWTP6800_OPT = -I ${SWTP6800D}
|
||||
|
||||
INTELSYSD = ${SIMHD}/Intel-Systems
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dc4.c: SWTP DC-4 FDC Simulator
|
||||
/* c: SWTP DC-4 FDC Simulator
|
||||
|
||||
Copyright (c) 2005-2012, William A. Beech
|
||||
|
||||
|
@ -25,7 +25,8 @@
|
|||
|
||||
MODIFICATIONS:
|
||||
|
||||
23 Apr 15 -- Modified to use simh_debug
|
||||
28 May 22 -- Roberto Sancho Villa (RSV) fixes for other disk formats
|
||||
and operating systems.
|
||||
|
||||
NOTES:
|
||||
|
||||
|
@ -186,6 +187,7 @@
|
|||
Writes the 8-bit value to the data register.
|
||||
|
||||
A FLEX disk is defined as follows:
|
||||
(first sector on track is number 1)
|
||||
|
||||
Track Sector Use
|
||||
0 1 Boot sector
|
||||
|
@ -197,7 +199,7 @@
|
|||
1 1 First available data sector
|
||||
last-1 last Last available data sector
|
||||
|
||||
System Identity Record
|
||||
System Identity Record (SIR)
|
||||
|
||||
Byte Use
|
||||
0x00 Two bytes of zeroes (Clears forward link)
|
||||
|
@ -230,15 +232,26 @@
|
|||
|
||||
#define NUM_DISK 4 /* standard 1797 maximum */
|
||||
#define SECT_SIZE 256 /* standard FLEX sector */
|
||||
#define NUM_SECT 72 /* sectors/track */
|
||||
#define NUM_SECT 36 //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 HEADS 2 //handle as DS
|
||||
#define NUM_CYL 80 /* maximum cylinders */
|
||||
#define DSK_SIZE (NUM_SECT * HEADS * NUM_CYL * SECT_SIZE) /* dsk size (bytes) */
|
||||
|
||||
/* SIR offsets */
|
||||
#define MAXCYL 0x26 /* last cylinder # */
|
||||
#define MAXSEC 0x27 /* last sector # */
|
||||
//SIR offsets TK 0, SEC 3
|
||||
|
||||
#define LABEL 0x10 //disk label (11 char)
|
||||
#define VOLNUM 0x1B //volume number (word)
|
||||
#define FSTUSRTRK 0x1D //first user track (byte)
|
||||
#define FSTUSRSEC 0x1E //first user sector (byte)
|
||||
#define LSTUSRTRK 0x1F //last user track (byte)
|
||||
#define LSTUSRSEC 0x20 //last user sector (byte)
|
||||
#define TOTSEC 0x21 //total sectors (word)
|
||||
#define CREMON 0x23 //creation month (byte)
|
||||
#define CREDAY 0x24 //creation day (byte)
|
||||
#define CREYR 0x25 //creation year (byte)
|
||||
#define MAXCYL 0x26 //last cylinder #
|
||||
#define MAXSEC 0x27 //last sector #
|
||||
|
||||
/* 1797 status bits type I commands*/
|
||||
|
||||
|
@ -248,7 +261,7 @@
|
|||
#define SEEKERR 0x10
|
||||
#define CRCERR 0x08
|
||||
#define LOST 0x04
|
||||
#define DRQ 0x02
|
||||
#define INDEX 0x02
|
||||
#define BUSY 0x01
|
||||
|
||||
/* 1797 status bits type II/III commands*/
|
||||
|
@ -265,6 +278,7 @@
|
|||
/* function prototypes */
|
||||
|
||||
t_stat dsk_reset (DEVICE *dptr);
|
||||
t_stat dsk_attach (UNIT *uptr, CONST char *cptr);
|
||||
|
||||
/* SS-50 I/O address space functions */
|
||||
|
||||
|
@ -277,15 +291,20 @@ int32 fdcdata(int32 io, int32 data);
|
|||
/* Local Variables */
|
||||
|
||||
int32 fdcbyte;
|
||||
int32 intrq = 0; /* interrupt request flag */
|
||||
int32 intrq; /* interrupt request flag */
|
||||
int32 cur_dsk; /* Currently selected drive */
|
||||
int32 wrt_flag = 0; /* FDC write flag */
|
||||
int32 wrt_flag; /* 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) */
|
||||
int32 sectsize; // Sector size (bytes)
|
||||
|
||||
int32 multiple_sector; // multiple read-write flag
|
||||
int32 index_countdown; // index countdown for type I commands
|
||||
int32 sector_base; // indicates is first sector on track is sector 1 or sector 0
|
||||
|
||||
/* Floppy Disk Controller data structures
|
||||
|
||||
|
@ -296,10 +315,10 @@ int32 dsksiz; /* dsk size (bytes) */
|
|||
*/
|
||||
|
||||
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) }
|
||||
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }
|
||||
};
|
||||
|
||||
REG dsk_reg[] = {
|
||||
|
@ -336,10 +355,10 @@ DEVICE dsk_dev = {
|
|||
NULL, //deposit
|
||||
&dsk_reset, //reset
|
||||
NULL, //boot
|
||||
NULL, //attach
|
||||
dsk_attach, //attach
|
||||
NULL, //detach
|
||||
NULL, //ctxt
|
||||
DEV_DEBUG, //flags
|
||||
DEV_DISABLE|DEV_DEBUG, //flags
|
||||
0, //dctrl
|
||||
dsk_debug, //debflags
|
||||
NULL, //msize
|
||||
|
@ -350,18 +369,18 @@ DEVICE dsk_dev = {
|
|||
|
||||
t_stat dsk_reset (DEVICE *dptr)
|
||||
{
|
||||
int i;
|
||||
uint32 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");
|
||||
for (i=0; i<dptr->numunits; i++) {
|
||||
dptr->units[i].u3 = NOTRDY; /* current flags = NOTRDY*/
|
||||
dptr->units[i].u4 = 0; /* clear current cylinder # */
|
||||
dptr->units[i].u5 = 0; /* clear current sector # */
|
||||
dptr->units[i].pos = 0; /* clear current byte ptr */
|
||||
if (dptr->units[i].filebuf == NULL) {
|
||||
dptr->units[i].filebuf = calloc(SECT_SIZE, sizeof(uint8)); /* allocate buffer */
|
||||
if (dptr->units[i].filebuf == NULL) {
|
||||
printf("dc-4_reset: Calloc error\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
}
|
||||
|
@ -371,11 +390,31 @@ t_stat dsk_reset (DEVICE *dptr)
|
|||
heds = 0;
|
||||
cpd = 0;
|
||||
dsksiz = 0;
|
||||
//RSV - for hansling multiple disk formats and OSs
|
||||
sectsize = SECT_SIZE;
|
||||
multiple_sector=0;
|
||||
index_countdown=0;
|
||||
sector_base=1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* dsk attach - attach an .IMG file to an FDD */
|
||||
|
||||
t_stat dsk_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
||||
sim_printf("dsk_attach: Attach error %d\n", r);
|
||||
return r;
|
||||
}
|
||||
uptr->u3 &= ~NOTRDY; //reset FDD to ready
|
||||
uptr->capac = sim_fsize(uptr->fileref); //file size
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* I/O instruction handlers, called from the MP-B2 module when a
|
||||
read or write occur to addresses 0x8004-0x8007. */
|
||||
read or write occur to addresses 0x8014-0x801B. */
|
||||
|
||||
/* DC-4 drive select register routine - this register is not part of the 1797
|
||||
*/
|
||||
|
@ -384,47 +423,59 @@ int32 fdcdrv(int32 io, int32 data)
|
|||
{
|
||||
static long pos;
|
||||
static int32 err;
|
||||
uint8 *SIR;
|
||||
int32 disk_image_size;
|
||||
|
||||
if (io) { /* write to DC-4 drive register */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\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 */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Drive set to %d", cur_dsk);
|
||||
dsk_unit[cur_dsk].flags &= ~LOST;
|
||||
if ((dsk_unit[cur_dsk].flags & UNIT_ENABLE) == 0) {
|
||||
dsk_unit[cur_dsk].u3 |= WRPROT; /* set 1797 WPROT */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Drive write protected");
|
||||
} else {
|
||||
dsk_unit[cur_dsk].u3 &= ~WRPROT; /* set 1797 not WPROT */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Drive NOT write protected");
|
||||
}
|
||||
pos = 0x200; /* Read in SIR */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Read pos = %ld ($%04X)",
|
||||
pos, (unsigned int) pos);
|
||||
err = sim_fseek(dsk_unit[cur_dsk].fileref, pos, SEEK_SET); /* seek to offset */
|
||||
if (err) {
|
||||
sim_printf("\nfdccmd: Seek error read in SIR\n");
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
err = sim_fread(dsk_unit[cur_dsk].filebuf, SECT_SIZE, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
|
||||
if (err != 1) {
|
||||
sim_printf("\nfdccmd: File error read in SIR\n");
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
if (io) { // write to DC-4 drive register
|
||||
if (cur_dsk == (data & 0x03)) // already selected?
|
||||
return 0; //yes
|
||||
cur_dsk = data & 0x03; // only 2 drive select bits/
|
||||
dsk_unit[cur_dsk].u3 &= ~LOST; //RSV - reset LOST flag
|
||||
if ((dsk_unit[cur_dsk].flags & UNIT_ENABLE) == 0) //RO?
|
||||
dsk_unit[cur_dsk].u3 |= WRPROT; /* Set WPROT */
|
||||
else
|
||||
dsk_unit[cur_dsk].u3 &= ~WRPROT; /* SET not WPROT */
|
||||
if (dsk_unit[cur_dsk].fileref == 0) // no file attached
|
||||
return 0;
|
||||
/* RSV - Read in SIR */
|
||||
pos = 0x200;
|
||||
sim_fseek(dsk_unit[cur_dsk].fileref, pos, SEEK_SET); /* seek to SIR */
|
||||
sim_fread(dsk_unit[cur_dsk].filebuf, SECT_SIZE, 1, dsk_unit[cur_dsk].fileref); /* read in SIR */
|
||||
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 * SECT_SIZE;
|
||||
SIR = (uint8 * )(dsk_unit[cur_dsk].filebuf);
|
||||
// detect disk type based on image geometry or SIR record
|
||||
disk_image_size = sim_fsize(dsk_unit[cur_dsk].fileref); //get actual file size
|
||||
if (disk_image_size == 35 * 10 * 256) { // 89600 bytes -> FDOS image
|
||||
// FDOS disc has no SIR record.
|
||||
spt = 10; // 10 sectors
|
||||
cpd = 35; // 35 tracks
|
||||
sectsize = 256;
|
||||
sector_base = 0; // first sector in track is number ZERO
|
||||
} else if (disk_image_size == 35 * 18 * 128) { // 80640 bytes -> FLEX 1.0 image
|
||||
spt = 18; // 18 sectors
|
||||
cpd = 35; // 35 tracks
|
||||
sectsize = 128;
|
||||
sector_base = 1; // first sector in track is number ONE
|
||||
} else if ((SIR[0] == 0) && (SIR[1] == 0)) {
|
||||
// FLEX disc has SIR record. on disk image offset $200
|
||||
spt = SIR[MAXSEC]; // Highest number of tracks. As in FLEX sectors are numbered as
|
||||
// 1,2,..Hi this is also the number of sectors per track
|
||||
cpd = SIR[MAXCYL] + 1; // highest track number . On FLEX, first track is track zero
|
||||
sectsize = 256;
|
||||
sector_base = 1; // first sector in track is number ONE
|
||||
} else {
|
||||
spt = 18;
|
||||
sectsize = 128;
|
||||
cpd = disk_image_size / (spt * sectsize);
|
||||
sector_base = 1; // first sector in track is number ONE
|
||||
}
|
||||
heds = 0; //RSV - always SS
|
||||
trksiz = spt * sectsize;
|
||||
dsksiz = trksiz * cpd;
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\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 */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Drive read as %02X", intrq);
|
||||
return intrq;
|
||||
}
|
||||
}
|
||||
|
@ -438,83 +489,88 @@ int32 fdccmd(int32 io, int32 data)
|
|||
static int32 err;
|
||||
|
||||
if ((dsk_unit[cur_dsk].flags & UNIT_ATT) == 0) { /* not attached */
|
||||
dsk_unit[cur_dsk].u3 |= NOTRDY; /* set not ready flag */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Drive %d is not attached", cur_dsk);
|
||||
return 0;
|
||||
val = dsk_unit[cur_dsk].u3 |= NOTRDY; /* set not ready flag */
|
||||
return SEEKERR; // RSV - return SEEK ERROR STATUS bit
|
||||
} else {
|
||||
dsk_unit[cur_dsk].u3 &= ~(NOTRDY); /* clear not ready flag */
|
||||
}
|
||||
if (io) { /* write command to fdc */
|
||||
// RSV - on commands type I ...
|
||||
if ((data & 0x80) == 0) {
|
||||
// ... set bits h V r1r0 to h=1 (home drive), V=0 (verify off), r1r0=11 (40msec track stepping)
|
||||
data = ((data & 0xF0) | 0x0B);
|
||||
// and starts countdown for index status bit
|
||||
index_countdown = 10;
|
||||
} else {
|
||||
index_countdown = 0;
|
||||
}
|
||||
// process command
|
||||
switch(data) {
|
||||
case 0x8C: //read sector command type II
|
||||
case 0x9C: //read multiple sectors command type II
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Read of disk %d, track %d, sector %d",
|
||||
cur_dsk, dsk_unit[cur_dsk].u4, dsk_unit[cur_dsk].u5);
|
||||
if ((dsk_unit[cur_dsk].u5 - sector_base >= spt) || (dsk_unit[cur_dsk].u5 < sector_base)) {
|
||||
dsk_unit[cur_dsk].u3 |= RECNF; /* RSV - set RECORD NOT FOUND */
|
||||
break;
|
||||
}
|
||||
dsk_unit[cur_dsk].u3 |= BUSY; /* set BUSY */
|
||||
pos = trksiz * dsk_unit[cur_dsk].u4; /* calculate file offset */
|
||||
pos += SECT_SIZE * (dsk_unit[cur_dsk].u5 - 1);
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Read pos = %ld ($%08X)",
|
||||
pos, (unsigned int) pos);
|
||||
pos += sectsize * (dsk_unit[cur_dsk].u5 - sector_base);
|
||||
err = sim_fseek(dsk_unit[cur_dsk].fileref, pos, SEEK_SET); /* seek to offset */
|
||||
if (err) {
|
||||
sim_printf("\nfdccmd: Seek error in read command\n");
|
||||
sim_printf("fdccmd: Seek error in read command\n");
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
err = sim_fread(dsk_unit[cur_dsk].filebuf, SECT_SIZE, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
|
||||
/* read in buffer */
|
||||
err = sim_fread(dsk_unit[cur_dsk].filebuf, sectsize, 1, dsk_unit[cur_dsk].fileref);
|
||||
if (err != 1) {
|
||||
sim_printf("\nfdccmd: File error in read command\n");
|
||||
sim_printf("fdccmd: File error in read command\n");
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
dsk_unit[cur_dsk].u3 |= DRQ; /* set DRQ */
|
||||
dsk_unit[cur_dsk].pos = 0; /* clear counter */
|
||||
multiple_sector = (data == 0x9C) ? 1:0; // RSV = set multiple sector TYPE II cmds
|
||||
break;
|
||||
case 0xAC: //write command type II
|
||||
case 0xBC: //write multiple sectors command type II
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\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 {
|
||||
dsk_unit[cur_dsk].u3 |= BUSY;/* set BUSY */
|
||||
pos = trksiz * dsk_unit[cur_dsk].u4; /* calculate file offset */
|
||||
pos += SECT_SIZE * (dsk_unit[cur_dsk].u5 - 1);
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Write pos = %ld ($%08X)",
|
||||
pos, (unsigned int) pos);
|
||||
pos += sectsize * (dsk_unit[cur_dsk].u5 - sector_base);
|
||||
err = sim_fseek(dsk_unit[cur_dsk].fileref, pos, SEEK_SET); /* seek to offset */
|
||||
if (err) {
|
||||
sim_printf("\nfdccmd: Seek error in write command\n");
|
||||
sim_printf("fdccmd: Seek error in write command\n");
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
dsk_unit[cur_dsk].u3 |= DRQ;/* set DRQ */
|
||||
wrt_flag = 1; /* set write flag */
|
||||
wrt_flag = 1; /* RSV - set write flag */
|
||||
dsk_unit[cur_dsk].pos = 0; /* clear counter */
|
||||
}
|
||||
break;
|
||||
case 0x18: //seek command type I
|
||||
case 0x1B: //seek command type I
|
||||
dsk_unit[cur_dsk].u4 = fdcbyte; /* set track */
|
||||
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Seek of disk %d, track %d",
|
||||
cur_dsk, fdcbyte);
|
||||
break;
|
||||
case 0x0B: //restore command type I
|
||||
dsk_unit[cur_dsk].u4 = 0; /* home the drive */
|
||||
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Drive %d homed", cur_dsk);
|
||||
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ | RECNF); /* clear flags */
|
||||
break;
|
||||
case 0xF0: //write track command type III
|
||||
case 0xF4: //write track command type III
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Write track command for drive %d",
|
||||
cur_dsk);
|
||||
break;
|
||||
case 0xD0: //Force Interrupt - terminate current command
|
||||
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
|
||||
break;
|
||||
default:
|
||||
printf("Unknown FDC command %02XH\n\r", data);
|
||||
sim_printf("Unknown FDC command %02X\n\r", data);
|
||||
}
|
||||
} else { /* read status from fdc */
|
||||
val = dsk_unit[cur_dsk].u3; /* set return value */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Exit Drive %d status=%02X",
|
||||
cur_dsk, val);
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\n%02X", val); //even this short fails it!
|
||||
if (index_countdown) { // RSV - Handle INDEX flag
|
||||
index_countdown--;
|
||||
// if index countdoen expires, set index flag in status returned to cpu
|
||||
if (index_countdown==0) val |= INDEX;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
@ -524,12 +580,9 @@ int32 fdccmd(int32 io, int32 data)
|
|||
int32 fdctrk(int32 io, int32 data)
|
||||
{
|
||||
if (io) {
|
||||
dsk_unit[cur_dsk].u4 = data & 0xFF;
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdctrk: Drive %d track set to %d",
|
||||
cur_dsk, dsk_unit[cur_dsk].u4);
|
||||
dsk_unit[cur_dsk].u3 &= ~(RECNF); /* reset RECNF flag */
|
||||
dsk_unit[cur_dsk].u4 = data & BYTEMASK;
|
||||
}
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdctrk: Drive %d track read as %d",
|
||||
cur_dsk, dsk_unit[cur_dsk].u4);
|
||||
return dsk_unit[cur_dsk].u4;
|
||||
}
|
||||
|
||||
|
@ -538,14 +591,12 @@ int32 fdctrk(int32 io, int32 data)
|
|||
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;
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcsec: Drive %d sector set to %d",
|
||||
cur_dsk, dsk_unit[cur_dsk].u5);
|
||||
dsk_unit[cur_dsk].u3 &= ~(RECNF); /* reset RECNF flag */
|
||||
dsk_unit[cur_dsk].u5 = data & BYTEMASK;
|
||||
if (dsk_unit[cur_dsk].u5 < sector_base) //RSV - force to sector 1
|
||||
dsk_unit[cur_dsk].u5 = sector_base;
|
||||
return 0;
|
||||
}
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcsec: Drive %d sector read as %d",
|
||||
cur_dsk, dsk_unit[cur_dsk].u5);
|
||||
return dsk_unit[cur_dsk].u5;
|
||||
}
|
||||
|
||||
|
@ -553,34 +604,44 @@ int32 fdcsec(int32 io, int32 data)
|
|||
|
||||
int32 fdcdata(int32 io, int32 data)
|
||||
{
|
||||
int32 val;
|
||||
int32 val, err;
|
||||
|
||||
if (cur_dsk >= NUM_DISK) // RSV - illegal disk
|
||||
return 0;
|
||||
if (io) { /* write byte to fdc */
|
||||
fdcbyte = data; /* save for seek */
|
||||
if (dsk_unit[cur_dsk].pos < SECT_SIZE) { /* copy bytes to buffer */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdata: Writing byte %d of %02X",
|
||||
dsk_unit[cur_dsk].pos, data);
|
||||
if (dsk_unit[cur_dsk].pos < (t_addr) sectsize) { /* copy bytes to buffer */
|
||||
*((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 == SECT_SIZE) {
|
||||
if (dsk_unit[cur_dsk].pos == sectsize) {
|
||||
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ);
|
||||
if (wrt_flag) { /* if initiated by FDC write command */
|
||||
sim_fwrite(dsk_unit[cur_dsk].filebuf, SECT_SIZE, 1, dsk_unit[cur_dsk].fileref); /* write it */
|
||||
sim_fwrite(dsk_unit[cur_dsk].filebuf, sectsize, 1, dsk_unit[cur_dsk].fileref); /* write it */
|
||||
wrt_flag = 0; /* clear write flag */
|
||||
}
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdata: Sector write complete");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else { /* read byte from fdc */
|
||||
if (dsk_unit[cur_dsk].pos < SECT_SIZE) { /* copy bytes from buffer */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\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;
|
||||
if (dsk_unit[cur_dsk].pos < (t_addr) sectsize) { /* copy bytes from buffer */
|
||||
val = *((uint8 *)(dsk_unit[cur_dsk].filebuf) + dsk_unit[cur_dsk].pos) & BYTEMASK;
|
||||
dsk_unit[cur_dsk].pos++; /* step counter */
|
||||
if (dsk_unit[cur_dsk].pos == SECT_SIZE) { /* done? */
|
||||
if (dsk_unit[cur_dsk].pos == sectsize) { // sector finished
|
||||
if ((multiple_sector) && (dsk_unit[cur_dsk].u5-sector_base < spt-1)) { // read multiple in progress
|
||||
dsk_unit[cur_dsk].u5++;
|
||||
err = sim_fread(dsk_unit[cur_dsk].filebuf, sectsize, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
|
||||
if (err != 1) {
|
||||
sim_printf("fdccmd: File error in read command\n");
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
dsk_unit[cur_dsk].pos = 0;
|
||||
} else { // RSV - handle multiple sector disk read
|
||||
dsk_unit[cur_dsk].u5++;
|
||||
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
|
||||
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdata: Sector read complete");
|
||||
if (multiple_sector) {
|
||||
multiple_sector=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return val;
|
||||
} else
|
||||
|
|
519
swtp6800/common/fd400.c
Normal file
519
swtp6800/common/fd400.c
Normal file
|
@ -0,0 +1,519 @@
|
|||
/* fd400.c: Percom LFD-400 FDC Simulator
|
||||
|
||||
Copyright (c) 2022, Roberto Sancho
|
||||
|
||||
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 Roberto Sancho shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Roberto Sancho .
|
||||
|
||||
MODIFICATIONS:
|
||||
|
||||
NOTES:
|
||||
|
||||
The FDC-400 is a 5-1/4"-inch floppy controller which can control up
|
||||
to four 5-1/4inch floppy drives.
|
||||
This file only emulates the minimum functionality to interface with
|
||||
the virtual disk file.
|
||||
|
||||
The floppy controller is interfaced to the CPU by use of 7 memory
|
||||
addreses (0xCC00-0xCC06).
|
||||
|
||||
Address Mode Function
|
||||
------- ---- --------
|
||||
|
||||
0xCC00 Read CONTROLLER STATUS
|
||||
0xCC00 Write SYNC WORD PORT
|
||||
0xCC01 Read RECEIVED DATA
|
||||
0xCC01 Write WRITE DATA PORT
|
||||
0xCC02 Read SECTOR COUNTER
|
||||
0xCC02 Write FILL WORD PORT
|
||||
0xCC03 Read DRIVE STATUS
|
||||
0xCC03 Write DRIVE AND TRACK SELECT
|
||||
0xCC04 Read RECEIVER RESTART PULSE
|
||||
0xCC04 Write WRITE PULSE
|
||||
0xCC05 Read MOTOR ON PULSE
|
||||
0xCC06 Read MOTOR OFF PULSE
|
||||
|
||||
|
||||
CONTROLLER STATUS (Read 0xCC00):
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| B | x | x | x | x | x | x | R |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
B = Controller Ready (0=Busy, 1=Ready)
|
||||
R = Read byte ready (1=can retrieve read byte)
|
||||
|
||||
|
||||
RECEIVED DATA (Read 0xCC01):
|
||||
WRITE DATA PORT (Write 0xCC01):
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| byte |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
Data byte from retrieved sector being read
|
||||
Data byte to store in sector being write
|
||||
|
||||
|
||||
CURRENT SECTOR (Read 0xCC02):
|
||||
WRITE FILL CHAR (Write 0xCC02):
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| x | Sector |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
Return current Sector
|
||||
Set the fill char for write sector
|
||||
|
||||
|
||||
DRIVE STATUS (Read 0xCC03):
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| DD | I | S | W | M | T | P |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
P = Write allowed Bit (0=disk is write protected)
|
||||
T = Track Zero Bit (1=head is NOT positioned in track zero)
|
||||
M = Motor Test Bit (1=motor stopped)
|
||||
W = Write Gate Bit (1=drive gate door is closed)
|
||||
S = Sector Pulse Bit (1=head at start of sector)
|
||||
I = Index Pulse bit (???)
|
||||
DD = Current selected drive (0..3)
|
||||
|
||||
|
||||
DRIVE AND TRACK SELECT (Write 0xCC03):
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| DD | S | D | x | x | x | x |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
D = Direction bit (1=Track In=increment track number)
|
||||
S = Step Bit (1=Move disk head one track using direction D)
|
||||
DD = Select drive (0..3)
|
||||
|
||||
LFD-400 Disck supports these operating systems (1977)
|
||||
|
||||
- MINIDOS: Just Load/Save ram starting at given sector in disk.
|
||||
No files. No sector allocation management. Rom based
|
||||
- MPX (also know as MiniDOS Plus or MiniDOS/MPX or MiniDOS-PlusX):
|
||||
Based on MiniDOS, add named files, contiguos allocation management. Transient disk command
|
||||
- MiniDisk+ DOS:
|
||||
Based on MiniDOS, add named files, contiguos allocation management. More disk commands
|
||||
|
||||
|
||||
MiniDOS files have 40 track (0..39) with 10 sectors (0..9) each with 256 bytes of data
|
||||
|
||||
The following unit registers are used by this controller emulation:
|
||||
|
||||
fd400_dsk_unit[cur_drv].u4 unit current track
|
||||
fd400_dsk_unit[cur_drv].u5 unit current sector
|
||||
fd400_dsk_unit[cur_drv].pos unit current sector byte index into buffer
|
||||
fd400_dsk_unit[cur_drv].filebuf unit current sector buffer
|
||||
fd400_dsk_unit[cur_drv].fileref unit current attached file reference
|
||||
|
||||
At start, units discs from controller are dissabled
|
||||
To use it, befor attaching the disk image, it is mecessary to do "set lfd-4000 enabled"
|
||||
(for unit 0), and optionally "set lfd-4001 enabled" (for unit 1) and so on.
|
||||
*/
|
||||
|
||||
#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 Disk disk with 10 sectors and 40 tracks */
|
||||
|
||||
#define NUM_DISK 4
|
||||
#define SECT_SIZE (8+4+256) /* sector size=header (10 bytes) + data (256 bytes) + CRC (2 bytes) */
|
||||
#define NUM_SECT 10 /* 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 40 /* maximum tracks */
|
||||
#define DSK_SIZE (NUM_SECT * HEADS * NUM_CYL * SECT_SIZE) /* dsk size (bytes) */
|
||||
|
||||
#define TRK fd400_dsk_unit[fd400.cur_dsk].u4 // current disk track and sector
|
||||
#define SECT fd400_dsk_unit[fd400.cur_dsk].u5
|
||||
|
||||
#define BUF_SIZE (SECT_SIZE+16) // sector buffer in memory
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
t_stat fd400_dsk_reset (DEVICE *dptr);
|
||||
t_stat fd400_attach (UNIT *, CONST char *);
|
||||
|
||||
/* SS-50 I/O address space functions */
|
||||
|
||||
int32 fd400_fdcstatus(int32 io, int32 data);
|
||||
int32 fd400_cstatus(int32 io, int32 data);
|
||||
int32 fd400_data(int32 io, int32 data);
|
||||
int32 fd400_cursect(int32 io, int32 data);
|
||||
int32 fd400_startrw(int32 io, int32 data);
|
||||
|
||||
/* Local Variables */
|
||||
|
||||
struct {
|
||||
int32 cur_dsk; /* Currently selected drive */
|
||||
int32 SectorPulse; // Head positioned at beginning of sector
|
||||
int32 StepBit;
|
||||
uint8 FillChar;
|
||||
} fd400 = {0};
|
||||
|
||||
/* Floppy Disk Controller data structures
|
||||
|
||||
fd400_dsk_dev Disk Controller device descriptor
|
||||
fd400_dsk_unit Disk Controller unit descriptor
|
||||
fd400_dsk_reg Disk Controller register list
|
||||
fd400_dsk_mod Disk Controller modifiers list
|
||||
*/
|
||||
|
||||
UNIT fd400_dsk_unit[] = {
|
||||
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+UNIT_DIS, 0) }
|
||||
};
|
||||
|
||||
REG fd400_dsk_reg[] = {
|
||||
{ HRDATA (DISK, fd400.cur_dsk, 4) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEBTAB fd400_dsk_debug[] = {
|
||||
{ "ALL", DEBUG_all, "All debug bits" },
|
||||
{ "FLOW", DEBUG_flow, "Flow control" },
|
||||
{ "READ", DEBUG_read, "Read Command" },
|
||||
{ "WRITE", DEBUG_write, "Write Command"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE fd400_dsk_dev = {
|
||||
"LFD-400", //name
|
||||
fd400_dsk_unit, //units
|
||||
fd400_dsk_reg, //registers
|
||||
NULL, //modifiers
|
||||
NUM_DISK, //numunits
|
||||
16, //aradix
|
||||
16, //awidth
|
||||
1, //aincr
|
||||
16, //dradix
|
||||
8, //dwidth
|
||||
NULL, //examine
|
||||
NULL, //deposit
|
||||
&fd400_dsk_reset, //reset
|
||||
NULL, //boot
|
||||
&fd400_attach, //attach
|
||||
NULL, //detach
|
||||
NULL, //ctxt
|
||||
DEV_DISABLE|DEV_DIS|DEV_DEBUG, //flags
|
||||
0, //dctrl
|
||||
fd400_dsk_debug, //debflags
|
||||
NULL, //msize
|
||||
NULL //lname
|
||||
};
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat fd400_dsk_reset (DEVICE *dptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NUM_DISK; i++) {
|
||||
fd400_dsk_unit[i].u3 = 0; /* clear current flags */
|
||||
fd400_dsk_unit[i].u4 = 0; /* clear current cylinder # */
|
||||
fd400_dsk_unit[i].u5 = 0; /* clear current sector # */
|
||||
fd400_dsk_unit[i].pos = 0; /* clear current byte ptr */
|
||||
if (fd400_dsk_unit[i].filebuf == NULL) {
|
||||
fd400_dsk_unit[i].filebuf = malloc(BUF_SIZE); /* allocate buffer */
|
||||
if (fd400_dsk_unit[i].filebuf == NULL) {
|
||||
printf("fc400_reset: Malloc error\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
memset(&fd400, 0, sizeof(fd400));
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* I/O instruction handlers, called from the MP-B2 module when a
|
||||
read or write occur to addresses 0xCC00-0xCC07. */
|
||||
|
||||
/* FDC STATUS register $CC03 */
|
||||
|
||||
int32 fd400_fdcstatus(int32 io, int32 data)
|
||||
{
|
||||
int32 val;
|
||||
UNIT * uptr;
|
||||
|
||||
uptr = &fd400_dsk_unit[fd400.cur_dsk];
|
||||
if (io==0) {
|
||||
// io=0 when reading from io register (return data read from i/o device register)
|
||||
val=(fd400.cur_dsk & 3) << 6;
|
||||
val |= 8; // write gate door allways closed
|
||||
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||
sim_debug (DEBUG_flow, &fd400_dsk_dev, "Current Drive %d has no file attached \n", fd400.cur_dsk);
|
||||
} else {
|
||||
// file attached = disk inserted into unit
|
||||
if ((uptr->flags & UNIT_RO) == 0) val |= 1; // unit is read/write
|
||||
if (TRK!=0) val |= 2; // head is NOT in track zero
|
||||
if (fd400.SectorPulse) {
|
||||
val |= 16;
|
||||
fd400.SectorPulse--;
|
||||
} else {
|
||||
// set sector pulse and incr current sector
|
||||
// Simulates somewhat disk rotation whitout having to set up _svr and sim_activate
|
||||
fd400.SectorPulse=2;
|
||||
SECT++; if (SECT >= NUM_SECT) SECT = 0;
|
||||
uptr->pos=0; // init sector read
|
||||
}
|
||||
if (SECT==0) val |= 32; // index pulse: head is positioned in sector zero
|
||||
}
|
||||
sim_debug (DEBUG_flow, &fd400_dsk_dev, "Status Returned %02X, Current Drive %d TRK %d SECT %d \n",
|
||||
val, fd400.cur_dsk, TRK, SECT);
|
||||
return val;
|
||||
}
|
||||
// io=1 -> writing data to i/o register,
|
||||
fd400.cur_dsk = data >> 6; // select current disk
|
||||
fd400.SectorPulse = 0; // init sector pulse
|
||||
if (data & 32) {
|
||||
fd400.StepBit=1; // Step bit set to one
|
||||
} else if ((data & 32)==0) { // Step bit set to zero
|
||||
if (fd400.StepBit==0) {
|
||||
// but was already zero -> no action
|
||||
} else {
|
||||
// StepBit changing from 1 to 0 -> step track motot
|
||||
fd400.StepBit=0;
|
||||
// step track depending on direction bit
|
||||
if (data & 16) TRK++; else TRK--;
|
||||
if (TRK < 0) TRK=0;
|
||||
if (TRK >= NUM_CYL) TRK = NUM_CYL-1;
|
||||
// on changing track also incr sect num, but not issue sector pulse (landed on middle of sector)
|
||||
SECT++; if (SECT >= NUM_SECT) SECT = 0;
|
||||
uptr->pos=0; // init sector read
|
||||
}
|
||||
}
|
||||
sim_debug (DEBUG_flow, &fd400_dsk_dev, "Set Drive and Track %02X, Current Drive %d TRK %d SECT %d \n",
|
||||
data, fd400.cur_dsk, TRK, SECT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CONTROLLER STATUS register (read $CC00)*/
|
||||
|
||||
int32 fd400_cstatus(int32 io, int32 data)
|
||||
{
|
||||
// controller allways ready, byte read from sector allways ready
|
||||
// writing to is set the sync byte. This is not implemented
|
||||
return 128+1;
|
||||
}
|
||||
|
||||
/* DATA register */
|
||||
|
||||
int32 fd400_data(int32 io, int32 data)
|
||||
{
|
||||
uint32 loc;
|
||||
UNIT * uptr = &fd400_dsk_unit[fd400.cur_dsk];
|
||||
uint8 dsk_sect[SECT_SIZE]; // image of sector read/saved in disk image
|
||||
uint8 * p = (uint8 *)(uptr->filebuf); // sector byte stream as seen by program
|
||||
int i, n;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return 0; // not attached
|
||||
if (io==0) {
|
||||
// io=0 when reading from io register (return data read from i/o device register)
|
||||
// read data from sector
|
||||
if (uptr->pos==0) {
|
||||
// read new sector buffer
|
||||
// init buffer to zero
|
||||
memset(uptr->filebuf, 0, SECT_SIZE);
|
||||
// calculate location of current sector in disk image file
|
||||
loc=(TRK * NUM_SECT + SECT) * SECT_SIZE;
|
||||
if (loc >= uptr->capac) {
|
||||
// reading past image file current size -> read as zeroes
|
||||
} else {
|
||||
// read sector
|
||||
sim_fseek(uptr->fileref, loc, SEEK_SET);
|
||||
sim_fread(dsk_sect, 1, SECT_SIZE, uptr->fileref);
|
||||
// reorganize buffer to match the byte order expected by MiniDOS
|
||||
//
|
||||
// Data in MiniDOS MPX disk image:
|
||||
// BT BS FT FS NN AH AL TY CH CL PH PL [256 data bytes] = 268 bytes
|
||||
// where BT=Backward link track, DS=Backward link sector,
|
||||
// FT=Forward link track, FS=Forward link sector. = 00 00 if this is last sector of file
|
||||
// NN=Number of data bytes (00=256 bytes)
|
||||
// AH AL=Addr in RAM where to load sector data bytes (H=High byte, L=Low byte)
|
||||
// TY=file type
|
||||
// CH CL=CheckSum Hi/Low byte
|
||||
// PH PL=Postamble Hi/Low byte. Holds program start addr on last sector
|
||||
//
|
||||
// Data as expected by MiniDOS ROM when reading a sector
|
||||
// SY TR SE BT BS FT FS NN AH AL TY [NN data bytes] CH CL PH PL
|
||||
// where SY=Sync Byte=$FD
|
||||
// TR SE=This track and sector
|
||||
// BT BS FT FS NN AH AL TY=same as above
|
||||
// CH CL=same as above
|
||||
//
|
||||
// so we create the filebuf (p pointer) reordering data read from disk image file (dsk_sect)
|
||||
p[0]=0xFB; // sync byte
|
||||
p[1]=TRK; p[2]=SECT; // this sector track and sector number
|
||||
for (i=0; i<8; i++) p[3+i]=dsk_sect[i]; // 8 byte header with bytes BT ... TY
|
||||
n=dsk_sect[4]; if (n==0) n=256; // number of data bytes
|
||||
for (i=0; i<n; i++) p[3+8+i]=dsk_sect[i+12]; // copy data bytes from disk-read-buffer to sector buffer in unit
|
||||
for (i=0; i<4; i++) p[3+8+n+i]=dsk_sect[i+8]; // copy checksum and postamble
|
||||
}
|
||||
sim_debug (DEBUG_read, &fd400_dsk_dev, "Read Disc Image at loc %d, Current Drive %d TRK %d SECT %d \n",
|
||||
loc, fd400.cur_dsk, TRK, SECT);
|
||||
uptr->pos=0;
|
||||
}
|
||||
// retrieve read byte from sector buffer
|
||||
if (uptr->pos>=BUF_SIZE) {
|
||||
sim_debug (DEBUG_write, &fd400_dsk_dev, "Sector overrun - do not read data\n");
|
||||
return 0;
|
||||
}
|
||||
data=p[uptr->pos];
|
||||
sim_debug (DEBUG_read, &fd400_dsk_dev, "Read byte %02X (dec=%d char='%c'), Current Drive %d TRK %d SECT %d POS %d\n",
|
||||
data, data, (data < 32) ? '?':data, fd400.cur_dsk, TRK, SECT, uptr->pos);
|
||||
uptr->pos++;
|
||||
|
||||
return data;
|
||||
}
|
||||
// io=1 -> writing data to i/o register,
|
||||
// write data to sector
|
||||
if (uptr->flags & UNIT_RO) {
|
||||
sim_debug (DEBUG_write, &fd400_dsk_dev, "Write data %02X, but Current Drive %d is Read Only\n",
|
||||
data, fd400.cur_dsk);
|
||||
return 0;
|
||||
}
|
||||
sim_debug (DEBUG_write, &fd400_dsk_dev, "Write data %02X, Current Drive %d TRK %d SECT %d POS %d\n",
|
||||
data, fd400.cur_dsk, TRK, SECT, uptr->pos);
|
||||
// store byte into sector buffer
|
||||
if (uptr->pos==0) {
|
||||
if (data==0) return 0; // ignore zero bytes before sync byte
|
||||
}
|
||||
if (uptr->pos >= BUF_SIZE) {
|
||||
sim_debug (DEBUG_write, &fd400_dsk_dev, "Sector overrun - do not write data\n");
|
||||
return 0;
|
||||
}
|
||||
// save byte to buffer
|
||||
p[uptr->pos]=data;
|
||||
uptr->pos++;
|
||||
// calculate location of current sector in disk image file
|
||||
loc=(TRK * NUM_SECT + SECT) * SECT_SIZE;
|
||||
if (loc >= uptr->capac) {
|
||||
// writing past image file current size -> extend disk image size
|
||||
uint8 buf[SECT_SIZE];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sim_fseek(uptr->fileref, uptr->capac, SEEK_SET);
|
||||
while (uptr->capac <= loc) {
|
||||
sim_fwrite(buf, 1, SECT_SIZE, uptr->fileref);
|
||||
uptr->capac += SECT_SIZE;
|
||||
}
|
||||
sim_debug (DEBUG_write, &fd400_dsk_dev, "Disk image extended up to %d bytes \n", uptr->capac);
|
||||
}
|
||||
// convert byte stream into sector format to save to disk.
|
||||
// reorganize buffer to match the byte order expected by MiniDOS
|
||||
//
|
||||
// Data as sent to controller by MiniDOS ROM when writing a sector
|
||||
// SY TR SE BT BS FT FS NN AH AL TY [NN data bytes] CH CL PH PL
|
||||
// where SY=Sync Byte=$FD
|
||||
// TR SE=This track and sector
|
||||
// BT BS FT FS NN AH AL TY=same as below
|
||||
// CH CL=same as below
|
||||
//
|
||||
// Data in MiniDOS MPX disk image:
|
||||
// BT BS FT FS NN AH AL TY CH CL PH PL [256 data bytes] = 268 bytes
|
||||
// where BT=Backward link track, DS=Backward link sector,
|
||||
// FT=Forward link track, FS=Forward link sector. = 00 00 if this is last sector of file
|
||||
// NN=Number of data bytes (00=256 bytes)
|
||||
// AH AL=Addr in RAM where to load sector data bytes (H=High byte, L=Low byte)
|
||||
// TY=file type
|
||||
// CH CL=CheckSum Hi/Low byte
|
||||
// PH PL=Postamble Hi/Low byte. Holds program start addr on last sector
|
||||
//
|
||||
// so we create the sector to write in disk image file (dsk_sect) reordering data from filebuf (p pointer)
|
||||
|
||||
memset(dsk_sect, 255, sizeof(dsk_sect));
|
||||
for (i=0; i<8; i++) dsk_sect[i]=p[3+i]; // disk sector start with 8 byte header with bytes BT BS FT FS NN AH AL TY
|
||||
n=uptr->pos-11; // number of data bytes
|
||||
if (n>256+4) n=256+4;
|
||||
if (n>4) {
|
||||
for (i=0; i<4; i++) dsk_sect[i+8]=p[3+8+n+i-4]; // copy checksum and postamble
|
||||
for (i=0; i<n-4; i++) dsk_sect[i+12]=p[3+8+i]; // copy data bytes to disk-write-buffer
|
||||
}
|
||||
// does a whole sector save for each byte sent to fdc controller, as there is no an end-of-sector-write signal
|
||||
// This is quite ineficient, but host is fast enought and has clever caching, so no worries
|
||||
sim_fseek(uptr->fileref, loc, SEEK_SET);
|
||||
sim_fwrite(dsk_sect, 1, SECT_SIZE, uptr->fileref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CURRENT SECTOR / FILL CHAR REGISTER */
|
||||
|
||||
int32 fd400_cursect(int32 io, int32 data)
|
||||
{
|
||||
UNIT * uptr;
|
||||
|
||||
uptr = &fd400_dsk_unit[fd400.cur_dsk];
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return 0; // not attached
|
||||
if (io==0) {
|
||||
// io=0 when reading from io register (return data read from i/o device register)
|
||||
// return current sector
|
||||
sim_debug (DEBUG_flow, &fd400_dsk_dev, "Current Drive %d TRK %d SECT %d \n",
|
||||
fd400.cur_dsk, TRK, SECT);
|
||||
return SECT;
|
||||
}
|
||||
// io=1 -> writing data to i/o register,
|
||||
// set fill char
|
||||
fd400.FillChar=data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RECEIVER RESTART / WRITE PULSE $CC00 */
|
||||
|
||||
int32 fd400_startrw(int32 io, int32 data)
|
||||
{
|
||||
UNIT * uptr;
|
||||
|
||||
uptr = &fd400_dsk_unit[fd400.cur_dsk];
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return 0; // not attached
|
||||
if (io==0) {
|
||||
// io=0 when reading from io register (return data read from i/o device register)
|
||||
// start read from sector -> init received so it will return sync char and tracks
|
||||
uptr->pos=0;
|
||||
return 0;
|
||||
}
|
||||
// io=1 -> writing data to i/o register,
|
||||
// start write to sector
|
||||
uptr->pos=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
t_stat fd400_attach (UNIT * uptr, CONST char * file)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
if ((r = attach_unit(uptr, file)) != SCPE_OK) return r;
|
||||
uptr->u4 = uptr->u5 = 0;
|
||||
uptr->capac = sim_fsize(uptr->fileref);
|
||||
uptr->pos = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* end of fd400.c */
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
MODIFICATIONS:
|
||||
|
||||
24 Apr 15 -- Modified to use simh_debug
|
||||
|
||||
NOTES:
|
||||
|
||||
These functions support a simulated 2704 to 2764 EPROMs device on an 8-bit
|
||||
|
@ -114,19 +112,15 @@ t_stat i2716_attach (UNIT *uptr, CONST char *cptr)
|
|||
t_stat r;
|
||||
FILE *fp;
|
||||
|
||||
sim_debug (DEBUG_flow, &i2716_dev, "i2716_attach: cptr=%s\n", cptr);
|
||||
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
|
||||
sim_debug (DEBUG_flow, &i2716_dev, "i2716_attach: Error\n");
|
||||
return r;
|
||||
}
|
||||
sim_debug (DEBUG_read, &i2716_dev, "\tOpen file\n");
|
||||
fp = fopen(uptr->filename, "rb"); /* open EPROM file */
|
||||
if (fp == NULL) {
|
||||
printf("i2716%d: Unable to open ROM file %s\n", (int)(uptr - i2716_dev.units), uptr->filename);
|
||||
printf("\tNo ROM image loaded!!!\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
sim_debug (DEBUG_read, &i2716_dev, "\tRead file\n");
|
||||
j = 0; /* load EPROM file */
|
||||
c = fgetc(fp);
|
||||
while (c != EOF) {
|
||||
|
@ -137,10 +131,7 @@ t_stat i2716_attach (UNIT *uptr, CONST char *cptr)
|
|||
break;
|
||||
}
|
||||
}
|
||||
sim_debug (DEBUG_read, &i2716_dev, "\tClose file\n");
|
||||
fclose(fp);
|
||||
// printf("i2716%d: %d bytes of ROM image %s loaded\n",uptr - i2716_dev.units, j, uptr->filename);
|
||||
sim_debug (DEBUG_flow, &i2716_dev, "i2716_attach: Done\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -151,32 +142,21 @@ t_stat i2716_reset (DEVICE *dptr)
|
|||
int32 i, base;
|
||||
UNIT *uptr;
|
||||
|
||||
sim_debug (DEBUG_flow, &i2716_dev, "i2716_reset: \n");
|
||||
for (i = 0; i < I2716_NUM; i++) { /* init all units */
|
||||
uptr = i2716_dev.units + i;
|
||||
sim_debug (DEBUG_flow, &i2716_dev, "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 */
|
||||
uptr->filebuf = calloc(2048, sizeof(uint8)); /* allocate EPROM buffer */
|
||||
if (uptr->filebuf == NULL) {
|
||||
sim_debug (DEBUG_flow, &i2716_dev, "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);
|
||||
// }
|
||||
}
|
||||
sim_debug (DEBUG_flow, &i2716_dev, "i2716_reset: Done\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -197,16 +177,13 @@ int32 i2716_get_mbyte(int32 offset)
|
|||
len = uptr->capac - 1;
|
||||
if ((offset >= org) && (offset < (org + len))) {
|
||||
if (uptr->filebuf == NULL) {
|
||||
sim_debug (DEBUG_read, &i2716_dev, "i2716_get_mbyte: EPROM not configured\n");
|
||||
return 0xFF;
|
||||
} else {
|
||||
val = *((uint8 *)(uptr->filebuf) + (offset - org));
|
||||
sim_debug (DEBUG_read, &i2716_dev, " val=%04X\n", val);
|
||||
return (val & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
sim_debug (DEBUG_read, &i2716_dev, "i2716_get_mbyte: Out of range\n");
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,8 +25,6 @@
|
|||
|
||||
MODIFICATIONS:
|
||||
|
||||
24 Apr 15 -- Modified to use simh_debug
|
||||
|
||||
NOTES:
|
||||
|
||||
These functions support a simulated m6810 RAM device on a CPU board. The
|
||||
|
@ -43,12 +41,11 @@
|
|||
t_stat m6810_reset (DEVICE *dptr);
|
||||
int32 m6810_get_mbyte(int32 offset);
|
||||
void m6810_put_mbyte(int32 offset, int32 val);
|
||||
t_stat m6810_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches);
|
||||
t_stat m6810_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches);
|
||||
|
||||
/* SIMH RAM Standard I/O Data Structures */
|
||||
|
||||
UNIT m6810_unit = { UDATA (NULL, UNIT_BINK, 128),
|
||||
UNIT m6810_unit = {
|
||||
UDATA (NULL, UNIT_BINK, 128),
|
||||
0 };
|
||||
|
||||
MTAB m6810_mod[] = {
|
||||
|
@ -74,8 +71,8 @@ DEVICE m6810_dev = {
|
|||
1, //aincr
|
||||
16, //dradix
|
||||
8, //dwidth
|
||||
&m6810_examine, //examine
|
||||
&m6810_deposit, //deposit
|
||||
NULL, //examine
|
||||
NULL, //deposit
|
||||
&m6810_reset, //reset
|
||||
NULL, //boot
|
||||
NULL, //attach
|
||||
|
@ -94,16 +91,14 @@ DEVICE m6810_dev = {
|
|||
|
||||
t_stat m6810_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_debug (DEBUG_flow, &m6810_dev, "m6810_reset: \n");
|
||||
if (m6810_unit.filebuf == NULL) {
|
||||
m6810_unit.filebuf = malloc(128);
|
||||
m6810_unit.filebuf = calloc(128, sizeof(uint8));
|
||||
if (m6810_unit.filebuf == NULL) {
|
||||
printf("m6810_reset: Malloc error\n");
|
||||
printf("m6810_reset: Calloc error\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
m6810_unit.capac = 128;
|
||||
}
|
||||
sim_debug (DEBUG_flow, &m6810_dev, "m6810_reset: Done\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -117,13 +112,10 @@ int32 m6810_get_mbyte(int32 offset)
|
|||
{
|
||||
int32 val;
|
||||
|
||||
sim_debug (DEBUG_read, &m6810_dev, "m6810_get_mbyte: offset=%04X\n", offset);
|
||||
if (((t_addr)offset) < m6810_unit.capac) {
|
||||
val = *((uint8 *)(m6810_unit.filebuf) + offset) & 0xFF;
|
||||
sim_debug (DEBUG_read, &m6810_dev, "val=%04X\n", val);
|
||||
return val;
|
||||
} else {
|
||||
sim_debug (DEBUG_read, &m6810_dev, "m6810_get_mbyte: out of range\n");
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
@ -132,30 +124,12 @@ int32 m6810_get_mbyte(int32 offset)
|
|||
|
||||
void m6810_put_mbyte(int32 offset, int32 val)
|
||||
{
|
||||
sim_debug (DEBUG_write, &m6810_dev, "m6810_put_mbyte: offset=%04X, val=%02X\n",
|
||||
offset, val);
|
||||
if ((t_addr)offset < m6810_unit.capac) {
|
||||
*((uint8 *)(m6810_unit.filebuf) + offset) = val & 0xFF;
|
||||
return;
|
||||
} else {
|
||||
sim_debug (DEBUG_write, &m6810_dev, "m6810_put_mbyte: out of range\n");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* end of m6810.c */
|
||||
|
||||
t_stat m6810_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
for (i=0; i<sim_emax; ++i)
|
||||
*eval_array++ = m6810_get_mbyte(addr++);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat m6810_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches)
|
||||
{
|
||||
m6810_put_mbyte(addr,value);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
MODIFICATIONS:
|
||||
|
||||
24 Apr 15 -- Modified to use simh_debug
|
||||
|
||||
NOTES:
|
||||
|
||||
These functions support 6 simulated MP-8M memory cards on an SS-50 system.
|
||||
|
@ -40,7 +38,7 @@
|
|||
#include <stdio.h>
|
||||
#include "swtp_defs.h"
|
||||
|
||||
#define MP_8M_NUM 6 /* number of MP-*m boards */
|
||||
#define MP_8M_NUM 6 /* number of MP-8M boards */
|
||||
|
||||
/* prototypes */
|
||||
|
||||
|
@ -105,11 +103,8 @@ t_stat mp_8m_reset (DEVICE *dptr)
|
|||
int32 i;
|
||||
UNIT *uptr;
|
||||
|
||||
sim_debug (DEBUG_flow, &mp_8m_dev, "mp_8m_reset: \n");
|
||||
for (i = 0; i < MP_8M_NUM; i++) { /* init all units */
|
||||
uptr = mp_8m_dev.units + i;
|
||||
sim_debug (DEBUG_flow, &mp_8m_dev, "MP-8M %d unit.flags=%08X\n",
|
||||
i, uptr->flags);
|
||||
uptr->capac = 0x2000;
|
||||
if (i < 4)
|
||||
uptr->u3 = 0x2000 * i;
|
||||
|
@ -121,15 +116,8 @@ t_stat mp_8m_reset (DEVICE *dptr)
|
|||
printf("mp_8m_reset: Calloc error\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
// for (j=0; j<8192; j++) { /* fill pattern for testing */
|
||||
// val = (0xA0 | i);
|
||||
// *((uint8 *)(uptr->filebuf) + j) = val & 0xFF;
|
||||
// }
|
||||
}
|
||||
sim_debug (DEBUG_flow, &mp_8m_dev, "MP-8M %d initialized at [%04X-%04XH]\n",
|
||||
i, uptr->u3, uptr->u3 + uptr->capac - 1);
|
||||
}
|
||||
sim_debug (DEBUG_flow, &mp_8m_dev, "mp_8m_reset: Done\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -145,19 +133,16 @@ int32 mp_8m_get_mbyte(int32 addr)
|
|||
int32 i;
|
||||
UNIT *uptr;
|
||||
|
||||
sim_debug (DEBUG_read, &mp_8m_dev, "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));
|
||||
sim_debug (DEBUG_read, &mp_8m_dev, " val=%04X\n", val);
|
||||
return (val & 0xFF);
|
||||
return (val & BYTEMASK);
|
||||
}
|
||||
}
|
||||
sim_debug (DEBUG_read, &mp_8m_dev, "mp_8m_get_mbyte: Out of range\n");
|
||||
return 0xFF; /* multibus has active high pullups */
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
/* get a word from memory */
|
||||
|
@ -179,19 +164,15 @@ void mp_8m_put_mbyte(int32 addr, int32 val)
|
|||
int32 i;
|
||||
UNIT *uptr;
|
||||
|
||||
sim_debug (DEBUG_write, &mp_8m_dev, "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;
|
||||
sim_debug (DEBUG_write, &mp_8m_dev, "\n");
|
||||
*((uint8 *)(uptr->filebuf) + (addr - org)) = val & BYTEMASK;
|
||||
return;
|
||||
}
|
||||
}
|
||||
sim_debug (DEBUG_write, &mp_8m_dev, "mp_8m_put_mbyte: Out of range\n");
|
||||
}
|
||||
|
||||
/* put a word into memory */
|
||||
|
|
|
@ -55,12 +55,10 @@ 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);
|
||||
t_stat mpa_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches);
|
||||
t_stat mpa_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches);
|
||||
|
||||
/* external routines */
|
||||
|
||||
/* MP-B2 bus routines */
|
||||
/* MP-B2 MB routines */
|
||||
extern int32 MB_get_mbyte(int32 addr);
|
||||
extern int32 MB_get_mword(int32 addr);
|
||||
extern void MB_put_mbyte(int32 addr, int32 val);
|
||||
|
@ -114,8 +112,8 @@ DEVICE CPU_BD_dev = {
|
|||
1, //aincr
|
||||
16, //dradix
|
||||
8, //dwidth
|
||||
mpa_examine, //examine
|
||||
mpa_deposit, //deposit
|
||||
NULL, //examine
|
||||
NULL, //deposit
|
||||
NULL, //reset
|
||||
NULL, //boot
|
||||
NULL, //attach
|
||||
|
@ -132,30 +130,27 @@ DEVICE CPU_BD_dev = {
|
|||
|
||||
int32 CPU_BD_get_mbyte(int32 addr)
|
||||
{
|
||||
int32 val;
|
||||
int32 val = 0, EA = 0, EA1 = 0;
|
||||
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "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;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: m6810 val=%02X\n", val);
|
||||
val = m6810_get_mbyte(addr - 0xA000) & BYTEMASK;
|
||||
} else {
|
||||
val = MB_get_mbyte(addr) & 0xFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: m6810 val=%02X\n", val);
|
||||
val = MB_get_mbyte(addr) & BYTEMASK;
|
||||
}
|
||||
break;
|
||||
case 0xE000:
|
||||
val = BOOTROM_get_mbyte(addr - 0xE000) & 0xFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: EPROM=%02X\n", val);
|
||||
val = BOOTROM_get_mbyte(addr - 0xE000) & BYTEMASK;
|
||||
break;
|
||||
case 0xF000:
|
||||
val = BOOTROM_get_mbyte(addr - (0x10000 - BOOTROM_unit.capac)) & 0xFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: EPROM=%02X\n", val);
|
||||
EA1 = 0x10000 - BOOTROM_unit.capac;
|
||||
EA = addr - EA1;
|
||||
val = BOOTROM_get_mbyte(EA) & BYTEMASK;
|
||||
break;
|
||||
default:
|
||||
val = MB_get_mbyte(addr) & 0xFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: mp_b2 val=%02X\n", val);
|
||||
val = MB_get_mbyte(addr) & BYTEMASK;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
@ -166,11 +161,9 @@ int32 CPU_BD_get_mword(int32 addr)
|
|||
{
|
||||
int32 val;
|
||||
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mword: addr=%04X\n", addr);
|
||||
val = (CPU_BD_get_mbyte(addr) << 8);
|
||||
val |= CPU_BD_get_mbyte(addr+1);
|
||||
val &= 0xFFFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mword: val=%04X\n", val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -178,8 +171,6 @@ int32 CPU_BD_get_mword(int32 addr)
|
|||
|
||||
void CPU_BD_put_mbyte(int32 addr, int32 val)
|
||||
{
|
||||
sim_debug (DEBUG_write, &CPU_BD_dev, "CPU_BD_put_mbyte: addr=%04X, val=%02X\n",
|
||||
addr, val);
|
||||
switch(addr & 0xF000) {
|
||||
case 0xA000:
|
||||
if (CPU_BD_unit.flags & UNIT_RAM)
|
||||
|
@ -196,25 +187,8 @@ void CPU_BD_put_mbyte(int32 addr, int32 val)
|
|||
|
||||
void CPU_BD_put_mword(int32 addr, int32 val)
|
||||
{
|
||||
sim_debug (DEBUG_write, &CPU_BD_dev, "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);
|
||||
}
|
||||
|
||||
t_stat mpa_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
for (i=0; i<sim_emax; ++i)
|
||||
*eval_array++ = CPU_BD_get_mbyte(addr++);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat mpa_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches)
|
||||
{
|
||||
CPU_BD_put_mbyte(addr,value);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* end of mp-a.c */
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
MODIFICATIONS:
|
||||
|
||||
24 Apr 15 -- Modified to use simh_debug
|
||||
|
||||
NOTES:
|
||||
|
||||
The MP-A2 CPU Board contains the following devices [mp-a2.c]:
|
||||
|
@ -70,10 +68,8 @@ 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);
|
||||
t_stat mpa2_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches);
|
||||
t_stat mpa2_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches);
|
||||
|
||||
/* external routines */
|
||||
/* external function prototypes */
|
||||
|
||||
/* MP-B2 bus routines */
|
||||
extern int32 MB_get_mbyte(int32 addr);
|
||||
|
@ -144,8 +140,8 @@ DEVICE CPU_BD_dev = {
|
|||
1, //aincr
|
||||
16, //dradix
|
||||
8, //dwidth
|
||||
mpa2_examine, //examine
|
||||
mpa2_deposit, //deposit
|
||||
NULL, //examine
|
||||
NULL, //deposit
|
||||
NULL, //reset
|
||||
NULL, //boot
|
||||
NULL, //attach
|
||||
|
@ -173,39 +169,34 @@ int32 get_base(void)
|
|||
|
||||
int32 CPU_BD_get_mbyte(int32 addr)
|
||||
{
|
||||
int32 val = 0;
|
||||
int32 val = 0, EA = 0, EA1 = 0;
|
||||
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "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;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: m6810 val=%02X\n", val);
|
||||
val = m6810_get_mbyte(addr - 0xA000) & BYTEMASK;
|
||||
} else {
|
||||
val = MB_get_mbyte(addr) & 0xFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: m6810 val=%02X\n", val);
|
||||
val = MB_get_mbyte(addr) & BYTEMASK;
|
||||
}
|
||||
break;
|
||||
case 0xC000:
|
||||
if (CPU_BD_unit.flags & UNIT_LO_PROM) {
|
||||
val = i2716_get_mbyte(addr - 0xC000) & 0xFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: 2716=%02X\n", val);
|
||||
val = i2716_get_mbyte(addr - 0xC000) & BYTEMASK;
|
||||
} else
|
||||
val = 0xFF;
|
||||
val = MB_get_mbyte(addr) & BYTEMASK;
|
||||
break;
|
||||
case 0xE000:
|
||||
val = BOOTROM_get_mbyte(addr - 0xE000) & 0xFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: EPROM=%02X\n", val);
|
||||
val = BOOTROM_get_mbyte(addr - 0xE000) & BYTEMASK;
|
||||
break;
|
||||
case 0xF000:
|
||||
if (CPU_BD_unit.flags & UNIT_MON) {
|
||||
val = BOOTROM_get_mbyte(addr - (0x10000 - BOOTROM_unit.capac)) & 0xFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: EPROM=%02X\n", val);
|
||||
EA1 = 0x10000 - BOOTROM_unit.capac;
|
||||
EA = addr - EA1;
|
||||
val = BOOTROM_get_mbyte(EA) & BYTEMASK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
val = MB_get_mbyte(addr) & 0xFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: mp_b2 val=%02X\n", val);
|
||||
val = MB_get_mbyte(addr) & BYTEMASK;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
@ -216,11 +207,9 @@ int32 CPU_BD_get_mword(int32 addr)
|
|||
{
|
||||
int32 val;
|
||||
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mword: addr=%04X\n", addr);
|
||||
val = (CPU_BD_get_mbyte(addr) << 8);
|
||||
val |= CPU_BD_get_mbyte(addr+1);
|
||||
val &= 0xFFFF;
|
||||
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mword: val=%04X\n", val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -228,8 +217,6 @@ int32 CPU_BD_get_mword(int32 addr)
|
|||
|
||||
void CPU_BD_put_mbyte(int32 addr, int32 val)
|
||||
{
|
||||
sim_debug (DEBUG_write, &CPU_BD_dev, "CPU_BD_put_mbyte: addr=%04X, val=%02X\n",
|
||||
addr, val);
|
||||
switch(addr & 0xF000) {
|
||||
case 0xA000:
|
||||
if (CPU_BD_unit.flags & UNIT_RAM)
|
||||
|
@ -246,25 +233,8 @@ void CPU_BD_put_mbyte(int32 addr, int32 val)
|
|||
|
||||
void CPU_BD_put_mword(int32 addr, int32 val)
|
||||
{
|
||||
sim_debug (DEBUG_write, &CPU_BD_dev, "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);
|
||||
}
|
||||
|
||||
t_stat mpa2_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
for (i=0; i<sim_emax; ++i)
|
||||
*eval_array++ = CPU_BD_get_mbyte(addr++);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat mpa2_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches)
|
||||
{
|
||||
CPU_BD_put_mbyte(addr,value);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* end of mp-a2.c */
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
MODIFICATIONS:
|
||||
|
||||
24 Apr 15 -- Modified to use simh_debug
|
||||
28 May 22 -- Roberto Sancho Villa (RSV) fixes for other disk controllers
|
||||
|
||||
NOTES:
|
||||
|
||||
|
@ -49,22 +49,20 @@
|
|||
|
||||
/* 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);
|
||||
// CPU Boards
|
||||
extern int32 CPU_BD_get_mbyte(int32 addr);
|
||||
extern int32 CPU_BD_get_mword(int32 addr);
|
||||
extern void CPU_BD_put_mbyte(int32 addr, int32 val);
|
||||
extern void CPU_BD_put_mword(int32 addr, int32 val);
|
||||
|
||||
/* empty I/O device routine */
|
||||
int32 nulldev(int32 io, int32 data);
|
||||
|
||||
/* SS-50 bus routines */
|
||||
/* SS-50 MB 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);
|
||||
t_stat mpb2_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches);
|
||||
t_stat mpb2_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches);
|
||||
|
||||
/* MP-8M bus routines */
|
||||
extern int32 mp_8m_get_mbyte(int32 addr);
|
||||
|
@ -85,6 +83,16 @@ extern int32 fdctrk(int32 io, int32 data);
|
|||
extern int32 fdcsec(int32 io, int32 data);
|
||||
extern int32 fdcdata(int32 io, int32 data);
|
||||
|
||||
/* LFD-400 FDC I/O routines */
|
||||
|
||||
extern int32 fd400_fdcstatus(int32 io, int32 data);
|
||||
extern int32 fd400_cstatus(int32 io, int32 data);
|
||||
extern int32 fd400_data(int32 io, int32 data);
|
||||
extern int32 fd400_cursect(int32 io, int32 data);
|
||||
extern int32 fd400_startrw(int32 io, int32 data);
|
||||
|
||||
extern DEVICE fd400_dsk_dev;
|
||||
|
||||
/* 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
|
||||
|
@ -107,6 +115,12 @@ struct idev dev_table[32] = {
|
|||
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /*Port 7 801C-801F*/
|
||||
};
|
||||
|
||||
/* RSV - LFD-400 routines */
|
||||
struct idev dev_table2[8] = {
|
||||
{&fd400_cstatus}, {&fd400_data}, {&fd400_cursect}, {&fd400_fdcstatus}, /* Port CC00-CC03 */
|
||||
{&fd400_startrw}, {&nulldev}, {&nulldev}, {&nulldev} /* Port CC04-CC07 */
|
||||
};
|
||||
|
||||
/* dummy i/o device */
|
||||
|
||||
int32 nulldev(int32 io, int32 data)
|
||||
|
@ -167,8 +181,8 @@ DEVICE MB_dev = {
|
|||
1, //aincr
|
||||
16, //dradix
|
||||
8, //dwidth
|
||||
mpb2_examine, //examine
|
||||
mpb2_deposit, //deposit
|
||||
NULL, //examine
|
||||
NULL, //deposit
|
||||
NULL, //reset
|
||||
NULL, //boot
|
||||
NULL, //attach
|
||||
|
@ -190,45 +204,45 @@ int32 MB_get_mbyte(int32 addr)
|
|||
switch(addr & 0xE000) {
|
||||
case 0x0000: //0000-1FFFh
|
||||
if (MB_unit.flags & UNIT_RAM_0000)
|
||||
val = mp_8m_get_mbyte(addr) & 0xFF;
|
||||
val = mp_8m_get_mbyte(addr) & BYTEMASK;
|
||||
else
|
||||
val = 0xFF;
|
||||
break;
|
||||
case 0x2000: //2000-3FFFh
|
||||
if (MB_unit.flags & UNIT_RAM_2000)
|
||||
val = mp_8m_get_mbyte(addr) & 0xFF;
|
||||
val = mp_8m_get_mbyte(addr) & BYTEMASK;
|
||||
else
|
||||
val = 0xFF;
|
||||
break;
|
||||
case 0x4000: //4000-5FFFh
|
||||
if (MB_unit.flags & UNIT_RAM_4000)
|
||||
val = mp_8m_get_mbyte(addr) & 0xFF;
|
||||
val = mp_8m_get_mbyte(addr) & BYTEMASK;
|
||||
else
|
||||
val = 0xFF;
|
||||
break;
|
||||
case 0x6000: //6000-7FFFh
|
||||
if (MB_unit.flags & UNIT_RAM_6000)
|
||||
val = mp_8m_get_mbyte(addr) & 0xFF;
|
||||
val = mp_8m_get_mbyte(addr) & BYTEMASK;
|
||||
else
|
||||
val = 0xFF;
|
||||
break;
|
||||
case 0x8000: //8000-9FFFh (I/O ports)
|
||||
if (addr < 0x8020)
|
||||
val = (dev_table[addr - 0x8000].routine(0, 0)) & 0xFF;
|
||||
else
|
||||
if (addr < 0x8020) {
|
||||
val = (dev_table[addr - 0x8000].routine(0, 0)) & BYTEMASK;
|
||||
} else
|
||||
val = 0xFF;
|
||||
sim_debug (DEBUG_read, &MB_dev, "MB_get_mbyte: I/O addr=%04X val=%02X\n",
|
||||
addr, val);
|
||||
break;
|
||||
case 0xA000: //A000-AFFFh
|
||||
if (MB_unit.flags & UNIT_RAM_A000)
|
||||
val = mp_8m_get_mbyte(addr) & 0xFF;
|
||||
val = mp_8m_get_mbyte(addr) & BYTEMASK;
|
||||
else
|
||||
val = 0xFF;
|
||||
break;
|
||||
case 0xC000: //C000-CFFFh
|
||||
if (MB_unit.flags & UNIT_RAM_C000)
|
||||
val = mp_8m_get_mbyte(addr) & 0xFF;
|
||||
if (((fd400_dsk_dev.flags & DEV_DIS) == 0) && ((addr & 0xFFF0) == 0xCC00)) //RSV
|
||||
val = (dev_table2[addr - 0xCC00].routine(0, 0));
|
||||
else if (MB_unit.flags & UNIT_RAM_C000)
|
||||
val = mp_8m_get_mbyte(addr) & BYTEMASK;
|
||||
else
|
||||
val = 0xFF;
|
||||
break;
|
||||
|
@ -244,11 +258,9 @@ int32 MB_get_mword(int32 addr)
|
|||
{
|
||||
int32 val;
|
||||
|
||||
sim_debug (DEBUG_read, &MB_dev, "MB_get_mword: addr=%04X\n", addr);
|
||||
val = (MB_get_mbyte(addr) << 8);
|
||||
val |= MB_get_mbyte(addr+1);
|
||||
val &= 0xFFFF;
|
||||
sim_debug (DEBUG_read, &MB_dev, "MB_get_mword: val=%04X\n", val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -282,7 +294,9 @@ void MB_put_mbyte(int32 addr, int32 val)
|
|||
mp_8m_put_mbyte(addr, val);
|
||||
break;
|
||||
case 0xC000: //C000-CFFFh
|
||||
if (MB_unit.flags & UNIT_RAM_C000)
|
||||
if (((fd400_dsk_dev.flags & DEV_DIS) == 0) && ((addr & 0xFFF0) == 0xCC00)) //RSV
|
||||
dev_table2[addr - 0xCC00].routine(1, val);
|
||||
else if (MB_unit.flags & UNIT_RAM_C000)
|
||||
mp_8m_put_mbyte(addr, val);
|
||||
break;
|
||||
default:
|
||||
|
@ -294,25 +308,9 @@ void MB_put_mbyte(int32 addr, int32 val)
|
|||
|
||||
void MB_put_mword(int32 addr, int32 val)
|
||||
{
|
||||
sim_debug (DEBUG_write, &MB_dev, "MB_ptt_mword: addr=%04X, val=%04X\n", addr, val);
|
||||
MB_put_mbyte(addr, val >> 8);
|
||||
MB_put_mbyte(addr+1, val);
|
||||
}
|
||||
|
||||
t_stat mpb2_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
for (i=0; i<sim_emax; ++i)
|
||||
*eval_array++ = CPU_BD_get_mbyte(addr++);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat mpb2_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches)
|
||||
{
|
||||
CPU_BD_put_mbyte(addr,value);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* end of mp-b2.c */
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
MODIFICATIONS:
|
||||
|
||||
24 Apr 15 -- Modified to use simh_debug
|
||||
28 May 22 -- Roberto Sancho Villa (RSV) fixes for DEL and BS
|
||||
|
||||
NOTES:
|
||||
|
||||
|
@ -64,6 +64,11 @@
|
|||
#define UNIT_V_TTY (UNIT_V_UF) // TTY or ANSI mode
|
||||
#define UNIT_TTY (1 << UNIT_V_TTY)
|
||||
|
||||
#define RXF 0x01
|
||||
#define TXE 0x02
|
||||
#define DCD 0x04
|
||||
#define CTS 0x08
|
||||
|
||||
/* local global variables */
|
||||
|
||||
int32 ptr_stopioe = 0; // stop on error
|
||||
|
@ -94,7 +99,8 @@ int32 sio1d(int32 io, int32 data);
|
|||
sio_reg SIO register list
|
||||
sio_mod SIO modifiers list */
|
||||
|
||||
UNIT sio_unit = { UDATA (&sio_svc, 0, 0), KBD_POLL_WAIT
|
||||
UNIT sio_unit = {
|
||||
UDATA (&sio_svc, 0, 0), KBD_POLL_WAIT
|
||||
};
|
||||
|
||||
REG sio_reg[] = {
|
||||
|
@ -110,10 +116,22 @@ MTAB sio_mod[] = {
|
|||
};
|
||||
|
||||
DEVICE sio_dev = {
|
||||
"MP-S", &sio_unit, sio_reg, sio_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &sio_reset,
|
||||
NULL, NULL, NULL
|
||||
"MP-S", //name
|
||||
&sio_unit, //units
|
||||
sio_reg, //registers
|
||||
sio_mod, //modifiers
|
||||
1, //numunits
|
||||
10, //aradix
|
||||
31, //awidth
|
||||
1, //aincr
|
||||
8, //dradix
|
||||
8, //dwidth
|
||||
NULL, //examine
|
||||
NULL, //deposit
|
||||
&sio_reset, //reset
|
||||
NULL, //boot
|
||||
NULL, //attach
|
||||
NULL //detach
|
||||
};
|
||||
|
||||
/* paper tape reader data structures
|
||||
|
@ -127,10 +145,22 @@ 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
|
||||
"PTR", //name
|
||||
&ptr_unit, //units
|
||||
NULL, //registers
|
||||
NULL, //modifiers
|
||||
1, //numunits
|
||||
10, //aradix
|
||||
31, //awidth
|
||||
1, //aincr
|
||||
8, //dradix
|
||||
8, //dwidth
|
||||
NULL, //examine
|
||||
NULL, //deposit
|
||||
&ptr_reset, //reset
|
||||
NULL, //boot
|
||||
NULL, //attach
|
||||
NULL //detach
|
||||
};
|
||||
|
||||
/* paper tape punch data structures
|
||||
|
@ -143,10 +173,22 @@ DEVICE ptr_dev = {
|
|||
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
|
||||
"PTP", //name
|
||||
&ptp_unit, //units
|
||||
NULL, //registers
|
||||
NULL, //modifiers
|
||||
1, //numunits
|
||||
10, //aradix
|
||||
31, //awidth
|
||||
1, //aincr
|
||||
8, //dradix
|
||||
8, //dwidth
|
||||
NULL, //examine
|
||||
NULL, //deposit
|
||||
&ptp_reset, //reset
|
||||
NULL, //boot
|
||||
NULL, //attach
|
||||
NULL //detach
|
||||
};
|
||||
|
||||
/* console input service routine */
|
||||
|
@ -158,8 +200,12 @@ t_stat sio_svc (UNIT *uptr)
|
|||
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
|
||||
sio_unit.buf = temp & BYTEMASK; // Save char
|
||||
if (sio_unit.buf==127) {
|
||||
// convert BackSpace (ascii 127) so del char (ascii 8) for swtbug
|
||||
sio_unit.buf=8;
|
||||
}
|
||||
sio_unit.u3 |= RXF; // Set RXF flag
|
||||
/* Do any special character handling here */
|
||||
sio_unit.pos++; // step character count
|
||||
return SCPE_OK;
|
||||
|
@ -174,8 +220,8 @@ t_stat ptr_svc (UNIT *uptr)
|
|||
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
|
||||
ptr_unit.buf = temp & BYTEMASK; // Save char
|
||||
ptr_unit.u3 |= RXF; // Set RXF flag
|
||||
/* Do any special character handling here */
|
||||
ptr_unit.pos++; // step character count
|
||||
return SCPE_OK;
|
||||
|
@ -192,8 +238,8 @@ t_stat ptp_svc (UNIT *uptr)
|
|||
|
||||
t_stat sio_reset (DEVICE *dptr)
|
||||
{
|
||||
sio_unit.buf = 0; // Data buffer
|
||||
sio_unit.u3 = 0x02; // Status buffer
|
||||
sio_unit.buf = 0; //clear data buffer
|
||||
sio_unit.u3 = TXE; //set TXE flag
|
||||
sio_unit.wait = 10000;
|
||||
sim_activate (&sio_unit, sio_unit.wait); // activate unit
|
||||
return SCPE_OK;
|
||||
|
@ -203,9 +249,8 @@ t_stat sio_reset (DEVICE *dptr)
|
|||
|
||||
t_stat ptr_reset (DEVICE *dptr)
|
||||
{
|
||||
ptr_unit.buf = 0;
|
||||
ptr_unit.u3 = 0x02;
|
||||
// sim_activate (&ptr_unit, ptr_unit.wait); // activate unit
|
||||
ptr_unit.buf = 0; //clear data buffer
|
||||
ptr_unit.u3 = TXE; //set TXE flag
|
||||
sim_cancel (&ptr_unit); // deactivate unit
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -214,9 +259,8 @@ t_stat ptr_reset (DEVICE *dptr)
|
|||
|
||||
t_stat ptp_reset (DEVICE *dptr)
|
||||
{
|
||||
ptp_unit.buf = 0;
|
||||
ptp_unit.u3 = 0x02;
|
||||
// sim_activate (&ptp_unit, ptp_unit.wait); // activate unit
|
||||
ptp_unit.buf = 0; //clear data buffer
|
||||
ptp_unit.u3 = TXE; //set TXE flag
|
||||
sim_cancel (&ptp_unit); // deactivate unit
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -229,15 +273,15 @@ 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_unit.u3 &= ~RXF; // 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_unit.u3 &= ~RXF; // clear RXF flag
|
||||
ptr_flag = 0; // clear reader flag
|
||||
} else // not EOF
|
||||
ptr_unit.u3 |= 0x01; // set ready
|
||||
ptr_unit.u3 |= RXF; // set ready
|
||||
}
|
||||
return (status = ptr_unit.u3); // return ptr status
|
||||
} else {
|
||||
|
@ -245,13 +289,13 @@ int32 sio0s(int32 io, int32 data)
|
|||
}
|
||||
} else { // control register write
|
||||
if (data == 0x03) { // reset port!
|
||||
sio_unit.u3 = 0x02; // reset console
|
||||
sio_unit.u3 = TXE; // reset console
|
||||
sio_unit.buf = 0;
|
||||
sio_unit.pos = 0;
|
||||
ptr_unit.u3 = 0x02; // reset reader
|
||||
ptr_unit.u3 = TXE; // reset reader
|
||||
ptr_unit.buf = 0;
|
||||
ptr_unit.pos = 0;
|
||||
ptp_unit.u3 = 0x02; // reset punch
|
||||
ptp_unit.u3 = TXE; // reset punch
|
||||
ptp_unit.buf = 0;
|
||||
ptp_unit.pos = 0;
|
||||
}
|
||||
|
@ -265,22 +309,18 @@ int32 sio0d(int32 io, int32 data)
|
|||
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 ((ptr_unit.u3 & RXF) == 0) // yes, more data?
|
||||
return (odata & BYTEMASK);
|
||||
if ((odata = getc(ptr_unit.fileref)) == EOF) { // end of file?
|
||||
// printf("Got EOF\n");
|
||||
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
|
||||
ptr_unit.u3 &= ~RXF; // clear RXF flag
|
||||
return (odata & BYTEMASK); // return character
|
||||
} else {
|
||||
sio_unit.u3 &= 0xFE; // clear RXF flag
|
||||
sio_unit.u3 &= ~RXF; // clear RXF flag
|
||||
return (odata = sio_unit.buf); // return next char
|
||||
}
|
||||
} else { // data register write
|
||||
|
@ -294,21 +334,25 @@ int32 sio0d(int32 io, int32 data)
|
|||
switch (data) {
|
||||
case 0x11: // PTR on
|
||||
ptr_flag = 1;
|
||||
ptr_unit.u3 |= 0x01;
|
||||
// printf("Reader on\n");
|
||||
ptr_unit.u3 |= RXF;
|
||||
printf("Reader on\n");
|
||||
break;
|
||||
case 0x12: // PTP on
|
||||
ptp_flag = 1;
|
||||
ptp_unit.u3 |= 0x02;
|
||||
// printf("Punch on\n");
|
||||
ptp_unit.u3 |= TXE;
|
||||
printf("Punch on\n");
|
||||
break;
|
||||
case 0x13: // PTR off
|
||||
ptr_flag = 0;
|
||||
// printf("Reader off-%d bytes read\n", ptr_unit.pos);
|
||||
if (ptr_unit.pos)
|
||||
printf("Reader off-%d bytes read\n", ptr_unit.pos);
|
||||
ptr_unit.pos = 0;
|
||||
break;
|
||||
case 0x14: // PTP off
|
||||
ptp_flag = 0;
|
||||
// printf("Punch off-%d bytes written\n", ptp_unit.pos);
|
||||
if (ptp_unit.pos)
|
||||
printf("Punch off-%d bytes written\n", ptp_unit.pos);
|
||||
ptp_unit.pos = 0;
|
||||
break;
|
||||
default: // ignore all other characters
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* mp-a2_sys.c: SWTP 6800 system interface
|
||||
/* mp-a2_sys.c: SWTP 6800 CPU Board Type 2
|
||||
|
||||
Copyright (c) 2005-2012, William Beech
|
||||
|
||||
|
@ -43,13 +43,7 @@ extern DEVICE ptr_dev;
|
|||
extern DEVICE ptp_dev;
|
||||
extern DEVICE mp_8m_dev;
|
||||
extern DEVICE dsk_dev;
|
||||
|
||||
/* external routines */
|
||||
|
||||
extern void CPU_BD_put_mbyte(int32 addr, int32 val);
|
||||
extern void CPU_BD_put_mword(int32 addr, int32 val);
|
||||
extern int32 CPU_BD_get_mbyte(int32 addr);
|
||||
extern int32 CPU_BD_get_mword(int32 addr);
|
||||
extern DEVICE fd400_dsk_dev;
|
||||
|
||||
extern int32 saved_PC; /* Program counter */
|
||||
|
||||
|
@ -70,8 +64,8 @@ REG *sim_PC = &m6800_reg[0];
|
|||
int32 sim_emax = 4;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&CPU_BD_dev,
|
||||
&m6800_dev,
|
||||
&CPU_BD_dev,
|
||||
&BOOTROM_dev,
|
||||
&m6810_dev,
|
||||
&i2716_dev,
|
||||
|
@ -81,6 +75,7 @@ DEVICE *sim_devices[] = {
|
|||
&ptp_dev,
|
||||
&mp_8m_dev,
|
||||
&dsk_dev,
|
||||
&fd400_dsk_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* mp-a_sys.c: SWTP 6800 system interface
|
||||
/* mp-a_sys.c: SWTP 6800 SWTP 6800 CPU Board Type 1
|
||||
|
||||
Copyright (c) 2005-2012, William Beech
|
||||
|
||||
|
@ -42,13 +42,7 @@ extern DEVICE ptr_dev;
|
|||
extern DEVICE ptp_dev;
|
||||
extern DEVICE mp_8m_dev;
|
||||
extern DEVICE dsk_dev;
|
||||
|
||||
/* external routines */
|
||||
|
||||
extern void CPU_BD_put_mbyte(int32 addr, int32 val);
|
||||
extern void CPU_BD_put_mword(int32 addr, int32 val);
|
||||
extern int32 CPU_BD_get_mbyte(int32 addr);
|
||||
extern int32 CPU_BD_get_mword(int32 addr);
|
||||
extern DEVICE fd400_dsk_dev;
|
||||
|
||||
extern int32 saved_PC; /* Program counter */
|
||||
|
||||
|
@ -69,8 +63,8 @@ REG *sim_PC = &m6800_reg[0];
|
|||
int32 sim_emax = 4;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&CPU_BD_dev,
|
||||
&m6800_dev,
|
||||
&CPU_BD_dev,
|
||||
&BOOTROM_dev,
|
||||
&m6810_dev,
|
||||
&MB_dev,
|
||||
|
@ -79,6 +73,7 @@ DEVICE *sim_devices[] = {
|
|||
&ptp_dev,
|
||||
&mp_8m_dev,
|
||||
&dsk_dev,
|
||||
&fd400_dsk_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue