From c9031657a5b615d737662ac3bb778e9f6f7892cc Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sat, 8 Sep 2018 23:58:44 -0400 Subject: [PATCH] ICL1900: Added CR, CP and EDS8 disk controller. Misc cleanup --- ICL1900/Makefile | 3 +- ICL1900/icl1900_cp.c | 300 +++++++++++++++++++ ICL1900/icl1900_cpu.c | 9 +- ICL1900/icl1900_cr.c | 339 +++++++++++++++++++++ ICL1900/icl1900_cty.c | 36 +-- ICL1900/icl1900_defs.h | 16 +- ICL1900/icl1900_eds8.c | 639 ++++++++++++++++++++++++++++++++++++++++ ICL1900/icl1900_lp.c | 3 +- ICL1900/icl1900_mt.c | 165 ++++++----- ICL1900/icl1900_mta.c | 4 +- ICL1900/icl1900_stdio.c | 8 +- ICL1900/icl1900_sys.c | 8 +- ICL1900/icl1900_tp.c | 52 ++-- ICL1900/icl1900_tr.c | 71 ++--- 14 files changed, 1491 insertions(+), 162 deletions(-) create mode 100644 ICL1900/icl1900_cp.c create mode 100644 ICL1900/icl1900_cr.c create mode 100644 ICL1900/icl1900_eds8.c diff --git a/ICL1900/Makefile b/ICL1900/Makefile index 25243cd..a43e0e3 100755 --- a/ICL1900/Makefile +++ b/ICL1900/Makefile @@ -1089,7 +1089,8 @@ DISPLAYD = display ICL1900D = . ICL1900 = ${ICL1900D}/icl1900_cpu.c ${ICL1900D}/icl1900_sys.c ${ICL1900D}/icl1900_stdio.c \ ${ICL1900D}/icl1900_cty.c ${ICL1900D}/icl1900_tr.c ${ICL1900D}/icl1900_tp.c \ - ${ICL1900D}/icl1900_mta.c ${ICL1900D}/icl1900_lp.c ${ICL1900D}/icl1900_mt.c + ${ICL1900D}/icl1900_cr.c ${ICL1900D}/icl1900_cp.c ${ICL1900D}/icl1900_lp.c \ + ${ICL1900D}/icl1900_mta.c ${ICL1900D}/icl1900_mt.c ${ICL1900D}/icl1900_eds8.c ICL1900_OPT = -I.. -DUSE_SIM_CARD diff --git a/ICL1900/icl1900_cp.c b/ICL1900/icl1900_cp.c new file mode 100644 index 0000000..eead953 --- /dev/null +++ b/ICL1900/icl1900_cp.c @@ -0,0 +1,300 @@ +/* icl1900_cr.c: ICL1900 Punch Card Reader simulator + + Copyright (c) 2018, Richard Cornwell + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Richard Cornwell shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Richard Cornwell + +*/ + +#include "icl1900_defs.h" +#include "sim_card.h" + +#ifndef NUM_DEVS_CDP +#define NUM_DEVS_CDP 0 +#endif + +#define UNIT_V_TYPE (UNIT_V_UF + 0) +#define UNIT_TYPE (0xf << UNIT_V_TYPE) +#define GET_TYPE(x) ((UNIT_TYPE & (x)) >> UNIT_V_TYPE) +#define SET_TYPE(x) (UNIT_TYPE & ((x) << UNIT_V_TYPE)) + +#define NSI_TYPE(x) ((GET_TYPE(x) & 1) == 0) +#define SI_TYPE(x) ((GET_TYPE(x) & 1) != 0) + + +#define STATUS u3 + +#define TERMINATE 000001 +#define OPAT 000002 +#define STOPPED 000030 +#define ERROR 000004 +#define DISC 010000 +#define BUSY 020000 + + +#if (NUM_DEVS_CDP > 0) + +#define T1920_1 0 +#define T1920_2 1 + +#define UNIT_CDP(x) UNIT_ADDR(x)|SET_TYPE(T1920_2)|UNIT_ATTABLE|UNIT_DISABLE + + +void cdp_cmd (int dev, uint32 cmd, uint32 *resp); +void cdp_nsi_cmd (int dev, uint32 cmd); +void cdp_nsi_status (int dev, uint32 *resp); +t_stat cdp_svc (UNIT *uptr); +t_stat cdp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +CONST char *cdp_description (DEVICE *dptr); + +DIB cdp_dib = { CHAR_DEV, &cdp_cmd, &cdp_nsi_cmd, &cdp_nsi_status }; + +UNIT cdp_unit[] = { + { UDATA (&cdp_svc, UNIT_CDP(10), 0), 10000 }, + { UDATA (&cdp_svc, UNIT_CDP(12), 0), 10000 }, + }; + + +MTAB cdp_mod[] = { + { UNIT_TYPE, SET_TYPE(T1920_1), "1920/1", "1920/1", NULL, NULL, "ICL 1920/1 NSI card punch."}, + { UNIT_TYPE, SET_TYPE(T1920_2), "1920/2", "1920/2", NULL, NULL, "ICL 1920/2 SI card punch."}, + {MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT", + &sim_card_set_fmt, &sim_card_show_fmt, NULL}, + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_chan, &get_chan, NULL, "Device Number"}, + { 0 } + }; + +DEVICE cdp_dev = { + "CP", cdp_unit, NULL, cdp_mod, + NUM_DEVS_CDP, 8, 22, 1, 8, 22, + NULL, NULL, NULL, NULL, &sim_card_attach, &sim_card_detach, + &cdp_dib, DEV_DISABLE | DEV_CARD | DEV_DEBUG, 0, dev_debug, + NULL, NULL, &cdp_help, NULL, NULL, &cdp_description + }; + +/* + * Command codes + * + * 011010 Punch + * 010000 Send Q. + * 010100 Send P. + * 011110 Disconnect. + */ + + +void cdp_cmd(int dev, uint32 cmd, uint32 *resp) { + int i; + UNIT *uptr = NULL; + + *resp = 0; + /* Find the unit from dev */ + for (i = 0; i < cdp_dev.numunits; i++) { + if (GET_UADDR(cdp_unit[i].flags) == dev) { + uptr = &cdp_unit[i]; + break; + } + } + + /* Should not happen, but just in case */ + if (uptr == NULL) + return; + + /* Ignore this command if not a SI device */ + if (NSI_TYPE(uptr->flags)) + return; + + if ((uptr->flags & UNIT_ATT) == 0) + return; + if (cmd == 020) { /* Send Q */ + *resp = uptr->STATUS & 001; /* TERMINATE */ + if ((uptr->flags & UNIT_ATT) != 0 || uptr->STATUS & 07700) + *resp |= 040; + if ((uptr->flags & BUSY) == 0) + *resp |= STOPPED; + } else if (cmd == 024) { /* Send P */ + *resp = uptr->STATUS & 016; /* IMAGE, ERROR, OPAT */ + if ((uptr->flags & UNIT_ATT) != 0) + *resp |= 1; + uptr->STATUS &= (BUSY|DISC); + chan_clr_done(dev); + } else if (cmd == 032) { + if ((uptr->flags & UNIT_ATT) == 0) + return; + if (uptr->STATUS & BUSY) { + *resp = 3; + return; + } + sim_debug(DEBUG_CMD, &cdp_dev, "CMD: %02o %08o\n", cmd, uptr->STATUS); + uptr->STATUS = BUSY; + sim_activate(uptr, uptr->wait); + chan_clr_done(dev); + *resp = 5; + } else if (cmd == 036) { /* Disconnect */ + uptr->STATUS |= DISC; + *resp = 5; + } +} + +/* + * Command codes + * + * xxxx01 Start punch. + * xxxx10 Stop punch. + */ +void cdp_nsi_cmd(int dev, uint32 cmd) { + int i; + UNIT *uptr = NULL; + + /* Find the unit from dev */ + for (i = 0; i < cdp_dev.numunits; i++) { + if (GET_UADDR(cdp_unit[i].flags) == dev) { + uptr = &cdp_unit[i]; + break; + } + } + + /* Should not happen, but just in case */ + if (uptr == NULL) + return; + + /* Ignore this command if not a SI device */ + if (SI_TYPE(uptr->flags)) + return; + + + if (cmd & 02) { + if (uptr->STATUS & BUSY) + uptr->STATUS |= DISC; + return; + } + + if (cmd & 01) { + if (uptr->STATUS & BUSY || (uptr->flags & UNIT_ATT) == 0) { + uptr->STATUS |= OPAT; + chan_set_done(dev); + return; + } + uptr->STATUS = BUSY; + chan_clr_done(dev); + sim_activate(uptr, uptr->wait); + } +} + +/* + * NSI Status bits. + * + * 001 End. + * 002 Opat. + * 004 ERROR + * 020 ACCEPT + * 040 BUSY + */ +void cdp_nsi_status(int dev, uint32 *resp) { + int i; + UNIT *uptr = NULL; + + *resp = 0; + /* Find the unit from dev */ + for (i = 0; i < cdp_dev.numunits; i++) { + if (GET_UADDR(cdp_unit[i].flags) == dev) { + uptr = &cdp_unit[i]; + break; + } + } + + /* Should not happen, but just in case */ + if (uptr == NULL) + return; + + /* Ignore this command if not a SI device */ + if (SI_TYPE(uptr->flags)) + return; + + *resp = uptr->STATUS & 3; + if (uptr->STATUS & BUSY) + *resp |= 040; + if ((uptr->flags & UNIT_ATT) == 0) + *resp |= 2; + uptr->STATUS &= BUSY|DISC; + chan_clr_done(dev); +} + +t_stat cdp_svc (UNIT *uptr) +{ + int dev = GET_UADDR(uptr->flags); + uint16 image[80]; + uint8 ch; + int eor; + int i; + + /* Handle a disconnect request */ + if (uptr->STATUS & DISC) { + uptr->STATUS |= TERMINATE; + uptr->STATUS &= ~(BUSY|DISC); + chan_set_done(dev); + return SCPE_OK; + } + /* If not busy, false schedule, just exit */ + if ((uptr->STATUS & BUSY) == 0) + return SCPE_OK; + + + memset(&image, 80, sizeof(uint16)); + for (i = 0; i < 80; i++) { + eor = chan_output_char(dev, &ch, 0); + if (eor) { + break; + } + image[i] = sim_bcd_to_hol(ch); + } + switch(sim_punch_card(uptr, image)) { + case CDSE_EMPTY: + case CDSE_EOF: + case CDSE_ERROR: + uptr->STATUS |= OPAT; + break; + case CDSE_OK: + break; + } + uptr->STATUS |= TERMINATE; + uptr->STATUS &= ~(BUSY|DISC); + chan_set_done(dev); + return SCPE_OK; +} + + +t_stat cdp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ + fprintf (st, "The Card Punch can be set to one of several types.\n\n"); + sim_card_attach_help(st, dptr, uptr, flag, cptr); + fprintf (st, "The device number can be set with DEV=# command.\n"); + fprint_set_help(st, dptr); + fprint_show_help(st, dptr); + + return SCPE_OK; +} + +CONST char *cdp_description (DEVICE *dptr) +{ + return "CP"; +} +#endif diff --git a/ICL1900/icl1900_cpu.c b/ICL1900/icl1900_cpu.c index e42008d..4cf9cb4 100644 --- a/ICL1900/icl1900_cpu.c +++ b/ICL1900/icl1900_cpu.c @@ -2231,8 +2231,8 @@ fexp: /* Fall through */ case 0174: /* Send control character to peripheral */ if (exe_mode) { - chan_send_cmd(RB, RA & 077, &RT); -//fprintf(stderr, "CMD %04o %04o %08o\n\r", RT, RB, RA); + chan_send_cmd(RB, RA & 07777, &RT); +//fprintf(stderr, "CMD C=%08o %04o %04o %08o\n\r", RC, RT, RB, RA); m = (m == 0) ? 3 : (XR[m] >> 22) & 3; m = 6 * (3 - m); RT = (RT & 077) << m; @@ -2243,8 +2243,13 @@ fexp: } /* Fall through */ case 0175: /* Null operation in Executive mode */ + if (exe_mode) { +fprintf(stderr, "CMD 175 C=%08o %04o %08o\n\r", RC, RB, RA); + break; + } case 0176: if (exe_mode) { +fprintf(stderr, "CMD 176 C=%08o %04o %08o\n\r", RC, RB, RA); break; } /* Fall through */ diff --git a/ICL1900/icl1900_cr.c b/ICL1900/icl1900_cr.c new file mode 100644 index 0000000..d768842 --- /dev/null +++ b/ICL1900/icl1900_cr.c @@ -0,0 +1,339 @@ +/* icl1900_cr.c: ICL1900 Punch Card Reader simulator + + Copyright (c) 2018, Richard Cornwell + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Richard Cornwell shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Richard Cornwell + +*/ + +#include "icl1900_defs.h" +#include "sim_card.h" + +#ifndef NUM_DEVS_CDR +#define NUM_DEVS_CDR 0 +#endif + +#define UNIT_V_TYPE (UNIT_V_UF + 0) +#define UNIT_TYPE (0xf << UNIT_V_TYPE) +#define GET_TYPE(x) ((UNIT_TYPE & (x)) >> UNIT_V_TYPE) +#define SET_TYPE(x) (UNIT_TYPE & ((x) << UNIT_V_TYPE)) + +#define NSI_TYPE(x) ((GET_TYPE(x) & 1) == 0) +#define SI_TYPE(x) ((GET_TYPE(x) & 1) != 0) + + +#define STATUS u4 + + +#define TERMINATE 0000001 +#define STOPPED 0000060 +#define OPAT 0000002 +#define ERROR 0000004 +#define IMAGE 0000010 +#define DISC 0010 +#define BUSY 0020 + + +#if (NUM_DEVS_CDR > 0) + +#define T1911_1 0 +#define T1911_2 1 +#define T1912_1 2 +#define T1912_2 3 + +#define UNIT_CDR(x) UNIT_ADDR(x)|SET_TYPE(T1912_2)|UNIT_ATTABLE|\ + UNIT_DISABLE|UNIT_RO + + +void cdr_cmd (int dev, uint32 cmd, uint32 *resp); +void cdr_nsi_cmd (int dev, uint32 cmd); +void cdr_nsi_status (int dev, uint32 *resp); +t_stat cdr_svc (UNIT *uptr); +t_stat cdr_boot (int32 unit_num, DEVICE * dptr); +t_stat cdr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +CONST char *cdr_description (DEVICE *dptr); + +DIB cdr_dib = { CHAR_DEV, &cdr_cmd, &cdr_nsi_cmd, &cdr_nsi_status }; + +UNIT cdr_unit[] = { + { UDATA (&cdr_svc, UNIT_CDR(8), 0), 10000 }, + { UDATA (&cdr_svc, UNIT_CDR(9), 0), 10000 }, + }; + + +MTAB cdr_mod[] = { + { UNIT_TYPE, SET_TYPE(T1911_1), "1911/1", "1911/1", NULL, NULL, "ICL 1911/1 NSI 900CPM reader."}, + { UNIT_TYPE, SET_TYPE(T1911_2), "1911/2", "1911/2", NULL, NULL, "ICL 1911/2 SI 900CPM reader."}, + { UNIT_TYPE, SET_TYPE(T1912_1), "1912/1", "1912/1", NULL, NULL, "ICL 1912/1 NSI 300CPM reader."}, + { UNIT_TYPE, SET_TYPE(T1912_2), "1912/2", "1912/2", NULL, NULL, "ICL 1912/2 SI 900CPM reader."}, + {MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT", + &sim_card_set_fmt, &sim_card_show_fmt, NULL}, + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_chan, &get_chan, NULL, "Device Number"}, + { 0 } + }; + +DEVICE cdr_dev = { + "CR", cdr_unit, NULL, cdr_mod, + NUM_DEVS_CDR, 8, 22, 1, 8, 22, + NULL, NULL, NULL, &cdr_boot, &sim_card_attach, &sim_card_detach, + &cdr_dib, DEV_DISABLE | DEV_CARD | DEV_DEBUG, 0, dev_debug, + NULL, NULL, &cdr_help, NULL, NULL, &cdr_description + }; + +/* + * Command codes + * + * 011001 Read + * 011011 Read in image mode. + * 010000 Send Q. + * 010100 Send P. + * 011110 Disconnect. + */ + + +void cdr_cmd(int dev, uint32 cmd, uint32 *resp) { + int i; + UNIT *uptr = NULL; + + *resp = 0; + /* Find the unit from dev */ + for (i = 0; i < cdr_dev.numunits; i++) { + if (GET_UADDR(cdr_unit[i].flags) == dev) { + uptr = &cdr_unit[i]; + break; + } + } + + /* Should not happen, but just in case */ + if (uptr == NULL) + return; + + /* Ignore this command if not a SI device */ + if (NSI_TYPE(uptr->flags)) + return; + + if ((uptr->flags & UNIT_ATT) == 0) + return; + if (cmd == 020) { /* Send Q */ + *resp = uptr->STATUS & 01; /* Terminate */ + if ((uptr->flags & UNIT_ATT) != 0 || uptr->STATUS & 07700) + *resp |= 040; + if ((uptr->STATUS & BUSY) == 0) + *resp |= STOPPED; + } else if (cmd == 024) { /* Send P */ + *resp = uptr->STATUS & 016; /* IMAGE, ERROR, OPAT */ + if ((uptr->flags & UNIT_ATT) != 0) + *resp |= 1; + uptr->STATUS &= (IMAGE|BUSY|DISC); + chan_clr_done(dev); + } else if (cmd == 031 || cmd == 033 || cmd == 037 ) { + if ((uptr->flags & UNIT_ATT) == 0) + return; + if (uptr->STATUS & BUSY) { + *resp = 3; + return; + } + sim_debug(DEBUG_CMD, &cdr_dev, "CMD: %02o %08o\n", cmd, uptr->STATUS); + uptr->STATUS = BUSY; + if (cmd & 02) + uptr->STATUS |= IMAGE; + sim_activate(uptr, uptr->wait); + chan_clr_done(dev); + *resp = 5; + } else if (cmd == 036) { /* Disconnect */ + uptr->STATUS |= DISC; + *resp = 5; + } +} + +/* + * Command codes + * + * xxxx01 Start reader. + * xxxx10 Stop reader. + */ +void cdr_nsi_cmd(int dev, uint32 cmd) { + int i; + UNIT *uptr = NULL; + + /* Find the unit from dev */ + for (i = 0; i < cdr_dev.numunits; i++) { + if (GET_UADDR(cdr_unit[i].flags) == dev) { + uptr = &cdr_unit[i]; + break; + } + } + + /* Should not happen, but just in case */ + if (uptr == NULL) + return; + + /* Ignore this command if not a SI device */ + if (SI_TYPE(uptr->flags)) + return; + + + if (cmd & 02) { + if (uptr->STATUS & BUSY) + uptr->STATUS |= DISC; + return; + } + + if (cmd & 01) { + if (uptr->STATUS & BUSY || (uptr->flags & UNIT_ATT) == 0) { + uptr->STATUS |= OPAT; + chan_set_done(dev); + return; + } + uptr->STATUS = BUSY; + sim_activate(uptr, uptr->wait); + chan_clr_done(dev); + } +} + +/* + * NSI Status bits. + * + * 001 End. + * 002 Opat. + * 004 ERROR + * 020 ACCEPT + * 040 BUSY + */ +void cdr_nsi_status(int dev, uint32 *resp) { + int i; + UNIT *uptr = NULL; + + *resp = 0; + /* Find the unit from dev */ + for (i = 0; i < cdr_dev.numunits; i++) { + if (GET_UADDR(cdr_unit[i].flags) == dev) { + uptr = &cdr_unit[i]; + break; + } + } + + /* Should not happen, but just in case */ + if (uptr == NULL) + return; + + /* Ignore this command if not a SI device */ + if (SI_TYPE(uptr->flags)) + return; + + *resp = uptr->STATUS & 7; + if (uptr->STATUS & BUSY) + *resp |= 040; + uptr->STATUS &= BUSY|DISC|IMAGE; + chan_clr_done(dev); +} + +t_stat cdr_svc (UNIT *uptr) +{ + uint16 image[80]; + int dev = GET_UADDR(uptr->flags); + uint8 ch; + int i; + int eor; + + /* Handle a disconnect request */ + if (uptr->STATUS & DISC) { + uptr->STATUS |= TERMINATE; + uptr->STATUS &= ~(BUSY|DISC); + chan_set_done(dev); + return SCPE_OK; + } + /* If not busy, false schedule, just exit */ + if ((uptr->STATUS & BUSY) == 0) + return SCPE_OK; + + switch(sim_read_card(uptr, image)) { + case CDSE_EMPTY: + case CDSE_EOF: + case CDSE_ERROR: + uptr->STATUS |= OPAT; + break; + case CDSE_OK: + for (i = 0; i < 80; i++) { + if (uptr->STATUS & IMAGE) { + ch = (image[i] >> 6) & 077; + eor = chan_input_char(dev, &ch, 0); + if (eor) + break; + ch = image[i] & 077; + } else { + ch = sim_hol_to_bcd(image[i]); + if (ch == 0x7f) { + uptr->STATUS |= ERROR; + break; + } + } + eor = chan_input_char(dev, &ch, 0); + if (eor) + break; + } + break; + } + + uptr->STATUS |= TERMINATE; + uptr->STATUS &= ~(BUSY|DISC); + chan_set_done(dev); + return SCPE_OK; +} + +/* Boot from given device */ +t_stat +cdr_boot(int32 unit_num, DEVICE * dptr) +{ + UNIT *uptr = &dptr->units[unit_num]; + int chan = GET_UADDR(uptr->flags); + + if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_UNATT; /* attached? */ + + M[64 + chan] = 0; + M[256 + 4 * chan] = 0; + M[257 + 4 * chan] = 0; + loading = 1; + uptr->STATUS = BUSY|IMAGE; + sim_activate (uptr, uptr->wait); + return SCPE_OK; +} + + +t_stat cdr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ + fprintf (st, "The card reader can be set to one of several device types\n\n"); + sim_card_attach_help(st, dptr, uptr, flag, cptr); + fprintf (st, "The device number can be set with DEV=# command.\n"); + fprint_set_help(st, dptr); + fprint_show_help(st, dptr); + + return SCPE_OK; +} + +CONST char *cdr_description (DEVICE *dptr) +{ + return "CR"; + +} +#endif diff --git a/ICL1900/icl1900_cty.c b/ICL1900/icl1900_cty.c index b7c08ef..460158a 100644 --- a/ICL1900/icl1900_cty.c +++ b/ICL1900/icl1900_cty.c @@ -109,15 +109,14 @@ void cty_cmd(int dev, uint32 cmd) { if (dev == 2) u++; if (cmd & START) { - cty_unit[u].STATUS &= ~END; - cty_unit[u].STATUS |= BUSY; + cty_unit[u].CMD = 1; + cty_unit[u].STATUS = BUSY; if (!u) sim_activate(&cty_unit[u], cty_unit[u].wait); } - else if (cmd & STOP) { + if (cmd & STOP) { cty_unit[u].STATUS &= ~BUSY; } - cty_unit[u].STATUS &= BUSY; chan_clr_done(GET_UADDR(cty_unit[u].flags)); } @@ -171,6 +170,7 @@ t_stat ctyo_svc (UNIT *uptr) r = SCPE_OK; } if (eor) { + uptr->CMD = 0; uptr->STATUS &= ~BUSY; uptr->STATUS |= END; chan_set_done(GET_UADDR(uptr->flags)); @@ -182,6 +182,7 @@ t_stat ctyo_svc (UNIT *uptr) t_stat ctyi_svc (UNIT *uptr) { + int dev = GET_UADDR(uptr->flags); t_stat r; uint8 ch; int eor; @@ -195,15 +196,16 @@ t_stat ctyi_svc (UNIT *uptr) ch = 0177 & sim_tt_inpcvt(r & 0377, TT_GET_MODE (uptr->flags)); if (uptr->HOLD) { if (ch >= '1' && ch <= '5') { - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); uptr->STATUS |= (F1 << (ch - '1')); + uptr->CMD = 0; } else { sim_putchar('\007'); } uptr->HOLD = 0; return SCPE_OK; } - if ((uptr->STATUS & BUSY) != 0) { + if (uptr->CMD && (uptr->STATUS & BUSY) != 0) { /* Handle end of buffer */ switch (ch) { case '\r': @@ -212,8 +214,8 @@ t_stat ctyi_svc (UNIT *uptr) sim_putchar('\r'); sim_putchar('\n'); uptr->STATUS |= ACCEPT; - uptr->STATUS &= ~BUSY; - chan_set_done(GET_UADDR(uptr->flags)); + uptr->CMD = 0; + chan_set_done(dev); break; case 033: /* function key n key */ @@ -223,17 +225,17 @@ t_stat ctyi_svc (UNIT *uptr) case 030: /* ^X Post input interrupt */ sim_debug(DEBUG_CMD, &cty_dev, ": inp\n"); uptr->STATUS |= INPUT; - uptr->STATUS &= ~BUSY; uptr->HOLD = 0; - chan_set_done(GET_UADDR(uptr->flags)); + uptr->CMD = 0; + chan_set_done(dev); break; case 03: /* ^C */ case 025: /* ^U clear line */ uptr->STATUS |= CANCEL; - uptr->STATUS &= ~BUSY; uptr->HOLD = 0; - chan_set_done(GET_UADDR(uptr->flags)); + uptr->CMD = 0; + chan_set_done(dev); break; default: @@ -250,7 +252,7 @@ t_stat ctyi_svc (UNIT *uptr) sim_putchar('\007'); break; } - eor = chan_input_char(GET_UADDR(uptr->flags), &ch, 0); + eor = chan_input_char(dev, &ch, 0); switch (ch & 060) { case 000: ch = 0060 | (ch & 017); break; case 020: ch = 0040 | (ch & 017); break; @@ -260,9 +262,9 @@ t_stat ctyi_svc (UNIT *uptr) ch = sim_tt_outcvt ( ch, TT_GET_MODE (uptr->flags)) ; sim_putchar (ch); if (eor) { - uptr->STATUS &= ~BUSY; + uptr->CMD = 0; uptr->STATUS |= END; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); } break; } @@ -277,14 +279,14 @@ t_stat ctyi_svc (UNIT *uptr) sim_debug(DEBUG_CMD, &cty_dev, ": inp\n"); uptr->STATUS |= INPUT; uptr->HOLD = 0; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); break; case 03: /* ^C */ case 025: /* ^U clear line */ uptr->STATUS |= CANCEL; uptr->HOLD = 0; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); break; default: diff --git a/ICL1900/icl1900_defs.h b/ICL1900/icl1900_defs.h index f3d7a98..edde197 100755 --- a/ICL1900/icl1900_defs.h +++ b/ICL1900/icl1900_defs.h @@ -30,13 +30,14 @@ #define NUM_DEVS_PTR 2 #define NUM_DEVS_PTP 2 -#define NUM_DEVS_CDR 0 -#define NUM_DEVS_CDP 0 +#define NUM_DEVS_CDR 1 +#define NUM_DEVS_CDP 1 #define NUM_DEVS_LPR 1 #define NUM_DEVS_CON 0 #define NUM_DEVS_MT 4 /* 1971 SI tape drives */ #define NUM_DEVS_MTA 8 /* 1974 NSI tape drives */ -#define NUM_DEVS_DSK 0 +#define NUM_DEVS_EDS8 8 +#define NUM_DEVS_EDS30 0 #define NUM_DEVS_DTC 0 #define MAXMEMSIZE (4096 * 1024) @@ -54,10 +55,8 @@ extern uint32 XR[8]; #define DEBUG_CMD 0x0000004 /* Show device commands */ #define DEBUG_DATA 0x0000008 /* Show data transfers */ #define DEBUG_DETAIL 0x0000010 /* Show details */ -#define DEBUG_EXP 0x0000020 /* Show error conditions */ -#define DEBUG_SNS 0x0000040 /* Shows sense data for 7909 devs */ -#define DEBUG_CTSS 0x0000080 /* Shows CTSS specail instructions */ -#define DEBUG_PROT 0x0000100 /* Protection traps */ +#define DEBUG_EXP 0x0000020 /* Show exeption conditions */ +#define DEBUG_STATUS 0x0000040 /* Show status conditions */ extern DEBTAB dev_debug[]; @@ -304,7 +303,8 @@ extern DEVICE cdr_dev; extern DEVICE cdp_dev; extern DEVICE lpr_dev; extern DEVICE dtc_dev; -extern DEVICE dsk_dev; +extern DEVICE eds8_dev; +extern DEVICE eds30_dev; extern DEVICE mt_dev; extern DEVICE mta_dev; diff --git a/ICL1900/icl1900_eds8.c b/ICL1900/icl1900_eds8.c new file mode 100644 index 0000000..bc74cb1 --- /dev/null +++ b/ICL1900/icl1900_eds8.c @@ -0,0 +1,639 @@ +/* icl1900_eds8.c: ICL1900 EDS8 disk drive simulator. + + Copyright (c) 2018, Richard Cornwell + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Richard Cornwell shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Richard Cornwell + +*/ + +#include "icl1900_defs.h" + +#if (NUM_DEVS_EDS8 > 0) +#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_WLK (1 << UNIT_V_WLK) +#define UNIT_EDS8 UNIT_ATTABLE | UNIT_DISABLE | UNIT_ROABLE + +#define CMD u3 /* Command */ +#define CYL u4 /* Current cylinder. */ +#define HDSEC u5 /* Head and sector to transfer */ +#define POS u6 /* Current position in block */ + +#define SECT_TRK 8 /* Sectors/ track */ +#define HD_CYL 10 /* Heads / cylinder */ +#define CYLS 203 /* Cylinders */ +#define WD_SEC 128 /* Number of words per sector */ + + +/* Command is packed follows: + * + * Low order 5 bits indicate current command. + * Bit 6 indicates command terminated. + * Bit 7 indicates that first qualifier has not been recieved. + * Bit 8 indicates that the second qualifier has not been recieved. + * Bit 9 set when unit is started. + * Bit 10 set when command starts transfering data. + * Bit 11 set during seeking. + * Bit 12 indicates error. + * Bit 13 indicates wrong track. + * Bit 14 indicates long block + * Bit 15 indicates drive IRQ. + * + * Bit 16-24 stores current qualifier. + */ + +#define EDS8_CMD 037 + +#define EDS8_NOP 000 +#define EDS8_WRID 007 /* Write Identifiers Q1=head, Q2=F */ +#define EDS8_ERASE 014 /* Erase Q1=head, Q2=sect */ +#define EDS8_TSTWR 016 /* Test Write Q1=head, Q2=sect */ +#define EDS8_SEEK 030 /* Seek Q1=Th, Q2=Tl */ +#define EDS8_READ 031 /* Read Q1=head, Q2=sect */ +#define EDS8_WRITE 032 /* Write Q1=head, Q2=sect */ +#define EDS8_WRCHK 033 /* Write & Check Q1=head, Q2=sect */ +#define EDS8_SUP_RD 034 /* Suppress read Q1=head, Q2=sect */ +#define EDS8_RD_TRK 035 /* Read Track Q1=head, Q2=ignored */ +#define EDS8_DISC 036 /* Disoconect No Qualifier */ +#define EDS8_BOOT 037 /* Boot No Qualifier */ + +#define EDS8_TERM 000040 /* Command terminated */ +#define EDS8_QUAL1 000100 /* 1st Qualifier expected */ +#define EDS8_QUAL2 000200 /* 2nd Qualifier expected */ +#define EDS8_BUSY 000400 /* Device running command */ +#define EDS8_RUN 001000 /* Command executing. */ +#define EDS8_SK 002000 /* Seeking in progress. */ +#define EDS8_ERR 004000 /* Hard error */ +#define EDS8_PATH 010000 /* Wrong track */ +#define EDS8_LONG 020000 /* Reached end of cylinder during read/write */ +#define EDS8_IRQ 040000 /* Drive changed status */ + +#define ST1_OK 001 /* Unit available */ +#define ST1_ERR 002 /* Hard error */ +#define ST1_PATH 004 /* Wrong track */ +#define ST1_LONG 010 /* Reached end of cylinder during read/write */ +#define ST1_IRQ 020 /* Drive changed status */ + +#define STQ_TERM 001 /* Operation terminated */ +#define STQ_DSK_RDY 004 /* Disk can accept orders */ +#define STQ_CTL_RDY 030 /* Controller ready to accept new order */ +#define STQ_P1 040 /* P1 Status on */ + + +int eds8_busy; /* Indicates that controller is talking to a drive */ +int eds8_drive; /* Indicates last selected drive */ +uint32 eds8_buffer[WD_SEC]; +void eds8_cmd (int dev, uint32 cmd, uint32 *resp); +t_stat eds8_svc (UNIT *uptr); +t_stat eds8_reset (DEVICE *dptr); +t_stat eds8_boot (int32 unit_num, DEVICE * dptr); +t_stat eds8_attach(UNIT *, CONST char *); +t_stat eds8_detach(UNIT *); +t_stat eds8_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +CONST char *eds8_description (DEVICE *dptr); + +DIB eds8_dib = { WORD_DEV|MULT_DEV, &eds8_cmd, NULL, NULL }; + + +MTAB eds8_mod[] = { + {UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL}, + {UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL}, + {MTAB_XTD | MTAB_VDV | MTAB_VALR, 0, "DEV", "DEV", + &set_chan, &get_chan, NULL, "Device Number"}, + {0} +}; + +UNIT eds8_unit[] = { + {UDATA(&eds8_svc, UNIT_EDS8, 0) }, /* 0 */ + {UDATA(&eds8_svc, UNIT_EDS8, 0) }, /* 1 */ + {UDATA(&eds8_svc, UNIT_EDS8, 0) }, /* 2 */ + {UDATA(&eds8_svc, UNIT_EDS8, 0) }, /* 3 */ + {UDATA(&eds8_svc, UNIT_EDS8, 0) }, /* 4 */ + {UDATA(&eds8_svc, UNIT_EDS8, 0) }, /* 5 */ + {UDATA(&eds8_svc, UNIT_EDS8, 0) }, /* 6 */ + {UDATA(&eds8_svc, UNIT_EDS8, 0) }, /* 7 */ +}; + +DEVICE eds8_dev = { + "ED", eds8_unit, NULL, eds8_mod, + NUM_DEVS_EDS8, 8, 22, 1, 8, 22, + NULL, NULL, &eds8_reset, &eds8_boot, &eds8_attach, &detach_unit, + &eds8_dib, DEV_DISABLE | DEV_DEBUG | UNIT_ADDR(27), 0, dev_debug, + NULL, NULL, &eds8_help, NULL, NULL, &eds8_description + }; + +void eds8_cmd(int dev, uint32 cmd, uint32 *resp) { + UNIT *uptr = &eds8_unit[eds8_drive]; + *resp = 0; + if (cmd & 0400) { + sim_debug(DEBUG_CMD, &eds8_dev, "Cmd: set unit=%d %04o\n", eds8_drive, cmd); + eds8_drive = cmd & 07; + uptr = &eds8_unit[eds8_drive]; + if ((uptr->flags & UNIT_ATT) != 0) + *resp = 5; + return; + } + switch(cmd & 070) { + case 000: if (cmd == 7) + cmd |= EDS8_QUAL1|EDS8_QUAL2; + else if (cmd != 0) { + *resp = 3; + return; + } + break; + + case 010: if ((cmd & 05) != 4) { + *resp = 3; + return; + } + cmd |= EDS8_QUAL1|EDS8_QUAL2; + break; + + case 020: if (cmd == SEND_Q) { + if (uptr->CMD & EDS8_TERM) + *resp |= STQ_TERM; + if ((uptr->CMD & (EDS8_BUSY|EDS8_QUAL1|EDS8_QUAL2)) == 0) + *resp |= STQ_DSK_RDY; + if (eds8_busy == 0) + *resp |= STQ_CTL_RDY; + if ((uptr->flags & UNIT_ATT) != 0) + *resp |= STQ_P1; + chan_clr_done(dev); + } else if (cmd == SEND_P) { + *resp = (uptr->CMD >> 10) & 036; + if ((uptr->flags & UNIT_ATT) != 0) + *resp |= 1; + } + sim_debug(DEBUG_STATUS, &eds8_dev, "Status: unit:=%d %02o %02o\n", eds8_drive, cmd, *resp); + return; + case 030: if (cmd < 036) + cmd |= EDS8_QUAL1|EDS8_QUAL2; + break; + case 040: + case 050: + if (uptr->CMD & EDS8_QUAL1) { + uptr->CMD |= ((cmd & 017) << 20); + uptr->CMD &= ~EDS8_QUAL1; + } else if (uptr->CMD & EDS8_QUAL2) { + uptr->CMD |= ((cmd & 017) << 16); + uptr->CMD &= ~EDS8_QUAL2; + } + cmd = uptr->CMD; + break; + default: + *resp = 3; + return; + } + sim_debug(DEBUG_CMD, &eds8_dev, "Cmd: unit=%d %02o\n", eds8_drive, cmd); + if ((uptr->flags & UNIT_ATT) == 0) { + *resp = 0; + return; + } + if (eds8_busy || (uptr->CMD & EDS8_BUSY)) { + *resp = 3; + return; + } + if (cmd == 0) { + *resp = 5; + return; + } + uptr->CMD = cmd; + if ((uptr->CMD & (EDS8_QUAL1|EDS8_QUAL2)) == 0) { + sim_debug(DEBUG_CMD, &eds8_dev, "Cmd: unit=%d start %02o\n", eds8_drive, uptr->CMD); + eds8_busy = 1; + uptr->CMD |= EDS8_BUSY; + chan_clr_done(dev); + sim_activate(uptr, 100); + } + *resp = 5; + return; +} + +t_stat eds8_svc (UNIT *uptr) +{ + DEVICE *dptr = &eds8_dev; + int unit = (uptr - dptr->units); + int dev = GET_UADDR(dptr->flags); + t_stat r; + uint32 word; + int i; + int wc; + int eor; + int da; + + /* If not busy, false schedule, just exit */ + if ((uptr->CMD & EDS8_BUSY) == 0) + return SCPE_OK; + + /* If we need to seek, move heads. */ + if (uptr->CMD & EDS8_SK) { + int diff; + diff = uptr->CYL - ((uptr->CMD >> 16) & 0377); + i = 1; + if (diff < 0) { + diff = -diff; + i = -1; + } + if (diff > 80) { + uptr->CYL -= i*20; + sim_activate(uptr, 2000); + return SCPE_OK; + } else if (diff > 50) { + uptr->CYL -= i*10; + sim_activate(uptr, 1000); + return SCPE_OK; + } else if (diff > 10) { + uptr->CYL -= i*10; + sim_activate(uptr, 500); + return SCPE_OK; + } else if (diff > 0) { + uptr->CYL -= i*1; + sim_activate(uptr, 10); + return SCPE_OK; + } else if (diff == 0) { + uptr->CMD &= ~EDS8_SK; + } + } + + switch (uptr->CMD & EDS8_CMD) { + case EDS8_TSTWR: + /* Compare disk control word with generated one */ + break; + + case EDS8_ERASE: + /* Write data directly to disk ignoring headers. */ + /* 146 to 166 words per sector */ + break; + + case EDS8_DISC: + /* Retract heads and offline the drive */ + detach_unit(uptr); + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM; + eds8_busy = 0; + chan_set_done(dev); + break; + + case EDS8_SEEK: + /* Set desired cylinder to value */ + if ((uptr->CMD & EDS8_RUN) == 0) { + int trk = (uptr->CMD >> 16) & 0377; + if (uptr->CYL == trk) { + /* Terminate */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_IRQ; + } else if (trk > CYLS) { + /* Terminate with error */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_PATH; + } else { + uptr->CMD |= EDS8_RUN|EDS8_SK; + } + eds8_busy = 0; + /* trigger controller available */ + chan_set_done(dev); + break; + } + if (uptr->CYL == ((uptr->CMD >> 16) & 0377)) { + /* Terminate */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_IRQ; + chan_set_done(dev); + } + break; + + case EDS8_SUP_RD: + /* Start reading sectors at the requested value. */ + /* Read one sector for each word transfered. */ + if ((uptr->CMD & EDS8_RUN) == 0) { + uptr->CMD |= EDS8_RUN; + uptr->HDSEC = (uptr->CMD >> 16) & 0377; + if (((uptr->HDSEC >> 4) & 017) > HD_CYL || (uptr->HDSEC & 017) > SECT_TRK) { + /* Terminate wrong track */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_PATH; + eds8_busy = 0; + chan_set_done(dev); + break; + } + } + if (eor = chan_output_word(dev, &word, 0)) { + /* Terminate */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM; + eds8_busy = 0; + chan_set_done(dev); + break; + } + + uptr->HDSEC += 9; /* Bump sector number, if more then 8, will bump head */ + uptr->HDSEC &= 0367; + /* If empty buffer, fill */ + if (((uptr->HDSEC >> 4) & 017) > HD_CYL) { + /* Terminate long read */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_LONG; + eds8_busy = 0; + chan_set_done(dev); + break; + } + sim_activate(uptr, 100); + break; + + case EDS8_BOOT: + /* Set cylinder to zero and set sector to zero and start read */ + if ((uptr->CMD & EDS8_RUN) == 0 && uptr->CYL != 0) { + uptr->CMD |= EDS8_SK; /* Restore to cylinder zero */ + sim_activate(uptr, 100); + return SCPE_OK; + } + /* Fall through */ + + + case EDS8_RD_TRK: + /* Read a track into memory */ + /* Format is: Word 0: T4 T5 T6 T7 0 0 + T0 T1 T2 T3 0 0 + H0 H1 H2 H3 0 0 + S0 S1 S2 F 0 0 + Word 1-129: sector data. + Word 130: control word of data block. + */ + + case EDS8_READ: + if ((uptr->CMD & EDS8_RUN) == 0) { + uptr->CMD |= EDS8_RUN; + uptr->HDSEC = (uptr->CMD >> 16) & 0377; + if (((uptr->HDSEC >> 4) & 017) > HD_CYL || (uptr->HDSEC & 017) > SECT_TRK) { + /* Terminate wrong track */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_PATH; + eds8_busy = 0; + chan_set_done(dev); + break; + } + } + da = ((((uptr->CYL * HD_CYL) + ((uptr->HDSEC >> 4) & 017)) * SECT_TRK) + + (uptr->HDSEC & 07)) * WD_SEC; + (void)sim_fseek(uptr->fileref, da * sizeof(uint32), SEEK_SET); + wc = sim_fread(&eds8_buffer[0], sizeof(uint32), WD_SEC, uptr->fileref); + while(wc < WD_SEC) + eds8_buffer[wc++] = 0; + + /* Compute header word */ + if ((uptr->CMD & EDS8_CMD) == EDS8_RD_TRK) { + word = (((uptr->CYL >> 4) & 017) << 18) | + ((uptr->CYL & 017) << 12) | + (((uptr->HDSEC >> 4) & 017) << 6) | + ((uptr->HDSEC << 1) & 016); + if (eor = chan_input_word(dev, &word, 0)) { + /* Terminate */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM; + eds8_busy = 0; + chan_set_done(dev); + break; + } + } + + for (i = 0; i < WD_SEC; i++) { + if (eor = chan_input_word(dev, &eds8_buffer[i], 0)) { + /* Terminate */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM; + eds8_busy = 0; + chan_set_done(dev); + break; + } + } + + /* Compute control word */ + if ((uptr->CMD & EDS8_CMD) == EDS8_RD_TRK) { + uint32 even = 0; + uint32 odd = 0; + + for (i = 0; i > 20) ^ (word >> 16) ^ (word >> 12) ^ + (word >> 8) ^ (word >> 4) ^ word; + odd ^= (word >> 18) ^ (word >> 12) ^ (word >> 6) ^ word; + } + word = ((even & 017) << 12) | (((odd ^ 017) & 017) << 8) | 0100; + if (eor = chan_input_word(dev, &word, 0)) { + /* Terminate */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM; + eds8_busy = 0; + chan_set_done(dev); + break; + } + } + + uptr->HDSEC += 9; /* Bump sector number, if more then 8, will bump head */ + uptr->HDSEC &= 0367; + /* If empty buffer, fill */ + if (((uptr->HDSEC >> 4) & 017) > HD_CYL) { + /* Terminate long read */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_LONG; + eds8_busy = 0; + chan_set_done(dev); + break; + } + sim_activate(uptr, 100); + break; + + case EDS8_WRID: + /* Write track id's set F if set */ + if ((uptr->CMD & EDS8_RUN) == 0) { + /* Write the starting at head/sector, if check, then check + that data can be read back at end of each track */ + /* Check if write protected */ + if ((uptr->flags & (UNIT_RO|UNIT_WLK)) != 0) { + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_ERR; + eds8_busy = 0; + chan_set_done(dev); + break; + } + uptr->CMD |= EDS8_RUN; + uptr->HDSEC = (uptr->CMD >> 16) & 0360; + if (((uptr->HDSEC >> 4) & 017) > HD_CYL) { + /* Terminate wrong track */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_PATH; + eds8_busy = 0; + chan_set_done(dev); + break; + } + } + for (wc = 0; wc < WD_SEC; wc++) + eds8_buffer[wc] = 0; + + da = ((((uptr->CYL * HD_CYL) + ((uptr->HDSEC >> 4) & 017)) * SECT_TRK) + + (uptr->HDSEC & 07)) * WD_SEC; + (void)sim_fseek(uptr->fileref, da * sizeof(uint32), SEEK_SET); + wc = sim_fwrite(&eds8_buffer[0], sizeof(uint32), WD_SEC, uptr->fileref); + + uptr->HDSEC += 9; /* Bump sector number, if more then 8, will bump head */ + /* If empty buffer, fill */ + if ((uptr->HDSEC & 010) != 0) { + /* Terminate */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM; + eds8_busy = 0; + chan_set_done(dev); + break; + } + sim_activate(uptr, 100); + break; + + case EDS8_WRCHK: + case EDS8_WRITE: + /* Write the starting at head/sector, if check, then check + that data can be read back at end of each track */ + if ((uptr->CMD & EDS8_RUN) == 0) { + /* Check if write protected */ + if ((uptr->flags & (UNIT_RO|UNIT_WLK)) != 0) { + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_ERR; + eds8_busy = 0; + chan_set_done(dev); + break; + } + uptr->CMD |= EDS8_RUN; + uptr->HDSEC = (uptr->CMD >> 16) & 0377; + if (((uptr->HDSEC >> 4) & 017) > HD_CYL || (uptr->HDSEC & 017) > SECT_TRK) { + /* Terminate wrong track */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_PATH; + eds8_busy = 0; + chan_set_done(dev); + break; + } + } + for (wc = 0; wc < WD_SEC; wc++) + eds8_buffer[wc] = 0; + + for (i = 0; i < WD_SEC; i++) { + if (eor = chan_output_word(dev, &eds8_buffer[i], 0)) + break; + } + + da = ((((uptr->CYL * HD_CYL) + ((uptr->HDSEC >> 4) & 017)) * SECT_TRK) + + (uptr->HDSEC & 07)) * WD_SEC; + (void)sim_fseek(uptr->fileref, da * sizeof(uint32), SEEK_SET); + wc = sim_fwrite(&eds8_buffer[0], sizeof(uint32), WD_SEC, uptr->fileref); + + if (eor) { + /* Terminate */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM; + eds8_busy = 0; + chan_set_done(dev); + break; + } + + + uptr->HDSEC += 9; /* Bump sector number, if more then 8, will bump head */ + uptr->HDSEC &= 0367; + /* If empty buffer, fill */ + if (((uptr->HDSEC >> 4) & 017) > HD_CYL) { + /* Terminate long read */ + uptr->CMD &= EDS8_RUN|EDS8_SK|EDS8_BUSY; + uptr->CMD |= EDS8_TERM|EDS8_LONG; + eds8_busy = 0; + chan_set_done(dev); + break; + } + sim_activate(uptr, 100); + break; + } + return SCPE_OK; +} + + +/* Reset */ + +t_stat eds8_reset (DEVICE *dptr) +{ + UNIT *uptr = dptr->units; + int unit; + + for (unit = 0; unit < dptr->numunits; unit++, uptr++) { + uptr->CMD = 0; + uptr->CYL = 0; + eds8_busy = 0; + } + chan_clr_done(GET_UADDR(dptr->flags)); + return SCPE_OK; +} + +/* Boot from given device */ +t_stat +eds8_boot(int32 unit_num, DEVICE * dptr) +{ + UNIT *uptr = &dptr->units[unit_num]; + int chan = GET_UADDR(dptr->flags); + + if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_UNATT; /* attached? */ + + M[64 + chan] = 0; + M[256 + 4 * chan] = B2; + M[257 + 4 * chan] = 020; + loading = 1; + eds8_busy = 1; + uptr->CMD = EDS8_BUSY|EDS8_BOOT; + sim_activate (uptr, 100); + return SCPE_OK; +} + +t_stat +eds8_attach(UNIT * uptr, CONST char *file) +{ + t_stat r; + + if ((r = attach_unit(uptr, file)) != SCPE_OK) + return r; + uptr->CYL = 0; + uptr->CMD = EDS8_TERM|EDS8_IRQ; + chan_set_done(GET_UADDR(eds8_dev.flags)); +} + + + +t_stat eds8_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cmt) +{ +fprintf (st, "The Paper Tape Reader can be set to one of twp modes: 7P, or 7B.\n\n"); +fprintf (st, " mode \n"); +fprintf (st, " 7P Process even parity input tapes. \n"); +fprintf (st, " 7B Ignore parity of input data.\n"); +fprintf (st, "The default mode is 7B.\n"); +return SCPE_OK; +} + +CONST char *eds8_description (DEVICE *dptr) +{ + return "ED"; + +} +#endif diff --git a/ICL1900/icl1900_lp.c b/ICL1900/icl1900_lp.c index dae8708..e429147 100644 --- a/ICL1900/icl1900_lp.c +++ b/ICL1900/icl1900_lp.c @@ -69,8 +69,7 @@ #define T1933_2 3+12 #define T1933_3 5+12 -#define UNIT_LPR(x) UNIT_ADDR(x)|SET_TYPE(T1931_2)|UNIT_ATTABLE|\ - UNIT_DISABLE|UNIT_TEXT +#define UNIT_LPR(x) UNIT_ADDR(x)|SET_TYPE(T1931_2)|UNIT_ATTABLE|UNIT_DISABLE void lpr_cmd (int dev, uint32 cmd, uint32 *resp); diff --git a/ICL1900/icl1900_mt.c b/ICL1900/icl1900_mt.c index 9079966..d1e6d87 100644 --- a/ICL1900/icl1900_mt.c +++ b/ICL1900/icl1900_mt.c @@ -81,21 +81,20 @@ #define MT_QUAL 0100 /* Qualifier expected */ #define MT_BUSY 0200 /* Device running command */ -#define ST1_OK 00100 /* Unit OK */ -#define ST1_WARN 00200 /* Warning, EOT, BOT, TM */ -#define ST1_ERR 00400 /* Parity error, blank, no unit */ -#define ST1_CORERR 01000 /* Corrected error */ -#define ST1_LONG 02000 /* Long Block */ +#define ST1_OK 001 /* Unit available */ +#define ST1_WARN 002 /* Warning, EOT, BOT, TM */ +#define ST1_ERR 004 /* Parity error, blank, no unit */ +#define ST1_CORERR 010 /* Corrected error */ +#define ST1_LONG 020 /* Long Block */ #define ST1_P2 040 /* P2 Status */ -#define ST2_ROWS 0030000 /* Number of rows read */ -#define ST2_BLNK 0040000 /* Blank Tape */ +#define ST2_ROWS 00300 /* Number of rows read */ +#define ST2_BLNK 00400 /* Blank Tape */ #define STQ_TERM 001 /* Operation terminated */ #define STQ_WRP 002 /* Write ring present */ -#define STQ_ACCP 004 /* Handler accepted order */ -#define STQ_S1 010 /* Controller ready to accept */ -#define STQ_S2 020 /* Controller ready to accept */ +#define STQ_TPT_RDY 004 /* Tape can accept orders */ +#define STQ_CTL_RDY 030 /* Controller ready to accept new order */ #define STQ_P1 040 /* P1 Status on */ @@ -139,75 +138,92 @@ DEVICE mt_dev = { "MT", mt_unit, NULL, mt_mod, NUM_DEVS_MT, 8, 22, 1, 8, 22, NULL, NULL, &mt_reset, &mt_boot, &mt_attach, &mt_detach, - &mt_dib, DEV_DISABLE | DEV_DEBUG | UNIT_ADDR(20), 0, dev_debug, + &mt_dib, DEV_DISABLE | DEV_DEBUG | UNIT_ADDR(24), 0, dev_debug, NULL, NULL, &mt_help, NULL, NULL, &mt_description }; void mt_cmd(int dev, uint32 cmd, uint32 *resp) { UNIT *uptr = &mt_unit[mt_drive]; *resp = 0; - if (dev & 0400) { + if (cmd & 0400) { + sim_debug(DEBUG_CMD, &mt_dev, "Cmd: set unit=%d %04o\n", mt_drive, cmd); mt_drive = cmd & 07; - return; - } - if ((uptr->flags & UNIT_ATT) == 0) { - uptr->CMD = 0; + *resp = 5; return; } if (uptr->CMD & MT_QUAL) { - *resp = 5; - uptr->CMD &= ~MT_QUAL; + sim_debug(DEBUG_CMD, &mt_dev, "Cmd: qual unit=%d %04o\n", mt_drive, cmd); + cmd = uptr->CMD & ~MT_QUAL; } else { switch(cmd & 070) { - case 000: if (cmd == 0) { - *resp = 5; - return; - } - uptr->CMD = cmd; - if (cmd != 1) - uptr->CMD |= MT_QUAL; + case 000: if (cmd > 1) + cmd |= MT_QUAL; break; - case 010: uptr->CMD = cmd; - if (cmd < 016) - uptr->CMD |= MT_QUAL; + case 010: if (cmd < 016) + cmd |= MT_QUAL; break; case 020: if (cmd == SEND_Q) { - if (!sim_tape_wrp(uptr)) - uptr->STATUS |= STQ_WRP; - *resp = uptr->STATUS & 037; - if (uptr->STATUS & 0777700) - *resp |= STQ_P1; + *resp = uptr->STATUS & 01; + if (mt_busy == 0) + *resp |= STQ_CTL_RDY; + if ((uptr->flags & UNIT_ATT) != 0) { + *resp |= STQ_TPT_RDY; + if (!sim_tape_wrp(uptr)) + *resp |= STQ_WRP; +// if ((uptr->CMD & MT_BUSY) == 0) + if (uptr->STATUS & 07776 || (uptr->CMD & MT_BUSY) == 0) + *resp |= STQ_P1; + } + uptr->STATUS &= ~1; + chan_clr_done(dev); } else if (cmd == SEND_P) { - *resp = (uptr->STATUS >> 6) & 037; - if (uptr->STATUS & 0770000) - *resp |= ST1_P2; + if ((uptr->flags & UNIT_ATT) != 0) { + *resp = uptr->STATUS & 036; + if ((uptr->CMD & MT_BUSY) == 0) + *resp |= ST1_OK; + if (uptr->STATUS & 07700) + *resp |= ST1_P2; + } } else if (cmd == SEND_P2) { - *resp = (uptr->STATUS >> 12) & 037; + if ((uptr->flags & UNIT_ATT) != 0) + *resp = (uptr->STATUS >> 6) & 037; } + sim_debug(DEBUG_STATUS, &mt_dev, "Status: unit:=%d %02o %02o\n", mt_drive, cmd, *resp); return; - case 030: uptr->CMD = cmd; - if (cmd < 036) - uptr->CMD |= MT_QUAL; + case 030: if (cmd < 036) + cmd |= MT_QUAL; break; default: + sim_debug(DEBUG_DETAIL, &mt_dev, "extra: unit:=%d %02o %02o\n", mt_drive, cmd, *resp); return; } } - sim_debug(DEBUG_CMD, &mt_dev, "Cmd: unit=%d %02o\n", mt_drive, uptr->CMD); - if (uptr->flags & MT_BUSY) { - *resp = 3; - return; + sim_debug(DEBUG_CMD, &mt_dev, "Cmd: unit=%d %02o\n", mt_drive, cmd); + if ((uptr->flags & UNIT_ATT) == 0) { + *resp = 3; + return; } + if (mt_busy || (uptr->CMD & MT_BUSY)) { + *resp = 3; + return; + } + if (cmd == 0) { + *resp = 5; + return; + } + uptr->CMD = cmd; if ((uptr->CMD & MT_QUAL) == 0) { sim_debug(DEBUG_CMD, &mt_dev, "Cmd: unit=%d start %02o\n", mt_drive, uptr->CMD); mt_busy = 1; CLR_BUF(uptr); uptr->POS = 0; uptr->CMD |= MT_BUSY; - uptr->STATUS = ST1_OK|STQ_ACCP; + uptr->STATUS = 0; + chan_clr_done(dev); sim_activate(uptr, 100); } *resp = 5; + return; } t_stat mt_svc (UNIT *uptr) @@ -235,7 +251,7 @@ t_stat mt_svc (UNIT *uptr) if ((r = sim_tape_rdrecf(uptr, &mt_buffer[0], &reclen, BUFFSIZE)) != MTSE_OK) { sim_debug(DEBUG_DETAIL, dptr, " error %d\n", r); - uptr->STATUS = ST1_OK|STQ_TERM; + uptr->STATUS = STQ_TERM; if (r == MTSE_TMK) uptr->STATUS |= ST1_WARN; else if (r == MTSE_WRP) @@ -270,9 +286,10 @@ t_stat mt_svc (UNIT *uptr) sim_debug(DEBUG_DATA, dptr, "unit=%d read %08o\n", unit, word); eor = chan_input_word(dev, &word, 0); if (eor || uptr->POS >= uptr->hwmark) { - uptr->STATUS = (stop << 12) | ST1_OK|STQ_TERM; + uptr->STATUS = (stop << 12) | STQ_TERM; if (uptr->POS < uptr->hwmark) uptr->STATUS |= ST1_LONG; + sim_debug(DEBUG_DATA, dptr, "unit=%d read done %08o\n", unit, uptr->STATUS); uptr->CMD = 0; mt_busy = 0; chan_set_done(dev); @@ -285,7 +302,7 @@ t_stat mt_svc (UNIT *uptr) case MT_WRITE: /* Check if write protected */ if (sim_tape_wrp(uptr)) { - uptr->STATUS = ST1_OK|STQ_TERM|ST1_ERR; + uptr->STATUS = STQ_TERM|ST1_ERR; uptr->CMD &= ~MT_BUSY; mt_busy = 0; chan_set_done(dev); @@ -307,7 +324,7 @@ t_stat mt_svc (UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "Write unit=%d Block %d chars\n", unit, reclen); r = sim_tape_wrrecf(uptr, &mt_buffer[0], reclen); - uptr->STATUS = ST1_OK|STQ_TERM; + uptr->STATUS = STQ_TERM; if (r != MTSE_OK) uptr->STATUS |= ST1_ERR; uptr->CMD = 0; @@ -322,7 +339,7 @@ t_stat mt_svc (UNIT *uptr) /* If empty buffer, fill */ if (BUF_EMPTY(uptr)) { if (sim_tape_bot(uptr)) { - uptr->STATUS = ST1_OK|ST1_WARN|STQ_TERM; + uptr->STATUS = ST1_WARN|STQ_TERM; uptr->CMD = 0; mt_busy = 0; chan_set_done(dev); @@ -332,7 +349,7 @@ t_stat mt_svc (UNIT *uptr) if ((r = sim_tape_rdrecr(uptr, &mt_buffer[0], &reclen, BUFFSIZE)) != MTSE_OK) { sim_debug(DEBUG_DETAIL, dptr, " error %d\n", r); - uptr->STATUS = ST1_OK|STQ_TERM; + uptr->STATUS = STQ_TERM; if (r == MTSE_TMK) uptr->STATUS |= ST1_WARN; else if (r == MTSE_WRP) @@ -362,7 +379,7 @@ t_stat mt_svc (UNIT *uptr) sim_debug(DEBUG_DATA, dptr, "unit=%d read %08o\n", unit, word); eor = chan_input_word(dev, &word, 0); if (eor || uptr->POS == 0) { - uptr->STATUS = (stop << 12) | ST1_OK|STQ_TERM; + uptr->STATUS = (stop << 12) |STQ_TERM; if (uptr->POS != 0) uptr->STATUS |= ST1_LONG; uptr->CMD = 0; @@ -376,6 +393,7 @@ t_stat mt_svc (UNIT *uptr) case MT_FSF: switch(uptr->POS) { case 0: + sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d\n", unit); uptr->POS ++; sim_activate(uptr, 500); break; @@ -396,7 +414,8 @@ t_stat mt_svc (UNIT *uptr) } break; case 2: - uptr->STATUS = ST1_OK|(ST1_WARN & uptr->STATUS) | STQ_TERM; + sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d done\n", unit); + uptr->STATUS = (ST1_WARN & uptr->STATUS) | STQ_TERM; uptr->CMD = 0; mt_busy = 0; chan_set_done(dev); @@ -406,7 +425,7 @@ t_stat mt_svc (UNIT *uptr) case MT_WTM: if (uptr->POS == 0) { if (sim_tape_wrp(uptr)) { - uptr->STATUS = ST1_OK|ST1_ERR|STQ_TERM; + uptr->STATUS = ST1_ERR|STQ_TERM; uptr->CMD = 0; mt_busy = 0; chan_set_done(dev); @@ -417,7 +436,7 @@ t_stat mt_svc (UNIT *uptr) } else { sim_debug(DEBUG_DETAIL, dptr, "Write Mark unit=%d\n", unit); r = sim_tape_wrtmk(uptr); - uptr->STATUS = ST1_OK|STQ_TERM; + uptr->STATUS = STQ_TERM; if (r != MTSE_OK) uptr->STATUS |= ST1_ERR; uptr->CMD = 0; @@ -430,7 +449,7 @@ t_stat mt_svc (UNIT *uptr) switch (uptr->POS ) { case 0: if (sim_tape_bot(uptr)) { - uptr->STATUS = ST1_OK|ST1_WARN|STQ_TERM; + uptr->STATUS = ST1_WARN|STQ_TERM; uptr->CMD = 0; mt_busy = 0; chan_set_done(dev); @@ -443,7 +462,7 @@ t_stat mt_svc (UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "Backspace rec unit=%d ", unit); r = sim_tape_sprecr(uptr, &reclen); /* We don't set EOF on BSR */ - uptr->STATUS = ST1_OK|STQ_TERM; + uptr->STATUS = STQ_TERM; if (r == MTSE_TMK || r == MTSE_BOT) { uptr->STATUS |= ST1_WARN; } @@ -457,7 +476,7 @@ t_stat mt_svc (UNIT *uptr) switch (uptr->POS ) { case 0: if (sim_tape_bot(uptr)) { - uptr->STATUS = ST1_OK|ST1_WARN|STQ_TERM; + uptr->STATUS = ST1_WARN|STQ_TERM; uptr->CMD = 0; mt_busy = 0; chan_set_done(dev); @@ -479,7 +498,7 @@ t_stat mt_svc (UNIT *uptr) } break; case 2: - uptr->STATUS = ST1_OK|STQ_TERM; + uptr->STATUS = STQ_TERM; uptr->CMD = 0; mt_busy = 0; chan_set_done(dev); @@ -495,11 +514,23 @@ t_stat mt_svc (UNIT *uptr) sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d\n", unit); r = sim_tape_rewind(uptr); uptr->CMD = 0; - uptr->STATUS = ST1_OK|STQ_TERM; + uptr->STATUS = STQ_TERM; chan_set_done(dev); } break; + case MT_RUN: + if (uptr->POS == 0) { + uptr->POS ++; + sim_activate(uptr, 30000); + mt_busy = 0; + } else { + sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit); + r = sim_tape_detach(uptr); + uptr->CMD = 0; + uptr->STATUS = 0; + } + break; } return SCPE_OK; } @@ -516,7 +547,7 @@ t_stat mt_reset (DEVICE *dptr) uptr->CMD = 0; uptr->STATUS = 0; if ((uptr->flags & UNIT_ATT) != 0) - uptr->STATUS = ST1_OK; + uptr->STATUS = 0; mt_busy = 0; } chan_clr_done(GET_UADDR(dptr->flags)); @@ -540,7 +571,7 @@ mt_boot(int32 unit_num, DEVICE * dptr) mt_busy = 1; CLR_BUF(uptr); uptr->CMD = MT_BUSY|MT_BOOT; - uptr->STATUS = ST1_OK|STQ_ACCP; + uptr->STATUS = 0; sim_activate (uptr, 100); return SCPE_OK; } @@ -548,14 +579,8 @@ mt_boot(int32 unit_num, DEVICE * dptr) t_stat mt_attach(UNIT * uptr, CONST char *file) { - t_stat r; - DEVICE *dptr = &mt_dev; - int unit = (uptr - dptr->units); - - if ((r = sim_tape_attach_ex(uptr, file, 0, 0)) != SCPE_OK) - return r; - uptr->STATUS = ST1_OK; - return SCPE_OK; + uptr->STATUS = 0; + return sim_tape_attach_ex(uptr, file, 0, 0); } t_stat diff --git a/ICL1900/icl1900_mta.c b/ICL1900/icl1900_mta.c index 341df23..4d03301 100644 --- a/ICL1900/icl1900_mta.c +++ b/ICL1900/icl1900_mta.c @@ -144,7 +144,7 @@ DEVICE mta_dev = { "MTA", mta_unit, NULL, mta_mod, NUM_DEVS_MTA, 8, 22, 1, 8, 22, NULL, NULL, &mta_reset, &mta_boot, &mta_attach, &mta_detach, - &mta_dib, DEV_DISABLE | DEV_DEBUG | UNIT_ADDR(030), 0, dev_debug, + &mta_dib, DEV_DIS | DEV_DISABLE | DEV_DEBUG | UNIT_ADDR(24), 0, dev_debug, NULL, NULL, &mta_help, NULL, NULL, &mta_description }; @@ -606,7 +606,7 @@ t_stat mta_svc (UNIT *uptr) sim_activate(uptr, 30000); mta_busy = 0; } else { - sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d\n", unit); + sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d dev=%d\n", unit, dev); r = sim_tape_rewind(uptr); uptr->STATUS &= ~BUSY; uptr->STATUS |= TERMINATE; diff --git a/ICL1900/icl1900_stdio.c b/ICL1900/icl1900_stdio.c index 345c5b2..e868d47 100644 --- a/ICL1900/icl1900_stdio.c +++ b/ICL1900/icl1900_stdio.c @@ -247,6 +247,8 @@ get_ccw(int dev, uint32 *addr, uint8 type) { cw0 = M[cw_addr]; cw1 = M[cw_addr+1]; *addr = cw1; + if (type & WORD_DEV) + cw0 |= WORDCCW; if (cw0 & WORDCCW) { if (cw0 & BACKWARD) cw1 = ((cw1 + M22) & M22) | (cw1 & CMASK); @@ -340,6 +342,8 @@ chan_nsi_status(int dev, uint32 *resp) { if (dibp != NULL && dibp->nsi_cmd != NULL) { (dibp->nsi_status)(dev, resp); } +if (dev > 10) +fprintf(stderr, "Status %d %08o\n\r", dev, *resp); } @@ -469,7 +473,7 @@ chan_set_done(int dev) { if (dev < 22) SR64 |= B2 >> dev; else - SR65 |= B1 >> (dev - 23); + SR65 |= ((io_flags & EXT_IO) ? B1 : B2) >> (dev - 24); } void @@ -477,7 +481,7 @@ chan_clr_done(int dev) { if (dev < 22) SR64 &= ~(B2 >> dev); else - SR65 &= ~(B1 >> (dev - 23)); + SR65 &= ~(((io_flags & EXT_IO) ? B1 : B2) >> (dev - 24)); } diff --git a/ICL1900/icl1900_sys.c b/ICL1900/icl1900_sys.c index fb44615..0df1a2f 100755 --- a/ICL1900/icl1900_sys.c +++ b/ICL1900/icl1900_sys.c @@ -68,8 +68,11 @@ DEVICE *sim_devices[] = { #if NUM_DEVS_MTA > 0 &mta_dev, #endif -#if NUM_DEVS_DSK > 0 - &dsk_dev, +#if NUM_DEVS_EDS8 > 0 + &eds8_dev, +#endif +#if NUM_DEVS_EDS30 > 0 + &eds30_dev, #endif #if NUM_DEVS_DTC > 0 &dtc_dev, @@ -88,6 +91,7 @@ DEBTAB dev_debug[] = { {"DATA", DEBUG_DATA, "Show data transfers"}, {"DETAIL", DEBUG_DETAIL, "Show details about device"}, {"EXP", DEBUG_EXP, "Show exception information"}, + {"STATUS", DEBUG_STATUS, "Show status conditions"}, {0, 0} }; diff --git a/ICL1900/icl1900_tp.c b/ICL1900/icl1900_tp.c index 3dce5c8..85eb3e3 100644 --- a/ICL1900/icl1900_tp.c +++ b/ICL1900/icl1900_tp.c @@ -72,7 +72,7 @@ #define T1926_2 3 #define UNIT_PTP(x) UNIT_ADDR(x)|SET_TYPE(T1925_2)|UNIT_ATTABLE|\ - UNIT_DISABLE|UNIT_TEXT|TT_MODE_7B + UNIT_DISABLE|TT_MODE_7B /* * Character translation. @@ -195,21 +195,26 @@ void ptp_cmd(int dev, uint32 cmd, uint32 *resp) { uptr->CMD |= BUSY | (cmd & 07); uptr->STATUS = 0; sim_activate(uptr, uptr->wait); - chan_clr_done(GET_UADDR(uptr->flags)); + chan_clr_done(dev); *resp = 5; break; case 020: if (cmd == 020) { /* Send Q */ - if ((uptr->flags & UNIT_ATT) == 0) + *resp = uptr->STATUS & TERMINATE; + if ((uptr->flags & UNIT_ATT) == 0) { *resp = 040; - if (uptr->STATUS & 06) - *resp = 040; - *resp |= uptr->STATUS & TERMINATE; + if ((uptr->CMD & BUSY) != 0) + *resp |= 030; + } + if ((uptr->STATUS & ERROR) != 0) + *resp |= 040; } else if (cmd == 024) { /* Send P */ if ((uptr->flags & UNIT_ATT) != 0) - *resp = (uptr->STATUS & ERROR) | 1; + *resp = 1; + if ((uptr->STATUS & ERROR) != 0) + *resp |= 2; uptr->STATUS = 0; - chan_clr_done(GET_UADDR(uptr->flags)); + chan_clr_done(dev); } break; @@ -263,7 +268,7 @@ void ptp_nsi_cmd(int dev, uint32 cmd) { if (cmd & 01) { if (uptr->CMD & BUSY || (uptr->flags & UNIT_ATT) == 0) { uptr->STATUS |= OPAT; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); return; } if (cmd & 010) @@ -277,7 +282,7 @@ void ptp_nsi_cmd(int dev, uint32 cmd) { uptr->CMD |= BUSY; uptr->STATUS = 0; sim_activate(uptr, uptr->wait); - chan_clr_done(GET_UADDR(uptr->flags)); + chan_clr_done(dev); } } @@ -315,14 +320,14 @@ void ptp_nsi_status(int dev, uint32 *resp) { if (uptr->CMD & BUSY) *resp |= 040; uptr->STATUS = 0; - chan_clr_done(GET_UADDR(uptr->flags)); + chan_clr_done(dev); } t_stat ptp_svc (UNIT *uptr) { - t_stat r; + int dev = GET_UADDR(uptr->flags); uint8 ch; int data; int eor; @@ -330,7 +335,7 @@ t_stat ptp_svc (UNIT *uptr) /* Handle a disconnect request */ if (uptr->CMD & DISC) { uptr->CMD &= 1; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); return SCPE_OK; } /* If not busy, false schedule, just exit */ @@ -341,11 +346,11 @@ t_stat ptp_svc (UNIT *uptr) if ((uptr->flags & UNIT_ATT) == 0) { uptr->CMD &= 1; uptr->STATUS = TERMINATE; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); return SCPE_OK; } - eor = chan_output_char(GET_UADDR(uptr->flags), &ch, 0); + eor = chan_output_char(dev, &ch, 0); if ((uptr->CMD & PUN_BLNK) != 0) { data = 0400; } else if (uptr->CMD & BIN_MODE) { @@ -408,7 +413,7 @@ t_stat ptp_svc (UNIT *uptr) if (ferror (uptr->fileref)) { uptr->STATUS |= TERMINATE|ERROR; uptr->CMD &= DELTA_MODE|1; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); return SCPE_OK; } } @@ -416,7 +421,7 @@ t_stat ptp_svc (UNIT *uptr) if (eor) { uptr->STATUS |= TERMINATE; uptr->CMD &= DELTA_MODE|1; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); return SCPE_OK; } sim_activate (uptr, uptr->wait); /* try again */ @@ -443,12 +448,13 @@ t_stat ptp_reset (DEVICE *dptr) t_stat ptp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { -fprintf (st, "The Paper Tape Punch can be set to one of two modes: 7P, or 7B.\n\n"); -fprintf (st, " mode \n"); -fprintf (st, " 7P Process even parity input tapes. \n"); -fprintf (st, " 7B Ignore parity of input data.\n"); -fprintf (st, "The default mode is 7B.\n"); -return SCPE_OK; + fprintf (st, "The Paper Tape Punch can be set to one of two modes: 7P, or 7B\n\n"); + fprintf (st, " 7P Generate even parity tapes.\n"); + fprintf (st, " 7B Generate 7 bit tapes.\n"); + fprintf (st, "The default mode is 7B.\n\n"); + fprintf (st, "The device number can be set with DEV=# command.\n"); + + return SCPE_OK; } CONST char *ptp_description (DEVICE *dptr) diff --git a/ICL1900/icl1900_tr.c b/ICL1900/icl1900_tr.c index a86a6fe..4d6b829 100644 --- a/ICL1900/icl1900_tr.c +++ b/ICL1900/icl1900_tr.c @@ -74,7 +74,7 @@ #define T1916_2 3 #define UNIT_PTR(x) UNIT_ADDR(x)|SET_TYPE(T1915_2)|UNIT_ATTABLE|\ - UNIT_DISABLE|UNIT_TEXT|UNIT_RO|TT_MODE_7B + UNIT_DISABLE|UNIT_RO|TT_MODE_7B /* * Character translation. @@ -196,21 +196,26 @@ void ptr_cmd(int dev, uint32 cmd, uint32 *resp) { uptr->CMD |= BUSY| (cmd & 07); uptr->STATUS = 0; sim_activate(uptr, uptr->wait); - chan_clr_done(GET_UADDR(uptr->flags)); + chan_clr_done(dev); *resp = 5; break; case 020: if (cmd == 020) { /* Send Q */ - if ((uptr->flags & UNIT_ATT) != 0) + *resp = uptr->STATUS & TERMINATE; + if ((uptr->flags & UNIT_ATT) != 0) { *resp = 040; - if (uptr->STATUS & 06) - *resp = 040; - *resp |= uptr->STATUS & TERMINATE; + if ((uptr->CMD & BUSY) == 0) + *resp |= 030; + } + if ((uptr->STATUS & ERROR) != 0) + *resp |= 040; } else if (cmd == 024) { /* Send P */ if ((uptr->flags & UNIT_ATT) != 0) - *resp = (uptr->STATUS & ERROR) | 1; + *resp = 1; + if ((uptr->STATUS & ERROR) != 0) + *resp |= 2; uptr->STATUS = 0; - chan_clr_done(GET_UADDR(uptr->flags)); + chan_clr_done(dev); } break; @@ -265,7 +270,7 @@ void ptr_nsi_cmd(int dev, uint32 cmd) { if (cmd & 01) { if (uptr->CMD & BUSY || (uptr->flags & UNIT_ATT) == 0) { uptr->STATUS |= OPAT; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); return; } if (cmd & 010) @@ -281,7 +286,7 @@ void ptr_nsi_cmd(int dev, uint32 cmd) { uptr->CMD |= BUSY; uptr->STATUS = 0; sim_activate(uptr, uptr->wait); - chan_clr_done(GET_UADDR(uptr->flags)); + chan_clr_done(dev); } } @@ -319,12 +324,12 @@ void ptr_nsi_status(int dev, uint32 *resp) { if (uptr->CMD & BUSY) *resp |= 040; uptr->STATUS = 0; - chan_clr_done(GET_UADDR(uptr->flags)); + chan_clr_done(dev); } t_stat ptr_svc (UNIT *uptr) { - t_stat r; + int dev = GET_UADDR(uptr->flags); uint8 ch; uint8 shift = 0; int data; @@ -333,7 +338,7 @@ t_stat ptr_svc (UNIT *uptr) /* Handle a disconnect request */ if (uptr->CMD & DISC) { uptr->CMD &= 1; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); return SCPE_OK; } /* If not busy, false schedule, just exit */ @@ -342,10 +347,10 @@ t_stat ptr_svc (UNIT *uptr) if (uptr->HOLD != 0) { ch = uptr->HOLD & 077; uptr->HOLD = 0; - eor = chan_input_char(GET_UADDR(uptr->flags), &ch, 0); + eor = chan_input_char(dev, &ch, 0); if (eor) { uptr->CMD &= 1; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); uptr->STATUS = TERMINATE; return SCPE_OK; } @@ -358,7 +363,7 @@ t_stat ptr_svc (UNIT *uptr) feof(uptr->fileref) || (data = getc (uptr->fileref)) == EOF) { uptr->CMD &= 1; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); uptr->STATUS = TERMINATE; return SCPE_OK; } @@ -371,7 +376,7 @@ t_stat ptr_svc (UNIT *uptr) ch = ch ^ (ch >> 1); if (ch != 0) uptr->STATUS = TERMINATE | ERROR; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); } data &= 0177; if ((data == 0 || data == 0177) && (uptr->CMD & IGN_BLNK) != 0) { @@ -384,7 +389,7 @@ t_stat ptr_svc (UNIT *uptr) case 0000: case 0020: /* Terminate */ uptr->STATUS |= TERMINATE; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); uptr->CMD &= 1; return SCPE_OK; case 0040: @@ -444,24 +449,24 @@ t_stat ptr_svc (UNIT *uptr) } /* Check if error */ if (shift != 0) { - eor = chan_input_char(GET_UADDR(uptr->flags), &shift, 0); + eor = chan_input_char(dev, &shift, 0); if (eor) { uptr->STATUS |= TERMINATE; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); uptr->CMD &= 1; uptr->HOLD = 0100 | ch; return SCPE_OK; } } - eor = chan_input_char(GET_UADDR(uptr->flags), &ch, 0); + eor = chan_input_char(dev, &ch, 0); if (eor) { uptr->STATUS |= TERMINATE; - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); uptr->CMD &= 1; return SCPE_OK; } if (uptr->STATUS & TERMINATE) { - chan_set_done(GET_UADDR(uptr->flags)); + chan_set_done(dev); uptr->CMD &= 1; return SCPE_OK; } @@ -491,14 +496,14 @@ t_stat ptr_boot(int32 unit_num, DEVICE * dptr) { UNIT *uptr = &dptr->units[unit_num]; - int chan = GET_UADDR(uptr->flags); + int dev = GET_UADDR(uptr->flags); if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ - M[64 + chan] = 0; - M[256 + 4 * chan] = 0; - M[257 + 4 * chan] = 0; + M[64 + dev] = 0; + M[256 + 4 * dev] = 0; + M[257 + 4 * dev] = 0; loading = 1; uptr->CMD = BUSY|ALPHA_MODE|BIN_MODE|IGN_BLNK; sim_activate (uptr, uptr->wait); @@ -508,12 +513,12 @@ ptr_boot(int32 unit_num, DEVICE * dptr) t_stat ptr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { -fprintf (st, "The Paper Tape Reader can be set to one of twp modes: 7P, or 7B.\n\n"); -fprintf (st, " mode \n"); -fprintf (st, " 7P Process even parity input tapes. \n"); -fprintf (st, " 7B Ignore parity of input data.\n"); -fprintf (st, "The default mode is 7B.\n"); -return SCPE_OK; + fprintf (st, "The Paper Tape Reader can be set to one of two modes: 7P, or 7B\n\n"); + fprintf (st, " 7P Process even parity input tapes. \n"); + fprintf (st, " 7B Ignore parity of input data.\n"); + fprintf (st, "The default mode is 7B.\n\n"); + fprintf (st, "The device number can be set with DEV=# command.\n"); + return SCPE_OK; } CONST char *ptr_description (DEVICE *dptr)