blob: 7d8fa67a532feab3de74ace7773ae9989aa9ccac [file] [log] [blame] [raw]
/* ibm1130_stddev.c: IBM 1130 standard I/O devices simulator
Copyright (c) 2001, Brian Knittel
Based on PDP-11 simulator written by Robert M Supnik
Brian Knittel
Revision History
31July2001 - Derived from pdp11_stddev.c, which carries this disclaimer:
Copyright (c) 1993-2001, 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.
*/
#include "ibm1130_defs.h"
/* ---------------------------------------------------------------------------- */
static void badio (char *dev)
{
// the real 1130 just ignores attempts to use uninstalled devices. They get tested
// at times, so it's best to be quiet about this
// printf("%s I/O is not yet supported", dev);
// wait_state = WAIT_INVALID_OP;
}
void xio_1134_papertape (int32 addr, int32 func, int32 modify) {badio("papertape");}
void xio_1627_plotter (int32 addr, int32 func, int32 modify) {badio("plotter");}
void xio_1231_optical (int32 addr, int32 func, int32 modify) {badio("optical mark");}
void xio_2501_card (int32 addr, int32 func, int32 modify) {badio("2501 card");}
void xio_1131_synch (int32 addr, int32 func, int32 modify) {badio("SCA");}
void xio_system7 (int32 addr, int32 func, int32 modify) {badio("System 7");}
void xio_1403_printer (int32 addr, int32 func, int32 modify) {badio("1403 printer");}
void xio_2250_display (int32 addr, int32 func, int32 modify)
{
if (func != XIO_CONTROL)
badio("2250 display"); // resmon issues stop control, so ignore XIO_CONTROL
}
/* ---------------------------------------------------------------------------- */
static int32 tti_dsw = 0; /* device status words */
static int32 tto_dsw = 0;
static int32 con_dsw = 0;
static t_stat tti_svc (UNIT *uptr);
static t_stat tto_svc (UNIT *uptr);
static t_stat tti_reset (DEVICE *dptr);
static t_stat tto_reset (DEVICE *dptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_wait_kbd (void);
extern t_stat sim_putchar (int32 out);
extern UNIT *sim_clock_queue;
#define CSET_MASK 1 /* character set */
#define CSET_NORMAL 0
#define CSET_ASCII 1
#define IRQ_KEY 0x11 /* ctrl-Q */
#define PROGRAM_STOP_KEY 0x03 /* ctrl-C */
#include "ibm1130_conout.h" /* conout_to_ascii table */
#include "ibm1130_conin.h" /* ascii_to_conin table */
/* TTI data structures
tti_dev TTI device descriptor
tti_unit TTI unit descriptor
tti_reg TTI register list
*/
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
REG tti_reg[] = {
{ ORDATA (BUF, tti_unit.buf, 8) },
{ ORDATA (DSW, tti_dsw, 16) },
{ DRDATA (POS, tti_unit.pos, 32), PV_LEFT },
{ DRDATA (STIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL } };
MTAB tti_mod[] = {
{ CSET_MASK, CSET_NORMAL, NULL, "1130", NULL},
{ CSET_MASK, CSET_ASCII, NULL, "ASCII", NULL},
{ 0 } };
DEVICE tti_dev = {
"KEYBOARD", &tti_unit, tti_reg, tti_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tti_reset,
NULL, NULL, NULL };
/* TTO data structures
tto_dev TTO device descriptor
tto_unit TTO unit descriptor
tto_reg TTO register list
*/
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, 8) },
{ ORDATA (DSW, tto_dsw, 16) },
{ DRDATA (POS, tto_unit.pos, 32), PV_LEFT },
{ DRDATA (STIME, tto_unit.wait, 24), PV_LEFT },
{ NULL } };
MTAB tto_mod[] = {
{ CSET_MASK, CSET_NORMAL, NULL, "1130", NULL},
{ CSET_MASK, CSET_ASCII, NULL, "ASCII", NULL},
{ 0 } };
DEVICE tto_dev = {
"TTO", &tto_unit, tto_reg, tto_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tto_reset,
NULL, NULL, NULL };
/* Terminal input routines
tti_svc process event (character ready)
tti_reset process reset
tto_svc process event (print character)
tto_reset process reset
*/
#define TT_DSW_PRINTER_RESPONSE 0x8000
#define TT_DSW_KEYBOARD_RESPONSE 0x4000
#define TT_DSW_INTERRUPT_REQUEST 0x2000
#define TT_DSW_KEYBOARD_CONSOLE 0x1000
#define TT_DSW_PRINTER_BUSY 0x0800
#define TT_DSW_PRINTER_NOT_READY 0x0400
#define TT_DSW_KEYBOARD_BUSY 0x0200
void xio_1131_console (int32 iocc_addr, int32 func, int32 modify)
{
int ch;
char msg[80];
switch (func) {
case XIO_CONTROL:
SETBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY);
keyboard_selected(TRUE);
// sim_activate(&tti_unit, tti_unit.wait); /* poll keyboard never stops */
break;
case XIO_READ:
WriteW(iocc_addr, tti_unit.buf);
CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY);
keyboard_selected(FALSE);
break;
case XIO_WRITE:
ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */
if ((tto_unit.flags & CSET_MASK) == CSET_NORMAL)
ch = conout_to_ascii[ch]; /* convert to ASCII */
if (ch == 0)
ch = '?'; /* hmmm, unknown character */
tto_unit.buf = ch; /* save character to write */
SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY);
sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */
break;
case XIO_SENSE_DEV:
ACC = tto_dsw | tti_dsw;
if (modify & 0x01) { /* reset interrupts */
CLRBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE);
CLRBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE);
CLRBIT(ILSW[4], ILSW_4_CONSOLE);
}
break;
default:
sprintf(msg, "Invalid console XIO function %x", func);
xio_error(msg);
}
}
static void Beep (void) // notify user keyboard was locked or key was bad
{
sim_putchar(7);
}
// tti_svc - keyboard polling (never stops)
t_stat tti_svc (UNIT *uptr)
{
int32 temp;
sim_activate(&tti_unit, tti_unit.wait); /* continue polling */
temp = sim_poll_kbd();
if (temp < SCPE_KFLAG)
return temp; /* no char or error? */
temp &= 0xFF; /* remove SCPE_KFLAG */
if (temp == IRQ_KEY) { /* interrupt request key */
SETBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); /* queue interrupt */
SETBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
return SCPE_OK;
}
if (temp == PROGRAM_STOP_KEY) { /* simulate the program stop button */
SETBIT(con_dsw, CON_DSW_PROGRAM_STOP);
SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP);
calc_ints();
return SCPE_OK;
}
if (tti_dsw & TT_DSW_KEYBOARD_BUSY) { /* only store character if it was requested (keyboard unlocked) */
if ((uptr->flags & CSET_MASK) == CSET_NORMAL)
temp = ascii_to_conin[temp];
if (temp == 0) { /* ignore invalid characters */
Beep();
calc_ints();
return SCPE_OK;
}
tti_unit.buf = temp & 0xFFFE; /* save keystroke except last bit (not defined, */
tti_unit.pos = tti_unit.pos + 1; /* but it lets us distinguish 0 from no punch ' ' */
CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* clear busy flag (relock keyboard) */
keyboard_selected(FALSE);
SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */
SETBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
}
else
Beep();
return SCPE_OK;
}
t_stat tti_reset (DEVICE *dptr)
{
tti_unit.buf = 0;
tti_dsw = 0;
CLRBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
keyboard_selected(FALSE);
sim_activate(&tti_unit, tti_unit.wait); /* always poll keyboard */
return SCPE_OK;
}
t_bool keyboard_is_locked (void) /* return TRUE if keyboard is not expecting a character */
{
return (tti_dsw & TT_DSW_KEYBOARD_BUSY) == 0;
}
t_stat tto_svc (UNIT *uptr)
{
int32 temp;
int ch;
CLRBIT(tto_dsw, TT_DSW_PRINTER_BUSY);
SETBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE);
SETBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
ch = tto_unit.buf & 0xFF;
switch (ch) {
case IGNR:
break;
case CRLF:
if ((temp = sim_putchar('\r')) != SCPE_OK)
return temp;
if ((temp = sim_putchar('\n')) != SCPE_OK)
return temp;
break;
default:
if ((temp = sim_putchar(ch)) != SCPE_OK)
return temp;
break;
}
tto_unit.pos = tto_unit.pos + 1; /* hmm, why do we count these? */
return SCPE_OK;
}
t_stat tto_reset (DEVICE *dptr)
{
tto_unit.buf = 0;
tto_dsw = 0;
CLRBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
sim_cancel(&tto_unit); /* deactivate unit */
return SCPE_OK;
}
/***************************************************************************************
* 1132 PRINTER
***************************************************************************************/
#define PRT_DSW_READ_EMITTER_RESPONSE 0x8000
#define PRT_DSW_SKIP_RESPONSE 0x4000
#define PRT_DSW_SPACE_RESPONSE 0x2000
#define PRT_DSW_CARRIAGE_BUSY 0x1000
#define PRT_DSW_PRINT_SCAN_CHECK 0x0800
#define PRT_DSW_NOT_READY 0x0400
#define PRT_DSW_PRINTER_BUSY 0x0200
#define PRT_DSW_CHANNEL_MASK 0x00FF
#define PRT_DSW_CHANNEL_1 0x0080
#define PRT_DSW_CHANNEL_2 0x0040
#define PRT_DSW_CHANNEL_3 0x0020
#define PRT_DSW_CHANNEL_4 0x0010
#define PRT_DSW_CHANNEL_5 0x0008
#define PRT_DSW_CHANNEL_6 0x0004
#define PRT_DSW_CHANNEL_9 0x0002
#define PRT_DSW_CHANNEL_12 0x0001
#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
static t_stat prt_svc (UNIT *uptr);
static t_stat prt_reset (DEVICE *dptr);
static t_stat prt_attach (UNIT *uptr, char *cptr);
static t_stat prt_detach (UNIT *uptr);
static int16 prt_dsw = 0; /* device status word */
static int32 prt_swait = 500; /* line skip wait */
static int32 prt_cwait = 1000; /* character rotation wait */
#define UNIT_V_FORMCHECK (UNIT_V_UF + 0) /* out of paper error */
#define UNIT_V_DATACHECK (UNIT_V_UF + 1) /* printer overrun error */
#define UNIT_V_SKIPPING (UNIT_V_UF + 2) /* printer skipping */
#define UNIT_V_SPACING (UNIT_V_UF + 3) /* printer is spacing */
#define UNIT_V_PRINTING (UNIT_V_UF + 4) /* printer printing */
#define UNIT_FORMCHECK (1u << UNIT_V_FORMCHECK)
#define UNIT_DATACHECK (1u << UNIT_V_DATACHECK)
#define UNIT_SKIPPING (1u << UNIT_V_SKIPPING)
#define UNIT_SPACING (1u << UNIT_V_SPACING)
#define UNIT_PRINTING (1u << UNIT_V_PRINTING)
UNIT prt_unit[] = {
{ UDATA (&prt_svc, UNIT_ATTABLE, 0) },
};
/* Parameter in the unit descriptor */
#define CMD_NONE 0
#define CMD_SPACE 1
#define CMD_SKIP 2
#define CMD_PRINT 3
REG prt_reg[] = {
{ HRDATA (PRTDSW, prt_dsw, 16) }, /* device status word */
{ DRDATA (STIME, prt_swait, 24), PV_LEFT }, /* line skip wait */
{ DRDATA (CTIME, prt_cwait, 24), PV_LEFT }, /* character rotation wait */
{ NULL } };
DEVICE prt_dev = {
"PRT", prt_unit, prt_reg, NULL,
1, 16, 16, 1, 16, 16,
NULL, NULL, &prt_reset,
NULL, prt_attach, prt_detach};
#define PRT_COLUMNS 120
#define PRT_ROWLEN 120
#define MAX_OVPRINT 20
static char prtbuf[PRT_ROWLEN*MAX_OVPRINT];
static int nprint[PRT_COLUMNS], ncol[MAX_OVPRINT], maxnp;
static int prt_nchar, prt_row; /* current printwheel position, current page row */
static int prt_nnl; /* number of queued newlines */
#define CC_CHANNEL_1 0x0080 /* carriage control tape punch values */
#define CC_CHANNEL_2 0x0040
#define CC_CHANNEL_3 0x0020
#define CC_CHANNEL_4 0x0010
#define CC_CHANNEL_5 0x0008
#define CC_CHANNEL_6 0x0004
#define CC_CHANNEL_9 0x0002
#define CC_CHANNEL_12 0x0001
#define PRT_PAGELENGTH 66
// glunk need to fill these two arrays in -- cctape and codewheel1132
static int cctape[PRT_PAGELENGTH]; /* standard carriage control tape */
static struct tag_ccpunches { /* list of rows and punches on tape */
int row, channels;
} ccpunches[] = {
7, CC_CHANNEL_12, /* these came from the tape in our printer */
13, CC_CHANNEL_1 /* modulo 66 */
};
#include "ibm1130_prtwheel.h"
// reset_prt_line - clear the print line following paper advancement
static void reset_prt_line (void)
{
memset(nprint, 0, sizeof(nprint));
memset(ncol, 0, sizeof(ncol));
maxnp = 0;
}
// save_prt_line - fire hammers for character 'ch'
static t_bool save_prt_line (int ch)
{
int i, r, addr = 32;
int32 mask = 0, wd = 0;
for (i = 0; i < PRT_COLUMNS; i++) {
if (mask == 0) { // fetch next word from memory
mask = 0x8000;
wd = M[addr++];
}
if (wd & mask) { // hammer is to fire in this column
if ((r = nprint[i]) < MAX_OVPRINT) {
if (ncol[r] <= i) { // we haven't moved this far yet
if (ncol[r] == 0) // first char in this row?
memset(prtbuf+r*PRT_ROWLEN, ' ', PRT_COLUMNS); // blank out the new row
ncol[r] = i+1; // remember new row length
}
prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character
nprint[i]++; // remember max overprintings for this column
maxnp = MAX(maxnp, nprint[i]);
}
}
mask >>= 1; // prepare to examine next bit
}
return wd & 1; // return TRUE if the last word has lsb set, which means all bits had been set
}
// write_line - write collected line to output file. No need to trim spaces as the hammers
// are never fired for them, so ncol[r] is the last printed position on each line.
static void flush_prt_line (FILE *fd, t_bool space)
{
int r;
if (! (space || maxnp)) // nothing to do
return;
prt_row = (prt_row+1) % PRT_PAGELENGTH; // NEXT line
if (space && ! maxnp) { // spacing only
if (prt_row == 0 && prt_nnl) {
putc('\f', fd);
prt_nnl = 0;
}
else
prt_nnl++;
return;
}
if (prt_nnl) { // there are queued newlines
if (prt_row == 0 && prt_nnl) { // we spaced to top of form: use formfeed
putc('\f', fd);
prt_nnl = 0;
}
else {
while (prt_nnl > 0) { // spit out queued newlines
#ifdef WIN32
putc('\r', fd); // DOS/Windows: end with cr/lf
#endif
putc('\n', fd); // otherwise end with lf
prt_nnl--;
}
}
}
for (r = 0; r < maxnp; r++) {
if (r > 0)
putc('\r', fd); // carriage return between overprinted lines
fwrite(&prtbuf[r*PRT_ROWLEN], 1, ncol[r], fd);
}
reset_prt_line();
prt_nnl++; // queue a newline
}
#define PRT_CMD_START_PRINTER 0x0080
#define PRT_CMD_STOP_PRINTER 0x0040
#define PRT_CMD_START_CARRIAGE 0x0004
#define PRT_CMD_STOP_CARRIAGE 0x0002
#define PRT_CMD_SPACE 0x0001
#define PRT_CMD_MASK 0x00C7
/* xio_1132_printer - XIO command interpreter for the 1132 printer */
void xio_1132_printer (int32 iocc_addr, int32 func, int32 modify)
{
char msg[80];
UNIT *uptr = &prt_unit[0];
switch (func) {
case XIO_READ:
M[iocc_addr & mem_mask] = codewheel1132[prt_nchar].ebcdic << 8;
if ((uptr->flags & UNIT_PRINTING) == 0) /* if we're not printing, advance this after every test */
prt_nchar = (prt_nchar + 1) % WHEELCHARS;
break;
case XIO_SENSE_DEV:
ACC = prt_dsw;
if (modify & 0x01) { /* reset interrupts */
CLRBIT(prt_dsw, PRT_DSW_READ_EMITTER_RESPONSE | PRT_DSW_SKIP_RESPONSE | PRT_DSW_SPACE_RESPONSE);
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
}
break;
case XIO_CONTROL:
if (modify & PRT_CMD_START_PRINTER)
SETBIT(uptr->flags, UNIT_PRINTING);
if (modify & PRT_CMD_STOP_PRINTER)
CLRBIT(uptr->flags, UNIT_PRINTING);
if (modify & PRT_CMD_START_CARRIAGE)
SETBIT(uptr->flags, UNIT_SKIPPING);
if (modify & PRT_CMD_STOP_CARRIAGE)
CLRBIT(uptr->flags, UNIT_SKIPPING);
if (modify & PRT_CMD_SPACE)
SETBIT(uptr->flags, UNIT_SPACING);
sim_cancel(uptr);
if (uptr->flags & PRT_CMD_MASK) { // busy bit = doing something
SETBIT(prt_dsw, PRT_DSW_PRINTER_BUSY);
sim_activate(uptr, prt_cwait);
}
else
CLRBIT(prt_dsw, PRT_DSW_PRINTER_BUSY);
if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING))
SETBIT(prt_dsw, PRT_DSW_CARRIAGE_BUSY);
else
CLRBIT(prt_dsw, PRT_DSW_CARRIAGE_BUSY);
if ((uptr->flags & (UNIT_SKIPPING|UNIT_SPACING)) == (UNIT_SKIPPING|UNIT_SPACING)) {
sprintf(msg, "1132 printer skip and space at same time?");
xio_error(msg);
}
break;
default:
sprintf(msg, "Invalid 1132 printer XIO function %x", func);
xio_error(msg);
}
}
#define SET_ACTION(u,a) {(u)->flags &= ~(UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING); (u)->flags |= a;}
static t_stat prt_svc (UNIT *uptr)
{
if (prt_dsw & PRT_DSW_NOT_READY) { // cancel operation if printer went offline
SETBIT(uptr->flags, UNIT_FORMCHECK);
SET_ACTION(uptr, 0);
forms_check(TRUE); // and turn on forms check lamp
return SCPE_OK;
}
if (uptr->flags & UNIT_SPACING) {
flush_prt_line(uptr->fileref, TRUE);
prt_dsw = prt_dsw & ~PRT_DSW_CHANNEL_MASK;
prt_dsw |= cctape[prt_row];
SETBIT(prt_dsw, PRT_DSW_SPACE_RESPONSE);
SETBIT(ILSW[1], ILSW_1_1132_PRINTER);
calc_ints();
CLRBIT(uptr->flags, UNIT_SPACING); // done with this
CLRBIT(prt_dsw, PRT_DSW_PRINTER_BUSY|PRT_DSW_CARRIAGE_BUSY);
}
if (uptr->flags & UNIT_SKIPPING) {
do {
flush_prt_line(uptr->fileref, TRUE);
prt_dsw = (prt_dsw & ~PRT_DSW_CHANNEL_MASK) | cctape[prt_row];
} while (cctape[prt_row] == 0); // slew directly to a cc tape punch
SETBIT(prt_dsw, PRT_DSW_SKIP_RESPONSE);
SETBIT(ILSW[1], ILSW_1_1132_PRINTER);
calc_ints();
}
if (uptr->flags & UNIT_PRINTING) {
if (! save_prt_line(codewheel1132[prt_nchar].ascii)) { // save previous printed line
SETBIT(uptr->flags, UNIT_DATACHECK); // buffer wasn't set in time
SET_ACTION(uptr, 0);
print_check(TRUE); // and turn on forms check lamp
return SCPE_OK;
}
prt_nchar = (prt_nchar + 1) % WHEELCHARS; // advance print drum
SETBIT(prt_dsw, PRT_DSW_READ_EMITTER_RESPONSE); // issue interrupt to tell printer to set buffer
SETBIT(ILSW[1], ILSW_1_1132_PRINTER); // we'll save the printed stuff just before next emitter response (later than on real 1130)
calc_ints();
}
if (uptr->flags & (UNIT_SPACING|UNIT_SKIPPING|UNIT_PRINTING)) { // still doing something
SETBIT(prt_dsw, PRT_DSW_PRINTER_BUSY);
sim_activate(uptr, prt_cwait);
}
else
CLRBIT(prt_dsw, PRT_DSW_PRINTER_BUSY);
return SCPE_OK;
}
static t_stat prt_reset (DEVICE *dptr)
{
UNIT *uptr = &prt_unit[0];
int i;
sim_cancel(uptr);
memset(cctape, 0, sizeof(cctape)); // copy punch list into carriage control tape image
for (i = 0; i < (sizeof(ccpunches)/sizeof(ccpunches[0])); i++)
cctape[ccpunches[i].row-1] |= ccpunches[i].channels;
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK);
SET_ACTION(uptr, 0);
calc_ints();
prt_nchar = 0;
prt_row = 0;
prt_nnl = 0;
prt_dsw = cctape[prt_row];
reset_prt_line();
if (! IS_ONLINE(uptr))
SETBIT(prt_dsw, PRT_DSW_NOT_READY);
forms_check(FALSE);
return SCPE_OK;
}
static t_stat prt_attach (UNIT *uptr, char *cptr)
{
t_stat rval;
if (uptr->flags & UNIT_ATT) {
if ((rval = prt_detach(uptr)) != SCPE_OK) {
prt_dsw |= PRT_DSW_NOT_READY;
return rval;
}
}
sim_cancel(uptr);
if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) {
prt_dsw |= PRT_DSW_NOT_READY;
return rval;
}
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK);
SET_ACTION(uptr, 0);
calc_ints();
prt_nchar = 0;
prt_nnl = 0;
prt_row = 0;
prt_dsw = (prt_dsw & ~PRT_DSW_CHANNEL_MASK) | cctape[prt_row];
if (IS_ONLINE(uptr))
CLRBIT(prt_dsw, PRT_DSW_NOT_READY);
else
SETBIT(prt_dsw, PRT_DSW_NOT_READY);
reset_prt_line();
forms_check(FALSE);
return SCPE_OK;
}
static t_stat prt_detach (UNIT *uptr)
{
t_stat rval;
flush_prt_line(uptr->fileref, FALSE);
if ((rval = detach_unit(uptr)) != SCPE_OK)
return rval;
sim_cancel(uptr);
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK);
SET_ACTION(uptr, 0);
calc_ints();
SETBIT(prt_dsw, PRT_DSW_NOT_READY);
forms_check(FALSE);
return SCPE_OK;
}