1 /* pdp10_lp20.c: PDP-10 LP20 line printer simulator
3 Copyright (c) 1993-2007, Robert M Supnik
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
28 19-Jan-07 RMS Added UNIT_TEXT flag
29 04-Sep-05 RMS Fixed missing return (found by Peter Schorn)
30 07-Jul-05 RMS Removed extraneous externs
31 18-Mar-05 RMS Added attached test to detach routine
32 29-Dec-03 RMS Fixed bug in scheduling
33 25-Apr-03 RMS Revised for extended file support
34 29-Sep-02 RMS Added variable vector support
35 Modified to use common Unibus routines
37 30-May-02 RMS Widened POS to 32b
38 06-Jan-02 RMS Added enable/disable support
39 30-Nov-01 RMS Added extended SET/SHOW support
42 #include "pdp10_defs.h"
44 #define UNIT_DUMMY (1 << UNIT_V_UF)
45 #define LP_WIDTH 132 /* printer width */
49 #define DV_SIZE 143 /* DAVFU size */
50 #define DV_DMASK 077 /* data mask per byte */
51 #define DV_TOF 0 /* top of form channel */
52 #define DV_MAX 11 /* max channel number */
56 #define TX_SIZE 256 /* translation RAM */
57 #define TX_AMASK (TX_SIZE - 1)
58 #define TX_DMASK 07777
59 #define TX_V_FL 8 /* flags */
61 /* define TX_INTR 04000 /* interrupt */
62 #define TX_DELH 02000 /* delimiter */
63 /* define TX_XLAT 01000 /* translate */
64 /* define TX_DVFU 00400 /* DAVFU */
65 #define TX_SLEW 00020 /* chan vs slew */
66 #define TX_VMASK 00017 /* spacing mask */
67 #define TX_CHR 0 /* states: pr char */
68 #define TX_RAM 1 /* pr translation */
69 #define TX_DVU 2 /* DAVFU action */
70 #define TX_INT 3 /* interrupt */
71 #define TX_GETFL(x) (((x) >> TX_V_FL) & TX_M_FL)
75 #define CSA_GO 0000001 /* go */
76 #define CSA_PAR 0000002 /* parity enable NI */
77 #define CSA_V_FNC 2 /* function */
79 #define FNC_PR 0 /* print */
80 #define FNC_TST 1 /* test */
81 #define FNC_DVU 2 /* load DAVFU */
82 #define FNC_RAM 3 /* load translation RAM */
83 #define FNC_INTERNAL 1 /* internal function */
84 #define CSA_FNC (CSA_M_FNC << CSA_V_FNC)
85 #define CSA_V_UAE 4 /* Unibus addr extension */
86 #define CSA_UAE (03 << CSA_V_UAE)
87 #define CSA_IE 0000100 /* interrupt enable */
88 #define CSA_DONE 0000200 /* done */
89 #define CSA_INIT 0000400 /* init */
90 #define CSA_ECLR 0001000 /* clear errors */
91 #define CSA_DELH 0002000 /* delimiter hold */
92 #define CSA_ONL 0004000 /* online */
93 #define CSA_DVON 0010000 /* DAVFU online */
94 #define CSA_UNDF 0020000 /* undefined char */
95 #define CSA_PZRO 0040000 /* page counter zero */
96 #define CSA_ERR 0100000 /* error */
97 #define CSA_RW (CSA_DELH | CSA_IE | CSA_UAE | CSA_FNC | CSA_PAR | CSA_GO)
98 #define CSA_MBZ (CSA_ECLR | CSA_INIT)
99 #define CSA_GETUAE(x) (((x) & CSA_UAE) << (16 - CSA_V_UAE))
100 #define CSA_GETFNC(x) (((x) >> CSA_V_FNC) & CSA_M_FNC)
102 /* LPCSRB (765402) */
104 #define CSB_GOE 0000001 /* go error */
105 #define CSB_DTE 0000002 /* DEM timing error NI */
106 #define CSB_MTE 0000004 /* MSYN error (Ubus timeout) */
107 #define CSB_RPE 0000010 /* RAM parity error NI */
108 #define CSB_MPE 0000020 /* MEM parity error NI */
109 #define CSB_LPE 0000040 /* LPT parity error NI */
110 #define CSB_DVOF 0000100 /* DAVFU not ready */
111 #define CSB_OFFL 0000200 /* offline */
112 #define CSB_TEST 0003400 /* test mode */
113 #define CSB_OVFU 0004000 /* optical VFU NI */
114 #define CSB_PBIT 0010000 /* data parity bit NI */
115 #define CSB_NRDY 0020000 /* printer error NI */
116 #define CSB_LA180 0040000 /* LA180 printer NI */
117 #define CSB_VLD 0100000 /* valid data NI */
118 #define CSB_ECLR (CSB_GOE | CSB_DTE | CSB_MTE | CSB_RPE | CSB_MPE | CSB_LPE)
119 #define CSB_ERR (CSB_ECLR | CSB_DVOF | CSB_OFFL)
120 #define CSB_RW CSB_TEST
121 #define CSB_MBZ (CSB_DTE | CSB_RPE | CSB_MPE | CSB_LPE | CSB_OVFU |\
122 CSB_PBIT | CSB_NRDY | CSB_LA180 | CSB_VLD)
128 #define BC_MASK 0007777 /* <15:12> MBZ */
130 /* LPPAGC (765510) */
132 #define PAGC_MASK 0007777 /* <15:12> MBZ */
134 /* LPRDAT (765512) */
136 #define RDAT_MASK 0007777 /* <15:12> MBZ */
138 /* LPCOLC/LPCBUF (765514) */
140 /* LPCSUM/LPPDAT (765516) */
142 extern d10
*M
; /* main memory */
143 extern int32 int_req
;
145 int32 lpcsa
= 0; /* control/status A */
146 int32 lpcsb
= 0; /* control/status B */
147 int32 lpba
= 0; /* bus address */
148 int32 lpbc
= 0; /* byte count */
149 int32 lppagc
= 0; /* page count */
150 int32 lprdat
= 0; /* RAM data */
151 int32 lpcbuf
= 0; /* character buffer */
152 int32 lpcolc
= 0; /* column count */
153 int32 lppdat
= 0; /* printer data */
154 int32 lpcsum
= 0; /* checksum */
155 int32 dvptr
= 0; /* davfu pointer */
156 int32 dvlnt
= 0; /* davfu length */
157 int32 lp20_irq
= 0; /* int request */
158 int32 lp20_stopioe
= 0; /* stop on error */
159 int16 txram
[TX_SIZE
] = { 0 }; /* translation RAM */
160 int16 davfu
[DV_SIZE
] = { 0 }; /* DAVFU */
163 t_stat
lp20_rd (int32
*data
, int32 pa
, int32 access
);
164 t_stat
lp20_wr (int32 data
, int32 pa
, int32 access
);
165 int32
lp20_inta (void);
166 t_stat
lp20_svc (UNIT
*uptr
);
167 t_stat
lp20_reset (DEVICE
*dptr
);
168 t_stat
lp20_attach (UNIT
*uptr
, char *ptr
);
169 t_stat
lp20_detach (UNIT
*uptr
);
170 t_stat
lp20_clear_vfu (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
171 t_bool
lp20_print (int32 c
);
172 t_bool
lp20_adv (int32 c
, t_bool advdvu
);
173 t_bool
lp20_davfu (int32 c
);
174 void update_lpcs (int32 flg
);
176 /* LP data structures
178 lp20_dev LPT device descriptor
179 lp20_unit LPT unit descriptor
180 lp20_reg LPT register list
184 IOBA_LP20
, IOLN_LP20
, &lp20_rd
, &lp20_wr
,
185 1, IVCL (LP20
), VEC_LP20
, { &lp20_inta
}
189 UDATA (&lp20_svc
, UNIT_SEQ
+UNIT_ATTABLE
+UNIT_TEXT
, 0), SERIAL_OUT_WAIT
193 { ORDATA (LPCSA
, lpcsa
, 16) },
194 { ORDATA (LPCSB
, lpcsb
, 16) },
195 { ORDATA (LPBA
, lpba
, 16) },
196 { ORDATA (LPBC
, lpbc
, 12) },
197 { ORDATA (LPPAGC
, lppagc
, 12) },
198 { ORDATA (LPRDAT
, lprdat
, 12) },
199 { ORDATA (LPCBUF
, lpcbuf
, 8) },
200 { ORDATA (LPCOLC
, lpcolc
, 8) },
201 { ORDATA (LPPDAT
, lppdat
, 8) },
202 { ORDATA (LPCSUM
, lpcsum
, 8) },
203 { ORDATA (DVPTR
, dvptr
, 7) },
204 { ORDATA (DVLNT
, dvlnt
, 7), REG_RO
+ REG_NZ
},
205 { FLDATA (INT
, int_req
, INT_V_LP20
) },
206 { FLDATA (IRQ
, lp20_irq
, 0) },
207 { FLDATA (ERR
, lpcsa
, CSR_V_ERR
) },
208 { FLDATA (DONE
, lpcsa
, CSR_V_DONE
) },
209 { FLDATA (IE
, lpcsa
, CSR_V_IE
) },
210 { DRDATA (POS
, lp20_unit
.pos
, T_ADDR_W
), PV_LEFT
},
211 { DRDATA (TIME
, lp20_unit
.wait
, 24), PV_LEFT
},
212 { FLDATA (STOP_IOE
, lp20_stopioe
, 0) },
213 { BRDATA (TXRAM
, txram
, 8, 12, TX_SIZE
) },
214 { BRDATA (DAVFU
, davfu
, 8, 12, DV_SIZE
) },
215 { ORDATA (DEVADDR
, lp20_dib
.ba
, 32), REG_HRO
},
216 { ORDATA (DEVVEC
, lp20_dib
.vec
, 16), REG_HRO
},
221 { UNIT_DUMMY
, 0, NULL
, "VFUCLEAR", &lp20_clear_vfu
},
222 { MTAB_XTD
|MTAB_VDV
, 004, "ADDRESS", "ADDRESS",
223 &set_addr
, &show_addr
, NULL
},
224 { MTAB_XTD
|MTAB_VDV
, 0, "VECTOR", "VECTOR",
225 &set_vec
, &show_vec
, NULL
},
230 "LP20", &lp20_unit
, lp20_reg
, lp20_mod
,
232 NULL
, NULL
, &lp20_reset
,
233 NULL
, &lp20_attach
, &lp20_detach
,
234 &lp20_dib
, DEV_DISABLE
| DEV_UBUS
237 /* Line printer routines
239 lp20_rd I/O page read
240 lp20_wr I/O page write
241 lp20_svc process event (printer ready)
242 lp20_reset process reset
243 lp20_attach process attach
244 lp20_detach process detach
247 t_stat
lp20_rd (int32
*data
, int32 pa
, int32 access
)
249 update_lpcs (0); /* update csr's */
250 switch ((pa
>> 1) & 07) { /* case on PA<3:1> */
253 *data
= lpcsa
= lpcsa
& ~CSA_MBZ
;
257 *data
= lpcsb
= lpcsb
& ~CSB_MBZ
;
265 *data
= lpbc
= lpbc
& BC_MASK
;
268 case 04: /* LPPAGC */
269 *data
= lppagc
= lppagc
& PAGC_MASK
;
272 case 05: /* LPRDAT */
273 *data
= lprdat
= lprdat
& RDAT_MASK
;
276 case 06: /* LPCOLC/LPCBUF */
277 *data
= (lpcolc
<< 8) | lpcbuf
;
280 case 07: /* LPCSUM/LPPDAT */
281 *data
= (lpcsum
<< 8) | lppdat
;
288 t_stat
lp20_wr (int32 data
, int32 pa
, int32 access
)
290 update_lpcs (0); /* update csr's */
291 switch ((pa
>> 1) & 07) { /* case on PA<3:1> */
294 if (access
== WRITEB
) data
= (pa
& 1)?
295 (lpcsa
& 0377) | (data
<< 8): (lpcsa
& ~0377) | data
;
296 if (data
& CSA_ECLR
) { /* error clear? */
297 lpcsa
= (lpcsa
| CSA_DONE
) & ~CSA_GO
; /* set done, clr go */
298 lpcsb
= lpcsb
& ~CSB_ECLR
; /* clear err */
299 sim_cancel (&lp20_unit
); /* cancel I/O */
301 if (data
& CSA_INIT
) lp20_reset (&lp20_dev
); /* init? */
302 if (data
& CSA_GO
) { /* go set? */
303 if ((lpcsa
& CSA_GO
) == 0) { /* not set before? */
304 if (lpcsb
& CSB_ERR
) lpcsb
= lpcsb
| CSB_GOE
;
305 lpcsum
= 0; /* clear checksum */
306 sim_activate (&lp20_unit
, lp20_unit
.wait
);
309 else sim_cancel (&lp20_unit
); /* go clr, stop DMA */
310 lpcsa
= (lpcsa
& ~CSA_RW
) | (data
& CSA_RW
);
314 break; /* ignore writes to TEST */
317 if (access
== WRITEB
) data
= (pa
& 1)?
318 (lpba
& 0377) | (data
<< 8): (lpba
& ~0377) | data
;
323 if (access
== WRITEB
) data
= (pa
& 1)?
324 (lpbc
& 0377) | (data
<< 8): (lpbc
& ~0377) | data
;
325 lpbc
= data
& BC_MASK
;
326 lpcsa
= lpcsa
& ~CSA_DONE
;
329 case 04: /* LPPAGC */
330 if (access
== WRITEB
) data
= (pa
& 1)?
331 (lppagc
& 0377) | (data
<< 8): (lppagc
& ~0377) | data
;
332 lppagc
= data
& PAGC_MASK
;
335 case 05: /* LPRDAT */
336 if (access
== WRITEB
) data
= (pa
& 1)?
337 (lprdat
& 0377) | (data
<< 8): (lprdat
& ~0377) | data
;
338 lprdat
= data
& RDAT_MASK
;
339 txram
[lpcbuf
& TX_AMASK
] = lprdat
; /* load RAM */
342 case 06: /* LPCOLC/LPCBUF */
343 if ((access
== WRITEB
) && (pa
& 1)) /* odd byte */
344 lpcolc
= data
& 0377;
346 lpcbuf
= data
& 0377; /* even byte, word */
347 if (access
== WRITE
) lpcolc
= (data
>> 8) & 0377;
351 case 07: /* LPCSUM/LPPDAT */
352 break; /* read only */
359 /* Line printer service
361 The translation RAM case table is derived from the LP20 spec and
362 verified against the LP20 RAM simulator in TOPS10 7.04 LPTSPL.
365 flags := inter, delim, xlate, paper, delim_hold (from CSRA)
366 actions : = print_input, print_xlate, davfu_action, interrupt
369 if (!xlate || delim || delim_hold) interrupt;
370 else if (paper) davfu_action;
374 if (xlate || delim || delim_hold) davfu_action;
378 if (xlate || delim || delim_hold) print_xlate;
383 t_stat
lp20_svc (UNIT
*uptr
)
385 int32 fnc
, i
, tbc
, temp
, txst
;
386 int32 dvld
= -2; /* must be even */
391 static const uint32 txcase
[32] = {
392 TX_CHR
, TX_RAM
, TX_CHR
, TX_DVU
, TX_RAM
, TX_RAM
, TX_DVU
, TX_DVU
,
393 TX_RAM
, TX_RAM
, TX_DVU
, TX_DVU
, TX_RAM
, TX_RAM
, TX_DVU
, TX_DVU
,
394 TX_INT
, TX_INT
, TX_INT
, TX_INT
, TX_RAM
, TX_INT
, TX_DVU
, TX_INT
,
395 TX_INT
, TX_INT
, TX_INT
, TX_INT
, TX_INT
, TX_INT
, TX_INT
, TX_INT
398 lpcsa
= lpcsa
& ~CSA_GO
;
399 ba
= CSA_GETUAE (lpcsa
) | lpba
;
400 fnc
= CSA_GETFNC (lpcsa
);
402 if (((fnc
& FNC_INTERNAL
) == 0) && ((lp20_unit
.flags
& UNIT_ATT
) == 0)) {
403 update_lpcs (CSA_ERR
);
404 return IORETURN (lp20_stopioe
, SCPE_UNATT
);
406 if ((fnc
== FNC_PR
) && (dvlnt
== 0)) {
407 update_lpcs (CSA_ERR
);
411 for (i
= 0, cont
= TRUE
; (i
< tbc
) && cont
; ba
++, i
++) {
412 if (Map_ReadW (ba
, 2, &wd10
)) { /* get word, err? */
413 lpcsb
= lpcsb
| CSB_MTE
; /* set NXM error */
414 update_lpcs (CSA_ERR
); /* set done */
417 lpcbuf
= (wd10
>> ((ba
& 1)? 8: 0)) & 0377; /* get character */
418 lpcsum
= (lpcsum
+ lpcbuf
) & 0377; /* add into checksum */
419 switch (fnc
) { /* switch on function */
421 /* Translation RAM load */
423 case FNC_RAM
: /* RAM load */
424 txram
[(i
>> 1) & TX_AMASK
] = wd10
& TX_DMASK
;
427 /* DAVFU RAM load. The DAVFU RAM is actually loaded in bytes, delimited by
428 a start (354 to 356) and stop (357) byte pair. If the number of bytes
429 loaded is odd, or no bytes are loaded, the DAVFU is invalid.
432 case FNC_DVU
: /* DVU load */
433 if ((lpcbuf
>= 0354) && (lpcbuf
<= 0356)) /* start DVU load? */
434 dvld
= dvlnt
= 0; /* reset lnt */
435 else if (lpcbuf
== 0357) { /* stop DVU load? */
436 dvptr
= 0; /* reset ptr */
437 if (dvld
& 1) dvlnt
= 0; /* if odd, invalid */
439 else if (dvld
== 0) { /* even state? */
440 temp
= lpcbuf
& DV_DMASK
;
443 else if (dvld
== 1) { /* odd state? */
444 if (dvlnt
< DV_SIZE
) davfu
[dvlnt
++] =
445 temp
| ((lpcbuf
& DV_DMASK
) << 6);
450 /* Print characters */
452 case FNC_PR
: /* print */
453 lprdat
= txram
[lpcbuf
]; /* get RAM char */
454 txst
= (TX_GETFL (lprdat
) << 1) | /* get state */
455 ((lpcsa
& CSA_DELH
)? 1: 0); /* plus delim hold */
456 if (lprdat
& TX_DELH
) lpcsa
= lpcsa
| CSA_DELH
;
457 else lpcsa
= lpcsa
& ~CSA_DELH
;
458 lpcsa
= lpcsa
& ~CSA_UNDF
; /* assume char ok */
459 switch (txcase
[txst
]) { /* case on state */
461 case TX_CHR
: /* take char */
462 cont
= lp20_print (lpcbuf
);
465 case TX_RAM
: /* take translation */
466 cont
= lp20_print (lprdat
);
469 case TX_DVU
: /* DAVFU action */
470 if (lprdat
& TX_SLEW
)
471 cont
= lp20_adv (lprdat
& TX_VMASK
, TRUE
);
472 else cont
= lp20_davfu (lprdat
& TX_VMASK
);
475 case TX_INT
: /* interrupt */
476 lpcsa
= lpcsa
| CSA_UNDF
; /* set flag */
477 cont
= FALSE
; /* force stop */
479 } /* end case char state */
482 case FNC_TST
: /* test */
484 } /* end case function */
487 lpcsa
= (lpcsa
& ~CSA_UAE
) | ((ba
>> (16 - CSA_V_UAE
)) & CSA_UAE
);
488 lpbc
= (lpbc
+ i
) & BC_MASK
;
489 if (lpbc
) update_lpcs (CSA_MBZ
); /* intr, but not done */
490 else update_lpcs (CSA_DONE
); /* intr and done */
491 if ((fnc
== FNC_PR
) && ferror (lp20_unit
.fileref
)) {
492 perror ("LP I/O error");
493 clearerr (uptr
->fileref
);
501 lp20_print print a character
502 lp20_adv advance n lines
503 lp20_davfu advance to channel on VFU
505 Return TRUE to continue printing, FALSE to stop
508 t_bool
lp20_print (int32 c
)
513 lppdat
= c
& 0177; /* mask char to 7b */
514 if (lppdat
== 000) return TRUE
; /* NUL? no op */
515 if (lppdat
== 012) return lp20_adv (1, TRUE
); /* LF? adv carriage */
516 if (lppdat
== 014) return lp20_davfu (DV_TOF
); /* FF? top of form */
517 if (lppdat
== 015) lpcolc
= 0; /* CR? reset col cntr */
518 else if (lppdat
== 011) { /* TAB? simulate */
519 lppdat
= ' '; /* with spaces */
521 r
= lp20_adv (1, TRUE
); /* eol? adv carriage */
522 rpt
= 8; /* adv to col 9 */
524 else rpt
= 8 - (lpcolc
& 07); /* else adv 1 to 8 */
527 if (lppdat
< 040) lppdat
= ' '; /* cvt non-prnt to spc */
528 if (lpcolc
>= LP_WIDTH
) /* line full? */
529 r
= lp20_adv (1, TRUE
); /* adv carriage */
531 for (i
= 0; i
< rpt
; i
++)
532 fputc (lppdat
, lp20_unit
.fileref
);
533 lp20_unit
.pos
= ftell (lp20_unit
.fileref
);
534 lpcolc
= lpcolc
+ rpt
;
538 t_bool
lp20_adv (int32 cnt
, t_bool dvuadv
)
542 if (cnt
== 0) return TRUE
;
543 lpcolc
= 0; /* reset col cntr */
544 for (i
= 0; i
< cnt
; i
++)
545 fputc ('\n', lp20_unit
.fileref
);
546 lp20_unit
.pos
= ftell (lp20_unit
.fileref
); /* print 'n' newlines */
547 if (dvuadv
) dvptr
= (dvptr
+ cnt
) % dvlnt
; /* update DAVFU ptr */
548 if (davfu
[dvptr
] & (1 << DV_TOF
)) { /* at top of form? */
549 if (lppagc
= (lppagc
- 1) & PAGC_MASK
) { /* decr page cntr */
550 lpcsa
= lpcsa
& ~CSA_PZRO
; /* update status */
554 lpcsa
= lpcsa
| CSA_PZRO
; /* stop if zero */
561 t_bool
lp20_davfu (int32 cnt
)
565 if (cnt
> DV_MAX
) cnt
= 7; /* inval chan? */
566 for (i
= 0; i
< dvlnt
; i
++) { /* search DAVFU */
567 dvptr
= dvptr
+ 1; /* adv DAVFU ptr */
568 if (dvptr
>= dvlnt
) dvptr
= 0; /* wrap at end */
569 if (davfu
[dvptr
] & (1 << cnt
)) { /* channel stop set? */
570 if (cnt
) return lp20_adv (i
+ 1, FALSE
); /* ~TOF, adv */
571 if (lpcolc
) lp20_adv (1, FALSE
); /* TOF, need newline? */
572 fputc ('\f', lp20_unit
.fileref
); /* print form feed */
573 lp20_unit
.pos
= ftell (lp20_unit
.fileref
);
574 if (lppagc
= (lppagc
- 1) & PAGC_MASK
) { /* decr page cntr */
575 lpcsa
= lpcsa
& ~CSA_PZRO
; /* update status */
579 lpcsa
= lpcsa
| CSA_PZRO
; /* stop if zero */
584 dvlnt
= 0; /* DAVFU error */
588 /* Update LPCSA, optionally request interrupt */
590 void update_lpcs (int32 flg
)
592 if (flg
) lp20_irq
= 1; /* set int req */
593 lpcsa
= (lpcsa
| flg
) & ~(CSA_MBZ
| CSA_ERR
| CSA_ONL
| CSA_DVON
);
594 lpcsb
= (lpcsb
| CSB_OFFL
| CSB_DVOF
) & ~CSB_MBZ
;
595 if (lp20_unit
.flags
& UNIT_ATT
) {
596 lpcsa
= lpcsa
| CSA_ONL
;
597 lpcsb
= lpcsb
& ~CSB_OFFL
;
599 else lpcsa
= lpcsa
& ~CSA_DONE
;
601 lpcsa
= lpcsa
| CSA_DVON
;
602 lpcsb
= lpcsb
& ~CSB_DVOF
;
604 if (lpcsb
& CSB_ERR
) lpcsa
= lpcsa
| CSA_ERR
;
605 if ((lpcsa
& CSA_IE
) && lp20_irq
) int_req
= int_req
| INT_LP20
;
606 else int_req
= int_req
& ~INT_LP20
;
610 /* Acknowledge interrupt (clear internal request) */
612 int32
lp20_inta (void)
614 lp20_irq
= 0; /* clear int req */
618 t_stat
lp20_reset (DEVICE
*dptr
)
622 lpba
= lpbc
= lppagc
= lpcolc
= 0; /* clear registers */
623 lprdat
= lppdat
= lpcbuf
= lpcsum
= 0;
624 lp20_irq
= 0; /* clear int req */
625 dvptr
= 0; /* reset davfu ptr */
626 sim_cancel (&lp20_unit
); /* deactivate unit */
627 update_lpcs (0); /* update status */
631 t_stat
lp20_attach (UNIT
*uptr
, char *cptr
)
635 reason
= attach_unit (uptr
, cptr
); /* attach file */
636 if (lpcsa
& CSA_ONL
) return reason
; /* just file chg? */
637 if (sim_is_active (&lp20_unit
)) update_lpcs (0); /* busy? no int */
638 else update_lpcs (CSA_MBZ
); /* interrupt */
642 t_stat
lp20_detach (UNIT
*uptr
)
646 if (!(uptr
->flags
& UNIT_ATT
)) return SCPE_OK
; /* attached? */
647 reason
= detach_unit (uptr
);
648 sim_cancel (&lp20_unit
);
649 lpcsa
= lpcsa
& ~CSA_GO
;
650 update_lpcs (CSA_MBZ
);
654 t_stat
lp20_clear_vfu (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
658 if (!get_yn ("Clear DAVFU? [N]", FALSE
)) return SCPE_OK
;
659 for (i
= 0; i
< DV_SIZE
; i
++) davfu
[i
] = 0;