From 59d0602b0daa5a6625a0c7a27e17f6c6aa448ccb Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 12 Feb 2014 21:08:18 -0800 Subject: [PATCH] PDP8: Add device buffer flush capability and keep track of data written state in the device buffer. Fixes #87 Finishing the last DECtape device which was missed when this functionality was added to pdp11_dt, pdp18b_dt and pdp8_dt in commits: 2934112a7003bd31c135197a01b36d969e9c79ba and c9e8121c16ca7af2b79f45bba4b220e1c95983ba Cleaned up the pdp11, pdp18b and other pdp8 implementations to make backporting cleaner. Made sure that buffer flushing happens correctly when simulation returns to the sim> prompt. --- PDP11/pdp11_tc.c | 33 +++++++++++++++++---------------- PDP18B/pdp18b_dt.c | 33 +++++++++++++++++---------------- PDP8/pdp8_dt.c | 33 +++++++++++++++++---------------- PDP8/pdp8_td.c | 30 ++++++++++++++++++++++-------- scp.c | 19 +++++++++---------- sim_defs.h | 1 - 6 files changed, 82 insertions(+), 67 deletions(-) diff --git a/PDP11/pdp11_tc.c b/PDP11/pdp11_tc.c index 3b819cf2..46d00670 100644 --- a/PDP11/pdp11_tc.c +++ b/PDP11/pdp11_tc.c @@ -328,22 +328,22 @@ DIB dt_dib = { }; UNIT dt_unit[] = { - { 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_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) }, { UDATA (&dt_svcdone, UNIT_DIS, 0) } }; @@ -1249,6 +1249,7 @@ else if (uptr->flags & UNIT_11FMT) printf ("16b format"); else printf ("18b/36b format"); printf (", buffering file in memory\n"); +uptr->io_flush = dt_flush; if (uptr->flags & UNIT_8FMT) { /* 12b? */ for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ k = fxread (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref); diff --git a/PDP18B/pdp18b_dt.c b/PDP18B/pdp18b_dt.c index 20f25994..09d920ba 100644 --- a/PDP18B/pdp18b_dt.c +++ b/PDP18B/pdp18b_dt.c @@ -372,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[] = { - { 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) } + { 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) } }; REG dt_reg[] = { @@ -1443,6 +1443,7 @@ else if (uptr->flags & UNIT_11FMT) printf ("16b format"); else printf ("18b/36b format"); printf (", buffering file in memory\n"); +uptr->io_flush = dt_flush; if (uptr->flags & UNIT_8FMT) { /* 12b? */ for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ k = fxread (pdp8b, sizeof (uint16), D8_NBSIZE, uptr->fileref); diff --git a/PDP8/pdp8_dt.c b/PDP8/pdp8_dt.c index d202cff1..2c846655 100644 --- a/PDP8/pdp8_dt.c +++ b/PDP8/pdp8_dt.c @@ -306,22 +306,22 @@ int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir); DIB dt_dib = { DEV_DTA, 2, { &dt76, &dt77 } }; UNIT dt_unit[] = { - { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) }, - { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) }, - { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) }, - { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) }, - { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) }, - { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) }, - { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) }, - { UDATAFLUSH (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC, &dt_flush) } + { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, + { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, + { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, + { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, + { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, + { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, + { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, + { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) } }; REG dt_reg[] = { @@ -1241,6 +1241,7 @@ else if (uptr->flags & UNIT_11FMT) printf ("16b format"); else printf ("18b/36b format"); printf (", buffering file in memory\n"); +uptr->io_flush = dt_flush; if (uptr->flags & UNIT_8FMT) /* 12b? */ uptr->hwmark = fxread (uptr->filebuf, sizeof (uint16), uptr->capac, uptr->fileref); diff --git a/PDP8/pdp8_td.c b/PDP8/pdp8_td.c index d4540a42..f85c404f 100644 --- a/PDP8/pdp8_td.c +++ b/PDP8/pdp8_td.c @@ -90,6 +90,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 */ @@ -197,6 +198,7 @@ int32 td77 (int32 IR, int32 AC); t_stat td_svc (UNIT *uptr); t_stat td_reset (DEVICE *dptr); t_stat td_attach (UNIT *uptr, char *cptr); +void td_flush (UNIT *uptr); t_stat td_detach (UNIT *uptr); t_stat td_boot (int32 unitno, DEVICE *dptr); t_bool td_newsa (int32 newf); @@ -659,6 +661,7 @@ int32 nibp = 3 * (DT_WSIZE - 1 - (line % DT_WSIZE)); /* nibble pos */ ba = ba + (line / DT_WSIZE); /* block addr */ fbuf[ba] = (fbuf[ba] & ~(07 << nibp)) | (dat << nibp); /* upd data nibble */ +uptr->WRITTEN = TRUE; if (ba >= uptr->hwmark) /* upd length */ uptr->hwmark = ba + 1; return; @@ -803,6 +806,7 @@ else if (uptr->flags & UNIT_11FMT) printf ("16b format"); else printf ("18b/36b format"); printf (", buffering file in memory\n"); +uptr->io_flush = td_flush; if (uptr->flags & UNIT_8FMT) /* 12b? */ uptr->hwmark = fxread (uptr->filebuf, sizeof (uint16), uptr->capac, uptr->fileref); @@ -856,20 +860,16 @@ return SCPE_OK; Deallocate buffer */ -t_stat td_detach (UNIT* uptr) +void td_flush (UNIT* uptr) { uint32 pdp18b[D18_NBSIZE]; uint16 pdp11b[D18_NBSIZE], *fbuf; int32 i, k; -int32 u = uptr - td_dev.units; uint32 ba; -if (!(uptr->flags & UNIT_ATT)) - return SCPE_OK; -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 (&td_dev), u); +if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ rewind (uptr->fileref); /* start of file */ + fbuf = (uint16 *) uptr->filebuf; /* file buffer */ if (uptr->flags & UNIT_8FMT) /* PDP8? */ fxwrite (uptr->filebuf, sizeof (uint16), /* write file */ uptr->hwmark, uptr->fileref); @@ -892,7 +892,21 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ D18_NBSIZE, uptr->fileref); } /* end loop buf */ } /* end else */ - if (ferror (uptr->fileref)) perror ("I/O error"); + if (ferror (uptr->fileref)) + perror ("I/O error"); + } +uptr->WRITTEN = FALSE; /* no longer dirty */ +} + +t_stat td_detach (UNIT* uptr) +{ +int u = (int)(uptr - td_dev.units); + +if (!(uptr->flags & UNIT_ATT)) + return SCPE_OK; +if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ + printf ("%s%d: writing buffer to file\n", sim_dname (&td_dev), u); + td_flush (uptr); } /* end if hwmark */ free (uptr->filebuf); /* release buf */ uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ diff --git a/scp.c b/scp.c index 45eb6726..a3becdab 100644 --- a/scp.c +++ b/scp.c @@ -3103,10 +3103,8 @@ if (1) { for (j = 0; j < dptr->numunits; j++) { /* if not buffered in mem */ uptr = dptr->units + j; if ((uptr->flags & UNIT_ATT) && /* attached, */ - !(uptr->flags & UNIT_BUF) && /* not buffered, */ - (uptr->fileref)) /* real file, */ - if (uptr->io_flush) /* unit specific flush routine */ - uptr->io_flush (uptr); + (uptr->io_flush)) /* unit specific flush routine */ + uptr->io_flush (uptr); } } } @@ -5429,15 +5427,16 @@ if (sim_deb) /* flush debug log */ for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* flush attached files */ for (j = 0; j < dptr->numunits; j++) { /* if not buffered in mem */ uptr = dptr->units + j; - if ((uptr->flags & UNIT_ATT) && /* attached, */ - !(uptr->flags & UNIT_BUF) && /* not buffered, */ - (uptr->fileref)) { /* real file, */ + if (uptr->flags & UNIT_ATT) { /* attached, */ if (uptr->io_flush) /* unit specific flush routine */ - uptr->io_flush (uptr); - else - if (!(uptr->dynflags & UNIT_NO_FIO) && /* is FILE *, */ + uptr->io_flush (uptr); /* call it */ + else { + if (!(uptr->flags & UNIT_BUF) && /* not buffered, */ + (uptr->fileref) && /* real file, */ + !(uptr->dynflags & UNIT_NO_FIO) && /* is FILE *, */ !(uptr->flags & UNIT_RO)) /* not read only? */ fflush (uptr->fileref); + } } } } diff --git a/sim_defs.h b/sim_defs.h index 76d42a4f..7b0f28e8 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -646,7 +646,6 @@ struct sim_fileref { /* 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 UDATAFLUSH(act,fl,cap,flush) NULL,act,NULL,NULL,NULL,0,0,(fl),0,(cap),0,flush,0,0 #if defined (__STDC__) || defined (_WIN32) /* Right Justified Octal Register Data */