mirror of
https://github.com/simh/simh.git
synced 2026-01-26 12:02:14 +00:00
Notes For V3.5-0
The source set has been extensively overhauled. For correct viewing, set Visual C++ or Emacs to have tab stops every 4 characters. 1. New Features in 3.4-1 1.1 All Ethernet devices - Added Windows user-defined adapter names (from Timothe Litt) 1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors - Added support for SET <unit>n DISCONNECT 1.3 VAX - Added latent QDSS support - Revised autoconfigure to handle QDSS 1.4 PDP-11 - Revised autoconfigure to handle more casees 2. Bugs Fixed in 3.4-1 2.1 SCP and libraries - Trim trailing spaces on all input (for example, attach file names) - Fixed sim_sock spurious SIGPIPE error in Unix/Linux - Fixed sim_tape misallocation of TPC map array for 64b simulators 2.2 1401 - Fixed bug, CPU reset was clearing SSB through SSG 2.3 PDP-11 - Fixed bug in VH vector display routine - Fixed XU runt packet processing (found by Tim Chapman) 2.4 Interdata - Fixed bug in SHOW PAS CONN/STATS - Fixed potential integer overflow exception in divide 2.5 SDS - Fixed bug in SHOW MUX CONN/STATS 2.6 HP - Fixed bug in SHOW MUX CONN/STATS 2.7 PDP-8 - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.8 PDP-18b - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.9 Nova, Eclipse - Fixed potential integer overflow exception in divide
This commit is contained in:
committed by
Mark Pizzolato
parent
ec60bbf329
commit
b7c1eae41f
154
PDP8/pdp8_clk.c
154
PDP8/pdp8_clk.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_clk.c: PDP-8 real-time clock simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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.
|
||||
|
||||
clk real time clock
|
||||
clk real time clock
|
||||
|
||||
01-Mar-03 RMS Aded SET/SHOW CLK FREQ support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
30-Dec-01 RMS Removed for generalized timers
|
||||
05-Sep-01 RMS Added terminal multiplexor support
|
||||
17-Jul-01 RMS Moved function prototype
|
||||
05-Mar-01 RMS Added clock calibration support
|
||||
01-Mar-03 RMS Aded SET/SHOW CLK FREQ support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
30-Dec-01 RMS Removed for generalized timers
|
||||
05-Sep-01 RMS Added terminal multiplexor support
|
||||
17-Jul-01 RMS Moved function prototype
|
||||
05-Mar-01 RMS Added clock calibration support
|
||||
|
||||
Note: includes the IOT's for both the PDP-8/E and PDP-8/A clocks
|
||||
*/
|
||||
@@ -39,8 +39,8 @@
|
||||
|
||||
extern int32 int_req, int_enable, dev_done, stop_inst;
|
||||
|
||||
int32 clk_tps = 60; /* ticks/second */
|
||||
int32 tmxr_poll = 16000; /* term mux poll */
|
||||
int32 clk_tps = 60; /* ticks/second */
|
||||
int32 tmxr_poll = 16000; /* term mux poll */
|
||||
|
||||
int32 clk (int32 IR, int32 AC);
|
||||
t_stat clk_svc (UNIT *uptr);
|
||||
@@ -50,9 +50,9 @@ t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
/* CLK data structures
|
||||
|
||||
clk_dev CLK device descriptor
|
||||
clk_unit CLK unit descriptor
|
||||
clk_reg CLK register list
|
||||
clk_dev CLK device descriptor
|
||||
clk_unit CLK unit descriptor
|
||||
clk_reg CLK register list
|
||||
*/
|
||||
|
||||
DIB clk_dib = { DEV_CLK, 1, { &clk } };
|
||||
@@ -60,30 +60,33 @@ DIB clk_dib = { DEV_CLK, 1, { &clk } };
|
||||
UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 };
|
||||
|
||||
REG clk_reg[] = {
|
||||
{ FLDATA (DONE, dev_done, INT_V_CLK) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_CLK) },
|
||||
{ FLDATA (INT, int_req, INT_V_CLK) },
|
||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
||||
{ NULL } };
|
||||
{ FLDATA (DONE, dev_done, INT_V_CLK) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_CLK) },
|
||||
{ FLDATA (INT, int_req, INT_V_CLK) },
|
||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB clk_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
|
||||
&clk_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
|
||||
&clk_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||
NULL, &clk_show_freq, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ 0 } };
|
||||
{ MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
|
||||
&clk_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
|
||||
&clk_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||
NULL, &clk_show_freq, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE clk_dev = {
|
||||
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &clk_reset,
|
||||
NULL, NULL, NULL,
|
||||
&clk_dib, 0 };
|
||||
|
||||
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &clk_reset,
|
||||
NULL, NULL, NULL,
|
||||
&clk_dib, 0
|
||||
};
|
||||
|
||||
/* IOT routine
|
||||
|
||||
IOT's 6131-6133 are the PDP-8/E clock
|
||||
@@ -92,34 +95,43 @@ DEVICE clk_dev = {
|
||||
|
||||
int32 clk (int32 IR, int32 AC)
|
||||
{
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 1: /* CLEI */
|
||||
int_enable = int_enable | INT_CLK; /* enable clk ints */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
case 2: /* CLDI */
|
||||
int_enable = int_enable & ~INT_CLK; /* disable clk ints */
|
||||
int_req = int_req & ~INT_CLK; /* update interrupts */
|
||||
return AC;
|
||||
case 3: /* CLSC */
|
||||
if (dev_done & INT_CLK) { /* flag set? */
|
||||
dev_done = dev_done & ~INT_CLK; /* clear flag */
|
||||
int_req = int_req & ~INT_CLK; /* clear int req */
|
||||
return IOT_SKP + AC; }
|
||||
return AC;
|
||||
case 5: /* CLLE */
|
||||
if (AC & 1) int_enable = int_enable | INT_CLK; /* test AC<11> */
|
||||
else int_enable = int_enable & ~INT_CLK;
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
case 6: /* CLCL */
|
||||
dev_done = dev_done & ~INT_CLK; /* clear flag */
|
||||
int_req = int_req & ~INT_CLK; /* clear int req */
|
||||
return AC;
|
||||
case 7: /* CLSK */
|
||||
return (dev_done & INT_CLK)? IOT_SKP + AC: AC;
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 1: /* CLEI */
|
||||
int_enable = int_enable | INT_CLK; /* enable clk ints */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
|
||||
case 2: /* CLDI */
|
||||
int_enable = int_enable & ~INT_CLK; /* disable clk ints */
|
||||
int_req = int_req & ~INT_CLK; /* update interrupts */
|
||||
return AC;
|
||||
|
||||
case 3: /* CLSC */
|
||||
if (dev_done & INT_CLK) { /* flag set? */
|
||||
dev_done = dev_done & ~INT_CLK; /* clear flag */
|
||||
int_req = int_req & ~INT_CLK; /* clear int req */
|
||||
return IOT_SKP + AC;
|
||||
}
|
||||
return AC;
|
||||
|
||||
case 5: /* CLLE */
|
||||
if (AC & 1) int_enable = int_enable | INT_CLK; /* test AC<11> */
|
||||
else int_enable = int_enable & ~INT_CLK;
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
|
||||
case 6: /* CLCL */
|
||||
dev_done = dev_done & ~INT_CLK; /* clear flag */
|
||||
int_req = int_req & ~INT_CLK; /* clear int req */
|
||||
return AC;
|
||||
|
||||
case 7: /* CLSK */
|
||||
return (dev_done & INT_CLK)? IOT_SKP + AC: AC;
|
||||
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
} /* end switch */
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
@@ -128,11 +140,11 @@ t_stat clk_svc (UNIT *uptr)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
dev_done = dev_done | INT_CLK; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
|
||||
sim_activate (&clk_unit, t); /* reactivate unit */
|
||||
tmxr_poll = t; /* set mux poll */
|
||||
dev_done = dev_done | INT_CLK; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
|
||||
sim_activate (&clk_unit, t); /* reactivate unit */
|
||||
tmxr_poll = t; /* set mux poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -140,10 +152,10 @@ return SCPE_OK;
|
||||
|
||||
t_stat clk_reset (DEVICE *dptr)
|
||||
{
|
||||
dev_done = dev_done & ~INT_CLK; /* clear done, int */
|
||||
dev_done = dev_done & ~INT_CLK; /* clear done, int */
|
||||
int_req = int_req & ~INT_CLK;
|
||||
int_enable = int_enable & ~INT_CLK; /* clear enable */
|
||||
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
|
||||
int_enable = int_enable & ~INT_CLK; /* clear enable */
|
||||
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
2063
PDP8/pdp8_cpu.c
2063
PDP8/pdp8_cpu.c
File diff suppressed because it is too large
Load Diff
255
PDP8/pdp8_defs.h
255
PDP8/pdp8_defs.h
@@ -1,6 +1,6 @@
|
||||
/* pdp8_defs.h: PDP-8 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,101 +19,102 @@
|
||||
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.
|
||||
|
||||
13-Oct-03 RMS Added TSC8-75 support
|
||||
04-Oct-02 RMS Added variable device number support
|
||||
20-Jan-02 RMS Fixed bug in TTx interrupt enable initialization
|
||||
25-Nov-01 RMS Added RL8A support
|
||||
16-Sep-01 RMS Added multiple KL support
|
||||
18-Mar-01 RMS Added DF32 support
|
||||
15-Feb-01 RMS Added DECtape support
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
19-Mar-95 RMS Added dynamic memory size
|
||||
02-May-94 RMS Added non-existent memory handling
|
||||
13-Oct-03 RMS Added TSC8-75 support
|
||||
04-Oct-02 RMS Added variable device number support
|
||||
20-Jan-02 RMS Fixed bug in TTx interrupt enable initialization
|
||||
25-Nov-01 RMS Added RL8A support
|
||||
16-Sep-01 RMS Added multiple KL support
|
||||
18-Mar-01 RMS Added DF32 support
|
||||
15-Feb-01 RMS Added DECtape support
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
19-Mar-95 RMS Added dynamic memory size
|
||||
02-May-94 RMS Added non-existent memory handling
|
||||
|
||||
The author gratefully acknowledges the help of Max Burnet, Richie Lary,
|
||||
and Bill Haygood in resolving questions about the PDP-8
|
||||
*/
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
#ifndef _PDP8_DEFS_H_
|
||||
#define _PDP8_DEFS_H_ 0
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_NOTSTD 4 /* non-std devno */
|
||||
#define STOP_DTOFF 5 /* DECtape off reel */
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_NOTSTD 4 /* non-std devno */
|
||||
#define STOP_DTOFF 5 /* DECtape off reel */
|
||||
|
||||
/* Memory */
|
||||
|
||||
#define MAXMEMSIZE 32768 /* max memory size */
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
|
||||
#define MAXMEMSIZE 32768 /* max memory size */
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
|
||||
|
||||
/* IOT subroutine return codes */
|
||||
|
||||
#define IOT_V_SKP 12 /* skip */
|
||||
#define IOT_V_REASON 13 /* reason */
|
||||
#define IOT_SKP (1 << IOT_V_SKP)
|
||||
#define IOT_REASON (1 << IOT_V_REASON)
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
|
||||
#define IOT_V_SKP 12 /* skip */
|
||||
#define IOT_V_REASON 13 /* reason */
|
||||
#define IOT_SKP (1 << IOT_V_SKP)
|
||||
#define IOT_REASON (1 << IOT_V_REASON)
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
|
||||
|
||||
/* Timers */
|
||||
|
||||
#define TMR_CLK 0 /* timer 0 = clock */
|
||||
#define TMR_TTX 1 /* timer 1 = TTx */
|
||||
#define TMR_CLK 0 /* timer 0 = clock */
|
||||
#define TMR_TTX 1 /* timer 1 = TTx */
|
||||
|
||||
/* Device information block */
|
||||
|
||||
#define DEV_MAXBLK 8 /* max dev block */
|
||||
#define DEV_MAX 64 /* total devices */
|
||||
#define DEV_MAXBLK 8 /* max dev block */
|
||||
#define DEV_MAX 64 /* total devices */
|
||||
|
||||
struct pdp8_dib {
|
||||
uint32 dev; /* base dev number */
|
||||
uint32 num; /* number of slots */
|
||||
int32 (*dsp[DEV_MAXBLK])(int32 IR, int32 dat);
|
||||
};
|
||||
|
||||
typedef struct pdp8_dib DIB;
|
||||
typedef struct {
|
||||
uint32 dev; /* base dev number */
|
||||
uint32 num; /* number of slots */
|
||||
int32 (*dsp[DEV_MAXBLK])(int32 IR, int32 dat);
|
||||
} DIB;
|
||||
|
||||
/* Standard device numbers */
|
||||
|
||||
#define DEV_PTR 001 /* paper tape reader */
|
||||
#define DEV_PTP 002 /* paper tape punch */
|
||||
#define DEV_TTI 003 /* console input */
|
||||
#define DEV_TTO 004 /* console output */
|
||||
#define DEV_CLK 013 /* clock */
|
||||
#define DEV_TSC 036
|
||||
#define DEV_KJ8 040 /* extra terminals */
|
||||
#define DEV_DF 060 /* DF32 */
|
||||
#define DEV_RF 060 /* RF08 */
|
||||
#define DEV_RL 060 /* RL8A */
|
||||
#define DEV_LPT 066 /* line printer */
|
||||
#define DEV_MT 070 /* TM8E */
|
||||
#define DEV_RK 074 /* RK8E */
|
||||
#define DEV_RX 075 /* RX8E/RX28 */
|
||||
#define DEV_DTA 076 /* TC08 */
|
||||
#define DEV_TD8E 077 /* TD8E */
|
||||
|
||||
#define DEV_PTR 001 /* paper tape reader */
|
||||
#define DEV_PTP 002 /* paper tape punch */
|
||||
#define DEV_TTI 003 /* console input */
|
||||
#define DEV_TTO 004 /* console output */
|
||||
#define DEV_CLK 013 /* clock */
|
||||
#define DEV_TSC 036
|
||||
#define DEV_KJ8 040 /* extra terminals */
|
||||
#define DEV_DF 060 /* DF32 */
|
||||
#define DEV_RF 060 /* RF08 */
|
||||
#define DEV_RL 060 /* RL8A */
|
||||
#define DEV_LPT 066 /* line printer */
|
||||
#define DEV_MT 070 /* TM8E */
|
||||
#define DEV_RK 074 /* RK8E */
|
||||
#define DEV_RX 075 /* RX8E/RX28 */
|
||||
#define DEV_DTA 076 /* TC08 */
|
||||
#define DEV_TD8E 077 /* TD8E */
|
||||
|
||||
/* Interrupt flags
|
||||
|
||||
The interrupt flags consist of three groups:
|
||||
|
||||
1. Devices with individual interrupt enables. These record
|
||||
their interrupt requests in device_done and their enables
|
||||
in device_enable, and must occupy the low bit positions.
|
||||
1. Devices with individual interrupt enables. These record
|
||||
their interrupt requests in device_done and their enables
|
||||
in device_enable, and must occupy the low bit positions.
|
||||
|
||||
2. Devices without interrupt enables. These record their
|
||||
interrupt requests directly in int_req, and must occupy
|
||||
the middle bit positions.
|
||||
2. Devices without interrupt enables. These record their
|
||||
interrupt requests directly in int_req, and must occupy
|
||||
the middle bit positions.
|
||||
|
||||
3. Overhead. These exist only in int_req and must occupy the
|
||||
high bit positions.
|
||||
3. Overhead. These exist only in int_req and must occupy the
|
||||
high bit positions.
|
||||
|
||||
Because the PDP-8 does not have priority interrupts, the order
|
||||
of devices within groups does not matter.
|
||||
@@ -122,73 +123,75 @@ typedef struct pdp8_dib DIB;
|
||||
to contiguous bits.
|
||||
*/
|
||||
|
||||
#define INT_V_START 0 /* enable start */
|
||||
#define INT_V_LPT (INT_V_START+0) /* line printer */
|
||||
#define INT_V_PTP (INT_V_START+1) /* tape punch */
|
||||
#define INT_V_PTR (INT_V_START+2) /* tape reader */
|
||||
#define INT_V_TTO (INT_V_START+3) /* terminal */
|
||||
#define INT_V_TTI (INT_V_START+4) /* keyboard */
|
||||
#define INT_V_CLK (INT_V_START+5) /* clock */
|
||||
#define INT_V_TTO1 (INT_V_START+6) /* tto1 */
|
||||
#define INT_V_TTO2 (INT_V_START+7) /* tto2 */
|
||||
#define INT_V_TTO3 (INT_V_START+8) /* tto3 */
|
||||
#define INT_V_TTO4 (INT_V_START+9) /* tto4 */
|
||||
#define INT_V_TTI1 (INT_V_START+10) /* tti1 */
|
||||
#define INT_V_TTI2 (INT_V_START+11) /* tti2 */
|
||||
#define INT_V_TTI3 (INT_V_START+12) /* tti3 */
|
||||
#define INT_V_TTI4 (INT_V_START+13) /* tti4 */
|
||||
#define INT_V_DIRECT (INT_V_START+14) /* direct start */
|
||||
#define INT_V_RX (INT_V_DIRECT+0) /* RX8E */
|
||||
#define INT_V_RK (INT_V_DIRECT+1) /* RK8E */
|
||||
#define INT_V_RF (INT_V_DIRECT+2) /* RF08 */
|
||||
#define INT_V_DF (INT_V_DIRECT+3) /* DF32 */
|
||||
#define INT_V_MT (INT_V_DIRECT+4) /* TM8E */
|
||||
#define INT_V_DTA (INT_V_DIRECT+5) /* TC08 */
|
||||
#define INT_V_RL (INT_V_DIRECT+6) /* RL8A */
|
||||
#define INT_V_PWR (INT_V_DIRECT+7) /* power int */
|
||||
#define INT_V_UF (INT_V_DIRECT+8) /* user int */
|
||||
#define INT_V_TSC (INT_V_DIRECT+9) /* TSC8-75 int */
|
||||
#define INT_V_OVHD (INT_V_DIRECT+10) /* overhead start */
|
||||
#define INT_V_NO_ION_PENDING (INT_V_OVHD+0) /* ion pending */
|
||||
#define INT_V_NO_CIF_PENDING (INT_V_OVHD+1) /* cif pending */
|
||||
#define INT_V_ION (INT_V_OVHD+2) /* interrupts on */
|
||||
#define INT_V_START 0 /* enable start */
|
||||
#define INT_V_LPT (INT_V_START+0) /* line printer */
|
||||
#define INT_V_PTP (INT_V_START+1) /* tape punch */
|
||||
#define INT_V_PTR (INT_V_START+2) /* tape reader */
|
||||
#define INT_V_TTO (INT_V_START+3) /* terminal */
|
||||
#define INT_V_TTI (INT_V_START+4) /* keyboard */
|
||||
#define INT_V_CLK (INT_V_START+5) /* clock */
|
||||
#define INT_V_TTO1 (INT_V_START+6) /* tto1 */
|
||||
#define INT_V_TTO2 (INT_V_START+7) /* tto2 */
|
||||
#define INT_V_TTO3 (INT_V_START+8) /* tto3 */
|
||||
#define INT_V_TTO4 (INT_V_START+9) /* tto4 */
|
||||
#define INT_V_TTI1 (INT_V_START+10) /* tti1 */
|
||||
#define INT_V_TTI2 (INT_V_START+11) /* tti2 */
|
||||
#define INT_V_TTI3 (INT_V_START+12) /* tti3 */
|
||||
#define INT_V_TTI4 (INT_V_START+13) /* tti4 */
|
||||
#define INT_V_DIRECT (INT_V_START+14) /* direct start */
|
||||
#define INT_V_RX (INT_V_DIRECT+0) /* RX8E */
|
||||
#define INT_V_RK (INT_V_DIRECT+1) /* RK8E */
|
||||
#define INT_V_RF (INT_V_DIRECT+2) /* RF08 */
|
||||
#define INT_V_DF (INT_V_DIRECT+3) /* DF32 */
|
||||
#define INT_V_MT (INT_V_DIRECT+4) /* TM8E */
|
||||
#define INT_V_DTA (INT_V_DIRECT+5) /* TC08 */
|
||||
#define INT_V_RL (INT_V_DIRECT+6) /* RL8A */
|
||||
#define INT_V_PWR (INT_V_DIRECT+7) /* power int */
|
||||
#define INT_V_UF (INT_V_DIRECT+8) /* user int */
|
||||
#define INT_V_TSC (INT_V_DIRECT+9) /* TSC8-75 int */
|
||||
#define INT_V_OVHD (INT_V_DIRECT+10) /* overhead start */
|
||||
#define INT_V_NO_ION_PENDING (INT_V_OVHD+0) /* ion pending */
|
||||
#define INT_V_NO_CIF_PENDING (INT_V_OVHD+1) /* cif pending */
|
||||
#define INT_V_ION (INT_V_OVHD+2) /* interrupts on */
|
||||
|
||||
#define INT_LPT (1 << INT_V_LPT)
|
||||
#define INT_PTP (1 << INT_V_PTP)
|
||||
#define INT_PTR (1 << INT_V_PTR)
|
||||
#define INT_TTO (1 << INT_V_TTO)
|
||||
#define INT_TTI (1 << INT_V_TTI)
|
||||
#define INT_CLK (1 << INT_V_CLK)
|
||||
#define INT_TTO1 (1 << INT_V_TTO1)
|
||||
#define INT_TTO2 (1 << INT_V_TTO2)
|
||||
#define INT_TTO3 (1 << INT_V_TTO3)
|
||||
#define INT_TTO4 (1 << INT_V_TTO4)
|
||||
#define INT_TTI1 (1 << INT_V_TTI1)
|
||||
#define INT_TTI2 (1 << INT_V_TTI2)
|
||||
#define INT_TTI3 (1 << INT_V_TTI3)
|
||||
#define INT_TTI4 (1 << INT_V_TTI4)
|
||||
#define INT_RX (1 << INT_V_RX)
|
||||
#define INT_RK (1 << INT_V_RK)
|
||||
#define INT_RF (1 << INT_V_RF)
|
||||
#define INT_DF (1 << INT_V_DF)
|
||||
#define INT_MT (1 << INT_V_MT)
|
||||
#define INT_DTA (1 << INT_V_DTA)
|
||||
#define INT_RL (1 << INT_V_RL)
|
||||
#define INT_PWR (1 << INT_V_PWR)
|
||||
#define INT_UF (1 << INT_V_UF)
|
||||
#define INT_TSC (1 << INT_V_TSC)
|
||||
#define INT_LPT (1 << INT_V_LPT)
|
||||
#define INT_PTP (1 << INT_V_PTP)
|
||||
#define INT_PTR (1 << INT_V_PTR)
|
||||
#define INT_TTO (1 << INT_V_TTO)
|
||||
#define INT_TTI (1 << INT_V_TTI)
|
||||
#define INT_CLK (1 << INT_V_CLK)
|
||||
#define INT_TTO1 (1 << INT_V_TTO1)
|
||||
#define INT_TTO2 (1 << INT_V_TTO2)
|
||||
#define INT_TTO3 (1 << INT_V_TTO3)
|
||||
#define INT_TTO4 (1 << INT_V_TTO4)
|
||||
#define INT_TTI1 (1 << INT_V_TTI1)
|
||||
#define INT_TTI2 (1 << INT_V_TTI2)
|
||||
#define INT_TTI3 (1 << INT_V_TTI3)
|
||||
#define INT_TTI4 (1 << INT_V_TTI4)
|
||||
#define INT_RX (1 << INT_V_RX)
|
||||
#define INT_RK (1 << INT_V_RK)
|
||||
#define INT_RF (1 << INT_V_RF)
|
||||
#define INT_DF (1 << INT_V_DF)
|
||||
#define INT_MT (1 << INT_V_MT)
|
||||
#define INT_DTA (1 << INT_V_DTA)
|
||||
#define INT_RL (1 << INT_V_RL)
|
||||
#define INT_PWR (1 << INT_V_PWR)
|
||||
#define INT_UF (1 << INT_V_UF)
|
||||
#define INT_TSC (1 << INT_V_TSC)
|
||||
#define INT_NO_ION_PENDING (1 << INT_V_NO_ION_PENDING)
|
||||
#define INT_NO_CIF_PENDING (1 << INT_V_NO_CIF_PENDING)
|
||||
#define INT_ION (1 << INT_V_ION)
|
||||
#define INT_DEV_ENABLE ((1 << INT_V_DIRECT) - 1) /* devices w/enables */
|
||||
#define INT_ALL ((1 << INT_V_OVHD) - 1) /* all interrupts */
|
||||
#define INT_INIT_ENABLE (INT_TTI+INT_TTO+INT_PTR+INT_PTP+INT_LPT) | \
|
||||
(INT_TTI1+INT_TTI2+INT_TTI3+INT_TTI4) | \
|
||||
(INT_TTO1+INT_TTO2+INT_TTO3+INT_TTO4)
|
||||
#define INT_PENDING (INT_ION+INT_NO_CIF_PENDING+INT_NO_ION_PENDING)
|
||||
#define INT_UPDATE ((int_req & ~INT_DEV_ENABLE) | (dev_done & int_enable))
|
||||
#define INT_ION (1 << INT_V_ION)
|
||||
#define INT_DEV_ENABLE ((1 << INT_V_DIRECT) - 1) /* devices w/enables */
|
||||
#define INT_ALL ((1 << INT_V_OVHD) - 1) /* all interrupts */
|
||||
#define INT_INIT_ENABLE (INT_TTI+INT_TTO+INT_PTR+INT_PTP+INT_LPT) | \
|
||||
(INT_TTI1+INT_TTI2+INT_TTI3+INT_TTI4) | \
|
||||
(INT_TTO1+INT_TTO2+INT_TTO3+INT_TTO4)
|
||||
#define INT_PENDING (INT_ION+INT_NO_CIF_PENDING+INT_NO_ION_PENDING)
|
||||
#define INT_UPDATE ((int_req & ~INT_DEV_ENABLE) | (dev_done & int_enable))
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
#endif
|
||||
|
||||
387
PDP8/pdp8_df.c
387
PDP8/pdp8_df.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_df.c: DF32 fixed head disk simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,90 +19,90 @@
|
||||
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.
|
||||
|
||||
df DF32 fixed head disk
|
||||
df DF32 fixed head disk
|
||||
|
||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
26-Jul-03 RMS Fixed bug in set size routine
|
||||
14-Mar-03 RMS Fixed variable platter interaction with save/restore
|
||||
03-Mar-03 RMS Fixed autosizing
|
||||
02-Feb-03 RMS Added variable platter and autosizing support
|
||||
04-Oct-02 RMS Added DIBs, device number support
|
||||
28-Nov-01 RMS Added RL8A support
|
||||
25-Apr-01 RMS Added device enable/disable support
|
||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
26-Jul-03 RMS Fixed bug in set size routine
|
||||
14-Mar-03 RMS Fixed variable platter interaction with save/restore
|
||||
03-Mar-03 RMS Fixed autosizing
|
||||
02-Feb-03 RMS Added variable platter and autosizing support
|
||||
04-Oct-02 RMS Added DIBs, device number support
|
||||
28-Nov-01 RMS Added RL8A support
|
||||
25-Apr-01 RMS Added device enable/disable support
|
||||
|
||||
The DF32 is a head-per-track disk. It uses the three cycle data break
|
||||
facility. To minimize overhead, the entire DF32 is buffered in memory.
|
||||
|
||||
Two timing parameters are provided:
|
||||
|
||||
df_time Interword timing, must be non-zero
|
||||
df_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise,
|
||||
DMA occurs in a burst
|
||||
df_time Interword timing, must be non-zero
|
||||
df_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise,
|
||||
DMA occurs in a burst
|
||||
*/
|
||||
|
||||
#include "pdp8_defs.h"
|
||||
#include <math.h>
|
||||
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 03
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 03
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define DF_NUMWD 2048 /* words/track */
|
||||
#define DF_NUMTR 16 /* tracks/disk */
|
||||
#define DF_DKSIZE (DF_NUMTR * DF_NUMWD) /* words/disk */
|
||||
#define DF_NUMDK 4 /* disks/controller */
|
||||
#define DF_WC 07750 /* word count */
|
||||
#define DF_MA 07751 /* mem address */
|
||||
#define DF_WMASK (DF_NUMWD - 1) /* word mask */
|
||||
#define DF_NUMWD 2048 /* words/track */
|
||||
#define DF_NUMTR 16 /* tracks/disk */
|
||||
#define DF_DKSIZE (DF_NUMTR * DF_NUMWD) /* words/disk */
|
||||
#define DF_NUMDK 4 /* disks/controller */
|
||||
#define DF_WC 07750 /* word count */
|
||||
#define DF_MA 07751 /* mem address */
|
||||
#define DF_WMASK (DF_NUMWD - 1) /* word mask */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
#define FUNC u4 /* function */
|
||||
#define DF_READ 2 /* read */
|
||||
#define DF_WRITE 4 /* write */
|
||||
#define FUNC u4 /* function */
|
||||
#define DF_READ 2 /* read */
|
||||
#define DF_WRITE 4 /* write */
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define DFS_PCA 04000 /* photocell status */
|
||||
#define DFS_DEX 03700 /* disk addr extension */
|
||||
#define DFS_MEX 00070 /* mem addr extension */
|
||||
#define DFS_DRL 00004 /* data late error */
|
||||
#define DFS_WLS 00002 /* write lock error */
|
||||
#define DFS_NXD 00002 /* non-existent disk */
|
||||
#define DFS_PER 00001 /* parity error */
|
||||
#define DFS_ERR (DFS_DRL | DFS_WLS | DFS_PER)
|
||||
#define DFS_V_DEX 6
|
||||
#define DFS_V_MEX 3
|
||||
#define DFS_PCA 04000 /* photocell status */
|
||||
#define DFS_DEX 03700 /* disk addr extension */
|
||||
#define DFS_MEX 00070 /* mem addr extension */
|
||||
#define DFS_DRL 00004 /* data late error */
|
||||
#define DFS_WLS 00002 /* write lock error */
|
||||
#define DFS_NXD 00002 /* non-existent disk */
|
||||
#define DFS_PER 00001 /* parity error */
|
||||
#define DFS_ERR (DFS_DRL | DFS_WLS | DFS_PER)
|
||||
#define DFS_V_DEX 6
|
||||
#define DFS_V_MEX 3
|
||||
|
||||
#define GET_MEX(x) (((x) & DFS_MEX) << (12 - DFS_V_MEX))
|
||||
#define GET_DEX(x) (((x) & DFS_DEX) << (12 - DFS_V_DEX))
|
||||
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) DF_NUMWD)))
|
||||
#define UPDATE_PCELL if (GET_POS (df_time) < 6) df_sta = df_sta | DFS_PCA; \
|
||||
else df_sta = df_sta & ~DFS_PCA
|
||||
|
||||
#define GET_MEX(x) (((x) & DFS_MEX) << (12 - DFS_V_MEX))
|
||||
#define GET_DEX(x) (((x) & DFS_DEX) << (12 - DFS_V_DEX))
|
||||
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) DF_NUMWD)))
|
||||
#define UPDATE_PCELL if (GET_POS (df_time) < 6) df_sta = df_sta | DFS_PCA; \
|
||||
else df_sta = df_sta & ~DFS_PCA
|
||||
|
||||
extern uint16 M[];
|
||||
extern int32 int_req, stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
int32 df_sta = 0; /* status register */
|
||||
int32 df_da = 0; /* disk address */
|
||||
int32 df_done = 0; /* done flag */
|
||||
int32 df_wlk = 0; /* write lock */
|
||||
int32 df_time = 10; /* inter-word time */
|
||||
int32 df_burst = 1; /* burst mode flag */
|
||||
int32 df_stopioe = 1; /* stop on error */
|
||||
int32 df_sta = 0; /* status register */
|
||||
int32 df_da = 0; /* disk address */
|
||||
int32 df_done = 0; /* done flag */
|
||||
int32 df_wlk = 0; /* write lock */
|
||||
int32 df_time = 10; /* inter-word time */
|
||||
int32 df_burst = 1; /* burst mode flag */
|
||||
int32 df_stopioe = 1; /* stop on error */
|
||||
|
||||
DEVICE df_dev;
|
||||
int32 df60 (int32 IR, int32 AC);
|
||||
@@ -117,49 +117,53 @@ t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* DF32 data structures
|
||||
|
||||
df_dev RF device descriptor
|
||||
df_unit RF unit descriptor
|
||||
pcell_unit photocell timing unit (orphan)
|
||||
df_reg RF register list
|
||||
df_dev RF device descriptor
|
||||
df_unit RF unit descriptor
|
||||
pcell_unit photocell timing unit (orphan)
|
||||
df_reg RF register list
|
||||
*/
|
||||
|
||||
DIB df_dib = { DEV_DF, 3, { &df60, &df61, &df62 } };
|
||||
|
||||
UNIT df_unit =
|
||||
{ UDATA (&df_svc, UNIT_FIX+UNIT_ATTABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, DF_DKSIZE) };
|
||||
UNIT df_unit = {
|
||||
UDATA (&df_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
||||
DF_DKSIZE)
|
||||
};
|
||||
|
||||
REG df_reg[] = {
|
||||
{ ORDATA (STA, df_sta, 12) },
|
||||
{ ORDATA (DA, df_da, 12) },
|
||||
{ ORDATA (WC, M[DF_WC], 12) },
|
||||
{ ORDATA (MA, M[DF_MA], 12) },
|
||||
{ FLDATA (DONE, df_done, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_DF) },
|
||||
{ ORDATA (WLS, df_wlk, 8) },
|
||||
{ DRDATA (TIME, df_time, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (BURST, df_burst, 0) },
|
||||
{ FLDATA (STOP_IOE, df_stopioe, 0) },
|
||||
{ DRDATA (CAPAC, df_unit.capac, 18), REG_HRO },
|
||||
{ ORDATA (DEVNUM, df_dib.dev, 6), REG_HRO },
|
||||
{ NULL } };
|
||||
{ ORDATA (STA, df_sta, 12) },
|
||||
{ ORDATA (DA, df_da, 12) },
|
||||
{ ORDATA (WC, M[DF_WC], 12) },
|
||||
{ ORDATA (MA, M[DF_MA], 12) },
|
||||
{ FLDATA (DONE, df_done, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_DF) },
|
||||
{ ORDATA (WLS, df_wlk, 8) },
|
||||
{ DRDATA (TIME, df_time, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (BURST, df_burst, 0) },
|
||||
{ FLDATA (STOP_IOE, df_stopioe, 0) },
|
||||
{ DRDATA (CAPAC, df_unit.capac, 18), REG_HRO },
|
||||
{ ORDATA (DEVNUM, df_dib.dev, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB df_mod[] = {
|
||||
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &df_set_size },
|
||||
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &df_set_size },
|
||||
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &df_set_size },
|
||||
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &df_set_size },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &df_set_size },
|
||||
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &df_set_size },
|
||||
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &df_set_size },
|
||||
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &df_set_size },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE df_dev = {
|
||||
"DF", &df_unit, df_reg, df_mod,
|
||||
1, 8, 17, 1, 8, 12,
|
||||
NULL, NULL, &df_reset,
|
||||
&df_boot, &df_attach, NULL,
|
||||
&df_dib, DEV_DISABLE };
|
||||
|
||||
"DF", &df_unit, df_reg, df_mod,
|
||||
1, 8, 17, 1, 8, 12,
|
||||
NULL, NULL, &df_reset,
|
||||
&df_boot, &df_attach, NULL,
|
||||
&df_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* IOT routines */
|
||||
|
||||
int32 df60 (int32 IR, int32 AC)
|
||||
@@ -167,30 +171,32 @@ int32 df60 (int32 IR, int32 AC)
|
||||
int32 t;
|
||||
int32 pulse = IR & 07;
|
||||
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) { /* DCMA */
|
||||
df_da = 0; /* clear disk addr */
|
||||
df_done = 0; /* clear done */
|
||||
df_sta = df_sta & ~DFS_ERR; /* clear errors */
|
||||
int_req = int_req & ~INT_DF; } /* clear int req */
|
||||
if (pulse & 6) { /* DMAR, DMAW */
|
||||
df_da = df_da | AC; /* disk addr |= AC */
|
||||
df_unit.FUNC = pulse & ~1; /* save function */
|
||||
t = (df_da & DF_WMASK) - GET_POS (df_time); /* delta to new loc */
|
||||
if (t < 0) t = t + DF_NUMWD; /* wrap around? */
|
||||
sim_activate (&df_unit, t * df_time); /* schedule op */
|
||||
AC = 0; } /* clear AC */
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) { /* DCMA */
|
||||
df_da = 0; /* clear disk addr */
|
||||
df_done = 0; /* clear done */
|
||||
df_sta = df_sta & ~DFS_ERR; /* clear errors */
|
||||
int_req = int_req & ~INT_DF; /* clear int req */
|
||||
}
|
||||
if (pulse & 6) { /* DMAR, DMAW */
|
||||
df_da = df_da | AC; /* disk addr |= AC */
|
||||
df_unit.FUNC = pulse & ~1; /* save function */
|
||||
t = (df_da & DF_WMASK) - GET_POS (df_time); /* delta to new loc */
|
||||
if (t < 0) t = t + DF_NUMWD; /* wrap around? */
|
||||
sim_activate (&df_unit, t * df_time); /* schedule op */
|
||||
AC = 0; /* clear AC */
|
||||
}
|
||||
return AC;
|
||||
}
|
||||
|
||||
/* Based on the hardware implementation. DEAL and DEAC work as follows:
|
||||
|
||||
6615 pulse 1 = clear df_sta<dex,mex>
|
||||
pulse 4 = df_sta = df_sta | AC<dex,mex>
|
||||
AC = AC | old_df_sta
|
||||
6616 pulse 2 = clear AC, skip if address confirmed
|
||||
pulse 4 = df_sta = df_sta | AC<dex,mex> = 0 (nop)
|
||||
AC = AC | old_df_sta
|
||||
6615 pulse 1 = clear df_sta<dex,mex>
|
||||
pulse 4 = df_sta = df_sta | AC<dex,mex>
|
||||
AC = AC | old_df_sta
|
||||
6616 pulse 2 = clear AC, skip if address confirmed
|
||||
pulse 4 = df_sta = df_sta | AC<dex,mex> = 0 (nop)
|
||||
AC = AC | old_df_sta
|
||||
*/
|
||||
|
||||
int32 df61 (int32 IR, int32 AC)
|
||||
@@ -198,14 +204,15 @@ int32 df61 (int32 IR, int32 AC)
|
||||
int32 old_df_sta = df_sta;
|
||||
int32 pulse = IR & 07;
|
||||
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) /* DCEA */
|
||||
df_sta = df_sta & ~(DFS_DEX | DFS_MEX); /* clear dex, mex */
|
||||
if (pulse & 2) /* DSAC */
|
||||
AC = ((df_da & DF_WMASK) == GET_POS (df_time))? IOT_SKP: 0;
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) /* DCEA */
|
||||
df_sta = df_sta & ~(DFS_DEX | DFS_MEX); /* clear dex, mex */
|
||||
if (pulse & 2) /* DSAC */
|
||||
AC = ((df_da & DF_WMASK) == GET_POS (df_time))? IOT_SKP: 0;
|
||||
if (pulse & 4) {
|
||||
df_sta = df_sta | (AC & (DFS_DEX | DFS_MEX)); /* DEAL */
|
||||
AC = AC | old_df_sta; } /* DEAC */
|
||||
df_sta = df_sta | (AC & (DFS_DEX | DFS_MEX)); /* DEAL */
|
||||
AC = AC | old_df_sta; /* DEAC */
|
||||
}
|
||||
return AC;
|
||||
}
|
||||
|
||||
@@ -213,16 +220,18 @@ int32 df62 (int32 IR, int32 AC)
|
||||
{
|
||||
int32 pulse = IR & 07;
|
||||
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) { /* DFSE */
|
||||
if ((df_sta & DFS_ERR) == 0) AC = AC | IOT_SKP; }
|
||||
if (pulse & 2) { /* DFSC */
|
||||
if (pulse & 4) AC = AC & ~07777; /* for DMAC */
|
||||
else if (df_done) AC = AC | IOT_SKP; }
|
||||
if (pulse & 4) AC = AC | df_da; /* DMAC */
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) { /* DFSE */
|
||||
if ((df_sta & DFS_ERR) == 0) AC = AC | IOT_SKP;
|
||||
}
|
||||
if (pulse & 2) { /* DFSC */
|
||||
if (pulse & 4) AC = AC & ~07777; /* for DMAC */
|
||||
else if (df_done) AC = AC | IOT_SKP;
|
||||
}
|
||||
if (pulse & 4) AC = AC | df_da; /* DMAC */
|
||||
return AC;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service
|
||||
|
||||
Note that for reads and writes, memory addresses wrap around in the
|
||||
@@ -235,77 +244,85 @@ int32 pa, t, mex;
|
||||
uint32 da;
|
||||
int16 *fbuf = uptr->filebuf;
|
||||
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
df_done = 1;
|
||||
int_req = int_req | INT_DF; /* update int req */
|
||||
return IORETURN (df_stopioe, SCPE_UNATT); }
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
df_done = 1;
|
||||
int_req = int_req | INT_DF; /* update int req */
|
||||
return IORETURN (df_stopioe, SCPE_UNATT);
|
||||
}
|
||||
|
||||
mex = GET_MEX (df_sta);
|
||||
da = GET_DEX (df_sta) | df_da; /* form disk addr */
|
||||
do { if (da >= uptr->capac) { /* nx disk addr? */
|
||||
df_sta = df_sta | DFS_NXD;
|
||||
break; }
|
||||
M[DF_WC] = (M[DF_WC] + 1) & 07777; /* incr word count */
|
||||
M[DF_MA] = (M[DF_MA] + 1) & 07777; /* incr mem addr */
|
||||
pa = mex | M[DF_MA]; /* add extension */
|
||||
if (uptr->FUNC == DF_READ) { /* read? */
|
||||
if (MEM_ADDR_OK (pa)) M[pa] = fbuf[da]; } /* if !nxm, read wd */
|
||||
else { /* write */
|
||||
t = (da >> 14) & 07; /* check wr lock */
|
||||
if ((df_wlk >> t) & 1) /* locked? set err */
|
||||
df_sta = df_sta | DFS_WLS;
|
||||
else { /* not locked */
|
||||
fbuf[da] = M[pa]; /* write word */
|
||||
if (da >= uptr->hwmark) uptr->hwmark = da + 1; } }
|
||||
da = (da + 1) & 0377777; } /* incr disk addr */
|
||||
while ((M[DF_WC] != 0) && (df_burst != 0)); /* brk if wc, no brst */
|
||||
da = GET_DEX (df_sta) | df_da; /* form disk addr */
|
||||
do {
|
||||
if (da >= uptr->capac) { /* nx disk addr? */
|
||||
df_sta = df_sta | DFS_NXD;
|
||||
break;
|
||||
}
|
||||
M[DF_WC] = (M[DF_WC] + 1) & 07777; /* incr word count */
|
||||
M[DF_MA] = (M[DF_MA] + 1) & 07777; /* incr mem addr */
|
||||
pa = mex | M[DF_MA]; /* add extension */
|
||||
if (uptr->FUNC == DF_READ) { /* read? */
|
||||
if (MEM_ADDR_OK (pa)) M[pa] = fbuf[da]; /* if !nxm, read wd */
|
||||
}
|
||||
else { /* write */
|
||||
t = (da >> 14) & 07; /* check wr lock */
|
||||
if ((df_wlk >> t) & 1) /* locked? set err */
|
||||
df_sta = df_sta | DFS_WLS;
|
||||
else { /* not locked */
|
||||
fbuf[da] = M[pa]; /* write word */
|
||||
if (da >= uptr->hwmark) uptr->hwmark = da + 1;
|
||||
}
|
||||
}
|
||||
da = (da + 1) & 0377777; /* incr disk addr */
|
||||
} while ((M[DF_WC] != 0) && (df_burst != 0)); /* brk if wc, no brst */
|
||||
|
||||
if ((M[DF_WC] != 0) && ((df_sta & DFS_ERR) == 0)) /* more to do? */
|
||||
sim_activate (&df_unit, df_time); /* sched next */
|
||||
else { if (uptr->FUNC != DF_READ) da = (da - 1) & 0377777;
|
||||
df_done = 1; /* done */
|
||||
int_req = int_req | INT_DF; } /* update int req */
|
||||
if ((M[DF_WC] != 0) && ((df_sta & DFS_ERR) == 0)) /* more to do? */
|
||||
sim_activate (&df_unit, df_time); /* sched next */
|
||||
else {
|
||||
if (uptr->FUNC != DF_READ) da = (da - 1) & 0377777;
|
||||
df_done = 1; /* done */
|
||||
int_req = int_req | INT_DF; /* update int req */
|
||||
}
|
||||
df_sta = (df_sta & ~DFS_DEX) | ((da >> (12 - DFS_V_DEX)) & DFS_DEX);
|
||||
df_da = da & 07777; /* separate disk addr */
|
||||
df_da = da & 07777; /* separate disk addr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat df_reset (DEVICE *dptr)
|
||||
{
|
||||
df_sta = df_da = 0;
|
||||
df_done = 1;
|
||||
int_req = int_req & ~INT_DF; /* clear interrupt */
|
||||
int_req = int_req & ~INT_DF; /* clear interrupt */
|
||||
sim_cancel (&df_unit);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define OS8_START 07750
|
||||
#define OS8_LEN (sizeof (os8_rom) / sizeof (int16))
|
||||
#define DM4_START 00200
|
||||
#define DM4_LEN (sizeof (dm4_rom) / sizeof (int16))
|
||||
#define OS8_START 07750
|
||||
#define OS8_LEN (sizeof (os8_rom) / sizeof (int16))
|
||||
#define DM4_START 00200
|
||||
#define DM4_LEN (sizeof (dm4_rom) / sizeof (int16))
|
||||
|
||||
static const uint16 os8_rom[] = {
|
||||
07600, /* 7750, CLA CLL ; also word count */
|
||||
06603, /* 7751, DMAR ; also address */
|
||||
06622, /* 7752, DFSC ; done? */
|
||||
05352, /* 7753, JMP .-1 ; no */
|
||||
05752 /* 7754, JMP @.-2 ; enter boot */
|
||||
};
|
||||
07600, /* 7750, CLA CLL ; also word count */
|
||||
06603, /* 7751, DMAR ; also address */
|
||||
06622, /* 7752, DFSC ; done? */
|
||||
05352, /* 7753, JMP .-1 ; no */
|
||||
05752 /* 7754, JMP @.-2 ; enter boot */
|
||||
};
|
||||
|
||||
static const uint16 dm4_rom[] = {
|
||||
00200, 07600, /* 0200, CLA CLL */
|
||||
00201, 06603, /* 0201, DMAR ; read */
|
||||
00202, 06622, /* 0202, DFSC ; done? */
|
||||
00203, 05202, /* 0203, JMP .-1 ; no */
|
||||
00204, 05600, /* 0204, JMP @.-4 ; enter boot */
|
||||
07750, 07576, /* 7750, 7576 ; word count */
|
||||
07751, 07576 /* 7751, 7576 ; address */
|
||||
};
|
||||
00200, 07600, /* 0200, CLA CLL */
|
||||
00201, 06603, /* 0201, DMAR ; read */
|
||||
00202, 06622, /* 0202, DFSC ; done? */
|
||||
00203, 05202, /* 0203, JMP .-1 ; no */
|
||||
00204, 05600, /* 0204, JMP @.-4 ; enter boot */
|
||||
07750, 07576, /* 7750, 7576 ; word count */
|
||||
07751, 07576 /* 7751, 7576 ; address */
|
||||
};
|
||||
|
||||
t_stat df_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
@@ -313,12 +330,15 @@ int32 i;
|
||||
extern int32 sim_switches, saved_PC;
|
||||
|
||||
if (sim_switches & SWMASK ('D')) {
|
||||
for (i = 0; i < DM4_LEN; i = i + 2)
|
||||
M[dm4_rom[i]] = dm4_rom[i + 1];
|
||||
saved_PC = DM4_START; }
|
||||
else { for (i = 0; i < OS8_LEN; i++)
|
||||
M[OS8_START + i] = os8_rom[i];
|
||||
saved_PC = OS8_START; }
|
||||
for (i = 0; i < DM4_LEN; i = i + 2)
|
||||
M[dm4_rom[i]] = dm4_rom[i + 1];
|
||||
saved_PC = DM4_START;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < OS8_LEN; i++)
|
||||
M[OS8_START + i] = os8_rom[i];
|
||||
saved_PC = OS8_START;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -333,10 +353,11 @@ t_stat r;
|
||||
r = attach_unit (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
|
||||
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (p >= DF_NUMDK) p = DF_NUMDK - 1;
|
||||
uptr->flags = (uptr->flags & ~UNIT_PLAT) |
|
||||
(p << UNIT_V_PLAT); }
|
||||
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (p >= DF_NUMDK) p = DF_NUMDK - 1;
|
||||
uptr->flags = (uptr->flags & ~UNIT_PLAT) |
|
||||
(p << UNIT_V_PLAT);
|
||||
}
|
||||
uptr->capac = UNIT_GETP (uptr->flags) * DF_DKSIZE;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-8 Simulator Usage
|
||||
Date: 15-Feb-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 PDP-8 simulator.
|
||||
@@ -401,8 +401,7 @@ or a DETACH TTIX command.
|
||||
|
||||
The SHOW TTIX CONNECTIONS command displays the current connections to the
|
||||
extra terminals. The SHOW TTIX STATISTICS command displays statistics for
|
||||
active connections. The SET TTIX DISCONNECT=linenumber disconnects the
|
||||
specified line.
|
||||
active connections. The SET TTIXn DISCONNECT command disconnects line n.
|
||||
|
||||
The input device (TTIX) implements these registers:
|
||||
|
||||
|
||||
1662
PDP8/pdp8_dt.c
1662
PDP8/pdp8_dt.c
File diff suppressed because it is too large
Load Diff
160
PDP8/pdp8_lp.c
160
PDP8/pdp8_lp.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_lp.c: PDP-8 line printer simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,23 +19,23 @@
|
||||
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 LP8E line printer
|
||||
lpt LP8E line printer
|
||||
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
04-Oct-02 RMS Added DIB, enable/disable, device number support
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
04-Oct-02 RMS Added DIB, enable/disable, device number support
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
*/
|
||||
|
||||
#include "pdp8_defs.h"
|
||||
|
||||
extern int32 int_req, int_enable, dev_done, stop_inst;
|
||||
|
||||
int32 lpt_err = 0; /* error flag */
|
||||
int32 lpt_stopioe = 0; /* stop on error */
|
||||
int32 lpt_err = 0; /* error flag */
|
||||
int32 lpt_stopioe = 0; /* stop on error */
|
||||
|
||||
DEVICE lpt_dev;
|
||||
int32 lpt (int32 IR, int32 AC);
|
||||
@@ -46,88 +46,104 @@ t_stat lpt_detach (UNIT *uptr);
|
||||
|
||||
/* LPT data structures
|
||||
|
||||
lpt_dev LPT device descriptor
|
||||
lpt_unit LPT unit descriptor
|
||||
lpt_reg LPT register list
|
||||
lpt_dev LPT device descriptor
|
||||
lpt_unit LPT unit descriptor
|
||||
lpt_reg LPT register list
|
||||
*/
|
||||
|
||||
DIB lpt_dib = { DEV_LPT, 1, { &lpt } };
|
||||
|
||||
UNIT lpt_unit = {
|
||||
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
|
||||
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
|
||||
};
|
||||
|
||||
REG lpt_reg[] = {
|
||||
{ ORDATA (BUF, lpt_unit.buf, 8) },
|
||||
{ FLDATA (ERR, lpt_err, 0) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_LPT) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_LPT) },
|
||||
{ FLDATA (INT, int_req, INT_V_LPT) },
|
||||
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
|
||||
{ ORDATA (DEVNUM, lpt_dib.dev, 6), REG_HRO },
|
||||
{ NULL } };
|
||||
{ ORDATA (BUF, lpt_unit.buf, 8) },
|
||||
{ FLDATA (ERR, lpt_err, 0) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_LPT) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_LPT) },
|
||||
{ FLDATA (INT, int_req, INT_V_LPT) },
|
||||
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
|
||||
{ ORDATA (DEVNUM, lpt_dib.dev, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB lpt_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 lpt_dev = {
|
||||
"LPT", &lpt_unit, lpt_reg, lpt_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &lpt_reset,
|
||||
NULL, &lpt_attach, &lpt_detach,
|
||||
&lpt_dib, DEV_DISABLE };
|
||||
|
||||
"LPT", &lpt_unit, lpt_reg, lpt_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &lpt_reset,
|
||||
NULL, &lpt_attach, &lpt_detach,
|
||||
&lpt_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* IOT routine */
|
||||
|
||||
int32 lpt (int32 IR, int32 AC)
|
||||
{
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 1: /* PSKF */
|
||||
return (dev_done & INT_LPT)? IOT_SKP + AC: AC;
|
||||
case 2: /* PCLF */
|
||||
dev_done = dev_done & ~INT_LPT; /* clear flag */
|
||||
int_req = int_req & ~INT_LPT; /* clear int req */
|
||||
return AC;
|
||||
case 3: /* PSKE */
|
||||
return (lpt_err)? IOT_SKP + AC: AC;
|
||||
case 6: /* PCLF!PSTB */
|
||||
dev_done = dev_done & ~INT_LPT; /* clear flag */
|
||||
int_req = int_req & ~INT_LPT; /* clear int req */
|
||||
case 4: /* PSTB */
|
||||
lpt_unit.buf = AC & 0177; /* load buffer */
|
||||
if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) ||
|
||||
(lpt_unit.buf == 012)) {
|
||||
sim_activate (&lpt_unit, lpt_unit.wait);
|
||||
return AC; }
|
||||
return (lpt_svc (&lpt_unit) << IOT_V_REASON) + AC;
|
||||
case 5: /* PSIE */
|
||||
int_enable = int_enable | INT_LPT; /* set enable */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
case 7: /* PCIE */
|
||||
int_enable = int_enable & ~INT_LPT; /* clear enable */
|
||||
int_req = int_req & ~INT_LPT; /* clear int req */
|
||||
return AC;
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 1: /* PSKF */
|
||||
return (dev_done & INT_LPT)? IOT_SKP + AC: AC;
|
||||
|
||||
case 2: /* PCLF */
|
||||
dev_done = dev_done & ~INT_LPT; /* clear flag */
|
||||
int_req = int_req & ~INT_LPT; /* clear int req */
|
||||
return AC;
|
||||
|
||||
case 3: /* PSKE */
|
||||
return (lpt_err)? IOT_SKP + AC: AC;
|
||||
|
||||
case 6: /* PCLF!PSTB */
|
||||
dev_done = dev_done & ~INT_LPT; /* clear flag */
|
||||
int_req = int_req & ~INT_LPT; /* clear int req */
|
||||
|
||||
case 4: /* PSTB */
|
||||
lpt_unit.buf = AC & 0177; /* load buffer */
|
||||
if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) ||
|
||||
(lpt_unit.buf == 012)) {
|
||||
sim_activate (&lpt_unit, lpt_unit.wait);
|
||||
return AC;
|
||||
}
|
||||
return (lpt_svc (&lpt_unit) << IOT_V_REASON) + AC;
|
||||
|
||||
case 5: /* PSIE */
|
||||
int_enable = int_enable | INT_LPT; /* set enable */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
|
||||
case 7: /* PCIE */
|
||||
int_enable = int_enable & ~INT_LPT; /* clear enable */
|
||||
int_req = int_req & ~INT_LPT; /* clear int req */
|
||||
return AC;
|
||||
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
} /* end switch */
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat lpt_svc (UNIT *uptr)
|
||||
{
|
||||
dev_done = dev_done | INT_LPT; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
dev_done = dev_done | INT_LPT; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) {
|
||||
lpt_err = 1;
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT); }
|
||||
lpt_err = 1;
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
}
|
||||
if (putc (lpt_unit.buf, lpt_unit.fileref) == EOF) {
|
||||
perror ("LPT I/O error");
|
||||
clearerr (lpt_unit.fileref);
|
||||
return SCPE_IOERR; }
|
||||
perror ("LPT I/O error");
|
||||
clearerr (lpt_unit.fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
lpt_unit.pos = lpt_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -137,11 +153,11 @@ return SCPE_OK;
|
||||
t_stat lpt_reset (DEVICE *dptr)
|
||||
{
|
||||
lpt_unit.buf = 0;
|
||||
dev_done = dev_done & ~INT_LPT; /* clear done, int */
|
||||
dev_done = dev_done & ~INT_LPT; /* clear done, int */
|
||||
int_req = int_req & ~INT_LPT;
|
||||
int_enable = int_enable | INT_LPT; /* set enable */
|
||||
int_enable = int_enable | INT_LPT; /* set enable */
|
||||
lpt_err = (lpt_unit.flags & UNIT_ATT) == 0;
|
||||
sim_cancel (&lpt_unit); /* deactivate unit */
|
||||
sim_cancel (&lpt_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
795
PDP8/pdp8_mt.c
795
PDP8/pdp8_mt.c
@@ -19,42 +19,43 @@
|
||||
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 TM8E/TU10 magtape
|
||||
mt TM8E/TU10 magtape
|
||||
|
||||
18-Mar-05 RMS Added attached test to detach routine
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
29-Mar-03 RMS Added multiformat support
|
||||
04-Mar-03 RMS Fixed bug in SKTR
|
||||
01-Mar-03 RMS Fixed interrupt handling
|
||||
Revised for magtape library
|
||||
30-Oct-02 RMS Revised BOT handling, added error record handling
|
||||
04-Oct-02 RMS Added DIBs, device number support
|
||||
30-Aug-02 RMS Revamped error handling
|
||||
28-Aug-02 RMS Added end of medium support
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
22-Apr-02 RMS Added maximum record length test
|
||||
06-Jan-02 RMS Changed enable/disable support
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Changed UST, POS, FLG to arrays
|
||||
25-Apr-01 RMS Added device enable/disable support
|
||||
04-Oct-98 RMS V2.4 magtape format
|
||||
22-Jan-97 RMS V2.3 magtape format
|
||||
01-Jan-96 RMS Rewritten from TM8-E Maintenance Manual
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
18-Mar-05 RMS Added attached test to detach routine
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
29-Mar-03 RMS Added multiformat support
|
||||
04-Mar-03 RMS Fixed bug in SKTR
|
||||
01-Mar-03 RMS Fixed interrupt handling
|
||||
Revised for magtape library
|
||||
30-Oct-02 RMS Revised BOT handling, added error record handling
|
||||
04-Oct-02 RMS Added DIBs, device number support
|
||||
30-Aug-02 RMS Revamped error handling
|
||||
28-Aug-02 RMS Added end of medium support
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
22-Apr-02 RMS Added maximum record length test
|
||||
06-Jan-02 RMS Changed enable/disable support
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Changed UST, POS, FLG to arrays
|
||||
25-Apr-01 RMS Added device enable/disable support
|
||||
04-Oct-98 RMS V2.4 magtape format
|
||||
22-Jan-97 RMS V2.3 magtape format
|
||||
01-Jan-96 RMS Rewritten from TM8-E Maintenance Manual
|
||||
|
||||
Magnetic tapes are represented as a series of variable records
|
||||
of the form:
|
||||
|
||||
32b byte count
|
||||
byte 0
|
||||
byte 1
|
||||
:
|
||||
byte n-2
|
||||
byte n-1
|
||||
32b byte count
|
||||
32b byte count
|
||||
byte 0
|
||||
byte 1
|
||||
:
|
||||
byte n-2
|
||||
byte n-1
|
||||
32b byte count
|
||||
|
||||
If the byte count is odd, the record is padded with an extra byte
|
||||
of junk. File marks are represented by a byte count of 0.
|
||||
@@ -63,85 +64,85 @@
|
||||
#include "pdp8_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define MT_NUMDR 8 /* #drives */
|
||||
#define USTAT u3 /* unit status */
|
||||
#define MT_MAXFR (1 << 16) /* max record lnt */
|
||||
#define WC_SIZE (1 << 12) /* max word count */
|
||||
#define WC_MASK (WC_SIZE - 1)
|
||||
#define MT_NUMDR 8 /* #drives */
|
||||
#define USTAT u3 /* unit status */
|
||||
#define MT_MAXFR (1 << 16) /* max record lnt */
|
||||
#define WC_SIZE (1 << 12) /* max word count */
|
||||
#define WC_MASK (WC_SIZE - 1)
|
||||
|
||||
/* Command/unit - mt_cu */
|
||||
|
||||
#define CU_V_UNIT 9 /* unit */
|
||||
#define CU_M_UNIT 07
|
||||
#define CU_PARITY 00400 /* parity select */
|
||||
#define CU_IEE 00200 /* error int enable */
|
||||
#define CU_IED 00100 /* done int enable */
|
||||
#define CU_V_EMA 3 /* ext mem address */
|
||||
#define CU_M_EMA 07
|
||||
#define CU_EMA (CU_M_EMA << CU_V_EMA)
|
||||
#define CU_DTY 00002 /* drive type */
|
||||
#define CU_UNPAK 00001 /* 6b vs 8b mode */
|
||||
#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT)
|
||||
#define GET_EMA(x) (((x) & CU_EMA) << (12 - CU_V_EMA))
|
||||
#define CU_V_UNIT 9 /* unit */
|
||||
#define CU_M_UNIT 07
|
||||
#define CU_PARITY 00400 /* parity select */
|
||||
#define CU_IEE 00200 /* error int enable */
|
||||
#define CU_IED 00100 /* done int enable */
|
||||
#define CU_V_EMA 3 /* ext mem address */
|
||||
#define CU_M_EMA 07
|
||||
#define CU_EMA (CU_M_EMA << CU_V_EMA)
|
||||
#define CU_DTY 00002 /* drive type */
|
||||
#define CU_UNPAK 00001 /* 6b vs 8b mode */
|
||||
#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT)
|
||||
#define GET_EMA(x) (((x) & CU_EMA) << (12 - CU_V_EMA))
|
||||
|
||||
/* Function - mt_fn */
|
||||
|
||||
#define FN_V_FNC 9 /* function */
|
||||
#define FN_M_FNC 07
|
||||
#define FN_UNLOAD 00
|
||||
#define FN_REWIND 01
|
||||
#define FN_READ 02
|
||||
#define FN_CMPARE 03
|
||||
#define FN_WRITE 04
|
||||
#define FN_WREOF 05
|
||||
#define FN_SPACEF 06
|
||||
#define FN_SPACER 07
|
||||
#define FN_ERASE 00400 /* erase */
|
||||
#define FN_CRC 00200 /* read CRC */
|
||||
#define FN_GO 00100 /* go */
|
||||
#define FN_INC 00040 /* incr mode */
|
||||
#define FN_RMASK 07700 /* readable bits */
|
||||
#define GET_FNC(x) (((x) >> FN_V_FNC) & FN_M_FNC)
|
||||
#define FN_V_FNC 9 /* function */
|
||||
#define FN_M_FNC 07
|
||||
#define FN_UNLOAD 00
|
||||
#define FN_REWIND 01
|
||||
#define FN_READ 02
|
||||
#define FN_CMPARE 03
|
||||
#define FN_WRITE 04
|
||||
#define FN_WREOF 05
|
||||
#define FN_SPACEF 06
|
||||
#define FN_SPACER 07
|
||||
#define FN_ERASE 00400 /* erase */
|
||||
#define FN_CRC 00200 /* read CRC */
|
||||
#define FN_GO 00100 /* go */
|
||||
#define FN_INC 00040 /* incr mode */
|
||||
#define FN_RMASK 07700 /* readable bits */
|
||||
#define GET_FNC(x) (((x) >> FN_V_FNC) & FN_M_FNC)
|
||||
|
||||
/* Status - stored in mt_sta or (*) uptr->USTAT */
|
||||
|
||||
#define STA_ERR (04000 << 12) /* error */
|
||||
#define STA_REW (02000 << 12) /* *rewinding */
|
||||
#define STA_BOT (01000 << 12) /* *start of tape */
|
||||
#define STA_REM (00400 << 12) /* *offline */
|
||||
#define STA_PAR (00200 << 12) /* parity error */
|
||||
#define STA_EOF (00100 << 12) /* *end of file */
|
||||
#define STA_RLE (00040 << 12) /* rec lnt error */
|
||||
#define STA_DLT (00020 << 12) /* data late */
|
||||
#define STA_EOT (00010 << 12) /* *end of tape */
|
||||
#define STA_WLK (00004 << 12) /* *write locked */
|
||||
#define STA_CPE (00002 << 12) /* compare error */
|
||||
#define STA_ILL (00001 << 12) /* illegal */
|
||||
#define STA_9TK 00040 /* 9 track */
|
||||
/* #define STA_BAD 00020 /* bad tape?? */
|
||||
#define STA_INC 00010 /* increment error */
|
||||
#define STA_LAT 00004 /* lateral par error */
|
||||
#define STA_CRC 00002 /* CRC error */
|
||||
#define STA_LON 00001 /* long par error */
|
||||
#define STA_ERR (04000 << 12) /* error */
|
||||
#define STA_REW (02000 << 12) /* *rewinding */
|
||||
#define STA_BOT (01000 << 12) /* *start of tape */
|
||||
#define STA_REM (00400 << 12) /* *offline */
|
||||
#define STA_PAR (00200 << 12) /* parity error */
|
||||
#define STA_EOF (00100 << 12) /* *end of file */
|
||||
#define STA_RLE (00040 << 12) /* rec lnt error */
|
||||
#define STA_DLT (00020 << 12) /* data late */
|
||||
#define STA_EOT (00010 << 12) /* *end of tape */
|
||||
#define STA_WLK (00004 << 12) /* *write locked */
|
||||
#define STA_CPE (00002 << 12) /* compare error */
|
||||
#define STA_ILL (00001 << 12) /* illegal */
|
||||
#define STA_9TK 00040 /* 9 track */
|
||||
/* #define STA_BAD 00020 /* bad tape?? */
|
||||
#define STA_INC 00010 /* increment error */
|
||||
#define STA_LAT 00004 /* lateral par error */
|
||||
#define STA_CRC 00002 /* CRC error */
|
||||
#define STA_LON 00001 /* long par error */
|
||||
|
||||
#define STA_CLR (FN_RMASK | 00020) /* always clear */
|
||||
#define STA_DYN (STA_REW | STA_BOT | STA_REM | STA_EOF | \
|
||||
STA_EOT | STA_WLK) /* kept in USTAT */
|
||||
|
||||
#define STA_CLR (FN_RMASK | 00020) /* always clear */
|
||||
#define STA_DYN (STA_REW | STA_BOT | STA_REM | STA_EOF | \
|
||||
STA_EOT | STA_WLK) /* kept in USTAT */
|
||||
|
||||
extern uint16 M[];
|
||||
extern int32 int_req, stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
int32 mt_cu = 0; /* command/unit */
|
||||
int32 mt_fn = 0; /* function */
|
||||
int32 mt_ca = 0; /* current address */
|
||||
int32 mt_wc = 0; /* word count */
|
||||
int32 mt_sta = 0; /* status register */
|
||||
int32 mt_db = 0; /* data buffer */
|
||||
int32 mt_done = 0; /* mag tape flag */
|
||||
int32 mt_time = 10; /* record latency */
|
||||
int32 mt_stopioe = 1; /* stop on error */
|
||||
uint8 *mtxb = NULL; /* transfer buffer */
|
||||
int32 mt_cu = 0; /* command/unit */
|
||||
int32 mt_fn = 0; /* function */
|
||||
int32 mt_ca = 0; /* current address */
|
||||
int32 mt_wc = 0; /* word count */
|
||||
int32 mt_sta = 0; /* status register */
|
||||
int32 mt_db = 0; /* data buffer */
|
||||
int32 mt_done = 0; /* mag tape flag */
|
||||
int32 mt_time = 10; /* record latency */
|
||||
int32 mt_stopioe = 1; /* stop on error */
|
||||
uint8 *mtxb = NULL; /* transfer buffer */
|
||||
|
||||
DEVICE mt_dev;
|
||||
int32 mt70 (int32 IR, int32 AC);
|
||||
@@ -160,58 +161,62 @@ void mt_set_done (void);
|
||||
|
||||
/* 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 = { DEV_MT, 3, { &mt70, &mt71, &mt72 } };
|
||||
|
||||
UNIT mt_unit[] = {
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } };
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }
|
||||
};
|
||||
|
||||
REG mt_reg[] = {
|
||||
{ ORDATA (CMD, mt_cu, 12) },
|
||||
{ ORDATA (FNC, mt_fn, 12) },
|
||||
{ ORDATA (CA, mt_ca, 12) },
|
||||
{ ORDATA (WC, mt_wc, 12) },
|
||||
{ ORDATA (DB, mt_db, 12) },
|
||||
{ GRDATA (STA, mt_sta, 8, 12, 12) },
|
||||
{ ORDATA (STA2, mt_sta, 6) },
|
||||
{ FLDATA (DONE, mt_done, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_MT) },
|
||||
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
|
||||
{ DRDATA (TIME, mt_time, 24), PV_LEFT },
|
||||
{ URDATA (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0) },
|
||||
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ FLDATA (DEVNUM, mt_dib.dev, 6), REG_HRO },
|
||||
{ NULL } };
|
||||
{ ORDATA (CMD, mt_cu, 12) },
|
||||
{ ORDATA (FNC, mt_fn, 12) },
|
||||
{ ORDATA (CA, mt_ca, 12) },
|
||||
{ ORDATA (WC, mt_wc, 12) },
|
||||
{ ORDATA (DB, mt_db, 12) },
|
||||
{ GRDATA (STA, mt_sta, 8, 12, 12) },
|
||||
{ ORDATA (STA2, mt_sta, 6) },
|
||||
{ FLDATA (DONE, mt_done, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_MT) },
|
||||
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
|
||||
{ DRDATA (TIME, mt_time, 24), PV_LEFT },
|
||||
{ URDATA (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0) },
|
||||
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ FLDATA (DEVNUM, mt_dib.dev, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB mt_mod[] = {
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mt_vlock },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mt_vlock },
|
||||
{ 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 },
|
||||
{ 0 } };
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mt_vlock },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mt_vlock },
|
||||
{ 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 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE mt_dev = {
|
||||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &mt_detach,
|
||||
&mt_dib, DEV_DISABLE };
|
||||
|
||||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &mt_detach,
|
||||
&mt_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* IOT routines */
|
||||
|
||||
int32 mt70 (int32 IR, int32 AC)
|
||||
@@ -219,113 +224,141 @@ int32 mt70 (int32 IR, int32 AC)
|
||||
int32 f;
|
||||
UNIT *uptr;
|
||||
|
||||
uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 1: /* LWCR */
|
||||
mt_wc = AC; /* load word count */
|
||||
return 0;
|
||||
case 2: /* CWCR */
|
||||
mt_wc = 0; /* clear word count */
|
||||
return AC;
|
||||
case 3: /* LCAR */
|
||||
mt_ca = AC; /* load mem address */
|
||||
return 0;
|
||||
case 4: /* CCAR */
|
||||
mt_ca = 0; /* clear mem address */
|
||||
return AC;
|
||||
case 5: /* LCMR */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||
mt_cu = AC; /* load command reg */
|
||||
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu));
|
||||
return 0;
|
||||
case 6: /* LFGR */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||
mt_fn = AC; /* load function */
|
||||
if ((mt_fn & FN_GO) == 0) { /* go set? */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return 0; }
|
||||
f = GET_FNC (mt_fn); /* get function */
|
||||
if (((uptr->flags & UNIT_ATT) == 0) ||
|
||||
sim_is_active (uptr) ||
|
||||
(((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr))
|
||||
|| (((f == FN_SPACER) || (f == FN_REWIND)) && sim_tape_bot (uptr))) {
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal op error */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return 0; }
|
||||
uptr->USTAT = uptr->USTAT & STA_WLK; /* clear status */
|
||||
if (f == FN_UNLOAD) { /* unload? */
|
||||
detach_unit (uptr); /* set offline */
|
||||
uptr->USTAT = STA_REW | STA_REM; /* rewinding, off */
|
||||
mt_set_done (); } /* set done */
|
||||
else if (f == FN_REWIND) { /* rewind */
|
||||
uptr->USTAT = uptr->USTAT | STA_REW; /* rewinding */
|
||||
mt_set_done (); } /* set done */
|
||||
else mt_done = 0; /* clear done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
sim_activate (uptr, mt_time); /* start io */
|
||||
return 0;
|
||||
case 7: /* LDBR */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||
mt_db = AC; /* load buffer */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return 0; } /* end switch */
|
||||
return (stop_inst << IOT_V_REASON) + AC; /* ill inst */
|
||||
uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 1: /* LWCR */
|
||||
mt_wc = AC; /* load word count */
|
||||
return 0;
|
||||
|
||||
case 2: /* CWCR */
|
||||
mt_wc = 0; /* clear word count */
|
||||
return AC;
|
||||
|
||||
case 3: /* LCAR */
|
||||
mt_ca = AC; /* load mem address */
|
||||
return 0;
|
||||
|
||||
case 4: /* CCAR */
|
||||
mt_ca = 0; /* clear mem address */
|
||||
return AC;
|
||||
|
||||
case 5: /* LCMR */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||
mt_cu = AC; /* load command reg */
|
||||
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu));
|
||||
return 0;
|
||||
|
||||
case 6: /* LFGR */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||
mt_fn = AC; /* load function */
|
||||
if ((mt_fn & FN_GO) == 0) { /* go set? */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return 0;
|
||||
}
|
||||
f = GET_FNC (mt_fn); /* get function */
|
||||
if (((uptr->flags & UNIT_ATT) == 0) ||
|
||||
sim_is_active (uptr) ||
|
||||
(((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr))
|
||||
|| (((f == FN_SPACER) || (f == FN_REWIND)) && sim_tape_bot (uptr))) {
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal op error */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return 0;
|
||||
}
|
||||
uptr->USTAT = uptr->USTAT & STA_WLK; /* clear status */
|
||||
if (f == FN_UNLOAD) { /* unload? */
|
||||
detach_unit (uptr); /* set offline */
|
||||
uptr->USTAT = STA_REW | STA_REM; /* rewinding, off */
|
||||
mt_set_done (); /* set done */
|
||||
}
|
||||
else if (f == FN_REWIND) { /* rewind */
|
||||
uptr->USTAT = uptr->USTAT | STA_REW; /* rewinding */
|
||||
mt_set_done (); /* set done */
|
||||
}
|
||||
else mt_done = 0; /* clear done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
sim_activate (uptr, mt_time); /* start io */
|
||||
return 0;
|
||||
|
||||
case 7: /* LDBR */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||
mt_db = AC; /* load buffer */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return 0;
|
||||
} /* end switch */
|
||||
|
||||
return (stop_inst << IOT_V_REASON) + AC; /* ill inst */
|
||||
}
|
||||
|
||||
/* IOTs, continued */
|
||||
|
||||
int32 mt71 (int32 IR, int32 AC)
|
||||
{
|
||||
UNIT *uptr;
|
||||
|
||||
uptr = mt_dev.units + GET_UNIT (mt_cu);
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 1: /* RWCR */
|
||||
return mt_wc; /* read word count */
|
||||
case 2: /* CLT */
|
||||
mt_reset (&mt_dev); /* reset everything */
|
||||
return AC;
|
||||
case 3: /* RCAR */
|
||||
return mt_ca; /* read mem address */
|
||||
case 4: /* RMSR */
|
||||
return ((mt_updcsta (uptr) >> 12) & 07777); /* read status */
|
||||
case 5: /* RCMR */
|
||||
return mt_cu; /* read command */
|
||||
case 6: /* RFSR */
|
||||
return (((mt_fn & FN_RMASK) | (mt_updcsta (uptr) & ~FN_RMASK))
|
||||
& 07777); /* read function */
|
||||
case 7: /* RDBR */
|
||||
return mt_db; } /* read data buffer */
|
||||
return (stop_inst << IOT_V_REASON) + AC; /* ill inst */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 1: /* RWCR */
|
||||
return mt_wc; /* read word count */
|
||||
|
||||
case 2: /* CLT */
|
||||
mt_reset (&mt_dev); /* reset everything */
|
||||
return AC;
|
||||
|
||||
case 3: /* RCAR */
|
||||
return mt_ca; /* read mem address */
|
||||
|
||||
case 4: /* RMSR */
|
||||
return ((mt_updcsta (uptr) >> 12) & 07777); /* read status */
|
||||
|
||||
case 5: /* RCMR */
|
||||
return mt_cu; /* read command */
|
||||
|
||||
case 6: /* RFSR */
|
||||
return (((mt_fn & FN_RMASK) | (mt_updcsta (uptr) & ~FN_RMASK))
|
||||
& 07777); /* read function */
|
||||
|
||||
case 7: /* RDBR */
|
||||
return mt_db; /* read data buffer */
|
||||
}
|
||||
|
||||
return (stop_inst << IOT_V_REASON) + AC; /* ill inst */
|
||||
}
|
||||
|
||||
int32 mt72 (int32 IR, int32 AC)
|
||||
{
|
||||
UNIT *uptr;
|
||||
|
||||
uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 1: /* SKEF */
|
||||
return (mt_sta & STA_ERR)? IOT_SKP + AC: AC;
|
||||
case 2: /* SKCB */
|
||||
return (!mt_busy ())? IOT_SKP + AC: AC;
|
||||
case 3: /* SKJD */
|
||||
return mt_done? IOT_SKP + AC: AC;
|
||||
case 4: /* SKTR */
|
||||
return (!sim_is_active (uptr) &&
|
||||
(uptr->flags & UNIT_ATT))? IOT_SKP + AC: AC;
|
||||
case 5: /* CLF */
|
||||
if (!sim_is_active (uptr)) mt_reset (&mt_dev); /* if TUR, zap */
|
||||
else { /* just ctrl zap */
|
||||
mt_sta = 0; /* clear status */
|
||||
mt_done = 0; /* clear done */
|
||||
mt_updcsta (uptr); } /* update status */
|
||||
return AC; } /* end switch */
|
||||
return (stop_inst << IOT_V_REASON) + AC; /* ill inst */
|
||||
uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 1: /* SKEF */
|
||||
return (mt_sta & STA_ERR)? IOT_SKP + AC: AC;
|
||||
|
||||
case 2: /* SKCB */
|
||||
return (!mt_busy ())? IOT_SKP + AC: AC;
|
||||
|
||||
case 3: /* SKJD */
|
||||
return mt_done? IOT_SKP + AC: AC;
|
||||
|
||||
case 4: /* SKTR */
|
||||
return (!sim_is_active (uptr) &&
|
||||
(uptr->flags & UNIT_ATT))? IOT_SKP + AC: AC;
|
||||
|
||||
case 5: /* CLF */
|
||||
if (!sim_is_active (uptr)) mt_reset (&mt_dev); /* if TUR, zap */
|
||||
else { /* just ctrl zap */
|
||||
mt_sta = 0; /* clear status */
|
||||
mt_done = 0; /* clear done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
}
|
||||
return AC;
|
||||
} /* end switch */
|
||||
|
||||
return (stop_inst << IOT_V_REASON) + AC; /* ill inst */
|
||||
}
|
||||
|
||||
|
||||
/* Unit service
|
||||
|
||||
If rewind done, reposition to start of tape, set status
|
||||
@@ -339,107 +372,115 @@ t_mtrlnt tbc, cbc;
|
||||
uint16 c, c1, c2;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
u = uptr - mt_dev.units; /* get unit number */
|
||||
f = GET_FNC (mt_fn); /* get command */
|
||||
xma = GET_EMA (mt_cu) + mt_ca; /* get mem addr */
|
||||
wc = WC_SIZE - mt_wc; /* get wc */
|
||||
u = (int32) (uptr - mt_dev.units); /* get unit number */
|
||||
f = GET_FNC (mt_fn); /* get command */
|
||||
xma = GET_EMA (mt_cu) + mt_ca; /* get mem addr */
|
||||
wc = WC_SIZE - mt_wc; /* get wc */
|
||||
|
||||
if (uptr->USTAT & STA_REW) { /* rewind? */
|
||||
sim_tape_rewind (uptr); /* update position */
|
||||
if (uptr->flags & UNIT_ATT) /* still on line? */
|
||||
uptr->USTAT = (uptr->USTAT & STA_WLK) | STA_BOT;
|
||||
else uptr->USTAT = STA_REM;
|
||||
if (u == GET_UNIT (mt_cu)) { /* selected? */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); } /* update status */
|
||||
return SCPE_OK; }
|
||||
if (uptr->USTAT & STA_REW) { /* rewind? */
|
||||
sim_tape_rewind (uptr); /* update position */
|
||||
if (uptr->flags & UNIT_ATT) /* still on line? */
|
||||
uptr->USTAT = (uptr->USTAT & STA_WLK) | STA_BOT;
|
||||
else uptr->USTAT = STA_REM;
|
||||
if (u == GET_UNIT (mt_cu)) { /* selected? */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
|
||||
uptr->USTAT = STA_REM; /* unit off line */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
|
||||
uptr->USTAT = STA_REM; /* unit off line */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return IORETURN (mt_stopioe, SCPE_UNATT);
|
||||
}
|
||||
|
||||
switch (f) { /* case on function */
|
||||
|
||||
/* Unit service, continued */
|
||||
switch (f) { /* case on function */
|
||||
|
||||
case FN_READ: /* read */
|
||||
case FN_CMPARE: /* read/compare */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||
if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
mt_sta = mt_sta | STA_RLE | STA_ERR; /* err, eof/eom, tmk */
|
||||
break; }
|
||||
cbc = (mt_cu & CU_UNPAK)? wc: wc * 2; /* expected bc */
|
||||
if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */
|
||||
if (tbc < cbc) { /* record small? */
|
||||
cbc = tbc; /* use smaller */
|
||||
wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; }
|
||||
for (i = p = 0; i < wc; i++) { /* copy buffer */
|
||||
xma = mt_ixma (xma); /* increment xma */
|
||||
mt_wc = (mt_wc + 1) & 07777; /* incr word cnt */
|
||||
if (mt_cu & CU_UNPAK) c = mtxb[p++];
|
||||
else {
|
||||
c1 = mtxb[p++] & 077;
|
||||
c2 = mtxb[p++] & 077;
|
||||
c = (c1 << 6) | c2; }
|
||||
if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c;
|
||||
else if ((f == FN_CMPARE) && (M[xma] != c)) {
|
||||
mt_sta = mt_sta | STA_CPE | STA_ERR;
|
||||
break; } }
|
||||
break;
|
||||
case FN_READ: /* read */
|
||||
case FN_CMPARE: /* read/compare */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||
if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
mt_sta = mt_sta | STA_RLE | STA_ERR; /* err, eof/eom, tmk */
|
||||
break;
|
||||
}
|
||||
cbc = (mt_cu & CU_UNPAK)? wc: wc * 2; /* expected bc */
|
||||
if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */
|
||||
if (tbc < cbc) { /* record small? */
|
||||
cbc = tbc; /* use smaller */
|
||||
wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2;
|
||||
}
|
||||
for (i = p = 0; i < wc; i++) { /* copy buffer */
|
||||
xma = mt_ixma (xma); /* increment xma */
|
||||
mt_wc = (mt_wc + 1) & 07777; /* incr word cnt */
|
||||
if (mt_cu & CU_UNPAK) c = mtxb[p++];
|
||||
else {
|
||||
c1 = mtxb[p++] & 077;
|
||||
c2 = mtxb[p++] & 077;
|
||||
c = (c1 << 6) | c2;
|
||||
}
|
||||
if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c;
|
||||
else if ((f == FN_CMPARE) && (M[xma] != c)) {
|
||||
mt_sta = mt_sta | STA_CPE | STA_ERR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FN_WRITE: /* write */
|
||||
tbc = (mt_cu & CU_UNPAK)? wc: wc * 2;
|
||||
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
|
||||
xma = mt_ixma (xma); /* incr mem addr */
|
||||
if (mt_cu & CU_UNPAK) mtxb[p++] = M[xma] & 0377;
|
||||
else {
|
||||
mtxb[p++] = (M[xma] >> 6) & 077;
|
||||
mtxb[p++] = M[xma] & 077; } }
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
xma = GET_EMA (mt_cu) + mt_ca; } /* restore xma */
|
||||
else mt_wc = 0; /* ok, clear wc */
|
||||
break;
|
||||
|
||||
/* Unit service, continued */
|
||||
case FN_WRITE: /* write */
|
||||
tbc = (mt_cu & CU_UNPAK)? wc: wc * 2;
|
||||
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
|
||||
xma = mt_ixma (xma); /* incr mem addr */
|
||||
if (mt_cu & CU_UNPAK) mtxb[p++] = M[xma] & 0377;
|
||||
else {
|
||||
mtxb[p++] = (M[xma] >> 6) & 077;
|
||||
mtxb[p++] = M[xma] & 077;
|
||||
}
|
||||
}
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
xma = GET_EMA (mt_cu) + mt_ca; /* restore xma */
|
||||
}
|
||||
else mt_wc = 0; /* ok, clear wc */
|
||||
break;
|
||||
|
||||
case FN_WREOF:
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
case FN_WREOF:
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case FN_SPACEF: /* space forward */
|
||||
do {
|
||||
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; } /* stop */
|
||||
}
|
||||
while (mt_wc != 0);
|
||||
break;
|
||||
case FN_SPACEF: /* space forward */
|
||||
do {
|
||||
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; /* stop */
|
||||
}
|
||||
} while (mt_wc != 0);
|
||||
break;
|
||||
|
||||
case FN_SPACER: /* space reverse */
|
||||
do {
|
||||
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; } /* stop */
|
||||
}
|
||||
while (mt_wc != 0);
|
||||
break; } /* end case */
|
||||
case FN_SPACER: /* space reverse */
|
||||
do {
|
||||
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; /* stop */
|
||||
}
|
||||
} while (mt_wc != 0);
|
||||
break;
|
||||
} /* end case */
|
||||
|
||||
mt_cu = (mt_cu & ~CU_EMA) | ((xma >> (12 - CU_V_EMA)) & CU_EMA);
|
||||
mt_ca = xma & 07777; /* update mem addr */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
mt_ca = xma & 07777; /* update mem addr */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Update controller status */
|
||||
|
||||
int32 mt_updcsta (UNIT *uptr)
|
||||
@@ -458,23 +499,25 @@ UNIT *mt_busy (void)
|
||||
int32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
uptr = mt_dev.units + u;
|
||||
if (sim_is_active (uptr) && ((uptr->USTAT & STA_REW) == 0))
|
||||
return uptr; }
|
||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
uptr = mt_dev.units + u;
|
||||
if (sim_is_active (uptr) && ((uptr->USTAT & STA_REW) == 0))
|
||||
return uptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Increment extended memory address */
|
||||
|
||||
int32 mt_ixma (int32 xma) /* incr extended ma */
|
||||
int32 mt_ixma (int32 xma) /* incr extended ma */
|
||||
{
|
||||
int32 v;
|
||||
|
||||
v = ((xma + 1) & 07777) | (xma & 070000); /* wrapped incr */
|
||||
if (mt_fn & FN_INC) { /* increment mode? */
|
||||
if (xma == 077777) mt_sta = mt_sta | STA_INC | STA_ERR; /* at limit? error */
|
||||
else v = xma + 1; } /* else 15b incr */
|
||||
v = ((xma + 1) & 07777) | (xma & 070000); /* wrapped incr */
|
||||
if (mt_fn & FN_INC) { /* increment mode? */
|
||||
if (xma == 077777) mt_sta = mt_sta | STA_INC | STA_ERR; /* at limit? error */
|
||||
else v = xma + 1; /* else 15b incr */
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -482,8 +525,8 @@ return v;
|
||||
|
||||
void mt_set_done (void)
|
||||
{
|
||||
mt_done = 1; /* set done */
|
||||
mt_fn = mt_fn & ~(FN_CRC | FN_GO | FN_INC); /* clear func<4:6> */
|
||||
mt_done = 1; /* set done */
|
||||
mt_fn = mt_fn & ~(FN_CRC | FN_GO | FN_INC); /* clear func<4:6> */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -492,36 +535,45 @@ return;
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
switch (st) {
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* unattached */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
case MTSE_TMK: /* end of file */
|
||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
if (mt_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
break;
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||
break; }
|
||||
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* unattached */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
|
||||
case MTSE_TMK: /* end of file */
|
||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
break;
|
||||
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
if (mt_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
return SCPE_MTRLNT;
|
||||
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
break;
|
||||
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
break;
|
||||
|
||||
case MTSE_WRP: /* write protect */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||
break;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat mt_reset (DEVICE *dptr)
|
||||
@@ -530,16 +582,17 @@ int32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
mt_cu = mt_fn = mt_wc = mt_ca = mt_db = mt_sta = mt_done = 0;
|
||||
int_req = int_req & ~INT_MT; /* clear interrupt */
|
||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
uptr = mt_dev.units + u;
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
sim_tape_reset (uptr); /* reset tape */
|
||||
if (uptr->flags & UNIT_ATT) uptr->USTAT =
|
||||
(sim_tape_bot (uptr)? STA_BOT: 0) |
|
||||
(sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||
else uptr->USTAT = STA_REM; }
|
||||
if (mtxb == NULL) mtxb = calloc (MT_MAXFR, sizeof (uint8));
|
||||
int_req = int_req & ~INT_MT; /* clear interrupt */
|
||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
uptr = mt_dev.units + u;
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
sim_tape_reset (uptr); /* reset tape */
|
||||
if (uptr->flags & UNIT_ATT) uptr->USTAT =
|
||||
(sim_tape_bot (uptr)? STA_BOT: 0) |
|
||||
(sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||
else uptr->USTAT = STA_REM;
|
||||
}
|
||||
if (mtxb == NULL) mtxb = (uint8 *) calloc (MT_MAXFR, sizeof (uint8));
|
||||
if (mtxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -549,7 +602,7 @@ return SCPE_OK;
|
||||
t_stat mt_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||
|
||||
r = sim_tape_attach (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
@@ -562,9 +615,9 @@ return r;
|
||||
|
||||
t_stat mt_detach (UNIT* uptr)
|
||||
{
|
||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check for attached */
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check for attached */
|
||||
if (!sim_is_active (uptr)) uptr->USTAT = STA_REM;
|
||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
||||
return sim_tape_detach (uptr);
|
||||
@@ -574,10 +627,10 @@ return sim_tape_detach (uptr);
|
||||
|
||||
t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr)))
|
||||
uptr->USTAT = uptr->USTAT | STA_WLK;
|
||||
uptr->USTAT = uptr->USTAT | STA_WLK;
|
||||
else uptr->USTAT = uptr->USTAT & ~STA_WLK;
|
||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
||||
return SCPE_OK;
|
||||
|
||||
292
PDP8/pdp8_pt.c
292
PDP8/pdp8_pt.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_pt.c: PDP-8 paper tape reader/punch simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,24 +19,24 @@
|
||||
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.
|
||||
|
||||
ptr,ptp PC8E paper tape reader/punch
|
||||
ptr,ptp PC8E paper tape reader/punch
|
||||
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
04-Oct-02 RMS Added DIBs
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
30-Nov-01 RMS Added read only unit support
|
||||
30-Mar-98 RMS Added RIM loader as PTR bootstrap
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
04-Oct-02 RMS Added DIBs
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
30-Nov-01 RMS Added read only unit support
|
||||
30-Mar-98 RMS Added RIM loader as PTR bootstrap
|
||||
*/
|
||||
|
||||
#include "pdp8_defs.h"
|
||||
|
||||
extern int32 int_req, int_enable, dev_done, stop_inst;
|
||||
|
||||
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
|
||||
int32 ptr (int32 IR, int32 AC);
|
||||
int32 ptp (int32 IR, int32 AC);
|
||||
@@ -45,98 +45,111 @@ t_stat ptp_svc (UNIT *uptr);
|
||||
t_stat ptr_reset (DEVICE *dptr);
|
||||
t_stat ptp_reset (DEVICE *dptr);
|
||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
||||
|
||||
|
||||
/* PTR data structures
|
||||
|
||||
ptr_dev PTR device descriptor
|
||||
ptr_unit PTR unit descriptor
|
||||
ptr_reg PTR register list
|
||||
ptr_dev PTR device descriptor
|
||||
ptr_unit PTR unit descriptor
|
||||
ptr_reg PTR register list
|
||||
*/
|
||||
|
||||
DIB ptr_dib = { DEV_PTR, 1, { &ptr } };
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT };
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT
|
||||
};
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (BUF, ptr_unit.buf, 8) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_PTR) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_PTR) },
|
||||
{ FLDATA (INT, int_req, INT_V_PTR) },
|
||||
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
||||
{ NULL } };
|
||||
{ ORDATA (BUF, ptr_unit.buf, 8) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_PTR) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_PTR) },
|
||||
{ FLDATA (INT, int_req, INT_V_PTR) },
|
||||
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ptr_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ 0 } };
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ptr_dev = {
|
||||
"PTR", &ptr_unit, ptr_reg, ptr_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptr_reset,
|
||||
&ptr_boot, NULL, NULL,
|
||||
&ptr_dib, 0 };
|
||||
"PTR", &ptr_unit, ptr_reg, ptr_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptr_reset,
|
||||
&ptr_boot, NULL, NULL,
|
||||
&ptr_dib, 0 };
|
||||
|
||||
/* PTP data structures
|
||||
|
||||
ptp_dev PTP device descriptor
|
||||
ptp_unit PTP unit descriptor
|
||||
ptp_reg PTP register list
|
||||
ptp_dev PTP device descriptor
|
||||
ptp_unit PTP unit descriptor
|
||||
ptp_reg PTP register list
|
||||
*/
|
||||
|
||||
DIB ptp_dib = { DEV_PTP, 1, { &ptp } };
|
||||
|
||||
UNIT ptp_unit = {
|
||||
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
|
||||
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
|
||||
};
|
||||
|
||||
REG ptp_reg[] = {
|
||||
{ ORDATA (BUF, ptp_unit.buf, 8) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_PTP) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_PTP) },
|
||||
{ FLDATA (INT, int_req, INT_V_PTP) },
|
||||
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
|
||||
{ NULL } };
|
||||
{ ORDATA (BUF, ptp_unit.buf, 8) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_PTP) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_PTP) },
|
||||
{ FLDATA (INT, int_req, INT_V_PTP) },
|
||||
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ptp_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ 0 } };
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ptp_dev = {
|
||||
"PTP", &ptp_unit, ptp_reg, ptp_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptp_reset,
|
||||
NULL, NULL, NULL,
|
||||
&ptp_dib, 0 };
|
||||
|
||||
"PTP", &ptp_unit, ptp_reg, ptp_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptp_reset,
|
||||
NULL, NULL, NULL,
|
||||
&ptp_dib, 0
|
||||
};
|
||||
|
||||
/* Paper tape reader: IOT routine */
|
||||
|
||||
int32 ptr (int32 IR, int32 AC)
|
||||
{
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 0: /* RPE */
|
||||
int_enable = int_enable | (INT_PTR+INT_PTP); /* set enable */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
case 1: /* RSF */
|
||||
return (dev_done & INT_PTR)? IOT_SKP + AC: AC;
|
||||
case 6: /* RFC!RRB */
|
||||
sim_activate (&ptr_unit, ptr_unit.wait);
|
||||
case 2: /* RRB */
|
||||
dev_done = dev_done & ~INT_PTR; /* clear flag */
|
||||
int_req = int_req & ~INT_PTR; /* clear int req */
|
||||
return (AC | ptr_unit.buf); /* or data to AC */
|
||||
case 4: /* RFC */
|
||||
sim_activate (&ptr_unit, ptr_unit.wait);
|
||||
dev_done = dev_done & ~INT_PTR; /* clear flag */
|
||||
int_req = int_req & ~INT_PTR; /* clear int req */
|
||||
return AC;
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 0: /* RPE */
|
||||
int_enable = int_enable | (INT_PTR+INT_PTP); /* set enable */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
|
||||
case 1: /* RSF */
|
||||
return (dev_done & INT_PTR)? IOT_SKP + AC: AC;
|
||||
|
||||
case 6: /* RFC!RRB */
|
||||
sim_activate (&ptr_unit, ptr_unit.wait);
|
||||
case 2: /* RRB */
|
||||
dev_done = dev_done & ~INT_PTR; /* clear flag */
|
||||
int_req = int_req & ~INT_PTR; /* clear int req */
|
||||
return (AC | ptr_unit.buf); /* or data to AC */
|
||||
|
||||
case 4: /* RFC */
|
||||
sim_activate (&ptr_unit, ptr_unit.wait);
|
||||
dev_done = dev_done & ~INT_PTR; /* clear flag */
|
||||
int_req = int_req & ~INT_PTR; /* clear int req */
|
||||
return AC;
|
||||
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
} /* end switch */
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
@@ -145,17 +158,19 @@ t_stat ptr_svc (UNIT *uptr)
|
||||
{
|
||||
int32 temp;
|
||||
|
||||
if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptr_stopioe, SCPE_UNATT);
|
||||
if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptr_stopioe, SCPE_UNATT);
|
||||
if ((temp = getc (ptr_unit.fileref)) == EOF) {
|
||||
if (feof (ptr_unit.fileref)) {
|
||||
if (ptr_stopioe) printf ("PTR end of file\n");
|
||||
else return SCPE_OK; }
|
||||
else perror ("PTR I/O error");
|
||||
clearerr (ptr_unit.fileref);
|
||||
return SCPE_IOERR; }
|
||||
dev_done = dev_done | INT_PTR; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
if (feof (ptr_unit.fileref)) {
|
||||
if (ptr_stopioe) printf ("PTR end of file\n");
|
||||
else return SCPE_OK;
|
||||
}
|
||||
else perror ("PTR I/O error");
|
||||
clearerr (ptr_unit.fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
dev_done = dev_done | INT_PTR; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
ptr_unit.buf = temp & 0377;
|
||||
ptr_unit.pos = ptr_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
@@ -166,51 +181,58 @@ return SCPE_OK;
|
||||
t_stat ptr_reset (DEVICE *dptr)
|
||||
{
|
||||
ptr_unit.buf = 0;
|
||||
dev_done = dev_done & ~INT_PTR; /* clear done, int */
|
||||
dev_done = dev_done & ~INT_PTR; /* clear done, int */
|
||||
int_req = int_req & ~INT_PTR;
|
||||
int_enable = int_enable | INT_PTR; /* set enable */
|
||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||
int_enable = int_enable | INT_PTR; /* set enable */
|
||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Paper tape punch: IOT routine */
|
||||
|
||||
int32 ptp (int32 IR, int32 AC)
|
||||
{
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 0: /* PCE */
|
||||
int_enable = int_enable & ~(INT_PTR+INT_PTP); /* clear enables */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
case 1: /* PSF */
|
||||
return (dev_done & INT_PTP)? IOT_SKP + AC: AC;
|
||||
case 2: /* PCF */
|
||||
dev_done = dev_done & ~INT_PTP; /* clear flag */
|
||||
int_req = int_req & ~INT_PTP; /* clear int req */
|
||||
return AC;
|
||||
case 6: /* PLS */
|
||||
dev_done = dev_done & ~INT_PTP; /* clear flag */
|
||||
int_req = int_req & ~INT_PTP; /* clear int req */
|
||||
case 4: /* PPC */
|
||||
ptp_unit.buf = AC & 0377; /* load punch buf */
|
||||
sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */
|
||||
return AC;
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 0: /* PCE */
|
||||
int_enable = int_enable & ~(INT_PTR+INT_PTP); /* clear enables */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
|
||||
case 1: /* PSF */
|
||||
return (dev_done & INT_PTP)? IOT_SKP + AC: AC;
|
||||
|
||||
case 2: /* PCF */
|
||||
dev_done = dev_done & ~INT_PTP; /* clear flag */
|
||||
int_req = int_req & ~INT_PTP; /* clear int req */
|
||||
return AC;
|
||||
|
||||
case 6: /* PLS */
|
||||
dev_done = dev_done & ~INT_PTP; /* clear flag */
|
||||
int_req = int_req & ~INT_PTP; /* clear int req */
|
||||
case 4: /* PPC */
|
||||
ptp_unit.buf = AC & 0377; /* load punch buf */
|
||||
sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */
|
||||
return AC;
|
||||
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
} /* end switch */
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat ptp_svc (UNIT *uptr)
|
||||
{
|
||||
dev_done = dev_done | INT_PTP; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptp_stopioe, SCPE_UNATT);
|
||||
dev_done = dev_done | INT_PTP; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptp_stopioe, SCPE_UNATT);
|
||||
if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) {
|
||||
perror ("PTP I/O error");
|
||||
clearerr (ptp_unit.fileref);
|
||||
return SCPE_IOERR; }
|
||||
perror ("PTP I/O error");
|
||||
clearerr (ptp_unit.fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
ptp_unit.pos = ptp_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -220,10 +242,10 @@ return SCPE_OK;
|
||||
t_stat ptp_reset (DEVICE *dptr)
|
||||
{
|
||||
ptp_unit.buf = 0;
|
||||
dev_done = dev_done & ~INT_PTP; /* clear done, int */
|
||||
dev_done = dev_done & ~INT_PTP; /* clear done, int */
|
||||
int_req = int_req & ~INT_PTP;
|
||||
int_enable = int_enable | INT_PTP; /* set enable */
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
int_enable = int_enable | INT_PTP; /* set enable */
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -233,25 +255,25 @@ return SCPE_OK;
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16))
|
||||
|
||||
static const uint16 boot_rom[] = {
|
||||
06014, /* 7756, RFC */
|
||||
06011, /* 7757, LOOP, RSF */
|
||||
05357, /* JMP .-1 */
|
||||
06016, /* RFC RRB */
|
||||
07106, /* CLL RTL*/
|
||||
07006, /* RTL */
|
||||
07510, /* SPA*/
|
||||
05374, /* JMP 7774 */
|
||||
07006, /* RTL */
|
||||
06011, /* RSF */
|
||||
05367, /* JMP .-1 */
|
||||
06016, /* RFC RRB */
|
||||
07420, /* SNL */
|
||||
03776, /* DCA I 7776 */
|
||||
03376, /* 7774, DCA 7776 */
|
||||
05357, /* JMP 7757 */
|
||||
00000, /* 7776, 0 */
|
||||
05301 /* 7777, JMP 7701 */
|
||||
};
|
||||
06014, /* 7756, RFC */
|
||||
06011, /* 7757, LOOP, RSF */
|
||||
05357, /* JMP .-1 */
|
||||
06016, /* RFC RRB */
|
||||
07106, /* CLL RTL*/
|
||||
07006, /* RTL */
|
||||
07510, /* SPA*/
|
||||
05374, /* JMP 7774 */
|
||||
07006, /* RTL */
|
||||
06011, /* RSF */
|
||||
05367, /* JMP .-1 */
|
||||
06016, /* RFC RRB */
|
||||
07420, /* SNL */
|
||||
03776, /* DCA I 7776 */
|
||||
03376, /* 7774, DCA 7776 */
|
||||
05357, /* JMP 7757 */
|
||||
00000, /* 7776, 0 */
|
||||
05301 /* 7777, JMP 7701 */
|
||||
};
|
||||
|
||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
@@ -259,7 +281,7 @@ int32 i;
|
||||
extern int32 saved_PC;
|
||||
extern uint16 M[];
|
||||
|
||||
if (ptr_dib.dev != DEV_PTR) return STOP_NOTSTD; /* only std devno */
|
||||
if (ptr_dib.dev != DEV_PTR) return STOP_NOTSTD; /* only std devno */
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||
saved_PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
|
||||
479
PDP8/pdp8_rf.c
479
PDP8/pdp8_rf.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_rf.c: RF08 fixed head disk simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,99 +19,99 @@
|
||||
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.
|
||||
|
||||
rf RF08 fixed head disk
|
||||
rf RF08 fixed head disk
|
||||
|
||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
26-Jul-03 RMS Fixed bug in set size routine
|
||||
14-Mar-03 RMS Fixed variable platter interaction with save/restore
|
||||
03-Mar-03 RMS Fixed autosizing
|
||||
02-Feb-03 RMS Added variable platter and autosizing support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
28-Nov-01 RMS Added RL8A support
|
||||
25-Apr-01 RMS Added device enable/disable support
|
||||
19-Mar-01 RMS Added disk monitor bootstrap, fixed IOT decoding
|
||||
15-Feb-01 RMS Fixed 3 cycle data break sequence
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
30-Mar-98 RMS Fixed bug in RF bootstrap
|
||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
26-Jul-03 RMS Fixed bug in set size routine
|
||||
14-Mar-03 RMS Fixed variable platter interaction with save/restore
|
||||
03-Mar-03 RMS Fixed autosizing
|
||||
02-Feb-03 RMS Added variable platter and autosizing support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
28-Nov-01 RMS Added RL8A support
|
||||
25-Apr-01 RMS Added device enable/disable support
|
||||
19-Mar-01 RMS Added disk monitor bootstrap, fixed IOT decoding
|
||||
15-Feb-01 RMS Fixed 3 cycle data break sequence
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
30-Mar-98 RMS Fixed bug in RF bootstrap
|
||||
|
||||
The RF08 is a head-per-track disk. It uses the three cycle data break
|
||||
facility. To minimize overhead, the entire RF08 is buffered in memory.
|
||||
|
||||
Two timing parameters are provided:
|
||||
|
||||
rf_time Interword timing, must be non-zero
|
||||
rf_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise,
|
||||
DMA occurs in a burst
|
||||
rf_time Interword timing, must be non-zero
|
||||
rf_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise,
|
||||
DMA occurs in a burst
|
||||
*/
|
||||
|
||||
#include "pdp8_defs.h"
|
||||
#include <math.h>
|
||||
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 03
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 03
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define RF_NUMWD 2048 /* words/track */
|
||||
#define RF_NUMTR 128 /* tracks/disk */
|
||||
#define RF_DKSIZE (RF_NUMTR * RF_NUMWD) /* words/disk */
|
||||
#define RF_NUMDK 4 /* disks/controller */
|
||||
#define RF_WC 07750 /* word count */
|
||||
#define RF_MA 07751 /* mem address */
|
||||
#define RF_WMASK (RF_NUMWD - 1) /* word mask */
|
||||
#define RF_NUMWD 2048 /* words/track */
|
||||
#define RF_NUMTR 128 /* tracks/disk */
|
||||
#define RF_DKSIZE (RF_NUMTR * RF_NUMWD) /* words/disk */
|
||||
#define RF_NUMDK 4 /* disks/controller */
|
||||
#define RF_WC 07750 /* word count */
|
||||
#define RF_MA 07751 /* mem address */
|
||||
#define RF_WMASK (RF_NUMWD - 1) /* word mask */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
#define FUNC u4 /* function */
|
||||
#define RF_READ 2 /* read */
|
||||
#define RF_WRITE 4 /* write */
|
||||
#define FUNC u4 /* function */
|
||||
#define RF_READ 2 /* read */
|
||||
#define RF_WRITE 4 /* write */
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define RFS_PCA 04000 /* photocell status */
|
||||
#define RFS_DRE 02000 /* data req enable */
|
||||
#define RFS_WLS 01000 /* write lock status */
|
||||
#define RFS_EIE 00400 /* error int enable */
|
||||
#define RFS_PIE 00200 /* photocell int enb */
|
||||
#define RFS_CIE 00100 /* done int enable */
|
||||
#define RFS_MEX 00070 /* memory extension */
|
||||
#define RFS_DRL 00004 /* data late error */
|
||||
#define RFS_NXD 00002 /* non-existent disk */
|
||||
#define RFS_PER 00001 /* parity error */
|
||||
#define RFS_ERR (RFS_WLS + RFS_DRL + RFS_NXD + RFS_PER)
|
||||
#define RFS_V_MEX 3
|
||||
#define RFS_PCA 04000 /* photocell status */
|
||||
#define RFS_DRE 02000 /* data req enable */
|
||||
#define RFS_WLS 01000 /* write lock status */
|
||||
#define RFS_EIE 00400 /* error int enable */
|
||||
#define RFS_PIE 00200 /* photocell int enb */
|
||||
#define RFS_CIE 00100 /* done int enable */
|
||||
#define RFS_MEX 00070 /* memory extension */
|
||||
#define RFS_DRL 00004 /* data late error */
|
||||
#define RFS_NXD 00002 /* non-existent disk */
|
||||
#define RFS_PER 00001 /* parity error */
|
||||
#define RFS_ERR (RFS_WLS + RFS_DRL + RFS_NXD + RFS_PER)
|
||||
#define RFS_V_MEX 3
|
||||
|
||||
#define GET_MEX(x) (((x) & RFS_MEX) << (12 - RFS_V_MEX))
|
||||
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) RF_NUMWD)))
|
||||
#define UPDATE_PCELL if (GET_POS(rf_time) < 6) rf_sta = rf_sta | RFS_PCA; \
|
||||
else rf_sta = rf_sta & ~RFS_PCA
|
||||
#define RF_INT_UPDATE if ((rf_done && (rf_sta & RFS_CIE)) || \
|
||||
((rf_sta & RFS_ERR) && (rf_sta & RFS_EIE)) || \
|
||||
((rf_sta & RFS_PCA) && (rf_sta & RFS_PIE))) \
|
||||
int_req = int_req | INT_RF; \
|
||||
else int_req = int_req & ~INT_RF
|
||||
|
||||
#define GET_MEX(x) (((x) & RFS_MEX) << (12 - RFS_V_MEX))
|
||||
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) RF_NUMWD)))
|
||||
#define UPDATE_PCELL if (GET_POS(rf_time) < 6) rf_sta = rf_sta | RFS_PCA; \
|
||||
else rf_sta = rf_sta & ~RFS_PCA
|
||||
#define RF_INT_UPDATE if ((rf_done && (rf_sta & RFS_CIE)) || \
|
||||
((rf_sta & RFS_ERR) && (rf_sta & RFS_EIE)) || \
|
||||
((rf_sta & RFS_PCA) && (rf_sta & RFS_PIE))) \
|
||||
int_req = int_req | INT_RF; \
|
||||
else int_req = int_req & ~INT_RF
|
||||
|
||||
extern uint16 M[];
|
||||
extern int32 int_req, stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
int32 rf_sta = 0; /* status register */
|
||||
int32 rf_da = 0; /* disk address */
|
||||
int32 rf_done = 0; /* done flag */
|
||||
int32 rf_wlk = 0; /* write lock */
|
||||
int32 rf_time = 10; /* inter-word time */
|
||||
int32 rf_burst = 1; /* burst mode flag */
|
||||
int32 rf_stopioe = 1; /* stop on error */
|
||||
int32 rf_sta = 0; /* status register */
|
||||
int32 rf_da = 0; /* disk address */
|
||||
int32 rf_done = 0; /* done flag */
|
||||
int32 rf_wlk = 0; /* write lock */
|
||||
int32 rf_time = 10; /* inter-word time */
|
||||
int32 rf_burst = 1; /* burst mode flag */
|
||||
int32 rf_stopioe = 1; /* stop on error */
|
||||
|
||||
DEVICE rf_dev;
|
||||
int32 rf60 (int32 IR, int32 AC);
|
||||
@@ -127,52 +127,56 @@ t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* RF08 data structures
|
||||
|
||||
rf_dev RF device descriptor
|
||||
rf_unit RF unit descriptor
|
||||
pcell_unit photocell timing unit (orphan)
|
||||
rf_reg RF register list
|
||||
rf_dev RF device descriptor
|
||||
rf_unit RF unit descriptor
|
||||
pcell_unit photocell timing unit (orphan)
|
||||
rf_reg RF register list
|
||||
*/
|
||||
|
||||
DIB rf_dib = { DEV_RF, 5, { &rf60, &rf61, &rf62, NULL, &rf64 } };
|
||||
|
||||
UNIT rf_unit =
|
||||
{ UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, RF_DKSIZE) };
|
||||
UNIT rf_unit = {
|
||||
UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, RF_DKSIZE)
|
||||
};
|
||||
|
||||
UNIT pcell_unit = { UDATA (&pcell_svc, 0, 0) };
|
||||
|
||||
REG rf_reg[] = {
|
||||
{ ORDATA (STA, rf_sta, 12) },
|
||||
{ ORDATA (DA, rf_da, 20) },
|
||||
{ ORDATA (WC, M[RF_WC], 12) },
|
||||
{ ORDATA (MA, M[RF_MA], 12) },
|
||||
{ FLDATA (DONE, rf_done, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_RF) },
|
||||
{ ORDATA (WLK, rf_wlk, 32) },
|
||||
{ DRDATA (TIME, rf_time, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (BURST, rf_burst, 0) },
|
||||
{ FLDATA (STOP_IOE, rf_stopioe, 0) },
|
||||
{ DRDATA (CAPAC, rf_unit.capac, 21), REG_HRO },
|
||||
{ ORDATA (DEVNUM, rf_dib.dev, 6), REG_HRO },
|
||||
{ NULL } };
|
||||
{ ORDATA (STA, rf_sta, 12) },
|
||||
{ ORDATA (DA, rf_da, 20) },
|
||||
{ ORDATA (WC, M[RF_WC], 12) },
|
||||
{ ORDATA (MA, M[RF_MA], 12) },
|
||||
{ FLDATA (DONE, rf_done, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_RF) },
|
||||
{ ORDATA (WLK, rf_wlk, 32) },
|
||||
{ DRDATA (TIME, rf_time, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (BURST, rf_burst, 0) },
|
||||
{ FLDATA (STOP_IOE, rf_stopioe, 0) },
|
||||
{ DRDATA (CAPAC, rf_unit.capac, 21), REG_HRO },
|
||||
{ ORDATA (DEVNUM, rf_dib.dev, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB rf_mod[] = {
|
||||
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size },
|
||||
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size },
|
||||
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size },
|
||||
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size },
|
||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size },
|
||||
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size },
|
||||
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size },
|
||||
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size },
|
||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE rf_dev = {
|
||||
"RF", &rf_unit, rf_reg, rf_mod,
|
||||
1, 8, 20, 1, 8, 12,
|
||||
NULL, NULL, &rf_reset,
|
||||
&rf_boot, &rf_attach, NULL,
|
||||
&rf_dib, DEV_DISABLE | DEV_DIS };
|
||||
|
||||
"RF", &rf_unit, rf_reg, rf_mod,
|
||||
1, 8, 20, 1, 8, 12,
|
||||
NULL, NULL, &rf_reset,
|
||||
&rf_boot, &rf_attach, NULL,
|
||||
&rf_dib, DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* IOT routines */
|
||||
|
||||
int32 rf60 (int32 IR, int32 AC)
|
||||
@@ -180,19 +184,21 @@ int32 rf60 (int32 IR, int32 AC)
|
||||
int32 t;
|
||||
int32 pulse = IR & 07;
|
||||
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) { /* DCMA */
|
||||
rf_da = rf_da & ~07777; /* clear DAR<8:19> */
|
||||
rf_done = 0; /* clear done */
|
||||
rf_sta = rf_sta & ~RFS_ERR; /* clear errors */
|
||||
RF_INT_UPDATE; } /* update int req */
|
||||
if (pulse & 6) { /* DMAR, DMAW */
|
||||
rf_da = rf_da | AC; /* DAR<8:19> |= AC */
|
||||
rf_unit.FUNC = pulse & ~1; /* save function */
|
||||
t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new loc */
|
||||
if (t < 0) t = t + RF_NUMWD; /* wrap around? */
|
||||
sim_activate (&rf_unit, t * rf_time); /* schedule op */
|
||||
AC = 0; } /* clear AC */
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) { /* DCMA */
|
||||
rf_da = rf_da & ~07777; /* clear DAR<8:19> */
|
||||
rf_done = 0; /* clear done */
|
||||
rf_sta = rf_sta & ~RFS_ERR; /* clear errors */
|
||||
RF_INT_UPDATE; /* update int req */
|
||||
}
|
||||
if (pulse & 6) { /* DMAR, DMAW */
|
||||
rf_da = rf_da | AC; /* DAR<8:19> |= AC */
|
||||
rf_unit.FUNC = pulse & ~1; /* save function */
|
||||
t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new loc */
|
||||
if (t < 0) t = t + RF_NUMWD; /* wrap around? */
|
||||
sim_activate (&rf_unit, t * rf_time); /* schedule op */
|
||||
AC = 0; /* clear AC */
|
||||
}
|
||||
return AC;
|
||||
}
|
||||
|
||||
@@ -200,41 +206,47 @@ int32 rf61 (int32 IR, int32 AC)
|
||||
{
|
||||
int32 pulse = IR & 07;
|
||||
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
switch (pulse) { /* decode IR<9:11> */
|
||||
case 1: /* DCIM */
|
||||
rf_sta = rf_sta & 07007; /* clear STA<3:8> */
|
||||
int_req = int_req & ~INT_RF; /* clear int req */
|
||||
sim_cancel (&pcell_unit); /* cancel photocell */
|
||||
return AC;
|
||||
case 2: /* DSAC */
|
||||
return ((rf_da & RF_WMASK) == GET_POS (rf_time))? IOT_SKP: 0;
|
||||
case 5: /* DIML */
|
||||
rf_sta = (rf_sta & 07007) | (AC & 0770); /* STA<3:8> <- AC */
|
||||
if (rf_sta & RFS_PIE) /* photocell int? */
|
||||
sim_activate (&pcell_unit, (RF_NUMWD - GET_POS (rf_time)) *
|
||||
rf_time);
|
||||
else sim_cancel (&pcell_unit);
|
||||
RF_INT_UPDATE; /* update int req */
|
||||
return 0; /* clear AC */
|
||||
case 6: /* DIMA */
|
||||
return rf_sta; } /* AC <- STA<0:11> */
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
switch (pulse) { /* decode IR<9:11> */
|
||||
|
||||
case 1: /* DCIM */
|
||||
rf_sta = rf_sta & 07007; /* clear STA<3:8> */
|
||||
int_req = int_req & ~INT_RF; /* clear int req */
|
||||
sim_cancel (&pcell_unit); /* cancel photocell */
|
||||
return AC;
|
||||
|
||||
case 2: /* DSAC */
|
||||
return ((rf_da & RF_WMASK) == GET_POS (rf_time))? IOT_SKP: 0;
|
||||
|
||||
case 5: /* DIML */
|
||||
rf_sta = (rf_sta & 07007) | (AC & 0770); /* STA<3:8> <- AC */
|
||||
if (rf_sta & RFS_PIE) /* photocell int? */
|
||||
sim_activate (&pcell_unit, (RF_NUMWD - GET_POS (rf_time)) *
|
||||
rf_time);
|
||||
else sim_cancel (&pcell_unit);
|
||||
RF_INT_UPDATE; /* update int req */
|
||||
return 0; /* clear AC */
|
||||
|
||||
case 6: /* DIMA */
|
||||
return rf_sta; /* AC <- STA<0:11> */
|
||||
}
|
||||
|
||||
return AC;
|
||||
}
|
||||
|
||||
/* IOT's, continued */
|
||||
|
||||
int32 rf62 (int32 IR, int32 AC)
|
||||
{
|
||||
int32 pulse = IR & 07;
|
||||
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) { /* DFSE */
|
||||
if (rf_sta & RFS_ERR) AC = AC | IOT_SKP; }
|
||||
if (pulse & 2) { /* DFSC */
|
||||
if (pulse & 4) AC = AC & ~07777; /* for DMAC */
|
||||
else if (rf_done) AC = AC | IOT_SKP; }
|
||||
if (pulse & 4) AC = AC | (rf_da & 07777); /* DMAC */
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if (pulse & 1) { /* DFSE */
|
||||
if (rf_sta & RFS_ERR) AC = AC | IOT_SKP;
|
||||
}
|
||||
if (pulse & 2) { /* DFSC */
|
||||
if (pulse & 4) AC = AC & ~07777; /* for DMAC */
|
||||
else if (rf_done) AC = AC | IOT_SKP;
|
||||
}
|
||||
if (pulse & 4) AC = AC | (rf_da & 07777); /* DMAC */
|
||||
return AC;
|
||||
}
|
||||
|
||||
@@ -242,31 +254,37 @@ int32 rf64 (int32 IR, int32 AC)
|
||||
{
|
||||
int32 pulse = IR & 07;
|
||||
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
switch (pulse) { /* decode IR<9:11> */
|
||||
case 1: /* DCXA */
|
||||
rf_da = rf_da & 07777; /* clear DAR<0:7> */
|
||||
break;
|
||||
case 3: /* DXAL */
|
||||
rf_da = rf_da & 07777; /* clear DAR<0:7> */
|
||||
case 2: /* DXAL w/o clear */
|
||||
rf_da = rf_da | ((AC & 0377) << 12); /* DAR<0:7> |= AC */
|
||||
AC = AC & ~07777; /* clear AC */
|
||||
break;
|
||||
case 5: /* DXAC */
|
||||
AC = AC & ~07777; /* clear AC */
|
||||
case 4: /* DXAC w/o clear */
|
||||
AC = AC | ((rf_da >> 12) & 0377); /* AC |= DAR<0:7> */
|
||||
break;
|
||||
default:
|
||||
AC = (stop_inst << IOT_V_REASON) + AC;
|
||||
break; } /* end switch */
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
switch (pulse) { /* decode IR<9:11> */
|
||||
|
||||
case 1: /* DCXA */
|
||||
rf_da = rf_da & 07777; /* clear DAR<0:7> */
|
||||
break;
|
||||
|
||||
case 3: /* DXAL */
|
||||
rf_da = rf_da & 07777; /* clear DAR<0:7> */
|
||||
case 2: /* DXAL w/o clear */
|
||||
rf_da = rf_da | ((AC & 0377) << 12); /* DAR<0:7> |= AC */
|
||||
AC = 0; /* clear AC */
|
||||
break;
|
||||
|
||||
case 5: /* DXAC */
|
||||
AC = 0; /* clear AC */
|
||||
case 4: /* DXAC w/o clear */
|
||||
AC = AC | ((rf_da >> 12) & 0377); /* AC |= DAR<0:7> */
|
||||
break;
|
||||
|
||||
default:
|
||||
AC = (stop_inst << IOT_V_REASON) + AC;
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
if ((uint32) rf_da >= rf_unit.capac) rf_sta = rf_sta | RFS_NXD;
|
||||
else rf_sta = rf_sta & ~RFS_NXD;
|
||||
RF_INT_UPDATE;
|
||||
return AC;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service
|
||||
|
||||
Note that for reads and writes, memory addresses wrap around in the
|
||||
@@ -278,37 +296,45 @@ t_stat rf_svc (UNIT *uptr)
|
||||
int32 pa, t, mex;
|
||||
int16 *fbuf = uptr->filebuf;
|
||||
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
rf_sta = rf_sta | RFS_NXD;
|
||||
rf_done = 1;
|
||||
RF_INT_UPDATE; /* update int req */
|
||||
return IORETURN (rf_stopioe, SCPE_UNATT); }
|
||||
UPDATE_PCELL; /* update photocell */
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
rf_sta = rf_sta | RFS_NXD;
|
||||
rf_done = 1;
|
||||
RF_INT_UPDATE; /* update int req */
|
||||
return IORETURN (rf_stopioe, SCPE_UNATT);
|
||||
}
|
||||
|
||||
mex = GET_MEX (rf_sta);
|
||||
do { if ((uint32) rf_da >= rf_unit.capac) { /* disk overflow? */
|
||||
rf_sta = rf_sta | RFS_NXD;
|
||||
break; }
|
||||
M[RF_WC] = (M[RF_WC] + 1) & 07777; /* incr word count */
|
||||
M[RF_MA] = (M[RF_MA] + 1) & 07777; /* incr mem addr */
|
||||
pa = mex | M[RF_MA]; /* add extension */
|
||||
if (uptr->FUNC == RF_READ) { /* read? */
|
||||
if (MEM_ADDR_OK (pa)) /* if !nxm */
|
||||
M[pa] = fbuf[rf_da]; } /* read word */
|
||||
else { /* write */
|
||||
t = ((rf_da >> 15) & 030) | ((rf_da >> 14) & 07);
|
||||
if ((rf_wlk >> t) & 1) /* write locked? */
|
||||
rf_sta = rf_sta | RFS_WLS;
|
||||
else { /* not locked */
|
||||
fbuf[rf_da] = M[pa]; /* write word */
|
||||
if (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; } }
|
||||
rf_da = (rf_da + 1) & 03777777; } /* incr disk addr */
|
||||
while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */
|
||||
do {
|
||||
if ((uint32) rf_da >= rf_unit.capac) { /* disk overflow? */
|
||||
rf_sta = rf_sta | RFS_NXD;
|
||||
break;
|
||||
}
|
||||
M[RF_WC] = (M[RF_WC] + 1) & 07777; /* incr word count */
|
||||
M[RF_MA] = (M[RF_MA] + 1) & 07777; /* incr mem addr */
|
||||
pa = mex | M[RF_MA]; /* add extension */
|
||||
if (uptr->FUNC == RF_READ) { /* read? */
|
||||
if (MEM_ADDR_OK (pa)) /* if !nxm */
|
||||
M[pa] = fbuf[rf_da]; /* read word */
|
||||
}
|
||||
else { /* write */
|
||||
t = ((rf_da >> 15) & 030) | ((rf_da >> 14) & 07);
|
||||
if ((rf_wlk >> t) & 1) /* write locked? */
|
||||
rf_sta = rf_sta | RFS_WLS;
|
||||
else { /* not locked */
|
||||
fbuf[rf_da] = M[pa]; /* write word */
|
||||
if (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1;
|
||||
}
|
||||
}
|
||||
rf_da = (rf_da + 1) & 03777777; /* incr disk addr */
|
||||
} while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */
|
||||
|
||||
if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */
|
||||
sim_activate (&rf_unit, rf_time); /* sched next */
|
||||
else { rf_done = 1; /* done */
|
||||
RF_INT_UPDATE; } /* update int req */
|
||||
if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */
|
||||
sim_activate (&rf_unit, rf_time); /* sched next */
|
||||
else {
|
||||
rf_done = 1; /* done */
|
||||
RF_INT_UPDATE; /* update int req */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -316,20 +342,21 @@ return SCPE_OK;
|
||||
|
||||
t_stat pcell_svc (UNIT *uptr)
|
||||
{
|
||||
rf_sta = rf_sta | RFS_PCA; /* set photocell */
|
||||
if (rf_sta & RFS_PIE) { /* int enable? */
|
||||
sim_activate (&pcell_unit, RF_NUMWD * rf_time);
|
||||
int_req = int_req | INT_RF; }
|
||||
rf_sta = rf_sta | RFS_PCA; /* set photocell */
|
||||
if (rf_sta & RFS_PIE) { /* int enable? */
|
||||
sim_activate (&pcell_unit, RF_NUMWD * rf_time);
|
||||
int_req = int_req | INT_RF;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat rf_reset (DEVICE *dptr)
|
||||
{
|
||||
rf_sta = rf_da = 0;
|
||||
rf_done = 1;
|
||||
int_req = int_req & ~INT_RF; /* clear interrupt */
|
||||
int_req = int_req & ~INT_RF; /* clear interrupt */
|
||||
sim_cancel (&rf_unit);
|
||||
sim_cancel (&pcell_unit);
|
||||
return SCPE_OK;
|
||||
@@ -337,42 +364,45 @@ return SCPE_OK;
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define OS8_START 07750
|
||||
#define OS8_LEN (sizeof (os8_rom) / sizeof (int16))
|
||||
#define DM4_START 00200
|
||||
#define DM4_LEN (sizeof (dm4_rom) / sizeof (int16))
|
||||
#define OS8_START 07750
|
||||
#define OS8_LEN (sizeof (os8_rom) / sizeof (int16))
|
||||
#define DM4_START 00200
|
||||
#define DM4_LEN (sizeof (dm4_rom) / sizeof (int16))
|
||||
|
||||
static const uint16 os8_rom[] = {
|
||||
07600, /* 7750, CLA CLL ; also word count */
|
||||
06603, /* 7751, DMAR ; also address */
|
||||
06622, /* 7752, DFSC ; done? */
|
||||
05352, /* 7753, JMP .-1 ; no */
|
||||
05752 /* 7754, JMP @.-2 ; enter boot */
|
||||
};
|
||||
07600, /* 7750, CLA CLL ; also word count */
|
||||
06603, /* 7751, DMAR ; also address */
|
||||
06622, /* 7752, DFSC ; done? */
|
||||
05352, /* 7753, JMP .-1 ; no */
|
||||
05752 /* 7754, JMP @.-2 ; enter boot */
|
||||
};
|
||||
|
||||
static const uint16 dm4_rom[] = {
|
||||
00200, 07600, /* 0200, CLA CLL */
|
||||
00201, 06603, /* 0201, DMAR ; read */
|
||||
00202, 06622, /* 0202, DFSC ; done? */
|
||||
00203, 05202, /* 0203, JMP .-1 ; no */
|
||||
00204, 05600, /* 0204, JMP @.-4 ; enter boot */
|
||||
07750, 07576, /* 7750, 7576 ; word count */
|
||||
07751, 07576 /* 7751, 7576 ; address */
|
||||
};
|
||||
00200, 07600, /* 0200, CLA CLL */
|
||||
00201, 06603, /* 0201, DMAR ; read */
|
||||
00202, 06622, /* 0202, DFSC ; done? */
|
||||
00203, 05202, /* 0203, JMP .-1 ; no */
|
||||
00204, 05600, /* 0204, JMP @.-4 ; enter boot */
|
||||
07750, 07576, /* 7750, 7576 ; word count */
|
||||
07751, 07576 /* 7751, 7576 ; address */
|
||||
};
|
||||
|
||||
t_stat rf_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
extern int32 sim_switches, saved_PC;
|
||||
|
||||
if (rf_dib.dev != DEV_RF) return STOP_NOTSTD; /* only std devno */
|
||||
if (rf_dib.dev != DEV_RF) return STOP_NOTSTD; /* only std devno */
|
||||
if (sim_switches & SWMASK ('D')) {
|
||||
for (i = 0; i < DM4_LEN; i = i + 2)
|
||||
M[dm4_rom[i]] = dm4_rom[i + 1];
|
||||
saved_PC = DM4_START; }
|
||||
else { for (i = 0; i < OS8_LEN; i++)
|
||||
M[OS8_START + i] = os8_rom[i];
|
||||
saved_PC = OS8_START; }
|
||||
for (i = 0; i < DM4_LEN; i = i + 2)
|
||||
M[dm4_rom[i]] = dm4_rom[i + 1];
|
||||
saved_PC = DM4_START;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < OS8_LEN; i++)
|
||||
M[OS8_START + i] = os8_rom[i];
|
||||
saved_PC = OS8_START;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -387,10 +417,11 @@ t_stat r;
|
||||
r = attach_unit (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
|
||||
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (p >= RF_NUMDK) p = RF_NUMDK - 1;
|
||||
uptr->flags = (uptr->flags & ~UNIT_PLAT) |
|
||||
(p << UNIT_V_PLAT); }
|
||||
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (p >= RF_NUMDK) p = RF_NUMDK - 1;
|
||||
uptr->flags = (uptr->flags & ~UNIT_PLAT) |
|
||||
(p << UNIT_V_PLAT);
|
||||
}
|
||||
uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
528
PDP8/pdp8_rk.c
528
PDP8/pdp8_rk.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_rk.c: RK8E cartridge disk simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,121 +19,121 @@
|
||||
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.
|
||||
|
||||
rk RK8E/RK05 cartridge disk
|
||||
rk RK8E/RK05 cartridge disk
|
||||
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
06-Jan-02 RMS Changed enable/disable support
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Converted FLG to array, made register names consistent
|
||||
25-Apr-01 RMS Added device enable/disable support
|
||||
29-Jun-96 RMS Added unit enable/disable support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
06-Jan-02 RMS Changed enable/disable support
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Converted FLG to array, made register names consistent
|
||||
25-Apr-01 RMS Added device enable/disable support
|
||||
29-Jun-96 RMS Added unit enable/disable support
|
||||
*/
|
||||
|
||||
#include "pdp8_defs.h"
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define RK_NUMSC 16 /* sectors/surface */
|
||||
#define RK_NUMSF 2 /* surfaces/cylinder */
|
||||
#define RK_NUMCY 203 /* cylinders/drive */
|
||||
#define RK_NUMWD 256 /* words/sector */
|
||||
#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */
|
||||
#define RK_NUMDR 4 /* drives/controller */
|
||||
#define RK_M_NUMDR 03
|
||||
#define RK_NUMSC 16 /* sectors/surface */
|
||||
#define RK_NUMSF 2 /* surfaces/cylinder */
|
||||
#define RK_NUMCY 203 /* cylinders/drive */
|
||||
#define RK_NUMWD 256 /* words/sector */
|
||||
#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */
|
||||
#define RK_NUMDR 4 /* drives/controller */
|
||||
#define RK_M_NUMDR 03
|
||||
|
||||
/* Flags in the unit flags word */
|
||||
|
||||
#define UNIT_V_HWLK (UNIT_V_UF + 0) /* hwre write lock */
|
||||
#define UNIT_V_SWLK (UNIT_V_UF + 1) /* swre write lock */
|
||||
#define UNIT_HWLK (1 << UNIT_V_HWLK)
|
||||
#define UNIT_SWLK (1 << UNIT_V_SWLK)
|
||||
#define UNIT_WPRT (UNIT_HWLK|UNIT_SWLK|UNIT_RO) /* write protect */
|
||||
#define UNIT_V_HWLK (UNIT_V_UF + 0) /* hwre write lock */
|
||||
#define UNIT_V_SWLK (UNIT_V_UF + 1) /* swre write lock */
|
||||
#define UNIT_HWLK (1 << UNIT_V_HWLK)
|
||||
#define UNIT_SWLK (1 << UNIT_V_SWLK)
|
||||
#define UNIT_WPRT (UNIT_HWLK|UNIT_SWLK|UNIT_RO) /* write protect */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
#define CYL u3 /* current cylinder */
|
||||
#define FUNC u4 /* function */
|
||||
#define CYL u3 /* current cylinder */
|
||||
#define FUNC u4 /* function */
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define RKS_DONE 04000 /* transfer done */
|
||||
#define RKS_HMOV 02000 /* heads moving */
|
||||
#define RKS_SKFL 00400 /* drive seek fail */
|
||||
#define RKS_NRDY 00200 /* drive not ready */
|
||||
#define RKS_BUSY 00100 /* control busy error */
|
||||
#define RKS_TMO 00040 /* timeout error */
|
||||
#define RKS_WLK 00020 /* write lock error */
|
||||
#define RKS_CRC 00010 /* CRC error */
|
||||
#define RKS_DLT 00004 /* data late error */
|
||||
#define RKS_STAT 00002 /* drive status error */
|
||||
#define RKS_CYL 00001 /* cyl address error */
|
||||
#define RKS_ERR (RKS_BUSY+RKS_TMO+RKS_WLK+RKS_CRC+RKS_DLT+RKS_STAT+RKS_CYL)
|
||||
#define RKS_DONE 04000 /* transfer done */
|
||||
#define RKS_HMOV 02000 /* heads moving */
|
||||
#define RKS_SKFL 00400 /* drive seek fail */
|
||||
#define RKS_NRDY 00200 /* drive not ready */
|
||||
#define RKS_BUSY 00100 /* control busy error */
|
||||
#define RKS_TMO 00040 /* timeout error */
|
||||
#define RKS_WLK 00020 /* write lock error */
|
||||
#define RKS_CRC 00010 /* CRC error */
|
||||
#define RKS_DLT 00004 /* data late error */
|
||||
#define RKS_STAT 00002 /* drive status error */
|
||||
#define RKS_CYL 00001 /* cyl address error */
|
||||
#define RKS_ERR (RKS_BUSY+RKS_TMO+RKS_WLK+RKS_CRC+RKS_DLT+RKS_STAT+RKS_CYL)
|
||||
|
||||
/* Command register */
|
||||
|
||||
#define RKC_M_FUNC 07 /* function */
|
||||
#define RKC_READ 0
|
||||
#define RKC_RALL 1
|
||||
#define RKC_WLK 2
|
||||
#define RKC_SEEK 3
|
||||
#define RKC_WRITE 4
|
||||
#define RKC_WALL 5
|
||||
#define RKC_V_FUNC 9
|
||||
#define RKC_IE 00400 /* interrupt enable */
|
||||
#define RKC_SKDN 00200 /* set done on seek done */
|
||||
#define RKC_HALF 00100 /* 128W sector */
|
||||
#define RKC_MEX 00070 /* memory extension */
|
||||
#define RKC_V_MEX 3
|
||||
#define RKC_M_DRV 03 /* drive select */
|
||||
#define RKC_V_DRV 1
|
||||
#define RKC_CYHI 00001 /* high cylinder addr */
|
||||
#define RKC_M_FUNC 07 /* function */
|
||||
#define RKC_READ 0
|
||||
#define RKC_RALL 1
|
||||
#define RKC_WLK 2
|
||||
#define RKC_SEEK 3
|
||||
#define RKC_WRITE 4
|
||||
#define RKC_WALL 5
|
||||
#define RKC_V_FUNC 9
|
||||
#define RKC_IE 00400 /* interrupt enable */
|
||||
#define RKC_SKDN 00200 /* set done on seek done */
|
||||
#define RKC_HALF 00100 /* 128W sector */
|
||||
#define RKC_MEX 00070 /* memory extension */
|
||||
#define RKC_V_MEX 3
|
||||
#define RKC_M_DRV 03 /* drive select */
|
||||
#define RKC_V_DRV 1
|
||||
#define RKC_CYHI 00001 /* high cylinder addr */
|
||||
|
||||
#define GET_FUNC(x) (((x) >> RKC_V_FUNC) & RKC_M_FUNC)
|
||||
#define GET_DRIVE(x) (((x) >> RKC_V_DRV) & RKC_M_DRV)
|
||||
#define GET_MEX(x) (((x) & RKC_MEX) << (12 - RKC_V_MEX))
|
||||
#define GET_FUNC(x) (((x) >> RKC_V_FUNC) & RKC_M_FUNC)
|
||||
#define GET_DRIVE(x) (((x) >> RKC_V_DRV) & RKC_M_DRV)
|
||||
#define GET_MEX(x) (((x) & RKC_MEX) << (12 - RKC_V_MEX))
|
||||
|
||||
/* Disk address */
|
||||
|
||||
#define RKD_V_SECT 0 /* sector */
|
||||
#define RKD_M_SECT 017
|
||||
#define RKD_V_SUR 4 /* surface */
|
||||
#define RKD_M_SUR 01
|
||||
#define RKD_V_CYL 5 /* cylinder */
|
||||
#define RKD_M_CYL 0177
|
||||
#define GET_CYL(x,y) ((((x) & RKC_CYHI) << (12-RKD_V_CYL)) | \
|
||||
(((y) >> RKD_V_CYL) & RKD_M_CYL))
|
||||
#define GET_DA(x,y) ((((x) & RKC_CYHI) << 12) | y)
|
||||
#define RKD_V_SECT 0 /* sector */
|
||||
#define RKD_M_SECT 017
|
||||
#define RKD_V_SUR 4 /* surface */
|
||||
#define RKD_M_SUR 01
|
||||
#define RKD_V_CYL 5 /* cylinder */
|
||||
#define RKD_M_CYL 0177
|
||||
#define GET_CYL(x,y) ((((x) & RKC_CYHI) << (12-RKD_V_CYL)) | \
|
||||
(((y) >> RKD_V_CYL) & RKD_M_CYL))
|
||||
#define GET_DA(x,y) ((((x) & RKC_CYHI) << 12) | y)
|
||||
|
||||
/* Reset commands */
|
||||
|
||||
#define RKX_CLS 0 /* clear status */
|
||||
#define RKX_CLC 1 /* clear control */
|
||||
#define RKX_CLD 2 /* clear drive */
|
||||
#define RKX_CLSA 3 /* clear status alt */
|
||||
#define RKX_CLS 0 /* clear status */
|
||||
#define RKX_CLC 1 /* clear control */
|
||||
#define RKX_CLD 2 /* clear drive */
|
||||
#define RKX_CLSA 3 /* clear status alt */
|
||||
|
||||
#define RK_INT_UPDATE \
|
||||
if (((rk_sta & (RKS_DONE + RKS_ERR)) != 0) && \
|
||||
((rk_cmd & RKC_IE) != 0)) int_req = int_req | INT_RK; \
|
||||
else int_req = int_req & ~INT_RK
|
||||
if (((rk_sta & (RKS_DONE + RKS_ERR)) != 0) && \
|
||||
((rk_cmd & RKC_IE) != 0)) int_req = int_req | INT_RK; \
|
||||
else int_req = int_req & ~INT_RK
|
||||
#define RK_MIN 10
|
||||
#define MAX(x,y) (((x) > (y))? (x): (y))
|
||||
|
||||
|
||||
extern uint16 M[];
|
||||
extern int32 int_req, stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
int32 rk_busy = 0; /* controller busy */
|
||||
int32 rk_sta = 0; /* status register */
|
||||
int32 rk_cmd = 0; /* command register */
|
||||
int32 rk_da = 0; /* disk address */
|
||||
int32 rk_ma = 0; /* memory address */
|
||||
int32 rk_swait = 10, rk_rwait = 10; /* seek, rotate wait */
|
||||
int32 rk_stopioe = 1; /* stop on error */
|
||||
int32 rk_busy = 0; /* controller busy */
|
||||
int32 rk_sta = 0; /* status register */
|
||||
int32 rk_cmd = 0; /* command register */
|
||||
int32 rk_da = 0; /* disk address */
|
||||
int32 rk_ma = 0; /* memory address */
|
||||
int32 rk_swait = 10, rk_rwait = 10; /* seek, rotate wait */
|
||||
int32 rk_stopioe = 1; /* stop on error */
|
||||
|
||||
DEVICE rk_dev;
|
||||
int32 rk (int32 IR, int32 AC);
|
||||
@@ -144,51 +144,55 @@ void rk_go (int32 function, int32 cylinder);
|
||||
|
||||
/* RK-8E data structures
|
||||
|
||||
rk_dev RK device descriptor
|
||||
rk_unit RK unit list
|
||||
rk_reg RK register list
|
||||
rk_mod RK modifiers list
|
||||
rk_dev RK device descriptor
|
||||
rk_unit RK unit list
|
||||
rk_reg RK register list
|
||||
rk_mod RK modifiers list
|
||||
*/
|
||||
|
||||
DIB rk_dib = { DEV_RK, 1, { &rk } };
|
||||
|
||||
UNIT rk_unit[] = {
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) } };
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) }
|
||||
};
|
||||
|
||||
REG rk_reg[] = {
|
||||
{ ORDATA (RKSTA, rk_sta, 12) },
|
||||
{ ORDATA (RKCMD, rk_cmd, 12) },
|
||||
{ ORDATA (RKDA, rk_da, 12) },
|
||||
{ ORDATA (RKMA, rk_ma, 12) },
|
||||
{ FLDATA (BUSY, rk_busy, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_RK) },
|
||||
{ DRDATA (STIME, rk_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, rk_rwait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, rk_stopioe, 0) },
|
||||
{ ORDATA (DEVNUM, rk_dib.dev, 6), REG_HRO },
|
||||
{ NULL } };
|
||||
{ ORDATA (RKSTA, rk_sta, 12) },
|
||||
{ ORDATA (RKCMD, rk_cmd, 12) },
|
||||
{ ORDATA (RKDA, rk_da, 12) },
|
||||
{ ORDATA (RKMA, rk_ma, 12) },
|
||||
{ FLDATA (BUSY, rk_busy, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_RK) },
|
||||
{ DRDATA (STIME, rk_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, rk_rwait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, rk_stopioe, 0) },
|
||||
{ ORDATA (DEVNUM, rk_dib.dev, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB rk_mod[] = {
|
||||
{ UNIT_HWLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_HWLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE rk_dev = {
|
||||
"RK", rk_unit, rk_reg, rk_mod,
|
||||
RK_NUMDR, 8, 24, 1, 8, 12,
|
||||
NULL, NULL, &rk_reset,
|
||||
&rk_boot, NULL, NULL,
|
||||
&rk_dib, DEV_DISABLE };
|
||||
|
||||
"RK", rk_unit, rk_reg, rk_mod,
|
||||
RK_NUMDR, 8, 24, 1, 8, 12,
|
||||
NULL, NULL, &rk_reset,
|
||||
&rk_boot, NULL, NULL,
|
||||
&rk_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* IOT routine */
|
||||
|
||||
int32 rk (int32 IR, int32 AC)
|
||||
@@ -196,57 +200,73 @@ int32 rk (int32 IR, int32 AC)
|
||||
int32 i;
|
||||
UNIT *uptr;
|
||||
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 0: /* unused */
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
case 1: /* DSKP */
|
||||
return (rk_sta & (RKS_DONE + RKS_ERR))? /* skip on done, err */
|
||||
IOT_SKP + AC: AC;
|
||||
case 2: /* DCLR */
|
||||
rk_sta = 0; /* clear status */
|
||||
switch (AC & 03) { /* decode AC<10:11> */
|
||||
case RKX_CLS: /* clear status */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
case RKX_CLSA: /* clear status alt */
|
||||
break;
|
||||
case RKX_CLC: /* clear control */
|
||||
rk_cmd = rk_busy = 0; /* clear registers */
|
||||
rk_ma = rk_da = 0;
|
||||
for (i = 0; i < RK_NUMDR; i++) sim_cancel (&rk_unit[i]);
|
||||
break;
|
||||
case RKX_CLD: /* reset drive */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
else rk_go (RKC_SEEK, 0); /* seek to 0 */
|
||||
break; } /* end switch AC */
|
||||
break;
|
||||
case 3: /* DLAG */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
else {
|
||||
rk_da = AC; /* load disk addr */
|
||||
rk_go (GET_FUNC (rk_cmd), GET_CYL (rk_cmd, rk_da)); }
|
||||
break;
|
||||
case 4: /* DLCA */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
else rk_ma = AC; /* load curr addr */
|
||||
break;
|
||||
case 5: /* DRST */
|
||||
uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */
|
||||
rk_sta = rk_sta & ~(RKS_HMOV + RKS_NRDY); /* clear dynamic */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) rk_sta = rk_sta | RKS_NRDY;
|
||||
if (sim_is_active (uptr)) rk_sta = rk_sta | RKS_HMOV;
|
||||
return rk_sta;
|
||||
case 6: /* DLDC */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
else {
|
||||
rk_cmd = AC; /* load command */
|
||||
rk_sta = 0; } /* clear status */
|
||||
break;
|
||||
case 7: /* DMAN */
|
||||
break; } /* end case pulse */
|
||||
RK_INT_UPDATE; /* update int req */
|
||||
return 0; /* clear AC */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 0: /* unused */
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
|
||||
case 1: /* DSKP */
|
||||
return (rk_sta & (RKS_DONE + RKS_ERR))? /* skip on done, err */
|
||||
IOT_SKP + AC: AC;
|
||||
|
||||
case 2: /* DCLR */
|
||||
rk_sta = 0; /* clear status */
|
||||
switch (AC & 03) { /* decode AC<10:11> */
|
||||
|
||||
case RKX_CLS: /* clear status */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
case RKX_CLSA: /* clear status alt */
|
||||
break;
|
||||
|
||||
case RKX_CLC: /* clear control */
|
||||
rk_cmd = rk_busy = 0; /* clear registers */
|
||||
rk_ma = rk_da = 0;
|
||||
for (i = 0; i < RK_NUMDR; i++) sim_cancel (&rk_unit[i]);
|
||||
break;
|
||||
|
||||
case RKX_CLD: /* reset drive */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
else rk_go (RKC_SEEK, 0); /* seek to 0 */
|
||||
break;
|
||||
} /* end switch AC */
|
||||
break;
|
||||
|
||||
case 3: /* DLAG */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
else {
|
||||
rk_da = AC; /* load disk addr */
|
||||
rk_go (GET_FUNC (rk_cmd), GET_CYL (rk_cmd, rk_da));
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* DLCA */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
else rk_ma = AC; /* load curr addr */
|
||||
break;
|
||||
|
||||
case 5: /* DRST */
|
||||
uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */
|
||||
rk_sta = rk_sta & ~(RKS_HMOV + RKS_NRDY); /* clear dynamic */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) rk_sta = rk_sta | RKS_NRDY;
|
||||
if (sim_is_active (uptr)) rk_sta = rk_sta | RKS_HMOV;
|
||||
return rk_sta;
|
||||
|
||||
case 6: /* DLDC */
|
||||
if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY;
|
||||
else {
|
||||
rk_cmd = AC; /* load command */
|
||||
rk_sta = 0; /* clear status */
|
||||
}
|
||||
break;
|
||||
|
||||
case 7: /* DMAN */
|
||||
break;
|
||||
} /* end case pulse */
|
||||
|
||||
RK_INT_UPDATE; /* update int req */
|
||||
return 0; /* clear AC */
|
||||
}
|
||||
|
||||
|
||||
/* Initiate new function
|
||||
|
||||
Called with function, cylinder, to allow recalibrate as well as
|
||||
@@ -261,33 +281,40 @@ void rk_go (int32 func, int32 cyl)
|
||||
int32 t;
|
||||
UNIT *uptr;
|
||||
|
||||
if (func == RKC_RALL) func = RKC_READ; /* all? use standard */
|
||||
if (func == RKC_RALL) func = RKC_READ; /* all? use standard */
|
||||
if (func == RKC_WALL) func = RKC_WRITE;
|
||||
uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT;
|
||||
return; }
|
||||
if (sim_is_active (uptr) || (cyl >= RK_NUMCY)) { /* busy or bad cyl? */
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_STAT;
|
||||
return; }
|
||||
uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT;
|
||||
return;
|
||||
}
|
||||
if (sim_is_active (uptr) || (cyl >= RK_NUMCY)) { /* busy or bad cyl? */
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_STAT;
|
||||
return;
|
||||
}
|
||||
if ((func == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) {
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */
|
||||
return; }
|
||||
if (func == RKC_WLK) { /* write lock? */
|
||||
uptr->flags = uptr->flags | UNIT_SWLK;
|
||||
rk_sta = rk_sta | RKS_DONE;
|
||||
return; }
|
||||
t = abs (cyl - uptr->CYL) * rk_swait; /* seek time */
|
||||
if (func == RKC_SEEK) { /* seek? */
|
||||
sim_activate (uptr, MAX (RK_MIN, t)); /* schedule */
|
||||
rk_sta = rk_sta | RKS_DONE; } /* set done */
|
||||
else { sim_activate (uptr, t + rk_rwait); /* schedule */
|
||||
rk_busy = 1; } /* set busy */
|
||||
uptr->FUNC = func; /* save func */
|
||||
uptr->CYL = cyl; /* put on cylinder */
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */
|
||||
return;
|
||||
}
|
||||
if (func == RKC_WLK) { /* write lock? */
|
||||
uptr->flags = uptr->flags | UNIT_SWLK;
|
||||
rk_sta = rk_sta | RKS_DONE;
|
||||
return;
|
||||
}
|
||||
t = abs (cyl - uptr->CYL) * rk_swait; /* seek time */
|
||||
if (func == RKC_SEEK) { /* seek? */
|
||||
sim_activate (uptr, MAX (RK_MIN, t)); /* schedule */
|
||||
rk_sta = rk_sta | RKS_DONE; /* set done */
|
||||
}
|
||||
else {
|
||||
sim_activate (uptr, t + rk_rwait); /* schedule */
|
||||
rk_busy = 1; /* set busy */
|
||||
}
|
||||
uptr->FUNC = func; /* save func */
|
||||
uptr->CYL = cyl; /* put on cylinder */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service
|
||||
|
||||
If seek, complete seek command
|
||||
@@ -305,64 +332,74 @@ t_stat rk_svc (UNIT *uptr)
|
||||
int32 err, wc, wc1, awc, swc, pa, da;
|
||||
UNIT *seluptr;
|
||||
|
||||
if (uptr->FUNC == RKC_SEEK) { /* seek? */
|
||||
seluptr = rk_dev.units + GET_DRIVE (rk_cmd); /* see if selected */
|
||||
if ((uptr == seluptr) && ((rk_cmd & RKC_SKDN) != 0)) {
|
||||
rk_sta = rk_sta | RKS_DONE;
|
||||
RK_INT_UPDATE; }
|
||||
return SCPE_OK; }
|
||||
if (uptr->FUNC == RKC_SEEK) { /* seek? */
|
||||
seluptr = rk_dev.units + GET_DRIVE (rk_cmd); /* see if selected */
|
||||
if ((uptr == seluptr) && ((rk_cmd & RKC_SKDN) != 0)) {
|
||||
rk_sta = rk_sta | RKS_DONE;
|
||||
RK_INT_UPDATE;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not att? abort */
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT;
|
||||
rk_busy = 0;
|
||||
RK_INT_UPDATE;
|
||||
return IORETURN (rk_stopioe, SCPE_UNATT); }
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not att? abort */
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT;
|
||||
rk_busy = 0;
|
||||
RK_INT_UPDATE;
|
||||
return IORETURN (rk_stopioe, SCPE_UNATT);
|
||||
}
|
||||
|
||||
if ((uptr->FUNC == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) {
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */
|
||||
rk_busy = 0;
|
||||
RK_INT_UPDATE;
|
||||
return SCPE_OK; }
|
||||
rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */
|
||||
rk_busy = 0;
|
||||
RK_INT_UPDATE;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
pa = GET_MEX (rk_cmd) | rk_ma; /* phys address */
|
||||
pa = GET_MEX (rk_cmd) | rk_ma; /* phys address */
|
||||
da = GET_DA (rk_cmd, rk_da) * RK_NUMWD * sizeof (int16);/* disk address */
|
||||
swc = wc = (rk_cmd & RKC_HALF)? RK_NUMWD / 2: RK_NUMWD; /* get transfer size */
|
||||
swc = wc = (rk_cmd & RKC_HALF)? RK_NUMWD / 2: RK_NUMWD; /* get transfer size */
|
||||
if ((wc1 = ((rk_ma + wc) - 010000)) > 0) wc = wc - wc1; /* if wrap, limit */
|
||||
err = fseek (uptr->fileref, da, SEEK_SET); /* locate sector */
|
||||
err = fseek (uptr->fileref, da, SEEK_SET); /* locate sector */
|
||||
|
||||
if ((uptr->FUNC == RKC_READ) && (err == 0) && MEM_ADDR_OK (pa)) { /* read? */
|
||||
awc = fxread (&M[pa], sizeof (int16), wc, uptr->fileref);
|
||||
for ( ; awc < wc; awc++) M[pa + awc] = 0; /* fill if eof */
|
||||
err = ferror (uptr->fileref);
|
||||
if ((wc1 > 0) && (err == 0)) { /* field wraparound? */
|
||||
pa = pa & 070000; /* wrap phys addr */
|
||||
awc = fxread (&M[pa], sizeof (int16), wc1, uptr->fileref);
|
||||
for ( ; awc < wc1; awc++) M[pa + awc] = 0; /* fill if eof */
|
||||
err = ferror (uptr->fileref); } }
|
||||
awc = fxread (&M[pa], sizeof (int16), wc, uptr->fileref);
|
||||
for ( ; awc < wc; awc++) M[pa + awc] = 0; /* fill if eof */
|
||||
err = ferror (uptr->fileref);
|
||||
if ((wc1 > 0) && (err == 0)) { /* field wraparound? */
|
||||
pa = pa & 070000; /* wrap phys addr */
|
||||
awc = fxread (&M[pa], sizeof (int16), wc1, uptr->fileref);
|
||||
for ( ; awc < wc1; awc++) M[pa + awc] = 0; /* fill if eof */
|
||||
err = ferror (uptr->fileref);
|
||||
}
|
||||
}
|
||||
|
||||
if ((uptr->FUNC == RKC_WRITE) && (err == 0)) { /* write? */
|
||||
fxwrite (&M[pa], sizeof (int16), wc, uptr->fileref);
|
||||
err = ferror (uptr->fileref);
|
||||
if ((wc1 > 0) && (err == 0)) { /* field wraparound? */
|
||||
pa = pa & 070000; /* wrap phys addr */
|
||||
fxwrite (&M[pa], sizeof (int16), wc1, uptr->fileref);
|
||||
err = ferror (uptr->fileref); }
|
||||
if ((rk_cmd & RKC_HALF) && (err == 0)) { /* fill half sector */
|
||||
fxwrite (fill, sizeof (int16), RK_NUMWD/2, uptr->fileref);
|
||||
err = ferror (uptr->fileref); } }
|
||||
if ((uptr->FUNC == RKC_WRITE) && (err == 0)) { /* write? */
|
||||
fxwrite (&M[pa], sizeof (int16), wc, uptr->fileref);
|
||||
err = ferror (uptr->fileref);
|
||||
if ((wc1 > 0) && (err == 0)) { /* field wraparound? */
|
||||
pa = pa & 070000; /* wrap phys addr */
|
||||
fxwrite (&M[pa], sizeof (int16), wc1, uptr->fileref);
|
||||
err = ferror (uptr->fileref);
|
||||
}
|
||||
if ((rk_cmd & RKC_HALF) && (err == 0)) { /* fill half sector */
|
||||
fxwrite (fill, sizeof (int16), RK_NUMWD/2, uptr->fileref);
|
||||
err = ferror (uptr->fileref);
|
||||
}
|
||||
}
|
||||
|
||||
rk_ma = (rk_ma + swc) & 07777; /* incr mem addr reg */
|
||||
rk_sta = rk_sta | RKS_DONE; /* set done */
|
||||
rk_ma = (rk_ma + swc) & 07777; /* incr mem addr reg */
|
||||
rk_sta = rk_sta | RKS_DONE; /* set done */
|
||||
rk_busy = 0;
|
||||
RK_INT_UPDATE;
|
||||
|
||||
if (err != 0) {
|
||||
perror ("RK I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
perror ("RK I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat rk_reset (DEVICE *dptr)
|
||||
@@ -371,12 +408,13 @@ int32 i;
|
||||
UNIT *uptr;
|
||||
|
||||
rk_cmd = rk_ma = rk_da = rk_sta = rk_busy = 0;
|
||||
int_req = int_req & ~INT_RK; /* clear interrupt */
|
||||
for (i = 0; i < RK_NUMDR; i++) { /* stop all units */
|
||||
uptr = rk_dev.units + i;
|
||||
sim_cancel (uptr);
|
||||
uptr->flags = uptr->flags & ~UNIT_SWLK;
|
||||
uptr->CYL = uptr->FUNC = 0; }
|
||||
int_req = int_req & ~INT_RK; /* clear interrupt */
|
||||
for (i = 0; i < RK_NUMDR; i++) { /* stop all units */
|
||||
uptr = rk_dev.units + i;
|
||||
sim_cancel (uptr);
|
||||
uptr->flags = uptr->flags & ~UNIT_SWLK;
|
||||
uptr->CYL = uptr->FUNC = 0;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -387,22 +425,22 @@ return SCPE_OK;
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16))
|
||||
|
||||
static const uint16 boot_rom[] = {
|
||||
06007, /* 23, CAF */
|
||||
06744, /* 24, DLCA ; addr = 0 */
|
||||
01032, /* 25, TAD UNIT ; unit no */
|
||||
06746, /* 26, DLDC ; command, unit */
|
||||
06743, /* 27, DLAG ; disk addr, go */
|
||||
01032, /* 30, TAD UNIT ; unit no, for OS */
|
||||
05031, /* 31, JMP . */
|
||||
00000 /* UNIT, 0 ; in bits <9:10> */
|
||||
};
|
||||
06007, /* 23, CAF */
|
||||
06744, /* 24, DLCA ; addr = 0 */
|
||||
01032, /* 25, TAD UNIT ; unit no */
|
||||
06746, /* 26, DLDC ; command, unit */
|
||||
06743, /* 27, DLAG ; disk addr, go */
|
||||
01032, /* 30, TAD UNIT ; unit no, for OS */
|
||||
05031, /* 31, JMP . */
|
||||
00000 /* UNIT, 0 ; in bits <9:10> */
|
||||
};
|
||||
|
||||
t_stat rk_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
extern int32 saved_PC;
|
||||
|
||||
if (rk_dib.dev != DEV_RK) return STOP_NOTSTD; /* only std devno */
|
||||
if (rk_dib.dev != DEV_RK) return STOP_NOTSTD; /* only std devno */
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||
M[BOOT_UNIT] = (unitno & RK_M_NUMDR) << 1;
|
||||
saved_PC = BOOT_START;
|
||||
|
||||
837
PDP8/pdp8_rl.c
837
PDP8/pdp8_rl.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_rl.c: RL8A cartridge disk simulator
|
||||
/* pdp8_rl.c: RL8A cartridge disk simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,17 +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.
|
||||
|
||||
rl RL8A cartridge disk
|
||||
rl RL8A cartridge disk
|
||||
|
||||
04-Jan-04 RMS Changed attach routine to use sim_fsize
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
06-Jan-02 RMS Changed enable/disable support
|
||||
30-Nov-01 RMS Cloned from RL11
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
04-Jan-04 RMS Changed attach routine to use sim_fsize
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
06-Jan-02 RMS Changed enable/disable support
|
||||
30-Nov-01 RMS Cloned from RL11
|
||||
|
||||
The RL8A is a four drive cartridge disk subsystem. An RL01 drive
|
||||
consists of 256 cylinders, each with 2 surfaces containing 40 sectors
|
||||
@@ -48,128 +49,128 @@
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define RL_NUMBY 256 /* 8b bytes/sector */
|
||||
#define RL_NUMSC 40 /* sectors/surface */
|
||||
#define RL_NUMSF 2 /* surfaces/cylinder */
|
||||
#define RL_NUMCY 256 /* cylinders/drive */
|
||||
#define RL_NUMDR 4 /* drives/controller */
|
||||
#define RL_MAXFR (1 << 12) /* max transfer */
|
||||
#define RL01_SIZE (RL_NUMCY*RL_NUMSF*RL_NUMSC*RL_NUMBY) /* words/drive */
|
||||
#define RL02_SIZE (RL01_SIZE * 2) /* words/drive */
|
||||
#define RL_BBMAP 014 /* sector for bblk map */
|
||||
#define RL_BBID 0123 /* ID for bblk map */
|
||||
#define RL_NUMBY 256 /* 8b bytes/sector */
|
||||
#define RL_NUMSC 40 /* sectors/surface */
|
||||
#define RL_NUMSF 2 /* surfaces/cylinder */
|
||||
#define RL_NUMCY 256 /* cylinders/drive */
|
||||
#define RL_NUMDR 4 /* drives/controller */
|
||||
#define RL_MAXFR (1 << 12) /* max transfer */
|
||||
#define RL01_SIZE (RL_NUMCY*RL_NUMSF*RL_NUMSC*RL_NUMBY) /* words/drive */
|
||||
#define RL02_SIZE (RL01_SIZE * 2) /* words/drive */
|
||||
#define RL_BBMAP 014 /* sector for bblk map */
|
||||
#define RL_BBID 0123 /* ID for bblk map */
|
||||
|
||||
/* Flags in the unit flags word */
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write lock */
|
||||
#define UNIT_V_RL02 (UNIT_V_UF + 1) /* RL01 vs RL02 */
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize enable */
|
||||
#define UNIT_V_DUMMY (UNIT_V_UF + 3) /* dummy flag */
|
||||
#define UNIT_DUMMY (1u << UNIT_V_DUMMY)
|
||||
#define UNIT_WLK (1u << UNIT_V_WLK)
|
||||
#define UNIT_RL02 (1u << UNIT_V_RL02)
|
||||
#define UNIT_AUTO (1u << UNIT_V_AUTO)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write lock */
|
||||
#define UNIT_V_RL02 (UNIT_V_UF + 1) /* RL01 vs RL02 */
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize enable */
|
||||
#define UNIT_V_DUMMY (UNIT_V_UF + 3) /* dummy flag */
|
||||
#define UNIT_DUMMY (1u << UNIT_V_DUMMY)
|
||||
#define UNIT_WLK (1u << UNIT_V_WLK)
|
||||
#define UNIT_RL02 (1u << UNIT_V_RL02)
|
||||
#define UNIT_AUTO (1u << UNIT_V_AUTO)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
#define TRK u3 /* current cylinder */
|
||||
#define STAT u4 /* status */
|
||||
#define TRK u3 /* current cylinder */
|
||||
#define STAT u4 /* status */
|
||||
|
||||
/* RLDS, NI = not implemented, * = kept in STAT, ^ = kept in TRK */
|
||||
|
||||
#define RLDS_LOAD 0 /* no cartridge */
|
||||
#define RLDS_LOCK 5 /* lock on */
|
||||
#define RLDS_BHO 0000010 /* brushes home NI */
|
||||
#define RLDS_HDO 0000020 /* heads out NI */
|
||||
#define RLDS_CVO 0000040 /* cover open NI */
|
||||
#define RLDS_HD 0000100 /* head select ^ */
|
||||
#define RLDS_RL02 0000200 /* RL02 */
|
||||
#define RLDS_DSE 0000400 /* drv sel err NI */
|
||||
#define RLDS_VCK 0001000 /* vol check * */
|
||||
#define RLDS_WGE 0002000 /* wr gate err * */
|
||||
#define RLDS_SPE 0004000 /* spin err * */
|
||||
#define RLDS_STO 0010000 /* seek time out NI */
|
||||
#define RLDS_WLK 0020000 /* wr locked */
|
||||
#define RLDS_HCE 0040000 /* hd curr err NI */
|
||||
#define RLDS_WDE 0100000 /* wr data err NI */
|
||||
#define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* att status */
|
||||
#define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unatt status */
|
||||
#define RLDS_ERR (RLDS_WDE+RLDS_HCE+RLDS_STO+RLDS_SPE+RLDS_WGE+ \
|
||||
RLDS_VCK+RLDS_DSE) /* errors bits */
|
||||
#define RLDS_LOAD 0 /* no cartridge */
|
||||
#define RLDS_LOCK 5 /* lock on */
|
||||
#define RLDS_BHO 0000010 /* brushes home NI */
|
||||
#define RLDS_HDO 0000020 /* heads out NI */
|
||||
#define RLDS_CVO 0000040 /* cover open NI */
|
||||
#define RLDS_HD 0000100 /* head select ^ */
|
||||
#define RLDS_RL02 0000200 /* RL02 */
|
||||
#define RLDS_DSE 0000400 /* drv sel err NI */
|
||||
#define RLDS_VCK 0001000 /* vol check * */
|
||||
#define RLDS_WGE 0002000 /* wr gate err * */
|
||||
#define RLDS_SPE 0004000 /* spin err * */
|
||||
#define RLDS_STO 0010000 /* seek time out NI */
|
||||
#define RLDS_WLK 0020000 /* wr locked */
|
||||
#define RLDS_HCE 0040000 /* hd curr err NI */
|
||||
#define RLDS_WDE 0100000 /* wr data err NI */
|
||||
#define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* att status */
|
||||
#define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unatt status */
|
||||
#define RLDS_ERR (RLDS_WDE+RLDS_HCE+RLDS_STO+RLDS_SPE+RLDS_WGE+ \
|
||||
RLDS_VCK+RLDS_DSE) /* errors bits */
|
||||
|
||||
/* RLCSA, seek = offset/rw = address (also uptr->TRK) */
|
||||
|
||||
#define RLCSA_DIR 04000 /* direction */
|
||||
#define RLCSA_HD 02000 /* head select */
|
||||
#define RLCSA_CYL 00777 /* cyl offset */
|
||||
#define GET_CYL(x) ((x) & RLCSA_CYL)
|
||||
#define GET_TRK(x) ((((x) & RLCSA_CYL) * RL_NUMSF) + \
|
||||
(((x) & RLCSA_HD)? 1: 0))
|
||||
#define GET_DA(x) ((GET_TRK(x) * RL_NUMSC) + rlsa)
|
||||
#define RLCSA_DIR 04000 /* direction */
|
||||
#define RLCSA_HD 02000 /* head select */
|
||||
#define RLCSA_CYL 00777 /* cyl offset */
|
||||
#define GET_CYL(x) ((x) & RLCSA_CYL)
|
||||
#define GET_TRK(x) ((((x) & RLCSA_CYL) * RL_NUMSF) + \
|
||||
(((x) & RLCSA_HD)? 1: 0))
|
||||
#define GET_DA(x) ((GET_TRK(x) * RL_NUMSC) + rlsa)
|
||||
|
||||
/* RLCSB, function/unit select */
|
||||
|
||||
#define RLCSB_V_FUNC 0 /* function */
|
||||
#define RLCSB_M_FUNC 07
|
||||
#define RLCSB_MNT 0
|
||||
#define RLCSB_CLRD 1
|
||||
#define RLCSB_GSTA 2
|
||||
#define RLCSB_SEEK 3
|
||||
#define RLCSB_RHDR 4
|
||||
#define RLCSB_WRITE 5
|
||||
#define RLCSB_READ 6
|
||||
#define RLCSB_RNOHDR 7
|
||||
#define RLCSB_V_MEX 3 /* memory extension */
|
||||
#define RLCSB_M_MEX 07
|
||||
#define RLCSB_V_DRIVE 6 /* drive */
|
||||
#define RLCSB_M_DRIVE 03
|
||||
#define RLCSB_V_IE 8 /* int enable */
|
||||
#define RLCSB_IE (1u << RLCSB_V_IE)
|
||||
#define RLCSB_8B 01000 /* 12b/8b */
|
||||
#define RCLS_MNT 02000 /* maint NI */
|
||||
#define RLCSB_RW 0001777 /* read/write */
|
||||
#define GET_FUNC(x) (((x) >> RLCSB_V_FUNC) & RLCSB_M_FUNC)
|
||||
#define GET_MEX(x) (((x) >> RLCSB_V_MEX) & RLCSB_M_MEX)
|
||||
#define GET_DRIVE(x) (((x) >> RLCSB_V_DRIVE) & RLCSB_M_DRIVE)
|
||||
#define RLCSB_V_FUNC 0 /* function */
|
||||
#define RLCSB_M_FUNC 07
|
||||
#define RLCSB_MNT 0
|
||||
#define RLCSB_CLRD 1
|
||||
#define RLCSB_GSTA 2
|
||||
#define RLCSB_SEEK 3
|
||||
#define RLCSB_RHDR 4
|
||||
#define RLCSB_WRITE 5
|
||||
#define RLCSB_READ 6
|
||||
#define RLCSB_RNOHDR 7
|
||||
#define RLCSB_V_MEX 3 /* memory extension */
|
||||
#define RLCSB_M_MEX 07
|
||||
#define RLCSB_V_DRIVE 6 /* drive */
|
||||
#define RLCSB_M_DRIVE 03
|
||||
#define RLCSB_V_IE 8 /* int enable */
|
||||
#define RLCSB_IE (1u << RLCSB_V_IE)
|
||||
#define RLCSB_8B 01000 /* 12b/8b */
|
||||
#define RCLS_MNT 02000 /* maint NI */
|
||||
#define RLCSB_RW 0001777 /* read/write */
|
||||
#define GET_FUNC(x) (((x) >> RLCSB_V_FUNC) & RLCSB_M_FUNC)
|
||||
#define GET_MEX(x) (((x) >> RLCSB_V_MEX) & RLCSB_M_MEX)
|
||||
#define GET_DRIVE(x) (((x) >> RLCSB_V_DRIVE) & RLCSB_M_DRIVE)
|
||||
|
||||
/* RLSA, disk sector */
|
||||
|
||||
#define RLSA_V_SECT 6 /* sector */
|
||||
#define RLSA_M_SECT 077
|
||||
#define GET_SECT(x) (((x) >> RLSA_V_SECT) & RLSA_M_SECT)
|
||||
#define RLSA_V_SECT 6 /* sector */
|
||||
#define RLSA_M_SECT 077
|
||||
#define GET_SECT(x) (((x) >> RLSA_V_SECT) & RLSA_M_SECT)
|
||||
|
||||
/* RLER, error register */
|
||||
|
||||
#define RLER_DRDY 00001 /* drive ready */
|
||||
#define RLER_DRE 00002 /* drive error */
|
||||
#define RLER_HDE 01000 /* header error */
|
||||
#define RLER_INCMP 02000 /* incomplete */
|
||||
#define RLER_ICRC 04000 /* CRC error */
|
||||
#define RLER_MASK 07003
|
||||
#define RLER_DRDY 00001 /* drive ready */
|
||||
#define RLER_DRE 00002 /* drive error */
|
||||
#define RLER_HDE 01000 /* header error */
|
||||
#define RLER_INCMP 02000 /* incomplete */
|
||||
#define RLER_ICRC 04000 /* CRC error */
|
||||
#define RLER_MASK 07003
|
||||
|
||||
/* RLSI, silo register, used only in read header */
|
||||
|
||||
#define RLSI_V_TRK 6 /* track */
|
||||
|
||||
#define RLSI_V_TRK 6 /* track */
|
||||
|
||||
extern uint16 M[];
|
||||
extern int32 int_req;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
uint8 *rlxb = NULL; /* xfer buffer */
|
||||
int32 rlcsa = 0; /* control/status A */
|
||||
int32 rlcsb = 0; /* control/status B */
|
||||
int32 rlma = 0; /* memory address */
|
||||
int32 rlwc = 0; /* word count */
|
||||
int32 rlsa = 0; /* sector address */
|
||||
int32 rler = 0; /* error register */
|
||||
int32 rlsi = 0, rlsi1 = 0, rlsi2 = 0; /* silo queue */
|
||||
int32 rl_lft = 0; /* silo left/right */
|
||||
int32 rl_done = 0; /* done flag */
|
||||
int32 rl_erf = 0; /* error flag */
|
||||
int32 rl_swait = 10; /* seek wait */
|
||||
int32 rl_rwait = 10; /* rotate wait */
|
||||
int32 rl_stopioe = 1; /* stop on error */
|
||||
uint8 *rlxb = NULL; /* xfer buffer */
|
||||
int32 rlcsa = 0; /* control/status A */
|
||||
int32 rlcsb = 0; /* control/status B */
|
||||
int32 rlma = 0; /* memory address */
|
||||
int32 rlwc = 0; /* word count */
|
||||
int32 rlsa = 0; /* sector address */
|
||||
int32 rler = 0; /* error register */
|
||||
int32 rlsi = 0, rlsi1 = 0, rlsi2 = 0; /* silo queue */
|
||||
int32 rl_lft = 0; /* silo left/right */
|
||||
int32 rl_done = 0; /* done flag */
|
||||
int32 rl_erf = 0; /* error flag */
|
||||
int32 rl_swait = 10; /* seek wait */
|
||||
int32 rl_rwait = 10; /* rotate wait */
|
||||
int32 rl_stopioe = 1; /* stop on error */
|
||||
|
||||
DEVICE rl_dev;
|
||||
int32 rl60 (int32 IR, int32 AC);
|
||||
@@ -184,181 +185,210 @@ t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* RL8A data structures
|
||||
|
||||
rl_dev RL device descriptor
|
||||
rl_unit RL unit list
|
||||
rl_reg RL register list
|
||||
rl_mod RL modifier list
|
||||
rl_dev RL device descriptor
|
||||
rl_unit RL unit list
|
||||
rl_reg RL register list
|
||||
rl_mod RL modifier list
|
||||
*/
|
||||
|
||||
DIB rl_dib = { DEV_RL, 2, { &rl60, &rl61 } };
|
||||
|
||||
UNIT rl_unit[] = {
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
UNIT_ROABLE, RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
UNIT_ROABLE, RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
UNIT_ROABLE, RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
UNIT_ROABLE, RL01_SIZE) } };
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
UNIT_ROABLE, RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
UNIT_ROABLE, RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
UNIT_ROABLE, RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
UNIT_ROABLE, RL01_SIZE) }
|
||||
};
|
||||
|
||||
REG rl_reg[] = {
|
||||
{ ORDATA (RLCSA, rlcsa, 12) },
|
||||
{ ORDATA (RLCSB, rlcsb, 12) },
|
||||
{ ORDATA (RLMA, rlma, 12) },
|
||||
{ ORDATA (RLWC, rlwc, 12) },
|
||||
{ ORDATA (RLSA, rlsa, 6) },
|
||||
{ ORDATA (RLER, rler, 12) },
|
||||
{ ORDATA (RLSI, rlsi, 16) },
|
||||
{ ORDATA (RLSI1, rlsi1, 16) },
|
||||
{ ORDATA (RLSI2, rlsi2, 16) },
|
||||
{ FLDATA (RLSIL, rl_lft, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_RL) },
|
||||
{ FLDATA (DONE, rl_done, INT_V_RL) },
|
||||
{ FLDATA (IE, rlcsb, RLCSB_V_IE) },
|
||||
{ FLDATA (ERR, rl_erf, 0) },
|
||||
{ DRDATA (STIME, rl_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, rl_rwait, 24), PV_LEFT },
|
||||
{ URDATA (CAPAC, rl_unit[0].capac, 10, T_ADDR_W, 0,
|
||||
RL_NUMDR, PV_LEFT + REG_HRO) },
|
||||
{ FLDATA (STOP_IOE, rl_stopioe, 0) },
|
||||
{ ORDATA (DEVNUM, rl_dib.dev, 6), REG_HRO },
|
||||
{ NULL } };
|
||||
{ ORDATA (RLCSA, rlcsa, 12) },
|
||||
{ ORDATA (RLCSB, rlcsb, 12) },
|
||||
{ ORDATA (RLMA, rlma, 12) },
|
||||
{ ORDATA (RLWC, rlwc, 12) },
|
||||
{ ORDATA (RLSA, rlsa, 6) },
|
||||
{ ORDATA (RLER, rler, 12) },
|
||||
{ ORDATA (RLSI, rlsi, 16) },
|
||||
{ ORDATA (RLSI1, rlsi1, 16) },
|
||||
{ ORDATA (RLSI2, rlsi2, 16) },
|
||||
{ FLDATA (RLSIL, rl_lft, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_RL) },
|
||||
{ FLDATA (DONE, rl_done, INT_V_RL) },
|
||||
{ FLDATA (IE, rlcsb, RLCSB_V_IE) },
|
||||
{ FLDATA (ERR, rl_erf, 0) },
|
||||
{ DRDATA (STIME, rl_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, rl_rwait, 24), PV_LEFT },
|
||||
{ URDATA (CAPAC, rl_unit[0].capac, 10, T_ADDR_W, 0,
|
||||
RL_NUMDR, PV_LEFT + REG_HRO) },
|
||||
{ FLDATA (STOP_IOE, rl_stopioe, 0) },
|
||||
{ ORDATA (DEVNUM, rl_dib.dev, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB rl_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ UNIT_DUMMY, 0, NULL, "BADBLOCK", &rl_set_bad },
|
||||
{ (UNIT_RL02+UNIT_ATT), UNIT_ATT, "RL01", NULL, NULL },
|
||||
{ (UNIT_RL02+UNIT_ATT), (UNIT_RL02+UNIT_ATT), "RL02", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_RL02+UNIT_ATT), 0, "RL01", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_RL02+UNIT_ATT), UNIT_RL02, "RL02", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },
|
||||
{ UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL },
|
||||
{ (UNIT_AUTO+UNIT_RL02), 0, NULL, "RL01", &rl_set_size },
|
||||
{ (UNIT_AUTO+UNIT_RL02), UNIT_RL02, NULL, "RL02", &rl_set_size },
|
||||
{ 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 },
|
||||
{ UNIT_DUMMY, 0, NULL, "BADBLOCK", &rl_set_bad },
|
||||
{ (UNIT_RL02+UNIT_ATT), UNIT_ATT, "RL01", NULL, NULL },
|
||||
{ (UNIT_RL02+UNIT_ATT), (UNIT_RL02+UNIT_ATT), "RL02", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_RL02+UNIT_ATT), 0, "RL01", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_RL02+UNIT_ATT), UNIT_RL02, "RL02", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },
|
||||
{ UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL },
|
||||
{ (UNIT_AUTO+UNIT_RL02), 0, NULL, "RL01", &rl_set_size },
|
||||
{ (UNIT_AUTO+UNIT_RL02), UNIT_RL02, NULL, "RL02", &rl_set_size },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE rl_dev = {
|
||||
"RL", rl_unit, rl_reg, rl_mod,
|
||||
RL_NUMDR, 8, 24, 1, 8, 8,
|
||||
NULL, NULL, &rl_reset,
|
||||
&rl_boot, &rl_attach, NULL,
|
||||
&rl_dib, DEV_DISABLE | DEV_DIS };
|
||||
|
||||
/* IOT 60 routine */
|
||||
"RL", rl_unit, rl_reg, rl_mod,
|
||||
RL_NUMDR, 8, 24, 1, 8, 8,
|
||||
NULL, NULL, &rl_reset,
|
||||
&rl_boot, &rl_attach, NULL,
|
||||
&rl_dib, DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* IOT routines */
|
||||
|
||||
int32 rl60 (int32 IR, int32 AC)
|
||||
{
|
||||
int32 curr, offs, newc, maxc;
|
||||
UNIT *uptr;
|
||||
|
||||
switch (IR & 07) { /* case IR<9:11> */
|
||||
case 0: /* RLDC */
|
||||
rl_reset (&rl_dev); /* reset device */
|
||||
break;
|
||||
case 1: /* RLSD */
|
||||
if (rl_done) AC = IOT_SKP; /* skip if done */
|
||||
else AC = 0;
|
||||
rl_done = 0; /* clear done */
|
||||
int_req = int_req & ~INT_RL; /* clear intr */
|
||||
return AC;
|
||||
case 2: /* RLMA */
|
||||
rlma = AC;
|
||||
break;
|
||||
case 3: /* RLCA */
|
||||
rlcsa = AC;
|
||||
break;
|
||||
case 4: /* RLCB */
|
||||
rlcsb = AC;
|
||||
rl_done = 0; /* clear done */
|
||||
rler = rl_erf = 0; /* clear errors */
|
||||
int_req = int_req & ~INT_RL; /* clear intr */
|
||||
rl_lft = 0; /* clear silo ptr */
|
||||
uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */
|
||||
switch (GET_FUNC (rlcsb)) { /* case on func */
|
||||
case RLCSB_CLRD: /* clear drive */
|
||||
uptr->STAT = uptr->STAT & ~RLDS_ERR; /* clear errors */
|
||||
case RLCSB_MNT: /* mnt */
|
||||
rl_set_done (0);
|
||||
break;
|
||||
case RLCSB_SEEK: /* seek */
|
||||
curr = GET_CYL (uptr->TRK); /* current cylinder */
|
||||
offs = GET_CYL (rlcsa); /* offset */
|
||||
if (rlcsa & RLCSA_DIR) { /* in or out? */
|
||||
newc = curr + offs; /* out */
|
||||
maxc = (uptr->flags & UNIT_RL02)?
|
||||
RL_NUMCY * 2: RL_NUMCY;
|
||||
if (newc >= maxc) newc = maxc - 1; }
|
||||
else {
|
||||
newc = curr - offs; /* in */
|
||||
if (newc < 0) newc = 0; }
|
||||
uptr->TRK = newc | (rlcsa & RLCSA_HD);
|
||||
sim_activate (uptr, rl_swait * abs (newc - curr));
|
||||
break;
|
||||
default: /* data transfer */
|
||||
sim_activate (uptr, rl_swait); /* activate unit */
|
||||
break; } /* end switch func */
|
||||
break;
|
||||
case 5: /* RLSA */
|
||||
rlsa = GET_SECT (AC);
|
||||
break;
|
||||
case 6: /* spare */
|
||||
return 0;
|
||||
case 7: /* RLWC */
|
||||
rlwc = AC;
|
||||
break; } /* end switch pulse */
|
||||
return 0; /* clear AC */
|
||||
switch (IR & 07) { /* case IR<9:11> */
|
||||
|
||||
case 0: /* RLDC */
|
||||
rl_reset (&rl_dev); /* reset device */
|
||||
break;
|
||||
|
||||
case 1: /* RLSD */
|
||||
if (rl_done) AC = IOT_SKP; /* skip if done */
|
||||
else AC = 0;
|
||||
rl_done = 0; /* clear done */
|
||||
int_req = int_req & ~INT_RL; /* clear intr */
|
||||
return AC;
|
||||
|
||||
case 2: /* RLMA */
|
||||
rlma = AC;
|
||||
break;
|
||||
|
||||
case 3: /* RLCA */
|
||||
rlcsa = AC;
|
||||
break;
|
||||
|
||||
case 4: /* RLCB */
|
||||
rlcsb = AC;
|
||||
rl_done = 0; /* clear done */
|
||||
rler = rl_erf = 0; /* clear errors */
|
||||
int_req = int_req & ~INT_RL; /* clear intr */
|
||||
rl_lft = 0; /* clear silo ptr */
|
||||
uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */
|
||||
switch (GET_FUNC (rlcsb)) { /* case on func */
|
||||
|
||||
case RLCSB_CLRD: /* clear drive */
|
||||
uptr->STAT = uptr->STAT & ~RLDS_ERR; /* clear errors */
|
||||
case RLCSB_MNT: /* mnt */
|
||||
rl_set_done (0);
|
||||
break;
|
||||
|
||||
case RLCSB_SEEK: /* seek */
|
||||
curr = GET_CYL (uptr->TRK); /* current cylinder */
|
||||
offs = GET_CYL (rlcsa); /* offset */
|
||||
if (rlcsa & RLCSA_DIR) { /* in or out? */
|
||||
newc = curr + offs; /* out */
|
||||
maxc = (uptr->flags & UNIT_RL02)?
|
||||
RL_NUMCY * 2: RL_NUMCY;
|
||||
if (newc >= maxc) newc = maxc - 1;
|
||||
}
|
||||
else {
|
||||
newc = curr - offs; /* in */
|
||||
if (newc < 0) newc = 0;
|
||||
}
|
||||
uptr->TRK = newc | (rlcsa & RLCSA_HD);
|
||||
sim_activate (uptr, rl_swait * abs (newc - curr));
|
||||
break;
|
||||
|
||||
default: /* data transfer */
|
||||
sim_activate (uptr, rl_swait); /* activate unit */
|
||||
break;
|
||||
} /* end switch func */
|
||||
break;
|
||||
|
||||
case 5: /* RLSA */
|
||||
rlsa = GET_SECT (AC);
|
||||
break;
|
||||
|
||||
case 6: /* spare */
|
||||
return 0;
|
||||
|
||||
case 7: /* RLWC */
|
||||
rlwc = AC;
|
||||
break;
|
||||
} /* end switch pulse */
|
||||
|
||||
return 0; /* clear AC */
|
||||
}
|
||||
|
||||
/* IOT 61 routine */
|
||||
|
||||
int32 rl61 (int32 pulse, int32 AC)
|
||||
{
|
||||
int32 dat;
|
||||
UNIT *uptr;
|
||||
|
||||
switch (pulse) { /* case IR<9:11> */
|
||||
case 0: /* RRER */
|
||||
uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */
|
||||
if (!sim_is_active (uptr) && /* update drdy */
|
||||
(uptr->flags & UNIT_ATT))
|
||||
rler = rler | RLER_DRDY;
|
||||
else rler = rler & ~RLER_DRDY;
|
||||
dat = rler & RLER_MASK;
|
||||
break;
|
||||
case 1: /* RRWC */
|
||||
dat = rlwc;
|
||||
break;
|
||||
case 2: /* RRCA */
|
||||
dat = rlcsa;
|
||||
break;
|
||||
case 3: /* RRCB */
|
||||
dat = rlcsb;
|
||||
break;
|
||||
case 4: /* RRSA */
|
||||
dat = (rlsa << RLSA_V_SECT) & 07777;
|
||||
break;
|
||||
case 5: /* RRSI */
|
||||
if (rl_lft) { /* silo left? */
|
||||
dat = (rlsi >> 8) & 0377; /* get left 8b */
|
||||
rlsi = rlsi1; /* ripple */
|
||||
rlsi1 = rlsi2; }
|
||||
else dat = rlsi & 0377; /* get right 8b */
|
||||
rl_lft = rl_lft ^ 1; /* change side */
|
||||
break;
|
||||
case 6: /* spare */
|
||||
return AC;
|
||||
case 7: /* RLSE */
|
||||
if (rl_erf) dat = IOT_SKP | AC; /* skip if err */
|
||||
else dat = AC;
|
||||
rl_erf = 0;
|
||||
break; } /* end switch pulse */
|
||||
switch (pulse) { /* case IR<9:11> */
|
||||
|
||||
case 0: /* RRER */
|
||||
uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */
|
||||
if (!sim_is_active (uptr) && /* update drdy */
|
||||
(uptr->flags & UNIT_ATT))
|
||||
rler = rler | RLER_DRDY;
|
||||
else rler = rler & ~RLER_DRDY;
|
||||
dat = rler & RLER_MASK;
|
||||
break;
|
||||
|
||||
case 1: /* RRWC */
|
||||
dat = rlwc;
|
||||
break;
|
||||
|
||||
case 2: /* RRCA */
|
||||
dat = rlcsa;
|
||||
break;
|
||||
|
||||
case 3: /* RRCB */
|
||||
dat = rlcsb;
|
||||
break;
|
||||
|
||||
case 4: /* RRSA */
|
||||
dat = (rlsa << RLSA_V_SECT) & 07777;
|
||||
break;
|
||||
|
||||
case 5: /* RRSI */
|
||||
if (rl_lft) { /* silo left? */
|
||||
dat = (rlsi >> 8) & 0377; /* get left 8b */
|
||||
rlsi = rlsi1; /* ripple */
|
||||
rlsi1 = rlsi2;
|
||||
}
|
||||
else dat = rlsi & 0377; /* get right 8b */
|
||||
rl_lft = rl_lft ^ 1; /* change side */
|
||||
break;
|
||||
|
||||
case 6: /* spare */
|
||||
return AC;
|
||||
|
||||
case 7: /* RLSE */
|
||||
if (rl_erf) dat = IOT_SKP | AC; /* skip if err */
|
||||
else dat = AC;
|
||||
rl_erf = 0;
|
||||
break;
|
||||
} /* end switch pulse */
|
||||
|
||||
return dat;
|
||||
}
|
||||
|
||||
|
||||
/* Service unit timeout
|
||||
|
||||
If seek in progress, complete seek command
|
||||
@@ -374,106 +404,120 @@ int32 err, wc, maxc;
|
||||
int32 i, j, func, da, bc, wbc;
|
||||
uint32 ma;
|
||||
|
||||
func = GET_FUNC (rlcsb); /* get function */
|
||||
if (func == RLCSB_GSTA) { /* get status? */
|
||||
rlsi = uptr->STAT |
|
||||
((uptr->TRK & RLCSA_HD)? RLDS_HD: 0) |
|
||||
((uptr->flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT);
|
||||
if (uptr->flags & UNIT_RL02) rlsi = rlsi | RLDS_RL02;
|
||||
if (uptr->flags & UNIT_WPRT) rlsi = rlsi | RLDS_WLK;
|
||||
rlsi2 = rlsi1 = rlsi;
|
||||
rl_set_done (0); /* done */
|
||||
return SCPE_OK; }
|
||||
func = GET_FUNC (rlcsb); /* get function */
|
||||
if (func == RLCSB_GSTA) { /* get status? */
|
||||
rlsi = uptr->STAT |
|
||||
((uptr->TRK & RLCSA_HD)? RLDS_HD: 0) |
|
||||
((uptr->flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT);
|
||||
if (uptr->flags & UNIT_RL02) rlsi = rlsi | RLDS_RL02;
|
||||
if (uptr->flags & UNIT_WPRT) rlsi = rlsi | RLDS_WLK;
|
||||
rlsi2 = rlsi1 = rlsi;
|
||||
rl_set_done (0); /* done */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
|
||||
uptr->STAT = uptr->STAT | RLDS_SPE; /* spin error */
|
||||
rl_set_done (RLER_INCMP); /* flag error */
|
||||
return IORETURN (rl_stopioe, SCPE_UNATT); }
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
|
||||
uptr->STAT = uptr->STAT | RLDS_SPE; /* spin error */
|
||||
rl_set_done (RLER_INCMP); /* flag error */
|
||||
return IORETURN (rl_stopioe, SCPE_UNATT);
|
||||
}
|
||||
|
||||
if ((func == RLCSB_WRITE) && (uptr->flags & UNIT_WPRT)) {
|
||||
uptr->STAT = uptr->STAT | RLDS_WGE; /* write and locked */
|
||||
rl_set_done (RLER_DRE); /* flag error */
|
||||
return SCPE_OK; }
|
||||
uptr->STAT = uptr->STAT | RLDS_WGE; /* write and locked */
|
||||
rl_set_done (RLER_DRE); /* flag error */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (func == RLCSB_SEEK) { /* seek? */
|
||||
rl_set_done (0); /* done */
|
||||
return SCPE_OK; }
|
||||
if (func == RLCSB_SEEK) { /* seek? */
|
||||
rl_set_done (0); /* done */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (func == RLCSB_RHDR) { /* read header? */
|
||||
rlsi = (GET_TRK (uptr->TRK) << RLSI_V_TRK) | rlsa;
|
||||
rlsi1 = rlsi2 = 0;
|
||||
rl_set_done (0); /* done */
|
||||
return SCPE_OK; }
|
||||
if (func == RLCSB_RHDR) { /* read header? */
|
||||
rlsi = (GET_TRK (uptr->TRK) << RLSI_V_TRK) | rlsa;
|
||||
rlsi1 = rlsi2 = 0;
|
||||
rl_set_done (0); /* done */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (((func != RLCSB_RNOHDR) && (GET_CYL (uptr->TRK) != GET_CYL (rlcsa)))
|
||||
|| (rlsa >= RL_NUMSC)) { /* bad cyl or sector? */
|
||||
rl_set_done (RLER_HDE | RLER_INCMP); /* flag error */
|
||||
return SCPE_OK; }
|
||||
|
||||
ma = (GET_MEX (rlcsb) << 12) | rlma; /* get mem addr */
|
||||
da = GET_DA (rlcsa) * RL_NUMBY; /* get disk addr */
|
||||
wc = 010000 - rlwc; /* get true wc */
|
||||
if (rlcsb & RLCSB_8B) { /* 8b mode? */
|
||||
bc = wc; /* bytes to xfr */
|
||||
maxc = (RL_NUMSC - rlsa) * RL_NUMBY; /* max transfer */
|
||||
if (bc > maxc) wc = bc = maxc; } /* trk ovrun? limit */
|
||||
else { bc = ((wc * 3) + 1) / 2; /* 12b mode */
|
||||
if (bc > RL_NUMBY) { /* > 1 sector */
|
||||
bc = RL_NUMBY; /* cap xfer */
|
||||
wc = (RL_NUMBY * 2) / 3; } }
|
||||
|| (rlsa >= RL_NUMSC)) { /* bad cyl or sector? */
|
||||
rl_set_done (RLER_HDE | RLER_INCMP); /* flag error */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
ma = (GET_MEX (rlcsb) << 12) | rlma; /* get mem addr */
|
||||
da = GET_DA (rlcsa) * RL_NUMBY; /* get disk addr */
|
||||
wc = 010000 - rlwc; /* get true wc */
|
||||
if (rlcsb & RLCSB_8B) { /* 8b mode? */
|
||||
bc = wc; /* bytes to xfr */
|
||||
maxc = (RL_NUMSC - rlsa) * RL_NUMBY; /* max transfer */
|
||||
if (bc > maxc) wc = bc = maxc; /* trk ovrun? limit */
|
||||
}
|
||||
else {
|
||||
bc = ((wc * 3) + 1) / 2; /* 12b mode */
|
||||
if (bc > RL_NUMBY) { /* > 1 sector */
|
||||
bc = RL_NUMBY; /* cap xfer */
|
||||
wc = (RL_NUMBY * 2) / 3;
|
||||
}
|
||||
}
|
||||
|
||||
err = fseek (uptr->fileref, da, SEEK_SET);
|
||||
|
||||
if ((func >= RLCSB_READ) && (err == 0) && /* read (no hdr)? */
|
||||
MEM_ADDR_OK (ma)) { /* valid bank? */
|
||||
i = fxread (rlxb, sizeof (int8), bc, uptr->fileref);
|
||||
err = ferror (uptr->fileref);
|
||||
for ( ; i < bc; i++) rlxb[i] = 0; /* fill buffer */
|
||||
for (i = j = 0; i < wc; i++) { /* store buffer */
|
||||
if (rlcsb & RLCSB_8B) /* 8b mode? */
|
||||
M[ma] = rlxb[i] & 0377; /* store */
|
||||
else if (i & 1) { /* odd wd 12b? */
|
||||
M[ma] = ((rlxb[j + 1] >> 4) & 017) |
|
||||
(((uint16) rlxb[j + 2]) << 4);
|
||||
j = j + 3; }
|
||||
else M[ma] = rlxb[j] | /* even wd 12b */
|
||||
((((uint16) rlxb[j + 1]) & 017) << 8);
|
||||
ma = (ma & 070000) + ((ma + 1) & 07777);
|
||||
} /* end for */
|
||||
} /* end if wr */
|
||||
if ((func >= RLCSB_READ) && (err == 0) && /* read (no hdr)? */
|
||||
MEM_ADDR_OK (ma)) { /* valid bank? */
|
||||
i = fxread (rlxb, sizeof (int8), bc, uptr->fileref);
|
||||
err = ferror (uptr->fileref);
|
||||
for ( ; i < bc; i++) rlxb[i] = 0; /* fill buffer */
|
||||
for (i = j = 0; i < wc; i++) { /* store buffer */
|
||||
if (rlcsb & RLCSB_8B) /* 8b mode? */
|
||||
M[ma] = rlxb[i] & 0377; /* store */
|
||||
else if (i & 1) { /* odd wd 12b? */
|
||||
M[ma] = ((rlxb[j + 1] >> 4) & 017) |
|
||||
(((uint16) rlxb[j + 2]) << 4);
|
||||
j = j + 3;
|
||||
}
|
||||
else M[ma] = rlxb[j] | /* even wd 12b */
|
||||
((((uint16) rlxb[j + 1]) & 017) << 8);
|
||||
ma = (ma & 070000) + ((ma + 1) & 07777);
|
||||
} /* end for */
|
||||
} /* end if wr */
|
||||
|
||||
if ((func == RLCSB_WRITE) && (err == 0)) { /* write? */
|
||||
for (i = j = 0; i < wc; i++) { /* fetch buffer */
|
||||
if (rlcsb & RLCSB_8B) /* 8b mode? */
|
||||
rlxb[i] = M[ma] & 0377; /* fetch */
|
||||
else if (i & 1) { /* odd wd 12b? */
|
||||
rlxb[j + 1] = rlxb[j + 1] | ((M[ma] & 017) << 4);
|
||||
rlxb[j + 2] = ((M[ma] >> 4) & 0377);
|
||||
j = j + 3; }
|
||||
else { /* even wd 12b */
|
||||
rlxb[j] = M[ma] & 0377;
|
||||
rlxb[j + 1] = (M[ma] >> 8) & 017; }
|
||||
ma = (ma & 070000) + ((ma + 1) & 07777);
|
||||
} /* end for */
|
||||
wbc = (bc + (RL_NUMBY - 1)) & ~(RL_NUMBY - 1); /* clr to */
|
||||
for (i = bc; i < wbc; i++) rlxb[i] = 0; /* end of blk */
|
||||
fxwrite (rlxb, sizeof (int8), wbc, uptr->fileref);
|
||||
err = ferror (uptr->fileref);
|
||||
} /* end write */
|
||||
if ((func == RLCSB_WRITE) && (err == 0)) { /* write? */
|
||||
for (i = j = 0; i < wc; i++) { /* fetch buffer */
|
||||
if (rlcsb & RLCSB_8B) /* 8b mode? */
|
||||
rlxb[i] = M[ma] & 0377; /* fetch */
|
||||
else if (i & 1) { /* odd wd 12b? */
|
||||
rlxb[j + 1] = rlxb[j + 1] | ((M[ma] & 017) << 4);
|
||||
rlxb[j + 2] = ((M[ma] >> 4) & 0377);
|
||||
j = j + 3;
|
||||
}
|
||||
else { /* even wd 12b */
|
||||
rlxb[j] = M[ma] & 0377;
|
||||
rlxb[j + 1] = (M[ma] >> 8) & 017;
|
||||
}
|
||||
ma = (ma & 070000) + ((ma + 1) & 07777);
|
||||
} /* end for */
|
||||
wbc = (bc + (RL_NUMBY - 1)) & ~(RL_NUMBY - 1); /* clr to */
|
||||
for (i = bc; i < wbc; i++) rlxb[i] = 0; /* end of blk */
|
||||
fxwrite (rlxb, sizeof (int8), wbc, uptr->fileref);
|
||||
err = ferror (uptr->fileref);
|
||||
} /* end write */
|
||||
|
||||
rlwc = (rlwc + wc) & 07777; /* final word count */
|
||||
if (rlwc != 0) rler = rler | RLER_INCMP; /* completed? */
|
||||
rlma = (rlma + wc) & 07777; /* final word addr */
|
||||
rlwc = (rlwc + wc) & 07777; /* final word count */
|
||||
if (rlwc != 0) rler = rler | RLER_INCMP; /* completed? */
|
||||
rlma = (rlma + wc) & 07777; /* final word addr */
|
||||
rlsa = rlsa + ((bc + (RL_NUMBY - 1)) / RL_NUMBY);
|
||||
rl_set_done (0);
|
||||
|
||||
if (err != 0) { /* error? */
|
||||
perror ("RL I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
if (err != 0) { /* error? */
|
||||
perror ("RL I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Set done and possibly errors */
|
||||
|
||||
void rl_set_done (int32 status)
|
||||
@@ -504,10 +548,11 @@ rl_done = 0;
|
||||
rl_erf = 0;
|
||||
int_req = int_req & ~INT_RL;
|
||||
for (i = 0; i < RL_NUMDR; i++) {
|
||||
uptr = rl_dev.units + i;
|
||||
sim_cancel (uptr);
|
||||
uptr->STAT = 0; }
|
||||
if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (uint8));
|
||||
uptr = rl_dev.units + i;
|
||||
sim_cancel (uptr);
|
||||
uptr->STAT = 0;
|
||||
}
|
||||
if (rlxb == NULL) rlxb = (uint8 *) calloc (RL_MAXFR, sizeof (uint8));
|
||||
if (rlxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -520,19 +565,23 @@ uint32 p;
|
||||
t_stat r;
|
||||
|
||||
uptr->capac = (uptr->flags & UNIT_RL02)? RL02_SIZE: RL01_SIZE;
|
||||
r = attach_unit (uptr, cptr); /* attach unit */
|
||||
if (r != SCPE_OK) return r; /* error? */
|
||||
uptr->TRK = 0; /* cyl 0 */
|
||||
uptr->STAT = RLDS_VCK; /* new volume */
|
||||
if ((p = sim_fsize (uptr->fileref)) == 0) { /* new disk image? */
|
||||
if (uptr->flags & UNIT_RO) return SCPE_OK;
|
||||
return rl_set_bad (uptr, 0, NULL, NULL); }
|
||||
if ((uptr->flags & UNIT_AUTO) == 0) return r; /* autosize? */
|
||||
r = attach_unit (uptr, cptr); /* attach unit */
|
||||
if (r != SCPE_OK) return r; /* error? */
|
||||
uptr->TRK = 0; /* cyl 0 */
|
||||
uptr->STAT = RLDS_VCK; /* new volume */
|
||||
if ((p = sim_fsize (uptr->fileref)) == 0) { /* new disk image? */
|
||||
if (uptr->flags & UNIT_RO) return SCPE_OK;
|
||||
return rl_set_bad (uptr, 0, NULL, NULL);
|
||||
}
|
||||
if ((uptr->flags & UNIT_AUTO) == 0) return r; /* autosize? */
|
||||
if (p > (RL01_SIZE * sizeof (int16))) {
|
||||
uptr->flags = uptr->flags | UNIT_RL02;
|
||||
uptr->capac = RL02_SIZE; }
|
||||
else { uptr->flags = uptr->flags & ~UNIT_RL02;
|
||||
uptr->capac = RL01_SIZE; }
|
||||
uptr->flags = uptr->flags | UNIT_RL02;
|
||||
uptr->capac = RL02_SIZE;
|
||||
}
|
||||
else {
|
||||
uptr->flags = uptr->flags & ~UNIT_RL02;
|
||||
uptr->capac = RL01_SIZE;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -549,16 +598,16 @@ return SCPE_OK;
|
||||
|
||||
This routine writes the OS/8 specific bad block map in track 0, sector 014 (RL_BBMAP):
|
||||
|
||||
words 0 magic number = 0123 (RL_BBID)
|
||||
words 1-n block numbers
|
||||
:
|
||||
words n+1 end of table = 0
|
||||
words 0 magic number = 0123 (RL_BBID)
|
||||
words 1-n block numbers
|
||||
:
|
||||
words n+1 end of table = 0
|
||||
|
||||
Inputs:
|
||||
uptr = pointer to unit
|
||||
val = ignored
|
||||
uptr = pointer to unit
|
||||
val = ignored
|
||||
Outputs:
|
||||
sta = status code
|
||||
sta = status code
|
||||
*/
|
||||
|
||||
t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
@@ -571,48 +620,48 @@ if (!get_yn ("Create bad block table? [N]", FALSE)) return SCPE_OK;
|
||||
if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR;
|
||||
rlxb[0] = RL_BBID;
|
||||
for (i = 1; i < RL_NUMBY; i++) rlxb[i] = 0;
|
||||
fxwrite (rlxb, sizeof (int8), RL_NUMBY, uptr->fileref);
|
||||
fxwrite (rlxb, sizeof (uint8), RL_NUMBY, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) return SCPE_IOERR;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Bootstrap */
|
||||
|
||||
#define BOOT_START 1 /* start */
|
||||
#define BOOT_UNIT 02006 /* unit number */
|
||||
#define BOOT_START 1 /* start */
|
||||
#define BOOT_UNIT 02006 /* unit number */
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16))
|
||||
|
||||
static const uint16 boot_rom[] = {
|
||||
06600, /* BT, RLDC ; reset */
|
||||
07201, /* 02, CLA IAC ; clr drv = 1 */
|
||||
04027, /* 03, JMS GO ; do io */
|
||||
01004, /* 04, TAD 4 ; rd hdr fnc */
|
||||
04027, /* 05, JMS GO ; do io */
|
||||
06615, /* 06, RRSI ; rd hdr lo */
|
||||
07002, /* 07, BSW ; swap */
|
||||
07012, /* 10, RTR ; lo cyl to L */
|
||||
06615, /* 11, RRSI ; rd hdr hi */
|
||||
00025, /* 12, AND 25 ; mask = 377 */
|
||||
07004, /* 13, RTL ; get cyl */
|
||||
06603, /* 14, RLCA ; set addr */
|
||||
07325, /* 15, CLA STL IAC RAL ; seek = 3 */
|
||||
04027, /* 16, JMS GO ; do io */
|
||||
07332, /* 17, CLA STL RTR ; dir in = 2000 */
|
||||
06605, /* 20, RLSA ; sector */
|
||||
01026, /* 21, TAD (-200) ; one sector */
|
||||
06607, /* 22, RLWC ; word cnt */
|
||||
07327, /* 23, CLA STL IAC RTL ; read = 6*/
|
||||
04027, /* 24, JMS GO ; do io */
|
||||
00377, /* 25, JMP 377 ; start */
|
||||
07600, /* 26, -200 ; word cnt */
|
||||
00000, /* GO, 0 ; subr */
|
||||
06604, /* 30, RLCB ; load fnc */
|
||||
06601, /* 31, RLSD ; wait */
|
||||
05031, /* 32, JMP .-1 ; */
|
||||
06617, /* 33, RLSE ; error? */
|
||||
05427, /* 34, JMP I GO ; no, ok */
|
||||
05001 /* 35, JMP BT ; restart */
|
||||
};
|
||||
06600, /* BT, RLDC ; reset */
|
||||
07201, /* 02, CLA IAC ; clr drv = 1 */
|
||||
04027, /* 03, JMS GO ; do io */
|
||||
01004, /* 04, TAD 4 ; rd hdr fnc */
|
||||
04027, /* 05, JMS GO ; do io */
|
||||
06615, /* 06, RRSI ; rd hdr lo */
|
||||
07002, /* 07, BSW ; swap */
|
||||
07012, /* 10, RTR ; lo cyl to L */
|
||||
06615, /* 11, RRSI ; rd hdr hi */
|
||||
00025, /* 12, AND 25 ; mask = 377 */
|
||||
07004, /* 13, RTL ; get cyl */
|
||||
06603, /* 14, RLCA ; set addr */
|
||||
07325, /* 15, CLA STL IAC RAL ; seek = 3 */
|
||||
04027, /* 16, JMS GO ; do io */
|
||||
07332, /* 17, CLA STL RTR ; dir in = 2000 */
|
||||
06605, /* 20, RLSA ; sector */
|
||||
01026, /* 21, TAD (-200) ; one sector */
|
||||
06607, /* 22, RLWC ; word cnt */
|
||||
07327, /* 23, CLA STL IAC RTL ; read = 6*/
|
||||
04027, /* 24, JMS GO ; do io */
|
||||
00377, /* 25, JMP 377 ; start */
|
||||
07600, /* 26, -200 ; word cnt */
|
||||
00000, /* GO, 0 ; subr */
|
||||
06604, /* 30, RLCB ; load fnc */
|
||||
06601, /* 31, RLSD ; wait */
|
||||
05031, /* 32, JMP .-1 ; */
|
||||
06617, /* 33, RLSE ; error? */
|
||||
05427, /* 34, JMP I GO ; no, ok */
|
||||
05001 /* 35, JMP BT ; restart */
|
||||
};
|
||||
|
||||
|
||||
t_stat rl_boot (int32 unitno, DEVICE *dptr)
|
||||
@@ -620,8 +669,8 @@ t_stat rl_boot (int32 unitno, DEVICE *dptr)
|
||||
int32 i;
|
||||
extern int32 saved_PC;
|
||||
|
||||
if (unitno) return SCPE_ARG; /* only unit 0 */
|
||||
if (rl_dib.dev != DEV_RL) return STOP_NOTSTD; /* only std devno */
|
||||
if (unitno) return SCPE_ARG; /* only unit 0 */
|
||||
if (rl_dib.dev != DEV_RL) return STOP_NOTSTD; /* only std devno */
|
||||
rl_unit[unitno].TRK = 0;
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||
saved_PC = BOOT_START;
|
||||
|
||||
1020
PDP8/pdp8_rx.c
1020
PDP8/pdp8_rx.c
File diff suppressed because it is too large
Load Diff
596
PDP8/pdp8_sys.c
596
PDP8/pdp8_sys.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_sys.c: PDP-8 simulator interface
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,24 +19,24 @@
|
||||
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-Oct-03 RMS Added TSC8-75, TD8E support, DECtape off reel message
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
30-Dec-01 RMS Revised for new TTX
|
||||
26-Nov-01 RMS Added RL8A support
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
16-Sep-01 RMS Added TSS/8 packed char support, added KL8A support
|
||||
27-May-01 RMS Added multiconsole support
|
||||
18-Mar-01 RMS Added DF32 support
|
||||
14-Mar-01 RMS Added extension detection of RIM binary tapes
|
||||
15-Feb-01 RMS Added DECtape support
|
||||
30-Oct-00 RMS Added support for examine to file
|
||||
27-Oct-98 RMS V2.4 load interface
|
||||
10-Apr-98 RMS Added RIM loader support
|
||||
17-Feb-97 RMS Fixed bug in handling of bin loader fields
|
||||
17-Oct-03 RMS Added TSC8-75, TD8E support, DECtape off reel message
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
30-Dec-01 RMS Revised for new TTX
|
||||
26-Nov-01 RMS Added RL8A support
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
16-Sep-01 RMS Added TSS/8 packed char support, added KL8A support
|
||||
27-May-01 RMS Added multiconsole support
|
||||
18-Mar-01 RMS Added DF32 support
|
||||
14-Mar-01 RMS Added extension detection of RIM binary tapes
|
||||
15-Feb-01 RMS Added DECtape support
|
||||
30-Oct-00 RMS Added support for examine to file
|
||||
27-Oct-98 RMS V2.4 load interface
|
||||
10-Apr-98 RMS Added RIM loader support
|
||||
17-Feb-97 RMS Fixed bug in handling of bin loader fields
|
||||
*/
|
||||
|
||||
#include "pdp8_defs.h"
|
||||
@@ -60,13 +60,13 @@ extern int32 sim_switches;
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax maximum number of words for examine/deposit
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_consoles array of pointers to consoles (if more than one)
|
||||
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 maximum number of words for examine/deposit
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_consoles array of pointers to consoles (if more than one)
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "PDP-8";
|
||||
@@ -76,34 +76,36 @@ REG *sim_PC = &cpu_reg[0];
|
||||
int32 sim_emax = 4;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&tsc_dev,
|
||||
&ptr_dev,
|
||||
&ptp_dev,
|
||||
&tti_dev,
|
||||
&tto_dev,
|
||||
&ttix_dev,
|
||||
&ttox_dev,
|
||||
&clk_dev,
|
||||
&lpt_dev,
|
||||
&rk_dev,
|
||||
&rl_dev,
|
||||
&rx_dev,
|
||||
&df_dev,
|
||||
&rf_dev,
|
||||
&dt_dev,
|
||||
&td_dev,
|
||||
&mt_dev,
|
||||
NULL };
|
||||
&cpu_dev,
|
||||
&tsc_dev,
|
||||
&ptr_dev,
|
||||
&ptp_dev,
|
||||
&tti_dev,
|
||||
&tto_dev,
|
||||
&ttix_dev,
|
||||
&ttox_dev,
|
||||
&clk_dev,
|
||||
&lpt_dev,
|
||||
&rk_dev,
|
||||
&rl_dev,
|
||||
&rx_dev,
|
||||
&df_dev,
|
||||
&rf_dev,
|
||||
&dt_dev,
|
||||
&td_dev,
|
||||
&mt_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"Unimplemented instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Non-standard device number",
|
||||
"DECtape off reel" };
|
||||
|
||||
"Unknown error",
|
||||
"Unimplemented instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Non-standard device number",
|
||||
"DECtape off reel"
|
||||
};
|
||||
|
||||
/* Binary loader
|
||||
|
||||
Two loader formats are supported: RIM loader (-r) and BIN (-b) loader.
|
||||
@@ -124,89 +126,105 @@ uint32 origin, field;
|
||||
|
||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
||||
rubout = state = field = newf = origin = csum = 0;
|
||||
if ((sim_switches & SWMASK ('R')) || /* RIM format? */
|
||||
if ((sim_switches & SWMASK ('R')) || /* RIM format? */
|
||||
(match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) {
|
||||
while ((i = getc (fileref)) != EOF) {
|
||||
switch (state) {
|
||||
case 0: /* leader */
|
||||
if ((i != 0) && (i < 0200)) state = 1;
|
||||
high = i;
|
||||
break;
|
||||
case 1: /* low byte */
|
||||
word = (high << 6) | i; /* form word */
|
||||
if (word > 07777) origin = word & 07777;
|
||||
else M[origin] = word;
|
||||
state = 2;
|
||||
break;
|
||||
case 2: /* high byte */
|
||||
if (i >= 0200) return SCPE_OK; /* end of tape? */
|
||||
high = i; /* save high */
|
||||
state = 1;
|
||||
break; } /* end switch */
|
||||
} /* end while */
|
||||
} /* end if */
|
||||
else { while ((i = getc (fileref)) != EOF) { /* BIN format */
|
||||
if (rubout) {
|
||||
rubout = 0;
|
||||
continue; }
|
||||
if (i == 0377) {
|
||||
rubout = 1;
|
||||
continue; }
|
||||
if (i > 0200) {
|
||||
newf = (i & 070) << 9;
|
||||
continue; }
|
||||
switch (state) {
|
||||
case 0: /* leader */
|
||||
if ((i != 0) && (i != 0200)) state = 1;
|
||||
high = i; /* save as high */
|
||||
break;
|
||||
case 1: /* low byte */
|
||||
low = i;
|
||||
state = 2;
|
||||
break;
|
||||
case 2: /* high with test */
|
||||
word = (high << 6) | low;
|
||||
if (i == 0200) { /* end of tape? */
|
||||
if ((csum - word) & 07777) return SCPE_CSUM;
|
||||
return SCPE_OK; }
|
||||
csum = csum + low + high;
|
||||
if (word >= 010000) origin = word & 07777;
|
||||
else {
|
||||
if ((field | origin) >= MEMSIZE)
|
||||
return SCPE_NXM;
|
||||
M[field | origin] = word & 07777;
|
||||
origin = (origin + 1) & 07777; }
|
||||
field = newf;
|
||||
high = i;
|
||||
state = 1;
|
||||
break; } /* end switch */
|
||||
} /* end while */
|
||||
} /* end else */
|
||||
return SCPE_FMT; /* eof? error */
|
||||
while ((i = getc (fileref)) != EOF) {
|
||||
switch (state) {
|
||||
|
||||
case 0: /* leader */
|
||||
if ((i != 0) && (i < 0200)) state = 1;
|
||||
high = i;
|
||||
break;
|
||||
|
||||
case 1: /* low byte */
|
||||
word = (high << 6) | i; /* form word */
|
||||
if (word > 07777) origin = word & 07777;
|
||||
else M[origin] = word;
|
||||
state = 2;
|
||||
break;
|
||||
|
||||
case 2: /* high byte */
|
||||
if (i >= 0200) return SCPE_OK; /* end of tape? */
|
||||
high = i; /* save high */
|
||||
state = 1;
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end while */
|
||||
} /* end if */
|
||||
|
||||
else {
|
||||
while ((i = getc (fileref)) != EOF) { /* BIN format */
|
||||
if (rubout) {
|
||||
rubout = 0;
|
||||
continue;
|
||||
}
|
||||
if (i == 0377) {
|
||||
rubout = 1;
|
||||
continue;
|
||||
}
|
||||
if (i > 0200) {
|
||||
newf = (i & 070) << 9;
|
||||
continue;
|
||||
}
|
||||
switch (state) {
|
||||
|
||||
case 0: /* leader */
|
||||
if ((i != 0) && (i != 0200)) state = 1;
|
||||
high = i; /* save as high */
|
||||
break;
|
||||
|
||||
case 1: /* low byte */
|
||||
low = i;
|
||||
state = 2;
|
||||
break;
|
||||
|
||||
case 2: /* high with test */
|
||||
word = (high << 6) | low;
|
||||
if (i == 0200) { /* end of tape? */
|
||||
if ((csum - word) & 07777) return SCPE_CSUM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
csum = csum + low + high;
|
||||
if (word >= 010000) origin = word & 07777;
|
||||
else {
|
||||
if ((field | origin) >= MEMSIZE)
|
||||
return SCPE_NXM;
|
||||
M[field | origin] = word & 07777;
|
||||
origin = (origin + 1) & 07777;
|
||||
}
|
||||
field = newf;
|
||||
high = i;
|
||||
state = 1;
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end while */
|
||||
} /* end else */
|
||||
return SCPE_FMT; /* eof? error */
|
||||
}
|
||||
|
||||
|
||||
/* Symbol tables */
|
||||
|
||||
#define I_V_FL 18 /* flag start */
|
||||
#define I_M_FL 07 /* flag mask */
|
||||
#define I_V_NPN 0 /* no operand */
|
||||
#define I_V_FLD 1 /* field change */
|
||||
#define I_V_MRF 2 /* mem ref */
|
||||
#define I_V_IOT 3 /* general IOT */
|
||||
#define I_V_OP1 4 /* operate 1 */
|
||||
#define I_V_OP2 5 /* operate 2 */
|
||||
#define I_V_OP3 6 /* operate 3 */
|
||||
#define I_NPN (I_V_NPN << I_V_FL)
|
||||
#define I_FLD (I_V_FLD << I_V_FL)
|
||||
#define I_MRF (I_V_MRF << I_V_FL)
|
||||
#define I_IOT (I_V_IOT << I_V_FL)
|
||||
#define I_OP1 (I_V_OP1 << I_V_FL)
|
||||
#define I_OP2 (I_V_OP2 << I_V_FL)
|
||||
#define I_OP3 (I_V_OP3 << I_V_FL)
|
||||
#define I_V_FL 18 /* flag start */
|
||||
#define I_M_FL 07 /* flag mask */
|
||||
#define I_V_NPN 0 /* no operand */
|
||||
#define I_V_FLD 1 /* field change */
|
||||
#define I_V_MRF 2 /* mem ref */
|
||||
#define I_V_IOT 3 /* general IOT */
|
||||
#define I_V_OP1 4 /* operate 1 */
|
||||
#define I_V_OP2 5 /* operate 2 */
|
||||
#define I_V_OP3 6 /* operate 3 */
|
||||
#define I_NPN (I_V_NPN << I_V_FL)
|
||||
#define I_FLD (I_V_FLD << I_V_FL)
|
||||
#define I_MRF (I_V_MRF << I_V_FL)
|
||||
#define I_IOT (I_V_IOT << I_V_FL)
|
||||
#define I_OP1 (I_V_OP1 << I_V_FL)
|
||||
#define I_OP2 (I_V_OP2 << I_V_FL)
|
||||
#define I_OP3 (I_V_OP3 << I_V_FL)
|
||||
|
||||
static const int32 masks[] = {
|
||||
07777, 07707, 07000, 07000,
|
||||
07416, 07571, 017457 };
|
||||
07416, 07571, 017457
|
||||
};
|
||||
|
||||
static const char *opcode[] = {
|
||||
"SKON", "ION", "IOF", "SRQ",
|
||||
@@ -261,11 +279,12 @@ static const char *opcode[] = {
|
||||
"ACS", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR",
|
||||
"SCA", "DAD", "DST", "SWBA",
|
||||
"DPSZ", "DPIC", "DCIM", "SAM",
|
||||
"CLA", "CLL", "CMA", "CML", "IAC", /* encode only */
|
||||
"CLA", "CLL", "CMA", "CML", "IAC", /* encode only */
|
||||
"CLA", "OAS", "HLT",
|
||||
"CLA", "MQA", "MQL",
|
||||
NULL, NULL, NULL, NULL, /* decode only */
|
||||
NULL };
|
||||
NULL, NULL, NULL, NULL, /* decode only */
|
||||
NULL
|
||||
};
|
||||
|
||||
static const int32 opc_val[] = {
|
||||
06000+I_NPN, 06001+I_NPN, 06002+I_NPN, 06003+I_NPN,
|
||||
@@ -328,42 +347,45 @@ static const int32 opc_val[] = {
|
||||
07600+I_OP2, 07404+I_OP2, 07402+I_OP2,
|
||||
07601+I_OP3, 07501+I_OP3, 07421+I_OP3,
|
||||
07000+I_OP1, 07400+I_OP2, 07401+I_OP3, 017401+I_OP3,
|
||||
-1 };
|
||||
|
||||
-1
|
||||
};
|
||||
|
||||
/* Operate decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
inst = mask bits
|
||||
class = instruction class code
|
||||
sp = space needed?
|
||||
*of = output stream
|
||||
inst = mask bits
|
||||
class = instruction class code
|
||||
sp = space needed?
|
||||
Outputs:
|
||||
status = space needed
|
||||
status = space needed
|
||||
*/
|
||||
|
||||
int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp)
|
||||
{
|
||||
int32 i, j;
|
||||
|
||||
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((j == class) && (opc_val[i] & inst)) { /* same class? */
|
||||
inst = inst & ~opc_val[i]; /* mask bit set? */
|
||||
fprintf (of, (sp? " %s": "%s"), opcode[i]);
|
||||
sp = 1; } }
|
||||
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((j == class) && (opc_val[i] & inst)) { /* same class? */
|
||||
inst = inst & ~opc_val[i]; /* mask bit set? */
|
||||
fprintf (of, (sp? " %s": "%s"), opcode[i]);
|
||||
sp = 1;
|
||||
}
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
/* Symbolic decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to data
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to data
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
return = status code
|
||||
return = status code
|
||||
*/
|
||||
|
||||
#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
|
||||
@@ -371,79 +393,93 @@ return sp;
|
||||
#define TSSTOASC(x) ((x) + 040)
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 cflag, i, j, sp, inst, disp;
|
||||
extern int32 emode;
|
||||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
inst = val[0];
|
||||
if (sw & SWMASK ('A')) { /* ASCII? */
|
||||
if (inst > 0377) return SCPE_ARG;
|
||||
fprintf (of, FMTASC (inst & 0177));
|
||||
return SCPE_OK; }
|
||||
if (sw & SWMASK ('C')) { /* characters? */
|
||||
fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));
|
||||
fprintf (of, "%c", SIXTOASC (inst & 077));
|
||||
return SCPE_OK; }
|
||||
if (sw & SWMASK ('T')) { /* TSS8 packed? */
|
||||
fprintf (of, "%c", TSSTOASC ((inst >> 6) & 077));
|
||||
fprintf (of, "%c", TSSTOASC (inst & 077));
|
||||
return SCPE_OK; }
|
||||
if (sw & SWMASK ('A')) { /* ASCII? */
|
||||
if (inst > 0377) return SCPE_ARG;
|
||||
fprintf (of, FMTASC (inst & 0177));
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (sw & SWMASK ('C')) { /* characters? */
|
||||
fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));
|
||||
fprintf (of, "%c", SIXTOASC (inst & 077));
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (sw & SWMASK ('T')) { /* TSS8 packed? */
|
||||
fprintf (of, "%c", TSSTOASC ((inst >> 6) & 077));
|
||||
fprintf (of, "%c", TSSTOASC (inst & 077));
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
|
||||
|
||||
|
||||
/* Instruction decode */
|
||||
|
||||
inst = val[0] | ((emode & 1) << 12); /* include EAE mode */
|
||||
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 017777) == (inst & masks[j])) { /* match? */
|
||||
inst = val[0] | ((emode & 1) << 12); /* include EAE mode */
|
||||
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 017777) == (inst & masks[j])) { /* match? */
|
||||
|
||||
switch (j) { /* case on class */
|
||||
case I_V_NPN: /* no operands */
|
||||
fprintf (of, "%s", opcode[i]); /* opcode */
|
||||
break;
|
||||
case I_V_FLD: /* field change */
|
||||
fprintf (of, "%s %-o", opcode[i], (inst >> 3) & 07);
|
||||
break;
|
||||
case I_V_MRF: /* mem ref */
|
||||
disp = inst & 0177; /* displacement */
|
||||
fprintf (of, "%s%s", opcode[i], ((inst & 00400)? " I ": " "));
|
||||
if (inst & 0200) { /* current page? */
|
||||
if (cflag) fprintf (of, "%-o", (addr & 07600) | disp);
|
||||
else fprintf (of, "C %-o", disp); }
|
||||
else fprintf (of, "%-o", disp); /* page zero */
|
||||
break;
|
||||
case I_V_IOT: /* IOT */
|
||||
fprintf (of, "%s %-o", opcode[i], inst & 0777);
|
||||
break;
|
||||
case I_V_OP1: /* operate group 1 */
|
||||
sp = fprint_opr (of, inst & 0361, j, 0);
|
||||
if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);
|
||||
break;
|
||||
case I_V_OP2: /* operate group 2 */
|
||||
if (opcode[i]) fprintf (of, "%s", opcode[i]); /* skips */
|
||||
fprint_opr (of, inst & 0206, j, opcode[i] != NULL);
|
||||
break;
|
||||
case I_V_OP3: /* operate group 3 */
|
||||
sp = fprint_opr (of, inst & 0320, j, 0);
|
||||
if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);
|
||||
break; } /* end case */
|
||||
return SCPE_OK; } /* end if */
|
||||
} /* end for */
|
||||
switch (j) { /* case on class */
|
||||
|
||||
case I_V_NPN: /* no operands */
|
||||
fprintf (of, "%s", opcode[i]); /* opcode */
|
||||
break;
|
||||
|
||||
case I_V_FLD: /* field change */
|
||||
fprintf (of, "%s %-o", opcode[i], (inst >> 3) & 07);
|
||||
break;
|
||||
|
||||
case I_V_MRF: /* mem ref */
|
||||
disp = inst & 0177; /* displacement */
|
||||
fprintf (of, "%s%s", opcode[i], ((inst & 00400)? " I ": " "));
|
||||
if (inst & 0200) { /* current page? */
|
||||
if (cflag) fprintf (of, "%-o", (addr & 07600) | disp);
|
||||
else fprintf (of, "C %-o", disp);
|
||||
}
|
||||
else fprintf (of, "%-o", disp); /* page zero */
|
||||
break;
|
||||
|
||||
case I_V_IOT: /* IOT */
|
||||
fprintf (of, "%s %-o", opcode[i], inst & 0777);
|
||||
break;
|
||||
|
||||
case I_V_OP1: /* operate group 1 */
|
||||
sp = fprint_opr (of, inst & 0361, j, 0);
|
||||
if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);
|
||||
break;
|
||||
|
||||
case I_V_OP2: /* operate group 2 */
|
||||
if (opcode[i]) fprintf (of, "%s", opcode[i]); /* skips */
|
||||
fprint_opr (of, inst & 0206, j, opcode[i] != NULL);
|
||||
break;
|
||||
|
||||
case I_V_OP3: /* operate group 3 */
|
||||
sp = fprint_opr (of, inst & 0320, j, 0);
|
||||
if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);
|
||||
break;
|
||||
} /* end case */
|
||||
|
||||
return SCPE_OK;
|
||||
} /* end if */
|
||||
} /* end for */
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
|
||||
/* Symbolic input
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*uptr = pointer to unit
|
||||
*val = pointer to output values
|
||||
sw = switches
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*uptr = pointer to unit
|
||||
*val = pointer to output values
|
||||
sw = switches
|
||||
Outputs:
|
||||
status = error status
|
||||
status = error status
|
||||
*/
|
||||
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
@@ -453,80 +489,96 @@ t_stat r;
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = (t_value) cptr[0] | 0200;
|
||||
return SCPE_OK; }
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = (t_value) cptr[0] | 0200;
|
||||
return SCPE_OK;
|
||||
}
|
||||
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = (((t_value) cptr[0] & 077) << 6) |
|
||||
((t_value) cptr[1] & 077);
|
||||
return SCPE_OK; }
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = (((t_value) cptr[0] & 077) << 6) |
|
||||
((t_value) cptr[1] & 077);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if ((sw & SWMASK ('T')) || ((*cptr == '"') && cptr++)) { /* TSS8 string? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = (((t_value) (cptr[0] - 040) & 077) << 6) |
|
||||
((t_value) (cptr[1] - 040) & 077);
|
||||
return SCPE_OK; }
|
||||
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = (((t_value) (cptr[0] - 040) & 077) << 6) |
|
||||
((t_value) (cptr[1] - 040) & 077);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Instruction parse */
|
||||
|
||||
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;
|
||||
val[0] = opc_val[i] & 07777; /* get value */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
val[0] = opc_val[i] & 07777; /* get value */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
|
||||
switch (j) { /* case on class */
|
||||
case I_V_IOT: /* IOT */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get dev+pulse */
|
||||
d = get_uint (gbuf, 8, 0777, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | d;
|
||||
break;
|
||||
case I_V_FLD: /* field */
|
||||
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
|
||||
cptr = get_glyph (cptr, gbuf, 0)) {
|
||||
for (i = 0; (opcode[i] != NULL) &&
|
||||
(strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
if (opcode[i] != NULL) {
|
||||
k = (opc_val[i] >> I_V_FL) & I_M_FL;
|
||||
if (k != j) return SCPE_ARG;
|
||||
val[0] = val[0] | (opc_val[i] & 07777); }
|
||||
else {
|
||||
d = get_uint (gbuf, 8, 07, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << 3);
|
||||
break; } }
|
||||
break;
|
||||
case I_V_MRF: /* mem ref */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next field */
|
||||
if (strcmp (gbuf, "I") == 0) { /* indirect? */
|
||||
val[0] = val[0] | 0400;
|
||||
cptr = get_glyph (cptr, gbuf, 0); }
|
||||
if ((k = (strcmp (gbuf, "C") == 0)) || (strcmp (gbuf, "Z") == 0)) {
|
||||
cptr = get_glyph (cptr, gbuf, 0);
|
||||
d = get_uint (gbuf, 8, 0177, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | d | (k? 0200: 0); }
|
||||
else {
|
||||
d = get_uint (gbuf, 8, 07777, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (d <= 0177) val[0] = val[0] | d;
|
||||
else if (cflag && (((addr ^ d) & 07600) == 0))
|
||||
val[0] = val[0] | (d & 0177) | 0200;
|
||||
else return SCPE_ARG; }
|
||||
break;
|
||||
case I_V_NPN: case I_V_OP1: case I_V_OP2: case I_V_OP3: /* operates */
|
||||
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
|
||||
cptr = get_glyph (cptr, gbuf, 0)) {
|
||||
for (i = 0; (opcode[i] != NULL) &&
|
||||
(strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
k = opc_val[i] & 07777;
|
||||
if ((opcode[i] == NULL) || (((k ^ val[0]) & 07000) != 0))
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | k; }
|
||||
break; } /* end case */
|
||||
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
|
||||
switch (j) { /* case on class */
|
||||
|
||||
case I_V_IOT: /* IOT */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get dev+pulse */
|
||||
d = get_uint (gbuf, 8, 0777, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | d;
|
||||
break;
|
||||
|
||||
case I_V_FLD: /* field */
|
||||
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
|
||||
cptr = get_glyph (cptr, gbuf, 0)) {
|
||||
for (i = 0; (opcode[i] != NULL) &&
|
||||
(strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
if (opcode[i] != NULL) {
|
||||
k = (opc_val[i] >> I_V_FL) & I_M_FL;
|
||||
if (k != j) return SCPE_ARG;
|
||||
val[0] = val[0] | (opc_val[i] & 07777);
|
||||
}
|
||||
else {
|
||||
d = get_uint (gbuf, 8, 07, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case I_V_MRF: /* mem ref */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next field */
|
||||
if (strcmp (gbuf, "I") == 0) { /* indirect? */
|
||||
val[0] = val[0] | 0400;
|
||||
cptr = get_glyph (cptr, gbuf, 0);
|
||||
}
|
||||
if ((k = (strcmp (gbuf, "C") == 0)) || (strcmp (gbuf, "Z") == 0)) {
|
||||
cptr = get_glyph (cptr, gbuf, 0);
|
||||
d = get_uint (gbuf, 8, 0177, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | d | (k? 0200: 0);
|
||||
}
|
||||
else {
|
||||
d = get_uint (gbuf, 8, 07777, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (d <= 0177) val[0] = val[0] | d;
|
||||
else if (cflag && (((addr ^ d) & 07600) == 0))
|
||||
val[0] = val[0] | (d & 0177) | 0200;
|
||||
else return SCPE_ARG;
|
||||
}
|
||||
break;
|
||||
|
||||
case I_V_NPN: case I_V_OP1: case I_V_OP2: case I_V_OP3: /* operates */
|
||||
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
|
||||
cptr = get_glyph (cptr, gbuf, 0)) {
|
||||
for (i = 0; (opcode[i] != NULL) &&
|
||||
(strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
k = opc_val[i] & 07777;
|
||||
if ((opcode[i] == NULL) || (((k ^ val[0]) & 07000) != 0))
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | k;
|
||||
}
|
||||
break;
|
||||
} /* end case */
|
||||
|
||||
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
1051
PDP8/pdp8_td.c
1051
PDP8/pdp8_td.c
File diff suppressed because it is too large
Load Diff
155
PDP8/pdp8_tsc.c
155
PDP8/pdp8_tsc.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_tsc.c: PDP-8 ETOS timesharing option board (TSC8-75)
|
||||
|
||||
Copyright (c) 2003-2004, Robert M Supnik
|
||||
Copyright (c) 2003-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,46 +19,46 @@
|
||||
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 module is based on Bernhard Baehr's PDP-8/E simulator
|
||||
|
||||
PDP-8/E Simulator Source Code
|
||||
PDP-8/E Simulator Source Code
|
||||
|
||||
Copyright ) 2001-2003 Bernhard Baehr
|
||||
Copyright ) 2001-2003 Bernhard Baehr
|
||||
|
||||
TSC8iots.c - IOTs for the TSC8-75 Board plugin
|
||||
TSC8iots.c - IOTs for the TSC8-75 Board plugin
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
tsc TSC8-75 option board
|
||||
tsc TSC8-75 option board
|
||||
*/
|
||||
|
||||
#include "pdp8_defs.h"
|
||||
|
||||
extern int32 int_req;
|
||||
extern int32 SF;
|
||||
extern int32 tsc_ir; /* "ERIOT" */
|
||||
extern int32 tsc_pc; /* "ERTB" */
|
||||
extern int32 tsc_cdf; /* "ECDF" */
|
||||
extern int32 tsc_enb; /* enable */
|
||||
extern int32 tsc_ir; /* "ERIOT" */
|
||||
extern int32 tsc_pc; /* "ERTB" */
|
||||
extern int32 tsc_cdf; /* "ECDF" */
|
||||
extern int32 tsc_enb; /* enable */
|
||||
|
||||
#define UNIT_V_SN699 (UNIT_V_UF + 0) /* SN 699 or above */
|
||||
#define UNIT_SN699 (1 << UNIT_V_SN699)
|
||||
#define UNIT_V_SN699 (UNIT_V_UF + 0) /* SN 699 or above */
|
||||
#define UNIT_SN699 (1 << UNIT_V_SN699)
|
||||
|
||||
DEVICE tsc_dev;
|
||||
int32 tsc (int32 IR, int32 AC);
|
||||
@@ -66,9 +66,9 @@ t_stat tsc_reset (DEVICE *dptr);
|
||||
|
||||
/* TSC data structures
|
||||
|
||||
tsc_dev TSC device descriptor
|
||||
tsc_unit TSC unit descriptor
|
||||
tsc_reg TSC register list
|
||||
tsc_dev TSC device descriptor
|
||||
tsc_unit TSC unit descriptor
|
||||
tsc_reg TSC register list
|
||||
*/
|
||||
|
||||
DIB tsc_dib = { DEV_TSC, 1, { &tsc } };
|
||||
@@ -76,57 +76,72 @@ DIB tsc_dib = { DEV_TSC, 1, { &tsc } };
|
||||
UNIT tsc_unit = { UDATA (NULL, UNIT_SN699, 0) };
|
||||
|
||||
REG tsc_reg[] = {
|
||||
{ ORDATA (IR, tsc_ir, 12) },
|
||||
{ ORDATA (PC, tsc_pc, 12) },
|
||||
{ FLDATA (CDF, tsc_cdf, 0) },
|
||||
{ FLDATA (ENB, tsc_enb, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_TSC) },
|
||||
{ NULL } };
|
||||
{ ORDATA (IR, tsc_ir, 12) },
|
||||
{ ORDATA (PC, tsc_pc, 12) },
|
||||
{ FLDATA (CDF, tsc_cdf, 0) },
|
||||
{ FLDATA (ENB, tsc_enb, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_TSC) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB tsc_mod[] = {
|
||||
{ UNIT_SN699, UNIT_SN699, "ESME", "ESME", NULL },
|
||||
{ UNIT_SN699, 0, "no ESME", "NOESME", NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_SN699, UNIT_SN699, "ESME", "ESME", NULL },
|
||||
{ UNIT_SN699, 0, "no ESME", "NOESME", NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE tsc_dev = {
|
||||
"TSC", &tsc_unit, tsc_reg, tsc_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tsc_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tsc_dib, DEV_DISABLE | DEV_DIS };
|
||||
|
||||
"TSC", &tsc_unit, tsc_reg, tsc_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tsc_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tsc_dib, DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* IOT routine */
|
||||
|
||||
int32 tsc (int32 IR, int32 AC)
|
||||
{
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 0: /* ETDS */
|
||||
tsc_enb = 0; /* disable int req */
|
||||
int_req = int_req & ~INT_TSC; /* clear flag */
|
||||
break;
|
||||
case 1: /* ESKP */
|
||||
return (int_req & INT_TSC)? IOT_SKP + AC: AC; /* skip on int req */
|
||||
case 2: /* ECTF */
|
||||
int_req = int_req & ~INT_TSC; /* clear int req */
|
||||
break;
|
||||
case 3: /* ECDF */
|
||||
AC = AC | ((tsc_ir >> 3) & 07); /* read "ERIOT"<6:8> */
|
||||
if (tsc_cdf) AC = AC | IOT_SKP; /* if cdf, skip */
|
||||
tsc_cdf = 0;
|
||||
break;
|
||||
case 4: /* ERTB */
|
||||
return tsc_pc;
|
||||
case 5: /* ESME */
|
||||
if (tsc_unit.flags & UNIT_SN699) { /* enabled? */
|
||||
if (tsc_cdf && ((tsc_ir & 070) >> 3) == (SF & 07)) {
|
||||
AC = AC | IOT_SKP;
|
||||
tsc_cdf = 0; } }
|
||||
break;
|
||||
case 6: /* ERIOT */
|
||||
return tsc_ir;
|
||||
case 7: /* ETEN */
|
||||
tsc_enb = 1;
|
||||
break; } /* end switch */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 0: /* ETDS */
|
||||
tsc_enb = 0; /* disable int req */
|
||||
int_req = int_req & ~INT_TSC; /* clear flag */
|
||||
break;
|
||||
|
||||
case 1: /* ESKP */
|
||||
return (int_req & INT_TSC)? IOT_SKP + AC: AC; /* skip on int req */
|
||||
|
||||
case 2: /* ECTF */
|
||||
int_req = int_req & ~INT_TSC; /* clear int req */
|
||||
break;
|
||||
|
||||
case 3: /* ECDF */
|
||||
AC = AC | ((tsc_ir >> 3) & 07); /* read "ERIOT"<6:8> */
|
||||
if (tsc_cdf) AC = AC | IOT_SKP; /* if cdf, skip */
|
||||
tsc_cdf = 0;
|
||||
break;
|
||||
|
||||
case 4: /* ERTB */
|
||||
return tsc_pc;
|
||||
|
||||
case 5: /* ESME */
|
||||
if (tsc_unit.flags & UNIT_SN699) { /* enabled? */
|
||||
if (tsc_cdf && ((tsc_ir & 070) >> 3) == (SF & 07)) {
|
||||
AC = AC | IOT_SKP;
|
||||
tsc_cdf = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: /* ERIOT */
|
||||
return tsc_ir;
|
||||
|
||||
case 7: /* ETEN */
|
||||
tsc_enb = 1;
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
return AC;
|
||||
}
|
||||
|
||||
|
||||
285
PDP8/pdp8_tt.c
285
PDP8/pdp8_tt.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_tt.c: PDP-8 console terminal simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,30 +19,30 @@
|
||||
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.
|
||||
|
||||
tti,tto KL8E terminal input/output
|
||||
tti,tto KL8E terminal input/output
|
||||
|
||||
28-May-04 RMS Removed SET TTI CTRL-C
|
||||
29-Dec-03 RMS Added console output backpressure support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
02-Mar-02 RMS Added SET TTI CTRL-C
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Added 7B/8B support
|
||||
04-Oct-02 RMS Added DIBs, device number support
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
28-May-04 RMS Removed SET TTI CTRL-C
|
||||
29-Dec-03 RMS Added console output backpressure support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
02-Mar-02 RMS Added SET TTI CTRL-C
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Added 7B/8B support
|
||||
04-Oct-02 RMS Added DIBs, device number support
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
*/
|
||||
|
||||
#include "pdp8_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)
|
||||
|
||||
extern int32 int_req, int_enable, dev_done, stop_inst;
|
||||
|
||||
@@ -53,13 +53,13 @@ t_stat tto_svc (UNIT *uptr);
|
||||
t_stat tti_reset (DEVICE *dptr);
|
||||
t_stat tto_reset (DEVICE *dptr);
|
||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
|
||||
/* TTI data structures
|
||||
|
||||
tti_dev TTI device descriptor
|
||||
tti_unit TTI unit descriptor
|
||||
tti_reg TTI register list
|
||||
tti_mod TTI modifiers list
|
||||
tti_dev TTI device descriptor
|
||||
tti_unit TTI unit descriptor
|
||||
tti_reg TTI register list
|
||||
tti_mod TTI modifiers list
|
||||
*/
|
||||
|
||||
DIB tti_dib = { DEV_TTI, 1, { &tti } };
|
||||
@@ -67,34 +67,37 @@ DIB tti_dib = { DEV_TTI, 1, { &tti } };
|
||||
UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT };
|
||||
|
||||
REG tti_reg[] = {
|
||||
{ ORDATA (BUF, tti_unit.buf, 8) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_TTI) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_TTI) },
|
||||
{ FLDATA (INT, int_req, INT_V_TTI) },
|
||||
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (UC, tti_unit.flags, UNIT_V_KSR), REG_HRO },
|
||||
{ NULL } };
|
||||
{ ORDATA (BUF, tti_unit.buf, 8) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_TTI) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_TTI) },
|
||||
{ FLDATA (INT, int_req, INT_V_TTI) },
|
||||
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (UC, tti_unit.flags, UNIT_V_KSR), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB tti_mod[] = {
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE tti_dev = {
|
||||
"TTI", &tti_unit, tti_reg, tti_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tti_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tti_dib, 0 };
|
||||
"TTI", &tti_unit, tti_reg, tti_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tti_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tti_dib, 0
|
||||
};
|
||||
|
||||
/* TTO data structures
|
||||
|
||||
tto_dev TTO device descriptor
|
||||
tto_unit TTO unit descriptor
|
||||
tto_reg TTO register list
|
||||
tto_dev TTO device descriptor
|
||||
tto_unit TTO unit descriptor
|
||||
tto_reg TTO register list
|
||||
*/
|
||||
|
||||
DIB tto_dib = { DEV_TTO, 1, { &tto } };
|
||||
@@ -102,56 +105,66 @@ DIB tto_dib = { DEV_TTO, 1, { &tto } };
|
||||
UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT };
|
||||
|
||||
REG tto_reg[] = {
|
||||
{ ORDATA (BUF, tto_unit.buf, 8) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_TTO) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_TTO) },
|
||||
{ FLDATA (INT, int_req, INT_V_TTO) },
|
||||
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
|
||||
{ NULL } };
|
||||
{ ORDATA (BUF, tto_unit.buf, 8) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_TTO) },
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_TTO) },
|
||||
{ FLDATA (INT, int_req, INT_V_TTO) },
|
||||
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB tto_mod[] = {
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ 0 } };
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE tto_dev = {
|
||||
"TTO", &tto_unit, tto_reg, tto_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tto_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tto_dib, 0 };
|
||||
|
||||
"TTO", &tto_unit, tto_reg, tto_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tto_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tto_dib, 0
|
||||
};
|
||||
|
||||
/* Terminal input: IOT routine */
|
||||
|
||||
int32 tti (int32 IR, int32 AC)
|
||||
{
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 0: /* KCF */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear flag */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
return AC;
|
||||
case 1: /* KSF */
|
||||
return (dev_done & INT_TTI)? IOT_SKP + AC: AC;
|
||||
case 2: /* KCC */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear flag */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
return 0; /* clear AC */
|
||||
case 4: /* KRS */
|
||||
return (AC | tti_unit.buf); /* return buffer */
|
||||
case 5: /* KIE */
|
||||
if (AC & 1) int_enable = int_enable | (INT_TTI+INT_TTO);
|
||||
else int_enable = int_enable & ~(INT_TTI+INT_TTO);
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
case 6: /* KRB */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear flag */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
return (tti_unit.buf); /* return buffer */
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 0: /* KCF */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear flag */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
return AC;
|
||||
|
||||
case 1: /* KSF */
|
||||
return (dev_done & INT_TTI)? IOT_SKP + AC: AC;
|
||||
|
||||
case 2: /* KCC */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear flag */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
return 0; /* clear AC */
|
||||
|
||||
case 4: /* KRS */
|
||||
return (AC | tti_unit.buf); /* return buffer */
|
||||
|
||||
case 5: /* KIE */
|
||||
if (AC & 1) int_enable = int_enable | (INT_TTI+INT_TTO);
|
||||
else int_enable = int_enable & ~(INT_TTI+INT_TTO);
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
|
||||
case 6: /* KRB */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear flag */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
return (tti_unit.buf); /* return buffer */
|
||||
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
} /* end switch */
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
@@ -160,17 +173,18 @@ t_stat tti_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */
|
||||
else if (tti_unit.flags & UNIT_KSR) { /* KSR? */
|
||||
c = c & 0177;
|
||||
if (islower (c)) c = toupper (c);
|
||||
tti_unit.buf = c | 0200; } /* add TTY bit */
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */
|
||||
else if (tti_unit.flags & UNIT_KSR) { /* KSR? */
|
||||
c = c & 0177;
|
||||
if (islower (c)) c = toupper (c);
|
||||
tti_unit.buf = c | 0200; /* add TTY bit */
|
||||
}
|
||||
else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177);
|
||||
tti_unit.pos = tti_unit.pos + 1;
|
||||
dev_done = dev_done | INT_TTI; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
dev_done = dev_done | INT_TTI; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -179,39 +193,46 @@ return SCPE_OK;
|
||||
t_stat tti_reset (DEVICE *dptr)
|
||||
{
|
||||
tti_unit.buf = 0;
|
||||
dev_done = dev_done & ~INT_TTI; /* clear done, int */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
int_enable = int_enable | INT_TTI; /* set enable */
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||
int_enable = int_enable | INT_TTI; /* set enable */
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Terminal output: IOT routine */
|
||||
|
||||
int32 tto (int32 IR, int32 AC)
|
||||
{
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
case 0: /* TLF */
|
||||
dev_done = dev_done | INT_TTO; /* set flag */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
case 1: /* TSF */
|
||||
return (dev_done & INT_TTO)? IOT_SKP + AC: AC;
|
||||
case 2: /* TCF */
|
||||
dev_done = dev_done & ~INT_TTO; /* clear flag */
|
||||
int_req = int_req & ~INT_TTO; /* clear int req */
|
||||
return AC;
|
||||
case 5: /* SPI */
|
||||
return (int_req & (INT_TTI+INT_TTO))? IOT_SKP + AC: AC;
|
||||
case 6: /* TLS */
|
||||
dev_done = dev_done & ~INT_TTO; /* clear flag */
|
||||
int_req = int_req & ~INT_TTO; /* clear int req */
|
||||
case 4: /* TPC */
|
||||
sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
|
||||
tto_unit.buf = AC; /* load buffer */
|
||||
return AC;
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 0: /* TLF */
|
||||
dev_done = dev_done | INT_TTO; /* set flag */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return AC;
|
||||
|
||||
case 1: /* TSF */
|
||||
return (dev_done & INT_TTO)? IOT_SKP + AC: AC;
|
||||
|
||||
case 2: /* TCF */
|
||||
dev_done = dev_done & ~INT_TTO; /* clear flag */
|
||||
int_req = int_req & ~INT_TTO; /* clear int req */
|
||||
return AC;
|
||||
|
||||
case 5: /* SPI */
|
||||
return (int_req & (INT_TTI+INT_TTO))? IOT_SKP + AC: AC;
|
||||
|
||||
case 6: /* TLS */
|
||||
dev_done = dev_done & ~INT_TTO; /* clear flag */
|
||||
int_req = int_req & ~INT_TTO; /* clear int req */
|
||||
case 4: /* TPC */
|
||||
sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
|
||||
tto_unit.buf = AC; /* load buffer */
|
||||
return AC;
|
||||
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
} /* end switch */
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
@@ -221,15 +242,17 @@ t_stat tto_svc (UNIT *uptr)
|
||||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
if (tto_unit.flags & UNIT_KSR) { /* UC only? */
|
||||
c = tto_unit.buf & 0177;
|
||||
if (islower (c)) c = toupper (c); }
|
||||
if (tto_unit.flags & UNIT_KSR) { /* UC only? */
|
||||
c = tto_unit.buf & 0177;
|
||||
if (islower (c)) c = toupper (c);
|
||||
}
|
||||
else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177);
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output char; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } /* if !stall, report */
|
||||
dev_done = dev_done | INT_TTO; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output char; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); /* if !stall, report */
|
||||
}
|
||||
dev_done = dev_done | INT_TTO; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
tto_unit.pos = tto_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -239,10 +262,10 @@ return SCPE_OK;
|
||||
t_stat tto_reset (DEVICE *dptr)
|
||||
{
|
||||
tto_unit.buf = 0;
|
||||
dev_done = dev_done & ~INT_TTO; /* clear done, int */
|
||||
dev_done = dev_done & ~INT_TTO; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTO;
|
||||
int_enable = int_enable | INT_TTO; /* set enable */
|
||||
sim_cancel (&tto_unit); /* deactivate unit */
|
||||
int_enable = int_enable | INT_TTO; /* set enable */
|
||||
sim_cancel (&tto_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
471
PDP8/pdp8_ttx.c
471
PDP8/pdp8_ttx.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_ttx.c: PDP-8 additional terminals simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-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,22 +19,25 @@
|
||||
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.
|
||||
|
||||
ttix,ttox PT08/KL8JA terminal input/output
|
||||
ttix,ttox PT08/KL8JA terminal input/output
|
||||
|
||||
05-Jan-04 RMS Revised for tmxr library changes
|
||||
09-May-03 RMS Added network device flag
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
22-Dec-02 RMS Added break support
|
||||
02-Nov-02 RMS Added 7B/8B support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
22-Aug-02 RMS Updated for changes to sim_tmxr.c
|
||||
06-Jan-02 RMS Added device enable/disable support
|
||||
30-Dec-01 RMS Complete rebuild
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
29-Jun-05 RMS Added SET TTOXn DISCONNECT
|
||||
Fixed bug in SET LOG/NOLOG
|
||||
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
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
22-Dec-02 RMS Added break support
|
||||
02-Nov-02 RMS Added 7B/8B support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
22-Aug-02 RMS Updated for changes to sim_tmxr.c
|
||||
06-Jan-02 RMS Added device enable/disable support
|
||||
30-Dec-01 RMS Complete rebuild
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
|
||||
This module implements four individual serial interfaces similar in function
|
||||
to the console. These interfaces are mapped to Telnet based connections as
|
||||
@@ -47,23 +50,23 @@
|
||||
#include "sim_tmxr.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define TTX_LINES 4
|
||||
#define TTX_MASK (TTX_LINES - 1)
|
||||
#define TTX_LINES 4
|
||||
#define TTX_MASK (TTX_LINES - 1)
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_UC (UNIT_V_UF + 1) /* upper case */
|
||||
#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) /* upper case */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
|
||||
#define TTX_GETLN(x) (((x) >> 4) & TTX_MASK)
|
||||
#define TTX_GETLN(x) (((x) >> 4) & TTX_MASK)
|
||||
|
||||
extern int32 int_req, int_enable, dev_done, stop_inst;
|
||||
|
||||
uint8 ttix_buf[TTX_LINES] = { 0 }; /* input buffers */
|
||||
uint8 ttox_buf[TTX_LINES] = { 0 }; /* output buffers */
|
||||
int32 ttx_tps = 100; /* polls per second */
|
||||
TMLN ttx_ldsc[TTX_LINES] = { 0 }; /* line descriptors */
|
||||
TMXR ttx_desc = { TTX_LINES, 0, 0, ttx_ldsc }; /* mux descriptor */
|
||||
uint8 ttix_buf[TTX_LINES] = { 0 }; /* input buffers */
|
||||
uint8 ttox_buf[TTX_LINES] = { 0 }; /* output buffers */
|
||||
int32 ttx_tps = 100; /* polls per second */
|
||||
TMLN ttx_ldsc[TTX_LINES] = { 0 }; /* line descriptors */
|
||||
TMXR ttx_desc = { TTX_LINES, 0, 0, ttx_ldsc }; /* mux descriptor */
|
||||
|
||||
DEVICE ttix_dev, ttox_dev;
|
||||
int32 ttix (int32 IR, int32 AC);
|
||||
@@ -77,121 +80,139 @@ t_stat ttx_detach (UNIT *uptr);
|
||||
t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
void ttx_enbdis (int32 dis);
|
||||
|
||||
|
||||
/* TTIx data structures
|
||||
|
||||
ttix_dev TTIx device descriptor
|
||||
ttix_unit TTIx unit descriptor
|
||||
ttix_reg TTIx register list
|
||||
ttix_mod TTIx modifiers list
|
||||
ttix_dev TTIx device descriptor
|
||||
ttix_unit TTIx unit descriptor
|
||||
ttix_reg TTIx register list
|
||||
ttix_mod TTIx modifiers list
|
||||
*/
|
||||
|
||||
DIB ttix_dib = { DEV_KJ8, 8,
|
||||
{ &ttix, &ttox, &ttix, &ttox, &ttix, &ttox, &ttix, &ttox } };
|
||||
{ &ttix, &ttox, &ttix, &ttox, &ttix, &ttox, &ttix, &ttox } };
|
||||
|
||||
UNIT ttix_unit = { UDATA (&ttix_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT };
|
||||
|
||||
REG ttix_reg[] = {
|
||||
{ BRDATA (BUF, ttix_buf, 8, 8, TTX_LINES) },
|
||||
{ GRDATA (DONE, dev_done, 8, TTX_LINES, INT_V_TTI1) },
|
||||
{ GRDATA (ENABLE, int_enable, 8, TTX_LINES, INT_V_TTI1) },
|
||||
{ GRDATA (INT, int_req, 8, TTX_LINES, INT_V_TTI1) },
|
||||
{ DRDATA (TIME, ttix_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, ttx_tps, 10), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (DEVNUM, ttix_dib.dev, 6), REG_HRO },
|
||||
{ NULL } };
|
||||
{ BRDATA (BUF, ttix_buf, 8, 8, TTX_LINES) },
|
||||
{ GRDATA (DONE, dev_done, 8, TTX_LINES, INT_V_TTI1) },
|
||||
{ GRDATA (ENABLE, int_enable, 8, TTX_LINES, INT_V_TTI1) },
|
||||
{ GRDATA (INT, int_req, 8, TTX_LINES, INT_V_TTI1) },
|
||||
{ DRDATA (TIME, ttix_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, ttx_tps, 10), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (DEVNUM, ttix_dib.dev, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ttix_mod[] = {
|
||||
{ UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &ttx_summ },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &ttx_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &ttx_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &ttx_show, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
|
||||
&tmxr_set_log, &tmxr_show_log, &ttx_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
|
||||
&tmxr_set_nolog, NULL, &ttx_desc },
|
||||
{ 0 } };
|
||||
{ UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &ttx_summ },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &ttx_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &ttx_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &ttx_show, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ttix_dev = {
|
||||
"TTIX", &ttix_unit, ttix_reg, ttix_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
&tmxr_ex, &tmxr_dep, &ttix_reset,
|
||||
NULL, &ttx_attach, &ttx_detach,
|
||||
&ttix_dib, DEV_NET | DEV_DISABLE };
|
||||
"TTIX", &ttix_unit, ttix_reg, ttix_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
&tmxr_ex, &tmxr_dep, &ttix_reset,
|
||||
NULL, &ttx_attach, &ttx_detach,
|
||||
&ttix_dib, DEV_NET | DEV_DISABLE
|
||||
};
|
||||
|
||||
/* TTOx data structures
|
||||
|
||||
ttox_dev TTOx device descriptor
|
||||
ttox_unit TTOx unit descriptor
|
||||
ttox_reg TTOx register list
|
||||
ttox_dev TTOx device descriptor
|
||||
ttox_unit TTOx unit descriptor
|
||||
ttox_reg TTOx register list
|
||||
*/
|
||||
|
||||
UNIT ttox_unit[] = {
|
||||
{ UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT } };
|
||||
{ UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG ttox_reg[] = {
|
||||
{ BRDATA (BUF, ttox_buf, 8, 8, TTX_LINES) },
|
||||
{ GRDATA (DONE, dev_done, 8, TTX_LINES, INT_V_TTO1) },
|
||||
{ GRDATA (ENABLE, int_enable, 8, TTX_LINES, INT_V_TTO1) },
|
||||
{ GRDATA (INT, int_req, 8, TTX_LINES, INT_V_TTO1) },
|
||||
{ URDATA (TIME, ttox_unit[0].wait, 10, 24, 0,
|
||||
TTX_LINES, PV_LEFT) },
|
||||
{ NULL } };
|
||||
{ BRDATA (BUF, ttox_buf, 8, 8, TTX_LINES) },
|
||||
{ GRDATA (DONE, dev_done, 8, TTX_LINES, INT_V_TTO1) },
|
||||
{ GRDATA (ENABLE, int_enable, 8, TTX_LINES, INT_V_TTO1) },
|
||||
{ GRDATA (INT, int_req, 8, TTX_LINES, INT_V_TTO1) },
|
||||
{ URDATA (TIME, ttox_unit[0].wait, 10, 24, 0,
|
||||
TTX_LINES, PV_LEFT) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ttox_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 },
|
||||
{ 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 },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &ttx_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
|
||||
&tmxr_set_log, &tmxr_show_log, &ttx_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
|
||||
&tmxr_set_nolog, NULL, &ttx_desc },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ttox_dev = {
|
||||
"TTOX", ttox_unit, ttox_reg, ttox_mod,
|
||||
4, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ttox_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_DISABLE };
|
||||
|
||||
"TTOX", ttox_unit, ttox_reg, ttox_mod,
|
||||
4, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ttox_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* Terminal input: IOT routine */
|
||||
|
||||
int32 ttix (int32 inst, int32 AC)
|
||||
{
|
||||
int32 pulse = inst & 07; /* IOT pulse */
|
||||
int32 ln = TTX_GETLN (inst); /* line # */
|
||||
int32 itti = (INT_TTI1 << ln); /* rx intr */
|
||||
int32 itto = (INT_TTO1 << ln); /* tx intr */
|
||||
int32 pulse = inst & 07; /* IOT pulse */
|
||||
int32 ln = TTX_GETLN (inst); /* line # */
|
||||
int32 itti = (INT_TTI1 << ln); /* rx intr */
|
||||
int32 itto = (INT_TTO1 << ln); /* tx intr */
|
||||
|
||||
switch (pulse) { /* case IR<9:11> */
|
||||
|
||||
case 0: /* KCF */
|
||||
dev_done = dev_done & ~itti; /* clear flag */
|
||||
int_req = int_req & ~itti;
|
||||
break;
|
||||
|
||||
case 1: /* KSF */
|
||||
return (dev_done & itti)? IOT_SKP + AC: AC;
|
||||
|
||||
case 2: /* KCC */
|
||||
dev_done = dev_done & ~itti; /* clear flag */
|
||||
int_req = int_req & ~itti;
|
||||
return 0; /* clear AC */
|
||||
|
||||
case 4: /* KRS */
|
||||
return (AC | ttix_buf[ln]); /* return buf */
|
||||
|
||||
case 5: /* KIE */
|
||||
if (AC & 1) int_enable = int_enable | (itti + itto);
|
||||
else int_enable = int_enable & ~(itti + itto);
|
||||
int_req = INT_UPDATE; /* update intr */
|
||||
break;
|
||||
|
||||
case 6: /* KRB */
|
||||
dev_done = dev_done & ~itti; /* clear flag */
|
||||
int_req = int_req & ~itti;
|
||||
return ttix_buf[ln]; /* return buf */
|
||||
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
} /* end switch */
|
||||
|
||||
switch (pulse) { /* case IR<9:11> */
|
||||
case 0: /* KCF */
|
||||
dev_done = dev_done & ~itti; /* clear flag */
|
||||
int_req = int_req & ~itti;
|
||||
break;
|
||||
case 1: /* KSF */
|
||||
return (dev_done & itti)? IOT_SKP + AC: AC;
|
||||
case 2: /* KCC */
|
||||
dev_done = dev_done & ~itti; /* clear flag */
|
||||
int_req = int_req & ~itti;
|
||||
return 0; /* clear AC */
|
||||
case 4: /* KRS */
|
||||
return (AC | ttix_buf[ln]); /* return buf */
|
||||
case 5: /* KIE */
|
||||
if (AC & 1) int_enable = int_enable | (itti + itto);
|
||||
else int_enable = int_enable & ~(itti + itto);
|
||||
int_req = INT_UPDATE; /* update intr */
|
||||
break;
|
||||
case 6: /* KRB */
|
||||
dev_done = dev_done & ~itti; /* clear flag */
|
||||
int_req = int_req & ~itti;
|
||||
return ttix_buf[ln]; /* return buf */
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
|
||||
return AC;
|
||||
}
|
||||
|
||||
@@ -201,24 +222,27 @@ t_stat ttix_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ln, c, temp;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
temp = sim_rtcn_calb (ttx_tps, TMR_TTX); /* calibrate */
|
||||
sim_activate (uptr, temp); /* continue poll */
|
||||
ln = tmxr_poll_conn (&ttx_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? */
|
||||
ttx_ldsc[ln].rcve = 1; } /* rcv enabled */
|
||||
tmxr_poll_rx (&ttx_desc); /* poll for input */
|
||||
for (ln = 0; ln < TTX_LINES; ln++) { /* loop thru lines */
|
||||
if (ttx_ldsc[ln].conn) { /* connected? */
|
||||
if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */
|
||||
if (temp & SCPE_BREAK) c = 0; /* break? */
|
||||
else if (ttox_unit[ln].flags & UNIT_UC) { /* UC? */
|
||||
c = temp & 0177;
|
||||
if (islower (c)) c = toupper (c); }
|
||||
else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
|
||||
ttix_buf[ln] = c;
|
||||
dev_done = dev_done | (INT_TTI1 << ln);
|
||||
int_req = INT_UPDATE; } } }
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
temp = sim_rtcn_calb (ttx_tps, TMR_TTX); /* calibrate */
|
||||
sim_activate (uptr, temp); /* continue poll */
|
||||
ln = tmxr_poll_conn (&ttx_desc); /* look for connect */
|
||||
if (ln >= 0) ttx_ldsc[ln].rcve = 1; /* got one? rcv enb*/
|
||||
tmxr_poll_rx (&ttx_desc); /* poll for input */
|
||||
for (ln = 0; ln < TTX_LINES; ln++) { /* loop thru lines */
|
||||
if (ttx_ldsc[ln].conn) { /* connected? */
|
||||
if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */
|
||||
if (temp & SCPE_BREAK) c = 0; /* break? */
|
||||
else if (ttox_unit[ln].flags & UNIT_UC) { /* UC? */
|
||||
c = temp & 0177;
|
||||
if (islower (c)) c = toupper (c);
|
||||
}
|
||||
else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
|
||||
ttix_buf[ln] = c;
|
||||
dev_done = dev_done | (INT_TTI1 << ln);
|
||||
int_req = INT_UPDATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -228,52 +252,63 @@ t_stat ttix_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 t, ln, itto;
|
||||
|
||||
ttx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
|
||||
if (ttix_unit.flags & UNIT_ATT) { /* if attached, */
|
||||
if (!sim_is_active (&ttix_unit)) {
|
||||
t = sim_rtcn_init (ttix_unit.wait, TMR_TTX);
|
||||
sim_activate (&ttix_unit, t); } } /* activate */
|
||||
else sim_cancel (&ttix_unit); /* else stop */
|
||||
for (ln = 0; ln < TTX_LINES; ln++) { /* for all lines */
|
||||
ttix_buf[ln] = 0; /* clear buf, */
|
||||
itto = (INT_TTI1 << ln); /* interrupt */
|
||||
dev_done = dev_done & ~itto; /* clr done, int */
|
||||
int_req = int_req & ~itto;
|
||||
int_enable = int_enable | itto; } /* set enable */
|
||||
ttx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
|
||||
if (ttix_unit.flags & UNIT_ATT) { /* if attached, */
|
||||
if (!sim_is_active (&ttix_unit)) {
|
||||
t = sim_rtcn_init (ttix_unit.wait, TMR_TTX);
|
||||
sim_activate (&ttix_unit, t); /* activate */
|
||||
}
|
||||
}
|
||||
else sim_cancel (&ttix_unit); /* else stop */
|
||||
for (ln = 0; ln < TTX_LINES; ln++) { /* for all lines */
|
||||
ttix_buf[ln] = 0; /* clear buf, */
|
||||
itto = (INT_TTI1 << ln); /* interrupt */
|
||||
dev_done = dev_done & ~itto; /* clr done, int */
|
||||
int_req = int_req & ~itto;
|
||||
int_enable = int_enable | itto; /* set enable */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Terminal output: IOT routine */
|
||||
|
||||
int32 ttox (int32 inst, int32 AC)
|
||||
{
|
||||
int32 pulse = inst & 07; /* pulse */
|
||||
int32 ln = TTX_GETLN (inst); /* line # */
|
||||
int32 itti = (INT_TTI1 << ln); /* rx intr */
|
||||
int32 itto = (INT_TTO1 << ln); /* tx intr */
|
||||
int32 pulse = inst & 07; /* pulse */
|
||||
int32 ln = TTX_GETLN (inst); /* line # */
|
||||
int32 itti = (INT_TTI1 << ln); /* rx intr */
|
||||
int32 itto = (INT_TTO1 << ln); /* tx intr */
|
||||
|
||||
switch (pulse) { /* case IR<9:11> */
|
||||
|
||||
case 0: /* TLF */
|
||||
dev_done = dev_done | itto; /* set flag */
|
||||
int_req = INT_UPDATE; /* update intr */
|
||||
break;
|
||||
|
||||
case 1: /* TSF */
|
||||
return (dev_done & itto)? IOT_SKP + AC: AC;
|
||||
|
||||
case 2: /* TCF */
|
||||
dev_done = dev_done & ~itto; /* clear flag */
|
||||
int_req = int_req & ~itto; /* clear intr */
|
||||
break;
|
||||
|
||||
case 5: /* SPI */
|
||||
return (int_req & (itti | itto))? IOT_SKP + AC: AC;
|
||||
|
||||
case 6: /* TLS */
|
||||
dev_done = dev_done & ~itto; /* clear flag */
|
||||
int_req = int_req & ~itto; /* clear int req */
|
||||
case 4: /* TPC */
|
||||
sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate */
|
||||
ttox_buf[ln] = AC & 0377; /* load buffer */
|
||||
break;
|
||||
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC;
|
||||
} /* end switch */
|
||||
|
||||
switch (pulse) { /* case IR<9:11> */
|
||||
case 0: /* TLF */
|
||||
dev_done = dev_done | itto; /* set flag */
|
||||
int_req = INT_UPDATE; /* update intr */
|
||||
break;
|
||||
case 1: /* TSF */
|
||||
return (dev_done & itto)? IOT_SKP + AC: AC;
|
||||
case 2: /* TCF */
|
||||
dev_done = dev_done & ~itto; /* clear flag */
|
||||
int_req = int_req & ~itto; /* clear intr */
|
||||
break;
|
||||
case 5: /* SPI */
|
||||
return (int_req & (itti | itto))? IOT_SKP + AC: AC;
|
||||
case 6: /* TLS */
|
||||
dev_done = dev_done & ~itto; /* clear flag */
|
||||
int_req = int_req & ~itto; /* clear int req */
|
||||
case 4: /* TPC */
|
||||
sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate */
|
||||
ttox_buf[ln] = AC & 0377; /* load buffer */
|
||||
break;
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
|
||||
return AC;
|
||||
}
|
||||
|
||||
@@ -281,23 +316,27 @@ return AC;
|
||||
|
||||
t_stat ttox_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c, ln = uptr - ttox_unit; /* line # */
|
||||
int32 c, ln = uptr - ttox_unit; /* line # */
|
||||
|
||||
if (ttx_ldsc[ln].conn) { /* connected? */
|
||||
if (ttx_ldsc[ln].xmte) { /* tx enabled? */
|
||||
TMLN *lp = &ttx_ldsc[ln]; /* get line */
|
||||
if (ttox_unit[ln].flags & UNIT_UC) { /* UC mode? */
|
||||
c = ttox_buf[ln] & 0177; /* get char */
|
||||
if (islower (c)) c = toupper (c); }
|
||||
else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
|
||||
tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&ttx_desc); } /* poll xmt */
|
||||
else {
|
||||
tmxr_poll_tx (&ttx_desc); /* poll xmt */
|
||||
sim_activate (uptr, ttox_unit[ln].wait); /* wait */
|
||||
return SCPE_OK; } }
|
||||
dev_done = dev_done | (INT_TTO1 << ln); /* set done */
|
||||
int_req = INT_UPDATE; /* update intr */
|
||||
if (ttx_ldsc[ln].conn) { /* connected? */
|
||||
if (ttx_ldsc[ln].xmte) { /* tx enabled? */
|
||||
TMLN *lp = &ttx_ldsc[ln]; /* get line */
|
||||
if (ttox_unit[ln].flags & UNIT_UC) { /* UC mode? */
|
||||
c = ttox_buf[ln] & 0177; /* get char */
|
||||
if (islower (c)) c = toupper (c);
|
||||
}
|
||||
else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
|
||||
tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&ttx_desc); /* poll xmt */
|
||||
}
|
||||
else {
|
||||
tmxr_poll_tx (&ttx_desc); /* poll xmt */
|
||||
sim_activate (uptr, ttox_unit[ln].wait); /* wait */
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
dev_done = dev_done | (INT_TTO1 << ln); /* set done */
|
||||
int_req = INT_UPDATE; /* update intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -307,17 +346,18 @@ t_stat ttox_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 ln, itto;
|
||||
|
||||
ttx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
|
||||
for (ln = 0; ln < TTX_LINES; ln++) { /* for all lines */
|
||||
ttox_buf[ln] = 0; /* clear buf */
|
||||
itto = (INT_TTO1 << ln); /* interrupt */
|
||||
dev_done = dev_done & ~itto; /* clr done, int */
|
||||
int_req = int_req & ~itto;
|
||||
int_enable = int_enable | itto; /* set enable */
|
||||
sim_cancel (&ttox_unit[ln]); } /* deactivate */
|
||||
ttx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
|
||||
for (ln = 0; ln < TTX_LINES; ln++) { /* for all lines */
|
||||
ttox_buf[ln] = 0; /* clear buf */
|
||||
itto = (INT_TTO1 << ln); /* interrupt */
|
||||
dev_done = dev_done & ~itto; /* clr done, int */
|
||||
int_req = int_req & ~itto;
|
||||
int_enable = int_enable | itto; /* set enable */
|
||||
sim_cancel (&ttox_unit[ln]); /* deactivate */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Attach master unit */
|
||||
|
||||
t_stat ttx_attach (UNIT *uptr, char *cptr)
|
||||
@@ -325,10 +365,10 @@ t_stat ttx_attach (UNIT *uptr, char *cptr)
|
||||
int32 t;
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) return r; /* error */
|
||||
t = sim_rtcn_init (ttix_unit.wait, TMR_TTX); /* init calib */
|
||||
sim_activate (uptr, t); /* start poll */
|
||||
r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) return r; /* error */
|
||||
t = sim_rtcn_init (ttix_unit.wait, TMR_TTX); /* init calib */
|
||||
sim_activate (uptr, t); /* start poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -339,10 +379,11 @@ t_stat ttx_detach (UNIT *uptr)
|
||||
int32 i;
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_detach (&ttx_desc, uptr); /* detach */
|
||||
for (i = 0; i < TTX_LINES; i++) { /* all lines, */
|
||||
ttx_ldsc[i].rcve = 0; /* disable rcv */
|
||||
sim_cancel (&ttox_unit[i]); } /* stop poll */
|
||||
r = tmxr_detach (&ttx_desc, uptr); /* detach */
|
||||
for (i = 0; i < TTX_LINES; i++) { /* all lines, */
|
||||
ttx_ldsc[i].rcve = 0; /* disable rcv */
|
||||
sim_cancel (&ttox_unit[i]); /* stop poll */
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -362,14 +403,17 @@ return SCPE_OK;
|
||||
|
||||
t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i;
|
||||
int32 i, t;
|
||||
|
||||
for (i = 0; (i < TTX_LINES) && (ttx_ldsc[i].conn == 0); i++) ;
|
||||
if (i < TTX_LINES) {
|
||||
for (i = 0; i < TTX_LINES; i++) {
|
||||
if (ttx_ldsc[i].conn)
|
||||
if (val) tmxr_fconns (st, &ttx_ldsc[i], i);
|
||||
else tmxr_fstats (st, &ttx_ldsc[i], i); } }
|
||||
for (i = t = 0; i < TTX_LINES; i++) t = t + (ttx_ldsc[i].conn != 0);
|
||||
if (t) {
|
||||
for (i = 0; i < TTX_LINES; i++) {
|
||||
if (ttx_ldsc[i].conn) {
|
||||
if (val) tmxr_fconns (st, &ttx_ldsc[i], i);
|
||||
else tmxr_fstats (st, &ttx_ldsc[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else fprintf (st, "all disconnected\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -379,9 +423,12 @@ return SCPE_OK;
|
||||
void ttx_enbdis (int32 dis)
|
||||
{
|
||||
if (dis) {
|
||||
ttix_dev.flags = ttox_dev.flags | DEV_DIS;
|
||||
ttox_dev.flags = ttox_dev.flags | DEV_DIS; }
|
||||
else { ttix_dev.flags = ttix_dev.flags & ~DEV_DIS;
|
||||
ttox_dev.flags = ttox_dev.flags & ~DEV_DIS; }
|
||||
ttix_dev.flags = ttox_dev.flags | DEV_DIS;
|
||||
ttox_dev.flags = ttox_dev.flags | DEV_DIS;
|
||||
}
|
||||
else {
|
||||
ttix_dev.flags = ttix_dev.flags & ~DEV_DIS;
|
||||
ttox_dev.flags = ttox_dev.flags & ~DEV_DIS;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user