41f43cf2bff6ec5b3cb7676cdee17c36311a2f37
1 /* hp2100_lpt.c: HP 2100 12845B 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.
26 lpt 12845B 2607 line printer
28 22-Jan-07 RMS Added UNIT_TEXT flag
29 28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
30 19-Nov-04 JDB Added restart when set online, etc.
31 29-Sep-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON
32 Fixed status returns for error conditions
33 Fixed TOF handling so form remains on line 0
34 03-Jun-04 RMS Fixed timing (found by Dave Bryan)
35 26-Apr-04 RMS Fixed SFS x,C and SFC x,C
36 Implemented DMA SRQ (follows FLG)
37 25-Apr-03 RMS Revised for extended file support
38 24-Oct-02 RMS Cloned from 12653A
40 The 2607 provides three status bits via the interface:
42 bit 15 -- printer ready (online)
46 The expected status returns are:
48 140001 -- power off or cable disconnected
49 100001 -- power on, paper loaded, printer ready
50 100000 -- power on, paper loaded, printer busy
51 040000 -- power on, paper out (at bottom-of-form)
52 000000 -- power on, paper out (not at BOF) / print button up / platen open
54 Manual Note: "2-33. PAPER OUT SIGNAL. [...] The signal is asserted only
55 when the format tape in the line printer has reached the bottom of form."
57 These simulator commands provide the listed printer states:
59 SET LPT POWEROFF --> power off or cable disconnected
60 SET LPT POWERON --> power on
61 SET LPT OFFLINE --> print button up
62 SET LPT ONLINE --> print button down
63 ATT LPT <file> --> paper loaded
67 - 12845A Line Printer Operating and Service Manual (12845-90001, Aug-1972)
70 #include "hp2100_defs.h"
72 #define LPT_PAGELNT 60 /* page length */
74 #define LPT_NBSY 0000001 /* not busy */
75 #define LPT_PAPO 0040000 /* paper out */
76 #define LPT_RDY 0100000 /* ready */
77 #define LPT_PWROFF LPT_RDY | LPT_PAPO | LPT_NBSY /* power-off status */
79 #define LPT_CTL 0100000 /* control output */
80 #define LPT_CHAN 0000100 /* skip to chan */
81 #define LPT_SKIPM 0000077 /* line count mask */
82 #define LPT_CHANM 0000007 /* channel mask */
84 #define UNIT_V_POWEROFF (UNIT_V_UF + 0) /* unit powered off */
85 #define UNIT_V_OFFLINE (UNIT_V_UF + 1) /* unit offline */
86 #define UNIT_POWEROFF (1 << UNIT_V_POWEROFF)
87 #define UNIT_OFFLINE (1 << UNIT_V_OFFLINE)
90 extern uint32 dev_cmd
[2], dev_ctl
[2], dev_flg
[2], dev_fbf
[2], dev_srq
[2];
92 int32 lpt_ctime
= 4; /* char time */
93 int32 lpt_ptime
= 10000; /* print time */
94 int32 lpt_stopioe
= 0; /* stop on error */
95 int32 lpt_lcnt
= 0; /* line count */
96 static int32 lpt_cct
[8] = {
97 1, 1, 1, 2, 3, LPT_PAGELNT
/2, LPT_PAGELNT
/4, LPT_PAGELNT
/6
101 int32
lptio (int32 inst
, int32 IR
, int32 dat
);
102 t_stat
lpt_svc (UNIT
*uptr
);
103 t_stat
lpt_reset (DEVICE
*dptr
);
104 t_stat
lpt_restart (UNIT
*uptr
, int32 value
, char *cptr
, void *desc
);
105 t_stat
lpt_attach (UNIT
*uptr
, char *cptr
);
107 /* LPT data structures
109 lpt_dev LPT device descriptor
110 lpt_unit LPT unit descriptor
111 lpt_reg LPT register list
114 DIB lpt_dib
= { LPT
, 0, 0, 0, 0, 0, &lptio
};
117 UDATA (&lpt_svc
, UNIT_SEQ
+UNIT_ATTABLE
+UNIT_DISABLE
+UNIT_TEXT
, 0)
121 { ORDATA (BUF
, lpt_unit
.buf
, 7) },
122 { FLDATA (CMD
, lpt_dib
.cmd
, 0) },
123 { FLDATA (CTL
, lpt_dib
.ctl
, 0) },
124 { FLDATA (FLG
, lpt_dib
.flg
, 0) },
125 { FLDATA (FBF
, lpt_dib
.fbf
, 0) },
126 { FLDATA (SRQ
, lpt_dib
.srq
, 0) },
127 { DRDATA (LCNT
, lpt_lcnt
, 7) },
128 { DRDATA (POS
, lpt_unit
.pos
, T_ADDR_W
), PV_LEFT
},
129 { DRDATA (CTIME
, lpt_ctime
, 31), PV_LEFT
},
130 { DRDATA (PTIME
, lpt_ptime
, 24), PV_LEFT
},
131 { FLDATA (STOP_IOE
, lpt_stopioe
, 0) },
132 { ORDATA (DEVNO
, lpt_dib
.devno
, 6), REG_HRO
},
137 { UNIT_POWEROFF
, UNIT_POWEROFF
, "power off", "POWEROFF", NULL
},
138 { UNIT_POWEROFF
, 0, "power on", "POWERON", lpt_restart
},
139 { UNIT_OFFLINE
, UNIT_OFFLINE
, "offline", "OFFLINE", NULL
},
140 { UNIT_OFFLINE
, 0, "online", "ONLINE", lpt_restart
},
141 { MTAB_XTD
| MTAB_VDV
, 0, "DEVNO", "DEVNO",
142 &hp_setdev
, &hp_showdev
, &lpt_dev
},
147 "LPT", &lpt_unit
, lpt_reg
, lpt_mod
,
149 NULL
, NULL
, &lpt_reset
,
150 NULL
, &lpt_attach
, NULL
,
151 &lpt_dib
, DEV_DISABLE
154 /* IO instructions */
156 int32
lptio (int32 inst
, int32 IR
, int32 dat
)
160 dev
= IR
& I_DEVMASK
; /* get device no */
161 switch (inst
) { /* case on opcode */
163 case ioFLG
: /* flag clear/set */
164 if ((IR
& I_HC
) == 0) { setFSR (dev
); } /* STF */
167 case ioSFC
: /* skip flag clear */
168 if (FLG (dev
) == 0) PC
= (PC
+ 1) & VAMASK
;
171 case ioSFS
: /* skip flag set */
172 if (FLG (dev
) != 0) PC
= (PC
+ 1) & VAMASK
;
175 case ioOTX
: /* output */
176 lpt_unit
.buf
= dat
& (LPT_CTL
| 0177);
179 case ioLIX
: /* load */
180 dat
= 0; /* default sta = 0 */
181 case ioMIX
: /* merge */
182 if (lpt_unit
.flags
& UNIT_POWEROFF
) /* power off? */
183 dat
= dat
| LPT_PWROFF
;
184 else if (!(lpt_unit
.flags
& UNIT_OFFLINE
)) { /* online? */
185 if (lpt_unit
.flags
& UNIT_ATT
) { /* paper loaded? */
187 if (!sim_is_active (&lpt_unit
)) /* printer busy? */
188 dat
= dat
| LPT_NBSY
;
190 else if (lpt_lcnt
== LPT_PAGELNT
- 1) /* paper out, at BOF? */
191 dat
= dat
| LPT_PAPO
;
195 case ioCRS
: /* control reset (action unverif) */
196 case ioCTL
: /* control clear/set */
197 if (IR
& I_CTL
) { /* CLC */
198 clrCMD (dev
); /* clear ctl, cmd */
202 setCMD (dev
); /* set ctl, cmd */
204 sim_activate (&lpt_unit
, /* schedule op */
205 (lpt_unit
.buf
& LPT_CTL
)? lpt_ptime
: lpt_ctime
);
213 if (IR
& I_HC
) { clrFSR (dev
); } /* H/C option */
219 t_stat
lpt_svc (UNIT
*uptr
)
221 int32 i
, skip
, chan
, dev
;
223 dev
= lpt_dib
.devno
; /* get dev no */
224 if ((uptr
->flags
& UNIT_ATT
) == 0) /* attached? */
225 return IORETURN (lpt_stopioe
, SCPE_UNATT
);
226 else if (uptr
->flags
& UNIT_OFFLINE
) /* offline? */
227 return IORETURN (lpt_stopioe
, STOP_OFFLINE
);
228 else if (uptr
->flags
& UNIT_POWEROFF
) /* powered off? */
229 return IORETURN (lpt_stopioe
, STOP_PWROFF
);
230 clrCMD (dev
); /* clear cmd */
231 setFSR (dev
); /* set flag, fbf */
232 if (uptr
->buf
& LPT_CTL
) { /* control word? */
233 if (uptr
->buf
& LPT_CHAN
) {
234 chan
= uptr
->buf
& LPT_CHANM
;
235 if (chan
== 0) { /* top of form? */
236 fputc ('\f', uptr
->fileref
); /* ffeed */
237 lpt_lcnt
= 0; /* reset line cnt */
240 else if (chan
== 1) skip
= LPT_PAGELNT
- lpt_lcnt
- 1;
241 else skip
= lpt_cct
[chan
] - (lpt_lcnt
% lpt_cct
[chan
]);
244 skip
= uptr
->buf
& LPT_SKIPM
;
245 if (skip
== 0) fputc ('\r', uptr
->fileref
);
247 for (i
= 0; i
< skip
; i
++) fputc ('\n', uptr
->fileref
);
248 lpt_lcnt
= (lpt_lcnt
+ skip
) % LPT_PAGELNT
;
250 else fputc (uptr
->buf
& 0177, uptr
->fileref
); /* no, just add char */
251 if (ferror (uptr
->fileref
)) {
252 perror ("LPT I/O error");
253 clearerr (uptr
->fileref
);
256 lpt_unit
.pos
= ftell (uptr
->fileref
); /* update pos */
260 /* Reset routine - called from SCP, flags in DIB */
262 t_stat
lpt_reset (DEVICE
*dptr
)
264 lpt_dib
.cmd
= lpt_dib
.ctl
= 0; /* clear cmd, ctl */
265 lpt_dib
.flg
= lpt_dib
.fbf
= lpt_dib
.srq
= 1; /* set flg, fbf, srq */
267 sim_cancel (&lpt_unit
); /* deactivate unit */
271 /* Restart I/O routine
273 If I/O is started via STC, and the printer is powered off, offline,
274 or out of paper, the CTL and CMD flip-flops will set, a service event
275 will be scheduled, and the service routine will be entered. If
276 STOP_IOE is not set, the I/O operation will "hang" at that point
277 until the printer is powered on, set online, or paper is supplied
280 If a pending operation is "hung" when this routine is called, it is
281 restarted, which clears CTL and sets FBF and FLG, completing the
282 original I/O request.
285 t_stat
lpt_restart (UNIT
*uptr
, int32 value
, char *cptr
, void *desc
)
287 if (lpt_dib
.cmd
&& lpt_dib
.ctl
&& !sim_is_active (uptr
))
288 sim_activate (uptr
, 0); /* reschedule I/O */
294 t_stat
lpt_attach (UNIT
*uptr
, char *cptr
)
296 lpt_lcnt
= 0; /* top of form */
297 lpt_restart (uptr
, 0, NULL
, NULL
); /* restart I/O if hung */
298 return attach_unit (uptr
, cptr
);