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:
Bill Beech 2022-06-09 14:28:04 -07:00 committed by Mark Pizzolato
parent 087e0c7bc8
commit 44428e53b6
17 changed files with 1410 additions and 695 deletions

View file

@ -199,6 +199,10 @@
RelativePath="..\swtp6800\common\dc-4.c"
>
</File>
<File
RelativePath="..\swtp6800\common\fd400.c"
>
</File>
<File
RelativePath="..\swtp6800\common\m6800.c"
>

View file

@ -199,6 +199,10 @@
RelativePath="..\swtp6800\common\dc-4.c"
>
</File>
<File
RelativePath="..\swtp6800\common\fd400.c"
>
</File>
<File
RelativePath="..\swtp6800\common\i2716.c"
>

View file

@ -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.

View file

@ -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

View file

@ -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*/
@ -264,28 +277,34 @@
/* function prototypes */
t_stat dsk_reset (DEVICE *dptr);
t_stat dsk_reset (DEVICE *dptr);
t_stat dsk_attach (UNIT *uptr, CONST char *cptr);
/* 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);
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 fdcbyte;
int32 intrq; /* interrupt request flag */
int32 cur_dsk; /* Currently selected drive */
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,21 +315,21 @@ 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[] = {
{ HRDATA (DISK, cur_dsk, 4) },
{ NULL }
{ HRDATA (DISK, cur_dsk, 4) },
{ NULL }
};
MTAB dsk_mod[] = {
{ UNIT_ENABLE, UNIT_ENABLE, "RW", "RW", NULL },
{ UNIT_ENABLE, 0, "RO", "RO", NULL },
{ 0 }
{ UNIT_ENABLE, UNIT_ENABLE, "RW", "RW", NULL },
{ UNIT_ENABLE, 0, "RO", "RO", NULL },
{ 0 }
};
DEBTAB dsk_debug[] = {
@ -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].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);
case 0x0B: //restore command type I
dsk_unit[cur_dsk].u4 = 0; /* home the drive */
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,38 +604,48 @@ 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;
dsk_unit[cur_dsk].pos++; /* step counter */
if (dsk_unit[cur_dsk].pos == SECT_SIZE) { /* done? */
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdata: Sector read complete");
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 == 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 */
if (multiple_sector) {
multiple_sector=0;
}
}
}
return val;
} else
return 0;
return 0;
}
}

519
swtp6800/common/fd400.c Normal file
View 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 */

View file

@ -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

View file

@ -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,13 +41,12 @@
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),
0 };
UNIT m6810_unit = {
UDATA (NULL, UNIT_BINK, 128),
0 };
MTAB m6810_mod[] = {
{ 0 }
@ -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;
}

View file

@ -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 */

View file

@ -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 */

View file

@ -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);
@ -135,17 +131,17 @@ DEBTAB CPU_BD_debug[] = {
DEVICE CPU_BD_dev = {
"MP-A2", //name
&CPU_BD_unit, //units
CPU_BD_reg, //registers
CPU_BD_mod, //modifiers
&CPU_BD_unit, //units
CPU_BD_reg, //registers
CPU_BD_mod, //modifiers
1, //numunits
16, //aradix
16, //awidth
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 */

View file

@ -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
@ -95,16 +103,22 @@ struct idev {
};
struct idev dev_table[32] = {
{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 0 8000-8003 */
{&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /*Port 1 8004-8007 */
{&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*/
{&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*/
};
/* 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 */
@ -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 */

View file

@ -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;

View file

@ -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
};

View file

@ -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
};