~ubuntu-branches/ubuntu/utopic/simh/utopic

« back to all changes in this revision

Viewing changes to PDP18B/pdp18b_tt1.c

  • Committer: Bazaar Package Importer
  • Author(s): Vince Mulhollon
  • Date: 2004-04-20 20:01:26 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040420200126-ehsuleda8xcgi51h
Tags: 3.2.0-1
New upstream 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* pdp15_ttx.c: PDP-15 additional terminals simulator
 
2
 
 
3
   Copyright (c) 1993-2004, 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
 
23
   be 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
   ttix,ttox    LT15/LT19 terminal input/output
 
27
 
 
28
   14-Jan-04    RMS     Cloned from pdp8_ttx.c
 
29
 
 
30
   This module implements 16 individual serial interfaces similar in function
 
31
   to the console.  These interfaces are mapped to Telnet based connections as
 
32
   though they were the four lines of a terminal multiplexor.  The connection
 
33
   polling mechanism is superimposed onto the keyboard of the first interface.
 
34
*/
 
35
 
 
36
#include "pdp18b_defs.h"
 
37
#include "sim_sock.h"
 
38
#include "sim_tmxr.h"
 
39
#include <ctype.h>
 
40
 
 
41
#if defined (PDP15)
 
42
#define TTX_MAXL        16                              /* max number of lines */
 
43
#elif defined (PDP9)
 
44
#define TTX_MAXL        4
 
45
#else
 
46
#define TTX_MAXL        1
 
47
#endif
 
48
 
 
49
#define UNIT_V_8B       (UNIT_V_UF + 0)                 /* 8B */
 
50
#define UNIT_V_KSR      (UNIT_V_UF + 1)                 /* KSR33 */
 
51
#define UNIT_8B         (1 << UNIT_V_8B)
 
52
#define UNIT_KSR        (1 << UNIT_V_KSR)
 
53
 
 
54
uint32 ttix_done = 0;                                   /* input flags */
 
55
uint32 ttox_done = 0;                                   /* output flags */
 
56
uint8 ttix_buf[TTX_MAXL] = { 0 };                       /* input buffers */
 
57
uint8 ttox_buf[TTX_MAXL] = { 0 };                       /* output buffers */
 
58
TMLN ttx_ldsc[TTX_MAXL] = { 0 };                        /* line descriptors */
 
59
TMXR ttx_desc = { 1, 0, 0, ttx_ldsc };                  /* mux descriptor */
 
60
#define ttx_lines ttx_desc.lines                        /* current number of lines */
 
61
 
 
62
extern int32 int_hwre[API_HLVL+1];
 
63
extern int32 tmxr_poll;
 
64
extern int32 stop_inst;
 
65
 
 
66
DEVICE ttix_dev, ttox_dev;
 
67
int32 ttix (int32 dev, int32 pulse, int32 dat);
 
68
int32 ttox (int32 dev, int32 pulse, int32 dat);
 
69
t_stat ttix_svc (UNIT *uptr);
 
70
t_bool ttix_test_done (int32 ln);
 
71
void ttix_set_done (int32 ln);
 
72
void ttix_clr_done (int32 ln);
 
73
t_stat ttox_svc (UNIT *uptr);
 
74
t_bool ttox_test_done (int32 ln);
 
75
void ttox_set_done (int32 ln);
 
76
void ttox_clr_done (int32 ln);
 
77
int32 ttx_getln (int32 dev, int32 pulse);
 
78
t_stat ttx_attach (UNIT *uptr, char *cptr);
 
79
t_stat ttx_detach (UNIT *uptr);
 
80
t_stat ttx_reset (DEVICE *dptr);
 
81
void ttx_reset_ln (int32 i);
 
82
t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
 
83
t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc);
 
84
t_stat ttx_vlines (UNIT *uptr, int32 val, char *cptr, void *desc);
 
85
 
 
86
/* TTIx data structures
 
87
 
 
88
   ttix_dev     TTIx device descriptor
 
89
   ttix_unit    TTIx unit descriptor
 
90
   ttix_reg     TTIx register list
 
91
   ttix_mod     TTIx modifiers list
 
92
*/
 
93
 
 
94
DIB ttix_dib = { DEV_TTO1, 8, NULL,
 
95
                 { &ttox, &ttix, &ttox, &ttix, &ttox, &ttix, &ttox, &ttix } };
 
96
 
 
97
UNIT ttix_unit = { UDATA (&ttix_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT };
 
98
 
 
99
REG ttx_nlreg = { DRDATA (NLINES, ttx_lines, 4), PV_LEFT };
 
100
 
 
101
REG ttix_reg[] = {
 
102
        { BRDATA (BUF, ttix_buf, 8, 8, TTX_MAXL) },
 
103
        { ORDATA (DONE, ttix_done, TTX_MAXL) },
 
104
        { FLDATA (INT, int_hwre[API_TTI1], INT_V_TTI1) },
 
105
        { DRDATA (TIME, ttix_unit.wait, 24), REG_NZ + PV_LEFT },
 
106
        { ORDATA (DEVNUM, ttix_dib.dev, 6), REG_HRO },
 
107
        { NULL }  };
 
108
 
 
109
MTAB ttix_mod[] = {
 
110
        { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES",
 
111
            &ttx_vlines, NULL, &ttx_nlreg },
 
112
        { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &ttx_summ },
 
113
        { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
 
114
                &tmxr_dscln, NULL, &ttx_desc },
 
115
        { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
 
116
                NULL, &ttx_show, NULL },
 
117
        { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
 
118
                NULL, &ttx_show, NULL },
 
119
        { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
 
120
                &set_devno, &show_devno, NULL },
 
121
        { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
 
122
            &tmxr_set_log, &tmxr_show_log, &ttx_desc },
 
123
        { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
 
124
            &tmxr_set_nolog, NULL, &ttx_desc },
 
125
        { 0 }  };
 
126
 
 
127
DEVICE tti1_dev = {
 
128
        "TTIX", &ttix_unit, ttix_reg, ttix_mod,
 
129
        1, 10, 31, 1, 8, 8,
 
130
        &tmxr_ex, &tmxr_dep, &ttx_reset,
 
131
        NULL, &ttx_attach, &ttx_detach,
 
132
        &ttix_dib, DEV_NET | DEV_DISABLE };
 
133
 
 
134
/* TTOx data structures
 
135
 
 
136
   ttox_dev     TTOx device descriptor
 
137
   ttox_unit    TTOx unit descriptor
 
138
   ttox_reg     TTOx register list
 
139
*/
 
140
 
 
141
UNIT ttox_unit[] = {
 
142
        { UDATA (&ttox_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT },
 
143
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
144
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
145
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
146
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
147
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
148
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
149
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
150
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
151
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
152
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
153
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
154
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
155
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
156
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
 
157
        { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }  };
 
158
 
 
159
REG ttox_reg[] = {
 
160
        { BRDATA (BUF, ttox_buf, 8, 8, TTX_MAXL) },
 
161
        { ORDATA (DONE, ttox_done, TTX_MAXL) },
 
162
        { FLDATA (INT, int_hwre[API_TTO1], INT_V_TTO1) },
 
163
        { URDATA (TIME, ttox_unit[0].wait, 10, 24, 0,
 
164
                  TTX_MAXL, PV_LEFT) },
 
165
        { NULL }  };
 
166
 
 
167
MTAB ttox_mod[] = {
 
168
        { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", NULL },
 
169
        { UNIT_KSR+UNIT_8B, 0       , "7b" , "7B" , NULL },
 
170
        { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , NULL },
 
171
        { 0 }  };
 
172
 
 
173
DEVICE tto1_dev = {
 
174
        "TTOX", ttox_unit, ttox_reg, ttox_mod,
 
175
        TTX_MAXL, 10, 31, 1, 8, 8,
 
176
        NULL, NULL, &ttx_reset, 
 
177
        NULL, NULL, NULL,
 
178
        NULL, DEV_DISABLE };
 
179
 
 
180
/* Terminal input: IOT routine */
 
181
 
 
182
int32 ttix (int32 dev, int32 pulse, int32 dat)
 
183
{
 
184
int32 ln = ttx_getln (dev, pulse);                      /* line # */
 
185
 
 
186
if (ln > ttx_lines) return dat;
 
187
if (pulse & 001) {                                      /* KSF1 */
 
188
        if (ttix_test_done (ln)) dat = dat | IOT_SKP;  }
 
189
if (pulse & 002) {                                      /* KRB1 */
 
190
        ttix_clr_done (ln);                             /* clear flag */
 
191
        dat = dat | ttix_buf[ln];  }                    /* return buffer */
 
192
return dat;
 
193
}
 
194
 
 
195
/* Unit service */
 
196
 
 
197
t_stat ttix_svc (UNIT *uptr)
 
198
{
 
199
int32 ln, c, temp;
 
200
 
 
201
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK;      /* attached? */
 
202
sim_activate (uptr, tmxr_poll);                         /* continue poll */
 
203
ln = tmxr_poll_conn (&ttx_desc);                        /* look for connect */
 
204
if (ln >= 0) ttx_ldsc[ln].rcve = 1;                     /* got one? rcv enab */
 
205
tmxr_poll_rx (&ttx_desc);                               /* poll for input */
 
206
for (ln = 0; ln < TTX_MAXL; ln++) {                     /* loop thru lines */
 
207
        if (ttx_ldsc[ln].conn) {                        /* connected? */
 
208
            if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) {  /* get char */
 
209
                if (temp & SCPE_BREAK) c = 0;           /* break? */
 
210
                else if (ttox_unit[ln].flags & UNIT_KSR) {      /* KSR? */
 
211
                    c = temp & 0177;
 
212
                    if (islower (c)) c = toupper (c);
 
213
                    c = c | 0200;  }
 
214
                else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
 
215
                ttix_buf[ln] = c;
 
216
                ttix_set_done (ln);  }  }  }
 
217
return SCPE_OK;
 
218
}
 
219
 
 
220
/* Interrupt handling routines */
 
221
 
 
222
t_bool ttix_test_done (int32 ln)
 
223
{
 
224
if (ttix_done & (1 << ln)) return TRUE;
 
225
return FALSE;
 
226
}
 
227
 
 
228
void ttix_set_done (int32 ln)
 
229
{
 
230
ttix_done = ttix_done | (1 << ln);
 
231
SET_INT (TTI1);
 
232
return;
 
233
}
 
234
 
 
235
void ttix_clr_done (int32 ln)
 
236
{
 
237
ttix_done = ttix_done & ~(1 << ln);
 
238
if (ttix_done) { SET_INT (TTI1); }
 
239
else {  CLR_INT (TTI1);  }
 
240
return;
 
241
}
 
242
 
 
243
/* Terminal output: IOT routine */
 
244
 
 
245
int32 ttox (int32 dev, int32 pulse, int32 dat)
 
246
{
 
247
int32 ln = ttx_getln (dev, pulse);                      /* line # */
 
248
 
 
249
if (ln > ttx_lines) return dat;
 
250
if (pulse & 001) {                                      /* TSF */
 
251
        if (ttox_test_done (ln)) dat = dat | IOT_SKP;  }
 
252
if (pulse & 002) ttox_clr_done (ln);                    /* clear flag */
 
253
if (pulse & 004) {                                      /* load buffer */
 
254
        sim_activate (&ttox_unit[ln], ttox_unit[ln].wait);      /* activate unit */
 
255
        ttox_buf[ln] = dat & 0377;  }                   /* load buffer */
 
256
return dat;
 
257
}
 
258
 
 
259
/* Unit service */
 
260
 
 
261
t_stat ttox_svc (UNIT *uptr)
 
262
{
 
263
int32 c, ln = uptr - ttox_unit;                         /* line # */
 
264
 
 
265
if (ttx_ldsc[ln].conn) {                                /* connected? */
 
266
        if (ttx_ldsc[ln].xmte) {                        /* tx enabled? */
 
267
            TMLN *lp = &ttx_ldsc[ln];                   /* get line */
 
268
            if (ttox_unit[ln].flags & UNIT_KSR) {       /* KSR mode? */
 
269
                c = ttox_buf[ln] & 0177;                /* get char */
 
270
                if (islower (c)) c = toupper (c);
 
271
                if ((c < 007) || (c > 0137)) c = -1;  }
 
272
            else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
 
273
            if (c >= 0) tmxr_putc_ln (lp, c);           /* output char */
 
274
            tmxr_poll_tx (&ttx_desc);  }                /* poll xmt */
 
275
        else {
 
276
            tmxr_poll_tx (&ttx_desc);                   /* poll xmt */
 
277
            sim_activate (uptr, ttox_unit[ln].wait);    /* wait */
 
278
            return SCPE_OK;  }  }
 
279
ttox_set_done (ln);                                     /* set done */
 
280
return SCPE_OK;
 
281
}
 
282
 
 
283
/* Interrupt handling routines */
 
284
 
 
285
t_bool ttox_test_done (int32 ln)
 
286
{
 
287
if (ttox_done & (1 << ln)) return TRUE;
 
288
return FALSE;
 
289
}
 
290
 
 
291
void ttox_set_done (int32 ln)
 
292
{
 
293
ttox_done = ttox_done | (1 << ln);
 
294
SET_INT (TTO1);
 
295
return;
 
296
}
 
297
 
 
298
void ttox_clr_done (int32 ln)
 
299
{
 
300
ttox_done = ttox_done & ~(1 << ln);
 
301
if (ttox_done) { SET_INT (TTO1); }
 
302
else {  CLR_INT (TTO1);  }
 
303
return;
 
304
}
 
305
 
 
306
/* Compute relative line number
 
307
 
 
308
   This algorithm does not assign contiguous line numbers of ascending
 
309
   LT19's.  Rather, line numbers follow a simple progression based on
 
310
   the relative IOT number and the subdevice select */
 
311
 
 
312
int32 ttx_getln (int32 dev, int32 pulse)
 
313
{
 
314
int32 rdno = ((dev - ttix_dib.dev) >> 1) & 3;
 
315
 
 
316
#if defined (PDP15)                                     /* PDP-15? */
 
317
int32 sub = (pulse >> 4) & 3;
 
318
return (rdno * 4) + sub;                                /* use dev, subdev */
 
319
#else                                                   /* others */                    
 
320
return rdno;                                            /* use dev only */
 
321
#endif
 
322
}
 
323
 
 
324
/* Reset routine */
 
325
 
 
326
t_stat ttx_reset (DEVICE *dptr)
 
327
{
 
328
int32 ln;
 
329
 
 
330
if (dptr->flags & DEV_DIS) {                            /* sync enables */
 
331
        ttix_dev.flags = ttox_dev.flags | DEV_DIS;
 
332
        ttox_dev.flags = ttox_dev.flags | DEV_DIS;  }
 
333
else {  ttix_dev.flags = ttix_dev.flags & ~DEV_DIS;
 
334
        ttox_dev.flags = ttox_dev.flags & ~DEV_DIS;  }
 
335
if (ttix_unit.flags & UNIT_ATT)                         /* if attached, */
 
336
        sim_activate (&ttix_unit, tmxr_poll);           /* activate */
 
337
else sim_cancel (&ttix_unit);                           /* else stop */
 
338
for (ln = 0; ln < TTX_MAXL; ln++) ttx_reset_ln (ln);    /* for all lines */
 
339
return SCPE_OK;
 
340
}
 
341
 
 
342
/* Reset line n */
 
343
 
 
344
void ttx_reset_ln (int32 ln)
 
345
{
 
346
ttix_buf[ln] = 0;                                       /* clear buf, */
 
347
ttox_buf[ln] = 0;
 
348
ttix_clr_done (ln);                                     /* clear done */
 
349
ttox_clr_done (ln);
 
350
sim_cancel (&ttox_unit[ln]);                            /* stop poll */
 
351
return;
 
352
}
 
353
 
 
354
/* Attach master unit */
 
355
 
 
356
t_stat ttx_attach (UNIT *uptr, char *cptr)
 
357
{
 
358
t_stat r;
 
359
 
 
360
r = tmxr_attach (&ttx_desc, uptr, cptr);                /* attach */
 
361
if (r != SCPE_OK) return r;                             /* error */
 
362
sim_activate (uptr, tmxr_poll);                         /* start poll */
 
363
return SCPE_OK;
 
364
}
 
365
 
 
366
/* Detach master unit */
 
367
 
 
368
t_stat ttx_detach (UNIT *uptr)
 
369
{
 
370
int32 i;
 
371
t_stat r;
 
372
 
 
373
r = tmxr_detach (&ttx_desc, uptr);                      /* detach */
 
374
sim_cancel (uptr);                                      /* stop poll */
 
375
for (i = 0; i < TTX_MAXL; i++) ttx_ldsc[i].rcve = 0;    /* disable rcv */
 
376
return r;
 
377
}
 
378
 
 
379
/* Show summary processor */
 
380
 
 
381
t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc)
 
382
{
 
383
int32 i, t;
 
384
 
 
385
for (i = t = 0; i < TTX_MAXL; i++) t = t + (ttx_ldsc[i].conn != 0);
 
386
if (t == 1) fprintf (st, "1 connection");
 
387
else fprintf (st, "%d connections", t);
 
388
return SCPE_OK;
 
389
}
 
390
 
 
391
/* SHOW CONN/STAT processor */
 
392
 
 
393
t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc)
 
394
{
 
395
int32 i;
 
396
 
 
397
for (i = 0; (i < ttx_lines) && (ttx_ldsc[i].conn == 0); i++) ;
 
398
if (i < ttx_lines) {
 
399
        for (i = 0; i < ttx_lines; i++) {
 
400
            if (ttx_ldsc[i].conn) 
 
401
                if (val) tmxr_fconns (st, &ttx_ldsc[i], i);
 
402
                else tmxr_fstats (st, &ttx_ldsc[i], i);  }  }
 
403
else fprintf (st, "all disconnected\n");
 
404
return SCPE_OK;
 
405
}
 
406
 
 
407
/* Change number of lines */
 
408
 
 
409
t_stat ttx_vlines (UNIT *uptr, int32 val, char *cptr, void *desc)
 
410
{
 
411
int32 newln, i, t;
 
412
t_stat r;
 
413
 
 
414
if (cptr == NULL) return SCPE_ARG;
 
415
newln = get_uint (cptr, 10, TTX_MAXL, &r);
 
416
if ((r != SCPE_OK) || (newln == ttx_lines)) return r;
 
417
if (newln == 0) return SCPE_ARG;
 
418
if (newln < ttx_lines) {
 
419
        for (i = newln, t = 0; i < ttx_lines; i++) t = t | ttx_ldsc[i].conn;
 
420
        if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
 
421
            return SCPE_OK;
 
422
        for (i = newln; i < ttx_lines; i++) {
 
423
            if (ttx_ldsc[i].conn) {
 
424
                tmxr_linemsg (&ttx_ldsc[i], "\r\nOperator disconnected line\r\n");
 
425
                tmxr_reset_ln (&ttx_ldsc[i]);  }        /* reset line */
 
426
            ttox_unit[i].flags = ttox_unit[i].flags | UNIT_DIS;
 
427
            ttx_reset_ln (i);  }
 
428
        }
 
429
else {  for (i = ttx_lines; i < newln; i++) {
 
430
            ttox_unit[i].flags = ttox_unit[i].flags & ~UNIT_DIS;
 
431
            ttx_reset_ln (i);  }
 
432
        }
 
433
ttx_lines = newln;
 
434
return SCPE_OK;
 
435
}
 
436
 
 
437