mirror of
https://github.com/simh/simh.git
synced 2026-03-26 18:13:51 +00:00
Notes For V3.8
The makefile now works for Linux and most Unix's. Howevr, for Solaris and MacOS, you must first export the OSTYPE environment variable: > export OSTYPE > make Otherwise, you will get build errors. 1. New Features 1.1 3.8-0 1.1.1 SCP and Libraries - BREAK, NOBREAK, and SHOW BREAK with no argument will set, clear, and show (respectively) a breakpoint at the current PC. 1.2 GRI - Added support for the GRI-99 processor. 1.3 HP2100 - Added support for the BACI terminal interface. - Added support for RTE OS/VMA/EMA, SIGNAL, VIS firmware extensions. 1.4 Nova - Added support for 64KW memory (implemented in third-party CPU's). 1.5 PDP-11 - Added support for DC11, RC11, KE11A, KG11A. - Added modem control support for DL11. - Added ASCII character support for all 8b devices. 2. Bugs Fixed Please see the revision history on http://simh.trailing-edge.com or in the source module sim_rev.h.
This commit is contained in:
committed by
Mark Pizzolato
parent
3cb7c60d5d
commit
59aa4a73b1
@@ -366,6 +366,7 @@ int32 speed = 0; /* Delay for each instru
|
||||
int32 XCT_mode = 0; /* 1 if XCT mode */
|
||||
int32 XCT_inst = 0; /* XCT instruction */
|
||||
int32 PPC = -1;
|
||||
int32 AMASK = 077777;
|
||||
|
||||
struct ndev dev_table[64]; /* dispatch table */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* nova_clk.c: NOVA real-time clock simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
clk real-time clock
|
||||
|
||||
04-Jul-07 BKR DEV_SET/CLR macros now used,
|
||||
changed CLK name to RTC for DG compatiblity,
|
||||
device may now bw DISABLED
|
||||
01-Mar-03 RMS Added SET/SHOW CLK FREQ support
|
||||
03-Oct-02 RMS Added DIB
|
||||
17-Sep-01 RMS Added terminal multiplexor support
|
||||
@@ -35,7 +38,7 @@
|
||||
|
||||
#include "nova_defs.h"
|
||||
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable ;
|
||||
|
||||
int32 clk_sel = 0; /* selected freq */
|
||||
int32 clk_time[4] = { 16000, 100000, 10000, 1000 }; /* freq table */
|
||||
@@ -43,7 +46,7 @@ int32 clk_tps[4] = { 60, 10, 100, 1000 }; /* ticks per sec */
|
||||
int32 clk_adj[4] = { 1, -5, 2, 20 }; /* tmxr adjust */
|
||||
int32 tmxr_poll = 16000; /* tmxr poll */
|
||||
|
||||
int32 clk (int32 pulse, int32 code, int32 AC);
|
||||
int32 clk (int32 pulse, int32 code, int32 AC);
|
||||
t_stat clk_svc (UNIT *uptr);
|
||||
t_stat clk_reset (DEVICE *dptr);
|
||||
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
@@ -85,39 +88,41 @@ MTAB clk_mod[] = {
|
||||
};
|
||||
|
||||
DEVICE clk_dev = {
|
||||
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||
"RTC", &clk_unit, clk_reg, clk_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &clk_reset,
|
||||
NULL, NULL, NULL,
|
||||
&clk_dib, 0
|
||||
&clk_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
|
||||
/* IOT routine */
|
||||
|
||||
int32 clk (int32 pulse, int32 code, int32 AC)
|
||||
{
|
||||
if (code == ioDOA) { /* DOA */
|
||||
clk_sel = AC & 3; /* save select */
|
||||
sim_rtc_init (clk_time[clk_sel]); /* init calibr */
|
||||
sim_rtc_init (clk_time[clk_sel]); /* init calibr */
|
||||
}
|
||||
|
||||
switch (pulse) { /* decode IR<8:9> */
|
||||
|
||||
case iopS: /* start */
|
||||
dev_busy = dev_busy | INT_CLK; /* set busy */
|
||||
dev_done = dev_done & ~INT_CLK; /* clear done, int */
|
||||
int_req = int_req & ~INT_CLK;
|
||||
if (!sim_is_active (&clk_unit)) /* not running? */
|
||||
sim_activate (&clk_unit, /* activate */
|
||||
sim_rtc_init (clk_time[clk_sel])); /* init calibr */
|
||||
break;
|
||||
case iopS: /* start */
|
||||
DEV_SET_BUSY( INT_CLK ) ;
|
||||
DEV_CLR_DONE( INT_CLK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
if (!sim_is_active (&clk_unit)) /* not running? */
|
||||
sim_activate (&clk_unit, /* activate */
|
||||
sim_rtc_init (clk_time[clk_sel])); /* init calibr */
|
||||
break;
|
||||
|
||||
case iopC: /* clear */
|
||||
dev_busy = dev_busy & ~INT_CLK; /* clear busy */
|
||||
dev_done = dev_done & ~INT_CLK; /* clear done, int */
|
||||
int_req = int_req & ~INT_CLK;
|
||||
sim_cancel (&clk_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
case iopC: /* clear */
|
||||
DEV_CLR_BUSY( INT_CLK ) ;
|
||||
DEV_CLR_DONE( INT_CLK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&clk_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -128,14 +133,19 @@ t_stat clk_svc (UNIT *uptr)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
dev_done = dev_done | INT_CLK; /* set done */
|
||||
dev_busy = dev_busy & ~INT_CLK; /* clear busy */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
if ( DEV_IS_BUSY(INT_CLK) )
|
||||
{
|
||||
DEV_CLR_BUSY( INT_CLK ) ;
|
||||
DEV_SET_DONE( INT_CLK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
}
|
||||
t = sim_rtc_calb (clk_tps[clk_sel]); /* calibrate delay */
|
||||
sim_activate (&clk_unit, t); /* reactivate unit */
|
||||
if (clk_adj[clk_sel] > 0) /* clk >= 60Hz? */
|
||||
tmxr_poll = t * clk_adj[clk_sel]; /* poll is longer */
|
||||
else tmxr_poll = t / (-clk_adj[clk_sel]); /* poll is shorter */
|
||||
else
|
||||
tmxr_poll = t / (-clk_adj[clk_sel]); /* poll is shorter */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -144,9 +154,10 @@ return SCPE_OK;
|
||||
t_stat clk_reset (DEVICE *dptr)
|
||||
{
|
||||
clk_sel = 0;
|
||||
dev_busy = dev_busy & ~INT_CLK; /* clear busy */
|
||||
dev_done = dev_done & ~INT_CLK; /* clear done, int */
|
||||
int_req = int_req & ~INT_CLK;
|
||||
DEV_CLR_BUSY( INT_CLK ) ;
|
||||
DEV_CLR_DONE( INT_CLK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
|
||||
sim_cancel (&clk_unit); /* deactivate unit */
|
||||
tmxr_poll = clk_time[0]; /* poll is default */
|
||||
return SCPE_OK;
|
||||
|
||||
775
NOVA/nova_cpu.c
775
NOVA/nova_cpu.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/* nova_defs.h: NOVA/Eclipse simulator definitions
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -23,6 +23,10 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
04-Jul-07 BKR BUSY/DONE/INTR "convenience" macros added,
|
||||
INT_TRAP added for Nova 3, 4 trap instruction handling,
|
||||
support for 3rd-party 64KW Nova extensions added,
|
||||
removed STOP_IND_TRP definition due to common INT/TRP handling
|
||||
14-Jan-04 BKR Added support for QTY and ALM
|
||||
22-Nov-03 CEO Added support for PIT device
|
||||
19-Jan-03 RMS Changed CMASK to CDMASK for Apple Dev kit conflict
|
||||
@@ -46,27 +50,41 @@
|
||||
#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_IND 4 /* indirect loop */
|
||||
#define STOP_IND_INT 5 /* ind loop, intr */
|
||||
#define STOP_IND_TRP 6 /* ind loop, trap */
|
||||
#define STOP_IND_INT 5 /* ind loop, intr or trap */
|
||||
|
||||
|
||||
/* Memory */
|
||||
|
||||
#if defined (ECLIPSE)
|
||||
#define MAXMEMSIZE 1048576 /* max memory size */
|
||||
#else
|
||||
#define MAXMEMSIZE 32768 /* max memory size */
|
||||
#endif
|
||||
#define AMASK 077777 /* logical addr mask */
|
||||
/*----------------------*/
|
||||
/* Eclipse */
|
||||
/*----------------------*/
|
||||
|
||||
#define MAXMEMSIZE 1048576 /* max memory size in 16-bit words */
|
||||
#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < (uint32) MEMSIZE)
|
||||
|
||||
#else
|
||||
/*----------------------*/
|
||||
/* Nova */
|
||||
/*----------------------*/
|
||||
|
||||
#define MAXMEMSIZE 65536 /* max memory size in 16-bit words: 32KW = DG max, */
|
||||
/* 64 KW = 3rd-party extended memory feature */
|
||||
#define DFTMEMSIZE 32768 /* default/initial mem size */
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < (uint32) MEMSIZE)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define A_V_IND 15 /* ind: indirect */
|
||||
#define A_IND (1 << A_V_IND)
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
|
||||
|
||||
/* Architectural constants */
|
||||
|
||||
@@ -82,8 +100,11 @@
|
||||
#define STK_JMP 3 /* stack jmp @ */
|
||||
#define TRP_SAV 046 /* trap saved PC */
|
||||
#define TRP_JMP 047 /* trap jmp @ */
|
||||
#define AUTO_INC 020 /* start autoinc */
|
||||
|
||||
#define AUTO_TOP 037 /* top of autoindex */
|
||||
#define AUTO_DEC 030 /* start autodec */
|
||||
#define AUTO_INC 020 /* start autoinc */
|
||||
|
||||
|
||||
/* Instruction format */
|
||||
|
||||
@@ -235,6 +256,7 @@ typedef struct {
|
||||
#define INT_V_STK 17 /* stack overflow */
|
||||
#define INT_V_NO_ION_PENDING 18 /* ion delay */
|
||||
#define INT_V_ION 19 /* interrupts on */
|
||||
#define INT_V_TRAP 20 /* trap instruction */
|
||||
|
||||
#define INT_PIT (1 << INT_V_PIT)
|
||||
#define INT_DKP (1 << INT_V_DKP)
|
||||
@@ -256,6 +278,7 @@ typedef struct {
|
||||
#define INT_ION (1 << INT_V_ION)
|
||||
#define INT_DEV ((1 << INT_V_STK) - 1) /* device ints */
|
||||
#define INT_PENDING INT_ION+INT_NO_ION_PENDING
|
||||
#define INT_TRAP (1 << INT_V_TRAP)
|
||||
|
||||
/* PI disable bits */
|
||||
|
||||
@@ -279,6 +302,18 @@ typedef struct {
|
||||
/* #define PI_CAS 0000040 */
|
||||
/* #define PI_ADCV 0000002 */
|
||||
|
||||
|
||||
/* Macros to clear/set BUSY/DONE/INTR bits */
|
||||
|
||||
#define DEV_SET_BUSY( x ) dev_busy = dev_busy | (x)
|
||||
#define DEV_CLR_BUSY( x ) dev_busy = dev_busy & (~(x))
|
||||
#define DEV_SET_DONE( x ) dev_done = dev_done | (x)
|
||||
#define DEV_CLR_DONE( x ) dev_done = dev_done & (~(x))
|
||||
#define DEV_UPDATE_INTR int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable)
|
||||
|
||||
#define DEV_IS_BUSY( x ) (dev_busy & (x))
|
||||
#define DEV_IS_DONE( x ) (dev_done & (x))
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
int32 MapAddr (int32 map, int32 addr);
|
||||
|
||||
510
NOVA/nova_dkp.c
510
NOVA/nova_dkp.c
@@ -1,6 +1,6 @@
|
||||
/* nova_dkp.c: NOVA moving head disk simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -25,6 +25,23 @@
|
||||
|
||||
dkp moving head disk
|
||||
|
||||
04-Jul-04 BKR device name changed to DG's DKP from DEC's DP,
|
||||
DEV_SET/CLR/INTR macro use started,
|
||||
fixed 'P' pulse code and secret quirks,
|
||||
added 6097 diag and size support,
|
||||
fixed losing unit drive type during unit change,
|
||||
tightened sector size determination calculations,
|
||||
controller DONE flag handling fixed,
|
||||
fixed cylinder overflow test error,
|
||||
seek error code fixed,
|
||||
restructured dkp_go() and dkp_svc() routines
|
||||
(for known future fixes needed),
|
||||
fixed DIA status calculation,
|
||||
fixed DKP read/write loop to properly emulate DG cylinder and sector overflows,
|
||||
added trace facility,
|
||||
changed 'stime' calculation to force delay time if no cylinders are crossed
|
||||
(this fixes some DG code that assumes disk seek takes some time),
|
||||
fixed boot code to match DG hardware standard
|
||||
04-Jan-04 RMS Changed attach routine to use sim_fsize
|
||||
28-Nov-03 CEO Boot from DP now puts device address in SR
|
||||
24-Nov-03 CEO Added support for disk sizing on 6099/6103
|
||||
@@ -110,15 +127,35 @@
|
||||
#define FCCY_SEEK 2
|
||||
#define FCCY_RECAL 3
|
||||
#define FCCY_FLAGS 0174000 /* flags */
|
||||
|
||||
#define GET_CMD(x,dt) ((drv_tab[dt].newf)? \
|
||||
(((x) >> FCCY_V_NCMD) & FCCY_M_NCMD): \
|
||||
(((x) >> FCCY_V_OCMD) & FCCY_M_OCMD) )
|
||||
|
||||
#define SET_CMD(x,dt) dkp_fccy = (dkp_fccy & ((drv_tab[dt].newf)? \
|
||||
(FCCY_M_NCMD << FCCY_V_NCMD) : (FCCY_M_OCMD << FCCY_V_OCMD))) | \
|
||||
((drv_tab[dt].newf)? \
|
||||
(((x) & FCCY_M_NCMD) << FCCY_V_NCMD): \
|
||||
(((x) & FCCY_M_OCMD) << FCCY_V_OCMD) )
|
||||
|
||||
#define GET_CYL(x,dt) ((drv_tab[dt].newf)? \
|
||||
(((x) >> FCCY_V_NCYL) & FCCY_M_NCYL): \
|
||||
((((x) >> FCCY_V_OCYL) & FCCY_M_OCYL) | \
|
||||
((dt != TYPE_D44)? 0: \
|
||||
(((x) & FCCY_OCEX) >> (FCCY_V_OCEX - FCCY_V_OCMD)))) )
|
||||
|
||||
|
||||
/* (Warning: no sector or surface masking is done!) */
|
||||
|
||||
#define DKP_UPDATE_USSC( type, count, surf, sect ) \
|
||||
dkp_ussc = (dkp_ussc & USSC_UNIT) \
|
||||
| ((dkp_ussc + count) & USSC_M_COUNT) \
|
||||
| ((drv_tab[dtype].newf)? \
|
||||
((surf << USSC_V_NSURFACE) | (sect << USSC_V_NSECTOR)): \
|
||||
((surf << USSC_V_OSURFACE) | (sect << USSC_V_OSECTOR)) \
|
||||
);
|
||||
|
||||
|
||||
/* Status */
|
||||
|
||||
#define STA_ERR 0000001 /* error */
|
||||
@@ -154,14 +191,17 @@
|
||||
|
||||
floppy 8 1 77 no
|
||||
DS/DD floppy 16 2 77 yes
|
||||
(6097 "quad floppy")
|
||||
Diablo 31 12 2 203 no
|
||||
6225 20 2 245 yes
|
||||
Century 111 6 10 203 no
|
||||
4048 (same as Century 111)
|
||||
Diablo 44 12 4 408 no
|
||||
6099 32 4 192 yes
|
||||
6227 20 6 245 yes
|
||||
6070 24 4 408 yes
|
||||
Century 114 12 20 203 no
|
||||
4057 (same as Century 114)
|
||||
6103 32 8 192 yes
|
||||
4231 23 19 411 yes
|
||||
|
||||
@@ -178,6 +218,7 @@
|
||||
#define NFMT_FLP FALSE
|
||||
|
||||
#define TYPE_DSDD 1
|
||||
#define TYPE_6097 TYPE_DSDD
|
||||
#define SECT_DSDD 16
|
||||
#define SURF_DSDD 2
|
||||
#define CYL_DSDD 77
|
||||
@@ -278,9 +319,20 @@ struct drvtyp drv_tab[] = {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
#define DKP_TRACE(x) (dkp_trace & (1<<(x)))
|
||||
#define DKP_TRACE_FP stderr
|
||||
/* current trace bit use (bit 0 = LSB)
|
||||
0 I/O instructions
|
||||
1 pre-seek/read/write event setup
|
||||
2 seek events
|
||||
3 read/write events
|
||||
4 post read/write events
|
||||
*/
|
||||
|
||||
extern uint16 M[];
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
extern int32 saved_PC, SR, AMASK;
|
||||
|
||||
int32 dkp_ma = 0; /* memory address */
|
||||
int32 dkp_map = 0; /* DCH map 0=A 3=B */
|
||||
@@ -291,13 +343,15 @@ int32 dkp_swait = 100; /* seek latency */
|
||||
int32 dkp_rwait = 100; /* rotate latency */
|
||||
int32 dkp_diagmode = 0; /* diagnostic mode */
|
||||
|
||||
int32 dkp_trace = 0 ;
|
||||
|
||||
DEVICE dkp_dev;
|
||||
int32 dkp (int32 pulse, int32 code, int32 AC);
|
||||
t_stat dkp_svc (UNIT *uptr);
|
||||
t_stat dkp_reset (DEVICE *dptr);
|
||||
t_stat dkp_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat dkp_attach (UNIT *uptr, char *cptr);
|
||||
t_stat dkp_go (void);
|
||||
t_stat dkp_go ( int32 pulse );
|
||||
t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* DKP data structures
|
||||
@@ -330,7 +384,8 @@ REG dkp_reg[] = {
|
||||
{ FLDATA (BUSY, dev_busy, INT_V_DKP) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_DKP) },
|
||||
{ FLDATA (DISABLE, dev_disable, INT_V_DKP) },
|
||||
{ FLDATA (DIAG, dkp_diagmode, 0) },
|
||||
{ FLDATA (DIAG, dkp_diagmode, 0) },
|
||||
{ DRDATA (TRACE, dkp_trace, 32) },
|
||||
{ ORDATA (MAP, dkp_map, 2) },
|
||||
{ DRDATA (STIME, dkp_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, dkp_rwait, 24), PV_LEFT },
|
||||
@@ -438,13 +493,14 @@ MTAB dkp_mod[] = {
|
||||
};
|
||||
|
||||
DEVICE dkp_dev = {
|
||||
"DP", dkp_unit, dkp_reg, dkp_mod,
|
||||
"DKP", dkp_unit, dkp_reg, dkp_mod,
|
||||
DKP_NUMDR, 8, 30, 1, 8, 16,
|
||||
NULL, NULL, &dkp_reset,
|
||||
&dkp_boot, &dkp_attach, NULL,
|
||||
&dkp_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
|
||||
/* IOT routine */
|
||||
|
||||
int32 dkp (int32 pulse, int32 code, int32 AC)
|
||||
@@ -456,14 +512,26 @@ rval = 0;
|
||||
uptr = dkp_dev.units + GET_UNIT (dkp_ussc); /* select unit */
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
|
||||
if ( DKP_TRACE(0) )
|
||||
{
|
||||
static char * f[8] =
|
||||
{ "NIO", "DIA", "DOA", "DIB", "DOB", "DIC", "DOC", "SKP" } ;
|
||||
static char * s[4] =
|
||||
{ " ", "S", "C", "P" } ;
|
||||
|
||||
printf( " [DKP %s%s %06o ", f[code & 0x07], s[pulse & 0x03], (AC & 0xFFFF) ) ;
|
||||
}
|
||||
|
||||
switch (code) { /* decode IR<5:7> */
|
||||
|
||||
case ioDIA: /* DIA */
|
||||
dkp_sta = dkp_sta & ~STA_DYN; /* clear dynamic */
|
||||
if (uptr->flags & UNIT_ATT) dkp_sta = dkp_sta | STA_DRDY;
|
||||
dkp_sta = dkp_sta & (~STA_DRDY) ; /* keep error flags */
|
||||
if (uptr->flags & UNIT_ATT) /* update ready */
|
||||
dkp_sta = dkp_sta | STA_DRDY;
|
||||
if (uptr->CYL >= drv_tab[dtype].cyl)
|
||||
dkp_sta = dkp_sta | STA_CYL; /* bad cylinder? */
|
||||
if (dkp_sta & STA_EFLGS) dkp_sta = dkp_sta | STA_ERR;
|
||||
if (dkp_sta & STA_EFLGS)
|
||||
dkp_sta = dkp_sta | STA_ERR;
|
||||
rval = dkp_sta;
|
||||
break;
|
||||
|
||||
@@ -474,20 +542,25 @@ switch (code) { /* decode IR<5:7> */
|
||||
dkp_fccy = AC; /* save cmd, cyl */
|
||||
dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS);
|
||||
}
|
||||
if ((dkp_sta & STA_DFLGS) == 0) /* done flags = 0? */
|
||||
dev_done = dev_done & ~INT_DKP; /* clear intr */
|
||||
DEV_CLR_DONE( INT_DKP ) ; /* assume done flags 0 */
|
||||
if ( dkp_sta & STA_DFLGS ) /* done flags = 0? */
|
||||
DEV_SET_DONE( INT_DKP ) ; /* nope - set done */
|
||||
DEV_UPDATE_INTR ; /* update intr */
|
||||
break;
|
||||
|
||||
case ioDIB: /* DIB */
|
||||
rval = dkp_ma; /* return buf addr */
|
||||
rval = dkp_ma & 077777 ; /* return buf addr */
|
||||
/* with B0 clear (no DCH B map support) */
|
||||
break;
|
||||
|
||||
case ioDOB: /* DOB */
|
||||
if ((dev_busy & INT_DKP) == 0) {
|
||||
dkp_ma = AC & (drv_tab[dtype].newf? DMASK: AMASK);
|
||||
if (AC & 0100000) dkp_map = 3; /* high bit is map */
|
||||
else dkp_map = 0;
|
||||
}
|
||||
if (AC & 0100000)
|
||||
dkp_map = 3; /* high bit is map */
|
||||
else
|
||||
dkp_map = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ioDIC: /* DIC */
|
||||
@@ -495,63 +568,97 @@ switch (code) { /* decode IR<5:7> */
|
||||
break;
|
||||
|
||||
case ioDOC: /* DOC */
|
||||
if ((dev_busy & INT_DKP) == 0) dkp_ussc = AC; /* save unit, sect */
|
||||
if (((dtype == TYPE_6099) || /* for 6099 and 6103 */
|
||||
(dtype == TYPE_6103)) && /* if data<0> set, */
|
||||
AC & 010000) dkp_diagmode = 1; /* set diagnostic mode */
|
||||
if ((dev_busy & INT_DKP) == 0) /* if device is not busy */
|
||||
dkp_ussc = AC ; /* save unit, sect */
|
||||
if (((dtype == TYPE_6099) || /* (BKR: don't forget 6097) */
|
||||
(dtype == TYPE_6097) || /* for 6099 and 6103 */
|
||||
(dtype == TYPE_6103)) && /* if data<0> set, */
|
||||
(AC & 010000) )
|
||||
dkp_diagmode = 1; /* set diagnostic mode */
|
||||
break;
|
||||
} /* end switch code */
|
||||
|
||||
u = GET_UNIT(dkp_ussc); /* select unit */
|
||||
u = GET_UNIT(dkp_ussc); /* update current unit */
|
||||
uptr = dkp_dev.units + u ; /* select unit */
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
|
||||
if ( DKP_TRACE(0) )
|
||||
{
|
||||
if ( code & 1 )
|
||||
printf( " [%06o] ", (rval & 0xFFFF) ) ;
|
||||
printf( "] \n" ) ;
|
||||
}
|
||||
|
||||
switch (pulse) { /* decode IR<8:9> */
|
||||
|
||||
case iopS: /* start */
|
||||
dev_busy = dev_busy | INT_DKP; /* set busy */
|
||||
dev_done = dev_done & ~INT_DKP; /* clear done */
|
||||
int_req = int_req & ~INT_DKP; /* clear int */
|
||||
DEV_SET_BUSY( INT_DKP ) ; /* set busy */
|
||||
DEV_CLR_DONE( INT_DKP ) ; /* clear done */
|
||||
DEV_UPDATE_INTR ; /* update ints */
|
||||
if (dkp_diagmode) { /* in diagnostic mode? */
|
||||
dkp_diagmode = 0; /* reset it */
|
||||
dkp_diagmode = 0; /* reset it */
|
||||
if (dtype == TYPE_6097) dkp_ussc = 010001; /* (BKR - quad floppy) */
|
||||
if (dtype == TYPE_6099) dkp_ussc = 010002; /* return size bits */
|
||||
if (dtype == TYPE_6103) dkp_ussc = 010003; /* for certain types */
|
||||
}
|
||||
else { /* normal mode ... */
|
||||
if (dkp_go ()) break; /* new cmd, error? */
|
||||
if (dkp_go (pulse)) /* do command */
|
||||
break ; /* break if no error */
|
||||
}
|
||||
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
||||
dev_done = dev_done | INT_DKP; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
dkp_sta = dkp_sta | STA_DONE;
|
||||
DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */
|
||||
DEV_SET_DONE( INT_DKP ) ; /* set done */
|
||||
DEV_UPDATE_INTR ; /* update ints */
|
||||
dkp_sta = dkp_sta | STA_DONE; /* set controller done */
|
||||
break;
|
||||
|
||||
case iopC: /* clear */
|
||||
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
||||
dev_done = dev_done & ~INT_DKP; /* clear done */
|
||||
int_req = int_req & ~INT_DKP; /* clear int */
|
||||
dkp_sta = dkp_sta & ~(STA_DFLGS + STA_EFLGS);
|
||||
if (dkp_unit[u].FUNC != FCCY_SEEK) sim_cancel (&dkp_unit[u]);
|
||||
DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */
|
||||
DEV_CLR_DONE( INT_DKP ) ; /* set done */
|
||||
DEV_UPDATE_INTR ; /* update ints */
|
||||
dkp_sta = dkp_sta & ~(STA_DFLGS + STA_EFLGS); /* clear controller flags */
|
||||
if (dkp_unit[u].FUNC != FCCY_SEEK)
|
||||
sim_cancel (&dkp_unit[u]); /* cancel any r/w op */
|
||||
break;
|
||||
|
||||
case iopP: /* pulse */
|
||||
dev_done = dev_done & ~INT_DKP; /* clear done */
|
||||
if (dkp_go ()) break; /* new seek command */
|
||||
dev_done = dev_done | INT_DKP; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
dkp_sta = dkp_sta | (STA_SKDN0 >> u); /* set seek done */
|
||||
if ( dkp_diagmode )
|
||||
{
|
||||
dkp_diagmode = 0 ; /* clear DG diagnostic mode */
|
||||
}
|
||||
else
|
||||
{
|
||||
DEV_CLR_DONE( INT_DKP ) ; /* clear done */
|
||||
DEV_UPDATE_INTR ;
|
||||
|
||||
/* DG "undocumented feature": 'P' pulse can not start a read/write operation!
|
||||
* Diagnostic routines will use this crock to do 'crazy things' to size a disk
|
||||
* and many assume that a recal is done, other assume that they can stop the
|
||||
* read operation before any damage is done. Must also [re]calculate unit, function
|
||||
* and type because DOx instruction may have updated the controller info after
|
||||
* start of this procedure and before our 'P' handler. BKR
|
||||
*/
|
||||
if (dkp_go(pulse))
|
||||
break; /* no error - do not set done and status */
|
||||
}
|
||||
|
||||
DEV_SET_DONE( INT_DKP ) ; /* set done */
|
||||
DEV_UPDATE_INTR ; /* update ints */
|
||||
dkp_sta = dkp_sta | (STA_SKDN0 >> u); /* set controller seek done */
|
||||
break;
|
||||
} /* end case pulse */
|
||||
} /* end case pulse */
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* New command, start vs pulse handled externally
|
||||
Returns true if command ok, false if error
|
||||
*/
|
||||
|
||||
t_stat dkp_go (void)
|
||||
t_stat dkp_go ( int32 pulse )
|
||||
{
|
||||
UNIT *uptr;
|
||||
int32 newcyl, func, u, dtype;
|
||||
UNIT * uptr;
|
||||
int32 oldCyl, u, dtype;
|
||||
|
||||
dkp_sta = dkp_sta & ~STA_EFLGS; /* clear errors */
|
||||
u = GET_UNIT (dkp_ussc); /* get unit number */
|
||||
@@ -560,31 +667,117 @@ if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr)) {
|
||||
dkp_sta = dkp_sta | STA_ERR; /* attached or busy? */
|
||||
return FALSE;
|
||||
}
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
func = GET_CMD (dkp_fccy, dtype); /* get function */
|
||||
newcyl = GET_CYL (dkp_fccy, dtype); /* get cylinder */
|
||||
|
||||
switch (func) { /* decode command */
|
||||
if (dkp_diagmode) { /* diagnostic mode? */
|
||||
dkp_sta = (dkp_sta | STA_DONE); /* Set error bit only */
|
||||
DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */
|
||||
DEV_SET_DONE( INT_DKP ) ; /* set done */
|
||||
DEV_UPDATE_INTR ; /* update interrupts */
|
||||
return ( TRUE ) ; /* do not do function */
|
||||
}
|
||||
|
||||
case FCCY_READ: case FCCY_WRITE:
|
||||
sim_activate (uptr, dkp_rwait); /* schedule */
|
||||
oldCyl = uptr->CYL ; /* get old cylinder */
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uptr->FUNC = GET_CMD (dkp_fccy, dtype) ; /* save command */
|
||||
uptr->CYL = GET_CYL (dkp_fccy, dtype) ;
|
||||
|
||||
if ( DKP_TRACE(1) )
|
||||
{
|
||||
int32 xSect ;
|
||||
int32 xSurf ;
|
||||
int32 xCyl ;
|
||||
int32 xCnt ;
|
||||
|
||||
xSect = GET_SECT(dkp_ussc, dtype) ;
|
||||
xSurf = GET_SURF(dkp_ussc, dtype) ;
|
||||
xCyl = GET_CYL (dkp_fccy, dtype) ;
|
||||
xCnt = 16 - (GET_COUNT(dkp_ussc)) ;
|
||||
|
||||
fprintf( DKP_TRACE_FP,
|
||||
" [%s:%c %-5s: %3d / %2d / %2d %2d %06o ] \r\n",
|
||||
"DKP",
|
||||
(char) (u + '0'),
|
||||
((uptr->FUNC == FCCY_READ) ?
|
||||
"read"
|
||||
: ((uptr->FUNC == FCCY_WRITE) ?
|
||||
"write"
|
||||
: ((uptr->FUNC == FCCY_SEEK) ?
|
||||
"seek"
|
||||
: "<???>"
|
||||
)
|
||||
)
|
||||
),
|
||||
(unsigned) xCyl,
|
||||
(unsigned) xSurf,
|
||||
(unsigned) xSect,
|
||||
(unsigned) (16 - xCnt),
|
||||
(unsigned) (dkp_ma & 0xFFFF) /* show all 16-bits in case DCH B */
|
||||
) ;
|
||||
}
|
||||
|
||||
|
||||
switch (uptr->FUNC) { /* decode command */
|
||||
|
||||
case FCCY_READ:
|
||||
case FCCY_WRITE:
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
|
||||
((uptr->flags & UNIT_WPRT) && (uptr->FUNC == FCCY_WRITE)))
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
|
||||
}
|
||||
else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder */
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_CYL ;
|
||||
}
|
||||
else if ( GET_SURF(dkp_ussc, dtype) >= drv_tab[dtype].surf ) /* bad surface */
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /* older drives may not even do this... */
|
||||
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /- newer disks give this error */
|
||||
}
|
||||
else if ( GET_SECT(dkp_ussc, dtype) >= drv_tab[dtype].sect ) /* or bad sector? */
|
||||
{
|
||||
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /- older drives may not even do this... */
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /* newer disks give this error */
|
||||
}
|
||||
if ( (pulse != iopS) || (dkp_sta & STA_ERR) )
|
||||
{
|
||||
return ( FALSE ) ;
|
||||
}
|
||||
sim_activate (uptr, dkp_rwait); /* schedule read or write request */
|
||||
break;
|
||||
|
||||
case FCCY_RECAL: /* recalibrate */
|
||||
newcyl = 0;
|
||||
func = FCCY_SEEK;
|
||||
uptr->FUNC = FCCY_SEEK ; /* save command */
|
||||
uptr->CYL = 0 ;
|
||||
|
||||
case FCCY_SEEK: /* seek */
|
||||
sim_activate (uptr, dkp_swait * abs (newcyl - uptr->CYL));
|
||||
if ( ! (uptr->flags & UNIT_ATT) ) /* not attached? */
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
|
||||
}
|
||||
else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder? */
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_ERR | STA_CYL;
|
||||
}
|
||||
if ( (pulse != iopP) || (dkp_sta & STA_ERR) )
|
||||
{
|
||||
return ( FALSE ) ; /* only 'P' pulse start seeks! */
|
||||
}
|
||||
|
||||
/* do the seek */
|
||||
/* must check for "do we support seeking bits" flag before setting SEEK0'ish bits! */
|
||||
dkp_sta = dkp_sta | (STA_SEEK0 >> u); /* set seeking */
|
||||
uptr->CYL = newcyl; /* on cylinder */
|
||||
oldCyl = abs(oldCyl - uptr->CYL) ;
|
||||
if ( (dkp_swait) && (! (oldCyl)) ) /* enforce minimum wait if req */
|
||||
oldCyl = 1 ;
|
||||
sim_activate ( uptr, (dkp_swait * oldCyl) ) ;
|
||||
break;
|
||||
} /* end case command */
|
||||
|
||||
uptr->FUNC = func; /* save command */
|
||||
return TRUE; /* no error */
|
||||
return ( TRUE ) ; /* no error */
|
||||
}
|
||||
|
||||
|
||||
/* Unit service
|
||||
|
||||
If seek done, put on cylinder;
|
||||
@@ -599,73 +792,127 @@ return TRUE; /* no error */
|
||||
|
||||
t_stat dkp_svc (UNIT *uptr)
|
||||
{
|
||||
int32 sc, sa, xcsa, bda;
|
||||
int32 sx, dx, pa, u;
|
||||
int32 sa, bda;
|
||||
int32 dx, pa, u;
|
||||
int32 dtype, err, newsect, newsurf;
|
||||
uint32 awc;
|
||||
t_stat rval;
|
||||
static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */
|
||||
|
||||
rval = SCPE_OK;
|
||||
|
||||
rval = SCPE_OK;
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
if (dkp_diagmode) { /* diagnostic mode? */
|
||||
dkp_sta = (dkp_sta | STA_DONE); /* Set error bit only */
|
||||
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
||||
dev_done = dev_done | INT_DKP; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
return SCPE_OK; /* do not do function */
|
||||
}
|
||||
u = uptr - dkp_dev.units; /* get unit number */
|
||||
|
||||
if (uptr->FUNC == FCCY_SEEK) { /* seek? */
|
||||
if (uptr->CYL >= drv_tab[dtype].cyl) /* bad cylinder? */
|
||||
if ( ! (uptr->flags & UNIT_ATT) ) /* not attached? */
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error (changed during queue time?) */
|
||||
}
|
||||
else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder? */
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_ERR | STA_CYL;
|
||||
dev_done = dev_done | INT_DKP; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
u = uptr - dkp_dev.units; /* get unit number */
|
||||
}
|
||||
DEV_SET_DONE( INT_DKP ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
dkp_sta = (dkp_sta | (STA_SKDN0 >> u)) /* set seek done */
|
||||
& ~(STA_SEEK0 >> u); /* clear seeking */
|
||||
& ~(STA_SEEK0 >> u); /* clear seeking */
|
||||
if ( DKP_TRACE(2) )
|
||||
{
|
||||
fprintf( DKP_TRACE_FP,
|
||||
" [%s:%c seek : %4d ] \r\n",
|
||||
"DKP",
|
||||
(char) (u + '0'),
|
||||
(unsigned) (uptr->CYL)
|
||||
) ;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* read or write */
|
||||
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
|
||||
((uptr->flags & UNIT_WPRT) && (uptr->FUNC == FCCY_WRITE)))
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
|
||||
|
||||
else if ((uptr->CYL >= drv_tab[dtype].cyl) || /* bad cylinder */
|
||||
(GET_SURF (dkp_ussc, dtype) >= drv_tab[dtype].surf) || /* bad surface */
|
||||
(GET_SECT (dkp_ussc, dtype) >= drv_tab[dtype].sect)) /* or bad sector? */
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS;
|
||||
|
||||
else if (GET_CYL (dkp_fccy, dtype) != uptr->CYL) /* address error? */
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS;
|
||||
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
|
||||
}
|
||||
else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder */
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_CYL ;
|
||||
dkp_sta = dkp_sta | STA_ERR | STA_CYL;
|
||||
DEV_SET_DONE( INT_DKP ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
return SCPE_OK ;
|
||||
}
|
||||
else if ( GET_SURF(dkp_ussc, dtype) >= drv_tab[dtype].surf ) /* bad surface */
|
||||
{
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /* older drives may not even do this... */
|
||||
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /- newer disks give this error */
|
||||
/* set sector to some bad value and wait then exit? */
|
||||
}
|
||||
else if ( GET_SECT(dkp_ussc, dtype) >= drv_tab[dtype].sect ) /* or bad sector? */
|
||||
{
|
||||
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /- older DG drives do not even give error(!), but we do */
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /* newer disks give this error */
|
||||
}
|
||||
else {
|
||||
sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */
|
||||
sa = GET_SA (uptr->CYL, GET_SURF (dkp_ussc, dtype),
|
||||
GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */
|
||||
xcsa = GET_SA (uptr->CYL + 1, 0, 0, dtype); /* get next cyl addr */
|
||||
if ((sa + sc) > xcsa ) { /* across cylinder? */
|
||||
sc = xcsa - sa; /* limit transfer */
|
||||
dkp_sta = dkp_sta | STA_XCY; /* xcyl error */
|
||||
err = 0 ;
|
||||
do {
|
||||
if ( DKP_TRACE(3) )
|
||||
{
|
||||
fprintf( DKP_TRACE_FP,
|
||||
" [%s:%c %-5s: %3d / %2d / %2d %06o ] \r\n",
|
||||
"DKP",
|
||||
(char) (u + '0'),
|
||||
((uptr->FUNC == FCCY_READ) ?
|
||||
"read"
|
||||
: ((uptr->FUNC == FCCY_WRITE) ?
|
||||
"write"
|
||||
: "<???>")
|
||||
),
|
||||
(unsigned) (uptr->CYL),
|
||||
(unsigned) (GET_SURF(dkp_ussc, dtype)),
|
||||
(unsigned) (GET_SECT(dkp_ussc, dtype)),
|
||||
(unsigned) (dkp_ma & 0xFFFF) /* show all 16-bits in case DCH B */
|
||||
) ;
|
||||
}
|
||||
bda = sa * DKP_NUMWD * sizeof (short); /* to words, bytes */
|
||||
|
||||
|
||||
if ( GET_SECT(dkp_ussc, dtype) >= drv_tab[dtype].sect ) /* or bad sector? */
|
||||
{
|
||||
/* sector overflows to 0 ;
|
||||
* surface gets incremented
|
||||
*/
|
||||
newsurf = GET_SURF(dkp_ussc, dtype) + 1 ;
|
||||
newsurf = newsurf & ((drv_tab[dtype].newf) ? USSC_M_NSURFACE : USSC_M_OSURFACE) ;
|
||||
DKP_UPDATE_USSC( type, 0, newsurf, 0 )
|
||||
|
||||
if ( (GET_SURF(dkp_ussc, dtype)) >= drv_tab[dtype].surf )
|
||||
{
|
||||
/* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /- older drives may not even do this... */
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /* newer disks give this error */
|
||||
/* DG retains overflowed surface number,
|
||||
* other vendors have different/expanded options
|
||||
*/
|
||||
break ;
|
||||
}
|
||||
}
|
||||
sa = GET_SA (uptr->CYL, GET_SURF (dkp_ussc, dtype),
|
||||
GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */
|
||||
bda = sa * DKP_NUMWD * sizeof(uint16) ; /* to words, bytes */
|
||||
err = fseek (uptr->fileref, bda, SEEK_SET); /* position drive */
|
||||
|
||||
if (uptr->FUNC == FCCY_READ) { /* read? */
|
||||
for (sx = 0; sx < sc; sx++) { /* loop thru sectors */
|
||||
awc = fxread (tbuf, sizeof(uint16), DKP_NUMWD, uptr->fileref);
|
||||
for ( ; awc < DKP_NUMWD; awc++) tbuf[awc] = 0;
|
||||
if (err = ferror (uptr->fileref)) break;
|
||||
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */
|
||||
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */
|
||||
pa = MapAddr (dkp_map, (dkp_ma & AMASK));
|
||||
if (MEM_ADDR_OK (pa)) M[pa] = tbuf[dx];
|
||||
dkp_ma = (dkp_ma + 1) & AMASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uptr->FUNC == FCCY_WRITE) { /* write? */
|
||||
for (sx = 0; sx < sc; sx++) { /* loop thru sectors */
|
||||
else if (uptr->FUNC == FCCY_WRITE) { /* write? */
|
||||
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop into buffer */
|
||||
pa = MapAddr (dkp_map, (dkp_ma & AMASK));
|
||||
tbuf[dx] = M[pa];
|
||||
@@ -674,27 +921,41 @@ else {
|
||||
fxwrite (tbuf, sizeof(int16), DKP_NUMWD, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
perror ("DKP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
clearerr (uptr->fileref);
|
||||
rval = SCPE_IOERR;
|
||||
break ;
|
||||
}
|
||||
|
||||
sa = sa + sc; /* update sector addr */
|
||||
newsect = sa % drv_tab[dtype].sect;
|
||||
newsurf = (sa / drv_tab[dtype].sect) % drv_tab[dtype].surf;
|
||||
dkp_ussc = (dkp_ussc & USSC_UNIT) | ((dkp_ussc + sc) & USSC_M_COUNT) |
|
||||
((drv_tab[dtype].newf)?
|
||||
((newsurf << USSC_V_NSURFACE) | (newsect << USSC_V_NSECTOR)):
|
||||
((newsurf << USSC_V_OSURFACE) | (newsect << USSC_V_OSECTOR)) );
|
||||
newsect = GET_SECT (dkp_ussc, dtype) + 1 ; /* update next sector */
|
||||
newsurf = GET_SURF (dkp_ussc, dtype) ; /* and next head */
|
||||
/* (count set below) */
|
||||
DKP_UPDATE_USSC( type, 1, newsurf, newsect )
|
||||
} /* end read/write loop */
|
||||
|
||||
while ( (GET_COUNT(dkp_ussc)) ) ;
|
||||
dkp_sta = dkp_sta | STA_DONE; /* set status */
|
||||
|
||||
if ( DKP_TRACE(4) )
|
||||
{
|
||||
fprintf( DKP_TRACE_FP,
|
||||
" [%s:%c %-5s: %3d / %2d / %2d %06o ] \r\n",
|
||||
"DKP",
|
||||
(char) (u + '0'),
|
||||
"post",
|
||||
(unsigned) (uptr->CYL),
|
||||
(unsigned) (GET_SURF(dkp_ussc, dtype)),
|
||||
(unsigned) (GET_SECT(dkp_ussc, dtype)),
|
||||
(unsigned) (dkp_ma & 0xFFFF) /* show all 16-bits in case DCH B */
|
||||
) ;
|
||||
}
|
||||
}
|
||||
|
||||
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
||||
dev_done = dev_done | INT_DKP; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
DEV_CLR_BUSY( INT_DKP ) ;
|
||||
DEV_SET_DONE( INT_DKP ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
return rval;
|
||||
}
|
||||
|
||||
@@ -705,9 +966,9 @@ t_stat dkp_reset (DEVICE *dptr)
|
||||
int32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
||||
dev_done = dev_done & ~INT_DKP; /* clear done, int */
|
||||
int_req = int_req & ~INT_DKP;
|
||||
DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */
|
||||
DEV_CLR_DONE( INT_DKP ) ; /* clear done */
|
||||
DEV_UPDATE_INTR ; /* update ints */
|
||||
dkp_fccy = dkp_ussc = dkp_ma = dkp_sta = 0; /* clear registers */
|
||||
dkp_diagmode = 0; /* clear diagnostic mode */
|
||||
dkp_map = 0;
|
||||
@@ -724,7 +985,7 @@ return SCPE_OK;
|
||||
t_stat dkp_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
int32 i, p;
|
||||
t_stat r;
|
||||
t_stat r;
|
||||
|
||||
uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; /* restore capac */
|
||||
r = attach_unit (uptr, cptr); /* attach */
|
||||
@@ -751,10 +1012,12 @@ return SCPE_OK;
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#if defined(_OLD_CODE_)
|
||||
|
||||
#define BOOT_START 02000
|
||||
#define BOOT_UNIT 02021
|
||||
#define BOOT_SEEK 02022
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
|
||||
#define BOOT_LEN (sizeof(boot_rom) / sizeof(int32))
|
||||
|
||||
static const int32 boot_rom[] = {
|
||||
0060233, /* NIOC 0,DKP ; clear disk */
|
||||
@@ -774,12 +1037,13 @@ static const int32 boot_rom[] = {
|
||||
0101113, /* MOVL# 0,0,SNC ; skip if done */
|
||||
0000776, /* JMP .-2 */
|
||||
0000377, /* JMP 377 */
|
||||
0000016, /* USSC: 0.B1+0.B7+0.B11+16 */
|
||||
0000016, /* USSC: 0.B1+0.B7+0.B11+16 */
|
||||
0175000, /* SEKCMD: 175000 */
|
||||
0074000, /* SEKDN: 074000 */
|
||||
0074000, /* SEKDN: 074000 */
|
||||
0174000 /* REDCMD: 174000 */
|
||||
};
|
||||
|
||||
|
||||
t_stat dkp_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i, dtype;
|
||||
@@ -794,3 +1058,27 @@ saved_PC = BOOT_START;
|
||||
SR = 0100000 + DEV_DKP;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#endif /* _OLD_CODE_ */
|
||||
|
||||
|
||||
|
||||
#define BOOT_START 0375
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
|
||||
|
||||
static const int32 boot_rom[] = {
|
||||
0062677 /* IORST ; reset the I/O system */
|
||||
, 0060133 /* NIOS DKP ; start the disk */
|
||||
, 0000377 /* JMP 377 ; wait for the world */
|
||||
} ;
|
||||
|
||||
|
||||
t_stat dkp_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = (uint16) boot_rom[i];
|
||||
saved_PC = BOOT_START;
|
||||
SR = 0100000 + DEV_DKP;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* nova_dsk.c: 4019 fixed head disk simulator
|
||||
|
||||
Copyright (c) 1993-2006, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -25,6 +25,10 @@
|
||||
|
||||
dsk fixed head disk
|
||||
|
||||
04-Jul-07 BKR device name changed to DG's DSK from DEC's DK,
|
||||
DEV_xxx macros now used for consistency,
|
||||
added secret DG DIC function,
|
||||
fixed boot info table size calculation
|
||||
15-May-06 RMS Fixed bug in autosize attach (reported by David Gesswein)
|
||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||
26-Jul-03 RMS Fixed bug in set size routine
|
||||
@@ -95,12 +99,13 @@ static const int32 sector_map[] = {
|
||||
extern uint16 M[];
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
extern int32 saved_PC, SR, AMASK;
|
||||
|
||||
int32 dsk_stat = 0; /* status register */
|
||||
int32 dsk_da = 0; /* disk address */
|
||||
int32 dsk_ma = 0; /* memory address */
|
||||
int32 dsk_wlk = 0; /* wrt lock switches */
|
||||
int32 dsk_stopioe = 1; /* stop on error */
|
||||
int32 dsk_stopioe = 0; /* stop on error */
|
||||
int32 dsk_time = 100; /* time per sector */
|
||||
|
||||
DEVICE dsk_dev;
|
||||
@@ -153,13 +158,14 @@ MTAB dsk_mod[] = {
|
||||
};
|
||||
|
||||
DEVICE dsk_dev = {
|
||||
"DK", &dsk_unit, dsk_reg, dsk_mod,
|
||||
"DSK", &dsk_unit, dsk_reg, dsk_mod,
|
||||
1, 8, 21, 1, 8, 16,
|
||||
NULL, NULL, &dsk_reset,
|
||||
&dsk_boot, &dsk_attach, NULL,
|
||||
&dsk_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
|
||||
/* IOT routine */
|
||||
|
||||
int32 dsk (int32 pulse, int32 code, int32 AC)
|
||||
@@ -184,32 +190,37 @@ switch (code) { /* decode IR<5:7> */
|
||||
case ioDOB: /* DOB */
|
||||
dsk_ma = AC & AMASK; /* save mem addr */
|
||||
break;
|
||||
|
||||
case ioDIC: /* DIC - undocumented DG feature(!) */
|
||||
rval = 256 ; /* return fixed sector size for DG for now */
|
||||
break ;
|
||||
} /* end switch code */
|
||||
|
||||
if (pulse) { /* any pulse? */
|
||||
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
|
||||
dev_done = dev_done & ~INT_DSK; /* clear done */
|
||||
int_req = int_req & ~INT_DSK; /* clear int */
|
||||
DEV_CLR_BUSY( INT_DSK ) ;
|
||||
DEV_CLR_DONE( INT_DSK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
dsk_stat = 0; /* clear status */
|
||||
sim_cancel (&dsk_unit); /* stop I/O */
|
||||
}
|
||||
|
||||
if ((pulse == iopP) && ((dsk_wlk >> GET_DISK (dsk_da)) & 1)) { /* wrt lock? */
|
||||
dev_done = dev_done | INT_DSK; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
DEV_SET_DONE( INT_DSK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
dsk_stat = DSKS_ERR + DSKS_WLS; /* set status */
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (pulse & 1) { /* read or write? */
|
||||
if (((uint32) (dsk_da * DSK_NUMWD)) >= dsk_unit.capac) { /* inv sev? */
|
||||
dev_done = dev_done | INT_DSK; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
DEV_SET_DONE( INT_DSK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */
|
||||
return rval; /* done */
|
||||
}
|
||||
dsk_unit.FUNC = pulse; /* save command */
|
||||
dev_busy = dev_busy | INT_DSK; /* set busy */
|
||||
DEV_SET_BUSY( INT_DSK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
t = sector_map[dsk_da & DSK_MMASK] - GET_SECTOR (dsk_time);
|
||||
if (t < 0) t = t + DSK_NUMSC;
|
||||
sim_activate (&dsk_unit, t * dsk_time); /* activate */
|
||||
@@ -217,6 +228,7 @@ if (pulse & 1) { /* read or write? */
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat dsk_svc (UNIT *uptr)
|
||||
@@ -224,9 +236,9 @@ t_stat dsk_svc (UNIT *uptr)
|
||||
int32 i, da, pa;
|
||||
int16 *fbuf = uptr->filebuf;
|
||||
|
||||
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
|
||||
dev_done = dev_done | INT_DSK; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
DEV_CLR_BUSY( INT_DSK ) ;
|
||||
DEV_SET_DONE( INT_DSK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */
|
||||
@@ -241,7 +253,7 @@ if (uptr->FUNC == iopS) { /* read? */
|
||||
}
|
||||
dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK;
|
||||
}
|
||||
if (uptr->FUNC == iopP) { /* write? */
|
||||
else if (uptr->FUNC == iopP) { /* write? */
|
||||
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
|
||||
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
|
||||
fbuf[da + i] = M[pa];
|
||||
@@ -255,43 +267,43 @@ dsk_stat = 0; /* set status */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat dsk_reset (DEVICE *dptr)
|
||||
{
|
||||
dsk_stat = dsk_da = dsk_ma = 0;
|
||||
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
|
||||
dev_done = dev_done & ~INT_DSK; /* clear done */
|
||||
int_req = int_req & ~INT_DSK; /* clear int */
|
||||
DEV_CLR_BUSY( INT_DSK ) ;
|
||||
DEV_CLR_DONE( INT_DSK ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&dsk_unit);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define BOOT_START 2000
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
|
||||
#define BOOT_START 0375
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
|
||||
|
||||
static const int32 boot_rom[] = {
|
||||
060220, /* NIOC DSK ; clear disk */
|
||||
0102400, /* SUB 0,0 ; addr = 0 */
|
||||
061020, /* DOA 0,DSK ; set disk addr */
|
||||
062120, /* DOBS 0,DSK ; set mem addr, rd */
|
||||
063620, /* SKPDN DSK ; done? */
|
||||
000776, /* JMP .-2 */
|
||||
000377, /* JMP 377 */
|
||||
};
|
||||
0062677 /* IORST ; reset the I/O system */
|
||||
, 0060120 /* NIOS DSK ; start the disk */
|
||||
, 0000377 /* JMP 377 ; wait for the world */
|
||||
} ;
|
||||
|
||||
|
||||
t_stat dsk_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
extern int32 saved_PC;
|
||||
int32 i;
|
||||
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = (uint16) boot_rom[i];
|
||||
saved_PC = BOOT_START;
|
||||
SR = 0100000 + DEV_DSK;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat dsk_attach (UNIT *uptr, char *cptr)
|
||||
@@ -308,6 +320,7 @@ uptr->capac = UNIT_GETP (uptr->flags) * DSK_DKSIZE; /* set capacity */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
|
||||
/* Change disk size */
|
||||
|
||||
t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* nova_lp.c: NOVA line printer simulator
|
||||
|
||||
Copyright (c) 1993-2007, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -25,16 +25,27 @@
|
||||
|
||||
lpt line printer
|
||||
|
||||
04-Jul-07 BKR DEV_SET/CLR macros now used,
|
||||
<FF>, <CR>, <LF> output character delay now contingent upon non-zero TIME value,
|
||||
LPT can now be DISABLED
|
||||
19-Jan-07 RMS Added UNIT_TEXT
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
|
||||
|
||||
Notes:
|
||||
- data currently masked to 7 bits.
|
||||
- if register TIME is non-zero, then delay TIME events if <FF>, <CR> or <LF> seen
|
||||
- register POS show the current file position
|
||||
- register STOP_IOE determines return value issued if output to unattached LPT is attempted
|
||||
*/
|
||||
|
||||
#include "nova_defs.h"
|
||||
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
|
||||
int32 lpt_stopioe = 0; /* stop on error */
|
||||
|
||||
int32 lpt_stopioe = 0; /* stop on error flag */
|
||||
|
||||
int32 lpt (int32 pulse, int32 code, int32 AC);
|
||||
t_stat lpt_svc (UNIT *uptr);
|
||||
@@ -49,7 +60,7 @@ t_stat lpt_reset (DEVICE *dptr);
|
||||
|
||||
DIB lpt_dib = { DEV_LPT, INT_LPT, PI_LPT, &lpt };
|
||||
|
||||
UNIT lpt_unit = {
|
||||
UNIT lpt_unit = { /* 2007-May-30, bkr */
|
||||
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 0), SERIAL_OUT_WAIT
|
||||
};
|
||||
|
||||
@@ -73,42 +84,51 @@ DEVICE lpt_dev = {
|
||||
&lpt_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
|
||||
/* IOT routine */
|
||||
|
||||
int32 lpt (int32 pulse, int32 code, int32 AC)
|
||||
{
|
||||
if (code == ioDOA)
|
||||
lpt_unit.buf = AC & 0177 ;
|
||||
|
||||
if (code == ioDOA) lpt_unit.buf = AC & 0177;
|
||||
switch (pulse) { /* decode IR<8:9> */
|
||||
|
||||
case iopS: /* start */
|
||||
dev_busy = dev_busy | INT_LPT; /* set busy */
|
||||
dev_done = dev_done & ~INT_LPT; /* clear done, int */
|
||||
int_req = int_req & ~INT_LPT;
|
||||
if ((lpt_unit.buf != 015) && (lpt_unit.buf != 014) &&
|
||||
(lpt_unit.buf != 012))
|
||||
return (lpt_svc (&lpt_unit) << IOT_V_REASON);
|
||||
switch (pulse)
|
||||
{ /* decode IR<8:9> */
|
||||
case iopS: /* start */
|
||||
DEV_SET_BUSY( INT_LPT ) ;
|
||||
DEV_CLR_DONE( INT_LPT ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
if ( lpt_unit.wait )
|
||||
if ( (lpt_unit.buf == 015)
|
||||
|| (lpt_unit.buf == 014)
|
||||
|| (lpt_unit.buf == 012)
|
||||
)
|
||||
{
|
||||
sim_activate (&lpt_unit, lpt_unit.wait);
|
||||
break;
|
||||
break ;
|
||||
}
|
||||
return (lpt_svc (&lpt_unit) << IOT_V_REASON);
|
||||
break;
|
||||
|
||||
case iopC: /* clear */
|
||||
dev_busy = dev_busy & ~INT_LPT; /* clear busy */
|
||||
dev_done = dev_done & ~INT_LPT; /* clear done, int */
|
||||
int_req = int_req & ~INT_LPT;
|
||||
sim_cancel (&lpt_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
case iopC: /* clear */
|
||||
DEV_CLR_BUSY( INT_LPT ) ;
|
||||
DEV_CLR_DONE( INT_LPT ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&lpt_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat lpt_svc (UNIT *uptr)
|
||||
{
|
||||
dev_busy = dev_busy & ~INT_LPT; /* clear busy */
|
||||
dev_done = dev_done | INT_LPT; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
DEV_CLR_BUSY( INT_LPT ) ;
|
||||
DEV_SET_DONE( INT_LPT ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
fputc (uptr->buf, uptr->fileref);
|
||||
@@ -121,14 +141,15 @@ if (ferror (uptr->fileref)) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat lpt_reset (DEVICE *dptr)
|
||||
{
|
||||
lpt_unit.buf = 0;
|
||||
dev_busy = dev_busy & ~INT_LPT; /* clear busy */
|
||||
dev_done = dev_done & ~INT_LPT; /* clear done, int */
|
||||
int_req = int_req & ~INT_LPT;
|
||||
lpt_unit.buf = 0; /* (not DG compatible) */
|
||||
DEV_CLR_BUSY( INT_LPT ) ;
|
||||
DEV_CLR_DONE( INT_LPT ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&lpt_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* nova_mta.c: NOVA magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
mta magnetic tape
|
||||
|
||||
04-Jul-07 BKR fixed boot code to properly boot self-boot tapes;
|
||||
boot routine now uses standard DG APL boot code;
|
||||
device name changed to DG's MTA from DEC's MT.
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
18-Mar-05 RMS Added attached test to detach routine
|
||||
22-Nov-03 CEO DIB returns # records skipped after space fwd
|
||||
@@ -146,9 +149,13 @@
|
||||
#define STA_MON (STA_REW | STA_BOT | STA_WLK | STA_RDY | \
|
||||
STA_PEM) /* set status chg */
|
||||
|
||||
extern uint16 M[];
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
extern uint16 M[];
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
extern int32 SR, AMASK;
|
||||
|
||||
extern t_stat cpu_boot(int32 unitno, DEVICE * dptr ) ;
|
||||
|
||||
|
||||
int32 mta_ma = 0; /* memory address */
|
||||
int32 mta_wc = 0; /* word count */
|
||||
@@ -225,7 +232,7 @@ MTAB mta_mod[] = {
|
||||
};
|
||||
|
||||
DEVICE mta_dev = {
|
||||
"MT", mta_unit, mta_reg, mta_mod,
|
||||
"MTA", mta_unit, mta_reg, mta_mod,
|
||||
MTA_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mta_reset,
|
||||
&mta_boot, &mta_attach, &mta_detach,
|
||||
@@ -601,42 +608,21 @@ else mta_upddsta (uptr, uptr->USTAT & ~STA_WLK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define BOOT_START 02000
|
||||
#define BOOT_UNIT 02020
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
|
||||
|
||||
static const int32 boot_rom[] = {
|
||||
0060222, /* NIOC 0,MTA ; clear disk */
|
||||
0020417, /* LDA 0,UNIT ; unit */
|
||||
0024417, /* LDA 1,REWIND ; cmd */
|
||||
0107000, /* ADD 0,1 ; cmd + unit */
|
||||
0065122, /* DOAS 1,MTA ; start rewind */
|
||||
0070422, /* DIA 2,MTA ; get status */
|
||||
0151213, /* MOVR# 2,2,SNC ; skip if done */
|
||||
0000776, /* JMP .-2 */
|
||||
0126400, /* SUB 1,1 ; ma, wc = 0 */
|
||||
0066022, /* DOB 1,MTA */
|
||||
0067022, /* DOC 1,MTA */
|
||||
0061122, /* DOAS 0,MTA ; start read */
|
||||
0070422, /* DIA 2,MTA ; get status */
|
||||
0151213, /* MOVR# 2,2,SNC ; skip if done */
|
||||
0000776, /* JMP .-2 */
|
||||
0000377, /* JMP 377 */
|
||||
0000000, /* UNIT: */
|
||||
0000010 /* REWIND: 10 */
|
||||
};
|
||||
/* Boot routine */
|
||||
|
||||
t_stat mta_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
extern int32 saved_PC, SR;
|
||||
|
||||
sim_tape_rewind (&mta_unit[unitno]);
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||
M[BOOT_UNIT] = (unitno & CU_M_UNIT) << CU_V_UNIT;
|
||||
saved_PC = BOOT_START;
|
||||
SR = 0100000 + DEV_MTA;
|
||||
return SCPE_OK;
|
||||
}
|
||||
{
|
||||
sim_tape_rewind( &mta_unit[unitno] ) ;
|
||||
/*
|
||||
use common rewind/reset code
|
||||
device reset
|
||||
rewind 'tape' file
|
||||
device
|
||||
unit
|
||||
controller
|
||||
*/
|
||||
cpu_boot( unitno, dptr ) ;
|
||||
SR = 0100000 + DEV_MTA ;
|
||||
return ( SCPE_OK );
|
||||
} /* end of 'mta_boot' */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* nova_plt.c: NOVA plotter simulator
|
||||
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
Copyright (c) 2000-2008, Robert M. Supnik
|
||||
Written by Bruce Ray and used with his gracious permission.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -26,11 +26,20 @@
|
||||
|
||||
plt plotter
|
||||
|
||||
04-Jul-07 BKR added 7B/8B support (default is 8B),
|
||||
DEV_SET/CLR macros now used
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
03-Oct-02 RMS Added DIB
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
06-Jan-02 RMS Revised enable/disable support
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
|
||||
|
||||
Notes:
|
||||
- data masked to 7- or 8- bits, based on 7B or 8B, default is 8-bits
|
||||
- if register TIME is non-zero, then delay TIME events if <FF>, <CR> or <LF> seen
|
||||
- register POS show the current file position
|
||||
- register STOP_IOE determines return value issued if output to unattached PLT is attempted
|
||||
*/
|
||||
|
||||
#include "nova_defs.h"
|
||||
@@ -44,6 +53,12 @@ int32 plt (int32 pulse, int32 code, int32 AC);
|
||||
t_stat plt_svc (UNIT *uptr);
|
||||
t_stat plt_reset (DEVICE *dptr);
|
||||
|
||||
|
||||
/* 7 or 8 bit data mask support for either device */
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8b output */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
|
||||
/* PLT data structures
|
||||
|
||||
plt_dev PLT device descriptor
|
||||
@@ -53,8 +68,8 @@ t_stat plt_reset (DEVICE *dptr);
|
||||
|
||||
DIB plt_dib = { DEV_PLT, INT_PLT, PI_PLT, &plt };
|
||||
|
||||
UNIT plt_unit = {
|
||||
UDATA (&plt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
|
||||
UNIT plt_unit = { /* 2007-May-30, bkr */
|
||||
UDATA (&plt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_8B, 0), SERIAL_OUT_WAIT
|
||||
};
|
||||
|
||||
REG plt_reg[] = {
|
||||
@@ -69,46 +84,58 @@ REG plt_reg[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB plt_mod[] = /* 2007-May-30, bkr */
|
||||
{
|
||||
{ UNIT_8B, 0, "7b", "7B", NULL },
|
||||
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
} ;
|
||||
|
||||
DEVICE plt_dev = {
|
||||
"PLT", &plt_unit, plt_reg, NULL,
|
||||
"PLT", &plt_unit, plt_reg, plt_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &plt_reset,
|
||||
NULL, NULL, NULL,
|
||||
&plt_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
|
||||
/* plotter: IOT routine */
|
||||
|
||||
int32 plt (int32 pulse, int32 code, int32 AC)
|
||||
{
|
||||
if (code == ioDOA) plt_unit.buf = AC & 0377;
|
||||
switch (pulse) { /* decode IR<8:9> */
|
||||
if (code == ioDOA)
|
||||
plt_unit.buf = AC & ((plt_unit.flags & UNIT_8B)?
|
||||
0377
|
||||
: 0177);
|
||||
switch (pulse)
|
||||
{ /* decode IR<8:9> */
|
||||
case iopS: /* start */
|
||||
DEV_SET_BUSY( INT_PLT ) ;
|
||||
DEV_CLR_DONE( INT_PLT ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_activate (&plt_unit, plt_unit.wait); /* activate unit */
|
||||
break;
|
||||
|
||||
case iopS: /* start */
|
||||
dev_busy = dev_busy | INT_PLT; /* set busy */
|
||||
dev_done = dev_done & ~INT_PLT; /* clear done, int */
|
||||
int_req = int_req & ~INT_PLT;
|
||||
sim_activate (&plt_unit, plt_unit.wait); /* activate unit */
|
||||
break;
|
||||
|
||||
case iopC: /* clear */
|
||||
dev_busy = dev_busy & ~INT_PLT; /* clear busy */
|
||||
dev_done = dev_done & ~INT_PLT; /* clear done, int */
|
||||
int_req = int_req & ~INT_PLT;
|
||||
sim_cancel (&plt_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
case iopC: /* clear */
|
||||
DEV_CLR_BUSY( INT_PLT ) ;
|
||||
DEV_CLR_DONE( INT_PLT ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&plt_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat plt_svc (UNIT *uptr)
|
||||
{
|
||||
dev_busy = dev_busy & ~INT_PLT; /* clear busy */
|
||||
dev_done = dev_done | INT_PLT; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
DEV_CLR_BUSY( INT_PLT ) ;
|
||||
DEV_SET_DONE( INT_PLT ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
if ((plt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (plt_stopioe, SCPE_UNATT);
|
||||
if (putc (plt_unit.buf, plt_unit.fileref) == EOF) {
|
||||
@@ -116,18 +143,19 @@ if (putc (plt_unit.buf, plt_unit.fileref) == EOF) {
|
||||
clearerr (plt_unit.fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
plt_unit.pos = plt_unit.pos + 1;
|
||||
++(plt_unit.pos);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat plt_reset (DEVICE *dptr)
|
||||
{
|
||||
plt_unit.buf = 0;
|
||||
dev_busy = dev_busy & ~INT_PLT; /* clear busy */
|
||||
dev_done = dev_done & ~INT_PLT; /* clear done, int */
|
||||
int_req = int_req & ~INT_PLT;
|
||||
plt_unit.buf = 0; /* <not DG compatible> */
|
||||
DEV_CLR_BUSY( INT_PLT ) ;
|
||||
DEV_CLR_DONE( INT_PLT ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&plt_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
191
NOVA/nova_pt.c
191
NOVA/nova_pt.c
@@ -1,6 +1,6 @@
|
||||
/* nova_pt.c: NOVA paper tape read/punch simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -26,15 +26,30 @@
|
||||
ptr paper tape reader
|
||||
ptp paper tape punch
|
||||
|
||||
04-Jul-07 BKR added PTR and PTP device DISABLE capability,
|
||||
added 7B/8B support PTR and PTP (default is 8B),
|
||||
DEV_SET/CLR macros now used,
|
||||
PTR and PTP can now be DISABLED
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
03-Oct-02 RMS Added DIBs
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
|
||||
|
||||
Notes:
|
||||
- data masked to 7- or 8- bits, based on 7B or 8B, default is 8-bits
|
||||
- register TIME is the delay between character read or write operations
|
||||
- register POS show the number of characters read from or sent to the PTR or PTP
|
||||
- register STOP_IOE determines return value issued if output to unattached PTR or PTP is attempted
|
||||
*/
|
||||
|
||||
#include "nova_defs.h"
|
||||
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable ;
|
||||
extern int32 SR ;
|
||||
|
||||
extern t_stat cpu_boot(int32 unitno, DEVICE * dptr ) ;
|
||||
|
||||
|
||||
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
|
||||
@@ -44,6 +59,14 @@ t_stat ptr_svc (UNIT *uptr);
|
||||
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);
|
||||
|
||||
|
||||
/* 7 or 8 bit data mask support for either device */
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8b output */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
|
||||
|
||||
/* PTR data structures
|
||||
|
||||
@@ -54,8 +77,8 @@ t_stat ptp_reset (DEVICE *dptr);
|
||||
|
||||
DIB ptr_dib = { DEV_PTR, INT_PTR, PI_PTR, &ptr };
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
UNIT ptr_unit = { /* 2007-May-30, bkr */
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE+UNIT_8B, 0),
|
||||
SERIAL_IN_WAIT
|
||||
};
|
||||
|
||||
@@ -71,12 +94,19 @@ REG ptr_reg[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ptr_mod[] = /* 2007-May-30, bkr */
|
||||
{
|
||||
{ UNIT_8B, 0, "7b", "7B", NULL },
|
||||
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
} ;
|
||||
|
||||
DEVICE ptr_dev = {
|
||||
"PTR", &ptr_unit, ptr_reg, NULL,
|
||||
"PTR", &ptr_unit, ptr_reg, ptr_mod /* 2007-May-30, bkr */,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptr_reset,
|
||||
NULL, NULL, NULL,
|
||||
&ptr_dib, 0
|
||||
&ptr_boot, NULL, NULL,
|
||||
&ptr_dib, DEV_DISABLE /* 2007-May-30, bkr */
|
||||
};
|
||||
|
||||
/* PTP data structures
|
||||
@@ -88,8 +118,9 @@ DEVICE ptr_dev = {
|
||||
|
||||
DIB ptp_dib = { DEV_PTP, INT_PTP, PI_PTP, &ptp };
|
||||
|
||||
UNIT ptp_unit = {
|
||||
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
|
||||
UNIT ptp_unit =
|
||||
{
|
||||
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_8B, 0), SERIAL_OUT_WAIT
|
||||
};
|
||||
|
||||
REG ptp_reg[] = {
|
||||
@@ -104,46 +135,58 @@ REG ptp_reg[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE ptp_dev = {
|
||||
"PTP", &ptp_unit, ptp_reg, NULL,
|
||||
MTAB ptp_mod[] =
|
||||
{
|
||||
{ UNIT_8B, 0, "7b", "7B", NULL },
|
||||
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
} ;
|
||||
|
||||
DEVICE ptp_dev =
|
||||
{
|
||||
"PTP", &ptp_unit, ptp_reg, ptp_mod /* 2007-May-30, bkr */,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptp_reset,
|
||||
NULL, NULL, NULL,
|
||||
&ptp_dib, 0
|
||||
&ptp_dib, DEV_DISABLE /* 2007-May-30, bkr */
|
||||
};
|
||||
|
||||
|
||||
/* Paper tape reader: IOT routine */
|
||||
|
||||
int32 ptr (int32 pulse, int32 code, int32 AC)
|
||||
{
|
||||
int32 iodata;
|
||||
int32 iodata;
|
||||
|
||||
iodata = (code == ioDIA)? ptr_unit.buf & 0377: 0;
|
||||
switch (pulse) { /* decode IR<8:9> */
|
||||
iodata = (code == ioDIA)?
|
||||
ptr_unit.buf & 0377
|
||||
: 0;
|
||||
switch (pulse)
|
||||
{ /* decode IR<8:9> */
|
||||
case iopS: /* start */
|
||||
DEV_SET_BUSY( INT_PTR ) ;
|
||||
DEV_CLR_DONE( INT_PTR ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_activate (&ptr_unit, ptr_unit.wait); /* activate unit */
|
||||
break;
|
||||
|
||||
case iopS: /* start */
|
||||
dev_busy = dev_busy | INT_PTR; /* set busy */
|
||||
dev_done = dev_done & ~INT_PTR; /* clear done, int */
|
||||
int_req = int_req & ~INT_PTR;
|
||||
sim_activate (&ptr_unit, ptr_unit.wait); /* activate unit */
|
||||
break;
|
||||
|
||||
case iopC: /* clear */
|
||||
dev_busy = dev_busy & ~INT_PTR; /* clear busy */
|
||||
dev_done = dev_done & ~INT_PTR; /* clear done, int */
|
||||
int_req = int_req & ~INT_PTR;
|
||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
case iopC: /* clear */
|
||||
DEV_CLR_BUSY( INT_PTR ) ;
|
||||
DEV_CLR_DONE( INT_PTR ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
return iodata;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat ptr_svc (UNIT *uptr)
|
||||
{
|
||||
int32 temp;
|
||||
int32 temp;
|
||||
|
||||
if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptr_stopioe, SCPE_UNATT);
|
||||
@@ -156,77 +199,99 @@ if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */
|
||||
clearerr (ptr_unit.fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
dev_busy = dev_busy & ~INT_PTR; /* clear busy */
|
||||
dev_done = dev_done | INT_PTR; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
ptr_unit.buf = temp & 0377;
|
||||
ptr_unit.pos = ptr_unit.pos + 1;
|
||||
|
||||
DEV_CLR_BUSY( INT_PTR ) ;
|
||||
DEV_SET_DONE( INT_PTR ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
ptr_unit.buf = temp & ((ptr_unit.flags & UNIT_8B)? 0377: 0177);
|
||||
++(ptr_unit.pos);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat ptr_reset (DEVICE *dptr)
|
||||
{
|
||||
ptr_unit.buf = 0;
|
||||
dev_busy = dev_busy & ~INT_PTR; /* clear busy */
|
||||
dev_done = dev_done & ~INT_PTR; /* clear done, int */
|
||||
int_req = int_req & ~INT_PTR;
|
||||
ptr_unit.buf = 0; /* <not DG compatible> */
|
||||
DEV_CLR_BUSY( INT_PTR ) ;
|
||||
DEV_CLR_DONE( INT_PTR ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Boot routine */
|
||||
|
||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
ptr_reset( dptr ) ;
|
||||
/* set position to 0? */
|
||||
cpu_boot( unitno, dptr ) ;
|
||||
SR = /* low-speed: no high-order bit set */ DEV_PTR ;
|
||||
return ( SCPE_OK );
|
||||
} /* end of 'ptr_boot' */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Paper tape punch: IOT routine */
|
||||
|
||||
int32 ptp (int32 pulse, int32 code, int32 AC)
|
||||
{
|
||||
if (code == ioDOA) ptp_unit.buf = AC & 0377;
|
||||
switch (pulse) { /* decode IR<8:9> */
|
||||
if (code == ioDOA)
|
||||
ptp_unit.buf = AC & 0377;
|
||||
|
||||
case iopS: /* start */
|
||||
dev_busy = dev_busy | INT_PTP; /* set busy */
|
||||
dev_done = dev_done & ~INT_PTP; /* clear done, int */
|
||||
int_req = int_req & ~INT_PTP;
|
||||
sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */
|
||||
break;
|
||||
switch (pulse)
|
||||
{ /* decode IR<8:9> */
|
||||
case iopS: /* start */
|
||||
DEV_SET_BUSY( INT_PTP ) ;
|
||||
DEV_CLR_DONE( INT_PTP ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */
|
||||
break;
|
||||
|
||||
case iopC: /* clear */
|
||||
dev_busy = dev_busy & ~INT_PTP; /* clear busy */
|
||||
dev_done = dev_done & ~INT_PTP; /* clear done, int */
|
||||
int_req = int_req & ~INT_PTP;
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
case iopC: /* clear */
|
||||
DEV_CLR_BUSY( INT_PTP ) ;
|
||||
DEV_CLR_DONE( INT_PTP ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat ptp_svc (UNIT *uptr)
|
||||
{
|
||||
dev_busy = dev_busy & ~INT_PTP; /* clear busy */
|
||||
dev_done = dev_done | INT_PTP; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
DEV_CLR_BUSY( INT_PTP ) ;
|
||||
DEV_SET_DONE( INT_PTP ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptp_stopioe, SCPE_UNATT);
|
||||
if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) {
|
||||
if (putc ((ptp_unit.buf & ((ptp_unit.flags & UNIT_8B)? 0377: 0177)), ptp_unit.fileref) == EOF) {
|
||||
perror ("PTP I/O error");
|
||||
clearerr (ptp_unit.fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
ptp_unit.pos = ptp_unit.pos + 1;
|
||||
++(ptp_unit.pos);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat ptp_reset (DEVICE *dptr)
|
||||
{
|
||||
ptp_unit.buf = 0;
|
||||
dev_busy = dev_busy & ~INT_PTP; /* clear busy */
|
||||
dev_done = dev_done & ~INT_PTP; /* clear done, int */
|
||||
int_req = int_req & ~INT_PTP;
|
||||
ptp_unit.buf = 0; /* <not DG compatible> */
|
||||
DEV_CLR_BUSY( INT_PTP ) ;
|
||||
DEV_CLR_DONE( INT_PTP ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* nova_qty.c: NOVA multiplexor (QTY/ALM) simulator
|
||||
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
Copyright (c) 2000-2008, Robert M. Supnik
|
||||
Written by Bruce Ray and used with his gracious permission.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
qty multiplexor: QTY = 4060, ALM = 42xx
|
||||
|
||||
04-Jul-07 BKR fixed QTY output line number calculation (affected higher line numbers),
|
||||
25-Mar-04 RMS Updated for V3.2
|
||||
12-Jan-04 BKR Initial release
|
||||
includes both original DG "quad" multiplexor (QTY)
|
||||
@@ -198,16 +199,6 @@ DEVICE qty_dev =
|
||||
&qty_dib, (DEV_DISABLE | DEV_DIS | DEV_NET)
|
||||
};
|
||||
|
||||
|
||||
/* <define these in 'nova_defs.h' someday...> */
|
||||
/* (need to mask off non-interrupt bit devices) */
|
||||
|
||||
#define DEV_SET_BUSY( dibp ) dev_busy = dev_busy | ( (dibp)->mask ) ;
|
||||
#define DEV_CLEAR_BUSY( dibp ) dev_busy = dev_busy & ~( (dibp)->mask ) ;
|
||||
#define DEV_SET_DONE( dibp ) dev_done = dev_done | ( (dibp)->mask ) ; int_req = int_req & ~( (dibp)->mask ) ;
|
||||
#define DEV_CLEAR_DONE( dibp ) dev_done = dev_done & ~( (dibp)->mask ) ; int_req = int_req & ~( (dibp)->mask ) ;
|
||||
#define DEV_UPDATE_INTR int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable) ;
|
||||
|
||||
#define DG_RETURN( status, data ) (int32)(((status) << IOT_V_REASON) | ((data) & 0x0FFFF) )
|
||||
|
||||
/*
|
||||
@@ -466,17 +457,17 @@ int qty_update_status( DIB * dibp, TMXR * tmxr_desc )
|
||||
}
|
||||
}
|
||||
/* <we could check each line for TX busy to set DEV_SET_BUSY)?> */
|
||||
DEV_CLEAR_BUSY( dibp )
|
||||
DEV_CLEAR_DONE( dibp )
|
||||
DEV_CLR_BUSY( INT_QTY ) ;
|
||||
DEV_CLR_DONE( INT_QTY ) ;
|
||||
if ( txbusy )
|
||||
{
|
||||
DEV_SET_BUSY( dibp ) ;
|
||||
DEV_SET_BUSY( INT_QTY ) ;
|
||||
}
|
||||
if ( status & (QTY_S_RI | QTY_S_TI) )
|
||||
{
|
||||
DEV_SET_DONE( dibp )
|
||||
DEV_SET_DONE( INT_QTY ) ;
|
||||
}
|
||||
DEV_UPDATE_INTR /* update final intr status */
|
||||
DEV_UPDATE_INTR ; /* update final intr status */
|
||||
return ( status ) ;
|
||||
} /* end of 'qty_update_status' */
|
||||
|
||||
@@ -568,9 +559,9 @@ t_stat qty_common_reset( DIB * dibp, UNIT * unitp, DEVICE * dptr )
|
||||
else qty_dev.flags |= DEV_DIS;
|
||||
}
|
||||
qty_clear( TRUE ) ;
|
||||
DEV_CLEAR_BUSY( dibp ) /* clear busy */
|
||||
DEV_CLEAR_DONE( dibp ) /* clear done, int */
|
||||
DEV_UPDATE_INTR
|
||||
DEV_CLR_BUSY( INT_QTY ) ; /* clear busy */
|
||||
DEV_CLR_DONE( INT_QTY ) ; /* clear done, int */
|
||||
DEV_UPDATE_INTR ;
|
||||
if ( QTY_MASTER_ACTIVE(&qty_desc) )
|
||||
{
|
||||
sim_activate( unitp, tmxr_poll ) ;
|
||||
@@ -692,7 +683,7 @@ int32 qty( int32 pulse, int32 code, int32 AC )
|
||||
break ;
|
||||
|
||||
case ioDOA : /* send character to QTY */
|
||||
line = QTY_LINE_EXTRACT( iodata ) ;
|
||||
line = QTY_LINE_EXTRACT( AC ) ;
|
||||
if ( line < qty_max )
|
||||
if ( QTY_LINE_BIT_SET(line,QTY_L_TXE) )
|
||||
{
|
||||
@@ -979,7 +970,7 @@ int32 alm( int32 pulse, int32 code, int32 AC )
|
||||
/* (mask with 'alm_line_mask' in case ALM mask is different than QTY */
|
||||
alm_section = 0 ;
|
||||
if ( ! ( iodata & QTY_S_RI) )
|
||||
if ( iodata & QTY_S_TI )
|
||||
if ( iodata & QTY_S_TI )
|
||||
{
|
||||
alm_section = 1 ; /* receiver quiet - transmitter done */
|
||||
}
|
||||
@@ -1100,7 +1091,7 @@ int32 alm( int32 pulse, int32 code, int32 AC )
|
||||
* clear device busy
|
||||
*/
|
||||
for ( a = 0 ; a < qty_max ; ++a )
|
||||
if ( 1 )
|
||||
if ( 1 /* (not yet optimized) */ )
|
||||
{
|
||||
QTY_LINE_CLEAR_BIT( a, (QTY_L_RXBZ | QTY_L_RXDN | QTY_L_TXBZ | QTY_L_TXDN) ) ;
|
||||
}
|
||||
@@ -1112,7 +1103,7 @@ int32 alm( int32 pulse, int32 code, int32 AC )
|
||||
|
||||
case iopC :
|
||||
for ( a = 0 ; a < qty_max ; ++a )
|
||||
if ( 1 )
|
||||
if ( 1 /* (not yet optimized) */ )
|
||||
{
|
||||
QTY_LINE_CLEAR_BIT( a, (QTY_L_RXBZ | QTY_L_RXDN | QTY_L_TXBZ | QTY_L_TXDN) ) ;
|
||||
}
|
||||
|
||||
166
NOVA/nova_sys.c
166
NOVA/nova_sys.c
@@ -1,6 +1,6 @@
|
||||
/* nova_sys.c: NOVA simulator interface
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -23,6 +23,10 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
04-Jul-07 BKR DEC's IOF/ION changed to DG's INTDS/INTEN mnemonic,
|
||||
Fixed QTY/ADCV device name,
|
||||
RDSW changed to DDG's READS mnemonic,
|
||||
fixed/enhanced 'load' command for DG-compatible binary tape format
|
||||
26-Mar-04 RMS Fixed warning with -std=c99
|
||||
14-Jan-04 BKR Added support for QTY and ALM
|
||||
04-Jan-04 RMS Fixed 64b issues found by VMS 8.1
|
||||
@@ -45,13 +49,6 @@
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern UNIT cpu_unit;
|
||||
#if defined (ECLIPSE)
|
||||
extern DEVICE map_dev;
|
||||
extern DEVICE fpu_dev;
|
||||
extern DEVICE pit_dev;
|
||||
extern int32 Usermap;
|
||||
extern int32 MapStat;
|
||||
#endif
|
||||
extern DEVICE ptr_dev;
|
||||
extern DEVICE ptp_dev;
|
||||
extern DEVICE plt_dev;
|
||||
@@ -69,6 +66,20 @@ extern DEVICE alm_dev;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 M[];
|
||||
extern int32 saved_PC;
|
||||
extern int32 AMASK;
|
||||
|
||||
#if defined (ECLIPSE)
|
||||
|
||||
extern DEVICE map_dev;
|
||||
extern DEVICE fpu_dev;
|
||||
extern DEVICE pit_dev;
|
||||
extern int32 Usermap;
|
||||
extern int32 MapStat;
|
||||
|
||||
#endif
|
||||
|
||||
extern int32 sim_switches;
|
||||
|
||||
|
||||
/* SCP data structures
|
||||
|
||||
@@ -120,8 +131,7 @@ const char *sim_stop_messages[] = {
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Nested indirect address limit exceeded",
|
||||
"Nested indirect interrupt address limit exceeded",
|
||||
"Nested indirect trap address limit exceeded",
|
||||
"Nested indirect interrupt or trap address limit exceeded",
|
||||
"Read breakpoint",
|
||||
"Write breakpoint"
|
||||
};
|
||||
@@ -147,29 +157,57 @@ const char *sim_stop_messages[] = {
|
||||
If the word count is [-21,-n], then the block is repeated data.
|
||||
If the word count is 1, the block is the start address.
|
||||
If the word count is >1, the block is an error block.
|
||||
|
||||
Notes:
|
||||
'start' block terminates loading.
|
||||
'start' block starting address 1B0 = do not auto-start, 0B0 = auto-start.
|
||||
'start' block starting address is saved in 'save_PC' so a "continue"
|
||||
should start the program.
|
||||
|
||||
specify -i switch ignores checksum errors
|
||||
|
||||
|
||||
internal state machine:
|
||||
|
||||
0,1 get byte count (low and high), ignore leader bytes (<000>)
|
||||
2,3 get origin
|
||||
4,5 get checksum
|
||||
6,7 process data block
|
||||
8 process 'ignore' (error) block
|
||||
*/
|
||||
|
||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
int32 data, csum, count, state, i;
|
||||
uint32 origin;
|
||||
int32 data, csum, count, state, i;
|
||||
int32 origin;
|
||||
int pos ;
|
||||
int block_start ;
|
||||
int done ;
|
||||
|
||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
||||
if ((*cptr != 0) || (flag != 0))
|
||||
return ( SCPE_ARG ) ;
|
||||
state = 0;
|
||||
while ((i = getc (fileref)) != EOF) {
|
||||
block_start = -1 ;
|
||||
done = 0 ;
|
||||
for ( pos = 0 ; (! done) && ((i=getc(fileref)) != EOF) ; ++pos )
|
||||
{
|
||||
i &= 0x00FF ; /* (insure no sign extension) */
|
||||
switch (state) {
|
||||
case 0: /* leader */
|
||||
count = i;
|
||||
state = (count != 0);
|
||||
state = (count != 0) ;
|
||||
if ( state )
|
||||
block_start = pos ;
|
||||
break;
|
||||
case 1: /* high count */
|
||||
csum = count = (i << 8) | count;
|
||||
csum = count = (i << 8) | count ;
|
||||
state = 2;
|
||||
break;
|
||||
case 2: /* low origin */
|
||||
origin = i;
|
||||
state = 3;
|
||||
break;
|
||||
break ;
|
||||
|
||||
case 3: /* high origin */
|
||||
origin = (i << 8) | origin;
|
||||
csum = csum + origin;
|
||||
@@ -180,56 +218,88 @@ while ((i = getc (fileref)) != EOF) {
|
||||
state = 5;
|
||||
break;
|
||||
case 5: /* high checksum */
|
||||
csum = csum + (i << 8);
|
||||
if (count == 1) saved_PC = origin; /* count = 1? */
|
||||
if (count <= 1) { /* count = 0/1? */
|
||||
if (csum & 0177777) return SCPE_CSUM;
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
if (count < 0100000) { /* count > 1 */
|
||||
state = 8;
|
||||
break;
|
||||
}
|
||||
count = 0200000 - count;
|
||||
state = 6;
|
||||
csum = (csum + (i << 8)) & 0xFFFF ;
|
||||
if (count == 1)
|
||||
{
|
||||
/* 'start' block */
|
||||
/* do any auto-start check or inhibit check */
|
||||
saved_PC = (origin & 077777) ; /* 0B0 = auto-start program */
|
||||
/* 1B0 = do not auto start */
|
||||
state = 0 ; /* indicate okay state */
|
||||
done = 1 ; /* we're done! */
|
||||
if ( ! (origin & 0x8000) )
|
||||
{
|
||||
printf( "auto start @ %05o \n", (origin & 0x7FFF) ) ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
if ( ((count & 0x8000) == 0) && (count > 1))
|
||||
{
|
||||
/* 'ignore' block */
|
||||
state = 8 ;
|
||||
}
|
||||
/* 'data' or 'repeat' block */
|
||||
count = 0200000 - count ;
|
||||
if ( count <= 020 )
|
||||
{
|
||||
/* 'data' block */
|
||||
state = 6 ;
|
||||
break ;
|
||||
}
|
||||
/* 'repeat' block (multiple data) */
|
||||
|
||||
if (count > 020) { /* large block */
|
||||
for (count = count - 1; count > 1; count--) {
|
||||
if (origin >= AMASK /* MEMSIZE? */)
|
||||
{
|
||||
return ( SCPE_NXM );
|
||||
}
|
||||
M[origin] = data;
|
||||
origin = origin + 1;
|
||||
}
|
||||
state = 0 ;
|
||||
}
|
||||
state = 0;
|
||||
break;
|
||||
case 6: /* low data */
|
||||
data = i;
|
||||
data = i;
|
||||
state = 7;
|
||||
break;
|
||||
case 7: /* high data */
|
||||
data = (i << 8) | data;
|
||||
csum = csum + data;
|
||||
if (count > 20) { /* large block */
|
||||
for (count = count - 1; count == 1; count--) {
|
||||
if (origin >= MEMSIZE) return SCPE_NXM;
|
||||
M[origin] = data;
|
||||
origin = origin + 1;
|
||||
}
|
||||
}
|
||||
if (origin >= MEMSIZE) return SCPE_NXM;
|
||||
csum = (csum + data) & 0xFFFF ;
|
||||
|
||||
if (origin >= AMASK /* MEMSIZE? */)
|
||||
return SCPE_NXM;
|
||||
M[origin] = data;
|
||||
origin = origin + 1;
|
||||
count = count - 1;
|
||||
if (count == 0) {
|
||||
if (csum & 0177777) return SCPE_CSUM;
|
||||
if ( csum )
|
||||
{
|
||||
printf( "checksum error: block start at %d [0x%x] \n", block_start, block_start ) ;
|
||||
printf( "calculated: 0%o [0x%4x]\n", csum, csum ) ;
|
||||
if ( ! (sim_switches & SWMASK('I')) )
|
||||
return SCPE_CSUM;
|
||||
}
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
state = 6;
|
||||
break;
|
||||
case 8: /* error block */
|
||||
if (i == 0377) state = 0;
|
||||
case 8: /* error (ignore) block */
|
||||
if (i == 0377)
|
||||
state = 0; /* (wait for 'RUBOUT' char) */
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end while */
|
||||
|
||||
/* Ok to find end of tape between blocks or in error state */
|
||||
|
||||
return ((state == 0) || (state == 8))? SCPE_OK: SCPE_FMT;
|
||||
return ( ((state == 0) || (state == 8)) ? SCPE_OK : SCPE_FMT ) ;
|
||||
}
|
||||
|
||||
|
||||
/* Symbol tables */
|
||||
|
||||
#define I_V_FL 18 /* flag bits */
|
||||
@@ -382,8 +452,8 @@ static const char *opcode[] = {
|
||||
"ANDL#", "ANDZL#", "ANDOL#", "ANDCL#",
|
||||
"ANDR#", "ANDZR#", "ANDOR#", "ANDCR#",
|
||||
"ANDS#", "ANDZS#", "ANDOS#", "ANDCS#",
|
||||
"ION", "IOF",
|
||||
"RDSW", "INTA", "MSKO", "IORST", "HALT",
|
||||
"INTEN", "INTDS",
|
||||
"READS", "INTA", "MSKO", "IORST", "HALT",
|
||||
#if !defined (ECLIPSE)
|
||||
"MUL", "DIV", "MULS", "DIVS",
|
||||
"PSHA", "POPA", "SAV", "RET",
|
||||
@@ -517,7 +587,7 @@ static const int32 opc_val[] = {
|
||||
0061001+I_R, 0060001+I_R, 0061201+I_R, 0060201+I_R,
|
||||
0060401+I_BY, 0062001+I_BY,
|
||||
#endif
|
||||
0060000+I_D, 0060100+I_D, 0060200+I_D, 0060300+I_D,
|
||||
0060000+I_RD, 0060100+I_RD, 0060200+I_RD, 0060300+I_RD,
|
||||
0060400+I_RD, 0060500+I_RD, 0060600+I_RD, 0060700+I_RD,
|
||||
0061000+I_RD, 0061100+I_RD, 0061200+I_RD, 0061300+I_RD,
|
||||
0061400+I_RD, 0061500+I_RD, 0061600+I_RD, 0061700+I_RD,
|
||||
@@ -541,7 +611,7 @@ static const char *device[] = {
|
||||
"ERCC", "MAP",
|
||||
#endif
|
||||
"TTI", "TTO", "PTR", "PTP", "RTC", "PLT", "CDR", "LPT",
|
||||
"DSK", "MTA", "DCM", "ADCV", "DKP", "CAS",
|
||||
"DSK", "MTA", "DCM", "QTY" /* "ADCV" */, "DKP", "CAS",
|
||||
"TTI1", "TTO1", "CPU",
|
||||
NULL
|
||||
};
|
||||
|
||||
134
NOVA/nova_tt.c
134
NOVA/nova_tt.c
@@ -1,6 +1,6 @@
|
||||
/* nova_tt.c: NOVA console terminal simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -26,6 +26,9 @@
|
||||
tti terminal input
|
||||
tto terminal output
|
||||
|
||||
04-Jul-07 BKR fixed Dasher CR/LF swap function in 'tti_svc()',
|
||||
DEV_SET/CLR macros now used,
|
||||
TTO device may now be DISABLED
|
||||
29-Dec-03 RMS Added console backpressure support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
05-Jan-02 RMS Fixed calling sequence for setmod
|
||||
@@ -35,12 +38,21 @@
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
31-May-01 RMS Added multiconsole support
|
||||
|
||||
Notes:
|
||||
- TTO output is always masked to 7 bits in this rev
|
||||
- TTO "Dasher" attribute sends '\b' to console instead of '\031'
|
||||
- TTO may be disabled
|
||||
- TTI input is always masked to 7 bits in this rev
|
||||
- TTI "Dasher" attribute swaps <CR> and <LF>
|
||||
- TTI may not be disabled
|
||||
*/
|
||||
|
||||
#include "nova_defs.h"
|
||||
|
||||
#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */
|
||||
#define UNIT_DASHER (1 << UNIT_V_DASHER)
|
||||
|
||||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
|
||||
int32 tti (int32 pulse, int32 code, int32 AC);
|
||||
@@ -78,7 +90,7 @@ MTAB ttx_mod[] = {
|
||||
{ UNIT_DASHER, 0, "ANSI", "ANSI", &ttx_setmod },
|
||||
{ UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx_setmod },
|
||||
{ 0 }
|
||||
};
|
||||
} ;
|
||||
|
||||
DEVICE tti_dev = {
|
||||
"TTI", &tti_unit, tti_reg, ttx_mod,
|
||||
@@ -115,7 +127,7 @@ DEVICE tto_dev = {
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tto_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tto_dib, 0
|
||||
&tto_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* Terminal input: IOT routine */
|
||||
@@ -124,21 +136,25 @@ int32 tti (int32 pulse, int32 code, int32 AC)
|
||||
{
|
||||
int32 iodata;
|
||||
|
||||
iodata = (code == ioDIA)? tti_unit.buf & 0377: 0;
|
||||
switch (pulse) { /* decode IR<8:9> */
|
||||
|
||||
case iopS: /* start */
|
||||
dev_busy = dev_busy | INT_TTI; /* set busy */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
break;
|
||||
if (code == ioDIA)
|
||||
iodata = tti_unit.buf & 0377;
|
||||
else iodata = 0;
|
||||
|
||||
case iopC: /* clear */
|
||||
dev_busy = dev_busy & ~INT_TTI; /* clear busy */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
break;
|
||||
} /* end switch */
|
||||
switch (pulse)
|
||||
{ /* decode IR<8:9> */
|
||||
case iopS: /* start */
|
||||
DEV_SET_BUSY( INT_TTI ) ;
|
||||
DEV_CLR_DONE( INT_TTI ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
break;
|
||||
|
||||
case iopC: /* clear */
|
||||
DEV_CLR_BUSY( INT_TTI ) ;
|
||||
DEV_CLR_DONE( INT_TTI ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
return iodata;
|
||||
}
|
||||
@@ -150,14 +166,19 @@ t_stat tti_svc (UNIT *uptr)
|
||||
int32 temp;
|
||||
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG)
|
||||
return temp; /* no char or error? */
|
||||
tti_unit.buf = temp & 0177;
|
||||
if ((tti_unit.flags & UNIT_DASHER) && (tti_unit.buf == '\r'))
|
||||
tti_unit.buf = '\n'; /* Dasher: cr -> nl */
|
||||
dev_busy = dev_busy & ~INT_TTI; /* clear busy */
|
||||
dev_done = dev_done | INT_TTI; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
tti_unit.pos = tti_unit.pos + 1;
|
||||
if (tti_unit.flags & UNIT_DASHER) {
|
||||
if (tti_unit.buf == '\r')
|
||||
tti_unit.buf = '\n'; /* Dasher: cr -> nl */
|
||||
else if (tti_unit.buf == '\n')
|
||||
tti_unit.buf = '\r' ; /* Dasher: nl -> cr */
|
||||
}
|
||||
DEV_CLR_BUSY( INT_TTI ) ;
|
||||
DEV_SET_DONE( INT_TTI ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
++(uptr->pos) ;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -165,10 +186,10 @@ return SCPE_OK;
|
||||
|
||||
t_stat tti_reset (DEVICE *dptr)
|
||||
{
|
||||
tti_unit.buf = 0;
|
||||
dev_busy = dev_busy & ~INT_TTI; /* clear busy */
|
||||
dev_done = dev_done & ~INT_TTI; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
tti_unit.buf = 0; /* <not DG compatible> */
|
||||
DEV_CLR_BUSY( INT_TTI ) ;
|
||||
DEV_CLR_DONE( INT_TTI ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -177,44 +198,47 @@ return SCPE_OK;
|
||||
|
||||
int32 tto (int32 pulse, int32 code, int32 AC)
|
||||
{
|
||||
if (code == ioDOA) tto_unit.buf = AC & 0377;
|
||||
switch (pulse) { /* decode IR<8:9> */
|
||||
if (code == ioDOA)
|
||||
tto_unit.buf = AC & 0377;
|
||||
|
||||
case iopS: /* start */
|
||||
dev_busy = dev_busy | INT_TTO; /* set busy */
|
||||
dev_done = dev_done & ~INT_TTO; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTO;
|
||||
sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
|
||||
break;
|
||||
|
||||
case iopC: /* clear */
|
||||
dev_busy = dev_busy & ~INT_TTO; /* clear busy */
|
||||
dev_done = dev_done & ~INT_TTO; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTO;
|
||||
sim_cancel (&tto_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
switch (pulse)
|
||||
{ /* decode IR<8:9> */
|
||||
case iopS: /* start */
|
||||
DEV_SET_BUSY( INT_TTO ) ;
|
||||
DEV_CLR_DONE( INT_TTO ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
|
||||
break;
|
||||
|
||||
case iopC: /* clear */
|
||||
DEV_CLR_BUSY( INT_TTO ) ;
|
||||
DEV_CLR_DONE( INT_TTO ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&tto_unit); /* deactivate unit */
|
||||
break;
|
||||
} /* end switch */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat tto_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
t_stat r;
|
||||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
c = tto_unit.buf & 0177;
|
||||
if ((tto_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b';
|
||||
if ((tto_unit.flags & UNIT_DASHER) && (c == 031))
|
||||
c = '\b';
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */
|
||||
return ((r == SCPE_STALL)? SCPE_OK : r); /* !stall? report */
|
||||
}
|
||||
dev_busy = dev_busy & ~INT_TTO; /* clear busy */
|
||||
dev_done = dev_done | INT_TTO; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
tto_unit.pos = tto_unit.pos + 1;
|
||||
DEV_CLR_BUSY( INT_TTO ) ;
|
||||
DEV_SET_DONE( INT_TTO ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
++(tto_unit.pos);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -222,10 +246,10 @@ return SCPE_OK;
|
||||
|
||||
t_stat tto_reset (DEVICE *dptr)
|
||||
{
|
||||
tto_unit.buf = 0;
|
||||
dev_busy = dev_busy & ~INT_TTO; /* clear busy */
|
||||
dev_done = dev_done & ~INT_TTO; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTO;
|
||||
tto_unit.buf = 0; /* <not DG compatible!> */
|
||||
DEV_CLR_BUSY( INT_TTO ) ;
|
||||
DEV_CLR_DONE( INT_TTO ) ;
|
||||
DEV_UPDATE_INTR ;
|
||||
sim_cancel (&tto_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* nova_tt1.c: NOVA second terminal simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M. Supnik
|
||||
Copyright (c) 1993-2008, Robert M. Supnik
|
||||
Written by Bruce Ray and used with his gracious permission.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -207,7 +207,7 @@ return SCPE_OK;
|
||||
t_stat tti1_reset (DEVICE *dptr)
|
||||
{
|
||||
ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */
|
||||
tti1_unit.buf = 0;
|
||||
tti1_unit.buf = 0; /* <not DG compatible> */
|
||||
dev_busy = dev_busy & ~INT_TTI1; /* clear busy */
|
||||
dev_done = dev_done & ~INT_TTI1; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTI1;
|
||||
@@ -275,7 +275,7 @@ return SCPE_OK;
|
||||
t_stat tto1_reset (DEVICE *dptr)
|
||||
{
|
||||
ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */
|
||||
tto1_unit.buf = 0;
|
||||
tto1_unit.buf = 0; /* <not DG compatible> */
|
||||
dev_busy = dev_busy & ~INT_TTO1; /* clear busy */
|
||||
dev_done = dev_done & ~INT_TTO1; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTO1;
|
||||
|
||||
Reference in New Issue
Block a user