PDP15: Update pdp18b_rp from Bob Supnik.

1. Added RP03 support and supporting "SET" commands.
2. Fixed implementation of DPCF (it's a full reset and not blocked by BUSY).
3. Fixed handling of JOB DONE flag (not touched by NOP, SEEK, or RECAL).
This commit is contained in:
Mark Pizzolato 2016-03-16 12:49:03 -07:00
parent af0420f92b
commit e0e58fce66
2 changed files with 73 additions and 36 deletions

View file

@ -23,8 +23,10 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
rp RP15/RP02 disk pack rp RP15/RP02/RP03 disk pack
15-Mar-16 RMS Added RP03 support
Fixed handling of done flag
07-Mar-16 RMS Revised for dynamically allocated memory 07-Mar-16 RMS Revised for dynamically allocated memory
13-Sep-15 RMS Added APIVEC register 13-Sep-15 RMS Added APIVEC register
14-Jan-04 RMS Revised IO device call interface 14-Jan-04 RMS Revised IO device call interface
@ -46,15 +48,20 @@
#define RP_NUMWD 256 /* words/sector */ #define RP_NUMWD 256 /* words/sector */
#define RP_NUMSC 10 /* sectors/surface */ #define RP_NUMSC 10 /* sectors/surface */
#define RP_NUMSF 20 /* surfaces/cylinder */ #define RP_NUMSF 20 /* surfaces/cylinder */
#define RP_NUMCY 203 /* cylinders/drive */ #define RP02_NUMCY 203 /* cylinders/drive */
#define RP03_NUMCY 406
#define RP_NUMDR 8 /* drives/controller */ #define RP_NUMDR 8 /* drives/controller */
#define RP_SIZE (RP_NUMCY * RP_NUMSF * RP_NUMSC * RP_NUMWD) #define RP02_SIZE (RP02_NUMCY * RP_NUMSF * RP_NUMSC * RP_NUMWD)
/* words/drive */ #define RP03_SIZE (RP03_NUMCY * RP_NUMSF * RP_NUMSC * RP_NUMWD)
#define RP_QCYL(f) (((f) & UNIT_RP03)? RP03_NUMCY: RP02_NUMCY)
#define RP_QSIZE(f) (((f) & UNIT_RP03)? RP03_SIZE: RP02_SIZE)
/* Unit specific flags */ /* Unit specific flags */
#define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */ #define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */
#define UNIT_V_RP03 (UNIT_V_UF + 1) /* RP03 */
#define UNIT_WLK (1u << UNIT_V_WLK) #define UNIT_WLK (1u << UNIT_V_WLK)
#define UNIT_RP03 (1u << UNIT_V_RP03)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
/* Parameters in the unit descriptor */ /* Parameters in the unit descriptor */
@ -120,16 +127,23 @@
#define DA_V_SECT 0 /* sector */ #define DA_V_SECT 0 /* sector */
#define DA_M_SECT 017 #define DA_M_SECT 017
#define DA_V_C256 4
#define DA_C256 (1 << DA_V_C256)
#define DA_V_SURF 5 #define DA_V_SURF 5
#define DA_M_SURF 037 #define DA_M_SURF 037
#define DA_V_CYL 10 /* cylinder */ #define DA_V_CYL 10 /* cylinder */
#define DA_M_CYL 0377 #define DA_M_CYL 0377
#define GET_SECT(x) (((x) >> DA_V_SECT) & DA_M_SECT) #define GET_SECT(x) (((x) >> DA_V_SECT) & DA_M_SECT)
#define GET_SURF(x) (((x) >> DA_V_SURF) & DA_M_SURF) #define GET_SURF(x) (((x) >> DA_V_SURF) & DA_M_SURF)
#define GET_CYL(x) (((x) >> DA_V_CYL) & DA_M_CYL) #define GET_CYL(x) ((((x) >> DA_V_CYL) & DA_M_CYL) + \
(((x) & DA_C256)? 256: 0))
#define GET_DA(x) ((((GET_CYL (x) * RP_NUMSF) + GET_SURF (x)) * \ #define GET_DA(x) ((((GET_CYL (x) * RP_NUMSF) + GET_SURF (x)) * \
RP_NUMSC) + GET_SECT (x)) RP_NUMSC) + GET_SECT (x))
/* Current cylinder */
#define CCYL_RP03 0400000 /* RP03 flag */
#define RP_MIN 2 #define RP_MIN 2
#define MAX(x,y) (((x) > (y))? (x): (y)) #define MAX(x,y) (((x) > (y))? (x): (y))
@ -154,6 +168,7 @@ int32 rp64 (int32 dev, int32 pulse, int32 dat);
int32 rp_iors (void); int32 rp_iors (void);
t_stat rp_svc (UNIT *uptr); t_stat rp_svc (UNIT *uptr);
void rp_updsta (int32 newa, int32 newb); void rp_updsta (int32 newa, int32 newb);
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat rp_reset (DEVICE *dptr); t_stat rp_reset (DEVICE *dptr);
t_stat rp_attach (UNIT *uptr, char *cptr); t_stat rp_attach (UNIT *uptr, char *cptr);
t_stat rp_detach (UNIT *uptr); t_stat rp_detach (UNIT *uptr);
@ -169,14 +184,14 @@ t_stat rp_detach (UNIT *uptr);
DIB rp_dib = { DEV_RP, 2, &rp_iors, { &rp63, &rp64 } }; DIB rp_dib = { DEV_RP, 2, &rp_iors, { &rp63, &rp64 } };
UNIT rp_unit[] = { UNIT rp_unit[] = {
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP02_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP02_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP02_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP02_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP02_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP02_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP02_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) } { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP02_SIZE) }
}; };
REG rp_reg[] = { REG rp_reg[] = {
@ -196,6 +211,8 @@ REG rp_reg[] = {
}; };
MTAB rp_mod[] = { MTAB rp_mod[] = {
{ UNIT_RP03, 0, "RP02", "RP02", &rp_set_size },
{ UNIT_RP03, UNIT_RP03, "RP03", "RP03", &rp_set_size },
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
@ -204,7 +221,7 @@ MTAB rp_mod[] = {
DEVICE rp_dev = { DEVICE rp_dev = {
"RP", rp_unit, rp_reg, rp_mod, "RP", rp_unit, rp_reg, rp_mod,
RP_NUMDR, 8, 24, 1, 8, 18, RP_NUMDR, 8, 26, 1, 8, 18,
NULL, NULL, &rp_reset, NULL, NULL, &rp_reset,
NULL, &rp_attach, &rp_detach, NULL, &rp_attach, &rp_detach,
&rp_dib, DEV_DISABLE &rp_dib, DEV_DISABLE
@ -236,20 +253,21 @@ if (pulse & 02) {
} }
if (pulse & 04) { if (pulse & 04) {
if (rp_busy) { /* busy? */ if (rp_busy) { /* busy? */
rp_updsta (0, STB_PGE); rp_updsta (0, STB_PGE); /* prog error */
return dat; return dat;
} }
else if (sb == 000) { /* DPLA */ else if (sb == 000) { /* DPLA */
int32 u = GET_UNIT (rp_sta);
rp_da = dat & DMASK; rp_da = dat & DMASK;
if (GET_SECT (rp_da) >= RP_NUMSC) if (GET_SECT (rp_da) >= RP_NUMSC)
rp_updsta (STA_NXS, 0); rp_updsta (STA_NXS, 0);
if (GET_SURF (rp_da) >= RP_NUMSF) if (GET_SURF (rp_da) >= RP_NUMSF)
rp_updsta (STA_NXF, 0); rp_updsta (STA_NXF, 0);
if (GET_CYL (rp_da) >= RP_NUMCY) if (GET_CYL (rp_da) >= RP_QCYL (rp_unit[u].flags))
rp_updsta (STA_NXC, 0); rp_updsta (STA_NXC, 0);
} }
else if (sb == 020) { /* DPCS */ else if (sb == 020) { /* DPCS */
rp_sta = rp_sta & ~(STA_HNF | STA_DON); rp_sta = rp_sta & ~(STA_HNF | STA_DON); /* clr err, done */
rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE | rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE |
STB_TME | STB_PGE | STB_EOP); STB_TME | STB_PGE | STB_EOP);
rp_updsta (0, 0); rp_updsta (0, 0);
@ -275,8 +293,11 @@ if (pulse & 01) {
dat = IOT_SKP | dat; dat = IOT_SKP | dat;
} }
if (pulse & 02) { if (pulse & 02) {
if (sb == 000) /* DPOU */ if (sb == 000) { /* DPOU */
dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL; u = GET_UNIT (rp_sta);
uptr = rp_dev.units + u; /* select unit */
dat = dat | uptr->CYL | ((uptr->flags & UNIT_RP03)? CCYL_RP03: 0);
}
else if (sb == 020) /* DPOA */ else if (sb == 020) /* DPOA */
dat = dat | rp_da; dat = dat | rp_da;
else if (sb == 040) /* DPOC */ else if (sb == 040) /* DPOC */
@ -285,25 +306,26 @@ if (pulse & 02) {
dat = dat | rp_wc; dat = dat | rp_wc;
} }
if (pulse & 04) { if (pulse & 04) {
if (rp_busy) { /* busy? */ if (sb == 000) { /* DPCF */
rp_updsta (0, STB_PGE); rp_reset (&rp_dev); /* reset dev */
return dat; return dat;
} }
if (sb == 000) /* DPCF */ if (rp_busy != 0) { /* others: busy? */
rp_sta = rp_sta & ~STA_RW; rp_updsta (0, STB_PGE); /* prog error */
else if (sb == 020) /* DPLZ */ return dat;
}
if (sb == 020) /* DPLZ */
rp_sta = rp_sta & (dat | ~STA_RW); rp_sta = rp_sta & (dat | ~STA_RW);
else if (sb == 040) /* DPLO */ else if (sb == 040) /* DPLO */
rp_sta = rp_sta | (dat & STA_RW); rp_sta = rp_sta | (dat & STA_RW);
else if (sb == 060) /* DPLF */ else if (sb == 060) /* DPLF */
rp_sta = (rp_sta & ~STA_RW) | (dat & STA_RW); rp_sta = (rp_sta & ~STA_RW) | (dat & STA_RW);
rp_sta = rp_sta & ~STA_DON; /* clear done */
u = GET_UNIT (rp_sta); /* get unit num */ u = GET_UNIT (rp_sta); /* get unit num */
uptr = rp_dev.units + u; /* select unit */ uptr = rp_dev.units + u; /* select unit */
if ((rp_sta & STA_GO) && !sim_is_active (uptr)) { if ((rp_sta & STA_GO) && !sim_is_active (uptr)) {
f = uptr->FUNC = GET_FUNC (rp_sta); /* get function */ f = uptr->FUNC = GET_FUNC (rp_sta); /* get function */
rp_busy = 1; /* set ctrl busy */ rp_busy = 1; /* set ctrl busy */
rp_sta = rp_sta & ~(STA_HNF | STA_DON); /* clear flags */ rp_sta = rp_sta & ~STA_HNF; /* clear flag */
rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE | rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE |
STB_TME | STB_PGE | STB_EOP | (1 << (STB_V_ATT0 - u))); STB_TME | STB_PGE | STB_EOP | (1 << (STB_V_ATT0 - u)));
if (((uptr->flags & UNIT_ATT) == 0) || (f == FN_IDLE) || if (((uptr->flags & UNIT_ATT) == 0) || (f == FN_IDLE) ||
@ -313,6 +335,7 @@ if (pulse & 04) {
c = GET_CYL (rp_da); c = GET_CYL (rp_da);
c = abs (c - uptr->CYL) * rp_swait; /* seek time */ c = abs (c - uptr->CYL) * rp_swait; /* seek time */
sim_activate (uptr, MAX (RP_MIN, c + rp_rwait)); sim_activate (uptr, MAX (RP_MIN, c + rp_rwait));
rp_sta = rp_sta & ~STA_DON; /* clear done */
} }
} }
} }
@ -323,7 +346,7 @@ return dat;
/* Unit service /* Unit service
If function = idle, clear busy If function = idle, clear busy
If seek or recal initial state, clear attention line, compute seek time, If seek or recal initial state, clear busy, compute seek time,
put on cylinder, set second state put on cylinder, set second state
If unit not attached, give error If unit not attached, give error
If seek or recal second state, set attention line, compute errors If seek or recal second state, set attention line, compute errors
@ -375,13 +398,14 @@ if (GET_SECT (rp_da) >= RP_NUMSC)
rp_updsta (STA_NXS, 0); rp_updsta (STA_NXS, 0);
if (GET_SURF (rp_da) >= RP_NUMSF) if (GET_SURF (rp_da) >= RP_NUMSF)
rp_updsta (STA_NXF, 0); rp_updsta (STA_NXF, 0);
if (GET_CYL (rp_da) >= RP_NUMCY) if (GET_CYL (rp_da) >= RP_QCYL (uptr->flags))
rp_updsta (STA_NXC, 0); rp_updsta (STA_NXC, 0);
if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) { /* or bad disk addr? */ if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) { /* or bad disk addr? */
rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */ rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */
return SCPE_OK; return SCPE_OK;
} }
uptr->CYL = GET_CYL (rp_da); /* on cylinder */
pa = rp_ma & AMASK; /* get mem addr */ pa = rp_ma & AMASK; /* get mem addr */
da = GET_DA (rp_da) * RP_NUMWD; /* get disk addr */ da = GET_DA (rp_da) * RP_NUMWD; /* get disk addr */
wc = 01000000 - rp_wc; /* get true wc */ wc = 01000000 - rp_wc; /* get true wc */
@ -389,12 +413,12 @@ if (((uint32) (pa + wc)) > MEMSIZE) { /* memory overrun? */
nexm = 1; /* set nexm flag */ nexm = 1; /* set nexm flag */
wc = MEMSIZE - pa; /* limit xfer */ wc = MEMSIZE - pa; /* limit xfer */
} }
if ((da + wc) > RP_SIZE) { /* disk overrun? */ if ((da + wc) > RP_QSIZE (uptr->flags)) { /* disk overrun? */
rp_updsta (0, STB_EOP); /* error */ rp_updsta (0, STB_EOP); /* error */
wc = RP_SIZE - da; /* limit xfer */ wc = RP_QSIZE (uptr->flags) - da; /* limit xfer */
} }
err = fseek (uptr->fileref, da * sizeof (int), SEEK_SET); err = fseek (uptr->fileref, da * sizeof (int32), SEEK_SET);
if ((f == FN_READ) && (err == 0)) { /* read? */ if ((f == FN_READ) && (err == 0)) { /* read? */
awc = fxread (&M[pa], sizeof (int32), wc, uptr->fileref); awc = fxread (&M[pa], sizeof (int32), wc, uptr->fileref);
@ -407,7 +431,7 @@ if ((f == FN_WRITE) && (err == 0)) { /* write? */
fxwrite (&M[pa], sizeof (int32), wc, uptr->fileref); fxwrite (&M[pa], sizeof (int32), wc, uptr->fileref);
err = ferror (uptr->fileref); err = ferror (uptr->fileref);
if ((err == 0) && (i = (wc & (RP_NUMWD - 1)))) { if ((err == 0) && (i = (wc & (RP_NUMWD - 1)))) {
fxwrite (fill, sizeof (int), i, uptr->fileref); fxwrite (fill, sizeof (int32), i, uptr->fileref);
err = ferror (uptr->fileref); err = ferror (uptr->fileref);
} }
} }
@ -427,11 +451,13 @@ rp_wc = (rp_wc + wc) & DMASK; /* final word count */
rp_ma = (rp_ma + wc) & DMASK; /* final mem addr */ rp_ma = (rp_ma + wc) & DMASK; /* final mem addr */
da = (da + wc + (RP_NUMWD - 1)) / RP_NUMWD; /* final sector num */ da = (da + wc + (RP_NUMWD - 1)) / RP_NUMWD; /* final sector num */
cyl = da / (RP_NUMSC * RP_NUMSF); /* get cyl */ cyl = da / (RP_NUMSC * RP_NUMSF); /* get cyl */
if (cyl >= RP_NUMCY) if (cyl >= RP_QCYL (uptr->flags)) /* cyl ovflo wraps */
cyl = RP_NUMCY - 1; cyl = 0;
surf = (da % (RP_NUMSC * RP_NUMSF)) / RP_NUMSC; /* get surface */ surf = (da % (RP_NUMSC * RP_NUMSF)) / RP_NUMSC; /* get surface */
sect = (da % (RP_NUMSC * RP_NUMSF)) % RP_NUMSC; /* get sector */ sect = (da % (RP_NUMSC * RP_NUMSF)) % RP_NUMSC; /* get sector */
rp_da = (cyl << DA_V_CYL) | (surf << DA_V_SURF) | (sect << DA_V_SECT); rp_da = ((cyl & DA_M_CYL) << DA_V_CYL) | (surf << DA_V_SURF) | (sect << DA_V_SECT);
if (cyl >= 256) /* cyl >= 8 bits? */
rp_da = rp_da | DA_C256;
rp_busy = 0; /* clear busy */ rp_busy = 0; /* clear busy */
rp_updsta (STA_DON, 0); /* set done */ rp_updsta (STA_DON, 0); /* set done */
@ -462,7 +488,7 @@ else if (sim_is_active (uptr)) {
if ((f == FN_SEEK) || (f == FN_RECAL)) if ((f == FN_SEEK) || (f == FN_RECAL))
rp_stb = rp_stb | STB_SUSU | STB_SUNR; rp_stb = rp_stb | STB_SUSU | STB_SUNR;
} }
else if (uptr->CYL >= RP_NUMCY) else if (uptr->CYL >= RP_QCYL (uptr->flags))
rp_sta = rp_sta | STA_SUSI; rp_sta = rp_sta | STA_SUSI;
if ((rp_sta & STA_EFLGS) || (rp_stb & STB_EFLGS)) if ((rp_sta & STA_EFLGS) || (rp_stb & STB_EFLGS))
rp_sta = rp_sta | STA_ERR; rp_sta = rp_sta | STA_ERR;
@ -503,6 +529,7 @@ t_stat rp_attach (UNIT *uptr, char *cptr)
{ {
t_stat reason; t_stat reason;
uptr->capac = RP_QSIZE (uptr->flags);
reason = attach_unit (uptr, cptr); reason = attach_unit (uptr, cptr);
rp_updsta (0, 0); rp_updsta (0, 0);
return reason; return reason;
@ -518,3 +545,13 @@ reason = detach_unit (uptr);
rp_updsta (0, 0); rp_updsta (0, 0);
return reason; return reason;
} }
/* Set size routine */
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
if (uptr->flags & UNIT_ATT)
return SCPE_ALATT;
uptr->capac = RP_QSIZE (val);
return SCPE_OK;
}

Binary file not shown.