First Commit of my working state
[simh.git] / PDP11 / pdp11_lp.c
1 /* pdp11_lp.c: PDP-11 line printer simulator
2
3 Copyright (c) 1993-2007, Robert M Supnik
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
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
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
25
26 lpt LP11 line printer
27
28 19-Jan-07 RMS Added UNIT_TEXT flag
29 07-Jul-05 RMS Removed extraneous externs
30 19-May-03 RMS Revised for new conditional compilation scheme
31 25-Apr-03 RMS Revised for extended file support
32 29-Sep-02 RMS Added vector change/display support
33 New data structures
34 30-May-02 RMS Widened POS to 32b
35 06-Jan-02 RMS Added enable/disable support
36 09-Nov-01 RMS Added VAX support
37 07-Sep-01 RMS Revised interrupt mechanism
38 30-Oct-00 RMS Standardized register naming
39 */
40
41 #if defined (VM_PDP10) /* PDP10 version */
42 #error "LP11 is not supported on the PDP-10!"
43
44 #elif defined (VM_VAX) /* VAX version */
45 #include "vax_defs.h"
46
47 #else /* PDP-11 version */
48 #include "pdp11_defs.h"
49 #endif
50
51 #define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */
52 #define LPTCSR_RW (CSR_IE) /* read/write */
53
54 extern int32 int_req[IPL_HLVL];
55
56 int32 lpt_csr = 0; /* control/status */
57 int32 lpt_stopioe = 0; /* stop on error */
58
59 DEVICE lpt_dev;
60 t_stat lpt_rd (int32 *data, int32 PA, int32 access);
61 t_stat lpt_wr (int32 data, int32 PA, int32 access);
62 t_stat lpt_svc (UNIT *uptr);
63 t_stat lpt_reset (DEVICE *dptr);
64 t_stat lpt_attach (UNIT *uptr, char *ptr);
65 t_stat lpt_detach (UNIT *uptr);
66
67 /* LPT data structures
68
69 lpt_dev LPT device descriptor
70 lpt_unit LPT unit descriptor
71 lpt_reg LPT register list
72 */
73
74 DIB lpt_dib = {
75 IOBA_LPT, IOLN_LPT, &lpt_rd, &lpt_wr,
76 1, IVCL (LPT), VEC_LPT, { NULL }
77 };
78
79 UNIT lpt_unit = {
80 UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 0), SERIAL_OUT_WAIT
81 };
82
83 REG lpt_reg[] = {
84 { GRDATA (BUF, lpt_unit.buf, DEV_RDX, 8, 0) },
85 { GRDATA (CSR, lpt_csr, DEV_RDX, 16, 0) },
86 { FLDATA (INT, IREQ (LPT), INT_V_LPT) },
87 { FLDATA (ERR, lpt_csr, CSR_V_ERR) },
88 { FLDATA (DONE, lpt_csr, CSR_V_DONE) },
89 { FLDATA (IE, lpt_csr, CSR_V_IE) },
90 { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
91 { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
92 { FLDATA (STOP_IOE, lpt_stopioe, 0) },
93 { GRDATA (DEVADDR, lpt_dib.ba, DEV_RDX, 32, 0), REG_HRO },
94 { GRDATA (DEVVEC, lpt_dib.vec, DEV_RDX, 16, 0), REG_HRO },
95 { NULL }
96 };
97
98 MTAB lpt_mod[] = {
99 { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS",
100 &set_addr, &show_addr, NULL },
101 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
102 &set_vec, &show_vec, NULL },
103 { 0 }
104 };
105
106 DEVICE lpt_dev = {
107 "LPT", &lpt_unit, lpt_reg, lpt_mod,
108 1, 10, 31, 1, DEV_RDX, 8,
109 NULL, NULL, &lpt_reset,
110 NULL, &lpt_attach, &lpt_detach,
111 &lpt_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS
112 };
113
114 /* Line printer routines
115
116 lpt_rd I/O page read
117 lpt_wr I/O page write
118 lpt_svc process event (printer ready)
119 lpt_reset process reset
120 lpt_attach process attach
121 lpt_detach process detach
122 */
123
124 t_stat lpt_rd (int32 *data, int32 PA, int32 access)
125 {
126 if ((PA & 02) == 0) *data = lpt_csr & LPTCSR_IMP; /* csr */
127 else *data = lpt_unit.buf; /* buffer */
128 return SCPE_OK;
129 }
130
131 t_stat lpt_wr (int32 data, int32 PA, int32 access)
132 {
133 if ((PA & 02) == 0) { /* csr */
134 if (PA & 1) return SCPE_OK;
135 if ((data & CSR_IE) == 0) CLR_INT (LPT);
136 else if ((lpt_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
137 SET_INT (LPT);
138 lpt_csr = (lpt_csr & ~LPTCSR_RW) | (data & LPTCSR_RW);
139 }
140 else {
141 if ((PA & 1) == 0) lpt_unit.buf = data & 0177; /* buffer */
142 lpt_csr = lpt_csr & ~CSR_DONE;
143 CLR_INT (LPT);
144 if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) ||
145 (lpt_unit.buf == 012)) sim_activate (&lpt_unit, lpt_unit.wait);
146 else sim_activate (&lpt_unit, 0);
147 }
148 return SCPE_OK;
149 }
150
151 t_stat lpt_svc (UNIT *uptr)
152 {
153 lpt_csr = lpt_csr | CSR_ERR | CSR_DONE;
154 if (lpt_csr & CSR_IE) SET_INT (LPT);
155 if ((uptr->flags & UNIT_ATT) == 0)
156 return IORETURN (lpt_stopioe, SCPE_UNATT);
157 fputc (uptr->buf & 0177, uptr->fileref);
158 uptr->pos = ftell (uptr->fileref);
159 if (ferror (uptr->fileref)) {
160 perror ("LPT I/O error");
161 clearerr (uptr->fileref);
162 return SCPE_IOERR;
163 }
164 lpt_csr = lpt_csr & ~CSR_ERR;
165 return SCPE_OK;
166 }
167
168 t_stat lpt_reset (DEVICE *dptr)
169 {
170 lpt_unit.buf = 0;
171 lpt_csr = CSR_DONE;
172 if ((lpt_unit.flags & UNIT_ATT) == 0) lpt_csr = lpt_csr | CSR_ERR;
173 CLR_INT (LPT);
174 sim_cancel (&lpt_unit); /* deactivate unit */
175 return SCPE_OK;
176 }
177
178 t_stat lpt_attach (UNIT *uptr, char *cptr)
179 {
180 t_stat reason;
181
182 lpt_csr = lpt_csr & ~CSR_ERR;
183 reason = attach_unit (uptr, cptr);
184 if ((lpt_unit.flags & UNIT_ATT) == 0) lpt_csr = lpt_csr | CSR_ERR;
185 return reason;
186 }
187
188 t_stat lpt_detach (UNIT *uptr)
189 {
190 lpt_csr = lpt_csr | CSR_ERR;
191 return detach_unit (uptr);
192 }