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:
@@ -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
300
ICL1900/icl1900_cp.c
Normal 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
|
||||
@@ -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
339
ICL1900/icl1900_cr.c
Normal 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
|
||||
@@ -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:
|
||||
|
||||
@@ -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
639
ICL1900/icl1900_eds8.c
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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}
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user