PDP8: Add device buffer flush capability and keep track of data written state in the device buffer. Fixes #87

This commit is contained in:
Mark Pizzolato 2014-02-05 10:30:22 -08:00
parent ffda4c1c41
commit c9e8121c16
2 changed files with 45 additions and 32 deletions

View file

@ -105,6 +105,7 @@
#define UNIT_11FMT (1 << UNIT_V_11FMT) #define UNIT_11FMT (1 << UNIT_V_11FMT)
#define STATE u3 /* unit state */ #define STATE u3 /* unit state */
#define LASTT u4 /* last time update */ #define LASTT u4 /* last time update */
#define WRITTEN u5 /* device buffer is dirty and needs flushing */
#define DT_WC 07754 /* word count */ #define DT_WC 07754 /* word count */
#define DT_CA 07755 /* current addr */ #define DT_CA 07755 /* current addr */
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
@ -281,6 +282,7 @@ int32 dt77 (int32 IR, int32 AC);
t_stat dt_svc (UNIT *uptr); t_stat dt_svc (UNIT *uptr);
t_stat dt_reset (DEVICE *dptr); t_stat dt_reset (DEVICE *dptr);
t_stat dt_attach (UNIT *uptr, char *cptr); t_stat dt_attach (UNIT *uptr, char *cptr);
t_stat dt_flush (UNIT *uptr);
t_stat dt_detach (UNIT *uptr); t_stat dt_detach (UNIT *uptr);
t_stat dt_boot (int32 unitno, DEVICE *dptr); t_stat dt_boot (int32 unitno, DEVICE *dptr);
void dt_deselect (int32 oldf); void dt_deselect (int32 oldf);
@ -304,22 +306,22 @@ int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir);
DIB dt_dib = { DEV_DTA, 2, { &dt76, &dt77 } }; DIB dt_dib = { DEV_DTA, 2, { &dt76, &dt77 } };
UNIT dt_unit[] = { UNIT dt_unit[] = {
{ UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+
UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) },
{ UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+
UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) },
{ UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+
UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) },
{ UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+
UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) },
{ UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+
UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) },
{ UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+
UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) },
{ UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+
UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) },
{ UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+
UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) } UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) }
}; };
REG dt_reg[] = { REG dt_reg[] = {
@ -870,6 +872,7 @@ switch (fnc) { /* at speed, check fnc *
if (dir) /* rev? comp obv */ if (dir) /* rev? comp obv */
dat = dt_comobv (dat); dat = dt_comobv (dat);
fbuf[ba] = dat; /* write word */ fbuf[ba] = dat; /* write word */
uptr->WRITTEN = TRUE;
if (ba >= uptr->hwmark) if (ba >= uptr->hwmark)
uptr->hwmark = ba + 1; uptr->hwmark = ba + 1;
if (M[DT_WC] == 0) if (M[DT_WC] == 0)
@ -1275,29 +1278,16 @@ return SCPE_OK;
If 16b or 18b, convert 12b buffer to 16b or 18b and write to file If 16b or 18b, convert 12b buffer to 16b or 18b and write to file
Deallocate buffer Deallocate buffer
*/ */
t_stat dt_flush (UNIT* uptr)
t_stat dt_detach (UNIT* uptr)
{ {
uint32 pdp18b[D18_NBSIZE]; uint32 pdp18b[D18_NBSIZE];
uint16 pdp11b[D18_NBSIZE], *fbuf; uint16 pdp11b[D18_NBSIZE], *fbuf;
int32 i, k; int32 i, k;
int32 u = uptr - dt_dev.units;
uint32 ba; uint32 ba;
if (!(uptr->flags & UNIT_ATT)) /* attached? */ if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */
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 = (uint16 *) 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);
rewind (uptr->fileref); /* start of file */ rewind (uptr->fileref); /* start of file */
fbuf = (uint16 *) uptr->filebuf; /* file buffer */
if (uptr->flags & UNIT_8FMT) /* PDP8? */ if (uptr->flags & UNIT_8FMT) /* PDP8? */
fxwrite (uptr->filebuf, sizeof (uint16), /* write file */ fxwrite (uptr->filebuf, sizeof (uint16), /* write file */
uptr->hwmark, uptr->fileref); uptr->hwmark, uptr->fileref);
@ -1322,6 +1312,28 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */
} /* end else */ } /* end else */
if (ferror (uptr->fileref)) if (ferror (uptr->fileref))
perror ("I/O error"); perror ("I/O error");
}
uptr->WRITTEN = FALSE; /* no longer dirty */
return SCPE_OK;
}
t_stat dt_detach (UNIT* uptr)
{
int u = (int)(uptr - dt_dev.units);
if (!(uptr->flags & UNIT_ATT)) /* attached? */
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 */ } /* end if hwmark */
free (uptr->filebuf); /* release buf */ free (uptr->filebuf); /* release buf */
uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */

View file

@ -646,6 +646,7 @@ struct sim_fileref {
/* The following macros define structure contents */ /* The following macros define structure contents */
#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),0,(cap),0,NULL,0,0 #define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),0,(cap),0,NULL,0,0
#define UDATAFLUSH(act,fl,cap,flush) NULL,act,NULL,NULL,NULL,0,0,(fl),0,(cap),0,flush,0,0
#if defined (__STDC__) || defined (_WIN32) #if defined (__STDC__) || defined (_WIN32)
/* Right Justified Octal Register Data */ /* Right Justified Octal Register Data */