mirror of
https://github.com/rcornwell/sims.git
synced 2026-03-27 02:14:49 +00:00
KA10: KL10B working, RH20 support added.
This commit is contained in:
@@ -533,7 +533,6 @@ void dte_second(UNIT *uptr) {
|
||||
cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff;
|
||||
M[SEC_DTCHR + base] = ch;
|
||||
M[SEC_DTMTD + base] = FMASK;
|
||||
M[SEC_DTF11 + base] = 0;
|
||||
sim_activate(&dte_unit[1], 100);
|
||||
break;
|
||||
case SEC_SETPRI:
|
||||
@@ -554,8 +553,9 @@ enter_pri:
|
||||
break;
|
||||
case SEC_SETDDT: /* Read character from console */
|
||||
if (cty_in.in_ptr == cty_in.out_ptr) {
|
||||
sim_activate(uptr, 100);
|
||||
return;
|
||||
M[SEC_DTF11 + base] = 0;
|
||||
M[SEC_DTMTI + base] = FMASK;
|
||||
break;
|
||||
}
|
||||
ch = cty_in.buff[cty_in.out_ptr];
|
||||
cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff;
|
||||
@@ -1543,8 +1543,6 @@ lpt_printline(UNIT *uptr, int nl) {
|
||||
uptr->pos += uptr->POS;
|
||||
uptr->COL = 0;
|
||||
uptr->POS = 0;
|
||||
// if (uptr->LINE == 0)
|
||||
// (void)dte_queue(PRI_EMHDS, PRI_EMLPT, 1, &data1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
1021
PDP10/kx10_cpu.c
1021
PDP10/kx10_cpu.c
File diff suppressed because it is too large
Load Diff
@@ -52,7 +52,8 @@
|
||||
|
||||
#if KL
|
||||
#define KLA 1
|
||||
#define KLB 0
|
||||
#define KLB 1
|
||||
#define EPT440 0 /* Force KL10A to 440 section address */
|
||||
#endif
|
||||
|
||||
#ifndef KLA
|
||||
@@ -183,6 +184,7 @@ extern DEBTAB crd_debug[];
|
||||
#define BIT9 00000400000000LL
|
||||
#define BIT10 00000200000000LL
|
||||
#define BIT10_35 00000377777777LL
|
||||
#define BIT12 00000040000000LL
|
||||
#define BIT17 00000001000000LL
|
||||
#define MANT 00000777777777LL
|
||||
#define EXPO 00377000000000LL
|
||||
@@ -293,6 +295,12 @@ extern DEBTAB crd_debug[];
|
||||
#define AMASK 00000017777777LL
|
||||
#define WMASK 0037777LL
|
||||
#define CSHIFT 22
|
||||
#if KL
|
||||
#define RH20_WMASK 003777LL
|
||||
#define RH20_XFER SMASK
|
||||
#define RH20_HALT BIT1
|
||||
#define RH20_REV BIT2
|
||||
#endif
|
||||
#else
|
||||
#define AMASK RMASK
|
||||
#define WMASK RMASK
|
||||
@@ -303,6 +311,10 @@ extern DEBTAB crd_debug[];
|
||||
#define PI_ENABLE 0000000010 /* Clear DONE */
|
||||
#define BUSY 0000000020 /* STOP */
|
||||
#define CCW_COMP 0000000040 /* Write Final CCW */
|
||||
/* RH10 / RH20 interrupt */
|
||||
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
|
||||
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
|
||||
#define CCW_COMP_1 0000000040000LL /* Control word written. */
|
||||
|
||||
#if KI
|
||||
#define DEF_SERIAL 514 /* Default DEC test machine */
|
||||
@@ -353,7 +365,12 @@ extern DEBTAB crd_debug[];
|
||||
#define UNIT_V_MPX (UNIT_V_WAITS + 1)
|
||||
#define UNIT_M_MPX (1 << UNIT_V_MPX)
|
||||
#define UNIT_MPX (UNIT_M_MPX) /* MPX Device for ITS */
|
||||
#define DEV_V_RH (DEV_V_UF + 8) /* Type RH20 */
|
||||
#define CNTRL_V_RH (UNIT_V_UF + 4)
|
||||
#define CNTRL_M_RH 7
|
||||
#define GET_CNTRL_RH(x) (((x) >> CNTRL_V_RH) & CNTRL_M_RH)
|
||||
#define CNTRL_RH(x) (((x) & CNTRL_M_RH) << CNTRL_V_RH)
|
||||
#define DEV_V_RH (DEV_V_UF + 1) /* Type RH20 */
|
||||
#define DEV_M_RH (1 << DEV_V_RH)
|
||||
#define TYPE_RH10 (0 << DEV_V_RH)
|
||||
#define TYPE_RH20 (1 << DEV_V_RH)
|
||||
|
||||
@@ -432,39 +449,64 @@ extern t_stat (*dev_tab[128])(uint32 dev, t_uint64 *data);
|
||||
|
||||
#define VEC_DEVMAX 8 /* max device vec */
|
||||
|
||||
/* DF10 Interface */
|
||||
struct df10 {
|
||||
uint32 status; /* DF10 status word */
|
||||
uint32 cia; /* Initial transfer address */
|
||||
uint32 ccw; /* Next control word address */
|
||||
uint32 wcr; /* CUrrent word count */
|
||||
uint32 cda; /* Current transfer address */
|
||||
uint32 devnum; /* Device number */
|
||||
t_uint64 buf; /* Data buffer */
|
||||
uint8 nxmerr; /* Bit to set for NXM */
|
||||
uint8 ccw_comp; /* Have we written out CCW */
|
||||
} ;
|
||||
|
||||
/* RH10/RH20 Interface */
|
||||
struct rh_if {
|
||||
void (*rh_write)(DEVICE *dptr, struct rh_if *rh, int reg, uint32 data);
|
||||
uint32 (*rh_read)(DEVICE *dptr, struct rh_if *rh, int reg);
|
||||
void (*rh_reset)(DEVICE *dptr);
|
||||
t_uint64 buf; /* Data buffer */
|
||||
uint32 status; /* DF10 status word */
|
||||
uint32 cia; /* Initial transfer address */
|
||||
uint32 ccw; /* Current word count */
|
||||
uint32 wcr;
|
||||
uint32 cda; /* Current transfer address */
|
||||
uint32 devnum; /* Device number */
|
||||
int ivect; /* Interrupt vector */
|
||||
uint8 imode; /* Mode of vector */
|
||||
int cop; /* RH20 Channel operator */
|
||||
uint32 sbar; /* RH20 Starting address */
|
||||
uint32 stcr; /* RH20 Count */
|
||||
uint32 pbar;
|
||||
uint32 ptcr;
|
||||
int reg; /* Last register selected */
|
||||
int drive; /* Last drive selected */
|
||||
int rae; /* Access register error */
|
||||
int attn; /* Attention bits */
|
||||
int xfer_drive; /* Current transfering drive */
|
||||
};
|
||||
|
||||
/* Device context block */
|
||||
struct pdp_dib {
|
||||
uint32 dev_num; /* device address */
|
||||
uint32 num_devs; /* length */
|
||||
t_stat (*io)(uint32 dev, t_uint64 *data);
|
||||
int (*irq)(uint32 dev, int addr);
|
||||
struct rh_if *rh;
|
||||
};
|
||||
|
||||
|
||||
#define RH10_DEV 01000
|
||||
#define RH20_DEV 02000
|
||||
struct rh_dev {
|
||||
uint32 dev_num;
|
||||
DEVICE *dev;
|
||||
struct rh_if *rh;
|
||||
};
|
||||
|
||||
|
||||
typedef struct pdp_dib DIB;
|
||||
|
||||
|
||||
/* DF10 Interface */
|
||||
struct df10 {
|
||||
uint32 status;
|
||||
uint32 cia;
|
||||
uint32 ccw;
|
||||
uint32 wcr;
|
||||
uint32 cda;
|
||||
uint32 devnum;
|
||||
t_uint64 buf;
|
||||
uint8 nxmerr;
|
||||
uint8 ccw_comp;
|
||||
} ;
|
||||
|
||||
|
||||
void df10_setirq(struct df10 *df) ;
|
||||
void df10_writecw(struct df10 *df) ;
|
||||
void df10_finish_op(struct df10 *df, int flags) ;
|
||||
@@ -478,6 +520,18 @@ int dct_write(int u, t_uint64 *data, int c);
|
||||
int dct_is_connect(int u);
|
||||
#endif
|
||||
|
||||
/* Define RH10/RH20 functions */
|
||||
t_stat rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
t_stat rh_devio(uint32 dev, t_uint64 *data);
|
||||
int rh_devirq(uint32 dev, int addr);
|
||||
void rh_setattn(struct rh_if *rh, int unit);
|
||||
int rh_blkend(struct rh_if *rh);
|
||||
void rh_setirq(struct rh_if *rh) ;
|
||||
void rh_finish_op(struct rh_if *rh, int flags);
|
||||
int rh_read(struct rh_if *rh);
|
||||
int rh_write(struct rh_if *rh);
|
||||
|
||||
int ten11_read (int addr, t_uint64 *data);
|
||||
int ten11_write (int addr, t_uint64 data);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* ka10_df.c: DF10 common routines.
|
||||
/* kx10_df.c: DF10 common routines.
|
||||
|
||||
Copyright (c) 2015-2017, Richard Cornwell
|
||||
Copyright (c) 2015-2019, Richard Cornwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,11 +23,14 @@
|
||||
|
||||
#include "kx10_defs.h"
|
||||
|
||||
|
||||
/* Set an IRQ for a DF10 device */
|
||||
void df10_setirq(struct df10 *df) {
|
||||
df->status |= PI_ENABLE;
|
||||
set_interrupt(df->devnum, df->status);
|
||||
}
|
||||
|
||||
/* Generate the DF10 complete word */
|
||||
void df10_writecw(struct df10 *df) {
|
||||
df->status |= 1 << df->ccw_comp;
|
||||
if (df->wcr != 0)
|
||||
@@ -35,6 +38,7 @@ void df10_writecw(struct df10 *df) {
|
||||
M[df->cia|1] = ((uint64)(df->ccw & WMASK) << CSHIFT) | ((uint64)(df->cda) & AMASK);
|
||||
}
|
||||
|
||||
/* Finish off a DF10 transfer */
|
||||
void df10_finish_op(struct df10 *df, int flags) {
|
||||
df->status &= ~BUSY;
|
||||
df->status |= flags;
|
||||
@@ -42,6 +46,7 @@ void df10_finish_op(struct df10 *df, int flags) {
|
||||
df10_setirq(df);
|
||||
}
|
||||
|
||||
/* Setup for a DF10 transfer */
|
||||
void df10_setup(struct df10 *df, uint32 addr) {
|
||||
df->cia = addr & ICWA;
|
||||
df->ccw = df->cia;
|
||||
@@ -50,6 +55,7 @@ void df10_setup(struct df10 *df, uint32 addr) {
|
||||
df->status &= ~(1 << df->ccw_comp);
|
||||
}
|
||||
|
||||
/* Fetch the next IO control word */
|
||||
int df10_fetch(struct df10 *df) {
|
||||
uint64 data;
|
||||
if (df->ccw > MEMSIZE) {
|
||||
@@ -84,6 +90,7 @@ int df10_fetch(struct df10 *df) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read next word */
|
||||
int df10_read(struct df10 *df) {
|
||||
uint64 data;
|
||||
if (df->wcr == 0) {
|
||||
@@ -113,6 +120,7 @@ int df10_read(struct df10 *df) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Write next word */
|
||||
int df10_write(struct df10 *df) {
|
||||
if (df->wcr == 0) {
|
||||
if (!df10_fetch(df))
|
||||
|
||||
@@ -423,7 +423,6 @@ t_stat dp_devio(uint32 dev, uint64 *data) {
|
||||
if (*data & BUSY) {
|
||||
/* Stop controller */
|
||||
sim_cancel(uptr);
|
||||
uptr->STATUS &= ~BUSY;
|
||||
df10_finish_op(df10, 0);
|
||||
}
|
||||
/* Clear flags */
|
||||
@@ -722,7 +721,7 @@ t_stat dp_svc (UNIT *uptr)
|
||||
CLR_BUF(uptr);
|
||||
}
|
||||
if (r)
|
||||
sim_activate(uptr, 25);
|
||||
sim_activate(uptr, 10);
|
||||
else {
|
||||
uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY);
|
||||
uptr->UFLAGS |= DONE;
|
||||
|
||||
750
PDP10/kx10_rh.c
Normal file
750
PDP10/kx10_rh.c
Normal file
@@ -0,0 +1,750 @@
|
||||
/* kx10_rh.c: RH10/RH20 interace routines.
|
||||
|
||||
Copyright (c) 2015-2019, Richard Cornwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "kx10_defs.h"
|
||||
|
||||
|
||||
/* CONI Flags */
|
||||
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
|
||||
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
|
||||
#define DIB_CBOV 0000000000200LL /* Control bus overrun */
|
||||
#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */
|
||||
#define CXR_ILC 0000000004000LL /* Illegal function code */
|
||||
#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */
|
||||
#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */
|
||||
#define CCW_COMP_1 0000000040000LL /* Control word written. */
|
||||
#define CXR_CHAN_ER 0000000100000LL /* Channel Error */
|
||||
#define CXR_EXC 0000000200000LL /* Error in drive transfer */
|
||||
#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */
|
||||
#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */
|
||||
#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */
|
||||
#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */
|
||||
#define CXR_SD_RAE 0000200000000LL /* Register access error */
|
||||
#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */
|
||||
#define B22_FLAG 0004000000000LL /* 22 bit channel */
|
||||
#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */
|
||||
#define CC_CHAN_ACT 0020000000000LL /* Channel in use */
|
||||
#define CC_INH 0040000000000LL /* Disconnect channel */
|
||||
#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */
|
||||
#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */
|
||||
|
||||
/* RH20 CONI Flags */
|
||||
#define RH20_PCR_FULL 0000000000020LL /* Primary command file full */
|
||||
#define RH20_ATTN_ENA 0000000000040LL /* Attention enable */
|
||||
#define RH20_SCR_FULL 0000000000100LL /* Secondary command full */
|
||||
#define RH20_ATTN 0000000000200LL /* Attention */
|
||||
#define RH20_MASS_ENA 0000000000400LL /* Mass bus enable */
|
||||
#define RH20_DATA_OVR 0000000001000LL /* Data overrun */
|
||||
#define RH20_CHAN_RDY 0000000002000LL /* Channel ready to start */
|
||||
#define RH20_RAE 0000000004000LL /* Register access error */
|
||||
#define RH20_DR_RESP 0000000010000LL /* Drive no response */
|
||||
#define RH20_CHAN_ERR 0000000020000LL /* Channel error */
|
||||
#define RH20_SHRT_WC 0000000040000LL /* Short word count */
|
||||
#define RH20_LONG_WC 0000000100000LL /* Long word count */
|
||||
#define RH20_DR_EXC 0000000200000LL /* Exception */
|
||||
#define RH20_DATA_PRI 0000000400000LL /* Data parity error */
|
||||
#define RH20_SBAR 0000001000000LL /* SBAR set */
|
||||
#define RH20_XEND 0000002000000LL /* Transfer ended */
|
||||
|
||||
/* CONO Flags */
|
||||
#define ATTN_EN 0000000000040LL /* enable attention interrupt. */
|
||||
#define REA_EN 0000000000100LL /* enable register error interrupt */
|
||||
#define CBOV_CLR 0000000000200LL /* Clear CBOV */
|
||||
#define CONT_RESET 0000000002000LL /* Clear All error bits */
|
||||
#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */
|
||||
#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */
|
||||
#define OVER_CLR 0000000020000LL /* Clear DTC overrun */
|
||||
#define WRT_CW 0000000040000LL /* Write control word */
|
||||
#define CHN_CLR 0000000100000LL /* Clear Channel Error */
|
||||
#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */
|
||||
#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */
|
||||
|
||||
/* RH20 CONO Flags */
|
||||
#define RH20_DELETE_SCR 0000000000100LL /* Clear SCR */
|
||||
#define RH20_RCLP 0000000000200LL /* Reset command list */
|
||||
#define RH20_MASS_EN 0000000000400LL /* Mass bus enable */
|
||||
#define RH20_XFER_CLR 0000000001000LL /* Clear XFER error */
|
||||
#define RH20_CLR_MBC 0000000002000LL /* Clear MBC */
|
||||
#define RH20_CLR_RAE 0000000004000LL /* Clear RAE error */
|
||||
|
||||
/* DATAO/DATAI */
|
||||
#define CR_REG 0770000000000LL /* Register number */
|
||||
#define LOAD_REG 0004000000000LL /* Load register */
|
||||
#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */
|
||||
#define CR_DRIVE 0000007000000LL
|
||||
#define CR_GEN_EVD 0000000400000LL /* Enable Parity */
|
||||
#define CR_DXES 0000000200000LL /* Disable DXES errors */
|
||||
#define CR_INAD 0000000077600LL
|
||||
#define CR_WTEVM 0000000000100LL /* Verify Parity */
|
||||
#define CR_FUNC 0000000000076LL
|
||||
#define CR_GO 0000000000001LL
|
||||
|
||||
#define IRQ_VECT 0000000000177LL /* Interupt vector */
|
||||
#define IRQ_KI10 0000002000000LL
|
||||
#define IRQ_KA10 0000001000000LL
|
||||
#define FNC_XFER 024 /* >=? data xfr */
|
||||
|
||||
/* Status register settings */
|
||||
#define DS_OFF 0000001 /* offset mode */
|
||||
#define DS_VV 0000100 /* volume valid */
|
||||
#define DS_DRY 0000200 /* drive ready */
|
||||
#define DS_DPR 0000400 /* drive present */
|
||||
#define DS_PGM 0001000 /* programable NI */
|
||||
#define DS_LST 0002000 /* last sector */
|
||||
#define DS_WRL 0004000 /* write locked */
|
||||
#define DS_MOL 0010000 /* medium online */
|
||||
#define DS_PIP 0020000 /* pos in progress */
|
||||
#define DS_ERR 0040000 /* error */
|
||||
#define DS_ATA 0100000 /* attention active */
|
||||
|
||||
/* RH20 channel status flags */
|
||||
#define RH20_MEM_PAR 00200000000000LL /* Memory parity error */
|
||||
#define RH20_ADR_PAR 00100000000000LL /* Address parity error */
|
||||
#define RH20_NOT_WC0 00040000000000LL /* Word count not zero */
|
||||
#define RH20_NXM_ERR 00020000000000LL /* Non existent memory */
|
||||
#define RH20_LAST_ERR 00000400000000LL /* Last transfer error */
|
||||
#define RH20_ERROR 00000200000000LL /* RH20 error */
|
||||
#define RH20_LONG_STS 00000100000000LL /* Did not reach wc */
|
||||
#define RH20_SHRT_STS 00000040000000LL /* WC reached zero */
|
||||
#define RH20_OVER 00000020000000LL /* Overrun error */
|
||||
|
||||
/* 0-37 mass bus register.
|
||||
70 SBAR, block address.
|
||||
71 STCR, neg block count, func
|
||||
72 PBAR
|
||||
73 PTCR
|
||||
74 IVIR Interrupt vector address.
|
||||
75 Diags read.
|
||||
76 Diags write.
|
||||
77 Status (tra,cb test, bar test, ev par, r/w, exc,ebl, 0, attn, sclk
|
||||
*/
|
||||
|
||||
/*
|
||||
* CCW 000..... New channel comand list pointer HALT.
|
||||
010..... Next CCW Address JUMP
|
||||
1xycount-address. x=halt last xfer, y=reverse
|
||||
*/
|
||||
|
||||
extern uint32 eb_ptr;
|
||||
void rh20_setup(struct rh_if *rhc);
|
||||
void rh_setup(struct rh_if *rh, uint32 addr);
|
||||
void rh_writecw(struct rh_if *rh, int nxm);
|
||||
|
||||
|
||||
t_stat
|
||||
rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL)
|
||||
return SCPE_IERR;
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
dptr->flags &= ~DEV_M_RH;
|
||||
dptr->flags |= val;
|
||||
dibp->dev_num &= ~(RH10_DEV|RH20_DEV);
|
||||
dibp->dev_num |= (val) ? RH20_DEV: RH10_DEV;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
|
||||
if (uptr == NULL)
|
||||
return SCPE_IERR;
|
||||
|
||||
dptr = find_dev_from_unit(uptr);
|
||||
if (dptr == NULL)
|
||||
return SCPE_IERR;
|
||||
fprintf (st, "%s", (dptr->flags & TYPE_RH20) ? "RH20" : "RH10");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
t_stat rh_devio(uint32 dev, uint64 *data) {
|
||||
DEVICE *dptr = NULL;
|
||||
struct rh_if *rhc = NULL;
|
||||
int drive;
|
||||
|
||||
for (drive = 0; rh[drive].dev_num != 0; drive++) {
|
||||
if (rh[drive].dev_num == (dev & 0774)) {
|
||||
rhc = rh[drive].rh;
|
||||
dptr = rh[drive].dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rhc == NULL)
|
||||
return SCPE_OK;
|
||||
rhc->devnum = dev & 0774;
|
||||
#if KL
|
||||
if (dptr->flags & TYPE_RH20) {
|
||||
switch(dev & 3) {
|
||||
case CONI:
|
||||
*data = rhc->status & RMASK;
|
||||
if (rhc->attn != 0)
|
||||
*data |= RH20_ATTN;
|
||||
if (rhc->rae != 0)
|
||||
*data |= RH20_RAE;
|
||||
if ((rhc->status & PI_ENABLE) == 0)
|
||||
*data |= RH20_CHAN_RDY;
|
||||
sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n",
|
||||
dptr->name, dev, (uint32)*data, PC, rhc->attn);
|
||||
return SCPE_OK;
|
||||
|
||||
case CONO:
|
||||
clr_interrupt(dev);
|
||||
rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN);
|
||||
rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN);
|
||||
/* Clear flags */
|
||||
if (*data & RH20_CLR_MBC) {
|
||||
if (rhc->rh_reset != NULL)
|
||||
rhc->rh_reset(dptr);
|
||||
rhc->imode = 2;
|
||||
}
|
||||
if (*data & RH20_DELETE_SCR)
|
||||
rhc->status &= ~(RH20_SBAR|RH20_SCR_FULL);
|
||||
if (*data & (RH20_RCLP|RH20_CLR_MBC))
|
||||
rhc->cia = eb_ptr | (rhc->devnum - 0540);
|
||||
if (*data & (RH20_CLR_RAE|RH20_CLR_MBC))
|
||||
rhc->rae = 0;
|
||||
if (*data & PI_ENABLE)
|
||||
rhc->status &= ~PI_ENABLE;
|
||||
if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0)
|
||||
|| (rhc->status & PI_ENABLE))
|
||||
set_interrupt(rhc->devnum, rhc->status);
|
||||
sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n",
|
||||
dptr->name, dev, (uint32)*data, PC, rhc->status);
|
||||
return SCPE_OK;
|
||||
|
||||
case DATAI:
|
||||
*data = 0;
|
||||
if (rhc->status & BUSY && rhc->reg != 04) {
|
||||
rhc->status |= CC_CHAN_ACT;
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (rhc->reg < 040) {
|
||||
int parity;
|
||||
*data = (uint64)(rhc->rh_read(dptr, rhc, rhc->reg) & 0177777);
|
||||
parity = (int)((*data >> 8) ^ *data);
|
||||
parity = (parity >> 4) ^ parity;
|
||||
parity = (parity >> 2) ^ parity;
|
||||
parity = ((parity >> 1) ^ parity) & 1;
|
||||
*data |= ((uint64)(parity ^ 1)) << 17;
|
||||
*data |= ((uint64)(rhc->drive)) << 18;
|
||||
*data |= BIT10;
|
||||
} else if ((rhc->reg & 070) != 070) {
|
||||
rhc->rae = 1;
|
||||
break;
|
||||
} else {
|
||||
switch(rhc->reg & 07) {
|
||||
case 0: *data = rhc->sbar; break;
|
||||
case 1: *data = rhc->stcr; break;
|
||||
case 2: *data = rhc->pbar; break;
|
||||
case 3: *data = rhc->ptcr; break;
|
||||
case 4: *data = rhc->ivect; break;
|
||||
case 5:
|
||||
case 6: break;
|
||||
case 7: *data = 0; break;
|
||||
}
|
||||
}
|
||||
*data |= ((uint64)(rhc->reg)) << 30;
|
||||
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n",
|
||||
dptr->name, dev, *data, rhc->drive, PC);
|
||||
return SCPE_OK;
|
||||
|
||||
case DATAO:
|
||||
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n",
|
||||
dptr->name, dev, *data, PC, rhc->status);
|
||||
rhc->reg = ((int)(*data >> 30)) & 077;
|
||||
rhc->imode |= 2;
|
||||
if (rhc->reg < 040 && rhc->reg != 04) {
|
||||
rhc->drive = (int)(*data >> 18) & 07;
|
||||
}
|
||||
if (*data & LOAD_REG) {
|
||||
if (rhc->reg < 040) {
|
||||
clr_interrupt(dev);
|
||||
/* Check if access error */
|
||||
if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) {
|
||||
set_interrupt(rhc->devnum, rhc->status);
|
||||
return SCPE_OK;
|
||||
}
|
||||
rhc->rh_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777));
|
||||
if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0)
|
||||
|| (rhc->status & PI_ENABLE))
|
||||
set_interrupt(rhc->devnum, rhc->status);
|
||||
/* Check if access error */
|
||||
if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0)
|
||||
set_interrupt(rhc->devnum, rhc->status);
|
||||
else
|
||||
rhc->rae &= ~(1 << rhc->drive);
|
||||
} else if ((rhc->reg & 070) != 070) {
|
||||
if ((*data & BIT9) == 0) {
|
||||
rhc->rae = (1 << rhc->drive);
|
||||
set_interrupt(rhc->devnum, rhc->status);
|
||||
}
|
||||
} else {
|
||||
switch(rhc->reg & 07) {
|
||||
case 0:
|
||||
rhc->sbar = (*data) & (CR_DRIVE|RMASK);
|
||||
rhc->status |= RH20_SBAR;
|
||||
break;
|
||||
case 1:
|
||||
rhc->stcr = (*data) & (BIT10|BIT7|CR_DRIVE|RMASK);
|
||||
rhc->status |= RH20_SCR_FULL;
|
||||
break;
|
||||
case 4:
|
||||
rhc->ivect = (*data & IRQ_VECT);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL))
|
||||
rh20_setup(rhc);
|
||||
return SCPE_OK;
|
||||
}
|
||||
#endif
|
||||
switch(dev & 3) {
|
||||
case CONI:
|
||||
*data = rhc->status & ~(IADR_ATTN|IARD_RAE);
|
||||
if (rhc->attn != 0 && (rhc->status & IADR_ATTN))
|
||||
*data |= IADR_ATTN;
|
||||
if (rhc->rae != 0 && (rhc->status & IARD_RAE))
|
||||
*data |= IARD_RAE;
|
||||
#if KI_22BIT
|
||||
*data |= B22_FLAG;
|
||||
#endif
|
||||
sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n",
|
||||
dptr->name, dev, (uint32)*data, PC, rhc->attn);
|
||||
return SCPE_OK;
|
||||
|
||||
case CONO:
|
||||
clr_interrupt(dev);
|
||||
rhc->status &= ~(07LL|IADR_ATTN|IARD_RAE);
|
||||
rhc->status |= *data & (07LL|IADR_ATTN|IARD_RAE);
|
||||
/* Clear flags */
|
||||
if (*data & CONT_RESET && rhc->rh_reset != NULL)
|
||||
rhc->rh_reset(dptr);
|
||||
if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR))
|
||||
rhc->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR));
|
||||
if (*data & OVER_CLR)
|
||||
rhc->status &= ~(DTC_OVER);
|
||||
if (*data & CBOV_CLR)
|
||||
rhc->status &= ~(DIB_CBOV);
|
||||
if (*data & CXR_ILC)
|
||||
rhc->status &= ~(CXR_ILFC|CXR_SD_RAE);
|
||||
if (*data & WRT_CW)
|
||||
rh_writecw(rhc, 0);
|
||||
if (*data & PI_ENABLE)
|
||||
rhc->status &= ~PI_ENABLE;
|
||||
if (rhc->status & PI_ENABLE)
|
||||
set_interrupt(dev, rhc->status);
|
||||
if ((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0)
|
||||
set_interrupt(dev, rhc->status);
|
||||
sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n",
|
||||
dptr->name, dev, (uint32)*data, PC, rhc->status);
|
||||
return SCPE_OK;
|
||||
|
||||
case DATAI:
|
||||
*data = 0;
|
||||
if (rhc->status & BUSY && rhc->reg != 04) {
|
||||
rhc->status |= CC_CHAN_ACT;
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (rhc->reg == 040) {
|
||||
*data = (uint64)(rhc->rh_read(dptr, rhc, 0) & 077);
|
||||
*data |= ((uint64)(rhc->cia)) << 6;
|
||||
*data |= ((uint64)(rhc->xfer_drive)) << 18;
|
||||
} else if (rhc->reg == 044) {
|
||||
*data = (uint64)rhc->ivect;
|
||||
if (rhc->imode)
|
||||
*data |= IRQ_KI10;
|
||||
else
|
||||
*data |= IRQ_KA10;
|
||||
} else if (rhc->reg == 054) {
|
||||
*data = (uint64)(rhc->rae);
|
||||
} else if ((rhc->reg & 040) == 0) {
|
||||
int parity;
|
||||
*data = (uint64)(rhc->rh_read(dptr, rhc, rhc->reg) & 0177777);
|
||||
parity = (int)((*data >> 8) ^ *data);
|
||||
parity = (parity >> 4) ^ parity;
|
||||
parity = (parity >> 2) ^ parity;
|
||||
parity = ((parity >> 1) ^ parity) & 1;
|
||||
*data |= ((uint64)(parity ^ 1)) << 17;
|
||||
*data |= ((uint64)(rhc->drive)) << 18;
|
||||
}
|
||||
*data |= ((uint64)(rhc->reg)) << 30;
|
||||
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n",
|
||||
dptr->name, dev, *data, rhc->drive, PC);
|
||||
return SCPE_OK;
|
||||
|
||||
case DATAO:
|
||||
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n",
|
||||
dptr->name, dev, *data, PC, rhc->status);
|
||||
rhc->reg = ((int)(*data >> 30)) & 077;
|
||||
rhc->imode &= ~2;
|
||||
if (rhc->reg < 040 && rhc->reg != 04) {
|
||||
rhc->drive = (int)(*data >> 18) & 07;
|
||||
}
|
||||
if (*data & LOAD_REG) {
|
||||
if (rhc->reg == 040) {
|
||||
if ((*data & 1) == 0) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (rhc->status & BUSY) {
|
||||
rhc->status |= CC_CHAN_ACT;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
rhc->status &= ~(CCW_COMP_1|PI_ENABLE);
|
||||
if (((*data >> 1) & 037) < FNC_XFER) {
|
||||
rhc->status |= CXR_ILC;
|
||||
rh_setirq(rhc);
|
||||
sim_debug(DEBUG_DATAIO, dptr,
|
||||
"%s %03o command abort %012llo, %d PC=%06o %06o\n",
|
||||
dptr->name, dev, *data, rhc->drive, PC, rhc->status);
|
||||
return SCPE_OK;
|
||||
}
|
||||
/* Check if access error */
|
||||
if (rhc->rae & (1 << rhc->drive))
|
||||
return SCPE_OK;
|
||||
/* Start command */
|
||||
rh_setup(rhc, (uint32)(*data >> 6));
|
||||
rhc->xfer_drive = (int)(*data >> 18) & 07;
|
||||
rhc->rh_write(dptr, rhc, 0, (uint32)(*data & 077));
|
||||
sim_debug(DEBUG_DATAIO, dptr,
|
||||
"%s %03o command %012llo, %d PC=%06o %06o\n",
|
||||
dptr->name, dev, *data, rhc->drive, PC, rhc->status);
|
||||
} else if (rhc->reg == 044) {
|
||||
/* Set KI10 Irq vector */
|
||||
rhc->ivect = (int)(*data & IRQ_VECT);
|
||||
rhc->imode = (*data & IRQ_KI10) != 0;
|
||||
} else if (rhc->reg == 050) {
|
||||
; /* Diagnostic access to mass bus. */
|
||||
} else if (rhc->reg == 054) {
|
||||
/* clear flags */
|
||||
rhc->rae &= ~(*data & 0377);
|
||||
if (rhc->rae == 0)
|
||||
clr_interrupt(dev);
|
||||
} else if ((rhc->reg & 040) == 0) {
|
||||
rhc->drive = (int)(*data >> 18) & 07;
|
||||
/* Check if access error */
|
||||
if (rhc->rae & (1 << rhc->drive)) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
rhc->rh_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777));
|
||||
}
|
||||
}
|
||||
clr_interrupt(dev);
|
||||
if (((rhc->status & (IADR_ATTN|BUSY)) == IADR_ATTN && rhc->attn != 0)
|
||||
|| (rhc->status & PI_ENABLE))
|
||||
set_interrupt(rhc->devnum, rhc->status);
|
||||
return SCPE_OK;
|
||||
}
|
||||
return SCPE_OK; /* Unreached */
|
||||
}
|
||||
|
||||
/* Handle KI and KL style interrupt vectors */
|
||||
int
|
||||
rh_devirq(uint32 dev, int addr) {
|
||||
DEVICE *dptr = NULL;
|
||||
struct rh_if *rhc = NULL;
|
||||
int drive;
|
||||
|
||||
for (drive = 0; rh[drive].dev_num != 0; drive++) {
|
||||
if (rh[drive].dev_num == (dev & 0774)) {
|
||||
rhc = rh[drive].rh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rhc != NULL) {
|
||||
return (rhc->imode ? rhc->ivect : addr);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* Set the attention flag for a unit */
|
||||
void rh_setattn(struct rh_if *rhc, int unit)
|
||||
{
|
||||
rhc->attn |= 1<<unit;
|
||||
if ((rhc->status & IADR_ATTN) != 0)
|
||||
rh_setirq(rhc);
|
||||
}
|
||||
|
||||
/* Decrement block count for RH20, nop for RH10 */
|
||||
int rh_blkend(struct rh_if *rhc)
|
||||
{
|
||||
#if KL
|
||||
if (rhc->imode == 2) {
|
||||
rhc->cia = (rhc->cia + 1) & RH20_WMASK;
|
||||
if (rhc->cia == 0) {
|
||||
rhc->status |= RH20_XEND;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set an IRQ for a DF10 device */
|
||||
void rh_setirq(struct rh_if *rhc) {
|
||||
rhc->status |= PI_ENABLE;
|
||||
set_interrupt(rhc->devnum, rhc->status);
|
||||
}
|
||||
|
||||
/* Generate the DF10 complete word */
|
||||
void rh_writecw(struct rh_if *rhc, int nxm) {
|
||||
#if KL
|
||||
if (rhc->imode == 2) {
|
||||
uint32 chan = (rhc->devnum - 0540);
|
||||
if (rhc->ptcr & BIT10) {
|
||||
int wc = (rhc->wcr ^ RH20_WMASK) + 1;
|
||||
uint64 wrd1 = SMASK|(uint64)(rhc->ccw);
|
||||
if (nxm)
|
||||
wrd1 |= RH20_NXM_ERR;
|
||||
if (wc != 0) {
|
||||
wrd1 |= RH20_NOT_WC0;
|
||||
if (rhc->status & RH20_XEND) {
|
||||
wrd1 |= RH20_LONG_STS;
|
||||
rhc->status |= RH20_LONG_WC;
|
||||
}
|
||||
} else if ((rhc->status & RH20_XEND) == 0) {
|
||||
wrd1 |= RH20_SHRT_STS;
|
||||
rhc->status |= RH20_SHRT_WC;
|
||||
}
|
||||
M[eb_ptr|chan|1] = wrd1;
|
||||
M[eb_ptr|chan|2] = ((uint64)rhc->cop << 30) |
|
||||
(((uint64)wc & RH20_WMASK) << CSHIFT) |
|
||||
((uint64)(rhc->cda) & AMASK);
|
||||
}
|
||||
rhc->status &= ~(RH20_PCR_FULL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (nxm)
|
||||
rhc->status |= CXR_NXM;
|
||||
rhc->status |= CCW_COMP_1;
|
||||
if (rhc->wcr != 0)
|
||||
rhc->cda++;
|
||||
M[rhc->cia|1] = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK);
|
||||
}
|
||||
|
||||
/* Finish off a DF10 transfer */
|
||||
void rh_finish_op(struct rh_if *rhc, int nxm) {
|
||||
#if KL
|
||||
if (rhc->imode != 2)
|
||||
#endif
|
||||
rhc->status &= ~BUSY;
|
||||
rh_writecw(rhc, nxm);
|
||||
rh_setirq(rhc);
|
||||
#if KL
|
||||
if (rhc->imode == 2 &&
|
||||
(rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL))
|
||||
rh20_setup(rhc);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if KL
|
||||
|
||||
/* Set up for a RH20 transfer */
|
||||
void rh20_setup(struct rh_if *rhc)
|
||||
{
|
||||
int reg;
|
||||
DEVICE *dptr;
|
||||
|
||||
for (reg = 0; rh[reg].dev_num != 0; reg++) {
|
||||
if (rh[reg].rh == rhc) {
|
||||
dptr = rh[reg].dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dptr == 0)
|
||||
return;
|
||||
rhc->pbar = rhc->sbar;
|
||||
rhc->ptcr = rhc->stcr;
|
||||
/* Read drive status */
|
||||
rhc->drive = (rhc->ptcr >> 18) & 07;
|
||||
rhc->status &= ~(RH20_SCR_FULL|PI_ENABLE|RH20_XEND);
|
||||
rhc->status |= RH20_PCR_FULL;
|
||||
reg = rhc->rh_read(dptr, rhc, 1);
|
||||
if ((reg & (DS_DRY|DS_DPR|DS_ERR)) != (DS_DRY|DS_DPR))
|
||||
return;
|
||||
if (rhc->status & RH20_SBAR) {
|
||||
rhc->drive = (rhc->pbar >> 18) & 07;
|
||||
rhc->rh_write(dptr, rhc, 5, (rhc->pbar & 0177777));
|
||||
rhc->status &= ~RH20_SBAR;
|
||||
}
|
||||
if (rhc->ptcr & BIT7) { /* If RCPL reset I/O pointers */
|
||||
rhc->ccw = eb_ptr + (rhc->devnum - 0540);
|
||||
rhc->wcr = 0;
|
||||
}
|
||||
/* Hold block count in cia */
|
||||
rhc->cia = (rhc->ptcr >> 6);
|
||||
rhc->rh_write(dptr, rhc, 0, (rhc->ptcr & 077));
|
||||
rhc->cop = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup for a DF10 transfer */
|
||||
void rh_setup(struct rh_if *rhc, uint32 addr)
|
||||
{
|
||||
rhc->cia = addr & ICWA;
|
||||
rhc->ccw = rhc->cia;
|
||||
rhc->wcr = 0;
|
||||
rhc->status |= BUSY;
|
||||
}
|
||||
|
||||
|
||||
/* Fetch the next IO control word */
|
||||
int rh_fetch(struct rh_if *rhc) {
|
||||
uint64 data;
|
||||
#if KL
|
||||
if (rhc->imode == 2 && (rhc->cop & 2) != 0) {
|
||||
rh_finish_op(rhc, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (rhc->ccw > MEMSIZE) {
|
||||
rh_finish_op(rhc, 1);
|
||||
return 0;
|
||||
}
|
||||
data = M[rhc->ccw];
|
||||
#if KL
|
||||
if (rhc->imode == 2) {
|
||||
while((data & RH20_XFER) == 0) {
|
||||
rhc->ccw = (uint32)(data & AMASK);
|
||||
if ((data & (BIT1|BIT2)) == 0) {
|
||||
rh_finish_op(rhc, 0);
|
||||
break;
|
||||
}
|
||||
if (rhc->ccw > MEMSIZE) {
|
||||
rh_finish_op(rhc, 1);
|
||||
return 0;
|
||||
}
|
||||
data = M[rhc->ccw];
|
||||
}
|
||||
rhc->wcr = (((data >> CSHIFT) & RH20_WMASK) ^ WMASK) + 1;
|
||||
rhc->cda = (data & AMASK);
|
||||
rhc->cop = (data >> 33) & 07;
|
||||
rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
while((data & (WMASK << CSHIFT)) == 0) {
|
||||
if ((data & AMASK) == 0 || (uint32)(data & AMASK) == rhc->ccw) {
|
||||
rh_finish_op(rhc,0);
|
||||
return 0;
|
||||
}
|
||||
rhc->ccw = (uint32)(data & AMASK);
|
||||
if (rhc->ccw > MEMSIZE) {
|
||||
rh_finish_op(rhc, 1);
|
||||
return 0;
|
||||
}
|
||||
data = M[rhc->ccw];
|
||||
}
|
||||
rhc->wcr = (uint32)((data >> CSHIFT) & WMASK);
|
||||
rhc->cda = (uint32)(data & AMASK);
|
||||
rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read next word */
|
||||
int rh_read(struct rh_if *rhc) {
|
||||
uint64 data;
|
||||
if (rhc->wcr == 0) {
|
||||
if (!rh_fetch(rhc))
|
||||
return 0;
|
||||
}
|
||||
rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK);
|
||||
if (rhc->cda != 0) {
|
||||
if (rhc->cda > MEMSIZE) {
|
||||
rh_finish_op(rhc, 1);
|
||||
return 0;
|
||||
}
|
||||
#if KL
|
||||
if (rhc->imode == 2) {
|
||||
data = M[rhc->cda];
|
||||
if (rhc->cop & 01)
|
||||
rhc->cda = (uint32)((rhc->cda - 1) & AMASK);
|
||||
else
|
||||
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
|
||||
} else {
|
||||
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
|
||||
data = M[rhc->cda];
|
||||
}
|
||||
#else
|
||||
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
|
||||
data = M[rhc->cda];
|
||||
#endif
|
||||
} else {
|
||||
data = 0;
|
||||
}
|
||||
rhc->buf = data;
|
||||
if (rhc->wcr == 0) {
|
||||
return rh_fetch(rhc);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Write next word */
|
||||
int rh_write(struct rh_if *rhc) {
|
||||
if (rhc->wcr == 0) {
|
||||
if (!rh_fetch(rhc))
|
||||
return 0;
|
||||
}
|
||||
rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK);
|
||||
if (rhc->cda != 0) {
|
||||
if (rhc->cda > MEMSIZE) {
|
||||
rh_finish_op(rhc, 1);
|
||||
return 0;
|
||||
}
|
||||
#if KL
|
||||
if (rhc->imode == 2) {
|
||||
M[rhc->cda] = rhc->buf;
|
||||
if (rhc->cop & 01)
|
||||
rhc->cda = (uint32)((rhc->cda - 1) & AMASK);
|
||||
else
|
||||
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
|
||||
} else {
|
||||
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
|
||||
M[rhc->cda] = rhc->buf;
|
||||
}
|
||||
#else
|
||||
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
|
||||
M[rhc->cda] = rhc->buf;
|
||||
#endif
|
||||
}
|
||||
if (rhc->wcr == 0) {
|
||||
return rh_fetch(rhc);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
704
PDP10/kx10_rp.c
704
PDP10/kx10_rp.c
File diff suppressed because it is too large
Load Diff
503
PDP10/kx10_rs.c
503
PDP10/kx10_rs.c
@@ -42,72 +42,14 @@
|
||||
#define DTYPE(x) (((x) & UNIT_M_DTYPE) << UNIT_V_DTYPE)
|
||||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define CNTRL_V_CTYPE (UNIT_V_UF + 4)
|
||||
#define CNTRL_M_CTYPE 7
|
||||
#define GET_CNTRL(x) (((x) >> CNTRL_V_CTYPE) & CNTRL_M_CTYPE)
|
||||
#define CNTRL(x) (((x) & CNTRL_M_CTYPE) << CNTRL_V_CTYPE)
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
|
||||
/* CONI Flags */
|
||||
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
|
||||
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
|
||||
#define DIB_CBOV 0000000000200LL /* Control bus overrun */
|
||||
#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */
|
||||
#define CXR_ILC 0000000004000LL /* Illegal function code */
|
||||
#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */
|
||||
#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */
|
||||
#define CCW_COMP_1 0000000040000LL /* Control word written. */
|
||||
#define CXR_CHAN_ER 0000000100000LL /* Channel Error */
|
||||
#define CXR_EXC 0000000200000LL /* Error in drive transfer */
|
||||
#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */
|
||||
#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */
|
||||
#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */
|
||||
#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */
|
||||
#define CXR_SD_RAE 0000200000000LL /* Register access error */
|
||||
#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */
|
||||
#define B22_FLAG 0004000000000LL /* 22 bit channel */
|
||||
#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */
|
||||
#define CC_CHAN_ACT 0020000000000LL /* Channel in use */
|
||||
#define CC_INH 0040000000000LL /* Disconnect channel */
|
||||
#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */
|
||||
#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */
|
||||
|
||||
/* CONO Flags */
|
||||
#define ATTN_EN 0000000000040LL /* enable attention interrupt. */
|
||||
#define REA_EN 0000000000100LL /* enable register error interrupt */
|
||||
#define CBOV_CLR 0000000000200LL /* Clear CBOV */
|
||||
#define CONT_RESET 0000000002000LL /* Clear All error bits */
|
||||
#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */
|
||||
#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */
|
||||
#define OVER_CLR 0000000020000LL /* Clear DTC overrun */
|
||||
#define WRT_CW 0000000040000LL /* Write control word */
|
||||
#define CHN_CLR 0000000100000LL /* Clear Channel Error */
|
||||
#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */
|
||||
#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */
|
||||
|
||||
/* DATAO/DATAI */
|
||||
#define CR_REG 0770000000000LL /* Register number */
|
||||
#define LOAD_REG 0004000000000LL /* Load register */
|
||||
#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */
|
||||
#define CR_DRIVE 0000007000000LL
|
||||
#define CR_GEN_EVD 0000000400000LL /* Enable Parity */
|
||||
#define CR_DXES 0000000200000LL /* Disable DXES errors */
|
||||
#define CR_INAD 0000000077600LL
|
||||
#define CR_WTEVM 0000000000100LL /* Verify Parity */
|
||||
#define CR_FUNC 0000000000076LL
|
||||
#define CR_GO 0000000000001LL
|
||||
|
||||
#define IRQ_VECT 0000000000177LL /* Interupt vector */
|
||||
#define IRQ_KI10 0000002000000LL
|
||||
#define IRQ_KA10 0000001000000LL
|
||||
|
||||
#define CMD u3
|
||||
/* u3 low */
|
||||
/* RSC - 00 - control */
|
||||
|
||||
#define CS1_GO CR_GO /* go */
|
||||
#define CS1_GO 1 /* go */
|
||||
#define CS1_V_FNC 1 /* function pos */
|
||||
#define CS1_M_FNC 037 /* function mask */
|
||||
#define CS1_FNC (CS1_M_FNC << CS1_V_FNC)
|
||||
@@ -228,20 +170,21 @@ struct drvtyp rs_drv_tab[] = {
|
||||
};
|
||||
|
||||
|
||||
struct df10 rs_df10[NUM_DEVS_RS];
|
||||
uint32 rs_xfer_drive[NUM_DEVS_RS];
|
||||
//struct df10 rs_df10[NUM_DEVS_RS];
|
||||
//uint32 rs_xfer_drive[NUM_DEVS_RS];
|
||||
uint64 rs_buf[NUM_DEVS_RS][RS_NUMWD];
|
||||
int rs_reg[NUM_DEVS_RS];
|
||||
int rs_ivect[NUM_DEVS_RS];
|
||||
int rs_imode[NUM_DEVS_RS];
|
||||
int rs_drive[NUM_DEVS_RS];
|
||||
int rs_rae[NUM_DEVS_RS];
|
||||
int rs_attn[NUM_DEVS_RS];
|
||||
//int rs_reg[NUM_DEVS_RS];
|
||||
//int rs_ivect[NUM_DEVS_RS];
|
||||
//int rs_imode[NUM_DEVS_RS];
|
||||
//int rs_drive[NUM_DEVS_RS];
|
||||
//int rs_rae[NUM_DEVS_RS];
|
||||
//int rs_attn[NUM_DEVS_RS];
|
||||
|
||||
t_stat rs_devio(uint32 dev, uint64 *data);
|
||||
int rs_devirq(uint32 dev, int addr);
|
||||
void rs_write(int ctlr, int unit, int reg, uint32 data);
|
||||
uint32 rs_read(int ctlr, int unit, int reg);
|
||||
//t_stat rs_devio(uint32 dev, uint64 *data);
|
||||
//int rs_devirq(uint32 dev, int addr);
|
||||
void rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data);
|
||||
uint32 rs_read(DEVICE *dptr, struct rh_if *rhc, int reg);
|
||||
void rs_rst(DEVICE *dptr);
|
||||
t_stat rs_svc(UNIT *);
|
||||
t_stat rs_boot(int32, DEVICE *);
|
||||
void rs_ini(UNIT *, t_bool);
|
||||
@@ -257,28 +200,38 @@ const char *rs_description (DEVICE *dptr);
|
||||
UNIT rs_unit[] = {
|
||||
/* Controller 1 */
|
||||
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) },
|
||||
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
|
||||
};
|
||||
|
||||
struct rh_if rs_rh[] = {
|
||||
{ &rs_write, &rs_read, &rs_rst},
|
||||
};
|
||||
|
||||
DIB rs_dib[] = {
|
||||
{RH10_DEV, 1, &rs_devio, &rs_devirq}
|
||||
{RH10_DEV, 1, &rh_devio, &rh_devirq, &rs_rh[0]}
|
||||
};
|
||||
|
||||
MTAB rs_mod[] = {
|
||||
#if KL
|
||||
{MTAB_XTD|MTAB_VDV, TYPE_RH10, NULL, "RH10", &rh_set_type, NULL,
|
||||
NULL, "Sets controller to RH10" },
|
||||
{MTAB_XTD|MTAB_VDV, TYPE_RH20, "RH20", "RH20", &rh_set_type, &rh_show_type,
|
||||
NULL, "Sets controller to RH20"},
|
||||
#endif
|
||||
{UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL},
|
||||
{UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL},
|
||||
{UNIT_DTYPE, (RS03_DTYPE << UNIT_V_DTYPE), "RS03", "RS03", &rs_set_type },
|
||||
@@ -287,22 +240,20 @@ MTAB rs_mod[] = {
|
||||
};
|
||||
|
||||
REG rsa_reg[] = {
|
||||
{ORDATA(IVECT, rs_ivect[0], 18)},
|
||||
{FLDATA(IMODE, rs_imode[0], 0)},
|
||||
{ORDATA(XFER, rs_xfer_drive[0], 3), REG_HRO},
|
||||
{ORDATA(DRIVE, rs_drive[0], 3), REG_HRO},
|
||||
{ORDATA(REG, rs_reg[0], 6), REG_RO},
|
||||
{ORDATA(RAE, rs_rae[0], 8), REG_RO},
|
||||
{ORDATA(ATTN, rs_attn[0], 8), REG_RO},
|
||||
{ORDATA(STATUS, rs_df10[0].status, 18), REG_RO},
|
||||
{ORDATA(CIA, rs_df10[0].cia, 18)},
|
||||
{ORDATA(CCW, rs_df10[0].ccw, 18)},
|
||||
{ORDATA(WCR, rs_df10[0].wcr, 18)},
|
||||
{ORDATA(CDA, rs_df10[0].cda, 18)},
|
||||
{ORDATA(DEVNUM, rs_df10[0].devnum, 9), REG_HRO},
|
||||
{ORDATA(BUF, rs_df10[0].buf, 36), REG_HRO},
|
||||
{ORDATA(NXM, rs_df10[0].nxmerr, 8), REG_HRO},
|
||||
{ORDATA(COMP, rs_df10[0].ccw_comp, 8), REG_HRO},
|
||||
{ORDATA(IVECT, rs_rh[0].ivect, 18)},
|
||||
{FLDATA(IMODE, rs_rh[0].imode, 0)},
|
||||
{ORDATA(XFER, rs_rh[0].xfer_drive, 3), REG_HRO},
|
||||
{ORDATA(DRIVE, rs_rh[0].drive, 3), REG_HRO},
|
||||
{ORDATA(REG, rs_rh[0].reg, 6), REG_RO},
|
||||
{ORDATA(RAE, rs_rh[0].rae, 8), REG_RO},
|
||||
{ORDATA(ATTN, rs_rh[0].attn, 8), REG_RO},
|
||||
{ORDATA(STATUS, rs_rh[0].status, 18), REG_RO},
|
||||
{ORDATA(CIA, rs_rh[0].cia, 18)},
|
||||
{ORDATA(CCW, rs_rh[0].ccw, 18)},
|
||||
{ORDATA(WCR, rs_rh[0].wcr, 18)},
|
||||
{ORDATA(CDA, rs_rh[0].cda, 18)},
|
||||
{ORDATA(DEVNUM, rs_rh[0].devnum, 9), REG_HRO},
|
||||
{ORDATA(BUF, rs_rh[0].buf, 36), REG_HRO},
|
||||
{BRDATA(BUFF, &rs_buf[0][0], 16, 64, RS_NUMWD), REG_HRO},
|
||||
{0}
|
||||
};
|
||||
@@ -320,213 +271,44 @@ DEVICE *rs_devs[] = {
|
||||
};
|
||||
|
||||
|
||||
t_stat rs_devio(uint32 dev, uint64 *data) {
|
||||
int ctlr = -1;
|
||||
DEVICE *dptr = NULL;
|
||||
struct df10 *df10;
|
||||
int drive;
|
||||
|
||||
for (drive = 0; rh[drive].dev_num != 0; drive++) {
|
||||
if (rh[drive].dev_num == (dev & 0774)) {
|
||||
dptr = rh[drive].dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dptr == NULL)
|
||||
return SCPE_OK;
|
||||
ctlr = GET_CNTRL(dptr->units[0].flags);
|
||||
df10 = &rs_df10[ctlr];
|
||||
df10->devnum = dev;
|
||||
switch(dev & 3) {
|
||||
case CONI:
|
||||
*data = df10->status & ~(IADR_ATTN|IARD_RAE);
|
||||
if (rs_attn[ctlr] != 0 && (df10->status & IADR_ATTN))
|
||||
*data |= IADR_ATTN;
|
||||
if (rs_rae[ctlr] != 0 && (df10->status & IARD_RAE))
|
||||
*data |= IARD_RAE;
|
||||
#if KI_22BIT
|
||||
*data |= B22_FLAG;
|
||||
#endif
|
||||
sim_debug(DEBUG_CONI, dptr, "RS %03o CONI %06o PC=%o %o\n",
|
||||
dev, (uint32)*data, PC, rs_attn[ctlr]);
|
||||
return SCPE_OK;
|
||||
|
||||
case CONO:
|
||||
clr_interrupt(dev);
|
||||
df10->status &= ~(07LL|IADR_ATTN|IARD_RAE);
|
||||
df10->status |= *data & (07LL|IADR_ATTN|IARD_RAE);
|
||||
/* Clear flags */
|
||||
if (*data & CONT_RESET) {
|
||||
UNIT *uptr=dptr->units;
|
||||
for(drive = 0; drive < NUM_UNITS_RS; drive++, uptr++) {
|
||||
uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076;
|
||||
uptr->DA &= 003400177777;
|
||||
}
|
||||
}
|
||||
if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR))
|
||||
df10->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR));
|
||||
if (*data & OVER_CLR)
|
||||
df10->status &= ~(DTC_OVER);
|
||||
if (*data & CBOV_CLR)
|
||||
df10->status &= ~(DIB_CBOV);
|
||||
if (*data & CXR_ILC)
|
||||
df10->status &= ~(CXR_ILFC|CXR_SD_RAE);
|
||||
if (*data & WRT_CW)
|
||||
df10_writecw(df10);
|
||||
if (*data & PI_ENABLE)
|
||||
df10->status &= ~PI_ENABLE;
|
||||
if (df10->status & PI_ENABLE)
|
||||
set_interrupt(dev, df10->status);
|
||||
if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0)
|
||||
set_interrupt(dev, df10->status);
|
||||
sim_debug(DEBUG_CONO, dptr, "RS %03o CONO %06o %d PC=%06o %06o\n",
|
||||
dev, (uint32)*data, ctlr, PC, df10->status);
|
||||
return SCPE_OK;
|
||||
|
||||
case DATAI:
|
||||
*data = 0;
|
||||
if (df10->status & BUSY && rs_reg[ctlr] != 04) {
|
||||
df10->status |= CC_CHAN_ACT;
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (rs_reg[ctlr] == 040) {
|
||||
*data = (uint64)(rs_read(ctlr, rs_drive[ctlr], 0) & 077);
|
||||
*data |= ((uint64)(df10->cia)) << 6;
|
||||
*data |= ((uint64)(rs_xfer_drive[ctlr])) << 18;
|
||||
} else if (rs_reg[ctlr] == 044) {
|
||||
*data = (uint64)rs_ivect[ctlr];
|
||||
if (rs_imode[ctlr])
|
||||
*data |= IRQ_KI10;
|
||||
else
|
||||
*data |= IRQ_KA10;
|
||||
} else if (rs_reg[ctlr] == 054) {
|
||||
*data = (uint64)(rs_rae[ctlr]);
|
||||
} else if ((rs_reg[ctlr] & 040) == 0) {
|
||||
int parity;
|
||||
|
||||
*data = (uint64)(rs_read(ctlr, rs_drive[ctlr], rs_reg[ctlr]) & 0177777);
|
||||
parity = (int)((*data >> 8) ^ *data);
|
||||
parity = (parity >> 4) ^ parity;
|
||||
parity = (parity >> 2) ^ parity;
|
||||
parity = ((parity >> 1) ^ parity) & 1;
|
||||
*data |= ((uint64)(parity ^ 1)) << 17;
|
||||
*data |= ((uint64)(rs_drive[ctlr])) << 18;
|
||||
}
|
||||
*data |= ((uint64)(rs_reg[ctlr])) << 30;
|
||||
sim_debug(DEBUG_DATAIO, dptr, "RS %03o DATI %012llo, %d %d PC=%06o\n",
|
||||
dev, *data, ctlr, rs_drive[ctlr], PC);
|
||||
return SCPE_OK;
|
||||
|
||||
case DATAO:
|
||||
sim_debug(DEBUG_DATAIO, dptr, "RS %03o DATO %012llo, %d PC=%06o %06o\n",
|
||||
dev, *data, ctlr, PC, df10->status);
|
||||
rs_reg[ctlr] = ((int)(*data >> 30)) & 077;
|
||||
if (rs_reg[ctlr] < 040 && rs_reg[ctlr] != 04) {
|
||||
rs_drive[ctlr] = (int)(*data >> 18) & 07;
|
||||
}
|
||||
if (*data & LOAD_REG) {
|
||||
if (rs_reg[ctlr] == 040) {
|
||||
if ((*data & 1) == 0) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (df10->status & BUSY) {
|
||||
df10->status |= CC_CHAN_ACT;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
df10->status &= ~(1 << df10->ccw_comp);
|
||||
df10->status &= ~PI_ENABLE;
|
||||
if (((*data >> 1) & 077) < FNC_XFER) {
|
||||
df10->status |= CXR_ILC;
|
||||
df10_setirq(df10);
|
||||
sim_debug(DEBUG_DATAIO, dptr,
|
||||
"RS %03o command abort %012llo, %d[%d] PC=%06o %06o\n",
|
||||
dev, *data, ctlr, rs_drive[ctlr], PC, df10->status);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Start command */
|
||||
df10_setup(df10, (uint32)(*data >> 6));
|
||||
rs_xfer_drive[ctlr] = (int)(*data >> 18) & 07;
|
||||
rs_write(ctlr, rs_drive[ctlr], 0, (uint32)(*data & 077));
|
||||
sim_debug(DEBUG_DATAIO, dptr,
|
||||
"RS %03o command %012llo, %d[%d] PC=%06o %06o\n",
|
||||
dev, *data, ctlr, rs_drive[ctlr], PC, df10->status);
|
||||
} else if (rs_reg[ctlr] == 044) {
|
||||
/* Set KI10 Irq vector */
|
||||
rs_ivect[ctlr] = (int)(*data & IRQ_VECT);
|
||||
rs_imode[ctlr] = (*data & IRQ_KI10) != 0;
|
||||
} else if (rs_reg[ctlr] == 050) {
|
||||
; /* Diagnostic access to mass bus. */
|
||||
} else if (rs_reg[ctlr] == 054) {
|
||||
/* clear flags */
|
||||
rs_rae[ctlr] &= ~(*data & 0377);
|
||||
if (rs_rae[ctlr] == 0)
|
||||
clr_interrupt(dev);
|
||||
} else if ((rs_reg[ctlr] & 040) == 0) {
|
||||
rs_drive[ctlr] = (int)(*data >> 18) & 07;
|
||||
/* Check if access error */
|
||||
if (rs_rae[ctlr] & (1 << rs_drive[ctlr])) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
rs_drive[ctlr] = (int)(*data >> 18) & 07;
|
||||
rs_write(ctlr, rs_drive[ctlr], rs_reg[ctlr] & 037,
|
||||
(int)(*data & 0777777));
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
return SCPE_OK; /* Unreached */
|
||||
}
|
||||
|
||||
/* Handle KI and KL style interrupt vectors */
|
||||
int
|
||||
rs_devirq(uint32 dev, int addr) {
|
||||
DEVICE *dptr = NULL;
|
||||
int drive;
|
||||
|
||||
for (drive = 0; rh[drive].dev_num != 0; drive++) {
|
||||
if (rh[drive].dev_num == (dev & 0774)) {
|
||||
dptr = rh[drive].dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dptr != NULL) {
|
||||
drive = GET_CNTRL(dptr->units[0].flags);
|
||||
return (rs_imode[drive] ? rs_ivect[drive] : addr);
|
||||
}
|
||||
return addr;
|
||||
void
|
||||
rs_rst(DEVICE *dptr)
|
||||
{
|
||||
UNIT *uptr=dptr->units;
|
||||
int drive;
|
||||
for(drive = 0; drive < NUM_UNITS_RS; drive++, uptr++) {
|
||||
uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076;
|
||||
uptr->DA &= 003400177777;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rs_write(int ctlr, int unit, int reg, uint32 data) {
|
||||
rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) {
|
||||
int i;
|
||||
DEVICE *dptr = rs_devs[ctlr];
|
||||
struct df10 *df10 = &rs_df10[ctlr];
|
||||
int unit = rhc->drive;
|
||||
UNIT *uptr = &dptr->units[unit];
|
||||
|
||||
if ((uptr->CMD & CR_GO) && reg != 04) {
|
||||
if ((uptr->CMD & CS1_GO) && reg != 04) {
|
||||
uptr->CMD |= (ER1_RMR << 16)|DS_ERR;
|
||||
return;
|
||||
}
|
||||
switch(reg) {
|
||||
case 000: /* control */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d Status=%06o\n", unit, ctlr, uptr->CMD);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o Status=%06o\n", dptr->name, unit, uptr->CMD);
|
||||
/* Set if drive not writable */
|
||||
if (uptr->flags & UNIT_WLK)
|
||||
uptr->CMD |= DS_WRL;
|
||||
/* If drive not ready don't do anything */
|
||||
if ((uptr->CMD & DS_DRY) == 0) {
|
||||
uptr->CMD |= (ER1_RMR << 16)|DS_ERR;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d busy\n", unit, ctlr);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o busy\n", dptr->name, unit);
|
||||
return;
|
||||
}
|
||||
/* Check if GO bit set */
|
||||
if ((data & 1) == 0) {
|
||||
uptr->CMD &= ~076;
|
||||
uptr->CMD |= data & 076;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d no go\n", unit, ctlr);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o no go\n", dptr->name, unit);
|
||||
return; /* No, nop */
|
||||
}
|
||||
uptr->CMD &= DS_ATA|DS_VV|DS_DPR|DS_MOL|DS_WRL;
|
||||
@@ -540,7 +322,7 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
|
||||
case FNC_WCHK: /* write check */
|
||||
case FNC_WRITE: /* write */
|
||||
case FNC_READ: /* read */
|
||||
uptr->CMD |= DS_PIP|CR_GO;
|
||||
uptr->CMD |= DS_PIP|CS1_GO;
|
||||
uptr->DATAPTR = 0;
|
||||
break;
|
||||
|
||||
@@ -549,30 +331,26 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
|
||||
if ((uptr->flags & UNIT_ATT) != 0)
|
||||
uptr->CMD |= DS_VV;
|
||||
uptr->CMD |= DS_DRY;
|
||||
df10_setirq(df10);
|
||||
rh_setirq(rhc);
|
||||
break;
|
||||
|
||||
case FNC_DCLR: /* drive clear */
|
||||
uptr->CMD |= DS_DRY;
|
||||
uptr->CMD &= ~(DS_ATA|CR_GO);
|
||||
rs_attn[ctlr] = 0;
|
||||
clr_interrupt(df10->devnum);
|
||||
uptr->CMD &= ~(DS_ATA|CS1_GO);
|
||||
rhc->attn = 0;
|
||||
clr_interrupt(rhc->devnum);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA)
|
||||
rs_attn[ctlr] = 1;
|
||||
if (dptr->units[i].CMD & DS_ATA)
|
||||
rhc->attn |= 1 << i;
|
||||
}
|
||||
if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0)
|
||||
df10_setirq(df10);
|
||||
break;
|
||||
default:
|
||||
uptr->CMD |= DS_DRY|DS_ERR|DS_ATA;
|
||||
uptr->CMD |= (ER1_ILF << 16);
|
||||
if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0)
|
||||
df10_setirq(df10);
|
||||
}
|
||||
if (uptr->CMD & CR_GO)
|
||||
if (uptr->CMD & CS1_GO)
|
||||
sim_activate(uptr, 100);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o AStatus=%06o\n", unit, uptr->CMD);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o AStatus=%06o\n", dptr->name, unit, uptr->CMD);
|
||||
return;
|
||||
case 001: /* status */
|
||||
break;
|
||||
@@ -585,17 +363,13 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
|
||||
case 003: /* maintenance */
|
||||
break;
|
||||
case 004: /* atten summary */
|
||||
rs_attn[ctlr] = 0;
|
||||
rhc->attn = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (data & (1<<i))
|
||||
rs_unit[(ctlr * 8) + i].CMD &= ~DS_ATA;
|
||||
if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA)
|
||||
rs_attn[ctlr] = 1;
|
||||
dptr->units[i].CMD &= ~DS_ATA;
|
||||
if (dptr->units[i].CMD & DS_ATA)
|
||||
rhc->attn |= 1 << i;
|
||||
}
|
||||
clr_interrupt(df10->devnum);
|
||||
if (((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0) ||
|
||||
(df10->status & PI_ENABLE))
|
||||
df10_setirq(df10);
|
||||
break;
|
||||
case 005: /* sector/track */
|
||||
uptr->DA = data & 0177777;
|
||||
@@ -605,14 +379,13 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
|
||||
break;
|
||||
default:
|
||||
uptr->CMD |= (ER1_ILR<<16)|DS_ERR;
|
||||
rs_rae[ctlr] &= ~(1<<unit);
|
||||
rhc->rae |= 1 << unit;
|
||||
}
|
||||
}
|
||||
|
||||
uint32
|
||||
rs_read(int ctlr, int unit, int reg) {
|
||||
DEVICE *dptr = rs_devs[ctlr];
|
||||
struct df10 *df10 = &rs_df10[ctlr];
|
||||
rs_read(DEVICE *dptr, struct rh_if *rhc, int reg) {
|
||||
int unit = rhc->drive;
|
||||
UNIT *uptr = &dptr->units[unit];
|
||||
uint32 temp = 0;
|
||||
int i;
|
||||
@@ -626,7 +399,7 @@ rs_read(int ctlr, int unit, int reg) {
|
||||
temp = uptr->CMD & 077;
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
temp |= CS1_DVA;
|
||||
if ((df10->status & BUSY) == 0 && (uptr->CMD & CR_GO) == 0)
|
||||
if ((uptr->CMD & CS1_GO) == 0)
|
||||
temp |= CS1_GO;
|
||||
break;
|
||||
case 001: /* status */
|
||||
@@ -637,7 +410,7 @@ rs_read(int ctlr, int unit, int reg) {
|
||||
break;
|
||||
case 004: /* atten summary */
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA) {
|
||||
if (dptr->units[i].CMD & DS_ATA) {
|
||||
temp |= 1 << i;
|
||||
}
|
||||
}
|
||||
@@ -653,7 +426,7 @@ rs_read(int ctlr, int unit, int reg) {
|
||||
break;
|
||||
default:
|
||||
uptr->CMD |= (ER1_ILR<<16);
|
||||
rs_rae[ctlr] &= ~(1<<unit);
|
||||
rhc->rae |= 1 << unit;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
@@ -661,22 +434,21 @@ rs_read(int ctlr, int unit, int reg) {
|
||||
|
||||
t_stat rs_svc (UNIT *uptr)
|
||||
{
|
||||
int dtype = GET_DTYPE(uptr->flags);
|
||||
int ctlr = GET_CNTRL(uptr->flags);
|
||||
int unit;
|
||||
DEVICE *dptr;
|
||||
struct df10 *df;
|
||||
int da;
|
||||
t_stat r;
|
||||
int dtype = GET_DTYPE(uptr->flags);
|
||||
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||
int unit;
|
||||
DEVICE *dptr;
|
||||
struct rh_if *rhc;
|
||||
int da;
|
||||
t_stat r;
|
||||
|
||||
/* Find dptr, and df10 */
|
||||
dptr = rs_devs[ctlr];
|
||||
rhc = &rs_rh[ctlr];
|
||||
unit = uptr - dptr->units;
|
||||
df = &rs_df10[ctlr];
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
uptr->CMD |= (ER1_UNS << 16) | DS_ATA|DS_ERR; /* set drive error */
|
||||
df->status &= ~BUSY;
|
||||
df10_setirq(df);
|
||||
rh_setirq(rhc);
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
@@ -691,26 +463,20 @@ t_stat rs_svc (UNIT *uptr)
|
||||
case FNC_DCLR: /* drive clear */
|
||||
break;
|
||||
case FNC_PRESET: /* read-in preset */
|
||||
rs_attn[ctlr] = 1;
|
||||
uptr->CMD |= DS_DRY|DS_ATA;
|
||||
uptr->CMD &= ~CR_GO;
|
||||
df->status &= ~BUSY;
|
||||
if (df->status & IADR_ATTN)
|
||||
df10_setirq(df);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o seekdone\n", unit);
|
||||
uptr->CMD &= ~CS1_GO;
|
||||
rh_setattn(rhc, unit);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o seekdone\n", dptr->name, unit);
|
||||
break;
|
||||
|
||||
case FNC_SEARCH: /* search */
|
||||
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect ||
|
||||
GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf)
|
||||
uptr->CMD |= (ER1_IAE << 16)|DS_ERR;
|
||||
rs_attn[ctlr] = 1;
|
||||
uptr->CMD |= DS_DRY|DS_ATA;
|
||||
uptr->CMD &= ~CR_GO;
|
||||
df->status &= ~BUSY;
|
||||
if ((df->status & (IADR_ATTN|BUSY)) == IADR_ATTN)
|
||||
df10_setirq(df);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o searchdone\n", unit);
|
||||
uptr->CMD &= ~CS1_GO;
|
||||
rh_setattn(rhc, unit);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o searchdone\n", dptr->name, unit);
|
||||
break;
|
||||
|
||||
case FNC_READ: /* read */
|
||||
@@ -720,13 +486,12 @@ t_stat rs_svc (UNIT *uptr)
|
||||
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect ||
|
||||
GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) {
|
||||
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
|
||||
df->status &= ~BUSY;
|
||||
uptr->CMD &= ~CR_GO;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o readx done\n", unit);
|
||||
df10_finish_op(df, 0);
|
||||
uptr->CMD &= ~CS1_GO;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o readx done\n", dptr->name, unit);
|
||||
rh_finish_op(rhc, 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o read (%d,%d)\n", unit,
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o read (%d,%d)\n", dptr->name, unit,
|
||||
GET_SC(uptr->DA), GET_SF(uptr->DA));
|
||||
da = GET_DA(uptr->DA, dtype) * RS_NUMWD;
|
||||
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET);
|
||||
@@ -737,10 +502,10 @@ t_stat rs_svc (UNIT *uptr)
|
||||
uptr->hwmark = RS_NUMWD;
|
||||
}
|
||||
|
||||
df->buf = rs_buf[ctlr][uptr->DATAPTR++];
|
||||
sim_debug(DEBUG_DATA, dptr, "RSA%o read word %d %012llo %09o %06o\n",
|
||||
unit, uptr->DATAPTR, df->buf, df->cda, df->wcr);
|
||||
if (df10_write(df)) {
|
||||
rhc->buf = rs_buf[ctlr][uptr->DATAPTR++];
|
||||
sim_debug(DEBUG_DATA, dptr, "%s%o read word %d %012llo %09o %06o\n",
|
||||
dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr);
|
||||
if (rh_write(rhc)) {
|
||||
if (uptr->DATAPTR == uptr->hwmark) {
|
||||
/* Increment to next sector. Set Last Sector */
|
||||
uptr->DATAPTR = 0;
|
||||
@@ -751,13 +516,16 @@ t_stat rs_svc (UNIT *uptr)
|
||||
if (GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf)
|
||||
uptr->CMD |= DS_LST;
|
||||
}
|
||||
if (rh_blkend(rhc))
|
||||
goto rd_end;
|
||||
}
|
||||
sim_activate(uptr, 20);
|
||||
} else {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o read done\n", unit);
|
||||
rd_end:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit);
|
||||
uptr->CMD |= DS_DRY;
|
||||
uptr->CMD &= ~CR_GO;
|
||||
df10_finish_op(df, 0);
|
||||
uptr->CMD &= ~CS1_GO;
|
||||
rh_finish_op(rhc, 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
break;
|
||||
@@ -767,20 +535,20 @@ t_stat rs_svc (UNIT *uptr)
|
||||
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect ||
|
||||
GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) {
|
||||
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
|
||||
uptr->CMD &= ~CR_GO;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o writex done\n", unit);
|
||||
df10_finish_op(df, 0);
|
||||
uptr->CMD &= ~CS1_GO;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o writex done\n", dptr->name, unit);
|
||||
rh_finish_op(rhc, 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
r = df10_read(df);
|
||||
rs_buf[ctlr][uptr->DATAPTR++] = df->buf;
|
||||
sim_debug(DEBUG_DATA, dptr, "RSA%o write word %d %012llo %09o %06o\n",
|
||||
unit, uptr->DATAPTR, df->buf, df->cda, df->wcr);
|
||||
r = rh_read(rhc);
|
||||
rs_buf[ctlr][uptr->DATAPTR++] = rhc->buf;
|
||||
sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %09o %06o\n",
|
||||
dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr);
|
||||
if (r == 0 || uptr->DATAPTR == RS_NUMWD) {
|
||||
while (uptr->DATAPTR < RS_NUMWD)
|
||||
rs_buf[ctlr][uptr->DATAPTR++] = 0;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o write (%d,%d)\n", unit,
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o write (%d,%d)\n", dptr->name, unit,
|
||||
GET_SC(uptr->DA), GET_SF(uptr->DA));
|
||||
da = GET_DA(uptr->DA, dtype) * RS_NUMWD;
|
||||
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET);
|
||||
@@ -795,15 +563,18 @@ t_stat rs_svc (UNIT *uptr)
|
||||
if (GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf)
|
||||
uptr->CMD |= DS_LST;
|
||||
}
|
||||
if (rh_blkend(rhc))
|
||||
goto wr_end;
|
||||
}
|
||||
}
|
||||
if (r) {
|
||||
sim_activate(uptr, 20);
|
||||
} else {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "RSA%o write done\n", unit);
|
||||
wr_end:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o write done\n", dptr->name, unit);
|
||||
uptr->CMD |= DS_DRY;
|
||||
uptr->CMD &= ~CR_GO;
|
||||
df10_finish_op(df, 0);
|
||||
uptr->CMD &= ~CS1_GO;
|
||||
rh_finish_op(rhc, 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
break;
|
||||
@@ -831,12 +602,10 @@ rs_reset(DEVICE * rstr)
|
||||
{
|
||||
int ctlr;
|
||||
for (ctlr = 0; ctlr < NUM_DEVS_RS; ctlr++) {
|
||||
rs_df10[ctlr].devnum = rs_dib[ctlr].dev_num;
|
||||
rs_df10[ctlr].nxmerr = 19;
|
||||
rs_df10[ctlr].ccw_comp = 14;
|
||||
rs_df10[ctlr].status = 0;
|
||||
rs_attn[ctlr] = 0;
|
||||
rs_rae[ctlr] = 0;
|
||||
rs_rh[ctlr].devnum = rs_dib[ctlr].dev_num;
|
||||
rs_rh[ctlr].status = 0;
|
||||
rs_rh[ctlr].attn = 0;
|
||||
rs_rh[ctlr].rae = 0;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -846,16 +615,16 @@ t_stat
|
||||
rs_boot(int32 unit_num, DEVICE * rptr)
|
||||
{
|
||||
UNIT *uptr = &rptr->units[unit_num];
|
||||
int ctlr = GET_CNTRL(uptr->flags);
|
||||
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||
struct rh_if *rhc;
|
||||
DEVICE *dptr;
|
||||
struct df10 *df;
|
||||
uint32 addr;
|
||||
uint32 ptr = 0;
|
||||
uint64 word;
|
||||
int wc;
|
||||
|
||||
df = &rs_df10[ctlr];
|
||||
dptr = rs_devs[ctlr];
|
||||
rhc = &rs_rh[ctlr];
|
||||
(void)sim_fseek(uptr->fileref, 0, SEEK_SET);
|
||||
(void)sim_fread (&rs_buf[0][0], sizeof(uint64), RS_NUMWD, uptr->fileref);
|
||||
uptr->CMD |= DS_VV;
|
||||
@@ -873,9 +642,9 @@ rs_boot(int32 unit_num, DEVICE * rptr)
|
||||
addr = rs_buf[0][ptr] & RMASK;
|
||||
wc = (rs_buf[0][ptr++] >> 18) & RMASK;
|
||||
word = rs_buf[0][ptr++];
|
||||
rs_reg[ctlr] = 040;
|
||||
rs_drive[ctlr] = uptr - dptr->units;
|
||||
df->status |= CCW_COMP_1|PI_ENABLE;
|
||||
rhc->reg = 040;
|
||||
rhc->drive = uptr - dptr->units;
|
||||
rhc->status |= CCW_COMP_1|PI_ENABLE;
|
||||
PC = word & RMASK;
|
||||
return SCPE_OK;
|
||||
|
||||
@@ -905,8 +674,8 @@ t_stat rs_attach (UNIT *uptr, CONST char *cptr)
|
||||
uptr->CMD |= DS_DPR|DS_MOL|DS_DRY;
|
||||
if (uptr->flags & UNIT_WLK)
|
||||
uptr->CMD |= DS_WRL;
|
||||
rs_df10[ctlr].status |= PI_ENABLE;
|
||||
set_interrupt(dib->dev_num, rs_df10[ctlr].status);
|
||||
rs_rh[ctlr].status |= PI_ENABLE;
|
||||
set_interrupt(dib->dev_num, rs_rh[ctlr].status);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -523,12 +523,22 @@ int get_word(FILE *fileref, uint64 *word)
|
||||
|
||||
if (sim_fread(cbuf, 1, 5, fileref) != 5)
|
||||
return 1;
|
||||
*word = ((uint64)(cbuf[0]) << 29) |
|
||||
((uint64)(cbuf[1]) << 22) |
|
||||
((uint64)(cbuf[2]) << 15) |
|
||||
((uint64)(cbuf[3]) << 8) |
|
||||
((uint64)(cbuf[4] & 0177) << 1) |
|
||||
((uint64)(cbuf[4] & 0200) >> 7);
|
||||
#if 1
|
||||
*word = ((uint64)(cbuf[0] & 0177) << 29) |
|
||||
((uint64)(cbuf[1] & 0177) << 22) |
|
||||
((uint64)(cbuf[2] & 0177) << 15) |
|
||||
((uint64)(cbuf[3] & 0177) << 8) |
|
||||
((uint64)(cbuf[4] & 0177) << 1);
|
||||
if (cbuf[4] & 0200)
|
||||
*word |= 1;
|
||||
#endif
|
||||
#if 0
|
||||
*word = ((uint64)(cbuf[0] & 0377) << 28) |
|
||||
((uint64)(cbuf[1] & 0377) << 20) |
|
||||
((uint64)(cbuf[2] & 0377) << 12) |
|
||||
((uint64)(cbuf[3] & 0377) << 4) |
|
||||
(uint64)(cbuf[4] & 017);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -613,7 +623,6 @@ cont = 1;
|
||||
do {
|
||||
|
||||
wc = get_word(fileref, &data);
|
||||
// wc = sim_fread (&data, sizeof (uint64), 1, fileref);/* read blk hdr */
|
||||
if (wc != 0) /* error? */
|
||||
return SCPE_FMT;
|
||||
bsz = (int32) ((data & RMASK) - 1); /* get count */
|
||||
@@ -630,9 +639,6 @@ do {
|
||||
return SCPE_FMT;
|
||||
}
|
||||
ndir = bsz;
|
||||
// ndir = sim_fread (dirbuf, sizeof (uint64), bsz, fileref);
|
||||
// if (ndir < bsz) /* error */
|
||||
// return SCPE_FMT;
|
||||
break;
|
||||
|
||||
case EXE_PDV: /* optional */
|
||||
@@ -646,9 +652,6 @@ do {
|
||||
if (get_word(fileref, &entbuf[i]))
|
||||
return SCPE_FMT;
|
||||
}
|
||||
// entvec = sim_fread (entbuf, sizeof (uint64), bsz, fileref);
|
||||
// if (entvec < 2) /* error? */
|
||||
// return SCPE_FMT;
|
||||
entvec = bsz;
|
||||
cont = 0; /* stop */
|
||||
break;
|
||||
@@ -673,24 +676,22 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */
|
||||
(void)sim_fseek (fileref, (fpage << PAG_V_PN) * 5, SEEK_SET);
|
||||
for (k = 0; k < PAG_SIZE; k++) {
|
||||
if (get_word(fileref, &pagbuf[k]))
|
||||
return SCPE_FMT;
|
||||
break;
|
||||
}
|
||||
// wc = sim_fread (pagbuf, sizeof (uint64), PAG_SIZE, fileref);
|
||||
// if (wc < PAG_SIZE)
|
||||
// return SCPE_FMT;
|
||||
fpage++;
|
||||
}
|
||||
ma = mpage << PAG_V_PN; /* mem addr */
|
||||
for (k = 0; k < PAG_SIZE; k++, ma++) { /* copy buf to mem */
|
||||
if (ma > MEMSIZE)
|
||||
return SCPE_NXM;
|
||||
fprintf(stderr, "M %06o %012llo\n", ma, pagbuf[k]);
|
||||
M[ma] = fpage? (pagbuf[k] & FMASK): 0;
|
||||
} /* end copy */
|
||||
} /* end rpt */
|
||||
} /* end directory */
|
||||
if (entvec && entbuf[1])
|
||||
PC = (int32) (entbuf[1] & RMASK); /* start addr */
|
||||
else if (entvec == 0)
|
||||
PC = (int32) (M[0120] & RMASK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
581
PDP10/kx10_tu.c
581
PDP10/kx10_tu.c
@@ -39,69 +39,12 @@
|
||||
/* Flags in the unit flags word */
|
||||
|
||||
#define TU_UNIT UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE
|
||||
#define CNTRL_V_CTYPE (MTUF_V_UF)
|
||||
#define CNTRL_M_CTYPE 7
|
||||
#define GET_CNTRL(x) (((x) >> CNTRL_V_CTYPE) & CNTRL_M_CTYPE)
|
||||
#define CNTRL(x) (((x) & CNTRL_M_CTYPE) << CNTRL_V_CTYPE)
|
||||
|
||||
/* CONI Flags */
|
||||
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
|
||||
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
|
||||
#define DIB_CBOV 0000000000200LL /* Control bus overrun */
|
||||
#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */
|
||||
#define CXR_ILC 0000000004000LL /* Illegal function code */
|
||||
#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */
|
||||
#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */
|
||||
#define CCW_COMP_1 0000000040000LL /* Control word written. */
|
||||
#define CXR_CHAN_ER 0000000100000LL /* Channel Error */
|
||||
#define CXR_EXC 0000000200000LL /* Error in drive transfer */
|
||||
#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */
|
||||
#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */
|
||||
#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */
|
||||
#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */
|
||||
#define CXR_SD_RAE 0000200000000LL /* Register access error */
|
||||
#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */
|
||||
#define B22_FLAG 0004000000000LL /* 22 bit channel */
|
||||
#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */
|
||||
#define CC_CHAN_ACT 0020000000000LL /* Channel in use */
|
||||
#define CC_INH 0040000000000LL /* Disconnect channel */
|
||||
#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */
|
||||
#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */
|
||||
|
||||
/* CONO Flags */
|
||||
#define ATTN_EN 0000000000040LL /* enable attention interrupt. */
|
||||
#define REA_EN 0000000000100LL /* enable register error interrupt */
|
||||
#define CBOV_CLR 0000000000200LL /* Clear CBOV */
|
||||
#define CONT_RESET 0000000002000LL /* Clear All error bits */
|
||||
#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */
|
||||
#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */
|
||||
#define OVER_CLR 0000000020000LL /* Clear DTC overrun */
|
||||
#define WRT_CW 0000000040000LL /* Write control word */
|
||||
#define CHN_CLR 0000000100000LL /* Clear Channel Error */
|
||||
#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */
|
||||
#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */
|
||||
|
||||
/* DATAO/DATAI */
|
||||
#define CR_REG 0770000000000LL /* Register number */
|
||||
#define LOAD_REG 0004000000000LL /* Load register */
|
||||
#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */
|
||||
#define CR_DRIVE 0000007000000LL
|
||||
#define CR_GEN_EVD 0000000400000LL /* Enable Parity */
|
||||
#define CR_DXES 0000000200000LL /* Disable DXES errors */
|
||||
#define CR_INAD 0000000077600LL
|
||||
#define CR_WTEVM 0000000000100LL /* Verify Parity */
|
||||
#define CR_FUNC 0000000000076LL
|
||||
#define CR_GO 0000000000001LL
|
||||
|
||||
#define IRQ_VECT 0000000000177LL /* Interupt vector */
|
||||
#define IRQ_KI10 0000002000000LL
|
||||
#define IRQ_KA10 0000001000000LL
|
||||
|
||||
#define CMD u3
|
||||
/* u3 low */
|
||||
/* TUC - 00 - control */
|
||||
|
||||
#define CS1_GO CR_GO /* go */
|
||||
#define CS1_GO 1 /* go */
|
||||
#define CS1_V_FNC 1 /* function pos */
|
||||
#define CS1_M_FNC 037 /* function mask */
|
||||
#define CS1_FNC (CS1_M_FNC << CS1_V_FNC)
|
||||
@@ -213,23 +156,15 @@
|
||||
#define CPOS u4
|
||||
#define DATAPTR u6
|
||||
|
||||
struct df10 tu_df10[NUM_DEVS_TU];
|
||||
int tu_xfer_drive[NUM_DEVS_TU];
|
||||
struct rh_if tu_rh[NUM_DEVS_TU];
|
||||
uint8 tu_buf[NUM_DEVS_TU][TU_NUMFR];
|
||||
int tu_reg[NUM_DEVS_TU];
|
||||
int tu_ivect[NUM_DEVS_TU];
|
||||
int tu_imode[NUM_DEVS_TU];
|
||||
int tu_drive[NUM_DEVS_TU];
|
||||
int tu_rae[NUM_DEVS_TU];
|
||||
int tu_attn[NUM_DEVS_TU];
|
||||
uint16 tu_frame[NUM_DEVS_TU];
|
||||
uint16 tu_tcr[NUM_DEVS_TU];
|
||||
static uint64 tu_boot_buffer;
|
||||
|
||||
t_stat tu_devio(uint32 dev, uint64 *data);
|
||||
int tu_devirq(uint32 dev, int addr);
|
||||
void tu_write(int ctlr, int unit, int reg, uint32 data);
|
||||
uint32 tu_read(int ctlr, int unit, int reg);
|
||||
void tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data);
|
||||
uint32 tu_read(DEVICE *dptr, struct rh_if *rhc, int reg);
|
||||
void tu_rst(DEVICE *dptr);
|
||||
t_stat tu_srv(UNIT *);
|
||||
t_stat tu_boot(int32, DEVICE *);
|
||||
void tu_ini(UNIT *, t_bool);
|
||||
@@ -243,21 +178,31 @@ const char *tu_description (DEVICE *dptr);
|
||||
|
||||
UNIT tu_unit[] = {
|
||||
/* Controller 1 */
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
||||
};
|
||||
|
||||
struct rh_if tu_rh[] = {
|
||||
{ &tu_write, &tu_read}
|
||||
};
|
||||
|
||||
DIB tu_dib[] = {
|
||||
{RH10_DEV, 1, &tu_devio, &tu_devirq}
|
||||
{RH10_DEV, 1, &rh_devio, &rh_devirq, &tu_rh[0]}
|
||||
};
|
||||
|
||||
MTAB tu_mod[] = {
|
||||
#if KL
|
||||
{MTAB_XTD|MTAB_VDV, TYPE_RH10, NULL, "RH10", &rh_set_type, NULL,
|
||||
NULL, "Sets controller to RH10" },
|
||||
{MTAB_XTD|MTAB_VDV, TYPE_RH20, "RH20", "RH20", &rh_set_type, &rh_show_type,
|
||||
NULL, "Sets controller to RH20"},
|
||||
#endif
|
||||
{MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL},
|
||||
{MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL},
|
||||
{MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
@@ -270,24 +215,22 @@ MTAB tu_mod[] = {
|
||||
};
|
||||
|
||||
REG tua_reg[] = {
|
||||
{ORDATA(IVECT, tu_ivect[0], 18)},
|
||||
{FLDATA(IMODE, tu_imode[0], 0)},
|
||||
{ORDATA(IVECT, tu_rh[0].ivect, 18)},
|
||||
{FLDATA(IMODE, tu_rh[0].imode, 0)},
|
||||
{ORDATA(FRAME, tu_frame[0], 16)},
|
||||
{ORDATA(TCR, tu_tcr[0], 16)},
|
||||
{ORDATA(XFER, tu_xfer_drive[0], 3), REG_HRO},
|
||||
{ORDATA(DRIVE, tu_drive[0], 3), REG_HRO},
|
||||
{ORDATA(REG, tu_reg[0], 6), REG_RO},
|
||||
{ORDATA(RAE, tu_rae[0], 8), REG_RO},
|
||||
{ORDATA(ATTN, tu_attn[0], 8), REG_RO},
|
||||
{ORDATA(STATUS, tu_df10[0].status, 18), REG_RO},
|
||||
{ORDATA(CIA, tu_df10[0].cia, 18)},
|
||||
{ORDATA(CCW, tu_df10[0].ccw, 18)},
|
||||
{ORDATA(WCR, tu_df10[0].wcr, 18)},
|
||||
{ORDATA(CDA, tu_df10[0].cda, 18)},
|
||||
{ORDATA(DEVNUM, tu_df10[0].devnum, 9), REG_HRO},
|
||||
{ORDATA(BUF, tu_df10[0].buf, 36), REG_HRO},
|
||||
{ORDATA(NXM, tu_df10[0].nxmerr, 8), REG_HRO},
|
||||
{ORDATA(COMP, tu_df10[0].ccw_comp, 8), REG_HRO},
|
||||
{ORDATA(XFER, tu_rh[0].xfer_drive, 3), REG_HRO},
|
||||
{ORDATA(DRIVE, tu_rh[0].drive, 3), REG_HRO},
|
||||
{ORDATA(REG, tu_rh[0].reg, 6), REG_RO},
|
||||
{ORDATA(RAE, tu_rh[0].rae, 8), REG_RO},
|
||||
{ORDATA(ATTN, tu_rh[0].attn, 8), REG_RO},
|
||||
{ORDATA(STATUS, tu_rh[0].status, 18), REG_RO},
|
||||
{ORDATA(CIA, tu_rh[0].cia, 18)},
|
||||
{ORDATA(CCW, tu_rh[0].ccw, 18)},
|
||||
{ORDATA(WCR, tu_rh[0].wcr, 18)},
|
||||
{ORDATA(CDA, tu_rh[0].cda, 18)},
|
||||
{ORDATA(DEVNUM, tu_rh[0].devnum, 9), REG_HRO},
|
||||
{ORDATA(BUF, tu_rh[0].buf, 36), REG_HRO},
|
||||
{BRDATA(BUFF, &tu_buf[0][0], 16, 64, TU_NUMFR), REG_HRO},
|
||||
{0}
|
||||
};
|
||||
@@ -305,196 +248,22 @@ DEVICE *tu_devs[] = {
|
||||
&tua_dev,
|
||||
};
|
||||
|
||||
|
||||
t_stat tu_devio(uint32 dev, uint64 *data) {
|
||||
int ctlr = -1;
|
||||
DEVICE *dptr = NULL;
|
||||
struct df10 *df10;
|
||||
int drive;
|
||||
|
||||
for (drive = 0; rh[drive].dev_num != 0; drive++) {
|
||||
if (rh[drive].dev_num == (dev & 0774)) {
|
||||
dptr = rh[drive].dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dptr == NULL)
|
||||
return SCPE_OK;
|
||||
ctlr = GET_CNTRL(dptr->units[0].flags);
|
||||
df10 = &tu_df10[ctlr];
|
||||
df10->devnum = dev;
|
||||
switch(dev & 3) {
|
||||
case CONI:
|
||||
*data = df10->status & ~(IADR_ATTN|IARD_RAE);
|
||||
if (tu_attn[ctlr] != 0 && (df10->status & IADR_ATTN))
|
||||
*data |= IADR_ATTN;
|
||||
if (tu_rae[ctlr] != 0 && (df10->status & IARD_RAE))
|
||||
*data |= IARD_RAE;
|
||||
#if KI_22BIT
|
||||
*data |= B22_FLAG;
|
||||
#endif
|
||||
sim_debug(DEBUG_CONI, dptr, "TU %03o CONI %06o PC=%o %o\n",
|
||||
dev, (uint32)*data, PC, tu_attn[ctlr]);
|
||||
return SCPE_OK;
|
||||
|
||||
case CONO:
|
||||
clr_interrupt(dev);
|
||||
df10->status &= ~07LL;
|
||||
df10->status |= *data & (07LL|IADR_ATTN|IARD_RAE);
|
||||
/* Clear flags */
|
||||
if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR))
|
||||
df10->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR));
|
||||
if (*data & OVER_CLR)
|
||||
df10->status &= ~(DTC_OVER);
|
||||
if (*data & CBOV_CLR)
|
||||
df10->status &= ~(DIB_CBOV);
|
||||
if (*data & CXR_ILC)
|
||||
df10->status &= ~(CXR_ILFC|CXR_SD_RAE);
|
||||
if (*data & WRT_CW)
|
||||
df10_writecw(df10);
|
||||
if (*data & PI_ENABLE)
|
||||
df10->status &= ~PI_ENABLE;
|
||||
if (df10->status & PI_ENABLE)
|
||||
set_interrupt(dev, df10->status);
|
||||
if ((df10->status & IADR_ATTN) != 0 && tu_attn[ctlr] != 0)
|
||||
set_interrupt(dev, df10->status);
|
||||
sim_debug(DEBUG_CONO, dptr, "TU %03o CONO %06o %d PC=%06o %06o\n",
|
||||
dev, (uint32)*data, ctlr, PC, df10->status);
|
||||
return SCPE_OK;
|
||||
|
||||
case DATAI:
|
||||
*data = 0;
|
||||
if (df10->status & BUSY && tu_reg[ctlr] != 04) {
|
||||
df10->status |= CC_CHAN_ACT;
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (tu_reg[ctlr] == 040) {
|
||||
*data = (uint64)(tu_read(ctlr, tu_drive[ctlr], 0) & 077);
|
||||
*data |= ((uint64)(df10->cia)) << 6;
|
||||
*data |= ((uint64)(tu_xfer_drive[ctlr])) << 18;
|
||||
} else if (tu_reg[ctlr] == 044) {
|
||||
*data = (uint64)tu_ivect[ctlr];
|
||||
if (tu_imode[ctlr])
|
||||
*data |= IRQ_KI10;
|
||||
else
|
||||
*data |= IRQ_KA10;
|
||||
} else if (tu_reg[ctlr] == 054) {
|
||||
*data = (uint64)(tu_rae[ctlr]);
|
||||
} else if ((tu_reg[ctlr] & 040) == 0) {
|
||||
*data = (uint64)(tu_read(ctlr, tu_drive[ctlr], tu_reg[ctlr]) & 0177777);
|
||||
*data |= ((uint64)(tu_drive[ctlr])) << 18;
|
||||
}
|
||||
*data |= ((uint64)(tu_reg[ctlr])) << 30;
|
||||
sim_debug(DEBUG_DATAIO, dptr, "TU %03o DATI %012llo, %d %d PC=%06o\n",
|
||||
dev, *data, ctlr, tu_drive[ctlr], PC);
|
||||
return SCPE_OK;
|
||||
|
||||
case DATAO:
|
||||
sim_debug(DEBUG_DATAIO, dptr, "TU %03o DATO %012llo, %d PC=%06o %06o\n",
|
||||
dev, *data, ctlr, PC, df10->status);
|
||||
tu_reg[ctlr] = ((int)(*data >> 30)) & 077;
|
||||
if (tu_reg[ctlr] < 040 && tu_reg[ctlr] != 04) {
|
||||
tu_drive[ctlr] = (int)(*data >> 18) & 07;
|
||||
}
|
||||
if (*data & LOAD_REG) {
|
||||
if (tu_reg[ctlr] == 040) {
|
||||
if ((*data & 1) == 0) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (df10->status & BUSY) {
|
||||
df10->status |= CC_CHAN_ACT;
|
||||
sim_debug(DEBUG_DATAIO, dptr,
|
||||
"TU %03o command busy %012llo, %d[%d] PC=%06o %06o\n",
|
||||
dev, *data, ctlr, tu_drive[ctlr], PC, df10->status);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
df10->status &= ~(1 << df10->ccw_comp);
|
||||
df10->status &= ~PI_ENABLE;
|
||||
if (((*data >> 1) & 077) < FNC_XFER) {
|
||||
df10->status |= CXR_ILC;
|
||||
df10_setirq(df10);
|
||||
sim_debug(DEBUG_DATAIO, dptr,
|
||||
"TU %03o command abort %012llo, %d[%d] PC=%06o %06o\n",
|
||||
dev, *data, ctlr, tu_drive[ctlr], PC, df10->status);
|
||||
return SCPE_OK;
|
||||
}
|
||||
/* Check if access error */
|
||||
if (tu_rae[ctlr] & (1 << tu_drive[ctlr])) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Start command */
|
||||
df10_setup(df10, (uint32)(*data >> 6));
|
||||
tu_xfer_drive[ctlr] = (int)(*data >> 18) & 07;
|
||||
tu_write(ctlr, tu_drive[ctlr], 0, (uint32)(*data & 077));
|
||||
sim_debug(DEBUG_DATAIO, dptr,
|
||||
"TU %03o command %012llo, %d[%d] PC=%06o %06o\n",
|
||||
dev, *data, ctlr, tu_drive[ctlr], PC, df10->status);
|
||||
} else if (tu_reg[ctlr] == 044) {
|
||||
/* Set KI10 Irq vector */
|
||||
tu_ivect[ctlr] = (int)(*data & IRQ_VECT);
|
||||
tu_imode[ctlr] = (*data & IRQ_KI10) != 0;
|
||||
} else if (tu_reg[ctlr] == 050) {
|
||||
; /* Diagnostic access to mass bus. */
|
||||
} else if (tu_reg[ctlr] == 054) {
|
||||
/* clear flags */
|
||||
tu_rae[ctlr] &= ~(*data & 0377);
|
||||
if (tu_rae[ctlr] == 0)
|
||||
clr_interrupt(dev);
|
||||
} else if ((tu_reg[ctlr] & 040) == 0) {
|
||||
tu_drive[ctlr] = (int)(*data >> 18) & 07;
|
||||
/* Check if access error */
|
||||
if (tu_rae[ctlr] & (1 << tu_drive[ctlr])) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
tu_drive[ctlr] = (int)(*data >> 18) & 07;
|
||||
tu_write(ctlr, tu_drive[ctlr], tu_reg[ctlr] & 037,
|
||||
(int)(*data & 0777777));
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
return SCPE_OK; /* Unreached */
|
||||
}
|
||||
|
||||
/* Handle KI and KL style interrupt vectors */
|
||||
int
|
||||
tu_devirq(uint32 dev, int addr) {
|
||||
DEVICE *dptr = NULL;
|
||||
int drive;
|
||||
|
||||
for (drive = 0; rh[drive].dev_num != 0; drive++) {
|
||||
if (rh[drive].dev_num == (dev & 0774)) {
|
||||
dptr = rh[drive].dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dptr != NULL) {
|
||||
drive = GET_CNTRL(dptr->units[0].flags);
|
||||
return (tu_imode[drive] ? tu_ivect[drive] : addr);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
void
|
||||
tu_write(int ctlr, int unit, int reg, uint32 data) {
|
||||
UNIT *uptr = &tu_unit[(ctlr * 8) + (tu_tcr[ctlr] & 07)];
|
||||
DEVICE *dptr = tu_devs[ctlr];
|
||||
struct df10 *df10 = &tu_df10[ctlr];
|
||||
tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) {
|
||||
int ctlr = GET_CNTRL_RH(dptr->units[0].flags);
|
||||
int unit = tu_tcr[ctlr] & 07;
|
||||
UNIT *uptr = &dptr->units[unit];
|
||||
int i;
|
||||
|
||||
if (uptr->CMD & CR_GO) {
|
||||
if (uptr->CMD & CS1_GO) {
|
||||
uptr->STATUS |= (ER1_RMR);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(reg) {
|
||||
case 000: /* control */
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TUA%o %d Status=%06o\n",
|
||||
unit, ctlr, uptr->STATUS);
|
||||
df10->status &= ~(1 << df10->ccw_comp);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o %d Status=%06o\n",
|
||||
dptr->name, unit, ctlr, uptr->STATUS);
|
||||
if ((data & 01) != 0 && (uptr->flags & UNIT_ATT) != 0) {
|
||||
uptr->CMD = data & 076;
|
||||
switch (GET_FNC(data)) {
|
||||
@@ -516,34 +285,28 @@ tu_write(int ctlr, int unit, int reg, uint32 data) {
|
||||
case FNC_REWIND: /* rewind */
|
||||
case FNC_UNLOAD: /* unload */
|
||||
case FNC_WCHKREV: /* write w/ headers */
|
||||
uptr->CMD |= CS_PIP|CR_GO;
|
||||
uptr->CMD |= CS_PIP|CS1_GO;
|
||||
uptr->CMD &= ~CS_TM;
|
||||
CLR_BUF(uptr);
|
||||
uptr->DATAPTR = 0;
|
||||
df10->status &= ~PI_ENABLE;
|
||||
sim_activate(uptr, 100);
|
||||
break;
|
||||
|
||||
case FNC_DCLR: /* drive clear */
|
||||
uptr->CMD &= ~(CS_ATA|CR_GO|CS_TM);
|
||||
uptr->CMD &= ~(CS_ATA|CS1_GO|CS_TM);
|
||||
uptr->STATUS = 0;
|
||||
tu_attn[ctlr] = 0;
|
||||
clr_interrupt(df10->devnum);
|
||||
rhc->attn = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (tu_unit[(ctlr * 8) + i].CMD & CS_ATA)
|
||||
tu_attn[ctlr] = 1;
|
||||
if (dptr->units[i].CMD & CS_ATA)
|
||||
rhc->attn = 1;
|
||||
}
|
||||
if ((df10->status & IADR_ATTN) != 0 && tu_attn[ctlr] != 0)
|
||||
df10_setirq(df10);
|
||||
break;
|
||||
default:
|
||||
uptr->STATUS |= (ER1_ILF);
|
||||
uptr->CMD |= CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
if ((df10->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df10);
|
||||
rhc->attn = 1;
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TUA%o AStatus=%06o\n", unit,
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o AStatus=%06o\n", dptr->name, unit,
|
||||
uptr->CMD);
|
||||
}
|
||||
return;
|
||||
@@ -556,17 +319,13 @@ tu_write(int ctlr, int unit, int reg, uint32 data) {
|
||||
case 003: /* maintenance */
|
||||
break;
|
||||
case 004: /* atten summary */
|
||||
tu_attn[ctlr] = 0;
|
||||
rhc->attn = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (data & (1<<i))
|
||||
tu_unit[(ctlr * 8) + i].CMD &= ~CS_ATA;
|
||||
if (tu_unit[(ctlr * 8) + i].CMD & CS_ATA)
|
||||
tu_attn[ctlr] = 1;
|
||||
dptr->units[i].CMD &= ~CS_ATA;
|
||||
if (dptr->units[i].CMD & CS_ATA)
|
||||
rhc->attn = 1;
|
||||
}
|
||||
clr_interrupt(df10->devnum);
|
||||
if (((df10->status & IADR_ATTN) != 0 && tu_attn[ctlr] != 0) ||
|
||||
(df10->status & PI_ENABLE))
|
||||
df10_setirq(df10);
|
||||
break;
|
||||
case 005: /* frame count */
|
||||
tu_frame[ctlr] = data & 0177777;
|
||||
@@ -579,31 +338,30 @@ tu_write(int ctlr, int unit, int reg, uint32 data) {
|
||||
default:
|
||||
uptr->STATUS |= ER1_ILR;
|
||||
uptr->CMD |= CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
tu_rae[ctlr] |= (1<<unit);
|
||||
if ((df10->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df10);
|
||||
rhc->attn = 1;
|
||||
rhc->rae = 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32
|
||||
tu_read(int ctlr, int unit, int reg) {
|
||||
UNIT *uptr = &tu_unit[(ctlr * 8) + (tu_tcr[ctlr] & 07)];
|
||||
struct df10 *df10 = &tu_df10[ctlr];
|
||||
uint32 temp = 0;
|
||||
int i;
|
||||
tu_read(DEVICE *dptr, struct rh_if *rhc, int reg) {
|
||||
int ctlr = GET_CNTRL_RH(dptr->units[0].flags);
|
||||
int unit = tu_tcr[ctlr] & 07;
|
||||
UNIT *uptr = &dptr->units[unit];
|
||||
uint32 temp = 0;
|
||||
int i;
|
||||
|
||||
switch(reg) {
|
||||
case 000: /* control */
|
||||
temp = uptr->CMD & 076;
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
temp |= CS1_DVA;
|
||||
if (df10->status & BUSY || uptr->CMD & CR_GO)
|
||||
if (uptr->CMD & CS1_GO)
|
||||
temp |= CS1_GO;
|
||||
break;
|
||||
case 001: /* status */
|
||||
temp = DS_DPR;
|
||||
if (tu_attn[ctlr] != 0)
|
||||
if (rhc->attn != 0)
|
||||
temp |= DS_ATA;
|
||||
if (uptr->CMD & CS_CHANGE)
|
||||
temp |= DS_SSC;
|
||||
@@ -615,7 +373,7 @@ tu_read(int ctlr, int unit, int reg) {
|
||||
temp |= DS_TM;
|
||||
if (uptr->flags & MTUF_WLK)
|
||||
temp |= DS_WRL;
|
||||
if ((uptr->CMD & (CS_MOTION|CS_PIP|CR_GO)) == 0)
|
||||
if ((uptr->CMD & (CS_MOTION|CS_PIP|CS1_GO)) == 0)
|
||||
temp |= DS_DRY;
|
||||
if (sim_tape_bot(uptr))
|
||||
temp |= DS_BOT;
|
||||
@@ -632,7 +390,7 @@ tu_read(int ctlr, int unit, int reg) {
|
||||
break;
|
||||
case 004: /* atten summary */
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (tu_unit[(ctlr * 8) + i].CMD & CS_ATA) {
|
||||
if (dptr->units[i].CMD & CS_ATA) {
|
||||
temp |= 1 << i;
|
||||
}
|
||||
}
|
||||
@@ -655,10 +413,8 @@ tu_read(int ctlr, int unit, int reg) {
|
||||
default:
|
||||
uptr->STATUS |= (ER1_ILR);
|
||||
uptr->CMD |= CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
tu_rae[ctlr] |= (1<<unit);
|
||||
if ((df10->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df10);
|
||||
rhc->attn = 1;
|
||||
rhc->rae = 1;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
@@ -667,8 +423,9 @@ tu_read(int ctlr, int unit, int reg) {
|
||||
/* Map simH errors into machine errors */
|
||||
void tu_error(UNIT * uptr, t_stat r)
|
||||
{
|
||||
int ctlr = GET_CNTRL(uptr->flags);
|
||||
DEVICE *dptr = tu_devs[ctlr];
|
||||
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||
DEVICE *dptr = tu_devs[ctlr];
|
||||
struct rh_if *rhc = &tu_rh[ctlr];
|
||||
|
||||
switch (r) {
|
||||
case MTSE_OK: /* no error */
|
||||
@@ -706,66 +463,61 @@ void tu_error(UNIT * uptr, t_stat r)
|
||||
|
||||
}
|
||||
if (uptr->CMD & CS_ATA) {
|
||||
tu_attn[ctlr] = 1;
|
||||
rh_setattn(rhc, 0);
|
||||
// rhc->attn = 1;
|
||||
}
|
||||
uptr->CMD &= ~(CS_MOTION|CS_PIP|CR_GO);
|
||||
uptr->CMD &= ~(CS_MOTION|CS_PIP|CS1_GO);
|
||||
sim_debug(DEBUG_EXP, dptr, "Setting status %d\n", r);
|
||||
}
|
||||
|
||||
/* Handle processing of tape requests. */
|
||||
t_stat tu_srv(UNIT * uptr)
|
||||
{
|
||||
int ctlr = GET_CNTRL(uptr->flags);
|
||||
int unit;
|
||||
DEVICE *dptr;
|
||||
struct df10 *df;
|
||||
t_stat r;
|
||||
t_mtrlnt reclen;
|
||||
uint8 ch;
|
||||
int cc;
|
||||
int cc_max;
|
||||
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||
int unit;
|
||||
struct rh_if *rhc;
|
||||
DEVICE *dptr;
|
||||
t_stat r;
|
||||
t_mtrlnt reclen;
|
||||
uint8 ch;
|
||||
int cc;
|
||||
int cc_max;
|
||||
|
||||
/* Find dptr, and df10 */
|
||||
dptr = tu_devs[ctlr];
|
||||
rhc = &tu_rh[ctlr];
|
||||
unit = uptr - dptr->units;
|
||||
df = &tu_df10[ctlr];
|
||||
cc_max = (4 + ((tu_tcr[ctlr] & TC_FMTSEL) == 0));
|
||||
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||
tu_error(uptr, MTSE_UNATT); /* attached? */
|
||||
df10_setirq(df);
|
||||
rh_setirq(rhc);
|
||||
return SCPE_OK;
|
||||
}
|
||||
switch (GET_FNC(uptr->CMD)) {
|
||||
case FNC_NOP:
|
||||
case FNC_DCLR:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o nop\n", unit);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o nop\n", dptr->name, unit);
|
||||
tu_error(uptr, MTSE_OK); /* Nop */
|
||||
df10_setirq(df);
|
||||
rh_setirq(rhc);
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_REWIND:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o rewind\n", unit);
|
||||
if (uptr->CMD & CR_GO) {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o rewind\n", dptr->name, unit);
|
||||
if (uptr->CMD & CS1_GO) {
|
||||
sim_activate(uptr,40000);
|
||||
uptr->CMD |= CS_MOTION;
|
||||
uptr->CMD &= ~(CR_GO);
|
||||
uptr->CMD &= ~(CS1_GO);
|
||||
} else {
|
||||
uptr->CMD &= ~(CS_MOTION|CS_PIP);
|
||||
uptr->CMD |= CS_CHANGE|CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
if ((df->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df);
|
||||
tu_error(uptr, sim_tape_rewind(uptr));
|
||||
}
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_UNLOAD:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o unload\n", unit);
|
||||
uptr->CMD &= ~(CR_GO);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o unload\n", dptr->name, unit);
|
||||
uptr->CMD &= ~(CS1_GO);
|
||||
uptr->CMD |= CS_CHANGE|CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
if ((df->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df);
|
||||
tu_error(uptr, sim_tape_detach(uptr));
|
||||
return SCPE_OK;
|
||||
|
||||
@@ -775,18 +527,18 @@ t_stat tu_srv(UNIT * uptr)
|
||||
uptr->CMD &= ~CS_PIP;
|
||||
if ((r = sim_tape_rdrecr(uptr, &tu_buf[ctlr][0], &reclen,
|
||||
TU_NUMFR)) != MTSE_OK) {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o read error %d\n", unit, r);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r);
|
||||
if (r == MTSE_BOT)
|
||||
uptr->STATUS |= ER1_NEF;
|
||||
tu_error(uptr, r);
|
||||
df10_finish_op(df, 0);
|
||||
rh_finish_op(rhc, 0);
|
||||
} else {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o read %d\n", unit, reclen);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d\n", dptr->name, unit, reclen);
|
||||
uptr->CMD |= CS_MOTION;
|
||||
uptr->hwmark = reclen;
|
||||
uptr->DATAPTR = uptr->hwmark-1;
|
||||
uptr->CPOS = cc_max;
|
||||
df->buf = 0;
|
||||
rhc->buf = 0;
|
||||
sim_activate(uptr, 100);
|
||||
}
|
||||
return SCPE_OK;
|
||||
@@ -796,26 +548,27 @@ t_stat tu_srv(UNIT * uptr)
|
||||
cc = (8 * (3 - uptr->CPOS)) + 4;
|
||||
ch = tu_buf[ctlr][uptr->DATAPTR];
|
||||
if (cc < 0)
|
||||
df->buf |= (uint64)(ch & 0x0f);
|
||||
rhc->buf |= (uint64)(ch & 0x0f);
|
||||
else
|
||||
df->buf |= (uint64)(ch & 0xff) << cc;
|
||||
rhc->buf |= (uint64)(ch & 0xff) << cc;
|
||||
uptr->DATAPTR--;
|
||||
uptr->CPOS--;
|
||||
if (uptr->CPOS == 0) {
|
||||
uptr->CPOS = cc_max;
|
||||
if (GET_FNC(uptr->CMD) == FNC_READREV &&
|
||||
df10_write(df) == 0) {
|
||||
if (GET_FNC(uptr->CMD) == FNC_READREV && rh_write(rhc) == 0) {
|
||||
tu_error(uptr, MTSE_OK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
sim_debug(DEBUG_DATA, dptr, "TU%o readrev %012llo\n",
|
||||
unit, df->buf);
|
||||
df->buf = 0;
|
||||
sim_debug(DEBUG_DATA, dptr, "%s%o readrev %012llo\n",
|
||||
dptr->name, unit, rhc->buf);
|
||||
rhc->buf = 0;
|
||||
}
|
||||
} else {
|
||||
if (uptr->CPOS != cc_max)
|
||||
df10_write(df);
|
||||
rh_write(rhc);
|
||||
(void)rh_blkend(rhc);
|
||||
tu_error(uptr, MTSE_OK);
|
||||
rh_finish_op(rhc, 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
break;
|
||||
@@ -827,15 +580,15 @@ t_stat tu_srv(UNIT * uptr)
|
||||
uptr->CMD |= CS_MOTION;
|
||||
if ((r = sim_tape_rdrecf(uptr, &tu_buf[ctlr][0], &reclen,
|
||||
TU_NUMFR)) != MTSE_OK) {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o read error %d\n", unit, r);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r);
|
||||
tu_error(uptr, r);
|
||||
df10_finish_op(df, 0);
|
||||
rh_finish_op(rhc, 0);
|
||||
} else {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o read %d\n", unit, reclen);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d %d\n", dptr->name, unit, reclen, uptr->pos);
|
||||
uptr->hwmark = reclen;
|
||||
uptr->DATAPTR = 0;
|
||||
uptr->CPOS = 0;
|
||||
df->buf = 0;
|
||||
rhc->buf = 0;
|
||||
sim_activate(uptr, 100);
|
||||
}
|
||||
return SCPE_OK;
|
||||
@@ -845,30 +598,30 @@ t_stat tu_srv(UNIT * uptr)
|
||||
cc = (8 * (3 - uptr->CPOS)) + 4;
|
||||
ch = tu_buf[ctlr][uptr->DATAPTR];
|
||||
if (cc < 0)
|
||||
df->buf |= (uint64)(ch & 0x0f);
|
||||
rhc->buf |= (uint64)(ch & 0x0f);
|
||||
else
|
||||
df->buf |= (uint64)(ch & 0xff) << cc;
|
||||
rhc->buf |= (uint64)(ch & 0xff) << cc;
|
||||
uptr->DATAPTR++;
|
||||
uptr->CPOS++;
|
||||
if (uptr->CPOS == cc_max) {
|
||||
uptr->CPOS = 0;
|
||||
if (GET_FNC(uptr->CMD) == FNC_READ &&
|
||||
df10_write(df) == 0) {
|
||||
if (GET_FNC(uptr->CMD) == FNC_READ && rh_write(rhc) == 0) {
|
||||
tu_error(uptr, MTSE_OK);
|
||||
return SCPE_OK;
|
||||
}
|
||||
sim_debug(DEBUG_DATA, dptr, "TU%o read %012llo\n",
|
||||
unit, df->buf);
|
||||
df->buf = 0;
|
||||
sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n",
|
||||
dptr->name, unit, rhc->buf);
|
||||
rhc->buf = 0;
|
||||
}
|
||||
} else {
|
||||
if (uptr->CPOS != 0) {
|
||||
sim_debug(DEBUG_DATA, dptr, "TU%o read %012llo\n",
|
||||
unit, df->buf);
|
||||
df10_write(df);
|
||||
sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n",
|
||||
dptr->name, unit, rhc->buf);
|
||||
rh_write(rhc);
|
||||
}
|
||||
tu_error(uptr, MTSE_OK);
|
||||
df10_finish_op(df, 0);
|
||||
(void)rh_blkend(rhc);
|
||||
rh_finish_op(rhc, 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
break;
|
||||
@@ -878,38 +631,38 @@ t_stat tu_srv(UNIT * uptr)
|
||||
uptr->CMD &= ~CS_PIP;
|
||||
if (tu_frame[ctlr] == 0) {
|
||||
uptr->STATUS |= ER1_NEF;
|
||||
uptr->CMD &= ~(CR_GO);
|
||||
uptr->CMD &= ~(CS1_GO);
|
||||
uptr->CMD |= CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
rhc->attn = 1;
|
||||
tu_error(uptr, MTSE_OK);
|
||||
df10_finish_op(df, 0);
|
||||
rh_finish_op(rhc, 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if ((uptr->flags & MTUF_WLK) != 0) {
|
||||
tu_error(uptr, MTSE_WRP);
|
||||
df10_finish_op(df, 0);
|
||||
rh_finish_op(rhc, 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
uptr->CMD |= CS_MOTION;
|
||||
sim_debug(DEBUG_EXP, dptr, "TU%o Init write\n", unit);
|
||||
sim_debug(DEBUG_EXP, dptr, "%s%o Init write\n", dptr->name, unit);
|
||||
uptr->hwmark = 0;
|
||||
uptr->CPOS = 0;
|
||||
uptr->DATAPTR = 0;
|
||||
df->buf = 0;
|
||||
rhc->buf = 0;
|
||||
}
|
||||
if (tu_frame[ctlr] != 0 && uptr->CPOS == 0 && df10_read(df) == 0)
|
||||
if (tu_frame[ctlr] != 0 && uptr->CPOS == 0 && rh_read(rhc) == 0)
|
||||
uptr->CPOS |= 010;
|
||||
|
||||
if ((uptr->CMD & CS_MOTION) != 0) {
|
||||
if (uptr->CPOS == 0)
|
||||
sim_debug(DEBUG_DATA, dptr, "TU%o write %012llo\n",
|
||||
unit, df->buf);
|
||||
sim_debug(DEBUG_DATA, dptr, "%s%o write %012llo\n",
|
||||
dptr->name, unit, rhc->buf);
|
||||
/* Write next char out */
|
||||
cc = (8 * (3 - (uptr->CPOS & 07))) + 4;
|
||||
if (cc < 0)
|
||||
ch = df->buf & 0x0f;
|
||||
ch = rhc->buf & 0x0f;
|
||||
else
|
||||
ch = (df->buf >> cc) & 0xff;
|
||||
ch = (rhc->buf >> cc) & 0xff;
|
||||
tu_buf[ctlr][uptr->DATAPTR] = ch;
|
||||
uptr->DATAPTR++;
|
||||
uptr->hwmark = uptr->DATAPTR;
|
||||
@@ -925,52 +678,44 @@ t_stat tu_srv(UNIT * uptr)
|
||||
/* Write out the block */
|
||||
reclen = uptr->hwmark;
|
||||
r = sim_tape_wrrecf(uptr, &tu_buf[ctlr][0], reclen);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o Write %d %d\n",
|
||||
unit, reclen, uptr->CPOS);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o Write %d %d\n",
|
||||
dptr->name, unit, reclen, uptr->CPOS);
|
||||
uptr->DATAPTR = 0;
|
||||
uptr->hwmark = 0;
|
||||
df10_finish_op(df,0 );
|
||||
(void)rh_blkend(rhc);
|
||||
tu_error(uptr, r); /* Record errors */
|
||||
rh_finish_op(rhc,0 );
|
||||
return SCPE_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case FNC_WTM:
|
||||
uptr->CMD |= CS_ATA;
|
||||
if ((uptr->flags & MTUF_WLK) != 0) {
|
||||
tu_error(uptr, MTSE_WRP);
|
||||
} else {
|
||||
tu_error(uptr, sim_tape_wrtmk(uptr));
|
||||
}
|
||||
uptr->CMD |= CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o WTM\n", unit);
|
||||
if ((df->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o WTM\n", dptr->name, unit);
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_ERASE:
|
||||
uptr->CMD |= CS_ATA;
|
||||
if ((uptr->flags & MTUF_WLK) != 0) {
|
||||
tu_error(uptr, MTSE_WRP);
|
||||
} else {
|
||||
tu_error(uptr, sim_tape_wrgap(uptr, 35));
|
||||
}
|
||||
uptr->CMD |= CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o ERG\n", unit);
|
||||
if ((df->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o ERG\n", dptr->name, unit);
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_SPACEF:
|
||||
case FNC_SPACEB:
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TU%o space %o\n", unit, GET_FNC(uptr->CMD));
|
||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o space %o\n", dptr->name, unit, GET_FNC(uptr->CMD));
|
||||
if (tu_frame[ctlr] == 0) {
|
||||
uptr->STATUS |= ER1_NEF;
|
||||
uptr->CMD |= CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
tu_error(uptr, MTSE_OK);
|
||||
if ((df->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df);
|
||||
return SCPE_OK;
|
||||
}
|
||||
uptr->CMD |= CS_MOTION;
|
||||
@@ -991,26 +736,22 @@ t_stat tu_srv(UNIT * uptr)
|
||||
case MTSE_EOM: /* end of medium */
|
||||
if (tu_frame[ctlr] != 0)
|
||||
uptr->STATUS |= ER1_FCE;
|
||||
uptr->CMD &= ~(CR_GO);
|
||||
uptr->CMD &= ~(CS1_GO);
|
||||
uptr->CMD |= CS_ATA;
|
||||
tu_attn[ctlr] = 1;
|
||||
/* Stop motion if we recieve any of these */
|
||||
tu_error(uptr, r);
|
||||
if ((df->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df);
|
||||
return SCPE_OK;
|
||||
}
|
||||
tu_frame[ctlr] = 0177777 & (tu_frame[ctlr] + 1);
|
||||
if (tu_frame[ctlr] == 0) {
|
||||
uptr->CMD |= CS_ATA;
|
||||
tu_error(uptr, MTSE_OK);
|
||||
if ((df->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df);
|
||||
return SCPE_OK;
|
||||
} else
|
||||
sim_activate(uptr, 5000);
|
||||
return SCPE_OK;
|
||||
}
|
||||
sim_activate(uptr, 200);
|
||||
sim_activate(uptr, 100);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1022,11 +763,9 @@ tu_reset(DEVICE * dptr)
|
||||
{
|
||||
int ctlr;
|
||||
for (ctlr = 0; ctlr < NUM_DEVS_TU; ctlr++) {
|
||||
tu_df10[ctlr].devnum = tu_dib[ctlr].dev_num;
|
||||
tu_df10[ctlr].nxmerr = 19;
|
||||
tu_df10[ctlr].ccw_comp = 14;
|
||||
tu_attn[ctlr] = 0;
|
||||
tu_rae[ctlr] = 0;
|
||||
tu_rh[ctlr].devnum = tu_dib[ctlr].dev_num;
|
||||
tu_rh[ctlr].attn = 0;
|
||||
tu_rh[ctlr].rae = 0;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -1100,20 +839,17 @@ tu_boot(int32 unit_num, DEVICE * dptr)
|
||||
t_stat
|
||||
tu_attach(UNIT * uptr, CONST char *file)
|
||||
{ t_stat r;
|
||||
int ctlr = GET_CNTRL(uptr->flags);
|
||||
struct df10 *df;
|
||||
|
||||
/* Find df10 */
|
||||
df = &tu_df10[ctlr];
|
||||
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||
struct rh_if *rhc = &tu_rh[ctlr];
|
||||
|
||||
uptr->CMD = 0;
|
||||
uptr->STATUS = 0;
|
||||
r = sim_tape_attach_ex(uptr, file, 0, 0);
|
||||
if (r == SCPE_OK) {
|
||||
uptr->CMD = CS_ATA|CS_CHANGE;
|
||||
tu_attn[ctlr] = 1;
|
||||
if ((df->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df);
|
||||
rhc->attn = 1;
|
||||
if ((rhc->status & IADR_ATTN) != 0)
|
||||
rh_setirq(rhc);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -1121,16 +857,15 @@ tu_attach(UNIT * uptr, CONST char *file)
|
||||
t_stat
|
||||
tu_detach(UNIT * uptr)
|
||||
{
|
||||
int ctlr = GET_CNTRL(uptr->flags);
|
||||
struct df10 *df;
|
||||
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||
struct rh_if *rhc = &tu_rh[ctlr];
|
||||
|
||||
/* Find df10 */
|
||||
df = &tu_df10[ctlr];
|
||||
uptr->STATUS = 0;
|
||||
uptr->CMD = CS_ATA|CS_CHANGE;
|
||||
tu_attn[ctlr] = 1;
|
||||
if ((df->status & IADR_ATTN) != 0)
|
||||
df10_setirq(df);
|
||||
rhc->attn = 1;
|
||||
if ((rhc->status & IADR_ATTN) != 0)
|
||||
rh_setirq(rhc);
|
||||
return sim_tape_detach(uptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,6 @@ The PDP6 runs TOPS 10 4.5 off Dectape.
|
||||
The KA10 sim has successfully run Tops 10 4.5, 5.03 and Tops 10 6.03, ITS and WAITS.
|
||||
The KI10 sim has successfully run Tops 10 6.03 with VMSER.
|
||||
The KL10 sim has successfully run Tops 10 6.03 with VMSER and ITS.
|
||||
KL10 extended addressing support is still in development.
|
||||
|
||||
Disk
|
||||
* RC10 RD10/RM10
|
||||
|
||||
29
makefile
29
makefile
@@ -1232,13 +1232,13 @@ KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.c \
|
||||
${KA10D}/kx10_rp.c ${KA10D}/kx10_rc.c ${KA10D}/kx10_dt.c \
|
||||
${KA10D}/kx10_dk.c ${KA10D}/kx10_cr.c ${KA10D}/kx10_cp.c \
|
||||
${KA10D}/kx10_tu.c ${KA10D}/kx10_rs.c ${KA10D}/ka10_pd.c \
|
||||
${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c ${KA10D}/ka10_mty.c \
|
||||
${KA10D}/ka10_imx.c ${KA10D}/ka10_ch10.c ${KA10D}/ka10_stk.c \
|
||||
${KA10D}/ka10_ten11.c ${KA10D}/ka10_auxcpu.c $(KA10D)/ka10_pmp.c \
|
||||
${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c ${KA10D}/pdp6_dtc.c \
|
||||
${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c ${KA10D}/pdp6_dcs.c \
|
||||
${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c ${PDP10D}/ka10_ai.c \
|
||||
${KA10D}/ka10_iii.c ${DISPLAYL} $(DISPLAY340)
|
||||
${KA10D}/kx10_rh.c ${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c \
|
||||
${KA10D}/ka10_mty.c ${KA10D}/ka10_imx.c ${KA10D}/ka10_ch10.c \
|
||||
${KA10D}/ka10_stk.c ${KA10D}/ka10_ten11.c ${KA10D}/ka10_auxcpu.c \
|
||||
$(KA10D)/ka10_pmp.c ${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c \
|
||||
${KA10D}/pdp6_dtc.c ${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c \
|
||||
${KA10D}/pdp6_dcs.c ${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c \
|
||||
${PDP10D}/ka10_ai.c ${KA10D}/ka10_iii.c ${DISPLAYL} $(DISPLAY340)
|
||||
KA10_OPT = -DKA=1 -DUSE_INT64 -I $(KA10D) -DUSE_SIM_CARD ${NETWORK_OPT} $(DISPLAY_OPT) $(KA10_DISPLAY_OPT)
|
||||
ifneq ($(PANDA_LIGHTS),)
|
||||
# ONLY for Panda display.
|
||||
@@ -1254,10 +1254,10 @@ endif
|
||||
KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.c \
|
||||
${KI10D}/kx10_dp.c ${KI10D}/kx10_mt.c ${KI10D}/kx10_cty.c \
|
||||
${KI10D}/kx10_lp.c ${KI10D}/kx10_pt.c ${KI10D}/kx10_dc.c \
|
||||
${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c ${KI10D}/kx10_dt.c \
|
||||
${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c ${KI10D}/kx10_cp.c \
|
||||
${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c ${KI10D}/kx10_imp.c \
|
||||
${KI10D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340)
|
||||
${KI10D}/kx10_rh.c ${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c \
|
||||
${KI10D}/kx10_dt.c ${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c \
|
||||
${KI10D}/kx10_cp.c ${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c \
|
||||
${KI10D}/kx10_imp.c ${KI10D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340)
|
||||
KI10_OPT = -DKI=1 -DUSE_INT64 -I $(KI10D) -DUSE_SIM_CARD ${NETWORK_OPT} $(DISPLAY_OPT) $(KI10_DISPLAY_OPT)
|
||||
ifneq ($(PANDA_LIGHTS),)
|
||||
# ONLY for Panda display.
|
||||
@@ -1268,9 +1268,10 @@ endif
|
||||
|
||||
KL10D = PDP10
|
||||
KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \
|
||||
${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rp.c \
|
||||
${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c ${KL10D}/kx10_imp.c \
|
||||
${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c ${KL10D}/ka10_ch10.c
|
||||
${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rh.c \
|
||||
${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \
|
||||
${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \
|
||||
${KL10D}/ka10_ch10.c
|
||||
KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT}
|
||||
|
||||
PDP1D = PDP1
|
||||
|
||||
Reference in New Issue
Block a user