mirror of
https://github.com/simh/simh.git
synced 2026-01-27 12:32:24 +00:00
The makefile now works for Linux and most Unix's. However, for Solaris and MacOS, you must first export the OSTYPE environment variable: > export OSTYPE > make Otherwise, you will get build errors. 1. New Features 1.1 3.9-0 1.1.1 SCP and libraries - added *nix READLINE support (Mark Pizzolato) - added "SHOW SHOW" and "SHOW <dev> SHOW" commands (Mark Pizzolato) - added support for BREAK key on Windows (Mark Pizzolato) 1.1.2 PDP-8 - floating point processor is now enabled 2. Bugs Fixed Please see the revision history on http://simh.trailing-edge.com or in the source module sim_rev.h. 3. Status Report This is the last release of SimH for which I will be sole editor. After this release, the source is moving to a public repository: under the general editorship of Dave Hittner and Mark Pizzolato. The status of the individual simulators is as follows: 3.1 PDP-1 Stable and working; runs available software. 3.2 PDP-4/7/9/15 Stable and working; runs available software. 3.3 PDP-8 Stable and working; runs available software. 3.4 PDP-10 [KS-10 only] Stable and working; runs available software. 3.5 PDP-11 Stable and working; runs available system software. The emulation of individual models has numerous errors of detail, which prevents many diagnostics from running correctly. 3.6 VAX-11/780 Stable and working; runs available software. 3.7 MicroVAX 3900 (VAX) Stable and working; runs available software. Thanks to the kind generosity of Camiel Vanderhoeven, this simulator has been verified with AXE, the VAX architectural exerciser. 3.8 Nova Stable and working; runs available software. 3.9 Eclipse Stable and working, but not really supported. There is no Eclipse-specific software available under a hobbyist license. 3.10 Interdata 16b Stable and working, but no software for it has been found, other than diagnostics. 3.11 Interdata 32b Stable and working; runs 32b UNIX and diagnostics. 3.12 IBM 1401 Stable and working; runs available software. 3.13 IBM 1620 Hand debug only. No software for it has been found or tested. 3.14 IBM 7094 Stable and working as a stock system; runs IBSYS. The CTSS extensions have not been debugged. 3.15 IBM S/3 Stable and working, but not really supported. Runs available software. 3.16 IBM 1130 Stable and working; runs available software. Supported and edited by Brian Knittel. 3.17 HP 2100/1000 Stable and working; runs available software. Supported and edited by Dave Bryan. 3.18 Honeywell 316/516 Stable and working; runs available software. 3.19 GRI-909/99 Hand debug only. No software for it has been found or tested. 3.20 SDS-940 Hand debug only, and a few diagnostics. 3.21 LGP-30 Unfinished; hand debug only. Does not run available software, probably due to my misunderstanding of the LGP-30 operational procedures. 3.22 Altair (original 8080 version) Stable and working, but not really supported. Runs available software. 3.23 AltairZ80 (Z80 version) Stable and working; runs available software. Supported and edited by Peter Schorn. 3.24 SWTP 6800 Stable and working; runs available software. Supported and edited by Bill Beech 3.25 Sigma 32b Incomplete; more work is needed on the peripherals for accuracy. 3.26 Alpha Incomplete; essentially just an EV-5 (21164) chip emulator. 4. Suggestions for Future Work 4.1 General Structure - Multi-threading, to allow true concurrency between SCP and the simulator - Graphics device support, particularly for the PDP-1 and PDP-11 4.2 Current Simulators - PDP-1 graphics, to run Space War - PDP-11 GT40 graphics, to run Lunar Lander - PDP-15 MUMPS-15 - Interdata native OS debug, both 16b and 32b - SDS 940 timesharing operating system debug - IBM 7094 CTSS feature debug and operating system debug - IBM 1620 debug and software - GRI-909 software - Sigma 32b completion and debug - LGP-30 debug 4.3 Possible Future Simulators - Data General MV8000 (if a hobbyist license can be obtained for AOS) - Alpha simulator - HP 3000 (16b) simulator with MPE
530 lines
20 KiB
C
530 lines
20 KiB
C
/* sigma_lp.c: Sigma 7440/7450 line printer
|
|
|
|
Copyright (c) 2007-2008, Robert M. Supnik
|
|
|
|
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
|
|
ROBERT M SUPNIK 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 Robert M Supnik shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from Robert M Supnik.
|
|
|
|
lp 7440/7445 or 7450 line printer
|
|
*/
|
|
|
|
#include "sigma_io_defs.h"
|
|
|
|
/* Device definitions */
|
|
|
|
#define CCT_LNT 256 /* carriage ctl max */
|
|
#define BUF_LNT4 132 /* line lengths */
|
|
#define BUF_LNT5 128
|
|
|
|
#define LP_7440 0 /* models */
|
|
#define LP_7450 1
|
|
|
|
/* Device states */
|
|
|
|
#define LPS_INIT 0x101
|
|
#define LPS_END 0x102
|
|
#define LPS_PRI 0x1
|
|
#define LPS_FMT 0x3
|
|
#define LPS_FMTP 0x5
|
|
#define LPS_INT 0x40
|
|
|
|
/* Device status */
|
|
|
|
#define LPDV_ODD 0x40 /* odd */
|
|
#define LPDV_TOF 0x10 /* top of form */
|
|
#define LPDV_MOV 0x08 /* paper moving */
|
|
#define LPDV_V_RUN 2 /* runaway CCT */
|
|
#define LPDV_RUN (1u << LPDV_V_RUN)
|
|
#define LPDV_WT2 0x02 /* waiting for 2nd */
|
|
|
|
/* Format characters */
|
|
|
|
#define FMT_INH 0x60
|
|
#define FMT_SPC 0xC0
|
|
#define FMT_SKP 0xF0
|
|
|
|
#define FMT_MSPC4 15 /* max space cmd */
|
|
#define FMT_MSPC5 7
|
|
#define SPC_MASK ((lp_model == LP_7440)? FMT_MSPC4: FMT_MSPC5)
|
|
#define FMT_MCH4 7 /* max CCT channel */
|
|
#define FMT_MCH5 1
|
|
#define CCH_MASK ((lp_model == LP_7440)? FMT_MCH5: FMT_MCH4)
|
|
|
|
#define CH_BOF 0 /* CCT bot of form */
|
|
#define CH_TOF 1 /* CCT top of form */
|
|
|
|
#define CHP(ch,val) ((val) & (1 << (ch)))
|
|
|
|
uint32 lp_cmd = 0;
|
|
uint32 lp_stopioe = 1;
|
|
uint32 lp_cctp = 0; /* CCT position */
|
|
uint32 lp_cctl = 1; /* CCT length */
|
|
uint32 lp_lastcmd = 0; /* last command */
|
|
uint32 lp_pass = 0; /* 7450 print pass */
|
|
uint32 lp_inh = 0; /* space inhibit */
|
|
uint32 lp_run = 0; /* CCT runaway */
|
|
uint32 lp_model = LP_7440;
|
|
uint8 lp_buf[BUF_LNT4]; /* print buffer */
|
|
uint8 lp_cct[CCT_LNT] = { 0xFF }; /* carriage ctl tape */
|
|
uint8 lp_to_ascii[64] = {
|
|
' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
|
'H', 'I', '`', '.', '<', '(', '+', '|',
|
|
'&', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
|
'Q', 'R', '!', '$', '*', ')', ';', '~',
|
|
'-', '/', 'S', 'T', 'U', 'V', 'W', 'X',
|
|
'Y', 'Z', '^', ',', '%', '_', '>', '?',
|
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
'8', '9', ':', '#', '@', '\'', '=', '"'
|
|
};
|
|
|
|
extern uint32 chan_ctl_time;
|
|
|
|
uint32 lp_disp (uint32 op, uint32 dva, uint32 *dvst);
|
|
uint32 lp_tio_status (void);
|
|
uint32 lp_tdv_status (void);
|
|
t_stat lp_chan_err (uint32 st);
|
|
t_stat lp_svc (UNIT *uptr);
|
|
t_stat lp_reset (DEVICE *dptr);
|
|
t_stat lp_attach (UNIT *uptr, char *cptr);
|
|
t_stat lp_settype (UNIT *uptr, int32 val, char *cptr, void *desc);
|
|
t_stat lp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc);
|
|
t_stat lp_load_cct (UNIT *uptr, int32 val, char *cptr, void *desc);
|
|
uint32 lp_fmt (UNIT *uptr);
|
|
uint32 lp_skip (UNIT *uptr, uint32 ch);
|
|
uint32 lp_space (UNIT *uptr, uint32 lines, t_bool skp);
|
|
uint32 lp_print (UNIT *uptr);
|
|
|
|
/* LP data structures
|
|
|
|
lp_dev LP device descriptor
|
|
lp_unit LP unit descriptors
|
|
lp_reg LP register list
|
|
lp_mod LP modifiers list
|
|
*/
|
|
|
|
dib_t lp_dib = { DVA_LP, lp_disp, 0, NULL };
|
|
|
|
UNIT lp_unit = { UDATA (&lp_svc, UNIT_ATTABLE+UNIT_SEQ, 0), SERIAL_OUT_WAIT };
|
|
|
|
REG lp_reg[] = {
|
|
{ HRDATA (CMD, lp_cmd, 9) },
|
|
{ BRDATA (BUF, lp_buf, 16, 7, BUF_LNT4) },
|
|
{ FLDATA (PASS, lp_pass, 0) },
|
|
{ FLDATA (INH, lp_inh, 0) },
|
|
{ FLDATA (RUNAWAY, lp_run, LPDV_V_RUN) },
|
|
{ BRDATA (CCT, lp_cct, 8, 8, CCT_LNT) },
|
|
{ DRDATA (CCTP, lp_cctp, 8), PV_LEFT },
|
|
{ DRDATA (CCTL, lp_cctl, 8), PV_LEFT + REG_HRO + REG_NZ },
|
|
{ DRDATA (POS, lp_unit.pos, T_ADDR_W), PV_LEFT },
|
|
{ DRDATA (TIME, lp_unit.wait, 24), PV_LEFT },
|
|
{ FLDATA (STOP_IOE, lp_stopioe, 0) },
|
|
{ HRDATA (LASTC, lp_lastcmd, 8), REG_HIDDEN },
|
|
{ FLDATA (MODEL, lp_model, 0), REG_HRO },
|
|
{ HRDATA (DEVNO, lp_dib.dva, 12), REG_HRO },
|
|
{ NULL }
|
|
};
|
|
|
|
MTAB lp_mod[] = {
|
|
{ MTAB_XTD | MTAB_VDV, LP_7440, NULL, "7440",
|
|
&lp_settype, NULL, NULL },
|
|
{ MTAB_XTD | MTAB_VDV, LP_7450, NULL, "7450",
|
|
&lp_settype, NULL, NULL },
|
|
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL,
|
|
NULL, &lp_showtype, NULL },
|
|
{ MTAB_XTD | MTAB_VDV | MTAB_NC, 0, NULL, "CCT",
|
|
&lp_load_cct, NULL, NULL },
|
|
{ MTAB_XTD|MTAB_VDV, 0, "CHAN", "CHAN",
|
|
&io_set_dvc, &io_show_dvc, NULL },
|
|
{ MTAB_XTD|MTAB_VDV, 0, "DVA", "DVA",
|
|
&io_set_dva, &io_show_dva, NULL },
|
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "CSTATE", NULL,
|
|
NULL, &io_show_cst, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
DEVICE lp_dev = {
|
|
"LP", &lp_unit, lp_reg, lp_mod,
|
|
1, 10, 31, 1, 16, 8,
|
|
NULL, NULL, &lp_reset,
|
|
NULL, &lp_attach, NULL,
|
|
&lp_dib, 0
|
|
};
|
|
|
|
/* Line printer: IO dispatch routine */
|
|
|
|
uint32 lp_disp (uint32 op, uint32 dva, uint32 *dvst)
|
|
{
|
|
switch (op) { /* case on op */
|
|
|
|
case OP_SIO: /* start I/O */
|
|
*dvst = lp_tio_status (); /* get status */
|
|
if ((*dvst & DVS_DST) == 0) { /* idle? */
|
|
lp_cmd = LPS_INIT; /* start dev thread */
|
|
sim_activate (&lp_unit, chan_ctl_time);
|
|
}
|
|
break;
|
|
|
|
case OP_TIO: /* test status */
|
|
*dvst = lp_tio_status (); /* return status */
|
|
break;
|
|
|
|
case OP_TDV: /* test status */
|
|
*dvst = lp_tdv_status (); /* return status */
|
|
break;
|
|
|
|
case OP_HIO: /* halt I/O */
|
|
chan_clr_chi (lp_dib.dva); /* clear int */
|
|
*dvst = lp_tio_status (); /* get status */
|
|
if ((*dvst & DVS_DST) != 0) { /* busy? */
|
|
sim_cancel (&lp_unit); /* stop dev thread */
|
|
chan_uen (lp_dib.dva); /* uend */
|
|
}
|
|
break;
|
|
|
|
case OP_AIO: /* acknowledge int */
|
|
chan_clr_chi (lp_dib.dva); /* clear int */
|
|
*dvst = lp_lastcmd & LPS_INT; /* int requested */
|
|
lp_lastcmd = 0;
|
|
break;
|
|
|
|
default:
|
|
*dvst = 0;
|
|
return SCPE_IERR;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Service routine */
|
|
|
|
t_stat lp_svc (UNIT *uptr)
|
|
{
|
|
uint32 cmd;
|
|
uint32 st;
|
|
|
|
switch (lp_cmd) { /* case on state */
|
|
|
|
case LPS_INIT: /* I/O init */
|
|
st = chan_get_cmd (lp_dib.dva, &cmd); /* get command */
|
|
if (CHS_IFERR (st)) /* channel error? */
|
|
return lp_chan_err (st);
|
|
lp_inh = 0; /* clear inhibit, */
|
|
lp_run = 0; /* runaway */
|
|
lp_cmd = lp_lastcmd = cmd; /* save command */
|
|
sim_activate (uptr, chan_ctl_time); /* continue thread */
|
|
break;
|
|
|
|
case LPS_FMT:
|
|
case LPS_FMT|LPS_INT: /* format only */
|
|
sim_activate (uptr, uptr->wait); /* continue thread */
|
|
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
|
return lp_stopioe? SCPE_UNATT: SCPE_OK;
|
|
st = lp_fmt (uptr); /* format */
|
|
if (CHS_IFERR (st)) /* error? */
|
|
return lp_chan_err (st);
|
|
if ((lp_model == LP_7440) && /* 7440? lnt chk */
|
|
(st != CHS_ZBC) &&
|
|
chan_set_chf (lp_dib.dva, CHF_LNTE)) /* not ignored? */
|
|
return lp_chan_err (SCPE_OK); /* force uend */
|
|
lp_cmd = LPS_END; /* actual print */
|
|
break;
|
|
|
|
case LPS_FMTP:
|
|
case LPS_FMTP|LPS_INT: /* format and print */
|
|
sim_activate (uptr, uptr->wait); /* continue thread */
|
|
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
|
return lp_stopioe? SCPE_UNATT: SCPE_OK;
|
|
st = lp_fmt (uptr); /* format */
|
|
if (CHS_IFERR (st)) /* error? */
|
|
return lp_chan_err (st);
|
|
if (st == CHS_ZBC) { /* command done? */
|
|
if ((lp_model == LP_7440) && /* 7440? lnt err */
|
|
chan_set_chf (lp_dib.dva, CHF_LNTE)) /* not ignored? */
|
|
return lp_chan_err (SCPE_OK);
|
|
}
|
|
else { /* more to do */
|
|
st = lp_print (uptr); /* print */
|
|
if (CHS_IFERR (st)) /* error */
|
|
return lp_chan_err (st);
|
|
}
|
|
break;
|
|
|
|
case LPS_PRI:
|
|
case LPS_PRI|LPS_INT: /* print only */
|
|
sim_activate (uptr, uptr->wait); /* continue thread */
|
|
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
|
return lp_stopioe? SCPE_UNATT: SCPE_OK;
|
|
st = lp_print (uptr); /* print */
|
|
if (CHS_IFERR (st)) /* error? */
|
|
return lp_chan_err (st);
|
|
break;
|
|
|
|
case LPS_END: /* command done */
|
|
if ((lp_lastcmd & LPS_INT) && !lp_pass) /* int requested? */
|
|
chan_set_chi (lp_dib.dva, 0);
|
|
st = chan_end (lp_dib.dva); /* set channel end */
|
|
if (CHS_IFERR (st)) /* channel error? */
|
|
return lp_chan_err (st);
|
|
if (st == CHS_CCH) { /* command chain? */
|
|
lp_cmd = LPS_INIT; /* restart thread */
|
|
sim_activate (uptr, chan_ctl_time);
|
|
}
|
|
break;
|
|
|
|
default: /* invalid cmd */
|
|
chan_uen (lp_dib.dva); /* uend */
|
|
break;
|
|
}
|
|
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Format routine */
|
|
|
|
uint32 lp_fmt (UNIT *uptr)
|
|
{
|
|
uint32 c, i;
|
|
uint32 st;
|
|
|
|
st = chan_RdMemB (lp_dib.dva, &c); /* get char */
|
|
if (CHS_IFERR (st)) /* channel error? */
|
|
return st; /* caller handles */
|
|
if (lp_pass) /* only on pass 1 */
|
|
return 0;
|
|
if ((c & 0x7F) == FMT_INH) /* inhibit? */
|
|
lp_inh = 1;
|
|
else if ((c & ~(((lp_model == LP_7450)? 0x20: 0) | SPC_MASK)) == FMT_SPC) {
|
|
c = c & SPC_MASK; /* space? */
|
|
for (i = 1; i <= c; i++) { /* look for BOF */
|
|
if (CHP (CH_BOF, lp_cct[(lp_cctp + i) % lp_cctl]))
|
|
return lp_skip (uptr, CH_TOF); /* found, TOF */
|
|
}
|
|
return lp_space (uptr, c, FALSE); /* space */
|
|
}
|
|
else if ((c & ~CCH_MASK) == FMT_SKP) /* skip? */
|
|
return lp_skip (uptr, c & CCH_MASK); /* skip to chan */
|
|
return 0;
|
|
}
|
|
|
|
/* Skip to channel */
|
|
|
|
uint32 lp_skip (UNIT *uptr, uint32 ch)
|
|
{
|
|
uint32 i;
|
|
|
|
for (i = 1; i < (lp_cctl + 1); i++) { /* sweep thru CCT */
|
|
if (CHP (ch, lp_cct[(lp_cctp + i) % lp_cctl])) /* channel punched? */
|
|
return lp_space (uptr, i, TRUE); /* space to chan */
|
|
}
|
|
lp_run = LPDV_RUN; /* runaway CCT */
|
|
return lp_space (uptr, lp_cctl, TRUE); /* space max */
|
|
}
|
|
|
|
/* Space routine */
|
|
|
|
uint32 lp_space (UNIT *uptr, uint32 cnt, t_bool skp)
|
|
{
|
|
uint32 i;
|
|
|
|
lp_cctp = (lp_cctp + cnt) % lp_cctl; /* adv cct, mod lnt */
|
|
if (skp && CHP (CH_TOF, lp_cct[lp_cctp])) /* skip, TOF? */
|
|
fputs ("\f", uptr->fileref); /* ff */
|
|
else { /* space */
|
|
for (i = 0; i < cnt; i++)
|
|
fputc ('\n', uptr->fileref);
|
|
}
|
|
uptr->pos = ftell (uptr->fileref); /* update position */
|
|
if (ferror (uptr->fileref)) { /* error? */
|
|
perror ("Line printer I/O error");
|
|
clearerr (uptr->fileref);
|
|
chan_set_chf (lp_dib.dva, CHF_XMDE);
|
|
return SCPE_IOERR;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Print routine */
|
|
|
|
uint32 lp_print (UNIT *uptr)
|
|
{
|
|
uint32 i, bp, c;
|
|
uint32 max = (lp_model == LP_7440)? BUF_LNT4: BUF_LNT5;
|
|
uint32 st;
|
|
|
|
if (lp_pass == 0) { /* pass 1? clr buf */
|
|
for (i = 0; i < BUF_LNT4; i++) lp_buf[i] = ' ';
|
|
}
|
|
for (bp = 0, st = 0; (bp < max) && !st; bp++) { /* fill buffer */
|
|
st = chan_RdMemB (lp_dib.dva, &c); /* get char */
|
|
if (CHS_IFERR (st)) /* channel error? */
|
|
return st; /* caller handles */
|
|
if ((lp_model == LP_7440) || /* 7440 or */
|
|
((bp & 1) == lp_pass)) /* correct pass? */
|
|
lp_buf[bp] = lp_to_ascii[c & 0x3F];
|
|
}
|
|
if ((lp_model == LP_7440) || lp_pass) { /* ready to print? */
|
|
lp_pass = 0;
|
|
for (i = BUF_LNT4; (i > 0) && (lp_buf[i - 1] == ' '); i--) ; /* trim */
|
|
if (i) /* write line */
|
|
sim_fwrite (lp_buf, 1, i, uptr->fileref);
|
|
fputc (lp_inh? '\r': '\n', uptr->fileref); /* cr or nl */
|
|
uptr->pos = ftell (uptr->fileref); /* update position */
|
|
if (ferror (uptr->fileref)) { /* error? */
|
|
perror ("Line printer I/O error");
|
|
clearerr (uptr->fileref);
|
|
chan_set_chf (lp_dib.dva, CHF_XMDE);
|
|
return SCPE_IOERR;
|
|
}
|
|
if ((lp_model == LP_7440) && /* 7440? */
|
|
((bp != BUF_LNT4) || (st != CHS_ZBC)) && /* check lnt err */
|
|
chan_set_chf (lp_dib.dva, CHF_LNTE))
|
|
return CHS_INACTV; /* stop if asked */
|
|
}
|
|
else lp_pass = 1; /* 7450 pass 2 */
|
|
lp_cmd = LPS_END; /* end state */
|
|
return 0;
|
|
}
|
|
|
|
/* LP status routine */
|
|
|
|
uint32 lp_tio_status (void)
|
|
{
|
|
uint32 st;
|
|
|
|
st = (lp_unit.flags & UNIT_ATT)? DVS_AUTO: 0; /* auto? */
|
|
if (sim_is_active (&lp_unit)) /* busy? */
|
|
st |= (DVS_CBUSY | DVS_DBUSY | (CC2 << DVT_V_CC));
|
|
return st;
|
|
}
|
|
|
|
uint32 lp_tdv_status (void)
|
|
{
|
|
uint32 st;
|
|
|
|
st = lp_run; /* runaway flag */
|
|
if ((lp_unit.flags & UNIT_ATT) == 0) /* fault? */
|
|
st |= (CC2 << DVT_V_CC);
|
|
if (lp_cmd == LPS_END) /* end state? */
|
|
st |= LPDV_MOV; /* printing */
|
|
if (lp_pass && (lp_model == LP_7450)) { /* 7450 pass 2? */
|
|
st |= LPDV_ODD; /* odd state */
|
|
if (lp_cmd == LPS_INIT) /* wait for cmd? */
|
|
st |= LPDV_WT2;
|
|
}
|
|
return st;
|
|
}
|
|
|
|
/* Channel error */
|
|
|
|
t_stat lp_chan_err (uint32 st)
|
|
{
|
|
sim_cancel (&lp_unit); /* stop dev thread */
|
|
chan_uen (lp_dib.dva); /* uend */
|
|
if (st < CHS_ERR)
|
|
return st;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Reset routine */
|
|
|
|
t_stat lp_reset (DEVICE *dptr)
|
|
{
|
|
sim_cancel (&lp_unit); /* stop dev thread */
|
|
lp_cmd = 0;
|
|
lp_lastcmd = 0;
|
|
lp_pass = 0;
|
|
lp_inh = 0;
|
|
lp_run = 0;
|
|
chan_reset_dev (lp_dib.dva); /* clr int, active */
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Attach routine */
|
|
|
|
t_stat lp_attach (UNIT *uptr, char *cptr)
|
|
{
|
|
lp_cctp = 0; /* clear cct ptr */
|
|
lp_pass = 0;
|
|
return attach_unit (uptr, cptr);
|
|
}
|
|
|
|
/* Set carriage control tape */
|
|
|
|
t_stat lp_load_cct (UNIT *uptr, int32 val, char *cptr, void *desc)
|
|
{
|
|
uint32 col, rpt, ptr, mask;
|
|
uint8 cctbuf[CCT_LNT];
|
|
t_stat r;
|
|
char cbuf[CBUFSIZE], gbuf[CBUFSIZE];
|
|
FILE *cfile;
|
|
|
|
if ((cptr == NULL) || (*cptr == 0)) return SCPE_ARG;
|
|
if ((cfile = fopen (cptr, "r")) == NULL)
|
|
return SCPE_OPENERR;
|
|
ptr = 0;
|
|
for ( ; (cptr = fgets (cbuf, CBUFSIZE, cfile)) != NULL; ) {
|
|
mask = 0;
|
|
if (*cptr == '(') { /* repeat count? */
|
|
cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */
|
|
rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */
|
|
if (r != SCPE_OK)
|
|
return SCPE_FMT;
|
|
}
|
|
else rpt = 1;
|
|
while (*cptr != 0) { /* get col no's */
|
|
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
|
|
col = get_uint (gbuf, 10, FMT_MCH4, &r); /* column number */
|
|
if (r != SCPE_OK)
|
|
return SCPE_FMT;
|
|
mask = mask | (1 << col); /* set bit */
|
|
}
|
|
for ( ; rpt > 0; rpt--) { /* store vals */
|
|
if (ptr >= CCT_LNT)
|
|
return SCPE_FMT;
|
|
cctbuf[ptr++] = mask;
|
|
}
|
|
}
|
|
if (ptr == 0)
|
|
return SCPE_FMT;
|
|
lp_cctl = ptr;
|
|
lp_cctp = 0;
|
|
for (rpt = 0; rpt < lp_cctl; rpt++)
|
|
lp_cct[rpt] = cctbuf[rpt];
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Set controller type */
|
|
|
|
t_stat lp_settype (UNIT *uptr, int32 val, char *cptr, void *desc)
|
|
{
|
|
lp_model = val;
|
|
lp_reset (&lp_dev);
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Show controller type */
|
|
|
|
t_stat lp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc)
|
|
{
|
|
fprintf (st, lp_model? "7450": "7440");
|
|
return SCPE_OK;
|
|
}
|