1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-04-03 12:22:52 +00:00

ICL1900: Added CR, CP and EDS8 disk controller. Misc cleanup

This commit is contained in:
Richard Cornwell
2018-09-08 23:58:44 -04:00
parent 49986d91e2
commit c9031657a5
14 changed files with 1491 additions and 162 deletions

View File

@@ -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

300
ICL1900/icl1900_cp.c Normal file
View File

@@ -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

View File

@@ -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 */

339
ICL1900/icl1900_cr.c Normal file
View File

@@ -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

View File

@@ -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 <escape>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:

View File

@@ -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;

639
ICL1900/icl1900_eds8.c Normal file
View File

@@ -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 <WD_SEC; i++) {
word = eds8_buffer[i];
even ^= (word >> 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

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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));
}

View File

@@ -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}
};

View File

@@ -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)

View File

@@ -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)