First Commit of my working state
[simh.git] / HP2100 / hp2100_baci.c
CommitLineData
196ba1fc
PH
1/* hp2100_baci.c: HP 12966A buffered asynchronous communications interface simulator\r
2\r
3 Copyright (c) 2007-2008, J. David Bryan\r
4\r
5 Permission is hereby granted, free of charge, to any person obtaining a\r
6 copy of this software and associated documentation files (the "Software"),\r
7 to deal in the Software without restriction, including without limitation\r
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
9 and/or sell copies of the Software, and to permit persons to whom the\r
10 Software is furnished to do so, subject to the following conditions:\r
11\r
12 The above copyright notice and this permission notice shall be included in\r
13 all copies or substantial portions of the Software.\r
14\r
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
18 THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21\r
22 Except as contained in this notice, the name of the author shall not be\r
23 used in advertising or otherwise to promote the sale, use or other dealings\r
24 in this Software without prior written authorization from the author.\r
25\r
26 BACI 12966A BACI card\r
27\r
28 13-Jun-08 JDB Cleaned up debug reporting for sim_activate calls\r
29 16-Apr-08 JDB Separated terminal I/O and Telnet poll for idle compatibility\r
30 07-Dec-07 JDB Created BACI device\r
31\r
32 References:\r
33 - HP 12966A Buffered Asynchronous Data Communications Interface Installation\r
34 and Reference Manual (12966-90001, Jul-1982)\r
35 - Western Digital Communications Products Handbook (Jun-1984)\r
36\r
37\r
38 The 12966A BACI card supplanted the 12531C Teletype and 12880A CRT interfaces\r
39 as the primary terminal connection for HP 1000 systems. The main advantage\r
40 of this card over the others was its 128-character FIFO memory. While this\r
41 allowed more efficient I/O than its interrupt-per-character predecessors, the\r
42 most significant advantage was that block input from the 264x-series of CRT\r
43 terminals was supported. The 264x were the first HP-supported terminals to\r
44 provide local editing and character storage, as well as mass storage via dual\r
45 DC-100 minicartridge drives. This support meant that input from the terminal\r
46 could come in bursts at the full baud rate, which would overrun the older\r
47 cards that needed a small intercharacter handling time. Also, the older\r
48 cards placed a substantial load on the CPU in high-baud-rate output\r
49 applications. Indeed, block output under RTE on a 1000 M-Series with a\r
50 12880A CRT card would saturate the CPU at about 5700 baud.\r
51\r
52 For a while, the BACI and the earlier cards were both supported as the system\r
53 console interface, and RTE primary systems were generated with drivers for\r
54 both cards. The boot-time I/O reconfigurator would detect the presence of\r
55 the BACI card and would dynamically select the correct driver (DVR05 vs.\r
56 DVR00). However, the 12880A card faded quickly as the 264x and later 262x\r
57 terminals gained in popularity, and support for the 12880A was dropped in\r
58 favor of the BACI. This meant that later RTE primary systems could only be\r
59 run on CPUs containing a BACI card.\r
60\r
61 The simulation supports terminal and diagnostic modes. The latter simulates\r
62 the installation of the 12966-60003 diagnostic loopback connector on the\r
63 card.\r
64\r
65 Fifteen programmable baud rates were supported by the BACI. We simulate\r
66 these "realistic" rates by scheduling I/O service based on the appropriate\r
67 number of 1000 E-Series instructions for the rate selected. We also provide\r
68 an "external rate" that is equivalent to 9600 baud, as most terminals were\r
69 set to their maximum speeds.\r
70\r
71 We support the 12966A connected to an HP terminal emulator via Telnet.\r
72 Internally, we model the BACI as a terminal multiplexer with one line. The\r
73 simulation is complicated by the half-duplex nature of the card (there is\r
74 only one FIFO, used selectively either for transmission or reception) and the\r
75 double-buffered UART (a Western Digital TR1863A), which has holding registers\r
76 as well as a shift registers for transmission and reception. We model both\r
77 sets of device registers.\r
78\r
79 During an output operation, the first character output to the card passes\r
80 through the FIFO and into the transmitter holding register. Subsequent\r
81 characters remain in the FIFO. If the FIFO is then turned around by a mode\r
82 switch from transmission to reception, the second character output becomes\r
83 the first character input to the CPU, as the first character output remains\r
84 in the THR. Also, the FIFO counter reflects the combined state of the FIFO\r
85 and the THR: it is incremented by a "shift in" to the FIFO and decremented by\r
86 the "transmit complete" signal from the UART. This has two implications:\r
87\r
88 1. If the FIFO is turned around before the character in the THR is\r
89 transmitted, the counter will not decrement when transmission is\r
90 complete, so the FIFO will show as "empty" when the counter reads "1".\r
91\r
92 2. The FIFO counter will indicate "half full" and "full" one character\r
93 before the FIFO itself reaches those stages.\r
94\r
95 The diagnostic hood connects the UART clock to a spare output register. This\r
96 allows the diagnostic to supply programmed clock pulses to the UART. The\r
97 serial transmit and receive lines from the UART are also available to the\r
98 diagnostic. Functional operation is checked by supplying or testing serial\r
99 data while clocking the UART sixteen times for each bit. This meant that we\r
100 had to model the UART shift registers for faithful hardware simulation.\r
101\r
102 The simulation provides both the "realistic timing" described above, as well\r
103 as an "optimized (fast) timing" option. Optimization makes three\r
104 improvements:\r
105\r
106 1. On output, characters in the FIFO are emptied into the Telnet buffer as a\r
107 block, rather than one character per service call, and on input, all of\r
108 the characters available in the Telnet buffer are loaded into the FIFO as\r
109 a block.\r
110\r
111 2. The ENQ/ACK handshake is done locally, without involving the Telnet\r
112 client.\r
113\r
114 3. Input occurring during an output operation is delayed until the second or\r
115 third consecutive ENQ/ACK handshake.\r
116\r
117 During development, it was noted that a comparatively long time elapsed\r
118 (approximately 30 milliseconds on a 3 GHz system) between the transmission of\r
119 an ENQ and the reception of the ACK. As the RTE BACI driver, DVR05, does\r
120 three ENQ/ACKs at the end of each line, plus an additional ENQ/ACK every 33\r
121 characters within a line, maximum throughput was about ten lines per second.\r
122 The source of this delay is not understood but apparently lies within the\r
123 terminal emulator, as it was observed with two emulators from two different\r
124 companies. Absorbing the ENQ and generating the ACK locally provided a\r
125 dramatic improvement in output speed.\r
126\r
127 However, as a result, RTE break-mode became effectively impossible, i.e.,\r
128 striking a key during output no longer produced the break-mode prompt. This\r
129 was traced to the RTE driver. DVR05 only checks for an input character\r
130 during ENQ/ACK processing, and then only during the second and third\r
131 end-of-line handshakes. When the ENQ/ACKs were eliminated, break-mode also\r
132 disappeared.\r
133\r
134 The workaround is to save a character received during output and supply it\r
135 during the second or third consecutive handshake. This ensures that\r
136 break-mode is recognized. Because the driver tries to "cheat" the card by\r
137 selecting receive mode before the ENQ has actually been transmitted (in order\r
138 to save an interrupt), the FIFO counter becomes "off by one" and is reset\r
139 with a master clear at the end of each handshake. This would normally clear\r
140 the UART receiving register, thereby losing the deferred character. We work\r
141 around this by skipping the register clear in "fast timing" mode.\r
142*/\r
143\r
144#include <ctype.h>\r
145\r
146#include "hp2100_defs.h"\r
147#include "sim_sock.h"\r
148#include "sim_tmxr.h"\r
149\r
150\r
151/* Program limits */\r
152\r
153#define FIFO_SIZE 128 /* read/write buffer size */\r
154\r
155\r
156/* Character constants */\r
157\r
158#define ENQ '\005'\r
159#define ACK '\006'\r
160\r
161\r
162/* Unit flags */\r
163\r
164#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */\r
165#define UNIT_V_FASTTIME (UNIT_V_UF + 1) /* fast timing mode */\r
166#define UNIT_V_CAPSLOCK (UNIT_V_UF + 2) /* caps lock mode */\r
167\r
168#define UNIT_DIAG (1 << UNIT_V_DIAG)\r
169#define UNIT_FASTTIME (1 << UNIT_V_FASTTIME)\r
170#define UNIT_CAPSLOCK (1 << UNIT_V_CAPSLOCK)\r
171\r
172\r
173/* Debug flags */\r
174\r
175#define DEB_CMDS (1 << 0) /* commands and status */\r
176#define DEB_CPU (1 << 1) /* CPU I/O */\r
177#define DEB_BUF (1 << 2) /* buffer gets and puts */\r
178#define DEB_XFER (1 << 3) /* character reads and writes */\r
179\r
180\r
181/* Bit flags */\r
182\r
183#define OUT_MR 0100000 /* common master reset */\r
184\r
185#define OUT_ENCM 0000040 /* ID1: enable character mode */\r
186#define OUT_ENCB 0000020 /* ID1: enable CB */\r
187#define OUT_ENCC 0000010 /* ID1: enable CC */\r
188#define OUT_ENCE 0000004 /* ID1: enable CE */\r
189#define OUT_ENCF 0000002 /* ID1: enable CF */\r
190#define OUT_ENSXX 0000001 /* ID1: enable SBB/SCF */\r
191\r
192#define OUT_DIAG 0000040 /* ID2: diagnostic output */\r
193#define OUT_REFCB 0000020 /* ID2: reference CB */\r
194#define OUT_REFCC 0000010 /* ID2: reference CC */\r
195#define OUT_REFCE 0000004 /* ID2: reference CE */\r
196#define OUT_REFCF 0000002 /* ID2: reference CF */\r
197#define OUT_REFSXX 0000001 /* ID2: reference SBB/SCF */\r
198\r
199#define OUT_STBITS 0000040 /* ID3: number of stop bits */\r
200#define OUT_ECHO 0000020 /* ID3: enable echo */\r
201#define OUT_PARITY 0000010 /* ID3: enable parity */\r
202#define OUT_PAREVEN 0000004 /* ID3: even parity or odd */\r
203\r
204#define OUT_XMIT 0000400 /* ID4: transmit or receive */\r
205#define OUT_CA 0000200 /* ID4: CA on */\r
206#define OUT_CD 0000100 /* ID4: CD on */\r
207#define OUT_SXX 0000040 /* ID4: SBA/SCA on */\r
208#define OUT_DCPC 0000020 /* ID4: DCPC on */\r
209\r
210#define OUT_CSC 0000040 /* ID5: clear special char interrupt */\r
211#define OUT_CBH 0000020 /* ID5: clear buffer half-full interrupt */\r
212#define OUT_CBF 0000010 /* ID5: clear buffer full interrupt */\r
213#define OUT_CBE 0000004 /* ID5: clear buffer empty interrupt */\r
214#define OUT_CBRK 0000002 /* ID5: clear break interrupt */\r
215#define OUT_COVR 0000001 /* ID5: clear overrun/parity interrupt */\r
216\r
217#define OUT_SPFLAG 0000400 /* ID6: special character */\r
218\r
219#define OUT_IRQCLR (OUT_CBH | OUT_CBF | OUT_CBE | OUT_CBRK | OUT_COVR)\r
220\r
221\r
222#define IN_VALID 0100000 /* received data: character valid */\r
223#define IN_SPFLAG 0040000 /* received data: is special character */\r
224\r
225#define IN_DEVINT 0100000 /* status: device interrupt */\r
226#define IN_SPCHAR 0040000 /* status: special char has been recd */\r
227#define IN_SPARE 0010000 /* status: spare receiver state */\r
228#define IN_TEST 0004000 /* status: unprocessed serial data line */\r
229#define IN_BUFHALF 0001000 /* status: buffer is half full */\r
230#define IN_BUFFULL 0000400 /* status: buffer is full */\r
231#define IN_BUFEMPTY 0000200 /* status: buffer is empty */\r
232#define IN_BREAK 0000100 /* status: break detected */\r
233#define IN_OVRUNPE 0000040 /* status: overrun or parity error */\r
234#define IN_CB 0000020 /* status: CB is on */\r
235#define IN_CC 0000010 /* status: CC is on */\r
236#define IN_CE 0000004 /* status: CE is on */\r
237#define IN_CF 0000002 /* status: CF is on */\r
238#define IN_SXX 0000001 /* status: SBB/SCF is on */\r
239\r
240#define IN_MODEM (IN_CB | IN_CC | IN_CE | IN_CF | IN_SXX)\r
241#define IN_LOOPBACK (IN_DEVINT | IN_SPARE | IN_TEST | IN_MODEM)\r
242#define IN_STDIRQ (IN_DEVINT | IN_SPCHAR | IN_BREAK | IN_OVRUNPE)\r
243#define IN_FIFOIRQ (IN_BUFEMPTY | IN_BUFHALF | IN_BUFFULL)\r
244\r
245\r
246/* Packed starting bit numbers */\r
247\r
248#define OUT_V_ID 12 /* common output word ID */\r
249#define OUT_V_DATA 0 /* ID 0: output data character */\r
250#define OUT_V_CHARSIZE 0 /* ID 3: character size */\r
251#define OUT_V_BAUDRATE 0 /* ID 4: baud rate */\r
252#define OUT_V_SPCHAR 0 /* ID 6: special character */\r
253\r
254#define IN_V_CHARCNT 8 /* data: char count in buffer */\r
255#define IN_V_DATA 0 /* data: input character */\r
256#define IN_V_IRQCLR 5 /* status: interrupt status clear */\r
257\r
258\r
259/* Packed bit widths */\r
260\r
261#define OUT_W_ID 3\r
262#define OUT_W_DATA 8\r
263#define OUT_W_CHARSIZE 2\r
264#define OUT_W_BAUDRATE 4\r
265#define OUT_W_SPCHAR 8\r
266\r
267#define IN_W_CHARCNT 6\r
268#define IN_W_DATA 8\r
269\r
270/* Packed bit masks */\r
271\r
272#define OUT_M_ID ((1 << OUT_W_ID) - 1)\r
273#define OUT_M_DATA ((1 << OUT_W_DATA) - 1)\r
274#define OUT_M_CHARSIZE ((1 << OUT_W_CHARSIZE) - 1)\r
275#define OUT_M_BAUDRATE ((1 << OUT_W_BAUDRATE) - 1)\r
276#define OUT_M_SPCHAR ((1 << OUT_W_SPCHAR) - 1)\r
277\r
278#define IN_M_CHARCNT ((1 << IN_W_CHARCNT) - 1)\r
279#define IN_M_DATA ((1 << IN_W_DATA) - 1)\r
280\r
281/* Packed field masks */\r
282\r
283#define OUT_ID (OUT_M_ID << OUT_V_ID)\r
284#define OUT_DATA (OUT_M_DATA << OUT_V_DATA)\r
285#define OUT_CHARSIZE (OUT_M_CHARSIZE << OUT_V_CHARSIZE)\r
286#define OUT_BAUDRATE (OUT_M_BAUDRATE << OUT_V_BAUDRATE)\r
287#define OUT_SPCHAR (OUT_M_SPCHAR << OUT_V_SPCHAR)\r
288\r
289#define IN_CHARCNT (IN_M_CHARCNT << IN_V_CHARCNT)\r
290#define IN_DATA (IN_M_DATA << IN_V_DATA)\r
291\r
292\r
293/* Command helpers */\r
294\r
295#define TO_CHARCNT(c) (((c) << IN_V_CHARCNT) & IN_CHARCNT)\r
296\r
297#define GET_ID(i) (((i) & OUT_ID) >> OUT_V_ID)\r
298#define GET_BAUDRATE(b) (((b) & OUT_BAUDRATE) >> OUT_V_BAUDRATE)\r
299\r
300#define IO_MODE (baci_icw & OUT_XMIT)\r
301#define XMIT OUT_XMIT\r
302#define RECV 0\r
303\r
304#define CLEAR_HR 0 /* UART holding register clear value */\r
305#define CLEAR_R -1 /* UART register clear value */\r
306\r
307\r
308/* Unit references */\r
309\r
310#define baci_term baci_unit[0] /* terminal I/O unit */\r
311#define baci_poll baci_unit[1] /* Telnet polling unit */\r
312\r
313\r
314/* External variables */\r
315\r
316extern uint32 PC;\r
317extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];\r
318extern FILE *sim_deb;\r
319\r
320\r
321/* BACI state variables */\r
322\r
323uint16 baci_ibuf = 0; /* status/data in */\r
324uint16 baci_obuf = 0; /* command/data out */\r
325uint16 baci_status = 0; /* current status */\r
326\r
327uint16 baci_edsiw = 0; /* enable device status word */\r
328uint16 baci_dsrw = 0; /* device status reference word */\r
329uint16 baci_cfcw = 0; /* character frame control word */\r
330uint16 baci_icw = 0; /* interface control word */\r
331uint16 baci_isrw = 0; /* interrupt status reset word */\r
332\r
333uint32 baci_fput = 0; /* FIFO buffer add index */\r
334uint32 baci_fget = 0; /* FIFO buffer remove index */\r
335uint32 baci_fcount = 0; /* FIFO buffer counter */\r
336uint32 baci_bcount = 0; /* break counter */\r
337\r
338uint8 baci_fifo [FIFO_SIZE]; /* read/write buffer FIFO */\r
339uint8 baci_spchar [256]; /* special character RAM */\r
340\r
341uint16 baci_uart_thr = CLEAR_HR; /* UART transmitter holding register */\r
342uint16 baci_uart_rhr = CLEAR_HR; /* UART receiver holding register */\r
343 int32 baci_uart_tr = CLEAR_R; /* UART transmitter register */\r
344 int32 baci_uart_rr = CLEAR_R; /* UART receiver register */\r
345uint32 baci_uart_clk = 0; /* UART transmit/receive clock */\r
346\r
347t_bool baci_enq_seen = FALSE; /* ENQ seen flag */\r
348uint32 baci_enq_cntr = 0; /* ENQ seen counter */\r
349\r
350\r
351/* Terminal multiplexer library interface */\r
352\r
353TMLN baci_ldsc = { 0 }; /* line descriptor */\r
354TMXR baci_desc = { 1, 0, 0, &baci_ldsc }; /* device descriptor */\r
355\r
356\r
357/* BACI local routines */\r
358\r
359static int32 service_time (uint32 control_word);\r
360static const char *fmt_char (uint8 ch);\r
361static void update_status (void);\r
362static void master_reset (uint32 selcode);\r
363\r
364static uint32 fifo_get (void);\r
365static void fifo_put (uint8 ch);\r
366static void clock_uart (void);\r
367\r
368/* BACI global routines */\r
369\r
370 int32 baci_io (int32 inst, int32 IR, int32 dat);\r
371t_stat baci_term_svc (UNIT *uptr);\r
372t_stat baci_poll_svc (UNIT *uptr);\r
373t_stat baci_reset (DEVICE *dptr);\r
374t_stat baci_attach (UNIT *uptr, char *cptr);\r
375t_stat baci_detach (UNIT *uptr);\r
376t_stat baci_show (FILE *st, UNIT *uptr, int32 val, void *desc);\r
377\r
378\r
379/* BACI data structures\r
380\r
381 baci_dib BACI device information block\r
382 baci_dev BACI device descriptor\r
383 baci_unit BACI unit list\r
384 baci_reg BACI register list\r
385 baci_mod BACI modifier list\r
386 baci_deb BACI debug list\r
387\r
388 Two units are used: one to handle character I/O via the Telnet library, and\r
389 another to poll for connections and input. The character I/O service routine\r
390 runs only when there are characters to read or write. It operates at the\r
391 approximate baud rate of the terminal (in CPU instructions per second) in\r
392 order to be compatible with the OS drivers. The Telnet poll must run\r
393 continuously, but it can operate much more slowly, as the only requirement is\r
394 that it must not present a perceptible lag to human input. To be compatible\r
395 with CPU idling, it is co-scheduled with the master poll timer, which uses a\r
396 ten millisecond period.\r
397*/\r
398\r
399DIB baci_dib = { BACI, 0, 0, 0, 0, 0, &baci_io };\r
400\r
401DEVICE baci_dev;\r
402\r
403UNIT baci_unit[] =\r
404 { { UDATA (&baci_term_svc, UNIT_ATTABLE | UNIT_FASTTIME, 0) }, /* terminal I/O unit */\r
405 { UDATA (&baci_poll_svc, UNIT_DIS, POLL_WAIT) } }; /* Telnet poll unit */\r
406\r
407REG baci_reg[] = {\r
408 { ORDATA (IBUF, baci_ibuf, 16) },\r
409 { ORDATA (OBUF, baci_obuf, 16) },\r
410 { ORDATA (STATUS, baci_status, 16) },\r
411\r
412 { ORDATA (EDSIW, baci_edsiw, 16) },\r
413 { ORDATA (DSRW, baci_dsrw, 16) },\r
414 { ORDATA (CFCW, baci_cfcw, 16) },\r
415 { ORDATA (ICW, baci_icw, 16) },\r
416 { ORDATA (ISRW, baci_isrw, 16) },\r
417\r
418 { DRDATA (FIFOPUT, baci_fput, 8) },\r
419 { DRDATA (FIFOGET, baci_fget, 8) },\r
420 { DRDATA (FIFOCNTR, baci_fcount, 8) },\r
421 { DRDATA (BRKCNTR, baci_bcount, 16) },\r
422\r
423 { BRDATA (FIFO, baci_fifo, 8, 8, FIFO_SIZE) },\r
424 { BRDATA (SPCHAR, baci_spchar, 8, 1, 256) },\r
425\r
426 { ORDATA (UARTTHR, baci_uart_thr, 16) },\r
427 { ORDATA (UARTTR, baci_uart_tr, 16), REG_NZ },\r
428 { ORDATA (UARTRHR, baci_uart_rhr, 16) },\r
429 { ORDATA (UARTRR, baci_uart_rr, 16), REG_NZ },\r
430 { DRDATA (UARTCLK, baci_uart_clk, 16) },\r
431\r
432 { DRDATA (CTIME, baci_term.wait, 19), REG_RO },\r
433\r
434 { FLDATA (ENQFLAG, baci_enq_seen, 0), REG_HRO },\r
435 { DRDATA (ENQCNTR, baci_enq_cntr, 16), REG_HRO },\r
436\r
437 { FLDATA (LKO, baci_dib.cmd, 0) },\r
438 { FLDATA (CTL, baci_dib.ctl, 0) },\r
439 { FLDATA (FLG, baci_dib.flg, 0) },\r
440 { FLDATA (FBF, baci_dib.fbf, 0) },\r
441 { FLDATA (SRQ, baci_dib.srq, 0) },\r
442 { ORDATA (DEVNO, baci_dib.devno, 6), REG_HRO },\r
443 { NULL }\r
444 };\r
445\r
446MTAB baci_mod[] = {\r
447 { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL, NULL, NULL },\r
448 { UNIT_DIAG, 0, "terminal mode", "TERMINAL", NULL, NULL, NULL },\r
449\r
450 { UNIT_FASTTIME, UNIT_FASTTIME, "fast timing", "FASTTIME", NULL, NULL, NULL },\r
451 { UNIT_FASTTIME, 0, "realistic timing", "REALTIME", NULL, NULL, NULL },\r
452\r
453 { UNIT_CAPSLOCK, UNIT_CAPSLOCK, "CAPS LOCK down", "CAPSLOCK", NULL, NULL, NULL },\r
454 { UNIT_CAPSLOCK, 0, "CAPS LOCK up", "NOCAPSLOCK", NULL, NULL, NULL },\r
455\r
456 { MTAB_XTD | MTAB_VDV | MTAB_NC, 0, "LOG", "LOG", &tmxr_set_log, &tmxr_show_log, &baci_desc },\r
457 { MTAB_XTD | MTAB_VDV | MTAB_NC, 0, NULL, "NOLOG", &tmxr_set_nolog, NULL, &baci_desc },\r
458\r
459 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTION", NULL, NULL, &baci_show, NULL },\r
460 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &baci_show, NULL },\r
461 { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &baci_desc },\r
462\r
463 { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &baci_dev },\r
464 { 0 }\r
465 };\r
466\r
467DEBTAB baci_deb[] = {\r
468 { "CMDS", DEB_CMDS },\r
469 { "CPU", DEB_CPU },\r
470 { "BUF", DEB_BUF },\r
471 { "XFER", DEB_XFER },\r
472 { NULL, 0 }\r
473 };\r
474\r
475DEVICE baci_dev = {\r
476 "BACI", /* device name */\r
477 baci_unit, /* unit array */\r
478 baci_reg, /* register array */\r
479 baci_mod, /* modifier array */\r
480 2, /* number of units */\r
481 10, /* address radix */\r
482 31, /* address width */\r
483 1, /* address increment */\r
484 8, /* data radix */\r
485 8, /* data width */\r
486 &tmxr_ex, /* examine routine */\r
487 &tmxr_dep, /* deposit routine */\r
488 &baci_reset, /* reset routine */\r
489 NULL, /* boot routine */\r
490 &baci_attach, /* attach routine */\r
491 &baci_detach, /* detach routine */\r
492 &baci_dib, /* device information block */\r
493 DEV_NET | DEV_DEBUG | DEV_DISABLE, /* device flags */\r
494 0, /* debug control flags */\r
495 baci_deb, /* debug flag name table */\r
496 NULL, /* memory size change routine */\r
497 NULL }; /* logical device name */\r
498\r
499\r
500\r
501/* I/O instruction processor.\r
502\r
503 The BACI processes seven types of output words and supplies two types of\r
504 input words. Output word type is identified by an ID code in bits 14-12.\r
505 Input word type is determined by the state of the control flip-flop.\r
506\r
507 The card has the usual control, flag buffer, flag, and SRQ flip-flops.\r
508 However, they have the following unusual characteristics:\r
509\r
510 - STC is not required to transfer a character.\r
511 - Flag is not set after character transfer completes.\r
512 - FLAG and SRQ are decoupled.\r
513\r
514 An interrupt lockout flip-flop is used to prevent the generation of multiple\r
515 interrupts until the cause of the first interrupt is identified and cleared.\r
516 CMD is used to model the lockout flip-flop.\r
517*/\r
518\r
519int32 baci_io (int32 inst, int32 IR, int32 dat)\r
520{\r
521uint8 ch;\r
522uint32 mask;\r
523uint32 dev = IR & I_DEVMASK;\r
524\r
525switch (inst) { /* dispatch by instruction */\r
526\r
527 case ioFLG: /* set or clear flag */\r
528 if ((IR & I_HC) == 0) { /* STF? */\r
529 setFSR (dev); /* set flag, flag buffer, and SRQ */\r
530 setCMD (dev); /* set lockout */\r
531\r
532 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
533 fputs (">>BACI cmds: [STF] Flag, SRQ, and lockout set\n", sim_deb);\r
534 }\r
535 break; /* CLF handled by H/C below */\r
536\r
537\r
538 case ioSFC: /* skip if flag clear */\r
539 if (FLG (dev) == 0) /* flag clear? */\r
540 PC = (PC + 1) & VAMASK; /* skip next instruction */\r
541 break;\r
542\r
543\r
544 case ioSFS: /* skip if flag set */\r
545 if (FLG (dev) != 0) /* flag set? */\r
546 PC = (PC + 1) & VAMASK; /* skip next instruction */\r
547 break;\r
548\r
549\r
550 case ioCRS: /* control reset */\r
551 master_reset (dev); /* issue master reset */\r
552\r
553 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
554 fputs (">>BACI cmds: [CRS] Master reset\n", sim_deb);\r
555 break;\r
556\r
557\r
558 case ioOTX: /* output word */\r
559 if (DEBUG_PRI (baci_dev, DEB_CPU))\r
560 fprintf (sim_deb, ">>BACI cpu: [OTx] Command = %06o\n", dat);\r
561\r
562 baci_obuf = dat;\r
563\r
564 if (baci_obuf & OUT_MR) { /* master reset? */\r
565 master_reset (dev); /* do before processing */\r
566\r
567 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
568 fputs (">>BACI cmds: [OTx] Master reset\n", sim_deb);\r
569 }\r
570\r
571 switch (GET_ID (baci_obuf)) { /* isolate ID code */\r
572\r
573 case 0: /* transmit data */\r
574 if (IO_MODE == XMIT) { /* transmitting? */\r
575 ch = baci_obuf & OUT_DATA; /* mask to character */\r
576 fifo_put (ch); /* queue character */\r
577\r
578 if (baci_term.flags & UNIT_ATT) { /* attached to network? */\r
579 if (DEBUG_PRI (baci_dev, DEB_CMDS) && /* debugging? */\r
580 (sim_is_active (&baci_term) == 0)) /* service stopped? */\r
581 fprintf (sim_deb, ">>BACI cmds: [OTx] Terminal service scheduled, "\r
582 "time = %d\n", baci_term.wait);\r
583\r
584 if (baci_fcount == 1) /* first char to xmit? */\r
585 sim_activate_abs (&baci_term, /* start service with full char time */\r
586 baci_term.wait);\r
587 else\r
588 sim_activate (&baci_term, /* start service if not running */\r
589 baci_term.wait);\r
590 }\r
591 }\r
592 break;\r
593\r
594 case 1: /* enable device status interrupt */\r
595 baci_edsiw = baci_obuf; /* load new enable word */\r
596 update_status (); /* may have enabled an interrupt */\r
597 break;\r
598\r
599 case 2: /* device status reference */\r
600 if ((baci_term.flags & UNIT_DIAG) && /* diagnostic mode? */\r
601 (baci_dsrw & OUT_DIAG) && /* and last DIAG was high? */\r
602 !(baci_obuf & OUT_DIAG) && /* and new DIAG is low? */\r
603 !(baci_icw & OUT_BAUDRATE)) /* and clock is external? */\r
604 clock_uart (); /* pulse UART clock */\r
605\r
606 baci_dsrw = baci_obuf; /* load new reference word */\r
607 update_status (); /* clocking UART may interrupt */\r
608 break;\r
609\r
610 case 3: /* character frame control */\r
611 baci_cfcw = baci_obuf; /* load new frame word */\r
612 break;\r
613\r
614 case 4: /* interface control */\r
615 if ((baci_icw ^ baci_obuf) & OUT_BAUDRATE) { /* baud rate change? */\r
616 baci_term.wait = service_time (baci_obuf); /* set service time to match rate */\r
617\r
618 if (baci_term.flags & UNIT_DIAG) /* diagnostic mode? */\r
619 if (baci_obuf & OUT_BAUDRATE) { /* internal baud rate requested? */\r
620 sim_activate (&baci_term, /* activate I/O service */\r
621 baci_term.wait);\r
622\r
623 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
624 fprintf (sim_deb, ">>BACI cmds: [OTx] Terminal service scheduled, "\r
625 "time = %d\n", baci_term.wait);\r
626 }\r
627\r
628 else { /* external rate */\r
629 sim_cancel (&baci_term); /* stop I/O service */\r
630\r
631 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
632 fputs (">>BACI cmds: [OTx] Terminal service stopped\n", sim_deb);\r
633 }\r
634 }\r
635\r
636 baci_icw = baci_obuf; /* load new reference word */\r
637 update_status (); /* loopback may change status */\r
638 break;\r
639\r
640 case 5: /* interrupt status reset */\r
641 baci_isrw = baci_obuf; /* load new reset word */\r
642\r
643 mask = (baci_isrw & OUT_IRQCLR) << /* form reset mask */\r
644 IN_V_IRQCLR; /* for common irqs */\r
645\r
646 if (baci_isrw & OUT_CSC) /* add special char mask bit */\r
647 mask = mask | IN_SPCHAR; /* if requested */\r
648\r
649 baci_status = baci_status & ~mask; /* clear specified status bits */\r
650 break;\r
651\r
652 case 6: /* special character */\r
653 baci_spchar [baci_obuf & OUT_SPCHAR] = /* set special character entry */\r
654 ((baci_obuf & OUT_SPFLAG) != 0);\r
655 break;\r
656 }\r
657\r
658 break;\r
659\r
660\r
661 case ioLIX: /* load word */\r
662 dat = 0;\r
663\r
664 case ioMIX: /* merge word */\r
665 if (CTL (dev)) { /* control set? */\r
666 baci_ibuf = TO_CHARCNT (baci_fcount); /* get FIFO count */\r
667\r
668 if (IO_MODE == RECV) /* receiving? */\r
669 baci_ibuf = baci_ibuf | fifo_get (); /* add char and validity flag */\r
670\r
671 dat = dat | baci_ibuf; /* return received data */\r
672\r
673 if (DEBUG_PRI (baci_dev, DEB_CPU))\r
674 fprintf (sim_deb, ">>BACI cpu: [LIx] Received data = %06o\n", dat);\r
675 }\r
676\r
677 else { /* control clear? */\r
678 dat = dat | baci_status; /* return status */\r
679\r
680 if (DEBUG_PRI (baci_dev, DEB_CPU))\r
681 fprintf (sim_deb, ">>BACI cpu: [LIx] Status = %06o\n", dat);\r
682 }\r
683 break;\r
684\r
685\r
686 case ioCTL: /* control set/clear */\r
687 if (IR & I_CTL) { /* CLC */\r
688 clrCTL (dev); /* clear control */\r
689\r
690 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
691 fputs (">>BACI cmds: [CLC] Control cleared\n", sim_deb);\r
692 }\r
693\r
694 else { /* STC */\r
695 setCTL (dev); /* set control */\r
696 clrCMD (dev); /* clear lockout */\r
697\r
698 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
699 fputs (">>BACI cmds: [STC] Control set and lockout cleared\n", sim_deb);\r
700\r
701 update_status (); /* clearing lockout might interrupt */\r
702 }\r
703 break;\r
704\r
705\r
706 default: /* all others */\r
707 break; /* do nothing */\r
708 }\r
709\r
710\r
711if (IR & I_HC) { /* H/C option */\r
712 clrFSR (dev); /* clear flag and SRQ */\r
713\r
714 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
715 fprintf (sim_deb, ">>BACI cmds: [%s] Flag and SRQ cleared\n",\r
716 (inst == ioFLG ? "CLF" : "x,C"));\r
717\r
718 update_status (); /* FLG might set when SRQ clears */\r
719 }\r
720\r
721return dat;\r
722}\r
723\r
724\r
725/* BACI terminal service.\r
726\r
727 The terminal service routine is used to transmit and receive characters.\r
728\r
729 In terminal mode, it is started when a character is ready for output or when\r
730 the Telnet poll routine determines that there are characters ready for input\r
731 and stopped when there are no more characters to output or input. When the\r
732 terminal is quiescent, this routine does not run.\r
733\r
734 In diagnostic mode, it is started whenever an internal baud rate is set and\r
735 stopped when the external clock is requested. In this mode, the routine will\r
736 be called without an attached socket, so character I/O will be skipped.\r
737\r
738 Because there is only one FIFO, the card is half-duplex and must be\r
739 configured for transmit or receive mode. The UART, though, is double-\r
740 buffered, so it may transmit and receive simultaneously. We implement both\r
741 the UART shift and holding registers for each mode.\r
742\r
743 If a character is received by the UART while the card is in transmit mode, it\r
744 will remain in the receiver holding register (RHR). When the mode is\r
745 reversed, the RHR contents will be unloaded into the FIFO. Conversely,\r
746 transmit mode enables the output of the FIFO to be unloaded into the\r
747 transmitter holding register (THR). Characters received or transmitted pass\r
748 through the receiver register (RR) or transmitter register (TR),\r
749 respectively. They are not strictly necessary in terminal (Telnet)\r
750 transactions but are critical to diagnostic operations.\r
751\r
752 The UART signals an overrun if a complete character is received while the RHR\r
753 still contains the previous character. The BACI does not use this signal,\r
754 though; an overrun is only indicated if the FIFO is full, and another\r
755 character is received.\r
756\r
757 In "fast timing" mode, we defer the recognition of a received character until\r
758 the card is put into receive mode for the second or third consecutive ENQ/ACK\r
759 handshake. This improves RTE break-mode recognition. "Realistic timing"\r
760 mode behaves as the hardware does: a character present in the RHR is unloaded\r
761 into the FIFO as soon as receive mode is set.\r
762\r
763 Fast timing mode also enables internal ENQ/ACK handshaking. We allow one\r
764 character time for the RTE driver to turn the card around, as otherwise the\r
765 ACK may not be seen by the driver. Also, the local ACK is supplied after any\r
766 received characters, as the driver detects operator attention only when the\r
767 first character after an ENQ is not an ACK.\r
768\r
769 Finally, fast timing enables buffer combining. For output, all characters\r
770 present in the FIFO are unloaded into the Telnet buffer before initiating a\r
771 packet send. For input, all characters present in the Telnet buffer are\r
772 loaded into the FIFO. This reduces network traffic and decreases simulator\r
773 overhead (there is only one service routine entry per block, rather than one\r
774 per character).\r
775\r
776 In fast output mode, it is imperative that not less than 1500 instructions\r
777 elapse between the first character load to the FIFO and the initiation of\r
778 transmission. The RTE driver must have enough time to output the maximum\r
779 number of contiguous characters (33) and reset the interrupt status flags\r
780 before the service routine is entered. Because all of the characters are\r
781 transmitted as a block, the FIFO empty flag will be set by the service\r
782 routine. If the driver has not yet exited at that time, the buffer-empty\r
783 interrupt will be cleared when the interrupt status reset is done. The\r
784 symptom will be a 3.8-second pause in output until the driver times out.\r
785\r
786 To avoid this, the OTx output character handler does an absolute schedule for\r
787 the first character to ensure that a full character time is used.\r
788*/\r
789\r
790t_stat baci_term_svc (UNIT *uptr)\r
791{\r
792uint32 data_bits, data_mask;\r
793const t_bool fast_timing = (baci_term.flags & UNIT_FASTTIME) != 0;\r
794const t_bool is_attached = (baci_term.flags & UNIT_ATT) != 0;\r
795t_stat status = SCPE_OK;\r
796t_bool xmit_loop = TRUE;\r
797t_bool recv_loop = TRUE;\r
798\r
799\r
800/* Transmission */\r
801\r
802while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UART? */\r
803 data_bits = 5 + (baci_cfcw & OUT_CHARSIZE); /* calculate number of data bits */\r
804 data_mask = (1 << data_bits) - 1; /* generate mask for data bits */\r
805 baci_uart_tr = baci_uart_thr & data_mask; /* mask data into transmitter register */\r
806\r
807 if ((baci_uart_tr == ENQ) && fast_timing) { /* char is ENQ and fast timing? */\r
808 baci_enq_seen = TRUE; /* set flag instead of transmitting */\r
809 baci_enq_cntr = baci_enq_cntr + 1; /* bump ENQ counter */\r
810 recv_loop = FALSE; /* skip recv to allow time before ACK */\r
811\r
812 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
813 fprintf (sim_deb, ">>BACI xfer: Character ENQ absorbed internally, "\r
814 "ENQ count = %d\n", baci_enq_cntr);\r
815 }\r
816\r
817 else { /* character is not an ENQ */\r
818 baci_enq_cntr = 0; /* reset ENQ counter */\r
819\r
820 if (is_attached) { /* attached to network? */\r
821 status = tmxr_putc_ln (&baci_ldsc, /* transmit the character */\r
822 baci_uart_tr);\r
823\r
824 if ((status == SCPE_OK) && /* transmitted OK? */\r
825 DEBUG_PRI (baci_dev, DEB_XFER))\r
826 fprintf (sim_deb, ">>BACI xfer: Character %s "\r
827 "transmitted from UART\n", fmt_char (baci_uart_tr));\r
828 }\r
829 }\r
830\r
831 if (status == SCPE_OK) { /* transmitted OK? */\r
832 baci_uart_tr = CLEAR_R; /* clear transmitter register */\r
833\r
834 if (IO_MODE == XMIT) { /* transmit mode? */\r
835 baci_fcount = baci_fcount - 1; /* decrement occupancy counter */\r
836 baci_uart_thr = fifo_get (); /* get next char into UART */\r
837 update_status (); /* update FIFO status */\r
838 }\r
839\r
840 else /* receive mode */\r
841 baci_uart_thr = CLEAR_HR; /* clear holding register */\r
842\r
843 xmit_loop = fast_timing && !baci_enq_seen; /* loop if fast mode and char not ENQ */\r
844 }\r
845\r
846 else\r
847 xmit_loop = FALSE;\r
848 }\r
849\r
850\r
851/* Deferred reception */\r
852\r
853if (recv_loop && /* ok to process? */\r
854 baci_uart_rhr && (IO_MODE == RECV) && /* and deferred char in RHR in recv mode? */\r
855 (!baci_enq_seen || (baci_enq_cntr >= 2))) { /* and either no ENQ or at least 2nd ENQ? */\r
856\r
857 baci_uart_rhr = baci_uart_rhr & ~IN_VALID; /* clear valid bit */\r
858\r
859 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
860 fprintf (sim_deb, ">>BACI xfer: Deferred character %s processed\n",\r
861 fmt_char ((uint8) baci_uart_rhr));\r
862\r
863 fifo_put ((uint8) baci_uart_rhr); /* move deferred character to FIFO */\r
864 baci_uart_rhr = CLEAR_HR; /* clear RHR */\r
865 update_status (); /* update FIFO status */\r
866 }\r
867\r
868\r
869/* Reception */\r
870\r
871while (recv_loop && /* OK to process? */\r
872 (baci_uart_rr = tmxr_getc_ln (&baci_ldsc))) { /* and new character available? */\r
873\r
874 if (baci_uart_rr & SCPE_BREAK) /* break detected? */\r
875 baci_status = baci_status | IN_BREAK; /* set break status */\r
876\r
877 data_bits = 5 + (baci_cfcw & OUT_CHARSIZE); /* calculate number of data bits */\r
878 data_mask = (1 << data_bits) - 1; /* generate mask for data bits */\r
879 baci_uart_rhr = baci_uart_rr & data_mask; /* mask data into holding register */\r
880 baci_uart_rr = CLEAR_R; /* clear receiver register */\r
881\r
882 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
883 fprintf (sim_deb, ">>BACI xfer: Character %s received by UART\n",\r
884 fmt_char ((uint8) baci_uart_rhr));\r
885\r
886 if (baci_term.flags & UNIT_CAPSLOCK) /* caps lock mode? */\r
887 baci_uart_rhr = toupper (baci_uart_rhr); /* convert to upper case if lower */\r
888\r
889 if (baci_cfcw & OUT_ECHO) /* echo wanted? */\r
890 tmxr_putc_ln (&baci_ldsc, baci_uart_rhr); /* send it back */\r
891\r
892 if ((IO_MODE == RECV) && !baci_enq_seen) { /* receive mode and not ENQ/ACK? */\r
893 fifo_put ((uint8) baci_uart_rhr); /* put data in FIFO */\r
894 baci_uart_rhr = CLEAR_HR; /* clear RHR */\r
895 update_status (); /* update FIFO status (may set flag) */\r
896\r
897 recv_loop = fast_timing && !FLG (baci_dib.devno); /* loop if fast mode and no IRQ */\r
898 }\r
899\r
900 else { /* xmit or ENQ/ACK, leave char in RHR */\r
901 baci_uart_rhr = baci_uart_rhr | IN_VALID; /* set character valid bit */\r
902 recv_loop = FALSE; /* terminate loop */\r
903 }\r
904 }\r
905\r
906\r
907/* Housekeeping */\r
908\r
909if (recv_loop && baci_enq_seen) { /* OK to process and ENQ seen? */\r
910 baci_enq_seen = FALSE; /* reset flag */\r
911\r
912 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
913 fputs (">>BACI xfer: Character ACK generated internally\n", sim_deb);\r
914\r
915 fifo_put (ACK); /* fake ACK from terminal */\r
916 update_status (); /* update FIFO status */\r
917 }\r
918\r
919if (is_attached) /* attached to network? */\r
920 tmxr_poll_tx (&baci_desc); /* output any accumulated chars */\r
921\r
922if ((baci_uart_thr & IN_VALID) || baci_enq_seen || /* more to transmit? */\r
923 tmxr_rqln (&baci_ldsc)) /* or more to receive? */\r
924 sim_activate (uptr, uptr->wait); /* reschedule service */\r
925else\r
926 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
927 fputs (">>BACI cmds: Terminal service stopped\n", sim_deb);\r
928\r
929return status;\r
930}\r
931\r
932\r
933/* BACI Telnet poll service.\r
934\r
935 This service routine is used to poll for Telnet connections and incoming\r
936 characters. If characters are available, the terminal I/O service routine is\r
937 scheduled. It starts when the socket is attached and stops when the socket\r
938 is detached.\r
939*/\r
940\r
941t_stat baci_poll_svc (UNIT *uptr)\r
942{\r
943if (baci_term.flags & UNIT_ATT) { /* attached to network? */\r
944 if (tmxr_poll_conn (&baci_desc) >= 0) /* new connection established? */\r
945 baci_ldsc.rcve = 1; /* enable line to receive */\r
946\r
947 tmxr_poll_rx (&baci_desc); /* poll for input */\r
948\r
949 if (tmxr_rqln (&baci_ldsc)) /* chars available? */\r
950 sim_activate (&baci_term, baci_term.wait); /* activate I/O service */\r
951 }\r
952\r
953uptr->wait = sync_poll (SERVICE); /* synchronize poll */\r
954sim_activate (uptr, uptr->wait); /* continue polling */\r
955\r
956return SCPE_OK;\r
957}\r
958\r
959\r
960/* Simulator reset routine */\r
961\r
962t_stat baci_reset (DEVICE *dptr)\r
963{\r
964master_reset (0); /* do master reset */\r
965\r
966baci_dib.ctl = 0; /* clear control */\r
967baci_dib.flg = 1; /* set flag */\r
968baci_dib.fbf = 1; /* set flag buffer */\r
969baci_dib.srq = 1; /* set SRQ */\r
970baci_dib.cmd = 1; /* set lockout */\r
971\r
972baci_ibuf = 0; /* clear input buffer */\r
973baci_obuf = 0; /* clear output buffer */\r
974\r
975baci_enq_seen = FALSE; /* reset ENQ seen flag */\r
976baci_enq_cntr = 0; /* clear ENQ counter */\r
977\r
978baci_term.wait = service_time (baci_icw); /* set terminal I/O time */\r
979\r
980if (baci_term.flags & UNIT_ATT) { /* device attached? */\r
981 baci_poll.wait = sync_poll (INITIAL); /* synchronize poll */\r
982 sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll */\r
983 }\r
984else\r
985 sim_cancel (&baci_poll); /* else stop Telnet poll */\r
986\r
987return SCPE_OK;\r
988}\r
989\r
990\r
991/* Attach controller */\r
992\r
993t_stat baci_attach (UNIT *uptr, char *cptr)\r
994{\r
995t_stat status = SCPE_OK;\r
996\r
997status = tmxr_attach (&baci_desc, uptr, cptr); /* attach to socket */\r
998\r
999if (status == SCPE_OK) {\r
1000 baci_poll.wait = sync_poll (INITIAL); /* synchronize poll */\r
1001 sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll */\r
1002 }\r
1003return status;\r
1004}\r
1005\r
1006/* Detach controller */\r
1007\r
1008t_stat baci_detach (UNIT *uptr)\r
1009{\r
1010t_stat status;\r
1011\r
1012status = tmxr_detach (&baci_desc, uptr); /* detach socket */\r
1013baci_ldsc.rcve = 0; /* disable line reception */\r
1014sim_cancel (&baci_poll); /* stop Telnet poll */\r
1015return status;\r
1016}\r
1017\r
1018/* Show connection status and statistics */\r
1019\r
1020t_stat baci_show (FILE *st, UNIT *uptr, int32 val, void *desc)\r
1021{\r
1022if (baci_ldsc.conn)\r
1023 if (val)\r
1024 tmxr_fconns (st, &baci_ldsc, -1);\r
1025 else\r
1026 tmxr_fstats (st, &baci_ldsc, -1);\r
1027else\r
1028 fprintf (st, "terminal disconnected\n");\r
1029\r
1030return SCPE_OK;\r
1031}\r
1032\r
1033\r
1034/* Local routines */\r
1035\r
1036\r
1037/* Master reset.\r
1038\r
1039 This is the programmed card master reset, not the simulator reset routine.\r
1040 It is called from the simulator reset routine with "selcode" = 0; the latter\r
1041 routine will take care of setting the card flip-flops appropriately.\r
1042\r
1043 Master reset normally clears the UART registers. However, if we are in "fast\r
1044 timing" mode, the receiver holding register may hold a deferred character.\r
1045 In this case, we do not clear the RHR, unless we are called from the\r
1046 simulator reset routine.\r
1047\r
1048 The HP BACI manual states that master reset "Clears Service Request (SRQ)."\r
1049 An examination of the schematic, though, shows that it sets SRQ instead.\r
1050*/\r
1051\r
1052static void master_reset (uint32 selcode)\r
1053{\r
1054baci_fput = baci_fget = 0; /* clear FIFO indexes */\r
1055baci_fcount = 0; /* clear FIFO counter */\r
1056memset (baci_fifo, 0, sizeof (baci_fifo)); /* clear FIFO data */\r
1057\r
1058baci_uart_thr = CLEAR_HR; /* clear transmitter holding register */\r
1059\r
1060if (!(baci_term.flags & UNIT_FASTTIME) || !selcode) /* real time mode or power-on init? */\r
1061 baci_uart_rhr = CLEAR_HR; /* clear receiver holding register */\r
1062\r
1063baci_uart_tr = CLEAR_R; /* clear transmitter register */\r
1064baci_uart_rr = CLEAR_R; /* clear receiver register */\r
1065\r
1066baci_uart_clk = 0; /* clear UART clock */\r
1067baci_bcount = 0; /* clear break counter */\r
1068\r
1069if (selcode) {\r
1070 clrCTL (selcode); /* clear control */\r
1071 setFLG (selcode); /* set flag and flag buffer */\r
1072 setSRQ (selcode); /* set SRQ */\r
1073 setCMD (selcode); /* set lockout flip-flop */\r
1074 }\r
1075\r
1076baci_edsiw = 0; /* clear interrupt enables */\r
1077baci_dsrw = 0; /* clear status reference */\r
1078baci_cfcw = baci_cfcw & ~OUT_ECHO; /* clear echo flag */\r
1079baci_icw = baci_icw & OUT_BAUDRATE; /* clear interface control */\r
1080\r
1081if (baci_term.flags & UNIT_DIAG) /* diagnostic mode? */\r
1082 baci_status = baci_status & ~IN_MODEM | IN_SPARE; /* clear loopback status, set BA */\r
1083\r
1084return;\r
1085}\r
1086\r
1087\r
1088/* Update status.\r
1089\r
1090 In diagnostic mode, several of the modem output lines are looped back to the\r
1091 input lines. Also, CD is tied to BB (received data), which is presented on\r
1092 the TEST status bit via an inversion. Echo mode couples BB to BA\r
1093 (transmitted data), which is presented on the SPARE status bit.\r
1094\r
1095 If a modem line interrupt condition is present and enabled, the DEVINT status\r
1096 bit is set. Other potential "standard" interrupt sources are the special\r
1097 character, break detected, and overrun/parity error bits. If DCPC transfers\r
1098 are not selected, then the FIFO interrupts (buffer empty, half-full, and\r
1099 full) and the "data ready" condition (i.e., receive and character modes\r
1100 enabled and FIFO not empty) also produces an interrupt request.\r
1101\r
1102 An interrupt request will set the card flag unless either the lockout or SRQ\r
1103 flip-flops are set. SRQ will set if DCPC mode is enabled and there is room\r
1104 (transmit mode) or data (receive mode) in the FIFO.\r
1105*/\r
1106\r
1107static void update_status (void)\r
1108{\r
1109if (baci_term.flags & UNIT_DIAG) { /* diagnostic mode? */\r
1110 baci_status = baci_status & ~IN_LOOPBACK; /* prepare loopback flags */\r
1111\r
1112 if (baci_icw & OUT_SXX) /* SCA to SCF and CF */\r
1113 baci_status = baci_status | IN_SXX | IN_CF;\r
1114 if ((baci_icw & OUT_CA) && (baci_fcount < 128)) /* CA to CC and CE */\r
1115 baci_status = baci_status | IN_CC | IN_CE;\r
1116 if (baci_icw & OUT_CD) /* CD to CB */\r
1117 baci_status = baci_status | IN_CB;\r
1118 else {\r
1119 baci_status = baci_status | IN_TEST; /* BB is inversion of CD */\r
1120 if (baci_cfcw & OUT_ECHO)\r
1121 baci_status = baci_status | IN_SPARE; /* BB couples to BA with echo */\r
1122 }\r
1123\r
1124 if (!(baci_cfcw & OUT_ECHO) && (baci_uart_tr & 1)) /* no echo and UART TR set? */\r
1125 baci_status = baci_status | IN_SPARE; /* BA to SPARE */\r
1126 }\r
1127\r
1128if (baci_edsiw & (baci_status ^ baci_dsrw) & IN_MODEM) /* device interrupt? */\r
1129 baci_status = baci_status | IN_DEVINT; /* set flag */\r
1130\r
1131if ((baci_status & IN_STDIRQ) || /* standard interrupt? */\r
1132 !(baci_icw & OUT_DCPC) && /* or under program control */\r
1133 (baci_status & IN_FIFOIRQ) || /* and FIFO interrupt? */\r
1134 (IO_MODE == RECV) && /* or receiving */\r
1135 (baci_edsiw & OUT_ENCM) && /* and char mode */\r
1136 (baci_fget != baci_fput)) { /* and FIFO not empty? */\r
1137\r
1138 if (CMD (baci_dib.devno)) { /* interrupt lockout? */\r
1139 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
1140 fputs (">>BACI cmds: Lockout prevents flag set", sim_deb);\r
1141 }\r
1142\r
1143 else if (SRQ (baci_dib.devno)) { /* SRQ? */\r
1144 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
1145 fputs (">>BACI cmds: SRQ prevents flag set", sim_deb);\r
1146 }\r
1147\r
1148 else {\r
1149 setFLG (baci_dib.devno); /* set device flag and flag buffer */\r
1150 setCMD (baci_dib.devno); /* set lockout */\r
1151\r
1152 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
1153 fputs (">>BACI cmds: Flag and lockout set", sim_deb);\r
1154 }\r
1155\r
1156 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
1157 fprintf (sim_deb, ", status = %06o\n", baci_status);\r
1158 }\r
1159\r
1160if ((baci_icw & OUT_DCPC) && /* DCPC enabled? */\r
1161 ((IO_MODE == XMIT) && (baci_fcount < 128) || /* and xmit and room in FIFO */\r
1162 (IO_MODE == RECV) && (baci_fcount > 0))) { /* or recv and data in FIFO? */\r
1163\r
1164 if (CMD (baci_dib.devno)) { /* interrupt lockout? */\r
1165 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
1166 fputs (">>BACI cmds: Lockout prevents SRQ set", sim_deb);\r
1167 }\r
1168\r
1169 else {\r
1170 setSRQ (baci_dib.devno); /* set SRQ */\r
1171\r
1172 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
1173 fputs (">>BACI cmds: SRQ set", sim_deb);\r
1174 }\r
1175\r
1176 if (DEBUG_PRI (baci_dev, DEB_CMDS))\r
1177 fprintf (sim_deb, ", status = %06o\n", baci_status);\r
1178 }\r
1179\r
1180return;\r
1181}\r
1182\r
1183\r
1184/* Calculate service time from baud rate.\r
1185\r
1186 Service times are based on 1580 instructions per second, which is the 1000\r
1187 E-Series execution speed. The "external clock" rate uses the 9600 baud rate,\r
1188 as most real terminals were set to their maximum rate.\r
1189\r
1190 Note that the RTE driver has a race condition that will trip if the service\r
1191 time is less than 1500 instructions. Therefore, these times cannot be\r
1192 shortened arbitrarily.\r
1193*/\r
1194\r
1195static int32 service_time (uint32 control_word)\r
1196{\r
1197static const int32 ticks [] = { 1646, 316000, 210667, 143636, 117472, 105333, 52667, 26333,\r
1198 17556, 13667, 8778, 6583, 4389, 3292, 2194, 1646 };\r
1199\r
1200return ticks [GET_BAUDRATE (control_word)]; /* return service time for indicated rate */\r
1201}\r
1202\r
1203\r
1204/* Format a character into a printable string.\r
1205\r
1206 Control characters are translated to readable strings. Printable characters\r
1207 retain their original form but are enclosed in single quotes. Characters\r
1208 outside of the ASCII range are represented as escaped octal values.\r
1209*/\r
1210\r
1211static const char *fmt_char (uint8 ch)\r
1212{\r
1213static const char *const ctl[] = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",\r
1214 "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",\r
1215 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",\r
1216 "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" };\r
1217static char rep[5];\r
1218\r
1219if (ch <= '\037') /* ASCII control character? */\r
1220 return ctl [ch]; /* return string representation */\r
1221\r
1222else if (ch == '\177') /* ASCII delete? */\r
1223 return "DEL"; /* return string representation */\r
1224\r
1225else if (ch > '\177') { /* beyond printable range? */\r
1226 sprintf (rep, "\\%03o", ch); /* format value */\r
1227 return rep; /* return escaped octal code */\r
1228 }\r
1229\r
1230else { /* printable character */\r
1231 rep[0] = '\''; /* form string */\r
1232 rep[1] = ch; /* containing character */\r
1233 rep[2] = '\'';\r
1234 rep[3] = '\0';\r
1235 return rep; /* return quoted character */\r
1236 }\r
1237}\r
1238\r
1239\r
1240/* FIFO manipulation routines.\r
1241\r
1242 The BACI is a half-duplex device that has a single 128-byte FIFO that is used\r
1243 for both transmitting and receiving. Whether the FIFO is connected to the\r
1244 input or output of the UART is determined by the XMIT bit in word 4. A\r
1245 separate 8-bit FIFO up/down counter is used to track the number of bytes\r
1246 available. FIFO operations are complicated slightly by the UART, which is\r
1247 double-buffered.\r
1248\r
1249 The FIFO is modeled as a circular 128-byte array. Separate get and put\r
1250 indexes track the current data extent. A FIFO character counter is used to\r
1251 derive empty, half-full, and full status indications, and counts greater than\r
1252 128 are possible.\r
1253\r
1254 In the transmit mode, an OTA/B with word type 0 generates SI (shift in) to\r
1255 load the FIFO and increment the FIFO counter. When the UART is ready for a\r
1256 character, THRE (UART transmitter holding register empty) and OR (FIFO output\r
1257 ready) generate THRL (transmitter holding register load) and SO (FIFO shift\r
1258 out) to unload the FIFO into the UART. When transmission of the character\r
1259 over the serial line is complete, TRE (UART transmitter register empty)\r
1260 decrements the FIFO counter.\r
1261\r
1262 In the receive mode, the UART sets DR (data received) when has obtained a\r
1263 character, which generates SI (FIFO shift in) to load the FIFO and increment\r
1264 the FIFO counter. This also clocks PE (UART parity error) and IR (FIFO input\r
1265 ready) into the overrun/parity error flip-flop. An LIA/B with control set\r
1266 and with OR (FIFO output ready) set, indicating valid data is available,\r
1267 generates SO (FIFO shift out) to unload the FIFO and decrement the FIFO\r
1268 counter.\r
1269\r
1270 Presuming an empty FIFO and UART, double-buffering in the transmit mode means\r
1271 that the first byte deposited into the FIFO is removed and loaded into the\r
1272 UART transmitter holding register. Even though the FIFO is actually empty,\r
1273 the FIFO counter remains at 1, because FIFO decrement does not occur until\r
1274 the UART actually transmits the data byte. The intended mode of operation is\r
1275 to wait until the buffer-empty interrupt occurs, which will happen when the\r
1276 final character is transmitted from the UART, before switching the BACI into\r
1277 receive mode. The counter will match the FIFO contents properly, i.e., will\r
1278 be zero, when the UART transmission completes.\r
1279\r
1280 However, during diagnostic operation, FIFO testing will take this "extra"\r
1281 count into consideration. For example, after a master reset, if ten bytes\r
1282 are written to the FIFO in transmit mode, the first byte will pass through to\r
1283 the UART transmitter holding register, and the next nine bytes will fill the\r
1284 FIFO. The first byte read in receive mode will be byte 2, not byte 1; the\r
1285 latter remains in the UART. After the ninth byte is read, OR (FIFO output\r
1286 ready) will drop, resetting the valid data flip-flop and inhibiting any\r
1287 further FIFO counter decrement pulses. The counter will remain at 1 until\r
1288 another master reset is done.\r
1289\r
1290 The same situation occurs in the RTE driver during ENQ/ACK handshakes. The\r
1291 driver sets the card to transmit mode, sends an ENQ, waits for a short time\r
1292 for the character to "bubble through" the FIFO and into the UART transmitter\r
1293 holding register, and then switches the card to receive mode to await the\r
1294 interrupt from the reception of the ACK. This is done to avoid the overhead\r
1295 of the interrupt after the ENQ is transmitted. However, switching the card\r
1296 into receive mode before the ENQ is actually transmitted means that the FIFO\r
1297 counter will not decrement when that occurs, leaving the counter in an "off\r
1298 by one" configuration. To remedy this, the driver does a master reset after\r
1299 the ACK is received.\r
1300\r
1301 Therefore, for proper operation, we must simulate both the UART\r
1302 double-buffering and the decoupling of the FIFO and FIFO character counter.\r
1303*/\r
1304\r
1305\r
1306/* Get a character from the FIFO.\r
1307\r
1308 In receive mode, getting a character from the FIFO decrements the character\r
1309 counter concurrently. In transmit mode, the counter must not be decremented\r
1310 until the character is actually sent; in this latter case, the caller is\r
1311 responsible for decrementing. Attempting to get a character when the FIFO is\r
1312 empty returns the last valid data and does not alter the FIFO indexes.\r
1313\r
1314 Because the FIFO counter may indicate more characters than are actually in\r
1315 the FIFO, the count is not an accurate indicator of FIFO fill status. We\r
1316 account for this by examining the get and put indexes. If these are equal,\r
1317 then the FIFO is either empty or exactly full. We differentiate by examining\r
1318 the FIFO counter and seeing if it is >= 128, indicating an (over)full\r
1319 condition. If it is < 128, then the FIFO is empty, even if the counter is\r
1320 not 0.\r
1321*/\r
1322\r
1323static uint32 fifo_get (void)\r
1324{\r
1325uint32 data;\r
1326\r
1327data = baci_fifo [baci_fget]; /* get character */\r
1328\r
1329if ((baci_fget != baci_fput) || (baci_fcount >= 128)) { /* FIFO occupied? */\r
1330 if (IO_MODE == RECV) /* receive mode? */\r
1331 baci_fcount = baci_fcount - 1; /* decrement occupancy counter */\r
1332\r
1333 if (DEBUG_PRI (baci_dev, DEB_BUF))\r
1334 fprintf (sim_deb, ">>BACI buf: Character %s get from FIFO [%d], "\r
1335 "character counter = %d\n", fmt_char (data), baci_fget, baci_fcount);\r
1336\r
1337 baci_fget = (baci_fget + 1) % FIFO_SIZE; /* bump index modulo array size */\r
1338\r
1339 if (baci_spchar [data]) /* is it a special character? */\r
1340 data = data | IN_SPFLAG; /* set flag */\r
1341\r
1342 data = data | IN_VALID; /* set valid flag in return */\r
1343 }\r
1344\r
1345else /* FIFO empty */\r
1346 if (DEBUG_PRI (baci_dev, DEB_BUF))\r
1347 fprintf (sim_deb, ">>BACI buf: Attempted get on empty FIFO, "\r
1348 "character count = %d\n", baci_fcount);\r
1349\r
1350if (baci_fcount == 0) /* count now zero? */\r
1351 baci_status = baci_status | IN_BUFEMPTY; /* set buffer empty flag */\r
1352\r
1353update_status (); /* update FIFO status */\r
1354\r
1355return data; /* return character */\r
1356}\r
1357\r
1358\r
1359/* Put a character into the FIFO.\r
1360\r
1361 In transmit mode, available characters are unloaded from the FIFO into the\r
1362 UART transmitter holding register as soon as the THR is empty. That is,\r
1363 given an empty FIFO and THR, a stored character will pass through the FIFO\r
1364 and into the THR immediately. Otherwise, the character will remain in the\r
1365 FIFO. In either case, the FIFO character counter is incremented.\r
1366\r
1367 In receive mode, characters are only unloaded from the FIFO explicitly, so\r
1368 stores always load the FIFO and increment the counter.\r
1369*/\r
1370\r
1371static void fifo_put (uint8 ch)\r
1372{\r
1373uint32 index = 0;\r
1374t_bool pass_thru;\r
1375\r
1376pass_thru = (IO_MODE == XMIT) && /* pass thru if XMIT and THR empty */\r
1377 !(baci_uart_thr & IN_VALID);\r
1378\r
1379if (pass_thru) /* pass char thru to UART */\r
1380 baci_uart_thr = ch | IN_VALID; /* and set valid character flag */\r
1381\r
1382else { /* RECV or THR occupied */\r
1383 index = baci_fput; /* save current index */\r
1384 baci_fifo [baci_fput] = ch; /* put char in FIFO */\r
1385 baci_fput = (baci_fput + 1) % FIFO_SIZE; /* bump index modulo array size */\r
1386 }\r
1387\r
1388baci_fcount = baci_fcount + 1; /* increment occupancy counter */\r
1389\r
1390if (DEBUG_PRI (baci_dev, DEB_BUF))\r
1391 if (pass_thru)\r
1392 fprintf (sim_deb, ">>BACI buf: Character %s put to UART transmitter holding register, "\r
1393 "character counter = 1\n", fmt_char (ch));\r
1394 else\r
1395 fprintf (sim_deb, ">>BACI buf: Character %s put to FIFO [%d], "\r
1396 "character counter = %d\n", fmt_char (ch), index, baci_fcount);\r
1397\r
1398if ((IO_MODE == RECV) && (baci_spchar [ch])) /* receive mode and special character? */\r
1399 baci_status = baci_status | IN_SPCHAR; /* set special char seen flag */\r
1400\r
1401if (baci_fcount == 64) /* FIFO half full? */\r
1402 baci_status = baci_status | IN_BUFHALF;\r
1403\r
1404else if (baci_fcount == 128) /* FIFO completely full? */\r
1405 baci_status = baci_status | IN_BUFFULL;\r
1406\r
1407else if (baci_fcount > 128) /* FIFO overrun? */\r
1408 baci_status = baci_status | IN_OVRUNPE;\r
1409\r
1410update_status (); /* update FIFO status */\r
1411\r
1412return;\r
1413}\r
1414\r
1415\r
1416/* Clock the UART.\r
1417\r
1418 In the diagnostic mode, the DIAG output is connected to the EXT CLK input.\r
1419 If the baud rate of the Interface Control Word is set to "external clock,"\r
1420 then raising and lowering the DIAG output will pulse the UART transmitter and\r
1421 receiver clock lines, initiating transmission or reception of serial data.\r
1422 Sixteen pulses are needed to shift one bit through the UART.\r
1423\r
1424 The diagnostic hood ties CD to BB (received data), so bits presented to CD\r
1425 via the Interface Control Word can be clocked into the UART receiver register\r
1426 (RR). Similarly, the UART transmitter register (TR) shifts data onto BA\r
1427 (transmitted data), and the hood ties BA to SPARE, so transmitted bits are\r
1428 presented to the SPARE bit in the status word.\r
1429\r
1430 "baci_uart_clk" contains the number of clock pulses remaining for the current\r
1431 character transfer. Calling this routine with "baci_uart_clk" = 0 initiates\r
1432 a transfer. The value will be a multiple of 16 and will account for the\r
1433 start bit, the data bits, the optional parity bit, and the stop bits. The\r
1434 transfer terminates when the count reaches zero (or eight, if 1.5 stop bits\r
1435 is selected during transmission).\r
1436\r
1437 Every sixteen pulses when the lower four bits of the clock count are zero,\r
1438 the transmitter or receiver register will be shifted to present or receive a\r
1439 new serial bit. The registers are initialized to all ones for proper\r
1440 handling of the stop bits.\r
1441\r
1442 A break counter is maintained and incremented whenever a space (0) condition\r
1443 is seen on the serial line. After 160 clock times (10 bits) of continuous\r
1444 zero data, the "break seen" status is set.\r
1445\r
1446 This routine is not used in terminal mode.\r
1447*/\r
1448\r
1449static void clock_uart (void)\r
1450{\r
1451uint32 uart_bits, data_bits, data_mask, parity, bit_low, i;\r
1452\r
1453if (baci_uart_clk > 0) { /* transfer in progress? */\r
1454 bit_low = (baci_icw & OUT_CD); /* get current receive bit */\r
1455\r
1456 if ((baci_uart_clk & 017) == 0) /* end of a bit? */\r
1457 if (IO_MODE == XMIT) /* transmit? */\r
1458 baci_uart_tr = baci_uart_tr >> 1; /* shift new bit onto line */\r
1459 else /* receive? */\r
1460 baci_uart_rr = (baci_uart_rr >> 1) & /* shift new bit in */\r
1461 (bit_low ? ~SIGN : -1); /* (inverted sense) */\r
1462\r
1463 if (bit_low) { /* another low bit? */\r
1464 baci_bcount = baci_bcount + 1; /* update break counter */\r
1465\r
1466 if (baci_bcount == 160) { /* break held long enough? */\r
1467 baci_status = baci_status | IN_BREAK; /* set break flag */\r
1468\r
1469 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
1470 fputs (">>BACI xfer: Break detected\n", sim_deb);\r
1471 }\r
1472 }\r
1473\r
1474 else /* high bit? */\r
1475 baci_bcount = 0; /* reset break counter */\r
1476\r
1477 baci_uart_clk = baci_uart_clk - 1; /* decrement clocks remaining */\r
1478\r
1479 if ((IO_MODE == XMIT) && /* transmit mode? */\r
1480 ((baci_uart_clk == 0) || /* and end of character? */\r
1481 (baci_uart_clk == 8) && /* or last stop bit */\r
1482 (baci_cfcw & OUT_STBITS) && /* and extra stop bit requested */\r
1483 ((baci_cfcw & OUT_CHARSIZE) == 0))) { /* and 1.5 stop bits used? */\r
1484\r
1485 baci_uart_clk = 0; /* clear clock count */\r
1486\r
1487 baci_fcount = baci_fcount - 1; /* decrement occupancy counter */\r
1488 baci_uart_thr = fifo_get (); /* get next char into THR */\r
1489 update_status (); /* update FIFO status */\r
1490\r
1491 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
1492 fprintf (sim_deb, ">>BACI xfer: UART transmitter empty, "\r
1493 "holding register = %06o\n", baci_uart_thr);\r
1494 }\r
1495\r
1496 else if ((IO_MODE == RECV) && /* receive mode? */\r
1497 (baci_uart_clk == 0)) { /* and end of character? */\r
1498\r
1499 data_bits = 5 + (baci_cfcw & OUT_CHARSIZE); /* calculate number of data bits */\r
1500 data_mask = (1 << data_bits) - 1; /* generate mask for data bits */\r
1501\r
1502 uart_bits = data_bits + /* calculate UART bits as data bits */\r
1503 ((baci_cfcw & OUT_PARITY) != 0) + /* plus parity bit if used */\r
1504 ((baci_cfcw & OUT_STBITS) != 0); /* plus extra stop bit if used */\r
1505\r
1506 baci_uart_rhr = baci_uart_rr >> (16 - uart_bits); /* position data to right align */\r
1507 baci_uart_rr = CLEAR_R; /* clear receiver register */\r
1508\r
1509 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
1510 fprintf (sim_deb, ">>BACI xfer: UART receiver = %06o (%s)\n",\r
1511 baci_uart_rhr, fmt_char (baci_uart_rhr & data_mask));\r
1512\r
1513 fifo_put (baci_uart_rhr & data_mask); /* put data in FIFO */\r
1514 update_status (); /* update FIFO status */\r
1515\r
1516 if (baci_cfcw & OUT_PARITY) { /* parity present? */\r
1517 data_mask = data_mask << 1 | 1; /* widen mask to encompass parity */\r
1518 uart_bits = baci_uart_rhr & data_mask; /* get data plus parity */\r
1519\r
1520 parity = (baci_cfcw & OUT_PAREVEN) == 0; /* preset for even/odd parity */\r
1521\r
1522 for (i = 0; i < data_bits + 1; i++) { /* calc parity of data + parity bit */\r
1523 parity = parity ^ uart_bits; /* parity calculated in LSB */\r
1524 uart_bits = uart_bits >> 1;\r
1525 }\r
1526\r
1527 if (parity & 1) { /* parity error? */\r
1528 baci_status = baci_status | IN_OVRUNPE; /* report it */\r
1529\r
1530 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
1531 fputs (">>BACI xfer: Parity error detected\n", sim_deb);\r
1532 }\r
1533 }\r
1534 }\r
1535 }\r
1536\r
1537if ((baci_uart_clk == 0) && /* start of transfer? */\r
1538 ((IO_MODE == RECV) || /* and receive mode */\r
1539 (baci_uart_thr & IN_VALID))) { /* or character ready to transmit? */\r
1540\r
1541 data_bits = 5 + (baci_cfcw & OUT_CHARSIZE); /* calculate number of data bits */\r
1542\r
1543 uart_bits = data_bits + /* calculate UART bits as data bits */\r
1544 ((baci_cfcw & OUT_PARITY) != 0) + /* plus parity bit if used */\r
1545 2 + ((baci_cfcw & OUT_STBITS) != 0); /* plus start/stop and extra stop if used */\r
1546\r
1547 baci_uart_clk = 16 * uart_bits; /* calculate clocks pulses expected */\r
1548\r
1549 if (IO_MODE == XMIT) { /* transmit mode? */\r
1550 data_mask = (1 << data_bits) - 1; /* generate mask for data bits */\r
1551 baci_uart_tr = baci_uart_thr & data_mask; /* mask data into holding register */\r
1552\r
1553 if (baci_cfcw & OUT_PARITY) { /* add parity to this transmission? */\r
1554 uart_bits = baci_uart_tr; /* copy data bits */\r
1555 parity = (baci_cfcw & OUT_PAREVEN) == 0; /* preset for even/odd parity */\r
1556\r
1557 for (i = 0; i < data_bits; i++) { /* calculate parity of data */\r
1558 parity = parity ^ uart_bits; /* parity calculated in LSB */\r
1559 uart_bits = uart_bits >> 1;\r
1560 }\r
1561\r
1562 data_mask = data_mask << 1 | 1; /* extend mask for the parity bit */\r
1563 baci_uart_tr = baci_uart_tr | /* include parity in transmission register */\r
1564 (parity & 1) << data_bits; /* (mask to parity bit and position it) */\r
1565 }\r
1566\r
1567 baci_uart_tr = (~data_mask | baci_uart_tr) << 2 | 1; /* form serial data stream */\r
1568\r
1569 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
1570 fprintf (sim_deb, ">>BACI xfer: UART transmitter = %06o (%s), "\r
1571 "clock count = %d\n", baci_uart_tr & DMASK,\r
1572 fmt_char (baci_uart_thr & data_mask), baci_uart_clk);\r
1573 }\r
1574\r
1575 else {\r
1576 baci_uart_rr = CLEAR_R; /* clear receiver register */\r
1577\r
1578 if (DEBUG_PRI (baci_dev, DEB_XFER))\r
1579 fprintf (sim_deb, ">>BACI xfer: UART receiver empty, "\r
1580 "clock count = %d\n", baci_uart_clk);\r
1581 }\r
1582 }\r
1583\r
1584return;\r
1585}\r