1 /* hp3000_lp.c: HP 3000 30209A Line Printer Interface simulator
2 
3    Copyright (c) 2016-2021, J. David Bryan
4 
5    Permission is hereby granted, free of charge, to any person obtaining a copy
6    of this software and associated documentation files (the "Software"), to deal
7    in the Software without restriction, including without limitation the rights
8    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9    copies of the Software, and to permit persons to whom the Software is
10    furnished to do so, subject to the following conditions:
11 
12    The above copyright notice and this permission notice shall be included in
13    all copies or substantial portions of the Software.
14 
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 THE
18    AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22    Except as contained in this notice, the name of the author shall not be used
23    in advertising or otherwise to promote the sale, use or other dealings in
24    this Software without prior written authorization from the author.
25 
26    LP           HP 30209A Line Printer Interface
27 
28    01-Apr-21    JDB     Changed VFU type from "uint16" to "uint32"
29    25-Mar-21    JDB     Converted ftell to position increment for pipes
30    09-Dec-19    JDB     Replaced debugging macros with tracing macros
31    01-Oct-19    JDB     DETACH -F now flushes the print buffer if not empty
32    27-Dec-18    JDB     Revised fall through comments to comply with gcc 7
33    07-Sep-17    JDB     Changed PCHR and UPCHR registers to PUNCHR and UNPCHR
34                         Changed PRTBUF, OVPCHR, PUNCHR, and UNPCHR to REG_A
35    05-Sep-17    JDB     Changed REG_A (permit any symbolic override) to REG_X
36    20-Jul-17    JDB     Added a forced detach option (-F switch) to "lp_detach"
37    24-Jun-17    JDB     Added "report_error", fixed "lp_set_model" times bug
38    22-Jun-17    JDB     Moved deferred offline/detach cancel to SET ONLINE
39    26-Apr-17    JDB     Fixed "lp_service" return for VFU channel not punched
40                         Restricted auto-print on buffer full to the 2607
41                         Paper fault is now delayed until the TOF for the 2607
42                         Changed "activate_unit" to schedule zero-length delays
43    12-Sep-16    JDB     Changed DIB register macro usage from SRDATA to DIB_REG
44    03-Sep-16    JDB     Added power-fail detection
45    08-Jul-16    JDB     Added REG entry to save the transfer unit wait field
46                         Extended "lp_show_vfu" to show the VFU channel definitions
47    01-Jul-16    JDB     First release version
48    27-Apr-16    JDB     Passes the On-Line HP Line Printers Verification (D466A)
49    19-Apr-16    JDB     Passes the universal interface diagnostic (D435A)
50    24-Mar-16    JDB     Created
51 
52    References:
53      - 30051A Universal Interface (Differential) Maintenance Manual
54          (30051-90001, May 1976)
55      - Installation and Service Manual for Line Printer Subsystems
56          (30209-90006, May 1976)
57      - Line Printer Operating and Programming Manual
58          (30209-90008, June 1976)
59      - HP 3000 Series III Engineering Diagrams Set
60          (30000-90141, April 1980)
61 
62 
63    The HP 30118A, 30127A, 30128A, and 30133A Line Printer Subsystems connect the
64    2607A, 2613A, 2618A, and 2617A printers, respectively, to the HP 3000.  Each
65    subsystem consists of a 30209A Line Printer Controller, employing a 30051A
66    Universal Interface (Differential) and interconnecting cable, and an HP
67    2607A (200 lines per minute), HP 2613 (300 lpm), HP 2617 (600 lpm), or HP
68    2618 (1250 lpm) line printer.  These subsystems employ the Multiplexer
69    Channel to achieve a 360 KB/second transfer rate from the CPU.
70 
71    This module simulates three hardware devices:
72 
73      - the HP 30051A Universal Interface (Differential)
74      - the HP 30049C Diagnostic Hardware Assembly
75      - the HP 2607A/13A/17A/18A line printer and 30209-60004 printer cable
76 
77    Available with either differential or TTL I/O logic levels, the Universal
78    Interface (UI) provides a 16-bit bidirectional parallel connection between a
79    device and the HP 3000 system.  Both direct and programmed I/O via the
80    Multiplexer Channel are supported, word or byte transfers may be selected,
81    and byte packing and unpacking is available.  In addition to the 16-bit data
82    path, a five-bit control word is supplied to the device, and an eight-bit
83    status word is returned.  Flexible configuration of interface operation is
84    provided via ten jumpers, and eight different interrupt sources are
85    available.  The Universal Interface is also used to connect the paper tape
86    reader, punch, and card reader to the HP 3000.
87 
88    The Diagnostic Hardware Assembly (DHA) connects to the UI device connectors
89    and provides a programmable loopback and configuration capability.  Five LEDs
90    continuously display the device control word, and test points are provided to
91    monitor the state of the 16-bit data path, the ten programmable jumper
92    settings, and the Device Command, Device Flag, and Device End signals.
93    Enabling the diagnostic mode simulates the installation of the DHA in place
94    of the printer device cable.
95 
96    The interface supports a single line printer.  The supported printers are
97    configured with Option 001, which provides a 128 (2607) or 96 (2613/17/18)
98    character set.  Two output modes are provided: an expanded mode that is
99    suitable for retaining printer output as a text file, and a compact mode that
100    is suitable for sending the printer output to a host-connected physical
101    printer.  An 8-channel (2607) or 12-channel (2613/17/18) Vertical Format Unit
102    is supported, and custom VFU tape images may be loaded from properly
103    formatted host-system text files.
104 
105    The printer supports realistic and optimized (fast) timing modes.  Realistic
106    timing attempts to model the print buffer load and print-and-space operation
107    delays inherent in the physical hardware.  For example, in REALTIME mode,
108    output of longer lines takes more time than output of shorter lines, and
109    spacing six lines takes approximately six times longer than spacing one line.
110    In FASTTIME mode, all timings are reduced to be "just long enough" to satisfy
111    MPE software driver requirements.
112 
113 
114    In hardware, the ten UI configuration jumpers perform these functions:
115 
116      Jumper  Interpretation when removed      Interpretation when installed
117      ------  -------------------------------  ------------------------------
118        W1    SR set by PCONTSTB               SR set by Device Status bit 11
119 
120        W2    Flag asserts on leading edge     Flag asserts on trailing edge
121 
122        W3    Command uses response mode       Command uses pulse mode
123 
124        W4    inhibit IRQ on Device Status     enable IRQ on Device Status
125                bit 8 leading edge               bit 8 leading edge
126 
127        W5    DATA IN latched on Flag          DATA IN always transparent
128 
129        W6    Flag denies on trailing edge     Flag denies on leading edge
130 
131        W7    normal byte-mode write transfer  test byte-mode write transfer
132 
133        W8    inhibit IRQ on Device Status     enable IRQ on Device Status
134                bit 9 leading edge               bit 9 leading edge
135 
136        W9    inhibit IRQ on Device Status     enable IRQ on Device Status
137                bit 10 trailing edge             bit 10 trailing edge
138 
139        W10   DEV CMD polarity is normal       DEV CMD polarity is inverted
140 
141    The line printer cable is wired with this configuration:
142 
143      Interface Connection                      Printer Connection
144      ----------------------------------------  ------------------
145      Data Out bit 15                           DATA 1
146      Data Out bit 14                           DATA 2
147      Data Out bit 13                           DATA 3
148      Data Out bit 12                           DATA 4
149      Data Out bit 11                           DATA 5
150      Data Out bit 10                           DATA 6
151      Data Out bit  9                           DATA 7
152      Device Command                            STROBE
153      Device Flag                               ~DEMAND
154      Control Word bit 10                       PAPER INSTRUCTION
155      Device Status bit 9                       ONLINE
156      Device Status bit 10                      ONLINE
157      Device Status bit 11                      ~READY
158      Device Status bit 12                      VFU CHANNEL 12
159      Device Status bit 13                      VFU CHANNEL 9
160      Device End                                ~ONLINE
161      Set Transfer Error Flip-Flop              (no connection)
162      Master Clear                              MASTER CLEAR
163 
164      Internal Connection                       Action
165      ----------------------------------------  --------------------------------
166      300 pF across the Write Delay One-Shot    sets 1.2 uS pulse width
167      1500 pF across the Master Clear One-Shot  sets 5.1 uS pulse width
168      jumper W4 shorted                         none (Status 8 is not connected)
169      jumper W8 shorted                         enables IRQ when ONLINE asserts
170      jumper W9 shorted                         enables IRQ when ONLINE denies
171 
172    DEMAND is wired inversely to Device Flag, so DEMAND assertion is Device Flag
173    denial and vice versa.  DEMAND dropping after STROBE assertion corresponds
174    with Device Flag asserting after Device Command asserts, and DEMAND asserting
175    after the printer is ready corresponds to Device Flag denying.
176 
177    Similarly, ONLINE is wired inversely to Device End, so the printer going
178    offline asserts Device End, and READY is wired inversely to Device Status bit
179    11, so bit 11 is asserted when the printer is not ready (either powered off
180    or out of paper).
181 
182    The READY and ONLINE signals indicate the current state of the printer.
183    READY asserts when printer power is on, no alarm condition (paper out, tape
184    format error) exits, and the VFU has been initialized.  ONLINE asserts when
185    READY is asserted and the Online button is pressed.  Therefore:
186 
187      ~ONLINE * ~READY = paper out or VFU error
188      ~ONLINE *  READY = paper loaded and offline
189       ONLINE * ~READY = (prohibited)
190       ONLINE *  READY = paper loaded and online
191 
192    The printer DEMAND signal asserts when the printer is ready for data and
193    denies when it is printing or slewing.  It also denies when the printer goes
194    offline.  DEMAND is cross-connected to the Device Flag differential input,
195    so that DEV FLAG is the complement of DEMAND, i.e., it asserts when the
196    printer is busy and denies when the printer is available.
197 
198    The normal sequence starts with DEMAND asserted (i.e., DEV FLAG denied).  The
199    interface asserts STROBE (DEV CMD), the printer denies DEMAND (asserts DEV
200    FLAG), the interface denies STROBE (DEV CMD), and the printer then asserts
201    DEMAND (denies DEV FLAG) when the character data is accepted or the print
202    operation is complete.
203 
204    When the ON/OFFLINE button on the printer is pressed, the printer will not go
205    offline (i.e., deny the ONLINE signal) if there are characters in the print
206    buffer.  Instead, the offline condition is held off until an internal "allow
207    offline" signal asserts.  This occurs when the print buffer is empty and the
208    print cycle is inactive.  When ONLINE denies, DEMAND is inhibited, so the
209    interface waits at the end of the handshake sequence for DEV FLAG to deny.
210    Note that this holds off SR to the Multiplexer Channel, so the channel
211    program waits.  When the printer is put back online, DEMAND asserts, so DEV
212    FLAG denies, the handshake completes, SR asserts, and the interface returns
213    to the idle condition to await the next command.
214 
215    This has implications for the SET OFFLINE and DETACH commands if they are
216    issued while the print buffer contains data or the printer unit is busy
217    executing a print action.
218 
219    The SET LP OFFLINE and DETACH LP commands check for data in the print buffer
220    or a print operation in progress.  If either condition is true, they set
221    their respective deferred-action flags and display "Command not completed."
222    A SHOW LP will show that the device is still online and attached.  Once
223    simulation is resumed and the print operation completes, the printer is set
224    offline or detached as requested.  No console message reports this, as it is
225    assumed that the executing program will detect the condition and report
226    accordingly.  A subsequent SHOW LP will indicate the new status.
227 
228    A SET LP ONLINE command when a deferred-action flag is set simply clears the
229    flag, which cancels the pending offline or detach condition.
230 
231    A RESET LP command also clears the deferred-action flags and so clears any
232    pending offline or detach.  However, it also clears the print buffer and
233    terminates any print action in progress, so a SET LP OFFLINE or DETACH LP
234    will succeed if issued subsequently.
235 
236 
237    The Universal Interface responds to both direct I/O and programmed I/O from
238    the Multiplexer Channel, as follows:
239 
240    Control Word Format (CIO and SIO Control word 2):
241 
242        0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
243      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
244      | M | R | irq reset | A |  device control   | X | S | B | I | T | device
245      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
246      | M | R | irq reset | A |   function    | E | X | S | B | I | T | DHA
247      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
248      | M | R | irq reset | A | -   -   -   - | F | X | S | B | I | T | printer
249      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
250 
251    Where:
252 
253      M = programmed master clear
254      R = reset interrupts
255      A = acquire data from device
256      E = enable diagnostic hardware assembly function
257      F = printer output character/format (0/1) code
258      X = enable data transfer interrupt
259      S = interrupt/device (0/1) status
260      B = word/byte (0/1) transfer
261      I = enable interrupts
262      T = enable transfer timer
263 
264    IRQ Reset:
265 
266      000 = none
267      001 = transfer timer and transfer error
268      010 = I/O system
269      011 = clear interface
270      100 = data transfer completion
271      101 = line ready (device status bit 8)
272      110 = ready (device status bit 9)
273      111 = not ready (device status bit 10)
274 
275    DHA Function:
276 
277      0000 = clear configuration registers (installs jumpers)
278      0001 = remove jumper J2W2
279      0010 = assert DEV END
280      0011 = remove jumper J2W8
281      0100 = set Transfer Error flip-flop
282      0101 = remove jumper J2W4
283      0110 = remove jumper J2W10
284      0111 = remove jumper J2W6
285      1000 = DEV FLAG follows DEV CMD or Control 6 (0/1)
286      1001 = remove jumper J2W5
287      1010 = assert CLEAR INTERFACE
288      1011 = remove jumper J2W9
289      1100 = Status 8-10 follow Control 6-8
290               or master clear, power on, and power fail (0/1)
291      1101 = remove jumper J2W1
292      1110 = remove jumper J2W3
293      1111 = remove jumper J2W7
294 
295    Bits 6-10 are the device control bits.  For the DHA, control bit 10 enables
296    the function decoder.  The decoder is combinatorial and the registers are
297    "ones-catching," so the function field must be set and then maintained while
298    bit 10 is asserted and then denied.  For the line printer, control bit 10
299    indicates whether character data (0) or format commands (1) will be output.
300    Programmed control word 1 (IOCW) is not used.
301 
302    Setting control bit 15 starts (or restarts) the five-second transfer timer.
303    Issuing a Reset Transfer Timer and Transfer Error Interrupts, a Master Reset,
304    or a Reset Interrupts command stops the timer.  If the timer expires, a
305    Transfer Timer interrupt occurs.
306 
307 
308    Status Word Format (TIO and SIO Status):
309 
310        0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
311      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
312      | S | D | I | seqct | F | 0 | 0 |  dev irq  | X | C | Y | E | T | interrupt
313      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
314      | S | D | I | seqct | F | 1 | 0 |         device status         | device
315      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
316      | S | D | I | seqct | F | 1 | 0 | - | L | L | N | V | U | - | - | printer
317      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
318 
319    Where:
320 
321      S = SIO OK
322      D = direct I/O OK
323      I = interrupt pending
324      F = device flag
325      X = data transfer interrupt
326      C = clear interface interrupt
327      Y = I/O system interrupt
328      E = transfer error interrupt
329      T = transfer timer interrupt
330      L = online
331      N = not ready
332      V = VFU channel 12
333      U = VFU channel 9
334 
335    Sequence Counter:
336 
337      00 = idle
338      10 = request to device issued for word or 1st byte
339      11 = device operation started
340      01 = request to device issued for 2nd byte
341 
342    Device Interrupt Request Bits:
343 
344       8 = device status bit 8 interrupt (not used by the printer)
345       9 = device status bit 9 interrupt (printer went online)
346      10 = device status bit 10 interrupt (printer went offline)
347 
348    Control word bit 12 determines whether the interrupt status word (0) or the
349    device status word (1) is returned.
350 
351    A transfer error occurs when the channel asserts XFERERROR to abort a
352    transfer for a parity error or memory address out of bounds.  Device status
353    bits assume the logic 1 state with the inputs disconnected (e.g., power off).
354 
355 
356    Output Data Word Format (WIO and SIO Write):
357 
358        0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
359      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
360      | - |    1st ASCII character    | - |    2nd ASCII character    | byte mode
361      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
362      | -   -   -   -   -   -   -   - | - |      ASCII character      | word mode
363      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
364      | -   -   -   -   -   -   -   - | - |        format word        | format
365      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
366 
367    The printer only uses seven data bits, so the MSB of each byte is ignored.
368    If the printer's line length is exceeded during write operations, the
369    buffered line will be printed, the paper will be advanced one line, and the
370    buffer will be cleared to accept the character causing the overflow.
371 
372 
373    Implementation notes:
374 
375     1. The Clear Interface Logic (CLRIL) signal inhibits SIO OK status.  The
376        Card Reader/Punch Interface version of the UI does not assert the CLRIL
377        signal in response to external CLEAR INTERFACE assertion; only a transfer
378        error does.  Therefore, the SIO OK signal is not inhibited while the
379        clear interface interrupt is present.  For this version, the external
380        Clear Interface signal sets the CLR INF flip-flop, which sets the (C) bit
381        in the status register and generates an interrupt, but otherwise has no
382        effect on the interface logic.
383 
384        The standard version of the UI asserts CLRIL, and therefore inhibits SIO
385        OK, for both the clear interface and transfer error conditions.
386 
387     2. Because the interface uses differential interface logic, the external
388        sense of a signal may be inverted by exchanging the + and - connections.
389        To accommodate this in simulation, separate variables are used for the
390        internal and external states.  For example, "device_command" represents
391        the internal state, while "device_command_out" represents the external
392        state (which may be inverted from the internal state if jumper J2W10 is
393        installed).
394 
395     3. The Universal Interface supports terminating channel transfers by
396        asserting DEVEND, and the line printer cable connects the ONLINE output
397        inversely to the Device End input, so that it is asserted when the
398        printer is offline.  However, when the printer goes offline, it holds its
399        DEMAND line denied, which keeps Device Flag asserted.  This hangs the
400        transfer handshake in the Device_Flag_1/2 state until the printer goes
401        online again.  As the interface recognizes Device End only in the
402        Device_Command_1/2 state, DEVEND will never be asserted to terminate a
403        channel transfer.
404 
405     4. In hardware, a paper-out condition is noted, but the line printer does
406        not go offline until the top of the next form is reached.  This ensures
407        that the current page is completed first.  By contrast, a torn-paper
408        condition causes the printer to go offline at the completion of the
409        current line.  In simulation, a DETACH is handled as a torn-paper
410        condition.
411 
412     5. Slewing in expanded mode is performed by appending CR LF pairs to the
413        character buffer and then writing the combined buffer to the printer
414        output file.  The size of the buffer must accommodate the largest print
415        line (136 characters) plus the largest possible slew (144 lines * 2
416        characters per line).
417 */
418 
419 
420 
421 #include "hp3000_defs.h"
422 #include "hp3000_io.h"
423 
424 
425 
426 /* Interface program constants */
427 
428 #define PULSE_TIME          uS (8)              /* device command pulse = 8 microseconds */
429 #define XFER_TIME           S (5)               /* transfer timeout = 5 seconds */
430 
431 /* Printer program constants */
432 
433 #define CR                  '\r'                /* carriage return */
434 #define LF                  '\n'                /* line feed */
435 #define FF                  '\f'                /* form feed */
436 #define DEL                 '\177'              /* delete */
437 
438 #define DATA_MASK           0177u               /* printer uses only 7 bits for data */
439 #define FORMAT_VFU          0100u               /* printer VFU selector */
440 #define FORMAT_MASK         0117u               /* printer format command mask for 12-channel VFU */
441 #define FORMAT_VFU_8_MASK   0107u               /* printer format command mask for 8-channel VFU */
442 
443 #define FORMAT_SUPPRESS     0000u               /* format code to slew 0 lines */
444 #define FORMAT_VFU_CHAN_1   0100u               /* format code to slew to VFU channel 1 */
445 #define FORMAT_VFU_BIAS     0077u               /* bias converting from format code to channel number */
446 
447 #define VFU_MAX             144                 /* maximum number of VFU form lines */
448 #define VFU_SIZE            (VFU_MAX + 1)       /* size of the VFU array */
449 #define LINE_SIZE           256                 /* size of the character array used to read the VFU file */
450 
451 #define VFU_WIDTH           12                  /* maximum number of VFU channels */
452 
453 #define VFU_CHANNEL_1       04000u              /* top of form */
454 #define VFU_CHANNEL_2       02000u              /* bottom of form */
455 #define VFU_CHANNEL_3       01000u              /* single space */
456 #define VFU_CHANNEL_4       00400u              /* double space */
457 #define VFU_CHANNEL_5       00200u              /* triple space */
458 #define VFU_CHANNEL_6       00100u              /* half page */
459 #define VFU_CHANNEL_7       00040u              /* quarter page */
460 #define VFU_CHANNEL_8       00020u              /* sixth page */
461 #define VFU_CHANNEL_9       00010u              /* bottom of form */
462 #define VFU_CHANNEL_10      00004u              /* (unassigned) */
463 #define VFU_CHANNEL_11      00002u              /* (unassigned) */
464 #define VFU_CHANNEL_12      00001u              /* (unassigned) */
465 
466 #define CHARS_MAX           136                 /* maximum number of characters buffered by the printers */
467 
468 #define BUFFER_SIZE         (CHARS_MAX + VFU_MAX * 2)   /* max chars + max VFU * 2 (CR LF) */
469 
470 #define PRINTER_JUMPERS     (W4 | W8 | W9)      /* jumpers J2W4, J2W8, and J2W9 are installed */
471 
472 
473 /* Debug flags */
474 
475 #define DEB_CMD             (1u << 0)           /* trace controller commands */
476 #define DEB_CSRW            (1u << 1)           /* trace command initiations and completions */
477 #define DEB_STATE           (1u << 2)           /* trace device handshake state changes */
478 #define DEB_SERV            (1u << 3)           /* trace channel service scheduling calls */
479 #define DEB_XFER            (1u << 4)           /* trace data transmissions */
480 #define DEB_IOB             (1u << 5)           /* trace I/O bus signals and data words */
481 
482 
483 /* Device flags */
484 
485 #define DEV_DIAG_SHIFT      (DEV_V_UF + 0)              /* Diagnostic Hardware Assembly is installed */
486 #define DEV_REALTIME_SHIFT  (DEV_V_UF + 1)              /* timing mode is realistic */
487 
488 #define DEV_DIAG            (1u << DEV_DIAG_SHIFT)      /* diagnostic mode flag */
489 #define DEV_REALTIME        (1u << DEV_REALTIME_SHIFT)  /* realistic timing flag */
490 
491 
492 /* Printer unit flags.
493 
494    UNIT_V_UF +  7   6   5   4   3   2   1   0
495               +---+---+---+---+---+---+---+---+
496               | - | - | - | O | E |   model   |
497               +---+---+---+---+---+---+---+---+
498 
499    Where:
500 
501      O = offline
502      E = expanded output
503 */
504 
505 #define UNIT_MODEL_SHIFT    (UNIT_V_UF + 0)     /* printer model ID */
506 #define UNIT_EXPAND_SHIFT   (UNIT_V_UF + 3)     /* printer uses expanded output */
507 #define UNIT_OFFLINE_SHIFT  (UNIT_V_UF + 4)     /* printer is offline */
508 
509 #define UNIT_MODEL_MASK     0000007u            /* model ID mask */
510 
511 #define UNIT_MODEL          (UNIT_MODEL_MASK << UNIT_MODEL_SHIFT)
512 #define UNIT_EXPAND         (1u << UNIT_EXPAND_SHIFT)
513 #define UNIT_OFFLINE        (1u << UNIT_OFFLINE_SHIFT)
514 #define UNIT_ONLINE         0
515 
516 #define UNIT_2607           (HP_2607 << UNIT_MODEL_SHIFT)
517 #define UNIT_2613           (HP_2613 << UNIT_MODEL_SHIFT)
518 #define UNIT_2617           (HP_2617 << UNIT_MODEL_SHIFT)
519 #define UNIT_2618           (HP_2618 << UNIT_MODEL_SHIFT)
520 
521 
522 /* Unit flags accessor */
523 
524 #define GET_MODEL(f)        ((PRINTER_TYPE) (((f) >> UNIT_MODEL_SHIFT) & UNIT_MODEL_MASK))
525 
526 
527 /* Unit references */
528 
529 #define xfer_unit           lp_unit [0]         /* transfer handshake unit */
530 
531 #define xfer_uptr           (&lp_unit [0])      /* transfer handshake unit pointer */
532 #define pulse_uptr          (&lp_unit [1])      /* pulse timer unit pointer */
533 #define timer_uptr          (&lp_unit [2])      /* transfer timer unit pointer */
534 
535 static const char *const unit_name [] = {       /* unit names, indexed by unit number */
536     "Transfer",
537     "Pulse",
538     "Watchdog"
539     };
540 
541 
542 /* Printer types */
543 
544 typedef enum {
545     HP_2607,                                    /* HP 2607A */
546     HP_2613,                                    /* HP 2613A */
547     HP_2617,                                    /* HP 2617A */
548     HP_2618                                     /* HP 2618A */
549     } PRINTER_TYPE;
550 
551 
552 /* Printer locality states */
553 
554 typedef enum {
555     Offline,                                    /* printer is going offline */
556     Online                                      /* printer is going online */
557     } LOCALITY;
558 
559 
560 /* Printer properties table.
561 
562    This table contains the characteristics that vary between printer models.
563    The "char_set" field values reflect printer Option 001, 96/128-character set.
564    The "not_ready" field indicates whether a paper fault sets a separate
565    not-ready status or simply takes the printer offline.  The "fault_at_eol"
566    field indicates whether a paper fault is reported at the end of any line or
567    only at the top of the next form.
568 */
569 
570 typedef struct {
571     uint32  line_length;                        /* the maximum number of print positions */
572     uint32  char_set;                           /* the size of the character set */
573     uint32  vfu_channels;                       /* the number of VFU channels */
574     t_bool  not_ready;                          /* TRUE if the printer reports a separate not ready status */
575     t_bool  overprints;                         /* TRUE if the printer supports overprinting */
576     t_bool  autoprints;                         /* TRUE if the printer automatically prints on buffer overflow */
577     t_bool  fault_at_eol;                       /* TRUE if a paper fault is reported at the end of any line */
578     } PRINTER_PROPS;
579 
580 static const PRINTER_PROPS print_props [] = {   /* printer properties, indexed by PRINTER_TYPE */
581 /*     line    char    VFU      not     over    auto   fault  */
582 /*    length   set   channels  ready   prints  prints  at EOL */
583 /*    ------  -----  --------  ------  ------  ------  ------ */
584     {  132,   128,      8,     FALSE,  FALSE,  TRUE,   FALSE  },    /* HP_2607 */
585     {  136,    96,     12,     TRUE,   TRUE,   FALSE,  TRUE   },    /* HP_2613 */
586     {  136,    96,     12,     TRUE,   TRUE,   FALSE,  TRUE   },    /* HP_2617 */
587     {  132,    96,     12,     TRUE,   TRUE,   FALSE,  TRUE   }     /* HP_2618 */
588     };
589 
590 
591 /* Delay properties table.
592 
593    To support the realistic timing mode, the delay properties table contains
594    timing specifications for the supported printers.  The times represent the
595    delays for mechanical and electronic operations.  Delay values are in event
596    tick counts; macros are used to convert from times to ticks.
597 
598 
599    Implementation notes:
600 
601     1. Although all of the printers operate more slowly with a 96/128-character
602        set installed than with a 64-character set, the times reflect the smaller
603        set size.  Also, some models provide different print rates, depending on
604        how many and/or which characters are printed.  These variations are not
605        simulated.
606 */
607 
608 typedef struct {
609     int32  buffer_load;                         /* per-character transfer time */
610     int32  print;                               /* print time */
611     int32  advance;                             /* paper advance time per line */
612     } DELAY_PROPS;
613 
614 static const DELAY_PROPS real_times [] = {      /* real-time delays, indexed by PRINTER_TYPE */
615    /*  buffer                paper   */
616    /*   load      print     advance  */
617    /* ---------  --------  --------- */
618     { uS (12.6), mS (260), mS (40.1) },         /* HP_2607  200 lines per minute */
619     { uS (1.75), mS (183), mS (8.33) },         /* HP_2613  300 lines per minute */
620     { uS (1.75), mS ( 86), mS (6.67) },         /* HP_2617  600 lines per minute */
621     { uS (1.75), mS ( 38), mS (4.76) }          /* HP_2618 1250 lines per minute */
622     };
623 
624 #define LP_BUFFER_LOAD      uS (1)              /* fast per-character transfer time */
625 #define LP_PRINT            mS (1)              /* fast print time */
626 #define LP_ADVANCE          uS (50)             /* fast paper advance time per line */
627 
628 static DELAY_PROPS fast_times =                 /* FASTTIME delays */
629     { LP_BUFFER_LOAD,
630       LP_PRINT,
631       LP_ADVANCE
632     };
633 
634 
635 /* Data transfer handshake sequencer.
636 
637    The sequencer controls the handshake that transfers data between the
638    interface and the device.
639 */
640 
641 typedef enum {
642     Idle,                                       /* the device is idle */
643     Device_Command_1,                           /* device command is asserted for a word or first byte */
644     Device_Flag_1,                              /* device flag is asserted for a word or first byte */
645     Device_Command_2,                           /* device command is asserted for the second byte */
646     Device_Flag_2                               /* device flag is asserted for the second byte */
647     } SEQ_STATE;
648 
649 static const char *const state_name [] = {      /* sequencer state names, indexed by SEQ_STATE */
650     "Idle",
651     "Device Command 1",
652     "Device Flag 1",
653     "Device Command 2",
654     "Device Flag 2"
655     };
656 
657 
658 /* Configuration jumpers.
659 
660    Various aspects of interface operation are configured by installing or
661    removing jumpers contained within the connector hood of the device
662    interconnection cable.  Jumpers are simulated by bits in the "jumper_set"
663    word, with a 1 value representing "installed" and a 0 value representing
664    "removed" (although in hardware installing a jumper pulls the corresponding
665    signal down to 0).
666 
667    The Diagnostic Hardware Assembly provides programmatic configuration of the
668    jumpers.  All jumpers are installed by executing a "clear registers" command,
669    and then individual jumpers may be removed by executing the corresponding
670    "remove jumper J2Wn" commands.  This is simulated by setting all of the bits
671    in the "jumper_set" word and then selectively ANDing the word with
672    complemented constants from the "jumper_map" table, thereby clearing
673    individual bits.
674 
675 
676    Implementation notes:
677 
678     1. In simulation, jumper W5 is not used.  The DATA IN signals are always
679        latched when DEV FLAG asserts.  Always-transparent operation is not
680        provided.
681 
682     2. In hardware, DHA control word bits 6-9 are wired to decoder input bits
683        0-3.  As the 3000 uses decreasing bit-number significance, while the
684        decoder chip uses increasing bit-number significance, the order of the
685        functions in the "jumper_map" table reflect the reversed bit order of the
686        index.  For example, index 0001 contains the function for decoder output
687        8 (1000).
688 */
689 
690 #define W1                  (1u << 0)           /* SR set by PCONTSTB/Device Status bit 11 */
691 #define W2                  (1u << 1)           /* +/- edge of Device Flag advances sequence counter from 1 to 2 */
692 #define W3                  (1u << 2)           /* Device Command operates in response/pulse mode */
693 #define W4                  (1u << 3)           /* inhibit/enable interrupt on STAT8 + edge */
694 #define W5                  (1u << 4)           /* Data In latched on sequence count 1 and 3/always transparent */
695 #define W6                  (1u << 5)           /* -/+ edge of Device Flag advances sequence counter from 2 to 3 */
696 #define W7                  (1u << 6)           /* normal/test write transfer */
697 #define W8                  (1u << 7)           /* inhibit/enable interrupt on STAT9 + edge */
698 #define W9                  (1u << 8)           /* inhibit/enable interrupt on STAT10 - edge */
699 #define W10                 (1u << 9)           /* Device Command same/inverted polarity as Data Out */
700 
701 #define J2W1_INSTALLED      ((jumper_set & W1)  != 0)
702 #define J2W2_INSTALLED      ((jumper_set & W2)  != 0)
703 #define J2W3_INSTALLED      ((jumper_set & W3)  != 0)
704 #define J2W4_INSTALLED      ((jumper_set & W4)  != 0)
705 #define J2W5_INSTALLED      ((jumper_set & W5)  != 0)
706 #define J2W6_INSTALLED      ((jumper_set & W6)  != 0)
707 #define J2W7_INSTALLED      ((jumper_set & W7)  != 0)
708 #define J2W8_INSTALLED      ((jumper_set & W8)  != 0)
709 #define J2W9_INSTALLED      ((jumper_set & W9)  != 0)
710 #define J2W10_INSTALLED     ((jumper_set & W10) != 0)
711 
712 static const uint32 jumper_map [16] = {         /* jumper removal map, indexed by CN_DHA_FN */
713      0,                                         /*   0000 = (unaffected) */
714     ~W2,                                        /*   0001 = remove jumper J2W2 */
715      0,                                         /*   0010 = (unaffected) */
716     ~W8,                                        /*   0011 = remove jumper J2W8 */
717      0,                                         /*   0100 = (unaffected) */
718     ~W4,                                        /*   0101 = remove jumper J2W4 */
719     ~W10,                                       /*   0110 = remove jumper J2W10 */
720     ~W6,                                        /*   0111 = remove jumper J2W6 */
721      0,                                         /*   1000 = (unaffected) */
722     ~W5,                                        /*   1001 = remove jumper J2W5 */
723      0,                                         /*   1010 = (unaffected) */
724     ~W9,                                        /*   1011 = remove jumper J2W9 */
725      0,                                         /*   1100 = (unaffected) */
726     ~W1,                                        /*   1101 = remove jumper J2W1 */
727     ~W3,                                        /*   1110 = remove jumper J2W3 */
728     ~W7                                         /*   1111 = remove jumper J2W7 */
729     };
730 
731 
732 /* Diagnostic Hardware Assembly control register.
733 
734        0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
735      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
736      | M | F | S | -   -   - |          jumpers J2W10-J2W1           |
737      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
738 
739    Where:
740 
741      M = master reset has occurred
742      F = device flag follows device command/control 6 (0/1)
743      S = status 8-10 follow control 6-8/master clear-power on-power fail (0/1)
744 
745 
746    Implementation notes:
747 
748     1. Jumper bits are defined as 0 = removed and 1 = installed.  This is
749        the opposite of the DHA hardware, for which a zero output "installs" a
750        jumper.
751 
752     2. Jumpers J2W10-J2W1, which are stored in the "jumpers" array, are mirrored
753        in the jumper control register to allow the diagnostic to test the full
754        set of jumpers with single assertions.  Otherwise, ten assertions would
755        be necessary for each test.
756 */
757 
758 #define DHA_MR              0100000u            /* (M) a master reset has occurred */
759 #define DHA_FLAG_SEL        0040000u            /* (F) device flag follows control 6 */
760 #define DHA_STAT_SEL        0020000u            /* (S) status 8-10 follow master clear-power on-power fail */
761 #define DHA_JUMPER_MASK     0001777u            /* J2Wx jumpers mask */
762 #define DHA_CLEAR           0001777u            /* control register clear value (all jumpers installed) */
763 
764 
765 /* Interface control word.
766 
767        0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
768      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
769      | M | R | irq reset | A |  device control   | X | S | B | I | T | device
770      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
771      | M | R | irq reset | A |   function    | E | X | S | B | I | T | DHA
772      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
773 */
774 
775 #define CN_MR               0100000u            /* (M) master reset */
776 #define CN_RIN              0040000u            /* (R) reset interrupt */
777 #define CN_RIN_MASK         0034000u            /* reset interrupt request selector mask */
778 #define CN_RIN_XFR_TMR      0004000u            /* reset watchdog timer and transfer error interrupts */
779 #define CN_ACQUIRE          0002000u            /* (A) acquire data from device */
780 #define CN_DHA_FN_MASK      0001700u            /* diagnostic hardware assembly function mask */
781 #define CN_DHA_ST_MASK      0001600u            /* diagnostic hardware assembly status mask */
782 #define CN_DHA_FLAG         0001000u            /* diagnostic hardware assembly device flag value */
783 #define CN_DHA_FN_ENABLE    0000040u            /* (E) enable diagnostic hardware assembly function */
784 #define CN_XFR_IRQ_ENABLE   0000020u            /* (X) enable data transfer interrupt */
785 #define CN_DEVSTAT          0000010u            /* (S) interrupt/device (0/1) status */
786 #define CN_BYTE_XFER        0000004u            /* (B) word/byte (0/1) transfer */
787 #define CN_IRQ_ENABLE       0000002u            /* (I) enable interrupts */
788 #define CN_XFR_TMR_ENABLE   0000001u            /* (T) enable data transfer timer */
789 
790 #define CN_RIN_SHIFT        11                  /* reset interrupt request alignment shift */
791 #define CN_DHA_ST_SHIFT      7                  /* diagnostic hardware assembly status alignment shift */
792 #define CN_DHA_FN_SHIFT      6                  /* diagnostic hardware assembly function alignment shift */
793 
794 #define CN_RESET(c)         (((c) & CN_RIN_MASK)    >> CN_RIN_SHIFT)
795 #define CN_DHA_ST(c)        (((c) & CN_DHA_ST_MASK) >> CN_DHA_ST_SHIFT)
796 #define CN_DHA_FN(c)        (((c) & CN_DHA_FN_MASK) >> CN_DHA_FN_SHIFT)
797 
798 static const char *const dha_fn_name [16] = {   /* DHA function names, indexed by CN_DHA_FN */
799     "clear registers",                          /*   0000 = clear registers (installs jumpers) */
800     "remove J2W2",                              /*   0001 = remove jumper J2W2 */
801     "assert DEVEND",                            /*   0010 = assert Device End */
802     "remove J2W8",                              /*   0011 = remove jumper J2W8 */
803     "set transfer error",                       /*   0100 = set Transfer Error flip-flop */
804     "remove J2W4",                              /*   0101 = remove jumper J2W4 */
805     "remove J2W10",                             /*   0110 = remove jumper J2W10 */
806     "remove J2W6",                              /*   0111 = remove jumper J2W6 */
807     "control 6 drives device flag",             /*   1000 = connect device flag to control bit 6 */
808     "remove J2W5",                              /*   1001 = remove jumper J2W5 */
809     "assert CLRIF",                             /*   1010 = assert Clear Interface */
810     "remove J2W9",                              /*   1011 = remove jumper J2W9 */
811     "CLR/PON/PF drive status 8-10",             /*   1100 = connect status 8-10 to master clear/power on/power fail */
812     "remove J2W1",                              /*   1101 = remove jumper J2W1 */
813     "remove J2W3",                              /*   1110 = remove jumper J2W3 */
814     "remove J2W7"                               /*   1111 = remove jumper J2W7 */
815     };
816 
817 static const char *const reset_irq_name [8] = { /* reset interrupt request names, indexed by CN_RESET */
818     "",                                         /*   000 = none */
819     " | reset timer/xfer error irq",            /*   001 = watchdog timer and transfer error */
820     " | reset I/O system irq",                  /*   010 = I/O system */
821     " | reset clear interface irq",             /*   011 = clear interface */
822     " | reset data xfer irq",                   /*   100 = data transfer completion */
823     " | reset status 8 irq",                    /*   101 = device status 8 */
824     " | reset status 9 irq",                    /*   110 = device status 9 */
825     " | reset status 10 irq"                    /*   111 = device status 10 */
826     };
827 
828 static const BITSET_NAME dha_control_names [] = {       /* DHA control word names */
829     "master clear",                                     /*   bit  0 */
830     "clear interrupts",                                 /*   bit  1 */
831     NULL,                                               /*   bit  2 */
832     NULL,                                               /*   bit  3 */
833     NULL,                                               /*   bit  4 */
834     "acquire data",                                     /*   bit  5 */
835     "DC6",                                              /*   bit  6 */
836     "DC7",                                              /*   bit  7 */
837     "DC8",                                              /*   bit  8 */
838     "DC9",                                              /*   bit  9 */
839     "enable function",                                  /*   bit 10 */
840     "enable data xfer interrupt",                       /*   bit 11 */
841     "\1device status\0interrupt status",                /*   bit 12 */
842     "\1byte xfer\0word xfer",                           /*   bit 13 */
843     "enable interrupts",                                /*   bit 14 */
844     "enable transfer timer"                             /*   bit 15 */
845     };
846 
847 static const BITSET_FORMAT dha_control_format =         /* names, offset, direction, alternates, bar */
848     { FMT_INIT (dha_control_names, 0, msb_first, has_alt, no_bar) };
849 
850 
851 /* Printer control word.
852 
853        0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
854      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
855      | M | R | irq reset | -   -   -   -   - | F | X | S | B | I | T | printer
856      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
857 */
858 
859 #define CN_FORMAT           0000040u            /* printer output character/format (0/1) code */
860 
861 static const BITSET_NAME prt_control_names [] = {       /* Printer control word names */
862     "master clear",                                     /*   bit  0 */
863     "clear interrupts",                                 /*   bit  1 */
864     NULL,                                               /*   bit  2 */
865     NULL,                                               /*   bit  3 */
866     NULL,                                               /*   bit  4 */
867     "acquire data",                                     /*   bit  5 */
868     NULL,                                               /*   bit  6 */
869     NULL,                                               /*   bit  7 */
870     NULL,                                               /*   bit  8 */
871     NULL,                                               /*   bit  9 */
872     "\1format\0character",                              /*   bit 10 */
873     "enable data xfer interrupt",                       /*   bit 11 */
874     "\1device status\0interrupt status",                /*   bit 12 */
875     "\1byte xfer\0word xfer",                           /*   bit 13 */
876     "enable interrupts",                                /*   bit 14 */
877     "enable transfer timer"                             /*   bit 15 */
878     };
879 
880 static const BITSET_FORMAT prt_control_format =         /* names, offset, direction, alternates, bar */
881     { FMT_INIT (prt_control_names, 0, msb_first, has_alt, no_bar) };
882 
883 
884 /* Interface status word.
885 
886        0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
887      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
888      | S | D | I | seqct | F | 0 | 0 |  dev irq  | X | C | Y | E | T | interrupt
889      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
890      | S | D | I | seqct | F | 1 | 0 |         device status         | device
891      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
892 
893 
894    Implementation notes:
895 
896     1. The entry for bit 6 of the interrupt status names formatting array is
897        given in the alternate form to print the "interrupt status" string when
898        the bit is zero.
899 */
900 
901 #define ST_SIO_OK           0100000u            /* (S) SIO OK to use */
902 #define ST_DIO_OK           0040000u            /* (D) direct I/O OK to use */
903 #define ST_IRQ_PENDING      0020000u            /* (I) interrupt pending */
904 #define ST_SEQ_COUNT_0      0000000u            /* sequence count 0 (00) */
905 #define ST_SEQ_COUNT_1      0010000u            /* sequence count 1 (10) */
906 #define ST_SEQ_COUNT_2      0014000u            /* sequence count 2 (11) */
907 #define ST_SEQ_COUNT_3      0004000u            /* sequence count 3 (01) */
908 #define ST_DEVFLAG          0002000u            /* (F) device flag */
909 #define ST_DEVSTAT          0001000u            /* interrupt/device (0/1) status */
910 #define ST_DEVIRQ_MASK      0000340u            /* device interrupt request mask */
911 #define ST_ST8_IRQ          0000200u            /* device status 8 interrupt */
912 #define ST_DHA_MR           0000200u            /* diagnostic hardware assembly status 8 (master clear) */
913 #define ST_ST9_IRQ          0000100u            /* device status 9 interrupt */
914 #define ST_DHA_PON          0000100u            /* diagnostic hardware assembly status 9 (power on) */
915 #define ST_ST10_IRQ         0000040u            /* device status 10 interrupt */
916 #define ST_DHA_NOT_PF       0000040u            /* diagnostic hardware assembly status 10 (~power fail) */
917 #define ST_DHA_DEVSTAT_MASK 0000037u            /* diagnostic hardware assembly status 11-15 mask */
918 #define ST_XFR_IRQ          0000020u            /* (X) data transfer interrupt */
919 #define ST_ST11_SR          0000020u            /* device status 11 service request */
920 #define ST_CLRIF_IRQ        0000010u            /* (C) clear interface interrupt */
921 #define ST_IOSYS_IRQ        0000004u            /* (Y) I/O system interrupt */
922 #define ST_XFERERR_IRQ      0000002u            /* (E) transfer error interrupt */
923 #define ST_XFR_TMR_IRQ      0000001u            /* (T) transfer timer interrupt */
924 
925 #define ST_DEVIRQ_SHIFT     5                   /* device status 8-10 interrupt request alignment shift */
926 
927 #define ST_DEVIRQ(n)        ((n) << ST_DEVIRQ_SHIFT & ST_DEVIRQ_MASK)
928 
929 #define ST_CLRIL            (ST_CLRIF_IRQ | ST_XFERERR_IRQ) /* conditions that assert the CLRIL signal */
930 
931 static const uint32 sequence_counter [] = {     /* externally visible sequencer values, indexed by SEQ_STATE */
932     ST_SEQ_COUNT_0,                             /*   00 = Idle */
933     ST_SEQ_COUNT_1,                             /*   10 = Device_Command_1 */
934     ST_SEQ_COUNT_2,                             /*   11 = Device_Flag_1 */
935     ST_SEQ_COUNT_3,                             /*   01 = Device_Command_2 */
936     ST_SEQ_COUNT_0                              /*   00 = Device_Flag_2 */
937     };
938 
939 static const uint32 reset_irq [8] = {           /* selective reset irq mask values, indexed by CN_RESET */
940     ~0u,                                        /*   000 = none */
941     ~(ST_XFR_TMR_IRQ | ST_XFERERR_IRQ),         /*   001 = watchdog timer and transfer error */
942     ~ST_IOSYS_IRQ,                              /*   010 = I/O system */
943     ~ST_CLRIF_IRQ,                              /*   011 = clear interface */
944     ~ST_XFR_IRQ,                                /*   100 = data transfer completion */
945     ~ST_ST8_IRQ,                                /*   101 = device status 8 */
946     ~ST_ST9_IRQ,                                /*   110 = device status 9 */
947     ~ST_ST10_IRQ                                /*   111 = device status 10 */
948     };
949 
950 static const BITSET_NAME int_status_names [] = {        /* Interrupt status word names */
951     "SIO OK",                                           /*   bit  0 */
952     "DIO OK",                                           /*   bit  1 */
953     "interrupt",                                        /*   bit  2 */
954     "SEQ 1",                                            /*   bit  3 */
955     "SEQ 2",                                            /*   bit  4 */
956     "device flag",                                      /*   bit  5 */
957     "\1\0interrupt status",                             /*   bit  6 */
958     NULL,                                               /*   bit  7 */
959     "status 8",                                         /*   bit  8 */
960     "status 9",                                         /*   bit  9 */
961     "status 10",                                        /*   bit 10 */
962     "data xfer",                                        /*   bit 11 */
963     "clear interface",                                  /*   bit 12 */
964     "system",                                           /*   bit 13 */
965     "transfer error",                                   /*   bit 14 */
966     "transfer timeout"                                  /*   bit 15 */
967     };
968 
969 static const BITSET_NAME dev_status_names [] = {        /* Device status word names */
970     "SIO OK",                                           /*   bit  0 */
971     "DIO OK",                                           /*   bit  1 */
972     "interrupt",                                        /*   bit  2 */
973     "SEQ 1",                                            /*   bit  3 */
974     "SEQ 2",                                            /*   bit  4 */
975     "device flag",                                      /*   bit  5 */
976     "device status",                                    /*   bit  6 */
977     NULL,                                               /*   bit  7 */
978     "DS8",                                              /*   bit  8 */
979     "DS9",                                              /*   bit  9 */
980     "DS10",                                             /*   bit 10 */
981     "DS11",                                             /*   bit 11 */
982     "DS12",                                             /*   bit 12 */
983     "DS13",                                             /*   bit 13 */
984     "DS14",                                             /*   bit 14 */
985     "DS15"                                              /*   bit 15 */
986     };
987 
988 static const BITSET_FORMAT int_status_format =          /* names, offset, direction, alternates, bar */
989     { FMT_INIT (int_status_names, 0, msb_first, has_alt, no_bar) };
990 
991 static const BITSET_FORMAT dev_status_format =          /* names, offset, direction, alternates, bar */
992     { FMT_INIT (dev_status_names, 0, msb_first, no_alt, no_bar) };
993 
994 
995 /* Printer status word.
996 
997        0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
998      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
999      | S | D | I | seqct | F | 1 | 0 | - | L | L | N | V | U | - | - | printer
1000      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1001 */
1002 
1003 #define ST_ONLINE           0000140u            /* online */
1004 #define ST_NOT_READY        0000020u            /* not ready */
1005 #define ST_VFU_12           0000010u            /* VFU channel 12 */
1006 #define ST_VFU_9            0000004u            /* VFU channel 9 */
1007 
1008 static const BITSET_NAME prt_status_names [] = {        /* Printer status word names */
1009     "SIO OK",                                           /*   bit  0 */
1010     "DIO OK",                                           /*   bit  1 */
1011     "interrupt",                                        /*   bit  2 */
1012     "SEQ 1",                                            /*   bit  3 */
1013     "SEQ 2",                                            /*   bit  4 */
1014     "device flag",                                      /*   bit  5 */
1015     "device status",                                    /*   bit  6 */
1016     NULL,                                               /*   bit  7 */
1017     NULL,                                               /*   bit  8 */
1018     "\1online\0offline",                                /*   bit  9 */
1019     NULL,                                               /*   bit 10 */
1020     "\1not ready\0ready",                               /*   bit 11 */
1021     "VFU 12",                                           /*   bit 12 */
1022     "VFU 9"                                             /*   bit 13 */
1023     };
1024 
1025 static const BITSET_FORMAT prt_status_format =          /* names, offset, direction, alternates, bar */
1026     { FMT_INIT (prt_status_names, 2, msb_first, has_alt, no_bar) };
1027 
1028 
1029 /* Interface state */
1030 
1031 static HP_WORD control_word     = 0;            /* control word */
1032 static HP_WORD int_status_word  = 0;            /* interrupt status word (bits 8-15) */
1033 static HP_WORD dev_status_word  = 0;            /* device status word (bits 8-15) */
1034 static HP_WORD read_word        = 0;            /* read word */
1035 static HP_WORD write_word       = 0;            /* write word */
1036 
1037 static SEQ_STATE sequencer  = Idle;             /* data transfer handshake sequencer */
1038 static uint32    jumper_set = PRINTER_JUMPERS;  /* set of configuration jumpers */
1039 
1040 static FLIP_FLOP sio_busy       = CLEAR;        /* SIO busy flip-flop */
1041 static FLIP_FLOP channel_sr     = CLEAR;        /* channel service request flip-flop */
1042 static FLIP_FLOP device_sr      = CLEAR;        /* device service request flip-flop */
1043 static FLIP_FLOP input_xfer     = CLEAR;        /* input transfer flip-flop */
1044 static FLIP_FLOP output_xfer    = CLEAR;        /* output transfer flip-flop */
1045 static FLIP_FLOP read_xfer      = CLEAR;        /* read transfer flip-flop */
1046 static FLIP_FLOP write_xfer     = CLEAR;        /* write transfer flip-flop */
1047 static FLIP_FLOP interrupt_mask = SET;          /* interrupt mask flip-flop */
1048 
1049 static FLIP_FLOP device_command = CLEAR;        /* device command flip-flop */
1050 static FLIP_FLOP device_flag    = CLEAR;        /* device flag flip-flop */
1051 static FLIP_FLOP device_end     = CLEAR;        /* device end flip-flop */
1052 
1053 static HP_WORD data_out           = 0;          /* external DATA OUT signal bus */
1054 static t_bool  device_command_out = FALSE;      /* external DEV CMD signal state */
1055 
1056 static HP_WORD data_in            = 0;          /* external DATA IN signal bus */
1057 static t_bool  device_flag_in     = FALSE;      /* external DEV FLAG signal state */
1058 static t_bool  device_end_in      = FALSE;      /* external DEV END signal state */
1059 
1060 
1061 /* Diagnostic Hardware Assembly state */
1062 
1063 static HP_WORD dha_control_word = 0;            /* Diagnostic Hardware Assembly control word */
1064 static t_bool  power_warning    = FALSE;        /* PFWARN is not asserted to the DHA */
1065 
1066 
1067 /* Printer state */
1068 
1069 static t_bool paper_fault     = TRUE;           /* TRUE if the printer is out of paper */
1070 static t_bool tape_fault      = FALSE;          /* TRUE if there is no punch in a commanded VFU channel */
1071 static t_bool offline_pending = FALSE;          /* TRUE if an offline request is waiting for the printer to finish */
1072 static uint32 overprint_char  = DEL;            /* character to use if overprinted */
1073 static uint32 current_line    = 1;              /* current form line */
1074 static uint32 buffer_index    = 0;              /* current index into the print buffer */
1075 
1076 static uint32 form_length;                      /* form length in lines */
1077 static uint8  buffer [BUFFER_SIZE];             /* character and paper advance buffer */
1078 static uint32 VFU [VFU_SIZE];                   /* vertical format unit tape */
1079 static char   vfu_title [LINE_SIZE];            /* descriptive title of the tape currently in the VFU */
1080 
1081 static int32  punched_char   = 'O';             /* character to display if VFU channel is punched */
1082 static int32  unpunched_char = '.';             /* character to display if VFU channel is not punched */
1083 
1084 static const DELAY_PROPS *dlyptr = &fast_times; /* pointer to the event delay times to use */
1085 
1086 
1087 /* Interface local SCP support routines */
1088 
1089 static CNTLR_INTRF ui_interface;
1090 static t_stat      xfer_service  (UNIT   *uptr);
1091 static t_stat      pulse_service (UNIT   *uptr);
1092 static t_stat      timer_service (UNIT   *uptr);
1093 static t_stat      ui_reset      (DEVICE *dptr);
1094 
1095 
1096 /* Interface local utility routines */
1097 
1098 static t_stat       master_reset          (t_bool programmed_clear);
1099 static void         clear_interface_logic (void);
1100 static void         activate_unit         (UNIT   *uptr);
1101 static void         report_error          (FILE   *stream);
1102 static OUTBOUND_SET set_interrupt         (uint32 interrupt);
1103 static OUTBOUND_SET set_device_status     (uint32 status_mask, uint32 new_status_word);
1104 static OUTBOUND_SET handshake_xfer        (void);
1105 
1106 
1107 /* Diagnostic Hardware Assembly local SCP support routines */
1108 
1109 static t_stat diag_service (UNIT *uptr);
1110 
1111 
1112 /* Diagnostic Hardware Assembly local utility routines */
1113 
1114 static t_stat       diag_reset   (t_bool programmed_clear);
1115 static OUTBOUND_SET diag_control (uint32 control_word);
1116 
1117 
1118 /* Printer local SCP support routines */
1119 
1120 static t_stat lp_service        (UNIT *uptr);
1121 static t_stat lp_attach         (UNIT *uptr, char *cptr);
1122 static t_stat lp_detach         (UNIT *uptr);
1123 
1124 static t_stat lp_set_mode       (UNIT *uptr, int32 value, char  *cptr, void *desc);
1125 static t_stat lp_set_model      (UNIT *uptr, int32 value, char  *cptr, void *desc);
1126 static t_stat lp_set_on_offline (UNIT *uptr, int32 value, char  *cptr, void *desc);
1127 static t_stat lp_set_vfu        (UNIT *uptr, int32 value, char  *cptr, void *desc);
1128 static t_stat lp_show_mode      (FILE *st,   UNIT  *uptr, int32 value, void *desc);
1129 static t_stat lp_show_vfu       (FILE *st,   UNIT  *uptr, int32 value, void *desc);
1130 
1131 
1132 /* Printer local utility routines */
1133 
1134 static t_stat       lp_reset        (t_bool programmed_clear);
1135 static OUTBOUND_SET lp_control      (uint32 control_word);
1136 static t_bool       lp_set_alarm    (UNIT   *uptr);
1137 static t_bool       lp_set_locality (UNIT   *uptr, LOCALITY printer_state);
1138 static t_stat       lp_load_vfu     (UNIT   *uptr, FILE *vf);
1139 static int32        lp_read_line    (FILE   *vf,   char *line, uint32 size);
1140 
1141 
1142 /* Interface SCP data structures */
1143 
1144 
1145 /* Device information block */
1146 
1147 static DIB lp_dib = {
1148     &ui_interface,                              /* device interface */
1149     14,                                         /* device number */
1150     11,                                         /* service request number */
1151     18,                                         /* interrupt priority */
1152     INTMASK_E                                   /* interrupt mask */
1153     };
1154 
1155 
1156 /* Unit list */
1157 
1158 #define UNIT_FLAGS          (UNIT_ATTABLE | UNIT_SEQ | UNIT_EXPAND | UNIT_OFFLINE)
1159 
1160 static UNIT lp_unit [] = {
1161     { UDATA (&xfer_service,  UNIT_FLAGS | UNIT_2617, 0), 0          },
1162     { UDATA (&pulse_service, UNIT_DIS,               0), PULSE_TIME },
1163     { UDATA (&timer_service, UNIT_DIS,               0), XFER_TIME  }
1164     };
1165 
1166 
1167 /* Register list.
1168 
1169    The list consists of the interface registers followed by the Diagnostic
1170    Hardware Assembly registers and then the printer registers.
1171 
1172 
1173    Implementation notes:
1174 
1175     1. The DHA hardware buffers control word bits 6-10 to LEDs.  Inspection and
1176        user confirmation of the control word state is required by the interface
1177        diagnostic.  In simulation, bits 6-10 of the control word are presented
1178        as the CNLED register to allow an ASSERT command to test this subrange of
1179        bits with single commands.
1180 */
1181 
1182 static REG lp_reg [] = {
1183 /*    Macro   Name    Location                  Radix     Width      Offset      Depth            Flags        */
1184 /*    ------  ------  ------------------------  -----  ------------  ------  -------------  ------------------ */
1185     { FLDATA (SIOBSY, sio_busy,                                        0)                                      },
1186     { FLDATA (CHANSR, channel_sr,                                      0)                                      },
1187     { FLDATA (DEVSR,  device_sr,                                       0)                                      },
1188     { FLDATA (INXFR,  input_xfer,                                      0)                                      },
1189     { FLDATA (OUTXFR, output_xfer,                                     0)                                      },
1190     { FLDATA (RDXFR,  read_xfer,                                       0)                                      },
1191     { FLDATA (WRXFR,  write_xfer,                                      0)                                      },
1192     { FLDATA (INTMSK, interrupt_mask,                                  0)                                      },
1193 
1194     { FLDATA (DEVCMD, device_command,                                  0)                                      },
1195     { FLDATA (DEVFLG, device_flag,                                     0)                                      },
1196     { FLDATA (DEVEND, device_end,                                      0)                                      },
1197 
1198     { DRDATA (SEQSTA, sequencer,                            8),                             PV_LEFT            },
1199     { ORDATA (CNTL,   control_word,                        16),                             PV_RZRO            },
1200     { ORDATA (ISTAT,  int_status_word,                     16),                             PV_RZRO            },
1201     { ORDATA (DSTAT,  dev_status_word,                     16),                             PV_RZRO            },
1202     { ORDATA (READ,   read_word,                           16),                             PV_RZRO | REG_X    },
1203     { ORDATA (WRITE,  write_word,                          16),                             PV_RZRO | REG_X    },
1204     { YRDATA (J2WX,   jumper_set,                          10),                             PV_RZRO            },
1205 
1206     { ORDATA (DATOUT, data_out,                            16),                             PV_RZRO | REG_X    },
1207     { ORDATA (DATIN,  data_in,                             16),                             PV_RZRO | REG_X    },
1208 
1209     { FLDATA (DCOUT,  device_command_out,                              0)                                      },
1210     { FLDATA (DFIN,   device_flag_in,                                  0)                                      },
1211     { FLDATA (DENDIN, device_end_in,                                   0)                                      },
1212 
1213       DIB_REGS (lp_dib),
1214 
1215     { ORDATA (DIAGCN, dha_control_word,                    16),                             PV_RZRO            },
1216     { GRDATA (CNLED,  control_word,               2,        5,         5),                  PV_RZRO            },
1217     { FLDATA (PFWARN, power_warning,                                   0)                                      },
1218 
1219     { FLDATA (PFAULT, paper_fault,                                     0)                                      },
1220     { FLDATA (TFAULT, tape_fault,                                      0)                                      },
1221     { FLDATA (OLPEND, offline_pending,                                 0)                                      },
1222 
1223     { DRDATA (PRLINE, current_line,                         8),                             PV_LEFT            },
1224     { DRDATA (BUFIDX, buffer_index,                         8),                             PV_LEFT            },
1225     { BRDATA (PRTBUF, buffer,                     8,        8,               BUFFER_SIZE),  PV_RZRO | REG_A    },
1226     { ORDATA (OVPCHR, overprint_char,                       8),                             PV_RZRO | REG_A    },
1227 
1228     { DRDATA (FORMLN, form_length,                          8),                             PV_LEFT | REG_RO   },
1229     { BRDATA (TITLE,  vfu_title,                  8,        8,                LINE_SIZE),             REG_HRO  },
1230     { BRDATA (VFU,    VFU,                        2,    VFU_WIDTH,            VFU_SIZE),    PV_RZRO | REG_RO   },
1231     { ORDATA (PUNCHR, punched_char,                         8),                             PV_RZRO | REG_A    },
1232     { ORDATA (UNPCHR, unpunched_char,                       8),                             PV_RZRO | REG_A    },
1233 
1234     { DRDATA (BTIME,  fast_times.buffer_load,              24),                             PV_LEFT | REG_NZ   },
1235     { DRDATA (PTIME,  fast_times.print,                    24),                             PV_LEFT | REG_NZ   },
1236     { DRDATA (STIME,  fast_times.advance,                  24),                             PV_LEFT | REG_NZ   },
1237     { DRDATA (POS,    lp_unit [0].pos,                  T_ADDR_W),                          PV_LEFT            },
1238     { DRDATA (UWAIT,  lp_unit [0].wait,                    32),                             PV_LEFT | REG_HRO  },
1239 
1240     { NULL }
1241     };
1242 
1243 
1244 /* Modifier list */
1245 
1246 typedef enum {                                  /* Device modes */
1247     Fast_Time,                                  /*   use optimized timing */
1248     Real_Time,                                  /*   use realistic timing */
1249     Printer,                                    /*   connect to the printer */
1250     Diagnostic                                  /*   connect to the DHA */
1251     } DEVICE_MODES;
1252 
1253 static MTAB lp_mod [] = {
1254 /*    Mask Value    Match Value   Print String       Match String  Validation          Display  Descriptor */
1255 /*    ------------  ------------  -----------------  ------------  ------------------  -------  ---------- */
1256     { UNIT_MODEL,   UNIT_2607,    "2607",            "2607",       &lp_set_model,      NULL,    NULL       },
1257     { UNIT_MODEL,   UNIT_2613,    "2613",            "2613",       &lp_set_model,      NULL,    NULL       },
1258     { UNIT_MODEL,   UNIT_2617,    "2617",            "2617",       &lp_set_model,      NULL,    NULL       },
1259     { UNIT_MODEL,   UNIT_2618,    "2618",            "2618",       &lp_set_model,      NULL,    NULL       },
1260 
1261     { UNIT_OFFLINE, UNIT_OFFLINE, "offline",         "OFFLINE",    &lp_set_on_offline, NULL,    NULL       },
1262     { UNIT_OFFLINE, 0,            "online",          "ONLINE",     &lp_set_on_offline, NULL,    NULL,      },
1263 
1264     { UNIT_EXPAND,  UNIT_EXPAND,  "expanded output", "EXPAND",     NULL,               NULL,    NULL       },
1265     { UNIT_EXPAND,  0,            "compact output",  "COMPACT",    NULL,               NULL,    NULL,      },
1266 
1267 /*    Entry Flags          Value        Print String  Match String  Validation    Display        Descriptor       */
1268 /*    -------------------  -----------  ------------  ------------  ------------  -------------  ---------------- */
1269     { MTAB_XDV,            Fast_Time,   NULL,         "FASTTIME",   &lp_set_mode, NULL,          NULL             },
1270     { MTAB_XDV,            Real_Time,   NULL,         "REALTIME",   &lp_set_mode, NULL,          NULL             },
1271     { MTAB_XDV,            Printer,     NULL,         "PRINTER",    &lp_set_mode, NULL,          NULL             },
1272     { MTAB_XDV,            Diagnostic,  NULL,         "DIAGNOSTIC", &lp_set_mode, NULL,          NULL             },
1273     { MTAB_XDV,            0,           "MODES",      NULL,         NULL,         &lp_show_mode, NULL             },
1274 
1275     { MTAB_XDV,            VAL_DEVNO,   "DEVNO",      "DEVNO",      &hp_set_dib,  &hp_show_dib,  (void *) &lp_dib },
1276     { MTAB_XDV,            VAL_INTMASK, "INTMASK",    "INTMASK",    &hp_set_dib,  &hp_show_dib,  (void *) &lp_dib },
1277     { MTAB_XDV,            VAL_INTPRI,  "INTPRI",     "INTPRI",     &hp_set_dib,  &hp_show_dib,  (void *) &lp_dib },
1278     { MTAB_XDV,            VAL_SRNO,    "SRNO",       "SRNO",       &hp_set_dib,  &hp_show_dib,  (void *) &lp_dib },
1279 
1280     { MTAB_XDV | MTAB_NMO, 1,           "VFU",        NULL,         NULL,         &lp_show_vfu,  NULL             },
1281     { MTAB_XDV | MTAB_NC,  0,           "VFU",        "VFU",        &lp_set_vfu,  &lp_show_vfu,  NULL             },
1282 
1283     { 0 }
1284     };
1285 
1286 
1287 /* Debugging trace list */
1288 
1289 static DEBTAB lp_deb [] = {
1290     { "CMD",   DEB_CMD   },                     /* controller commands */
1291     { "CSRW",  DEB_CSRW  },                     /* interface control, status, read, and write actions */
1292     { "SERV",  DEB_SERV  },                     /* controller unit service scheduling calls */
1293     { "XFER",  DEB_XFER  },                     /* controller data reads and writes */
1294     { "STATE", DEB_STATE },                     /* handshake execution state changes */
1295     { "IOBUS", DEB_IOB   },                     /* interface I/O bus signals and data words */
1296     { NULL,    0         }
1297     };
1298 
1299 
1300 /* Device descriptor */
1301 
1302 DEVICE lp_dev = {
1303     "LP",                                       /* device name */
1304     lp_unit,                                    /* unit array */
1305     lp_reg,                                     /* register array */
1306     lp_mod,                                     /* modifier array */
1307     3,                                          /* number of units */
1308     10,                                         /* address radix */
1309     32,                                         /* address width = 4 GB */
1310     1,                                          /* address increment */
1311     8,                                          /* data radix */
1312     8,                                          /* data width */
1313     NULL,                                       /* examine routine */
1314     NULL,                                       /* deposit routine */
1315     &ui_reset,                                  /* reset routine */
1316     NULL,                                       /* boot routine */
1317     &lp_attach,                                 /* attach routine */
1318     &lp_detach,                                 /* detach routine */
1319     &lp_dib,                                    /* device information block pointer */
1320     DEV_DISABLE | DEV_DEBUG,                    /* device flags */
1321     0,                                          /* debug control flags */
1322     lp_deb,                                     /* debug flag name array */
1323     NULL,                                       /* memory size change routine */
1324     NULL                                        /* logical device name */
1325     };
1326 
1327 
1328 
1329 /* Interface local SCP support routines */
1330 
1331 
1332 
1333 /* Universal interface.
1334 
1335    The universal interface is installed on the IOP and Multiplexer Channel buses
1336    and receives direct and programmed I/O commands from the IOP and Multiplexer
1337    Channel, respectively.  In simulation, the asserted signals on the buses are
1338    represented as bits in the inbound_signals set.  Each signal is processed
1339    sequentially in numerical order, and a set of similar outbound_signals is
1340    assembled and returned to the caller, simulating assertion of the
1341    corresponding backplane signals.
1342 
1343    After setting the control mode to establish word or byte mode, SIO data
1344    transfer between the interface and the connected device is initiated by a
1345    PWRITESTB or READNEXTWD order.  For direct I/O, a DWRITESTB or a DCONTSTB
1346    with the "acquire" bit set initiates a transfer.
1347 
1348    A sequencer governs the generation of the device handshake signals.  The
1349    handshake begins with the assertion of the Device Control signal.  In
1350    response, the device asserts the Device Flag signal.  The interface then
1351    denies Device Control, and the device denies Device Flag.  For a byte
1352    transfer, this sequence repeats automatically for the second byte.  Byte
1353    packing and unpacking is provided by the interface.
1354 
1355    Eight interrupt sources are provided and may be individually set by their
1356    associated conditions.  A master interrupt enable is provided by setting the
1357    appropriate control word bit, and the requesting sources may be cleared
1358    independently.  An interrupt acknowledgement from the IOP clears the master
1359    interrupt enable to prevent multiple sources from interrupting
1360    simultaneously.
1361 
1362    The status word returned by a DSTATSTB or PSTATSTB signal consists of
1363    interface status in the upper byte and either interrupt or device status in
1364    the lower byte, as selected by a control word bit.
1365 
1366 
1367    Implementation notes:
1368 
1369     1. In a hardware transfer abort, READNEXTWD or PWRITESTB causes the
1370        sequencer to transition to the Device_Command_1 state and set the Device
1371        End flip-flop, which asserts DEVEND to the multiplexer channel, and then
1372        the Device End flip-flop is cleared by ACKSR.  In simulation, ACKSR
1373        occurs before the PREADSTB or PWRITESTB that asserts DEVEND, so the state
1374        of the Device End flip-flop is saved in the ACKSR handler and is then
1375        checked in a subsequent PREADSTB or PWRITESTB to assert DEVEND.
1376 
1377     2. In hardware, the SETJMP signal is ignored, and the JMPMET signal is
1378        asserted continuously when enabled by CHANSO.
1379 
1380     3. In hardware, a power fail warning (PFWARN) is asserted continuously from
1381        detection until power is lost.  In simulation, the "power_warning" flag
1382        is set by a PFWARN assertion and is cleared by a power-on reset.  PFWARN
1383        is used only by the DHA.
1384 */
1385 
ui_interface(DIB * dibptr,INBOUND_SET inbound_signals,HP_WORD inbound_value)1386 static SIGNALS_DATA ui_interface (DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
1387 {
1388 INBOUND_SIGNAL signal;
1389 INBOUND_SET    working_set      = inbound_signals;
1390 HP_WORD        outbound_value   = 0;
1391 OUTBOUND_SET   outbound_signals = NO_SIGNALS;
1392 t_bool         abort_transfer   = FALSE;
1393 
1394 tprintf (lp_dev, DEB_IOB, "Received data %06o with signals %s\n",
1395          inbound_value, fmt_bitset (inbound_signals, inbound_format));
1396 
1397 while (working_set) {
1398     signal = IONEXTSIG (working_set);                   /* isolate the next signal */
1399 
1400     switch (signal) {                                   /* dispatch an I/O signal */
1401 
1402         case INTPOLLIN:
1403             if (dibptr->interrupt_request) {            /* if a request is pending */
1404                 dibptr->interrupt_request = CLEAR;      /*   then clear it */
1405                 dibptr->interrupt_active  = SET;        /*     and mark it now active */
1406 
1407                 outbound_signals |= INTACK;             /* acknowledge the interrupt */
1408                 outbound_value = dibptr->device_number; /*   and return our device number */
1409 
1410                 control_word &= ~(CN_DEVSTAT | CN_IRQ_ENABLE);  /* clear the device status and IRQ enable flip-flops */
1411                 }
1412 
1413             else                                        /* otherwise the request has been reset */
1414                 outbound_signals |= INTPOLLOUT;         /*   so let the IOP know to cancel it */
1415             break;
1416 
1417 
1418         case SETINT:
1419         case DSETINT:
1420             outbound_signals |= set_interrupt (ST_IOSYS_IRQ);   /* set the I/O system interrupt flip-flop */
1421             break;
1422 
1423 
1424         case DRESETINT:
1425             dibptr->interrupt_active = CLEAR;           /* reset the interrupt active flip-flop */
1426             outbound_signals |= set_interrupt (0);      /*   and check whether another IRQ is pending */
1427             break;
1428 
1429 
1430         case DSETMASK:
1431             if (dibptr->interrupt_mask == INTMASK_E)            /* if the mask is always enabled */
1432                 interrupt_mask = SET;                           /*   then set the mask flip-flop */
1433             else                                                /* otherwise */
1434                 interrupt_mask = D_FF (dibptr->interrupt_mask   /*   set the mask flip-flop if the mask bit */
1435                                        & inbound_value);        /*     is present in the mask value */
1436 
1437             outbound_signals |= set_interrupt (0);              /* check whether an IRQ is pending */
1438             break;
1439 
1440 
1441         case PCONTSTB:
1442             if (! J2W1_INSTALLED)                       /* if W1 (SR set by Device Status) is not installed */
1443                 device_sr = SET;                        /*   then set the device service request flip-flop */
1444 
1445         /* fall through into the DCONTSTB case */
1446 
1447         case DCONTSTB:
1448             tprintf (lp_dev, DEB_CSRW,
1449                      (lp_dev.flags & DEV_DIAG && inbound_value & CN_DHA_FN_ENABLE
1450                        ? "Control is %s%s | %s\n"
1451                        : "Control is %s%s\n"),
1452                      fmt_bitset (inbound_value,
1453                                  (lp_dev.flags & DEV_DIAG
1454                                    ? dha_control_format
1455                                    : prt_control_format)),
1456                      reset_irq_name [CN_RESET (inbound_value)],
1457                      dha_fn_name [CN_DHA_FN (inbound_value)]);
1458 
1459             if (inbound_value & CN_MR)                  /* if the programmed master reset bit is set */
1460                 master_reset (TRUE);                    /*   then reset the interface and the control word */
1461 
1462             else if (inbound_value & CN_RIN) {          /* otherwise if the reset interrupt bit is set */
1463                 dibptr->interrupt_request = CLEAR;      /*   then clear the interrupt request */
1464                 int_status_word = 0;                    /*     and all interrupt sources */
1465 
1466                 sim_cancel (timer_uptr);                /* cancel the transfer timer */
1467                 control_word = inbound_value;           /*   and set the control word */
1468                 }
1469 
1470             else {                                                          /* otherwise */
1471                 int_status_word &= reset_irq [CN_RESET (inbound_value)];    /*   clear the specified IRQ source */
1472 
1473                 if ((inbound_value & CN_RIN_MASK) == CN_RIN_XFR_TMR)    /* if the timer interrupt was cleared */
1474                     sim_cancel (timer_uptr);                            /*   then stop the timer too */
1475 
1476                 else if (CN_XFR_TMR_ENABLE                      /* otherwise if the transfer timer */
1477                            & ~control_word & inbound_value) {   /*   is enabled with a 0-to-1 transition */
1478                     sim_cancel (timer_uptr);                    /*     then retrigger */
1479                     activate_unit (timer_uptr);                 /*       the timer */
1480                     }
1481 
1482                 control_word = inbound_value;                   /* set the control word */
1483                 }
1484 
1485             if (control_word & CN_ACQUIRE) {            /* if the next word is requested */
1486                 device_command = SET;                   /*   then set the device command flip-flop */
1487                 read_xfer      = SET;                   /*     and the read transfer flip-flop */
1488                 outbound_signals |= handshake_xfer ();  /*       and start the device handshake */
1489                 }
1490 
1491             if (lp_dev.flags & DEV_DIAG)                            /* if the DHA is installed */
1492                 outbound_signals |= diag_control (control_word);    /*   then process the DHA-specific controls */
1493             else                                                    /* otherwise */
1494                 outbound_signals |= lp_control (control_word);      /*   process the device-specific controls */
1495 
1496             break;
1497 
1498 
1499         case PSTATSTB:
1500         case DSTATSTB:
1501             outbound_value = sequence_counter [sequencer];  /* start with the sequence counter value */
1502 
1503             if (sio_busy == CLEAR                       /* if the interface is inactive */
1504               && (int_status_word & ST_CLRIL) == 0)     /*   and the clear interface logic IRQ is denied */
1505                 outbound_value |= ST_SIO_OK;            /*     then programmed I/O is enabled */
1506 
1507             if (sequencer == Idle)                      /* if the device is inactive */
1508                 outbound_value |= ST_DIO_OK;            /*   then direct I/O is enabled */
1509 
1510             if (int_status_word)                        /* if any interrupt requests are pending */
1511                 outbound_value |= ST_IRQ_PENDING;       /*   then set the status bit */
1512 
1513             if (device_flag_in)                         /* if the device flag is asserted */
1514                 outbound_value |= ST_DEVFLAG;           /*   then set the status bit */
1515 
1516             if (control_word & CN_DEVSTAT)                      /* if the device status flip-flop is set */
1517                 outbound_value |= ST_DEVSTAT | dev_status_word; /*   then return the device status */
1518             else                                                /* otherwise */
1519                 outbound_value |= int_status_word;              /*   return the interrupt status */
1520 
1521             tprintf (lp_dev, DEB_CSRW, "Status is %s\n",
1522                      fmt_bitset (outbound_value,
1523                                  (control_word & CN_DEVSTAT
1524                                    ? (lp_dev.flags & DEV_DIAG
1525                                        ? dev_status_format
1526                                        : prt_status_format)
1527                                    : int_status_format)));
1528             break;
1529 
1530 
1531         case DREADSTB:
1532             outbound_value = (HP_WORD) read_word;       /* return the data input register value */
1533             break;
1534 
1535 
1536         case DWRITESTB:
1537             write_word = (uint32) inbound_value;        /* store the value in the data output register */
1538 
1539             device_command = SET;                       /* set the device command flip-flop */
1540             write_xfer     = SET;                       /*   and the write transfer flip-flop */
1541             outbound_signals |= handshake_xfer ();      /*     and start the device handshake */
1542             break;
1543 
1544 
1545         case DSTARTIO:
1546             tprintf (lp_dev, DEB_CSRW, "Channel program started\n");
1547 
1548             sio_busy = SET;                             /* set the SIO busy flip-flop */
1549 
1550             mpx_assert_REQ (dibptr);                    /* request the channel */
1551 
1552             channel_sr = SET;                           /* set the service request flip-flop */
1553             outbound_signals |= SRn;                    /*   and assert a service request */
1554             break;
1555 
1556 
1557         case ACKSR:
1558             device_sr = CLEAR;                          /* acknowledge the service request */
1559 
1560             abort_transfer = (t_bool) device_end;       /* TRUE if the transfer is to be aborted */
1561             device_end = CLEAR;                         /* clear the device end flip-flop */
1562             break;
1563 
1564 
1565         case TOGGLESR:
1566             TOGGLE (channel_sr);                        /* set or clear the channel service request flip-flop */
1567             break;
1568 
1569 
1570         case TOGGLESIOOK:
1571             TOGGLE (sio_busy);                          /* set or clear the SIO busy flip-flop */
1572 
1573             if (sio_busy == CLEAR)
1574                 tprintf (lp_dev, DEB_CSRW, "Channel program ended\n");
1575             break;
1576 
1577 
1578         case TOGGLEINXFER:
1579             TOGGLE (input_xfer);                        /* set or clear the input transfer flip-flop */
1580 
1581             device_end_in = FALSE;                      /* clear the external device end condition */
1582             break;
1583 
1584 
1585         case TOGGLEOUTXFER:
1586             TOGGLE (output_xfer);                       /* set or clear the output transfer flip-flop */
1587 
1588             if (output_xfer == SET)                     /* if starting an output transfer */
1589                 device_sr = SET;                        /*   request the first word to write */
1590 
1591             device_end_in = FALSE;                      /* clear the external device end condition */
1592             break;
1593 
1594 
1595         case PCMD1:
1596             device_sr = SET;                            /* request the second control word */
1597             break;
1598 
1599 
1600         case READNEXTWD:
1601             device_command = SET;                       /* set the device command flip-flop */
1602             read_xfer      = SET;                       /*   and the read transfer flip-flop */
1603             outbound_signals |= handshake_xfer ();      /*     and start the device handshake */
1604             break;
1605 
1606 
1607         case PREADSTB:
1608             if (abort_transfer) {                           /* if the transfer has been aborted */
1609                 outbound_value = dibptr->device_number * 4; /*   then return the DRT address */
1610                 outbound_signals |= DEVEND;                 /*     and indicate a device abort */
1611                 }
1612 
1613             else                                            /* otherwise the transfer continues */
1614                 outbound_value = (HP_WORD) read_word;       /*   so return the data input register value */
1615             break;
1616 
1617 
1618         case PWRITESTB:
1619             if (abort_transfer) {                           /* if the transfer has been aborted */
1620                 outbound_value = dibptr->device_number * 4; /*   then return the DRT address */
1621                 outbound_signals |= DEVEND;                 /*     and indicate a device abort */
1622                 }
1623 
1624             else {                                          /* otherwise the transfer continues */
1625                 write_word = (uint32) inbound_value;        /*   so store the value in the data output register */
1626 
1627                 device_command = SET;                       /* set the device command flip-flop */
1628                 write_xfer     = SET;                       /*   and the write transfer flip-flop */
1629                 outbound_signals |= handshake_xfer ();      /*     and start the device handshake */
1630                 }
1631             break;
1632 
1633 
1634         case DEVNODB:
1635             outbound_value = dibptr->device_number * 4;     /* return the DRT address */
1636             break;
1637 
1638 
1639         case XFERERROR:
1640             tprintf (lp_dev, DEB_CSRW, "Channel program aborted\n");
1641 
1642             clear_interface_logic ();                   /* clear the interface to abort the transfer */
1643 
1644             outbound_signals |= set_interrupt (ST_XFERERR_IRQ); /* set the transfer error interrupt flip-flop */
1645             break;
1646 
1647 
1648         case CHANSO:
1649             if (channel_sr | device_sr)                 /* if the interface has requested service */
1650                 outbound_signals |= SRn;                /*   then assert SRn to the channel */
1651 
1652             outbound_signals |= JMPMET;                 /* JMPMET is tied active on this interface */
1653             break;
1654 
1655 
1656         case EOT:
1657             if (inbound_signals & PREADSTB)             /* if this is the end of a read transfer */
1658                 device_sr = SET;                        /*   then request channel service */
1659             break;
1660 
1661 
1662         case PFWARN:
1663             power_warning = TRUE;                       /* system power is in the process of failing */
1664             break;
1665 
1666 
1667         case SETJMP:                                    /* not used by this interface */
1668             break;
1669         }
1670 
1671     IOCLEARSIG (working_set, signal);                   /* remove the current signal from the set */
1672     }
1673 
1674 
1675 tprintf (lp_dev, DEB_IOB, "Returned data %06o with signals %s\n",
1676          outbound_value, fmt_bitset (outbound_signals, outbound_format));
1677 
1678 return IORETURN (outbound_signals, outbound_value);     /* return the outbound signals and value */
1679 }
1680 
1681 
1682 /* Service the transfer handshake.
1683 
1684    This service routine is called once for each state of the device transfer
1685    handshake.  The handshake sequencer schedules the transfer events with the
1686    appropriate delays.
1687 
1688    Jumper W10 determines the output polarity of the DEV CMD signal to the
1689    device, and jumpers W2 and W6 determine the input edges of the DEV FLAG
1690    signal from the device used to assert and deny the Device Flag, as follows:
1691 
1692      Jumper  Interpretation when removed    Interpretation when installed
1693      ------  -----------------------------  -----------------------------
1694        W10   DEV CMD polarity is normal     DEV CMD polarity is inverted
1695 
1696        W2    Flag asserts on leading edge   Flag asserts on trailing edge
1697 
1698        W6    Flag denies on trailing edge   Flag denies on leading edge
1699 
1700    Note that if jumpers W2 and W6 are not installed or removed in pairs, the
1701    Device Flag asserts and denies on the same edge of the DEV FLAG signal.  In
1702    this case, the service routine sets the flag on the first call and clears the
1703    flag on the second call without requiring a change in the incoming signal.
1704 
1705 
1706    Implementation notes:
1707 
1708     1. The "device_command_out" and "device_flag_in" variables represent the
1709        states of the DEV CMD and DEV FLAG signal lines.  Edge detection for the
1710        Device Flag is accomplished by comparing the current state to the prior
1711        state.
1712 
1713     2. As the routine was entered by an event timer expiration, the handshake
1714        sequencer must be called explicitly, and any returned backplane signals
1715        must be asserted explicitly.
1716 
1717     3. This routine may be called with a NULL "uptr" parameter to update the
1718        saved last state of the "device_flag_in" variable.  The NULL value
1719        indicates that this is not part of the normal handshake sequence.
1720 */
1721 
xfer_service(UNIT * uptr)1722 static t_stat xfer_service (UNIT *uptr)
1723 {
1724 static t_bool device_flag_last = FALSE;
1725 t_stat        result;
1726 OUTBOUND_SET  signals;
1727 
1728 device_command_out = device_command ^ J2W10_INSTALLED;  /* set device command out; invert if W10 is installed */
1729 
1730 if (lp_dev.flags & DEV_DIAG)                            /* if the DHA is connected */
1731     result = diag_service (uptr);                       /*   then service the diagnostic hardware */
1732 else                                                    /* otherwise */
1733     result = lp_service (uptr);                         /*   service the connected device */
1734 
1735 if (sequencer == Device_Command_1                       /* if Device Command */
1736   || sequencer == Device_Command_2) {                   /*   is asserted */
1737     if (device_flag_last != device_flag_in              /*     then if the flag input has changed */
1738       && J2W2_INSTALLED ^ device_flag_in)               /*     and jumper W2 is in and 1 -> 0 or W2 is out and 0 -> 1 */
1739         device_flag = SET;                              /*       then Device Flag sets */
1740     }
1741 
1742 else                                                    /* otherwise Device Command is denied */
1743     if (J2W2_INSTALLED != J2W6_INSTALLED                /*   so if W2 installation differs from W6 installation */
1744       || (device_flag_last != device_flag_in            /*     or if the flag input has changed */
1745       && J2W6_INSTALLED ^ device_flag_last))            /*     and jumper W6 is in and 0 -> 1 or W6 is out and 1 -> 0 */
1746         device_flag = CLEAR;                            /*       then Device Flag clears */
1747 
1748 device_flag_last = device_flag_in;                      /* save the current state of the flag */
1749 
1750 signals = handshake_xfer ();                            /* continue the handshake */
1751 
1752 if (signals & INTREQ)                                   /* if an interrupt request was generated */
1753     iop_assert_INTREQ (&lp_dib);                        /*   then assert the INTREQ signal */
1754 
1755 if (signals & SRn)                                      /* if a service request was generated */
1756     mpx_assert_SRn (&lp_dib);                           /*   then assert the SRn signal */
1757 
1758 return result;                                          /* return the result of the service call */
1759 }
1760 
1761 
1762 /* Service the device command pulse timer.
1763 
1764    In pulse mode, the DEV CMD signal asserts for 8 microseconds.  This service
1765    routine is entered to deny DEV CMD.  The transfer service is called directly
1766    to notify it of Device Command clearing, and the handshake sequencer is then
1767    called in case the transfer service altered the Device Flag in response.
1768 */
1769 
pulse_service(UNIT * uptr)1770 static t_stat pulse_service (UNIT *uptr)
1771 {
1772 t_stat status;
1773 
1774 tprintf (lp_dev, DEB_SERV, "Pulse service entered\n");
1775 
1776 device_command = CLEAR;                                 /* clear the device command flip-flop */
1777 
1778 status = xfer_service (xfer_uptr);                      /* let the device know that command has denied */
1779 handshake_xfer ();                                      /*   and continue the handshake */
1780 
1781 return status;
1782 }
1783 
1784 
1785 /* Service the transfer timer.
1786 
1787    Setting the appropriate bit in the control word starts the five-second
1788    transfer timer.  If it expires, this routine is entered.  The transfer timer
1789    interrupt is set, and if interrupts are enabled, INTREQ is asserted to the
1790    IOP.  As a convenience to the user, the file attached to the device unit is
1791    flushed.
1792 */
1793 
timer_service(UNIT * uptr)1794 static t_stat timer_service (UNIT *uptr)
1795 {
1796 tprintf (lp_dev, DEB_SERV, "Watchdog service entered\n");
1797 
1798 if (set_interrupt (ST_XFR_TMR_IRQ) == INTREQ)           /* set the transfer timer interrupt flip-flop */
1799     iop_assert_INTREQ (&lp_dib);                        /*   and assert the INTREQ signal if enabled */
1800 
1801 if (xfer_unit.flags & UNIT_ATT)                         /* if the transfer unit is attached */
1802     fflush (xfer_unit.fileref);                         /*   then flush any partial output */
1803 
1804 return SCPE_OK;                                         /* return success */
1805 }
1806 
1807 
1808 /* Device reset routine.
1809 
1810    This routine is called for a RESET or RESET LP command.  It is the simulation
1811    equivalent of the IORESET signal, which is asserted by the front panel LOAD
1812    and DUMP switches.
1813 
1814    For this interface, IORESET is identical to the Programmed Master Clear
1815    invoked by setting bit 0 of the control word.
1816 
1817 
1818    Implementation notes:
1819 
1820     1. Calling "master_reset" with a FALSE parameter indicates that this is a
1821        commanded reset.  This allows the connected device-specific reset
1822        routines to distinguish from a Programmed Master Clear.
1823 */
1824 
ui_reset(DEVICE * dptr)1825 static t_stat ui_reset (DEVICE *dptr)
1826 {
1827 return master_reset (FALSE);                            /* perform a non-programmed master reset */
1828 }
1829 
1830 
1831 
1832 /* Interface local utility routines */
1833 
1834 
1835 
1836 /* Master reset.
1837 
1838    A master reset is generated either by an I/O Reset signal or a Programmed
1839    Master Clear (CIO bit 0).  It sets the interrupt mask, clears any pending or
1840    active interrupt, clears all interrupt sources, clears the control word,
1841    clears the read and write registers, resets the handshake sequencer to its
1842    idle state, clears the interface logic flip-flops, and cancels all active
1843    event timers.  It also calls pulses the MASTER CLEAR signal line to the
1844    device for a preset time.
1845 
1846 
1847    Implementation notes:
1848 
1849     1. Calling the reset routine for the connected device simulates asserting
1850        the MASTER CLEAR signal.
1851 */
1852 
master_reset(t_bool programmed_clear)1853 static t_stat master_reset (t_bool programmed_clear)
1854 {
1855 interrupt_mask = SET;                                   /* set the interrupt mask flip-flop */
1856 
1857 lp_dib.interrupt_request = CLEAR;                       /* clear any current */
1858 lp_dib.interrupt_active  = CLEAR;                       /*   interrupt request */
1859 
1860 int_status_word = 0;                                    /* clear all interrupt request sources */
1861 
1862 control_word = 0;                                       /* clear the control word */
1863 write_word   = 0;                                       /*   and the output data register */
1864 read_word    = 0;                                       /*     and the input data register */
1865 
1866 sequencer = Idle;                                       /* clear the handshake sequencer to the idle state */
1867 
1868 read_xfer  = CLEAR;                                     /* clear the read transfer */
1869 write_xfer = CLEAR;                                     /*   and write transfer flip-flops */
1870 
1871 device_command = CLEAR;                                 /* clear the device command */
1872 device_flag    = CLEAR;                                 /*   and device flag flip-flops */
1873 
1874 data_out      = 0;                                      /* clear the external state */
1875 data_in       = 0;                                      /*   of the I/O lines */
1876 device_end_in = FALSE;                                  /*     and the external device end line */
1877 
1878 clear_interface_logic ();                               /* clear the interface to abort any transfer in progress */
1879 
1880 sim_cancel (xfer_uptr);                                 /* cancel */
1881 sim_cancel (pulse_uptr);                                /*   any pending */
1882 sim_cancel (timer_uptr);                                /*     event timers */
1883 
1884 if (lp_dev.flags & DEV_DIAG)                            /* if the DHA is installed */
1885     return diag_reset (programmed_clear);               /*   then reset the diagnostic hardware */
1886 else                                                    /* otherwise */
1887     return lp_reset (programmed_clear);                 /*   reset the device */
1888 }
1889 
1890 
1891 /* Clear the interface logic.
1892 
1893    The clear interface logic signal is asserted when the channel indicates a
1894    transfer failure by asserting XFERERROR, or when the device asserts the CLEAR
1895    INTERFACE signal.  It clears the SIO Busy, Channel and Device Service
1896    Request, Input Transfer, Output Transfer, and Device End flip-flops.
1897 */
1898 
clear_interface_logic(void)1899 static void clear_interface_logic (void)
1900 {
1901 sio_busy    = CLEAR;                                    /* clear the SIO busy flip-flop */
1902 channel_sr  = CLEAR;                                    /*   and the channel service request flip-flop */
1903 device_sr   = CLEAR;                                    /*   and the device service request flip-flop */
1904 input_xfer  = CLEAR;                                    /*   and the input transfer flip-flop */
1905 output_xfer = CLEAR;                                    /*   and the output transfer flip-flop */
1906 device_end  = CLEAR;                                    /*   and the device end flip-flop */
1907 
1908 return;
1909 }
1910 
1911 
1912 /* Activate the unit.
1913 
1914    The specified unit is activated using the unit's "wait" time.  If tracing
1915    is enabled, the activation is logged to the debug file.
1916 
1917 
1918    Implementation notes:
1919 
1920     1. A zero-length delay is scheduled, rather than calling the service routine
1921        directly, so that the status return value from the event service routine
1922        is correctly passed back to SCP.
1923 */
1924 
activate_unit(UNIT * uptr)1925 static void activate_unit (UNIT *uptr)
1926 {
1927 tprintf (lp_dev, DEB_SERV, "%s delay %u service scheduled\n",
1928          unit_name [uptr - lp_unit], uptr->wait);
1929 
1930 sim_activate (uptr, uptr->wait);                    /* activate the unit */
1931 
1932 return;
1933 }
1934 
1935 
1936 /* Report a stream I/O error to the console.
1937 
1938    If a stream I/O error has been detected, this routine will print an error
1939    message to the simulation console and clear the stream's error indicator.
1940 */
1941 
report_error(FILE * stream)1942 static void report_error (FILE *stream)
1943 {
1944 cprintf ("%s simulator printer I/O error: %s\n",        /* report the error to the console */
1945          sim_name, strerror (errno));
1946 
1947 clearerr (stream);                                      /* clear the error */
1948 
1949 return;
1950 }
1951 
1952 
1953 /* Set an interrupt.
1954 
1955    The interrupt bit specified is set in the interrupt status word.  If enabled,
1956    INTREQ is returned to request an interrupt.
1957 
1958    The routine is also called with a zero "interrupt" parameter value to check
1959    whether an interrupt should be requested.
1960 */
1961 
set_interrupt(uint32 interrupt)1962 static OUTBOUND_SET set_interrupt (uint32 interrupt)
1963 {
1964 int_status_word |= interrupt;                           /* set the specified interrupt flip-flop */
1965 
1966 if (int_status_word                                     /* if an interrupt request is present */
1967   && control_word & CN_IRQ_ENABLE                       /*   and the IRQ enable flip-flop is set */
1968   && lp_dib.interrupt_active == CLEAR                   /*   and no interrupt is currently active */
1969   && interrupt_mask == SET) {                           /*   and the interrupt mask is satisfied */
1970     lp_dib.interrupt_request = SET;                     /*     then request an interrupt */
1971     return INTREQ;                                      /*       and assert the INTREQ signal */
1972     }
1973 
1974 else                                                    /* otherwise an interrupt request */
1975     return NO_SIGNALS;                                  /*   cannot be made at this time */
1976 }
1977 
1978 
1979 /* Set the device status.
1980 
1981    The device status word is masked with the supplied "status_mask" and then the
1982    corresponding bits of the "new_status_word" are merged in.  If enabled by the
1983    associated jumpers and the required edge transitions, interrupts for status
1984    bits 8-10 may be generated.
1985 */
1986 
set_device_status(uint32 status_mask,uint32 new_status_word)1987 static OUTBOUND_SET set_device_status (uint32 status_mask, uint32 new_status_word)
1988 {
1989 OUTBOUND_SET outbound_signals = NO_SIGNALS;
1990 
1991 if (status_mask & ST_DEVIRQ_MASK) {                         /* if a status interrupt is possible */
1992     if (J2W4_INSTALLED                                      /*   then if jumper J4 is installed to enable */
1993       && ~dev_status_word & new_status_word & ST_ST8_IRQ)   /*     and a 0 -> 1 transition occurred on status 8 */
1994         outbound_signals |= set_interrupt (ST_ST8_IRQ);     /*       then set the status 8 interrupt flip-flop */
1995 
1996     if (J2W8_INSTALLED                                      /* if jumper J8 is installed to enable */
1997       && ~dev_status_word & new_status_word & ST_ST9_IRQ)   /*   and a 0 -> 1 transition occurred on status 9 */
1998         outbound_signals |= set_interrupt (ST_ST9_IRQ);     /*     then set the status 9 interrupt flip-flop */
1999 
2000     if (J2W9_INSTALLED                                      /* if jumper J9 is installed to enable */
2001       && dev_status_word & ~new_status_word & ST_ST10_IRQ)  /*   and a 1 -> 0 transition occurred on status 10 */
2002         outbound_signals |= set_interrupt (ST_ST10_IRQ);    /*     then set the status 10 interrupt flip-flop */
2003     }
2004 
2005 dev_status_word = dev_status_word & ~status_mask            /* clear the old device status */
2006                     | new_status_word & status_mask;        /*   and set the new status */
2007 
2008 return outbound_signals;                                    /* return INTREQ if any interrupts were requested */
2009 }
2010 
2011 
2012 /* Start or continue the data transfer handshake.
2013 
2014    This routine implements the two-wire data transfer handshake with the device.
2015    For each word or byte transferred, the Device Command signal from the
2016    interface and the Device Flag signal from the device assume these states:
2017 
2018      Command     Flag         State          Next State
2019       State      State        Action         Transition
2020      --------  --------  ----------------  --------------
2021      denied    denied    device idle       Command sets
2022      asserted  denied    device started    Flag sets
2023      asserted  asserted  device completed  Command clears
2024      denied    asserted  interface idle    Flag clears
2025 
2026    In hardware, a two-bit gray counter implements a four-state sequencer, with
2027    three states assigned as follows for a word transfer:
2028 
2029                                 Command     Flag
2030      State  State Action         State      State   Next State Transition
2031      -----  ------------------  --------  --------  ---------------------
2032       0 0   idle                denied    denied    read or write command
2033       1 0   word requested      asserted  denied    Flag sets
2034       1 1   word started        denied    asserted  Flag clears
2035       0 0   word completed      denied    denied    ---
2036 
2037    For a two-byte transfer, the states are:
2038 
2039                                 Command     Flag
2040      State  State Action         State      State   Next State Transition
2041      -----  ------------------  --------  --------  ---------------------
2042       0 0   idle                denied    denied    read or write command
2043       1 0   1st byte requested  asserted  denied    Flag sets
2044       1 1   1st byte started    denied    asserted  Flag clears
2045       1 0   1st byte completed  asserted  denied    Flag sets
2046             2nd byte requested
2047       0 0   2nd byte started    denied    asserted  Flag clears
2048       0 0   2nd byte completed  denied    denied    ---
2049 
2050    The presence of the asserted Device Flag when the count is 00 differentiates
2051    between the "2nd byte started" and "operation completed" conditions.
2052 
2053    In simulation, these last two conditions are assigned to separate states, as
2054    follows:
2055 
2056      Hdwe      Simulation     Command     Flag
2057      State       State         State      State
2058      -----  ----------------  --------  --------
2059       0 0   Idle              denied    denied
2060       1 0   Device_Command_1  asserted  denied
2061       1 1   Device_Flag_1     denied    asserted
2062       1 0   Device_Command_2  asserted  denied
2063       0 0   Device_Flag_2     denied    asserted
2064       0 0   Idle              denied    denied
2065 
2066    To provide the proper values to appear in the Sequence Counter field of the
2067    status word, a mapping array is used to supply the value 00 for the
2068    Device_Flag_2 state.
2069 
2070    The device service is scheduled after each state transition, except the
2071    return to the idle state, to detect the change in the Device Command signal
2072    or to schedule the change in the Device Flag.  The device determines whether
2073    the service will be entered immediately (at the next poll) or after a delay
2074    time expires.
2075 
2076    For the diagnostic device, the service routine is entered immediately for all
2077    transitions.  For the printer device, the service routine is entered
2078    immediately for Device Flag assertions, but flag denials are scheduled with a
2079    delay corresponding to the printer operation time.  The operations are as
2080    follows:
2081 
2082                                          Diagnostic Service  Diagnostic Service
2083      State             Printer Service    Flag follows Cmd   Flag follows cont.6
2084      ----------------  ----------------  ------------------  -------------------
2085      Device_Command_1  set Flag          set Flag            wait for Control.6
2086      Device_Flag_1     wait for service  clear Flag          wait for Control.6
2087      Device_Command_2  set Flag          set Flag            wait for Control.6
2088      Device_Flag_2     wait for service  clear Flag          wait for Control.6
2089 
2090    If the device asserts the DEV END signal in response to Device Command, the
2091    Device End flip-flop is set, and the sequencer is reset back to the Idle
2092    state to abort the transfer.  DEV END assertion in any other state is ignored
2093    until Device Command is set.
2094 
2095    If jumper W3 is installed, DEV CMD is pulsed for 8 microseconds by asserting
2096    Device Command and scheduling the pulse timer to deny it when the event timer
2097    expires.
2098 
2099    A DWRITESTB or PWRITESTB signal stores a 16-bit value in the data output
2100    register.  In word mode, the value is presented continuously on the 16 DATA
2101    OUT lines.  In byte mode, the upper byte in the data output register is
2102    presented on both bytes of the DATA OUT lines until the Device Flag sets to
2103    indicate that the device has accepted the first byte, whereupon the full
2104    16-bit value is presented on the DATA OUT lines.  The result is that the
2105    upper byte and then the lower byte appears on the lower byte of the DATA OUT
2106    lines.
2107 
2108    During byte-mode read cycles, the previously stored full 16-bit output value
2109    is presented on the DATA OUT lines if J2W7 is removed.  If J2W7 is installed,
2110    the upper byte and then the lower byte appears on the lower byte.  In other
2111    words, a byte read with J2W7 installed causes the DATA OUT lines to assume
2112    the same values in sequence that occur during a byte write.  This is used by
2113    the diagnostic to test the DATA OUT multiplexer.
2114 
2115    A read is initiated by the READNEXTWD signal or by setting the Acquire bit in
2116    the control word.  Device Command sets in response.  While Device Command is
2117    set, the data input register is transparent and passes the value on the Data
2118    In lines through.  When Device Flag sets, the value on the DATA IN lines is
2119    latched in the register.  A DREADSTB or PREADSTB signal then enables the
2120    register onto the IOP Data bus.  With J2W5 installed, the data in register is
2121    always transparent, and a DREADSTB or PREADSTB signal presents the current
2122    value on the DATA IN lines to the IOP Data bus.
2123 
2124    In word mode with J2W5 removed, 16-bit data presented at the DATA IN lines is
2125    passed through the data input register while Device Command is set and is
2126    latched when the Device Flag sets.  In byte mode with J2W5 removed, the value
2127    presented on the lower byte of the DATA IN lines is presented to both bytes
2128    of the data input register, passed through while Device Command is set, and
2129    latched into both bytes of the register when the Device Flag sets to indicate
2130    that the device has supplied the first byte.  When Device Command sets for
2131    the second byte, the value presented on the lower byte of the DATA IN lines
2132    is presented to the lower byte of the data input register, passed through
2133    while Device Command is set, and latched into the lower byte when the Device
2134    Flag sets to indicate that the device has supplied the second byte.  The
2135    result is that the data input register presents the first byte in both bytes
2136    of the register and then the second byte presents as the lower byte of the
2137    register, resulting in a packed 16-bit value.
2138 
2139 
2140    Implementation notes:
2141 
2142     1. In hardware, the sequencer moves from state 2 through state 3 to state 0
2143        when the device flag denies at the end of a word transfer.  For a packed
2144        byte transfer, the sequencer moves from state 3 to state 0 when the
2145        device flag asserts for the second byte, with logic holding off the
2146        "operation done" signal until the flag denies.
2147 
2148        In simulation, the sequencer moves on flag denial directly from
2149        Device_Flag_1 to Idle for a word transfer and on flag assertion from
2150        Device_Command_2 to Device_Flag_2 and then on flag denial to Idle for a
2151        second byte transfer.  The sequence count reported in a status return is
2152        0 for Device_Flag_2, preserving the appearance of returning to state 0
2153        while the internal Device_Flag_2 state holds off the "operation done"
2154        signal.
2155 
2156     2. In hardware, a DEV END signal asserts the Q2 and Q3 qualifiers, enabling
2157        the sequence counter to proceed through the state sequence back to the
2158        idle state.  In simulation, the sequencer state is set directly back to
2159        Idle.
2160 
2161     3. In hardware, with jumper W5 out, the DATA IN latches are transparent in
2162        the Device_Command_1 and Device_Command_2 states and are latched
2163        otherwise, i.e., when Device Flag asserts.  With jumper W5 in, the
2164        latches are transparent always, and a read gets the real-time state of
2165        the DATA IN lines.  In simulation, the read register is set when Device
2166        Flag asserts; transparency is not simulated.
2167 
2168     4. The diagnostic tests the byte unpacking and packing multiplexers on the
2169        DATA OUT and DATA IN lines, so we must simulate the multiplexing
2170        accurately with respect to the intermediate values before the handshake
2171        is complete.
2172 
2173     5. The sequencer loop is used only during a device end assertion to move
2174        from Idle to Device_Command_1 and back to Idle.  All other transitions
2175        involve unit activation and so exit this routine after the sequence state
2176        is changed.
2177 */
2178 
handshake_xfer(void)2179 static OUTBOUND_SET handshake_xfer (void)
2180 {
2181 const SEQ_STATE entry_state      = sequencer;           /* the state of the sequencer at entry */
2182 t_bool          reset            = FALSE;               /* TRUE if the sequencer is reset */
2183 OUTBOUND_SET    outbound_signals = NO_SIGNALS;
2184 SEQ_STATE       last_state;
2185 
2186 do {                                                    /* run the sequencer as long as it advances */
2187     last_state = sequencer;                             /* save the last state to see if it changes */
2188 
2189     if (sequencer < Device_Command_2                    /* if this is the first byte */
2190       && control_word & CN_BYTE_XFER                    /*   of a byte transfer */
2191       && (J2W7_INSTALLED || write_xfer))                /*     and W7 is installed or it's a write transfer */
2192         data_out = write_word & ~D8_MASK                /*       then the upper 8 bits appear */
2193                       | UPPER_BYTE (write_word);        /*         in both bytes */
2194     else                                                /* otherwise */
2195         data_out = write_word;                          /*   the full 16 bits appear */
2196 
2197 
2198     switch (sequencer) {                                /* dispatch the current state */
2199 
2200         case Idle:
2201             if (device_command == SET) {                /* if device command has been set */
2202                 sequencer = Device_Command_1;           /*   then proceed to the next state */
2203 
2204                 if (device_end_in                       /* if external device end asserts */
2205                   && (read_xfer || write_xfer))         /*   during a transfer */
2206                     device_command = CLEAR;             /*     then device command is inhibited */
2207 
2208                 else {                                  /* otherwise */
2209                     if (J2W3_INSTALLED)                 /*   if jumper W3 (pulse mode) is installed */
2210                         activate_unit (pulse_uptr);     /*     then schedule device command denial */
2211 
2212                     activate_unit (xfer_uptr);          /* schedule device flag assertion */
2213                     }
2214                 }
2215             break;
2216 
2217 
2218         case Device_Command_1:
2219             if (device_end_in)                          /* if external device end asserts */
2220                 if (read_xfer || write_xfer) {          /*   then if a transfer is in progress */
2221                     device_end = SET;                   /*     then set the Device End flip-flop to abort */
2222 
2223                     device_command = CLEAR;             /* clear the device command */
2224                     read_xfer      = CLEAR;             /*   and read transfer  */
2225                     write_xfer     = CLEAR;             /*     and write transfer flip-flops */
2226 
2227                     sequencer = Idle;                   /* idle the sequencer */
2228                     reset     = TRUE;                   /*   and indicate that it was reset */
2229 
2230                     device_sr = SET;                    /* request channel service */
2231                     break;
2232                     }
2233 
2234                 else                                    /* otherwise no transfer is in progress */
2235                     device_end_in = FALSE;              /*   so clear the signal */
2236 
2237             if (device_flag == SET) {                   /* if the device flag has been set */
2238                 sequencer = Device_Flag_1;              /*   then proceed to the next state */
2239                 device_command = CLEAR;                 /*     and deny device command */
2240 
2241                 activate_unit (xfer_uptr);              /* schedule device flag denial */
2242 
2243                 if (control_word & CN_BYTE_XFER)            /* if this is a byte transfer */
2244                     read_word = TO_WORD (data_in, data_in); /*   then the lower 8 bits appear in both bytes */
2245                 else                                        /* otherwise */
2246                     read_word = data_in;                    /*   the full 16 bits appear */
2247 
2248                 if (J2W1_INSTALLED && sio_busy          /* if jumper W1 (status drives SR) is installed */
2249                   && dev_status_word & ST_ST11_SR)      /*   and a transfer is in progress with status 11 set */
2250                     device_sr = SET;                    /*     then request channel service */
2251                 }
2252             break;
2253 
2254 
2255         case Device_Flag_1:
2256             if (device_flag == CLEAR)                   /* if the device flag has been cleared */
2257                 if (control_word & CN_BYTE_XFER) {      /*   then if this is a byte transfer */
2258                     sequencer = Device_Command_2;       /*     then proceed to the next state */
2259                     device_command = SET;               /*       and assert device command for the second byte */
2260 
2261                     data_out = write_word;              /* latch the output word */
2262 
2263                     activate_unit (xfer_uptr);          /* schedule device flag assertion */
2264                     }
2265 
2266                 else {                                  /* otherwise the transfer is complete */
2267                     read_xfer  = CLEAR;                 /*   so clear the read transfer  */
2268                     write_xfer = CLEAR;                 /*     and write transfer flip-flops */
2269 
2270                     sequencer = Idle;                   /* idle the sequencer */
2271                     device_sr = SET;                    /*   and request channel service */
2272 
2273                     if (control_word & CN_XFR_IRQ_ENABLE)               /* if a transfer interrupt is requested */
2274                         outbound_signals |= set_interrupt (ST_XFR_IRQ); /*   then set the transfer interrupt flip-flop */
2275                     }
2276             break;
2277 
2278 
2279         case Device_Command_2:
2280             if (device_flag == SET || device_end_in) {  /* if the device flag or external device end has been set */
2281                 sequencer = Device_Flag_2;              /*   then proceed to the next state */
2282                 device_command = CLEAR;
2283 
2284                 activate_unit (xfer_uptr);              /* schedule device flag denial */
2285 
2286                 read_word &= ~D8_MASK;                  /* clear the lower byte */
2287 
2288                 if (device_end_in == FALSE)             /* if the transfer succeeded */
2289                     read_word |= LOWER_BYTE (data_in);  /*   then merge the received lower byte */
2290                 }
2291             break;
2292 
2293 
2294         case Device_Flag_2:
2295             if (device_flag == CLEAR) {                 /* if the device flag was cleared */
2296                 read_xfer  = CLEAR;                     /*   then clear the read transfer  */
2297                 write_xfer = CLEAR;                     /*     and write transfer flip-flops */
2298 
2299                 sequencer = Idle;                       /* idle the sequencer */
2300                 device_sr = SET;                        /*   and request channel service */
2301 
2302                 if (control_word & CN_XFR_IRQ_ENABLE)               /* if a transfer interrupt is requested */
2303                     outbound_signals |= set_interrupt (ST_XFR_IRQ); /*   then set the transfer interrupt flip-flop */
2304                 }
2305             break;
2306         }                                               /* end of state dispatching */
2307     }
2308 while (sequencer != last_state);                        /* continue as long as the sequence is progressing */
2309 
2310 
2311 if (TRACING (lp_dev, DEB_STATE))
2312     if (sequencer != entry_state)
2313         hp_trace (&lp_dev, DEB_STATE, "Sequencer transitioned from the %s state to the %s state\n",
2314                   state_name [entry_state], state_name [sequencer]);
2315 
2316     else if (reset && device_end)
2317         hp_trace (&lp_dev, DEB_STATE, "Sequencer reset by device end\n");
2318 
2319 if (device_sr && sio_busy)                              /* if the interface has requested service */
2320     outbound_signals |= SRn;                            /*   then assert SRn to the channel */
2321 
2322 return outbound_signals;                                /* return the accumulated signals */
2323 }
2324 
2325 
2326 
2327 /* Diagnostic Hardware Assembly local SCP support routines */
2328 
2329 
2330 
2331 /* Service the transfer handshake for the Diagnostic Hardware Assembly.
2332 
2333    The DHA loops the data out lines back to the data in lines, with bits 11-15
2334    also connecting to bits 11-15 of the status in lines.  The DHA also may be
2335    configured to connect either the DEV CMD output or the CONT 6 output to the
2336    DEV FLAG input.
2337 
2338 
2339    Implementation notes:
2340 
2341     1. The DHA transfer service is called with a null pointer to update the
2342        potential change in the flag state.
2343 */
2344 
diag_service(UNIT * uptr)2345 static t_stat diag_service (UNIT *uptr)
2346 {
2347 if (uptr)                                               /* trace only if this is a handshake entry */
2348     tprintf (lp_dev, DEB_SERV, "%s state transfer service entered\n",
2349              state_name [sequencer]);
2350 
2351 if (dha_control_word & DHA_FLAG_SEL)                    /* if in "flag follows control 6" mode */
2352     device_flag_in = (control_word & CN_DHA_FLAG) != 0; /*   then set the flag from control word bit 6 */
2353 else                                                    /* otherwise */
2354     device_flag_in = device_command_out;                /*   device flag is connected to device command */
2355 
2356 data_in = data_out;                                     /* data in is connected to data out */
2357 
2358 set_device_status (ST_DHA_DEVSTAT_MASK, data_out);      /* status bits 11-15 are connected to data out */
2359 
2360 return SCPE_OK;
2361 }
2362 
2363 
2364 
2365 /* Diagnostic Hardware Assembly local utility routines */
2366 
2367 
2368 
2369 /* Diagnostic hardware assembly reset.
2370 
2371    When the MASTER CLEAR signal is asserted to the DHA, the master reset bit in
2372    the DHA control word is set.  In addition, the status bits connected to the
2373    DATA OUT lines from the interface are cleared, as the interface has cleared
2374    its output register.
2375 
2376    If this reset was caused by a RESET or RESET LP command, the set of installed
2377    jumpers in the DHA control word is updated.  This picks up any jumper changes
2378    made at the user interface.
2379 
2380 
2381    Implementation notes:
2382 
2383     1. The DHA transfer service is called with a null pointer to update the
2384        potential change in the DEV FLAG state that may have occurred by a change
2385        to the DEV CMD state if the lines are connected.
2386 */
2387 
diag_reset(t_bool programmed_clear)2388 static t_stat diag_reset (t_bool programmed_clear)
2389 {
2390 if (programmed_clear) {                                 /* if this is a programmed master clear */
2391     dha_control_word |= DHA_MR;                         /*   then record the master reset */
2392 
2393     set_device_status (ST_DHA_DEVSTAT_MASK, data_out);  /* clear the status bits connected to data out */
2394 
2395     xfer_service (NULL);                                /* update the current device flag state */
2396     }
2397 
2398 else                                                        /* otherwise this is a commanded reset */
2399     dha_control_word = dha_control_word & DHA_JUMPER_MASK   /*   so refresh the DHA control word */
2400                          | jumper_set;                      /*     from the jumpers */
2401 
2402 return SCPE_OK;
2403 }
2404 
2405 
2406 /* Process the diagnostic hardware assembly control word.
2407 
2408    This routine is called when a DCONTSTB or PCONTSTB assertion indicates that
2409    the control word is to be set.  If bit 10 is set, then bits 6-9 represent an
2410    encoded action to be taken by the DHA.  Two of the actions potentially change
2411    the state of the device status lines, which may also generate an interrupt if
2412    properly configured and enabled.  In addition, the DEV FLAG signal may
2413    change, depending on the state of the "flag follows control bit 6" action,
2414    which may cause the handshake sequencer to change states.
2415 
2416 
2417    Implementation notes:
2418 
2419     1. The jumpers part of the DHA control word is "cleared" to all ones, which
2420        corresponds to installing all of the jumpers.
2421 
2422     2. The DHA transfer service is called with a null pointer to update the
2423        potential change in the flag state.
2424 
2425     3. Setting bit 2 of the DHA control word reflects the current state of the
2426        PON and ~PFWARN signals in status bits 9 and 10, respectively.  Status 9
2427        is always set, as PON is always active while the machine is operating.
2428        Status 10 is normally set to indicate that PFWARN is denied.  However, if
2429        the system power is failing, PFWARN is asserted from detection until
2430        power is lost.
2431 */
2432 
diag_control(uint32 control_word)2433 static OUTBOUND_SET diag_control (uint32 control_word)
2434 {
2435 uint32       new_status;
2436 OUTBOUND_SET outbound_signals = NO_SIGNALS;
2437 
2438 if (control_word & CN_DHA_FN_ENABLE)                    /* if the decoder is enabled */
2439     switch (CN_DHA_FN (control_word)) {                 /*   then decode the DHA command */
2440 
2441         case 0:                                         /* clear the registers */
2442             dha_control_word = DHA_CLEAR;               /* initialize the DHA control word */
2443             jumper_set = DHA_CLEAR & DHA_JUMPER_MASK;   /*   and install all of the jumpers */
2444             break;
2445 
2446         case 2:                                         /* assert the Device End signal */
2447             device_end_in = TRUE;                       /* set the external device end line */
2448             break;
2449 
2450         case 4:                                                 /* set the Transfer Error flip-flop */
2451             outbound_signals = set_interrupt (ST_XFERERR_IRQ);  /* set the transfer error interrupt flip-flop */
2452             break;
2453 
2454         case 8:                                         /* connect the device flag to control bit 6 */
2455             dha_control_word |= DHA_FLAG_SEL;           /* set the "flag follows control 6" bit */
2456             break;
2457 
2458         case 10:                                                /* assert the Clear Interface signal */
2459             clear_interface_logic ();                           /* clear the interface logic */
2460             outbound_signals = set_interrupt (ST_CLRIF_IRQ);    /*   and set the clear interface interrupt flip-flop */
2461             break;
2462 
2463         case 12:                                        /* connect status 8-10 to master clear/power on/power fail */
2464             dha_control_word |= DHA_STAT_SEL;           /* set the "status follows master clear-power on-power fail" bit */
2465             break;
2466 
2467         default:                                                        /* remove a jumper */
2468             dha_control_word &= jumper_map [CN_DHA_FN (control_word)];  /* clear the specified control register bit */
2469             jumper_set = dha_control_word & DHA_JUMPER_MASK;            /*   and remove the indicated jumper */
2470             break;
2471         }
2472 
2473 
2474 if (dha_control_word & DHA_STAT_SEL) {                  /* if status follows master clear/power on/power fail */
2475     new_status = ST_DHA_PON;                            /*   then indicate that power is on */
2476 
2477     if (power_warning == FALSE)                         /* if we have seen a PFWARN signal */
2478         new_status |= ST_DHA_NOT_PF;                    /*   then indicate that power has not failed */
2479 
2480     if (dha_control_word & DHA_MR)                      /* if a master reset is requested */
2481         new_status |= ST_DHA_MR;                        /*   then indicate a master clear */
2482     }
2483 
2484 else                                                    /* otherwise set the device status */
2485     new_status = ST_DEVIRQ (CN_DHA_ST (control_word));  /*   from the connected DHA control bits */
2486 
2487 outbound_signals |= set_device_status (ST_DEVIRQ_MASK, new_status); /* set the status and test for IRQs */
2488 
2489 xfer_service (NULL);                                    /* record the current device flag state */
2490 
2491 outbound_signals |= handshake_xfer ();                  /* check for a device handshake transition */
2492 
2493 return outbound_signals;                                /* return INTREQ if any interrupts were requested */
2494 }
2495 
2496 
2497 
2498 /* Printer local SCP support routines */
2499 
2500 
2501 
2502 /* Service the transfer handshake for the printer.
2503 
2504    The printer transfer service is called to output a character to the printer
2505    buffer or to output a format command that causes the buffered line to be
2506    printed with specified paper movement.
2507 
2508    In hardware, the interface places a character or format code on the lower
2509    seven data out lines and asserts STROBE (DEV CMD) to the printer.  The
2510    printer responds by denying DEMAND (asserting DEV FLAG).  The interface then
2511    denies STROBE and waits for the printer to reassert DEMAND (deny DEV FLAG) to
2512    indicate that the buffer load or print operation is complete.
2513 
2514    In simulation, this service routine is called twice for each transfer.  It is
2515    called immediately with Device Command set and then after a variable delay
2516    with Device Command clear.  In response to the former call, the routine sets
2517    the Device Flag, loads the character buffer or prints the buffered line, and
2518    then sets up an event delay corresponding to the operation performed.  In
2519    response to the latter call, the routine clears the Device Flag and then
2520    clears the event delay time, so that the routine will be reentered
2521    immediately when Device Command sets again.
2522 
2523    If a SET LP OFFLINE command or a DETACH LP command simulating an out-of-paper
2524    condition is given, the printer will not honor the command immediately if
2525    data exists in the print buffer or the printer is currently printing a line.
2526    In this case, the action is deferred until the service routine is entered to
2527    complete a print operation.  At that point, the printer goes offline with
2528    DEMAND denied.  This leaves the transfer handshake incomplete.  When the
2529    printer is placed back online, this routine is called to assert DEMAND and
2530    conclude the handshake.
2531 
2532    Control word bit 10 determines whether the code on the data out lines is
2533    interpreted as a character (0) or a format command (1).  If there is room in
2534    the print buffer, the character is loaded.  If not, then depending on the
2535    model, the printer either discards the character or automatically prints the
2536    buffer contents, advances the paper one line, and stores the new character in
2537    the empty buffer.  If a control character is sent but the printer cannot
2538    print it, a space is loaded in its place.
2539 
2540    A format command causes the current buffer to be printed, and then the paper
2541    is advanced by a prescribed amount.  Two output modes are provided: compact
2542    and expanded.
2543 
2544    In compact mode, a printed line is terminated by a CR LF pair, but subsequent
2545    line spacing is performed by LFs alone.  Also, a top-of-form request will
2546    emit a FF character instead of the number of LFs required to reach the top of
2547    the next form, and overprinting is handled by emitting a lone CR at the end
2548    of the line.  This mode is used when the printer output file will be sent to
2549    a physical printer connected to the host.
2550 
2551    In expanded mode, paper advance is handled solely by emitting CR LF pairs.
2552    Overprinting is handled by merging characters in the buffer.  This mode is
2553    used where the printer output file will be saved or manipulated as a text
2554    file.
2555 
2556    The format commands recognized by the printer are:
2557 
2558      0 x x 0 0 0 0 -- slew 0 lines (suppress spacing) after printing
2559           ...
2560      0 x x 1 1 1 1 -- slew 15 lines after printing
2561 
2562    and:
2563 
2564      1 x x 0 0 0 0 -- slew to VFU channel 1 after printing
2565           ...
2566      1 x x 1 0 1 1 -- slew to VFU channel 12 after printing
2567 
2568    A command to slew to a VFU channel that is not punched or to a VFU channel
2569    other than those defined for the printer will cause a tape fault, and the
2570    printer will go offline; setting the printer back online will clear the
2571    fault.  Otherwise, LFs or a FF (compact mode) or CR LF pairs (expanded mode)
2572    will be added to the buffer to advance the paper the required number of
2573    lines.
2574 
2575    Not all printers can overprint.  A request to suppress spacing on a printer
2576    that cannot (e.g., the HP 2607) is treated as a request for single spacing.
2577 
2578    If the stream write fails, an error message is displayed on the simulation
2579    console, a printer alarm condition is set (which takes the printer offline),
2580    and SCPE_IOERR is returned to cause a simulation stop to give the user the
2581    opportunity to fix the problem.  Simulation may then be resumed, either with
2582    the printer set back online if the problem is fixed, or with the printer
2583    remaining offline if the problem is uncorrectable.
2584 
2585 
2586    Implementation notes:
2587 
2588     1. When a paper-out condition is detected, the 2607 printer goes offline
2589        only when the next top-of-form is reached.  The 2613/17/18 printers go
2590        offline as soon as the current line completes.
2591 
2592     2. Because attached files are opened in binary mode, newline translation
2593        (i.e., from LF to CR LF) is not performed by the host system.  Therefore,
2594        we write explicit CR LF pairs to end lines, even in compact mode, as
2595        required for fidelity to HP peripherals.  If bare LFs are used by the
2596        host system, the printer output file must be postprocessed to remove the
2597        CRs.
2598 
2599     3. Overprinting in expanded mode is simulated by merging the lines in the
2600        buffer.  A format command to suppress spacing resets the buffer index but
2601        saves the previous buffer length as a "high water mark" that will be
2602        extended if the overlaying line is longer.  This process may be repeated
2603        as many times as desired before issuing a format command that prints the
2604        buffer.
2605 
2606        When overlaying characters, if a space overlays a printing character, a
2607        printing character overlays a space, or a printing character overlays
2608        itself, then the printing character is retained.  Otherwise, an
2609        "overprint character" (which defaults to DEL, but can be changed by the
2610        user) replaces the character in the buffer.
2611 
2612     4. Printers that support 12-channel VFUs treat the VFU format command as
2613        modulo 16.  Printers that support 8-channel VFUs treat the command as
2614        modulo 8.
2615 
2616     5. As a convenience to the user, the printer output file is flushed when a
2617        TOF operation is performed.  This permits inspection of the output file
2618        from the SCP command prompt while output is ongoing.
2619 
2620     6. The user may examine the TFAULT and PFAULT registers to determine why the
2621        printer went offline.
2622 
2623     7. The transfer service may be called with a null pointer to update the
2624        potential change in the flag state.
2625 
2626     8. If printing is attempted with the printer offline, this routine will be
2627        called with STROBE asserted (device_command_in TRUE) and DEMAND denied
2628        (device_flag_in TRUE).  The printer ignores STROBE if DEMAND is not
2629        asserted, so we simply return in this case.  This will hang the handshake
2630        until the printer is set online, and we are reentered with DEMAND
2631        asserted.  As a consequence, explicit protection against "uptr->fileref"
2632        being NULL is not required.
2633 
2634     9. Explicit tests for lowercase and control characters are much faster and
2635        are used rather than calls to "islower" and "iscntrl", which must
2636        consider the current locale.
2637 */
2638 
lp_service(UNIT * uptr)2639 static t_stat lp_service (UNIT *uptr)
2640 {
2641 const t_bool  printing = ((control_word & CN_FORMAT) != 0);    /* TRUE if a print command was received */
2642 static uint32 overprint_index = 0;
2643 PRINTER_TYPE  model;
2644 uint8         data_byte, format_byte;
2645 uint32        channel, line_count, slew_count, vfu_status;
2646 
2647 if (uptr == NULL)                                       /* if we're called for a state update */
2648     return SCPE_OK;                                     /*   then return with no other action */
2649 else                                                    /* otherwise */
2650     model = GET_MODEL (uptr->flags);                    /*   get the printer type */
2651 
2652 tprintf (lp_dev, DEB_SERV, "%s state printer service entered\n",
2653          state_name [sequencer]);
2654 
2655 if (device_command_out == FALSE) {                      /* if STROBE has denied */
2656     if (printing) {                                     /*   then if printing occurred */
2657         buffer_index = 0;                               /*     then clear the buffer */
2658 
2659         if (paper_fault) {                              /* if an out-of-paper condition is pending */
2660             if (print_props [model].fault_at_eol        /*   then if the printer faults at the end of any line */
2661               || current_line == 1)                     /*     or the printer is at the top of the form */
2662                 return lp_detach (uptr);                /*       then complete it now with the printer offline */
2663             }
2664 
2665         else if (tape_fault) {                          /* otherwise if a referenced VFU channel was not punched */
2666             tprintf (lp_dev, DEB_CMD, "Commanded VFU channel is not punched\n");
2667             lp_set_alarm (uptr);                        /*   then set an alarm condition that takes the printer offline */
2668             return SCPE_OK;
2669             }
2670 
2671         else if (offline_pending) {                     /* otherwise if a non-alarm offline request is pending */
2672             lp_set_locality (uptr, Offline);            /*   then take the printer offline now */
2673             return SCPE_OK;
2674             }
2675         }
2676 
2677     device_flag_in = FALSE;                             /* assert DEMAND to complete the handshake */
2678     uptr->wait = 0;                                     /*   and request direct entry when STROBE next asserts */
2679     }
2680 
2681 else if (device_flag_in == FALSE) {                     /* otherwise if STROBE has asserted while DEMAND is asserted */
2682     device_flag_in = TRUE;                              /*   then deny DEMAND */
2683 
2684     data_byte = (uint8) (data_out & DATA_MASK);         /* only the lower 7 bits are connected */
2685 
2686     if (printing == FALSE) {                            /* if loading the print buffer */
2687         if (data_byte > '_'                             /*   then if the character is "lowercase" */
2688           && print_props [model].char_set == 64)        /*     but the printer doesn't support it */
2689             data_byte = data_byte - 040;                /*       then shift it to "uppercase" */
2690 
2691         if ((data_byte < ' ' || data_byte == DEL)       /* if the character is a control character */
2692           && print_props [model].char_set != 128)       /*   but the printer doesn't support it */
2693             data_byte = ' ';                            /*     then substitute a space */
2694 
2695         if (buffer_index < print_props [model].line_length) {   /* if there is room in the buffer */
2696             if (overprint_index == 0                            /*   then if not overprinting */
2697               || buffer_index >= overprint_index                /*     or past the current buffer limit */
2698               || buffer [buffer_index] == ' ')                  /*     or overprinting a blank */
2699                 buffer [buffer_index] = data_byte;              /*       then store the character */
2700 
2701             else if (data_byte != ' '                           /* otherwise if we're overprinting a character */
2702               && data_byte != buffer [buffer_index])            /*   with a different character */
2703                 buffer [buffer_index] = (uint8) overprint_char; /*     then substitute the overprint character */
2704 
2705             buffer_index++;                             /* increment the buffer index */
2706 
2707             uptr->wait = dlyptr->buffer_load;           /* schedule the buffer load delay */
2708 
2709             tprintf (lp_dev, DEB_XFER, "Character %s sent to printer\n",
2710                      fmt_char (data_byte));
2711             }
2712 
2713         else if (print_props [model].autoprints) {      /* otherwise if a buffer overflow auto-prints */
2714             tprintf (lp_dev, DEB_CMD, "Buffer overflow printed %u characters on line %u\n",
2715                      buffer_index, current_line);
2716 
2717             buffer [buffer_index++] = CR;               /* tie off */
2718             buffer [buffer_index++] = LF;               /*   the current buffer */
2719 
2720             uptr->pos += sizeof buffer [0]                  /* write the buffer to the printer file */
2721               * (t_addr) fwrite (buffer, sizeof buffer [0], /*   and update the file position */
2722                                  buffer_index, uptr->fileref);
2723 
2724             current_line = current_line + 1;            /* move the paper one line */
2725 
2726             if (current_line > form_length)             /* if the current line is beyond the end of the form */
2727                 current_line = 1;                       /*   then reset to the top of the next form */
2728 
2729             tprintf (lp_dev, DEB_CMD, "Printer advanced 1 line to line %u\n",
2730                      current_line);
2731 
2732             overprint_index = 0;                        /* clear any accumulated overprint index */
2733 
2734             buffer [0] = data_byte;                     /* store the character */
2735             buffer_index = 1;                           /*   in the empty buffer */
2736 
2737             uptr->wait = dlyptr->print                  /* schedule the print delay */
2738                            + dlyptr->advance            /*   plus the paper advance delay */
2739                            + dlyptr->buffer_load;       /*   plus the buffer load delay */
2740 
2741             tprintf (lp_dev, DEB_XFER, "Character %s sent to printer\n",
2742                      fmt_char (data_byte));
2743             }
2744 
2745         else {
2746             uptr->wait = dlyptr->buffer_load;           /* schedule the buffer load delay */
2747 
2748             tprintf (lp_dev, DEB_CMD, "Buffer overflow discards character %s\n",
2749                      fmt_char (data_byte));
2750             }
2751         }
2752 
2753     else {                                              /* otherwise this is a print format command */
2754         tprintf (lp_dev, DEB_XFER, "Format code %03o sent to printer\n",
2755                  data_byte);
2756 
2757         format_byte = data_byte & FORMAT_MASK;          /* format commands ignore bits 10-11 */
2758 
2759         if (overprint_index > buffer_index)             /* if the overprinted line is longer than the current line */
2760             buffer_index = overprint_index;             /*   then extend the current buffer index */
2761 
2762         if (buffer_index > 0 && format_byte != FORMAT_SUPPRESS) /* if printing will occur, then trace it */
2763             tprintf (lp_dev, DEB_CMD, "Printed %u character%s on line %u\n",
2764                      buffer_index, (buffer_index == 1 ? "" : "s"), current_line);
2765 
2766         if (format_byte == FORMAT_SUPPRESS              /* if this is a "suppress space" request */
2767           && print_props [model].overprints) {          /*   and the printer is capable of overprinting */
2768             slew_count = 0;                             /*     then do not slew after printing */
2769 
2770             if (uptr->flags & UNIT_EXPAND) {            /* if the printer is in expanded mode */
2771                 if (buffer_index > overprint_index)     /*   then if the current line is longer than the overprinted line */
2772                     overprint_index = buffer_index;     /*     then extend the overprinted line */
2773 
2774                 buffer_index = 0;                       /* reset the buffer index to overprint the next line */
2775                 }
2776 
2777             else                                        /* otherwise the printer is in compact mode */
2778                 buffer [buffer_index++] = CR;           /*   so overprint by emitting a CR without a LF */
2779 
2780             tprintf (lp_dev, DEB_CMD, "Printer commanded to suppress spacing on line %u\n",
2781                      current_line);
2782             }
2783 
2784         else if (format_byte & FORMAT_VFU) {            /* otherwise if this is a VFU command */
2785             if (print_props [model].vfu_channels == 8)  /*   then if it's an 8-channel VFU */
2786                 format_byte &= FORMAT_VFU_8_MASK;       /*     then only three bits are significant */
2787 
2788             channel = VFU_CHANNEL_1 >> (format_byte - FORMAT_VFU_BIAS - 1); /* set the requested channel */
2789 
2790             tprintf (lp_dev, DEB_CMD, "Printer commanded to slew to VFU channel %u from line %u\n",
2791                      format_byte - FORMAT_VFU_BIAS, current_line);
2792 
2793             tape_fault = (channel & VFU [0]) == 0;      /* a tape fault occurs if there is no punch in this channel */
2794 
2795             slew_count = 0;                             /* initialize the slew counter */
2796 
2797             do {                                        /* the VFU always slews at least one line */
2798                 slew_count++;                           /* increment the slew counter */
2799                 current_line++;                         /*   and the line counter */
2800 
2801                 if (current_line > form_length)         /* if the current line is beyond the end of the form */
2802                     current_line = 1;                   /*   then reset to the top of the next form */
2803                 }
2804             while (!tape_fault && (channel & VFU [current_line]) == 0); /* continue until a punch is seen */
2805             }
2806 
2807         else {                                          /* otherwise it must be a slew command */
2808             slew_count = format_byte;                   /* get the number of lines to slew */
2809 
2810             if (format_byte == FORMAT_SUPPRESS)         /* if the printer cannot overprint */
2811                 slew_count = 1;                         /*   then the paper advances after printing */
2812 
2813             tprintf (lp_dev, DEB_CMD, "Printer commanded to slew %u line%s from line %u\n",
2814                      slew_count, (slew_count == 1 ? "" : "s"), current_line);
2815 
2816             current_line = current_line + slew_count;   /* move the current line */
2817 
2818             if (current_line > form_length)                 /* if the current line is beyond the end of the form */
2819                 current_line = current_line - form_length;  /*   then it extends onto the next form */
2820             }
2821 
2822         if (format_byte == FORMAT_VFU_CHAN_1            /* if a TOF was requested */
2823           && !(uptr->flags & UNIT_EXPAND)               /*   and the printer is in compact mode */
2824           && slew_count > 1) {                          /*     and more than one line is needed to reach the TOF */
2825             if (buffer_index > 0) {                     /*       then if the buffer not empty */
2826                 buffer [buffer_index++] = CR;           /*         then print */
2827                 buffer [buffer_index++] = LF;           /*           the current line */
2828                 }
2829 
2830             buffer [buffer_index++] = FF;               /* emit a FF to move to the TOF */
2831             }
2832 
2833         else if (slew_count > 0) {                      /* otherwise a slew is needed */
2834             buffer [buffer_index++] = CR;               /*   then emit a CR LF */
2835             buffer [buffer_index++] = LF;               /*     to print the current line */
2836 
2837             line_count = slew_count;                    /* get the number of lines to slew */
2838 
2839             while (--line_count > 0) {                  /* while movement is needed */
2840                 if (uptr->flags & UNIT_EXPAND)          /* if the printer is in expanded mode */
2841                     buffer [buffer_index++] = CR;       /*   then blank lines are CR LF pairs */
2842 
2843                 buffer [buffer_index++] = LF;           /* otherwise just LFs are used */
2844                 }
2845             }
2846 
2847         if (buffer_index > 0) {                             /* if the buffer is not empty */
2848             uptr->pos += sizeof buffer [0]                  /*   then write the buffer to the printer file */
2849               * (t_addr) fwrite (buffer, sizeof buffer [0], /*     and update the file position */
2850                                  buffer_index, uptr->fileref);
2851 
2852             overprint_index = 0;                        /* clear any existing overprint index */
2853             }
2854 
2855         vfu_status = 0;                                 /* assume no punches for channels 9 and 12 */
2856 
2857         if (print_props [model].vfu_channels > 8) {     /* if the printer VFU has more than 8 channels */
2858             if (VFU [current_line] & VFU_CHANNEL_9)     /*   then if channel 9 is punched for this line */
2859                 vfu_status |= ST_VFU_9;                 /*     then report it in the device status */
2860 
2861             if (VFU [current_line] & VFU_CHANNEL_12)    /* if channel 12 is punched for this line */
2862                 vfu_status |= ST_VFU_12;                /*   then report it in the device status */
2863             }
2864 
2865         set_device_status (ST_VFU_9 | ST_VFU_12, vfu_status);   /* set the VFU status */
2866 
2867         if (format_byte == FORMAT_VFU_CHAN_1)           /* if a TOF request was performed */
2868             fflush (uptr->fileref);                     /*   then flush the file buffer for inspection */
2869 
2870         uptr->wait = dlyptr->print                      /* schedule the print delay */
2871                        + slew_count * dlyptr->advance;  /*   plus the paper advance delay */
2872 
2873         if (slew_count > 0)
2874             tprintf (lp_dev, DEB_CMD, "Printer advanced %u line%s to line %u\n",
2875                      slew_count, (slew_count == 1 ? "" : "s"), current_line);
2876         }
2877 
2878     if (ferror (uptr->fileref)) {                       /* if a host file system error occurred */
2879         report_error (uptr->fileref);                   /*   then report the error to the console */
2880 
2881         lp_set_alarm (uptr);                            /* set an alarm condition */
2882         return SCPE_IOERR;                              /*   and stop the simulator */
2883         }
2884     }
2885 
2886 return SCPE_OK;                                         /* return event service success */
2887 }
2888 
2889 
2890 /* Attach the printer image file.
2891 
2892    The specified file is attached to the indicated unit.  This is the simulation
2893    equivalent of loading paper into the printer and pressing the ONLINE button.
2894    The transition from offline to online causes an interrupt.
2895 
2896    A new image file may be requested by giving the "-N" switch to the ATTACH
2897    command.  If an existing file is specified with "-N", it will be cleared; if
2898    specified without "-N", printer output will be appended to the end of the
2899    existing file content.  In all cases, the paper is positioned at the top of
2900    the form.
2901 
2902 
2903    Implementation notes:
2904 
2905     1. If we are called during a RESTORE command to reattach a file previously
2906        attached when the simulation was SAVEd, the device status and file
2907        position are not altered.
2908 
2909     2. The pointer to the appropriate event delay times is set in case we are
2910        being called during a RESTORE command (the assignment is redundant
2911        otherwise).
2912 */
2913 
lp_attach(UNIT * uptr,char * cptr)2914 static t_stat lp_attach (UNIT *uptr, char *cptr)
2915 {
2916 t_stat result;
2917 
2918 result = attach_unit (uptr, cptr);                      /* attach the specified printer image file */
2919 
2920 if (result == SCPE_OK                                   /* if the attach was successful */
2921   && not (sim_switches & SIM_SW_REST)) {                /*   and we are not being called during a RESTORE command */
2922     set_device_status (ST_NOT_READY, 0);                /*     then clear not-ready status */
2923 
2924     current_line = 1;                                   /* reset the line counter to the top of the form */
2925 
2926     tprintf (lp_dev, DEB_CMD, "Printer paper loaded\n");
2927 
2928     lp_set_locality (uptr, Online);                 /* set the printer online */
2929     }
2930 
2931 paper_fault = FALSE;                                    /* clear any existing paper fault */
2932 
2933 if (lp_dev.flags & DEV_REALTIME)                        /* if the printer is in real-time mode */
2934     dlyptr = &real_times [GET_MODEL (uptr->flags)];     /*   then point at the times for the current model */
2935 else                                                    /* otherwise */
2936     dlyptr = &fast_times;                               /*   point at the fast times */
2937 
2938 return result;                                          /* return the result of the attach */
2939 }
2940 
2941 
2942 /* Detach the printer image file.
2943 
2944    The specified file is detached from the indicated unit.  This is the
2945    simulation equivalent of running out of paper or unloading the paper from the
2946    printer.  The out-of-paper condition cause a paper fault alarm, and the
2947    printer goes offline.  The transition from online to offline causes an
2948    interrupt.
2949 
2950    When the printer runs out of paper, it will not go offline until characters
2951    present in the buffer are printed and paper motion stops.  In addition, the
2952    2607 printer waits until the paper reaches the top-of-form position before
2953    going offline.
2954 
2955    In simulation, entering a DETACH LP command while the printer is busy will
2956    defer the file detach until print operations reach the top of the next form
2957    (2607) or until the current print operation completes (2613/17/18).  An
2958    immediate detach may be forced by adding the -F switch to the DETACH command.
2959    This simulates physically removing the paper from the printer and succeeds
2960    regardless of the current printer state.
2961 
2962 
2963    Implementation notes:
2964 
2965     1. During simulator shutdown, this routine is called for all three units,
2966        not just the printer unit.  The printer must be detached, even if a
2967        detach has been deferred, to ensure that the file is closed properly.  We
2968        do this in response to a detach request with the SIM_SW_SHUT switch
2969        present.
2970 
2971     2. The DETACH ALL command will fail if any detach routine returns a status
2972        other than SCPE_OK.  Because a deferred detach is not fatal, we must
2973        return SCPE_OK, but we still want to print a warning to the user.
2974 
2975     3. Because the 2607 only paper faults at TOF, we must explicitly set the
2976        offline_pending flag, as lp_set_alarm may not have been called.
2977 */
2978 
lp_detach(UNIT * uptr)2979 static t_stat lp_detach (UNIT *uptr)
2980 {
2981 const PRINTER_TYPE model = GET_MODEL (uptr->flags);     /* the printer model number */
2982 
2983 if (uptr->flags & UNIT_ATTABLE)                         /* if we're being called for the printer unit */
2984     if ((uptr->flags & UNIT_ATT) == 0)                  /*   then if the unit is not currently attached */
2985         return SCPE_UNATT;                              /*     then report it */
2986 
2987     else {                                                  /* otherwise */
2988         if (sim_switches & (SWMASK ('F') | SIM_SW_SHUT)) {  /*   if this is a forced detach or shut down request */
2989             if (buffer_index != 0) {                        /*     then if the buffer is not empty */
2990                 if (buffer [buffer_index - 1] != LF         /*       then if the last buffer character */
2991                   && buffer [buffer_index - 1] != FF) {     /*         is not a line feed or form feed */
2992                     buffer [buffer_index++] = CR;           /*           then tie off */
2993                     buffer [buffer_index++] = LF;           /*             the current buffer */
2994                     }
2995 
2996                 fwrite (buffer, sizeof buffer [0],          /* write the partial buffer to the printer file */
2997                         buffer_index, uptr->fileref);
2998 
2999                 buffer_index = 0;                           /* clear the buffer index to permit detaching */
3000                 }
3001 
3002             current_line = 1;                               /* reset the printer to TOF to enable detaching */
3003             sim_cancel (uptr);                              /*   and terminate */
3004             device_command_out = FALSE;                     /*     any print action in progress */
3005             }
3006 
3007         if ((print_props [model].fault_at_eol           /* if the printer faults at the end of any line */
3008           || current_line == 1)                         /*   or the printer is at the top of the form */
3009           && lp_set_alarm (uptr)) {                     /*   and a paper alarm is accepted */
3010             paper_fault = TRUE;                         /*     then set the out-of-paper condition */
3011 
3012             tprintf (lp_dev, DEB_CMD, "Printer is out of paper\n");
3013 
3014             return detach_unit (uptr);                  /* detach the unit */
3015             }
3016 
3017         else {                                          /* otherwise the alarm was rejected at this time */
3018             paper_fault = TRUE;                         /*   so set the out-of-paper condition */
3019             offline_pending = TRUE;                     /*     but defer the detach */
3020 
3021             tprintf (lp_dev, DEB_CMD, "Paper out request deferred until print completes\n");
3022 
3023             cprintf ("%s\n", sim_error_text (SCPE_INCOMP)); /* report that the actual detach must be deferred */
3024             return SCPE_OK;                                 /*   until the buffer has been printed */
3025             }
3026         }
3027 
3028 else                                                    /* otherwise */
3029     return SCPE_UNATT;                                  /*   we've been called for the wrong unit */
3030 }
3031 
3032 
3033 /* Set the device modes.
3034 
3035    This validation routine is entered with the "value" parameter set to one of
3036    the DEVICE_MODES values.  The device flag implied by the value is set or
3037    cleared.  The unit, character, and descriptor pointers are not used.
3038 
3039 
3040    Implementation notes:
3041 
3042     1. Switching between printer and diagnostic mode sets the configuration
3043        jumpers accordingly.
3044 
3045     2. Switching between printer and diagnostic mode clears the event delay.
3046        This is necessary in case the command was entered while an event was
3047        queued.
3048 */
3049 
lp_set_mode(UNIT * uptr,int32 value,char * cptr,void * desc)3050 static t_stat lp_set_mode (UNIT *uptr, int32 value, char *cptr, void *desc)
3051 {
3052 switch ((DEVICE_MODES) value) {                         /* dispatch the mode to set */
3053 
3054     case Fast_Time:                                     /* entering optimized timing mode */
3055         lp_dev.flags &= ~DEV_REALTIME;                  /*   so clear the real-time flag */
3056         dlyptr = &fast_times;                           /*     and point at the fast times */
3057         break;
3058 
3059 
3060     case Real_Time:                                     /* entering realistic timing mode */
3061         lp_dev.flags |= DEV_REALTIME;                   /*   so set the real-time flag */
3062         dlyptr = &real_times [GET_MODEL (uptr->flags)]; /*     and point at the times for the current model */
3063         break;
3064 
3065 
3066     case Printer:                                       /* entering printer mode */
3067         lp_dev.flags &= ~DEV_DIAG;                      /*   so clear the diagnostic flag */
3068         xfer_unit.wait = 0;                             /*     and clear any event delay that had been set */
3069 
3070         jumper_set = PRINTER_JUMPERS;                   /* set the jumpers for printer operation */
3071         break;
3072 
3073 
3074     case Diagnostic:                                    /* entering diagnostic mode */
3075         lp_dev.flags |= DEV_DIAG;                       /*   so set the diagnostic flag */
3076         xfer_unit.wait = 0;                             /*     and clear any event delay that had been set */
3077 
3078         jumper_set = dha_control_word & DHA_JUMPER_MASK;    /* set the jumpers for DHA operation */
3079         break;
3080     }
3081 
3082 return SCPE_OK;                                         /* mode changes always succeed */
3083 }
3084 
3085 
3086 /* Set the printer model.
3087 
3088    This validation routine is called to set the model of the printer.  The
3089    "value" parameter is one of the UNIT_26nn constants that indicates the new
3090    model.  Validation isn't necessary, except to detect a model change and alter
3091    the real-time delays accordingly.
3092 */
3093 
lp_set_model(UNIT * uptr,int32 value,char * cptr,void * desc)3094 static t_stat lp_set_model (UNIT *uptr, int32 value, char *cptr, void *desc)
3095 {
3096 if (lp_dev.flags & DEV_REALTIME)                        /* if the printer is in real-time mode */
3097     dlyptr = &real_times [GET_MODEL (value)];           /*   then use the times for the new model */
3098 
3099 return SCPE_OK;                                         /* allow the reassignment to proceed */
3100 }
3101 
3102 
3103 /* Set the printer online or offline.
3104 
3105    This validation routine is called to set the printer online or offline.  The
3106    "value" parameter is UNIT_OFFLINE if the printer is going offline and is zero
3107    if the printer is going online.  This simulates pressing the ON/OFFLINE
3108    button on the printer.  The unit must be attached (i.e., paper must be
3109    loaded), before the printer may be set online or offline.
3110 
3111    If the printer is being taken offline, the buffer is checked to see if any
3112    characters are present.  If they are, or if the printer unit is currently
3113    scheduled (i.e., executing a print operation), the offline request is
3114    deferred until printing completes, and the routine returns "Command not
3115    complete" status to inform the user.  Otherwise, the unit is set offline,
3116    DEMAND is denied, and DEV END is asserted to indicate that the printer is not
3117    ready.
3118 
3119    If the printer is being put online and paper is present, the unit is set
3120    online, and any paper or tape fault present is cleared.  If the sequencer
3121    indicates an incomplete handshake, as would occur if paper ran out while
3122    printing, the transfer service is called to complete the handshake by
3123    asserting DEMAND.  Otherwise, DEMAND is asserted explicitly, and DEV END is
3124    denied.
3125 
3126    As a special case, a detach (out-of-paper condition) or offline request that
3127    has been deferred until printing completes may be cancelled by setting the
3128    printer online.  No other action is taken, because the printer has never
3129    transitioned to the offline state.
3130 
3131    Transitions between the offline and online state cause interrupts, and INTREQ
3132    is asserted to the IOP if a transition occurred (but not, e.g., for a SET LP
3133    OFFLINE command where the printer is already offline).
3134 
3135 
3136    Implementation notes:
3137 
3138     1. Although a deferred offline request is not fatal, we return SCPE_INCOMP
3139        to prevent "set_cmd" from setting the UNIT_OFFLINE bit in the unit flags
3140        before the printer actually goes offline.
3141 */
3142 
lp_set_on_offline(UNIT * uptr,int32 value,char * cptr,void * desc)3143 static t_stat lp_set_on_offline (UNIT *uptr, int32 value, char *cptr, void *desc)
3144 {
3145 if ((uptr->flags & UNIT_ATT) == 0)                      /* if the printer is detached */
3146     return SCPE_UNATT;                                  /*   then it can't be set online or offline */
3147 
3148 else if (value == UNIT_ONLINE)                          /* otherwise if this is an online request */
3149     if (paper_fault && offline_pending) {               /*   then if an out-of-paper condition is deferred */
3150         paper_fault = FALSE;                            /*     then cancel the request */
3151         offline_pending = FALSE;                        /*       leaving the file attached */
3152         }
3153 
3154     else                                                /*   otherwise it's a normal online request */
3155         lp_set_locality (uptr, Online);                 /*     so set the printer online */
3156 
3157 else if (lp_set_locality (uptr, Offline) == FALSE) {    /* otherwise if it cannot be set offline now */
3158     tprintf (lp_dev, DEB_CMD, "Offline request deferred until print completes\n");
3159     return SCPE_INCOMP;                                 /*   then let the user know */
3160     }
3161 
3162 return SCPE_OK;                                         /* return operation success */
3163 }
3164 
3165 
3166 /* Set the VFU tape.
3167 
3168    This validation routine is entered to set up the VFU on the printer.  It is
3169    invoked by one of two commands:
3170 
3171      SET LP VFU
3172      SET LP VFU=<filename>
3173 
3174    The first form loads the standard 66-line tape into the VFU.  The second form
3175    loads the VFU with the tape image specified by the filename.  The format of
3176    the tape image is described in the comments for the "lp_load_vfu" routine.
3177 
3178    On entry, "uptr" points at the printer unit, "cptr" points to the first
3179    character after the "VFU" keyword, and the "value" and "desc" parameters are
3180    unused.  If "cptr" is NULL, then the first command form was given, and the
3181    "lp_load_vfu" routine is called with a NULL file stream pointer to indicate
3182    that the standard VFU tape should be used.  Otherwise, the second command
3183    form was given, and "cptr" points to the supplied filename.  The file is
3184    opened, and the "lp_load_vfu" routine is called with the stream pointer to
3185    load the VFU tape image contained therein.
3186 */
3187 
lp_set_vfu(UNIT * uptr,int32 value,char * cptr,void * desc)3188 static t_stat lp_set_vfu (UNIT *uptr, int32 value, char *cptr, void *desc)
3189 {
3190 FILE   *vfu_stream;
3191 t_stat result;
3192 
3193 if (cptr == NULL)                                       /* if a VFU reset is requested */
3194     result = lp_load_vfu (uptr, NULL);                  /*   then reload the standard VFU tape */
3195 
3196 else if (*cptr == '\0')                                 /* otherwise if the filename was omitted */
3197     return SCPE_MISVAL;                                 /*   then report the missing argument */
3198 
3199 else {                                                  /* otherwise the filename was specified */
3200     vfu_stream = fopen (cptr, "r");                     /*   so attempt to open it */
3201 
3202     if (vfu_stream == NULL)                             /* if the open failed */
3203         return SCPE_OPENERR;                            /*   then report the error */
3204 
3205     result = lp_load_vfu (uptr, vfu_stream);            /* load the VFU tape from the file */
3206 
3207     fclose (vfu_stream);                                /* close the file */
3208     }
3209 
3210 return result;                                          /* return the result of the load */
3211 }
3212 
3213 
3214 /* Show the device modes.
3215 
3216    This display routine is called to show the device modes for the printer.  The
3217    output stream is passed in the "st" parameter, and the other parameters are
3218    ignored.  The timing mode and connection mode are printed.
3219 */
3220 
lp_show_mode(FILE * st,UNIT * uptr,int32 value,void * desc)3221 static t_stat lp_show_mode (FILE *st, UNIT *uptr, int32 value, void *desc)
3222 {
3223 fprintf (st, "%s timing, %s mode",                      /* print the timing and connection modes */
3224          (lp_dev.flags & DEV_REALTIME ? "realistic" : "fast"),
3225          (lp_dev.flags & DEV_DIAG ? "diagnostic" : "printer"));
3226 
3227 return SCPE_OK;
3228 }
3229 
3230 
3231 /* Show the VFU tape.
3232 
3233    This display routine is called to show the content of the tape currently
3234    loaded in the printer's VFU.  The "value" parameter indicates how the routine
3235    was called.  It is 0 if a SHOW LP command was given and 1 if a SHOW LP VFU
3236    command was issued.  For the former, only the VFU title is displayed.  The
3237    latter displays the VFU title, followed by a header labelling each of the
3238    channel columns  and then one line for each line of the form consisting of
3239    punch and no-punch characters, according to the VFU definition.
3240 
3241    The output stream is passed in the "st" parameter, and the "uptr" and "desc"
3242    parameters are ignored.
3243 
3244 
3245    Implementation notes:
3246 
3247     1. Setting the string precision for the header lines trims them to the
3248        appropriate number of channels.
3249 */
3250 
lp_show_vfu(FILE * st,UNIT * uptr,int32 value,void * desc)3251 static t_stat lp_show_vfu (FILE *st, UNIT *uptr, int32 value, void *desc)
3252 {
3253 static const char header_1 [] = " Ch 1 Ch 2 Ch 3 Ch 4 Ch 5 Ch 6 Ch 7 Ch 8 Ch 9 Ch10 Ch11 Ch12";
3254 static const char header_2 [] = " ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----";
3255 
3256 const PRINTER_TYPE model = GET_MODEL (uptr->flags);             /* the printer model number */
3257 const uint32 channel_count = print_props [model].vfu_channels;  /* the count of VFU channels */
3258 uint32 chan, line, current_channel;
3259 
3260 if (value == 0)                                         /* if we're called for a summary display */
3261     fputs (vfu_title, st);                              /*   then output only the VFU title */
3262 
3263 else {                                                      /* otherwise the full VFU definition is requested */
3264     fprintf (st, "\n%s tape is loaded.\n\n", vfu_title);    /*   so start by displaying the VFU title */
3265 
3266     fprintf (st, "Line %.*s\n", channel_count * 5, header_1);   /* display the */
3267     fprintf (st, "---- %.*s\n", channel_count * 5, header_2);   /*   channel headers */
3268 
3269     for (line = 1; line <= form_length; line++) {           /* loop through the VFU array */
3270         fprintf (st, "%3d ", line);                         /* display the current form line number */
3271 
3272         current_channel = VFU_CHANNEL_1;                    /* start with channel 1 */
3273 
3274         for (chan = 1; chan <= channel_count; chan++) {     /* loop through the defined channels */
3275             fputs ("    ", st);                             /* add some space */
3276 
3277             if (VFU [line] & current_channel)               /* if the current channel is punched for this line */
3278                 fputc (punched_char, st);                   /*   then display a punched location */
3279             else                                            /* otherwise */
3280                 fputc (unpunched_char, st);                 /*   display an unpunched location */
3281 
3282             current_channel = current_channel >> 1;         /* move to the next channel */
3283             }
3284 
3285         fputc ('\n', st);                                   /* end the line */
3286         }
3287     }
3288 
3289 return SCPE_OK;
3290 }
3291 
3292 
3293 
3294 /* Printer local utility routines */
3295 
3296 
3297 
3298 /* Printer reset.
3299 
3300    This routine is called when the MASTER CLEAR signal is asserted to the
3301    printer.  The "programmed_clear" parameter is TRUE if the routine is called
3302    for a Programmed Master Clear or IORESET assertion, and FALSE if the routine
3303    is called for a RESET or RESET LP command.  In the latter case, the presence
3304    of the "-P" switch indicates that this is a power-on reset.  In either case,
3305    the interface reset has already been performed; this routine is responsible
3306    for resetting the printer only.
3307 
3308    In hardware, asserting MASTER CLEAR:
3309 
3310      - clears the input buffer without printing
3311      - finishes printing the current line and performs any stored VFU action
3312      - inhibits DEMAND for approximately three milliseconds
3313 
3314    In simulation, the buffer index is reset, a tape fault is cleared, a paper
3315    fault is determined by the paper status, and any deferred offline command is
3316    cleared.  Printing is always "complete" at the point of entry, as the actual
3317    file write is instantaneous from the simulation perspective.  DEMAND is not
3318    altered, as the printer is "ready" as soon as the command completes.  DEV END
3319    is reset to the offline status (asserted if the printer is offline, denied if
3320    online).
3321 
3322    In addition, if a power-on reset (RESET -P) is done, the original FASTTIME
3323    settings are restored, the standard VFU tape is loaded, and the power failure
3324    warning is cleared.
3325 */
3326 
lp_reset(t_bool programmed_clear)3327 static t_stat lp_reset (t_bool programmed_clear)
3328 {
3329 const PRINTER_TYPE model = GET_MODEL (xfer_unit.flags); /* the printer model number */
3330 OUTBOUND_SET signals;
3331 uint32       new_status = 0;
3332 t_stat       result     = SCPE_OK;
3333 
3334 if (! programmed_clear && (sim_switches & SWMASK ('P'))) {  /* if this is a commanded power-on reset */
3335     fast_times.buffer_load = LP_BUFFER_LOAD;                /*   then reset the per-character transfer time, */
3336     fast_times.print       = LP_PRINT;                      /*     the print and advance-one-line time, */
3337     fast_times.advance     = LP_ADVANCE;                    /*       and the slew additional lines time */
3338 
3339     result = lp_load_vfu (xfer_uptr, NULL);                 /* load the standard VFU tape */
3340 
3341     power_warning = FALSE;                                  /* clear the power failure warning */
3342     }
3343 
3344 buffer_index = 0;                                       /* clear the buffer without printing */
3345 
3346 offline_pending = FALSE;                                /* cancel any pending offline request */
3347 
3348 tape_fault  = FALSE;                                    /* clear any tape fault */
3349 paper_fault = ! (xfer_unit.flags & UNIT_ATT);           /*   and set paper fault if out of paper */
3350 
3351 if (paper_fault && print_props [model].not_ready)       /* if paper is out and the printer reports it separately */
3352     new_status |= ST_NOT_READY;                         /*   then set not-ready status */
3353 
3354 if (xfer_unit.flags & UNIT_OFFLINE) {                   /* if the printer is offline */
3355     device_flag_in = TRUE;                              /*   then DEMAND denies while the printer is not ready */
3356     device_end_in  = TRUE;                              /*     and DEV END asserts while the printer is offline */
3357     }
3358 
3359 else {                                                  /* otherwise the printer is online */
3360     new_status |= ST_ONLINE;                            /*   so set online status */
3361 
3362     device_flag_in = FALSE;                             /* DEMAND asserts when the printer is ready */
3363     device_end_in  = FALSE;                             /*   and DEV END denies when the printer is online */
3364     }
3365 
3366 xfer_service (NULL);                                    /* tell the data transfer service that signals have changed */
3367 
3368 signals = set_device_status (ST_ONLINE | ST_NOT_READY,  /* set the new device status */
3369                              new_status);
3370 
3371 if (signals & INTREQ)                                   /* if the status change caused an interrupt */
3372     iop_assert_INTREQ (&lp_dib);                        /*   then assert the INTREQ signal */
3373 
3374 return result;                                          /* return the result of the reset */
3375 }
3376 
3377 
3378 /* Process the printer control word.
3379 
3380    This routine is called when a DCONTSTB or PCONTSTB assertion indicates that
3381    the control word is to be set.  No direct action is taken by the printer in
3382    response, so the routine simply returns.
3383 */
3384 
lp_control(uint32 control_word)3385 static OUTBOUND_SET lp_control (uint32 control_word)
3386 {
3387 return NO_SIGNALS;                                      /* no special control action is needed */
3388 }
3389 
3390 
3391 /* Set an alarm condition.
3392 
3393    This routine is called when an alarm condition exists.  An alarm occurs when
3394    paper is out (paper fault) or a VFU command addresses a channel that does not
3395    contain a punch (tape fault).  In response, the printer goes offline and,
3396    for all models except the 2607, becomes not-ready.
3397 
3398    On entry, the routine attempts to set the printer offline.  If this succeeds,
3399    the printer is set not-ready.  If it fails (for reasons explained in the
3400    comments for the "lp_set_on_offline" routine), it will be set offline and
3401    not-ready when printing completes.
3402 */
3403 
lp_set_alarm(UNIT * uptr)3404 static t_bool lp_set_alarm (UNIT *uptr)
3405 {
3406 const PRINTER_TYPE model = GET_MODEL (uptr->flags);     /* the printer model number */
3407 
3408 if (lp_set_locality (uptr, Offline)) {                  /* if the printer went offline */
3409     if (print_props [model].not_ready)                  /*   then if the printer reports ready status separately */
3410         set_device_status (ST_NOT_READY, ST_NOT_READY); /*     then set the printer not-ready */
3411 
3412     return TRUE;                                        /* return completion success */
3413     }
3414 
3415 else                                                    /* otherwise the offline request is pending */
3416     return FALSE;                                       /*   so return deferral status */
3417 }
3418 
3419 
3420 /* Set the printer locality.
3421 
3422    This routine is called to set the printer online or offline and returns TRUE
3423    if the request succeeded or FALSE if it was deferred.  An online request
3424    always succeeds, so it is up to the caller to ensure that going online is
3425    permissible (e.g., that paper is loaded into the printer).  An offline
3426    request succeeds only if the printer is idle.  If characters are present in
3427    the print buffer, or if the printer is printing or slewing, then the request
3428    is deferred until the current line is complete.
3429 
3430    The printer cable inversely connects DEMAND to the Device Flag input and
3431    ONLINE to the Device End input.  As both deny when the printer goes offline
3432    and assert when the printer goes online, Device Flag and Device End assert
3433    and deny, respectively.
3434 
3435    If the printer goes offline with an operation in progress, Device Flag will
3436    remain asserted, and the handshake sequencer will remain in the Device_Flag_1
3437    or Device_Flag_2 state until the printer is set online again.  The transfer
3438    service routine is informed of these state changes, so that the handshake can
3439    complete when the printer is again set online.
3440 
3441 
3442    Implementation notes:
3443 
3444     1. When called with a NULL parameter, the transfer service routine will
3445        update its internal device flag state but will take no other action.
3446        When called with a unit pointer, the routine continues the handshake
3447        sequence.
3448 */
3449 
lp_set_locality(UNIT * uptr,LOCALITY printer_state)3450 static t_bool lp_set_locality (UNIT *uptr, LOCALITY printer_state)
3451 {
3452 OUTBOUND_SET signals;
3453 
3454 if (printer_state == Offline) {                         /* if the printer is going offline */
3455     if (buffer_index == 0                               /*   then if the buffer is empty */
3456       && sim_is_active (uptr) == FALSE) {               /*     and the printer is idle */
3457         uptr->flags |= UNIT_OFFLINE;                    /*       then set the printer offline now */
3458 
3459         signals = set_device_status (ST_ONLINE, 0);     /* update the printer status */
3460 
3461         device_flag_in = TRUE;                          /* DEMAND denies while the printer is offline */
3462         device_end_in  = TRUE;                          /* DEV END asserts while the printer is offline */
3463 
3464         xfer_service (NULL);                            /* inform the service routine of the signal changes */
3465         }
3466 
3467     else {                                              /*   otherwise the request must wait */
3468         offline_pending = TRUE;                         /*     until the line is printed */
3469         return FALSE;                                   /*       and the command is not complete */
3470         }
3471     }
3472 
3473 else {                                                  /* otherwise the printer is going online */
3474     uptr->flags &= ~UNIT_OFFLINE;                       /*   so clear the unit flag */
3475 
3476     paper_fault = FALSE;                                /* clear any paper fault */
3477     tape_fault  = FALSE;                                /*   and any tape fault */
3478 
3479     signals = set_device_status (ST_ONLINE | ST_NOT_READY,  /* set online status */
3480                                  ST_ONLINE);                /*   and clear not ready status */
3481 
3482     device_flag_in = FALSE;                             /* DEMAND asserts when the printer is online */
3483     device_end_in  = FALSE;                             /*   and DEV END denies when the printer is online */
3484 
3485     if (sequencer != Idle)                              /* if the transfer handshake is in progress */
3486         xfer_service (uptr);                            /*   then complete the suspended operation */
3487     else                                                /* otherwise */
3488         xfer_service (NULL);                            /*   inform the service routine of the signal changes */
3489     }
3490 
3491 tprintf (lp_dev, DEB_CMD, "Printer set %s\n",
3492          (printer_state == Offline ? "offline" : "online"));
3493 
3494 if (signals & INTREQ)                                   /* if the transition caused an interrupt */
3495     iop_assert_INTREQ (&lp_dib);                        /*   then assert the INTREQ signal */
3496 
3497 offline_pending = FALSE;                                /* the operation completed */
3498 return TRUE;                                            /*   successfully */
3499 }
3500 
3501 
3502 /* Load the VFU.
3503 
3504    The printer VFU is loaded either with a custom tape image stored in the file
3505    associated with the stream "vf" or with the standard 66-line tape if the
3506    stream is NULL.  The "uptr" parameter points to the printer unit.
3507 
3508    The standard VFU tape (02607-80024 for the 8-channel HP 2607 and 02613-80001
3509    for the 12-channel HP 2613, 2617, and 2618) defines the channels as:
3510 
3511      Chan  Description
3512      ----  --------------
3513        1   Top of form
3514        2   Bottom of form
3515        3   Single space
3516        4   Double space
3517        5   Triple space
3518        6   Half page
3519        7   Quarter page
3520        8   Sixth page
3521        9   Bottom of form
3522 
3523    ...with channels 10-12 uncommitted.
3524 
3525    A custom tape file starts with a VFU definition line and then contains one
3526    channel-definition line for each line of the form.  The number of lines
3527    establishes the form length.  Channel 1 must be dedicated to the top-of-form,
3528    but the other channels may be defined as desired.
3529 
3530    A semicolon appearing anywhere on a line begins a comment, and the semicolon
3531    and all following characters are ignored.  Zero-length lines, including lines
3532    beginning with a semicolon, are ignored.
3533 
3534    Note that a line containing one or more blanks is not a zero-length line, so,
3535    for example, the line " ; a comment starting in column 2" is not ignored.
3536 
3537    The first (non-ignored) line in the file is a VFU definition line of this
3538    exact form:
3539 
3540      VFU=<punch characters>,<no-punch character>{,<title>}
3541 
3542    ...where:
3543 
3544      Parameter           Description
3545      ------------------  -------------------------------------------------------
3546      punch characters    a string of one or more characters used interchangeably
3547                          to represent a punched location
3548 
3549      no-punch character  a single character representing a non-punched location
3550 
3551      title               an optional descriptive string printed by the SHOW LP
3552                          VFU command ("Custom VFU" is used by default)
3553 
3554    If the "VFU" line is missing or not of the correct form, then "Format error"
3555    status is returned, and the VFU tape is not changed.
3556 
3557    The remaining (non-ignored) lines define the channels punched for each line
3558    of the printed form.  The line format consists of a sequence of punch,
3559    no-punch, and "other" characters in channel order.  Each punch or no-punch
3560    character defines a channel state, starting with channel 1 and proceeding
3561    left-to-right until all channels for the VFU are defined; if the line
3562    terminates before all channels are defined, the remaining channels are set to
3563    the no-punch state.  Any "other" characters (i.e., neither a punch character
3564    nor a no-punch character) are ignored and may be used freely to delineate the
3565    tape channels.
3566 
3567    Examples using the standard 66-line tape definition for an 8-channel VFU:
3568 
3569 
3570      ; the VFU definition                 |   VFU=1234578,  ; no-punch is a ' '
3571      VFU=1,0,a binary tape image          |
3572                                           |   1             ; top of form
3573      ; the channel definitions            |     345         ; form line 1
3574                                           |     3           ; form line 2
3575      10111111   ; top of form             |     34          ; form line 3
3576      00100000   ; single space            |     3 5         ; form line 4
3577      0011       ; channels 5-8 no-punch   |     34          ; form line 5
3578                                           |
3579      -------------------------------------+-------------------------------------
3580                                           |
3581      VFU=X,-,blanks are "others"          |   VFU=TO,.,brackets are "others"
3582                                           |   ; 1   2   3   4   5   6   7   8
3583      X  -  X  X  X  X  X  X   ; line 1    |   ;--- --- --- --- --- --- --- ---
3584      -  -  X  -  -  -  -  -   ; line 2    |    [T]  .  [O] [O] [O] [O] [O] [O]
3585      -  -  X  X  -  -  -  -   ; line 3    |     .   .  [O]  .   .   .   .   .
3586                                           |     .   .  [O] [O]  .   .   .   .
3587 
3588 
3589    On entry, the "vf" parameter determines whether the standard tape or a custom
3590    tape is to be loaded.  If "vf" is NULL, a standard 66-line tape is generated
3591    and stored in the tape buffer.  Otherwise, a custom tape file is read,
3592    parsed, and assembled VFU entries are stored in the tape buffer.  After
3593    generation or a successful tape load, the buffer is copied to the VFU array,
3594    the form length is set, the current line is reset to the top-of-form, and the
3595    state of VFU channels 9 and 12 are set into the device status.
3596 
3597 
3598    Implementation notes:
3599 
3600     1. VFU array entries 1-n correspond to form print lines 1-n.  Entry 0 is the
3601        logical OR of all of the other entries and is used during VFU format
3602        command processing to determine if a punch is present somewhere in a
3603        given channel.
3604 */
3605 
lp_load_vfu(UNIT * uptr,FILE * vf)3606 static t_stat lp_load_vfu (UNIT *uptr, FILE *vf)
3607 {
3608 const PRINTER_TYPE model = GET_MODEL (uptr->flags);     /* the printer model number */
3609 uint32             line, channel, vfu_status;
3610 int32              len;
3611 char               buffer [LINE_SIZE], punch [LINE_SIZE], no_punch;
3612 char               *bptr, *tptr;
3613 uint32             tape [VFU_SIZE] = { 0 };
3614 
3615 if (vf == NULL) {                                       /* if the standard VFU is requested */
3616     tape [ 1] = VFU_CHANNEL_1;                          /*   then punch channel 1 for the top of form */
3617     tape [60] = VFU_CHANNEL_2 | VFU_CHANNEL_9;          /*     and channels 2 and 9 for the bottom of form */
3618 
3619     for (line = 1; line <= 60; line++) {                            /* load each of the 60 printable lines */
3620         tape [line] |= VFU_CHANNEL_3                                /* punch channel 3 for single space */
3621                          | (line %  2 ==  1 ? VFU_CHANNEL_4 : 0)    /* punch channel 4 for double space */
3622                          | (line %  3 ==  1 ? VFU_CHANNEL_5 : 0)    /* punch channel 5 for triple space */
3623                          | (line % 30 ==  1 ? VFU_CHANNEL_6 : 0)    /* punch channel 6 for next half page */
3624                          | (line % 15 ==  1 ? VFU_CHANNEL_7 : 0)    /* punch channel 7 for next quarter page */
3625                          | (line % 10 ==  1 ? VFU_CHANNEL_8 : 0);   /* punch channel 8 for next sixth page */
3626 
3627         tape [0] |= tape [line];                        /* accumulate the channel punches */
3628         }
3629 
3630     form_length = 66;                                   /* set the form length */
3631     strcpy (vfu_title, "Standard VFU");                 /*   and set the title */
3632     }
3633 
3634 else {                                                  /* otherwise load a custom VFU from the file */
3635     len = lp_read_line (vf, buffer, sizeof buffer);     /* read the first line */
3636 
3637     if (len <= 0                                            /* if there isn't one */
3638       || strncmp (buffer, "VFU=", strlen ("VFU=")) != 0) {  /*   or it's not a VFU definition statement */
3639         cputs ("Missing VFU definition line\n");            /*     then complain to the console */
3640         return SCPE_FMT;                                    /*       and fail with a format error */
3641         }
3642 
3643     bptr = buffer + strlen ("VFU=");                    /* point at the first control argument */
3644 
3645     tptr = strtok (bptr, ",");                          /* parse the punch token */
3646 
3647     if (tptr == NULL) {                                             /* if it's missing */
3648         cputs ("Missing punch field in the VFU control line\n");    /*   then complain to the console */
3649         return SCPE_FMT;                                            /*     and fail with a format error */
3650         }
3651 
3652     strcpy (punch, tptr);                               /* save the set of punch characters */
3653 
3654     tptr = strtok (NULL, ",");                          /* parse the no-punch token */
3655 
3656     if (tptr == NULL){                                              /* if it's missing */
3657         cputs ("Missing no-punch field in the VFU control line\n"); /*   then complain to the console */
3658         return SCPE_FMT;                                            /*     and fail with a format error */
3659         }
3660 
3661     no_punch = *tptr;                                   /* save the no-punch character */
3662 
3663     tptr = strtok (NULL, ",");                          /* parse the optional title */
3664 
3665     if (tptr != NULL)                                   /* if it's present */
3666         strcpy (vfu_title, tptr);                       /*   then save the user's title */
3667     else                                                /* otherwise */
3668         strcpy (vfu_title, "Custom VFU");               /*   use a generic title */
3669 
3670 
3671     for (line = 1; line <= VFU_MAX; line++) {           /* load up to the maximum VFU tape length */
3672         len = lp_read_line (vf, buffer, sizeof buffer); /* read a tape definition line */
3673 
3674         if (len <= 0)                                   /* if at the EOF or an error occurred */
3675             break;                                      /*   then the load is complete */
3676 
3677         tptr = buffer;                                  /* point at the first character of the line */
3678 
3679         channel = VFU_CHANNEL_1;                        /* set the channel 1 indicator */
3680 
3681         while (channel != 0 && *tptr != '\0') {         /* loop until the channel or definition is exhausted */
3682             if (strchr (punch, *tptr) != NULL) {        /* if the character is in the punch set */
3683                 tape [line] |= channel;                 /*   then punch the current channel */
3684                 channel = channel >> 1;                 /*     and move to the next one */
3685                 }
3686 
3687             else if (*tptr == no_punch)                 /* otherwise if the character is the no-punch character */
3688                 channel = channel >> 1;                 /*   then move to the next channel */
3689 
3690             tptr++;                                     /* otherwise the character is neither, so ignore it */
3691             }
3692 
3693         tape [0] |= tape [line];                        /* accumulate the channel punches */
3694         }
3695 
3696 
3697     if ((tape [1] & VFU_CHANNEL_1) == 0) {                  /* if there is no channel 1 punch in the first line */
3698         cputs ("Missing punch in channel 1 of line 1\n");   /*   then complain to the console */
3699         return SCPE_FMT;                                    /*     and fail with a format error */
3700         }
3701 
3702     form_length = line - 1;                             /* set the form length */
3703     }
3704 
3705 memcpy (VFU, tape, sizeof VFU);                         /* copy the tape buffer to the VFU array */
3706 
3707 current_line = 1;                                       /* reset the line counter to the top of the form */
3708 
3709 vfu_status = 0;                                         /* assume no punches for channels 9 and 12 */
3710 
3711 if (print_props [model].vfu_channels > 8) {             /* if the printer VFU has more than 8 channels */
3712     if (VFU [1] & VFU_CHANNEL_9)                        /*   then if channel 9 is punched for this line */
3713         vfu_status |= ST_VFU_9;                         /*     then report it in the device status */
3714 
3715     if (VFU [1] & VFU_CHANNEL_12)                       /* if channel 12 is punched for this line */
3716         vfu_status |= ST_VFU_12;                        /*   then report it in the device status */
3717     }
3718 
3719 set_device_status (ST_VFU_9 | ST_VFU_12, vfu_status);   /* set the VFU status */
3720 
3721 return SCPE_OK;                                         /* the VFU was successfully loaded */
3722 }
3723 
3724 
3725 /* Read a line from the VFU file.
3726 
3727    This routine reads a line from the VFU tape image file designated by the file
3728    stream parameter "vf", stores the data in the string buffer pointed to by
3729    "line" and whose size is given by "size", and returns the length of that
3730    string.  Comments are stripped from lines that are read, and the routine
3731    continues to read until a non-zero-length line is found.  If the end of the
3732    file was reached, the return value is 0.  If a file error occurred, the
3733    return value is -1.
3734 
3735 
3736    Implementation notes:
3737 
3738     1. The routine assumes that the file was opened in text mode, so that
3739        automatic CRLF-to-LF conversion is done if needed.  This simplifies
3740        the end-of-line removal.
3741 */
3742 
lp_read_line(FILE * vf,char * line,uint32 size)3743 static int32 lp_read_line (FILE *vf, char *line, uint32 size)
3744 {
3745 char  *result;
3746 int32 len = 0;
3747 
3748 while (len == 0) {
3749     result = fgets (line, size, vf);                    /* get the next line from the file */
3750 
3751     if (result == NULL)                                 /* if an error occurred */
3752         if (feof (vf))                                  /*   then if the end of file was seen */
3753             return 0;                                   /*     then return an EOF indication */
3754 
3755         else {                                          /*   otherwise */
3756             report_error (vf);                          /*     report the error to the console */
3757             return -1;                                  /*       and return an error indication */
3758             }
3759 
3760     len = strlen (line);                                /* get the current line length */
3761 
3762     if (len > 0 && line [len - 1] == '\n')              /* if the last character is a newline */
3763         line [--len] = '\0';                            /*   then remove it and decrease the length */
3764 
3765     result = strchr (line, ';');                        /* search for a comment indicator */
3766 
3767     if (result != NULL) {                               /* if one was found */
3768         *result = '\0';                                 /*   then truncate the line at that point */
3769         len = (int32) (result - line);                  /*     and recalculate the line length */
3770         }
3771     }
3772 
3773 return len;
3774 }
3775