ae6b7095eee7ad02c8c96d72f02201a643976106
1 /* id_pas.c: Interdata programmable async line adapter simulator
3 Copyright (c) 2001-2007, Robert M Supnik
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
26 pas Programmable asynchronous line adapter(s)
28 18-Jun-07 RMS Added UNIT_IDLE flag
29 18-Oct-06 RMS Synced PASLA to clock
30 22-Nov-05 RMS Revised for new terminal processing routines
31 29-Jun-05 RMS Added SET PASLn DISCONNECT
32 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS
33 05-Jan-04 RMS Revised for tmxr library changes
34 09-May-03 RMS Added network device flag
36 This module implements up to 32 individual serial interfaces, representing
37 either individual PASLA modules or combinations of the 2-line and 8-line
38 multiplexors, which are functionally very similar. These interfaces are mapped
39 to Telnet based connections as the lines of a terminal multiplexor. The
40 connection polling mechanism and the character input polling for all lines
41 are done through a single polling job.
51 #define UNIT_V_MDM (TTUF_V_UF + 0) /* modem control */
52 #define UNIT_MDM (1 << UNIT_V_MDM)
58 #define STA_OVR 0x80 /* overrun RO */
59 #define STA_PF 0x40 /* parity err RONI */
60 #define STA_NCL2S 0x40 /* not clr to snd XO */
61 #define STA_FR 0x20 /* framing err RO */
62 #define STA_RCR 0x10 /* rv chan rcv NI */
63 #define STA_CROF 0x02 /* carrier off RO */
64 #define STA_RING 0x01 /* ring RO */
65 #define STA_RCV (STA_OVR|STA_PF|STA_FR|STA_RCR|STA_CROF|STA_RING)
66 #define SET_EX (STA_OVR|STA_PF|STA_FR)
67 #define STA_XMT (STA_BSY)
69 /* Command bytes 1,0 */
71 #define CMD_DTR (0x20 << 8) /* DTR */
72 #define CMD_ECHO (0x10 << 8) /* echoplex */
73 #define CMD_RCT (0x08 << 8) /* RCT/DTB NI */
74 #define CMD_XMTB (0x04 << 8) /* xmt break NI */
75 #define CMD_WRT (0x02 << 8) /* write/read */
76 #define CMD_V_CLK 6 /* baud rate */
78 #define CMD_V_DB 4 /* data bits */
80 #define CMD_STOP 0x80 /* stop bit */
81 #define CMD_V_PAR 1 /* parity */
83 #define GET_PAR(x) (((x) >> CMD_V_PAR) & CMD_M_PAR)
89 #define CMD_TYP 0x01 /* command type */
91 extern uint32 int_req
[INTSZ
], int_enb
[INTSZ
];
92 extern int32 lfc_poll
;
94 uint8 pas_sta
[PAS_LINES
]; /* status */
95 uint16 pas_cmd
[PAS_LINES
]; /* command */
96 uint8 pas_rbuf
[PAS_LINES
]; /* rcv buf */
97 uint8 pas_xbuf
[PAS_LINES
]; /* xmt buf */
98 uint8 pas_rarm
[PAS_LINES
]; /* rcvr int armed */
99 uint8 pas_xarm
[PAS_LINES
]; /* xmt int armed */
100 uint8 pas_rchp
[PAS_LINES
]; /* rcvr chr pend */
101 uint8 pas_tplte
[PAS_LINES
* 2 + 1]; /* template */
103 TMLN pas_ldsc
[PAS_LINES
] = { 0 }; /* line descriptors */
104 TMXR pas_desc
= { 8, 0, 0, pas_ldsc
}; /* mux descriptor */
105 #define PAS_ENAB pas_desc.lines
107 uint32
pas (uint32 dev
, uint32 op
, uint32 dat
);
108 void pas_ini (t_bool dtpl
);
109 t_stat
pasi_svc (UNIT
*uptr
);
110 t_stat
paso_svc (UNIT
*uptr
);
111 t_stat
pas_reset (DEVICE
*dptr
);
112 t_stat
pas_attach (UNIT
*uptr
, char *cptr
);
113 t_stat
pas_detach (UNIT
*uptr
);
114 t_stat
pas_summ (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
115 t_stat
pas_show (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
116 int32
pas_par (int32 cmd
, int32 c
);
117 t_stat
pas_vlines (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
118 void pas_reset_ln (int32 i
);
120 /* PAS data structures
122 pas_dev PAS device descriptor
123 pas_unit PAS unit descriptor
124 pas_reg PAS register list
125 pas_mod PAS modifiers list
128 DIB pas_dib
= { d_PAS
, -1, v_PAS
, pas_tplte
, &pas
, &pas_ini
};
130 UNIT pas_unit
= { UDATA (&pasi_svc
, UNIT_ATTABLE
|UNIT_IDLE
, 0), 0 };
132 REG pas_nlreg
= { DRDATA (NLINES
, PAS_ENAB
, 6), PV_LEFT
};
135 { BRDATA (STA
, pas_sta
, 16, 8, PAS_LINES
) },
136 { BRDATA (CMD
, pas_cmd
, 16, 16, PAS_LINES
) },
137 { BRDATA (RBUF
, pas_rbuf
, 16, 8, PAS_LINES
) },
138 { BRDATA (XBUF
, pas_xbuf
, 16, 8, PAS_LINES
) },
139 { BRDATA (IREQ
, &int_req
[l_PAS
], 16, 32, PAS_LINES
/ 16) },
140 { BRDATA (IENB
, &int_enb
[l_PAS
], 16, 32, PAS_LINES
/ 16) },
141 { BRDATA (RARM
, pas_rarm
, 16, 1, PAS_LINES
) },
142 { BRDATA (XARM
, pas_xarm
, 16, 1, PAS_LINES
) },
143 { BRDATA (RCHP
, pas_rchp
, 16, 1, PAS_LINES
) },
144 { HRDATA (DEVNO
, pas_dib
.dno
, 8), REG_HRO
},
149 { MTAB_XTD
| MTAB_VDV
| MTAB_VAL
, 0, "lines", "LINES",
150 &pas_vlines
, NULL
, &pas_nlreg
},
151 { MTAB_XTD
| MTAB_VDV
, 1, NULL
, "DISCONNECT",
152 &tmxr_dscln
, NULL
, &pas_desc
},
153 { UNIT_ATT
, UNIT_ATT
, "connections", NULL
, NULL
, &pas_summ
},
154 { MTAB_XTD
| MTAB_VDV
| MTAB_NMO
, 1, "CONNECTIONS", NULL
,
155 NULL
, &pas_show
, NULL
},
156 { MTAB_XTD
| MTAB_VDV
| MTAB_NMO
, 0, "STATISTICS", NULL
,
157 NULL
, &pas_show
, NULL
},
158 { MTAB_XTD
|MTAB_VDV
, 0, "DEVNO", "DEVNO",
159 &set_dev
, &show_dev
, NULL
},
164 "PAS", &pas_unit
, pas_reg
, pas_mod
,
166 &tmxr_ex
, &tmxr_dep
, &pas_reset
,
167 NULL
, &pas_attach
, &pas_detach
,
168 &pas_dib
, DEV_NET
| DEV_DISABLE
171 /* PASL data structures
173 pasl_dev PASL device descriptor
174 pasl_unit PASL unit descriptor
175 pasl_reg PASL register list
176 pasl_mod PASL modifiers list
180 { UDATA (&paso_svc
, 0, 0), PASL_WAIT
}, /* all but 8 dis */
181 { UDATA (&paso_svc
, 0, 0), PASL_WAIT
},
182 { UDATA (&paso_svc
, 0, 0), PASL_WAIT
},
183 { UDATA (&paso_svc
, 0, 0), PASL_WAIT
},
184 { UDATA (&paso_svc
, 0, 0), PASL_WAIT
},
185 { UDATA (&paso_svc
, 0, 0), PASL_WAIT
},
186 { UDATA (&paso_svc
, 0, 0), PASL_WAIT
},
187 { UDATA (&paso_svc
, 0, 0), PASL_WAIT
},
188 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
189 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
190 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
191 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
192 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
193 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
194 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
195 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
196 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
197 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
198 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
199 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
200 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
201 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
202 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
203 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
204 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
205 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
206 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
207 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
208 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
209 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
210 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
},
211 { UDATA (&paso_svc
, UNIT_DIS
, 0), PASL_WAIT
}
215 { TT_MODE
, TT_MODE_UC
, "UC", "UC", NULL
},
216 { TT_MODE
, TT_MODE_7B
, "7b", "7B", NULL
},
217 { TT_MODE
, TT_MODE_8B
, "8b", "8B", NULL
},
218 { TT_MODE
, TT_MODE_7P
, "7p", "7P", NULL
},
219 { UNIT_MDM
, 0, "no dataset", "NODATASET", NULL
},
220 { UNIT_MDM
, UNIT_MDM
, "dataset", "DATASET", NULL
},
221 { MTAB_XTD
|MTAB_VDV
, 0, NULL
, "DISCONNECT",
222 &tmxr_dscln
, NULL
, &pas_desc
},
223 { MTAB_XTD
|MTAB_VUN
|MTAB_NC
, 0, "LOG", "LOG",
224 &tmxr_set_log
, &tmxr_show_log
, &pas_desc
},
225 { MTAB_XTD
|MTAB_VUN
|MTAB_NC
, 0, NULL
, "NOLOG",
226 &tmxr_set_nolog
, NULL
, &pas_desc
},
231 { URDATA (TIME
, pasl_unit
[0].wait
, 16, 24, 0,
232 PAS_LINES
, REG_NZ
+ PV_LEFT
) },
237 "PASL", pasl_unit
, pasl_reg
, pasl_mod
,
238 PAS_LINES
, 10, 31, 1, 16, 8,
239 NULL
, NULL
, &pas_reset
,
244 /* PAS: IO routine */
246 uint32
pas (uint32 dev
, uint32 op
, uint32 dat
)
248 int32 ln
= (dev
- pas_dib
.dno
) >> 1;
249 int32 xmt
= (dev
- pas_dib
.dno
) & 1;
252 switch (op
) { /* case IO op */
254 case IO_ADR
: /* select */
255 return BY
; /* byte only */
257 case IO_RD
: /* read */
258 pas_rchp
[ln
] = 0; /* clr chr pend */
259 pas_sta
[ln
] = pas_sta
[ln
] & ~STA_OVR
; /* clr overrun */
260 return pas_rbuf
[ln
]; /* return buf */
262 case IO_WD
: /* write */
263 pas_xbuf
[ln
] = dat
& 0xFF; /* store char */
264 pas_sta
[ln
] = pas_sta
[ln
] | STA_BSY
; /* set busy */
265 sim_activate (&pasl_unit
[ln
], pasl_unit
[ln
].wait
);
268 case IO_SS
: /* status */
269 if (xmt
) { /* xmt side? */
270 if (pas_ldsc
[ln
].conn
== 0) /* not conn? */
271 t
= STA_NCL2S
| STA_BSY
; /* busy, not clr */
272 else t
= pas_sta
[ln
] & STA_XMT
; /* else just busy */
275 t
= pas_sta
[ln
] & STA_RCV
; /* get static */
276 if (!pas_rchp
[ln
]) t
= t
| STA_BSY
; /* no char? busy */
277 if (pas_ldsc
[ln
].conn
== 0) /* not connected? */
278 t
= t
| STA_BSY
| STA_EX
; /* = !dsr */
279 if (t
& SET_EX
) t
= t
| STA_EX
; /* test for ex */
283 case IO_OC
: /* command */
284 old_cmd
= pas_cmd
[ln
]; /* old cmd */
285 if (dat
& CMD_TYP
) { /* type 1? */
286 pas_cmd
[ln
] = (pas_cmd
[ln
] & 0xFF) | (dat
<< 8);
287 if (pas_cmd
[ln
] & CMD_WRT
) /* write? */
288 pas_xarm
[ln
] = int_chg (v_PASX
+ ln
+ ln
, dat
, pas_xarm
[ln
]);
289 else pas_rarm
[ln
] = int_chg (v_PAS
+ ln
+ ln
, dat
, pas_rarm
[ln
]);
291 else pas_cmd
[ln
] = (pas_cmd
[ln
] & ~0xFF) | dat
;
292 if (pasl_unit
[ln
].flags
& UNIT_MDM
) { /* modem ctrl? */
293 if ((pas_cmd
[ln
] & CMD_DTR
) && (pas_sta
[ln
] & STA_RING
))
294 pas_sta
[ln
] = pas_sta
[ln
] & ~(STA_CROF
| STA_RING
);
295 if (old_cmd
& ~pas_cmd
[ln
] & CMD_DTR
) {
296 tmxr_linemsg (&pas_ldsc
[ln
], "\r\nLine hangup\r\n");
297 tmxr_reset_ln (&pas_ldsc
[ln
]); /* reset line */
298 pas_sta
[ln
] = pas_sta
[ln
] | STA_CROF
; /* no carrier */
299 if (pas_rarm
[ln
]) SET_INT (v_PAS
+ ln
+ ln
);
308 /* Unit service - receive side
310 Poll all active lines for input
311 Poll for new connections
314 t_stat
pasi_svc (UNIT
*uptr
)
318 if ((uptr
->flags
& UNIT_ATT
) == 0) return SCPE_OK
; /* attached? */
319 sim_activate (uptr
, lfc_poll
); /* continue poll */
320 ln
= tmxr_poll_conn (&pas_desc
); /* look for connect */
321 if (ln
>= 0) { /* got one? */
322 if ((pasl_unit
[ln
].flags
& UNIT_MDM
) && /* modem control */
323 ((pas_cmd
[ln
] & CMD_DTR
) == 0)) /* & !dtr? */
324 pas_sta
[ln
] = pas_sta
[ln
] | STA_RING
| STA_CROF
; /* set ring, no cd */
325 else pas_sta
[ln
] = pas_sta
[ln
] & ~STA_CROF
; /* just answer */
326 if (pas_rarm
[ln
]) SET_INT (v_PAS
+ ln
+ ln
); /* interrupt */
327 pas_ldsc
[ln
].rcve
= 1; /* rcv enabled */
329 tmxr_poll_rx (&pas_desc
); /* poll for input */
330 for (ln
= 0; ln
< PAS_ENAB
; ln
++) { /* loop thru lines */
331 if (pas_ldsc
[ln
].conn
) { /* connected? */
332 if (c
= tmxr_getc_ln (&pas_ldsc
[ln
])) { /* any char? */
333 pas_sta
[ln
] = pas_sta
[ln
] & ~(STA_FR
| STA_PF
);
334 if (pas_rchp
[ln
]) pas_sta
[ln
] = pas_sta
[ln
] | STA_OVR
;
335 if (pas_rarm
[ln
]) SET_INT (v_PAS
+ ln
+ ln
);
336 if (c
& SCPE_BREAK
) { /* break? */
337 pas_sta
[ln
] = pas_sta
[ln
] | STA_FR
; /* framing error */
338 pas_rbuf
[ln
] = 0; /* no character */
341 out
= c
& 0x7F; /* echo is 7b */
342 c
= sim_tt_inpcvt (c
, TT_GET_MODE (pasl_unit
[ln
].flags
));
343 if (TT_GET_MODE (pasl_unit
[ln
].flags
) != TT_MODE_8B
)
344 c
= pas_par (pas_cmd
[ln
], c
); /* apply parity */
345 pas_rbuf
[ln
] = c
; /* save char */
346 pas_rchp
[ln
] = 1; /* char pending */
347 if ((pas_cmd
[ln
] & CMD_ECHO
) && pas_ldsc
[ln
].xmte
) {
348 TMLN
*lp
= &pas_ldsc
[ln
]; /* get line */
349 out
= sim_tt_outcvt (out
, TT_GET_MODE (pasl_unit
[ln
].flags
));
350 if (out
>= 0) tmxr_putc_ln (lp
, out
); /* output char */
351 tmxr_poll_tx (&pas_desc
); /* poll xmt */
353 } /* end else normal */
356 else if ((pas_sta
[ln
] & STA_CROF
) == 0) { /* not conn, was conn? */
357 pas_sta
[ln
] = pas_sta
[ln
] | STA_CROF
; /* no carrier */
358 if (pas_rarm
[ln
]) SET_INT (v_PAS
+ ln
+ ln
); /* intr */
364 /* Unit service - transmit side */
366 t_stat
paso_svc (UNIT
*uptr
)
369 uint32 ln
= uptr
- pasl_unit
; /* line # */
371 if (pas_ldsc
[ln
].conn
) { /* connected? */
372 if (pas_ldsc
[ln
].xmte
) { /* xmt enabled? */
373 TMLN
*lp
= &pas_ldsc
[ln
]; /* get line */
374 if (TT_GET_MODE (pasl_unit
[ln
].flags
) == TT_MODE_8B
)
375 c
= pas_par (pas_cmd
[ln
], pas_xbuf
[ln
]); /* apply parity */
376 else c
= sim_tt_outcvt (pas_xbuf
[ln
], TT_GET_MODE (pasl_unit
[ln
].flags
));
378 tmxr_putc_ln (lp
, c
); /* output char */
380 tmxr_poll_tx (&pas_desc
); /* poll xmt */
382 else { /* buf full */
383 tmxr_poll_tx (&pas_desc
); /* poll xmt */
384 sim_activate (uptr
, pasl_unit
[ln
].wait
); /* wait */
388 pas_sta
[ln
] = pas_sta
[ln
] & ~STA_BSY
; /* not busy */
389 if (pas_xarm
[ln
]) SET_INT (v_PASX
+ ln
+ ln
); /* set intr */
393 int32
pas_par (int32 cmd
, int32 c
)
395 int32 pf
= GET_PAR (cmd
);
396 static const uint8 odd_par
[] = {
397 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 00 */
398 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
399 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 10 */
400 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
401 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 20 */
402 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
403 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 30 */
404 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
405 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 40 */
406 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
407 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 50 */
408 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
409 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 60 */
410 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
411 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 70 */
412 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
413 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 80 */
414 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
415 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 90 */
416 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
417 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* A0 */
418 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
419 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* B0 */
420 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
421 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* C0 */
422 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
423 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* D0 */
424 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
425 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* E0 */
426 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
427 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* F0 */
428 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80
431 switch (pf
) { /* case on parity */
434 return (odd_par
[c
& 0x7F]) | (c
& 0x7F);
437 return (odd_par
[c
& 0x7F] ^ 0x80) | (c
& 0x7F);
449 t_stat
pas_reset (DEVICE
*dptr
)
453 if (dptr
->flags
& DEV_DIS
) { /* disabled? */
454 pas_dev
.flags
= pas_dev
.flags
| DEV_DIS
; /* disable lines */
455 pasl_dev
.flags
= pasl_dev
.flags
| DEV_DIS
;
458 pas_dev
.flags
= pas_dev
.flags
& ~DEV_DIS
; /* enable lines */
459 pasl_dev
.flags
= pasl_dev
.flags
& ~DEV_DIS
;
461 if (pas_unit
.flags
& UNIT_ATT
) /* master att? */
462 sim_activate_abs (&pas_unit
, lfc_poll
); /* cosched with clock */
463 else sim_cancel (&pas_unit
); /* else stop */
464 for (i
= 0; i
< PAS_LINES
; i
++) pas_reset_ln (i
);
468 /* Attach master unit */
470 t_stat
pas_attach (UNIT
*uptr
, char *cptr
)
474 r
= tmxr_attach (&pas_desc
, uptr
, cptr
); /* attach */
475 if (r
!= SCPE_OK
) return r
; /* error */
476 sim_activate_abs (uptr
, 100); /* quick poll */
480 /* Detach master unit */
482 t_stat
pas_detach (UNIT
*uptr
)
487 r
= tmxr_detach (&pas_desc
, uptr
); /* detach */
488 for (i
= 0; i
< PAS_LINES
; i
++) pas_ldsc
[i
].rcve
= 0; /* disable rcv */
489 sim_cancel (uptr
); /* stop poll */
493 /* Show summary processor */
495 t_stat
pas_summ (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
499 for (i
= t
= 0; i
< PAS_LINES
; i
++) t
= t
+ (pas_ldsc
[i
].conn
!= 0);
500 if (t
== 1) fprintf (st
, "1 connection");
501 else fprintf (st
, "%d connections", t
);
505 /* SHOW CONN/STAT processor */
507 t_stat
pas_show (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
511 for (i
= t
= 0; i
< PAS_LINES
; i
++) t
= t
+ (pas_ldsc
[i
].conn
!= 0);
513 for (i
= 0; i
< PAS_LINES
; i
++) {
514 if (pas_ldsc
[i
].conn
) {
515 if (val
) tmxr_fconns (st
, &pas_ldsc
[i
], i
);
516 else tmxr_fstats (st
, &pas_ldsc
[i
], i
);
520 else fprintf (st
, "all disconnected\n");
524 /* Change number of lines */
526 t_stat
pas_vlines (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
531 if (cptr
== NULL
) return SCPE_ARG
;
532 newln
= get_uint (cptr
, 10, PAS_LINES
, &r
);
533 if ((r
!= SCPE_OK
) || (newln
== PAS_ENAB
)) return r
;
534 if (newln
== 0) return SCPE_ARG
;
535 if (newln
< PAS_ENAB
) {
536 for (i
= newln
, t
= 0; i
< PAS_ENAB
; i
++) t
= t
| pas_ldsc
[i
].conn
;
537 if (t
&& !get_yn ("This will disconnect users; proceed [N]?", FALSE
))
539 for (i
= newln
; i
< PAS_ENAB
; i
++) {
540 if (pas_ldsc
[i
].conn
) {
541 tmxr_linemsg (&pas_ldsc
[i
], "\r\nOperator disconnected line\r\n");
542 tmxr_reset_ln (&pas_ldsc
[i
]); /* reset line */
544 pasl_unit
[i
].flags
= pasl_unit
[i
].flags
| UNIT_DIS
;
549 for (i
= PAS_ENAB
; i
< newln
; i
++) {
550 pasl_unit
[i
].flags
= pasl_unit
[i
].flags
& ~UNIT_DIS
;
558 /* Reset an individual line */
560 void pas_reset_ln (int32 i
)
562 CLR_INT (v_PAS
+ i
+ i
); /* clear int */
563 CLR_ENB (v_PAS
+ i
+ i
);
564 CLR_INT (v_PASX
+ i
+ i
); /* disable int */
565 CLR_ENB (v_PASX
+ i
+ i
);
566 pas_rarm
[i
] = pas_xarm
[i
] = 0; /* disarm int */
567 pas_rbuf
[i
] = pas_xbuf
[i
] = 0; /* clear state */
571 if (pas_ldsc
[i
].conn
== 0) /* clear carrier */
572 pas_sta
[i
] = pas_sta
[i
] | STA_CROF
;
573 sim_cancel (&pasl_unit
[i
]);
579 void pas_ini (t_bool dtpl
)
583 for (i
= j
= 0; i
< PAS_ENAB
; i
++) {
585 pas_tplte
[j
+ 1] = j
+ o_PASX
;
588 pas_tplte
[j
] = TPL_END
;