mirror of
https://github.com/simh/simh.git
synced 2026-03-23 17:22:11 +00:00
Notes For V3.5-0
The source set has been extensively overhauled. For correct viewing, set Visual C++ or Emacs to have tab stops every 4 characters. 1. New Features in 3.4-1 1.1 All Ethernet devices - Added Windows user-defined adapter names (from Timothe Litt) 1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors - Added support for SET <unit>n DISCONNECT 1.3 VAX - Added latent QDSS support - Revised autoconfigure to handle QDSS 1.4 PDP-11 - Revised autoconfigure to handle more casees 2. Bugs Fixed in 3.4-1 2.1 SCP and libraries - Trim trailing spaces on all input (for example, attach file names) - Fixed sim_sock spurious SIGPIPE error in Unix/Linux - Fixed sim_tape misallocation of TPC map array for 64b simulators 2.2 1401 - Fixed bug, CPU reset was clearing SSB through SSG 2.3 PDP-11 - Fixed bug in VH vector display routine - Fixed XU runt packet processing (found by Tim Chapman) 2.4 Interdata - Fixed bug in SHOW PAS CONN/STATS - Fixed potential integer overflow exception in divide 2.5 SDS - Fixed bug in SHOW MUX CONN/STATS 2.6 HP - Fixed bug in SHOW MUX CONN/STATS 2.7 PDP-8 - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.8 PDP-18b - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.9 Nova, Eclipse - Fixed potential integer overflow exception in divide
This commit is contained in:
committed by
Mark Pizzolato
parent
ec60bbf329
commit
b7c1eae41f
2758
Interdata/id16_cpu.c
2758
Interdata/id16_cpu.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/* id16_dboot.c: Interdata 16b simulator disk bootstrap
|
||||
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,16 +19,16 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
#define DBOOT_BEG 0x1000
|
||||
#define DBOOT_START 0x100e
|
||||
#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8))
|
||||
#define DBOOT_BEG 0x1000
|
||||
#define DBOOT_START 0x100e
|
||||
#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8))
|
||||
|
||||
/* Boot ROM: transcription of OS/16 MT2 ALO Direct Access Loader */
|
||||
|
||||
@@ -288,62 +288,64 @@ static uint8 dboot_rom[] = {
|
||||
0x04, 0xc0,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
};
|
||||
|
||||
/* Lower memory setup
|
||||
|
||||
78 = binary input device address
|
||||
79 = binary device input command
|
||||
7A = disk device number
|
||||
7B = device code
|
||||
7C = disk controller address
|
||||
7D = selector channel address
|
||||
7E:7F = operating system extension (user specified)
|
||||
78 = binary input device address
|
||||
79 = binary device input command
|
||||
7A = disk device number
|
||||
7B = device code
|
||||
7C = disk controller address
|
||||
7D = selector channel address
|
||||
7E:7F = operating system extension (user specified)
|
||||
*/
|
||||
|
||||
struct dboot_id {
|
||||
char *name;
|
||||
uint32 sw;
|
||||
uint32 cap;
|
||||
uint32 dtype;
|
||||
uint32 offset;
|
||||
uint32 adder;
|
||||
};
|
||||
char *name;
|
||||
uint32 sw;
|
||||
uint32 cap;
|
||||
uint32 dtype;
|
||||
uint32 offset;
|
||||
uint32 adder;
|
||||
};
|
||||
|
||||
static struct dboot_id dboot_tab[] = {
|
||||
{ "DP", 0, 2, 0x31, o_DP0, 0 },
|
||||
{ "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF },
|
||||
{ "DP", 0, 9, 0x33, o_DP0, 0 },
|
||||
{ "DM", 0, 64, 0x35, o_ID0, 0 },
|
||||
{ "DM", 0, 244, 0x36, o_ID0, 0 },
|
||||
{ NULL } };
|
||||
{ "DP", 0, 2, 0x31, o_DP0, 0 },
|
||||
{ "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF },
|
||||
{ "DP", 0, 9, 0x33, o_DP0, 0 },
|
||||
{ "DM", 0, 64, 0x35, o_ID0, 0 },
|
||||
{ "DM", 0, 244, 0x36, o_ID0, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
t_stat id_dboot (int32 u, DEVICE *dptr)
|
||||
{
|
||||
extern DIB pt_dib, sch_dib;
|
||||
extern uint32 PC;
|
||||
extern int32 sim_switches;
|
||||
uint32 i, typ, ctlno, off, add, cap, sch_dev;
|
||||
UNIT *uptr;
|
||||
|
||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||
ctlno = ddib->dno; /* get ctrl devno */
|
||||
sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */
|
||||
uptr = dptr->units + u; /* get capacity */
|
||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||
ctlno = ddib->dno; /* get ctrl devno */
|
||||
sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */
|
||||
uptr = dptr->units + u; /* get capacity */
|
||||
cap = uptr->capac >> 20;
|
||||
for (i = typ = 0; dboot_tab[i].name != NULL; i++) {
|
||||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||
(dboot_tab[i].cap == cap)) {
|
||||
typ = dboot_tab[i].dtype;
|
||||
off = dboot_tab[i].offset;
|
||||
add = dboot_tab[i].adder;
|
||||
break; } }
|
||||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||
(dboot_tab[i].cap == cap)) {
|
||||
typ = dboot_tab[i].dtype;
|
||||
off = dboot_tab[i].offset;
|
||||
add = dboot_tab[i].adder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (typ == 0) return SCPE_NOFNC;
|
||||
|
||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */
|
||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */
|
||||
IOWriteB (AL_IOC, 0x99);
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk param */
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk param */
|
||||
IOWriteB (AL_DSKT, typ);
|
||||
IOWriteB (AL_DSKC, ctlno);
|
||||
IOWriteB (AL_SCH, sch_dev);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id16_sys.c: Interdata 16b simulator interface
|
||||
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,18 +19,18 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
26-Mar-04 RMS Fixed warning with -std=c99
|
||||
27-Feb-03 RMS Added relative addressing support
|
||||
26-Mar-04 RMS Fixed warning with -std=c99
|
||||
27-Feb-03 RMS Added relative addressing support
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define MSK_SBF 0x0100
|
||||
#define MSK_SBF 0x0100
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE sch_dev;
|
||||
@@ -52,12 +52,12 @@ extern t_stat pt_dump (FILE *of, char *cptr, char *fnam);
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "Interdata 16b";
|
||||
@@ -67,29 +67,31 @@ REG *sim_PC = &cpu_reg[0];
|
||||
int32 sim_emax = 2;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&sch_dev,
|
||||
&pt_dev,
|
||||
&tt_dev,
|
||||
&ttp_dev,
|
||||
&pas_dev,
|
||||
&pasl_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&lpt_dev,
|
||||
&dp_dev,
|
||||
&idc_dev,
|
||||
&fd_dev,
|
||||
&mt_dev,
|
||||
NULL };
|
||||
&cpu_dev,
|
||||
&sch_dev,
|
||||
&pt_dev,
|
||||
&tt_dev,
|
||||
&ttp_dev,
|
||||
&pas_dev,
|
||||
&pasl_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&lpt_dev,
|
||||
&dp_dev,
|
||||
&idc_dev,
|
||||
&fd_dev,
|
||||
&mt_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"Reserved instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Wait state",
|
||||
"Runaway VFU" };
|
||||
"Unknown error",
|
||||
"Reserved instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Wait state",
|
||||
"Runaway VFU"
|
||||
};
|
||||
|
||||
/* Binary loader -- load carriage control tape
|
||||
Binary dump -- paper tape dump */
|
||||
@@ -99,53 +101,56 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
if (flag) return pt_dump (fileref, cptr, fnam);
|
||||
return lp_load (fileref, cptr, fnam);
|
||||
}
|
||||
|
||||
|
||||
/* Symbol tables */
|
||||
|
||||
#define I_V_FL 16 /* class bits */
|
||||
#define I_M_FL 0xF /* class mask */
|
||||
#define I_V_MR 0x0 /* mask-register */
|
||||
#define I_V_RR 0x1 /* register-register */
|
||||
#define I_V_R 0x2 /* register */
|
||||
#define I_V_MX 0x3 /* mask-memory */
|
||||
#define I_V_RX 0x4 /* register-memory */
|
||||
#define I_V_X 0x5 /* memory */
|
||||
#define I_V_FF 0x6 /* float reg-reg */
|
||||
#define I_V_FX 0x7 /* float reg-mem */
|
||||
#define I_V_SI 0x8 /* short immed */
|
||||
#define I_V_SB 0x9 /* short branch */
|
||||
#define I_V_SX 0xA /* short ext branch */
|
||||
#define I_MR (I_V_MR << I_V_FL)
|
||||
#define I_RR (I_V_RR << I_V_FL)
|
||||
#define I_R (I_V_R << I_V_FL)
|
||||
#define I_MX (I_V_MX << I_V_FL)
|
||||
#define I_RX (I_V_RX << I_V_FL)
|
||||
#define I_X (I_V_X << I_V_FL)
|
||||
#define I_FF (I_V_FF << I_V_FL)
|
||||
#define I_FX (I_V_FX << I_V_FL)
|
||||
#define I_SI (I_V_SI << I_V_FL)
|
||||
#define I_SB (I_V_SB << I_V_FL)
|
||||
#define I_SX (I_V_SX << I_V_FL)
|
||||
#define I_V_FL 16 /* class bits */
|
||||
#define I_M_FL 0xF /* class mask */
|
||||
#define I_V_MR 0x0 /* mask-register */
|
||||
#define I_V_RR 0x1 /* register-register */
|
||||
#define I_V_R 0x2 /* register */
|
||||
#define I_V_MX 0x3 /* mask-memory */
|
||||
#define I_V_RX 0x4 /* register-memory */
|
||||
#define I_V_X 0x5 /* memory */
|
||||
#define I_V_FF 0x6 /* float reg-reg */
|
||||
#define I_V_FX 0x7 /* float reg-mem */
|
||||
#define I_V_SI 0x8 /* short immed */
|
||||
#define I_V_SB 0x9 /* short branch */
|
||||
#define I_V_SX 0xA /* short ext branch */
|
||||
#define I_MR (I_V_MR << I_V_FL)
|
||||
#define I_RR (I_V_RR << I_V_FL)
|
||||
#define I_R (I_V_R << I_V_FL)
|
||||
#define I_MX (I_V_MX << I_V_FL)
|
||||
#define I_RX (I_V_RX << I_V_FL)
|
||||
#define I_X (I_V_X << I_V_FL)
|
||||
#define I_FF (I_V_FF << I_V_FL)
|
||||
#define I_FX (I_V_FX << I_V_FL)
|
||||
#define I_SI (I_V_SI << I_V_FL)
|
||||
#define I_SB (I_V_SB << I_V_FL)
|
||||
#define I_SX (I_V_SX << I_V_FL)
|
||||
|
||||
#define R_X 0 /* no reg */
|
||||
#define R_M 1 /* reg mask */
|
||||
#define R_R 2 /* reg int reg */
|
||||
#define R_F 3 /* reg flt reg */
|
||||
#define R_X 0 /* no reg */
|
||||
#define R_M 1 /* reg mask */
|
||||
#define R_R 2 /* reg int reg */
|
||||
#define R_F 3 /* reg flt reg */
|
||||
|
||||
static const int32 masks[] = {
|
||||
0xFF00, 0xFF00, 0xFFF0, 0xFF00,
|
||||
0xFF00, 0xFFF0, 0xFF00, 0xFF00,
|
||||
0xFF00, 0xFE00, 0xFEF0 };
|
||||
0xFF00, 0xFE00, 0xFEF0
|
||||
};
|
||||
|
||||
static const uint32 r1_type[] = {
|
||||
R_M, R_R, R_X, R_M,
|
||||
R_R, R_X, R_F, R_F,
|
||||
R_R, R_M, R_X };
|
||||
R_R, R_M, R_X
|
||||
};
|
||||
|
||||
static const uint32 r2_type[] = {
|
||||
R_X, R_R, R_R, R_X,
|
||||
R_X, R_X, R_F, R_X,
|
||||
R_M, R_X, R_X };
|
||||
R_M, R_X, R_X
|
||||
};
|
||||
|
||||
static const char *opcode[] = {
|
||||
"BER", "BNER","BZR", "BNZR",
|
||||
@@ -199,7 +204,8 @@ static const char *opcode[] = {
|
||||
"SVC", "SINT",
|
||||
"RRL", "RLL",
|
||||
"SRL", "SLL", "SRA", "SLA",
|
||||
NULL };
|
||||
NULL
|
||||
};
|
||||
|
||||
static const uint32 opc_val[] = {
|
||||
0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R,
|
||||
@@ -251,59 +257,65 @@ static const uint32 opc_val[] = {
|
||||
0xD800+I_RX, 0xD900+I_RX, 0xDA00+I_RX, 0xDB00+I_RX,
|
||||
0xDC00+I_RX, 0xDD00+I_RX, 0xDE00+I_RX, 0xDF00+I_RX,
|
||||
0xE100+I_RX, 0xE200+I_RX,
|
||||
0xEA00+I_RX, 0xEB00+I_RX,
|
||||
0xEA00+I_RX, 0xEB00+I_RX,
|
||||
0xEC00+I_RX, 0xED00+I_RX, 0xEE00+I_RX, 0xEF00+I_RX,
|
||||
0xFFFF };
|
||||
|
||||
0xFFFF
|
||||
};
|
||||
|
||||
/* Symbolic decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 c1, c2, rdx;
|
||||
t_stat r;
|
||||
DEVICE *dptr;
|
||||
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
else if (sw & SWMASK ('O')) rdx = 8;
|
||||
else if (sw & SWMASK ('H')) rdx = 16;
|
||||
else rdx = dptr->dradix;
|
||||
|
||||
if (sw & SWMASK ('A')) { /* ASCII char? */
|
||||
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */
|
||||
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
|
||||
return 0; }
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */
|
||||
fprint_val (of, c1, rdx, 8, PV_RZRO);
|
||||
return 0; }
|
||||
if (sw & SWMASK ('C')) { /* string? */
|
||||
c1 = (val[0] >> 8) & 0x7F;
|
||||
c2 = val[0] & 0x7F;
|
||||
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
|
||||
fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
|
||||
return -1; }
|
||||
if (sw & SWMASK ('F')) { /* fullword? */
|
||||
fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO);
|
||||
return -3; }
|
||||
if (sw & SWMASK ('M')) { /* inst format? */
|
||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
||||
if (r <= 0) return r; }
|
||||
if (sw & SWMASK ('A')) { /* ASCII char? */
|
||||
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */
|
||||
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
|
||||
return 0;
|
||||
}
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */
|
||||
fprint_val (of, c1, rdx, 8, PV_RZRO);
|
||||
return 0;
|
||||
}
|
||||
if (sw & SWMASK ('C')) { /* string? */
|
||||
c1 = (val[0] >> 8) & 0x7F;
|
||||
c2 = val[0] & 0x7F;
|
||||
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
|
||||
fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK ('F')) { /* fullword? */
|
||||
fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO);
|
||||
return -3;
|
||||
}
|
||||
if (sw & SWMASK ('M')) { /* inst format? */
|
||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
||||
if (r <= 0) return r;
|
||||
}
|
||||
|
||||
fprint_val (of, val[0], rdx, 16, PV_RZRO);
|
||||
return -1;
|
||||
@@ -312,12 +324,12 @@ return -1;
|
||||
/* Symbolic decode for -m
|
||||
|
||||
Inputs:
|
||||
of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
|
||||
@@ -325,73 +337,86 @@ t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
|
||||
uint32 i, j, inst, r1, r2, ea, vp;
|
||||
|
||||
vp = 0;
|
||||
inst = val[0]; /* first 16b */
|
||||
ea = val[1]; /* second 16b */
|
||||
for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||
r1 = (inst >> 4) & 0xF;
|
||||
r2 = inst & 0xF;
|
||||
fprintf (of, "%s ", opcode[i]); /* print opcode */
|
||||
switch (j) { /* case on class */
|
||||
case I_V_MR: /* mask-register */
|
||||
fprintf (of, "%-X,R%d", r1, r2);
|
||||
return -1;
|
||||
case I_V_RR: /* register-register */
|
||||
case I_V_FF: /* floating-floating */
|
||||
fprintf (of, "R%d,R%d", r1, r2);
|
||||
return -1;
|
||||
case I_V_SI: /* short immediate */
|
||||
fprintf (of, "R%d,%-X", r1, r2);
|
||||
return -1;
|
||||
case I_V_SB: /* short branch */
|
||||
fprintf (of, "%-X,", r1);
|
||||
case I_V_SX: /* ext short branch */
|
||||
fprintf (of, "%-X", ((inst & MSK_SBF)?
|
||||
(addr + r2 + r2): (addr - r2 - r2)));
|
||||
return -1;
|
||||
case I_V_R: /* register */
|
||||
fprintf (of, "R%d", r2);
|
||||
return -1;
|
||||
case I_V_MX: /* mask-memory */
|
||||
fprintf (of, "%-X,%-X", r1, ea);
|
||||
break;
|
||||
case I_V_RX: /* register-memory */
|
||||
case I_V_FX: /* floating-memory */
|
||||
fprintf (of, "R%d,%-X", r1, ea);
|
||||
break;
|
||||
case I_V_X: /* memory */
|
||||
fprintf (of, "%-X", ea);
|
||||
break; } /* end case */
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -3; } /* end if */
|
||||
} /* end for */
|
||||
return SCPE_ARG; /* no match */
|
||||
inst = val[0]; /* first 16b */
|
||||
ea = val[1]; /* second 16b */
|
||||
for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||
r1 = (inst >> 4) & 0xF;
|
||||
r2 = inst & 0xF;
|
||||
fprintf (of, "%s ", opcode[i]); /* print opcode */
|
||||
switch (j) { /* case on class */
|
||||
|
||||
case I_V_MR: /* mask-register */
|
||||
fprintf (of, "%-X,R%d", r1, r2);
|
||||
return -1;
|
||||
|
||||
case I_V_RR: /* register-register */
|
||||
case I_V_FF: /* floating-floating */
|
||||
fprintf (of, "R%d,R%d", r1, r2);
|
||||
return -1;
|
||||
|
||||
case I_V_SI: /* short immediate */
|
||||
fprintf (of, "R%d,%-X", r1, r2);
|
||||
return -1;
|
||||
|
||||
case I_V_SB: /* short branch */
|
||||
fprintf (of, "%-X,", r1);
|
||||
case I_V_SX: /* ext short branch */
|
||||
fprintf (of, "%-X", ((inst & MSK_SBF)?
|
||||
(addr + r2 + r2): (addr - r2 - r2)));
|
||||
return -1;
|
||||
|
||||
case I_V_R: /* register */
|
||||
fprintf (of, "R%d", r2);
|
||||
return -1;
|
||||
|
||||
case I_V_MX: /* mask-memory */
|
||||
fprintf (of, "%-X,%-X", r1, ea);
|
||||
break;
|
||||
|
||||
case I_V_RX: /* register-memory */
|
||||
case I_V_FX: /* floating-memory */
|
||||
fprintf (of, "R%d,%-X", r1, ea);
|
||||
break;
|
||||
|
||||
case I_V_X: /* memory */
|
||||
fprintf (of, "%-X", ea);
|
||||
break;
|
||||
} /* end case */
|
||||
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -3;
|
||||
} /* end if */
|
||||
} /* end for */
|
||||
return SCPE_ARG; /* no match */
|
||||
}
|
||||
|
||||
|
||||
/* Register number
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
**optr = pointer to pointer to next char
|
||||
rtype = mask, integer, or float
|
||||
*cptr = pointer to input string
|
||||
**optr = pointer to pointer to next char
|
||||
rtype = mask, integer, or float
|
||||
Outputs:
|
||||
rnum = output register number, -1 if error
|
||||
rnum = output register number, -1 if error
|
||||
*/
|
||||
|
||||
int32 get_reg (char *cptr, char **optr, int32 rtype)
|
||||
{
|
||||
int32 reg;
|
||||
|
||||
if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */
|
||||
cptr++; /* skip */
|
||||
if (rtype == R_M) return -1; } /* cant be mask */
|
||||
if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */
|
||||
cptr++; /* skip */
|
||||
if (rtype == R_M) return -1; /* cant be mask */
|
||||
}
|
||||
if ((*cptr >= '0') && (*cptr <= '9')) {
|
||||
reg = *cptr++ - '0';
|
||||
if ((*cptr >= '0') && (*cptr <= '9'))
|
||||
reg = (reg * 10) + (*cptr - '0');
|
||||
else --cptr;
|
||||
if (reg > 0xF) return -1; }
|
||||
reg = *cptr++ - '0';
|
||||
if ((*cptr >= '0') && (*cptr <= '9'))
|
||||
reg = (reg * 10) + (*cptr - '0');
|
||||
else --cptr;
|
||||
if (reg > 0xF) return -1;
|
||||
}
|
||||
else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10;
|
||||
else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10;
|
||||
else return -1;
|
||||
@@ -403,33 +428,35 @@ return reg;
|
||||
/* Address
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
**tptr = pointer to moved pointer
|
||||
*ea = effective address
|
||||
addr = base address
|
||||
*cptr = pointer to input string
|
||||
**tptr = pointer to moved pointer
|
||||
*ea = effective address
|
||||
addr = base address
|
||||
Outputs:
|
||||
status = SCPE_OK if ok, else error code
|
||||
status = SCPE_OK if ok, else error code
|
||||
*/
|
||||
|
||||
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_addr addr)
|
||||
{
|
||||
int32 sign = 1;
|
||||
|
||||
if (*cptr == '.') { /* relative? */
|
||||
cptr++;
|
||||
*ea = addr;
|
||||
if (*cptr == '+') cptr++; /* .+? */
|
||||
else if (*cptr == '-') { /* .-? */
|
||||
sign = -1;
|
||||
cptr++; }
|
||||
else return SCPE_OK; }
|
||||
if (*cptr == '.') { /* relative? */
|
||||
cptr++;
|
||||
*ea = addr;
|
||||
if (*cptr == '+') cptr++; /* .+? */
|
||||
else if (*cptr == '-') { /* .-? */
|
||||
sign = -1;
|
||||
cptr++;
|
||||
}
|
||||
else return SCPE_OK;
|
||||
}
|
||||
else *ea = 0;
|
||||
errno = 0;
|
||||
*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
|
||||
if (errno || (cptr == *tptr)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Symbolic input */
|
||||
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
@@ -438,40 +465,44 @@ int32 by, rdx, num;
|
||||
t_stat r;
|
||||
DEVICE *dptr;
|
||||
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
else if (sw & SWMASK ('O')) rdx = 8;
|
||||
else if (sw & SWMASK ('H')) rdx = 16;
|
||||
else rdx = dptr->dradix;
|
||||
|
||||
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]);
|
||||
else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8);
|
||||
return 0; }
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (addr & 1) val[0] = (val[0] & ~0xFF) | by;
|
||||
else val[0] = (val[0] & 0xFF) | (by << 8);
|
||||
return 0; }
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]);
|
||||
else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8);
|
||||
return 0;
|
||||
}
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (addr & 1) val[0] = (val[0] & ~0xFF) | by;
|
||||
else val[0] = (val[0] & 0xFF) | (by << 8);
|
||||
return 0;
|
||||
}
|
||||
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1];
|
||||
return -1; }
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1];
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK ('F')) {
|
||||
num = (int32) get_uint (cptr, rdx, DMASK32, &r);/* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
val[0] = (num >> 16) & DMASK16;
|
||||
val[1] = num & DMASK16;
|
||||
return -3; }
|
||||
num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
val[0] = (num >> 16) & DMASK16;
|
||||
val[1] = num & DMASK16;
|
||||
return -3;
|
||||
}
|
||||
|
||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
||||
if (r <= 0) return r;
|
||||
val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */
|
||||
val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
return -1;
|
||||
}
|
||||
@@ -479,13 +510,13 @@ return -1;
|
||||
/* Symbolic input for -m
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*val = pointer to output values
|
||||
cf = true if parsing for CPU
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*val = pointer to output values
|
||||
cf = true if parsing for CPU
|
||||
Outputs:
|
||||
status = > 0 error code
|
||||
<= 0 -number of extra words
|
||||
status = > 0 error code
|
||||
<= 0 -number of extra words
|
||||
*/
|
||||
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
|
||||
@@ -495,62 +526,64 @@ int32 st, r1, r2;
|
||||
t_stat r;
|
||||
char *tptr, gbuf[CBUFSIZE];
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
|
||||
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
if (opcode[i] == NULL) return SCPE_ARG;
|
||||
inst = opc_val[i] & 0xFFFF; /* get value */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if (r1_type[j]) { /* any R1 field? */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */
|
||||
if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG; /* all done? */
|
||||
inst = inst | (r1 << 4); } /* or in R1 */
|
||||
inst = opc_val[i] & 0xFFFF; /* get value */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if (r1_type[j]) { /* any R1 field? */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */
|
||||
if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG; /* all done? */
|
||||
inst = inst | (r1 << 4); /* or in R1 */
|
||||
}
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get operand */
|
||||
if (*cptr) return SCPE_ARG; /* should be end */
|
||||
switch (j) { /* case on class */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get operand */
|
||||
if (*cptr) return SCPE_ARG; /* should be end */
|
||||
switch (j) { /* case on class */
|
||||
|
||||
case I_V_FF: case I_V_SI: /* flt-flt, sh imm */
|
||||
case I_V_MR: case I_V_RR: /* mask/reg-reg */
|
||||
case I_V_R: /* register */
|
||||
if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG; /* all done? */
|
||||
inst = inst | r2; /* or in R2 */
|
||||
break;
|
||||
case I_V_FF: case I_V_SI: /* flt-flt, sh imm */
|
||||
case I_V_MR: case I_V_RR: /* mask/reg-reg */
|
||||
case I_V_R: /* register */
|
||||
if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG; /* all done? */
|
||||
inst = inst | r2; /* or in R2 */
|
||||
break;
|
||||
|
||||
case I_V_FX: /* float-memory */
|
||||
case I_V_MX: case I_V_RX: /* mask/reg-mem */
|
||||
case I_V_X: /* memory */
|
||||
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
|
||||
if ((r != SCPE_OK) || (t > PAMASK16)) return SCPE_ARG;
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr++ != ')') return SCPE_ARG;
|
||||
inst = inst | r2; } /* or in R2 */
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
val[0] = inst;
|
||||
val[1] = t;
|
||||
return -3;
|
||||
case I_V_FX: /* float-memory */
|
||||
case I_V_MX: case I_V_RX: /* mask/reg-mem */
|
||||
case I_V_X: /* memory */
|
||||
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
|
||||
if ((r != SCPE_OK) || (t > PAMASK16)) return SCPE_ARG;
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr++ != ')') return SCPE_ARG;
|
||||
inst = inst | r2; /* or in R2 */
|
||||
}
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
val[0] = inst;
|
||||
val[1] = t;
|
||||
return -3;
|
||||
|
||||
case I_V_SB: case I_V_SX: /* short branches */
|
||||
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
|
||||
return SCPE_ARG;
|
||||
st = t; /* signed version */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
else return SCPE_ARG;
|
||||
break;
|
||||
} /* end case */
|
||||
case I_V_SB: case I_V_SX: /* short branches */
|
||||
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
|
||||
return SCPE_ARG;
|
||||
st = t; /* signed version */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
else return SCPE_ARG;
|
||||
break;
|
||||
} /* end case */
|
||||
|
||||
val[0] = inst;
|
||||
return -1;
|
||||
|
||||
3315
Interdata/id32_cpu.c
3315
Interdata/id32_cpu.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/* id32_dboot.c: Interdata 32b simulator disk bootstrap
|
||||
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,18 +19,18 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
17-Feb-03 RMS Fixed for UNIX bootstrap, upper platter bootstrap
|
||||
17-Feb-03 RMS Fixed for UNIX bootstrap, upper platter bootstrap
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
#define DBOOT_BEG 0x1000
|
||||
#define DBOOT_START 0x100E
|
||||
#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8))
|
||||
#define DBOOT_BEG 0x1000
|
||||
#define DBOOT_START 0x100E
|
||||
#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8))
|
||||
|
||||
/* Transcribed from 32b Bootstrap Loader, 03-074N81R03A13 */
|
||||
|
||||
@@ -252,35 +252,36 @@ static uint8 dboot_rom[] = {
|
||||
0x00, 0x40,
|
||||
0x00, 0x40,
|
||||
0x00
|
||||
};
|
||||
};
|
||||
|
||||
/* Lower memory setup
|
||||
|
||||
78 = binary input device address
|
||||
79 = binary device input command
|
||||
7A = disk device number
|
||||
7B = device code
|
||||
7C = disk controller address
|
||||
7D = selector channel address
|
||||
7E:7F = operating system extension (user specified)
|
||||
78 = binary input device address
|
||||
79 = binary device input command
|
||||
7A = disk device number
|
||||
7B = device code
|
||||
7C = disk controller address
|
||||
7D = selector channel address
|
||||
7E:7F = operating system extension (user specified)
|
||||
*/
|
||||
|
||||
struct dboot_id {
|
||||
char *name;
|
||||
uint32 sw;
|
||||
uint32 cap;
|
||||
uint32 dtype;
|
||||
uint32 offset;
|
||||
uint32 adder;
|
||||
};
|
||||
char *name;
|
||||
uint32 sw;
|
||||
uint32 cap;
|
||||
uint32 dtype;
|
||||
uint32 offset;
|
||||
uint32 adder;
|
||||
};
|
||||
|
||||
static struct dboot_id dboot_tab[] = {
|
||||
{ "DP", 0, 2, 0x31, o_DP0, 0 },
|
||||
{ "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF },
|
||||
{ "DP", 0, 9, 0x33, o_DP0, 0 },
|
||||
{ "DM", 0, 64, 0x35, o_ID0, 0 },
|
||||
{ "DM", 0, 244, 0x36, o_ID0, 0 },
|
||||
{ NULL } };
|
||||
{ "DP", 0, 2, 0x31, o_DP0, 0 },
|
||||
{ "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF },
|
||||
{ "DP", 0, 9, 0x33, o_DP0, 0 },
|
||||
{ "DM", 0, 64, 0x35, o_ID0, 0 },
|
||||
{ "DM", 0, 244, 0x36, o_ID0, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
t_stat id_dboot (int32 u, DEVICE *dptr)
|
||||
{
|
||||
@@ -290,27 +291,29 @@ extern int32 sim_switches;
|
||||
uint32 i, typ, ctlno, off, add, cap, sch_dev;
|
||||
UNIT *uptr;
|
||||
|
||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||
ctlno = ddib->dno; /* get ctrl devno */
|
||||
sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */
|
||||
uptr = dptr->units + u; /* get capacity */
|
||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||
ctlno = ddib->dno; /* get ctrl devno */
|
||||
sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */
|
||||
uptr = dptr->units + u; /* get capacity */
|
||||
cap = uptr->capac >> 20;
|
||||
for (i = typ = 0; dboot_tab[i].name != NULL; i++) {
|
||||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||
((dboot_tab[i].sw == 0) || (dboot_tab[i].sw & sim_switches)) &&
|
||||
(dboot_tab[i].cap == cap)) {
|
||||
typ = dboot_tab[i].dtype;
|
||||
off = dboot_tab[i].offset;
|
||||
add = dboot_tab[i].adder;
|
||||
break; } }
|
||||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||
((dboot_tab[i].sw == 0) || (dboot_tab[i].sw & sim_switches)) &&
|
||||
(dboot_tab[i].cap == cap)) {
|
||||
typ = dboot_tab[i].dtype;
|
||||
off = dboot_tab[i].offset;
|
||||
add = dboot_tab[i].adder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (typ == 0) return SCPE_NOFNC;
|
||||
|
||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, ttp_dib.dno); /* bin input dev */
|
||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, ttp_dib.dno); /* bin input dev */
|
||||
IOWriteB (AL_IOC, 0xa3);
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk dev addr */
|
||||
IOWriteB (AL_DSKT, typ); /* disk type */
|
||||
IOWriteB (AL_DSKC, ctlno); /* disk ctl addr */
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk dev addr */
|
||||
IOWriteB (AL_DSKT, typ); /* disk type */
|
||||
IOWriteB (AL_DSKC, ctlno); /* disk ctl addr */
|
||||
IOWriteB (AL_SCH, sch_dev);
|
||||
PC = DBOOT_START;
|
||||
return SCPE_OK;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id32_sys.c: Interdata 32b simulator interface
|
||||
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,21 +19,21 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
02-Jul-04 RMS Fixed missing type in declaration
|
||||
15-Jul-03 RMS Fixed signed/unsigned bug in get_imm
|
||||
27-Feb-03 RMS Added relative addressing support
|
||||
23-Dec-01 RMS Cloned from ID4 sources
|
||||
02-Jul-04 RMS Fixed missing type in declaration
|
||||
15-Jul-03 RMS Fixed signed/unsigned bug in get_imm
|
||||
27-Feb-03 RMS Added relative addressing support
|
||||
23-Dec-01 RMS Cloned from ID4 sources
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define MSK_SBF 0x0100
|
||||
#define SEXT15(x) (((x) & 0x4000)? ((x) | ~0x3FFF): ((x) & 0x3FFF))
|
||||
#define MSK_SBF 0x0100
|
||||
#define SEXT15(x) (((x) & 0x4000)? ((x) | ~0x3FFF): ((x) & 0x3FFF))
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE sch_dev;
|
||||
@@ -55,12 +55,12 @@ extern t_stat pt_dump (FILE *of, char *cptr, char *fnam);
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "Interdata 32b";
|
||||
@@ -70,29 +70,31 @@ REG *sim_PC = &cpu_reg[0];
|
||||
int32 sim_emax = 6;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&sch_dev,
|
||||
&pt_dev,
|
||||
&tt_dev,
|
||||
&ttp_dev,
|
||||
&pas_dev,
|
||||
&pasl_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&lpt_dev,
|
||||
&dp_dev,
|
||||
&idc_dev,
|
||||
&fd_dev,
|
||||
&mt_dev,
|
||||
NULL };
|
||||
&cpu_dev,
|
||||
&sch_dev,
|
||||
&pt_dev,
|
||||
&tt_dev,
|
||||
&ttp_dev,
|
||||
&pas_dev,
|
||||
&pasl_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&lpt_dev,
|
||||
&dp_dev,
|
||||
&idc_dev,
|
||||
&fd_dev,
|
||||
&mt_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"Reserved instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Wait state",
|
||||
"Runaway VFU" };
|
||||
"Unknown error",
|
||||
"Reserved instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Wait state",
|
||||
"Runaway VFU"
|
||||
};
|
||||
|
||||
/* Binary loader -- load carriage control tape
|
||||
Binary dump -- paper tape dump */
|
||||
@@ -102,60 +104,63 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
if (flag) return pt_dump (fileref, cptr, fnam);
|
||||
return lp_load (fileref, cptr, fnam);
|
||||
}
|
||||
|
||||
|
||||
/* Symbol tables */
|
||||
|
||||
#define I_V_FL 16 /* class bits */
|
||||
#define I_M_FL 0xF /* class mask */
|
||||
#define I_V_MR 0x0 /* mask-register */
|
||||
#define I_V_RR 0x1 /* register-register */
|
||||
#define I_V_R 0x2 /* register */
|
||||
#define I_V_MX 0x3 /* mask-memory */
|
||||
#define I_V_RX 0x4 /* register-memory */
|
||||
#define I_V_X 0x5 /* memory */
|
||||
#define I_V_FF 0x6 /* float reg-reg */
|
||||
#define I_V_FX 0x7 /* float reg-mem */
|
||||
#define I_V_SI 0x8 /* short immed */
|
||||
#define I_V_SB 0x9 /* short branch */
|
||||
#define I_V_SX 0xA /* short ext branch */
|
||||
#define I_V_RI 0xB /* halfword imm */
|
||||
#define I_V_RF 0xC /* fullword imm */
|
||||
#define I_MR (I_V_MR << I_V_FL)
|
||||
#define I_RR (I_V_RR << I_V_FL)
|
||||
#define I_R (I_V_R << I_V_FL)
|
||||
#define I_MX (I_V_MX << I_V_FL)
|
||||
#define I_RX (I_V_RX << I_V_FL)
|
||||
#define I_X (I_V_X << I_V_FL)
|
||||
#define I_FF (I_V_FF << I_V_FL)
|
||||
#define I_FX (I_V_FX << I_V_FL)
|
||||
#define I_SI (I_V_SI << I_V_FL)
|
||||
#define I_SB (I_V_SB << I_V_FL)
|
||||
#define I_SX (I_V_SX << I_V_FL)
|
||||
#define I_RI (I_V_RI << I_V_FL)
|
||||
#define I_RF (I_V_RF << I_V_FL)
|
||||
#define I_V_FL 16 /* class bits */
|
||||
#define I_M_FL 0xF /* class mask */
|
||||
#define I_V_MR 0x0 /* mask-register */
|
||||
#define I_V_RR 0x1 /* register-register */
|
||||
#define I_V_R 0x2 /* register */
|
||||
#define I_V_MX 0x3 /* mask-memory */
|
||||
#define I_V_RX 0x4 /* register-memory */
|
||||
#define I_V_X 0x5 /* memory */
|
||||
#define I_V_FF 0x6 /* float reg-reg */
|
||||
#define I_V_FX 0x7 /* float reg-mem */
|
||||
#define I_V_SI 0x8 /* short immed */
|
||||
#define I_V_SB 0x9 /* short branch */
|
||||
#define I_V_SX 0xA /* short ext branch */
|
||||
#define I_V_RI 0xB /* halfword imm */
|
||||
#define I_V_RF 0xC /* fullword imm */
|
||||
#define I_MR (I_V_MR << I_V_FL)
|
||||
#define I_RR (I_V_RR << I_V_FL)
|
||||
#define I_R (I_V_R << I_V_FL)
|
||||
#define I_MX (I_V_MX << I_V_FL)
|
||||
#define I_RX (I_V_RX << I_V_FL)
|
||||
#define I_X (I_V_X << I_V_FL)
|
||||
#define I_FF (I_V_FF << I_V_FL)
|
||||
#define I_FX (I_V_FX << I_V_FL)
|
||||
#define I_SI (I_V_SI << I_V_FL)
|
||||
#define I_SB (I_V_SB << I_V_FL)
|
||||
#define I_SX (I_V_SX << I_V_FL)
|
||||
#define I_RI (I_V_RI << I_V_FL)
|
||||
#define I_RF (I_V_RF << I_V_FL)
|
||||
|
||||
#define R_X 0 /* no R1 */
|
||||
#define R_M 1 /* R1 mask */
|
||||
#define R_R 2 /* R1 int reg */
|
||||
#define R_F 3 /* R1 flt reg */
|
||||
#define R_X 0 /* no R1 */
|
||||
#define R_M 1 /* R1 mask */
|
||||
#define R_R 2 /* R1 int reg */
|
||||
#define R_F 3 /* R1 flt reg */
|
||||
|
||||
static const int32 masks[] = {
|
||||
0xFF00, 0xFF00, 0xFFF0, 0xFF00,
|
||||
0xFF00, 0xFFF0, 0xFF00, 0xFF00,
|
||||
0xFF00, 0xFE00, 0xFEF0, 0xFF00,
|
||||
0xFF00 };
|
||||
0xFF00
|
||||
};
|
||||
|
||||
static const uint32 r1_type[] = {
|
||||
R_M, R_R, R_X, R_M,
|
||||
R_R, R_X, R_F, R_F,
|
||||
R_R, R_M, R_X, R_R,
|
||||
R_R };
|
||||
R_R
|
||||
};
|
||||
|
||||
static const uint32 r2_type[] = {
|
||||
R_X, R_R, R_R, R_X,
|
||||
R_X, R_X, R_F, R_X,
|
||||
R_M, R_X, R_X, R_X,
|
||||
R_X };
|
||||
R_X
|
||||
};
|
||||
|
||||
static const char *opcode[] = {
|
||||
"BER", "BNER","BZR", "BNZR",
|
||||
@@ -220,7 +225,8 @@ static const char *opcode[] = {
|
||||
"TI",
|
||||
"NI", "CLI", "OI", "XI",
|
||||
"LI", "CI", "AI", "SI",
|
||||
NULL };
|
||||
NULL
|
||||
};
|
||||
|
||||
static const uint32 opc_val[] = {
|
||||
0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R,
|
||||
@@ -285,25 +291,28 @@ static const uint32 opc_val[] = {
|
||||
0xF300+I_RF,
|
||||
0xF400+I_RF, 0xF500+I_RF, 0xF600+I_RF, 0xF700+I_RF,
|
||||
0xF800+I_RF, 0xF900+I_RF, 0xFA00+I_RF, 0xFB00+I_RF,
|
||||
0xFFFF };
|
||||
|
||||
0xFFFF
|
||||
};
|
||||
|
||||
/* Print an RX specifier */
|
||||
|
||||
t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1,
|
||||
uint32 ea2)
|
||||
uint32 ea2)
|
||||
{
|
||||
uint32 rx2;
|
||||
|
||||
if ((ea1 & 0xC000) == 0) { /* RX1 */
|
||||
fprintf (of, "%-X", ea1);
|
||||
if (rx) fprintf (of, "(R%d)", rx);
|
||||
return -3; }
|
||||
if (ea1 & 0x8000) { /* RX2 */
|
||||
ea1 = addr + 4 + SEXT15 (ea1);
|
||||
fprintf (of, "%-X", ea1 & VAMASK32);
|
||||
if (rx) fprintf (of, "(R%d)", rx);
|
||||
return -3; }
|
||||
rx2 = (ea1 >> 8) & 0xF; /* RX3 */
|
||||
if ((ea1 & 0xC000) == 0) { /* RX1 */
|
||||
fprintf (of, "%-X", ea1);
|
||||
if (rx) fprintf (of, "(R%d)", rx);
|
||||
return -3;
|
||||
}
|
||||
if (ea1 & 0x8000) { /* RX2 */
|
||||
ea1 = addr + 4 + SEXT15 (ea1);
|
||||
fprintf (of, "%-X", ea1 & VAMASK32);
|
||||
if (rx) fprintf (of, "(R%d)", rx);
|
||||
return -3;
|
||||
}
|
||||
rx2 = (ea1 >> 8) & 0xF; /* RX3 */
|
||||
fprintf (of, "%-X", ((ea1 << 16) | ea2) & VAMASK32);
|
||||
if (rx && !rx2) fprintf (of, "(R%d)", rx);
|
||||
if (rx2) fprintf (of, "(R%d,R%d)", rx, rx2);
|
||||
@@ -313,52 +322,57 @@ return -5;
|
||||
/* Symbolic decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 c1, c2, rdx;
|
||||
t_stat r;
|
||||
DEVICE *dptr;
|
||||
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
else if (uptr != &cpu_unit) return SCPE_ARG; /* only for CPU */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
else if (uptr != &cpu_unit) return SCPE_ARG; /* only for CPU */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
else if (sw & SWMASK ('O')) rdx = 8;
|
||||
else if (sw & SWMASK ('H')) rdx = 16;
|
||||
else rdx = dptr->dradix;
|
||||
|
||||
if (sw & SWMASK ('A')) { /* ASCII char? */
|
||||
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */
|
||||
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
|
||||
return 0; }
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */
|
||||
fprint_val (of, c1, rdx, 8, PV_RZRO);
|
||||
return 0; }
|
||||
if (sw & SWMASK ('C')) { /* string? */
|
||||
c1 = (val[0] >> 8) & 0x7F;
|
||||
c2 = val[0] & 0x7F;
|
||||
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
|
||||
fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
|
||||
return -1; }
|
||||
if (sw & SWMASK ('H')) { /* halfword? */
|
||||
fprint_val (of, val[0], rdx, 16, PV_RZRO);
|
||||
return -1; }
|
||||
if (sw & SWMASK ('M')) { /* inst format? */
|
||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
||||
if (r <= 0) return r; }
|
||||
if (sw & SWMASK ('A')) { /* ASCII char? */
|
||||
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */
|
||||
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
|
||||
return 0;
|
||||
}
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */
|
||||
fprint_val (of, c1, rdx, 8, PV_RZRO);
|
||||
return 0;
|
||||
}
|
||||
if (sw & SWMASK ('C')) { /* string? */
|
||||
c1 = (val[0] >> 8) & 0x7F;
|
||||
c2 = val[0] & 0x7F;
|
||||
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
|
||||
fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK ('H')) { /* halfword? */
|
||||
fprint_val (of, val[0], rdx, 16, PV_RZRO);
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK ('M')) { /* inst format? */
|
||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
||||
if (r <= 0) return r;
|
||||
}
|
||||
|
||||
fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO);
|
||||
return -3;
|
||||
@@ -367,13 +381,13 @@ return -3;
|
||||
/* Symbolic decode for -m
|
||||
|
||||
Inputs:
|
||||
of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
cf = true if parsing for CPU
|
||||
of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
cf = true if parsing for CPU
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
|
||||
@@ -383,78 +397,89 @@ uint32 i, j, inst, r1, r2, ea1, ea2;
|
||||
inst = val[0];
|
||||
ea1 = val[1];
|
||||
ea2 = val[2];
|
||||
for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||
r1 = (inst >> 4) & 0xF;
|
||||
r2 = inst & 0xF;
|
||||
fprintf (of, "%s ", opcode[i]); /* print opcode */
|
||||
switch (j) { /* case on class */
|
||||
case I_V_MR: /* mask-register */
|
||||
fprintf (of, "%-X,R%d", r1, r2);
|
||||
return -1;
|
||||
case I_V_RR: /* register-register */
|
||||
case I_V_FF: /* floating-floating */
|
||||
fprintf (of, "R%d,R%d", r1, r2);
|
||||
return -1;
|
||||
case I_V_SI: /* short immediate */
|
||||
fprintf (of, "R%d,%-X", r1, r2);
|
||||
return -1;
|
||||
case I_V_SB: /* short branch */
|
||||
fprintf (of, "%-X,", r1);
|
||||
case I_V_SX: /* ext short branch */
|
||||
fprintf (of, "%-X", ((inst & MSK_SBF)?
|
||||
(addr + r2 + r2): (addr - r2 - r2)));
|
||||
return -1;
|
||||
case I_V_R: /* register */
|
||||
fprintf (of, "R%d", r2);
|
||||
return -1;
|
||||
case I_V_RI: /* reg-immed */
|
||||
fprintf (of, "R%d,%-X", r1, ea1);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -3;
|
||||
case I_V_RF: /* reg-full imm */
|
||||
fprintf (of, "R%d,%-X", r1, (ea1 << 16) | ea2);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -5;
|
||||
case I_V_MX: /* mask-memory */
|
||||
fprintf (of, "%-X,", r1);
|
||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
||||
case I_V_RX: /* register-memory */
|
||||
case I_V_FX: /* floating-memory */
|
||||
fprintf (of, "R%d,", r1);
|
||||
case I_V_X: /* memory */
|
||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
||||
} /* end case */
|
||||
return SCPE_IERR;
|
||||
} /* end if */
|
||||
} /* end for */
|
||||
return SCPE_ARG; /* no match */
|
||||
for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||
r1 = (inst >> 4) & 0xF;
|
||||
r2 = inst & 0xF;
|
||||
fprintf (of, "%s ", opcode[i]); /* print opcode */
|
||||
switch (j) { /* case on class */
|
||||
|
||||
case I_V_MR: /* mask-register */
|
||||
fprintf (of, "%-X,R%d", r1, r2);
|
||||
return -1;
|
||||
|
||||
case I_V_RR: /* register-register */
|
||||
case I_V_FF: /* floating-floating */
|
||||
fprintf (of, "R%d,R%d", r1, r2);
|
||||
return -1;
|
||||
|
||||
case I_V_SI: /* short immediate */
|
||||
fprintf (of, "R%d,%-X", r1, r2);
|
||||
return -1;
|
||||
|
||||
case I_V_SB: /* short branch */
|
||||
fprintf (of, "%-X,", r1);
|
||||
case I_V_SX: /* ext short branch */
|
||||
fprintf (of, "%-X", ((inst & MSK_SBF)?
|
||||
(addr + r2 + r2): (addr - r2 - r2)));
|
||||
return -1;
|
||||
|
||||
case I_V_R: /* register */
|
||||
fprintf (of, "R%d", r2);
|
||||
return -1;
|
||||
|
||||
case I_V_RI: /* reg-immed */
|
||||
fprintf (of, "R%d,%-X", r1, ea1);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -3;
|
||||
|
||||
case I_V_RF: /* reg-full imm */
|
||||
fprintf (of, "R%d,%-X", r1, (ea1 << 16) | ea2);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -5;
|
||||
|
||||
case I_V_MX: /* mask-memory */
|
||||
fprintf (of, "%-X,", r1);
|
||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
||||
|
||||
case I_V_RX: /* register-memory */
|
||||
case I_V_FX: /* floating-memory */
|
||||
fprintf (of, "R%d,", r1);
|
||||
case I_V_X: /* memory */
|
||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
||||
} /* end case */
|
||||
return SCPE_IERR;
|
||||
} /* end if */
|
||||
} /* end for */
|
||||
return SCPE_ARG; /* no match */
|
||||
}
|
||||
|
||||
|
||||
/* Register number
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
**optr = pointer to pointer to next char
|
||||
rtype = mask, integer, or float
|
||||
*cptr = pointer to input string
|
||||
**optr = pointer to pointer to next char
|
||||
rtype = mask, integer, or float
|
||||
Outputs:
|
||||
rnum = output register number, -1 if error
|
||||
rnum = output register number, -1 if error
|
||||
*/
|
||||
|
||||
int32 get_reg (char *cptr, char **optr, int32 rtype)
|
||||
{
|
||||
int32 reg;
|
||||
|
||||
if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */
|
||||
cptr++; /* skip */
|
||||
if (rtype == R_M) return -1; } /* cant be mask */
|
||||
if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */
|
||||
cptr++; /* skip */
|
||||
if (rtype == R_M) return -1; /* cant be mask */
|
||||
}
|
||||
if ((*cptr >= '0') && (*cptr <= '9')) {
|
||||
reg = *cptr++ - '0';
|
||||
if ((*cptr >= '0') && (*cptr <= '9'))
|
||||
reg = (reg * 10) + (*cptr - '0');
|
||||
else --cptr;
|
||||
if (reg > 0xF) return -1; }
|
||||
reg = *cptr++ - '0';
|
||||
if ((*cptr >= '0') && (*cptr <= '9'))
|
||||
reg = (reg * 10) + (*cptr - '0');
|
||||
else --cptr;
|
||||
if (reg > 0xF) return -1;
|
||||
}
|
||||
else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10;
|
||||
else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10;
|
||||
else return -1;
|
||||
@@ -466,12 +491,12 @@ return reg;
|
||||
/* Immediate
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
*imm = pointer to output value
|
||||
*inst = pointer to instruction
|
||||
max = max value
|
||||
*cptr = pointer to input string
|
||||
*imm = pointer to output value
|
||||
*inst = pointer to instruction
|
||||
max = max value
|
||||
Outputs:
|
||||
sta = status
|
||||
sta = status
|
||||
*/
|
||||
|
||||
t_stat get_imm (char *cptr, uint32 *imm, uint32 *inst, uint32 max)
|
||||
@@ -480,13 +505,14 @@ char *tptr;
|
||||
int32 idx;
|
||||
|
||||
errno = 0;
|
||||
*imm = strtoul (cptr, &tptr, 16); /* get immed */
|
||||
*imm = strtoul (cptr, &tptr, 16); /* get immed */
|
||||
if (errno || (*imm > max) || (cptr == tptr)) return SCPE_ARG;
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((idx = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr++ != ')') return SCPE_ARG;
|
||||
*inst = *inst | idx; }
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((idx = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr++ != ')') return SCPE_ARG;
|
||||
*inst = *inst | idx;
|
||||
}
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -494,33 +520,35 @@ return SCPE_OK;
|
||||
/* Address
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
**tptr = pointer to moved pointer
|
||||
*ea = effective address
|
||||
addr = base address
|
||||
*cptr = pointer to input string
|
||||
**tptr = pointer to moved pointer
|
||||
*ea = effective address
|
||||
addr = base address
|
||||
Outputs:
|
||||
status = SCPE_OK if ok, else error code
|
||||
status = SCPE_OK if ok, else error code
|
||||
*/
|
||||
|
||||
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_addr addr)
|
||||
{
|
||||
int32 sign = 1;
|
||||
|
||||
if (*cptr == '.') { /* relative? */
|
||||
cptr++;
|
||||
*ea = addr;
|
||||
if (*cptr == '+') cptr++; /* .+? */
|
||||
else if (*cptr == '-') { /* .-? */
|
||||
sign = -1;
|
||||
cptr++; }
|
||||
else return SCPE_OK; }
|
||||
if (*cptr == '.') { /* relative? */
|
||||
cptr++;
|
||||
*ea = addr;
|
||||
if (*cptr == '+') cptr++; /* .+? */
|
||||
else if (*cptr == '-') { /* .-? */
|
||||
sign = -1;
|
||||
cptr++;
|
||||
}
|
||||
else return SCPE_OK;
|
||||
}
|
||||
else *ea = 0;
|
||||
errno = 0;
|
||||
*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
|
||||
if (errno || (cptr == *tptr)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Symbolic input */
|
||||
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
@@ -529,38 +557,42 @@ int32 by, rdx, num;
|
||||
t_stat r;
|
||||
DEVICE *dptr;
|
||||
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
else if (sw & SWMASK ('O')) rdx = 8;
|
||||
else if (sw & SWMASK ('H')) rdx = 16;
|
||||
else rdx = dptr->dradix;
|
||||
|
||||
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]);
|
||||
else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8);
|
||||
return 0; }
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (addr & 1) val[0] = (val[0] & ~0xFF) | by;
|
||||
else val[0] = (val[0] & 0xFF) | (by << 8);
|
||||
return 0; }
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]);
|
||||
else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8);
|
||||
return 0;
|
||||
}
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (addr & 1) val[0] = (val[0] & ~0xFF) | by;
|
||||
else val[0] = (val[0] & 0xFF) | (by << 8);
|
||||
return 0;
|
||||
}
|
||||
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1];
|
||||
return -1; }
|
||||
if (sw & SWMASK ('H')) { /* halfword? */
|
||||
val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
return -1; }
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1];
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK ('H')) { /* halfword? */
|
||||
val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
||||
if (r <= 0) return r;
|
||||
num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */
|
||||
num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
val[0] = (num >> 16) & DMASK16;
|
||||
val[1] = num & DMASK16;
|
||||
@@ -570,13 +602,13 @@ return -3;
|
||||
/* Symbolic input for -m
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*val = pointer to output values
|
||||
cf = true if parsing for CPU
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*val = pointer to output values
|
||||
cf = true if parsing for CPU
|
||||
Outputs:
|
||||
status = > 0 error code
|
||||
<= 0 -number of extra words
|
||||
status = > 0 error code
|
||||
<= 0 -number of extra words
|
||||
*/
|
||||
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
|
||||
@@ -587,91 +619,97 @@ t_stat r;
|
||||
char *tptr, gbuf[CBUFSIZE];
|
||||
|
||||
vp = 0;
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
|
||||
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
if (opcode[i] == NULL) return SCPE_ARG;
|
||||
inst = opc_val[i] & 0xFFFF; /* get value */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if (r1_type[j]) { /* any R1 field? */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */
|
||||
if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
inst = inst | (r1 << 4); } /* or in R1 */
|
||||
inst = opc_val[i] & 0xFFFF; /* get value */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if (r1_type[j]) { /* any R1 field? */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */
|
||||
if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
inst = inst | (r1 << 4); /* or in R1 */
|
||||
}
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get operand */
|
||||
if (*cptr) return SCPE_ARG; /* should be end */
|
||||
switch (j) { /* case on class */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get operand */
|
||||
if (*cptr) return SCPE_ARG; /* should be end */
|
||||
switch (j) { /* case on class */
|
||||
|
||||
case I_V_FF: case I_V_SI: /* flt-flt, sh imm */
|
||||
case I_V_MR: case I_V_RR: /* mask/reg-register */
|
||||
case I_V_R: /* register */
|
||||
if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
inst = inst | r2; /* or in R2 */
|
||||
break;
|
||||
case I_V_FF: case I_V_SI: /* flt-flt, sh imm */
|
||||
case I_V_MR: case I_V_RR: /* mask/reg-register */
|
||||
case I_V_R: /* register */
|
||||
if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
inst = inst | r2; /* or in R2 */
|
||||
break;
|
||||
|
||||
case I_V_FX: /* float-memory */
|
||||
case I_V_MX: case I_V_RX: /* mask/reg-memory */
|
||||
case I_V_X: /* memory */
|
||||
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
|
||||
if (r != SCPE_OK) return SCPE_ARG; /* error? */
|
||||
rx2 = 0; /* assume no 2nd */
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
inst = inst | r2; /* or in R2 */
|
||||
if (*tptr == ',') { /* 2nd index? */
|
||||
if ((rx2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG; }
|
||||
if (*tptr++ != ')') return SCPE_ARG; } /* all done? */
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
val[0] = inst; /* store inst */
|
||||
if (rx2 == 0) { /* no 2nd? */
|
||||
if (t < 0x4000) { /* RX1? */
|
||||
val[1] = t; /* store ea */
|
||||
return -3; }
|
||||
st = (t - (addr + 4)); /* displ */
|
||||
if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */
|
||||
t = (st & 0x7FFF) | 0x8000;
|
||||
val[1] = t; /* store displ */
|
||||
return -3; } }
|
||||
t = (t & VAMASK32) | 0x40000000 | (rx2 << 24);
|
||||
val[1] = (t >> 16) & DMASK16;
|
||||
val[2] = t & DMASK16;
|
||||
return -5;
|
||||
case I_V_FX: /* float-memory */
|
||||
case I_V_MX: case I_V_RX: /* mask/reg-memory */
|
||||
case I_V_X: /* memory */
|
||||
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
|
||||
if (r != SCPE_OK) return SCPE_ARG; /* error? */
|
||||
rx2 = 0; /* assume no 2nd */
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
inst = inst | r2; /* or in R2 */
|
||||
if (*tptr == ',') { /* 2nd index? */
|
||||
if ((rx2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
}
|
||||
if (*tptr++ != ')') return SCPE_ARG; /* all done? */
|
||||
}
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
val[0] = inst; /* store inst */
|
||||
if (rx2 == 0) { /* no 2nd? */
|
||||
if (t < 0x4000) { /* RX1? */
|
||||
val[1] = t; /* store ea */
|
||||
return -3;
|
||||
}
|
||||
st = (t - (addr + 4)); /* displ */
|
||||
if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */
|
||||
t = (st & 0x7FFF) | 0x8000;
|
||||
val[1] = t; /* store displ */
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
t = (t & VAMASK32) | 0x40000000 | (rx2 << 24);
|
||||
val[1] = (t >> 16) & DMASK16;
|
||||
val[2] = t & DMASK16;
|
||||
return -5;
|
||||
|
||||
case I_V_RI: /* 16b immediate */
|
||||
r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */
|
||||
if (r != SCPE_OK) return r;
|
||||
val[0] = inst;
|
||||
val[1] = t;
|
||||
return -3;
|
||||
case I_V_RI: /* 16b immediate */
|
||||
r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */
|
||||
if (r != SCPE_OK) return r;
|
||||
val[0] = inst;
|
||||
val[1] = t;
|
||||
return -3;
|
||||
|
||||
case I_V_RF:
|
||||
r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */
|
||||
if (r != SCPE_OK) return r;
|
||||
val[0] = inst;
|
||||
val[1] = (t >> 16) & DMASK16;
|
||||
val[2] = t & DMASK16;
|
||||
return -5;
|
||||
case I_V_RF:
|
||||
r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */
|
||||
if (r != SCPE_OK) return r;
|
||||
val[0] = inst;
|
||||
val[1] = (t >> 16) & DMASK16;
|
||||
val[2] = t & DMASK16;
|
||||
return -5;
|
||||
|
||||
case I_V_SB: case I_V_SX: /* short branches */
|
||||
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
|
||||
return SCPE_ARG;
|
||||
st = t; /* signed version */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
else return SCPE_ARG;
|
||||
} /* end case */
|
||||
case I_V_SB: case I_V_SX: /* short branches */
|
||||
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
|
||||
return SCPE_ARG;
|
||||
st = t; /* signed version */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
else return SCPE_ARG;
|
||||
} /* end case */
|
||||
|
||||
val[0] = inst;
|
||||
return -1;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id_defs.h: Interdata 16b/32b simulator definitions
|
||||
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,444 +19,444 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
The author gratefully acknowledges the help of Carl Friend and Al Kossow,
|
||||
who provided key documents about the Interdata product line.
|
||||
|
||||
25-Jan-04 RMS Removed local logging support
|
||||
22-Sep-03 RMS Added additional instruction decode types
|
||||
21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Feb-03 RMS Changed magtape device default to 0x85
|
||||
25-Jan-04 RMS Removed local logging support
|
||||
22-Sep-03 RMS Added additional instruction decode types
|
||||
21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Feb-03 RMS Changed magtape device default to 0x85
|
||||
*/
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
#ifndef _ID_DEFS_H_
|
||||
#define _ID_DEFS_H_ 0
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* undef instr */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_WAIT 4 /* wait */
|
||||
#define STOP_VFU 5 /* runaway VFU */
|
||||
#define STOP_RSRV 1 /* undef instr */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_WAIT 4 /* wait */
|
||||
#define STOP_VFU 5 /* runaway VFU */
|
||||
|
||||
/* Memory */
|
||||
|
||||
#define PAWIDTH16 16
|
||||
#define PAWIDTH16E 18
|
||||
#define PAWIDTH32 20
|
||||
#define MAXMEMSIZE16 (1u << PAWIDTH16) /* max mem size, 16b */
|
||||
#define MAXMEMSIZE16E (1u << PAWIDTH16E) /* max mem size, 16b E */
|
||||
#define MAXMEMSIZE32 (1u << PAWIDTH32) /* max mem size, 32b */
|
||||
#define PAMASK16 (MAXMEMSIZE16 - 1) /* phys mem mask */
|
||||
#define PAMASK16E (MAXMEMSIZE16E - 1)
|
||||
#define PAMASK32 (MAXMEMSIZE32 - 1)
|
||||
#define PAWIDTH16 16
|
||||
#define PAWIDTH16E 18
|
||||
#define PAWIDTH32 20
|
||||
#define MAXMEMSIZE16 (1u << PAWIDTH16) /* max mem size, 16b */
|
||||
#define MAXMEMSIZE16E (1u << PAWIDTH16E) /* max mem size, 16b E */
|
||||
#define MAXMEMSIZE32 (1u << PAWIDTH32) /* max mem size, 32b */
|
||||
#define PAMASK16 (MAXMEMSIZE16 - 1) /* phys mem mask */
|
||||
#define PAMASK16E (MAXMEMSIZE16E - 1)
|
||||
#define PAMASK32 (MAXMEMSIZE32 - 1)
|
||||
|
||||
#define MEMSIZE (cpu_unit.capac) /* act memory size */
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
|
||||
#define MEMSIZE (cpu_unit.capac) /* act memory size */
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
|
||||
|
||||
/* Single precision floating point registers */
|
||||
|
||||
#if defined (IFP_IN_MEM)
|
||||
#define ReadFReg(r) (fp_in_hwre? \
|
||||
F[(r) >> 1]: ReadF (((r) << 1) & ~3, P))
|
||||
#define WriteFReg(r,v) if (fp_in_hwre) F[(r) >> 1] = (v); \
|
||||
else WriteF (((r) << 1) & ~3, (v), P)
|
||||
#define ReadFReg(r) (fp_in_hwre? \
|
||||
F[(r) >> 1]: ReadF (((r) << 1) & ~3, P))
|
||||
#define WriteFReg(r,v) if (fp_in_hwre) F[(r) >> 1] = (v); \
|
||||
else WriteF (((r) << 1) & ~3, (v), P)
|
||||
#else
|
||||
#define ReadFReg(r) (F[(r) >> 1])
|
||||
#define WriteFReg(r,v) F[(r) >> 1] = (v)
|
||||
#define ReadFReg(r) (F[(r) >> 1])
|
||||
#define WriteFReg(r,v) F[(r) >> 1] = (v)
|
||||
#endif
|
||||
|
||||
/* Double precision floating point registers */
|
||||
|
||||
struct dpr {
|
||||
uint32 h; /* high 32b */
|
||||
uint32 l; /* low 32b */
|
||||
};
|
||||
|
||||
typedef struct dpr dpr_t;
|
||||
typedef struct {
|
||||
uint32 h; /* high 32b */
|
||||
uint32 l; /* low 32b */
|
||||
} dpr_t;
|
||||
|
||||
/* Architectural constants */
|
||||
|
||||
#define VAMASK16 (0xFFFF) /* 16b virt addr */
|
||||
#define VAMASK32 (0x000FFFFF) /* 32b virt addr */
|
||||
#define VAMASK16 (0xFFFF) /* 16b virt addr */
|
||||
#define VAMASK32 (0x000FFFFF) /* 32b virt addr */
|
||||
|
||||
#define SIGN8 0x80 /* 8b sign bit */
|
||||
#define DMASK8 0xFF /* 8b data mask */
|
||||
#define MMASK8 0x7F /* 8b magnitude mask */
|
||||
#define SIGN16 0x8000 /* 16b sign bit */
|
||||
#define DMASK16 0xFFFF /* 16b data mask */
|
||||
#define MMASK16 0x7FFF /* 16b magnitude mask */
|
||||
#define SIGN32 0x80000000 /* 32b sign bit */
|
||||
#define DMASK32 0xFFFFFFFF /* 32b data mask */
|
||||
#define MMASK32 0x7FFFFFFF /* 32b magn mask */
|
||||
#define SIGN8 0x80 /* 8b sign bit */
|
||||
#define DMASK8 0xFF /* 8b data mask */
|
||||
#define MMASK8 0x7F /* 8b magnitude mask */
|
||||
#define SIGN16 0x8000 /* 16b sign bit */
|
||||
#define DMASK16 0xFFFF /* 16b data mask */
|
||||
#define MMASK16 0x7FFF /* 16b magnitude mask */
|
||||
#define SIGN32 0x80000000 /* 32b sign bit */
|
||||
#define DMASK32 0xFFFFFFFF /* 32b data mask */
|
||||
#define MMASK32 0x7FFFFFFF /* 32b magn mask */
|
||||
|
||||
#define CC_C 0x8 /* carry */
|
||||
#define CC_V 0x4 /* overflow */
|
||||
#define CC_G 0x2 /* greater than */
|
||||
#define CC_L 0x1 /* less than */
|
||||
#define CC_MASK (CC_C | CC_V | CC_G | CC_L)
|
||||
#define CC_C 0x8 /* carry */
|
||||
#define CC_V 0x4 /* overflow */
|
||||
#define CC_G 0x2 /* greater than */
|
||||
#define CC_L 0x1 /* less than */
|
||||
#define CC_MASK (CC_C | CC_V | CC_G | CC_L)
|
||||
|
||||
#define PSW_WAIT 0x8000 /* wait */
|
||||
#define PSW_EXI 0x4000 /* ext intr enable */
|
||||
#define PSW_MCI 0x2000 /* machine check enable */
|
||||
#define PSW_AFI 0x1000 /* arith fault enb */
|
||||
#define PSW_AIO 0x0800 /* auto I/O int enable */
|
||||
#define PSW_FPF 0x0400 /* flt fault enb, 16b */
|
||||
#define PSW_REL 0x0400 /* reloc enb, 32b */
|
||||
#define PSW_SQI 0x0200 /* sys q int enable */
|
||||
#define PSW_PRO 0x0100 /* protect mode */
|
||||
#define PSW_V_MAP 4 /* mem map, 16b */
|
||||
#define PSW_M_MAP 0xF
|
||||
#define PSW_MAP (PSW_M_MAP << PSW_V_MAP)
|
||||
#define PSW_V_REG 4 /* reg set, 32b */
|
||||
#define PSW_M_REG 0x1
|
||||
#define PSW_ID4 0xF40F /* I3, I4 PSW */
|
||||
#define PSW_x16 0xFF0F /* 7/16, 8/16 PSW */
|
||||
#define PSW_816E 0xFFFF /* 8/16E PSW */
|
||||
#define PSW_x32 0xFFFF /* 7/32, 8/32 PSW */
|
||||
#define PSW_GETMAP(x) (((x) >> PSW_V_MAP) & PSW_M_MAP)
|
||||
#define PSW_GETREG(x) (((x) >> PSW_V_REG) & PSW_M_REG)
|
||||
#define PSW_WAIT 0x8000 /* wait */
|
||||
#define PSW_EXI 0x4000 /* ext intr enable */
|
||||
#define PSW_MCI 0x2000 /* machine check enable */
|
||||
#define PSW_AFI 0x1000 /* arith fault enb */
|
||||
#define PSW_AIO 0x0800 /* auto I/O int enable */
|
||||
#define PSW_FPF 0x0400 /* flt fault enb, 16b */
|
||||
#define PSW_REL 0x0400 /* reloc enb, 32b */
|
||||
#define PSW_SQI 0x0200 /* sys q int enable */
|
||||
#define PSW_PRO 0x0100 /* protect mode */
|
||||
#define PSW_V_MAP 4 /* mem map, 16b */
|
||||
#define PSW_M_MAP 0xF
|
||||
#define PSW_MAP (PSW_M_MAP << PSW_V_MAP)
|
||||
#define PSW_V_REG 4 /* reg set, 32b */
|
||||
#define PSW_M_REG 0x1
|
||||
#define PSW_ID4 0xF40F /* I3, I4 PSW */
|
||||
#define PSW_x16 0xFF0F /* 7/16, 8/16 PSW */
|
||||
#define PSW_816E 0xFFFF /* 8/16E PSW */
|
||||
#define PSW_x32 0xFFFF /* 7/32, 8/32 PSW */
|
||||
#define PSW_GETMAP(x) (((x) >> PSW_V_MAP) & PSW_M_MAP)
|
||||
#define PSW_GETREG(x) (((x) >> PSW_V_REG) & PSW_M_REG)
|
||||
|
||||
#define MCKOPSW 0x20 /* mchk old PSW, 32b */
|
||||
#define FPFPSW 0x28 /* flt fault PSW, 16b */
|
||||
#define ILOPSW 0x30 /* ill op PSW */
|
||||
#define MCKPSW 0x38 /* mach chk PSW */
|
||||
#define EXIPSW 0x40 /* ext intr PSW, 16b */
|
||||
#define AFIPSW 0x48 /* arith flt PSW */
|
||||
#define SQP 0x80 /* system queue ptr */
|
||||
#define SQIPSW 0x82 /* sys q int PSW, 16b */
|
||||
#define SQOP 0x8A /* sys q ovf ptr, 16b */
|
||||
#define SQVPSW 0x8C /* sys q ovf PSW, 16b */
|
||||
#define SQTPSW 0x88 /* sys q int PSW, 32b */
|
||||
#define MPRPSW 0x90 /* mprot int PSW, 32b */
|
||||
#define SVCAP 0x94 /* svc arg ptr, 16b */
|
||||
#define SVOPS 0x96 /* svc old PS, 16b */
|
||||
#define SVOPC 0x98 /* svc old PC, 16b */
|
||||
#define SVNPS32 0x98 /* svc new PS, 32b */
|
||||
#define SVNPS 0x9A /* svc new PS, 16b */
|
||||
#define SVNPC 0x9C /* svc new PC */
|
||||
#define INTSVT 0xD0 /* int service table */
|
||||
#define MCKOPSW 0x20 /* mchk old PSW, 32b */
|
||||
#define FPFPSW 0x28 /* flt fault PSW, 16b */
|
||||
#define ILOPSW 0x30 /* ill op PSW */
|
||||
#define MCKPSW 0x38 /* mach chk PSW */
|
||||
#define EXIPSW 0x40 /* ext intr PSW, 16b */
|
||||
#define AFIPSW 0x48 /* arith flt PSW */
|
||||
#define SQP 0x80 /* system queue ptr */
|
||||
#define SQIPSW 0x82 /* sys q int PSW, 16b */
|
||||
#define SQOP 0x8A /* sys q ovf ptr, 16b */
|
||||
#define SQVPSW 0x8C /* sys q ovf PSW, 16b */
|
||||
#define SQTPSW 0x88 /* sys q int PSW, 32b */
|
||||
#define MPRPSW 0x90 /* mprot int PSW, 32b */
|
||||
#define SVCAP 0x94 /* svc arg ptr, 16b */
|
||||
#define SVOPS 0x96 /* svc old PS, 16b */
|
||||
#define SVOPC 0x98 /* svc old PC, 16b */
|
||||
#define SVNPS32 0x98 /* svc new PS, 32b */
|
||||
#define SVNPS 0x9A /* svc new PS, 16b */
|
||||
#define SVNPC 0x9C /* svc new PC */
|
||||
#define INTSVT 0xD0 /* int service table */
|
||||
|
||||
#define AL_DEV 0x78 /* autoload: dev */
|
||||
#define AL_IOC 0x79 /* command */
|
||||
#define AL_DSKU 0x7A /* disk unit */
|
||||
#define AL_DSKT 0x7B /* disk type */
|
||||
#define AL_DSKC 0x7C /* disk ctrl */
|
||||
#define AL_SCH 0x7D /* sel chan */
|
||||
#define AL_EXT 0x7E /* OS extension */
|
||||
#define AL_BUF 0x80 /* buffer start */
|
||||
#define AL_DEV 0x78 /* autoload: dev */
|
||||
#define AL_IOC 0x79 /* command */
|
||||
#define AL_DSKU 0x7A /* disk unit */
|
||||
#define AL_DSKT 0x7B /* disk type */
|
||||
#define AL_DSKC 0x7C /* disk ctrl */
|
||||
#define AL_SCH 0x7D /* sel chan */
|
||||
#define AL_EXT 0x7E /* OS extension */
|
||||
#define AL_BUF 0x80 /* buffer start */
|
||||
|
||||
#define Q16_SLT 0 /* list: # slots */
|
||||
#define Q16_USD 1 /* # in use */
|
||||
#define Q16_TOP 2 /* current top */
|
||||
#define Q16_BOT 3 /* next bottom */
|
||||
#define Q16_BASE 4 /* base of q */
|
||||
#define Q16_SLNT 2 /* slot length */
|
||||
#define Q16_SLT 0 /* list: # slots */
|
||||
#define Q16_USD 1 /* # in use */
|
||||
#define Q16_TOP 2 /* current top */
|
||||
#define Q16_BOT 3 /* next bottom */
|
||||
#define Q16_BASE 4 /* base of q */
|
||||
#define Q16_SLNT 2 /* slot length */
|
||||
|
||||
#define Q32_SLT 0 /* list: # slots */
|
||||
#define Q32_USD 2 /* # in use */
|
||||
#define Q32_TOP 4 /* current top */
|
||||
#define Q32_BOT 6 /* next bottom */
|
||||
#define Q32_BASE 8 /* base of q */
|
||||
#define Q32_SLNT 4 /* slot length */
|
||||
#define Q32_SLT 0 /* list: # slots */
|
||||
#define Q32_USD 2 /* # in use */
|
||||
#define Q32_TOP 4 /* current top */
|
||||
#define Q32_BOT 6 /* next bottom */
|
||||
#define Q32_BASE 8 /* base of q */
|
||||
#define Q32_SLNT 4 /* slot length */
|
||||
|
||||
/* CPU event flags */
|
||||
|
||||
#define EV_MAC 0x01 /* MAC interrupt */
|
||||
#define EV_BLK 0x02 /* block I/O in prog */
|
||||
#define EV_INT 0x04 /* interrupt pending */
|
||||
#define EV_WAIT 0x08 /* wait state pending */
|
||||
#define EV_MAC 0x01 /* MAC interrupt */
|
||||
#define EV_BLK 0x02 /* block I/O in prog */
|
||||
#define EV_INT 0x04 /* interrupt pending */
|
||||
#define EV_WAIT 0x08 /* wait state pending */
|
||||
|
||||
/* Block I/O state */
|
||||
|
||||
struct BlockIO {
|
||||
uint32 dfl; /* devno, flags */
|
||||
uint32 cur; /* current addr */
|
||||
uint32 end; /* end addr */
|
||||
};
|
||||
uint32 dfl; /* devno, flags */
|
||||
uint32 cur; /* current addr */
|
||||
uint32 end; /* end addr */
|
||||
};
|
||||
|
||||
#define BL_RD 0x8000 /* block read */
|
||||
#define BL_LZ 0x4000 /* skip 0's */
|
||||
#define BL_RD 0x8000 /* block read */
|
||||
#define BL_LZ 0x4000 /* skip 0's */
|
||||
|
||||
/* Instruction decode ROM, for all, 16b, 32b */
|
||||
|
||||
#define OP_UNDEF 0x0000 /* undefined */
|
||||
#define OP_NO 0x0001 /* all: short or fp rr */
|
||||
#define OP_RR 0x0002 /* all: reg-reg */
|
||||
#define OP_RS 0x0003 /* 16b: reg-storage */
|
||||
#define OP_RI1 0x0003 /* 32b: reg-imm 16b */
|
||||
#define OP_RX 0x0004 /* all: reg-mem */
|
||||
#define OP_RXB 0x0005 /* all: reg-mem, rd BY */
|
||||
#define OP_RXH 0x0006 /* all: reg-mem, rd HW */
|
||||
#define OP_RXF 0x0007 /* 32b: reg-mem, rd FW */
|
||||
#define OP_RI2 0x0008 /* 32b: reg-imm 32b */
|
||||
#define OP_MASK 0x000F
|
||||
#define OP_UNDEF 0x0000 /* undefined */
|
||||
#define OP_NO 0x0001 /* all: short or fp rr */
|
||||
#define OP_RR 0x0002 /* all: reg-reg */
|
||||
#define OP_RS 0x0003 /* 16b: reg-storage */
|
||||
#define OP_RI1 0x0003 /* 32b: reg-imm 16b */
|
||||
#define OP_RX 0x0004 /* all: reg-mem */
|
||||
#define OP_RXB 0x0005 /* all: reg-mem, rd BY */
|
||||
#define OP_RXH 0x0006 /* all: reg-mem, rd HW */
|
||||
#define OP_RXF 0x0007 /* 32b: reg-mem, rd FW */
|
||||
#define OP_RI2 0x0008 /* 32b: reg-imm 32b */
|
||||
#define OP_MASK 0x000F
|
||||
|
||||
#define OP_ID4 0x0010 /* 16b: ID4 */
|
||||
#define OP_716 0x0020 /* 16b: 7/16 */
|
||||
#define OP_816 0x0040 /* 16b: 8/16 */
|
||||
#define OP_816E 0x0080 /* 16b: 8/16E */
|
||||
#define OP_ID4 0x0010 /* 16b: ID4 */
|
||||
#define OP_716 0x0020 /* 16b: 7/16 */
|
||||
#define OP_816 0x0040 /* 16b: 8/16 */
|
||||
#define OP_816E 0x0080 /* 16b: 8/16E */
|
||||
|
||||
#define OP_DPF 0x4000 /* all: hwre FP */
|
||||
#define OP_PRV 0x8000 /* all: privileged */
|
||||
#define OP_DPF 0x4000 /* all: hwre FP */
|
||||
#define OP_PRV 0x8000 /* all: privileged */
|
||||
|
||||
#define OP_TYPE(x) (decrom[(x)] & OP_MASK)
|
||||
#define OP_DPFP(x) (decrom[(x)] & OP_DPF)
|
||||
|
||||
#define OP_TYPE(x) (decrom[(x)] & OP_MASK)
|
||||
#define OP_DPFP(x) (decrom[(x)] & OP_DPF)
|
||||
|
||||
/* Device information block */
|
||||
|
||||
struct interdib {
|
||||
uint32 dno; /* device number */
|
||||
int32 sch; /* sch */
|
||||
uint32 irq; /* interrupt */
|
||||
uint8 *tplte; /* template */
|
||||
uint32 (*iot)(uint32 d, uint32 o, uint32 dat);
|
||||
void (*ini)(t_bool f); };
|
||||
typedef struct {
|
||||
uint32 dno; /* device number */
|
||||
int32 sch; /* sch */
|
||||
uint32 irq; /* interrupt */
|
||||
uint8 *tplte; /* template */
|
||||
uint32 (*iot)(uint32 d, uint32 o, uint32 dat);
|
||||
void (*ini)(t_bool f);
|
||||
} DIB;
|
||||
|
||||
typedef struct interdib DIB;
|
||||
|
||||
#define TPL_END 0xFF /* template end */
|
||||
#define TPL_END 0xFF /* template end */
|
||||
|
||||
/* Device select return codes */
|
||||
|
||||
#define BY 0 /* 8b only */
|
||||
#define HW 1 /* 8b/16b */
|
||||
#define BY 0 /* 8b only */
|
||||
#define HW 1 /* 8b/16b */
|
||||
|
||||
/* I/O operations */
|
||||
|
||||
#define IO_ADR 0x0 /* address select */
|
||||
#define IO_RD 0x1 /* read byte */
|
||||
#define IO_RH 0x2 /* read halfword */
|
||||
#define IO_WD 0x3 /* write byte */
|
||||
#define IO_WH 0x4 /* write halfword */
|
||||
#define IO_OC 0x5 /* output command */
|
||||
#define IO_SS 0x6 /* sense status */
|
||||
#define IO_ADR 0x0 /* address select */
|
||||
#define IO_RD 0x1 /* read byte */
|
||||
#define IO_RH 0x2 /* read halfword */
|
||||
#define IO_WD 0x3 /* write byte */
|
||||
#define IO_WH 0x4 /* write halfword */
|
||||
#define IO_OC 0x5 /* output command */
|
||||
#define IO_SS 0x6 /* sense status */
|
||||
|
||||
/* Device command byte */
|
||||
|
||||
#define CMD_V_INT 6 /* interrupt control */
|
||||
#define CMD_M_INT 0x3
|
||||
#define CMD_IENB 1 /* enable */
|
||||
#define CMD_IDIS 2 /* disable */
|
||||
#define CMD_IDSA 3 /* disarm */
|
||||
#define CMD_GETINT(x) (((x) >> CMD_V_INT) & CMD_M_INT)
|
||||
#define CMD_V_INT 6 /* interrupt control */
|
||||
#define CMD_M_INT 0x3
|
||||
#define CMD_IENB 1 /* enable */
|
||||
#define CMD_IDIS 2 /* disable */
|
||||
#define CMD_IDSA 3 /* disarm */
|
||||
#define CMD_GETINT(x) (((x) >> CMD_V_INT) & CMD_M_INT)
|
||||
|
||||
/* Device status byte */
|
||||
|
||||
#define STA_BSY 0x8 /* busy */
|
||||
#define STA_EX 0x4 /* examine status */
|
||||
#define STA_EOM 0x2 /* end of medium */
|
||||
#define STA_DU 0x1 /* device unavailable */
|
||||
#define STA_BSY 0x8 /* busy */
|
||||
#define STA_EX 0x4 /* examine status */
|
||||
#define STA_EOM 0x2 /* end of medium */
|
||||
#define STA_DU 0x1 /* device unavailable */
|
||||
|
||||
/* Default device numbers */
|
||||
|
||||
#define DEV_LOW 0x01 /* lowest intr dev */
|
||||
#define DEV_MAX 0xFF /* highest intr dev */
|
||||
#define DEVNO (DEV_MAX + 1) /* number of devices */
|
||||
#define d_DS 0x01 /* display, switches */
|
||||
#define d_TT 0x02 /* teletype */
|
||||
#define d_PT 0x03 /* reader */
|
||||
#define d_CD 0x04 /* card reader */
|
||||
#define d_TTP 0x10 /* PAS as console */
|
||||
#define d_PAS 0x10 /* first PAS */
|
||||
#define o_PASX 0x01 /* offset to xmt */
|
||||
#define d_LPT 0x62 /* line printer */
|
||||
#define d_PIC 0x6C /* interval timer */
|
||||
#define d_LFC 0x6D /* line freq clk */
|
||||
#define d_MT 0x85 /* magtape */
|
||||
#define o_MT0 0x10
|
||||
#define d_DPC 0xB6 /* disk controller */
|
||||
#define o_DP0 0x10
|
||||
#define o_DPF 0x01 /* offset to fixed */
|
||||
#define d_FD 0xC1 /* floppy disk */
|
||||
#define d_SCH 0xF0 /* selector chan */
|
||||
#define d_IDC 0xFB /* MSM disk ctrl */
|
||||
#define o_ID0 0x01
|
||||
#define DEV_LOW 0x01 /* lowest intr dev */
|
||||
#define DEV_MAX 0xFF /* highest intr dev */
|
||||
#define DEVNO (DEV_MAX + 1) /* number of devices */
|
||||
#define d_DS 0x01 /* display, switches */
|
||||
#define d_TT 0x02 /* teletype */
|
||||
#define d_PT 0x03 /* reader */
|
||||
#define d_CD 0x04 /* card reader */
|
||||
#define d_TTP 0x10 /* PAS as console */
|
||||
#define d_PAS 0x10 /* first PAS */
|
||||
#define o_PASX 0x01 /* offset to xmt */
|
||||
#define d_LPT 0x62 /* line printer */
|
||||
#define d_PIC 0x6C /* interval timer */
|
||||
#define d_LFC 0x6D /* line freq clk */
|
||||
#define d_MT 0x85 /* magtape */
|
||||
#define o_MT0 0x10
|
||||
#define d_DPC 0xB6 /* disk controller */
|
||||
#define o_DP0 0x10
|
||||
#define o_DPF 0x01 /* offset to fixed */
|
||||
#define d_FD 0xC1 /* floppy disk */
|
||||
#define d_SCH 0xF0 /* selector chan */
|
||||
#define d_IDC 0xFB /* MSM disk ctrl */
|
||||
#define o_ID0 0x01
|
||||
|
||||
/* Interrupts
|
||||
|
||||
To make interrupt flags independent of device numbers, each device is
|
||||
assigned an interrupt flag in one of four interrupt words
|
||||
|
||||
word 0 DMA devices
|
||||
word 1 programmed I/O devices
|
||||
word 2-3 PAS devices
|
||||
word 0 DMA devices
|
||||
word 1 programmed I/O devices
|
||||
word 2-3 PAS devices
|
||||
|
||||
Devices are identified by a level and a bit within a level. Priorities
|
||||
run low to high in the array, right to left within words
|
||||
*/
|
||||
|
||||
#define INTSZ 4 /* interrupt words */
|
||||
#define SCH_NUMCH 4 /* #channels */
|
||||
#define ID_NUMDR 4 /* # MSM drives */
|
||||
#define DP_NUMDR 4 /* # DPC drives */
|
||||
#define MT_NUMDR 4 /* # MT drives */
|
||||
#define INTSZ 4 /* interrupt words */
|
||||
#define SCH_NUMCH 4 /* #channels */
|
||||
#define ID_NUMDR 4 /* # MSM drives */
|
||||
#define DP_NUMDR 4 /* # DPC drives */
|
||||
#define MT_NUMDR 4 /* # MT drives */
|
||||
|
||||
/* Word 0, DMA devices */
|
||||
|
||||
#define i_SCH 0 /* highest priority */
|
||||
#define i_IDC (i_SCH + SCH_NUMCH) /* MSM disk ctrl */
|
||||
#define i_DPC (i_IDC + ID_NUMDR + 1) /* cartridge disk ctrl */
|
||||
#define i_MT (i_DPC + DP_NUMDR + 1) /* magtape */
|
||||
#define i_SCH 0 /* highest priority */
|
||||
#define i_IDC (i_SCH + SCH_NUMCH) /* MSM disk ctrl */
|
||||
#define i_DPC (i_IDC + ID_NUMDR + 1) /* cartridge disk ctrl */
|
||||
#define i_MT (i_DPC + DP_NUMDR + 1) /* magtape */
|
||||
|
||||
#define l_SCH 0
|
||||
#define l_IDC 0
|
||||
#define l_DPC 0
|
||||
#define l_MT 0
|
||||
#define l_SCH 0
|
||||
#define l_IDC 0
|
||||
#define l_DPC 0
|
||||
#define l_MT 0
|
||||
|
||||
#define v_SCH (l_SCH * 32) + i_SCH
|
||||
#define v_IDC (l_IDC * 32) + i_IDC
|
||||
#define v_DPC (l_DPC * 32) + i_DPC
|
||||
#define v_MT (l_MT * 32) + i_MT
|
||||
#define v_SCH (l_SCH * 32) + i_SCH
|
||||
#define v_IDC (l_IDC * 32) + i_IDC
|
||||
#define v_DPC (l_DPC * 32) + i_DPC
|
||||
#define v_MT (l_MT * 32) + i_MT
|
||||
|
||||
/* Word 1, programmed I/O devices */
|
||||
|
||||
#define i_PIC 0 /* precision clock */
|
||||
#define i_LFC 1 /* line clock */
|
||||
#define i_FD 2 /* floppy disk */
|
||||
#define i_CD 3 /* card reader */
|
||||
#define i_LPT 4 /* line printer */
|
||||
#define i_PT 5 /* paper tape */
|
||||
#define i_TT 6 /* teletype */
|
||||
#define i_DS 7 /* display */
|
||||
#define i_TTP 10 /* PAS console */
|
||||
#define i_PIC 0 /* precision clock */
|
||||
#define i_LFC 1 /* line clock */
|
||||
#define i_FD 2 /* floppy disk */
|
||||
#define i_CD 3 /* card reader */
|
||||
#define i_LPT 4 /* line printer */
|
||||
#define i_PT 5 /* paper tape */
|
||||
#define i_TT 6 /* teletype */
|
||||
#define i_DS 7 /* display */
|
||||
#define i_TTP 10 /* PAS console */
|
||||
|
||||
#define l_PIC 1
|
||||
#define l_LFC 1
|
||||
#define l_FD 1
|
||||
#define l_CD 1
|
||||
#define l_LPT 1
|
||||
#define l_PT 1
|
||||
#define l_TT 1
|
||||
#define l_DS 1
|
||||
#define l_TTP 1
|
||||
#define l_PIC 1
|
||||
#define l_LFC 1
|
||||
#define l_FD 1
|
||||
#define l_CD 1
|
||||
#define l_LPT 1
|
||||
#define l_PT 1
|
||||
#define l_TT 1
|
||||
#define l_DS 1
|
||||
#define l_TTP 1
|
||||
|
||||
#define v_PIC (l_PIC * 32) + i_PIC
|
||||
#define v_LFC (l_LFC * 32) + i_LFC
|
||||
#define v_FD (l_FD * 32) + i_FD
|
||||
#define v_CD (l_CD * 32) + i_CD
|
||||
#define v_LPT (l_LPT * 32) + i_LPT
|
||||
#define v_PT (l_PT * 32) + i_PT
|
||||
#define v_TT (l_TT * 32) + i_TT
|
||||
#define v_DS (l_DS * 32) + i_DS
|
||||
#define v_TTP (l_TTP * 32) + i_TTP
|
||||
#define v_PIC (l_PIC * 32) + i_PIC
|
||||
#define v_LFC (l_LFC * 32) + i_LFC
|
||||
#define v_FD (l_FD * 32) + i_FD
|
||||
#define v_CD (l_CD * 32) + i_CD
|
||||
#define v_LPT (l_LPT * 32) + i_LPT
|
||||
#define v_PT (l_PT * 32) + i_PT
|
||||
#define v_TT (l_TT * 32) + i_TT
|
||||
#define v_DS (l_DS * 32) + i_DS
|
||||
#define v_TTP (l_TTP * 32) + i_TTP
|
||||
|
||||
/* Word 2-3, PAS devices */
|
||||
|
||||
#define i_PAS 0
|
||||
#define l_PAS 2
|
||||
#define v_PAS (l_PAS * 32) + i_PAS
|
||||
#define v_PASX (v_PAS + 1) /* offset to xmt */
|
||||
#define i_PAS 0
|
||||
#define l_PAS 2
|
||||
#define v_PAS (l_PAS * 32) + i_PAS
|
||||
#define v_PASX (v_PAS + 1) /* offset to xmt */
|
||||
|
||||
/* I/O macros */
|
||||
|
||||
#define SET_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] | (1u << ((v) & 0x1F))
|
||||
#define CLR_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] & ~(1u << ((v) & 0x1F))
|
||||
#define SET_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] | (1u << ((v) & 0x1F))
|
||||
#define CLR_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] & ~(1u << ((v) & 0x1F))
|
||||
#define SET_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] | (1u << ((v) & 0x1F))
|
||||
#define CLR_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] & ~(1u << ((v) & 0x1F))
|
||||
#define SET_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] | (1u << ((v) & 0x1F))
|
||||
#define CLR_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] & ~(1u << ((v) & 0x1F))
|
||||
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
|
||||
|
||||
/* Device accessible macro */
|
||||
|
||||
#define DEV_ACC(d) (dev_tab[d] && !sch_blk (d))
|
||||
|
||||
#define DEV_ACC(d) (dev_tab[d] && !sch_blk (d))
|
||||
|
||||
/* Automatic I/O channel programs, 16b */
|
||||
|
||||
#define CCB16_CHN -4 /* chain */
|
||||
#define CCB16_DEV -2 /* dev no */
|
||||
#define CCB16_STS -1 /* status */
|
||||
#define CCB16_CCW 0 /* cmd wd */
|
||||
#define CCB16_STR 2 /* start */
|
||||
#define CCB16_END 4 /* end */
|
||||
#define CCB16_IOC 6 /* OC byte */
|
||||
#define CCB16_TRM 7 /* term byte */
|
||||
#define CCB16_CHN -4 /* chain */
|
||||
#define CCB16_DEV -2 /* dev no */
|
||||
#define CCB16_STS -1 /* status */
|
||||
#define CCB16_CCW 0 /* cmd wd */
|
||||
#define CCB16_STR 2 /* start */
|
||||
#define CCB16_END 4 /* end */
|
||||
#define CCB16_IOC 6 /* OC byte */
|
||||
#define CCB16_TRM 7 /* term byte */
|
||||
|
||||
#define CCW16_INIT 0x8000 /* init */
|
||||
#define CCW16_NOP 0x4000 /* nop */
|
||||
#define CCW16_V_FNC 12 /* function */
|
||||
#define CCW16_M_FNC 0x3
|
||||
#define CCW16_FNC(x) (((x) >> CCW16_V_FNC) & CCW16_M_FNC)
|
||||
#define CCW16_RD 0 /* read */
|
||||
#define CCW16_WR 1 /* write */
|
||||
#define CCW16_DMT 2 /* dec mem */
|
||||
#define CCW16_NUL 3 /* null */
|
||||
#define CCW16_TRM 0x0400 /* term char */
|
||||
#define CCW16_Q 0x0200 /* queue */
|
||||
#define CCW16_HI 0x0100 /* queue hi */
|
||||
#define CCW16_OC 0x0080 /* OC */
|
||||
#define CCW16_CHN 0x0020 /* chain */
|
||||
#define CCW16_CON 0x0010 /* continue */
|
||||
#define CCW16_V_BPI 0 /* bytes per int */
|
||||
#define CCW16_M_BPI 0xF
|
||||
#define CCW16_BPI(x) (((x) >> CCW16_V_BPI) & CCW16_M_BPI)
|
||||
#define CCW16_INIT 0x8000 /* init */
|
||||
#define CCW16_NOP 0x4000 /* nop */
|
||||
#define CCW16_V_FNC 12 /* function */
|
||||
#define CCW16_M_FNC 0x3
|
||||
#define CCW16_FNC(x) (((x) >> CCW16_V_FNC) & CCW16_M_FNC)
|
||||
#define CCW16_RD 0 /* read */
|
||||
#define CCW16_WR 1 /* write */
|
||||
#define CCW16_DMT 2 /* dec mem */
|
||||
#define CCW16_NUL 3 /* null */
|
||||
#define CCW16_TRM 0x0400 /* term char */
|
||||
#define CCW16_Q 0x0200 /* queue */
|
||||
#define CCW16_HI 0x0100 /* queue hi */
|
||||
#define CCW16_OC 0x0080 /* OC */
|
||||
#define CCW16_CHN 0x0020 /* chain */
|
||||
#define CCW16_CON 0x0010 /* continue */
|
||||
#define CCW16_V_BPI 0 /* bytes per int */
|
||||
#define CCW16_M_BPI 0xF
|
||||
#define CCW16_BPI(x) (((x) >> CCW16_V_BPI) & CCW16_M_BPI)
|
||||
|
||||
/* Automatic I/O channel programs, 32b */
|
||||
|
||||
#define CCB32_CCW 0 /* cmd wd */
|
||||
#define CCB32_B0C 2 /* buf 0 cnt */
|
||||
#define CCB32_B0E 4 /* buf 0 end */
|
||||
#define CCB32_CHK 8 /* check word */
|
||||
#define CCB32_B1C 10 /* buf 1 cnt */
|
||||
#define CCB32_B1E 12 /* buf 1 end */
|
||||
#define CCB32_TAB 16 /* trans table */
|
||||
#define CCB32_SUB 20 /* subroutine */
|
||||
#define CCB32_CCW 0 /* cmd wd */
|
||||
#define CCB32_B0C 2 /* buf 0 cnt */
|
||||
#define CCB32_B0E 4 /* buf 0 end */
|
||||
#define CCB32_CHK 8 /* check word */
|
||||
#define CCB32_B1C 10 /* buf 1 cnt */
|
||||
#define CCB32_B1E 12 /* buf 1 end */
|
||||
#define CCB32_TAB 16 /* trans table */
|
||||
#define CCB32_SUB 20 /* subroutine */
|
||||
|
||||
#define CCW32_V_STA 8 /* status */
|
||||
#define CCW32_M_STA 0xFF
|
||||
#define CCW32_STA(x) (((x) >> CCW32_V_STA) & CCW32_M_STA)
|
||||
#define CCW32_EXE 0x80 /* execute */
|
||||
#define CCW32_CRC 0x10
|
||||
#define CCW32_B1 0x08 /* buffer 1 */
|
||||
#define CCW32_WR 0x04 /* write */
|
||||
#define CCW32_TL 0x02 /* translate */
|
||||
#define CCW32_FST 0x01 /* fast mode */
|
||||
#define CCW32_V_STA 8 /* status */
|
||||
#define CCW32_M_STA 0xFF
|
||||
#define CCW32_STA(x) (((x) >> CCW32_V_STA) & CCW32_M_STA)
|
||||
#define CCW32_EXE 0x80 /* execute */
|
||||
#define CCW32_CRC 0x10
|
||||
#define CCW32_B1 0x08 /* buffer 1 */
|
||||
#define CCW32_WR 0x04 /* write */
|
||||
#define CCW32_TL 0x02 /* translate */
|
||||
#define CCW32_FST 0x01 /* fast mode */
|
||||
|
||||
/* MAC, 32b */
|
||||
|
||||
#define P 0 /* physical */
|
||||
#define VE 1 /* virtual inst */
|
||||
#define VR 2 /* virtual read */
|
||||
#define VW 3 /* virtual write */
|
||||
#define P 0 /* physical */
|
||||
#define VE 1 /* virtual inst */
|
||||
#define VR 2 /* virtual read */
|
||||
#define VW 3 /* virtual write */
|
||||
|
||||
#define MAC_BASE 0x300 /* MAC base */
|
||||
#define MAC_STA 0x340 /* MAC status */
|
||||
#define MAC_LNT 16
|
||||
#define VA_V_OFF 0 /* offset */
|
||||
#define VA_M_OFF 0xFFFF
|
||||
#define VA_GETOFF(x) (((x) >> VA_V_OFF) & VA_M_OFF)
|
||||
#define VA_V_SEG 16 /* segment */
|
||||
#define VA_M_SEG 0xF
|
||||
#define VA_GETSEG(x) (((x) >> VA_V_SEG) & VA_M_SEG)
|
||||
#define MAC_BASE 0x300 /* MAC base */
|
||||
#define MAC_STA 0x340 /* MAC status */
|
||||
#define MAC_LNT 16
|
||||
#define VA_V_OFF 0 /* offset */
|
||||
#define VA_M_OFF 0xFFFF
|
||||
#define VA_GETOFF(x) (((x) >> VA_V_OFF) & VA_M_OFF)
|
||||
#define VA_V_SEG 16 /* segment */
|
||||
#define VA_M_SEG 0xF
|
||||
#define VA_GETSEG(x) (((x) >> VA_V_SEG) & VA_M_SEG)
|
||||
|
||||
#define SRF_MASK 0x000FFF00 /* base mask */
|
||||
#define SRL_MASK 0x0FF00000 /* limit mask */
|
||||
#define GET_SRL(x) ((((x) & SRL_MASK) >> 12) + 0x100)
|
||||
#define SR_EXP 0x80 /* execute prot */
|
||||
#define SR_WPI 0x40 /* wr prot int */
|
||||
#define SR_WRP 0x20 /* wr prot */
|
||||
#define SR_PRS 0x10 /* present */
|
||||
#define SR_MASK (SRF_MASK|SRL_MASK|SR_EXP|SR_WPI|SR_WRP|SR_PRS)
|
||||
#define SRF_MASK 0x000FFF00 /* base mask */
|
||||
#define SRL_MASK 0x0FF00000 /* limit mask */
|
||||
#define GET_SRL(x) ((((x) & SRL_MASK) >> 12) + 0x100)
|
||||
#define SR_EXP 0x80 /* execute prot */
|
||||
#define SR_WPI 0x40 /* wr prot int */
|
||||
#define SR_WRP 0x20 /* wr prot */
|
||||
#define SR_PRS 0x10 /* present */
|
||||
#define SR_MASK (SRF_MASK|SRL_MASK|SR_EXP|SR_WPI|SR_WRP|SR_PRS)
|
||||
|
||||
#define MACS_L 0x10 /* limit viol */
|
||||
#define MACS_NP 0x08 /* not present */
|
||||
#define MACS_WP 0x04 /* write prot */
|
||||
#define MACS_WI 0x02 /* write int */
|
||||
#define MACS_EX 0x01 /* exec prot */
|
||||
#define MACS_L 0x10 /* limit viol */
|
||||
#define MACS_NP 0x08 /* not present */
|
||||
#define MACS_WP 0x04 /* write prot */
|
||||
#define MACS_WI 0x02 /* write int */
|
||||
#define MACS_EX 0x01 /* exec prot */
|
||||
|
||||
/* Miscellaneous */
|
||||
|
||||
#define TMR_LFC 0 /* LFC = timer 0 */
|
||||
#define TMR_PIC 1 /* PIC = timer 1 */
|
||||
#define TMR_PAS 2 /* PAS = timer 2 */
|
||||
#define LPT_WIDTH 132
|
||||
#define VFU_LNT 132
|
||||
#define MIN(x,y) (((x) < (y))? (x): (y))
|
||||
#define MAX(x,y) (((x) > (y))? (x): (y))
|
||||
#define TMR_LFC 0 /* LFC = timer 0 */
|
||||
#define TMR_PIC 1 /* PIC = timer 1 */
|
||||
#define TMR_PAS 2 /* PAS = timer 2 */
|
||||
#define LPT_WIDTH 132
|
||||
#define VFU_LNT 132
|
||||
#define MIN(x,y) (((x) < (y))? (x): (y))
|
||||
#define MAX(x,y) (((x) > (y))? (x): (y))
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
@@ -479,3 +479,5 @@ t_stat set_sch (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat show_sch (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: Interdata 16b/32b Simulator Usage
|
||||
Date: 15-Mar-2005
|
||||
Date: 01-Jul-2005
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
@@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary:
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
This memorandum documents the Interdata 16b and 32b simulators.
|
||||
@@ -641,8 +641,7 @@ or a DETACH PAS command.
|
||||
|
||||
The SHOW PAS CONNECTIONS command displays the current connections to the
|
||||
extra terminals. The SHOW PAS STATISTICS command displays statistics for
|
||||
active connections. The SET PAS DISCONNECT=linenumber disconnects the
|
||||
specified line.
|
||||
active connections. The SET PASLn DISCONNECT command disconnects line n.
|
||||
|
||||
The controller (PAS) implements these registers:
|
||||
|
||||
|
||||
@@ -19,96 +19,96 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
dp M46-421 2.5MB/10MB cartridge disk
|
||||
dp M46-421 2.5MB/10MB cartridge disk
|
||||
|
||||
18-Mar-05 RMS Added attached test to detach routine
|
||||
25-Jan-04 RMS Revised for device debug support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
16-Feb-03 RMS Fixed read to test transfer ok before selch operation
|
||||
18-Mar-05 RMS Added attached test to detach routine
|
||||
25-Jan-04 RMS Revised for device debug support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
16-Feb-03 RMS Fixed read to test transfer ok before selch operation
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <math.h>
|
||||
|
||||
#define DP_NUMBY 256 /* bytes/sector */
|
||||
#define DP_NUMSC 24 /* sectors/track */
|
||||
#define DP_NUMBY 256 /* bytes/sector */
|
||||
#define DP_NUMSC 24 /* sectors/track */
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */
|
||||
#define UNIT_M_DTYPE 0x1
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */
|
||||
#define UNIT_M_DTYPE 0x1
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
|
||||
|
||||
#define CYL u3 /* current cylinder */
|
||||
#define STD u4 /* drive status */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define CYL u3 /* current cylinder */
|
||||
#define STD u4 /* drive status */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Controller status */
|
||||
|
||||
#define STC_OVR 0x80 /* overrun */
|
||||
#define STC_ACF 0x40 /* addr cmp fail */
|
||||
#define STC_DEF 0x20 /* def track NI */
|
||||
#define STC_CYO 0x10 /* cylinder ovflo */
|
||||
#define STC_IDL 0x02 /* ctrl idle */
|
||||
#define STC_DTE 0x01 /* xfer error */
|
||||
#define SETC_EX (STC_OVR|STC_ACF|STC_DEF|STC_CYO)
|
||||
#define STC_MASK (STC_OVR|STC_ACF|STC_DEF|STC_CYO|STA_BSY|STC_IDL|STC_DTE)
|
||||
#define STC_OVR 0x80 /* overrun */
|
||||
#define STC_ACF 0x40 /* addr cmp fail */
|
||||
#define STC_DEF 0x20 /* def track NI */
|
||||
#define STC_CYO 0x10 /* cylinder ovflo */
|
||||
#define STC_IDL 0x02 /* ctrl idle */
|
||||
#define STC_DTE 0x01 /* xfer error */
|
||||
#define SETC_EX (STC_OVR|STC_ACF|STC_DEF|STC_CYO)
|
||||
#define STC_MASK (STC_OVR|STC_ACF|STC_DEF|STC_CYO|STA_BSY|STC_IDL|STC_DTE)
|
||||
|
||||
/* Controller command */
|
||||
|
||||
#define CMC_MASK 0xF
|
||||
#define CMC_CLR 0x8 /* reset */
|
||||
#define CMC_RD 0x1 /* read */
|
||||
#define CMC_WR 0x2 /* write */
|
||||
#define CMC_RCHK 0x3 /* read check */
|
||||
#define CMC_RFMT 0x5 /* read fmt NI */
|
||||
#define CMC_WFMT 0x6 /* write fmt NI */
|
||||
#define CMC_MASK 0xF
|
||||
#define CMC_CLR 0x8 /* reset */
|
||||
#define CMC_RD 0x1 /* read */
|
||||
#define CMC_WR 0x2 /* write */
|
||||
#define CMC_RCHK 0x3 /* read check */
|
||||
#define CMC_RFMT 0x5 /* read fmt NI */
|
||||
#define CMC_WFMT 0x6 /* write fmt NI */
|
||||
|
||||
/* Drive status, ^ = dynamic, * = in unit status */
|
||||
|
||||
#define STD_WRP 0x80 /* ^write prot */
|
||||
#define STD_WCK 0x40 /* write check NI */
|
||||
#define STD_ILA 0x20 /* *illegal addr */
|
||||
#define STD_ILK 0x10 /* ^addr interlock */
|
||||
#define STD_MOV 0x08 /* *heads in motion */
|
||||
#define STD_INC 0x02 /* seek incomplete NI */
|
||||
#define STD_NRDY 0x01 /* ^not ready */
|
||||
#define STD_UST (STD_ILA | STD_MOV) /* set from unit */
|
||||
#define SETD_EX (STD_WCK | STD_ILA | STD_ILK) /* set examine */
|
||||
#define STD_WRP 0x80 /* ^write prot */
|
||||
#define STD_WCK 0x40 /* write check NI */
|
||||
#define STD_ILA 0x20 /* *illegal addr */
|
||||
#define STD_ILK 0x10 /* ^addr interlock */
|
||||
#define STD_MOV 0x08 /* *heads in motion */
|
||||
#define STD_INC 0x02 /* seek incomplete NI */
|
||||
#define STD_NRDY 0x01 /* ^not ready */
|
||||
#define STD_UST (STD_ILA | STD_MOV) /* set from unit */
|
||||
#define SETD_EX (STD_WCK | STD_ILA | STD_ILK) /* set examine */
|
||||
|
||||
/* Drive command */
|
||||
|
||||
#define CMD_SK 0x02 /* seek */
|
||||
#define CMD_RST 0x01 /* restore */
|
||||
#define CMD_SK 0x02 /* seek */
|
||||
#define CMD_RST 0x01 /* restore */
|
||||
|
||||
/* Head/sector register */
|
||||
|
||||
#define HS_SMASK 0x1F /* sector mask */
|
||||
#define HS_V_SRF 5 /* surface */
|
||||
#define HS_HMASK 0x20 /* head mask */
|
||||
#define HS_MASK (HS_HMASK | HS_SMASK)
|
||||
#define GET_SEC(x) ((x) & HS_SMASK)
|
||||
#define GET_SRF(x) (((x) & HS_HMASK) >> HS_V_SRF)
|
||||
#define HS_SMASK 0x1F /* sector mask */
|
||||
#define HS_V_SRF 5 /* surface */
|
||||
#define HS_HMASK 0x20 /* head mask */
|
||||
#define HS_MASK (HS_HMASK | HS_SMASK)
|
||||
#define GET_SEC(x) ((x) & HS_SMASK)
|
||||
#define GET_SRF(x) (((x) & HS_HMASK) >> HS_V_SRF)
|
||||
|
||||
#define GET_SA(p,cy,sf,sc,t) (((((((p)*drv_tab[t].cyl)+(cy))*drv_tab[t].surf)+(sf))* \
|
||||
DP_NUMSC)+(sc))
|
||||
#define GET_ROTATE(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) DP_NUMSC)))
|
||||
|
||||
DP_NUMSC)+(sc))
|
||||
#define GET_ROTATE(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) DP_NUMSC)))
|
||||
|
||||
/* This controller supports two different disk drive types:
|
||||
|
||||
type #sectors/ #surfaces/ #cylinders/
|
||||
surface cylinder drive
|
||||
type #sectors/ #surfaces/ #cylinders/
|
||||
surface cylinder drive
|
||||
|
||||
2315 24 2 203
|
||||
5440 24 4 408
|
||||
2315 24 2 203
|
||||
5440 24 4 408
|
||||
|
||||
In theory, each drive can be a different type. The size field in
|
||||
each unit selects the drive capacity for each drive and thus the
|
||||
@@ -116,45 +116,46 @@
|
||||
THE SAME SECTORS/TRACK.
|
||||
*/
|
||||
|
||||
#define TYPE_2315 0
|
||||
#define CYL_2315 203
|
||||
#define SURF_2315 2
|
||||
#define SIZE_2315 (DP_NUMSC * SURF_2315 * CYL_2315 * DP_NUMBY)
|
||||
#define TYPE_2315 0
|
||||
#define CYL_2315 203
|
||||
#define SURF_2315 2
|
||||
#define SIZE_2315 (DP_NUMSC * SURF_2315 * CYL_2315 * DP_NUMBY)
|
||||
|
||||
#define TYPE_5440 1
|
||||
#define CYL_5440 408
|
||||
#define SURF_5440 2
|
||||
#define SIZE_5440 (2 * DP_NUMSC * SURF_5440 * CYL_5440 * DP_NUMBY)
|
||||
#define TYPE_5440 1
|
||||
#define CYL_5440 408
|
||||
#define SURF_5440 2
|
||||
#define SIZE_5440 (2 * DP_NUMSC * SURF_5440 * CYL_5440 * DP_NUMBY)
|
||||
|
||||
struct drvtyp {
|
||||
int32 cyl; /* cylinders */
|
||||
uint32 surf; /* surfaces */
|
||||
uint32 size; /* #blocks */
|
||||
};
|
||||
int32 cyl; /* cylinders */
|
||||
uint32 surf; /* surfaces */
|
||||
uint32 size; /* #blocks */
|
||||
};
|
||||
|
||||
static struct drvtyp drv_tab[] = {
|
||||
{ CYL_2315, SURF_2315, SIZE_2315 },
|
||||
{ CYL_5440, SURF_5440, SIZE_5440 },
|
||||
{ 0 } };
|
||||
|
||||
{ CYL_2315, SURF_2315, SIZE_2315 },
|
||||
{ CYL_5440, SURF_5440, SIZE_5440 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
extern FILE *sim_deb;
|
||||
|
||||
uint8 dpxb[DP_NUMBY]; /* xfer buffer */
|
||||
uint32 dp_bptr = 0; /* buffer ptr */
|
||||
uint32 dp_db = 0; /* ctrl buffer */
|
||||
uint32 dp_cyl = 0; /* drive buffer */
|
||||
uint32 dp_sta = 0; /* ctrl status */
|
||||
uint32 dp_cmd = 0; /* ctrl command */
|
||||
uint32 dp_plat = 0; /* platter */
|
||||
uint32 dp_hdsc = 0; /* head/sector */
|
||||
uint32 dp_svun = 0; /* most recent unit */
|
||||
uint32 dp_1st = 0; /* first byte */
|
||||
uint32 dpd_arm[DP_NUMDR] = { 0 }; /* drives armed */
|
||||
int32 dp_stime = 100; /* seek latency */
|
||||
int32 dp_rtime = 100; /* rotate latency */
|
||||
int32 dp_wtime = 1; /* word time */
|
||||
uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */
|
||||
uint8 dpxb[DP_NUMBY]; /* xfer buffer */
|
||||
uint32 dp_bptr = 0; /* buffer ptr */
|
||||
uint32 dp_db = 0; /* ctrl buffer */
|
||||
uint32 dp_cyl = 0; /* drive buffer */
|
||||
uint32 dp_sta = 0; /* ctrl status */
|
||||
uint32 dp_cmd = 0; /* ctrl command */
|
||||
uint32 dp_plat = 0; /* platter */
|
||||
uint32 dp_hdsc = 0; /* head/sector */
|
||||
uint32 dp_svun = 0; /* most recent unit */
|
||||
uint32 dp_1st = 0; /* first byte */
|
||||
uint32 dpd_arm[DP_NUMDR] = { 0 }; /* drives armed */
|
||||
int32 dp_stime = 100; /* seek latency */
|
||||
int32 dp_rtime = 100; /* rotate latency */
|
||||
int32 dp_wtime = 1; /* word time */
|
||||
uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */
|
||||
|
||||
DEVICE dp_dev;
|
||||
uint32 dp (uint32 dev, uint32 op, uint32 dat);
|
||||
@@ -173,81 +174,85 @@ extern t_stat id_dboot (int32 u, DEVICE *dptr);
|
||||
|
||||
/* DP data structures
|
||||
|
||||
dp_dev DP device descriptor
|
||||
dp_unit DP unit list
|
||||
dp_reg DP register list
|
||||
dp_mod DP modifier list
|
||||
dp_dev DP device descriptor
|
||||
dp_unit DP unit list
|
||||
dp_reg DP register list
|
||||
dp_mod DP modifier list
|
||||
*/
|
||||
|
||||
DIB dp_dib = { d_DPC, 0, v_DPC, dp_tplte, &dp, &dp_ini };
|
||||
|
||||
UNIT dp_unit[] = {
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) } };
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) }
|
||||
};
|
||||
|
||||
REG dp_reg[] = {
|
||||
{ HRDATA (CMD, dp_cmd, 3) },
|
||||
{ HRDATA (STA, dp_sta, 8) },
|
||||
{ HRDATA (BUF, dp_db, 8) },
|
||||
{ HRDATA (PLAT, dp_plat, 1) },
|
||||
{ HRDATA (HDSC, dp_hdsc, 6) },
|
||||
{ HRDATA (CYL, dp_cyl, 9) },
|
||||
{ HRDATA (SVUN, dp_svun, 8), REG_HIDDEN },
|
||||
{ BRDATA (DBUF, dpxb, 16, 8, DP_NUMBY) },
|
||||
{ HRDATA (DBPTR, dp_bptr, 9), REG_RO },
|
||||
{ FLDATA (FIRST, dp_1st, 0) },
|
||||
{ GRDATA (IREQ, int_req[l_DPC], 16, DP_NUMDR + 1, i_DPC) },
|
||||
{ GRDATA (IENB, int_enb[l_DPC], 16, DP_NUMDR + 1, i_DPC) },
|
||||
{ BRDATA (IARM, dpd_arm, 16, 1, DP_NUMDR) },
|
||||
{ DRDATA (RTIME, dp_rtime, 0), PV_LEFT | REG_NZ },
|
||||
{ DRDATA (STIME, dp_stime, 0), PV_LEFT | REG_NZ },
|
||||
{ DRDATA (WTIME, dp_wtime, 0), PV_LEFT | REG_NZ },
|
||||
{ URDATA (UCYL, dp_unit[0].CYL, 16, 9, 0,
|
||||
DP_NUMDR, REG_RO) },
|
||||
{ URDATA (UST, dp_unit[0].STD, 16, 8, 0,
|
||||
DP_NUMDR, REG_RO) },
|
||||
{ URDATA (CAPAC, dp_unit[0].capac, 10, T_ADDR_W, 0,
|
||||
DP_NUMDR, PV_LEFT | REG_HRO) },
|
||||
{ HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO },
|
||||
{ HRDATA (SELCH, dp_dib.sch, 2), REG_HRO },
|
||||
{ NULL } };
|
||||
{ HRDATA (CMD, dp_cmd, 3) },
|
||||
{ HRDATA (STA, dp_sta, 8) },
|
||||
{ HRDATA (BUF, dp_db, 8) },
|
||||
{ HRDATA (PLAT, dp_plat, 1) },
|
||||
{ HRDATA (HDSC, dp_hdsc, 6) },
|
||||
{ HRDATA (CYL, dp_cyl, 9) },
|
||||
{ HRDATA (SVUN, dp_svun, 8), REG_HIDDEN },
|
||||
{ BRDATA (DBUF, dpxb, 16, 8, DP_NUMBY) },
|
||||
{ HRDATA (DBPTR, dp_bptr, 9), REG_RO },
|
||||
{ FLDATA (FIRST, dp_1st, 0) },
|
||||
{ GRDATA (IREQ, int_req[l_DPC], 16, DP_NUMDR + 1, i_DPC) },
|
||||
{ GRDATA (IENB, int_enb[l_DPC], 16, DP_NUMDR + 1, i_DPC) },
|
||||
{ BRDATA (IARM, dpd_arm, 16, 1, DP_NUMDR) },
|
||||
{ DRDATA (RTIME, dp_rtime, 0), PV_LEFT | REG_NZ },
|
||||
{ DRDATA (STIME, dp_stime, 0), PV_LEFT | REG_NZ },
|
||||
{ DRDATA (WTIME, dp_wtime, 0), PV_LEFT | REG_NZ },
|
||||
{ URDATA (UCYL, dp_unit[0].CYL, 16, 9, 0,
|
||||
DP_NUMDR, REG_RO) },
|
||||
{ URDATA (UST, dp_unit[0].STD, 16, 8, 0,
|
||||
DP_NUMDR, REG_RO) },
|
||||
{ URDATA (CAPAC, dp_unit[0].capac, 10, T_ADDR_W, 0,
|
||||
DP_NUMDR, PV_LEFT | REG_HRO) },
|
||||
{ HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO },
|
||||
{ HRDATA (SELCH, dp_dib.sch, 2), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB dp_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"2315", NULL, NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"5440", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE),
|
||||
"2315", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE),
|
||||
"5440", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },
|
||||
{ UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_2315 << UNIT_V_DTYPE),
|
||||
NULL, "2315", &dp_set_size },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_5440 << UNIT_V_DTYPE),
|
||||
NULL, "5440", &dp_set_size },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
||||
&set_sch, &show_sch, NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"2315", NULL, NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"5440", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE),
|
||||
"2315", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE),
|
||||
"5440", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },
|
||||
{ UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_2315 << UNIT_V_DTYPE),
|
||||
NULL, "2315", &dp_set_size },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_5440 << UNIT_V_DTYPE),
|
||||
NULL, "5440", &dp_set_size },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
||||
&set_sch, &show_sch, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE dp_dev = {
|
||||
"DP", dp_unit, dp_reg, dp_mod,
|
||||
DP_NUMDR, 16, 24, 1, 16, 8,
|
||||
NULL, NULL, &dp_reset,
|
||||
&id_dboot, &dp_attach, &dp_detach,
|
||||
&dp_dib, DEV_DISABLE | DEV_DEBUG };
|
||||
|
||||
"DP", dp_unit, dp_reg, dp_mod,
|
||||
DP_NUMDR, 16, 24, 1, 16, 8,
|
||||
NULL, NULL, &dp_reset,
|
||||
&id_dboot, &dp_attach, &dp_detach,
|
||||
&dp_dib, DEV_DISABLE | DEV_DEBUG
|
||||
};
|
||||
|
||||
/* Controller: IO routine */
|
||||
|
||||
uint32 dpc (uint32 dev, uint32 op, uint32 dat)
|
||||
@@ -256,49 +261,58 @@ uint32 f, t, u;
|
||||
UNIT *uptr;
|
||||
static uint8 good_cmd[8] = { 0, 1, 1, 1, 0, 0, 0, 0 };
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
sch_adr (dp_dib.sch, dev); /* inform sel ch */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read data */
|
||||
if (dp_sta & STC_IDL) /* if idle */
|
||||
return GET_ROTATE (dp_rtime); /* return sector */
|
||||
else dp_sta = dp_sta | STA_BSY; /* xfr? set busy */
|
||||
return dp_db; /* return data */
|
||||
case IO_WD: /* write data */
|
||||
if (DEBUG_PRS (dp_dev)) fprintf (sim_deb,
|
||||
">>DPC WD = %02X, STA = %02X\n", dat, dp_sta);
|
||||
if (dp_sta & STC_IDL) dp_hdsc = dat & HS_MASK; /* idle? hdsc */
|
||||
else { /* data xfer */
|
||||
dp_sta = dp_sta | STA_BSY; /* set busy */
|
||||
dp_db = dat & 0xFF; } /* store data */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = dp_sta & STC_MASK; /* get status */
|
||||
if (t & SETC_EX) t = t | STA_EX; /* test for EX */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
if (DEBUG_PRS (dp_dev)) fprintf (sim_deb,
|
||||
">>DPC OC = %02X, STA = %02X\n", dat, dp_sta);
|
||||
f = dat & CMC_MASK; /* get cmd */
|
||||
if (f & CMC_CLR) { /* clear? */
|
||||
dp_reset (&dp_dev); /* reset world */
|
||||
break; }
|
||||
u = (dp_svun - dp_dib.dno - o_DP0) / o_DP0; /* get unit */
|
||||
uptr = dp_dev.units + u; /* ignore if busy */
|
||||
if (!(dp_sta & STC_IDL) || sim_is_active (uptr)) break;
|
||||
dp_cmd = f; /* save cmd */
|
||||
if (dp_cmd == CMC_WR) dp_sta = 0; /* write: bsy=0 else */
|
||||
else dp_sta = STA_BSY; /* bsy=1,idl,err=0 */
|
||||
dp_1st = 1; /* xfr not started */
|
||||
dp_bptr = 0; /* buffer empty */
|
||||
if (dp_svun & o_DPF) dp_plat = 1; /* upper platter? */
|
||||
else dp_plat = 0; /* no, lower */
|
||||
if (good_cmd[f]) sim_activate (uptr, dp_rtime); /* legal? sched */
|
||||
break; }
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
sch_adr (dp_dib.sch, dev); /* inform sel ch */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_RD: /* read data */
|
||||
if (dp_sta & STC_IDL) /* if idle */
|
||||
return GET_ROTATE (dp_rtime); /* return sector */
|
||||
else dp_sta = dp_sta | STA_BSY; /* xfr? set busy */
|
||||
return dp_db; /* return data */
|
||||
|
||||
case IO_WD: /* write data */
|
||||
if (DEBUG_PRS (dp_dev)) fprintf (sim_deb,
|
||||
">>DPC WD = %02X, STA = %02X\n", dat, dp_sta);
|
||||
if (dp_sta & STC_IDL) dp_hdsc = dat & HS_MASK; /* idle? hdsc */
|
||||
else { /* data xfer */
|
||||
dp_sta = dp_sta | STA_BSY; /* set busy */
|
||||
dp_db = dat & 0xFF; /* store data */
|
||||
}
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
t = dp_sta & STC_MASK; /* get status */
|
||||
if (t & SETC_EX) t = t | STA_EX; /* test for EX */
|
||||
return t;
|
||||
|
||||
case IO_OC: /* command */
|
||||
if (DEBUG_PRS (dp_dev)) fprintf (sim_deb,
|
||||
">>DPC OC = %02X, STA = %02X\n", dat, dp_sta);
|
||||
f = dat & CMC_MASK; /* get cmd */
|
||||
if (f & CMC_CLR) { /* clear? */
|
||||
dp_reset (&dp_dev); /* reset world */
|
||||
break;
|
||||
}
|
||||
u = (dp_svun - dp_dib.dno - o_DP0) / o_DP0; /* get unit */
|
||||
uptr = dp_dev.units + u; /* ignore if busy */
|
||||
if (!(dp_sta & STC_IDL) || sim_is_active (uptr)) break;
|
||||
dp_cmd = f; /* save cmd */
|
||||
if (dp_cmd == CMC_WR) dp_sta = 0; /* write: bsy=0 else */
|
||||
else dp_sta = STA_BSY; /* bsy=1,idl,err=0 */
|
||||
dp_1st = 1; /* xfr not started */
|
||||
dp_bptr = 0; /* buffer empty */
|
||||
if (dp_svun & o_DPF) dp_plat = 1; /* upper platter? */
|
||||
else dp_plat = 0; /* no, lower */
|
||||
if (good_cmd[f]) sim_activate (uptr, dp_rtime); /* legal? sched */
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Drives: IO routine */
|
||||
|
||||
uint32 dp (uint32 dev, uint32 op, uint32 dat)
|
||||
@@ -307,45 +321,51 @@ int32 diff;
|
||||
uint32 t, u;
|
||||
UNIT *uptr;
|
||||
|
||||
if (dev == dp_dib.dno) return dpc (dev, op, dat); /* controller? */
|
||||
u = (dev - dp_dib.dno - o_DP0) / o_DP0; /* get unit num */
|
||||
uptr = dp_dev.units + u; /* get unit ptr */
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
if (dp_sta & STC_IDL) dp_svun = dev; /* idle? save unit */
|
||||
return BY; /* byte only */
|
||||
case IO_WD: /* write data */
|
||||
if (DEBUG_PRS (dp_dev)) fprintf (sim_deb,
|
||||
">>DP%d WD = %02X, STA = %02X\n", u, dat, dp_sta);
|
||||
if (GET_DTYPE (uptr->flags) == TYPE_2315) /* 2.5MB drive? */
|
||||
dp_cyl = dat & 0xFF; /* cyl is 8b */
|
||||
else dp_cyl = ((dp_cyl << 8) | dat) & DMASK16; /* insert byte */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
if (uptr->flags & UNIT_ATT) t = /* onl? */
|
||||
((uptr->flags & UNIT_WPRT)? STD_WRP: 0) |
|
||||
((dp_sta & STC_IDL)? 0: STD_ILK) |
|
||||
(uptr->STD & STD_UST);
|
||||
else t = STD_MOV | STD_NRDY; /* off = X'09' */
|
||||
if (t & SETD_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
if (DEBUG_PRS (dp_dev)) fprintf (sim_deb,
|
||||
">>DP%d OC = %02X, STA = %02X\n", u, dat, dp_sta);
|
||||
dpd_arm[u] = int_chg (v_DPC + u + 1, dat, dpd_arm[u]);
|
||||
if (dat & CMD_SK) t = dp_cyl; /* seek? get cyl */
|
||||
else if (dat & CMD_RST) t = 0; /* rest? cyl 0 */
|
||||
else break; /* no action */
|
||||
diff = t - uptr->CYL;
|
||||
if (diff < 0) diff = -diff; /* ABS cyl diff */
|
||||
else if (diff == 0) diff = 1; /* must be nz */
|
||||
uptr->STD = STD_MOV; /* stat = moving */
|
||||
uptr->CYL = t; /* put on cyl */
|
||||
sim_activate (uptr, diff * dp_stime); /* schedule */
|
||||
break; }
|
||||
if (dev == dp_dib.dno) return dpc (dev, op, dat); /* controller? */
|
||||
u = (dev - dp_dib.dno - o_DP0) / o_DP0; /* get unit num */
|
||||
uptr = dp_dev.units + u; /* get unit ptr */
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
if (dp_sta & STC_IDL) dp_svun = dev; /* idle? save unit */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_WD: /* write data */
|
||||
if (DEBUG_PRS (dp_dev)) fprintf (sim_deb,
|
||||
">>DP%d WD = %02X, STA = %02X\n", u, dat, dp_sta);
|
||||
if (GET_DTYPE (uptr->flags) == TYPE_2315) /* 2.5MB drive? */
|
||||
dp_cyl = dat & 0xFF; /* cyl is 8b */
|
||||
else dp_cyl = ((dp_cyl << 8) | dat) & DMASK16; /* insert byte */
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
if (uptr->flags & UNIT_ATT) t = /* onl? */
|
||||
((uptr->flags & UNIT_WPRT)? STD_WRP: 0) |
|
||||
((dp_sta & STC_IDL)? 0: STD_ILK) |
|
||||
(uptr->STD & STD_UST);
|
||||
else t = STD_MOV | STD_NRDY; /* off = X'09' */
|
||||
if (t & SETD_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
|
||||
case IO_OC: /* command */
|
||||
if (DEBUG_PRS (dp_dev)) fprintf (sim_deb,
|
||||
">>DP%d OC = %02X, STA = %02X\n", u, dat, dp_sta);
|
||||
dpd_arm[u] = int_chg (v_DPC + u + 1, dat, dpd_arm[u]);
|
||||
if (dat & CMD_SK) t = dp_cyl; /* seek? get cyl */
|
||||
else if (dat & CMD_RST) t = 0; /* rest? cyl 0 */
|
||||
else break; /* no action */
|
||||
diff = t - uptr->CYL;
|
||||
if (diff < 0) diff = -diff; /* ABS cyl diff */
|
||||
else if (diff == 0) diff = 1; /* must be nz */
|
||||
uptr->STD = STD_MOV; /* stat = moving */
|
||||
uptr->CYL = t; /* put on cyl */
|
||||
sim_activate (uptr, diff * dp_stime); /* schedule */
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service
|
||||
|
||||
If seek done, on cylinder;
|
||||
@@ -355,60 +375,65 @@ return 0;
|
||||
|
||||
t_stat dp_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 u = uptr - dp_dev.units; /* get unit number */
|
||||
int32 cyl = uptr->CYL; /* get cylinder */
|
||||
uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uint32 u = uptr - dp_dev.units; /* get unit number */
|
||||
int32 cyl = uptr->CYL; /* get cylinder */
|
||||
uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uint32 t;
|
||||
t_stat r;
|
||||
|
||||
if (uptr->STD & STD_MOV) { /* seek? */
|
||||
uptr->STD = 0; /* clr seek in prog */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* offl? hangs */
|
||||
if (cyl >= drv_tab[dtype].cyl) { /* bad cylinder? */
|
||||
uptr->STD = STD_ILA; /* error */
|
||||
uptr->CYL = drv_tab[dtype].cyl - 1; } /* put at edge */
|
||||
if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* req intr */
|
||||
return SCPE_OK; }
|
||||
if (uptr->STD & STD_MOV) { /* seek? */
|
||||
uptr->STD = 0; /* clr seek in prog */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* offl? hangs */
|
||||
if (cyl >= drv_tab[dtype].cyl) { /* bad cylinder? */
|
||||
uptr->STD = STD_ILA; /* error */
|
||||
uptr->CYL = drv_tab[dtype].cyl - 1; /* put at edge */
|
||||
}
|
||||
if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* req intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
switch (dp_cmd & 0x7) { /* case on func */
|
||||
switch (dp_cmd & 0x7) { /* case on func */
|
||||
|
||||
case CMC_RCHK: /* read check */
|
||||
dp_dter (uptr, 1); /* check xfr err */
|
||||
break;
|
||||
case CMC_RCHK: /* read check */
|
||||
dp_dter (uptr, 1); /* check xfr err */
|
||||
break;
|
||||
|
||||
case CMC_RD: /* read */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */
|
||||
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
||||
if (r = dp_rds (uptr)) return r; /* read sec, err? */
|
||||
dp_1st = 0;
|
||||
t = sch_wrmem (dp_dib.sch, dpxb, DP_NUMBY); /* write to memory */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, dp_rtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; } /* no, set done */
|
||||
|
||||
dp_sta = dp_sta | STC_DTE; /* can't work */
|
||||
break;
|
||||
case CMC_RD: /* read */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */
|
||||
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
||||
if (r = dp_rds (uptr)) return r; /* read sec, err? */
|
||||
dp_1st = 0;
|
||||
t = sch_wrmem (dp_dib.sch, dpxb, DP_NUMBY); /* write to memory */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, dp_rtime); /* reschedule */
|
||||
return SCPE_OK;
|
||||
}
|
||||
break; /* no, set done */
|
||||
}
|
||||
dp_sta = dp_sta | STC_DTE; /* can't work */
|
||||
break;
|
||||
|
||||
case CMC_WR: /* write */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */
|
||||
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
||||
dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */
|
||||
dp_db = dpxb[dp_bptr - 1]; /* last byte */
|
||||
if (r = dp_wds (uptr)) return r; /* write sec, err? */
|
||||
dp_1st = 0;
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, dp_rtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; } /* no, set done */
|
||||
case CMC_WR: /* write */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */
|
||||
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
||||
dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */
|
||||
dp_db = dpxb[dp_bptr - 1]; /* last byte */
|
||||
if (r = dp_wds (uptr)) return r; /* write sec, err? */
|
||||
dp_1st = 0;
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, dp_rtime); /* reschedule */
|
||||
return SCPE_OK;
|
||||
}
|
||||
break; /* no, set done */
|
||||
}
|
||||
dp_sta = dp_sta | STC_DTE; /* can't work */
|
||||
break;
|
||||
} /* end case func */
|
||||
|
||||
dp_sta = dp_sta | STC_DTE; /* can't work */
|
||||
break; }
|
||||
|
||||
dp_done (0); /* done */
|
||||
dp_done (0); /* done */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Read data sector */
|
||||
|
||||
t_stat dp_rds (UNIT *uptr)
|
||||
@@ -416,12 +441,13 @@ t_stat dp_rds (UNIT *uptr)
|
||||
uint32 i;
|
||||
|
||||
i = fxread (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref);
|
||||
for ( ; i < DP_NUMBY; i++) dpxb[i] = 0; /* fill with 0's */
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
perror ("DP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
dp_done (STC_DTE);
|
||||
return SCPE_IOERR; }
|
||||
for ( ; i < DP_NUMBY; i++) dpxb[i] = 0; /* fill with 0's */
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
perror ("DP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
dp_done (STC_DTE);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -430,13 +456,14 @@ return SCPE_OK;
|
||||
t_stat dp_wds (UNIT *uptr)
|
||||
{
|
||||
for ( ; dp_bptr < DP_NUMBY; dp_bptr++)
|
||||
dpxb[dp_bptr] = dp_db; /* fill with last */
|
||||
dpxb[dp_bptr] = dp_db; /* fill with last */
|
||||
fxwrite (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
perror ("DP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
dp_done (STC_DTE);
|
||||
return SCPE_IOERR; }
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
perror ("DP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
dp_done (STC_DTE);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -445,29 +472,34 @@ return SCPE_OK;
|
||||
t_bool dp_dter (UNIT *uptr, uint32 first)
|
||||
{
|
||||
uint32 hd, sc, sa;
|
||||
uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
|
||||
((uptr->flags & UNIT_WPRT) && (dp_cmd == CMC_WR))) {
|
||||
dp_done (STC_DTE); /* error, done */
|
||||
return TRUE; }
|
||||
hd = GET_SRF (dp_hdsc); /* get head */
|
||||
sc = GET_SEC (dp_hdsc); /* get sector */
|
||||
if (dp_cyl != (uint32) uptr->CYL) { /* wrong cylinder? */
|
||||
if (dp_cyl == 0) uptr->CYL = 0;
|
||||
else {
|
||||
dp_done (STC_ACF); /* error, done */
|
||||
return TRUE; } }
|
||||
if (sc >= DP_NUMSC) { /* bad sector? */
|
||||
dp_done (STC_OVR); /* error, done */
|
||||
return TRUE; }
|
||||
if (!first && (sc == 0) && (hd == 0)) { /* cyl overflow? */
|
||||
dp_done (STC_CYO); /* error, done */
|
||||
return TRUE; }
|
||||
sa = GET_SA (dp_plat, uptr->CYL, hd, sc, dtype); /* curr disk addr */
|
||||
dp_done (STC_DTE); /* error, done */
|
||||
return TRUE;
|
||||
}
|
||||
hd = GET_SRF (dp_hdsc); /* get head */
|
||||
sc = GET_SEC (dp_hdsc); /* get sector */
|
||||
if (dp_cyl != (uint32) uptr->CYL) { /* wrong cylinder? */
|
||||
if (dp_cyl == 0) uptr->CYL = 0;
|
||||
else {
|
||||
dp_done (STC_ACF); /* error, done */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (sc >= DP_NUMSC) { /* bad sector? */
|
||||
dp_done (STC_OVR); /* error, done */
|
||||
return TRUE;
|
||||
}
|
||||
if (!first && (sc == 0) && (hd == 0)) { /* cyl overflow? */
|
||||
dp_done (STC_CYO); /* error, done */
|
||||
return TRUE;
|
||||
}
|
||||
sa = GET_SA (dp_plat, uptr->CYL, hd, sc, dtype); /* curr disk addr */
|
||||
fseek (uptr->fileref, sa * DP_NUMBY, SEEK_SET);
|
||||
if ((sc + 1) < DP_NUMSC) dp_hdsc = dp_hdsc + 1; /* end of track? */
|
||||
else dp_hdsc = (dp_hdsc ^ HS_HMASK) & HS_HMASK; /* sec 0, nxt srf */
|
||||
if ((sc + 1) < DP_NUMSC) dp_hdsc = dp_hdsc + 1; /* end of track? */
|
||||
else dp_hdsc = (dp_hdsc ^ HS_HMASK) & HS_HMASK; /* sec 0, nxt srf */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -475,12 +507,12 @@ return FALSE;
|
||||
|
||||
void dp_done (uint32 flg)
|
||||
{
|
||||
dp_sta = (dp_sta | STC_IDL | flg) & ~STA_BSY; /* set flag, idle */
|
||||
SET_INT (v_DPC); /* unmaskable intr */
|
||||
if (flg) sch_stop (dp_dib.sch); /* if err, stop ch */
|
||||
dp_sta = (dp_sta | STC_IDL | flg) & ~STA_BSY; /* set flag, idle */
|
||||
SET_INT (v_DPC); /* unmaskable intr */
|
||||
if (flg) sch_stop (dp_dib.sch); /* if err, stop ch */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat dp_reset (DEVICE *dptr)
|
||||
@@ -488,21 +520,22 @@ t_stat dp_reset (DEVICE *dptr)
|
||||
uint32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
dp_cmd = 0; /* clear cmd */
|
||||
dp_sta = STA_BSY | STC_IDL; /* idle, busy */
|
||||
dp_1st = 0; /* clear flag */
|
||||
dp_svun = dp_db = 0; /* clear unit, buf */
|
||||
dp_cmd = 0; /* clear cmd */
|
||||
dp_sta = STA_BSY | STC_IDL; /* idle, busy */
|
||||
dp_1st = 0; /* clear flag */
|
||||
dp_svun = dp_db = 0; /* clear unit, buf */
|
||||
dp_plat = 0;
|
||||
dp_hdsc = 0; /* clear addr */
|
||||
CLR_INT (v_DPC); /* clear ctrl int */
|
||||
SET_ENB (v_DPC); /* always enabled */
|
||||
for (u = 0; u < DP_NUMDR; u++) { /* loop thru units */
|
||||
uptr = dp_dev.units + u;
|
||||
uptr->CYL = uptr->STD = 0;
|
||||
CLR_INT (v_DPC + u + 1); /* clear intr */
|
||||
CLR_ENB (v_DPC + u + 1); /* clear enable */
|
||||
dpd_arm[u] = 0; /* clear arm */
|
||||
sim_cancel (uptr); } /* cancel activity */
|
||||
dp_hdsc = 0; /* clear addr */
|
||||
CLR_INT (v_DPC); /* clear ctrl int */
|
||||
SET_ENB (v_DPC); /* always enabled */
|
||||
for (u = 0; u < DP_NUMDR; u++) { /* loop thru units */
|
||||
uptr = dp_dev.units + u;
|
||||
uptr->CYL = uptr->STD = 0;
|
||||
CLR_INT (v_DPC + u + 1); /* clear intr */
|
||||
CLR_ENB (v_DPC + u + 1); /* clear enable */
|
||||
dpd_arm[u] = 0; /* clear arm */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -514,16 +547,18 @@ uint32 i, p;
|
||||
t_stat r;
|
||||
|
||||
uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size;
|
||||
r = attach_unit (uptr, cptr); /* attach unit */
|
||||
if (r != SCPE_OK) return r; /* error? */
|
||||
r = attach_unit (uptr, cptr); /* attach unit */
|
||||
if (r != SCPE_OK) return r; /* error? */
|
||||
uptr->CYL = 0;
|
||||
if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */
|
||||
if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */
|
||||
if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK;
|
||||
for (i = 0; drv_tab[i].surf != 0; i++) {
|
||||
if (p <= drv_tab[i].size) {
|
||||
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE);
|
||||
uptr->capac = drv_tab[i].size;
|
||||
return SCPE_OK; } }
|
||||
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE);
|
||||
uptr->capac = drv_tab[i].size;
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -533,8 +568,8 @@ t_stat dp_detach (UNIT *uptr)
|
||||
{
|
||||
uint32 u = uptr - dp_dev.units;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
|
||||
if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* if arm, intr */
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
|
||||
if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* if arm, intr */
|
||||
return detach_unit (uptr);
|
||||
}
|
||||
|
||||
@@ -553,12 +588,13 @@ void dp_ini (t_bool dtpl)
|
||||
{
|
||||
int32 u, j, dev;
|
||||
|
||||
dp_tplte[0] = 0; /* controller */
|
||||
for (u = 0, j = 1; u < DP_NUMDR; u++) { /* loop thru units */
|
||||
dev = (u + 1) * o_DP0; /* drive dev # */
|
||||
dp_tplte[j++] = dev;
|
||||
if (dtpl && (GET_DTYPE (dp_unit[u].flags) == TYPE_5440))
|
||||
dp_tplte[j++] = dev + o_DPF; } /* if fixed */
|
||||
dp_tplte[j] = TPL_END; /* end marker */
|
||||
dp_tplte[0] = 0; /* controller */
|
||||
for (u = 0, j = 1; u < DP_NUMDR; u++) { /* loop thru units */
|
||||
dev = (u + 1) * o_DP0; /* drive dev # */
|
||||
dp_tplte[j++] = dev;
|
||||
if (dtpl && (GET_DTYPE (dp_unit[u].flags) == TYPE_5440))
|
||||
dp_tplte[j++] = dev + o_DPF; /* if fixed */
|
||||
}
|
||||
dp_tplte[j] = TPL_END; /* end marker */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id_fd.c: Interdata floppy disk simulator
|
||||
|
||||
Copyright (c) 2001-2004, Robert M Supnik
|
||||
Copyright (c) 2001-2005, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,11 +19,11 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
fd M46-630 floppy disk
|
||||
fd M46-630 floppy disk
|
||||
|
||||
A diskette consists of 77 tracks, each with 26 sectors of 128B. The
|
||||
Interdata floppy uses a logical record numbering scheme from 1 to 2002.
|
||||
@@ -36,97 +36,98 @@
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
#define FD_NUMTR 77 /* tracks/disk */
|
||||
#define FD_NUMSC 26 /* sectors/track */
|
||||
#define FD_NUMBY 128 /* bytes/sector */
|
||||
#define FD_NUMLRN (FD_NUMTR * FD_NUMSC) /* LRNs/disk */
|
||||
#define FD_SIZE (FD_NUMLRN * FD_NUMBY) /* bytes/disk */
|
||||
#define FD_NUMDR 4 /* drives/controller */
|
||||
#define UNIT_V_WLK (UNIT_V_UF) /* write locked */
|
||||
#define UNIT_WLK (1u << UNIT_V_UF)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define LRN u3 /* last LRN */
|
||||
#define FNC u4 /* last function */
|
||||
#define GET_DA(x) (((x) - 1) * FD_NUMBY)
|
||||
#define GET_TRK(x) (((x) - 1) / FD_NUMSC)
|
||||
#define GET_SEC(x) ((((x) - 1) % FD_NUMSC) + 1)
|
||||
#define LRN_BOOT 5 /* boot block LRN */
|
||||
#define FD_NUMTR 77 /* tracks/disk */
|
||||
#define FD_NUMSC 26 /* sectors/track */
|
||||
#define FD_NUMBY 128 /* bytes/sector */
|
||||
#define FD_NUMLRN (FD_NUMTR * FD_NUMSC) /* LRNs/disk */
|
||||
#define FD_SIZE (FD_NUMLRN * FD_NUMBY) /* bytes/disk */
|
||||
#define FD_NUMDR 4 /* drives/controller */
|
||||
#define UNIT_V_WLK (UNIT_V_UF) /* write locked */
|
||||
#define UNIT_WLK (1u << UNIT_V_UF)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define LRN u3 /* last LRN */
|
||||
#define FNC u4 /* last function */
|
||||
#define GET_DA(x) (((x) - 1) * FD_NUMBY)
|
||||
#define GET_TRK(x) (((x) - 1) / FD_NUMSC)
|
||||
#define GET_SEC(x) ((((x) - 1) % FD_NUMSC) + 1)
|
||||
#define LRN_BOOT 5 /* boot block LRN */
|
||||
|
||||
/* Command byte */
|
||||
|
||||
#define CMD_V_UNIT 4 /* unit */
|
||||
#define CMD_M_UNIT 0x3
|
||||
#define GET_UNIT(x) (((x) >> CMD_V_UNIT) & CMD_M_UNIT)
|
||||
#define CMD_V_FNC 0 /* function */
|
||||
#define CMD_M_FNC 0xF
|
||||
#define GET_FNC(x) (((x) >> CMD_V_FNC) & CMD_M_FNC)
|
||||
#define FNC_RD 0x1 /* read */
|
||||
#define FNC_WR 0x2 /* write */
|
||||
#define FNC_RDID 0x3 /* read ID */
|
||||
#define FNC_RSTA 0x4 /* read status */
|
||||
#define FNC_DEL 0x5 /* write deleted */
|
||||
#define FNC_BOOT 0x6 /* boot */
|
||||
#define FNC_STOP 0x7 /* stop */
|
||||
#define FNC_RESET 0x8 /* reset */
|
||||
#define FNC_FMT 0x9 /* format NI */
|
||||
#define FNC_STOPPING 0x10 /* stopping */
|
||||
#define CMD_V_UNIT 4 /* unit */
|
||||
#define CMD_M_UNIT 0x3
|
||||
#define GET_UNIT(x) (((x) >> CMD_V_UNIT) & CMD_M_UNIT)
|
||||
#define CMD_V_FNC 0 /* function */
|
||||
#define CMD_M_FNC 0xF
|
||||
#define GET_FNC(x) (((x) >> CMD_V_FNC) & CMD_M_FNC)
|
||||
#define FNC_RD 0x1 /* read */
|
||||
#define FNC_WR 0x2 /* write */
|
||||
#define FNC_RDID 0x3 /* read ID */
|
||||
#define FNC_RSTA 0x4 /* read status */
|
||||
#define FNC_DEL 0x5 /* write deleted */
|
||||
#define FNC_BOOT 0x6 /* boot */
|
||||
#define FNC_STOP 0x7 /* stop */
|
||||
#define FNC_RESET 0x8 /* reset */
|
||||
#define FNC_FMT 0x9 /* format NI */
|
||||
#define FNC_STOPPING 0x10 /* stopping */
|
||||
|
||||
/* Status byte, * = dynamic */
|
||||
|
||||
#define STA_WRP 0x80 /* *write prot */
|
||||
#define STA_DEF 0x40 /* def track NI */
|
||||
#define STA_DEL 0x20 /* del record */
|
||||
#define STA_ERR 0x10 /* error */
|
||||
#define STA_IDL 0x02 /* idle */
|
||||
#define STA_OFL 0x01 /* fault */
|
||||
#define STA_MASK (STA_DEF|STA_DEL|STA_ERR|STA_BSY|STA_IDL)
|
||||
#define SET_EX (STA_ERR) /* set EX */
|
||||
#define STA_WRP 0x80 /* *write prot */
|
||||
#define STA_DEF 0x40 /* def track NI */
|
||||
#define STA_DEL 0x20 /* del record */
|
||||
#define STA_ERR 0x10 /* error */
|
||||
#define STA_IDL 0x02 /* idle */
|
||||
#define STA_OFL 0x01 /* fault */
|
||||
#define STA_MASK (STA_DEF|STA_DEL|STA_ERR|STA_BSY|STA_IDL)
|
||||
#define SET_EX (STA_ERR) /* set EX */
|
||||
|
||||
/* Extended status, 6 bytes, * = dynamic */
|
||||
|
||||
#define ES_SIZE 6
|
||||
#define ES0_HCRC 0x80 /* ID CRC NI */
|
||||
#define ES0_DCRC 0x40 /* data CRC NI */
|
||||
#define ES0_LRN 0x20 /* illegal LRN */
|
||||
#define ES0_WRP 0x10 /* *write prot */
|
||||
#define ES0_ERR 0x08 /* error */
|
||||
#define ES0_DEF 0x04 /* def trk NI */
|
||||
#define ES0_DEL 0x02 /* del rec NI */
|
||||
#define ES0_FLT 0x01 /* fault */
|
||||
#define ES1_TK0 0x80 /* track 0 */
|
||||
#define ES1_NRDY 0x40 /* not ready */
|
||||
#define ES1_NOAM 0x20 /* no addr mk NI */
|
||||
#define ES1_CMD 0x10 /* illegal cmd */
|
||||
#define ES1_SKE 0x08 /* seek err NI */
|
||||
#define ES1_UNS 0x04 /* unsafe NI */
|
||||
#define ES1_UNIT 0x03 /* unit # */
|
||||
#define ES_SIZE 6
|
||||
#define ES0_HCRC 0x80 /* ID CRC NI */
|
||||
#define ES0_DCRC 0x40 /* data CRC NI */
|
||||
#define ES0_LRN 0x20 /* illegal LRN */
|
||||
#define ES0_WRP 0x10 /* *write prot */
|
||||
#define ES0_ERR 0x08 /* error */
|
||||
#define ES0_DEF 0x04 /* def trk NI */
|
||||
#define ES0_DEL 0x02 /* del rec NI */
|
||||
#define ES0_FLT 0x01 /* fault */
|
||||
#define ES1_TK0 0x80 /* track 0 */
|
||||
#define ES1_NRDY 0x40 /* not ready */
|
||||
#define ES1_NOAM 0x20 /* no addr mk NI */
|
||||
#define ES1_CMD 0x10 /* illegal cmd */
|
||||
#define ES1_SKE 0x08 /* seek err NI */
|
||||
#define ES1_UNS 0x04 /* unsafe NI */
|
||||
#define ES1_UNIT 0x03 /* unit # */
|
||||
|
||||
/* Processing options for commands */
|
||||
|
||||
#define C_RD 0x1 /* cmd reads disk */
|
||||
#define C_WD 0x2 /* cmd writes disk */
|
||||
|
||||
#define C_RD 0x1 /* cmd reads disk */
|
||||
#define C_WD 0x2 /* cmd writes disk */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint32 fd_sta = 0; /* status */
|
||||
uint32 fd_cmd = 0; /* command */
|
||||
uint32 fd_db = 0; /* data buffer */
|
||||
uint32 fd_bptr = 0; /* buffer pointer */
|
||||
uint8 fdxb[FD_NUMBY] = { 0 }; /* sector buffer */
|
||||
uint8 fd_es[FD_NUMDR][ES_SIZE] = { 0 }; /* ext status */
|
||||
uint32 fd_lrn = 0; /* log rec # */
|
||||
uint32 fd_wdv = 0; /* wd valid */
|
||||
uint32 fd_stopioe = 1; /* stop on error */
|
||||
uint32 fd_arm = 0; /* intr arm */
|
||||
int32 fd_ctime = 100; /* command time */
|
||||
int32 fd_stime = 10; /* seek, per LRN */
|
||||
int32 fd_xtime = 1; /* tr set time */
|
||||
uint32 fd_sta = 0; /* status */
|
||||
uint32 fd_cmd = 0; /* command */
|
||||
uint32 fd_db = 0; /* data buffer */
|
||||
uint32 fd_bptr = 0; /* buffer pointer */
|
||||
uint8 fdxb[FD_NUMBY] = { 0 }; /* sector buffer */
|
||||
uint8 fd_es[FD_NUMDR][ES_SIZE] = { 0 }; /* ext status */
|
||||
uint32 fd_lrn = 0; /* log rec # */
|
||||
uint32 fd_wdv = 0; /* wd valid */
|
||||
uint32 fd_stopioe = 1; /* stop on error */
|
||||
uint32 fd_arm = 0; /* intr arm */
|
||||
int32 fd_ctime = 100; /* command time */
|
||||
int32 fd_stime = 10; /* seek, per LRN */
|
||||
int32 fd_xtime = 1; /* tr set time */
|
||||
|
||||
static uint32 ctab[16] = {
|
||||
0, C_RD, C_WD, 0, /* 0, rd, wr, 0 */
|
||||
0, C_WD, C_RD, 0, /* 0, del, boot, 0 */
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 };
|
||||
0, C_RD, C_WD, 0, /* 0, rd, wr, 0 */
|
||||
0, C_WD, C_RD, 0, /* 0, del, boot, 0 */
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
DEVICE fd_dev;
|
||||
uint32 fd (uint32 dev, uint32 op, uint32 dat);
|
||||
@@ -138,62 +139,66 @@ t_bool fd_dte (UNIT *uptr, t_bool wr);
|
||||
uint32 fd_crc (uint32 crc, uint32 dat, uint32 cnt);
|
||||
void fd_done (uint32 u, uint32 nsta, uint32 nes0, uint32 nes1);
|
||||
void sched_seek (UNIT *uptr, int32 newlrn);
|
||||
|
||||
|
||||
/* FD data structures
|
||||
|
||||
fd_dev FD device descriptor
|
||||
fd_unit FD unit list
|
||||
fd_reg FD register list
|
||||
fd_mod FD modifier list
|
||||
fd_dev FD device descriptor
|
||||
fd_unit FD unit list
|
||||
fd_reg FD register list
|
||||
fd_mod FD modifier list
|
||||
*/
|
||||
|
||||
DIB fd_dib = { d_FD, -1, v_FD, NULL, &fd, NULL };
|
||||
|
||||
UNIT fd_unit[] = {
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) },
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) },
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) },
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) } };
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) },
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) },
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) },
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) }
|
||||
};
|
||||
|
||||
REG fd_reg[] = {
|
||||
{ HRDATA (CMD, fd_cmd, 8) },
|
||||
{ HRDATA (STA, fd_sta, 8) },
|
||||
{ HRDATA (BUF, fd_db, 8) },
|
||||
{ HRDATA (LRN, fd_lrn, 16) },
|
||||
{ BRDATA (ESTA, fd_es, 16, 8, ES_SIZE * FD_NUMDR) },
|
||||
{ BRDATA (DBUF, fdxb, 16, 8, FD_NUMBY) },
|
||||
{ HRDATA (DBPTR, fd_bptr, 8) },
|
||||
{ FLDATA (WDV, fd_wdv, 0) },
|
||||
{ FLDATA (IREQ, int_req[l_FD], i_FD) },
|
||||
{ FLDATA (IENB, int_enb[l_FD], i_FD) },
|
||||
{ FLDATA (IARM, fd_arm, 0) },
|
||||
{ DRDATA (CTIME, fd_ctime, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, fd_stime, 24), PV_LEFT },
|
||||
{ DRDATA (XTIME, fd_xtime, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, fd_stopioe, 0) },
|
||||
{ URDATA (ULRN, fd_unit[0].LRN, 16, 16, 0, FD_NUMDR, REG_HRO) },
|
||||
{ URDATA (UFNC, fd_unit[0].FNC, 16, 8, 0, FD_NUMDR, REG_HRO) },
|
||||
{ HRDATA (DEVNO, fd_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
{ HRDATA (CMD, fd_cmd, 8) },
|
||||
{ HRDATA (STA, fd_sta, 8) },
|
||||
{ HRDATA (BUF, fd_db, 8) },
|
||||
{ HRDATA (LRN, fd_lrn, 16) },
|
||||
{ BRDATA (ESTA, fd_es, 16, 8, ES_SIZE * FD_NUMDR) },
|
||||
{ BRDATA (DBUF, fdxb, 16, 8, FD_NUMBY) },
|
||||
{ HRDATA (DBPTR, fd_bptr, 8) },
|
||||
{ FLDATA (WDV, fd_wdv, 0) },
|
||||
{ FLDATA (IREQ, int_req[l_FD], i_FD) },
|
||||
{ FLDATA (IENB, int_enb[l_FD], i_FD) },
|
||||
{ FLDATA (IARM, fd_arm, 0) },
|
||||
{ DRDATA (CTIME, fd_ctime, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, fd_stime, 24), PV_LEFT },
|
||||
{ DRDATA (XTIME, fd_xtime, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, fd_stopioe, 0) },
|
||||
{ URDATA (ULRN, fd_unit[0].LRN, 16, 16, 0, FD_NUMDR, REG_HRO) },
|
||||
{ URDATA (UFNC, fd_unit[0].FNC, 16, 8, 0, FD_NUMDR, REG_HRO) },
|
||||
{ HRDATA (DEVNO, fd_dib.dno, 8), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB fd_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE fd_dev = {
|
||||
"FD", fd_unit, fd_reg, fd_mod,
|
||||
FD_NUMDR, 16, 20, 1, 16, 8,
|
||||
NULL, NULL, &fd_reset,
|
||||
&fd_boot, NULL, NULL,
|
||||
&fd_dib, DEV_DISABLE };
|
||||
|
||||
"FD", fd_unit, fd_reg, fd_mod,
|
||||
FD_NUMDR, 16, 20, 1, 16, 8,
|
||||
NULL, NULL, &fd_reset,
|
||||
&fd_boot, NULL, NULL,
|
||||
&fd_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* Floppy disk: IO routine */
|
||||
|
||||
uint32 fd (uint32 dev, uint32 op, uint32 dat)
|
||||
@@ -201,76 +206,91 @@ uint32 fd (uint32 dev, uint32 op, uint32 dat)
|
||||
int32 u, t, fnc;
|
||||
UNIT *uptr;
|
||||
|
||||
fnc = GET_FNC (fd_cmd); /* get fnc */
|
||||
u = GET_UNIT (fd_cmd); /* get unit */
|
||||
fnc = GET_FNC (fd_cmd); /* get fnc */
|
||||
u = GET_UNIT (fd_cmd); /* get unit */
|
||||
uptr = fd_dev.units + u;
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read */
|
||||
if (fd_sta & (STA_IDL | STA_BSY)) return fd_db; /* idle, busy? */
|
||||
if (fd_bptr < FD_NUMBY) fd_db = fdxb[fd_bptr++];/* get byte */
|
||||
if (fd_bptr >= FD_NUMBY) { /* buf end? */
|
||||
if (ctab[fnc] & C_RD) { /* disk read? */
|
||||
sched_seek (uptr, uptr->LRN + 1); /* sched read */
|
||||
fd_sta = fd_sta | STA_BSY; } /* set busy */
|
||||
else fd_bptr = 0; } /* just wrap */
|
||||
if ((ctab[fnc] & C_RD) && fd_arm) /* if rd & arm, */
|
||||
SET_INT (v_FD); /* interrupt */
|
||||
return fd_db; /* return buf */
|
||||
case IO_WD: /* write */
|
||||
if (fd_sta & STA_IDL) { /* idle? */
|
||||
fd_lrn = ((fd_lrn << 8) | dat) & DMASK16; /* insert byte */
|
||||
fd_wdv = 1;
|
||||
break; }
|
||||
if (fd_bptr < FD_NUMBY) /* if room, */
|
||||
fdxb[fd_bptr++] = fd_db = dat; /* store byte */
|
||||
if (fd_bptr >= FD_NUMBY) { /* buf end? */
|
||||
if (ctab[fnc] & C_WD) { /* disk write? */
|
||||
sched_seek (uptr, uptr->LRN + 1); /* sched write */
|
||||
fd_sta = fd_sta | STA_BSY; } /* set busy */
|
||||
else fd_bptr = 0; } /* just wrap */
|
||||
if ((ctab[fnc] & C_WD) && fd_arm) /* if wr & arm, */
|
||||
SET_INT (v_FD); /* interrupt */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = fd_sta & STA_MASK; /* get status */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) t = t | STA_DU;
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
fd_arm = int_chg (v_FD, dat, fd_arm); /* upd int ctrl */
|
||||
fnc = GET_FNC (dat); /* new fnc */
|
||||
fd_cmd = dat; /* save cmd */
|
||||
u = GET_UNIT (dat); /* get unit */
|
||||
uptr = fd_dev.units + u;
|
||||
if (fnc == FNC_STOP) { /* stop? */
|
||||
uptr->FNC = uptr->FNC | FNC_STOPPING; /* flag stop */
|
||||
if (sim_is_active (uptr)) break; /* busy? cont */
|
||||
if (ctab[GET_FNC (uptr->FNC)] & C_WD) { /* write? */
|
||||
sched_seek (uptr, uptr->LRN + 1); /* sched write */
|
||||
fd_sta = fd_sta | STA_BSY; } /* set busy */
|
||||
else fd_done (u, 0, 0, 0); /* nrml done */
|
||||
break; }
|
||||
else if (fd_sta & STA_IDL) { /* must be idle */
|
||||
if (fnc != FNC_RSTA) { /* !rd status */
|
||||
fd_sta = STA_BSY; /* busy, !idle */
|
||||
fd_es[u][0] = 0;
|
||||
fd_es[u][1] = u; } /* init ext sta */
|
||||
else fd_sta = (fd_sta & ~STA_IDL) | STA_BSY;
|
||||
if (fnc == FNC_BOOT) t = LRN_BOOT; /* boot? fixed sec */
|
||||
else if (fd_wdv) t = fd_lrn; /* valid data? use */
|
||||
else t = uptr->LRN; /* use prev */
|
||||
fd_wdv = 0; /* data invalid */
|
||||
fd_bptr = 0; /* init buffer */
|
||||
uptr->FNC = fnc; /* save function */
|
||||
uptr->LRN = t; /* save LRN */
|
||||
if (ctab[fnc] & C_RD) sched_seek (uptr, t); /* seek now? */
|
||||
else sim_activate (uptr, fd_ctime); } /* start cmd */
|
||||
break; }
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_RD: /* read */
|
||||
if (fd_sta & (STA_IDL | STA_BSY)) return fd_db; /* idle, busy? */
|
||||
if (fd_bptr < FD_NUMBY) fd_db = fdxb[fd_bptr++];/* get byte */
|
||||
if (fd_bptr >= FD_NUMBY) { /* buf end? */
|
||||
if (ctab[fnc] & C_RD) { /* disk read? */
|
||||
sched_seek (uptr, uptr->LRN + 1); /* sched read */
|
||||
fd_sta = fd_sta | STA_BSY; /* set busy */
|
||||
}
|
||||
else fd_bptr = 0; /* just wrap */
|
||||
}
|
||||
if ((ctab[fnc] & C_RD) && fd_arm) /* if rd & arm, */
|
||||
SET_INT (v_FD); /* interrupt */
|
||||
return fd_db; /* return buf */
|
||||
|
||||
case IO_WD: /* write */
|
||||
if (fd_sta & STA_IDL) { /* idle? */
|
||||
fd_lrn = ((fd_lrn << 8) | dat) & DMASK16; /* insert byte */
|
||||
fd_wdv = 1;
|
||||
break;
|
||||
}
|
||||
if (fd_bptr < FD_NUMBY) /* if room, */
|
||||
fdxb[fd_bptr++] = fd_db = dat; /* store byte */
|
||||
if (fd_bptr >= FD_NUMBY) { /* buf end? */
|
||||
if (ctab[fnc] & C_WD) { /* disk write? */
|
||||
sched_seek (uptr, uptr->LRN + 1); /* sched write */
|
||||
fd_sta = fd_sta | STA_BSY; /* set busy */
|
||||
}
|
||||
else fd_bptr = 0; /* just wrap */
|
||||
}
|
||||
if ((ctab[fnc] & C_WD) && fd_arm) /* if wr & arm, */
|
||||
SET_INT (v_FD); /* interrupt */
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
t = fd_sta & STA_MASK; /* get status */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) t = t | STA_DU;
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
|
||||
case IO_OC: /* command */
|
||||
fd_arm = int_chg (v_FD, dat, fd_arm); /* upd int ctrl */
|
||||
fnc = GET_FNC (dat); /* new fnc */
|
||||
fd_cmd = dat; /* save cmd */
|
||||
u = GET_UNIT (dat); /* get unit */
|
||||
uptr = fd_dev.units + u;
|
||||
if (fnc == FNC_STOP) { /* stop? */
|
||||
uptr->FNC = uptr->FNC | FNC_STOPPING; /* flag stop */
|
||||
if (sim_is_active (uptr)) break; /* busy? cont */
|
||||
if (ctab[GET_FNC (uptr->FNC)] & C_WD) { /* write? */
|
||||
sched_seek (uptr, uptr->LRN + 1); /* sched write */
|
||||
fd_sta = fd_sta | STA_BSY; /* set busy */
|
||||
}
|
||||
else fd_done (u, 0, 0, 0); /* nrml done */
|
||||
break;
|
||||
}
|
||||
else if (fd_sta & STA_IDL) { /* must be idle */
|
||||
if (fnc != FNC_RSTA) { /* !rd status */
|
||||
fd_sta = STA_BSY; /* busy, !idle */
|
||||
fd_es[u][0] = 0;
|
||||
fd_es[u][1] = u; /* init ext sta */
|
||||
}
|
||||
else fd_sta = (fd_sta & ~STA_IDL) | STA_BSY;
|
||||
if (fnc == FNC_BOOT) t = LRN_BOOT; /* boot? fixed sec */
|
||||
else if (fd_wdv) t = fd_lrn; /* valid data? use */
|
||||
else t = uptr->LRN; /* use prev */
|
||||
fd_wdv = 0; /* data invalid */
|
||||
fd_bptr = 0; /* init buffer */
|
||||
uptr->FNC = fnc; /* save function */
|
||||
uptr->LRN = t; /* save LRN */
|
||||
if (ctab[fnc] & C_RD) sched_seek (uptr, t); /* seek now? */
|
||||
else sim_activate (uptr, fd_ctime); /* start cmd */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service; the action to be taken depends on command */
|
||||
|
||||
t_stat fd_svc (UNIT *uptr)
|
||||
@@ -278,102 +298,108 @@ t_stat fd_svc (UNIT *uptr)
|
||||
uint32 i, u, tk, sc, crc, fnc, da;
|
||||
uint8 *fbuf = uptr->filebuf;
|
||||
|
||||
u = uptr - fd_dev.units; /* get unit number */
|
||||
fnc = GET_FNC (uptr->FNC); /* get function */
|
||||
switch (fnc) { /* case on function */
|
||||
u = uptr - fd_dev.units; /* get unit number */
|
||||
fnc = GET_FNC (uptr->FNC); /* get function */
|
||||
switch (fnc) { /* case on function */
|
||||
|
||||
case FNC_RESET: /* reset */
|
||||
fd_clr (&fd_dev); /* clear device */
|
||||
fd_done (u, 0, 0, 0); /* set idle */
|
||||
return SCPE_OK;
|
||||
case FNC_RESET: /* reset */
|
||||
fd_clr (&fd_dev); /* clear device */
|
||||
fd_done (u, 0, 0, 0); /* set idle */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_STOP: /* stop */
|
||||
fd_done (u, 0, 0, 0); /* set idle */
|
||||
return SCPE_OK;
|
||||
case FNC_STOP: /* stop */
|
||||
fd_done (u, 0, 0, 0); /* set idle */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_BOOT: /* boot, buf empty */
|
||||
case FNC_RD: /* read, buf empty */
|
||||
if (uptr->FNC & FNC_STOPPING) break; /* stopped? */
|
||||
if (fd_dte (uptr, FALSE)) return SCPE_OK; /* xfr error? */
|
||||
da = GET_DA (uptr->LRN); /* get disk addr */
|
||||
for (i = 0; i < FD_NUMBY; i++) /* read sector */
|
||||
fdxb[i] = fbuf[da + i];
|
||||
if (fbuf[FD_SIZE + uptr->LRN - 1]) { /* deleted? set err */
|
||||
fd_sta = fd_sta | STA_DEL;
|
||||
fd_es[u][0] = fd_es[u][0] | ES0_DEL; }
|
||||
fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */
|
||||
fd_es[u][3] = GET_TRK (uptr->LRN);
|
||||
fd_bptr = 0; /* init buf */
|
||||
uptr->LRN = uptr->LRN + 1; /* next block */
|
||||
break;
|
||||
case FNC_BOOT: /* boot, buf empty */
|
||||
case FNC_RD: /* read, buf empty */
|
||||
if (uptr->FNC & FNC_STOPPING) break; /* stopped? */
|
||||
if (fd_dte (uptr, FALSE)) return SCPE_OK; /* xfr error? */
|
||||
da = GET_DA (uptr->LRN); /* get disk addr */
|
||||
for (i = 0; i < FD_NUMBY; i++) /* read sector */
|
||||
fdxb[i] = fbuf[da + i];
|
||||
if (fbuf[FD_SIZE + uptr->LRN - 1]) { /* deleted? set err */
|
||||
fd_sta = fd_sta | STA_DEL;
|
||||
fd_es[u][0] = fd_es[u][0] | ES0_DEL;
|
||||
}
|
||||
fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */
|
||||
fd_es[u][3] = GET_TRK (uptr->LRN);
|
||||
fd_bptr = 0; /* init buf */
|
||||
uptr->LRN = uptr->LRN + 1; /* next block */
|
||||
break;
|
||||
|
||||
case FNC_WR: case FNC_DEL: /* write block */
|
||||
if (fd_dte (uptr, TRUE)) return SCPE_OK; /* xfr error? */
|
||||
if (fd_bptr) { /* any transfer? */
|
||||
da = GET_DA (uptr->LRN); /* get disk addr */
|
||||
for (i = fd_bptr; i < FD_NUMBY; i++) /* pad sector */
|
||||
fdxb[i] = fd_db;
|
||||
for (i = 0; i < FD_NUMBY; i++) /* write sector */
|
||||
fbuf[da + i] = fdxb[i]; /* then dir */
|
||||
fbuf[FD_SIZE + uptr->LRN - 1] = ((fnc == FNC_DEL)? 1: 0);
|
||||
uptr->hwmark = uptr->capac; /* rewrite all */
|
||||
fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */
|
||||
fd_es[u][3] = GET_TRK (uptr->LRN);
|
||||
fd_bptr = 0; /* init buf */
|
||||
uptr->LRN = uptr->LRN + 1; } /* next block */
|
||||
break;
|
||||
case FNC_WR: case FNC_DEL: /* write block */
|
||||
if (fd_dte (uptr, TRUE)) return SCPE_OK; /* xfr error? */
|
||||
if (fd_bptr) { /* any transfer? */
|
||||
da = GET_DA (uptr->LRN); /* get disk addr */
|
||||
for (i = fd_bptr; i < FD_NUMBY; i++) /* pad sector */
|
||||
fdxb[i] = fd_db;
|
||||
for (i = 0; i < FD_NUMBY; i++) /* write sector */
|
||||
fbuf[da + i] = fdxb[i]; /* then dir */
|
||||
fbuf[FD_SIZE + uptr->LRN - 1] = ((fnc == FNC_DEL)? 1: 0);
|
||||
uptr->hwmark = uptr->capac; /* rewrite all */
|
||||
fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */
|
||||
fd_es[u][3] = GET_TRK (uptr->LRN);
|
||||
fd_bptr = 0; /* init buf */
|
||||
uptr->LRN = uptr->LRN + 1; /* next block */
|
||||
}
|
||||
break;
|
||||
|
||||
case FNC_RSTA: /* read status */
|
||||
if (uptr->flags & UNIT_WPRT) /* wr protected? */
|
||||
fd_es[u][0] = fd_es[u][0] | ES0_WRP;
|
||||
if (GET_TRK (uptr->LRN) == 0) /* on track 0? */
|
||||
fd_es[u][1] = fd_es[u][1] | ES1_TK0;
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */
|
||||
fd_es[u][0] = fd_es[u][0] | ES0_FLT; /* set err */
|
||||
fd_es[u][1] = fd_es[u][1] | ES1_NRDY; }
|
||||
for (i = 0; i < ES_SIZE; i++) fdxb[i] = fd_es[u][i]; /* copy to buf */
|
||||
for (i = ES_SIZE; i < FD_NUMBY; i++) fdxb[i] = 0;
|
||||
break;
|
||||
case FNC_RSTA: /* read status */
|
||||
if (uptr->flags & UNIT_WPRT) /* wr protected? */
|
||||
fd_es[u][0] = fd_es[u][0] | ES0_WRP;
|
||||
if (GET_TRK (uptr->LRN) == 0) /* on track 0? */
|
||||
fd_es[u][1] = fd_es[u][1] | ES1_TK0;
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */
|
||||
fd_es[u][0] = fd_es[u][0] | ES0_FLT; /* set err */
|
||||
fd_es[u][1] = fd_es[u][1] | ES1_NRDY;
|
||||
}
|
||||
for (i = 0; i < ES_SIZE; i++) fdxb[i] = fd_es[u][i]; /* copy to buf */
|
||||
for (i = ES_SIZE; i < FD_NUMBY; i++) fdxb[i] = 0;
|
||||
break;
|
||||
|
||||
case FNC_RDID: /* read ID */
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY);
|
||||
return SCPE_OK; }
|
||||
for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr buf */
|
||||
tk = GET_TRK (uptr->LRN); /* get track */
|
||||
sc = GET_SEC (uptr->LRN); /* get sector */
|
||||
fdxb[0] = tk & 0xFF; /* store track */
|
||||
fdxb[2] = sc & 0xFF; /* store sector */
|
||||
crc = fd_crc (0xFFFF, 0xFE00, 8); /* CRC addr mark */
|
||||
crc = fd_crc (crc, tk << 8, 16); /* CRC track */
|
||||
crc = fd_crc (crc, sc << 8, 16); /* CRC sector */
|
||||
fdxb[4] = (crc >> 8) & 0xFF; /* store CRC */
|
||||
fdxb[5] = crc & 0xFF;
|
||||
break;
|
||||
case FNC_RDID: /* read ID */
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY);
|
||||
return SCPE_OK;
|
||||
}
|
||||
for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr buf */
|
||||
tk = GET_TRK (uptr->LRN); /* get track */
|
||||
sc = GET_SEC (uptr->LRN); /* get sector */
|
||||
fdxb[0] = tk & 0xFF; /* store track */
|
||||
fdxb[2] = sc & 0xFF; /* store sector */
|
||||
crc = fd_crc (0xFFFF, 0xFE00, 8); /* CRC addr mark */
|
||||
crc = fd_crc (crc, tk << 8, 16); /* CRC track */
|
||||
crc = fd_crc (crc, sc << 8, 16); /* CRC sector */
|
||||
fdxb[4] = (crc >> 8) & 0xFF; /* store CRC */
|
||||
fdxb[5] = crc & 0xFF;
|
||||
break;
|
||||
|
||||
case FNC_FMT: /* format */
|
||||
default:
|
||||
fd_done (u, STA_ERR, ES0_ERR, ES1_CMD); /* ill cmd */
|
||||
uptr->LRN = 1; /* on track 0 */
|
||||
return SCPE_OK; }
|
||||
case FNC_FMT: /* format */
|
||||
default:
|
||||
fd_done (u, STA_ERR, ES0_ERR, ES1_CMD); /* ill cmd */
|
||||
uptr->LRN = 1; /* on track 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (uptr->FNC & FNC_STOPPING) { /* stopping? */
|
||||
uptr->FNC = FNC_STOP; /* fnc = STOP */
|
||||
sim_activate (uptr, fd_ctime); } /* schedule */
|
||||
fd_sta = fd_sta & ~STA_BSY; /* clear busy */
|
||||
if (fd_arm) SET_INT (v_FD); /* if armed, int */
|
||||
if (uptr->FNC & FNC_STOPPING) { /* stopping? */
|
||||
uptr->FNC = FNC_STOP; /* fnc = STOP */
|
||||
sim_activate (uptr, fd_ctime); /* schedule */
|
||||
}
|
||||
fd_sta = fd_sta & ~STA_BSY; /* clear busy */
|
||||
if (fd_arm) SET_INT (v_FD); /* if armed, int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Schedule seek */
|
||||
|
||||
void sched_seek (UNIT *uptr, int32 newlrn)
|
||||
{
|
||||
int32 diff = newlrn - uptr->LRN; /* LRN diff */
|
||||
int32 diff = newlrn - uptr->LRN; /* LRN diff */
|
||||
|
||||
if (diff < 0) diff = -diff; /* ABS */
|
||||
if (diff < 10) diff = 10; /* MIN 10 */
|
||||
sim_activate (uptr, diff * fd_stime); /* schedule */
|
||||
if (diff < 0) diff = -diff; /* ABS */
|
||||
if (diff < 10) diff = 10; /* MIN 10 */
|
||||
sim_activate (uptr, diff * fd_stime); /* schedule */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -381,9 +407,9 @@ return;
|
||||
|
||||
void fd_done (uint32 u, uint32 nsta, uint32 nes0, uint32 nes1)
|
||||
{
|
||||
fd_sta = (fd_sta | STA_IDL | nsta) & ~STA_BSY; /* set idle */
|
||||
if (fd_arm) SET_INT (v_FD); /* if armed, int */
|
||||
fd_es[u][0] = fd_es[u][0] | nes0; /* set ext state */
|
||||
fd_sta = (fd_sta | STA_IDL | nsta) & ~STA_BSY; /* set idle */
|
||||
if (fd_arm) SET_INT (v_FD); /* if armed, int */
|
||||
fd_es[u][0] = fd_es[u][0] | nes0; /* set ext state */
|
||||
fd_es[u][1] = fd_es[u][1] | nes1;
|
||||
return;
|
||||
}
|
||||
@@ -394,15 +420,18 @@ t_bool fd_dte (UNIT *uptr, t_bool wr)
|
||||
{
|
||||
uint32 u = uptr - fd_dev.units;
|
||||
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY);
|
||||
return TRUE; }
|
||||
if (wr && (uptr->flags & UNIT_WPRT)) { /* wr protected? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_WRP, 0);
|
||||
return TRUE; }
|
||||
if ((uptr->LRN == 0) || (uptr->LRN > FD_NUMLRN)) { /* bad LRN? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_LRN, 0);
|
||||
return TRUE; }
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY);
|
||||
return TRUE;
|
||||
}
|
||||
if (wr && (uptr->flags & UNIT_WPRT)) { /* wr protected? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_WRP, 0);
|
||||
return TRUE;
|
||||
}
|
||||
if ((uptr->LRN == 0) || (uptr->LRN > FD_NUMLRN)) { /* bad LRN? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_LRN, 0);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -413,10 +442,11 @@ uint32 fd_crc (uint32 crc, uint32 dat, uint32 cnt)
|
||||
uint32 i, wrk;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
wrk = crc ^ dat;
|
||||
crc = (crc << 1) & DMASK16;
|
||||
if (wrk & SIGN16) crc = ((crc ^ 0x1020) + 1) & DMASK16;
|
||||
dat = (dat << 1) & DMASK16; }
|
||||
wrk = crc ^ dat;
|
||||
crc = (crc << 1) & DMASK16;
|
||||
if (wrk & SIGN16) crc = ((crc ^ 0x1020) + 1) & DMASK16;
|
||||
dat = (dat << 1) & DMASK16;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
@@ -427,53 +457,52 @@ t_stat fd_clr (DEVICE *dptr)
|
||||
int32 i, j;
|
||||
UNIT *uptr;
|
||||
|
||||
fd_sta = STA_IDL; /* idle */
|
||||
fd_cmd = 0; /* clear state */
|
||||
fd_sta = STA_IDL; /* idle */
|
||||
fd_cmd = 0; /* clear state */
|
||||
fd_db = 0;
|
||||
fd_bptr = 0;
|
||||
fd_lrn = 1;
|
||||
fd_wdv = 0;
|
||||
for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr xfr buf */
|
||||
for (i = 0; i < FD_NUMDR; i++) { /* loop thru units */
|
||||
for (j = 0; j < ES_SIZE; j++) fd_es[i][j] = 0; /* clr ext sta */
|
||||
fd_es[i][2] = 1; /* sector 1 */
|
||||
uptr = fd_dev.units + i;
|
||||
sim_cancel (uptr); /* stop drive */
|
||||
uptr->LRN = 1; /* clear state */
|
||||
uptr->FNC = 0; }
|
||||
for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr xfr buf */
|
||||
for (i = 0; i < FD_NUMDR; i++) { /* loop thru units */
|
||||
for (j = 0; j < ES_SIZE; j++) fd_es[i][j] = 0; /* clr ext sta */
|
||||
fd_es[i][2] = 1; /* sector 1 */
|
||||
uptr = fd_dev.units + i;
|
||||
sim_cancel (uptr); /* stop drive */
|
||||
uptr->LRN = 1; /* clear state */
|
||||
uptr->FNC = 0;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat fd_reset (DEVICE *dptr)
|
||||
{
|
||||
CLR_INT (v_FD); /* clear int */
|
||||
CLR_ENB (v_FD); /* disable int */
|
||||
fd_arm = 0; /* disarm int */
|
||||
CLR_INT (v_FD); /* clear int */
|
||||
CLR_ENB (v_FD); /* disable int */
|
||||
fd_arm = 0; /* disarm int */
|
||||
return fd_clr (dptr);;
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define BOOT_START 0x50
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
#define BOOT_START 0x50
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
|
||||
static uint8 boot_rom[] = {
|
||||
0xD5, 0x00, /* ST: AL CF */
|
||||
0x00, 0xCF,
|
||||
0x43, 0x00, /* BR 80 */
|
||||
0x00, 0x80
|
||||
};
|
||||
0xD5, 0x00, 0x00, 0xCF, /* ST: AL CF */
|
||||
0x43, 0x00, 0x00, 0x80 /* BR 80 */
|
||||
};
|
||||
|
||||
t_stat fd_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
extern uint32 PC, dec_flgs;
|
||||
extern uint16 decrom[];
|
||||
|
||||
if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */
|
||||
IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, fd_dib.dno); /* set dev no */
|
||||
IOWriteB (AL_IOC, 0x86 + (unitno << CMD_V_UNIT)); /* set dev cmd, unit num */
|
||||
IOWriteB (AL_SCH, 0); /* clr sch dev no */
|
||||
if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */
|
||||
IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, fd_dib.dno); /* set dev no */
|
||||
IOWriteB (AL_IOC, 0x86 + (unitno << CMD_V_UNIT)); /* set dev cmd, unit num */
|
||||
IOWriteB (AL_SCH, 0); /* clr sch dev no */
|
||||
PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id_fp.c: Interdata floating point instructions
|
||||
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,8 +19,8 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
The Interdata uses IBM 360 floating point format:
|
||||
@@ -32,9 +32,9 @@
|
||||
| fraction low | :double
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
where S = 0 for plus, 1 for minus
|
||||
exponent = 16**n, in excess 64 code
|
||||
fraction = .hhhhhh, seen as 6-14 hexadecimal digits
|
||||
where S = 0 for plus, 1 for minus
|
||||
exponent = 16**n, in excess 64 code
|
||||
fraction = .hhhhhh, seen as 6-14 hexadecimal digits
|
||||
|
||||
Numbers can be normalized or unnormalized but are always normalized
|
||||
when loaded.
|
||||
@@ -52,61 +52,65 @@
|
||||
are rounded, double precision operations are truncated, and the floating
|
||||
point registers are kept in separate hardware arrays.
|
||||
*/
|
||||
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
struct ufp { /* unpacked fp */
|
||||
int32 sign; /* sign */
|
||||
int32 exp; /* unbiased exp */
|
||||
uint32 h; /* fr high */
|
||||
uint32 l; }; /* fr low */
|
||||
struct ufp { /* unpacked fp */
|
||||
int32 sign; /* sign */
|
||||
int32 exp; /* unbiased exp */
|
||||
uint32 h; /* fr high */
|
||||
uint32 l; /* fr low */
|
||||
};
|
||||
|
||||
#define FP_V_SIGN 31 /* sign */
|
||||
#define FP_M_SIGN 0x1
|
||||
#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN)
|
||||
#define FP_V_EXP 24 /* exponent */
|
||||
#define FP_M_EXP 0x7F
|
||||
#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP)
|
||||
#define FP_V_FRH 0 /* fraction */
|
||||
#define FP_M_FRH 0xFFFFFF
|
||||
#define FP_GETFRH(x) (((x) >> FP_V_FRH) & FP_M_FRH)
|
||||
#define FP_GETFRL(x) (x)
|
||||
#define FP_V_SIGN 31 /* sign */
|
||||
#define FP_M_SIGN 0x1
|
||||
#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN)
|
||||
#define FP_V_EXP 24 /* exponent */
|
||||
#define FP_M_EXP 0x7F
|
||||
#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP)
|
||||
#define FP_V_FRH 0 /* fraction */
|
||||
#define FP_M_FRH 0xFFFFFF
|
||||
#define FP_GETFRH(x) (((x) >> FP_V_FRH) & FP_M_FRH)
|
||||
#define FP_GETFRL(x) (x)
|
||||
|
||||
#define FP_BIAS 0x40 /* exp bias */
|
||||
#define FP_CARRY (1 << FP_V_EXP ) /* carry out */
|
||||
#define FP_NORM (0xF << (FP_V_EXP - 4)) /* normalized */
|
||||
#define FP_ROUND 0x80000000
|
||||
#define FP_BIAS 0x40 /* exp bias */
|
||||
#define FP_CARRY (1 << FP_V_EXP ) /* carry out */
|
||||
#define FP_NORM (0xF << (FP_V_EXP - 4)) /* normalized */
|
||||
#define FP_ROUND 0x80000000
|
||||
|
||||
/* Double precision fraction add/subtract/compare */
|
||||
|
||||
#define FR_ADD(d,s) d.l = (d.l + s.l) & DMASK32; \
|
||||
d.h = (d.h + s.h + (d.l < s.l)) & DMASK32
|
||||
#define FR_ADD(d,s) d.l = (d.l + s.l) & DMASK32; \
|
||||
d.h = (d.h + s.h + (d.l < s.l)) & DMASK32
|
||||
|
||||
#define FR_SUB(d,s) d.h = (d.h - s.h - (d.l < s.l)) & DMASK32; \
|
||||
d.l = (d.l - s.l) & DMASK32
|
||||
#define FR_SUB(d,s) d.h = (d.h - s.h - (d.l < s.l)) & DMASK32; \
|
||||
d.l = (d.l - s.l) & DMASK32
|
||||
|
||||
#define FR_GE(s1,s2) ((s1.h > s2.h) || \
|
||||
((s1.h == s2.h) && (s1.l >= s2.l)))
|
||||
#define FR_GE(s1,s2) ((s1.h > s2.h) || \
|
||||
((s1.h == s2.h) && (s1.l >= s2.l)))
|
||||
|
||||
/* Variable and constant shifts; for constants, 0 < k < 32 */
|
||||
|
||||
#define FR_RSH_V(v,s) if ((s) < 32) { \
|
||||
v.l = ((v.l >> (s)) | \
|
||||
(v.h << (32 - (s)))) & DMASK32; \
|
||||
v.h = (v.h >> (s)) & DMASK32; } \
|
||||
else { v.l = v.h >> ((s) - 32); \
|
||||
v.h = 0; }
|
||||
#define FR_RSH_V(v,s) if ((s) < 32) { \
|
||||
v.l = ((v.l >> (s)) | \
|
||||
(v.h << (32 - (s)))) & DMASK32; \
|
||||
v.h = (v.h >> (s)) & DMASK32; \
|
||||
} \
|
||||
else { \
|
||||
v.l = v.h >> ((s) - 32); \
|
||||
v.h = 0; \
|
||||
}
|
||||
|
||||
#define FR_RSH_K(v,s) v.l = ((v.l >> (s)) | \
|
||||
(v.h << (32 - (s)))) & DMASK32; \
|
||||
v.h = (v.h >> (s)) & DMASK32
|
||||
#define FR_RSH_K(v,s) v.l = ((v.l >> (s)) | \
|
||||
(v.h << (32 - (s)))) & DMASK32; \
|
||||
v.h = (v.h >> (s)) & DMASK32
|
||||
|
||||
#define FR_LSH_K(v,s) v.h = ((v.h << (s)) | \
|
||||
(v.l >> (32 - (s)))) & DMASK32; \
|
||||
v.l = (v.l << (s)) & DMASK32
|
||||
#define FR_LSH_K(v,s) v.h = ((v.h << (s)) | \
|
||||
(v.l >> (32 - (s)))) & DMASK32; \
|
||||
v.l = (v.l << (s)) & DMASK32
|
||||
|
||||
#define Q_RND(op) (OP_DPFP (op) == 0)
|
||||
#define Q_RND_AS(op) ((OP_DPFP (op) == 0) && fp_in_hwre)
|
||||
#define Q_RND(op) (OP_DPFP (op) == 0)
|
||||
#define Q_RND_AS(op) ((OP_DPFP (op) == 0) && fp_in_hwre)
|
||||
|
||||
extern uint32 *R;
|
||||
extern uint32 F[8];
|
||||
@@ -120,15 +124,15 @@ void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1);
|
||||
void NormUFP (struct ufp *fop);
|
||||
uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd);
|
||||
uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1);
|
||||
|
||||
|
||||
/* Floating point load */
|
||||
|
||||
uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea)
|
||||
{
|
||||
struct ufp fop2;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op, normalize */
|
||||
return StoreFPR (&fop2, op, r1, 0); /* store, chk unflo */
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op, normalize */
|
||||
return StoreFPR (&fop2, op, r1, 0); /* store, chk unflo */
|
||||
}
|
||||
|
||||
/* Floating point compare */
|
||||
@@ -137,105 +141,120 @@ uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea)
|
||||
{
|
||||
struct ufp fop1, fop2;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (fop1.sign ^ fop2.sign) /* signs differ? */
|
||||
return (fop2.sign? CC_G: (CC_C | CC_L));
|
||||
if (fop1.exp != fop2.exp) /* exps differ? */
|
||||
return (((fop1.exp > fop2.exp) ^ fop1.sign)? CC_G: (CC_C | CC_L));
|
||||
if (fop1.h != fop2.h) /* hi fracs differ? */
|
||||
return (((fop1.h > fop2.h) ^ fop1.sign)? CC_G: (CC_C | CC_L));
|
||||
if (OP_DPFP (op) && (fop1.l != fop2.l)) /* dp: low fracs diff? */
|
||||
return (((fop1.l > fop2.l) ^ fop1.sign)? CC_G: (CC_C | CC_L));
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (fop1.sign ^ fop2.sign) /* signs differ? */
|
||||
return (fop2.sign? CC_G: (CC_C | CC_L));
|
||||
if (fop1.exp != fop2.exp) /* exps differ? */
|
||||
return (((fop1.exp > fop2.exp) ^ fop1.sign)? CC_G: (CC_C | CC_L));
|
||||
if (fop1.h != fop2.h) /* hi fracs differ? */
|
||||
return (((fop1.h > fop2.h) ^ fop1.sign)? CC_G: (CC_C | CC_L));
|
||||
if (OP_DPFP (op) && (fop1.l != fop2.l)) /* dp: low fracs diff? */
|
||||
return (((fop1.l > fop2.l) ^ fop1.sign)? CC_G: (CC_C | CC_L));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Floating to integer conversion */
|
||||
|
||||
uint32 f_fix (uint32 op, uint32 r1, uint32 r2) /* 16b */
|
||||
uint32 f_fix (uint32 op, uint32 r1, uint32 r2) /* 16b */
|
||||
{
|
||||
struct ufp res;
|
||||
uint32 cc;
|
||||
|
||||
UnpackFPR (&res, op, r2); /* get op2, norm */
|
||||
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
|
||||
R[r1] = 0;
|
||||
return 0; }
|
||||
if ((res.exp > 0x44) || /* result too big? */
|
||||
UnpackFPR (&res, op, r2); /* get op2, norm */
|
||||
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
|
||||
R[r1] = 0;
|
||||
return 0;
|
||||
}
|
||||
if ((res.exp > 0x44) || /* result too big? */
|
||||
((res.exp == 0x44) && (res.h >= 0x00800000))) {
|
||||
res.h = MMASK16;
|
||||
cc = CC_V; }
|
||||
else { res.h = res.h >> ((0x46 - res.exp) * 4); /* right align frac */
|
||||
cc = 0; }
|
||||
res.h = MMASK16;
|
||||
cc = CC_V;
|
||||
}
|
||||
else {
|
||||
res.h = res.h >> ((0x46 - res.exp) * 4); /* right align frac */
|
||||
cc = 0;
|
||||
}
|
||||
if (res.sign) {
|
||||
R[r1] = ((res.h ^ DMASK16) + 1) & DMASK16; /* negate result */
|
||||
return cc | CC_L; }
|
||||
R[r1] = ((res.h ^ DMASK16) + 1) & DMASK16; /* negate result */
|
||||
return cc | CC_L;
|
||||
}
|
||||
R[r1] = res.h & DMASK16;
|
||||
return cc | CC_G;
|
||||
}
|
||||
|
||||
uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
|
||||
uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
|
||||
{
|
||||
struct ufp res;
|
||||
uint32 cc;
|
||||
|
||||
UnpackFPR (&res, op, r2); /* get op2, norm */
|
||||
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
|
||||
R[r1] = 0;
|
||||
return 0; }
|
||||
if ((res.exp > 0x48) || /* result too big? */
|
||||
UnpackFPR (&res, op, r2); /* get op2, norm */
|
||||
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
|
||||
R[r1] = 0;
|
||||
return 0;
|
||||
}
|
||||
if ((res.exp > 0x48) || /* result too big? */
|
||||
((res.exp == 0x48) && (res.h >= 0x00800000))) {
|
||||
res.h = MMASK32;
|
||||
cc = CC_V; }
|
||||
else { FR_LSH_K (res, 8); /* get all in 32b */
|
||||
res.h = res.h >> ((0x48 - res.exp) * 4); /* right align frac */
|
||||
cc = 0; }
|
||||
res.h = MMASK32;
|
||||
cc = CC_V;
|
||||
}
|
||||
else {
|
||||
FR_LSH_K (res, 8); /* get all in 32b */
|
||||
res.h = res.h >> ((0x48 - res.exp) * 4); /* right align frac */
|
||||
cc = 0;
|
||||
}
|
||||
if (res.sign) {
|
||||
R[r1] = (res.h ^ DMASK32) + 1; /* negate result */
|
||||
return cc | CC_L; }
|
||||
R[r1] = (res.h ^ DMASK32) + 1; /* negate result */
|
||||
return cc | CC_L;
|
||||
}
|
||||
R[r1] = res.h;
|
||||
return cc | CC_G;
|
||||
}
|
||||
|
||||
/* Integer to floating conversion */
|
||||
|
||||
uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */
|
||||
uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */
|
||||
{
|
||||
struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */
|
||||
struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */
|
||||
uint32 cc;
|
||||
|
||||
if (R[r2] == 0) cc = 0; /* zero arg? */
|
||||
else if (R[r2] & SIGN16) { /* neg arg? */
|
||||
res.sign = FP_M_SIGN; /* set sign */
|
||||
res.h = ((~R[r2] + 1) & DMASK16) << 8; /* get magnitude */
|
||||
cc = CC_L; }
|
||||
else { res.h = R[r2] << 8; /* pos nz arg */
|
||||
cc = CC_G; }
|
||||
NormUFP (&res); /* normalize */
|
||||
StoreFPR (&res, op, r1, 0); /* store result */
|
||||
if (R[r2] == 0) cc = 0; /* zero arg? */
|
||||
else if (R[r2] & SIGN16) { /* neg arg? */
|
||||
res.sign = FP_M_SIGN; /* set sign */
|
||||
res.h = ((~R[r2] + 1) & DMASK16) << 8; /* get magnitude */
|
||||
cc = CC_L;
|
||||
}
|
||||
else {
|
||||
res.h = R[r2] << 8; /* pos nz arg */
|
||||
cc = CC_G;
|
||||
}
|
||||
NormUFP (&res); /* normalize */
|
||||
StoreFPR (&res, op, r1, 0); /* store result */
|
||||
return cc;
|
||||
}
|
||||
|
||||
uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
|
||||
uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
|
||||
{
|
||||
struct ufp res = { 0, 0x48, 0, 0 }; /* +, 16**8 */
|
||||
struct ufp res = { 0, 0x48, 0, 0 }; /* +, 16**8 */
|
||||
uint32 cc, t;
|
||||
|
||||
t = R[r2]; /* int op */
|
||||
if (t) { /* nonzero arg? */
|
||||
if (t & SIGN32) { /* neg arg? */
|
||||
res.sign = FP_M_SIGN; /* set sign */
|
||||
t = (~t + 1) & DMASK32; /* get magnitude */
|
||||
cc = CC_L; }
|
||||
else cc = CC_G; /* pos nz arg */
|
||||
res.h = t >> 8; /* hi frac */
|
||||
res.l = t << 24; } /* lo frac */
|
||||
else cc = 0; /* zero arg */
|
||||
NormUFP (&res); /* normalize */
|
||||
StoreFPR (&res, op, r1, 0); /* store result */
|
||||
t = R[r2]; /* int op */
|
||||
if (t) { /* nonzero arg? */
|
||||
if (t & SIGN32) { /* neg arg? */
|
||||
res.sign = FP_M_SIGN; /* set sign */
|
||||
t = (~t + 1) & DMASK32; /* get magnitude */
|
||||
cc = CC_L;
|
||||
}
|
||||
else cc = CC_G; /* pos nz arg */
|
||||
res.h = t >> 8; /* hi frac */
|
||||
res.l = t << 24; /* lo frac */
|
||||
}
|
||||
else cc = 0; /* zero arg */
|
||||
NormUFP (&res); /* normalize */
|
||||
StoreFPR (&res, op, r1, 0); /* store result */
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
/* Floating point add/subtract */
|
||||
|
||||
uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea)
|
||||
@@ -243,37 +262,44 @@ uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea)
|
||||
struct ufp fop1, fop2, t;
|
||||
int32 ediff;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (op & 1) fop2.sign = fop2.sign ^ 1; /* if sub, inv sign2 */
|
||||
if (fop1.h == 0) fop1 = fop2; /* if op1 = 0, res = op2 */
|
||||
else if (fop2.h != 0) { /* if op2 = 0, no add */
|
||||
if ((fop1.exp < fop2.exp) || /* |op1| < |op2|? */
|
||||
((fop1.exp == fop2.exp) &&
|
||||
((fop1.h < fop2.h) ||
|
||||
((fop1.h == fop2.h) && (fop1.l < fop2.l))))) {
|
||||
t = fop2; /* swap operands */
|
||||
fop2 = fop1;
|
||||
fop1 = t; }
|
||||
ediff = fop1.exp - fop2.exp; /* exp difference */
|
||||
if (OP_DPFP (op) || fp_in_hwre) { /* dbl prec or hwre? */
|
||||
if (ediff >= 14) fop2.h = fop2.l = 0; /* diff too big? */
|
||||
else if (ediff) { /* any difference? */
|
||||
FR_RSH_V (fop2, ediff * 4); } } /* shift frac */
|
||||
else { /* sgl prec ucode */
|
||||
if (ediff >= 6) fop2.h = 0; /* diff too big? */
|
||||
else if (ediff) /* any difference? */
|
||||
fop2.h = fop2.h >> (ediff * 4); } /* shift frac */
|
||||
if (fop1.sign ^ fop2.sign) { /* eff subtract */
|
||||
FR_SUB (fop1, fop2); /* sub fractions */
|
||||
NormUFP (&fop1); } /* normalize result */
|
||||
else {
|
||||
FR_ADD (fop1, fop2); /* add fractions */
|
||||
if (fop1.h & FP_CARRY) { /* carry out? */
|
||||
FR_RSH_K (fop1, 4); /* renormalize */
|
||||
fop1.exp = fop1.exp + 1; } } /* incr exp */
|
||||
} /* end if fop2 */
|
||||
return StoreFPR (&fop1, op, r1, Q_RND_AS (op)); /* store result */
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (op & 1) fop2.sign = fop2.sign ^ 1; /* if sub, inv sign2 */
|
||||
if (fop1.h == 0) fop1 = fop2; /* if op1 = 0, res = op2 */
|
||||
else if (fop2.h != 0) { /* if op2 = 0, no add */
|
||||
if ((fop1.exp < fop2.exp) || /* |op1| < |op2|? */
|
||||
((fop1.exp == fop2.exp) &&
|
||||
((fop1.h < fop2.h) ||
|
||||
((fop1.h == fop2.h) && (fop1.l < fop2.l))))) {
|
||||
t = fop2; /* swap operands */
|
||||
fop2 = fop1;
|
||||
fop1 = t;
|
||||
}
|
||||
ediff = fop1.exp - fop2.exp; /* exp difference */
|
||||
if (OP_DPFP (op) || fp_in_hwre) { /* dbl prec or hwre? */
|
||||
if (ediff >= 14) fop2.h = fop2.l = 0; /* diff too big? */
|
||||
else if (ediff) { /* any difference? */
|
||||
FR_RSH_V (fop2, ediff * 4); /* shift frac */
|
||||
}
|
||||
}
|
||||
else { /* sgl prec ucode */
|
||||
if (ediff >= 6) fop2.h = 0; /* diff too big? */
|
||||
else if (ediff) /* any difference? */
|
||||
fop2.h = fop2.h >> (ediff * 4); /* shift frac */
|
||||
}
|
||||
if (fop1.sign ^ fop2.sign) { /* eff subtract */
|
||||
FR_SUB (fop1, fop2); /* sub fractions */
|
||||
NormUFP (&fop1); /* normalize result */
|
||||
}
|
||||
else {
|
||||
FR_ADD (fop1, fop2); /* add fractions */
|
||||
if (fop1.h & FP_CARRY) { /* carry out? */
|
||||
FR_RSH_K (fop1, 4); /* renormalize */
|
||||
fop1.exp = fop1.exp + 1; /* incr exp */
|
||||
}
|
||||
}
|
||||
} /* end if fop2 */
|
||||
return StoreFPR (&fop1, op, r1, Q_RND_AS (op)); /* store result */
|
||||
}
|
||||
|
||||
/* Floating point multiply
|
||||
@@ -293,35 +319,39 @@ struct ufp fop1, fop2;
|
||||
struct ufp res = { 0, 0, 0, 0 };
|
||||
uint32 i;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (fop1.h && fop2.h) { /* if both != 0 */
|
||||
res.sign = fop1.sign ^ fop2.sign; /* sign = diff */
|
||||
res.exp = fop1.exp + fop2.exp - FP_BIAS; /* exp = sum */
|
||||
if ((res.exp < 0) || (res.exp > FP_M_EXP)) /* ovf/undf? */
|
||||
return StoreFPX (&res, op, r1); /* early out */
|
||||
if ((fop1.l | fop2.l) == 0) { /* 24b x 24b? */
|
||||
for (i = 0; i < 24; i++) { /* 24 iterations */
|
||||
if (fop2.h & 1) res.h = res.h + fop1.h; /* add hi only */
|
||||
FR_RSH_K (res, 1); /* shift dp res */
|
||||
fop2.h = fop2.h >> 1; }
|
||||
}
|
||||
else { /* some low 0's */
|
||||
if (fop2.l != 0) { /* 56b x 56b? */
|
||||
for (i = 0; i < 32; i++) { /* do low 32b */
|
||||
if (fop2.l & 1) { FR_ADD (res, fop1); }
|
||||
FR_RSH_K (res, 1);
|
||||
fop2.l = fop2.l >> 1; } }
|
||||
for (i = 0; i < 24; i++) { /* do hi 24b */
|
||||
if (fop2.h & 1) { FR_ADD (res, fop1); }
|
||||
FR_RSH_K (res, 1);
|
||||
fop2.h = fop2.h >> 1; }
|
||||
}
|
||||
NormUFP (&res); /* normalize */
|
||||
if (res.exp < 0) /* underflow? */
|
||||
return StoreFPX (&res, op, r1); /* early out */
|
||||
}
|
||||
return StoreFPR (&res, op, r1, Q_RND (op)); /* store */
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (fop1.h && fop2.h) { /* if both != 0 */
|
||||
res.sign = fop1.sign ^ fop2.sign; /* sign = diff */
|
||||
res.exp = fop1.exp + fop2.exp - FP_BIAS; /* exp = sum */
|
||||
if ((res.exp < 0) || (res.exp > FP_M_EXP)) /* ovf/undf? */
|
||||
return StoreFPX (&res, op, r1); /* early out */
|
||||
if ((fop1.l | fop2.l) == 0) { /* 24b x 24b? */
|
||||
for (i = 0; i < 24; i++) { /* 24 iterations */
|
||||
if (fop2.h & 1) res.h = res.h + fop1.h; /* add hi only */
|
||||
FR_RSH_K (res, 1); /* shift dp res */
|
||||
fop2.h = fop2.h >> 1;
|
||||
}
|
||||
}
|
||||
else { /* some low 0's */
|
||||
if (fop2.l != 0) { /* 56b x 56b? */
|
||||
for (i = 0; i < 32; i++) { /* do low 32b */
|
||||
if (fop2.l & 1) { FR_ADD (res, fop1); }
|
||||
FR_RSH_K (res, 1);
|
||||
fop2.l = fop2.l >> 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 24; i++) { /* do hi 24b */
|
||||
if (fop2.h & 1) { FR_ADD (res, fop1); }
|
||||
FR_RSH_K (res, 1);
|
||||
fop2.h = fop2.h >> 1;
|
||||
}
|
||||
}
|
||||
NormUFP (&res); /* normalize */
|
||||
if (res.exp < 0) /* underflow? */
|
||||
return StoreFPX (&res, op, r1); /* early out */
|
||||
}
|
||||
return StoreFPR (&res, op, r1, Q_RND (op)); /* store */
|
||||
}
|
||||
|
||||
/* Floating point divide - see overflow/underflow notes for multiply */
|
||||
@@ -332,35 +362,39 @@ struct ufp fop1, fop2;
|
||||
struct ufp quo = { 0, 0, 0, 0 };
|
||||
int32 i;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (fop2.h == 0) return CC_C | CC_V; /* div by zero? */
|
||||
if (fop1.h) { /* dvd != 0? */
|
||||
quo.sign = fop1.sign ^ fop2.sign; /* sign = diff */
|
||||
quo.exp = fop1.exp - fop2.exp + FP_BIAS; /* exp = diff */
|
||||
if ((quo.exp < 0) || (quo.exp > FP_M_EXP)) /* ovf/undf? */
|
||||
return StoreFPX (&quo, op, r1); /* early out */
|
||||
if (!FR_GE (fop1, fop2)) {
|
||||
FR_LSH_K (fop1, 4); } /* ensure success */
|
||||
else { /* exp off by 1 */
|
||||
quo.exp = quo.exp + 1; /* incr exponent */
|
||||
if (quo.exp > FP_M_EXP) /* overflow? */
|
||||
return StoreFPX (&quo, op, r1); } /* early out */
|
||||
for (i = 0; i < (OP_DPFP (op)? 14: 6); i++) { /* 6/14 hex digits */
|
||||
FR_LSH_K (quo, 4); /* shift quotient */
|
||||
while (FR_GE (fop1, fop2)) { /* while sub works */
|
||||
FR_SUB (fop1, fop2); /* decrement */
|
||||
quo.l = quo.l + 1; } /* add quo bit */
|
||||
FR_LSH_K (fop1, 4); } /* shift divd */
|
||||
if (!OP_DPFP (op)) { /* single? */
|
||||
quo.h = quo.l; /* move quotient */
|
||||
if (fop1.h >= (fop2.h << 3)) quo.l = FP_ROUND;
|
||||
else quo.l = 0; }
|
||||
/* don't need to normalize */
|
||||
} /* end if fop1.h */
|
||||
return StoreFPR (&quo, op, r1, Q_RND (op)); /* store result */
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (fop2.h == 0) return CC_C | CC_V; /* div by zero? */
|
||||
if (fop1.h) { /* dvd != 0? */
|
||||
quo.sign = fop1.sign ^ fop2.sign; /* sign = diff */
|
||||
quo.exp = fop1.exp - fop2.exp + FP_BIAS; /* exp = diff */
|
||||
if ((quo.exp < 0) || (quo.exp > FP_M_EXP)) /* ovf/undf? */
|
||||
return StoreFPX (&quo, op, r1); /* early out */
|
||||
if (!FR_GE (fop1, fop2)) {
|
||||
FR_LSH_K (fop1, 4); /* ensure success */
|
||||
}
|
||||
else { /* exp off by 1 */
|
||||
quo.exp = quo.exp + 1; /* incr exponent */
|
||||
if (quo.exp > FP_M_EXP) /* overflow? */
|
||||
return StoreFPX (&quo, op, r1); /* early out */
|
||||
}
|
||||
for (i = 0; i < (OP_DPFP (op)? 14: 6); i++) { /* 6/14 hex digits */
|
||||
FR_LSH_K (quo, 4); /* shift quotient */
|
||||
while (FR_GE (fop1, fop2)) { /* while sub works */
|
||||
FR_SUB (fop1, fop2); /* decrement */
|
||||
quo.l = quo.l + 1; /* add quo bit */
|
||||
}
|
||||
FR_LSH_K (fop1, 4); /* shift divd */
|
||||
}
|
||||
if (!OP_DPFP (op)) { /* single? */
|
||||
quo.h = quo.l; /* move quotient */
|
||||
if (fop1.h >= (fop2.h << 3)) quo.l = FP_ROUND;
|
||||
else quo.l = 0;
|
||||
} /* don't need to normalize */
|
||||
} /* end if fop1.h */
|
||||
return StoreFPR (&quo, op, r1, Q_RND (op)); /* store result */
|
||||
}
|
||||
|
||||
|
||||
/* Utility routines */
|
||||
|
||||
/* Unpack floating point number */
|
||||
@@ -369,17 +403,21 @@ void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1)
|
||||
{
|
||||
uint32 hi;
|
||||
|
||||
if (OP_DPFP (op)) { /* double prec? */
|
||||
hi = D[r1 >> 1].h; /* get hi */
|
||||
fop->l = FP_GETFRL (D[r1 >> 1].l); } /* get lo */
|
||||
else { hi = ReadFReg (r1); /* single prec */
|
||||
fop->l = 0; } /* lo is zero */
|
||||
fop->h = FP_GETFRH (hi); /* get hi frac */
|
||||
if (fop->h || fop->l) { /* non-zero? */
|
||||
fop->sign = FP_GETSIGN (hi); /* get sign */
|
||||
fop->exp = FP_GETEXP (hi); /* get exp */
|
||||
NormUFP (fop); } /* normalize */
|
||||
else fop->sign = fop->exp = 0; /* clean zero */
|
||||
if (OP_DPFP (op)) { /* double prec? */
|
||||
hi = D[r1 >> 1].h; /* get hi */
|
||||
fop->l = FP_GETFRL (D[r1 >> 1].l); /* get lo */
|
||||
}
|
||||
else {
|
||||
hi = ReadFReg (r1); /* single prec */
|
||||
fop->l = 0; /* lo is zero */
|
||||
}
|
||||
fop->h = FP_GETFRH (hi); /* get hi frac */
|
||||
if (fop->h || fop->l) { /* non-zero? */
|
||||
fop->sign = FP_GETSIGN (hi); /* get sign */
|
||||
fop->exp = FP_GETEXP (hi); /* get exp */
|
||||
NormUFP (fop); /* normalize */
|
||||
}
|
||||
else fop->sign = fop->exp = 0; /* clean zero */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -389,22 +427,28 @@ void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea)
|
||||
{
|
||||
uint32 hi;
|
||||
|
||||
if (OP_TYPE (op) > OP_RR) { /* mem ref? */
|
||||
hi = ReadF (ea, VR); /* get hi */
|
||||
if (OP_DPFP (op)) fop->l = ReadF (ea + 4, VR); /* dp? get lo */
|
||||
else fop->l = 0; } /* sp, lo = 0 */
|
||||
else { if (OP_DPFP (op)) { /* RR */
|
||||
hi = D[r2 >> 1].h; /* dp? get dp reg */
|
||||
fop->l = D[r2 >> 1].l; }
|
||||
else {
|
||||
hi = ReadFReg (r2); /* get sp reg */
|
||||
fop->l = 0; } }
|
||||
fop->h = FP_GETFRH (hi); /* get hi frac */
|
||||
if (fop->h || fop->l) { /* non-zero? */
|
||||
fop->sign = FP_GETSIGN (hi); /* get sign */
|
||||
fop->exp = FP_GETEXP (hi); /* get exp */
|
||||
NormUFP (fop); } /* normalize */
|
||||
else fop->sign = fop->exp = 0; /* clean zero */
|
||||
if (OP_TYPE (op) > OP_RR) { /* mem ref? */
|
||||
hi = ReadF (ea, VR); /* get hi */
|
||||
if (OP_DPFP (op)) fop->l = ReadF (ea + 4, VR); /* dp? get lo */
|
||||
else fop->l = 0; /* sp, lo = 0 */
|
||||
}
|
||||
else {
|
||||
if (OP_DPFP (op)) { /* RR */
|
||||
hi = D[r2 >> 1].h; /* dp? get dp reg */
|
||||
fop->l = D[r2 >> 1].l;
|
||||
}
|
||||
else {
|
||||
hi = ReadFReg (r2); /* get sp reg */
|
||||
fop->l = 0;
|
||||
}
|
||||
}
|
||||
fop->h = FP_GETFRH (hi); /* get hi frac */
|
||||
if (fop->h || fop->l) { /* non-zero? */
|
||||
fop->sign = FP_GETSIGN (hi); /* get sign */
|
||||
fop->exp = FP_GETEXP (hi); /* get exp */
|
||||
NormUFP (fop); /* normalize */
|
||||
}
|
||||
else fop->sign = fop->exp = 0; /* clean zero */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -412,12 +456,14 @@ return;
|
||||
|
||||
void NormUFP (struct ufp *fop)
|
||||
{
|
||||
if ((fop->h & FP_M_FRH) || fop->l) { /* any fraction? */
|
||||
while ((fop->h & FP_NORM) == 0) { /* until norm */
|
||||
fop->h = (fop->h << 4) | ((fop->l >> 28) & 0xF);
|
||||
fop->l = fop->l << 4;
|
||||
fop->exp = fop->exp - 1; } }
|
||||
else fop->sign = fop->exp = 0; /* clean 0 */
|
||||
if ((fop->h & FP_M_FRH) || fop->l) { /* any fraction? */
|
||||
while ((fop->h & FP_NORM) == 0) { /* until norm */
|
||||
fop->h = (fop->h << 4) | ((fop->l >> 28) & 0xF);
|
||||
fop->l = fop->l << 4;
|
||||
fop->exp = fop->exp - 1;
|
||||
}
|
||||
}
|
||||
else fop->sign = fop->exp = 0; /* clean 0 */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -427,29 +473,39 @@ uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd)
|
||||
{
|
||||
uint32 hi, cc;
|
||||
|
||||
if (rnd && (fop->l & FP_ROUND)) { /* round? */
|
||||
fop->h = fop->h + 1; /* add 1 to frac */
|
||||
if (fop->h & FP_CARRY) { /* carry out? */
|
||||
fop->h = fop->h >> 4; /* renormalize */
|
||||
fop->exp = fop->exp + 1; } } /* incr exp */
|
||||
if (fop->h == 0) { /* result 0? */
|
||||
hi = fop->l = 0; /* store clean 0 */
|
||||
cc = 0; }
|
||||
else if (fop->exp < 0) { /* underflow? */
|
||||
hi = fop->l = 0; /* store clean 0 */
|
||||
cc = CC_V; }
|
||||
else if (fop->exp > FP_M_EXP) { /* overflow? */
|
||||
hi = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF;
|
||||
fop->l = 0xFFFFFFFF;
|
||||
cc = (CC_V | ((fop->sign)? CC_L: CC_G)); }
|
||||
else { hi = ((fop->sign & FP_M_SIGN) << FP_V_SIGN) | /* pack result */
|
||||
((fop->exp & FP_M_EXP) << FP_V_EXP) |
|
||||
((fop->h & FP_M_FRH) << FP_V_FRH);
|
||||
cc = (fop->sign)? CC_L: CC_G; } /* set cc's */
|
||||
if (OP_DPFP (op)) { /* double precision? */
|
||||
D[r1 >> 1].h = hi;
|
||||
D[r1 >> 1].l = fop->l; }
|
||||
else { WriteFReg (r1, hi); }
|
||||
if (rnd && (fop->l & FP_ROUND)) { /* round? */
|
||||
fop->h = fop->h + 1; /* add 1 to frac */
|
||||
if (fop->h & FP_CARRY) { /* carry out? */
|
||||
fop->h = fop->h >> 4; /* renormalize */
|
||||
fop->exp = fop->exp + 1; /* incr exp */
|
||||
}
|
||||
}
|
||||
if (fop->h == 0) { /* result 0? */
|
||||
hi = fop->l = 0; /* store clean 0 */
|
||||
cc = 0;
|
||||
}
|
||||
else if (fop->exp < 0) { /* underflow? */
|
||||
hi = fop->l = 0; /* store clean 0 */
|
||||
cc = CC_V;
|
||||
}
|
||||
else if (fop->exp > FP_M_EXP) { /* overflow? */
|
||||
hi = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF;
|
||||
fop->l = 0xFFFFFFFF;
|
||||
cc = (CC_V | ((fop->sign)? CC_L: CC_G));
|
||||
}
|
||||
else {
|
||||
hi = ((fop->sign & FP_M_SIGN) << FP_V_SIGN) | /* pack result */
|
||||
((fop->exp & FP_M_EXP) << FP_V_EXP) |
|
||||
((fop->h & FP_M_FRH) << FP_V_FRH);
|
||||
cc = (fop->sign)? CC_L: CC_G; /* set cc's */
|
||||
}
|
||||
if (OP_DPFP (op)) { /* double precision? */
|
||||
D[r1 >> 1].h = hi;
|
||||
D[r1 >> 1].l = fop->l;
|
||||
}
|
||||
else {
|
||||
WriteFReg (r1, hi);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
|
||||
@@ -459,13 +515,18 @@ uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1)
|
||||
{
|
||||
uint32 cc = CC_V;
|
||||
|
||||
if (fop->exp < 0) fop->h = fop->l = 0; /* undf? clean 0 */
|
||||
else { fop->h = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; /* overflow */
|
||||
fop->l = 0xFFFFFFFF;
|
||||
cc = cc | ((fop->sign)? CC_L: CC_G); }
|
||||
if (OP_DPFP (op)) { /* double precision? */
|
||||
D[r1 >> 1].h = fop->h;
|
||||
D[r1 >> 1].l = fop->l; }
|
||||
else { WriteFReg (r1, fop->h); }
|
||||
if (fop->exp < 0) fop->h = fop->l = 0; /* undf? clean 0 */
|
||||
else {
|
||||
fop->h = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; /* overflow */
|
||||
fop->l = 0xFFFFFFFF;
|
||||
cc = cc | ((fop->sign)? CC_L: CC_G);
|
||||
}
|
||||
if (OP_DPFP (op)) { /* double precision? */
|
||||
D[r1 >> 1].h = fop->h;
|
||||
D[r1 >> 1].l = fop->l;
|
||||
}
|
||||
else {
|
||||
WriteFReg (r1, fop->h);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/* id_io.c: Interdata CPU-independent I/O routines
|
||||
|
||||
Copyright (c) 2001-2004, Robert M. Supnik
|
||||
Copyright (c) 2001-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,47 +19,47 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
|
||||
21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
|
||||
|
||||
Interdata I/O devices are defined by a device information block:
|
||||
|
||||
dno base device number
|
||||
sch selector channel, -1 if none
|
||||
irq interrupt request flag
|
||||
tplte device number template, NULL if one device number
|
||||
iot I/O processing routine
|
||||
ini initialization routine
|
||||
dno base device number
|
||||
sch selector channel, -1 if none
|
||||
irq interrupt request flag
|
||||
tplte device number template, NULL if one device number
|
||||
iot I/O processing routine
|
||||
ini initialization routine
|
||||
|
||||
Interdata I/O uses the following interconnected tables:
|
||||
|
||||
dev_tab[dev] Indexed by device number, points to the I/O instruction
|
||||
processing routine for the device.
|
||||
dev_tab[dev] Indexed by device number, points to the I/O instruction
|
||||
processing routine for the device.
|
||||
|
||||
sch_tab[dev] Indexed by device number, if non-zero, the number + 1
|
||||
of the selector channel used by the device.
|
||||
sch_tab[dev] Indexed by device number, if non-zero, the number + 1
|
||||
of the selector channel used by the device.
|
||||
|
||||
int_req[level] Indexed by interrupt level, device interrupt flags.
|
||||
int_req[level] Indexed by interrupt level, device interrupt flags.
|
||||
|
||||
int_enb[level] Indexed by interrupt level, device interrupt enable flags.
|
||||
int_enb[level] Indexed by interrupt level, device interrupt enable flags.
|
||||
|
||||
int_tab[idx] Indexed by ((interrupt level * 32) + interrupt number),
|
||||
maps bit positions in int_req to device numbers.
|
||||
int_tab[idx] Indexed by ((interrupt level * 32) + interrupt number),
|
||||
maps bit positions in int_req to device numbers.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
/* Selector channel */
|
||||
|
||||
#define SCHC_EXA 0x40 /* read ext addr */
|
||||
#define SCHC_RD 0x20 /* read */
|
||||
#define SCHC_GO 0x10 /* go */
|
||||
#define SCHC_STOP 0x08 /* stop */
|
||||
#define SCHC_SSTA 0x04 /* sel ch status */
|
||||
#define SCHC_EXM 0x03 /* ext mem */
|
||||
#define SCHC_EXA 0x40 /* read ext addr */
|
||||
#define SCHC_RD 0x20 /* read */
|
||||
#define SCHC_GO 0x10 /* go */
|
||||
#define SCHC_STOP 0x08 /* stop */
|
||||
#define SCHC_SSTA 0x04 /* sel ch status */
|
||||
#define SCHC_EXM 0x03 /* ext mem */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
extern uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout);
|
||||
@@ -68,29 +68,29 @@ extern UNIT cpu_unit;
|
||||
extern FILE *sim_log;
|
||||
extern DEVICE *sim_devices[];
|
||||
|
||||
uint32 sch_max = 2; /* sch count */
|
||||
uint32 sch_sa[SCH_NUMCH] = { 0 }; /* start addr */
|
||||
uint32 sch_ea[SCH_NUMCH] = { 0 }; /* end addr */
|
||||
uint8 sch_sdv[SCH_NUMCH] = { 0 }; /* device */
|
||||
uint8 sch_cmd[SCH_NUMCH] = { 0 }; /* command */
|
||||
uint8 sch_rdp[SCH_NUMCH] = { 0 }; /* read ptr */
|
||||
uint8 sch_wdc[SCH_NUMCH] = { 0 }; /* write ctr */
|
||||
uint32 sch_tab[DEVNO] = { 0 }; /* dev to sch map */
|
||||
uint32 int_tab[INTSZ * 32] = { 0 }; /* int to dev map */
|
||||
uint8 sch_tplte[SCH_NUMCH + 1]; /* dnum template */
|
||||
uint32 sch_max = 2; /* sch count */
|
||||
uint32 sch_sa[SCH_NUMCH] = { 0 }; /* start addr */
|
||||
uint32 sch_ea[SCH_NUMCH] = { 0 }; /* end addr */
|
||||
uint8 sch_sdv[SCH_NUMCH] = { 0 }; /* device */
|
||||
uint8 sch_cmd[SCH_NUMCH] = { 0 }; /* command */
|
||||
uint8 sch_rdp[SCH_NUMCH] = { 0 }; /* read ptr */
|
||||
uint8 sch_wdc[SCH_NUMCH] = { 0 }; /* write ctr */
|
||||
uint32 sch_tab[DEVNO] = { 0 }; /* dev to sch map */
|
||||
uint32 int_tab[INTSZ * 32] = { 0 }; /* int to dev map */
|
||||
uint8 sch_tplte[SCH_NUMCH + 1]; /* dnum template */
|
||||
|
||||
uint32 sch (uint32 dev, uint32 op, uint32 dat);
|
||||
void sch_ini (t_bool dtpl);
|
||||
t_stat sch_reset (DEVICE *dptr);
|
||||
t_stat sch_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
|
||||
/* Selector channel data structures
|
||||
|
||||
sch_dev channel device descriptor
|
||||
sch_unit channel unit descriptor
|
||||
sch_mod channel modifiers list
|
||||
sch_reg channel register list
|
||||
sch_dev channel device descriptor
|
||||
sch_unit channel unit descriptor
|
||||
sch_mod channel modifiers list
|
||||
sch_reg channel register list
|
||||
*/
|
||||
|
||||
DIB sch_dib = { d_SCH, -1, v_SCH, sch_tplte, &sch, &sch_ini };
|
||||
@@ -98,115 +98,133 @@ DIB sch_dib = { d_SCH, -1, v_SCH, sch_tplte, &sch, &sch_ini };
|
||||
UNIT sch_unit = { UDATA (NULL, 0, 0) };
|
||||
|
||||
REG sch_reg[] = {
|
||||
{ HRDATA (CHAN, sch_max, 3), REG_HRO },
|
||||
{ BRDATA (SA, sch_sa, 16, 20, SCH_NUMCH) },
|
||||
{ BRDATA (EA, sch_ea, 16, 20, SCH_NUMCH) },
|
||||
{ BRDATA (CMD, sch_cmd, 16, 8, SCH_NUMCH) },
|
||||
{ BRDATA (DEV, sch_sdv, 16, 8, SCH_NUMCH) },
|
||||
{ BRDATA (RDP, sch_rdp, 16, 2, SCH_NUMCH) },
|
||||
{ BRDATA (WDC, sch_wdc, 16, 3, SCH_NUMCH) },
|
||||
{ GRDATA (IREQ, int_req[l_SCH], 16, SCH_NUMCH, i_SCH) },
|
||||
{ GRDATA (IENB, int_enb[l_SCH], 16, SCH_NUMCH, i_SCH) },
|
||||
{ HRDATA (DEVNO, sch_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
{ HRDATA (CHAN, sch_max, 3), REG_HRO },
|
||||
{ BRDATA (SA, sch_sa, 16, 20, SCH_NUMCH) },
|
||||
{ BRDATA (EA, sch_ea, 16, 20, SCH_NUMCH) },
|
||||
{ BRDATA (CMD, sch_cmd, 16, 8, SCH_NUMCH) },
|
||||
{ BRDATA (DEV, sch_sdv, 16, 8, SCH_NUMCH) },
|
||||
{ BRDATA (RDP, sch_rdp, 16, 2, SCH_NUMCH) },
|
||||
{ BRDATA (WDC, sch_wdc, 16, 3, SCH_NUMCH) },
|
||||
{ GRDATA (IREQ, int_req[l_SCH], 16, SCH_NUMCH, i_SCH) },
|
||||
{ GRDATA (IENB, int_enb[l_SCH], 16, SCH_NUMCH, i_SCH) },
|
||||
{ HRDATA (DEVNO, sch_dib.dno, 8), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB sch_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS",
|
||||
&sch_set_nchan, NULL, &sch_reg[0] },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "0", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "1", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "2", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "3", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, &sch_dib },
|
||||
{ 0 } };
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS",
|
||||
&sch_set_nchan, NULL, &sch_reg[0] },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "0", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "1", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "2", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "3", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, &sch_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE sch_dev = {
|
||||
"SELCH", &sch_unit, sch_reg, sch_mod,
|
||||
1, 16, 8, 1, 16, 8,
|
||||
NULL, NULL, &sch_reset,
|
||||
NULL, NULL, NULL,
|
||||
&sch_dib, 0 };
|
||||
|
||||
"SELCH", &sch_unit, sch_reg, sch_mod,
|
||||
1, 16, 8, 1, 16, 8,
|
||||
NULL, NULL, &sch_reset,
|
||||
NULL, NULL, NULL,
|
||||
&sch_dib, 0
|
||||
};
|
||||
|
||||
/* (Extended) selector channel
|
||||
|
||||
There are really three different selector channels:
|
||||
- 16b selector channel (max 4B of data)
|
||||
- 18b selector channel (max 4B of data)
|
||||
- 20b selector channel (max 6B of data)
|
||||
- 16b selector channel (max 4B of data)
|
||||
- 18b selector channel (max 4B of data)
|
||||
- 20b selector channel (max 6B of data)
|
||||
The algorithm for loading the start and end addresses is taken
|
||||
from the maintenance manual for the Extended Selector Channel.
|
||||
*/
|
||||
|
||||
#define SCH_EXR(ch) ((sch_cmd[ch] & SCHC_EXA) && (pawidth == PAWIDTH32))
|
||||
#define SCH_EXR(ch) ((sch_cmd[ch] & SCHC_EXA) && (pawidth == PAWIDTH32))
|
||||
|
||||
uint32 sch (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 t, bank, sdv, ch = dev - sch_dib.dno;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read data */
|
||||
t = (sch_sa[ch] >> (sch_rdp[ch] * 8)) & DMASK8; /* get sa byte */
|
||||
if (sch_rdp[ch] == 0) sch_rdp[ch] = /* wrap? */
|
||||
SCH_EXR (ch)? 2: 1;
|
||||
else sch_rdp[ch] = sch_rdp[ch] - 1; /* dec byte ptr */
|
||||
return t;
|
||||
case IO_WD: /* write data */
|
||||
if (pawidth != PAWIDTH32) { /* 16b? max 4 */
|
||||
if (sch_wdc[ch] >= 4) break; /* stop at 4 */
|
||||
sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea to sa */
|
||||
(sch_ea[ch] >> 8)) & DMASK16;
|
||||
sch_ea[ch] = ((sch_ea[ch] << 8) | /* ripple ea low */
|
||||
dat) & DMASK16; } /* insert byte */
|
||||
else { /* 32b? max 6 */
|
||||
if (sch_wdc[ch] >= 6) break; /* stop at 6 */
|
||||
if (sch_wdc[ch] != 5) { /* if not last */
|
||||
sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea<15:8> to sa */
|
||||
((sch_ea[ch] >> 8) & DMASK8)) & PAMASK32;
|
||||
sch_ea[ch] = /* ripple ea<7:0> */
|
||||
(((sch_ea[ch] & DMASK8) << 8) | dat) & PAMASK32; }
|
||||
else sch_ea[ch] = ((sch_ea[ch] << 8) | dat) & PAMASK32; }
|
||||
sch_wdc[ch] = sch_wdc[ch] + 1; /* adv sequencer */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
if (sch_cmd[ch] & SCHC_GO) return STA_BSY; /* test busy */
|
||||
if (sch_cmd[ch] & SCHC_SSTA) return 0; /* test sch sta */
|
||||
else {
|
||||
sdv = sch_sdv[ch]; /* get dev */
|
||||
if (dev_tab[sdv] == 0) return CC_V; /* not there? */
|
||||
dev_tab[sdv] (sdv, IO_ADR, 0); /* select dev */
|
||||
t = dev_tab[sdv] (sdv, IO_SS, 0); /* get status */
|
||||
return t & ~STA_BSY; } /* clr busy */
|
||||
case IO_OC: /* command */
|
||||
bank = 0; /* assume no bank */
|
||||
if (pawidth != PAWIDTH32) { /* 16b/18b proc? */
|
||||
dat = dat & ~(SCHC_EXA | SCHC_SSTA); /* clr ext func */
|
||||
if (pawidth == PAWIDTH16E) /* 18b proc? */
|
||||
bank = (dat & SCHC_EXM) << 16; }
|
||||
if (dat & SCHC_STOP) { /* stop? */
|
||||
sch_cmd[ch] = dat & (SCHC_EXA | SCHC_SSTA); /* clr go */
|
||||
CLR_INT (v_SCH + ch); /* clr intr */
|
||||
sch_rdp[ch] = SCH_EXR (ch)? 2: 1; /* init sequencers */
|
||||
sch_wdc[ch] = 0; }
|
||||
else if (dat & SCHC_GO) { /* go? */
|
||||
sch_cmd[ch] = dat & (SCHC_GO | SCHC_RD);
|
||||
if (sch_wdc[ch] <= 4) { /* 4 bytes? */
|
||||
sch_sa[ch] = (sch_sa[ch] & PAMASK16) | bank; /* 16b addr */
|
||||
sch_ea[ch] = (sch_ea[ch] & PAMASK16) | bank; }
|
||||
sch_sa[ch] = sch_sa[ch] & ~1;
|
||||
if (sch_ea[ch] <= sch_sa[ch]) /* wrap? */
|
||||
sch_ea[ch] = sch_ea[ch] | /* modify end addr */
|
||||
((pawidth == PAWIDTH32)? PAMASK32: PAMASK16); }
|
||||
break; }
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_RD: /* read data */
|
||||
t = (sch_sa[ch] >> (sch_rdp[ch] * 8)) & DMASK8; /* get sa byte */
|
||||
if (sch_rdp[ch] == 0) sch_rdp[ch] = /* wrap? */
|
||||
SCH_EXR (ch)? 2: 1;
|
||||
else sch_rdp[ch] = sch_rdp[ch] - 1; /* dec byte ptr */
|
||||
return t;
|
||||
|
||||
case IO_WD: /* write data */
|
||||
if (pawidth != PAWIDTH32) { /* 16b? max 4 */
|
||||
if (sch_wdc[ch] >= 4) break; /* stop at 4 */
|
||||
sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea to sa */
|
||||
(sch_ea[ch] >> 8)) & DMASK16;
|
||||
sch_ea[ch] = ((sch_ea[ch] << 8) | /* ripple ea low */
|
||||
dat) & DMASK16; /* insert byte */
|
||||
}
|
||||
else { /* 32b? max 6 */
|
||||
if (sch_wdc[ch] >= 6) break; /* stop at 6 */
|
||||
if (sch_wdc[ch] != 5) { /* if not last */
|
||||
sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea<15:8> to sa */
|
||||
((sch_ea[ch] >> 8) & DMASK8)) & PAMASK32;
|
||||
sch_ea[ch] = /* ripple ea<7:0> */
|
||||
(((sch_ea[ch] & DMASK8) << 8) | dat) & PAMASK32;
|
||||
}
|
||||
else sch_ea[ch] = ((sch_ea[ch] << 8) | dat) & PAMASK32;
|
||||
}
|
||||
sch_wdc[ch] = sch_wdc[ch] + 1; /* adv sequencer */
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
if (sch_cmd[ch] & SCHC_GO) return STA_BSY; /* test busy */
|
||||
if (sch_cmd[ch] & SCHC_SSTA) return 0; /* test sch sta */
|
||||
else {
|
||||
sdv = sch_sdv[ch]; /* get dev */
|
||||
if (dev_tab[sdv] == 0) return CC_V; /* not there? */
|
||||
dev_tab[sdv] (sdv, IO_ADR, 0); /* select dev */
|
||||
t = dev_tab[sdv] (sdv, IO_SS, 0); /* get status */
|
||||
return t & ~STA_BSY; /* clr busy */
|
||||
}
|
||||
|
||||
case IO_OC: /* command */
|
||||
bank = 0; /* assume no bank */
|
||||
if (pawidth != PAWIDTH32) { /* 16b/18b proc? */
|
||||
dat = dat & ~(SCHC_EXA | SCHC_SSTA); /* clr ext func */
|
||||
if (pawidth == PAWIDTH16E) /* 18b proc? */
|
||||
bank = (dat & SCHC_EXM) << 16;
|
||||
}
|
||||
if (dat & SCHC_STOP) { /* stop? */
|
||||
sch_cmd[ch] = dat & (SCHC_EXA | SCHC_SSTA); /* clr go */
|
||||
CLR_INT (v_SCH + ch); /* clr intr */
|
||||
sch_rdp[ch] = SCH_EXR (ch)? 2: 1; /* init sequencers */
|
||||
sch_wdc[ch] = 0;
|
||||
}
|
||||
else if (dat & SCHC_GO) { /* go? */
|
||||
sch_cmd[ch] = dat & (SCHC_GO | SCHC_RD);
|
||||
if (sch_wdc[ch] <= 4) { /* 4 bytes? */
|
||||
sch_sa[ch] = (sch_sa[ch] & PAMASK16) | bank; /* 16b addr */
|
||||
sch_ea[ch] = (sch_ea[ch] & PAMASK16) | bank;
|
||||
}
|
||||
sch_sa[ch] = sch_sa[ch] & ~1;
|
||||
if (sch_ea[ch] <= sch_sa[ch]) /* wrap? */
|
||||
sch_ea[ch] = sch_ea[ch] | /* modify end addr */
|
||||
((pawidth == PAWIDTH32)? PAMASK32: PAMASK16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* CPU call to test if channel blocks access to device */
|
||||
|
||||
t_bool sch_blk (uint32 dev)
|
||||
@@ -229,10 +247,10 @@ return;
|
||||
|
||||
t_bool sch_actv (uint32 ch, uint32 dev)
|
||||
{
|
||||
if ((ch < sch_max) && /* chan valid, */
|
||||
(sch_cmd[ch] & SCHC_GO) && /* on, and */
|
||||
(sch_sdv[ch] == dev)) return TRUE; /* set for dev? */
|
||||
return FALSE; /* no */
|
||||
if ((ch < sch_max) && /* chan valid, */
|
||||
(sch_cmd[ch] & SCHC_GO) && /* on, and */
|
||||
(sch_sdv[ch] == dev)) return TRUE; /* set for dev? */
|
||||
return FALSE; /* no */
|
||||
}
|
||||
|
||||
/* Device call to read a block of memory */
|
||||
@@ -242,15 +260,16 @@ uint32 sch_rdmem (uint32 ch, uint8 *buf, uint32 cnt)
|
||||
uint32 addr, end, xfr, inc;
|
||||
|
||||
if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0;
|
||||
addr = sch_sa[ch]; /* start */
|
||||
end = sch_ea[ch]; /* end */
|
||||
xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */
|
||||
inc = IOReadBlk (addr, xfr, buf); /* read mem */
|
||||
if ((addr + inc) > end) { /* end? */
|
||||
SET_INT (v_SCH + ch); /* interrupt */
|
||||
sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
|
||||
sch_sa[ch] = sch_sa[ch] + inc - 1; } /* end addr */
|
||||
else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */
|
||||
addr = sch_sa[ch]; /* start */
|
||||
end = sch_ea[ch]; /* end */
|
||||
xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */
|
||||
inc = IOReadBlk (addr, xfr, buf); /* read mem */
|
||||
if ((addr + inc) > end) { /* end? */
|
||||
SET_INT (v_SCH + ch); /* interrupt */
|
||||
sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
|
||||
sch_sa[ch] = sch_sa[ch] + inc - 1; /* end addr */
|
||||
}
|
||||
else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */
|
||||
return inc;
|
||||
}
|
||||
|
||||
@@ -261,15 +280,16 @@ uint32 sch_wrmem (uint32 ch, uint8 *buf, uint32 cnt)
|
||||
uint32 addr, end, xfr, inc;
|
||||
|
||||
if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0;
|
||||
addr = sch_sa[ch]; /* start */
|
||||
end = sch_ea[ch]; /* end */
|
||||
xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */
|
||||
inc = IOWriteBlk (addr, xfr, buf); /* write mem */
|
||||
if ((addr + inc) > end) { /* end? */
|
||||
SET_INT (v_SCH + ch); /* interrupt */
|
||||
sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
|
||||
sch_sa[ch] = sch_sa[ch] + inc - 1; } /* end addr */
|
||||
else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */
|
||||
addr = sch_sa[ch]; /* start */
|
||||
end = sch_ea[ch]; /* end */
|
||||
xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */
|
||||
inc = IOWriteBlk (addr, xfr, buf); /* write mem */
|
||||
if ((addr + inc) > end) { /* end? */
|
||||
SET_INT (v_SCH + ch); /* interrupt */
|
||||
sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
|
||||
sch_sa[ch] = sch_sa[ch] + inc - 1; /* end addr */
|
||||
}
|
||||
else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */
|
||||
return inc;
|
||||
}
|
||||
|
||||
@@ -278,11 +298,12 @@ return inc;
|
||||
void sch_stop (uint32 ch)
|
||||
{
|
||||
if (ch < sch_max) {
|
||||
SET_INT (v_SCH + ch); /* interrupt */
|
||||
sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); } /* clear GO */
|
||||
SET_INT (v_SCH + ch); /* interrupt */
|
||||
sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Reset */
|
||||
|
||||
void sch_reset_ch (uint32 rst_lim)
|
||||
@@ -291,18 +312,20 @@ uint32 ch;
|
||||
|
||||
for (ch = 0; ch < SCH_NUMCH; ch++) {
|
||||
if (ch >= rst_lim) {
|
||||
CLR_INT (v_SCH + ch);
|
||||
SET_ENB (v_SCH + ch);
|
||||
sch_sa[ch] = sch_ea[ch] = 0;
|
||||
sch_cmd[ch] = sch_sdv[ch] = 0;
|
||||
sch_wdc[ch] = 0;
|
||||
sch_rdp[ch] = 1; } }
|
||||
CLR_INT (v_SCH + ch);
|
||||
SET_ENB (v_SCH + ch);
|
||||
sch_sa[ch] = sch_ea[ch] = 0;
|
||||
sch_cmd[ch] = sch_sdv[ch] = 0;
|
||||
sch_wdc[ch] = 0;
|
||||
sch_rdp[ch] = 1;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
t_stat sch_reset (DEVICE *dptr)
|
||||
{
|
||||
sch_reset_ch (0); /* reset all chan */
|
||||
sch_reset_ch (0); /* reset all chan */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -316,20 +339,23 @@ uint32 i, newmax;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
newmax = get_uint (cptr, 10, SCH_NUMCH, &r); /* get new max */
|
||||
if ((r != SCPE_OK) || (newmax == sch_max)) return r; /* err or no chg? */
|
||||
if (newmax == 0) return SCPE_ARG; /* must be > 0 */
|
||||
if (newmax < sch_max) { /* reducing? */
|
||||
for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */
|
||||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||
if (dibp && (dibp->sch >= (int32) newmax)) {/* dev using chan? */
|
||||
printf ("Device %02X uses channel %d\n",
|
||||
dibp->dno, dibp->sch);
|
||||
if (sim_log) fprintf (sim_log, "Device %02X uses channel %d\n",
|
||||
dibp->dno, dibp->sch);
|
||||
return SCPE_OK; } } }
|
||||
sch_max = newmax; /* set new max */
|
||||
sch_reset_ch (sch_max); /* reset chan */
|
||||
newmax = get_uint (cptr, 10, SCH_NUMCH, &r); /* get new max */
|
||||
if ((r != SCPE_OK) || (newmax == sch_max)) return r; /* err or no chg? */
|
||||
if (newmax == 0) return SCPE_ARG; /* must be > 0 */
|
||||
if (newmax < sch_max) { /* reducing? */
|
||||
for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */
|
||||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||
if (dibp && (dibp->sch >= (int32) newmax)) { /* dev using chan? */
|
||||
printf ("Device %02X uses channel %d\n",
|
||||
dibp->dno, dibp->sch);
|
||||
if (sim_log) fprintf (sim_log, "Device %02X uses channel %d\n",
|
||||
dibp->dno, dibp->sch);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
sch_max = newmax; /* set new max */
|
||||
sch_reset_ch (sch_max); /* reset chan */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -339,12 +365,14 @@ t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
if (val < 0) return SCPE_IERR;
|
||||
if (val >= (int32) sch_max) fprintf (st, "Channel %d disabled\n", val);
|
||||
else { fprintf (st, "SA: %05X\n", sch_sa[val]);
|
||||
fprintf (st, "EA: %05X\n", sch_ea[val]);
|
||||
fprintf (st, "CMD: %02X\n", sch_cmd[val]);
|
||||
fprintf (st, "DEV: %02X\n", sch_sdv[val]);
|
||||
fprintf (st, "RDP: %X\n", sch_rdp[val]);
|
||||
fprintf (st, "WDC: %X\n", sch_wdc[val]); }
|
||||
else {
|
||||
fprintf (st, "SA: %05X\n", sch_sa[val]);
|
||||
fprintf (st, "EA: %05X\n", sch_ea[val]);
|
||||
fprintf (st, "CMD: %02X\n", sch_cmd[val]);
|
||||
fprintf (st, "DEV: %02X\n", sch_sdv[val]);
|
||||
fprintf (st, "RDP: %X\n", sch_rdp[val]);
|
||||
fprintf (st, "WDC: %X\n", sch_wdc[val]);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -358,7 +386,7 @@ for (i = 0; i < sch_max; i++) sch_tplte[i] = i;
|
||||
sch_tplte[sch_max] = TPL_END;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Evaluate interrupt */
|
||||
|
||||
void int_eval (void)
|
||||
@@ -366,10 +394,12 @@ void int_eval (void)
|
||||
int i;
|
||||
extern uint32 qevent;
|
||||
|
||||
for (i = 0; i < INTSZ; i++)
|
||||
if (int_req[i] & int_enb[i]) {
|
||||
qevent = qevent | EV_INT;
|
||||
return; }
|
||||
for (i = 0; i < INTSZ; i++) {
|
||||
if (int_req[i] & int_enb[i]) {
|
||||
qevent = qevent | EV_INT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
qevent = qevent & ~EV_INT;
|
||||
return;
|
||||
}
|
||||
@@ -381,13 +411,17 @@ uint32 int_getdev (void)
|
||||
int32 i, j, t;
|
||||
uint32 r;
|
||||
|
||||
for (i = t = 0; i < INTSZ; i++) { /* loop thru array */
|
||||
if (r = int_req[i] & int_enb[i]) { /* find nz int wd */
|
||||
for (j = 0; j < 32; t++, j++) {
|
||||
if (r & (1u << j)) {
|
||||
int_req[i] = int_req[i] & ~(1u << j); /* clr request */
|
||||
return int_tab[t]; } } }
|
||||
else t = t + 32; }
|
||||
for (i = t = 0; i < INTSZ; i++) { /* loop thru array */
|
||||
if (r = int_req[i] & int_enb[i]) { /* find nz int wd */
|
||||
for (j = 0; j < 32; t++, j++) {
|
||||
if (r & (1u << j)) {
|
||||
int_req[i] = int_req[i] & ~(1u << j); /* clr request */
|
||||
return int_tab[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
else t = t + 32;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -395,18 +429,21 @@ return 0;
|
||||
|
||||
int32 int_chg (uint32 irq, int32 dat, int32 armdis)
|
||||
{
|
||||
int32 t = CMD_GETINT (dat); /* get int ctrl */
|
||||
|
||||
if (t == CMD_IENB) { /* enable? */
|
||||
SET_ENB (irq);
|
||||
return 1; }
|
||||
else if (t == CMD_IDIS) { /* disable? */
|
||||
CLR_ENB (irq);
|
||||
return 1; }
|
||||
if (t == CMD_IDSA) { /* disarm? */
|
||||
CLR_ENB (irq);
|
||||
CLR_INT (irq);
|
||||
return 0; }
|
||||
int32 t = CMD_GETINT (dat); /* get int ctrl */
|
||||
|
||||
if (t == CMD_IENB) { /* enable? */
|
||||
SET_ENB (irq);
|
||||
return 1;
|
||||
}
|
||||
else if (t == CMD_IDIS) { /* disable? */
|
||||
CLR_ENB (irq);
|
||||
return 1;
|
||||
}
|
||||
if (t == CMD_IDSA) { /* disarm? */
|
||||
CLR_ENB (irq);
|
||||
CLR_INT (irq);
|
||||
return 0;
|
||||
}
|
||||
return armdis;
|
||||
}
|
||||
|
||||
@@ -442,7 +479,7 @@ if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc;
|
||||
for (i = 0; i < cnt; i++) IOWriteB (loc + i, buf[i]);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
/* Change selector channel for a device */
|
||||
|
||||
t_stat set_sch (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
@@ -458,9 +495,9 @@ dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR;
|
||||
newch = get_uint (cptr, 16, sch_max - 1, &r); /* get new */
|
||||
newch = get_uint (cptr, 16, sch_max - 1, &r); /* get new */
|
||||
if (r != SCPE_OK) return r;
|
||||
dibp->sch = newch; /* store */
|
||||
dibp->sch = newch; /* store */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -495,10 +532,10 @@ dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL) return SCPE_IERR;
|
||||
newdev = get_uint (cptr, 16, DEV_MAX, &r); /* get new */
|
||||
newdev = get_uint (cptr, 16, DEV_MAX, &r); /* get new */
|
||||
if ((r != SCPE_OK) || (newdev == dibp->dno)) return r;
|
||||
if (newdev == 0) return SCPE_ARG; /* must be > 0 */
|
||||
dibp->dno = newdev; /* store */
|
||||
if (newdev == 0) return SCPE_ARG; /* must be > 0 */
|
||||
dibp->dno = newdev; /* store */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -530,38 +567,40 @@ uint8 *tplte, dflt_tplte[] = { 0, TPL_END };
|
||||
/* Clear tables, device map */
|
||||
|
||||
for (i = 0; i < DEVNO; i++) {
|
||||
dev_tab[i] = NULL;
|
||||
sch_tab[i] = 0; }
|
||||
dev_tab[i] = NULL;
|
||||
sch_tab[i] = 0;
|
||||
}
|
||||
for (i = 0; i < (INTSZ * 32); i++) int_tab[i] = 0;
|
||||
for (i = 0; i < (DEVNO / 32); i++) dmap[i] = 0;
|
||||
|
||||
/* Test each device for conflict; add to map; init tables */
|
||||
|
||||
for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */
|
||||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||
if ((dibp == NULL) || (dptr->flags & DEV_DIS)) continue; /* exist, enabled? */
|
||||
dno = dibp->dno; /* get device num */
|
||||
if (dibp->ini) dibp->ini (TRUE); /* gen dno template */
|
||||
tplte = dibp->tplte; /* get template */
|
||||
if (tplte == NULL) tplte = dflt_tplte; /* none? use default */
|
||||
for ( ; *tplte != TPL_END; tplte++) { /* loop thru template */
|
||||
t = (dno + *tplte) & DEV_MAX; /* loop thru template */
|
||||
dmsk = 1u << (t & 0x1F); /* bit to test */
|
||||
doff = t / 32; /* word to test */
|
||||
if (dmap[doff] & dmsk) { /* in use? */
|
||||
printf ("Device number conflict, devno = %02X\n", t);
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"Device number conflict, devno = %02X\n", t);
|
||||
return TRUE; }
|
||||
dmap[doff] = dmap[doff] | dmsk;
|
||||
if (dibp->sch >= 0) sch_tab[t] = dibp->sch + 1;
|
||||
dev_tab[t] = dibp->iot; }
|
||||
|
||||
if (dibp->ini) dibp->ini (FALSE); /* gen int template */
|
||||
tplte = dibp->tplte; /* get template */
|
||||
if (tplte == NULL) tplte = dflt_tplte; /* none? use default */
|
||||
for (j = dibp->irq; *tplte != TPL_END; j++, tplte++) {
|
||||
int_tab[j] = (dno + *tplte) & DEV_MAX; }
|
||||
} /* end for i */
|
||||
for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */
|
||||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||
if ((dibp == NULL) || (dptr->flags & DEV_DIS)) continue; /* exist, enabled? */
|
||||
dno = dibp->dno; /* get device num */
|
||||
if (dibp->ini) dibp->ini (TRUE); /* gen dno template */
|
||||
tplte = dibp->tplte; /* get template */
|
||||
if (tplte == NULL) tplte = dflt_tplte; /* none? use default */
|
||||
for ( ; *tplte != TPL_END; tplte++) { /* loop thru template */
|
||||
t = (dno + *tplte) & DEV_MAX; /* loop thru template */
|
||||
dmsk = 1u << (t & 0x1F); /* bit to test */
|
||||
doff = t / 32; /* word to test */
|
||||
if (dmap[doff] & dmsk) { /* in use? */
|
||||
printf ("Device number conflict, devno = %02X\n", t);
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"Device number conflict, devno = %02X\n", t);
|
||||
return TRUE;
|
||||
}
|
||||
dmap[doff] = dmap[doff] | dmsk;
|
||||
if (dibp->sch >= 0) sch_tab[t] = dibp->sch + 1;
|
||||
dev_tab[t] = dibp->iot;
|
||||
}
|
||||
if (dibp->ini) dibp->ini (FALSE); /* gen int template */
|
||||
tplte = dibp->tplte; /* get template */
|
||||
if (tplte == NULL) tplte = dflt_tplte; /* none? use default */
|
||||
for (j = dibp->irq; *tplte != TPL_END; j++, tplte++)
|
||||
int_tab[j] = (dno + *tplte) & DEV_MAX;
|
||||
} /* end for i */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id_lp.c: Interdata line printer
|
||||
|
||||
Copyright (c) 2001-2004, Robert M. Supnik
|
||||
Copyright (c) 2001-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,13 +19,13 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
lpt M46-206 line printer
|
||||
lpt M46-206 line printer
|
||||
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
@@ -33,35 +33,35 @@
|
||||
|
||||
/* Device definitions */
|
||||
|
||||
#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
#define SPC_BASE 0x40 /* spacing base */
|
||||
#define VFU_BASE 0x78 /* VFU base */
|
||||
#define VFU_WIDTH 0x8 /* VFU width */
|
||||
#define LF 0xA
|
||||
#define VT 0xB
|
||||
#define VT_VFU 4 /* VFU chan for VT */
|
||||
#define FF 0xC
|
||||
#define FF_VFU 8 /* VFU chan for FF */
|
||||
#define CR 0xD
|
||||
#define VFUP(ch,val) ((val) & (1 << (ch))) /* VFU chan test */
|
||||
#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
#define SPC_BASE 0x40 /* spacing base */
|
||||
#define VFU_BASE 0x78 /* VFU base */
|
||||
#define VFU_WIDTH 0x8 /* VFU width */
|
||||
#define LF 0xA
|
||||
#define VT 0xB
|
||||
#define VT_VFU 4 /* VFU chan for VT */
|
||||
#define FF 0xC
|
||||
#define FF_VFU 8 /* VFU chan for FF */
|
||||
#define CR 0xD
|
||||
#define VFUP(ch,val) ((val) & (1 << (ch))) /* VFU chan test */
|
||||
|
||||
/* Status byte, * = dynamic */
|
||||
|
||||
#define STA_PAPE 0x40 /* *paper empty */
|
||||
#define STA_MASK (STA_BSY) /* static status */
|
||||
#define STA_PAPE 0x40 /* *paper empty */
|
||||
#define STA_MASK (STA_BSY) /* static status */
|
||||
|
||||
uint32 lpt_sta = STA_BSY; /* status */
|
||||
char lpxb[LPT_WIDTH + 1]; /* line buffer */
|
||||
uint32 lpt_bptr = 0; /* buf ptr */
|
||||
uint32 lpt_spnd = 0; /* space pending */
|
||||
uint32 lpt_vfup = 0; /* VFU ptr */
|
||||
uint32 lpt_vful = 1; /* VFU lnt */
|
||||
uint8 lpt_vfut[VFU_LNT] = { 0xFF }; /* VFU tape */
|
||||
uint32 lpt_arm = 0; /* int armed */
|
||||
int32 lpt_ctime = 10; /* char time */
|
||||
int32 lpt_stime = 1000; /* space time */
|
||||
int32 lpt_stopioe = 0; /* stop on err */
|
||||
uint32 lpt_sta = STA_BSY; /* status */
|
||||
char lpxb[LPT_WIDTH + 1]; /* line buffer */
|
||||
uint32 lpt_bptr = 0; /* buf ptr */
|
||||
uint32 lpt_spnd = 0; /* space pending */
|
||||
uint32 lpt_vfup = 0; /* VFU ptr */
|
||||
uint32 lpt_vful = 1; /* VFU lnt */
|
||||
uint8 lpt_vfut[VFU_LNT] = { 0xFF }; /* VFU tape */
|
||||
uint32 lpt_arm = 0; /* int armed */
|
||||
int32 lpt_ctime = 10; /* char time */
|
||||
int32 lpt_stime = 1000; /* space time */
|
||||
int32 lpt_stopioe = 0; /* stop on err */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
@@ -73,12 +73,12 @@ t_stat lpt_attach (UNIT *uptr, char *cptr);
|
||||
t_stat lpt_bufout (UNIT *uptr);
|
||||
t_stat lpt_vfu (UNIT *uptr, int32 ch);
|
||||
t_stat lpt_spc (UNIT *uptr, int32 cnt);
|
||||
|
||||
|
||||
/* LPT data structures
|
||||
|
||||
lpt_dev LPT device descriptor
|
||||
lpt_unit LPT unit descriptors
|
||||
lpt_reg LPT register list
|
||||
lpt_dev LPT device descriptor
|
||||
lpt_unit LPT unit descriptors
|
||||
lpt_reg LPT register list
|
||||
*/
|
||||
|
||||
DIB lpt_dib = { d_LPT, -1, v_LPT, NULL, &lpt, NULL };
|
||||
@@ -86,61 +86,70 @@ DIB lpt_dib = { d_LPT, -1, v_LPT, NULL, &lpt, NULL };
|
||||
UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_UC, 0) };
|
||||
|
||||
REG lpt_reg[] = {
|
||||
{ HRDATA (STA, lpt_sta, 8) },
|
||||
{ HRDATA (BUF, lpt_unit.buf, 7) },
|
||||
{ BRDATA (DBUF, lpxb, 16, 7, LPT_WIDTH) },
|
||||
{ HRDATA (DBPTR, lpt_bptr, 8) },
|
||||
{ HRDATA (VFUP, lpt_vfup, 8) },
|
||||
{ HRDATA (VFUL, lpt_vful, 8) },
|
||||
{ BRDATA (VFUT, lpt_vfut, 16, 8, VFU_LNT) },
|
||||
{ FLDATA (IREQ, int_req[l_LPT], i_LPT) },
|
||||
{ FLDATA (IENB, int_enb[l_LPT], i_LPT) },
|
||||
{ FLDATA (IARM, lpt_arm, 0) },
|
||||
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (CTIME, lpt_ctime, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, lpt_stime, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
|
||||
{ HRDATA (DEVNO, lpt_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
{ HRDATA (STA, lpt_sta, 8) },
|
||||
{ HRDATA (BUF, lpt_unit.buf, 7) },
|
||||
{ BRDATA (DBUF, lpxb, 16, 7, LPT_WIDTH) },
|
||||
{ HRDATA (DBPTR, lpt_bptr, 8) },
|
||||
{ HRDATA (VFUP, lpt_vfup, 8) },
|
||||
{ HRDATA (VFUL, lpt_vful, 8) },
|
||||
{ BRDATA (VFUT, lpt_vfut, 16, 8, VFU_LNT) },
|
||||
{ FLDATA (IREQ, int_req[l_LPT], i_LPT) },
|
||||
{ FLDATA (IENB, int_enb[l_LPT], i_LPT) },
|
||||
{ FLDATA (IARM, lpt_arm, 0) },
|
||||
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (CTIME, lpt_ctime, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, lpt_stime, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
|
||||
{ HRDATA (DEVNO, lpt_dib.dno, 8), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB lpt_mod[] = {
|
||||
{ UNIT_UC, 0, "lower case", "LC", NULL },
|
||||
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_UC, 0, "lower case", "LC", NULL },
|
||||
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE lpt_dev = {
|
||||
"LPT", &lpt_unit, lpt_reg, lpt_mod,
|
||||
1, 10, 31, 1, 16, 7,
|
||||
NULL, NULL, &lpt_reset,
|
||||
NULL, &lpt_attach, NULL,
|
||||
&lpt_dib, DEV_DISABLE };
|
||||
|
||||
"LPT", &lpt_unit, lpt_reg, lpt_mod,
|
||||
1, 10, 31, 1, 16, 7,
|
||||
NULL, NULL, &lpt_reset,
|
||||
NULL, &lpt_attach, NULL,
|
||||
&lpt_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* Line printer: IO routine */
|
||||
|
||||
uint32 lpt (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_OC: /* command */
|
||||
lpt_arm = int_chg (v_LPT, dat, lpt_arm); /* upd int ctrl */
|
||||
break;
|
||||
case IO_WD: /* write */
|
||||
t = lpt_unit.buf = dat & 0x7F; /* mask char */
|
||||
lpt_sta = STA_BSY; /* set busy */
|
||||
if (lpt_spnd || ((t >= LF) && (t <= CR))) /* space op? */
|
||||
sim_activate (&lpt_unit, lpt_stime);
|
||||
else sim_activate (&lpt_unit, lpt_ctime); /* normal char */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = lpt_sta & STA_MASK; /* status byte */
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* test paper out */
|
||||
t = t | STA_EX | STA_PAPE | STA_BSY;
|
||||
return t; }
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_OC: /* command */
|
||||
lpt_arm = int_chg (v_LPT, dat, lpt_arm); /* upd int ctrl */
|
||||
break;
|
||||
|
||||
case IO_WD: /* write */
|
||||
t = lpt_unit.buf = dat & 0x7F; /* mask char */
|
||||
lpt_sta = STA_BSY; /* set busy */
|
||||
if (lpt_spnd || ((t >= LF) && (t <= CR))) /* space op? */
|
||||
sim_activate (&lpt_unit, lpt_stime);
|
||||
else sim_activate (&lpt_unit, lpt_ctime); /* normal char */
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
t = lpt_sta & STA_MASK; /* status byte */
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* test paper out */
|
||||
t = t | STA_EX | STA_PAPE | STA_BSY;
|
||||
return t;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -151,37 +160,41 @@ t_stat lpt_svc (UNIT *uptr)
|
||||
int32 t;
|
||||
t_stat r = SCPE_OK;
|
||||
|
||||
lpt_sta = 0; /* clear busy */
|
||||
if (lpt_arm) SET_INT (v_LPT); /* armed? intr */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
t = uptr->buf; /* get character */
|
||||
if (lpt_spnd || ((t >= LF) && (t < CR))) { /* spc pend or spc op? */
|
||||
lpt_spnd = 0;
|
||||
if (lpt_bufout (uptr) != SCPE_OK) return SCPE_IOERR; /* print */
|
||||
if ((t == 1) || (t == LF)) lpt_spc (uptr, 1); /* single space */
|
||||
else if (t == VT) r = lpt_vfu (uptr, VT_VFU - 1); /* VT->VFU */
|
||||
else if (t == 0xC) r = lpt_vfu (uptr, FF_VFU - 1); /* FF->VFU */
|
||||
else if ((t >= SPC_BASE) && (t < VFU_BASE))
|
||||
lpt_spc (uptr, t - SPC_BASE); /* space */
|
||||
else if ((t >= VFU_BASE) && (t < VFU_BASE + VFU_WIDTH))
|
||||
r = lpt_vfu (uptr, t - VFU_BASE); /* VFU */
|
||||
else fputs ("\r", uptr->fileref); /* overprint */
|
||||
uptr->pos = ftell (uptr->fileref); /* update position */
|
||||
if (ferror (lpt_unit.fileref)) {
|
||||
perror ("LPT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; } }
|
||||
else if (t == CR) { /* CR? */
|
||||
lpt_spnd = 1; /* set spc pend */
|
||||
return lpt_bufout (uptr); } /* print line */
|
||||
else if (t >= 0x40) { /* printable? */
|
||||
if ((uptr->flags & UNIT_UC) && islower (t)) /* UC only? */
|
||||
t = toupper (t);
|
||||
if (lpt_bptr < LPT_WIDTH) lpxb[lpt_bptr++] = t; }
|
||||
lpt_sta = 0; /* clear busy */
|
||||
if (lpt_arm) SET_INT (v_LPT); /* armed? intr */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
t = uptr->buf; /* get character */
|
||||
if (lpt_spnd || ((t >= LF) && (t < CR))) { /* spc pend or spc op? */
|
||||
lpt_spnd = 0;
|
||||
if (lpt_bufout (uptr) != SCPE_OK) return SCPE_IOERR; /* print */
|
||||
if ((t == 1) || (t == LF)) lpt_spc (uptr, 1); /* single space */
|
||||
else if (t == VT) r = lpt_vfu (uptr, VT_VFU - 1); /* VT->VFU */
|
||||
else if (t == 0xC) r = lpt_vfu (uptr, FF_VFU - 1); /* FF->VFU */
|
||||
else if ((t >= SPC_BASE) && (t < VFU_BASE))
|
||||
lpt_spc (uptr, t - SPC_BASE); /* space */
|
||||
else if ((t >= VFU_BASE) && (t < VFU_BASE + VFU_WIDTH))
|
||||
r = lpt_vfu (uptr, t - VFU_BASE); /* VFU */
|
||||
else fputs ("\r", uptr->fileref); /* overprint */
|
||||
uptr->pos = ftell (uptr->fileref); /* update position */
|
||||
if (ferror (lpt_unit.fileref)) {
|
||||
perror ("LPT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
}
|
||||
else if (t == CR) { /* CR? */
|
||||
lpt_spnd = 1; /* set spc pend */
|
||||
return lpt_bufout (uptr); /* print line */
|
||||
}
|
||||
else if (t >= 0x40) { /* printable? */
|
||||
if ((uptr->flags & UNIT_UC) && islower (t)) /* UC only? */
|
||||
t = toupper (t);
|
||||
if (lpt_bptr < LPT_WIDTH) lpxb[lpt_bptr++] = t;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Printing and spacing routines */
|
||||
|
||||
t_stat lpt_bufout (UNIT *uptr)
|
||||
@@ -189,17 +202,19 @@ t_stat lpt_bufout (UNIT *uptr)
|
||||
int32 i;
|
||||
t_stat r = SCPE_OK;
|
||||
|
||||
if (lpt_bptr == 0) return SCPE_OK; /* any char in buf? */
|
||||
if (lpt_bptr == 0) return SCPE_OK; /* any char in buf? */
|
||||
for (i = LPT_WIDTH - 1; (i >= 0) && (lpxb[i] == ' '); i--)
|
||||
lpxb[i] = 0; /* backscan line */
|
||||
if (lpxb[0]) { /* any char left? */
|
||||
fputs (lpxb, uptr->fileref); /* write line */
|
||||
lpt_unit.pos = ftell (uptr->fileref); /* update position */
|
||||
if (ferror (uptr->fileref)) {
|
||||
perror ("LPT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
r = SCPE_IOERR; } }
|
||||
lpt_bptr = 0; /* reset buffer */
|
||||
lpxb[i] = 0; /* backscan line */
|
||||
if (lpxb[0]) { /* any char left? */
|
||||
fputs (lpxb, uptr->fileref); /* write line */
|
||||
lpt_unit.pos = ftell (uptr->fileref); /* update position */
|
||||
if (ferror (uptr->fileref)) {
|
||||
perror ("LPT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
r = SCPE_IOERR;
|
||||
}
|
||||
}
|
||||
lpt_bptr = 0; /* reset buffer */
|
||||
for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' ';
|
||||
lpxb[LPT_WIDTH] = 0;
|
||||
return r;
|
||||
@@ -209,16 +224,19 @@ t_stat lpt_vfu (UNIT *uptr, int32 ch)
|
||||
{
|
||||
uint32 i, j;
|
||||
|
||||
if ((ch == (FF_VFU - 1)) && VFUP (ch, lpt_vfut[0])) { /* top of form? */
|
||||
fputs ("\n\f", uptr->fileref); /* nl + ff */
|
||||
lpt_vfup = 0; /* top of page */
|
||||
return SCPE_OK; }
|
||||
for (i = 1; i < lpt_vful + 1; i++) { /* sweep thru cct */
|
||||
lpt_vfup = (lpt_vfup + 1) % lpt_vful; /* adv pointer */
|
||||
if (VFUP (ch, lpt_vfut[lpt_vfup])) { /* chan punched? */
|
||||
for (j = 0; j < i; j++) fputc ('\n', uptr->fileref);
|
||||
return SCPE_OK; } }
|
||||
return STOP_VFU; /* runaway channel */
|
||||
if ((ch == (FF_VFU - 1)) && VFUP (ch, lpt_vfut[0])) { /* top of form? */
|
||||
fputs ("\n\f", uptr->fileref); /* nl + ff */
|
||||
lpt_vfup = 0; /* top of page */
|
||||
return SCPE_OK;
|
||||
}
|
||||
for (i = 1; i < lpt_vful + 1; i++) { /* sweep thru cct */
|
||||
lpt_vfup = (lpt_vfup + 1) % lpt_vful; /* adv pointer */
|
||||
if (VFUP (ch, lpt_vfut[lpt_vfup])) { /* chan punched? */
|
||||
for (j = 0; j < i; j++) fputc ('\n', uptr->fileref);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
return STOP_VFU; /* runaway channel */
|
||||
}
|
||||
|
||||
t_stat lpt_spc (UNIT *uptr, int32 cnt)
|
||||
@@ -226,25 +244,27 @@ t_stat lpt_spc (UNIT *uptr, int32 cnt)
|
||||
int32 i;
|
||||
|
||||
if (cnt == 0) fputc ('\r', uptr->fileref);
|
||||
else { for (i = 0; i < cnt; i++) fputc ('\n', uptr->fileref);
|
||||
lpt_vfup = (lpt_vfup + cnt) % lpt_vful; }
|
||||
else {
|
||||
for (i = 0; i < cnt; i++) fputc ('\n', uptr->fileref);
|
||||
lpt_vfup = (lpt_vfup + cnt) % lpt_vful;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat lpt_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
sim_cancel (&lpt_unit); /* deactivate */
|
||||
lpt_sta = 0; /* clr busy */
|
||||
lpt_bptr = 0; /* clr buf ptr */
|
||||
for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' '; /* clr buf */
|
||||
sim_cancel (&lpt_unit); /* deactivate */
|
||||
lpt_sta = 0; /* clr busy */
|
||||
lpt_bptr = 0; /* clr buf ptr */
|
||||
for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' '; /* clr buf */
|
||||
lpxb[LPT_WIDTH] = 0;
|
||||
CLR_INT (v_LPT); /* clearr int */
|
||||
CLR_ENB (v_LPT); /* disable int */
|
||||
lpt_arm = 0; /* disarm int */
|
||||
CLR_INT (v_LPT); /* clearr int */
|
||||
CLR_ENB (v_LPT); /* disable int */
|
||||
lpt_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -252,7 +272,7 @@ return SCPE_OK;
|
||||
|
||||
t_stat lpt_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
lpt_vfup = 0; /* top of form */
|
||||
lpt_vfup = 0; /* top of form */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
@@ -267,21 +287,25 @@ char cbuf[CBUFSIZE], gbuf[CBUFSIZE];
|
||||
|
||||
if (*cptr != 0) return SCPE_ARG;
|
||||
ptr = 0;
|
||||
for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */
|
||||
mask = 0;
|
||||
if (*cptr == '(') { /* repeat count? */
|
||||
cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */
|
||||
rpt = get_uint (gbuf, 10, VFU_LNT, &r); /* repeat count */
|
||||
if (r != SCPE_OK) return SCPE_FMT; }
|
||||
else rpt = 1;
|
||||
while (*cptr != 0) { /* get col no's */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
|
||||
col = get_uint (gbuf, 10, 7, &r); /* column number */
|
||||
if (r != SCPE_OK) return SCPE_FMT;
|
||||
mask = mask | (1 << col); } /* set bit */
|
||||
for ( ; rpt > 0; rpt--) { /* store vals */
|
||||
if (ptr >= VFU_LNT) return SCPE_FMT;
|
||||
vfubuf[ptr++] = mask; } }
|
||||
for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */
|
||||
mask = 0;
|
||||
if (*cptr == '(') { /* repeat count? */
|
||||
cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */
|
||||
rpt = get_uint (gbuf, 10, VFU_LNT, &r); /* repeat count */
|
||||
if (r != SCPE_OK) return SCPE_FMT;
|
||||
}
|
||||
else rpt = 1;
|
||||
while (*cptr != 0) { /* get col no's */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
|
||||
col = get_uint (gbuf, 10, 7, &r); /* column number */
|
||||
if (r != SCPE_OK) return SCPE_FMT;
|
||||
mask = mask | (1 << col); /* set bit */
|
||||
}
|
||||
for ( ; rpt > 0; rpt--) { /* store vals */
|
||||
if (ptr >= VFU_LNT) return SCPE_FMT;
|
||||
vfubuf[ptr++] = mask;
|
||||
}
|
||||
}
|
||||
if (ptr == 0) return SCPE_FMT;
|
||||
lpt_vful = ptr;
|
||||
lpt_vfup = 0;
|
||||
|
||||
@@ -19,29 +19,29 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
mt M46-494 dual density 9-track magtape controller
|
||||
mt M46-494 dual density 9-track magtape controller
|
||||
|
||||
18-Mar-05 RMS Added attached test to detach routine
|
||||
07-Dec-04 RMS Added read-only file support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Mar-03 RMS Added multiformat support
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
20-Feb-03 RMS Fixed read to stop selch on error
|
||||
18-Mar-05 RMS Added attached test to detach routine
|
||||
07-Dec-04 RMS Added read-only file support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Mar-03 RMS Added multiformat support
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
20-Feb-03 RMS Fixed read to stop selch on error
|
||||
|
||||
Magnetic tapes are represented as a series of variable 8b records
|
||||
of the form:
|
||||
|
||||
32b record length in bytes - exact number
|
||||
byte 0
|
||||
byte 1
|
||||
:
|
||||
byte n-2
|
||||
byte n-1
|
||||
32b record length in bytes - exact number
|
||||
32b record length in bytes - exact number
|
||||
byte 0
|
||||
byte 1
|
||||
:
|
||||
byte n-2
|
||||
byte n-1
|
||||
32b record length in bytes - exact number
|
||||
|
||||
If the byte count is odd, the record is padded with an extra byte
|
||||
of junk. File marks are represented by a single record length of 0.
|
||||
@@ -51,53 +51,54 @@
|
||||
#include "id_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define UST u3 /* unit status */
|
||||
#define UCMD u4 /* unit command */
|
||||
#define MT_MAXFR (1 << 16) /* max transfer */
|
||||
#define UST u3 /* unit status */
|
||||
#define UCMD u4 /* unit command */
|
||||
#define MT_MAXFR (1 << 16) /* max transfer */
|
||||
|
||||
/* Command - in UCMD */
|
||||
|
||||
#define MTC_SPCR 0x11 /* backspace */
|
||||
#define MTC_SKFR 0x13 /* space file rev */
|
||||
#define MTC_CLR 0x20 /* clear */
|
||||
#define MTC_RD 0x21 /* read */
|
||||
#define MTC_WR 0x22 /* write */
|
||||
#define MTC_SKFF 0x23 /* space file fwd */
|
||||
#define MTC_WEOF 0x30 /* write eof */
|
||||
#define MTC_REW 0x38 /* rewind */
|
||||
#define MTC_MASK 0x3F
|
||||
#define MTC_STOP1 0x40 /* stop, set EOM */
|
||||
#define MTC_STOP2 0x80 /* stop, set NMTN */
|
||||
#define MTC_SPCR 0x11 /* backspace */
|
||||
#define MTC_SKFR 0x13 /* space file rev */
|
||||
#define MTC_CLR 0x20 /* clear */
|
||||
#define MTC_RD 0x21 /* read */
|
||||
#define MTC_WR 0x22 /* write */
|
||||
#define MTC_SKFF 0x23 /* space file fwd */
|
||||
#define MTC_WEOF 0x30 /* write eof */
|
||||
#define MTC_REW 0x38 /* rewind */
|
||||
#define MTC_MASK 0x3F
|
||||
#define MTC_STOP1 0x40 /* stop, set EOM */
|
||||
#define MTC_STOP2 0x80 /* stop, set NMTN */
|
||||
|
||||
/* Status byte, * = in UST */
|
||||
|
||||
#define STA_ERR 0x80 /* error */
|
||||
#define STA_EOF 0x40 /* end of file */
|
||||
#define STA_EOT 0x20 /* *end of tape */
|
||||
#define STA_NMTN 0x10 /* *no motion */
|
||||
#define STA_UFLGS (STA_EOT|STA_NMTN) /* unit flags */
|
||||
#define STA_MASK (STA_ERR|STA_EOF|STA_BSY|STA_EOM)
|
||||
#define SET_EX (STA_ERR|STA_EOF|STA_NMTN)
|
||||
|
||||
#define STA_ERR 0x80 /* error */
|
||||
#define STA_EOF 0x40 /* end of file */
|
||||
#define STA_EOT 0x20 /* *end of tape */
|
||||
#define STA_NMTN 0x10 /* *no motion */
|
||||
#define STA_UFLGS (STA_EOT|STA_NMTN) /* unit flags */
|
||||
#define STA_MASK (STA_ERR|STA_EOF|STA_BSY|STA_EOM)
|
||||
#define SET_EX (STA_ERR|STA_EOF|STA_NMTN)
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint8 mtxb[MT_MAXFR]; /* xfer buffer */
|
||||
uint32 mt_bptr = 0; /* pointer */
|
||||
uint32 mt_blnt = 0; /* length */
|
||||
uint32 mt_sta = 0; /* status byte */
|
||||
uint32 mt_db = 0; /* data buffer */
|
||||
uint32 mt_xfr = 0; /* data xfr in prog */
|
||||
uint32 mt_arm[MT_NUMDR] = { 0 }; /* intr armed */
|
||||
int32 mt_wtime = 10; /* byte latency */
|
||||
int32 mt_rtime = 1000; /* record latency */
|
||||
int32 mt_stopioe = 1; /* stop on error */
|
||||
uint8 mtxb[MT_MAXFR]; /* xfer buffer */
|
||||
uint32 mt_bptr = 0; /* pointer */
|
||||
uint32 mt_blnt = 0; /* length */
|
||||
uint32 mt_sta = 0; /* status byte */
|
||||
uint32 mt_db = 0; /* data buffer */
|
||||
uint32 mt_xfr = 0; /* data xfr in prog */
|
||||
uint32 mt_arm[MT_NUMDR] = { 0 }; /* intr armed */
|
||||
int32 mt_wtime = 10; /* byte latency */
|
||||
int32 mt_rtime = 1000; /* record latency */
|
||||
int32 mt_stopioe = 1; /* stop on error */
|
||||
uint8 mt_tplte[] = { 0, o_MT0, o_MT0*2, o_MT0*3, TPL_END };
|
||||
|
||||
static const uint8 bad_cmd[64] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 };
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1
|
||||
};
|
||||
|
||||
DEVICE mt_dev;
|
||||
uint32 mt (uint32 dev, uint32 op, uint32 dat);
|
||||
@@ -107,62 +108,66 @@ t_stat mt_attach (UNIT *uptr, char *cptr);
|
||||
t_stat mt_detach (UNIT *uptr);
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||
|
||||
|
||||
/* MT data structures
|
||||
|
||||
mt_dev MT device descriptor
|
||||
mt_unit MT unit list
|
||||
mt_reg MT register list
|
||||
mt_mod MT modifier list
|
||||
mt_dev MT device descriptor
|
||||
mt_unit MT unit list
|
||||
mt_reg MT register list
|
||||
mt_mod MT modifier list
|
||||
*/
|
||||
|
||||
DIB mt_dib = { d_MT, 0, v_MT, mt_tplte, &mt, NULL };
|
||||
|
||||
UNIT mt_unit[] = {
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } };
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mt_reg[] = {
|
||||
{ HRDATA (STA, mt_sta, 8) },
|
||||
{ HRDATA (BUF, mt_db, 8) },
|
||||
{ BRDATA (DBUF, mtxb, 16, 8, MT_MAXFR) },
|
||||
{ HRDATA (DBPTR, mt_bptr, 16) },
|
||||
{ HRDATA (DBLNT, mt_blnt, 17), REG_RO },
|
||||
{ FLDATA (XFR, mt_xfr, 0) },
|
||||
{ GRDATA (IREQ, int_req[l_MT], 16, MT_NUMDR, i_MT) },
|
||||
{ GRDATA (IENB, int_enb[l_MT], 16, MT_NUMDR, i_MT) },
|
||||
{ BRDATA (IARM, mt_arm, 16, 1, MT_NUMDR) },
|
||||
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
|
||||
{ DRDATA (WTIME, mt_wtime, 24), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (RTIME, mt_rtime, 24), PV_LEFT + REG_NZ },
|
||||
{ URDATA (UST, mt_unit[0].UST, 16, 8, 0, MT_NUMDR, 0) },
|
||||
{ URDATA (CMD, mt_unit[0].UCMD, 16, 8, 0, MT_NUMDR, 0) },
|
||||
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ HRDATA (DEVNO, mt_dib.dno, 8), REG_HRO },
|
||||
{ HRDATA (SELCH, mt_dib.sch, 1), REG_HRO },
|
||||
{ NULL } };
|
||||
{ HRDATA (STA, mt_sta, 8) },
|
||||
{ HRDATA (BUF, mt_db, 8) },
|
||||
{ BRDATA (DBUF, mtxb, 16, 8, MT_MAXFR) },
|
||||
{ HRDATA (DBPTR, mt_bptr, 16) },
|
||||
{ HRDATA (DBLNT, mt_blnt, 17), REG_RO },
|
||||
{ FLDATA (XFR, mt_xfr, 0) },
|
||||
{ GRDATA (IREQ, int_req[l_MT], 16, MT_NUMDR, i_MT) },
|
||||
{ GRDATA (IENB, int_enb[l_MT], 16, MT_NUMDR, i_MT) },
|
||||
{ BRDATA (IARM, mt_arm, 16, 1, MT_NUMDR) },
|
||||
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
|
||||
{ DRDATA (WTIME, mt_wtime, 24), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (RTIME, mt_rtime, 24), PV_LEFT + REG_NZ },
|
||||
{ URDATA (UST, mt_unit[0].UST, 16, 8, 0, MT_NUMDR, 0) },
|
||||
{ URDATA (CMD, mt_unit[0].UCMD, 16, 8, 0, MT_NUMDR, 0) },
|
||||
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ HRDATA (DEVNO, mt_dib.dno, 8), REG_HRO },
|
||||
{ HRDATA (SELCH, mt_dib.sch, 1), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB mt_mod[] = {
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
||||
&set_sch, &show_sch, NULL },
|
||||
{ 0 } };
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
||||
&set_sch, &show_sch, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE mt_dev = {
|
||||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
&mt_boot, &mt_attach, &mt_detach,
|
||||
&mt_dib, DEV_DISABLE };
|
||||
|
||||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
&mt_boot, &mt_attach, &mt_detach,
|
||||
&mt_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* Magtape: IO routine */
|
||||
|
||||
uint32 mt (uint32 dev, uint32 op, uint32 dat)
|
||||
@@ -171,59 +176,70 @@ uint32 i, f, t;
|
||||
uint32 u = (dev - mt_dib.dno) / o_MT0;
|
||||
UNIT *uptr = mt_dev.units + u;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
sch_adr (mt_dib.sch, dev); /* inform sel ch */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read data */
|
||||
if (mt_xfr) mt_sta = mt_sta | STA_BSY; /* xfr? set busy */
|
||||
return mt_db; /* return data */
|
||||
case IO_WD: /* write data */
|
||||
if (mt_xfr) { /* transfer? */
|
||||
mt_sta = mt_sta | STA_BSY; /* set busy */
|
||||
if ((uptr->UCMD & (MTC_STOP1 | MTC_STOP2)) &&
|
||||
((uptr->UCMD & MTC_MASK) == MTC_WR)) /* while stopping? */
|
||||
mt_sta = mt_sta | STA_ERR; } /* write overrun */
|
||||
mt_db = dat & DMASK8; /* store data */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
mt_sta = mt_sta & STA_MASK; /* ctrl status */
|
||||
if (uptr->flags & UNIT_ATT) /* attached? */
|
||||
t = mt_sta | (uptr->UST & STA_UFLGS); /* yes, unit status */
|
||||
else t = mt_sta | STA_DU; /* no, dev unavail */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
mt_arm[u] = int_chg (v_MT + u, dat, mt_arm[u]);
|
||||
f = dat & MTC_MASK; /* get cmd */
|
||||
if (f == MTC_CLR) { /* clear? */
|
||||
mt_reset (&mt_dev); /* reset world */
|
||||
break; }
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* ignore if unatt */
|
||||
bad_cmd[f] || /* or bad cmd */
|
||||
(((f == MTC_WR) || (f == MTC_WEOF)) && /* or write */
|
||||
sim_tape_wrp (uptr))) break; /* and protected */
|
||||
for (i = 0; i < MT_NUMDR; i++) { /* check other drvs */
|
||||
if (sim_is_active (&mt_unit[i]) && /* active? */
|
||||
(mt_unit[i].UCMD != MTC_REW)) { /* not rewind? */
|
||||
sim_cancel (&mt_unit[i]); /* stop */
|
||||
mt_unit[i].UCMD = 0; }
|
||||
if (sim_is_active (uptr) && /* unit active? */
|
||||
!(uptr->UCMD & (MTC_STOP1 | MTC_STOP2))) /* not stopping? */
|
||||
break; /* ignore */
|
||||
if ((f == MTC_WR) || (f == MTC_REW)) mt_sta = 0;/* write, rew: bsy=0 */
|
||||
else mt_sta = STA_BSY; /* bsy=1,nmtn,eom,err=0 */
|
||||
mt_bptr = mt_blnt = 0; /* not yet started */
|
||||
if ((f == MTC_RD) || (f == MTC_WR)) /* data xfr? */
|
||||
mt_xfr = 1; /* set xfr flag */
|
||||
else mt_xfr = 0; }
|
||||
uptr->UCMD = f; /* save cmd */
|
||||
uptr->UST = 0; /* clr tape stat */
|
||||
sim_activate (uptr, mt_rtime); /* start op */
|
||||
break; }
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
sch_adr (mt_dib.sch, dev); /* inform sel ch */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_RD: /* read data */
|
||||
if (mt_xfr) mt_sta = mt_sta | STA_BSY; /* xfr? set busy */
|
||||
return mt_db; /* return data */
|
||||
|
||||
case IO_WD: /* write data */
|
||||
if (mt_xfr) { /* transfer? */
|
||||
mt_sta = mt_sta | STA_BSY; /* set busy */
|
||||
if ((uptr->UCMD & (MTC_STOP1 | MTC_STOP2)) &&
|
||||
((uptr->UCMD & MTC_MASK) == MTC_WR)) /* while stopping? */
|
||||
mt_sta = mt_sta | STA_ERR; /* write overrun */
|
||||
}
|
||||
mt_db = dat & DMASK8; /* store data */
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
mt_sta = mt_sta & STA_MASK; /* ctrl status */
|
||||
if (uptr->flags & UNIT_ATT) /* attached? */
|
||||
t = mt_sta | (uptr->UST & STA_UFLGS); /* yes, unit status */
|
||||
else t = mt_sta | STA_DU; /* no, dev unavail */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
|
||||
case IO_OC: /* command */
|
||||
mt_arm[u] = int_chg (v_MT + u, dat, mt_arm[u]);
|
||||
f = dat & MTC_MASK; /* get cmd */
|
||||
if (f == MTC_CLR) { /* clear? */
|
||||
mt_reset (&mt_dev); /* reset world */
|
||||
break;
|
||||
}
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* ignore if unatt */
|
||||
bad_cmd[f] || /* or bad cmd */
|
||||
(((f == MTC_WR) || (f == MTC_WEOF)) && /* or write */
|
||||
sim_tape_wrp (uptr))) break; /* and protected */
|
||||
for (i = 0; i < MT_NUMDR; i++) { /* check other drvs */
|
||||
if (sim_is_active (&mt_unit[i]) && /* active? */
|
||||
(mt_unit[i].UCMD != MTC_REW)) { /* not rewind? */
|
||||
sim_cancel (&mt_unit[i]); /* stop */
|
||||
mt_unit[i].UCMD = 0;
|
||||
}
|
||||
}
|
||||
if (sim_is_active (uptr) && /* unit active? */
|
||||
!(uptr->UCMD & (MTC_STOP1 | MTC_STOP2))) /* not stopping? */
|
||||
break; /* ignore */
|
||||
if ((f == MTC_WR) || (f == MTC_REW)) mt_sta = 0;/* write, rew: bsy=0 */
|
||||
else mt_sta = STA_BSY; /* bsy=1,nmtn,eom,err=0 */
|
||||
mt_bptr = mt_blnt = 0; /* not yet started */
|
||||
if ((f == MTC_RD) || (f == MTC_WR)) /* data xfr? */
|
||||
mt_xfr = 1; /* set xfr flag */
|
||||
else mt_xfr = 0;
|
||||
uptr->UCMD = f; /* save cmd */
|
||||
uptr->UST = 0; /* clr tape stat */
|
||||
sim_activate (uptr, mt_rtime); /* start op */
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service
|
||||
|
||||
A given operation can generate up to three interrupts
|
||||
@@ -246,129 +262,137 @@ uint32 dev = mt_dib.dno + (u * o_MT0);
|
||||
t_mtrlnt tbc;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->UST = 0; /* set status */
|
||||
mt_xfr = 0; /* clr op flags */
|
||||
mt_sta = STA_ERR | STA_EOM; /* set status */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->UST = 0; /* set status */
|
||||
mt_xfr = 0; /* clr op flags */
|
||||
mt_sta = STA_ERR | STA_EOM; /* set status */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
return IORETURN (mt_stopioe, SCPE_UNATT);
|
||||
}
|
||||
|
||||
if (uptr->UCMD & MTC_STOP2) { /* stop, gen NMTN? */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->UST = STA_NMTN; /* set nmtn, not eot */
|
||||
mt_xfr = 0; /* clr xfr */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
return SCPE_OK; }
|
||||
if (uptr->UCMD & MTC_STOP2) { /* stop, gen NMTN? */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->UST = STA_NMTN; /* set nmtn, not eot */
|
||||
mt_xfr = 0; /* clr xfr */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (uptr->UCMD & MTC_STOP1) { /* stop, gen EOM? */
|
||||
uptr->UCMD = uptr->UCMD | MTC_STOP2; /* clr cmd */
|
||||
mt_sta = (mt_sta & ~STA_BSY) | STA_EOM; /* clr busy, set eom */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
sim_activate (uptr, mt_rtime); /* schedule */
|
||||
return SCPE_OK; } /* end case */
|
||||
if (uptr->UCMD & MTC_STOP1) { /* stop, gen EOM? */
|
||||
uptr->UCMD = uptr->UCMD | MTC_STOP2; /* clr cmd */
|
||||
mt_sta = (mt_sta & ~STA_BSY) | STA_EOM; /* clr busy, set eom */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
sim_activate (uptr, mt_rtime); /* schedule */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
switch (uptr->UCMD) { /* case on function */
|
||||
switch (uptr->UCMD) { /* case on function */
|
||||
|
||||
case MTC_REW: /* rewind */
|
||||
sim_tape_rewind (uptr); /* reposition */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->UST = STA_NMTN | STA_EOT; /* update status */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* don't set EOM */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
return SCPE_OK;
|
||||
|
||||
/* Unit service, continued
|
||||
case MTC_REW: /* rewind */
|
||||
sim_tape_rewind (uptr); /* reposition */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->UST = STA_NMTN | STA_EOT; /* update status */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* don't set EOM */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
return SCPE_OK;
|
||||
|
||||
For read, busy = 1 => buffer empty
|
||||
/* For read, busy = 1 => buffer empty
|
||||
For write, busy = 1 => buffer full
|
||||
For read, data transfers continue for the full length of the
|
||||
record, or the maximum size of the transfer buffer
|
||||
record, or the maximum size of the transfer buffer
|
||||
For write, data transfers continue until a write is attempted
|
||||
and the buffer is empty
|
||||
and the buffer is empty
|
||||
*/
|
||||
|
||||
case MTC_RD: /* read */
|
||||
if (mt_blnt == 0) { /* first time? */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||
if (st == MTSE_RECE) mt_sta = mt_sta | STA_ERR; /* rec in err? */
|
||||
else if (st != SCPE_OK) { /* other error? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
if (sch_actv (mt_dib.sch, dev)) /* if sch, stop */
|
||||
sch_stop (mt_dib.sch);
|
||||
break; }
|
||||
mt_blnt = tbc; /* set buf lnt */
|
||||
}
|
||||
case MTC_RD: /* read */
|
||||
if (mt_blnt == 0) { /* first time? */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||
if (st == MTSE_RECE) mt_sta = mt_sta | STA_ERR; /* rec in err? */
|
||||
else if (st != SCPE_OK) { /* other error? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
if (sch_actv (mt_dib.sch, dev)) /* if sch, stop */
|
||||
sch_stop (mt_dib.sch);
|
||||
break;
|
||||
}
|
||||
mt_blnt = tbc; /* set buf lnt */
|
||||
}
|
||||
|
||||
if (sch_actv (mt_dib.sch, dev)) { /* sch active? */
|
||||
i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt); /* store rec in mem */
|
||||
if (sch_actv (mt_dib.sch, dev)) /* sch still active? */
|
||||
sch_stop (mt_dib.sch); /* stop chan, long rd */
|
||||
else if (i < mt_blnt) /* process entire rec? */
|
||||
mt_sta = mt_sta | STA_ERR; } /* no, overrun error */
|
||||
else if (mt_bptr < mt_blnt) { /* no, if !eor */
|
||||
if (!(mt_sta & STA_BSY)) /* busy still clr? */
|
||||
mt_sta = mt_sta | STA_ERR; /* read overrun */
|
||||
mt_db = mtxb[mt_bptr++]; /* get next byte */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* !busy = buf full */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
sim_activate (uptr, mt_wtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; /* record done */
|
||||
if (sch_actv (mt_dib.sch, dev)) { /* sch active? */
|
||||
i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt); /* store rec in mem */
|
||||
if (sch_actv (mt_dib.sch, dev)) /* sch still active? */
|
||||
sch_stop (mt_dib.sch); /* stop chan, long rd */
|
||||
else if (i < mt_blnt) /* process entire rec? */
|
||||
mt_sta = mt_sta | STA_ERR; /* no, overrun error */
|
||||
}
|
||||
else if (mt_bptr < mt_blnt) { /* no, if !eor */
|
||||
if (!(mt_sta & STA_BSY)) /* busy still clr? */
|
||||
mt_sta = mt_sta | STA_ERR; /* read overrun */
|
||||
mt_db = mtxb[mt_bptr++]; /* get next byte */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* !busy = buf full */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
sim_activate (uptr, mt_wtime); /* reschedule */
|
||||
return SCPE_OK;
|
||||
}
|
||||
break; /* record done */
|
||||
|
||||
case MTC_WR: /* write */
|
||||
if (sch_actv (mt_dib.sch, dev)) { /* sch active? */
|
||||
mt_bptr = sch_rdmem (mt_dib.sch, mtxb, MT_MAXFR); /* get rec */
|
||||
if (sch_actv (mt_dib.sch, dev)) /* not done? */
|
||||
sch_stop (mt_dib.sch); } /* stop chan */
|
||||
else if (mt_sta & STA_BSY) { /* no, if !eor */
|
||||
if (mt_bptr < MT_MAXFR) /* if room */
|
||||
mtxb[mt_bptr++] = mt_db; /* store in buf */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* !busy = buf emp */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
sim_activate (uptr, mt_wtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
case MTC_WR: /* write */
|
||||
if (sch_actv (mt_dib.sch, dev)) { /* sch active? */
|
||||
mt_bptr = sch_rdmem (mt_dib.sch, mtxb, MT_MAXFR); /* get rec */
|
||||
if (sch_actv (mt_dib.sch, dev)) /* not done? */
|
||||
sch_stop (mt_dib.sch); /* stop chan */
|
||||
}
|
||||
else if (mt_sta & STA_BSY) { /* no, if !eor */
|
||||
if (mt_bptr < MT_MAXFR) /* if room */
|
||||
mtxb[mt_bptr++] = mt_db; /* store in buf */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* !busy = buf emp */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
sim_activate (uptr, mt_wtime); /* reschedule */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (mt_bptr) { /* any chars? */
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, mt_bptr)) /* write, err? */
|
||||
r = mt_map_err (uptr, st); } /* map error */
|
||||
break; /* record done */
|
||||
|
||||
/* Unit service, continued */
|
||||
if (mt_bptr) { /* any chars? */
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, mt_bptr)) /* write, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
}
|
||||
break; /* record done */
|
||||
|
||||
case MTC_WEOF: /* write eof */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
break;
|
||||
case MTC_WEOF: /* write eof */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
break;
|
||||
|
||||
case MTC_SKFF: /* skip file fwd */
|
||||
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) { /* stopped by tmk? */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */
|
||||
else r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
case MTC_SKFF: /* skip file fwd */
|
||||
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) { /* stopped by tmk? */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
}
|
||||
else r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case MTC_SKFR: /* skip file rev */
|
||||
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) { /* stopped by tmk? */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */
|
||||
else r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
case MTC_SKFR: /* skip file rev */
|
||||
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) { /* stopped by tmk? */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
}
|
||||
else r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case MTC_SPCR: /* backspace */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* skip rec rev, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; } /* end case */
|
||||
case MTC_SPCR: /* backspace */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* skip rec rev, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
} /* end case */
|
||||
|
||||
uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */
|
||||
sim_activate (uptr, mt_rtime); /* schedule */
|
||||
uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */
|
||||
sim_activate (uptr, mt_rtime); /* schedule */
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Map tape error status */
|
||||
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||
@@ -376,33 +400,41 @@ t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||
int32 u = uptr - mt_dev.units;
|
||||
|
||||
switch (st) {
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* not attached */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR;
|
||||
case MTSE_TMK: /* end of file */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
if (mt_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_WRP: /* write protect */
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
break;
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
uptr->UST = uptr->UST | STA_EOT; /* set err */
|
||||
break; } /* end switch */
|
||||
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* not attached */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR;
|
||||
|
||||
case MTSE_TMK: /* end of file */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
break;
|
||||
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
if (mt_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
return SCPE_MTRLNT;
|
||||
|
||||
case MTSE_WRP: /* write protect */
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
break;
|
||||
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
uptr->UST = uptr->UST | STA_EOT; /* set err */
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat mt_reset (DEVICE *dptr)
|
||||
@@ -410,18 +442,19 @@ t_stat mt_reset (DEVICE *dptr)
|
||||
uint32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
mt_bptr = mt_blnt = 0; /* clr buf */
|
||||
mt_sta = STA_BSY; /* clr flags */
|
||||
mt_xfr = 0; /* clr controls */
|
||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
CLR_INT (v_MT + u); /* clear int */
|
||||
CLR_ENB (v_MT + u); /* disable int */
|
||||
mt_arm[u] = 0; /* disarm int */
|
||||
uptr = mt_dev.units + u;
|
||||
sim_tape_reset (uptr); /* clear pos flag */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
uptr->UST = (uptr->UST & STA_UFLGS) | STA_NMTN; /* init status */
|
||||
uptr->UCMD = 0; } /* init cmd */
|
||||
mt_bptr = mt_blnt = 0; /* clr buf */
|
||||
mt_sta = STA_BSY; /* clr flags */
|
||||
mt_xfr = 0; /* clr controls */
|
||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
CLR_INT (v_MT + u); /* clear int */
|
||||
CLR_ENB (v_MT + u); /* disable int */
|
||||
mt_arm[u] = 0; /* disarm int */
|
||||
uptr = mt_dev.units + u;
|
||||
sim_tape_reset (uptr); /* clear pos flag */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
uptr->UST = (uptr->UST & STA_UFLGS) | STA_NMTN; /* init status */
|
||||
uptr->UCMD = 0; /* init cmd */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -456,15 +489,13 @@ return SCPE_OK;
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define BOOT_START 0x50
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
#define BOOT_START 0x50
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
|
||||
static uint8 boot_rom[] = {
|
||||
0xD5, 0x00, /* ST: AL CF */
|
||||
0x00, 0xCF,
|
||||
0x43, 0x00, /* BR 80 */
|
||||
0x00, 0x80
|
||||
};
|
||||
0xD5, 0x00, 0x00, 0xCF, /* ST: AL CF */
|
||||
0x43, 0x00, 0x00, 0x80 /* BR 80 */
|
||||
};
|
||||
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
@@ -473,13 +504,13 @@ extern uint16 decrom[];
|
||||
extern DIB sch_dib;
|
||||
uint32 sch_dev;
|
||||
|
||||
if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */
|
||||
sim_tape_rewind (&mt_unit[unitno]); /* rewind */
|
||||
sch_dev = sch_dib.dno + mt_dib.sch; /* sch dev # */
|
||||
IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, mt_dib.dno + (unitno * o_MT0)); /* set dev no for unit */
|
||||
IOWriteB (AL_IOC, 0xA1); /* set dev cmd */
|
||||
IOWriteB (AL_SCH, sch_dev); /* set dev no for chan */
|
||||
if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */
|
||||
sim_tape_rewind (&mt_unit[unitno]); /* rewind */
|
||||
sch_dev = sch_dib.dno + mt_dib.sch; /* sch dev # */
|
||||
IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, mt_dib.dno + (unitno * o_MT0)); /* set dev no for unit */
|
||||
IOWriteB (AL_IOC, 0xA1); /* set dev cmd */
|
||||
IOWriteB (AL_SCH, sch_dev); /* set dev no for chan */
|
||||
PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id_pas.c: Interdata programmable async line adapter simulator
|
||||
|
||||
Copyright (c) 2001-2004, Robert M Supnik
|
||||
Copyright (c) 2001-2005, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,14 +19,16 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
pas Programmable asynchronous line adapter(s)
|
||||
pas Programmable asynchronous line adapter(s)
|
||||
|
||||
05-Jan-04 RMS Revised for tmxr library changes
|
||||
09-May-03 RMS Added network device flag
|
||||
29-Jun-05 RMS Added SET PASLn DISCONNECT
|
||||
21-Jun-05 RMS Fixed bug in SHOW CONN/STATS
|
||||
05-Jan-04 RMS Revised for tmxr library changes
|
||||
09-May-03 RMS Added network device flag
|
||||
|
||||
This module implements up to 32 individual serial interfaces, representing
|
||||
either individual PASLA modules or combinations of the 2-line and 8-line
|
||||
@@ -41,68 +43,68 @@
|
||||
#include "sim_tmxr.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define PAS_LINES 32
|
||||
#define PAS_LINES 32
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */
|
||||
#define UNIT_V_MDM (UNIT_V_UF + 2) /* modem control */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
#define UNIT_MDM (1 << UNIT_V_MDM)
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */
|
||||
#define UNIT_V_MDM (UNIT_V_UF + 2) /* modem control */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
#define UNIT_MDM (1 << UNIT_V_MDM)
|
||||
|
||||
#define PAS_INIT_POLL 8000
|
||||
#define PASL_WAIT 500
|
||||
#define PAS_INIT_POLL 8000
|
||||
#define PASL_WAIT 500
|
||||
|
||||
/* Status byte */
|
||||
|
||||
#define STA_OVR 0x80 /* overrun RO */
|
||||
#define STA_PF 0x40 /* parity err RONI */
|
||||
#define STA_NCL2S 0x40 /* not clr to snd XO */
|
||||
#define STA_FR 0x20 /* framing err RO */
|
||||
#define STA_RCR 0x10 /* rv chan rcv NI */
|
||||
#define STA_CROF 0x02 /* carrier off RO */
|
||||
#define STA_RING 0x01 /* ring RO */
|
||||
#define STA_RCV (STA_OVR|STA_PF|STA_FR|STA_RCR|STA_CROF|STA_RING)
|
||||
#define SET_EX (STA_OVR|STA_PF|STA_FR)
|
||||
#define STA_XMT (STA_BSY)
|
||||
#define STA_OVR 0x80 /* overrun RO */
|
||||
#define STA_PF 0x40 /* parity err RONI */
|
||||
#define STA_NCL2S 0x40 /* not clr to snd XO */
|
||||
#define STA_FR 0x20 /* framing err RO */
|
||||
#define STA_RCR 0x10 /* rv chan rcv NI */
|
||||
#define STA_CROF 0x02 /* carrier off RO */
|
||||
#define STA_RING 0x01 /* ring RO */
|
||||
#define STA_RCV (STA_OVR|STA_PF|STA_FR|STA_RCR|STA_CROF|STA_RING)
|
||||
#define SET_EX (STA_OVR|STA_PF|STA_FR)
|
||||
#define STA_XMT (STA_BSY)
|
||||
|
||||
/* Command bytes 1,0 */
|
||||
|
||||
#define CMD_DTR (0x20 << 8) /* DTR */
|
||||
#define CMD_ECHO (0x10 << 8) /* echoplex */
|
||||
#define CMD_RCT (0x08 << 8) /* RCT/DTB NI */
|
||||
#define CMD_XMTB (0x04 << 8) /* xmt break NI */
|
||||
#define CMD_WRT (0x02 << 8) /* write/read */
|
||||
#define CMD_V_CLK 6 /* baud rate */
|
||||
#define CMD_M_CLK 0x3
|
||||
#define CMD_V_DB 4 /* data bits */
|
||||
#define CMD_M_DB 0x3
|
||||
#define CMD_STOP 0x80 /* stop bit */
|
||||
#define CMD_V_PAR 1 /* parity */
|
||||
#define CMD_M_PAR 0x3
|
||||
#define GET_PAR(x) (((x) >> CMD_V_PAR) & CMD_M_PAR)
|
||||
#define PAR_NONE 0
|
||||
#define PAR_RAW 1
|
||||
#define PAR_ODD 2
|
||||
#define PAR_EVEN 3
|
||||
#define CMD_DTR (0x20 << 8) /* DTR */
|
||||
#define CMD_ECHO (0x10 << 8) /* echoplex */
|
||||
#define CMD_RCT (0x08 << 8) /* RCT/DTB NI */
|
||||
#define CMD_XMTB (0x04 << 8) /* xmt break NI */
|
||||
#define CMD_WRT (0x02 << 8) /* write/read */
|
||||
#define CMD_V_CLK 6 /* baud rate */
|
||||
#define CMD_M_CLK 0x3
|
||||
#define CMD_V_DB 4 /* data bits */
|
||||
#define CMD_M_DB 0x3
|
||||
#define CMD_STOP 0x80 /* stop bit */
|
||||
#define CMD_V_PAR 1 /* parity */
|
||||
#define CMD_M_PAR 0x3
|
||||
#define GET_PAR(x) (((x) >> CMD_V_PAR) & CMD_M_PAR)
|
||||
#define PAR_NONE 0
|
||||
#define PAR_RAW 1
|
||||
#define PAR_ODD 2
|
||||
#define PAR_EVEN 3
|
||||
|
||||
#define CMD_TYP 0x01 /* command type */
|
||||
#define CMD_TYP 0x01 /* command type */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint8 pas_sta[PAS_LINES]; /* status */
|
||||
uint16 pas_cmd[PAS_LINES]; /* command */
|
||||
uint8 pas_rbuf[PAS_LINES]; /* rcv buf */
|
||||
uint8 pas_xbuf[PAS_LINES]; /* xmt buf */
|
||||
uint8 pas_rarm[PAS_LINES]; /* rcvr int armed */
|
||||
uint8 pas_xarm[PAS_LINES]; /* xmt int armed */
|
||||
uint8 pas_rchp[PAS_LINES]; /* rcvr chr pend */
|
||||
uint32 pas_tps = 50; /* polls/second */
|
||||
uint8 pas_tplte[PAS_LINES * 2 + 1]; /* template */
|
||||
uint8 pas_sta[PAS_LINES]; /* status */
|
||||
uint16 pas_cmd[PAS_LINES]; /* command */
|
||||
uint8 pas_rbuf[PAS_LINES]; /* rcv buf */
|
||||
uint8 pas_xbuf[PAS_LINES]; /* xmt buf */
|
||||
uint8 pas_rarm[PAS_LINES]; /* rcvr int armed */
|
||||
uint8 pas_xarm[PAS_LINES]; /* xmt int armed */
|
||||
uint8 pas_rchp[PAS_LINES]; /* rcvr chr pend */
|
||||
uint32 pas_tps = 50; /* polls/second */
|
||||
uint8 pas_tplte[PAS_LINES * 2 + 1]; /* template */
|
||||
|
||||
TMLN pas_ldsc[PAS_LINES] = { 0 }; /* line descriptors */
|
||||
TMXR pas_desc = { 8, 0, 0, pas_ldsc }; /* mux descriptor */
|
||||
#define PAS_ENAB pas_desc.lines
|
||||
TMLN pas_ldsc[PAS_LINES] = { 0 }; /* line descriptors */
|
||||
TMXR pas_desc = { 8, 0, 0, pas_ldsc }; /* mux descriptor */
|
||||
#define PAS_ENAB pas_desc.lines
|
||||
|
||||
uint32 pas (uint32 dev, uint32 op, uint32 dat);
|
||||
void pas_ini (t_bool dtpl);
|
||||
@@ -116,13 +118,13 @@ t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
int32 pas_par (int32 cmd, int32 c);
|
||||
t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
void pas_reset_ln (int32 i);
|
||||
|
||||
|
||||
/* PAS data structures
|
||||
|
||||
pas_dev PAS device descriptor
|
||||
pas_unit PAS unit descriptor
|
||||
pas_reg PAS register list
|
||||
pas_mod PAS modifiers list
|
||||
pas_dev PAS device descriptor
|
||||
pas_unit PAS unit descriptor
|
||||
pas_reg PAS register list
|
||||
pas_mod PAS modifiers list
|
||||
*/
|
||||
|
||||
DIB pas_dib = { d_PAS, -1, v_PAS, pas_tplte, &pas, &pas_ini };
|
||||
@@ -132,105 +134,114 @@ UNIT pas_unit = { UDATA (&pasi_svc, UNIT_ATTABLE, 0), PAS_INIT_POLL };
|
||||
REG pas_nlreg = { DRDATA (NLINES, PAS_ENAB, 6), PV_LEFT };
|
||||
|
||||
REG pas_reg[] = {
|
||||
{ BRDATA (STA, pas_sta, 16, 8, PAS_LINES) },
|
||||
{ BRDATA (CMD, pas_cmd, 16, 16, PAS_LINES) },
|
||||
{ BRDATA (RBUF, pas_rbuf, 16, 8, PAS_LINES) },
|
||||
{ BRDATA (XBUF, pas_xbuf, 16, 8, PAS_LINES) },
|
||||
{ BRDATA (IREQ, &int_req[l_PAS], 16, 32, PAS_LINES / 16) },
|
||||
{ BRDATA (IENB, &int_enb[l_PAS], 16, 32, PAS_LINES / 16) },
|
||||
{ BRDATA (RARM, pas_rarm, 16, 1, PAS_LINES) },
|
||||
{ BRDATA (XARM, pas_xarm, 16, 1, PAS_LINES) },
|
||||
{ BRDATA (RCHP, pas_rchp, 16, 1, PAS_LINES) },
|
||||
{ HRDATA (DEVNO, pas_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
{ BRDATA (STA, pas_sta, 16, 8, PAS_LINES) },
|
||||
{ BRDATA (CMD, pas_cmd, 16, 16, PAS_LINES) },
|
||||
{ BRDATA (RBUF, pas_rbuf, 16, 8, PAS_LINES) },
|
||||
{ BRDATA (XBUF, pas_xbuf, 16, 8, PAS_LINES) },
|
||||
{ BRDATA (IREQ, &int_req[l_PAS], 16, 32, PAS_LINES / 16) },
|
||||
{ BRDATA (IENB, &int_enb[l_PAS], 16, 32, PAS_LINES / 16) },
|
||||
{ BRDATA (RARM, pas_rarm, 16, 1, PAS_LINES) },
|
||||
{ BRDATA (XARM, pas_xarm, 16, 1, PAS_LINES) },
|
||||
{ BRDATA (RCHP, pas_rchp, 16, 1, PAS_LINES) },
|
||||
{ HRDATA (DEVNO, pas_dib.dno, 8), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB pas_mod[] = {
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES",
|
||||
&pas_vlines, NULL, &pas_nlreg },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &pas_desc },
|
||||
{ UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &pas_summ },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &pas_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &pas_show, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES",
|
||||
&pas_vlines, NULL, &pas_nlreg },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &pas_desc },
|
||||
{ UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &pas_summ },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &pas_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &pas_show, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE pas_dev = {
|
||||
"PAS", &pas_unit, pas_reg, pas_mod,
|
||||
1, 10, 31, 1, 16, 8,
|
||||
&tmxr_ex, &tmxr_dep, &pas_reset,
|
||||
NULL, &pas_attach, &pas_detach,
|
||||
&pas_dib, DEV_NET | DEV_DISABLE };
|
||||
"PAS", &pas_unit, pas_reg, pas_mod,
|
||||
1, 10, 31, 1, 16, 8,
|
||||
&tmxr_ex, &tmxr_dep, &pas_reset,
|
||||
NULL, &pas_attach, &pas_detach,
|
||||
&pas_dib, DEV_NET | DEV_DISABLE
|
||||
};
|
||||
|
||||
/* PASL data structures
|
||||
|
||||
pasl_dev PASL device descriptor
|
||||
pasl_unit PASL unit descriptor
|
||||
pasl_reg PASL register list
|
||||
pasl_mod PASL modifiers list
|
||||
pasl_dev PASL device descriptor
|
||||
pasl_unit PASL unit descriptor
|
||||
pasl_reg PASL register list
|
||||
pasl_mod PASL modifiers list
|
||||
*/
|
||||
|
||||
UNIT pasl_unit[] = {
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT }, /* all but 8 dis */
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT } };
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT }, /* all but 8 dis */
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }
|
||||
};
|
||||
|
||||
MTAB pasl_mod[] = {
|
||||
{ UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL },
|
||||
{ UNIT_UC+UNIT_8B, 0 , "7b", "7B", NULL },
|
||||
{ UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", NULL },
|
||||
{ UNIT_MDM, 0, "no dataset", "NODATASET", NULL },
|
||||
{ UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
|
||||
&tmxr_set_log, &tmxr_show_log, &pas_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
|
||||
&tmxr_set_nolog, NULL, &pas_desc },
|
||||
{ 0 } };
|
||||
{ UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL },
|
||||
{ UNIT_UC+UNIT_8B, 0 , "7b", "7B", NULL },
|
||||
{ UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", NULL },
|
||||
{ UNIT_MDM, 0, "no dataset", "NODATASET", NULL },
|
||||
{ UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &pas_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
|
||||
&tmxr_set_log, &tmxr_show_log, &pas_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
|
||||
&tmxr_set_nolog, NULL, &pas_desc },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
REG pasl_reg[] = {
|
||||
{ URDATA (TIME, pasl_unit[0].wait, 16, 24, 0,
|
||||
PAS_LINES, REG_NZ + PV_LEFT) },
|
||||
{ NULL } };
|
||||
{ URDATA (TIME, pasl_unit[0].wait, 16, 24, 0,
|
||||
PAS_LINES, REG_NZ + PV_LEFT) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE pasl_dev = {
|
||||
"PASL", pasl_unit, pasl_reg, pasl_mod,
|
||||
PAS_LINES, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &pas_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, 0 };
|
||||
|
||||
"PASL", pasl_unit, pasl_reg, pasl_mod,
|
||||
PAS_LINES, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &pas_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, 0
|
||||
};
|
||||
|
||||
/* PAS: IO routine */
|
||||
|
||||
uint32 pas (uint32 dev, uint32 op, uint32 dat)
|
||||
@@ -239,50 +250,62 @@ int32 ln = (dev - pas_dib.dno) >> 1;
|
||||
int32 xmt = (dev - pas_dib.dno) & 1;
|
||||
int32 t, old_cmd;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read */
|
||||
pas_rchp[ln] = 0; /* clr chr pend */
|
||||
pas_sta[ln] = pas_sta[ln] & ~STA_OVR; /* clr overrun */
|
||||
return pas_rbuf[ln]; /* return buf */
|
||||
case IO_WD: /* write */
|
||||
pas_xbuf[ln] = dat & 0xFF; /* store char */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_BSY; /* set busy */
|
||||
sim_activate (&pasl_unit[ln], pasl_unit[ln].wait);
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
if (xmt) { /* xmt side? */
|
||||
if (pas_ldsc[ln].conn == 0) /* not conn? */
|
||||
t = STA_NCL2S | STA_BSY; /* busy, not clr */
|
||||
else t = pas_sta[ln] & STA_XMT; } /* else just busy */
|
||||
else {
|
||||
t = pas_sta[ln] & STA_RCV; /* get static */
|
||||
if (!pas_rchp[ln]) t = t | STA_BSY; /* no char? busy */
|
||||
if (pas_ldsc[ln].conn == 0) /* not connected? */
|
||||
t = t | STA_BSY | STA_EX; /* = !dsr */
|
||||
if (t & SET_EX) t = t | STA_EX; } /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
old_cmd = pas_cmd[ln]; /* old cmd */
|
||||
if (dat & CMD_TYP) { /* type 1? */
|
||||
pas_cmd[ln] = (pas_cmd[ln] & 0xFF) | (dat << 8);
|
||||
if (pas_cmd[ln] & CMD_WRT) /* write? */
|
||||
pas_xarm[ln] = int_chg (v_PASX + ln + ln, dat, pas_xarm[ln]);
|
||||
else pas_rarm[ln] = int_chg (v_PAS + ln + ln, dat, pas_rarm[ln]); }
|
||||
else pas_cmd[ln] = (pas_cmd[ln] & ~0xFF) | dat;
|
||||
if (pasl_unit[ln].flags & UNIT_MDM) { /* modem ctrl? */
|
||||
if ((pas_cmd[ln] & CMD_DTR) && (pas_sta[ln] & STA_RING))
|
||||
pas_sta[ln] = pas_sta[ln] & ~(STA_CROF | STA_RING);
|
||||
if (old_cmd & ~pas_cmd[ln] & CMD_DTR) {
|
||||
tmxr_linemsg (&pas_ldsc[ln], "\r\nLine hangup\r\n");
|
||||
tmxr_reset_ln (&pas_ldsc[ln]); /* reset line */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); } }
|
||||
break; }
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_RD: /* read */
|
||||
pas_rchp[ln] = 0; /* clr chr pend */
|
||||
pas_sta[ln] = pas_sta[ln] & ~STA_OVR; /* clr overrun */
|
||||
return pas_rbuf[ln]; /* return buf */
|
||||
|
||||
case IO_WD: /* write */
|
||||
pas_xbuf[ln] = dat & 0xFF; /* store char */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_BSY; /* set busy */
|
||||
sim_activate (&pasl_unit[ln], pasl_unit[ln].wait);
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
if (xmt) { /* xmt side? */
|
||||
if (pas_ldsc[ln].conn == 0) /* not conn? */
|
||||
t = STA_NCL2S | STA_BSY; /* busy, not clr */
|
||||
else t = pas_sta[ln] & STA_XMT; /* else just busy */
|
||||
}
|
||||
else {
|
||||
t = pas_sta[ln] & STA_RCV; /* get static */
|
||||
if (!pas_rchp[ln]) t = t | STA_BSY; /* no char? busy */
|
||||
if (pas_ldsc[ln].conn == 0) /* not connected? */
|
||||
t = t | STA_BSY | STA_EX; /* = !dsr */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for ex */
|
||||
}
|
||||
return t;
|
||||
|
||||
case IO_OC: /* command */
|
||||
old_cmd = pas_cmd[ln]; /* old cmd */
|
||||
if (dat & CMD_TYP) { /* type 1? */
|
||||
pas_cmd[ln] = (pas_cmd[ln] & 0xFF) | (dat << 8);
|
||||
if (pas_cmd[ln] & CMD_WRT) /* write? */
|
||||
pas_xarm[ln] = int_chg (v_PASX + ln + ln, dat, pas_xarm[ln]);
|
||||
else pas_rarm[ln] = int_chg (v_PAS + ln + ln, dat, pas_rarm[ln]);
|
||||
}
|
||||
else pas_cmd[ln] = (pas_cmd[ln] & ~0xFF) | dat;
|
||||
if (pasl_unit[ln].flags & UNIT_MDM) { /* modem ctrl? */
|
||||
if ((pas_cmd[ln] & CMD_DTR) && (pas_sta[ln] & STA_RING))
|
||||
pas_sta[ln] = pas_sta[ln] & ~(STA_CROF | STA_RING);
|
||||
if (old_cmd & ~pas_cmd[ln] & CMD_DTR) {
|
||||
tmxr_linemsg (&pas_ldsc[ln], "\r\nLine hangup\r\n");
|
||||
tmxr_reset_ln (&pas_ldsc[ln]); /* reset line */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service - receive side
|
||||
|
||||
Poll all active lines for input
|
||||
@@ -293,48 +316,53 @@ t_stat pasi_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ln, c, out, t;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
t = sim_rtcn_calb (pas_tps, TMR_PAS); /* calibrate */
|
||||
sim_activate (uptr, t); /* continue poll */
|
||||
ln = tmxr_poll_conn (&pas_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? */
|
||||
if ((pasl_unit[ln].flags & UNIT_MDM) && /* modem control */
|
||||
((pas_cmd[ln] & CMD_DTR) == 0)) /* & !dtr? */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_RING | STA_CROF; /* set ring, no cd */
|
||||
else pas_sta[ln] = pas_sta[ln] & ~STA_CROF; /* just answer */
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); /* interrupt */
|
||||
pas_ldsc[ln].rcve = 1; } /* rcv enabled */
|
||||
tmxr_poll_rx (&pas_desc); /* poll for input */
|
||||
for (ln = 0; ln < PAS_ENAB; ln++) { /* loop thru lines */
|
||||
if (pas_ldsc[ln].conn) { /* connected? */
|
||||
if (c = tmxr_getc_ln (&pas_ldsc[ln])) { /* any char? */
|
||||
pas_sta[ln] = pas_sta[ln] & ~(STA_FR | STA_PF);
|
||||
if (pas_rchp[ln]) pas_sta[ln] = pas_sta[ln] | STA_OVR;
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln);
|
||||
if (c & SCPE_BREAK) { /* break? */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_FR; /* framing error */
|
||||
pas_rbuf[ln] = 0; } /* no character */
|
||||
else { /* normal */
|
||||
out = c & 0x7F; /* echo is 7b */
|
||||
if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */
|
||||
c = c & 0xFF;
|
||||
else { /* UC or 7b */
|
||||
if ((pasl_unit[ln].flags & UNIT_UC) && islower (out))
|
||||
out = toupper (out); /* cvt to UC */
|
||||
c = pas_par (pas_cmd[ln], out); } /* apply parity */
|
||||
pas_rbuf[ln] = c; /* save char */
|
||||
pas_rchp[ln] = 1; /* char pending */
|
||||
if ((pas_cmd[ln] & CMD_ECHO) && pas_ldsc[ln].xmte) {
|
||||
TMLN *lp = &pas_ldsc[ln]; /* get line */
|
||||
tmxr_putc_ln (lp, out); /* output char */
|
||||
tmxr_poll_tx (&pas_desc); } /* poll xmt */
|
||||
} /* end else normal */
|
||||
} /* end if char */
|
||||
} /* end if conn */
|
||||
else if ((pas_sta[ln] & STA_CROF) == 0) { /* not conn, was conn? */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); } /* intr */
|
||||
} /* end for */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
t = sim_rtcn_calb (pas_tps, TMR_PAS); /* calibrate */
|
||||
sim_activate (uptr, t); /* continue poll */
|
||||
ln = tmxr_poll_conn (&pas_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? */
|
||||
if ((pasl_unit[ln].flags & UNIT_MDM) && /* modem control */
|
||||
((pas_cmd[ln] & CMD_DTR) == 0)) /* & !dtr? */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_RING | STA_CROF; /* set ring, no cd */
|
||||
else pas_sta[ln] = pas_sta[ln] & ~STA_CROF; /* just answer */
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); /* interrupt */
|
||||
pas_ldsc[ln].rcve = 1; /* rcv enabled */
|
||||
}
|
||||
tmxr_poll_rx (&pas_desc); /* poll for input */
|
||||
for (ln = 0; ln < PAS_ENAB; ln++) { /* loop thru lines */
|
||||
if (pas_ldsc[ln].conn) { /* connected? */
|
||||
if (c = tmxr_getc_ln (&pas_ldsc[ln])) { /* any char? */
|
||||
pas_sta[ln] = pas_sta[ln] & ~(STA_FR | STA_PF);
|
||||
if (pas_rchp[ln]) pas_sta[ln] = pas_sta[ln] | STA_OVR;
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln);
|
||||
if (c & SCPE_BREAK) { /* break? */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_FR; /* framing error */
|
||||
pas_rbuf[ln] = 0; /* no character */
|
||||
}
|
||||
else { /* normal */
|
||||
out = c & 0x7F; /* echo is 7b */
|
||||
if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */
|
||||
c = c & 0xFF;
|
||||
else { /* UC or 7b */
|
||||
if ((pasl_unit[ln].flags & UNIT_UC) && islower (out))
|
||||
out = toupper (out); /* cvt to UC */
|
||||
c = pas_par (pas_cmd[ln], out); /* apply parity */
|
||||
}
|
||||
pas_rbuf[ln] = c; /* save char */
|
||||
pas_rchp[ln] = 1; /* char pending */
|
||||
if ((pas_cmd[ln] & CMD_ECHO) && pas_ldsc[ln].xmte) {
|
||||
TMLN *lp = &pas_ldsc[ln]; /* get line */
|
||||
tmxr_putc_ln (lp, out); /* output char */
|
||||
tmxr_poll_tx (&pas_desc); /* poll xmt */
|
||||
}
|
||||
} /* end else normal */
|
||||
} /* end if char */
|
||||
} /* end if conn */
|
||||
else if ((pas_sta[ln] & STA_CROF) == 0) { /* not conn, was conn? */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); /* intr */
|
||||
}
|
||||
} /* end for */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -343,25 +371,29 @@ return SCPE_OK;
|
||||
t_stat paso_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
uint32 ln = uptr - pasl_unit; /* line # */
|
||||
uint32 ln = uptr - pasl_unit; /* line # */
|
||||
|
||||
if (pas_ldsc[ln].conn) { /* connected? */
|
||||
if (pas_ldsc[ln].xmte) { /* xmt enabled? */
|
||||
TMLN *lp = &pas_ldsc[ln]; /* get line */
|
||||
if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */
|
||||
c = pas_par (pas_cmd[ln], pas_xbuf[ln]);/* apply parity */
|
||||
else { /* UC or 7b */
|
||||
c = pas_xbuf[ln] & 0x7F; /* mask char */
|
||||
if ((pasl_unit[ln].flags & UNIT_UC) && islower (c))
|
||||
c = toupper (c); } /* cvt to UC */
|
||||
tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&pas_desc); } /* poll xmt */
|
||||
else { /* buf full */
|
||||
tmxr_poll_tx (&pas_desc); /* poll xmt */
|
||||
sim_activate (uptr, pasl_unit[ln].wait); /* wait */
|
||||
return SCPE_OK; } }
|
||||
pas_sta[ln] = pas_sta[ln] & ~STA_BSY; /* not busy */
|
||||
if (pas_xarm[ln]) SET_INT (v_PASX + ln + ln); /* set intr */
|
||||
if (pas_ldsc[ln].conn) { /* connected? */
|
||||
if (pas_ldsc[ln].xmte) { /* xmt enabled? */
|
||||
TMLN *lp = &pas_ldsc[ln]; /* get line */
|
||||
if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */
|
||||
c = pas_par (pas_cmd[ln], pas_xbuf[ln]); /* apply parity */
|
||||
else { /* UC or 7b */
|
||||
c = pas_xbuf[ln] & 0x7F; /* mask char */
|
||||
if ((pasl_unit[ln].flags & UNIT_UC) && islower (c))
|
||||
c = toupper (c); /* cvt to UC */
|
||||
}
|
||||
tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&pas_desc); /* poll xmt */
|
||||
}
|
||||
else { /* buf full */
|
||||
tmxr_poll_tx (&pas_desc); /* poll xmt */
|
||||
sim_activate (uptr, pasl_unit[ln].wait); /* wait */
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
pas_sta[ln] = pas_sta[ln] & ~STA_BSY; /* not busy */
|
||||
if (pas_xarm[ln]) SET_INT (v_PASX + ln + ln); /* set intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -369,66 +401,77 @@ int32 pas_par (int32 cmd, int32 c)
|
||||
{
|
||||
int32 pf = GET_PAR (cmd);
|
||||
static const uint8 odd_par[] = {
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 00 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 10 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 20 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 30 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 40 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 50 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 60 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 70 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 80 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 90 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* A0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* B0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* C0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* D0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* E0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* F0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80 };
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 00 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 10 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 20 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 30 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 40 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 50 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 60 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 70 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 80 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 90 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* A0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* B0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* C0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* D0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* E0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* F0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80
|
||||
};
|
||||
|
||||
switch (pf) { /* case on parity */
|
||||
|
||||
case PAR_ODD:
|
||||
return (odd_par[c & 0x7F]) | (c & 0x7F);
|
||||
|
||||
case PAR_EVEN:
|
||||
return (odd_par[c & 0x7F] ^ 0x80) | (c & 0x7F);
|
||||
|
||||
case PAR_NONE:
|
||||
case PAR_RAW:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pf) { /* case on parity */
|
||||
case PAR_ODD:
|
||||
return (odd_par[c & 0x7F]) | (c & 0x7F);
|
||||
case PAR_EVEN:
|
||||
return (odd_par[c & 0x7F] ^ 0x80) | (c & 0x7F);
|
||||
case PAR_NONE:
|
||||
case PAR_RAW:
|
||||
break; }
|
||||
return c & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat pas_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i, t;
|
||||
|
||||
if (dptr->flags & DEV_DIS) { /* disabled? */
|
||||
pas_dev.flags = pas_dev.flags | DEV_DIS; /* disable lines */
|
||||
pasl_dev.flags = pasl_dev.flags | DEV_DIS; }
|
||||
else { pas_dev.flags = pas_dev.flags & ~DEV_DIS; /* enable lines */
|
||||
pasl_dev.flags = pasl_dev.flags & ~DEV_DIS; }
|
||||
if (pas_unit.flags & UNIT_ATT) { /* master att? */
|
||||
if (!sim_is_active (&pas_unit)) {
|
||||
t = sim_rtcn_init (pas_unit.wait, TMR_PAS);
|
||||
sim_activate (&pas_unit, t); } } /* activate */
|
||||
else sim_cancel (&pas_unit); /* else stop */
|
||||
if (dptr->flags & DEV_DIS) { /* disabled? */
|
||||
pas_dev.flags = pas_dev.flags | DEV_DIS; /* disable lines */
|
||||
pasl_dev.flags = pasl_dev.flags | DEV_DIS;
|
||||
}
|
||||
else {
|
||||
pas_dev.flags = pas_dev.flags & ~DEV_DIS; /* enable lines */
|
||||
pasl_dev.flags = pasl_dev.flags & ~DEV_DIS;
|
||||
}
|
||||
if (pas_unit.flags & UNIT_ATT) { /* master att? */
|
||||
if (!sim_is_active (&pas_unit)) {
|
||||
t = sim_rtcn_init (pas_unit.wait, TMR_PAS);
|
||||
sim_activate (&pas_unit, t); /* activate */
|
||||
}
|
||||
}
|
||||
else sim_cancel (&pas_unit); /* else stop */
|
||||
for (i = 0; i < PAS_LINES; i++) pas_reset_ln (i);
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -439,10 +482,10 @@ t_stat pas_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_attach (&pas_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) return r; /* error */
|
||||
r = tmxr_attach (&pas_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) return r; /* error */
|
||||
sim_rtcn_init (pas_unit.wait, TMR_PAS);
|
||||
sim_activate (uptr, 100); /* quick poll */
|
||||
sim_activate (uptr, 100); /* quick poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -453,9 +496,9 @@ t_stat pas_detach (UNIT *uptr)
|
||||
int32 i;
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_detach (&pas_desc, uptr); /* detach */
|
||||
for (i = 0; i < PAS_LINES; i++) pas_ldsc[i].rcve = 0; /* disable rcv */
|
||||
sim_cancel (uptr); /* stop poll */
|
||||
r = tmxr_detach (&pas_desc, uptr); /* detach */
|
||||
for (i = 0; i < PAS_LINES; i++) pas_ldsc[i].rcve = 0; /* disable rcv */
|
||||
sim_cancel (uptr); /* stop poll */
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -475,14 +518,17 @@ return SCPE_OK;
|
||||
|
||||
t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i;
|
||||
int32 i, t;
|
||||
|
||||
for (i = 0; (i < PAS_LINES) && (pas_ldsc[i].conn == 0); i++) ;
|
||||
if (i < PAS_LINES) {
|
||||
for (i = 0; i < PAS_LINES; i++) {
|
||||
if (pas_ldsc[i].conn)
|
||||
if (val) tmxr_fconns (st, &pas_ldsc[i], i);
|
||||
else tmxr_fstats (st, &pas_ldsc[i], i); } }
|
||||
for (i = t = 0; i < PAS_LINES; i++) t = t + (pas_ldsc[i].conn != 0);
|
||||
if (t) {
|
||||
for (i = 0; i < PAS_LINES; i++) {
|
||||
if (pas_ldsc[i].conn) {
|
||||
if (val) tmxr_fconns (st, &pas_ldsc[i], i);
|
||||
else tmxr_fstats (st, &pas_ldsc[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else fprintf (st, "all disconnected\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -499,20 +545,24 @@ newln = get_uint (cptr, 10, PAS_LINES, &r);
|
||||
if ((r != SCPE_OK) || (newln == PAS_ENAB)) return r;
|
||||
if (newln == 0) return SCPE_ARG;
|
||||
if (newln < PAS_ENAB) {
|
||||
for (i = newln, t = 0; i < PAS_ENAB; i++) t = t | pas_ldsc[i].conn;
|
||||
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
|
||||
return SCPE_OK;
|
||||
for (i = newln; i < PAS_ENAB; i++) {
|
||||
if (pas_ldsc[i].conn) {
|
||||
tmxr_linemsg (&pas_ldsc[i], "\r\nOperator disconnected line\r\n");
|
||||
tmxr_reset_ln (&pas_ldsc[i]); } /* reset line */
|
||||
pasl_unit[i].flags = pasl_unit[i].flags | UNIT_DIS;
|
||||
pas_reset_ln (i); }
|
||||
}
|
||||
else { for (i = PAS_ENAB; i < newln; i++) {
|
||||
pasl_unit[i].flags = pasl_unit[i].flags & ~UNIT_DIS;
|
||||
pas_reset_ln (i); }
|
||||
}
|
||||
for (i = newln, t = 0; i < PAS_ENAB; i++) t = t | pas_ldsc[i].conn;
|
||||
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
|
||||
return SCPE_OK;
|
||||
for (i = newln; i < PAS_ENAB; i++) {
|
||||
if (pas_ldsc[i].conn) {
|
||||
tmxr_linemsg (&pas_ldsc[i], "\r\nOperator disconnected line\r\n");
|
||||
tmxr_reset_ln (&pas_ldsc[i]); /* reset line */
|
||||
}
|
||||
pasl_unit[i].flags = pasl_unit[i].flags | UNIT_DIS;
|
||||
pas_reset_ln (i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = PAS_ENAB; i < newln; i++) {
|
||||
pasl_unit[i].flags = pasl_unit[i].flags & ~UNIT_DIS;
|
||||
pas_reset_ln (i);
|
||||
}
|
||||
}
|
||||
PAS_ENAB = newln;
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -521,17 +571,17 @@ return SCPE_OK;
|
||||
|
||||
void pas_reset_ln (int32 i)
|
||||
{
|
||||
CLR_INT (v_PAS + i + i); /* clear int */
|
||||
CLR_INT (v_PAS + i + i); /* clear int */
|
||||
CLR_ENB (v_PAS + i + i);
|
||||
CLR_INT (v_PASX + i + i); /* disable int */
|
||||
CLR_INT (v_PASX + i + i); /* disable int */
|
||||
CLR_ENB (v_PASX + i + i);
|
||||
pas_rarm[i] = pas_xarm[i] = 0; /* disarm int */
|
||||
pas_rbuf[i] = pas_xbuf[i] = 0; /* clear state */
|
||||
pas_rarm[i] = pas_xarm[i] = 0; /* disarm int */
|
||||
pas_rbuf[i] = pas_xbuf[i] = 0; /* clear state */
|
||||
pas_cmd[i] = 0;
|
||||
pas_rchp[i] = 0;
|
||||
pas_sta[i] = 0;
|
||||
if (pas_ldsc[i].conn == 0) /* clear carrier */
|
||||
pas_sta[i] = pas_sta[i] | STA_CROF;
|
||||
if (pas_ldsc[i].conn == 0) /* clear carrier */
|
||||
pas_sta[i] = pas_sta[i] | STA_CROF;
|
||||
sim_cancel (&pasl_unit[i]);
|
||||
return;
|
||||
}
|
||||
@@ -543,9 +593,10 @@ void pas_ini (t_bool dtpl)
|
||||
int32 i, j;
|
||||
|
||||
for (i = j = 0; i < PAS_ENAB; i++) {
|
||||
pas_tplte[j] = j;
|
||||
pas_tplte[j + 1] = j + o_PASX;
|
||||
j = j + 2; }
|
||||
pas_tplte[j] = j;
|
||||
pas_tplte[j + 1] = j + o_PASX;
|
||||
j = j + 2;
|
||||
}
|
||||
pas_tplte[j] = TPL_END;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id_pt.c: Interdata paper tape reader
|
||||
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,14 +19,14 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
pt paper tape reader and punch
|
||||
pt paper tape reader and punch
|
||||
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
10-Apr-03 RMS Fixed type problem in ptr service (from Mark Pizzolato)
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
10-Apr-03 RMS Fixed type problem in ptr service (from Mark Pizzolato)
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
@@ -34,25 +34,25 @@
|
||||
|
||||
/* Device definitions */
|
||||
|
||||
#define PTR 0 /* unit subscripts */
|
||||
#define PTP 1
|
||||
#define PTR 0 /* unit subscripts */
|
||||
#define PTP 1
|
||||
|
||||
#define STA_OVR 0x80 /* overrun */
|
||||
#define STA_NMTN 0x10 /* no motion */
|
||||
#define STA_MASK (STA_BSY | STA_OVR | STA_DU) /* static bits */
|
||||
#define SET_EX (STA_OVR | STA_NMTN) /* set EX */
|
||||
#define STA_OVR 0x80 /* overrun */
|
||||
#define STA_NMTN 0x10 /* no motion */
|
||||
#define STA_MASK (STA_BSY | STA_OVR | STA_DU) /* static bits */
|
||||
#define SET_EX (STA_OVR | STA_NMTN) /* set EX */
|
||||
|
||||
#define CMD_V_RUN 4 /* run/stop */
|
||||
#define CMD_V_SLEW 2 /* slew/step */
|
||||
#define CMD_V_RD 0 /* read/write */
|
||||
#define CMD_V_RUN 4 /* run/stop */
|
||||
#define CMD_V_SLEW 2 /* slew/step */
|
||||
#define CMD_V_RD 0 /* read/write */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint32 pt_run = 0, pt_slew = 0; /* ptr modes */
|
||||
uint32 pt_rd = 1, pt_chp = 0; /* pt state */
|
||||
uint32 pt_arm = 0; /* int arm */
|
||||
uint32 pt_sta = STA_BSY; /* status */
|
||||
uint32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
uint32 pt_run = 0, pt_slew = 0; /* ptr modes */
|
||||
uint32 pt_rd = 1, pt_chp = 0; /* pt state */
|
||||
uint32 pt_arm = 0; /* int arm */
|
||||
uint32 pt_sta = STA_BSY; /* status */
|
||||
uint32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
|
||||
DEVICE pt_dev;
|
||||
uint32 pt (uint32 dev, uint32 op, uint32 dat);
|
||||
@@ -60,270 +60,278 @@ t_stat ptr_svc (UNIT *uptr);
|
||||
t_stat ptp_svc (UNIT *uptr);
|
||||
t_stat pt_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat pt_reset (DEVICE *dptr);
|
||||
|
||||
|
||||
/* PT data structures
|
||||
|
||||
pt_dev PT device descriptor
|
||||
pt_unit PT unit descriptors
|
||||
pt_reg PT register list
|
||||
pt_dev PT device descriptor
|
||||
pt_unit PT unit descriptors
|
||||
pt_reg PT register list
|
||||
*/
|
||||
|
||||
DIB pt_dib = { d_PT, -1, v_PT, NULL, &pt, NULL };
|
||||
|
||||
UNIT pt_unit[] = {
|
||||
{ UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT },
|
||||
{ UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0),
|
||||
SERIAL_OUT_WAIT } };
|
||||
{ UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT },
|
||||
{ UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG pt_reg[] = {
|
||||
{ HRDATA (STA, pt_sta, 8) },
|
||||
{ HRDATA (RBUF, pt_unit[PTR].buf, 8) },
|
||||
{ DRDATA (RPOS, pt_unit[PTR].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (RTIME, pt_unit[PTR].wait, 24), PV_LEFT },
|
||||
{ FLDATA (RSTOP_IOE, ptr_stopioe, 0) },
|
||||
{ HRDATA (PBUF, pt_unit[PTP].buf, 8) },
|
||||
{ DRDATA (PPOS, pt_unit[PTP].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (PTIME, pt_unit[PTP].wait, 24), PV_LEFT },
|
||||
{ FLDATA (PSTOP_IOE, ptp_stopioe, 0) },
|
||||
{ FLDATA (IREQ, int_req[l_PT], i_PT) },
|
||||
{ FLDATA (IENB, int_enb[l_PT], i_PT) },
|
||||
{ FLDATA (IARM, pt_arm, 0) },
|
||||
{ FLDATA (RD, pt_rd, 0) },
|
||||
{ FLDATA (RUN, pt_run, 0) },
|
||||
{ FLDATA (SLEW, pt_slew, 0) },
|
||||
{ FLDATA (CHP, pt_chp, 0) },
|
||||
{ HRDATA (DEVNO, pt_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
{ HRDATA (STA, pt_sta, 8) },
|
||||
{ HRDATA (RBUF, pt_unit[PTR].buf, 8) },
|
||||
{ DRDATA (RPOS, pt_unit[PTR].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (RTIME, pt_unit[PTR].wait, 24), PV_LEFT },
|
||||
{ FLDATA (RSTOP_IOE, ptr_stopioe, 0) },
|
||||
{ HRDATA (PBUF, pt_unit[PTP].buf, 8) },
|
||||
{ DRDATA (PPOS, pt_unit[PTP].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (PTIME, pt_unit[PTP].wait, 24), PV_LEFT },
|
||||
{ FLDATA (PSTOP_IOE, ptp_stopioe, 0) },
|
||||
{ FLDATA (IREQ, int_req[l_PT], i_PT) },
|
||||
{ FLDATA (IENB, int_enb[l_PT], i_PT) },
|
||||
{ FLDATA (IARM, pt_arm, 0) },
|
||||
{ FLDATA (RD, pt_rd, 0) },
|
||||
{ FLDATA (RUN, pt_run, 0) },
|
||||
{ FLDATA (SLEW, pt_slew, 0) },
|
||||
{ FLDATA (CHP, pt_chp, 0) },
|
||||
{ HRDATA (DEVNO, pt_dib.dno, 8), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB pt_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "devno", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "devno", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE pt_dev = {
|
||||
"PT", pt_unit, pt_reg, pt_mod,
|
||||
2, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &pt_reset,
|
||||
&pt_boot, NULL, NULL,
|
||||
&pt_dib, DEV_DISABLE };
|
||||
|
||||
"PT", pt_unit, pt_reg, pt_mod,
|
||||
2, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &pt_reset,
|
||||
&pt_boot, NULL, NULL,
|
||||
&pt_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* Paper tape: IO routine */
|
||||
|
||||
uint32 pt (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 t, old_rd, old_run;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_OC: /* command */
|
||||
old_rd = pt_rd; /* save curr rw */
|
||||
old_run = pt_run; /* save curr run */
|
||||
pt_arm = int_chg (v_PT, dat, pt_arm); /* upd int ctrl */
|
||||
pt_rd = io_2b (dat, CMD_V_RD, pt_rd); /* upd read/wr */
|
||||
if (old_rd != pt_rd) { /* rw change? */
|
||||
pt_sta = pt_sta & ~STA_OVR; /* clr overrun */
|
||||
if (sim_is_active (&pt_unit[pt_rd? PTR: PTP])) {
|
||||
pt_sta = pt_sta | STA_BSY; /* busy = 1 */
|
||||
CLR_INT (v_PT); } /* clear int */
|
||||
else { /* not active */
|
||||
pt_sta = pt_sta & ~STA_BSY; /* busy = 0 */
|
||||
if (pt_arm) SET_INT (v_PT); } } /* no, set int */
|
||||
if (pt_rd) { /* reader? */
|
||||
pt_run = io_2b (dat, CMD_V_RUN, pt_run); /* upd run/stop */
|
||||
pt_slew = io_2b (dat, CMD_V_SLEW, pt_slew); /* upd slew/inc */
|
||||
if (pt_run) { /* run set? */
|
||||
if (old_run == 0) { /* run 0 -> 1? */
|
||||
sim_activate (&pt_unit[PTR], pt_unit[PTR].wait);
|
||||
pt_sta = pt_sta & ~STA_DU; } } /* clear eof */
|
||||
else sim_cancel (&pt_unit[PTR]); } /* clr, stop rdr */
|
||||
else pt_sta = pt_sta & ~STA_DU; /* punch, clr eof */
|
||||
break;
|
||||
case IO_RD: /* read */
|
||||
if (pt_run && !pt_slew) { /* incremental? */
|
||||
sim_activate (&pt_unit[PTR], pt_unit[PTR].wait);
|
||||
pt_sta = pt_sta & ~STA_DU; } /* clr eof */
|
||||
pt_chp = 0; /* clr char pend */
|
||||
if (pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */
|
||||
return (pt_unit[PTR].buf & 0xFF); /* return char */
|
||||
case IO_WD: /* write */
|
||||
pt_unit[PTP].buf = dat & DMASK8; /* save char */
|
||||
if (!pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */
|
||||
sim_activate (&pt_unit[PTP], pt_unit[PTP].wait);
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = pt_sta & STA_MASK; /* get status */
|
||||
if (pt_rd && !pt_run && !sim_is_active (&pt_unit[PTR]))
|
||||
t = t | STA_NMTN; /* stopped? */
|
||||
if ((pt_unit[pt_rd? PTR: PTP].flags & UNIT_ATT) == 0)
|
||||
t = t | STA_DU; /* offline? */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for EX */
|
||||
return t; }
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_OC: /* command */
|
||||
old_rd = pt_rd; /* save curr rw */
|
||||
old_run = pt_run; /* save curr run */
|
||||
pt_arm = int_chg (v_PT, dat, pt_arm); /* upd int ctrl */
|
||||
pt_rd = io_2b (dat, CMD_V_RD, pt_rd); /* upd read/wr */
|
||||
if (old_rd != pt_rd) { /* rw change? */
|
||||
pt_sta = pt_sta & ~STA_OVR; /* clr overrun */
|
||||
if (sim_is_active (&pt_unit[pt_rd? PTR: PTP])) {
|
||||
pt_sta = pt_sta | STA_BSY; /* busy = 1 */
|
||||
CLR_INT (v_PT); /* clear int */
|
||||
}
|
||||
else { /* not active */
|
||||
pt_sta = pt_sta & ~STA_BSY; /* busy = 0 */
|
||||
if (pt_arm) SET_INT (v_PT); /* no, set int */
|
||||
}
|
||||
}
|
||||
if (pt_rd) { /* reader? */
|
||||
pt_run = io_2b (dat, CMD_V_RUN, pt_run); /* upd run/stop */
|
||||
pt_slew = io_2b (dat, CMD_V_SLEW, pt_slew); /* upd slew/inc */
|
||||
if (pt_run) { /* run set? */
|
||||
if (old_run == 0) { /* run 0 -> 1? */
|
||||
sim_activate (&pt_unit[PTR], pt_unit[PTR].wait);
|
||||
pt_sta = pt_sta & ~STA_DU; /* clear eof */
|
||||
}
|
||||
}
|
||||
else sim_cancel (&pt_unit[PTR]); /* clr, stop rdr */
|
||||
}
|
||||
else pt_sta = pt_sta & ~STA_DU; /* punch, clr eof */
|
||||
break;
|
||||
|
||||
case IO_RD: /* read */
|
||||
if (pt_run && !pt_slew) { /* incremental? */
|
||||
sim_activate (&pt_unit[PTR], pt_unit[PTR].wait);
|
||||
pt_sta = pt_sta & ~STA_DU; /* clr eof */
|
||||
}
|
||||
pt_chp = 0; /* clr char pend */
|
||||
if (pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */
|
||||
return (pt_unit[PTR].buf & 0xFF); /* return char */
|
||||
|
||||
case IO_WD: /* write */
|
||||
pt_unit[PTP].buf = dat & DMASK8; /* save char */
|
||||
if (!pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */
|
||||
sim_activate (&pt_unit[PTP], pt_unit[PTP].wait);
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
t = pt_sta & STA_MASK; /* get status */
|
||||
if (pt_rd && !pt_run && !sim_is_active (&pt_unit[PTR]))
|
||||
t = t | STA_NMTN; /* stopped? */
|
||||
if ((pt_unit[pt_rd? PTR: PTP].flags & UNIT_ATT) == 0)
|
||||
t = t | STA_DU; /* offline? */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for EX */
|
||||
return t;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat ptr_svc (UNIT *uptr)
|
||||
{
|
||||
int32 temp;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptr_stopioe, SCPE_UNATT);
|
||||
if (pt_rd) { /* read mode? */
|
||||
pt_sta = pt_sta & ~STA_BSY; /* clear busy */
|
||||
if (pt_arm) SET_INT (v_PT); /* if armed, intr */
|
||||
if (pt_chp) pt_sta = pt_sta | STA_OVR; } /* overrun? */
|
||||
pt_chp = 1; /* char pending */
|
||||
if ((temp = getc (uptr->fileref)) == EOF) { /* error? */
|
||||
if (feof (uptr->fileref)) { /* eof? */
|
||||
pt_sta = pt_sta | STA_DU; /* set DU */
|
||||
if (ptr_stopioe) printf ("PTR end of file\n");
|
||||
else return SCPE_OK; }
|
||||
else perror ("PTR I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
uptr->buf = temp & DMASK8; /* store char */
|
||||
uptr->pos = uptr->pos + 1; /* incr pos */
|
||||
if (pt_slew) sim_activate (uptr, uptr->wait); /* slew? continue */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptr_stopioe, SCPE_UNATT);
|
||||
if (pt_rd) { /* read mode? */
|
||||
pt_sta = pt_sta & ~STA_BSY; /* clear busy */
|
||||
if (pt_arm) SET_INT (v_PT); /* if armed, intr */
|
||||
if (pt_chp) pt_sta = pt_sta | STA_OVR; /* overrun? */
|
||||
}
|
||||
pt_chp = 1; /* char pending */
|
||||
if ((temp = getc (uptr->fileref)) == EOF) { /* error? */
|
||||
if (feof (uptr->fileref)) { /* eof? */
|
||||
pt_sta = pt_sta | STA_DU; /* set DU */
|
||||
if (ptr_stopioe) printf ("PTR end of file\n");
|
||||
else return SCPE_OK;
|
||||
}
|
||||
else perror ("PTR I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
uptr->buf = temp & DMASK8; /* store char */
|
||||
uptr->pos = uptr->pos + 1; /* incr pos */
|
||||
if (pt_slew) sim_activate (uptr, uptr->wait); /* slew? continue */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ptp_svc (UNIT *uptr)
|
||||
{
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptp_stopioe, SCPE_UNATT);
|
||||
if (!pt_rd) { /* write mode? */
|
||||
pt_sta = pt_sta & ~STA_BSY; /* clear busy */
|
||||
if (pt_arm) SET_INT (v_PT); } /* if armed, intr */
|
||||
if (putc (uptr->buf, uptr -> fileref) == EOF) { /* write char */
|
||||
perror ("PTP I/O error");
|
||||
clearerr (uptr -> fileref);
|
||||
return SCPE_IOERR; }
|
||||
uptr -> pos = uptr -> pos + 1; /* incr pos */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptp_stopioe, SCPE_UNATT);
|
||||
if (!pt_rd) { /* write mode? */
|
||||
pt_sta = pt_sta & ~STA_BSY; /* clear busy */
|
||||
if (pt_arm) SET_INT (v_PT); /* if armed, intr */
|
||||
}
|
||||
if (putc (uptr->buf, uptr -> fileref) == EOF) { /* write char */
|
||||
perror ("PTP I/O error");
|
||||
clearerr (uptr -> fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
uptr -> pos = uptr -> pos + 1; /* incr pos */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat pt_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel (&pt_unit[PTR]); /* deactivate units */
|
||||
sim_cancel (&pt_unit[PTR]); /* deactivate units */
|
||||
sim_cancel (&pt_unit[PTP]);
|
||||
pt_rd = 1; /* read */
|
||||
pt_chp = pt_run = pt_slew = 0; /* stop, inc, disarm */
|
||||
pt_sta = STA_BSY; /* buf empty */
|
||||
CLR_INT (v_PT); /* clear int */
|
||||
CLR_ENB (v_PT); /* disable int */
|
||||
pt_arm = 0; /* disarm int */
|
||||
pt_rd = 1; /* read */
|
||||
pt_chp = pt_run = pt_slew = 0; /* stop, inc, disarm */
|
||||
pt_sta = STA_BSY; /* buf empty */
|
||||
CLR_INT (v_PT); /* clear int */
|
||||
CLR_ENB (v_PT); /* disable int */
|
||||
pt_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define BOOT_START 0x50
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
#define BOOT3_START 0x3E
|
||||
#define BOOT3_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
#define BOOT_START 0x50
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
#define BOOT3_START 0x3E
|
||||
#define BOOT3_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
|
||||
static uint8 boot_rom[] = {
|
||||
0xD5, 0x00, /* ST AL CF */
|
||||
0x00, 0xCF,
|
||||
0x43, 0x00, /* BR 80 */
|
||||
0x00, 0x80
|
||||
};
|
||||
0xD5, 0x00, 0x00, 0xCF, /* ST AL CF */
|
||||
0x43, 0x00, 0x00, 0x80 /* BR 80 */
|
||||
};
|
||||
|
||||
static uint8 boot3_rom[] = {
|
||||
0xC8, 0x20, /* ST LHI 2,80 */
|
||||
0x00, 0x80,
|
||||
0xC8, 0x30, /* LHI 3,1 */
|
||||
0x00, 0x01,
|
||||
0xC8, 0x40, /* LHI 4,CF */
|
||||
0x00, 0xCF,
|
||||
0xD3, 0xA0, /* LB A,78 */
|
||||
0x00, 0x78,
|
||||
0xDE, 0xA0, /* OC A,79 */
|
||||
0x00, 0x79,
|
||||
0x9D, 0xAE, /* LP SSR A,E */
|
||||
0x42, 0xF0, /* BTC F,LP */
|
||||
0x00, 0x52,
|
||||
0x9B, 0xAE, /* RDR A,E */
|
||||
0x08, 0xEE, /* LHR E,E */
|
||||
0x43, 0x30, /* BZ LP */
|
||||
0x00, 0x52,
|
||||
0x43, 0x00, /* BR STO */
|
||||
0x00, 0x6C,
|
||||
0x9D, 0xAE, /* LP1 SSR A,E */
|
||||
0x42, 0xF0, /* BTC F,LP1 */
|
||||
0x00, 0x64,
|
||||
0x9B, 0xAE, /* RDR A,E */
|
||||
0xD2, 0xE2, /* STO STB E,0(2) */
|
||||
0x00, 0x00,
|
||||
0xC1, 0x20, /* BXLE 2,LP1 */
|
||||
0x00, 0x64,
|
||||
0x43, 0x00, /* BR 80 */
|
||||
0x00, 0x80
|
||||
};
|
||||
0xC8, 0x20, 0x00, 0x80, /* ST LHI 2,80 */
|
||||
0xC8, 0x30, 0x00, 0x01, /* LHI 3,1 */
|
||||
0xC8, 0x40, 0x00, 0xCF, /* LHI 4,CF */
|
||||
0xD3, 0xA0, 0x00, 0x78, /* LB A,78 */
|
||||
0xDE, 0xA0, 0x00, 0x79, /* OC A,79 */
|
||||
0x9D, 0xAE, /* LP SSR A,E */
|
||||
0x42, 0xF0, 0x00, 0x52, /* BTC F,LP */
|
||||
0x9B, 0xAE, /* RDR A,E */
|
||||
0x08, 0xEE, /* LHR E,E */
|
||||
0x43, 0x30, 0x00, 0x52, /* BZ LP */
|
||||
0x43, 0x00, 0x00, 0x6C, /* BR STO */
|
||||
0x9D, 0xAE, /* LP1 SSR A,E */
|
||||
0x42, 0xF0, 0x00, 0x64, /* BTC F,LP1 */
|
||||
0x9B, 0xAE, /* RDR A,E */
|
||||
0xD2, 0xE2, 0x00, 0x00, /* STO STB E,0(2) */
|
||||
0xC1, 0x20, 0x00, 0x64, /* BXLE 2,LP1 */
|
||||
0x43, 0x00, 0x00, 0x80 /* BR 80 */
|
||||
};
|
||||
|
||||
t_stat pt_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
extern uint32 PC, dec_flgs;
|
||||
extern uint16 decrom[];
|
||||
|
||||
if (decrom[0xD5] & dec_flgs) /* AL defined? */
|
||||
IOWriteBlk (BOOT3_START, BOOT3_LEN, boot3_rom); /* no, 50 seq */
|
||||
else IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy AL boot */
|
||||
IOWriteB (AL_DEV, pt_dib.dno); /* set dev no */
|
||||
IOWriteB (AL_IOC, 0x99); /* set dev cmd */
|
||||
IOWriteB (AL_SCH, 0); /* clr sch dev no */
|
||||
if (decrom[0xD5] & dec_flgs) /* AL defined? */
|
||||
IOWriteBlk (BOOT3_START, BOOT3_LEN, boot3_rom); /* no, 50 seq */
|
||||
else IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy AL boot */
|
||||
IOWriteB (AL_DEV, pt_dib.dno); /* set dev no */
|
||||
IOWriteB (AL_IOC, 0x99); /* set dev cmd */
|
||||
IOWriteB (AL_SCH, 0); /* clr sch dev no */
|
||||
PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Dump routine */
|
||||
|
||||
#define LOAD_START 0x80
|
||||
#define LOAD_LO 0x8A
|
||||
#define LOAD_HI 0x8E
|
||||
#define LOAD_CS 0x93
|
||||
#define LOAD_LEN (sizeof (load_rom) / sizeof (uint8))
|
||||
#define LOAD_LDR 50
|
||||
#define LOAD_START 0x80
|
||||
#define LOAD_LO 0x8A
|
||||
#define LOAD_HI 0x8E
|
||||
#define LOAD_CS 0x93
|
||||
#define LOAD_LEN (sizeof (load_rom) / sizeof (uint8))
|
||||
#define LOAD_LDR 50
|
||||
|
||||
static uint8 load_rom[] = {
|
||||
0x24, 0x21, /* BOOT LIS R2,1 */
|
||||
0x23, 0x03, /* BS BOOT */
|
||||
0x00, 0x00, /* 32b psw pointer */
|
||||
0x00, 0x00, /* 32b reg pointer */
|
||||
0xC8, 0x10, /* ST LHI R1,lo */
|
||||
0x00, 0x00,
|
||||
0xC8, 0x30, /* LHI R3,hi */
|
||||
0x00, 0x00,
|
||||
0xC8, 0x60, /* LHI R3,cs */
|
||||
0x00, 0x00,
|
||||
0xD3, 0x40, /* LB R4,X'78' */
|
||||
0x00, 0x78,
|
||||
0xDE, 0x40, /* OC R4,X'79' */
|
||||
0x00, 0x79,
|
||||
0x9D, 0x45, /* LDR SSR R4,R5 */
|
||||
0x20, 0x91, /* BTBS 9,.-2 */
|
||||
0x9B, 0x45, /* RDR R4,R5 */
|
||||
0x08, 0x55, /* L(H)R R5,R5 */
|
||||
0x22, 0x34, /* BZS LDR */
|
||||
0xD2, 0x51, /* LOOP STB R5,0(R1) */
|
||||
0x00, 0x00,
|
||||
0x07, 0x65, /* X(H)R R6,R5 */
|
||||
0x9A, 0x26, /* WDR R2,R6 */
|
||||
0x9D, 0x45, /* SSR R4,R5 */
|
||||
0x20, 0x91, /* BTBS 9,.-2 */
|
||||
0x9B, 0x45, /* RDR R4,R5 */
|
||||
0xC1, 0x10, /* BXLE R1,LOOP */
|
||||
0x00, 0xA6,
|
||||
0x24, 0x78, /* LIS R7,8 */
|
||||
0x91, 0x7C, /* SLLS R7,12 */
|
||||
0x95, 0x57, /* EPSR R5,R7 */
|
||||
0x22, 0x03 /* BS .-6 */
|
||||
};
|
||||
0x24, 0x21, /* BOOT LIS R2,1 */
|
||||
0x23, 0x03, /* BS BOOT */
|
||||
0x00, 0x00, /* 32b psw pointer */
|
||||
0x00, 0x00, /* 32b reg pointer */
|
||||
0xC8, 0x10, /* ST LHI R1,lo */
|
||||
0x00, 0x00,
|
||||
0xC8, 0x30, /* LHI R3,hi */
|
||||
0x00, 0x00,
|
||||
0xC8, 0x60, /* LHI R3,cs */
|
||||
0x00, 0x00,
|
||||
0xD3, 0x40, /* LB R4,X'78' */
|
||||
0x00, 0x78,
|
||||
0xDE, 0x40, /* OC R4,X'79' */
|
||||
0x00, 0x79,
|
||||
0x9D, 0x45, /* LDR SSR R4,R5 */
|
||||
0x20, 0x91, /* BTBS 9,.-2 */
|
||||
0x9B, 0x45, /* RDR R4,R5 */
|
||||
0x08, 0x55, /* L(H)R R5,R5 */
|
||||
0x22, 0x34, /* BZS LDR */
|
||||
0xD2, 0x51, /* LOOP STB R5,0(R1) */
|
||||
0x00, 0x00,
|
||||
0x07, 0x65, /* X(H)R R6,R5 */
|
||||
0x9A, 0x26, /* WDR R2,R6 */
|
||||
0x9D, 0x45, /* SSR R4,R5 */
|
||||
0x20, 0x91, /* BTBS 9,.-2 */
|
||||
0x9B, 0x45, /* RDR R4,R5 */
|
||||
0xC1, 0x10, /* BXLE R1,LOOP */
|
||||
0x00, 0xA6,
|
||||
0x24, 0x78, /* LIS R7,8 */
|
||||
0x91, 0x7C, /* SLLS R7,12 */
|
||||
0x95, 0x57, /* EPSR R5,R7 */
|
||||
0x22, 0x03 /* BS .-6 */
|
||||
};
|
||||
|
||||
t_stat pt_dump (FILE *of, char *cptr, char *fnam)
|
||||
{
|
||||
@@ -344,7 +352,7 @@ IOWriteB (LOAD_HI + 1, hi & 0xFF);
|
||||
IOWriteB (LOAD_CS, cs & 0xFF);
|
||||
for (i = 0; i < LOAD_LDR; i++) fputc (0, of);
|
||||
for (i = LOAD_START; i < (LOAD_START + LOAD_LEN); i++)
|
||||
fputc (IOReadB (i), of);
|
||||
fputc (IOReadB (i), of);
|
||||
for (i = 0; i < LOAD_LDR; i++) fputc (0, of);
|
||||
for (i = lo; i <= hi; i++) fputc (IOReadB (i), of);
|
||||
for (i = 0; i < LOAD_LDR; i++) fputc (0, of);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id_tt.c: Interdata teletype
|
||||
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,45 +19,45 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
tt console
|
||||
tt console
|
||||
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
11-Jan-03 RMS Added TTP support
|
||||
22-Dec-02 RMS Added break support
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
11-Jan-03 RMS Added TTP support
|
||||
22-Dec-02 RMS Added break support
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_KSR (1 << UNIT_V_KSR)
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_KSR (1 << UNIT_V_KSR)
|
||||
|
||||
/* Device definitions */
|
||||
|
||||
#define TTI 0
|
||||
#define TTO 1
|
||||
#define TTI 0
|
||||
#define TTO 1
|
||||
|
||||
#define STA_OVR 0x80 /* overrun */
|
||||
#define STA_BRK 0x20 /* break */
|
||||
#define STA_MASK (STA_OVR | STA_BRK | STA_BSY) /* status mask */
|
||||
#define SET_EX (STA_OVR | STA_BRK) /* set EX */
|
||||
#define STA_OVR 0x80 /* overrun */
|
||||
#define STA_BRK 0x20 /* break */
|
||||
#define STA_MASK (STA_OVR | STA_BRK | STA_BSY) /* status mask */
|
||||
#define SET_EX (STA_OVR | STA_BRK) /* set EX */
|
||||
|
||||
#define CMD_V_FDPX 4 /* full/half duplex */
|
||||
#define CMD_V_RD 2 /* read/write */
|
||||
#define CMD_V_FDPX 4 /* full/half duplex */
|
||||
#define CMD_V_RD 2 /* read/write */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint32 tt_sta = STA_BSY; /* status */
|
||||
uint32 tt_fdpx = 1; /* tt mode */
|
||||
uint32 tt_rd = 1, tt_chp = 0; /* tt state */
|
||||
uint32 tt_arm = 0; /* int arm */
|
||||
uint32 tt_sta = STA_BSY; /* status */
|
||||
uint32 tt_fdpx = 1; /* tt mode */
|
||||
uint32 tt_rd = 1, tt_chp = 0; /* tt state */
|
||||
uint32 tt_arm = 0; /* int arm */
|
||||
|
||||
uint32 tt (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat tti_svc (UNIT *uptr);
|
||||
@@ -66,96 +66,109 @@ t_stat tt_reset (DEVICE *dptr);
|
||||
t_stat tt_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat tt_set_break (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat tt_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
|
||||
/* TT data structures
|
||||
|
||||
tt_dev TT device descriptor
|
||||
tt_unit TT unit descriptors
|
||||
tt_reg TT register list
|
||||
tt_mod TT modifiers list
|
||||
tt_dev TT device descriptor
|
||||
tt_unit TT unit descriptors
|
||||
tt_reg TT register list
|
||||
tt_mod TT modifiers list
|
||||
*/
|
||||
|
||||
DIB tt_dib = { d_TT, -1, v_TT, NULL, &tt, NULL };
|
||||
|
||||
UNIT tt_unit[] = {
|
||||
{ UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
{ UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG tt_reg[] = {
|
||||
{ HRDATA (STA, tt_sta, 8) },
|
||||
{ HRDATA (KBUF, tt_unit[TTI].buf, 8) },
|
||||
{ DRDATA (KPOS, tt_unit[TTI].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (KTIME, tt_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ HRDATA (TBUF, tt_unit[TTO].buf, 8) },
|
||||
{ DRDATA (TPOS, tt_unit[TTO].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TTIME, tt_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (IREQ, int_req[l_TT], i_TT) },
|
||||
{ FLDATA (IENB, int_enb[l_TT], i_TT) },
|
||||
{ FLDATA (IARM, tt_arm, 0) },
|
||||
{ FLDATA (RD, tt_rd, 0) },
|
||||
{ FLDATA (FDPX, tt_fdpx, 0) },
|
||||
{ FLDATA (CHP, tt_chp, 0) },
|
||||
{ HRDATA (DEVNO, tt_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
{ HRDATA (STA, tt_sta, 8) },
|
||||
{ HRDATA (KBUF, tt_unit[TTI].buf, 8) },
|
||||
{ DRDATA (KPOS, tt_unit[TTI].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (KTIME, tt_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ HRDATA (TBUF, tt_unit[TTO].buf, 8) },
|
||||
{ DRDATA (TPOS, tt_unit[TTO].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TTIME, tt_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (IREQ, int_req[l_TT], i_TT) },
|
||||
{ FLDATA (IENB, int_enb[l_TT], i_TT) },
|
||||
{ FLDATA (IARM, tt_arm, 0) },
|
||||
{ FLDATA (RD, tt_rd, 0) },
|
||||
{ FLDATA (FDPX, tt_fdpx, 0) },
|
||||
{ FLDATA (CHP, tt_chp, 0) },
|
||||
{ HRDATA (DEVNO, tt_dib.dno, 8), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB tt_mod[] = {
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED",
|
||||
&tt_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED",
|
||||
&tt_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK",
|
||||
&tt_set_break, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, &tt_dib },
|
||||
{ 0 } };
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED",
|
||||
&tt_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED",
|
||||
&tt_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK",
|
||||
&tt_set_break, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, &tt_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE tt_dev = {
|
||||
"TT", tt_unit, tt_reg, tt_mod,
|
||||
2, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &tt_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tt_dib, 0 };
|
||||
|
||||
"TT", tt_unit, tt_reg, tt_mod,
|
||||
2, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &tt_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tt_dib, 0
|
||||
};
|
||||
|
||||
/* Terminal: IO routine */
|
||||
|
||||
uint32 tt (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 old_rd, t;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_OC: /* command */
|
||||
old_rd = tt_rd;
|
||||
tt_arm = int_chg (v_TT, dat, tt_arm); /* upd int ctrl */
|
||||
tt_fdpx = io_2b (dat, CMD_V_FDPX, tt_fdpx); /* upd full/half */
|
||||
tt_rd = io_2b (dat, CMD_V_RD, tt_rd); /* upd rd/write */
|
||||
if (tt_rd != old_rd) { /* rw change? */
|
||||
if (tt_rd? tt_chp: !sim_is_active (&tt_unit[TTO])) {
|
||||
tt_sta = 0; /* busy = 0 */
|
||||
if (tt_arm) SET_INT (v_TT); } /* req intr */
|
||||
else {
|
||||
tt_sta = STA_BSY; /* busy = 1 */
|
||||
CLR_INT (v_TT); } } /* clr int */
|
||||
else tt_sta = tt_sta & ~STA_OVR; /* clr ovflo */
|
||||
break;
|
||||
case IO_RD: /* read */
|
||||
tt_chp = 0; /* clear pend */
|
||||
if (tt_rd) tt_sta = (tt_sta | STA_BSY) & ~STA_OVR;
|
||||
return (tt_unit[TTI].buf & 0xFF);
|
||||
case IO_WD: /* write */
|
||||
tt_unit[TTO].buf = dat & 0xFF; /* save char */
|
||||
if (!tt_rd) tt_sta = tt_sta | STA_BSY; /* set busy */
|
||||
sim_activate (&tt_unit[TTO], tt_unit[TTO].wait);
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = tt_sta & STA_MASK; /* get status */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for EX */
|
||||
return t; }
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_OC: /* command */
|
||||
old_rd = tt_rd;
|
||||
tt_arm = int_chg (v_TT, dat, tt_arm); /* upd int ctrl */
|
||||
tt_fdpx = io_2b (dat, CMD_V_FDPX, tt_fdpx); /* upd full/half */
|
||||
tt_rd = io_2b (dat, CMD_V_RD, tt_rd); /* upd rd/write */
|
||||
if (tt_rd != old_rd) { /* rw change? */
|
||||
if (tt_rd? tt_chp: !sim_is_active (&tt_unit[TTO])) {
|
||||
tt_sta = 0; /* busy = 0 */
|
||||
if (tt_arm) SET_INT (v_TT); /* req intr */
|
||||
}
|
||||
else {
|
||||
tt_sta = STA_BSY; /* busy = 1 */
|
||||
CLR_INT (v_TT); /* clr int */
|
||||
}
|
||||
}
|
||||
else tt_sta = tt_sta & ~STA_OVR; /* clr ovflo */
|
||||
break;
|
||||
|
||||
case IO_RD: /* read */
|
||||
tt_chp = 0; /* clear pend */
|
||||
if (tt_rd) tt_sta = (tt_sta | STA_BSY) & ~STA_OVR;
|
||||
return (tt_unit[TTI].buf & 0xFF);
|
||||
|
||||
case IO_WD: /* write */
|
||||
tt_unit[TTO].buf = dat & 0xFF; /* save char */
|
||||
if (!tt_rd) tt_sta = tt_sta | STA_BSY; /* set busy */
|
||||
sim_activate (&tt_unit[TTO], tt_unit[TTO].wait);
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
t = tt_sta & STA_MASK; /* get status */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for EX */
|
||||
return t;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -165,26 +178,30 @@ t_stat tti_svc (UNIT *uptr)
|
||||
{
|
||||
int32 out, temp;
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
tt_sta = tt_sta & ~STA_BRK; /* clear break */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
|
||||
if (tt_rd) { /* read mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); /* if armed, intr */
|
||||
if (tt_chp) tt_sta = tt_sta | STA_OVR; } /* got char? overrun */
|
||||
tt_chp = 1; /* char pending */
|
||||
out = temp & 0x7F; /* echo is 7B */
|
||||
if (temp & SCPE_BREAK) { /* break? */
|
||||
tt_sta = tt_sta | STA_BRK; /* set status */
|
||||
uptr->buf = 0; } /* no character */
|
||||
else if (uptr->flags & UNIT_KSR) { /* KSR mode? */
|
||||
if (islower (out)) out = toupper (out); /* cvt to UC */
|
||||
uptr->buf = out | 0x80; } /* set high bit */
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
tt_sta = tt_sta & ~STA_BRK; /* clear break */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
|
||||
if (tt_rd) { /* read mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); /* if armed, intr */
|
||||
if (tt_chp) tt_sta = tt_sta | STA_OVR; /* got char? overrun */
|
||||
}
|
||||
tt_chp = 1; /* char pending */
|
||||
out = temp & 0x7F; /* echo is 7B */
|
||||
if (temp & SCPE_BREAK) { /* break? */
|
||||
tt_sta = tt_sta | STA_BRK; /* set status */
|
||||
uptr->buf = 0; /* no character */
|
||||
}
|
||||
else if (uptr->flags & UNIT_KSR) { /* KSR mode? */
|
||||
if (islower (out)) out = toupper (out); /* cvt to UC */
|
||||
uptr->buf = out | 0x80; /* set high bit */
|
||||
}
|
||||
else uptr->buf = temp & ((tt_unit[TTI].flags & UNIT_8B)? 0xFF: 0x7F);
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
if (!tt_fdpx) { /* half duplex? */
|
||||
if (out) sim_putchar (out); /* write char */
|
||||
tt_unit[TTO].pos = tt_unit[TTO].pos + 1; }
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
if (!tt_fdpx) { /* half duplex? */
|
||||
if (out) sim_putchar (out); /* write char */
|
||||
tt_unit[TTO].pos = tt_unit[TTO].pos + 1;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -193,19 +210,23 @@ t_stat tto_svc (UNIT *uptr)
|
||||
int32 ch;
|
||||
t_stat r;
|
||||
|
||||
if (uptr->flags & UNIT_KSR) { /* KSR mode? */
|
||||
ch = uptr->buf & 0x7F; /* mask to 7b */
|
||||
if (islower (ch)) ch = toupper (ch); } /* cvt to UC */
|
||||
if (uptr->flags & UNIT_KSR) { /* KSR mode? */
|
||||
ch = uptr->buf & 0x7F; /* mask to 7b */
|
||||
if (islower (ch)) ch = toupper (ch); /* cvt to UC */
|
||||
}
|
||||
else ch = uptr->buf & ((tt_unit[TTO].flags & UNIT_8B)? 0xFF: 0x7F);
|
||||
if ((uptr->flags & UNIT_8B) || /* KSR or 7b? */
|
||||
((ch != 0) && (ch != 0x7F))) { /* supr NULL, DEL */
|
||||
if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } }
|
||||
if (!tt_rd) { /* write mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); } /* if armed, intr */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
if ((uptr->flags & UNIT_8B) || /* KSR or 7b? */
|
||||
((ch != 0) && (ch != 0x7F))) { /* supr NULL, DEL */
|
||||
if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r);
|
||||
}
|
||||
}
|
||||
if (!tt_rd) { /* write mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); /* if armed, intr */
|
||||
}
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -213,15 +234,15 @@ return SCPE_OK;
|
||||
|
||||
t_stat tt_reset (DEVICE *dptr)
|
||||
{
|
||||
if (dptr->flags & DEV_DIS) sim_cancel (&tt_unit[TTI]); /* dis? cancel poll */
|
||||
else sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* activate input */
|
||||
sim_cancel (&tt_unit[TTO]); /* cancel output */
|
||||
tt_rd = tt_fdpx = 1; /* read, full duplex */
|
||||
tt_chp = 0; /* no char */
|
||||
tt_sta = STA_BSY; /* buffer empty */
|
||||
CLR_INT (v_TT); /* clear int */
|
||||
CLR_ENB (v_TT); /* disable int */
|
||||
tt_arm = 0; /* disarm int */
|
||||
if (dptr->flags & DEV_DIS) sim_cancel (&tt_unit[TTI]); /* dis? cancel poll */
|
||||
else sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* activate input */
|
||||
sim_cancel (&tt_unit[TTO]); /* cancel output */
|
||||
tt_rd = tt_fdpx = 1; /* read, full duplex */
|
||||
tt_chp = 0; /* no char */
|
||||
tt_sta = STA_BSY; /* buffer empty */
|
||||
CLR_INT (v_TT); /* clear int */
|
||||
CLR_ENB (v_TT); /* disable int */
|
||||
tt_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -240,11 +261,12 @@ t_stat tt_set_break (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (tt_dev.flags & DEV_DIS) return SCPE_NOFNC;
|
||||
tt_sta = tt_sta | STA_BRK;
|
||||
if (tt_rd) { /* read mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); } /* if armed, intr */
|
||||
sim_cancel (&tt_unit[TTI]); /* restart TT poll */
|
||||
sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* so brk is seen */
|
||||
if (tt_rd) { /* read mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); /* if armed, intr */
|
||||
}
|
||||
sim_cancel (&tt_unit[TTI]); /* restart TT poll */
|
||||
sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* so brk is seen */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id_ttp.c: Interdata PASLA console interface
|
||||
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,49 +19,49 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
ttp console (on PAS)
|
||||
ttp console (on PAS)
|
||||
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
|
||||
#define TTI 0
|
||||
#define TTO 1
|
||||
#define TTI 0
|
||||
#define TTO 1
|
||||
|
||||
/* Status byte */
|
||||
|
||||
#define STA_OVR 0x80 /* overrun RO */
|
||||
#define STA_PF 0x40 /* parity err RO */
|
||||
#define STA_FR 0x20 /* framing err RO */
|
||||
#define STA_RCV (STA_OVR|STA_PF|STA_FR)
|
||||
#define SET_EX (STA_OVR|STA_PF|STA_FR)
|
||||
#define STA_XMT (STA_BSY)
|
||||
#define STA_OVR 0x80 /* overrun RO */
|
||||
#define STA_PF 0x40 /* parity err RO */
|
||||
#define STA_FR 0x20 /* framing err RO */
|
||||
#define STA_RCV (STA_OVR|STA_PF|STA_FR)
|
||||
#define SET_EX (STA_OVR|STA_PF|STA_FR)
|
||||
#define STA_XMT (STA_BSY)
|
||||
|
||||
/* Command bytes 1,0 */
|
||||
|
||||
#define CMD_ECHO (0x10 << 8) /* echoplex */
|
||||
#define CMD_WRT (0x02 << 8) /* write/read */
|
||||
#define CMD_TYP 0x01 /* command type */
|
||||
#define CMD_ECHO (0x10 << 8) /* echoplex */
|
||||
#define CMD_WRT (0x02 << 8) /* write/read */
|
||||
#define CMD_TYP 0x01 /* command type */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint32 ttp_sta = 0; /* status */
|
||||
uint32 ttp_cmd = 0; /* command */
|
||||
uint32 ttp_kchp = 0; /* rcvr chr pend */
|
||||
uint32 ttp_karm = 0; /* rcvr int armed */
|
||||
uint32 ttp_tarm = 0; /* xmt int armed */
|
||||
uint32 ttp_sta = 0; /* status */
|
||||
uint32 ttp_cmd = 0; /* command */
|
||||
uint32 ttp_kchp = 0; /* rcvr chr pend */
|
||||
uint32 ttp_karm = 0; /* rcvr int armed */
|
||||
uint32 ttp_tarm = 0; /* xmt int armed */
|
||||
uint8 ttp_tplte[] = { 0, 1, TPL_END };
|
||||
|
||||
uint32 ttp (uint32 dev, uint32 op, uint32 dat);
|
||||
@@ -73,56 +73,58 @@ t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
extern int32 pas_par (int32 cmd, int32 c);
|
||||
|
||||
|
||||
/* TTP data structures */
|
||||
|
||||
DIB ttp_dib = { d_TTP, -1, v_TTP, ttp_tplte, &ttp, NULL };
|
||||
|
||||
UNIT ttp_unit[] = {
|
||||
{ UDATA (&ttpi_svc, 0, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&ttpo_svc, 0, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
{ UDATA (&ttpi_svc, 0, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&ttpo_svc, 0, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG ttp_reg[] = {
|
||||
{ HRDATA (CMD, ttp_cmd, 16) },
|
||||
{ HRDATA (KBUF, ttp_unit[TTI].buf, 8) },
|
||||
{ DRDATA (KPOS, ttp_unit[TTI].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (KTIME, ttp_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (KIREQ, int_req[l_TTP], i_TTP) },
|
||||
{ FLDATA (KIENB, int_enb[l_TTP], i_TTP) },
|
||||
{ FLDATA (KARM, ttp_karm, 0) },
|
||||
{ FLDATA (CHP, ttp_kchp, 0) },
|
||||
{ HRDATA (TBUF, ttp_unit[TTO].buf, 8) },
|
||||
{ DRDATA (TPOS, ttp_unit[TTO].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TTIME, ttp_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (TIREQ, int_req[l_TTP], i_TTP + 1) },
|
||||
{ FLDATA (TIENB, int_enb[l_TTP], i_TTP + 1) },
|
||||
{ FLDATA (TARM, ttp_tarm, 0) },
|
||||
{ HRDATA (DEVNO, ttp_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
{ HRDATA (CMD, ttp_cmd, 16) },
|
||||
{ HRDATA (KBUF, ttp_unit[TTI].buf, 8) },
|
||||
{ DRDATA (KPOS, ttp_unit[TTI].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (KTIME, ttp_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (KIREQ, int_req[l_TTP], i_TTP) },
|
||||
{ FLDATA (KIENB, int_enb[l_TTP], i_TTP) },
|
||||
{ FLDATA (KARM, ttp_karm, 0) },
|
||||
{ FLDATA (CHP, ttp_kchp, 0) },
|
||||
{ HRDATA (TBUF, ttp_unit[TTO].buf, 8) },
|
||||
{ DRDATA (TPOS, ttp_unit[TTO].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TTIME, ttp_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (TIREQ, int_req[l_TTP], i_TTP + 1) },
|
||||
{ FLDATA (TIENB, int_enb[l_TTP], i_TTP + 1) },
|
||||
{ FLDATA (TARM, ttp_tarm, 0) },
|
||||
{ HRDATA (DEVNO, ttp_dib.dno, 8), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ttp_mod[] = {
|
||||
{ UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &ttp_set_mode },
|
||||
{ UNIT_UC+UNIT_8B, 0 , "7b", "7B", &ttp_set_mode },
|
||||
{ UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &ttp_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED",
|
||||
&ttp_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED",
|
||||
&ttp_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK",
|
||||
&ttp_set_break, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &ttp_set_mode },
|
||||
{ UNIT_UC+UNIT_8B, 0 , "7b", "7B", &ttp_set_mode },
|
||||
{ UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &ttp_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED",
|
||||
&ttp_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED",
|
||||
&ttp_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK",
|
||||
&ttp_set_break, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ttp_dev = {
|
||||
"TTP", ttp_unit, ttp_reg, ttp_mod,
|
||||
2, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &ttp_reset,
|
||||
NULL, NULL, NULL,
|
||||
&ttp_dib, DEV_DIS };
|
||||
"TTP", ttp_unit, ttp_reg, ttp_mod,
|
||||
2, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &ttp_reset,
|
||||
NULL, NULL, NULL,
|
||||
&ttp_dib, DEV_DIS
|
||||
};
|
||||
|
||||
|
||||
/* Terminal: I/O routine */
|
||||
|
||||
uint32 ttp (uint32 dev, uint32 op, uint32 dat)
|
||||
@@ -130,64 +132,77 @@ uint32 ttp (uint32 dev, uint32 op, uint32 dat)
|
||||
int32 xmt = dev & 1;
|
||||
int32 t, old_cmd;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read */
|
||||
ttp_kchp = 0; /* clr chr pend */
|
||||
ttp_sta = ttp_sta & ~STA_OVR; /* clr overrun */
|
||||
return ttp_unit[TTI].buf; /* return buf */
|
||||
case IO_WD: /* write */
|
||||
ttp_unit[TTO].buf = dat & 0xFF; /* store char */
|
||||
ttp_sta = ttp_sta | STA_BSY; /* set busy */
|
||||
sim_activate (&ttp_unit[TTO], ttp_unit[TTO].wait);
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
if (xmt) t = ttp_sta & STA_XMT; /* xmt? Just busy */
|
||||
else { /* rcv */
|
||||
t = ttp_sta & STA_RCV; /* get static */
|
||||
if (!ttp_kchp) t = t | STA_BSY; /* no char? busy */
|
||||
if (t & SET_EX) t = t | STA_EX; } /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
old_cmd = ttp_cmd; /* old cmd */
|
||||
if (dat & CMD_TYP) { /* type 1? */
|
||||
ttp_cmd = (ttp_cmd & 0xFF) | (dat << 8);
|
||||
if (ttp_cmd & CMD_WRT) /* write? */
|
||||
ttp_tarm = int_chg (v_TTP + 1, dat, ttp_tarm);
|
||||
else ttp_karm = int_chg (v_TTP, dat, ttp_karm); }
|
||||
else ttp_cmd = (ttp_cmd & ~0xFF) | dat;
|
||||
break; }
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_RD: /* read */
|
||||
ttp_kchp = 0; /* clr chr pend */
|
||||
ttp_sta = ttp_sta & ~STA_OVR; /* clr overrun */
|
||||
return ttp_unit[TTI].buf; /* return buf */
|
||||
|
||||
case IO_WD: /* write */
|
||||
ttp_unit[TTO].buf = dat & 0xFF; /* store char */
|
||||
ttp_sta = ttp_sta | STA_BSY; /* set busy */
|
||||
sim_activate (&ttp_unit[TTO], ttp_unit[TTO].wait);
|
||||
break;
|
||||
|
||||
case IO_SS: /* status */
|
||||
if (xmt) t = ttp_sta & STA_XMT; /* xmt? just busy */
|
||||
else { /* rcv */
|
||||
t = ttp_sta & STA_RCV; /* get static */
|
||||
if (!ttp_kchp) t = t | STA_BSY; /* no char? busy */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for ex */
|
||||
}
|
||||
return t;
|
||||
|
||||
case IO_OC: /* command */
|
||||
old_cmd = ttp_cmd; /* old cmd */
|
||||
if (dat & CMD_TYP) { /* type 1? */
|
||||
ttp_cmd = (ttp_cmd & 0xFF) | (dat << 8);
|
||||
if (ttp_cmd & CMD_WRT) /* write? */
|
||||
ttp_tarm = int_chg (v_TTP + 1, dat, ttp_tarm);
|
||||
else ttp_karm = int_chg (v_TTP, dat, ttp_karm);
|
||||
}
|
||||
else ttp_cmd = (ttp_cmd & ~0xFF) | dat;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat ttpi_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c, out;
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
ttp_sta = ttp_sta & ~STA_FR; /* clear break */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
ttp_sta = ttp_sta & ~STA_PF; /* clear parity err */
|
||||
if (ttp_kchp) ttp_sta = ttp_sta | STA_OVR; /* overrun? */
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
ttp_sta = ttp_sta & ~STA_FR; /* clear break */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
ttp_sta = ttp_sta & ~STA_PF; /* clear parity err */
|
||||
if (ttp_kchp) ttp_sta = ttp_sta | STA_OVR; /* overrun? */
|
||||
if (ttp_karm) SET_INT (v_TTP);
|
||||
if (c & SCPE_BREAK) { /* break? */
|
||||
ttp_sta = ttp_sta | STA_FR; /* framing error */
|
||||
uptr->buf = 0; } /* no character */
|
||||
else { c = c & 0xFF; /* char is 8b */
|
||||
out = c & 0x7F; /* echo is 7b */
|
||||
if (!(uptr->flags & UNIT_8B)) { /* not 8b? */
|
||||
if ((uptr->flags & UNIT_UC) && islower (out))
|
||||
out = toupper (out); /* cvt to UC */
|
||||
c = pas_par (ttp_cmd, out); } /* apply parity */
|
||||
uptr->buf = c; /* save char */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
ttp_kchp = 1; /* char pending */
|
||||
if (ttp_cmd & CMD_ECHO) {
|
||||
sim_putchar (out);
|
||||
ttp_unit[TTO].pos = ttp_unit[TTO].pos + 1; } }
|
||||
if (c & SCPE_BREAK) { /* break? */
|
||||
ttp_sta = ttp_sta | STA_FR; /* framing error */
|
||||
uptr->buf = 0; /* no character */
|
||||
}
|
||||
else { c = c & 0xFF; /* char is 8b */
|
||||
out = c & 0x7F; /* echo is 7b */
|
||||
if (!(uptr->flags & UNIT_8B)) { /* not 8b? */
|
||||
if ((uptr->flags & UNIT_UC) && islower (out))
|
||||
out = toupper (out); /* cvt to UC */
|
||||
c = pas_par (ttp_cmd, out); /* apply parity */
|
||||
}
|
||||
uptr->buf = c; /* save char */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
ttp_kchp = 1; /* char pending */
|
||||
if (ttp_cmd & CMD_ECHO) {
|
||||
sim_putchar (out);
|
||||
ttp_unit[TTO].pos = ttp_unit[TTO].pos + 1;
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -196,19 +211,23 @@ t_stat ttpo_svc (UNIT *uptr)
|
||||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
if (uptr->flags & UNIT_8B) /* 8b? */
|
||||
c = pas_par (ttp_cmd, uptr->buf); /* apply parity */
|
||||
else { c = uptr->buf & 0x7F; /* mask char */
|
||||
if ((uptr->flags & UNIT_UC) && islower (c))
|
||||
c = toupper (c); } /* cvt to UC */
|
||||
if ((uptr->flags & UNIT_8B) || /* UC or 7b? */
|
||||
((c != 0) && (c != 0x7F))){ /* supr NULL, DEL */
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } }
|
||||
ttp_sta = ttp_sta & ~STA_BSY; /* not busy */
|
||||
if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
if (uptr->flags & UNIT_8B) /* 8b? */
|
||||
c = pas_par (ttp_cmd, uptr->buf); /* apply parity */
|
||||
else {
|
||||
c = uptr->buf & 0x7F; /* mask char */
|
||||
if ((uptr->flags & UNIT_UC) && islower (c))
|
||||
c = toupper (c); /* cvt to UC */
|
||||
}
|
||||
if ((uptr->flags & UNIT_8B) || /* UC or 7b? */
|
||||
((c != 0) && (c != 0x7F))){ /* supr NULL, DEL */
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r);
|
||||
}
|
||||
}
|
||||
ttp_sta = ttp_sta & ~STA_BSY; /* not busy */
|
||||
if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -216,16 +235,14 @@ return SCPE_OK;
|
||||
|
||||
t_stat ttp_reset (DEVICE *dptr)
|
||||
{
|
||||
extern DEVICE tt_dev;
|
||||
|
||||
if (dptr->flags & DEV_DIS) sim_cancel (&ttp_unit[TTI]);
|
||||
else sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait);
|
||||
sim_cancel (&ttp_unit[TTO]);
|
||||
CLR_INT (v_TTP); /* clear int */
|
||||
CLR_INT (v_TTP); /* clear int */
|
||||
CLR_ENB (v_TTP);
|
||||
CLR_INT (v_TTP + 1); /* disable int */
|
||||
CLR_INT (v_TTP + 1); /* disable int */
|
||||
CLR_ENB (v_TTP + 1);
|
||||
ttp_karm = ttp_tarm = 0; /* disarm int */
|
||||
ttp_karm = ttp_tarm = 0; /* disarm int */
|
||||
ttp_cmd = 0;
|
||||
ttp_sta = 0;
|
||||
ttp_kchp = 0;
|
||||
@@ -247,8 +264,8 @@ t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (ttp_dev.flags & DEV_DIS) return SCPE_NOFNC;
|
||||
ttp_sta = ttp_sta | STA_FR;
|
||||
if (ttp_karm) SET_INT (v_TTP); /* if armed, intr */
|
||||
sim_cancel (&ttp_unit[TTI]); /* restart TT poll */
|
||||
if (ttp_karm) SET_INT (v_TTP); /* if armed, intr */
|
||||
sim_cancel (&ttp_unit[TTI]); /* restart TT poll */
|
||||
sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* id_uvc.c: Interdata universal clock
|
||||
|
||||
Copyright (c) 2001-2004, Robert M. Supnik
|
||||
Copyright (c) 2001-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,15 +19,16 @@
|
||||
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 Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
pic precision incremental clock
|
||||
lfc line frequency clock
|
||||
pic precision incremental clock
|
||||
lfc line frequency clock
|
||||
|
||||
01-Mar-03 RMS Added SET/SHOW LFC FREQ support
|
||||
Changed precision clock algorithm for V7 UNIX
|
||||
23-Jul-05 RMS Fixed {} error in OC
|
||||
01-Mar-03 RMS Added SET/SHOW LFC FREQ support
|
||||
Changed precision clock algorithm for V7 UNIX
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
@@ -35,35 +36,36 @@
|
||||
|
||||
/* Device definitions */
|
||||
|
||||
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diag mode */
|
||||
#define UNIT_DIAG (1 << UNIT_V_DIAG)
|
||||
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diag mode */
|
||||
#define UNIT_DIAG (1 << UNIT_V_DIAG)
|
||||
|
||||
#define STA_OVF 0x08 /* PIC overflow */
|
||||
#define CMD_STRT 0x20 /* start */
|
||||
#define PIC_V_RATE 12 /* rate */
|
||||
#define PIC_M_RATE 0xF
|
||||
#define PIC_RATE (PIC_M_RATE << PIC_V_RATE)
|
||||
#define PIC_CTR 0x0FFF /* PIC counters */
|
||||
#define GET_RATE(x) (((x) >> PIC_V_RATE) & PIC_M_RATE)
|
||||
#define GET_CTR(x) ((x) & PIC_CTR)
|
||||
#define PIC_TPS 1000
|
||||
#define STA_OVF 0x08 /* PIC overflow */
|
||||
#define CMD_STRT 0x20 /* start */
|
||||
#define PIC_V_RATE 12 /* rate */
|
||||
#define PIC_M_RATE 0xF
|
||||
#define PIC_RATE (PIC_M_RATE << PIC_V_RATE)
|
||||
#define PIC_CTR 0x0FFF /* PIC counters */
|
||||
#define GET_RATE(x) (((x) >> PIC_V_RATE) & PIC_M_RATE)
|
||||
#define GET_CTR(x) ((x) & PIC_CTR)
|
||||
#define PIC_TPS 1000
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
int32 pic_db = 0; /* output buf */
|
||||
int32 pic_ric = 0; /* reset count */
|
||||
int32 pic_cic = 0; /* current count */
|
||||
uint32 pic_save = 0; /* saved time */
|
||||
uint32 pic_ovf = 0; /* overflow */
|
||||
int32 pic_db = 0; /* output buf */
|
||||
int32 pic_ric = 0; /* reset count */
|
||||
int32 pic_cic = 0; /* current count */
|
||||
uint32 pic_save = 0; /* saved time */
|
||||
uint32 pic_ovf = 0; /* overflow */
|
||||
uint32 pic_rdp = 0;
|
||||
uint32 pic_wdp = 0;
|
||||
uint32 pic_cnti = 0; /* instr/timer */
|
||||
uint32 pic_arm = 0; /* int arm */
|
||||
uint32 pic_decr = 1; /* decrement */
|
||||
uint16 pic_time[4] = { 1, 10, 100, 1000 }; /* delays */
|
||||
uint16 pic_usec[4] = { 1, 10, 100, 1000 }; /* usec per tick */
|
||||
static int32 pic_map[16] = { /* map rate to delay */
|
||||
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
|
||||
uint32 pic_cnti = 0; /* instr/timer */
|
||||
uint32 pic_arm = 0; /* int arm */
|
||||
uint32 pic_decr = 1; /* decrement */
|
||||
uint16 pic_time[4] = { 1, 10, 100, 1000 }; /* delays */
|
||||
uint16 pic_usec[4] = { 1, 10, 100, 1000 }; /* usec per tick */
|
||||
static int32 pic_map[16] = { /* map rate to delay */
|
||||
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
|
||||
};
|
||||
|
||||
DEVICE pic_dev;
|
||||
uint32 pic (uint32 dev, uint32 op, uint32 dat);
|
||||
@@ -72,8 +74,8 @@ t_stat pic_reset (DEVICE *dptr);
|
||||
void pic_sched (t_bool strt);
|
||||
uint32 pic_rd_cic (void);
|
||||
|
||||
int32 lfc_tps = 120; /* ticks per */
|
||||
uint32 lfc_arm = 0; /* int arm */
|
||||
int32 lfc_tps = 120; /* ticks per */
|
||||
uint32 lfc_arm = 0; /* int arm */
|
||||
|
||||
DEVICE lfc_dev;
|
||||
uint32 lfc (uint32 dev, uint32 op, uint32 dat);
|
||||
@@ -81,12 +83,12 @@ t_stat lfc_svc (UNIT *uptr);
|
||||
t_stat lfc_reset (DEVICE *dptr);
|
||||
t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat lfc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
|
||||
/* PIC data structures
|
||||
|
||||
pic_dev PIC device descriptor
|
||||
pic_unit PIC unit descriptor
|
||||
pic_reg PIC register list
|
||||
pic_dev PIC device descriptor
|
||||
pic_unit PIC unit descriptor
|
||||
pic_reg PIC register list
|
||||
*/
|
||||
|
||||
DIB pic_dib = { d_PIC, -1, v_PIC, NULL, &pic, NULL };
|
||||
@@ -94,41 +96,44 @@ DIB pic_dib = { d_PIC, -1, v_PIC, NULL, &pic, NULL };
|
||||
UNIT pic_unit = { UDATA (&pic_svc, 0, 0), 1000 };
|
||||
|
||||
REG pic_reg[] = {
|
||||
{ HRDATA (BUF, pic_db, 16) },
|
||||
{ HRDATA (RIC, pic_ric, 16) },
|
||||
{ HRDATA (CIC, pic_cic, 12) },
|
||||
{ FLDATA (RDP, pic_rdp, 0) },
|
||||
{ FLDATA (WDP, pic_wdp, 0) },
|
||||
{ FLDATA (OVF, pic_ovf, 0) },
|
||||
{ FLDATA (IREQ, int_req[l_PIC], i_PIC) },
|
||||
{ FLDATA (IENB, int_enb[l_PIC], i_PIC) },
|
||||
{ FLDATA (IARM, pic_arm, 0) },
|
||||
{ BRDATA (TIME, pic_time, 10, 16, 4), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT },
|
||||
{ DRDATA (DECR, pic_decr, 16), REG_HRO + PV_LEFT },
|
||||
{ FLDATA (MODE, pic_cnti, 0), REG_HRO },
|
||||
{ HRDATA (DEVNO, pic_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
{ HRDATA (BUF, pic_db, 16) },
|
||||
{ HRDATA (RIC, pic_ric, 16) },
|
||||
{ HRDATA (CIC, pic_cic, 12) },
|
||||
{ FLDATA (RDP, pic_rdp, 0) },
|
||||
{ FLDATA (WDP, pic_wdp, 0) },
|
||||
{ FLDATA (OVF, pic_ovf, 0) },
|
||||
{ FLDATA (IREQ, int_req[l_PIC], i_PIC) },
|
||||
{ FLDATA (IENB, int_enb[l_PIC], i_PIC) },
|
||||
{ FLDATA (IARM, pic_arm, 0) },
|
||||
{ BRDATA (TIME, pic_time, 10, 16, 4), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT },
|
||||
{ DRDATA (DECR, pic_decr, 16), REG_HRO + PV_LEFT },
|
||||
{ FLDATA (MODE, pic_cnti, 0), REG_HRO },
|
||||
{ HRDATA (DEVNO, pic_dib.dno, 8), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB pic_mod[] = {
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
||||
{ UNIT_DIAG, 0, NULL, "NORMAL", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
||||
{ UNIT_DIAG, 0, NULL, "NORMAL", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE pic_dev = {
|
||||
"PIC", &pic_unit, pic_reg, pic_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &pic_reset,
|
||||
NULL, NULL, NULL,
|
||||
&pic_dib, DEV_DISABLE };
|
||||
"PIC", &pic_unit, pic_reg, pic_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &pic_reset,
|
||||
NULL, NULL, NULL,
|
||||
&pic_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* LFC data structures
|
||||
|
||||
lfc_dev LFC device descriptor
|
||||
lfc_unit LFC unit descriptor
|
||||
lfc_reg LFC register list
|
||||
lfc_dev LFC device descriptor
|
||||
lfc_unit LFC unit descriptor
|
||||
lfc_reg LFC register list
|
||||
*/
|
||||
|
||||
DIB lfc_dib = { d_LFC, -1, v_LFC, NULL, &lfc, NULL };
|
||||
@@ -136,76 +141,89 @@ DIB lfc_dib = { d_LFC, -1, v_LFC, NULL, &lfc, NULL };
|
||||
UNIT lfc_unit = { UDATA (&lfc_svc, 0, 0), 8333 };
|
||||
|
||||
REG lfc_reg[] = {
|
||||
{ FLDATA (IREQ, int_req[l_LFC], i_LFC) },
|
||||
{ FLDATA (IENB, int_enb[l_LFC], i_LFC) },
|
||||
{ FLDATA (IARM, lfc_arm, 0) },
|
||||
{ DRDATA (TIME, lfc_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, lfc_tps, 8), PV_LEFT + REG_HRO },
|
||||
{ HRDATA (DEVNO, lfc_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
{ FLDATA (IREQ, int_req[l_LFC], i_LFC) },
|
||||
{ FLDATA (IENB, int_enb[l_LFC], i_LFC) },
|
||||
{ FLDATA (IARM, lfc_arm, 0) },
|
||||
{ DRDATA (TIME, lfc_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, lfc_tps, 8), PV_LEFT + REG_HRO },
|
||||
{ HRDATA (DEVNO, lfc_dib.dno, 8), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB lfc_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 100, NULL, "50HZ",
|
||||
&lfc_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 120, NULL, "60HZ",
|
||||
&lfc_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||
NULL, &lfc_show_freq, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ MTAB_XTD|MTAB_VDV, 100, NULL, "50HZ",
|
||||
&lfc_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 120, NULL, "60HZ",
|
||||
&lfc_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||
NULL, &lfc_show_freq, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE lfc_dev = {
|
||||
"LFC", &lfc_unit, lfc_reg, lfc_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &lfc_reset,
|
||||
NULL, NULL, NULL,
|
||||
&lfc_dib, DEV_DISABLE };
|
||||
|
||||
"LFC", &lfc_unit, lfc_reg, lfc_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &lfc_reset,
|
||||
NULL, NULL, NULL,
|
||||
&lfc_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* Precision clock: IO routine */
|
||||
|
||||
uint32 pic (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return HW; /* HW capable */
|
||||
case IO_RH: /* read halfword */
|
||||
pic_rdp = 0; /* clr ptr */
|
||||
return pic_rd_cic ();
|
||||
case IO_RD: /* read */
|
||||
t = pic_rd_cic (); /* get cic */
|
||||
if (pic_rdp) t = t & DMASK8; /* 2nd? get lo */
|
||||
else t = (t >> 8) & DMASK8; /* 1st? get hi */
|
||||
pic_rdp = pic_rdp ^ 1; /* flip byte ptr */
|
||||
return t;
|
||||
case IO_WH: /* write halfword */
|
||||
pic_wdp = 0; /* clr ptr */
|
||||
pic_db = dat;
|
||||
break;
|
||||
case IO_WD: /* write */
|
||||
if (pic_wdp) pic_db = (pic_db & 0xFF00) | dat;
|
||||
else pic_db = (pic_db & 0xFF) | (dat << 8);
|
||||
pic_wdp = pic_wdp ^ 1; /* flip byte ptr */
|
||||
break;
|
||||
case IO_SS: /* sense status */
|
||||
if (pic_ovf) { /* overflow? */
|
||||
pic_ovf = 0; /* clear flag */
|
||||
CLR_INT (v_PIC); /* clear intr */
|
||||
return STA_OVF; }
|
||||
return 0;
|
||||
case IO_OC: /* output cmd */
|
||||
pic_arm = int_chg (v_PIC, dat, pic_arm); /* upd int ctrl */
|
||||
if (dat & CMD_STRT) { /* start? */
|
||||
pic_ric = pic_db; /* new ric */
|
||||
pic_cic = GET_CTR (pic_ric); /* new cic */
|
||||
pic_ovf = 0; /* clear flag */
|
||||
sim_cancel (&pic_unit); /* stop clock */
|
||||
pic_rdp = pic_wdp = 0; /* init ptrs */
|
||||
if (pic_ric & PIC_RATE) pic_sched (TRUE); /* any rate? */
|
||||
} /* end if start */
|
||||
break; } /* end case */
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
return HW; /* HW capable */
|
||||
|
||||
case IO_RH: /* read halfword */
|
||||
pic_rdp = 0; /* clr ptr */
|
||||
return pic_rd_cic ();
|
||||
|
||||
case IO_RD: /* read */
|
||||
t = pic_rd_cic (); /* get cic */
|
||||
if (pic_rdp) t = t & DMASK8; /* 2nd? get lo */
|
||||
else t = (t >> 8) & DMASK8; /* 1st? get hi */
|
||||
pic_rdp = pic_rdp ^ 1; /* flip byte ptr */
|
||||
return t;
|
||||
|
||||
case IO_WH: /* write halfword */
|
||||
pic_wdp = 0; /* clr ptr */
|
||||
pic_db = dat;
|
||||
break;
|
||||
|
||||
case IO_WD: /* write */
|
||||
if (pic_wdp) pic_db = (pic_db & 0xFF00) | dat;
|
||||
else pic_db = (pic_db & 0xFF) | (dat << 8);
|
||||
pic_wdp = pic_wdp ^ 1; /* flip byte ptr */
|
||||
break;
|
||||
|
||||
case IO_SS: /* sense status */
|
||||
if (pic_ovf) { /* overflow? */
|
||||
pic_ovf = 0; /* clear flag */
|
||||
CLR_INT (v_PIC); /* clear intr */
|
||||
return STA_OVF;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case IO_OC: /* output cmd */
|
||||
pic_arm = int_chg (v_PIC, dat, pic_arm); /* upd int ctrl */
|
||||
if (dat & CMD_STRT) { /* start? */
|
||||
pic_ric = pic_db; /* new ric */
|
||||
pic_cic = GET_CTR (pic_ric); /* new cic */
|
||||
pic_ovf = 0; /* clear flag */
|
||||
sim_cancel (&pic_unit); /* stop clock */
|
||||
pic_rdp = pic_wdp = 0; /* init ptrs */
|
||||
if (pic_ric & PIC_RATE) pic_sched (TRUE); /* any rate? */
|
||||
} /* end if start */
|
||||
break;
|
||||
} /* end case */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -215,16 +233,17 @@ t_stat pic_svc (UNIT *uptr)
|
||||
{
|
||||
t_bool rate_chg = FALSE;
|
||||
|
||||
if (pic_cnti) pic_cic = 0; /* one shot? */
|
||||
pic_cic = pic_cic - pic_decr; /* decrement */
|
||||
if (pic_cic <= 0) { /* overflow? */
|
||||
if (pic_wdp) pic_ovf = 1; /* broken wr? set flag */
|
||||
if (pic_arm) SET_INT (v_PIC); /* if armed, intr */
|
||||
if (GET_RATE (pic_ric) != GET_RATE (pic_db)) /* rate change? */
|
||||
rate_chg = TRUE;
|
||||
pic_ric = pic_db; /* new ric */
|
||||
pic_cic = GET_CTR (pic_ric); /* new cic */
|
||||
if ((pic_ric & PIC_RATE) == 0) return SCPE_OK; }
|
||||
if (pic_cnti) pic_cic = 0; /* one shot? */
|
||||
pic_cic = pic_cic - pic_decr; /* decrement */
|
||||
if (pic_cic <= 0) { /* overflow? */
|
||||
if (pic_wdp) pic_ovf = 1; /* broken wr? set flag */
|
||||
if (pic_arm) SET_INT (v_PIC); /* if armed, intr */
|
||||
if (GET_RATE (pic_ric) != GET_RATE (pic_db)) /* rate change? */
|
||||
rate_chg = TRUE;
|
||||
pic_ric = pic_db; /* new ric */
|
||||
pic_cic = GET_CTR (pic_ric); /* new cic */
|
||||
if ((pic_ric & PIC_RATE) == 0) return SCPE_OK;
|
||||
}
|
||||
pic_sched (rate_chg);
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -239,34 +258,38 @@ void pic_sched (t_bool strt)
|
||||
{
|
||||
int32 r, t, intv, intv_usec;
|
||||
|
||||
pic_save = sim_grtime (); /* save start */
|
||||
r = pic_map[GET_RATE (pic_ric)]; /* get mapped rate */
|
||||
intv = pic_cic? pic_cic: 1; /* get cntr */
|
||||
intv_usec = intv * pic_usec[r]; /* cvt to usec */
|
||||
if (!(pic_unit.flags & UNIT_DIAG) && /* not diag? */
|
||||
((intv_usec % 1000) == 0)) { /* 1ms multiple? */
|
||||
pic_cnti = 0; /* clr mode */
|
||||
pic_decr = pic_usec[3 - r]; /* set decrement */
|
||||
if (strt) t = sim_rtcn_init (pic_time[3], TMR_PIC); /* init or */
|
||||
else t = sim_rtcn_calb (PIC_TPS, TMR_PIC); } /* calibrate */
|
||||
else { pic_cnti = 1; /* set mode */
|
||||
pic_decr = 1; /* decr = 1 */
|
||||
t = pic_time[r] * intv; /* interval */
|
||||
if (t == 1) t++; } /* for diagn */
|
||||
sim_activate (&pic_unit, t); /* activate */
|
||||
pic_save = sim_grtime (); /* save start */
|
||||
r = pic_map[GET_RATE (pic_ric)]; /* get mapped rate */
|
||||
intv = pic_cic? pic_cic: 1; /* get cntr */
|
||||
intv_usec = intv * pic_usec[r]; /* cvt to usec */
|
||||
if (!(pic_unit.flags & UNIT_DIAG) && /* not diag? */
|
||||
((intv_usec % 1000) == 0)) { /* 1ms multiple? */
|
||||
pic_cnti = 0; /* clr mode */
|
||||
pic_decr = pic_usec[3 - r]; /* set decrement */
|
||||
if (strt) t = sim_rtcn_init (pic_time[3], TMR_PIC); /* init or */
|
||||
else t = sim_rtcn_calb (PIC_TPS, TMR_PIC); /* calibrate */
|
||||
}
|
||||
else {
|
||||
pic_cnti = 1; /* set mode */
|
||||
pic_decr = 1; /* decr = 1 */
|
||||
t = pic_time[r] * intv; /* interval */
|
||||
if (t == 1) t++; /* for diagn */
|
||||
}
|
||||
sim_activate (&pic_unit, t); /* activate */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Read (interpolated) current interval */
|
||||
|
||||
uint32 pic_rd_cic (void)
|
||||
{
|
||||
if (sim_is_active (&pic_unit) && pic_cnti) { /* running, one shot? */
|
||||
uint32 delta = sim_grtime () - pic_save; /* interval */
|
||||
uint32 tm = pic_time[pic_map[GET_RATE (pic_ric)]]; /* ticks/intv */
|
||||
delta = delta / tm; /* ticks elapsed */
|
||||
if (delta >= ((uint32) pic_cic)) return 0; /* cap value */
|
||||
return pic_cic - delta; }
|
||||
if (sim_is_active (&pic_unit) && pic_cnti) { /* running, one shot? */
|
||||
uint32 delta = sim_grtime () - pic_save; /* interval */
|
||||
uint32 tm = pic_time[pic_map[GET_RATE (pic_ric)]]; /* ticks/intv */
|
||||
delta = delta / tm; /* ticks elapsed */
|
||||
if (delta >= ((uint32) pic_cic)) return 0; /* cap value */
|
||||
return pic_cic - delta;
|
||||
}
|
||||
return pic_cic;
|
||||
}
|
||||
|
||||
@@ -274,34 +297,38 @@ return pic_cic;
|
||||
|
||||
t_stat pic_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel (&pic_unit); /* cancel unit */
|
||||
sim_cancel (&pic_unit); /* cancel unit */
|
||||
pic_ric = pic_cic = 0;
|
||||
pic_db = 0;
|
||||
pic_ovf = 0; /* clear state */
|
||||
pic_ovf = 0; /* clear state */
|
||||
pic_cnti = 0;
|
||||
pic_decr = 1;
|
||||
pic_rdp = pic_wdp = 0;
|
||||
CLR_INT (v_PIC); /* clear int */
|
||||
CLR_ENB (v_PIC); /* disable int */
|
||||
pic_arm = 0; /* disarm int */
|
||||
CLR_INT (v_PIC); /* clear int */
|
||||
CLR_ENB (v_PIC); /* disable int */
|
||||
pic_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Line clock: IO routine */
|
||||
|
||||
uint32 lfc (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_OC: /* command */
|
||||
lfc_arm = int_chg (v_LFC, dat, lfc_arm); /* upd int ctrl */
|
||||
if (lfc_arm && !sim_is_active (&lfc_unit)) { /* starting? */
|
||||
t = sim_rtcn_init (lfc_unit.wait, TMR_LFC);
|
||||
sim_activate (&lfc_unit, t); } /* init clock */
|
||||
break; }
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
|
||||
case IO_OC: /* command */
|
||||
lfc_arm = int_chg (v_LFC, dat, lfc_arm); /* upd int ctrl */
|
||||
if (lfc_arm && !sim_is_active (&lfc_unit)) { /* starting? */
|
||||
t = sim_rtcn_init (lfc_unit.wait, TMR_LFC);
|
||||
sim_activate (&lfc_unit, t); /* init clock */
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -311,11 +338,12 @@ t_stat lfc_svc (UNIT *uptr)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
if (lfc_arm) { /* armed? */
|
||||
SET_INT (v_LFC); /* req intr */
|
||||
if (pic_unit.flags & UNIT_DIAG) t = uptr->wait; /* diag? fixed delay */
|
||||
else t = sim_rtcn_calb (lfc_tps, TMR_LFC); /* else calibrate */
|
||||
sim_activate (uptr, t); } /* reactivate */
|
||||
if (lfc_arm) { /* armed? */
|
||||
SET_INT (v_LFC); /* req intr */
|
||||
if (pic_unit.flags & UNIT_DIAG) t = uptr->wait; /* diag? fixed delay */
|
||||
else t = sim_rtcn_calb (lfc_tps, TMR_LFC); /* else calibrate */
|
||||
sim_activate (uptr, t); /* reactivate */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -323,10 +351,10 @@ return SCPE_OK;
|
||||
|
||||
t_stat lfc_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel (&lfc_unit); /* cancel unit */
|
||||
CLR_INT (v_LFC); /* clear int */
|
||||
CLR_ENB (v_LFC); /* disable int */
|
||||
lfc_arm = 0; /* disarm int */
|
||||
sim_cancel (&lfc_unit); /* cancel unit */
|
||||
CLR_INT (v_LFC); /* clear int */
|
||||
CLR_ENB (v_LFC); /* disable int */
|
||||
lfc_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user