mirror of
https://github.com/open-simh/simh.git
synced 2026-01-13 15:27:46 +00:00
PDP11: Addition of the RS03/RS04 disk devices from Bob Supnik
Note that this is not the fully general Massbus implementation people were dreaming of. MB#1 is for RP/RM, MB#2 is for TU, and MB#3 is for RS. I know that there were requests for four Massbus channels and multiple RP/RP subcontrollers, but if people want more disks, they can use the RQ.
This commit is contained in:
parent
68fbca919c
commit
1141339e5b
@ -26,6 +26,7 @@
|
||||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||
and John Wilson in resolving questions about the PDP-11
|
||||
|
||||
02-Sep-13 RMS Added third Massbus adapter and RS drive
|
||||
11-Dec-11 RMS Fixed priority of PIRQ vs IO; added INT_INTERNALn
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
19-Nov-08 RMS Moved I/O support routines to I/O library
|
||||
@ -598,10 +599,11 @@ typedef struct pdp_dib DIB;
|
||||
#define INT_V_TU 15
|
||||
#define INT_V_RF 16
|
||||
#define INT_V_RC 17
|
||||
#define INT_V_DMCRX 18
|
||||
#define INT_V_DMCTX 19
|
||||
#define INT_V_DUPRX 20
|
||||
#define INT_V_DUPTX 21
|
||||
#define INT_V_RS 18
|
||||
#define INT_V_DMCRX 19
|
||||
#define INT_V_DMCTX 20
|
||||
#define INT_V_DUPRX 21
|
||||
#define INT_V_DUPTX 22
|
||||
|
||||
#define INT_V_PIR4 0 /* BR4 */
|
||||
#define INT_V_TTI 1
|
||||
@ -645,6 +647,7 @@ typedef struct pdp_dib DIB;
|
||||
#define INT_TU (1u << INT_V_TU)
|
||||
#define INT_RF (1u << INT_V_RF)
|
||||
#define INT_RC (1u << INT_V_RC)
|
||||
#define INT_RS (1u << INT_V_RS)
|
||||
#define INT_DMCRX (1u << INT_V_DMCRX)
|
||||
#define INT_DMCTX (1u << INT_V_DMCTX)
|
||||
#define INT_DUPRX (1u << INT_V_DUPRX)
|
||||
@ -695,6 +698,7 @@ typedef struct pdp_dib DIB;
|
||||
#define IPL_TU 5
|
||||
#define IPL_RF 5
|
||||
#define IPL_RC 5
|
||||
#define IPL_RS 5
|
||||
#define IPL_DMCRX 5
|
||||
#define IPL_DMCTX 5
|
||||
#define IPL_DUPRX 5
|
||||
@ -741,9 +745,10 @@ typedef struct pdp_dib DIB;
|
||||
|
||||
/* Massbus definitions */
|
||||
|
||||
#define MBA_NUM 2 /* number of MBA's */
|
||||
#define MBA_NUM 3 /* number of MBA's */
|
||||
#define MBA_RP 0 /* MBA for RP */
|
||||
#define MBA_TU 1 /* MBA for TU */
|
||||
#define MBA_RS 2 /* MBA for RS */
|
||||
#define MBA_RMASK 037 /* max 32 reg */
|
||||
#define MBE_NXD 1 /* nx drive */
|
||||
#define MBE_NXR 2 /* nx reg */
|
||||
|
||||
@ -451,8 +451,8 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */
|
||||
{017300} }, /* KE11-A - fx CSR, no VEC */
|
||||
{ { "KG" }, 1, 0, 0, 0,
|
||||
{010700} }, /* KG11-A - fx CSR, no VEC */
|
||||
{ { "RHA", "RHB" }, 1, 1, 0, 0,
|
||||
{016700, 012440}, {0254, 0224} }, /* RH11/RH70 - fx CSR, fx VEC */
|
||||
{ { "RHA", "RHB", "RHC" }, 1, 1, 0, 0,
|
||||
{016700, 012440, 012040}, {0254, 0224, 0204} }, /* RH11/RH70 - fx CSR, fx VEC */
|
||||
{ { "CLK" }, 1, 1, 0, 0,
|
||||
{017546}, {0100} }, /* KW11L - fx CSR, fx VEC */
|
||||
{ { "PCLK" }, 1, 1, 0, 0,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* pdp11_rh.c: PDP-11 Massbus adapter simulator
|
||||
|
||||
Copyright (c) 2005-2012, Robert M Supnik
|
||||
Copyright (c) 2005-2013, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
rha, rhb RH11/RH70 Massbus adapter
|
||||
|
||||
02-Sep-13 RMS Added third Massbus adapter, debug printouts
|
||||
19-Mar-12 RMS Fixed declaration of cpu_opt (Mark Pizzolato)
|
||||
02-Feb-08 RMS Fixed DMA memory address limit test (John Dundas)
|
||||
17-May-07 RMS Moved CS1 drive enable to devices
|
||||
@ -172,6 +173,7 @@ t_stat mba_set_type (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat mba_show_type (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
int32 mba0_inta (void);
|
||||
int32 mba1_inta (void);
|
||||
int32 mba2_inta (void);
|
||||
void mba_set_int (uint32 mb);
|
||||
void mba_clr_int (uint32 mb);
|
||||
void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb);
|
||||
@ -273,6 +275,41 @@ MTAB mba1_mod[] = {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
#define IOLN_RS 040
|
||||
|
||||
DIB mba2_dib = {
|
||||
IOBA_AUTO, IOLN_RS, &mba_rd, &mba_wr,
|
||||
1, IVCL (RS), VEC_AUTO, { &mba2_inta }
|
||||
};
|
||||
|
||||
UNIT mba2_unit = { UDATA (NULL, 0, 0) };
|
||||
|
||||
REG mba2_reg[] = {
|
||||
{ ORDATA (CS1, massbus[2].cs1, 16) },
|
||||
{ ORDATA (WC, massbus[2].wc, 16) },
|
||||
{ ORDATA (BA, massbus[2].ba, 16) },
|
||||
{ ORDATA (CS2, massbus[2].cs2, 16) },
|
||||
{ ORDATA (DB, massbus[2].db, 16) },
|
||||
{ ORDATA (BAE, massbus[2].bae, 6) },
|
||||
{ ORDATA (CS3, massbus[2].cs3, 16) },
|
||||
{ FLDATA (IFF, massbus[2].iff, 0) },
|
||||
{ FLDATA (INT, IREQ (TU), INT_V_TU) },
|
||||
{ FLDATA (SC, massbus[2].cs1, CSR_V_ERR) },
|
||||
{ FLDATA (DONE, massbus[2].cs1, CSR_V_DONE) },
|
||||
{ FLDATA (IE, massbus[2].cs1, CSR_V_IE) },
|
||||
{ ORDATA (DEVADDR, mba2_dib.ba, 32), REG_HRO },
|
||||
{ ORDATA (DEVVEC, mba2_dib.vec, 16), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB mba2_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0040, "ADDRESS", "ADDRESS",
|
||||
&set_addr, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
||||
&set_vec, &show_vec, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE mba_dev[] = {
|
||||
{
|
||||
"RHA", &mba0_unit, mba0_reg, mba0_mod,
|
||||
@ -287,6 +324,13 @@ DEVICE mba_dev[] = {
|
||||
NULL, NULL, &mba_reset,
|
||||
NULL, NULL, NULL,
|
||||
&mba1_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS
|
||||
},
|
||||
{
|
||||
"RHC", &mba2_unit, mba2_reg, mba2_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &mba_reset,
|
||||
NULL, NULL, NULL,
|
||||
&mba2_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS
|
||||
}
|
||||
};
|
||||
|
||||
@ -416,6 +460,9 @@ switch (ofs) { /* case on reg */
|
||||
massbus[mb].cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE);
|
||||
massbus[mb].cs2 &= ~CS2_ERR; /* clear errors */
|
||||
massbus[mb].cs3 &= ~(CS3_ERR | CS3_DBL);
|
||||
if (DEBUG_PRS (mba_dev[mb]))
|
||||
fprintf (sim_deb, ">>RH%d STRT: cs1=%o, cs2=%o,ba=%o, wc=%o\n",
|
||||
mb, massbus[mb].cs1, massbus[mb].cs2, massbus[mb].ba, massbus[mb].wc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -624,6 +671,9 @@ return i;
|
||||
void mba_set_don (uint32 mb)
|
||||
{
|
||||
mba_upd_cs1 (CS1_DONE, 0, mb);
|
||||
if (DEBUG_PRS (mba_dev[mb]))
|
||||
fprintf (sim_deb, ">>RH%d DONE: cs1=%o, cs2=%o,ba=%o, wc=%o\n",
|
||||
mb, massbus[mb].cs1, massbus[mb].cs2, massbus[mb].ba, massbus[mb].wc);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -727,6 +777,14 @@ massbus[1].iff = 0; /* clear CSTB INTR */
|
||||
return mba1_dib.vec; /* acknowledge */
|
||||
}
|
||||
|
||||
int32 mba2_inta (void)
|
||||
{
|
||||
massbus[2].cs1 &= ~CS1_IE; /* clear int enable */
|
||||
massbus[2].cs3 &= ~CS1_IE; /* in both registers */
|
||||
massbus[2].iff = 0; /* clear CSTB INTR */
|
||||
return mba2_dib.vec; /* acknowledge */
|
||||
}
|
||||
|
||||
/* Map physical address to Massbus number, offset */
|
||||
|
||||
uint32 mba_map_pa (int32 pa, int32 *ofs)
|
||||
@ -784,11 +842,15 @@ return auto_config (0, 0);
|
||||
|
||||
void mba_set_enbdis (uint32 mb, t_bool dis)
|
||||
{
|
||||
t_bool orig;
|
||||
if (mb >= MBA_NUM) /* valid MBA? */
|
||||
return;
|
||||
orig = mba_dev[mb].flags & DEV_DIS;
|
||||
if (dis)
|
||||
mba_dev[mb].flags |= DEV_DIS;
|
||||
else mba_dev[mb].flags &= ~DEV_DIS;
|
||||
if (orig ^ dis)
|
||||
mba_reset (&mba_dev[mb]); /* reset on change */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -639,6 +639,8 @@ REG rp_reg[] = {
|
||||
};
|
||||
|
||||
MTAB rp_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MASSBUS", NULL,
|
||||
NULL, &mba_show_num, NULL, "Display Massbus number" },
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED",
|
||||
NULL, NULL, NULL, "Write enable disk drive" },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED",
|
||||
|
||||
724
PDP11/pdp11_rs.c
Normal file
724
PDP11/pdp11_rs.c
Normal file
@ -0,0 +1,724 @@
|
||||
/* pdp11_rs.c - RS03/RS04 Massbus disk controller
|
||||
|
||||
Copyright (c) 2013, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
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
|
||||
ROBERT M SUPNIK 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.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
rs RS03/RS04 fixed head disks
|
||||
*/
|
||||
|
||||
#if defined (VM_PDP10)
|
||||
#error "RS03/RS04 not supported on the PDP-10!"
|
||||
|
||||
#elif defined (VM_PDP11)
|
||||
#include "pdp11_defs.h"
|
||||
#define DEV_RADIX 8
|
||||
|
||||
#elif defined (VM_VAX)
|
||||
#error "RS03/RS04 not supported on the VAX!"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define RS_NUMDR 8 /* #drives */
|
||||
#define RS03_NUMWD 64 /* words/sector */
|
||||
#define RS04_NUMWD 128 /* words/sector */
|
||||
#define RS_NUMSC 64 /* sectors/track */
|
||||
#define RS_NUMTK 64 /* tracks/disk */
|
||||
#define RS_MAXFR (1 << 16) /* max transfer */
|
||||
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) (RS03_NUMWD * RS_NUMSC))))
|
||||
#define RS03_ID 0
|
||||
#define RS04_ID 2
|
||||
#define RS03_SIZE (RS_NUMTK * RS_NUMSC * RS03_NUMWD)
|
||||
#define RS04_SIZE (RS_NUMTK * RS_NUMSC * RS04_NUMWD)
|
||||
#define RS_NUMWD(d) ((d)? RS04_NUMWD: RS03_NUMWD)
|
||||
#define RS_SIZE(d) ((d)? RS04_SIZE: RS03_SIZE)
|
||||
|
||||
/* Flags in the unit flags word */
|
||||
|
||||
#define UNIT_V_DTYPE (UNIT_V_UF + 0) /* disk type */
|
||||
#define RS03_DTYPE (0)
|
||||
#define RS04_DTYPE (1)
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 1) /* autosize */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 2) /* write lock */
|
||||
#define UNIT_DTYPE (1 << UNIT_V_DTYPE)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & 1)
|
||||
|
||||
/* RSCS1 - control/status 1 - offset 0 */
|
||||
|
||||
#define RS_CS1_OF 0
|
||||
#define CS1_GO CSR_GO /* go */
|
||||
#define CS1_V_FNC 1 /* function pos */
|
||||
#define CS1_M_FNC 037 /* function mask */
|
||||
#define CS1_N_FNC (CS1_M_FNC + 1)
|
||||
#define FNC_NOP 000 /* no operation */
|
||||
#define FNC_DCLR 004 /* drive clear */
|
||||
#define FNC_SEARCH 014 /* search */
|
||||
#define FNC_XFR 020 /* divide line for xfr */
|
||||
#define FNC_WCHK 024 /* write check */
|
||||
#define FNC_WRITE 030 /* write */
|
||||
#define FNC_READ 034 /* read */
|
||||
#define CS1_RW 076
|
||||
#define CS1_DVA 04000 /* drive avail */
|
||||
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
|
||||
|
||||
/* RSDS - drive status - offset 1 */
|
||||
|
||||
#define RS_DS_OF 1
|
||||
#define DS_RDY 0000200 /* drive ready */
|
||||
#define DS_DPR 0000400 /* drive present */
|
||||
#define DS_LST 0002000 /* last sector */
|
||||
#define DS_WLK 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 */
|
||||
#define DS_MBZ 0001177
|
||||
|
||||
/* RSER - error status - offset 2 */
|
||||
|
||||
#define RS_ER_OF 2
|
||||
#define ER_ILF 0000001 /* illegal func */
|
||||
#define ER_ILR 0000002 /* illegal register */
|
||||
#define ER_RMR 0000004 /* reg mod refused */
|
||||
#define ER_PAR 0000010 /* parity err */
|
||||
#define ER_AOE 0001000 /* addr ovflo err */
|
||||
#define ER_IAE 0002000 /* invalid addr err */
|
||||
#define ER_WLE 0004000 /* write lock err NI */
|
||||
#define ER_DTE 0010000 /* drive time err NI */
|
||||
#define ER_OPI 0020000 /* op incomplete */
|
||||
#define ER_UNS 0040000 /* drive unsafe */
|
||||
#define ER_DCK 0100000 /* data check NI */
|
||||
#define ER_MBZ 0000760
|
||||
|
||||
/* RSMR - maintenace register - offset 3 */
|
||||
|
||||
#define RS_MR_OF 3
|
||||
|
||||
/* RSAS - attention summary - offset 4 */
|
||||
|
||||
#define RS_AS_OF 4
|
||||
#define AS_U0 0000001 /* unit 0 flag */
|
||||
|
||||
/* RSDA - sector/track - offset 5
|
||||
All 16b are RW, but only <14:12> are tested for "invalid" address */
|
||||
|
||||
#define RS_DA_OF 5
|
||||
#define DA_V_SC 0 /* sector pos */
|
||||
#define DA_M_SC 077 /* sector mask */
|
||||
#define DA_V_TK 6 /* track pos */
|
||||
#define DA_M_TK 077 /* track mask */
|
||||
#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC)
|
||||
#define GET_TK(x) (((x) >> DA_V_TK) & DA_M_TK)
|
||||
#define DA_INV 0070000 /* inv addr */
|
||||
#define DA_IGN 0100000 /* ignored */
|
||||
|
||||
/* RSDT - drive type - offset 6 */
|
||||
|
||||
#define RS_DT_OF 6
|
||||
|
||||
/* RSLA - look ahead register - offset 7 */
|
||||
|
||||
#define RS_LA_OF 7
|
||||
|
||||
/* This controller supports many two disk drive types:
|
||||
|
||||
type #words/ #sectors/ #tracks/
|
||||
sector track drive
|
||||
|
||||
RS03 64 64 64 =256KW
|
||||
RS04 128 64 640 =512KW
|
||||
|
||||
In theory, each drive can be a different type. The size field in
|
||||
each unit selects the drive capacity for each drive and thus the
|
||||
drive type.
|
||||
*/
|
||||
|
||||
uint16 rscs1[RS_NUMDR] = { 0 }; /* control/status 1 */
|
||||
uint16 rsda[RS_NUMDR] = { 0 }; /* track/sector */
|
||||
uint16 rsds[RS_NUMDR] = { 0 }; /* drive status */
|
||||
uint16 rser[RS_NUMDR] = { 0 }; /* error status */
|
||||
uint16 rsmr[RS_NUMDR] = { 0 }; /* maint register */
|
||||
uint8 rswlk[RS_NUMDR] = { 0 }; /* wlk switches */
|
||||
int32 rs_stopioe = 1; /* stop on error */
|
||||
int32 rs_wait = 10; /* rotate time */
|
||||
static const char *rs_fname[CS1_N_FNC] = {
|
||||
"NOP", "01", "02", "03", "DCLR", "05", "06", "07",
|
||||
"10", "11", "12", "13", "SCH", "15", "16", "17",
|
||||
"20", "21", "22", "23", "WRCHK", "25", "26", "27",
|
||||
"WRITE", "31", "32", "33", "READ", "35", "36", "37"
|
||||
};
|
||||
|
||||
t_stat rs_mbrd (int32 *data, int32 ofs, int32 drv);
|
||||
t_stat rs_mbwr (int32 data, int32 ofs, int32 drv);
|
||||
t_stat rs_svc (UNIT *uptr);
|
||||
t_stat rs_reset (DEVICE *dptr);
|
||||
t_stat rs_attach (UNIT *uptr, char *cptr);
|
||||
t_stat rs_detach (UNIT *uptr);
|
||||
t_stat rs_boot (int32 unitno, DEVICE *dptr);
|
||||
void rs_set_er (int32 flg, int32 drv);
|
||||
void rs_clr_as (int32 mask);
|
||||
void rs_update_ds (int32 flg, int32 drv);
|
||||
t_stat rs_go (int32 drv);
|
||||
t_stat rs_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
int32 rs_abort (void);
|
||||
t_stat rs_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
char *rs_description (DEVICE *dptr);
|
||||
|
||||
/* RS data structures
|
||||
|
||||
rs_dev RS device descriptor
|
||||
rs_unit RS unit list
|
||||
rs_reg RS register list
|
||||
rs_mod RS modifier list
|
||||
*/
|
||||
|
||||
DIB rs_dib = { MBA_RS, 0, &rs_mbrd, &rs_mbwr, 0, 0, 0, { &rs_abort } };
|
||||
|
||||
UNIT rs_unit[] = {
|
||||
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
|
||||
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
|
||||
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
|
||||
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
|
||||
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
|
||||
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
|
||||
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
|
||||
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
|
||||
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
|
||||
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) }
|
||||
};
|
||||
|
||||
REG rs_reg[] = {
|
||||
{ BRDATAD (CS1, rscs1, DEV_RDX, 16, RS_NUMDR, "control/status 1") },
|
||||
{ BRDATAD (DA, rsda, DEV_RDX, 16, RS_NUMDR, "track/sector") },
|
||||
{ BRDATAD (DS, rsds, DEV_RDX, 16, RS_NUMDR, "drive status") },
|
||||
{ BRDATAD (ER, rser, DEV_RDX, 16, RS_NUMDR, "error status") },
|
||||
{ BRDATAD (MR, rsmr, DEV_RDX, 16, RS_NUMDR, "maint register") },
|
||||
{ BRDATAD (WLKS, rswlk, DEV_RDX, 6, RS_NUMDR, "write lock switches") },
|
||||
{ DRDATAD (TIME, rs_wait, 24, "rotate time"), REG_NZ + PV_LEFT },
|
||||
{ URDATAD (CAPAC, rs_unit[0].capac, 10, T_ADDR_W, 0,
|
||||
RS_NUMDR, PV_LEFT | REG_HRO, "Capacity") },
|
||||
{ FLDATAD (STOP_IOE, rs_stopioe, 0, "stop on I/O error") },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB rs_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MASSBUS", NULL, NULL, &mba_show_num, NULL, "Display Massbus Address" },
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL, NULL, NULL, "Write enable disk drive" },
|
||||
{ UNIT_WLK, UNIT_WLK, "write lockable", "LOCKED", NULL, NULL, NULL, "Write lock disk drive" },
|
||||
{ (UNIT_DTYPE|UNIT_ATT), (RS03_DTYPE << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"RS03", NULL, NULL },
|
||||
{ (UNIT_DTYPE|UNIT_ATT), (RS04_DTYPE << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"RS04", NULL, NULL },
|
||||
{ (UNIT_AUTO|UNIT_DTYPE|UNIT_ATT), (RS03_DTYPE << UNIT_V_DTYPE),
|
||||
"RS03", NULL, NULL },
|
||||
{ (UNIT_AUTO|UNIT_DTYPE|UNIT_ATT), (RS04_DTYPE << UNIT_V_DTYPE),
|
||||
"RS04", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },
|
||||
{ UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL, NULL, NULL, "set type based on file size at ATTACH" },
|
||||
{ (UNIT_AUTO|UNIT_DTYPE), (RS03_DTYPE << UNIT_V_DTYPE),
|
||||
NULL, "RS03", &rs_set_size, NULL, NULL, "Set drive type RS03" },
|
||||
{ (UNIT_AUTO|UNIT_DTYPE), (RS04_DTYPE << UNIT_V_DTYPE),
|
||||
NULL, "RS04", &rs_set_size, NULL, NULL, "Set drive type RS04" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE rs_dev = {
|
||||
"RS", rs_unit, rs_reg, rs_mod,
|
||||
RS_NUMDR, DEV_RADIX, 19, 1, DEV_RADIX, 16,
|
||||
NULL, NULL, &rs_reset,
|
||||
&rs_boot, &rs_attach, &rs_detach,
|
||||
&rs_dib, DEV_DISABLE|DEV_DIS|DEV_UBUS|DEV_QBUS|DEV_MBUS|DEV_DEBUG, 0,
|
||||
NULL, NULL, NULL, &rs_help, NULL, NULL,
|
||||
&rs_description
|
||||
};
|
||||
|
||||
/* Massbus register read */
|
||||
|
||||
t_stat rs_mbrd (int32 *data, int32 ofs, int32 drv)
|
||||
{
|
||||
uint32 val, dtype, i;
|
||||
UNIT *uptr;
|
||||
|
||||
rs_update_ds (0, drv); /* update ds */
|
||||
uptr = rs_dev.units + drv; /* get unit */
|
||||
if (uptr->flags & UNIT_DIS) { /* nx disk */
|
||||
*data = 0;
|
||||
return MBE_NXD;
|
||||
}
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
ofs = ofs & MBA_RMASK; /* mask offset */
|
||||
|
||||
switch (ofs) { /* decode offset */
|
||||
|
||||
case RS_CS1_OF: /* RSCS1 */
|
||||
val = (rscs1[drv] & CS1_RW) | CS1_DVA; /* DVA always set */
|
||||
break;
|
||||
|
||||
case RS_DA_OF: /* RSDA */
|
||||
val = rsda[drv];
|
||||
break;
|
||||
|
||||
case RS_DS_OF: /* RSDS */
|
||||
val = rsds[drv] & ~DS_MBZ;
|
||||
break;
|
||||
|
||||
case RS_ER_OF: /* RSER */
|
||||
val = rser[drv] & ~ER_MBZ;
|
||||
break;
|
||||
|
||||
case RS_AS_OF: /* RSAS */
|
||||
val = 0;
|
||||
for (i = 0; i < RS_NUMDR; i++) {
|
||||
if (rsds[i] & DS_ATA)
|
||||
val |= (AS_U0 << i);
|
||||
}
|
||||
break;
|
||||
|
||||
case RS_LA_OF: /* RSLA */
|
||||
val = GET_POS (rs_wait);
|
||||
break;
|
||||
|
||||
case RS_MR_OF: /* RSMR */
|
||||
val = rsmr[drv];
|
||||
break;
|
||||
|
||||
case RS_DT_OF: /* RSDT */
|
||||
val = dtype? RS04_ID: RS03_ID;
|
||||
break;
|
||||
|
||||
default: /* all others */
|
||||
*data = 0;
|
||||
return MBE_NXR;
|
||||
}
|
||||
|
||||
*data = val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Massbus register write */
|
||||
|
||||
t_stat rs_mbwr (int32 data, int32 ofs, int32 drv)
|
||||
{
|
||||
int32 dtype;
|
||||
UNIT *uptr;
|
||||
|
||||
uptr = rs_dev.units + drv; /* get unit */
|
||||
if (uptr->flags & UNIT_DIS) /* nx disk */
|
||||
return MBE_NXD;
|
||||
if ((ofs != RS_AS_OF) && sim_is_active (uptr)) { /* unit busy? */
|
||||
rs_set_er (ER_RMR, drv); /* won't write */
|
||||
rs_update_ds (0, drv);
|
||||
return SCPE_OK;
|
||||
}
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
ofs = ofs & MBA_RMASK; /* mask offset */
|
||||
|
||||
switch (ofs) { /* decode PA<5:1> */
|
||||
|
||||
case RS_CS1_OF: /* RSCS1 */
|
||||
rscs1[drv] = data & CS1_RW;
|
||||
if (data & CS1_GO) /* start op */
|
||||
return rs_go (drv);
|
||||
break;
|
||||
|
||||
case RS_DA_OF: /* RSDA */
|
||||
rsda[drv] = data;
|
||||
break;
|
||||
|
||||
case RS_AS_OF: /* RSAS */
|
||||
rs_clr_as (data);
|
||||
break;
|
||||
|
||||
case RS_MR_OF: /* RSMR */
|
||||
rsmr[drv] = data;
|
||||
break;
|
||||
|
||||
case RS_ER_OF: /* RSER */
|
||||
case RS_DS_OF: /* RSDS */
|
||||
case RS_LA_OF: /* RSLA */
|
||||
case RS_DT_OF: /* RSDT */
|
||||
break; /* read only */
|
||||
|
||||
default: /* all others */
|
||||
return MBE_NXR;
|
||||
} /* end switch */
|
||||
|
||||
rs_update_ds (0, drv); /* update status */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Initiate operation - unit not busy, function set */
|
||||
|
||||
t_stat rs_go (int32 drv)
|
||||
{
|
||||
int32 fnc, dtype, t;
|
||||
UNIT *uptr;
|
||||
|
||||
fnc = GET_FNC (rscs1[drv]); /* get function */
|
||||
if (DEBUG_PRS (rs_dev))
|
||||
fprintf (sim_deb, ">>RS%d STRT: fnc=%s, ds=%o, da=%o, er=%o\n",
|
||||
drv, rs_fname[fnc], rsds[drv], rsda[drv], rser[drv]);
|
||||
uptr = rs_dev.units + drv; /* get unit */
|
||||
rs_clr_as (AS_U0 << drv); /* clear attention */
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
if ((fnc != FNC_DCLR) && (rsds[drv] & DS_ERR)) { /* err & ~clear? */
|
||||
rs_set_er (ER_ILF, drv); /* not allowed */
|
||||
rs_update_ds (DS_ATA, drv); /* set attention */
|
||||
return MBE_GOE;
|
||||
}
|
||||
|
||||
switch (fnc) { /* case on function */
|
||||
|
||||
case FNC_DCLR: /* drive clear */
|
||||
rser[drv] = 0; /* clear errors */
|
||||
case FNC_NOP: /* no operation */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_SEARCH: /* search */
|
||||
case FNC_WRITE: /* write */
|
||||
case FNC_WCHK: /* write check */
|
||||
case FNC_READ: /* read */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
rs_set_er (ER_UNS, drv); /* unsafe */
|
||||
break;
|
||||
}
|
||||
if (rsda[drv] & DA_INV) { /* bad address? */
|
||||
rs_set_er (ER_IAE, drv);
|
||||
break;
|
||||
}
|
||||
rsds[drv] = rsds[drv] & ~DS_RDY; /* clr drive rdy */
|
||||
if (fnc == FNC_SEARCH) /* search? */
|
||||
rsds[drv] = rsds[drv] | DS_PIP; /* set PIP */
|
||||
t = abs (rsda[drv] - GET_POS (rs_wait)); /* pos diff */
|
||||
if (t < 1) /* min time */
|
||||
t = 1;
|
||||
sim_activate (uptr, rs_wait * t); /* schedule */
|
||||
return SCPE_OK;
|
||||
|
||||
default: /* all others */
|
||||
rs_set_er (ER_ILF, drv); /* not supported */
|
||||
break;
|
||||
}
|
||||
|
||||
rs_update_ds (DS_ATA, drv); /* set attn, req int */
|
||||
return MBE_GOE;
|
||||
}
|
||||
|
||||
/* Abort opertion - there is a data transfer in progress */
|
||||
|
||||
int32 rs_abort (void)
|
||||
{
|
||||
return rs_reset (&rs_dev);
|
||||
}
|
||||
|
||||
/* Service unit timeout
|
||||
|
||||
Complete search or data transfer command
|
||||
Unit must exist - can't remove an active unit
|
||||
Drives are buffered in memory - no IO errors
|
||||
*/
|
||||
|
||||
t_stat rs_svc (UNIT *uptr)
|
||||
{
|
||||
int32 i, fnc, dtype, drv;
|
||||
int32 wc, abc, awc, mbc, da;
|
||||
uint16 *fbuf = (uint16 *)uptr->filebuf;
|
||||
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
drv = (int32) (uptr - rs_dev.units); /* get drv number */
|
||||
da = rsda[drv] * RS_NUMWD (dtype); /* get disk addr */
|
||||
fnc = GET_FNC (rscs1[drv]); /* get function */
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
rs_set_er (ER_UNS, drv); /* set drive error */
|
||||
if (fnc >= FNC_XFR) /* xfr? set done */
|
||||
mba_set_don (rs_dib.ba);
|
||||
rs_update_ds (DS_ATA, drv); /* set attn */
|
||||
return (rs_stopioe? SCPE_UNATT: SCPE_OK);
|
||||
}
|
||||
rsds[drv] = (rsds[drv] & ~DS_PIP) | DS_RDY; /* change drive status */
|
||||
|
||||
switch (fnc) { /* case on function */
|
||||
|
||||
case FNC_SEARCH: /* search */
|
||||
rs_update_ds (DS_ATA, drv);
|
||||
break;
|
||||
|
||||
case FNC_WRITE: /* write */
|
||||
if ((uptr->flags & UNIT_WLK) && /* write locked? */
|
||||
(GET_TK (rsda[drv]) <= (int32) rswlk[drv])) {
|
||||
rs_set_er (ER_WLE, drv); /* set drive error */
|
||||
mba_set_exc (rs_dib.ba); /* set exception */
|
||||
rs_update_ds (DS_ATA, drv); /* set attn */
|
||||
return SCPE_OK;
|
||||
}
|
||||
case FNC_WCHK: /* write check */
|
||||
case FNC_READ: /* read */
|
||||
if (rsda[drv] & DA_INV) { /* bad addr? */
|
||||
rs_set_er (ER_IAE, drv); /* set error */
|
||||
mba_set_exc (rs_dib.ba); /* set exception */
|
||||
rs_update_ds (DS_ATA, drv); /* set attn */
|
||||
break;
|
||||
}
|
||||
fbuf = fbuf + da; /* ptr into buffer */
|
||||
mbc = mba_get_bc (rs_dib.ba); /* get byte count */
|
||||
wc = (mbc + 1) >> 1; /* convert to words */
|
||||
if ((da + wc) > RS_SIZE (dtype)) { /* disk overrun? */
|
||||
rs_set_er (ER_AOE, drv); /* set err */
|
||||
wc = RS_SIZE (dtype) - da; /* trim xfer */
|
||||
mbc = wc << 1; /* trim mb count */
|
||||
}
|
||||
if (fnc == FNC_WRITE) { /* write? */
|
||||
abc = mba_rdbufW (rs_dib.ba, mbc, fbuf); /* rd mem to buf */
|
||||
wc = (abc + 1) >> 1; /* actual # wds */
|
||||
awc = (wc + (RS_NUMWD (dtype) - 1)) & ~(RS_NUMWD (dtype) - 1);
|
||||
for (i = wc; i < awc; i++) /* fill buf */
|
||||
fbuf[i] = 0;
|
||||
if ((da + awc) > (int32) uptr->hwmark) /* update hw mark*/
|
||||
uptr->hwmark = da + awc;
|
||||
} /* end if wr */
|
||||
else if (fnc == FNC_READ) /* read */
|
||||
mba_wrbufW (rs_dib.ba, mbc, fbuf); /* wri buf to mem */
|
||||
else mba_chbufW (rs_dib.ba, mbc, fbuf); /* check vs mem */
|
||||
|
||||
da = da + wc + (RS_NUMWD (dtype) - 1);
|
||||
if (da >= RS_SIZE (dtype))
|
||||
rsds[drv] = rsds[drv] | DS_LST;
|
||||
rsda[drv] = da / RS_NUMWD (dtype);
|
||||
mba_set_don (rs_dib.ba); /* set done */
|
||||
rs_update_ds (0, drv); /* update ds */
|
||||
break;
|
||||
} /* end case func */
|
||||
|
||||
if (DEBUG_PRS (rs_dev))
|
||||
fprintf (sim_deb, ">>RS%d DONE: fnc=%s, ds=%o, da=%o, er=%d\n",
|
||||
drv, rs_fname[fnc], rsds[drv], rsda[drv], rser[drv]);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set drive error */
|
||||
|
||||
void rs_set_er (int32 flag, int32 drv)
|
||||
{
|
||||
rser[drv] = rser[drv] | flag;
|
||||
rsds[drv] = rsds[drv] | DS_ATA;
|
||||
mba_upd_ata (rs_dib.ba, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear attention flags */
|
||||
|
||||
void rs_clr_as (int32 mask)
|
||||
{
|
||||
uint32 i, as;
|
||||
|
||||
for (i = as = 0; i < RS_NUMDR; i++) {
|
||||
if (mask & (AS_U0 << i))
|
||||
rsds[i] &= ~DS_ATA;
|
||||
if (rsds[i] & DS_ATA)
|
||||
as = 1;
|
||||
}
|
||||
mba_upd_ata (rs_dib.ba, as);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Drive status update */
|
||||
|
||||
void rs_update_ds (int32 flag, int32 drv)
|
||||
{
|
||||
if (flag & DS_ATA)
|
||||
mba_upd_ata (rs_dib.ba, 1);
|
||||
if (rs_unit[drv].flags & UNIT_DIS) {
|
||||
rsds[drv] = rser[drv] = 0;
|
||||
return;
|
||||
}
|
||||
else rsds[drv] = (rsds[drv] | DS_DPR) & ~(DS_ERR | DS_WLK);
|
||||
if (rs_unit[drv].flags & UNIT_ATT) {
|
||||
rsds[drv] = rsds[drv] | DS_MOL;
|
||||
if ((rs_unit[drv].flags & UNIT_WLK) &&
|
||||
(GET_TK (rsda[drv]) <= (int32) rswlk[drv]))
|
||||
rsds[drv] = rsds[drv] | DS_WLK;
|
||||
}
|
||||
if (rser[drv])
|
||||
rsds[drv] = rsds[drv] | DS_ERR;
|
||||
rsds[drv] = rsds[drv] | flag;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Device reset */
|
||||
|
||||
t_stat rs_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
UNIT *uptr;
|
||||
|
||||
mba_set_enbdis (MBA_RS, rs_dev.flags & DEV_DIS);
|
||||
for (i = 0; i < RS_NUMDR; i++) {
|
||||
uptr = rs_dev.units + i;
|
||||
sim_cancel (uptr);
|
||||
rscs1[i] = 0;
|
||||
rser[i] = 0;
|
||||
rsda[i] = 0;
|
||||
rsmr[i] = 0;
|
||||
rsds[i] = DS_RDY;
|
||||
rs_update_ds (0, i); /* upd drive status */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Device attach */
|
||||
|
||||
t_stat rs_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
int32 drv, p;
|
||||
t_stat r;
|
||||
|
||||
uptr->capac = RS_SIZE (GET_DTYPE (uptr->flags));
|
||||
r = attach_unit (uptr, cptr); /* attach unit */
|
||||
if (r != SCPE_OK) /* error? */
|
||||
return r;
|
||||
drv = (int32) (uptr - rs_dev.units); /* get drv number */
|
||||
rsds[drv] = DS_MOL | DS_RDY | DS_DPR; /* upd drv status */
|
||||
rser[drv] = 0;
|
||||
rs_update_ds (DS_ATA, drv); /* upd drive status */
|
||||
|
||||
if ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */
|
||||
return SCPE_OK;
|
||||
p = sim_fsize (uptr->fileref); /* get file size */
|
||||
if (((p + 1) >> 1) <= RS03_SIZE) {
|
||||
uptr->flags &= ~UNIT_DTYPE;
|
||||
uptr->capac = RS03_SIZE;
|
||||
}
|
||||
else {
|
||||
uptr->flags |= UNIT_DTYPE;
|
||||
uptr->capac = RS04_SIZE;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Device detach */
|
||||
|
||||
t_stat rs_detach (UNIT *uptr)
|
||||
{
|
||||
int32 drv;
|
||||
extern int32 sim_is_running;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT)) /* attached? */
|
||||
return SCPE_OK;
|
||||
drv = (int32) (uptr - rs_dev.units); /* get drv number */
|
||||
rsds[drv] = 0;
|
||||
if (!sim_is_running) /* from console? */
|
||||
rs_update_ds (DS_ATA, drv); /* request intr */
|
||||
return detach_unit (uptr);
|
||||
}
|
||||
|
||||
/* Set size command validation routine */
|
||||
|
||||
t_stat rs_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 dtype = GET_DTYPE (val);
|
||||
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
return SCPE_ALATT;
|
||||
uptr->capac = RS_SIZE (dtype);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set bad block routine */
|
||||
|
||||
/* Boot routine */
|
||||
|
||||
#define BOOT_START 02000 /* start */
|
||||
#define BOOT_ENTRY (BOOT_START + 002) /* entry */
|
||||
#define BOOT_UNIT (BOOT_START + 010) /* unit number */
|
||||
#define BOOT_CSR (BOOT_START + 014) /* CSR */
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint16))
|
||||
|
||||
static const uint16 boot_rom[] = {
|
||||
0042123, /* "SD" */
|
||||
0012706, BOOT_START, /* mov #boot_start, sp */
|
||||
0012700, 0000000, /* mov #unit, r0 */
|
||||
0012701, 0172040, /* mov #RSCS1, r1 */
|
||||
0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */
|
||||
0010061, 0000010, /* mov r0, 10(r1) ; set unit */
|
||||
0012761, 0177000, 0000002, /* mov #-512., 2(r1) ; set wc */
|
||||
0005061, 0000004, /* clr 4(r1) ; clr ba */
|
||||
0005061, 0000006, /* clr 6(r1) ; clr da */
|
||||
0012711, 0000071, /* mov #READ+GO, (r1) ; read */
|
||||
0105711, /* tstb (r1) ; wait */
|
||||
0100376, /* bpl .-2 */
|
||||
0005002, /* clr R2 */
|
||||
0005003, /* clr R3 */
|
||||
0012704, BOOT_START+020, /* mov #start+020, r4 */
|
||||
0005005, /* clr R5 */
|
||||
0105011, /* clrb (r1) */
|
||||
0005007 /* clr PC */
|
||||
};
|
||||
|
||||
t_stat rs_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
extern int32 saved_PC;
|
||||
extern uint16 *M;
|
||||
UNIT *uptr = rs_dev.units + unitno;
|
||||
|
||||
for (i = 0; i < BOOT_LEN; i++)
|
||||
M[(BOOT_START >> 1) + i] = boot_rom[i];
|
||||
M[BOOT_UNIT >> 1] = unitno & (RS_NUMDR - 1);
|
||||
M[BOOT_CSR >> 1] = mba_get_csr (rs_dib.ba) & DMASK;
|
||||
saved_PC = BOOT_ENTRY;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat rs_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
|
||||
{
|
||||
fprintf (st, "RS03/RS04 Massbus disk controller (RS)\n\n");
|
||||
fprintf (st, "Options include the ability to set units write enabled or write locked,\n");
|
||||
fprintf (st, "to set the drive type to RS03, RS04, or autosize:\n\n");
|
||||
fprint_set_help (st, dptr);
|
||||
fprint_show_help (st, dptr);
|
||||
fprintf (st, "\nThe type options can be used only when a unit is not attached to a file.\n");
|
||||
fprintf (st, "The RS device supports the BOOT command.\n");
|
||||
fprint_reg_help (st, dptr);
|
||||
fprintf (st, "\nError handling is as follows:\n\n");
|
||||
fprintf (st, " error STOP_IOE processed as\n");
|
||||
fprintf (st, " not attached 1 report error and stop\n");
|
||||
fprintf (st, " 0 disk not ready\n\n");
|
||||
fprintf (st, " end of file x assume rest of disk is zero\n");
|
||||
fprintf (st, " OS I/O error x report error and stop\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
char *rs_description (DEVICE *dptr)
|
||||
{
|
||||
return "RS03/RS04 Massbus disk controller";
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/* pdp11_sys.c: PDP-11 simulator interface
|
||||
|
||||
Copyright (c) 1993-2012, Robert M Supnik
|
||||
Copyright (c) 1993-2013, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@ -23,6 +23,7 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
02-Sep-13 RMS Added third Massbus, RS03/RS04
|
||||
29-Apr-12 RMS Fixed compiler warning (Mark Pizzolato)
|
||||
19-Nov-08 RMS Moved I/O support routines to I/O library
|
||||
15-May-08 RMS Added KE11-A, DC11 support
|
||||
@ -92,6 +93,7 @@ extern DEVICE rx_dev;
|
||||
extern DEVICE ry_dev;
|
||||
extern DEVICE mba_dev[];
|
||||
extern DEVICE rp_dev;
|
||||
extern DEVICE rs_dev;
|
||||
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
|
||||
extern DEVICE tm_dev;
|
||||
extern DEVICE tq_dev;
|
||||
@ -131,6 +133,7 @@ DEVICE *sim_devices[] = {
|
||||
&sys_dev,
|
||||
&mba_dev[0],
|
||||
&mba_dev[1],
|
||||
&mba_dev[2],
|
||||
&clk_dev,
|
||||
&pclk_dev,
|
||||
&ptr_dev,
|
||||
@ -153,6 +156,7 @@ DEVICE *sim_devices[] = {
|
||||
&rx_dev,
|
||||
&ry_dev,
|
||||
&rp_dev,
|
||||
&rs_dev,
|
||||
&rq_dev,
|
||||
&rqb_dev,
|
||||
&rqc_dev,
|
||||
|
||||
@ -291,6 +291,10 @@
|
||||
RelativePath="..\PDP11\pdp11_rq.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PDP11\pdp11_rs.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PDP11\pdp11_rx.c"
|
||||
>
|
||||
|
||||
@ -534,7 +534,8 @@ PDP11_SOURCE1 = $(PDP11_DIR)PDP11_FP.C,$(PDP11_DIR)PDP11_CPU.C,\
|
||||
$(PDP11_DIR)PDP11_SYS.C,$(PDP11_DIR)PDP11_TC.C, \
|
||||
$(PDP11_DIR)PDP11_CPUMOD.C,$(PDP11_DIR)PDP11_CR.C,\
|
||||
$(PDP11_DIR)PDP11_TA.C,$(PDP11_DIR)PDP11_DMC.C,\
|
||||
$(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_IO_LIB.C
|
||||
$(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_RS.C,\
|
||||
$(PDP11_DIR)PDP11_IO_LIB.C
|
||||
PDP11_LIB2 = $(LIB_DIR)PDP11L2-$(ARCH).OLB
|
||||
PDP11_SOURCE2 = $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.C,\
|
||||
$(PDP11_DIR)PDP11_IO.C,$(PDP11_DIR)PDP11_RQ.C,\
|
||||
|
||||
2
makefile
2
makefile
@ -711,7 +711,7 @@ PDP11 = ${PDP11D}/pdp11_fp.c ${PDP11D}/pdp11_cpu.c ${PDP11D}/pdp11_dz.c \
|
||||
${PDP11D}/pdp11_cr.c ${PDP11D}/pdp11_rf.c ${PDP11D}/pdp11_dl.c \
|
||||
${PDP11D}/pdp11_ta.c ${PDP11D}/pdp11_rc.c ${PDP11D}/pdp11_kg.c \
|
||||
${PDP11D}/pdp11_ke.c ${PDP11D}/pdp11_dc.c ${PDP11D}/pdp11_dmc.c \
|
||||
${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_io_lib.c
|
||||
${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_rs.c ${PDP11D}/pdp11_io_lib.c
|
||||
PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user