1
0
mirror of https://github.com/simh/simh.git synced 2026-03-26 10:12:20 +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:
Bob Supnik
2008-06-24 14:21:00 -07:00
committed by Mark Pizzolato
parent 3cb7c60d5d
commit 59aa4a73b1
136 changed files with 57039 additions and 10915 deletions

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@@ -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' */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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