1
0
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:
Bob Supnik
2005-09-09 18:09:00 -07:00
committed by Mark Pizzolato
parent ec60bbf329
commit b7c1eae41f
257 changed files with 107140 additions and 97195 deletions

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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