PDP11: fix RK device unit detection when some units are disabled.

This commit is contained in:
Mark Pizzolato 2013-09-05 19:03:06 -07:00
parent 59232fed53
commit ddc9398f90

View file

@ -97,40 +97,75 @@
/* RKDS */ /* RKDS */
BITFIELD rk_ds_bits[] = {
#define RKDS_SC 0000017 /* sector counter */ #define RKDS_SC 0000017 /* sector counter */
BITF(SC,4),
#define RKDS_ON_SC 0000020 /* on sector */ #define RKDS_ON_SC 0000020 /* on sector */
BIT(ON_SC),
#define RKDS_WLK 0000040 /* write locked */ #define RKDS_WLK 0000040 /* write locked */
BIT(WLK),
#define RKDS_RWS 0000100 /* rd/wr/seek ready */ #define RKDS_RWS 0000100 /* rd/wr/seek ready */
BIT(RWS),
#define RKDS_RDY 0000200 /* drive ready */ #define RKDS_RDY 0000200 /* drive ready */
BIT(RDY),
#define RKDS_SC_OK 0000400 /* SC valid */ #define RKDS_SC_OK 0000400 /* SC valid */
BIT(SC_OK),
#define RKDS_INC 0001000 /* seek incomplete */ #define RKDS_INC 0001000 /* seek incomplete */
BIT(INC),
#define RKDS_UNSAFE 0002000 /* unsafe */ #define RKDS_UNSAFE 0002000 /* unsafe */
BIT(UNSAFE),
#define RKDS_RK05 0004000 /* RK05 */ #define RKDS_RK05 0004000 /* RK05 */
BIT(RK05),
#define RKDS_PWR 0010000 /* power low */ #define RKDS_PWR 0010000 /* power low */
BIT(PWR),
#define RKDS_ID 0160000 /* drive ID */ #define RKDS_ID 0160000 /* drive ID */
#define RKDS_V_ID 13 #define RKDS_V_ID 13
BITF(ID,3),
ENDBITS
};
/* RKER */ /* RKER */
BITFIELD rk_er_bits[] = {
#define RKER_WCE 0000001 /* write check */ #define RKER_WCE 0000001 /* write check */
BIT(WCE),
#define RKER_CSE 0000002 /* checksum */ #define RKER_CSE 0000002 /* checksum */
BIT(CSE),
#define RKER_NXS 0000040 /* nx sector */ #define RKER_NXS 0000040 /* nx sector */
BIT(NXS),
#define RKER_NXC 0000100 /* nx cylinder */ #define RKER_NXC 0000100 /* nx cylinder */
BIT(NXC),
#define RKER_NXD 0000200 /* nx drive */ #define RKER_NXD 0000200 /* nx drive */
BIT(NXD),
#define RKER_TE 0000400 /* timing error */ #define RKER_TE 0000400 /* timing error */
BIT(TE),
#define RKER_DLT 0001000 /* data late */ #define RKER_DLT 0001000 /* data late */
BIT(DLT),
#define RKER_NXM 0002000 /* nx memory */ #define RKER_NXM 0002000 /* nx memory */
BIT(NXM),
#define RKER_PGE 0004000 /* programming error */ #define RKER_PGE 0004000 /* programming error */
BIT(PGE),
#define RKER_SKE 0010000 /* seek error */ #define RKER_SKE 0010000 /* seek error */
BIT(SKE),
#define RKER_WLK 0020000 /* write lock */ #define RKER_WLK 0020000 /* write lock */
BIT(WLK),
#define RKER_OVR 0040000 /* overrun */ #define RKER_OVR 0040000 /* overrun */
BIT(OVR),
#define RKER_DRE 0100000 /* drive error */ #define RKER_DRE 0100000 /* drive error */
BIT(DRE),
#define RKER_IMP 0177743 /* implemented */ #define RKER_IMP 0177743 /* implemented */
#define RKER_SOFT (RKER_WCE+RKER_CSE) /* soft errors */ #define RKER_SOFT (RKER_WCE+RKER_CSE) /* soft errors */
#define RKER_HARD 0177740 /* hard errors */ #define RKER_HARD 0177740 /* hard errors */
ENDBITS
};
/* RKCS */ /* RKCS */
static const char *rk_funcs[] = {
"CTLRESET", "WRITE", "READ", "WCHK", "SEEK", "RCHK", "DRVRESET", "WLK"};
BITFIELD rk_cs_bits[] = {
BIT(GO),
#define RKCS_M_FUNC 0000007 /* function */ #define RKCS_M_FUNC 0000007 /* function */
#define RKCS_CTLRESET 0 #define RKCS_CTLRESET 0
#define RKCS_WRITE 1 #define RKCS_WRITE 1
@ -141,38 +176,91 @@
#define RKCS_DRVRESET 6 #define RKCS_DRVRESET 6
#define RKCS_WLK 7 #define RKCS_WLK 7
#define RKCS_V_FUNC 1 #define RKCS_V_FUNC 1
BITFNAM(FUNC,3,rk_funcs),
#define RKCS_MEX 0000060 /* memory extension */ #define RKCS_MEX 0000060 /* memory extension */
#define RKCS_V_MEX 4 #define RKCS_V_MEX 4
BITF(MEX,2),
BIT(IE),
BIT(DONE),
#define RKCS_SSE 0000400 /* stop on soft err */ #define RKCS_SSE 0000400 /* stop on soft err */
BIT(SSE),
BITNC,
#define RKCS_FMT 0002000 /* format */ #define RKCS_FMT 0002000 /* format */
BIT(FMT),
#define RKCS_INH 0004000 /* inhibit increment */ #define RKCS_INH 0004000 /* inhibit increment */
BIT(INH),
BITNC,
#define RKCS_SCP 0020000 /* search complete */ #define RKCS_SCP 0020000 /* search complete */
BIT(SCP),
#define RKCS_HERR 0040000 /* hard error */ #define RKCS_HERR 0040000 /* hard error */
BIT(HERR),
#define RKCS_ERR 0100000 /* error */ #define RKCS_ERR 0100000 /* error */
BIT(ERR),
#define RKCS_REAL 0026776 /* kept here */ #define RKCS_REAL 0026776 /* kept here */
#define RKCS_RW 0006576 /* read/write */ #define RKCS_RW 0006576 /* read/write */
#define GET_FUNC(x) (((x) >> RKCS_V_FUNC) & RKCS_M_FUNC) #define GET_FUNC(x) (((x) >> RKCS_V_FUNC) & RKCS_M_FUNC)
ENDBITS
};
/* RKDA */ /* RKDA */
BITFIELD rk_da_bits[] = {
#define RKDA_V_SECT 0 /* sector */ #define RKDA_V_SECT 0 /* sector */
#define RKDA_M_SECT 017 #define RKDA_M_SECT 017
BITF(SECT,4),
#define RKDA_V_TRACK 4 /* track */ #define RKDA_V_TRACK 4 /* track */
#define RKDA_M_TRACK 0777 #define RKDA_M_TRACK 0777
BITF(SURF,1),
#define RKDA_V_CYL 5 /* cylinder */ #define RKDA_V_CYL 5 /* cylinder */
#define RKDA_M_CYL 0377 #define RKDA_M_CYL 0377
BITF(CYL,8),
#define RKDA_V_DRIVE 13 /* drive */ #define RKDA_V_DRIVE 13 /* drive */
#define RKDA_M_DRIVE 07 #define RKDA_M_DRIVE 07
#define RKDA_DRIVE (RKDA_M_DRIVE << RKDA_V_DRIVE) #define RKDA_DRIVE (RKDA_M_DRIVE << RKDA_V_DRIVE)
BITF(DRIVE,3),
#define GET_SECT(x) (((x) >> RKDA_V_SECT) & RKDA_M_SECT) #define GET_SECT(x) (((x) >> RKDA_V_SECT) & RKDA_M_SECT)
#define GET_CYL(x) (((x) >> RKDA_V_CYL) & RKDA_M_CYL) #define GET_CYL(x) (((x) >> RKDA_V_CYL) & RKDA_M_CYL)
#define GET_TRACK(x) (((x) >> RKDA_V_TRACK) & RKDA_M_TRACK) #define GET_TRACK(x) (((x) >> RKDA_V_TRACK) & RKDA_M_TRACK)
#define GET_DRIVE(x) (((x) >> RKDA_V_DRIVE) & RKDA_M_DRIVE) #define GET_DRIVE(x) (((x) >> RKDA_V_DRIVE) & RKDA_M_DRIVE)
#define GET_DA(x) ((GET_TRACK (x) * RK_NUMSC) + GET_SECT (x)) #define GET_DA(x) ((GET_TRACK (x) * RK_NUMSC) + GET_SECT (x))
ENDBITS
};
/* RKWC */
BITFIELD rk_wc_bits[] = {
BITF(WC,16),
ENDBITS
};
/* RKBA */ /* RKBA */
BITFIELD rk_ba_bits[] = {
#define RKBA_IMP 0177776 /* implemented */ #define RKBA_IMP 0177776 /* implemented */
BITF(BA,16),
ENDBITS
};
BITFIELD *rk_reg_bits[] = {
rk_ds_bits,
rk_er_bits,
rk_cs_bits,
rk_wc_bits,
rk_ba_bits,
rk_da_bits,
NULL,
NULL,
};
/* Debug detail levels */
#define RKDEB_OPS 001 /* transactions */
#define RKDEB_RRD 002 /* reg reads */
#define RKDEB_RWR 004 /* reg writes */
#define RKDEB_TRC 010 /* trace */
#define RKDEB_INT 020 /* interrupts */
#define RK_MIN 10 #define RK_MIN 10
#define MAX(x,y) (((x) > (y))? (x): (y)) #define MAX(x,y) (((x) > (y))? (x): (y))
@ -193,6 +281,26 @@ int32 rk_stopioe = 1; /* stop on error */
int32 rk_swait = 10; /* seek time */ int32 rk_swait = 10; /* seek time */
int32 rk_rwait = 10; /* rotate time */ int32 rk_rwait = 10; /* rotate time */
char *rk_regnames[] = {
"RKDS",
"RKER",
"RKCS",
"RKWC",
"RKBA",
"RKDA",
"unused",
"RKDB",
};
int32 *rk_regs[] = {
&rkds,
&rker,
&rkcs,
&rkwc,
&rkba,
&rkda,
};
DEVICE rk_dev; DEVICE rk_dev;
t_stat rk_rd (int32 *data, int32 PA, int32 access); t_stat rk_rd (int32 *data, int32 PA, int32 access);
t_stat rk_wr (int32 data, int32 PA, int32 access); t_stat rk_wr (int32 data, int32 PA, int32 access);
@ -206,6 +314,15 @@ t_stat rk_boot (int32 unitno, DEVICE *dptr);
t_stat rk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat rk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
char *rk_description (DEVICE *dptr); char *rk_description (DEVICE *dptr);
DEBTAB rk_deb[] = {
{ "OPS", RKDEB_OPS },
{ "RRD", RKDEB_RRD },
{ "RWR", RKDEB_RWR },
{ "INTERRUPT", RKDEB_INT },
{ "TRACE", RKDEB_TRC },
{ NULL, 0 }
};
/* RK11 data structures /* RK11 data structures
rk_dev RK device descriptor rk_dev RK device descriptor
@ -278,8 +395,8 @@ DEVICE rk_dev = {
RK_NUMDR, 8, 24, 1, 8, 16, RK_NUMDR, 8, 24, 1, 8, 16,
NULL, NULL, &rk_reset, NULL, NULL, &rk_reset,
&rk_boot, NULL, NULL, &rk_boot, NULL, NULL,
&rk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18, 0, &rk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 | DEV_DEBUG, 0,
NULL, NULL, NULL, &rk_help, NULL, NULL, rk_deb, NULL, NULL, &rk_help, NULL, NULL,
&rk_description &rk_description
}; };
@ -304,9 +421,11 @@ UNIT *uptr;
switch ((PA >> 1) & 07) { /* decode PA<3:1> */ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
case 0: /* RKDS: read only */ case 0: /* RKDS: read only */
rkds = (rkds & RKDS_ID) | RKDS_RK05 | RKDS_SC_OK | rkds = (rkds & RKDS_ID) | RKDS_SC_OK |
(rand () % RK_NUMSC); /* random sector */ (rand () % RK_NUMSC); /* random sector */
uptr = rk_dev.units + GET_DRIVE (rkda); /* selected unit */ uptr = rk_dev.units + GET_DRIVE (rkda); /* selected unit */
if (!(uptr->flags & UNIT_DIS)) /* enabled? */
rkds = rkds | RKDS_RK05;
if (uptr->flags & UNIT_ATT) /* attached? */ if (uptr->flags & UNIT_ATT) /* attached? */
rkds = rkds | RKDS_RDY; rkds = rkds | RKDS_RDY;
if (!sim_is_active (uptr)) /* idle? */ if (!sim_is_active (uptr)) /* idle? */
@ -316,11 +435,11 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
if (GET_SECT (rkda) == (rkds & RKDS_SC)) if (GET_SECT (rkda) == (rkds & RKDS_SC))
rkds = rkds | RKDS_ON_SC; rkds = rkds | RKDS_ON_SC;
*data = rkds; *data = rkds;
return SCPE_OK; break;
case 1: /* RKER: read only */ case 1: /* RKER: read only */
*data = rker & RKER_IMP; *data = rker & RKER_IMP;
return SCPE_OK; break;
case 2: /* RKCS */ case 2: /* RKCS */
rkcs = rkcs & RKCS_REAL; rkcs = rkcs & RKCS_REAL;
@ -329,35 +448,40 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
if (rker & RKER_HARD) if (rker & RKER_HARD)
rkcs = rkcs | RKCS_HERR; rkcs = rkcs | RKCS_HERR;
*data = rkcs; *data = rkcs;
return SCPE_OK; break;
case 3: /* RKWC */ case 3: /* RKWC */
*data = rkwc; *data = rkwc;
return SCPE_OK; break;
case 4: /* RKBA */ case 4: /* RKBA */
*data = rkba & RKBA_IMP; *data = rkba & RKBA_IMP;
return SCPE_OK; break;
case 5: /* RKDA */ case 5: /* RKDA */
*data = rkda; *data = rkda;
return SCPE_OK; break;
default: default:
*data = 0; *data = 0;
return SCPE_OK; return SCPE_OK;
} /* end switch */ } /* end switch */
sim_debug (RKDEB_RRD, &rk_dev, ">>RK read: %s=0%o\n", rk_regnames[(PA >> 1) & 07], *data);
sim_debug_bits (RKDEB_RRD, &rk_dev, rk_reg_bits[(PA >> 1) & 07], *data, *data, 1);
return SCPE_OK;
} }
t_stat rk_wr (int32 data, int32 PA, int32 access) t_stat rk_wr (int32 data, int32 PA, int32 access)
{ {
int32 old_val = *rk_regs[(PA >> 1) & 07], new_val = 0;
switch ((PA >> 1) & 07) { /* decode PA<3:1> */ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
case 0: /* RKDS: read only */ case 0: /* RKDS: read only */
return SCPE_OK; break;
case 1: /* RKER: read only */ case 1: /* RKER: read only */
return SCPE_OK; break;
case 2: /* RKCS */ case 2: /* RKCS */
rkcs = rkcs & RKCS_REAL; rkcs = rkcs & RKCS_REAL;
@ -365,28 +489,30 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
data = (PA & 1)? (rkcs & 0377) | (data << 8): (rkcs & ~0377) | data; data = (PA & 1)? (rkcs & 0377) | (data << 8): (rkcs & ~0377) | data;
if ((data & CSR_IE) == 0) { /* int disable? */ if ((data & CSR_IE) == 0) { /* int disable? */
rkintq = 0; /* clr int queue */ rkintq = 0; /* clr int queue */
sim_debug (RKDEB_INT, &rk_dev, "rk_wr(CLR_INT)\n");
CLR_INT (RK); /* clr int request */ CLR_INT (RK); /* clr int request */
} }
else if ((rkcs & (CSR_DONE + CSR_IE)) == CSR_DONE) { else if ((rkcs & (CSR_DONE + CSR_IE)) == CSR_DONE) {
rkintq = rkintq | RK_CTLI; /* queue ctrl int */ rkintq = rkintq | RK_CTLI; /* queue ctrl int */
sim_debug (RKDEB_INT, &rk_dev, "rk_wr(SET_INT)\n");
SET_INT (RK); /* set int request */ SET_INT (RK); /* set int request */
} }
rkcs = (rkcs & ~RKCS_RW) | (data & RKCS_RW); rkcs = (rkcs & ~RKCS_RW) | (data & RKCS_RW);
if ((rkcs & CSR_DONE) && (data & CSR_GO)) /* new function? */ if ((rkcs & CSR_DONE) && (data & CSR_GO)) /* new function? */
rk_go (); rk_go ();
return SCPE_OK; break;
case 3: /* RKWC */ case 3: /* RKWC */
if (access == WRITEB) if (access == WRITEB)
data = (PA & 1)? (rkwc & 0377) | (data << 8): (rkwc & ~0377) | data; data = (PA & 1)? (rkwc & 0377) | (data << 8): (rkwc & ~0377) | data;
rkwc = data; rkwc = data;
return SCPE_OK; break;
case 4: /* RKBA */ case 4: /* RKBA */
if (access == WRITEB) if (access == WRITEB)
data = (PA & 1)? (rkba & 0377) | (data << 8): (rkba & ~0377) | data; data = (PA & 1)? (rkba & 0377) | (data << 8): (rkba & ~0377) | data;
rkba = data & RKBA_IMP; rkba = data & RKBA_IMP;
return SCPE_OK; break;
case 5: /* RKDA */ case 5: /* RKDA */
if ((rkcs & CSR_DONE) == 0) if ((rkcs & CSR_DONE) == 0)
@ -394,11 +520,14 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
if (access == WRITEB) if (access == WRITEB)
data = (PA & 1)? (rkda & 0377) | (data << 8): (rkda & ~0377) | data; data = (PA & 1)? (rkda & 0377) | (data << 8): (rkda & ~0377) | data;
rkda = data; rkda = data;
return SCPE_OK; break;
default: default:
return SCPE_OK; return SCPE_OK;
} /* end switch */ } /* end switch */
sim_debug (RKDEB_RWR, &rk_dev, ">>RK write: %s=0%o\n", rk_regnames[(PA >> 1) & 07], data);
sim_debug_bits (RKDEB_RWR, &rk_dev, rk_reg_bits[(PA >> 1) & 07], old_val, *rk_regs[(PA >> 1) & 07], 1);
return SCPE_OK;
} }
/* Initiate new function */ /* Initiate new function */
@ -415,6 +544,7 @@ if (func == RKCS_CTLRESET) { /* control reset? */
rkba = 0; rkba = 0;
rkcs = CSR_DONE; rkcs = CSR_DONE;
rkintq = 0; /* clr int queue */ rkintq = 0; /* clr int queue */
sim_debug (RKDEB_INT, &rk_dev, "rk_go(CLR_INT)\n");
CLR_INT (RK); /* clr int request */ CLR_INT (RK); /* clr int request */
return; return;
} }
@ -498,11 +628,14 @@ if (uptr->FUNC == RKCS_SEEK) { /* seek */
rkcs = rkcs | RKCS_SCP; /* set seek done */ rkcs = rkcs | RKCS_SCP; /* set seek done */
if (rkcs & CSR_IE) { /* ints enabled? */ if (rkcs & CSR_IE) { /* ints enabled? */
rkintq = rkintq | RK_SCPI (drv); /* queue request */ rkintq = rkintq | RK_SCPI (drv); /* queue request */
if (rkcs & CSR_DONE) if (rkcs & CSR_DONE) {
sim_debug (RKDEB_INT, &rk_dev, "rk_svc(SET_INT)\n");
SET_INT (RK); SET_INT (RK);
}
} }
else { else {
rkintq = 0; /* clear queue */ rkintq = 0; /* clear queue */
sim_debug (RKDEB_INT, &rk_dev, "rk_svc(CLR_INT)\n");
CLR_INT (RK); /* clear interrupt */ CLR_INT (RK); /* clear interrupt */
} }
return SCPE_OK; return SCPE_OK;
@ -659,10 +792,12 @@ if (error != 0) {
} }
if (rkcs & CSR_IE) { /* int enable? */ if (rkcs & CSR_IE) { /* int enable? */
rkintq = rkintq | RK_CTLI; /* set ctrl int */ rkintq = rkintq | RK_CTLI; /* set ctrl int */
sim_debug (RKDEB_INT, &rk_dev, "rk_set_done(SET_INT)\n");
SET_INT (RK); /* request int */ SET_INT (RK); /* request int */
} }
else { else {
rkintq = 0; /* clear queue */ rkintq = 0; /* clear queue */
sim_debug (RKDEB_INT, &rk_dev, "rk_set_done(CLR_INT)\n");
CLR_INT (RK); CLR_INT (RK);
} }
return; return;
@ -672,6 +807,7 @@ void rk_clr_done (void)
{ {
rkcs = rkcs & ~CSR_DONE; /* clear done */ rkcs = rkcs & ~CSR_DONE; /* clear done */
rkintq = rkintq & ~RK_CTLI; /* clear ctl int */ rkintq = rkintq & ~RK_CTLI; /* clear ctl int */
sim_debug (RKDEB_INT, &rk_dev, "rk_clr_done(CLR_INT)\n");
CLR_INT (RK); /* clear int req */ CLR_INT (RK); /* clear int req */
return; return;
} }
@ -683,14 +819,17 @@ int32 i;
for (i = 0; i <= RK_NUMDR; i++) { /* loop thru intq */ for (i = 0; i <= RK_NUMDR; i++) { /* loop thru intq */
if (rkintq & (1u << i)) { /* bit i set? */ if (rkintq & (1u << i)) { /* bit i set? */
rkintq = rkintq & ~(1u << i); /* clear bit i */ rkintq = rkintq & ~(1u << i); /* clear bit i */
if (rkintq) /* queue next */ if (rkintq) { /* queue next */
sim_debug (RKDEB_INT, &rk_dev, "rk_inta(SET_INT)\n");
SET_INT (RK); SET_INT (RK);
}
rkds = (rkds & ~RKDS_ID) | /* id drive */ rkds = (rkds & ~RKDS_ID) | /* id drive */
(((i == 0)? last_drv: i - 1) << RKDS_V_ID); (((i == 0)? last_drv: i - 1) << RKDS_V_ID);
sim_debug (RKDEB_INT, &rk_dev, "rk_inta(vec=0%o)\n", rk_dib.vec);
return rk_dib.vec; /* return vector */ return rk_dib.vec; /* return vector */
} }
} }
rkintq = 0; /* clear queue */ rkintq = 0; /* clear queue */
return 0; /* passive release */ return 0; /* passive release */
} }
@ -704,6 +843,7 @@ UNIT *uptr;
rkcs = CSR_DONE; rkcs = CSR_DONE;
rkda = rkba = rker = rkds = 0; rkda = rkba = rker = rkds = 0;
rkintq = last_drv = 0; rkintq = last_drv = 0;
sim_debug (RKDEB_INT, &rk_dev, "rk_reset(CLR_INT)\n");
CLR_INT (RK); CLR_INT (RK);
for (i = 0; i < RK_NUMDR; i++) { for (i = 0; i < RK_NUMDR; i++) {
uptr = rk_dev.units + i; uptr = rk_dev.units + i;