PDP11,PDP18B: Add device buffer flush capability and keep track of data written state in the device buffer. These are cousin bugs described in issue #87
This commit is contained in:
parent
b2133aede8
commit
2934112a70
2 changed files with 120 additions and 89 deletions
|
@ -117,6 +117,7 @@
|
|||
#define UNIT_11FMT (1 << UNIT_V_11FMT)
|
||||
#define STATE u3 /* unit state */
|
||||
#define LASTT u4 /* last time update */
|
||||
#define WRITTEN u5 /* device buffer is dirty and needs flushing */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* System independent DECtape constants */
|
||||
|
@ -295,6 +296,7 @@ t_stat dt_svc (UNIT *uptr);
|
|||
t_stat dt_svcdone (UNIT *uptr);
|
||||
t_stat dt_reset (DEVICE *dptr);
|
||||
t_stat dt_attach (UNIT *uptr, char *cptr);
|
||||
void dt_flush (UNIT *uptr);
|
||||
t_stat dt_detach (UNIT *uptr);
|
||||
t_stat dt_boot (int32 unitno, DEVICE *dptr);
|
||||
void dt_deselect (int32 oldf);
|
||||
|
@ -326,22 +328,22 @@ DIB dt_dib = {
|
|||
};
|
||||
|
||||
UNIT dt_unit[] = {
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_11FMT, DT_CAPAC, &dt_flush) },
|
||||
{ UDATA (&dt_svcdone, UNIT_DIS, 0) }
|
||||
};
|
||||
|
||||
|
@ -942,6 +944,7 @@ switch (fnc) { /* at speed, check fnc *
|
|||
}
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
fbuf[ba] = tcdt; /* write word */
|
||||
uptr->WRITTEN = TRUE;
|
||||
if (ba >= uptr->hwmark)
|
||||
uptr->hwmark = ba + 1;
|
||||
if (tcwc == 0)
|
||||
|
@ -1292,29 +1295,16 @@ return SCPE_OK;
|
|||
Deallocate buffer
|
||||
*/
|
||||
|
||||
t_stat dt_detach (UNIT* uptr)
|
||||
void dt_flush (UNIT* uptr)
|
||||
{
|
||||
uint16 pdp8b[D8_NBSIZE];
|
||||
uint16 pdp11b[D18_BSIZE];
|
||||
uint32 ba, k, *fbuf;
|
||||
int32 u = uptr - dt_dev.units;
|
||||
int32 k;
|
||||
uint32 ba, *fbuf;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT))
|
||||
return SCPE_OK;
|
||||
if (sim_is_active (uptr)) { /* active? cancel op */
|
||||
sim_cancel (uptr);
|
||||
if ((u == CSR_GETUNIT (tccm)) && ((tccm & CSR_DONE) == 0)) {
|
||||
tcst = tcst | STA_SEL;
|
||||
tccm = tccm | CSR_ERR | CSR_DONE;
|
||||
if (tccm & CSR_IE)
|
||||
SET_INT (DTA);
|
||||
}
|
||||
uptr->STATE = uptr->pos = 0;
|
||||
}
|
||||
fbuf = (uint32 *) uptr->filebuf; /* file buffer */
|
||||
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
||||
if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */
|
||||
rewind (uptr->fileref); /* start of file */
|
||||
fbuf = (uint32 *) uptr->filebuf; /* file buffer */
|
||||
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
|
||||
|
@ -1329,7 +1319,8 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
|||
break;
|
||||
} /* end loop file */
|
||||
} /* end if 12b */
|
||||
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||
else
|
||||
if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D18_BSIZE; k++) /* loop blk */
|
||||
pdp11b[k] = fbuf[ba++] & DMASK;
|
||||
|
@ -1338,9 +1329,34 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
|||
break;
|
||||
} /* end loop file */
|
||||
} /* end if 16b */
|
||||
else fxwrite (uptr->filebuf, sizeof (uint32), /* write file */
|
||||
else
|
||||
fxwrite (uptr->filebuf, sizeof (uint32), /* write file */
|
||||
uptr->hwmark, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) perror ("I/O error");
|
||||
if (ferror (uptr->fileref))
|
||||
perror ("I/O error");
|
||||
}
|
||||
uptr->WRITTEN = FALSE; /* no longer dirty */
|
||||
}
|
||||
|
||||
t_stat dt_detach (UNIT* uptr)
|
||||
{
|
||||
int32 u = uptr - dt_dev.units;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT))
|
||||
return SCPE_OK;
|
||||
if (sim_is_active (uptr)) { /* active? cancel op */
|
||||
sim_cancel (uptr);
|
||||
if ((u == CSR_GETUNIT (tccm)) && ((tccm & CSR_DONE) == 0)) {
|
||||
tcst = tcst | STA_SEL;
|
||||
tccm = tccm | CSR_ERR | CSR_DONE;
|
||||
if (tccm & CSR_IE)
|
||||
SET_INT (DTA);
|
||||
}
|
||||
uptr->STATE = uptr->pos = 0;
|
||||
}
|
||||
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
||||
dt_flush (uptr);
|
||||
} /* end if hwmark */
|
||||
free (uptr->filebuf); /* release buf */
|
||||
uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */
|
||||
|
|
|
@ -121,6 +121,7 @@
|
|||
#define UNIT_11FMT (1 << UNIT_V_11FMT)
|
||||
#define STATE u3 /* unit state */
|
||||
#define LASTT u4 /* last time update */
|
||||
#define WRITTEN u5 /* device buffer is dirty and needs flushing */
|
||||
#define DT_WC 030 /* word count */
|
||||
#define DT_CA 031 /* current addr */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
@ -348,6 +349,7 @@ int32 dt_iors (void);
|
|||
t_stat dt_svc (UNIT *uptr);
|
||||
t_stat dt_reset (DEVICE *dptr);
|
||||
t_stat dt_attach (UNIT *uptr, char *cptr);
|
||||
void dt_flush (UNIT *uptr);
|
||||
t_stat dt_detach (UNIT *uptr);
|
||||
void dt_deselect (int32 oldf);
|
||||
void dt_newsa (int32 newf);
|
||||
|
@ -370,22 +372,22 @@ int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos);
|
|||
DIB dt_dib = { DEV_DTA, 2, &dt_iors, { &dt75, &dt76 } };
|
||||
|
||||
UNIT dt_unit[] = {
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) }
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC, &dt_flush) },
|
||||
{ UDATAFLUSH (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC, &dt_flush) }
|
||||
};
|
||||
|
||||
REG dt_reg[] = {
|
||||
|
@ -1053,6 +1055,7 @@ switch (fnc) { /* at speed, check fnc *
|
|||
if (dir) /* rev? comp obv */
|
||||
dtdb = dt_comobv (dtdb);
|
||||
fbuf[ba] = dtdb; /* write word */
|
||||
uptr->WRITTEN = TRUE;
|
||||
if (ba >= uptr->hwmark)
|
||||
uptr->hwmark = ba + 1;
|
||||
if (M[DT_WC] == 0)
|
||||
|
@ -1486,27 +1489,16 @@ return SCPE_OK;
|
|||
Deallocate buffer
|
||||
*/
|
||||
|
||||
t_stat dt_detach (UNIT* uptr)
|
||||
void dt_flush (UNIT* uptr)
|
||||
{
|
||||
uint16 pdp8b[D8_NBSIZE];
|
||||
uint16 pdp11b[D18_BSIZE];
|
||||
uint32 ba, k, *fbuf;
|
||||
int32 u = uptr - dt_dev.units;
|
||||
int32 k;
|
||||
uint32 ba, *fbuf;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT))
|
||||
return SCPE_OK;
|
||||
if (sim_is_active (uptr)) {
|
||||
sim_cancel (uptr);
|
||||
if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) {
|
||||
dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF;
|
||||
DT_UPDINT;
|
||||
}
|
||||
uptr->STATE = uptr->pos = 0;
|
||||
}
|
||||
fbuf = (uint32 *) uptr->filebuf; /* file buffer */
|
||||
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
||||
if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */
|
||||
rewind (uptr->fileref); /* start of file */
|
||||
fbuf = (uint32 *) uptr->filebuf; /* file buffer */
|
||||
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
|
||||
|
@ -1521,7 +1513,8 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
|||
break;
|
||||
} /* end loop file */
|
||||
} /* end if 12b */
|
||||
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||
else
|
||||
if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D18_BSIZE; k++) /* loop blk */
|
||||
pdp11b[k] = fbuf[ba++] & 0177777;
|
||||
|
@ -1530,10 +1523,32 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
|||
break;
|
||||
} /* end loop file */
|
||||
} /* end if 16b */
|
||||
else fxwrite (uptr->filebuf, sizeof (uint32), /* write file */
|
||||
else
|
||||
fxwrite (uptr->filebuf, sizeof (uint32), /* write file */
|
||||
uptr->hwmark, uptr->fileref);
|
||||
if (ferror (uptr->fileref))
|
||||
perror ("I/O error");
|
||||
}
|
||||
uptr->WRITTEN = FALSE; /* no longer dirty */
|
||||
}
|
||||
|
||||
t_stat dt_detach (UNIT* uptr)
|
||||
{
|
||||
int32 u = uptr - dt_dev.units;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT))
|
||||
return SCPE_OK;
|
||||
if (sim_is_active (uptr)) {
|
||||
sim_cancel (uptr);
|
||||
if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) {
|
||||
dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF;
|
||||
DT_UPDINT;
|
||||
}
|
||||
uptr->STATE = uptr->pos = 0;
|
||||
}
|
||||
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
||||
dt_flush (uptr);
|
||||
} /* end if hwmark */
|
||||
free (uptr->filebuf); /* release buf */
|
||||
uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */
|
||||
|
|
Loading…
Add table
Reference in a new issue