Intel-Systems: Add enable/disable functionality for various option boards

This commit is contained in:
Bill Beech 2020-09-01 12:10:12 -07:00
parent 5c48229ce4
commit 782fe167ca
26 changed files with 1009 additions and 475 deletions

View file

@ -169,8 +169,8 @@ uint32 IM = 0; /* Interrupt Mask Register */
uint8 xack = 0; /* XACK signal */
uint32 int_req = 0; /* Interrupt request */
uint8 INTA = 0; // interrupt acknowledge
uint16 PCX; /* External view of PC */
uint16 PCY; /* Internal view of PC */
uint16 PCX; /* External view of PC */
uint16 PCY; /* Internal view of PC */
uint16 PC;
UNIT *uptr;
uint16 port; //port used in any IN/OUT
@ -294,7 +294,11 @@ DEVICE i8080_dev = {
0, //dctrl
i8080_debug, //debflags
NULL, //msize
NULL //lname
NULL, //lname
NULL, //help routine
NULL, //attach help routine
NULL, //help context
NULL //device description
};
/* tables for the disassembler */
@ -406,7 +410,6 @@ int32 sim_instr(void)
sim_printf(" CPU = 8085\n");
else
sim_printf(" CPU = 8080\n");
// sim_printf(" i8080:\n");
}
/* Main instruction fetch/decode loop */
@ -443,7 +446,7 @@ int32 sim_instr(void)
PC = 0x002C;
int_req &= ~I55;
} else if (int_req & INT_R) { /* intr */
push_word(PC); /* do an RST 7 */
push_word(PC); /* do an RST 7 */
PC = 0x0038;
int_req &= ~INT_R;
}

View file

@ -207,11 +207,15 @@ DEVICE i8251_dev = {
NULL, //attach
NULL, //detach
NULL, //ctxt
0, //flags
DEV_DISABLE, //flags
0, //dctrl
i8251_debug, //debflags
NULL, //msize
NULL //lname
NULL, //memeory size change
NULL, //lname
NULL, //help routine
NULL, //attach help routine
NULL, //help context
NULL //device description
};
// i8251 configuration

View file

@ -96,9 +96,9 @@ extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
/* these bytes represent the input and output to/from a port instance */
uint8 i8255_A[4]; //port A byte I/O
uint8 i8255_B[4]; //port B byte I/O
uint8 i8255_C[4]; //port C byte I/O
uint8 i8255_A[I8255_NUM]; //port A byte I/O
uint8 i8255_B[I8255_NUM]; //port B byte I/O
uint8 i8255_C[I8255_NUM]; //port C byte I/O
/* external globals */
@ -173,12 +173,12 @@ DEVICE i8255_dev = {
t_stat i8255_cfg(uint8 base, uint8 devnum)
{
sim_printf(" i8255[%d]: at base port 0%02XH\n",
devnum, base & 0xFF);
reg_dev(i8255a, base, devnum);
reg_dev(i8255b, base + 1, devnum);
reg_dev(i8255c, base + 2, devnum);
reg_dev(i8255s, base + 3, devnum);
sim_printf(" i8255[%d]: at base port 0%02XH\n",
devnum, base & 0xFF);
return SCPE_OK;
}

View file

@ -140,10 +140,10 @@ DEVICE i8259_dev = {
t_stat i8259_cfg(uint8 base, uint8 devnum)
{
reg_dev(i8259a, base, devnum);
reg_dev(i8259b, base + 1, devnum);
sim_printf(" i8259[%d]: at base port 0%02XH\n",
devnum, base & 0xFF);
reg_dev(i8259a, base, devnum);
reg_dev(i8259b, base + 1, devnum);
return SCPE_OK;
}

View file

@ -62,7 +62,6 @@ extern t_stat ioc_cont_cfg(uint8 base, uint8 devnum);
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
extern t_stat EPROM_cfg(uint16 base, uint16 size, uint8 devnum);
extern t_stat RAM_cfg(uint16 base, uint16 size);
extern t_stat multibus_cfg();
/* globals */
@ -109,7 +108,6 @@ t_stat SBC_reset (DEVICE *dptr)
{
if (onetime == 0) {
SBC_config();
multibus_cfg();
onetime++;
}
i8080_reset(&i8080_dev);
@ -126,7 +124,7 @@ t_stat SBC_reset (DEVICE *dptr)
uint8 get_mbyte(uint16 addr)
{
SET_XACK(1); /* set no XACK */
SET_XACK(0); /* set XACK */
if (addr >= 0xF800) { //monitor ROM - always there
return EPROM_get_mbyte(addr - 0xF000, 0); //top half of EPROM
}
@ -139,7 +137,6 @@ uint8 get_mbyte(uint16 addr)
if (addr < 0x8000) { //IPB RAM
return RAM_get_mbyte(addr);
}
SET_XACK(0); /* set no XACK */
return multibus_get_mbyte(addr); //check multibus cards
}
@ -160,13 +157,13 @@ void put_mbyte(uint16 addr, uint8 val)
{
SET_XACK(0); /* set no XACK */
if (addr >= 0xF800) { //monitor ROM - always there
return;
return; //do nothing
}
if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup
return;
return; //do nothing
}
if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM
return;
return; //do nothing
}
if (addr < 0x8000) {
RAM_put_mbyte(addr, val); //IPB RAM

View file

@ -65,7 +65,6 @@ extern t_stat ioc_cont_cfg(uint8 base, uint8 devnum);
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
extern t_stat EPROM_cfg(uint16 base, uint16 size, uint8 devnum);
extern t_stat RAM_cfg(uint16 base, uint16 size);
extern t_stat multibus_cfg();
/* external globals */
@ -112,7 +111,6 @@ t_stat SBC_reset (DEVICE *dptr)
{
if (onetime == 0) {
SBC_config();
multibus_cfg();
onetime++;
}
i8080_reset(&i8080_dev);

View file

@ -37,15 +37,15 @@
#include "system_defs.h"
#if defined (SBC064_NUM) && (SBC064_NUM > 0)
#if defined (SBC064_NUM) && (SBC064_NUM > 0) //if board allowed with this system
#define UNIT_V_MSIZE (UNIT_V_UF+2) /* Memory Size */
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
#define BASE_ADDR u3
/* prototypes */
t_stat isbc064_cfg(uint16 base, uint16 size);
t_stat isbc064_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc064_set_base(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc064_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat isbc064_reset(DEVICE *dptr);
uint8 isbc064_get_mbyte(uint16 addr);
void isbc064_put_mbyte(uint16 addr, uint8 val);
@ -54,6 +54,8 @@ void isbc064_put_mbyte(uint16 addr, uint8 val);
/* local globals */
int isbc064_onetime = 1;
/* external globals */
extern uint8 xack;
@ -61,14 +63,37 @@ extern uint8 xack;
/* isbc064 Standard SIMH Device Data Structures */
UNIT isbc064_unit = {
UDATA (NULL, UNIT_FIX+UNIT_DISABLE+UNIT_BINK, 65536), KBD_POLL_WAIT
UDATA (NULL, 0, 0)
};
MTAB isbc064_mod[] = {
{ UNIT_MSIZE, 16384, "16K", "16K", &isbc064_set_size },
{ UNIT_MSIZE, 32768, "32K", "32K", &isbc064_set_size },
{ UNIT_MSIZE, 49152, "48K", "48K", &isbc064_set_size },
{ UNIT_MSIZE, 65536, "64K", "64K", &isbc064_set_size },
{ MTAB_XTD | MTAB_VDV, /* mask */
0, /* match */
NULL, /* print string */
"SIZE", /* match string */
&isbc064_set_size, /* validation routine */
NULL, /* display routine */
NULL, /* location descriptor */
"Sets the RAM size for iSB 064" /* help string */
},
{ MTAB_XTD | MTAB_VDV, /* mask */
0 /* match */,
NULL, /* print string */
"BASE", /* match string */
&isbc064_set_base, /* validation routine */
NULL, /* display routine */
NULL, /* location descriptor */
"Sets the RAM base for iSBC 064" /* help string */
},
{ MTAB_XTD|MTAB_VDV, /* mask */
0, /* match */
"PARAM", /* print string */
NULL, /* match string */
NULL, /* validation routine */
&isbc064_show_param, /* display routine */
NULL, /* location descriptor */
"Show current Parameters for iSBC 064" /* help string */
},
{ 0 }
};
@ -96,45 +121,78 @@ DEVICE isbc064_dev = {
8, //dwidth
NULL, //examine
NULL, //deposit
NULL, //reset
&isbc064_reset, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
DEV_DISABLE+DEV_DIS, //flags
0, //dctrl
isbc064_debug, //debflags
NULL, //msize
NULL //lname
NULL, //lname
NULL, //help routine
NULL, //attach help routine
NULL, //help context
NULL //device description
};
/* Service routines to handle simulator functions */
// configuration routine
t_stat isbc064_cfg(uint16 base, uint16 size)
{
sim_printf(" sbc064: 0%04XH bytes at base 0%04XH\n",
size, base);
isbc064_unit.capac = size; //set size
isbc064_unit.u3 = base; //and base
isbc064_unit.filebuf = (uint8 *)calloc(size, sizeof(uint8));
if (isbc064_unit.filebuf == NULL) {
sim_printf (" sbc064: Calloc error\n");
return SCPE_MEM;
}
return SCPE_OK;
}
// set size parameter
t_stat isbc064_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if ((val <= 0) || (val > MAXMEMSIZE)) {
sim_printf("Memory size error - val=%d\n", val);
uint32 size, result, i;
if (cptr == NULL)
return SCPE_ARG;
}
isbc064_reset(&isbc064_dev);
isbc064_unit.capac = val;
sim_printf("SBC064: Size set to %04X\n", val);
result = sscanf(cptr, "%i%n", &size, &i);
if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) ||
((cptr[i + 1] == 'B') && (cptr[i + 2] == 0)))) {
if (size & 0xff8f) {
sim_printf("SBC064: Size error\n");
return SCPE_ARG;
} else {
isbc064_unit.capac = (size * 1024) - 1;
sim_printf("SBC064: Size=%04XH\n", isbc064_unit.capac);
return SCPE_OK;
}
}
return SCPE_ARG;
}
// set base address parameter
t_stat isbc064_set_base(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 size, result, i;
if (cptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%i%n", &size, &i);
if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) ||
((cptr[i + 1] == 'B') && (cptr[i + 2] == 0)))) {
if (size & 0xff8f) {
sim_printf("SBC064: Base error\n");
return SCPE_ARG;
} else {
isbc064_unit.BASE_ADDR = size * 1024;
sim_printf("SBC064: Base=%04XH\n", isbc064_unit.BASE_ADDR);
return SCPE_OK;
}
}
return SCPE_ARG;
}
// show configuration parameters
t_stat isbc064_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
fprintf(st, "%s Base=%04XH Size=%04XH ",
((isbc064_dev.flags & DEV_DIS) == 0) ? "Enabled" : "Disabled",
isbc064_unit.BASE_ADDR, isbc064_unit.capac);
return SCPE_OK;
}
@ -142,6 +200,26 @@ t_stat isbc064_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
t_stat isbc064_reset (DEVICE *dptr)
{
if (dptr == NULL)
return SCPE_ARG;
if (isbc064_onetime) {
isbc064_dev.units->capac = SBC064_SIZE; //set default size
isbc064_dev.units->BASE_ADDR = SBC064_BASE; //set default base
isbc064_onetime = 0;
}
if ((dptr->flags & DEV_DIS) == 0) { //already enabled
isbc064_dev.units->filebuf = (uint8 *)calloc(isbc064_unit.capac, sizeof(uint8)); //alloc buffer
if (isbc064_dev.units->filebuf == NULL) { //CALLOC error
sim_printf (" sbc064: Calloc error\n");
return SCPE_MEM;
}
sim_printf(" sbc064: Enabled 0%04XH bytes at base 0%04XH\n",
isbc064_dev.units->capac, isbc064_dev.units->BASE_ADDR);
} else {
if (isbc064_dev.units->filebuf)
free(isbc064_dev.units->filebuf); //return allocated memory
sim_printf(" sbc064: Disabled\n");
}
return SCPE_OK;
}
@ -151,7 +229,7 @@ uint8 isbc064_get_mbyte(uint16 addr)
{
uint8 val;
val = *((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.u3));
val = *((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.BASE_ADDR));
return (val & 0xFF);
}
@ -159,7 +237,7 @@ uint8 isbc064_get_mbyte(uint16 addr)
void isbc064_put_mbyte(uint16 addr, uint8 val)
{
*((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.u3)) = val & 0xFF;
*((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.BASE_ADDR)) = val & 0xFF;
return;
}

View file

@ -206,6 +206,8 @@
#define MAXSECSD 26 //single density last sector
#define MAXTRK 76 //last track
#define isbc201_NAME "Intel iSBC 201 Floppy Disk Controller Board"
/* external globals */
extern uint16 PCX;
@ -213,16 +215,20 @@ extern uint16 PCX;
/* external function prototypes */
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
extern uint8 multibus_get_mbyte(uint16 addr);
extern void multibus_put_mbyte(uint16 addr, uint8 val);
extern uint8 unreg_dev(uint8);
extern uint8 get_mbyte(uint16 addr);
extern void put_mbyte(uint16 addr, uint8 val);
/* function prototypes */
t_stat isbc201_cfg(uint8 base);
t_stat isbc201_reset(DEVICE *dptr);
void isbc201_reset1(void);
t_stat isbc201_attach (UNIT *uptr, CONST char *cptr);
t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc201_set_port (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc201_set_int (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc201_set_verb (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc201_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat isbc201_reset(DEVICE *dptr);
void isbc201_reset_dev(void);
t_stat isbc201_attach (UNIT *uptr, CONST char *cptr);
uint8 isbc201r0(t_bool io, uint8 data, uint8 devnum); /* isbc201 0 */
uint8 isbc201r1(t_bool io, uint8 data, uint8 devnum); /* isbc201 1 */
uint8 isbc201r2(t_bool io, uint8 data, uint8 devnum); /* isbc201 2 */
@ -232,12 +238,20 @@ void isbc201_diskio(void); //do actual disk i/o
/* globals */
int isbc201_onetime = 1;
static const char* isbc201_desc(DEVICE *dptr) {
return isbc201_NAME;
}
typedef struct { //FDD definition
uint8 sec;
uint8 cyl;
} FDDDEF;
typedef struct { //FDC definition
uint8 baseport; //FDC base port
uint8 intnum; //interrupt number
uint8 verb; //verbose flag
uint16 iopb; //FDC IOPB
uint8 stat; //FDC status
uint8 rdychg; //FDC ready changed
@ -248,13 +262,13 @@ typedef struct { //FDC definition
FDDDEF fdd[FDD_NUM]; //indexed by the FDD number
} FDCDEF;
FDCDEF fdc201;
FDCDEF fdc201; //indexed by the isbc-202 instance number
/* isbc201 Standard I/O Data Structures */
UNIT isbc201_unit[] = { //2 FDDs
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF, MDSSD) }
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSSD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSSD) }
};
REG isbc201_reg[] = {
@ -269,6 +283,14 @@ REG isbc201_reg[] = {
MTAB isbc201_mod[] = {
{ UNIT_WPMODE, 0, "RW", "RW", &isbc201_set_mode },
{ UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc201_set_mode },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "VERB", &isbc201_set_verb,
NULL, NULL, "Sets the verbose mode for iSBC201"},
{ MTAB_XTD | MTAB_VDV, 0, NULL, "PORT", &isbc201_set_port,
NULL, NULL, "Sets the base port for iSBC201"},
{ MTAB_XTD | MTAB_VDV, 0, NULL, "INT", &isbc201_set_int,
NULL, NULL, "Sets the interrupt number for iSBC201"},
{ MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, &isbc201_show_param, NULL,
"show configured parametes for iSBC201" },
{ 0 }
};
@ -307,41 +329,140 @@ DEVICE isbc201_dev = {
0, //dctrl
isbc201_debug, //debflags
NULL, //msize
NULL //lname
NULL, //lname
NULL, //help routine
NULL, //attach help routine
NULL, //help context
&isbc201_desc //device description
};
// configuration routine
/* fdc201 set mode = Write protect */
t_stat isbc201_cfg(uint8 base)
t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int32 i;
UNIT *uptr;
sim_printf(" sbc201: at base 0%02XH\n",
base);
reg_dev(isbc201r0, base, 0); //read status
reg_dev(isbc201r1, base + 1, 0); //read rslt type/write IOPB addr-l
reg_dev(isbc201r2, base + 2, 0); //write IOPB addr-h and start
reg_dev(isbc201r3, base + 3, 0); //read rstl byte
reg_dev(isbc201r7, base + 7, 0); //write reset fdc201
// one-time initialization for all FDDs for this FDC instance
for (i = 0; i < FDD_NUM; i++) {
uptr = isbc201_dev.units + i;
uptr->u6 = i; //fdd unit number
if (uptr == NULL)
return SCPE_ARG;
if (uptr->flags & UNIT_ATT)
return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename);
if (val & UNIT_WPMODE) { /* write protect */
uptr->flags |= val;
if (fdc201.verb)
sim_printf(" sbc201: WP\n");
} else { /* read write */
uptr->flags &= ~val;
if (fdc201.verb)
sim_printf(" sbc201: RW\n");
}
return SCPE_OK;
}
// set base address parameter
t_stat isbc201_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 size, result;
if (uptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%02x", &size);
fdc201.baseport = size;
if (fdc201.verb)
sim_printf("SBC201: Base port=%04X\n", fdc201.baseport);
return SCPE_OK;
}
// set interrupt parameter
t_stat isbc201_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 size, result;
if (uptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%02x", &size);
fdc201.intnum = size;
if (fdc201.verb)
sim_printf("SBC201: Interrupt number=%04X\n", fdc201.intnum);
return SCPE_OK;
}
t_stat isbc201_set_verb(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (uptr == NULL)
return SCPE_ARG;
if (cptr == NULL)
return SCPE_ARG;
if (strncasecmp(cptr, "OFF", 4) == 0) {
fdc201.verb = 0;
return SCPE_OK;
}
if (strncasecmp(cptr, "ON", 3) == 0) {
fdc201.verb = 1;
sim_printf(" SBC201: fdc201.verb=%d\n", fdc201.verb);
return SCPE_OK;
}
return SCPE_ARG;
}
// show configuration parameters
t_stat isbc201_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (uptr == NULL)
return SCPE_ARG;
fprintf(st, "%s Base port at %04X Interrupt # is %i %s",
((isbc201_dev.flags & DEV_DIS) == 0) ? "Enabled" : "Disabled",
fdc201.baseport, fdc201.intnum,
fdc201.verb ? "Verbose" : "Quiet"
);
return SCPE_OK;
}
/* Hardware reset routine */
t_stat isbc201_reset(DEVICE *dptr)
{
isbc201_reset1();
int i;
UNIT *uptr;
if (dptr == NULL)
return SCPE_ARG;
if (isbc201_onetime) {
fdc201.baseport = SBC201_BASE; //set default base
fdc201.intnum = SBC201_INT; //set default interrupt
fdc201.verb = 0; //set verb = 0
isbc201_onetime = 0;
// one-time initialization for all FDDs for this FDC instance
for (i = 0; i < FDD_NUM; i++) {
uptr = isbc201_dev.units + i;
uptr->u6 = i; //fdd unit number
}
}
if ((dptr->flags & DEV_DIS) == 0) { // enabled
reg_dev(isbc201r0, fdc201.baseport, 0); //read status
reg_dev(isbc201r1, fdc201.baseport + 1, 0); //read rslt type/write IOPB addr-l
reg_dev(isbc201r2, fdc201.baseport + 2, 0); //write IOPB addr-h and start
reg_dev(isbc201r3, fdc201.baseport + 3, 0); //read rstl byte
reg_dev(isbc201r7, fdc201.baseport + 7, 0); //write reset fdc201
isbc201_reset_dev(); //software reset
// if (fdc201.verb)
sim_printf(" sbc201: Enabled base port at 0%02XH Interrupt #=%02X %s\n",
fdc201.baseport, fdc201.intnum, fdc201.verb ? "Verbose" : "Quiet" );
} else {
unreg_dev(fdc201.baseport); //read status
unreg_dev(fdc201.baseport + 1); //read rslt type/write IOPB addr-l
unreg_dev(fdc201.baseport + 2); //write IOPB addr-h and start
unreg_dev(fdc201.baseport + 3); //read rstl byte
unreg_dev(fdc201.baseport + 7); //write reset fdc201
// if (fdc201.verb)
sim_printf(" sbc201: Disabled\n");
}
return SCPE_OK;
}
/* Software reset routine */
void isbc201_reset1(void)
void isbc201_reset_dev(void)
{
int32 i;
UNIT *uptr;
@ -395,20 +516,6 @@ t_stat isbc201_attach (UNIT *uptr, CONST char *cptr)
return SCPE_OK;
}
/* fdc201 set mode = Write protect */
t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (uptr->flags & UNIT_ATT)
return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename);
if (val & UNIT_WPMODE) { /* write protect */
uptr->flags |= val;
} else { /* read write */
uptr->flags &= ~val;
}
return SCPE_OK;
}
/* I/O instruction handlers, called from the CPU module when an
IN or OUT instruction is issued.
*/
@ -471,7 +578,7 @@ uint8 isbc201r7(t_bool io, uint8 data, uint8 devnum)
if (io == 0) { /* read data port */
;
} else { /* write data port */
isbc201_reset1();
isbc201_reset_dev();
}
return 0;
}
@ -489,21 +596,21 @@ void isbc201_diskio(void)
uint8 *fbuf;
//parse the IOPB
cw = multibus_get_mbyte(fdc201.iopb);
di = multibus_get_mbyte(fdc201.iopb + 1);
nr = multibus_get_mbyte(fdc201.iopb + 2);
ta = multibus_get_mbyte(fdc201.iopb + 3);
sa = multibus_get_mbyte(fdc201.iopb + 4) & 0x1f;
ba = multibus_get_mbyte(fdc201.iopb + 5);
ba |= (multibus_get_mbyte(fdc201.iopb + 6) << 8);
bn = multibus_get_mbyte(fdc201.iopb + 7);
ni = multibus_get_mbyte(fdc201.iopb + 8);
ni |= (multibus_get_mbyte(fdc201.iopb + 9) << 8);
cw = get_mbyte(fdc201.iopb);
di = get_mbyte(fdc201.iopb + 1);
nr = get_mbyte(fdc201.iopb + 2);
ta = get_mbyte(fdc201.iopb + 3);
sa = get_mbyte(fdc201.iopb + 4) & 0x1f;
ba = get_mbyte(fdc201.iopb + 5);
ba |= (get_mbyte(fdc201.iopb + 6) << 8);
bn = get_mbyte(fdc201.iopb + 7);
ni = get_mbyte(fdc201.iopb + 8);
ni |= (get_mbyte(fdc201.iopb + 9) << 8);
fddnum = (di & 0x10) >> 4;
uptr = isbc201_dev.units + fddnum;
fbuf = (uint8 *) (isbc201_dev.units + fddnum)->filebuf;
//check for not ready
switch(fddnum) {
switch(fddnum) {
case 0:
if ((fdc201.stat & RDY0) == 0) {
fdc201.rtype = ROK;
@ -571,7 +678,7 @@ void isbc201_diskio(void)
sim_printf("\n SBC201: FDD %d - Write protect error 1", fddnum);
return;
}
fmtb = multibus_get_mbyte(ba); //get the format byte
fmtb = get_mbyte(ba); //get the format byte
//calculate offset into disk image
dskoff = ((ta * MAXSECSD) + (sa - 1)) * SECSIZ;
for(i=0; i<=((uint32)(MAXSECSD) * SECSIZ); i++) {
@ -589,7 +696,7 @@ void isbc201_diskio(void)
//copy sector from image to RAM
for (i=0; i<SECSIZ; i++) {
data = *(fbuf + (dskoff + i));
multibus_put_mbyte(ba + i, data);
put_mbyte(ba + i, data);
}
sa++;
ba+=0x80;
@ -613,7 +720,7 @@ void isbc201_diskio(void)
//calculate offset into disk image
dskoff = ((ta * MAXSECSD) + (sa - 1)) * SECSIZ;
for (i=0; i<SECSIZ; i++) { //copy sector from image to RAM
data = multibus_get_mbyte(ba + i);
data = get_mbyte(ba + i);
*(fbuf + (dskoff + i)) = data;
}
sa++;

View file

@ -27,11 +27,6 @@
27 Jun 16 - Original file.
NOTES:
This controller will mount 4 DD disk images on drives :F0: thru :F3: addressed
at ports 078H to 07FH.
Registers:
078H - Read - Subsystem status
@ -128,7 +123,24 @@
u4 -
u5 -
u6 - fdd number.
NOTES:
This iSBC 202 device simulator (DEVICES) supports 4 floppy disk drives
(UNITS). It uses the SBC202_BASE and SBC202_INT from system_defs.h to
set the default base port and interrupt.
The default base port can be changed by "sim> set sbc202 port=88". The
default interrupt can be changed by "sim> set sbc202 int=5". Current
settings can be shown by "sim> show sbc202 param".
This device simulator can be enabled or disabled if SBC202_NUM in
system_defs.h is set to 1. Only one board can be simulated. It is
enabled by "sim> Sset sbc202 ena" and disabled by "sim> set sbc202 dis".
The disk images in each FDD can be set to RW or WP. They default to WP
*/
#include "system_defs.h" /* system header in system dir */
@ -184,6 +196,8 @@
#define MAXSECDD 52 //double density last sector
#define MAXTRK 76 //last track
#define isbc202_NAME "Intel iSBC 202 Floppy Disk Controller Board"
/* external globals */
extern uint16 PCX;
@ -191,12 +205,16 @@ extern uint16 PCX;
/* external function prototypes */
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
extern uint8 unreg_dev(uint8);
extern uint8 get_mbyte(uint16 addr);
extern void put_mbyte(uint16 addr, uint8 val);
/* function prototypes */
t_stat isbc202_cfg(uint8 base);
t_stat isbc202_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc202_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc202_set_verb(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc202_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat isbc202_reset(DEVICE *dptr);
void isbc202_reset_dev(void);
t_stat isbc202_attach (UNIT *uptr, CONST char *cptr);
@ -210,13 +228,21 @@ void isbc202_diskio(void); //do actual disk i/o
/* globals */
int isbc202_onetime = 1;
static const char* isbc202_desc(DEVICE *dptr) {
return isbc202_NAME;
}
typedef struct { //FDD definition
uint8 sec;
uint8 cyl;
} FDDDEF;
typedef struct { //FDC definition
// uint16 baseport; //FDC base port
uint8 baseport; //FDC base port
uint8 intnum; //interrupt number
uint8 verb; //verbose flag
uint16 iopb; //FDC IOPB
uint8 stat; //FDC status
uint8 rdychg; //FDC ready change
@ -227,15 +253,15 @@ typedef struct { //FDC definition
FDDDEF fdd[FDD_NUM]; //indexed by the FDD number
} FDCDEF;
FDCDEF fdc202; //indexed by the isbc-202 instance number
FDCDEF fdc202; //indexed by the isbc-202 instance number
/* isbc202 Standard I/O Data Structures */
UNIT isbc202_unit[] = { // 4 FDDs
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD) },
{ NULL }
};
@ -251,6 +277,14 @@ REG isbc202_reg[] = {
MTAB isbc202_mod[] = {
{ UNIT_WPMODE, 0, "RW", "RW", &isbc202_set_mode },
{ UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc202_set_mode },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "VERB", &isbc202_set_verb,
NULL, NULL, "Sets the verbose mode for iSBC202"},
{ MTAB_XTD | MTAB_VDV, 0, NULL, "PORT", &isbc202_set_port,
NULL, NULL, "Sets the base port for iSBC202"},
{ MTAB_XTD | MTAB_VDV, 0, NULL, "INT", &isbc202_set_int,
NULL, NULL, "Sets the interrupt number for iSBC202"},
{ MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, &isbc202_show_param, NULL,
"show configured parametes for iSBC202" },
{ 0 }
};
@ -289,36 +323,135 @@ DEVICE isbc202_dev = {
0, //dctrl
isbc202_debug, //debflags
NULL, //msize
NULL //lname
NULL, //lname
NULL, //help routine
NULL, //attach help routine
NULL, //help context
&isbc202_desc //device description
};
// configuration routine
/* isbc202 set mode = Write protect */
t_stat isbc202_cfg(uint8 base)
t_stat isbc202_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int32 i;
UNIT *uptr;
sim_printf(" sbc202: at base 0%02XH\n",
base);
reg_dev(isbc202r0, base, 0); //read status
reg_dev(isbc202r1, base + 1, 0); //read rslt type/write IOPB addr-l
reg_dev(isbc202r2, base + 2, 0); //write IOPB addr-h and start
reg_dev(isbc202r3, base + 3, 0); //read rstl byte
reg_dev(isbc202r7, base + 7, 0); //write reset fdc201
// one-time initialization for all FDDs for this FDC instance
for (i = 0; i < FDD_NUM; i++) {
uptr = isbc202_dev.units + i;
uptr->u6 = i; //fdd unit number
if (uptr == NULL)
return SCPE_ARG;
if (uptr->flags & UNIT_ATT)
return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr),
uptr->filename);
if (val & UNIT_WPMODE) { /* write protect */
uptr->flags |= val;
if (fdc202.verb)
sim_printf(" sbc202: WP\n");
} else { /* read write */
uptr->flags &= ~val;
if (fdc202.verb)
sim_printf(" sbc202: RW\n");
}
return SCPE_OK;
}
// set base address parameter
t_stat isbc202_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 size, result;
if (uptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%02x", &size);
fdc202.baseport = size;
if (fdc202.verb)
sim_printf("SBC202: Base port=%04X\n", fdc202.baseport);
return SCPE_OK;
}
// set interrupt parameter
t_stat isbc202_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 size, result;
if (uptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%02x", &size);
fdc202.intnum = size;
if (fdc202.verb)
sim_printf("SBC202: Interrupt number=%04X\n", fdc202.intnum);
return SCPE_OK;
}
t_stat isbc202_set_verb(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (uptr == NULL)
return SCPE_ARG;
if (cptr == NULL)
return SCPE_ARG;
if (strncasecmp(cptr, "OFF", 4) == 0) {
fdc202.verb = 0;
return SCPE_OK;
}
if (strncasecmp(cptr, "ON", 3) == 0) {
fdc202.verb = 1;
sim_printf(" SBC202: fdc202.verb=%d\n", fdc202.verb);
return SCPE_OK;
}
return SCPE_ARG;
}
// show configuration parameters
t_stat isbc202_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (uptr == NULL)
return SCPE_ARG;
fprintf(st, "%s Base port at %04X Interrupt # is %i %s",
((isbc202_dev.flags & DEV_DIS) == 0) ? "Enabled" : "Disabled",
fdc202.baseport, fdc202.intnum,
fdc202.verb ? "Verbose" : "Quiet"
);
return SCPE_OK;
}
/* Hardware reset routine */
t_stat isbc202_reset(DEVICE *dptr)
{
isbc202_reset_dev(); //software reset
int i;
UNIT *uptr;
if (dptr == NULL)
return SCPE_ARG;
if (isbc202_onetime) {
fdc202.baseport = SBC202_BASE; //set default base
fdc202.intnum = SBC202_INT; //set default interrupt
fdc202.verb = 0; //set verb = off
isbc202_onetime = 0;
// one-time initialization for all FDDs for this FDC instance
for (i = 0; i < FDD_NUM; i++) {
uptr = isbc202_dev.units + i;
uptr->u6 = i; //fdd unit number
}
}
if ((dptr->flags & DEV_DIS) == 0) { // enabled
reg_dev(isbc202r0, fdc202.baseport, 0); //read status
reg_dev(isbc202r1, fdc202.baseport + 1, 0); //read rslt type/write IOPB addr-l
reg_dev(isbc202r2, fdc202.baseport + 2, 0); //write IOPB addr-h and start
reg_dev(isbc202r3, fdc202.baseport + 3, 0); //read rstl byte
reg_dev(isbc202r7, fdc202.baseport + 7, 0); //write reset fdc201
isbc202_reset_dev(); //software reset
// if (fdc202.verb)
sim_printf(" sbc202: Enabled base port at 0%02XH Interrupt #=%02X %s\n",
fdc202.baseport, fdc202.intnum, fdc202.verb ? "Verbose" : "Quiet" );
} else {
unreg_dev(fdc202.baseport); //read status
unreg_dev(fdc202.baseport + 1); //read rslt type/write IOPB addr-l
unreg_dev(fdc202.baseport + 2); //write IOPB addr-h and start
unreg_dev(fdc202.baseport + 3); //read rstl byte
unreg_dev(fdc202.baseport + 7); //write reset fdc201
// if (fdc202.verb)
sim_printf(" sbc202: Disabled\n");
}
return SCPE_OK;
}
@ -394,20 +527,6 @@ t_stat isbc202_attach (UNIT *uptr, CONST char *cptr)
return SCPE_OK;
}
/* isbc202 set mode = Write protect */
t_stat isbc202_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (uptr->flags & UNIT_ATT)
return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename);
if (val & UNIT_WPMODE) { /* write protect */
uptr->flags |= val;
} else { /* read write */
uptr->flags &= ~val;
}
return SCPE_OK;
}
/* iSBC202 control port functions */
uint8 isbc202r0(t_bool io, uint8 data, uint8 devnum)
@ -638,7 +757,8 @@ void isbc202_diskio(void)
fdc202.intff = 1; //set interrupt FF
break;
default:
sim_printf("\n SBC202: FDD %d - isbc202_diskio bad di=%02X", fddnum, di & 0x07);
sim_printf("\n SBC202: FDD %d - isbc202_diskio bad command di=%02X",
fddnum, di & 0x07);
break;
}
}

View file

@ -133,7 +133,7 @@
#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */
#define UNIT_WPMODE (1 << UNIT_V_WPMODE)
#define HD_NUM 2 //one fixed and one removable
#define HDD_NUM 2 //one fixed and one removable
//disk controller operations
#define DNOP 0x00 //HDC no operation
@ -174,6 +174,8 @@
#define MAXSECHD 144 //hard disk last sector (2 heads/2 tracks)
#define MAXTRKHD 206 //hard disk last track
#define isbc206_NAME "Intel iSBC 206 Hard Disk Controller Board"
/* external globals */
extern uint16 PCX;
@ -181,16 +183,18 @@ extern uint16 PCX;
/* external function prototypes */
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
extern uint8 multibus_get_mbyte(uint16 addr);
extern uint16 multibus_get_mword(uint16 addr);
extern void multibus_put_mbyte(uint16 addr, uint8 val);
extern uint8 multibus_put_mword(uint16 addr, uint16 val);
extern uint8 unreg_dev(uint8);
extern uint8 get_mbyte(uint16 addr);
extern void put_mbyte(uint16 addr, uint8 val);
/* function prototypes */
t_stat isbc206_cfg(uint8 base);
t_stat isbc206_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc206_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc206_set_verb(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc206_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat isbc206_reset(DEVICE *dptr);
void isbc206_reset1(void);
void isbc206_reset_dev(void);
t_stat isbc206_attach (UNIT *uptr, CONST char *cptr);
t_stat isbc206_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
uint8 isbc206r0(t_bool io, uint8 data, uint8 devnum); /* isbc206 port 0 */
@ -202,6 +206,11 @@ void isbc206_diskio(void); //do actual disk i/o
/* globals */
int isbc206_onetime = 1;
static const char* isbc206_desc(DEVICE *dptr) {
return isbc206_NAME;
}
typedef struct { //HDD definition
int t0;
int rdy;
@ -210,7 +219,9 @@ typedef struct { //HDD definition
} HDDDEF;
typedef struct { //HDC definition
uint16 baseport; //HDC base port
uint8 baseport; //HDC base port
uint8 intnum; //interrupt number
uint8 verb; //verbose flag
uint16 iopb; //HDC IOPB
uint8 stat; //HDC status
uint8 rdychg; //HDC ready change
@ -218,14 +229,15 @@ typedef struct { //HDC definition
uint8 rbyte0; //HDC result byte for type 00
uint8 rbyte1; //HDC result byte for type 10
uint8 intff; //HDC interrupt FF
HDDDEF hd[HD_NUM]; //indexed by the HDD number
HDDDEF hd[HDD_NUM]; //indexed by the HDD number
} HDCDEF;
HDCDEF hdc206;
HDCDEF hdc206; //indexed by the isbc-206 instance number
UNIT isbc206_unit[] = {
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF|UNIT_FIX, MDSHD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF|UNIT_FIX, MDSHD), 20 },
UNIT isbc206_unit[] = { // 2 HDDs
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF|UNIT_FIX, MDSHD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF|UNIT_FIX, MDSHD) },
{ NULL }
};
@ -241,6 +253,14 @@ REG isbc206_reg[] = {
MTAB isbc206_mod[] = {
{ UNIT_WPMODE, 0, "RW", "RW", &isbc206_set_mode },
{ UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc206_set_mode },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "VERB", &isbc206_set_verb,
NULL, NULL, "Sets the verbose mode for iSBC206"},
{ MTAB_XTD | MTAB_VDV, 0, NULL, "PORT", &isbc206_set_port,
NULL, NULL, "Sets the base port for iSBC206"},
{ MTAB_XTD | MTAB_VDV, 0, NULL, "INT", &isbc206_set_int,
NULL, NULL, "Sets the interrupt number for iSBC206"},
{ MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, &isbc206_show_param, NULL,
"show configured parametes for iSBC206" },
{ 0 }
};
@ -262,7 +282,7 @@ DEVICE isbc206_dev = {
isbc206_unit, //units
isbc206_reg, //registers
isbc206_mod, //modifiers
HD_NUM, //numunits
HDD_NUM, //numunits
16, //aradix
16, //awidth
1, //aincr
@ -282,45 +302,139 @@ DEVICE isbc206_dev = {
NULL //lname
};
// configuration routine
/* isbc206 set mode = Write protect */
t_stat isbc206_cfg(uint8 base)
t_stat isbc206_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int32 i;
UNIT *uptr;
sim_printf(" sbc206: at base 0%02XH\n",
base);
reg_dev(isbc206r0, base, 0); //read status
reg_dev(isbc206r1, base + 1, 0); //read rslt type/write IOPB addr-l
reg_dev(isbc206r2, base + 2, 0); //write IOPB addr-h and start
reg_dev(isbc206r3, base + 3, 0); //read rstl byte
reg_dev(isbc206r7, base + 7, 0); //write reset fdc201
// one-time initialization for all FDDs for this FDC instance
for (i = 0; i < HD_NUM; i++) {
uptr = isbc206_dev.units + i;
uptr->u6 = i; //fdd unit number
if (uptr == NULL)
return SCPE_ARG;
if (uptr->flags & UNIT_ATT)
return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename);
if (val & UNIT_WPMODE) { /* write protect */
uptr->flags |= val;
if (hdc206.verb)
sim_printf(" sbc206: WP\n");
} else { /* read write */
uptr->flags &= ~val;
if (hdc206.verb)
sim_printf(" sbc206: RW\n");
}
return SCPE_OK;
}
// set base address parameter
t_stat isbc206_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 size, result;
if (uptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%02x", &size);
hdc206.baseport = size;
if (hdc206.verb)
sim_printf("SBC206: Base port=%04X\n", hdc206.baseport);
return SCPE_OK;
}
// set interrupt parameter
t_stat isbc206_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 size, result;
if (uptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%02x", &size);
hdc206.intnum = size;
if (hdc206.verb)
sim_printf("SBC206: Interrupt number=%04X\n", hdc206.intnum);
return SCPE_OK;
}
t_stat isbc206_set_verb(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (uptr == NULL)
return SCPE_ARG;
if (cptr == NULL)
return SCPE_ARG;
if (strncasecmp(cptr, "OFF", 4) == 0) {
hdc206.verb = 0;
return SCPE_OK;
}
if (strncasecmp(cptr, "ON", 3) == 0) {
hdc206.verb = 1;
sim_printf(" SBC206: hdc206.verb=%d\n", hdc206.verb);
return SCPE_OK;
}
return SCPE_ARG;
}
// show configuration parameters
t_stat isbc206_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (uptr == NULL)
return SCPE_ARG;
fprintf(st, "%s Base port at %04X Interrupt # is %i %s",
((isbc206_dev.flags & DEV_DIS) == 0) ? "Enabled" : "Disabled",
hdc206.baseport, hdc206.intnum,
hdc206.verb ? "Verbose" : "Quiet"
);
return SCPE_OK;
}
/* Hardware reset routine */
t_stat isbc206_reset(DEVICE *dptr)
{
isbc206_reset1(); //software reset
int i;
UNIT *uptr;
if (dptr == NULL)
return SCPE_ARG;
if (isbc206_onetime) {
hdc206.baseport = SBC206_BASE; //set default base
hdc206.intnum = SBC206_INT; //set default interrupt
hdc206.verb = 0; //set verb = 0
isbc206_onetime = 0;
// one-time initialization for all FDDs for this FDC instance
for (i = 0; i < HDD_NUM; i++) {
uptr = isbc206_dev.units + i;
uptr->u6 = i; //fdd unit number
}
}
if ((dptr->flags & DEV_DIS) == 0) { // enabled
reg_dev(isbc206r0, hdc206.baseport, 0); //read status
reg_dev(isbc206r1, hdc206.baseport + 1, 0); //read rslt type/write IOPB addr-l
reg_dev(isbc206r2, hdc206.baseport + 2, 0); //write IOPB addr-h and start
reg_dev(isbc206r3, hdc206.baseport + 3, 0); //read rstl byte
reg_dev(isbc206r7, hdc206.baseport + 7, 0); //write reset fdc201
isbc206_reset_dev(); //software reset
if (hdc206.verb)
sim_printf(" sbc206: Enabled base port at 0%02XH Interrupt #=%02X %s\n",
hdc206.baseport, hdc206.intnum, hdc206.verb ? "Verbose" : "Quiet" );
} else {
unreg_dev(hdc206.baseport); //read status
unreg_dev(hdc206.baseport + 1); //read rslt type/write IOPB addr-l
unreg_dev(hdc206.baseport + 2); //write IOPB addr-h and start
unreg_dev(hdc206.baseport + 3); //read rstl byte
unreg_dev(hdc206.baseport + 7); //write reset fdc201
if (hdc206.verb)
sim_printf(" sbc206: Disabled\n");
}
return SCPE_OK;
}
/* Software reset routine */
void isbc206_reset1(void)
void isbc206_reset_dev(void)
{
int32 i;
UNIT *uptr;
hdc206.stat = 0; //clear status
for (i = 0; i < HD_NUM; i++) { /* handle all units */
for (i = 0; i < HDD_NUM; i++) { /* handle all units */
uptr = isbc206_dev.units + i;
hdc206.stat |= (HDCPRE + 0x80); //set the HDC status
hdc206.rtype = ROK;
@ -368,20 +482,6 @@ t_stat isbc206_attach (UNIT *uptr, CONST char *cptr)
return SCPE_OK;
}
/* isbc206 set mode = Write protect */
t_stat isbc206_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (uptr->flags & UNIT_ATT)
return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename);
if (val & UNIT_WPMODE) { /* write protect */
uptr->flags |= val;
} else { /* read write */
uptr->flags &= ~val;
}
return SCPE_OK;
}
/* iSBC206 control port functions */
uint8 isbc206r0(t_bool io, uint8 data, uint8 devnum)
@ -442,7 +542,7 @@ uint8 isbc206r7(t_bool io, uint8 data, uint8 devnum)
if (io == 0) { /* read data port */
;
} else { /* write data port */
isbc206_reset1();
isbc206_reset_dev();
}
return 0;
}
@ -460,12 +560,12 @@ void isbc206_diskio(void)
uint8 *fbuf;
//parse the IOPB
cw = multibus_get_mbyte(hdc206.iopb);
di = multibus_get_mbyte(hdc206.iopb + 1);
nr = multibus_get_mbyte(hdc206.iopb + 2);
ta = multibus_get_mbyte(hdc206.iopb + 3);
sa = multibus_get_mbyte(hdc206.iopb + 4);
ba = multibus_get_mbyte(hdc206.iopb + 5);
cw = get_mbyte(hdc206.iopb);
di = get_mbyte(hdc206.iopb + 1);
nr = get_mbyte(hdc206.iopb + 2);
ta = get_mbyte(hdc206.iopb + 3);
sa = get_mbyte(hdc206.iopb + 4);
ba = get_mbyte(hdc206.iopb + 5);
hddnum = (di & 0x30) >> 4;
uptr = isbc206_dev.units + hddnum;
fbuf = (uint8 *) (isbc206_dev.units + hddnum)->filebuf;
@ -539,7 +639,7 @@ void isbc206_diskio(void)
sim_printf("\n SBC206: HDD %d - Write protect error DFMT", hddnum);
return;
}
fmtb = multibus_get_mbyte(ba); //get the format byte
fmtb = get_mbyte(ba); //get the format byte
//calculate offset into disk image
dskoff = ((ta * MAXSECHD) + (sa - 1)) * 128;
for(i=0; i<=((uint32)(MAXSECHD) * 128); i++) {
@ -557,7 +657,7 @@ void isbc206_diskio(void)
//copy sector from image to RAM
for (i=0; i<128; i++) {
data = *(fbuf + (dskoff + i));
multibus_put_mbyte(ba + i, data);
put_mbyte(ba + i, data);
}
sa++;
ba+=0x80;
@ -582,7 +682,7 @@ void isbc206_diskio(void)
dskoff = ((ta * MAXSECHD) + (sa - 1)) * 128;
//copy sector from image to RAM
for (i=0; i<128; i++) {
data = multibus_get_mbyte(ba + i);
data = get_mbyte(ba + i);
*(fbuf + (dskoff + i)) = data;
}
sa++;

View file

@ -35,9 +35,13 @@
#if defined (SBC464_NUM) && (SBC464_NUM > 0)
#define BASE_ADDR u3
/* prototypes */
t_stat isbc464_cfg(uint16 base, uint16 size);
t_stat isbc464_set_base(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc464_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat isbc464_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat isbc464_reset (DEVICE *dptr);
t_stat isbc464_attach (UNIT *uptr, CONST char *cptr);
uint8 isbc464_get_mbyte(uint16 addr);
@ -50,10 +54,23 @@ extern uint8 xack; /* XACK signal */
/* local globals */
int isbc464_onetime = 1;
/* isbc464 Standard I/O Data Structures */
UNIT isbc464_unit = {
UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO+UNIT_BUFABLE+UNIT_MUSTBUF, 0), 0
UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO+UNIT_BUFABLE+
UNIT_MUSTBUF, 0)
};
MTAB isbc464_mod[] = {
{ MTAB_XTD | MTAB_VDV, 0, NULL, "SIZE", &isbc464_set_size,
NULL, NULL, "Sets the ROM size for iSBC464" },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "BASE", &isbc464_set_base,
NULL, NULL, "Sets the ROM base for iSBC464" },
{ MTAB_XTD|MTAB_VDV, 0, "PARAM", NULL, NULL, &isbc464_show_param, NULL,
"Parameter" },
{ 0 }
};
DEBTAB isbc464_debug[] = {
@ -71,7 +88,7 @@ DEVICE isbc464_dev = {
"SBC464", //name
&isbc464_unit, //units
NULL, //registers
NULL, //modifiers
isbc464_mod, //modifiers
1, //numunits
16, //aradix
16, //awidth
@ -80,12 +97,12 @@ DEVICE isbc464_dev = {
8, //dwidth
NULL, //examine
NULL, //deposite
NULL, //reset
&isbc464_reset, //reset
NULL, //boot
isbc464_attach, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
DEV_DISABLE+DEV_DIS, //flags
0, //dctrl
isbc464_debug, //debflags
NULL, //msize
@ -94,21 +111,81 @@ DEVICE isbc464_dev = {
/* isbc464 globals */
// configuration routine
// set size parameter
t_stat isbc464_cfg(uint16 base, uint16 size)
t_stat isbc464_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
sim_printf(" sbc464: 0%04XH bytes at base 0%04XH\n",
size, base);
isbc464_unit.capac = size; //set size
isbc464_unit.u3 = base; //and base
isbc464_unit.filebuf = (uint8 *)calloc(size, sizeof(uint8));
if (isbc464_unit.filebuf == NULL) {
sim_printf (" sbc464: Calloc error\n");
return SCPE_MEM;
}
// sim_printf(" sbc464: 0%04XH bytes at base 0%04XH\n",
// isbc464_unit.capac, isbc464_unit.u3);
uint32 size, result, i;
if (cptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%i%n", &size, &i);
if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) ||
((cptr[i + 1] == 'B') && (cptr[i + 2] == 0)))) {
switch (size) {
case 0x10: //16K
uptr->capac = 16384;
break;
case 0x20: //32K
uptr->capac = 32768;
break;
case 0x30: //48K
uptr->capac = 49152;
break;
case 0x40: //64K
uptr->capac = 65536;
break;
default:
sim_printf("SBC464: Size error\n");
return SCPE_ARG;
}
sim_printf("SBC464: Size=%04X\n", uptr->capac);
return SCPE_OK;
}
return SCPE_ARG;
}
// set base address parameter
t_stat isbc464_set_base(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 size, result, i;
if (cptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%i%n", &size, &i);
if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) ||
((cptr[i + 1] == 'B') && (cptr[i + 2] == 0)))) {
switch (size) {
case 0x00: //0K
uptr->BASE_ADDR = 0;
break;
case 0x10: //16K
uptr->BASE_ADDR = 16384;
break;
case 0x20: //32K
uptr->BASE_ADDR = 32768;
break;
case 0x30: //48K
uptr->BASE_ADDR = 49152;
break;
default:
sim_printf("SBC464: Base error\n");
return SCPE_ARG;
}
sim_printf("SBC464: Base=%04X\n", uptr->BASE_ADDR);
return SCPE_OK;
}
return SCPE_ARG;
}
// show configuration parameters
t_stat isbc464_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
fprintf(st, "%s Size=%04X Base=%04X ",
((isbc464_dev.flags & DEV_DIS) == 0) ? "Enabled" : "Disabled",
uptr->capac, uptr->BASE_ADDR);
return SCPE_OK;
}
@ -116,6 +193,26 @@ t_stat isbc464_cfg(uint16 base, uint16 size)
t_stat isbc464_reset (DEVICE *dptr)
{
if (isbc464_onetime) {
isbc464_dev.units->capac = SBC464_SIZE; //set default size
isbc464_dev.units->BASE_ADDR = SBC464_BASE; //set default base
isbc464_onetime = 0;
}
if (dptr == NULL)
return SCPE_ARG;
if ((dptr->flags & DEV_DIS) == 0) { //already enabled
isbc464_dev.units->filebuf = (uint8 *)calloc(isbc464_dev.units->capac, sizeof(uint8)); //alloc buffer
if (isbc464_dev.units->filebuf == NULL) { //CALLOC error
sim_printf (" sbc464: Calloc error\n");
return SCPE_MEM;
}
sim_printf(" sbc464: Enabled 0%04XH bytes at base 0%04XH\n",
isbc464_dev.units->capac, isbc464_dev.units->BASE_ADDR);
} else {
if (isbc464_dev.units->filebuf)
free(isbc464_dev.units->filebuf); //return allocated memory
sim_printf(" sbc464: Disabled\n");
}
return SCPE_OK;
}
@ -137,13 +234,9 @@ t_stat isbc464_attach (UNIT *uptr, CONST char *cptr)
uint8 isbc464_get_mbyte(uint16 addr)
{
uint32 val, org, len;
uint8 *fbuf;
uint8 val;
org = isbc464_unit.u3;
len = isbc464_unit.capac;
fbuf = (uint8 *) isbc464_unit.filebuf;
val = *(fbuf + (addr - org));
val = *((uint8 *)isbc464_unit.filebuf + (addr - isbc464_unit.BASE_ADDR));
return (val & 0xFF);
}

View file

@ -34,15 +34,17 @@
#include "system_defs.h"
#define BASE_ADDR u3
/* function prototypes */
t_stat multibus_cfg(void);
t_stat multibus_svc(UNIT *uptr);
t_stat multibus_reset(DEVICE *dptr);
void set_irq(int32 int_num);
void clr_irq(int32 int_num);
uint8 nulldev(t_bool io, uint8 port, uint8 devnum);
uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
uint8 unreg_dev(uint8 port);
t_stat multibus_reset (DEVICE *dptr);
uint8 multibus_get_mbyte(uint16 addr);
void multibus_put_mbyte(uint16 addr, uint8 val);
@ -54,20 +56,6 @@ extern uint8 isbc064_get_mbyte(uint16 addr);
extern void isbc064_put_mbyte(uint16 addr, uint8 val);
extern uint8 isbc464_get_mbyte(uint16 addr);
extern void set_cpuint(int32 int_num);
extern t_stat isbc064_reset (DEVICE *);
extern t_stat isbc464_reset (DEVICE *);
extern t_stat isbc201_reset (DEVICE *);
extern t_stat isbc202_reset (DEVICE *);
extern t_stat isbc206_reset (DEVICE *);
extern t_stat isbc208_reset (DEVICE *);
extern t_stat zx200a_reset(DEVICE *);
extern t_stat isbc064_cfg(uint16 base, uint16 size);
extern t_stat isbc464_cfg(uint16 base, uint16 size);
extern t_stat isbc201_cfg(uint8 base);
extern t_stat isbc202_cfg(uint8 base);
extern t_stat isbc206_cfg(uint8 base);
extern t_stat isbc208_cfg(uint8 base);
extern t_stat zx200a_cfg(uint8 base);
/* local globals */
@ -80,18 +68,11 @@ extern int32 int_req; /* i8080 INT signal */
extern uint16 PCX;
extern DEVICE isbc064_dev;
extern DEVICE isbc464_dev;
extern DEVICE isbc201_dev;
extern DEVICE isbc202_dev;
extern DEVICE isbc206_dev;
extern DEVICE isbc208_dev;
extern DEVICE zx200a_dev;
extern UNIT isbc064_unit;
extern UNIT isbc464_unit;
/* multibus Standard SIMH Device Data Structures */
UNIT multibus_unit = {
UDATA (&multibus_svc, 0, 0), 20
UDATA (&multibus_svc, 0, 0), 1
};
REG multibus_reg[] = {
@ -111,95 +92,42 @@ DEBTAB multibus_debug[] = {
};
DEVICE multibus_dev = {
"MBIRQ", //name
&multibus_unit, //units
multibus_reg, //registers
NULL, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
&multibus_reset, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
multibus_debug, //debflags
NULL, //msize
NULL //lname
"MBIRQ", //name
&multibus_unit, //units
multibus_reg, //registers
NULL, //modifiers
1, //numunits
16, //aradix
16, //awidth
1, //aincr
16, //dradix
8, //dwidth
NULL, //examine
NULL, //deposit
&multibus_reset, //reset
NULL, //boot
NULL, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG, //flags
0, //dctrl
multibus_debug, //debflags
NULL, //msize
NULL, //lname
NULL, //help routine
NULL, //attach help routine
NULL, //help context
NULL //device description
};
/* Service routines to handle simulator functions */
// multibus_cfg
t_stat multibus_cfg(void)
{
sim_printf("Configuring Multibus Devices\n");
#if defined (SBC064_NUM) && (SBC064_NUM > 0)
isbc064_cfg(SBC064_BASE, SBC064_SIZE);
#endif
#if defined (SBC464_NUM) && (SBC464_NUM > 0)
isbc464_cfg(SBC464_BASE, SBC464_SIZE);
#endif
#if defined (SBC201_NUM) && (SBC201_NUM > 0)
isbc201_cfg(SBC201_BASE);
#endif
#if defined (SBC202_NUM) && (SBC202_NUM > 0)
isbc202_cfg(SBC202_BASE);
#endif
#if defined (SBC206_NUM) && (SBC206_NUM > 0)
isbc206_cfg(SBC206_BASE);
#endif
#if defined (SBC208_NUM) && (SBC208_NUM > 0)
isbc208_cfg(SBC208_BASE);
#endif
#if defined (ZX200A_NUM) && (ZX200A_NUM > 0)
zx200a_cfg(ZX200A_BASE);
#endif
return SCPE_OK;
}
/* Reset routine */
t_stat multibus_reset(DEVICE *dptr)
{
if (SBC_reset(NULL) == 0) {
sim_printf(" Multibus: Reset\n");
#if defined (SBC064_NUM) && (SBC064_NUM > 0)
isbc064_reset(&isbc064_dev);
sim_printf(" Multibus: SBC064 reset\n");
#endif
#if defined (SBC464_NUM) && (SBC464_NUM > 0)
isbc464_reset(&isbc464_dev);
sim_printf(" Multibus: SBC464 reset\n");
#endif
#if defined (SBC201_NUM) && (SBC201_NUM > 0)
isbc201_reset(&isbc201_dev);
sim_printf(" Multibus: SBC201 reset\n");
#endif
#if defined (SBC202_NUM) && (SBC202_NUM > 0)
isbc202_reset(&isbc202_dev);
sim_printf(" Multibus: SBC202 reset\n");
#endif
#if defined (SBC208_NUM) && (SBC208_NUM > 0)
isbc206_reset(&isbc206_dev);
sim_printf(" Multibus: SBC206 reset\n");
#endif
#if defined (SBC208_NUM) && (SBC208_NUM > 0)
isbc208_reset(&isbc208_dev);
sim_printf(" Multibus: SBC208 reset\n");
#endif
#if defined (ZX200A_NUM) && (ZX200A_NUM > 0)
zx200a_reset(&zx200a_dev);
sim_printf(" Multibus: ZX200A reset\n");
#endif
sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */
return SCPE_OK;
} else {
@ -313,17 +241,31 @@ struct idev dev_table[256] = {
uint8 nulldev(t_bool io, uint8 data, uint8 devnum)
{
SET_XACK(0); /* set no XACK */
return 0xff; /* multibus has active high pullups and inversion */
// return 0xff; /* multibus has active high pullups and inversion */
return 0; //corrects "illegal disk at port X8H" error in ISIS
}
uint8 reg_dev(uint8 (*routine)(t_bool io, uint8 data, uint8 devnum), uint8 port, uint8 devnum)
{
if (dev_table[port].routine != &nulldev) { /* port already assigned */
if (dev_table[port].routine != routine)
sim_printf(" I/O Port %02X is already assigned\n", port);
sim_printf(" I/O Port %02X is already assigned\n", port);
} else {
dev_table[port].routine = routine;
dev_table[port].devnum = devnum;
sim_printf(" I/O Port %02X has been assigned\n", port);
}
return 0;
}
uint8 unreg_dev(uint8 port)
{
if (dev_table[port].routine == &nulldev) { /* port already free */
sim_printf(" I/O Port %02X is already free\n", port);
} else {
dev_table[port].routine = &nulldev;
dev_table[port].devnum = 0;
sim_printf(" I/O Port %02X is free\n", port);
}
return 0;
}
@ -334,16 +276,18 @@ uint8 multibus_get_mbyte(uint16 addr)
{
SET_XACK(0); /* set no XACK */
#if defined (SBC464_NUM) && (SBC464_NUM > 0)
if ((isbc464_dev.flags & DEV_DIS) == 0) { //ROM is enabled
if (addr >= isbc464_unit.u3 && addr < (isbc464_unit.u3 + isbc464_unit.capac))
return(isbc464_get_mbyte(addr));
}
if ((isbc464_dev.flags & DEV_DIS) == 0) { //ROM is enabled
if (addr >= isbc464_dev.units->BASE_ADDR && addr <
(isbc464_dev.units->BASE_ADDR + isbc464_dev.units->capac))
return(isbc464_get_mbyte(addr));
}
#endif
#if defined (SBC064_NUM) && (SBC064_NUM > 0)
if ((isbc064_dev.flags & DEV_DIS) == 0) { //RAM is enabled
if (addr >= isbc064_unit.u3 && addr < (isbc064_unit.u3 + isbc064_unit.capac))
return (isbc064_get_mbyte(addr));
}
if ((isbc064_dev.flags & DEV_DIS) == 0) { //RAM is enabled
if (addr >= isbc064_dev.units->BASE_ADDR && addr <
(isbc064_dev.units->BASE_ADDR + isbc064_dev.units->capac))
return (isbc064_get_mbyte(addr));
}
#endif
return 0;
}
@ -352,10 +296,11 @@ void multibus_put_mbyte(uint16 addr, uint8 val)
{
SET_XACK(0); /* set no XACK */
#if defined (SBC064_NUM) && (SBC064_NUM > 0)
if ((isbc064_dev.flags & DEV_DIS) == 0) { //device is enabled
if ((addr >= SBC064_BASE) && (addr <= (SBC064_BASE + SBC064_SIZE - 1)))
isbc064_put_mbyte(addr, val);
}
if ((isbc064_dev.flags & DEV_DIS) == 0) { //device is enabled
if (addr >= isbc064_dev.units->BASE_ADDR && addr <
(isbc064_dev.units->BASE_ADDR + isbc064_dev.units->capac))
isbc064_put_mbyte(addr, val);
}
#endif
}

View file

@ -145,6 +145,7 @@
#define UNIT_WPMODE (1 << UNIT_V_WPMODE)
#define FDD_NUM 6
#define SECSIZ 128
//disk controoler operations
#define DNOP 0x00 //disk no operation
@ -191,21 +192,27 @@
#define MAXSECDD 52 //double density last sector
#define MAXTRK 76 //last track
/* external function prototypes */
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
extern uint8 multibus_get_mbyte(uint16 addr);
extern void multibus_put_mbyte(uint16 addr, uint8 val);
#define zx200a_NAME "Zendex ZX-200A Floppy Disk Controller Board"
/* external globals */
extern uint16 PCX;
/* external function prototypes */
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
extern uint8 unreg_dev(uint8);
extern uint8 get_mbyte(uint16 addr);
extern void put_mbyte(uint16 addr, uint8 val);
/* internal function prototypes */
t_stat isbc064_cfg(uint16 base);
t_stat zx200a_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat zx200a_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat zx200a_set_verb(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat zx200a_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat zx200a_reset(DEVICE *dptr);
void zx200a_reset1(void);
void zx200a_reset_dev(void);
t_stat zx200a_attach (UNIT *uptr, CONST char *cptr);
t_stat zx200a_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
uint8 zx200ar0SD(t_bool io, uint8 data, uint8 devnum);
@ -220,19 +227,21 @@ void zx200a_diskio(void);
/* globals */
int zx200a_onetime = 1;
static const char* zx200a_desc(DEVICE *dptr) {
return zx200a_NAME;
}
typedef struct { //FDD definition
// uint8 *buf;
// int t0;
// int rdy;
uint8 sec;
uint8 cyl;
uint8 dd;
// uint8 maxsec;
// uint8 maxcyl;
} FDDDEF;
typedef struct { //FDC definition
uint16 baseport; //FDC base port
uint8 baseport; //FDC base port
uint8 intnum; //interrupt number
uint8 verb; //verbose flag
uint16 iopb; //FDC IOPB
uint8 DDstat; //FDC DD status
uint8 SDstat; //FDC SD status
@ -249,12 +258,13 @@ FDCDEF zx200a;
/* ZX-200A Standard I/O Data Structures */
UNIT zx200a_unit[] = {
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSSD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSSD), 20 },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSDD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSSD) },
{ UDATA (0, UNIT_ATTABLE+UNIT_DISABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_FIX, MDSSD) },
{ NULL }
};
REG zx200a_reg[] = {
@ -270,6 +280,15 @@ REG zx200a_reg[] = {
MTAB zx200a_mod[] = {
{ UNIT_WPMODE, 0, "RW", "RW", &zx200a_set_mode },
{ UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &zx200a_set_mode },
// { UNIT_WPMODE, UNIT_WPMODE, "RO", "RO", &zx200a_set_mode },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "VERB", &zx200a_set_verb,
NULL, NULL, "Sets the verbose mode for ZX-200A"},
{ MTAB_XTD | MTAB_VDV, 0, NULL, "PORT", &zx200a_set_port,
NULL, NULL, "Sets the base port for ZX-200A"},
{ MTAB_XTD | MTAB_VDV, 0, NULL, "INT", &zx200a_set_int,
NULL, NULL, "Sets the interrupt number for ZX-200A"},
{ MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, &zx200a_show_param, NULL,
"show configured parametes for ZX-200A" },
{ 0 }
};
@ -304,59 +323,160 @@ DEVICE zx200a_dev = {
&zx200a_attach, //attach
NULL, //detach
NULL, //ctxt
DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags
// DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl
DEV_DISABLE+DEV_DIS, //flags
0, //dctrl
zx200a_debug, //debflags
NULL, //msize
NULL //lname
NULL, //lname
NULL, //help routine
NULL, //attach help routine
NULL, //help context
&zx200a_desc //device description
};
/* zx200a set mode = Write protect */
t_stat zx200a_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (uptr == NULL)
return SCPE_ARG;
if (uptr->flags & UNIT_ATT)
return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename);
if (val & UNIT_WPMODE) { /* write protect */
uptr->flags |= val;
if (zx200a.verb)
sim_printf(" sbc202: WP\n");
} else { /* read write */
uptr->flags &= ~val;
if (zx200a.verb)
sim_printf(" sbc202: RW\n");
}
return SCPE_OK;
}
/* I/O instruction handlers, called from the CPU module when an
IN or OUT instruction is issued.
*/
/* Service routines to handle simulator functions */
// configuration routine
// set base address parameter
t_stat zx200a_cfg(uint8 base)
t_stat zx200a_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int32 i;
UNIT *uptr;
sim_printf(" zx200a: at base 0%02XH\n",
base);
//register I/O port addresses for each function
reg_dev(zx200ar0DD, base, 0); //read status
reg_dev(zx200ar1DD, base + 1, 0); //read rslt type/write IOPB addr-l
reg_dev(zx200ar2DD, base + 2, 0); //write IOPB addr-h and start
reg_dev(zx200ar3, base + 3, 0); //read rstl byte
reg_dev(zx200ar7, base + 7, 0); //write reset zx200a
reg_dev(zx200ar0SD, base + 16, 0); //read status
reg_dev(zx200ar1SD, base + 17, 0); //read rslt type/write IOPB addr-l
reg_dev(zx200ar2SD, base + 18, 0); //write IOPB addr-h and start
reg_dev(zx200ar3, base + 19, 0); //read rstl byte
reg_dev(zx200ar7, base + 23, 0); //write reset zx200a
// one-time initialization for all FDDs
for (i = 0; i < FDD_NUM; i++) {
uptr = zx200a_dev.units + i;
uptr->u6 = i; //fdd unit number
}
uint32 size, result;
if (uptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%02x", &size);
zx200a.baseport = size;
if (zx200a.verb)
sim_printf("SBC202: Base port=%04X\n", zx200a.baseport);
return SCPE_OK;
}
/* Reset routine */
// set interrupt parameter
t_stat zx200a_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 size, result;
if (uptr == NULL)
return SCPE_ARG;
result = sscanf(cptr, "%02x", &size);
zx200a.intnum = size;
if (zx200a.verb)
sim_printf("SBC202: Interrupt number=%04X\n", zx200a.intnum);
return SCPE_OK;
}
t_stat zx200a_set_verb(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (uptr == NULL)
return SCPE_ARG;
if (cptr == NULL)
return SCPE_ARG;
if (strncasecmp(cptr, "OFF", 4) == 0) {
zx200a.verb = 0;
return SCPE_OK;
}
if (strncasecmp(cptr, "ON", 3) == 0) {
zx200a.verb = 1;
sim_printf(" SBC202: zx200a.verb=%d\n", zx200a.verb);
return SCPE_OK;
}
return SCPE_ARG;
}
// show configuration parameters
t_stat zx200a_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (uptr == NULL)
return SCPE_ARG;
fprintf(st, "%s Base port at %04X Interrupt # is %i %s",
((zx200a_dev.flags & DEV_DIS) == 0) ? "Enabled" : "Disabled",
zx200a.baseport, zx200a.intnum,
zx200a.verb ? "Verbose" : "Quiet"
);
return SCPE_OK;
}
/* Hardware reset routine */
t_stat zx200a_reset(DEVICE *dptr)
{
zx200a_reset1(); //software reset
int i;
UNIT *uptr;
if (dptr == NULL)
return SCPE_ARG;
if (zx200a_onetime) {
zx200a.baseport = SBC202_BASE; //set default base
zx200a.intnum = SBC202_INT; //set default interrupt
zx200a.verb = 0; //set verb = 0
zx200a_onetime = 0;
// one-time initialization for all FDDs for this FDC instance
for (i = 0; i < FDD_NUM; i++) {
uptr = zx200a_dev.units + i;
uptr->u6 = i; //fdd unit number
}
}
if ((dptr->flags & DEV_DIS) == 0) { // enabled
reg_dev(zx200ar0DD, zx200a.baseport, 0); //read status
reg_dev(zx200ar0DD, zx200a.baseport + 1, 0); //read rslt type/write IOPB addr-l
reg_dev(zx200ar0DD, zx200a.baseport + 2, 0); //write IOPB addr-h and start
reg_dev(zx200ar3, zx200a.baseport + 3, 0); //read rstl byte
reg_dev(zx200ar7, zx200a.baseport + 7, 0); //write reset fdc201
reg_dev(zx200ar0SD, zx200a.baseport + 16, 0); //read status
reg_dev(zx200ar1SD, zx200a.baseport + 17, 0); //read rslt type/write IOPB addr-l
reg_dev(zx200ar2SD, zx200a.baseport + 18, 0); //write IOPB addr-h and start
reg_dev(zx200ar3, zx200a.baseport + 19, 0); //read rstl byte
reg_dev(zx200ar7, zx200a.baseport + 23, 0); //write reset zx200a
zx200a_reset_dev(); //software reset
if (zx200a.verb)
sim_printf(" ZX200A: Enabled base port at 0%02XH Interrupt #=%02X %s\n",
zx200a.baseport, zx200a.intnum, zx200a.verb ? "Verbose" : "Quiet" );
} else {
unreg_dev(zx200a.baseport); //read status
unreg_dev(zx200a.baseport + 1); //read rslt type/write IOPB addr-l
unreg_dev(zx200a.baseport + 2); //write IOPB addr-h and start
unreg_dev(zx200a.baseport + 3); //read rstl byte
unreg_dev(zx200a.baseport + 7); //write reset fdc201
unreg_dev(zx200a.baseport + 16); //read status
unreg_dev(zx200a.baseport + 17); //read rslt type/write IOPB addr-l
unreg_dev(zx200a.baseport + 18); //write IOPB addr-h and start
unreg_dev(zx200a.baseport + 19); //read rstl byte
unreg_dev(zx200a.baseport + 23); //write reset fdc201
if (zx200a.verb)
sim_printf(" ZX200A: Disabled\n");
}
return SCPE_OK;
}
/* Software reset routine */
void zx200a_reset1(void)
void zx200a_reset_dev(void)
{
int32 i;
UNIT *uptr;
@ -450,20 +570,6 @@ t_stat zx200a_attach (UNIT *uptr, CONST char *cptr)
return SCPE_OK;
}
/* zx200a set mode = Write protect */
t_stat zx200a_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (uptr->flags & UNIT_ATT)
return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename);
if (val & UNIT_WPMODE) { /* write protect */
uptr->flags |= val;
} else { /* read write */
uptr->flags &= ~val;
}
return SCPE_OK;
}
/* I/O instruction handlers, called from the CPU module when an
IN or OUT instruction is issued.
*/
@ -564,7 +670,7 @@ uint8 zx200ar7(t_bool io, uint8 data, uint8 devnum)
if (io == 0) { /* read data port */
;
} else { /* write data port */
zx200a_reset1();
zx200a_reset_dev();
}
return 0;
}
@ -582,13 +688,13 @@ void zx200a_diskio(void)
uint8 *fbuf;
//parse the IOPB
cw = multibus_get_mbyte(zx200a.iopb);
di = multibus_get_mbyte(zx200a.iopb + 1);
nr = multibus_get_mbyte(zx200a.iopb + 2);
ta = multibus_get_mbyte(zx200a.iopb + 3);
sa = multibus_get_mbyte(zx200a.iopb + 4);
ba = multibus_get_mbyte(zx200a.iopb + 5);
ba |= (multibus_get_mbyte(zx200a.iopb + 6) << 8);
cw = get_mbyte(zx200a.iopb);
di = get_mbyte(zx200a.iopb + 1);
nr = get_mbyte(zx200a.iopb + 2);
ta = get_mbyte(zx200a.iopb + 3);
sa = get_mbyte(zx200a.iopb + 4);
ba = get_mbyte(zx200a.iopb + 5);
ba |= (get_mbyte(zx200a.iopb + 6) << 8);
fddnum = (di & 0x30) >> 4;
uptr = zx200a_dev.units + fddnum;
fbuf = (uint8 *) uptr->filebuf;
@ -715,7 +821,7 @@ void zx200a_diskio(void)
sim_printf("\n zx200a: Write protect error 1 on drive %d", fddnum);
return;
}
fmtb = multibus_get_mbyte(ba); //get the format byte
fmtb = get_mbyte(ba); //get the format byte
if (zx200a.fdd[fddnum].dd == 1) {
//calculate offset into DD disk image
dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128;
@ -745,7 +851,7 @@ void zx200a_diskio(void)
//copy sector from image to RAM
for (i=0; i<128; i++) {
data = *(fbuf + (dskoff + i));
multibus_put_mbyte(ba + i, data);
put_mbyte(ba + i, data);
}
sa++;
ba+=0x80;
@ -773,7 +879,7 @@ void zx200a_diskio(void)
dskoff = ((ta * MAXSECSD) + (sa - 1)) * 128;
}
for (i=0; i<128; i++) { //copy sector from image to RAM
data = multibus_get_mbyte(ba + i);
data = get_mbyte(ba + i);
*(fbuf + (dskoff + i)) = data;
}
sa++;

View file

Before

Width:  |  Height:  |  Size: 788 KiB

After

Width:  |  Height:  |  Size: 788 KiB

View file

@ -40,6 +40,7 @@ extern DEVICE ipc_cont_dev;
extern DEVICE multibus_dev;
extern DEVICE isbc201_dev;
extern DEVICE isbc202_dev;
extern DEVICE isbc206_dev;
extern DEVICE zx200a_dev;
/* SCP data structures
@ -73,6 +74,9 @@ DEVICE *sim_devices[] = {
#if defined (SBC202_NUM) && (SBC202_NUM > 0)
&isbc202_dev,
#endif
#if defined (SBC206_NUM) && (SBC206_NUM > 0)
&isbc206_dev,
#endif
#if defined (ZX200A_NUM) && (ZX200A_NUM > 0)
&zx200a_dev,
#endif

View file

@ -73,7 +73,7 @@
/* set the base I/O address for the iSBC 201 */
#define SBC201_BASE 0x88
#define SBC201_INT INT_2
#define SBC201_NUM 0
#define SBC201_NUM 1
/* set the base I/O address for the iSBC 202 */
#define SBC202_BASE 0x78
@ -82,8 +82,8 @@
/* set the base I/O address for the iSBC 206 */
#define SBC206_BASE 0x68
#define SBC206_INT INT_1
#define SBC206_NUM 0
#define SBC206_INT INT_2
#define SBC206_NUM 1
/* set the base I/O address for the iSBC 208 */
#define SBC208_BASE 0x40
@ -98,7 +98,7 @@
/* set the base and size for the iSBC 064 RAM*/
#define SBC064_BASE 0x8000
#define SBC064_SIZE 0x7FFF
#define SBC064_NUM 0
#define SBC064_NUM 1
/* set the base and size for the iSBC 464 ROM */
#define SBC464_BASE 0xA800

View file

@ -84,7 +84,7 @@
/* set the base I/O address for the iSBC 206 */
#define SBC206_BASE 0x68
#define SBC206_INT INT_1
#define SBC206_NUM 0
#define SBC206_NUM 1
/* set the base I/O address for the iSBC 208 */
#define SBC208_BASE 0x40

View file

@ -27,35 +27,38 @@
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "sim_defs.h" /* simulator defns */
#define SET_XACK(VAL) (xack = VAL)
// This file sets the initial stats of devices and units
#define I3214_NUM 0
/* set the base for the DBB ports */
#define DBB_BASE 0xC0
/* set the base I/O address for the 8255 */
#define I8255_BASE_0 0xE4
#define I8255_BASE_1 0xE8
#define I8255_NUM 2
/* set the base I/O address for the 8253 */
#define I8253_BASE 0xF0
#define I8253_NUM 1
/* set the base I/O address for the 8251 */
#define I8251_BASE_0 0xF4
#define I8251_BASE_1 0xF6
#define I8251_NUM 2
/* set the base I/O address for the 8253 */
#define I8253_BASE 0xF0
#define I8253_NUM 1
/* set the base I/O address for the 8255 */
#define I8255_BASE_0 0xE4
#define I8255_BASE_1 0xE8
#define I8255_NUM 2
/* set the base I/O address for the 8259 */
#define I8259_BASE_0 0xFA
#define I8259_BASE_1 0xFC
#define I8259_NUM 2
/* set the base for the DBB ports */
#define DBB_BASE 0xC0
/* set the base I/O address for the IPC control port */
#define ICONT_BASE 0xFF
@ -71,9 +74,9 @@
//board definitions for the multibus
/* set the base I/O address for the iSBC 201 */
#define SBC201_BASE 0x78
#define SBC201_BASE 0x88
#define SBC201_INT INT_2
#define SBC201_NUM 0
#define SBC201_NUM 1
/* set the base I/O address for the iSBC 202 */
#define SBC202_BASE 0x78
@ -93,7 +96,7 @@
/* set the base for the zx-200a disk controller */
#define ZX200A_BASE 0x78
#define ZX200A_INT INT_2
#define ZX200A_NUM 0
#define ZX200A_NUM 1
/* set the base and size for the iSBC 464 ROM */
#define SBC464_BASE 0xA800
@ -101,7 +104,7 @@
#define SBC464_NUM 0
/* set the base and size for the iSBC 064 RAM */
#define SBC064_BASE 0x08000
#define SBC064_BASE 0x8000
#define SBC064_SIZE 0x7FFF
#define SBC064_NUM 1

View file

@ -52,7 +52,6 @@ extern t_stat fp_reset (void);
extern t_stat fp_cfg(void);
extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */
extern uint8 EPROM_get_mbyte(uint16 addr, uint8 devnum);
extern t_stat multibus_cfg(void);
extern uint8 multibus_get_mbyte(uint16 addr);
extern void multibus_put_mbyte(uint16 addr, uint8 val);
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
@ -84,7 +83,6 @@ t_stat SBC_reset (DEVICE *dptr)
{
if (onetime == 0) {
SBC_config();
multibus_cfg();
onetime++;
}
i8080_reset(&i8080_dev);

View file

@ -57,7 +57,6 @@ extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
extern t_stat i3214_cfg(uint8 base, uint8 devnum);
extern t_stat fp_cfg(void);
extern t_stat monitor_cfg(void);
extern t_stat multibus_cfg(void);
// external globals
@ -83,7 +82,6 @@ t_stat SBC_reset (DEVICE *dptr)
{
if (onetime == 0) {
SBC_config();
multibus_cfg();
onetime++;
}
EPROM_enable = 1;

View file

@ -67,7 +67,6 @@ extern t_stat i8251_cfg(uint8 base, uint8 devnum);
extern t_stat i8255_cfg(uint8 base, uint8 devnum);
extern t_stat RAM_cfg(uint16 base, uint16 size);
extern t_stat EPROM_cfg(uint16 base, uint16 size, uint8 devnum);
extern t_stat multibus_cfg();
/* globals */
@ -90,7 +89,6 @@ t_stat SBC_reset (DEVICE *dptr)
{
if (onetime == 0) {
SBC_config();
multibus_cfg();
onetime++;
}
i8080_reset(&i8080_dev);

View file

@ -36,14 +36,12 @@
/* function prototypes */
t_stat multibus_cfg(void);
t_stat multibus_svc(UNIT *uptr);
t_stat multibus_reset(DEVICE *dptr);
void set_irq(int32 int_num);
void clr_irq(int32 int_num);
uint8 nulldev(t_bool io, uint8 port, uint8 devnum);
uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
t_stat multibus_reset (DEVICE *dptr);
uint8 multibus_get_mbyte(uint16 addr);
void multibus_put_mbyte(uint16 addr, uint8 val);
@ -137,14 +135,6 @@ DEVICE multibus_dev = {
/* Service routines to handle simulator functions */
// multibus_cfg
t_stat multibus_cfg(void)
{
sim_printf("Configuring Multibus Devices\n");
return SCPE_OK;
}
/* Reset routine */
t_stat multibus_reset(DEVICE *dptr)

View file

@ -74,7 +74,6 @@ extern t_stat i8251_cfg(uint8 base, uint8 devnum);
extern t_stat i8255_cfg(uint8 base, uint8 devnum);
extern t_stat RAM_cfg(uint16 base, uint16 size);
extern t_stat EPROM_cfg(uint16 base, uint16 size, uint8 devnum);
extern t_stat multibus_cfg();
/* globals */
@ -97,7 +96,6 @@ t_stat SBC_reset (DEVICE *dptr)
{
if (onetime == 0) {
SBC_config();
multibus_cfg();
onetime++;
}
i8080_reset(&i8080_dev);

View file

@ -84,7 +84,6 @@ extern t_stat i8255_cfg(uint8 base, uint8 devnum);
extern t_stat i8259_cfg(uint8 base, uint8 devnum);
extern t_stat RAM_cfg(uint16 base, uint16 size);
extern t_stat EPROM_cfg(uint16 base, uint16 size, uint8 devnum);
extern t_stat multibus_cfg();
extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8);
// globals
@ -111,7 +110,6 @@ t_stat SBC_reset (DEVICE *dptr)
{
if (onetime == 0) {
SBC_config();
multibus_cfg();
onetime++;
}
i8080_reset(&i8080_dev);

View file

@ -88,7 +88,6 @@ extern t_stat i8255_cfg(uint8 base, uint8 devnum);
extern t_stat i8259_cfg(uint8 base, uint8 devnum);
extern t_stat RAM_cfg(uint16 base, uint16 size);
extern t_stat EPROM_cfg(uint16 base, uint16 size, uint8 devnum);
extern t_stat multibus_cfg();
// globals
@ -113,7 +112,6 @@ t_stat SBC_reset (DEVICE *dptr)
{
if (onetime == 0) {
SBC_config();
multibus_cfg();
onetime++;
}
i8080_reset(&i8080_dev);

View file

@ -76,7 +76,6 @@ extern t_stat i8255_cfg(uint8 base, uint8 devnum);
extern t_stat i8259_cfg(uint8 base, uint8 devnum);
extern t_stat RAM_cfg(uint16 base, uint16 size);
extern t_stat EPROM_cfg(uint16 base, uint16 size, uint8 devnum);
extern t_stat multibus_cfg();
// globals
@ -100,7 +99,6 @@ t_stat SBC_reset (DEVICE *dptr)
{
if (onetime == 0) {
SBC_config();
multibus_cfg();
onetime++;
}
i8080_reset(&i8080_dev);