home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Boot_Images / 2.11_on_rl02 / pdpsim.tz / pdpsim / pdp18b_lp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-29  |  15.7 KB  |  554 lines

  1. /* pdp18b_lp.c: 18b PDP's line printer simulator
  2.  
  3.    Copyright (c) 1994, 1996, Robert M Supnik, Digital Equipment Corporation
  4.    All rights reserved
  5.  
  6.    lpt        Type 62 line printer for the PDP-4
  7.         Type 647 line printer for the PDP-7 and PDP-9
  8.         LP15 line printer for the PDP-15
  9. */
  10.  
  11. #include "pdp18b_defs.h"
  12.  
  13. #if defined (TYPE62)
  14.  
  15. #define LPT_BSIZE    120                /* line size */
  16. extern int int_req;
  17. int lpt_iot = 0, lpt_stopioe = 0, bptr = 0;
  18. unsigned char lpt_buf[LPT_BSIZE] = { 0 };
  19.  
  20. int lpt_svc (UNIT *uptr);
  21. int lpt_reset (DEVICE *dptr);
  22. extern int sim_activate (UNIT *uptr, int interval);
  23. extern int sim_cancel (UNIT *uptr);
  24.  
  25. /* Type 62 LPT data structures
  26.  
  27.    lpt_dev    LPT device descriptor
  28.    lpt_unit    LPT unit
  29.    lpt_reg    LPT register list
  30. */
  31.  
  32. UNIT lpt_unit = {
  33.     UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
  34.  
  35. REG lpt_reg[] = {
  36.     { ORDATA (BUF, lpt_unit.buf, 8) },
  37.     { FLDATA (INT, int_req, INT_V_LPT) },
  38.     { FLDATA (DONE, int_req, INT_V_LPT) },
  39.     { FLDATA (SPC, int_req, INT_V_LPTSPC) },
  40.     { DRDATA (BPTR, bptr, 7) },
  41.     { ORDATA (SCMD, lpt_iot, 6), REG_HRO },
  42.     { DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
  43.     { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
  44.     { FLDATA (STOP_IOE, lpt_stopioe, 0) },
  45.     { BRDATA (**BUF, lpt_buf, 8, 8, LPT_BSIZE), REG_HRO },
  46.     { NULL }  };
  47.  
  48. DEVICE lpt_dev = {
  49.     "LPT", &lpt_unit, lpt_reg, NULL,
  50.     1, 10, 32, 1, 8, 8,
  51.     NULL, NULL, &lpt_reset,
  52.     NULL, NULL, NULL };
  53.  
  54. /* Type 62 line printer: IOT routines */
  55.  
  56. int lpt65 (int pulse, int AC)
  57. {
  58. static const unsigned char lpt_trans[64] = {
  59.     ' ','1','2','3','4','5','6','7','8','9','\'','~','#','V','^','<',
  60.     '0','/','S','T','U','V','W','X','Y','Z','"',',','>','^','-','?',
  61.     'o','J','K','L','M','N','O','P','Q','R','$','=','-',')','-','(',
  62.     '_','A','B','C','D','E','F','G','H','I','*','.','+',']','|','[' };
  63.  
  64. if (pulse == 001) return (int_req & INT_LPT)? IOT_SKP + AC: AC;    /* LPSF */
  65. if (pulse == 002) int_req = int_req & ~INT_LPT;        /* LPCF */
  66. else if (pulse == 042) {                /* LPLD */
  67.     if (bptr < LPT_BSIZE)                /* char 1 */
  68.         lpt_buf[bptr++] = lpt_trans[(AC >> 12) & 077];
  69.     if (bptr < LPT_BSIZE)                /* char 2 */
  70.         lpt_buf[bptr++] = lpt_trans[(AC >> 6) & 077];
  71.     if (bptr < LPT_BSIZE)                /* char 3 */
  72.         lpt_buf[bptr++] = lpt_trans[AC & 077];  }
  73. else if (pulse == 006) {                /* LPSE */
  74.     int_req = int_req & ~INT_LPT;            /* clear flag */
  75.     sim_activate (&lpt_unit, lpt_unit.wait);  }    /* activate */
  76. return AC;
  77. }
  78.  
  79. int lpt66 (int pulse, int AC)
  80. {
  81. if (pulse == 001) return (int_req & INT_LPTSPC)? IOT_SKP + AC: AC; /* LSSF */
  82. if (pulse & 002) int_req = int_req & ~INT_LPTSPC;    /* LSCF */
  83. if (pulse & 004) {                    /* LSPR */
  84.     int_req = int_req & ~INT_LPTSPC;        /* clear flag */
  85.     lpt_iot = 020 | (AC & 07);            /* space, no print */
  86.     sim_activate (&lpt_unit, lpt_unit.wait);  }    /* activate */
  87. return AC;
  88. }
  89.  
  90. /* Unit service, printer is in one of three states
  91.  
  92.    lpt_iot = 0        write buffer to file, set state to
  93.    lpt_iot = 10        write cr, then write buffer to file
  94.    lpt_iot = 2x        space command x, then set state to 0
  95. */
  96.  
  97. int lpt_svc (UNIT *uptr)
  98. {
  99. static const char *lpt_cc[] = {
  100.     "\n",
  101.     "\n\n",
  102.     "\n\n\n",
  103.     "\n\n\n\n\n\n",
  104.     "\n\n\n\n\n\n\n\n\n\n\n",
  105.     "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
  106.     "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
  107.     "\f" };
  108.  
  109. if (lpt_iot & 020) {                    /* space? */
  110.     int_req = int_req | INT_LPTSPC;            /* set flag */
  111.     if ((lpt_unit.flags & UNIT_ATT) == 0)        /* attached? */
  112.         return IORETURN (lpt_stopioe, SCPE_UNATT);
  113.     fputs (lpt_cc[lpt_iot & 07], lpt_unit.fileref);    /* print cctl */
  114.     if (ferror (lpt_unit.fileref)) {        /* error? */
  115.         perror ("LPT I/O error");
  116.         clearerr (lpt_unit.fileref);
  117.         return SCPE_IOERR;  }
  118.     lpt_unit.pos = lpt_unit.pos + strlen (lpt_cc[lpt_iot & 07]);
  119.     lpt_iot = 0;  }                    /* clear state */
  120. else {    int_req = int_req | INT_LPT;            /* print */
  121.     if ((lpt_unit.flags & UNIT_ATT) == 0)        /* attached? */
  122.         return IORETURN (lpt_stopioe, SCPE_UNATT);
  123.     if (lpt_iot & 10) fputc ('\r', lpt_unit.fileref);
  124.     fwrite (lpt_buf, 1, bptr, lpt_unit.fileref);    /* print buffer */
  125.     if (ferror (lpt_unit.fileref)) {        /* test error */
  126.         perror ("LPT I/O error");
  127.         clearerr (lpt_unit.fileref);
  128.         return SCPE_IOERR;  }
  129.     lpt_unit.pos = lpt_unit.pos + bptr + ((lpt_iot & 10) != 0);
  130.     bptr = 0;
  131.     lpt_iot = 010;  }                /* set state */
  132. return SCPE_OK;
  133. }
  134.  
  135. /* Reset routine */
  136.  
  137. int lpt_reset (DEVICE *dptr)
  138. {
  139. int i;
  140.  
  141. int_req = int_req & ~(INT_LPT + INT_LPTSPC);        /* clear flag, space */
  142. sim_cancel (&lpt_unit);                    /* deactivate unit */
  143. lpt_iot = 0;                        /* clear state */
  144. bptr = 0;                        /* clear buffer ptr */
  145. for (i = 0; i < LPT_BSIZE; i++) lpt_buf[i] = 0;        /* clear buffer */
  146. return SCPE_OK;
  147. }
  148.  
  149. /* IORS routine */
  150.  
  151. int lpt_iors (void)
  152. {
  153. return    ((int_req & INT_LPT)? IOS_LPT: 0) |
  154.     ((int_req & INT_LPTSPC)? IOS_LPT1: 0);
  155. }
  156.  
  157. #elif defined (TYPE647)
  158.  
  159. #define LPT_BSIZE    120                /* line size */
  160. extern int int_req;
  161. int lpt_done = 0, lpt_ie = 1, lpt_err = 0;
  162. int lpt_iot = 0, lpt_stopioe = 0, bptr = 0;
  163. unsigned char lpt_buf[LPT_BSIZE] = { 0 };
  164.  
  165. int lpt_svc (UNIT *uptr);
  166. int lpt_reset (DEVICE *dptr);
  167. int lpt_attach (UNIT *uptr, char *cptr);
  168. int lpt_detach (UNIT *uptr);
  169. extern int sim_activate (UNIT *uptr, int interval);
  170. extern int sim_cancel (UNIT *uptr);
  171. extern int attach_unit (UNIT *uptr, char *cptr);
  172. extern int detach_unit (UNIT *uptr);
  173.  
  174. /* Type 647 LPT data structures
  175.  
  176.    lpt_dev    LPT device descriptor
  177.    lpt_unit    LPT unit
  178.    lpt_reg    LPT register list
  179. */
  180.  
  181. UNIT lpt_unit = {
  182.     UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
  183.  
  184. REG lpt_reg[] = {
  185.     { ORDATA (BUF, lpt_unit.buf, 8) },
  186.     { FLDATA (INT, int_req, INT_V_LPT) },
  187.     { FLDATA (DONE, lpt_done, 0) },
  188. #if defined (PDP9)
  189.     { FLDATA (ENABLE, lpt_ie, 0) },
  190. #endif
  191.     { FLDATA (ERR, lpt_err, 0) },
  192.     { DRDATA (BPTR, bptr, 7) },
  193.     { ORDATA (SCMD, lpt_iot, 6), REG_HRO },
  194.     { DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
  195.     { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
  196.     { FLDATA (STOP_IOE, lpt_stopioe, 0) },
  197.     { BRDATA (**BUF, lpt_buf, 8, 8, LPT_BSIZE), REG_HRO },
  198.     { NULL }  };
  199.  
  200. DEVICE lpt_dev = {
  201.     "LPT", &lpt_unit, lpt_reg, NULL,
  202.     1, 10, 32, 1, 8, 8,
  203.     NULL, NULL, &lpt_reset,
  204.     NULL, &lpt_attach, &lpt_detach };
  205.  
  206. /* Type 647 line printer: IOT routines */
  207.  
  208. int lpt65 (int pulse, int AC)
  209. {
  210. int i;
  211.  
  212. if (pulse == 001) return (int_req & INT_LPT)? IOT_SKP + AC: AC;    /* LPSF */
  213. if (pulse & 002) {                    /* pulse 02 */
  214.     lpt_done = 0;                    /* clear done */
  215.     int_req = int_req & ~INT_LPT;  }        /* clear int req */
  216. if (pulse == 002) {                    /* LPCB */
  217.     for (i = 0; i = LPT_BSIZE; i++) lpt_buf[i] = 0;
  218.     bptr = 0;                    /* reset buf ptr */
  219.     lpt_done = 1;                    /* set done */
  220.     if (lpt_ie) int_req = int_req | INT_LPT;  }    /* set int */
  221. #if defined (PDP9)
  222. if (pulse == 004) {                    /* LPDI */
  223.     lpt_ie = 0;                    /* clear int enable */
  224.     int_req = int_req & ~INT_LPT;  }        /* clear int req */
  225. #endif
  226. if ((pulse == 046) && (bptr < LPT_BSIZE)) {        /* LPB3 */
  227.         lpt_buf[bptr] = lpt_buf[bptr] | ((AC >> 12) & 077);
  228.         bptr = bptr + 1;  }
  229. if (((pulse == 046) || (pulse == 026)) && (bptr < LPT_BSIZE)) {
  230.         lpt_buf[bptr] = lpt_buf[bptr] | ((AC >> 6) & 077);
  231.         bptr = bptr + 1;  }
  232. if ((pulse == 046) || (pulse == 026) || (pulse == 066)) {
  233.     if (bptr < LPT_BSIZE) {
  234.         lpt_buf[bptr] = lpt_buf[bptr] | (AC & 077);
  235.         bptr = bptr + 1;  }
  236.     lpt_done = 1;                    /* set done */
  237.     if (lpt_ie) int_req = int_req | INT_LPT;  }    /* set int */
  238. return AC;
  239. }
  240.  
  241. int lpt66 (int pulse, int AC)
  242. {
  243. if (pulse == 001) return lpt_err? IOT_SKP + AC: AC;    /* LPSE */
  244. if (pulse & 002) {                    /* LPCF */
  245.     lpt_done = 0;                    /* clear done, int */
  246.     int_req = int_req & ~INT_LPT;  }
  247. if (((pulse & 060) < 060) && (pulse & 004)) {        /* LPLS, LPPB, LPPS */
  248.     lpt_iot = (pulse & 060) | (AC & 07);        /* save parameters */
  249.     sim_activate (&lpt_unit, lpt_unit.wait);  }    /* activate */
  250. #if defined (PDP9)
  251. if (pulse == 064) {                    /* LPEI */
  252.     lpt_ie = 1;                    /* set int enable */
  253.     if (lpt_done) int_req = int_req | INT_LPT;  }
  254. #endif
  255. return AC;
  256. }
  257.  
  258. /* Unit service.  lpt_iot specifies the action to be taken
  259.  
  260.    lpt_iot = 0x        print only
  261.    lpt_iot = 2x        space only, x is spacing command
  262.    lpt_iot = 4x        print then space, x is spacing command
  263. */
  264.  
  265. int lpt_svc (UNIT *uptr)
  266. {
  267. int i;
  268. char pbuf[LPT_BSIZE + 1];
  269. static const char *lpt_cc[] = {
  270.     "\n",
  271.     "\n\n",
  272.     "\n\n\n",
  273.     "\n\n\n\n\n\n",
  274.     "\n\n\n\n\n\n\n\n\n\n\n",
  275.     "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
  276.     "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
  277.     "\f" };
  278.  
  279. lpt_done = 1;
  280. if (lpt_ie) int_req = int_req | INT_LPT;        /* set flag */
  281. if ((lpt_unit.flags & UNIT_ATT) == 0) {            /* not attached? */
  282.     lpt_err = 1;                    /* set error */
  283.     return IORETURN (lpt_stopioe, SCPE_UNATT);  }
  284. if ((lpt_iot & 020) == 0) {                /* print? */
  285.     for (i = 0; i < bptr; i++)             /* translate buffer */
  286.         pbuf[i] = lpt_buf[i] | ((lpt_buf[i] >= 040)? 0: 0100);
  287.     if ((lpt_iot & 060) == 0) pbuf[bptr++] = '\r';
  288.     for (i = 0; i < LPT_BSIZE; i++) lpt_buf[i] = 0;    /* clear buffer */
  289.     fwrite (pbuf, 1, bptr, lpt_unit.fileref);    /* print buffer */
  290.     if (ferror (lpt_unit.fileref)) {        /* error? */
  291.         perror ("LPT I/O error");
  292.         clearerr (lpt_unit.fileref);
  293.         bptr = 0;
  294.         return SCPE_IOERR;  }
  295.     lpt_unit.pos = lpt_unit.pos + bptr;
  296.     bptr = 0;  }                    /* clear buffer ptr */
  297. if (lpt_iot & 060) {                    /* space? */
  298.     fputs (lpt_cc[lpt_iot & 07], lpt_unit.fileref);    /* write cctl */
  299.     if (ferror (lpt_unit.fileref)) {        /* error? */
  300.         perror ("LPT I/O error");
  301.         clearerr (lpt_unit.fileref);
  302.         return SCPE_IOERR;  }
  303.     lpt_unit.pos = lpt_unit.pos + strlen (lpt_cc[lpt_iot & 07]);  }
  304. return SCPE_OK;
  305. }
  306.  
  307. /* Reset routine */
  308.  
  309. int lpt_reset (DEVICE *dptr)
  310. {
  311. int i;
  312.  
  313. lpt_done = 0;                        /* clear done */
  314. lpt_err = (lpt_unit.flags & UNIT_ATT)? 0: 1;        /* compute error */
  315. lpt_ie = 1;                        /* set enable */
  316. int_req = int_req & ~INT_LPT;                /* clear int */
  317. sim_cancel (&lpt_unit);                    /* deactivate unit */
  318. bptr = 0;                        /* clear buffer ptr */
  319. lpt_iot = 0;                        /* clear state */
  320. for (i = 0; i < LPT_BSIZE; i++) lpt_buf[i] = 0;        /* clear buffer */
  321. return SCPE_OK;
  322. }
  323.  
  324. /* IORS routine */
  325.  
  326. int lpt_iors (void)
  327. {
  328. return    (lpt_done? IOS_LPT: 0) | (lpt_err? IOS_LPT1: 0);
  329. }
  330.  
  331. /* Attach routine */
  332.  
  333. int lpt_attach (UNIT *uptr, char *cptr)
  334. {
  335. int reason;
  336.  
  337. reason = attach_unit (uptr, cptr);
  338. lpt_err = (lpt_unit.flags & UNIT_ATT)? 0: 1;        /* compute error */
  339. return reason;
  340. }
  341.  
  342. /* Detach routine */
  343.  
  344. int lpt_detach (UNIT *uptr)
  345. {
  346. lpt_err = 1;
  347. return detach_unit (uptr);
  348. }
  349.  
  350. #elif defined (LP15)
  351.  
  352. #define LPT_BSIZE    132                /* line size */
  353. #define LPT_WC        034                /* word count */
  354. #define LPT_MA        035                /* mem address */
  355.  
  356. /* Status register */
  357.  
  358. #define STA_ERR        0400000                /* error */
  359. #define STA_ALM        0200000                /* alarm */
  360. #define STA_OVF        0100000                /* line overflow */
  361. #define STA_IHT        0040000                /* illegal HT */
  362. #define STA_BUSY    0020000                /* busy */
  363. #define STA_DON        0010000                /* done */
  364. #define STA_ILK        0004000                /* interlock */
  365. #define STA_EFLGS    (STA_ALM | STA_OVF | STA_IHT | STA_ILK)
  366. #define STA_CLR        0003777                /* always clear */
  367.  
  368. extern unsigned int M[];
  369. extern int int_req;
  370. int lpt_sta = 0, lpt_ie = 1, lpt_stopioe = 0;
  371. int mode = 0, lcnt = 0, bptr = 0;
  372. unsigned char lpt_buf[LPT_BSIZE] = { 0 };
  373.  
  374. int lpt_svc (UNIT *uptr);
  375. int lpt_reset (DEVICE *dptr);
  376. int lpt_attach (UNIT *uptr, char *cptr);
  377. int lpt_detach (UNIT *uptr);
  378. int lpt_updsta (int new);
  379. extern int sim_activate (UNIT *uptr, int interval);
  380. extern int sim_cancel (UNIT *uptr);
  381. extern int sim_is_active (UNIT *uptr);
  382. extern int attach_unit (UNIT *uptr, char *cptr);
  383. extern int detach_unit (UNIT *uptr);
  384.  
  385. /* LP15 LPT data structures
  386.  
  387.    lpt_dev    LPT device descriptor
  388.    lpt_unit    LPT unit
  389.    lpt_reg    LPT register list
  390. */
  391.  
  392. UNIT lpt_unit = {
  393.     UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
  394.  
  395. REG lpt_reg[] = {
  396.     { ORDATA (STA, lpt_sta, 18) },
  397.     { ORDATA (MA, M[LPT_MA], 18) },
  398.     { FLDATA (INT, int_req, INT_V_LPT) },
  399.     { FLDATA (ENABLE, lpt_ie, 0) },
  400.     { DRDATA (LCNT, lcnt, 9) },
  401.     { DRDATA (BPTR, bptr, 8) },
  402.     { FLDATA (MODE, mode, 0) },
  403.     { DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
  404.     { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
  405.     { FLDATA (STOP_IOE, lpt_stopioe, 0) },
  406.     { BRDATA (**BUF, lpt_buf, 8, 8, LPT_BSIZE), REG_HRO },
  407.     { NULL }  };
  408.  
  409. DEVICE lpt_dev = {
  410.     "LPT", &lpt_unit, lpt_reg, NULL,
  411.     1, 10, 32, 1, 8, 8,
  412.     NULL, NULL, &lpt_reset,
  413.     NULL, &lpt_attach, &lpt_detach };
  414.  
  415. /* LP15 line printer: IOT routines */
  416.  
  417. int lpt65 (int pulse, int AC)
  418. {
  419. int header;
  420.  
  421. if (pulse == 001)                    /* LPSF */
  422.     return (lpt_sta & (STA_ERR | STA_DON))? IOT_SKP + AC: AC;
  423. if ((pulse == 021) || (pulse == 041)) {            /* LPP1, LPPM */
  424.     header = M[(M[LPT_MA] + 1) & ADDRMASK];        /* get first word */
  425.     M[LPT_MA] = (M[LPT_MA] + 2) & 0777777;
  426.     mode = header & 1;                /* mode */
  427.     if (pulse == 041) lcnt = 1;            /* line count */
  428.     else lcnt = (header >> 9) & 0377;
  429.     if (lcnt == 0) lcnt = 256;
  430.     bptr = 0;                    /* reset buf ptr */
  431.     sim_activate (&lpt_unit, lpt_unit.wait);  }    /* activate */
  432. if (pulse == 061) lpt_ie = 0;                /* LPDI */
  433. if (pulse == 042) return lpt_updsta (0);        /* LPOS, LPRS */
  434. if (pulse == 044) lpt_ie = 1;                /* LPEI */
  435. lpt_updsta (0);                        /* update status */
  436. return AC;
  437. }
  438.  
  439. int lpt66 (int pulse, int AC)
  440. {
  441. if (pulse == 021) lpt_sta = lpt_sta & ~STA_DON;        /* LPCD */
  442. if (pulse == 041) lpt_sta = lpt_sta & STA_ALM;        /* LPCF */
  443. lpt_updsta (0);                        /* update status */
  444. return AC;
  445. }
  446.  
  447. /* Unit service */
  448.  
  449. int lpt_svc (UNIT *uptr)
  450. {
  451. int i, ccnt, more, reason, w0, w1;
  452. unsigned char c[5];
  453. static const char *ctrl[040] = {
  454.     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  455.     NULL, NULL, "\n", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
  456.     "\f", "\r", NULL, NULL,
  457.     "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
  458.     "\n\n", "\n\n\n", "\n",
  459.     "\n\n\n\n\n\n\n\n\n\n", NULL, NULL, NULL,
  460.     NULL, NULL, NULL, "\r", NULL, NULL, NULL, NULL };
  461.  
  462. if ((lpt_unit.flags & UNIT_ATT) == 0) {            /* not attached? */
  463.     lpt_updsta (STA_DON | STA_ALM);            /* set done, err */
  464.     return IORETURN (lpt_stopioe, SCPE_UNATT);  }
  465.  
  466. for (more = 1; more != 0; ) {                /* loop until ctrl */
  467.     w0 = M[(M[LPT_MA] + 1) & ADDRMASK];        /* get first word */
  468.     w1 = M[(M[LPT_MA] + 2) & ADDRMASK];        /* get second word */
  469.     M[LPT_MA] = (M[LPT_MA] + 2) & 0777777;        /* advance mem addr */
  470.     if (mode) {                    /* unpacked? */
  471.         c[0] = w0 & 0177;
  472.         c[1] = w1 & 0177;
  473.         ccnt = 2;  }
  474.     else {    c[0] = (w0 >> 11) & 0177;        /* packed */
  475.         c[1] = (w0 >> 4) & 0177;
  476.         c[2] = (((w0 << 3) | (w1 >> 15))) & 0177;
  477.         c[3] = (w1 >> 8) & 0177;
  478.         c[4] = (w1 >> 1) & 0177;
  479.         ccnt = 5;  }
  480.     for (i = 0; i < ccnt; i++) {            /* loop through */
  481.         if ((c[i] <= 037) && ctrl[c[i]]) {    /* control char? */
  482.             fwrite (lpt_buf, 1, bptr, lpt_unit.fileref);
  483.             fputs (ctrl[c[i]], lpt_unit.fileref);
  484.             if (ferror (lpt_unit.fileref)) {    /* error? */
  485.                 perror ("LPT I/O error");
  486.                 clearerr (lpt_unit.fileref);
  487.                 bptr = 0;
  488.                 lpt_updsta (STA_DON | STA_ALM);
  489.                 return SCPE_IOERR;  }
  490.             lpt_unit.pos = lpt_unit.pos + bptr +
  491.                 strlen (ctrl[c[i]]);
  492.             bptr = more = 0;  }
  493.         else {    if (bptr < LPT_BSIZE) lpt_buf[bptr++] = c[i];
  494.             else lpt_sta = lpt_sta | STA_OVF;  }  }  }
  495.  
  496. lcnt = lcnt - 1;                    /* decr line count */
  497. if (lcnt) sim_activate (&lpt_unit, lpt_unit.wait);    /* more to do? */
  498. else lpt_updsta (STA_DON);                /* no, set done */
  499. return SCPE_OK;
  500. }
  501.  
  502. /* Update status */
  503.  
  504. int lpt_updsta (new)
  505. {
  506. lpt_sta = (lpt_sta | new) & ~(STA_CLR | STA_ERR | STA_BUSY);
  507. if (lpt_sta & STA_EFLGS) lpt_sta = lpt_sta | STA_ERR;    /* update errors */
  508. if (sim_is_active (&lpt_unit)) lpt_sta = lpt_sta | STA_BUSY;
  509. if (lpt_ie && (lpt_sta & STA_DON)) int_req = int_req | INT_LPT;
  510. else int_req = int_req & ~INT_LPT;            /* update int */
  511. return lpt_sta;
  512. }
  513.  
  514. /* Reset routine */
  515.  
  516. int lpt_reset (DEVICE *dptr)
  517. {
  518. mode = lcnt = bptr = 0;                    /* clear controls */
  519. sim_cancel (&lpt_unit);                    /* deactivate unit */
  520. if (lpt_unit.flags & UNIT_ATT) lpt_sta = 0;
  521. else lpt_sta = STA_ALM;
  522. lpt_ie = 1;                        /* enable interrupts */
  523. lpt_updsta (0);                        /* update status */
  524. return SCPE_OK;
  525. }
  526.  
  527. /* IORS routine */
  528.  
  529. int lpt_iors (void)
  530. {
  531. return ((lpt_sta & STA_DON)? IOS_LPT: 0);
  532. }
  533.  
  534. /* Attach routine */
  535.  
  536. int lpt_attach (UNIT *uptr, char *cptr)
  537. {
  538. int reason;
  539.  
  540. reason = attach_unit (uptr, cptr);
  541. if (lpt_unit.flags & UNIT_ATT) lpt_sta = lpt_sta & ~STA_ALM;
  542. lpt_updsta (0);
  543. return reason;
  544. }
  545.  
  546. /* Detach routine */
  547.  
  548. int lpt_detach (UNIT *uptr)
  549. {
  550. lpt_updsta (STA_ALM);
  551. return detach_unit (uptr);
  552. }
  553. #endif
  554.