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:
parent
d9283178d9
commit
3fde270ca3
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user