1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-19 17:38:13 +00:00

SEL32: Correct carriage control operations

This commit is contained in:
James C. Bevier 2019-07-17 21:39:18 -04:00 committed by Richard Cornwell
parent d9283178d9
commit 3fde270ca3

View File

@ -75,391 +75,418 @@ P00070 20 DATAB C' ' 0x20 FORMS CONTROL FO
*/
#ifdef NUM_DEVS_LPR
#define UNIT_LPR UNIT_ATTABLE | UNIT_DISABLE
#define UNIT_LPR UNIT_ATTABLE | UNIT_DISABLE
extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
extern t_stat show_dev_addr(FILE *st, UNIT * uptr, int32 v, CONST void *desc);
extern void chan_end(uint16 chan, uint8 flags);
extern int chan_read_byte(uint16 chan, uint8 *data);
extern int chan_write_byte(uint16 chan, uint8 *data);
extern void set_devattn(uint16 addr, uint8 flags);
extern t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
extern t_stat show_dev_addr(FILE *st, UNIT * uptr, int32 v, CONST void *desc);
extern void chan_end(uint16 chan, uint8 flags);
extern int chan_read_byte(uint16 chan, uint8 *data);
extern int chan_write_byte(uint16 chan, uint8 *data);
extern void set_devattn(uint16 addr, uint8 flags);
/* u3 hold command and status information */
#define LPR_INCH 0x00 /* INCH command */
#define LPR_INCH 0x00 /* INCH command */
/* print buffer then CC commands */
#define LPR_PBNCC 0x01 /* print only, no forms control */
#define LPR_PBC 0x05 /* print buffer, then <CR> */
#define LPR_PBL 0x15 /* print buffer, then <LF> */
#define LPR_PBLL 0x25 /* print buffer, then <LF> <LF> */
#define LPR_PBLLL 0x35 /* print buffer, then <LF> <LF> <LF> */
#define LPR_PBF 0x45 /* print buffer, then <FF> */
#define LPR_PBCCB 0x85 /* print buffer, then <CR> <CLEAR BUFFER> */
/* Do CC then print commands then CC */
#define LPR_CPBC 0x0d /* <CR> print buffer <CR> */
#define LPR_LPBC 0x1d /* <LF> print buffer <CR> */
#define LPR_LLPBC 0x2d /* <LF> <LF> print buffer <CR> */
#define LPR_LLLPBC 0x3d /* <LF> <LF> <LF> print buffer <CR> */
#define LPR_FPBC 0x4d /* <FF> print buffer <CR> */
/* Do CC only, no print */
#define LPR_NPC 0x03 /* <CR> */
#define LPR_NPL 0x17 /* <LF> */
#define LPR_NPLL 0x27 /* <LF> <LF> */
#define LPR_NPLLL 0x37 /* <LF> <LF> <LF> */
#define LPR_NPF 0x47 /* <FF> */
#define LPR_PBNCC 0x01 /* print only, no forms control */
#define LPR_PBC 0x05 /* print buffer, then <CR> */
#define LPR_PBL 0x15 /* print buffer, then <LF> */
#define LPR_PBLL 0x25 /* print buffer, then <LF> <LF> */
#define LPR_PBLLL 0x35 /* print buffer, then <LF> <LF> <LF> */
#define LPR_PBF 0x45 /* print buffer, then <FF> */
#define LPR_PBCCB 0x85 /* print buffer, then <CR> <CLEAR BUFFER> */
/* Do CC then print commands then CC */
#define LPR_CPBC 0x0d /* <CR> print buffer <CR> */
#define LPR_LPBC 0x1d /* <LF> print buffer <CR> */
#define LPR_LLPBC 0x2d /* <LF> <LF> print buffer <CR> */
#define LPR_LLLPBC 0x3d /* <LF> <LF> <LF> print buffer <CR> */
#define LPR_FPBC 0x4d /* <FF> print buffer <CR> */
/* Do CC only, no print */
#define LPR_NPC 0x03 /* <CR> */
#define LPR_NPL 0x17 /* <LF> */
#define LPR_NPLL 0x27 /* <LF> <LF> */
#define LPR_NPLLL 0x37 /* <LF> <LF> <LF> */
#define LPR_NPF 0x47 /* <FF> */
#define LPR_SNS 0x04 /* Sense command */
#define LPR_CMDMSK 0xff /* Mask command part. */
#define LPR_FULL 0x100 /* Buffer full (BOF) */
#define LPR_PRE 0x200 /* Apply pre CC */
#define LPR_POST 0x400 /* Apply post CC */
#define LPR_SNS 0x04 /* Sense command */
#define LPR_CMDMSK 0xff /* Mask command part. */
#define LPR_FULL 0x100 /* Buffer full (BOF) */
#define LPR_PRE 0x200 /* Apply pre CC */
#define LPR_POST 0x400 /* Apply post CC */
/* u4 holds current line */
/* in u5 packs sense byte 0,1 and 3 */
/* Sense byte 0 */
#define SNS_CMDREJ 0x80 /* Command reject */
#define SNS_INTVENT 0x40 /* Unit intervention required */
#define SNS_BUSCHK 0x20 /* Parity error on bus */
#define SNS_EQUCHK 0x10 /* Equipment check */
#define SNS_DATCHK 0x08 /* Data Check */
#define SNS_OVRRUN 0x04 /* Data overrun */
#define SNS_SEQUENCE 0x02 /* Unusual sequence */
#define SNS_BOF 0x01 /* BOF on printer */
#define SNS_CMDREJ 0x80 /* Command reject */
#define SNS_INTVENT 0x40 /* Unit intervention required */
#define SNS_BUSCHK 0x20 /* Parity error on bus */
#define SNS_EQUCHK 0x10 /* Equipment check */
#define SNS_DATCHK 0x08 /* Data Check */
#define SNS_OVRRUN 0x04 /* Data overrun */
#define SNS_SEQUENCE 0x02 /* Unusual sequence */
#define SNS_BOF 0x01 /* BOF on printer */
/* u6 hold buffer position */
/* std devices. data structures
lpr_dev Line Printer device descriptor
lpr_unit Line Printer unit descriptor
lpr_reg Line Printer register list
lpr_mod Line Printer modifiers list
lpr_dev Line Printer device descriptor
lpr_unit Line Printer unit descriptor
lpr_reg Line Printer register list
lpr_mod Line Printer modifiers list
*/
struct _lpr_data
{
uint8 lbuff[160]; /* Output line buffer */
uint8 lbuff[160]; /* Output line buffer */
}
lpr_data[NUM_DEVS_LPR];
uint8 lpr_startcmd(UNIT *, uint16, uint8);
void lpr_ini(UNIT *, t_bool);
t_stat lpr_srv(UNIT *);
t_stat lpr_reset(DEVICE *);
t_stat lpr_attach(UNIT *, CONST char *);
t_stat lpr_detach(UNIT *);
t_stat lpr_setlpp(UNIT *, int32, CONST char *, void *);
t_stat lpr_getlpp(FILE *, UNIT *, int32, CONST void *);
uint8 lpr_startcmd(UNIT *, uint16, uint8);
void lpr_ini(UNIT *, t_bool);
t_stat lpr_srv(UNIT *);
t_stat lpr_reset(DEVICE *);
t_stat lpr_attach(UNIT *, CONST char *);
t_stat lpr_detach(UNIT *);
t_stat lpr_setlpp(UNIT *, int32, CONST char *, void *);
t_stat lpr_getlpp(FILE *, UNIT *, int32, CONST void *);
/* channel program information */
CHANP lpr_chp[NUM_DEVS_LPR] = {0};
CHANP lpr_chp[NUM_DEVS_LPR] = {0};
MTAB lpr_mod[] = {
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE",
&lpr_setlpp, &lpr_getlpp, NULL, "Number of lines per page"},
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr,
&show_dev_addr, NULL},
{0}
MTAB lpr_mod[] = {
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE",
&lpr_setlpp, &lpr_getlpp, NULL, "Number of lines per page"},
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr,
&show_dev_addr, NULL},
{0}
};
UNIT lpr_unit[] = {
{UDATA(lpr_srv, UNIT_LPR, 55), 300, UNIT_ADDR(0x7EF8)}, /* A */
UNIT lpr_unit[] = {
{UDATA(lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF8)}, /* A */
#if NUM_DEVS_LPR > 1
{UDATA(lpr_srv, UNIT_LPR, 55), 300, UNIT_ADDR(0x7EF9)}, /* B */
{UDATA(lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF9)}, /* B */
#endif
};
/* Device Information Block */
//DIB lpr_dib = {NULL, lpr_startcmd, NULL, NULL, lpr_ini, lpr_unit, lpr_chp, NUM_DEVS_LPR, 0xff, 0x7e00, 0, 0, 0};
DIB lpr_dib = {
NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */
lpr_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */
NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */
NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */
NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */
lpr_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */
lpr_unit, /* UNIT* units */ /* Pointer to units structure */
lpr_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */
NUM_DEVS_LPR, /* uint8 numunits */ /* number of units defined */
0xff, /* uint8 mask */ /* 2 devices - device mask */
0x7e00, /* uint16 chan_addr */ /* parent channel address */
0, /* uint32 chan_fifo_in */ /* fifo input index */
0, /* uint32 chan_fifo_out */ /* fifo output index */
0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */
DIB lpr_dib = {
NULL, /* uint8 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */
lpr_startcmd, /* uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start a command */
NULL, /* uint8 (*halt_io)(UNIT *uptr) */ /* Stop I/O */
NULL, /* uint8 (*test_io)(UNIT *uptr) */ /* Test I/O */
NULL, /* uint8 (*post_io)(UNIT *uptr) */ /* Post I/O */
lpr_ini, /* void (*dev_ini)(UNIT *, t_bool) */ /* init function */
lpr_unit, /* UNIT* units */ /* Pointer to units structure */
lpr_chp, /* CHANP* chan_prg */ /* Pointer to chan_prg structure */
NUM_DEVS_LPR, /* uint8 numunits */ /* number of units defined */
0xff, /* uint8 mask */ /* 2 devices - device mask */
0x7e00, /* uint16 chan_addr */ /* parent channel address */
0, /* uint32 chan_fifo_in */ /* fifo input index */
0, /* uint32 chan_fifo_out */ /* fifo output index */
0, /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */
};
DEVICE lpr_dev = {
"LPR", lpr_unit, NULL, lpr_mod,
NUM_DEVS_LPR, 8, 15, 1, 8, 8,
NULL, NULL, NULL, NULL, &lpr_attach, &lpr_detach,
&lpr_dib, DEV_UADDR | DEV_DISABLE | DEV_DEBUG, 0, dev_debug
DEVICE lpr_dev = {
"LPR", lpr_unit, NULL, lpr_mod,
NUM_DEVS_LPR, 8, 15, 1, 8, 8,
NULL, NULL, NULL, NULL, &lpr_attach, &lpr_detach,
&lpr_dib, DEV_UADDR | DEV_DISABLE | DEV_DEBUG, 0, dev_debug
};
/* initialize the line printer */
void lpr_ini(UNIT *uptr, t_bool f) {
/* do nothing for now */
/* do nothing for now */
}
/* start an I/O operation */
uint8 lpr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd)
{
uint8 ch;
uint8 ch;
if ((uptr->u3 & LPR_CMDMSK) != 0) { /* unit busy */
return SNS_BSY; /* yes, busy (already tested) */
}
if ((uptr->u3 & LPR_CMDMSK) != 0) { /* unit busy */
return SNS_BSY; /* yes, busy (already tested) */
}
uptr->u3 &= ~(LPR_POST|LPR_PRE); /* set no CC */
if (((cmd & 0x03) == 0x03) || (cmd & 0x0d) == 0x0d) {
uptr->u3 |= LPR_PRE; /* apply pre CC */
}
if (((cmd & 0x05) == 0x05) || (cmd & 0x0d) == 0x0d) {
uptr->u3 |= LPR_POST; /* apply post CC */
}
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd Cmd %02x\n", cmd);
uptr->u3 &= ~(LPR_POST|LPR_PRE); /* set no CC */
if (((cmd & 0x03) == 0x03) || (cmd & 0x0f) == 0x0d) {
uptr->u3 |= LPR_PRE; /* apply pre CC */
}
if (((cmd & 0x0f) == 0x05) || (cmd & 0x0f) == 0x0d) {
uptr->u3 |= LPR_POST; /* apply post CC */
}
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd Cmd %02x\n", cmd);
/* process the command */
switch (cmd & LPR_CMDMSK) {
case 0x00: /* INCH command */
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %x: Cmd INCH\n", chan);
return SNS_CHNEND|SNS_DEVEND; /* all is well */
break;
/* process the command */
switch (cmd & LPR_CMDMSK) {
case 0x00: /* INCH command */
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %x: Cmd INCH\n", chan);
return SNS_CHNEND|SNS_DEVEND; /* all is well */
break;
/* No CC */
case 0x01: /* print only, no forms control */
/* print buffer then CC commands */
case 0x05: /* print buffer, then <CR> */
case 0x15: /* print buffer, then <LF> */
case 0x25: /* print buffer, then <LF> <LF> */
case 0x35: /* print buffer, then <LF> <LF> <LF> */
case 0x45: /* print buffer, then <FF> */
case 0x85: /* print buffer, then <CR> <CLEAR BUFFER> */
/* Do CC then print commands then CC */
case 0x0d: /* <CR> print buffer <CR> */
case 0x1d: /* <LF> print buffer <CR> */
case 0x2d: /* <LF> <LF> print buffer <CR> */
case 0x3d: /* <LF> <LF> <LF> print buffer <CR> */
case 0x4d: /* <FF> print buffer <CR> */
/* Do CC only, no print */
case 0x03: /* <CR> */
case 0x17: /* <LF> */
case 0x27: /* <LF> <LF> */
case 0x37: /* <LF> <LF> <LF> */
case 0x47: /* <FF> */
/* process the command */
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %x: Cmd %x print\n", chan, cmd&LPR_CMDMSK);
uptr->u3 &= ~(LPR_CMDMSK); /* zero cmd */
uptr->u3 |= (cmd & LPR_CMDMSK); /* save new command in u3 */
sim_activate(uptr, 10); /* Start unit off */
uptr->u5 = 0; /* no status */
uptr->u6 = 0; /* start of buffer */
return 0; /* we are good to go */
/* No CC */
case 0x01: /* print only, no forms control */
/* print buffer then CC commands */
case 0x05: /* print buffer, then <CR> */
case 0x15: /* print buffer, then <LF> */
case 0x25: /* print buffer, then <LF> <LF> */
case 0x35: /* print buffer, then <LF> <LF> <LF> */
case 0x45: /* print buffer, then <FF> */
case 0x85: /* print buffer, then <CR> <CLEAR BUFFER> */
/* Do CC then print commands then CC */
case 0x0d: /* <CR> print buffer <CR> */
case 0x1d: /* <LF> print buffer <CR> */
case 0x2d: /* <LF> <LF> print buffer <CR> */
case 0x3d: /* <LF> <LF> <LF> print buffer <CR> */
case 0x4d: /* <FF> print buffer <CR> */
/* Do CC only, no print */
case 0x03: /* <CR> */
case 0x17: /* <LF> */
case 0x27: /* <LF> <LF> */
case 0x37: /* <LF> <LF> <LF> */
case 0x47: /* <FF> */
/* process the command */
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %x: Cmd %x print\n", chan, cmd&LPR_CMDMSK);
uptr->u3 &= ~(LPR_CMDMSK); /* zero cmd */
uptr->u3 |= (cmd & LPR_CMDMSK); /* save new command in u3 */
sim_activate(uptr, 100); /* Start unit off */
uptr->u5 = 0; /* no status */
uptr->u6 = 0; /* start of buffer */
return 0; /* we are good to go */
case 0x4: /* Sense Status */
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %x: Cmd %x sense\n", chan, cmd&LPR_CMDMSK);
uptr->u3 &= ~(LPR_CMDMSK); /* zero cmd */
uptr->u3 |= (cmd & LPR_CMDMSK); /* save new command in u3 */
sim_activate(uptr, 10); /* Start unit off */
uptr->u5 = 0; /* no status */
uptr->u6 = 0; /* start of buffer */
return 0; /* we are good to go */
case 0x4: /* Sense Status */
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %x: Cmd %x sense\n", chan, cmd&LPR_CMDMSK);
uptr->u3 &= ~(LPR_CMDMSK); /* zero cmd */
uptr->u3 |= (cmd & LPR_CMDMSK); /* save new command in u3 */
sim_activate(uptr, 100); /* Start unit off */
uptr->u5 = 0; /* no status */
uptr->u6 = 0; /* start of buffer */
return 0; /* we are good to go */
default: /* invalid command */
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %x: Cmd %x INVALID \r\n", chan, cmd&LPR_CMDMSK);
uptr->u5 |= SNS_CMDREJ;
break;
}
if (uptr->u5 & 0xff)
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
return SNS_CHNEND|SNS_DEVEND;
default: /* invalid command */
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %x: Cmd %x INVALID \r\n", chan, cmd&LPR_CMDMSK);
uptr->u5 |= SNS_CMDREJ;
break;
}
if (uptr->u5 & 0xff)
return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK;
return SNS_CHNEND|SNS_DEVEND;
}
/* Handle transfer of data for printer */
t_stat lpr_srv(UNIT *uptr) {
int chsa = GET_UADDR(uptr->u3);
int u = (uptr - lpr_unit);
int cmd = (uptr->u3 & 0xff);
int chsa = GET_UADDR(uptr->u3);
int u = (uptr - lpr_unit);
int cmd = (uptr->u3 & 0xff);
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_srv called chsa %x cmd %x u3 %x cnt %x\r\n", chsa, cmd, uptr->u3, uptr->u6);
sim_debug(DEBUG_CMD, &lpr_dev, "lpr_srv called chsa %x cmd %x u3 %x cnt %x\r\n", chsa, cmd, uptr->u3, uptr->u6);
/* FIXME, need IOP lp status bit assignments */
if (cmd == 0x04) { /* sense? */
uint8 ch = uptr->u5; /* get current status */
uptr->u3 &= ~(LPR_CMDMSK); /* clear command */
chan_write_byte(chsa, &ch); /* write the status to memory */
uptr->u6 = 0; /* reset to beginning of buffer */
chan_end(chsa, SNS_DEVEND|SNS_CHNEND); /* we are done */
return SCPE_OK;
}
/* FIXME, need IOP lp status bit assignments */
if (cmd == 0x04) { /* sense? */
uint8 ch = uptr->u5; /* get current status */
uptr->u3 &= ~(LPR_CMDMSK); /* clear command */
chan_write_byte(chsa, &ch); /* write the status to memory */
uptr->u6 = 0; /* reset to beginning of buffer */
chan_end(chsa, SNS_DEVEND|SNS_CHNEND); /* we are done */
return SCPE_OK;
}
/* process any CC before printing buffer */
if ((uptr->u3 & LPR_PRE) && (((cmd & 0x03) == 0x03) || (cmd & 0x0d) == 0x0d)) {
uptr->u3 &= ~LPR_PRE; /* remove pre flag */
/* we have CC to do */
switch ((cmd & 0xf0) >> 4) {
case 0: /* <CR> (0x0d) */
lpr_data[u].lbuff[uptr->u6++] = 0x0d;
break;
case 3: /* <LF> <LF> <LF> */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
uptr->u4++; /* increment the line count */
/* drop thru */
case 2: /* <LF> <LF> */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
uptr->u4++; /* increment the line count */
/* drop thru */
case 1: /* <LF> (0x0a) */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
uptr->u4++; /* increment the line count */
break;
case 4: /* <FF> (0x0c) */
lpr_data[u].lbuff[uptr->u6++] = 0x0c;
uptr->u4 = 0; /* restart line count */
break;
}
}
/* process any CC before printing buffer */
if ((uptr->u3 & LPR_PRE) && (((cmd & 0x03) == 0x03) || (cmd & 0x0f) == 0x0d)) {
uptr->u3 &= ~LPR_PRE; /* remove pre flag */
/* we have CC to do */
switch ((cmd & 0xf0) >> 4) {
case 0: /* <CR> (0x0d) */
lpr_data[u].lbuff[uptr->u6++] = 0x0d;
break;
case 3: /* <LF> <LF> <LF> */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
uptr->u4++; /* increment the line count */
/* drop thru */
case 2: /* <LF> <LF> */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
uptr->u4++; /* increment the line count */
/* drop thru */
case 1: /* <LF> (0x0a) */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
uptr->u4++; /* increment the line count */
break;
case 4: /* <FF> (0x0c) */
lpr_data[u].lbuff[uptr->u6++] = 0x0d; /* add C/R */
lpr_data[u].lbuff[uptr->u6++] = 0x0a; /* add L/F */
lpr_data[u].lbuff[uptr->u6++] = 0x0c; /* add FF */
uptr->u4 = 0; /* restart line count */
break;
}
}
/* Copy next byte from users buffer */
if ((uptr->u3 & LPR_FULL) == 0) { /* copy in a char if not full */
if(chan_read_byte(chsa, &lpr_data[u].lbuff[uptr->u6])) {
uptr->u3 |= LPR_FULL; /* end of buffer or error */
} else {
sim_activate(uptr, 20); /* got a char, wait for a while */
uptr->u6++; /* next buffer loc */
return SCPE_OK; /* done til next char */
}
}
#ifdef OLDWAY
/* Copy next byte from users buffer */
if ((uptr->u3 & LPR_FULL) == 0) { /* copy in a char if not full */
if(chan_read_byte(chsa, &lpr_data[u].lbuff[uptr->u6])) {
uptr->u3 |= LPR_FULL; /* end of buffer or error */
} else {
sim_activate(uptr, 20); /* got a char, wait for a while */
uptr->u6++; /* next buffer loc */
return SCPE_OK; /* done til next char */
}
}
#else
/* Copy next byte from users buffer */
while ((uptr->u3 & LPR_FULL) == 0) { /* copy in a char if not full */
if(chan_read_byte(chsa, &lpr_data[u].lbuff[uptr->u6])) {
uptr->u3 |= LPR_FULL; /* end of buffer or error */
break; /* done reading */
} else {
uptr->u6++; /* next buffer loc */
}
}
#endif
/* process any CC after printing buffer */
if ((uptr->u3 & LPR_FULL) && (uptr->u3 & LPR_POST) && ((cmd & 0x0d) == 0x0d)) {
/* we have CC to do */
uptr->u3 &= ~LPR_POST; /* remove post flag */
lpr_data[u].lbuff[uptr->u6++] = 0x0d; /* just a <CR> */
}
/* process any CC after printing buffer */
if ((uptr->u3 & LPR_FULL) && (uptr->u3 & LPR_POST) && ((cmd & 0x0f) == 0x0d)) {
/* we have CC to do */
uptr->u3 &= ~LPR_POST; /* remove post flag */
lpr_data[u].lbuff[uptr->u6++] = 0x0d; /* just a <CR> */
}
/* process any CC after printing buffer */
if ((uptr->u3 & LPR_FULL) && (uptr->u3 & LPR_POST) && ((cmd & 0x05) == 0x05)) {
/* we have CC to do */
uptr->u3 &= ~LPR_POST; /* remove post flag */
switch ((cmd & 0xf0) >> 4) {
case 0: /* <CR> (0x0d) */
lpr_data[u].lbuff[uptr->u6++] = 0x0d;
break;
case 3: /* <LF> <LF> <LF> */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
/* drop thru */
case 2: /* <LF> <LF> */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
/* drop thru */
case 1: /* <LF> (0x0a) */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
break;
case 4: /* <FF> (0x0c) */
lpr_data[u].lbuff[uptr->u6++] = 0x0c;
uptr->u4 = 0; /* restart line count */
break;
}
}
/* process any CC after printing buffer */
if ((uptr->u3 & LPR_FULL) && (uptr->u3 & LPR_POST) && ((cmd & 0x0f) == 0x05)) {
/* we have CC to do */
uptr->u3 &= ~LPR_POST; /* remove post flag */
switch ((cmd & 0xf0) >> 4) {
case 0: /* <CR> (0x0d) */
lpr_data[u].lbuff[uptr->u6++] = 0x0d;
break;
case 3: /* <LF> <LF> <LF> */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
uptr->u4++; /* increment the line count */
/* drop thru */
case 2: /* <LF> <LF> */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
uptr->u4++; /* increment the line count */
/* drop thru */
case 1: /* <LF> (0x0a) */
lpr_data[u].lbuff[uptr->u6++] = 0x0a;
uptr->u4++; /* increment the line count */
break;
case 4: /* <FF> (0x0c) */
lpr_data[u].lbuff[uptr->u6++] = 0x0d; /* add C/R */
lpr_data[u].lbuff[uptr->u6++] = 0x0a; /* add L/F */
lpr_data[u].lbuff[uptr->u6++] = 0x0c; /* add FF */
uptr->u4 = 0; /* restart line count */
break;
}
}
/* print the line if buffer is full */
if (uptr->u3 & LPR_FULL || uptr->u6 >= 156) {
lpr_data[u].lbuff[uptr->u6] = 0x00; /* NULL terminate */
sim_fwrite(&lpr_data[u].lbuff, 1, uptr->u6, uptr->fileref); /* Print our buffer */
sim_debug(DEBUG_DETAIL, &lpr_dev, "LPR %s", &lpr_data[u].lbuff);
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK); /* clear old status */
uptr->u6 = 0; /* start at beginning of buffer */
uptr->u4++; /* increment the line count */
if (uptr->u4 > uptr->capac) { /* see if at max lines/page */
uptr->u4 = 0; /* yes, restart count */
chan_end(chsa, SNS_DEVEND|SNS_CHNEND|SNS_UNITEXP); /* we are done */
} else
chan_end(chsa, SNS_DEVEND|SNS_CHNEND); /* we are done */
sim_activate(uptr, 3000); /* wait a long time for next look */
return SCPE_OK;
}
/* print the line if buffer is full */
if (uptr->u3 & LPR_FULL || uptr->u6 >= 156) {
lpr_data[u].lbuff[uptr->u6] = 0x00; /* NULL terminate */
sim_fwrite(&lpr_data[u].lbuff, 1, uptr->u6, uptr->fileref); /* Print our buffer */
sim_debug(DEBUG_DETAIL, &lpr_dev, "LPR %s", &lpr_data[u].lbuff);
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK); /* clear old status */
uptr->u6 = 0; /* start at beginning of buffer */
uptr->u4++; /* increment the line count */
if (uptr->u4 > uptr->capac) { /* see if at max lines/page */
uptr->u4 = 0; /* yes, restart count */
chan_end(chsa, SNS_DEVEND|SNS_CHNEND|SNS_UNITEXP); /* we are done */
} else
chan_end(chsa, SNS_DEVEND|SNS_CHNEND); /* we are done */
#if 0 /* done, so no time out */
#ifdef OLDWAY
sim_activate(uptr, 3000); /* wait a long time for next look */
#else
/* 600 lpm lp does 10 lines / sec, so 100ms wait*/
sim_activate(uptr, 100); /* wait a time for next look */
#endif
#endif
return SCPE_OK;
}
sim_activate(uptr, 20); /* got a char, wait for a while */
return SCPE_OK;
/* should not get here */
sim_activate(uptr, 20); /* got a char, wait for a while */
return SCPE_OK;
}
/* print a line to the "printer" */
void print_line(UNIT *uptr)
{
char out[150]; /* Temp conversion buffer */
int i;
int u = (uptr - lpr_unit);
char out[150]; /* Temp conversion buffer */
int i;
int u = (uptr - lpr_unit);
/* Try to convert to text */
memset(out, ' ', sizeof(out));
/* Try to convert to text */
memset(out, ' ', sizeof(out));
/* Scan each column */
for (i = 0; i < uptr->u6; i++) {
int ch = lpr_data[u].lbuff[i];
/* Scan each column */
for (i = 0; i < uptr->u6; i++) {
int ch = lpr_data[u].lbuff[i];
if (!isprint(ch)) /* make sure char is printable */
ch = '.'; /* not printable, make it a '.' */
out[i] = ch; /* save to buffer */
}
if (!isprint(ch)) /* make sure char is printable */
ch = '.'; /* not printable, make it a '.' */
out[i] = ch; /* save to buffer */
}
for (--i; i > 0 && out[i] == ' '; i--) /* Trim trailing spaces */
;
out[++i] = '\r'; /* output CR, LF. NULL */
out[++i] = '\n';
out[++i] = '\0';
for (--i; i > 0 && out[i] == ' '; i--) /* Trim trailing spaces */
;
out[++i] = '\r'; /* output CR, LF. NULL */
out[++i] = '\n';
out[++i] = '\0';
sim_fwrite(&out, 1, i, uptr->fileref); /* Print our buffer */
sim_debug(DEBUG_DETAIL, &lpr_dev, "%s", out);
sim_fwrite(&out, 1, i, uptr->fileref); /* Print our buffer */
sim_debug(DEBUG_DETAIL, &lpr_dev, "%s", out);
memset(&lpr_data[u].lbuff[0], 0, 144); /* clear the output buffer */
memset(&lpr_data[u].lbuff[0], 0, 144); /* clear the output buffer */
}
/* Set the number of lines per page on printer */
t_stat lpr_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int i;
if (cptr == NULL)
return SCPE_ARG;
if (uptr == NULL)
return SCPE_IERR;
i = 0;
while(*cptr != '\0') {
if (*cptr < '0' || *cptr > '9')
return SCPE_ARG;
i = (i * 10) + (*cptr++) - '0';
}
if (i < 20 || i > 100)
return SCPE_ARG;
uptr->capac = i;
uptr->u4 = 0;
return SCPE_OK;
int i;
if (cptr == NULL)
return SCPE_ARG;
if (uptr == NULL)
return SCPE_IERR;
i = 0;
while(*cptr != '\0') {
if (*cptr < '0' || *cptr > '9')
return SCPE_ARG;
i = (i * 10) + (*cptr++) - '0';
}
if (i < 20 || i > 100)
return SCPE_ARG;
uptr->capac = i;
uptr->u4 = 0;
return SCPE_OK;
}
/* display the number of lines per page */
t_stat lpr_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc)
{
if (uptr == NULL)
return SCPE_IERR;
fprintf(st, "linesperpage=%d", uptr->capac);
return SCPE_OK;
if (uptr == NULL)
return SCPE_IERR;
fprintf(st, "linesperpage=%d", uptr->capac);
return SCPE_OK;
}
/* attach a file to the line printer device */
t_stat lpr_attach(UNIT * uptr, CONST char *file)
{
t_stat r;
t_stat r;
if ((r = attach_unit(uptr, file)) != SCPE_OK)
return r;
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
uptr->u4 = 0;
uptr->u5 = 0;
return SCPE_OK;
if ((r = attach_unit(uptr, file)) != SCPE_OK)
return r;
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
uptr->u4 = 0;
uptr->u5 = 0;
return SCPE_OK;
}
/* detach a file from the line printer */
t_stat lpr_detach(UNIT * uptr)
{
if (uptr->u3 & LPR_FULL)
print_line(uptr);
return detach_unit(uptr);
if (uptr->u3 & LPR_FULL)
print_line(uptr);
return detach_unit(uptr);
}
#endif