This source file includes following definitions.
- absi_show_nunits
- absi_set_nunits
- absi_show_device_name
- absi_set_device_name
- absi_reset
- absiAttach
- absiDetach
- absi_init
- absi_cmd
- absi_iom_cmd
- absi_process_event
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <stdio.h>
22 #include <ctype.h>
23 #include <unistd.h>
24 #include <stdint.h>
25
26 #include "dps8.h"
27 #include "dps8_iom.h"
28 #include "dps8_absi.h"
29 #include "dps8_sys.h"
30 #include "dps8_faults.h"
31 #include "dps8_scu.h"
32 #include "dps8_cable.h"
33 #include "dps8_cpu.h"
34 #include "dps8_utils.h"
35
36 #include "udplib.h"
37
38 #ifdef TESTING
39 # undef FREE
40 # define FREE(p) free(p)
41 #endif
42
43 #ifdef WITH_ABSI_DEV
44 # define DBG_CTR 1
45
46 static struct absi_state
47 {
48 char device_name [MAX_DEV_NAME_LEN];
49 int link;
50 } absi_state [N_ABSI_UNITS_MAX];
51
52 # define N_ABSI_UNITS 1
53
54 # define UNIT_FLAGS ( UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | \
55 UNIT_IDLE )
56 UNIT absi_unit[N_ABSI_UNITS_MAX] =
57 {
58 {UDATA (NULL, UNIT_FLAGS, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL}
59 };
60
61 # define ABSI_UNIT_IDX(uptr) ((uptr) - absi_unit)
62
63 static DEBTAB absi_dt[] =
64 {
65 { "NOTIFY", DBG_NOTIFY, NULL },
66 { "INFO", DBG_INFO, NULL },
67 { "ERR", DBG_ERR, NULL },
68 { "WARN", DBG_WARN, NULL },
69 { "DEBUG", DBG_DEBUG, NULL },
70 { "ALL", DBG_ALL, NULL },
71 { NULL, 0, NULL }
72 };
73
74 static t_stat absi_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr,
75 UNUSED int val, UNUSED const void * desc)
76 {
77 sim_printf ("Number of ABSI units in system is %d\n", absi_dev.numunits);
78 return SCPE_OK;
79 }
80
81 static t_stat absi_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value,
82 const char * cptr, UNUSED void * desc)
83 {
84 if (! cptr)
85 return SCPE_ARG;
86 int n = atoi (cptr);
87 if (n < 1 || n > N_ABSI_UNITS_MAX)
88 return SCPE_ARG;
89 absi_dev.numunits = (uint32) n;
90 return SCPE_OK;
91 }
92
93 static t_stat absi_show_device_name (UNUSED FILE * st, UNIT * uptr,
94 UNUSED int val, UNUSED const void * desc)
95 {
96 int n = (int) ABSI_UNIT_IDX (uptr);
97 if (n < 0 || n >= N_ABSI_UNITS_MAX)
98 return SCPE_ARG;
99 if (absi_state[n].device_name[1] != 0)
100 sim_printf("name : %s", absi_state[n].device_name);
101 else
102 sim_printf("name : ABSI%d", n);
103 return SCPE_OK;
104 }
105
106 static t_stat absi_set_device_name (UNIT * uptr, UNUSED int32 value,
107 const char * cptr, UNUSED void * desc)
108 {
109 int n = (int) ABSI_UNIT_IDX (uptr);
110 if (n < 0 || n >= N_ABSI_UNITS_MAX)
111 return SCPE_ARG;
112 if (cptr)
113 {
114 strncpy (absi_state[n].device_name, cptr, MAX_DEV_NAME_LEN-1);
115 absi_state[n].device_name[MAX_DEV_NAME_LEN-1] = 0;
116 }
117 else
118 absi_state[n].device_name[0] = 0;
119 return SCPE_OK;
120 }
121
122 # define UNIT_WATCH UNIT_V_UF
123
124 static MTAB absi_mod[] =
125 {
126 # ifndef SPEED
127 { UNIT_WATCH, 1, "WATCH", "WATCH", 0, 0, NULL, NULL },
128 { UNIT_WATCH, 0, "NOWATCH", "NOWATCH", 0, 0, NULL, NULL },
129 # endif
130 {
131 MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_VALR,
132 0,
133 "NUNITS",
134 "NUNITS",
135 absi_set_nunits,
136 absi_show_nunits,
137 "Number of ABSI units in the system",
138 NULL
139 },
140 {
141 MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,
142 0,
143 "NAME",
144 "NAME",
145 absi_set_device_name,
146 absi_show_device_name,
147 "Set the device name",
148 NULL
149 },
150 MTAB_eol
151 };
152
153 static t_stat absi_reset (UNUSED DEVICE * dptr)
154 {
155
156
157 return SCPE_OK;
158 }
159
160 static t_stat absiAttach (UNIT * uptr, const char * cptr)
161 {
162 if (! cptr)
163 return SCPE_ARG;
164 int unitno = (int) (uptr - absi_unit);
165
166
167
168 t_stat ret;
169 char * pfn;
170
171
172
173 if ((uptr->flags & UNIT_ATT) != 0)
174 detach_unit (uptr);
175
176
177
178
179 pfn = (char *) calloc ((CBUFSIZE + 1), sizeof (char));
180 if (pfn == NULL)
181 return SCPE_MEM;
182 strncpy (pfn, cptr, CBUFSIZE);
183
184
185 ret = udp_create (cptr, & absi_state[unitno].link);
186 if (ret != SCPE_OK)
187 {
188 FREE (pfn);
189 return ret;
190 }
191
192 uptr->flags |= UNIT_ATT;
193 uptr->filename = pfn;
194 return SCPE_OK;
195 }
196
197
198 static t_stat absiDetach (UNIT * uptr)
199 {
200 int unitno = (int) (uptr - absi_unit);
201 t_stat ret;
202 if ((uptr->flags & UNIT_ATT) == 0)
203 return SCPE_OK;
204 if (absi_state[unitno].link == NOLINK)
205 return SCPE_OK;
206
207 ret = udp_release (absi_state[unitno].link);
208 if (ret != SCPE_OK)
209 return ret;
210 absi_state[unitno].link = NOLINK;
211 uptr->flags &= ~ (unsigned int) UNIT_ATT;
212 FREE (uptr->filename);
213 uptr->filename = NULL;
214 return SCPE_OK;
215 }
216
217 DEVICE absi_dev = {
218 "ABSI",
219 absi_unit,
220 NULL,
221 absi_mod,
222 N_ABSI_UNITS,
223 10,
224 24,
225 1,
226 8,
227 36,
228 NULL,
229 NULL,
230 absi_reset,
231 NULL,
232 absiAttach,
233 absiDetach,
234 NULL,
235 DEV_DEBUG,
236 0,
237 absi_dt,
238 NULL,
239 NULL,
240 NULL,
241 NULL,
242 NULL,
243 NULL,
244 NULL
245 };
246
247
248
249
250
251
252
253 void absi_init (void)
254 {
255 memset (absi_state, 0, sizeof (absi_state));
256 for (int i = 0; i < N_ABSI_UNITS_MAX; i ++)
257 absi_state[i].link = NOLINK;
258 }
259
260 static iom_cmd_rc_t absi_cmd (uint iomUnitIdx, uint chan)
261 {
262 iom_chan_data_t * p = &iom_chan_data[iomUnitIdx][chan];
263
264
265 sim_debug (DBG_TRACE, & absi_dev,
266 "absi_cmd CHAN_CMD %o DEV_CODE %o DEV_CMD %o COUNT %o\n",
267 p->IDCW_CHAN_CMD, p->IDCW_DEV_CODE, p->IDCW_DEV_CMD,
268 p->IDCW_COUNT);
269
270
271 if (IS_NOT_IDCW (p))
272 {
273 sim_warn ("%s: Unexpected IOTx\n", __func__);
274 return IOM_CMD_ERROR;
275 }
276
277 switch (p->IDCW_DEV_CMD)
278 {
279 case 000:
280 {
281 p->stati = 04000;
282 sim_printf ("absi request status\n");
283 }
284 break;
285
286 case 001:
287 {
288 p->stati = 04000;
289 sim_printf ("absi read\n");
290 }
291 break;
292
293 case 011:
294 {
295 p->stati = 04000;
296 sim_printf ("absi write\n");
297 }
298 break;
299
300 case 020:
301 {
302 p->stati = 04000;
303 sim_printf ("absi host switch down\n");
304 }
305 break;
306
307 case 040:
308 {
309 p->stati = 04000;
310 sim_printf ("absi reset status\n");
311 }
312 break;
313
314 case 060:
315 {
316 p->stati = 04000;
317 sim_printf ("absi host switch up\n");
318 }
319 break;
320
321 default:
322 {
323 if (p->IDCW_DEV_CMD != 051)
324 sim_warn ("%s: ABSI unrecognized device command %02o\n", __func__, p->IDCW_DEV_CMD);
325 p->stati = 04501;
326 p->chanStatus = chanStatIncorrectDCW;
327 }
328 return IOM_CMD_ERROR;
329 }
330
331 if (p->IDCW_CHAN_CMD == 0)
332 return IOM_CMD_DISCONNECT;
333 return IOM_CMD_PROCEED;
334 }
335
336
337
338
339 iom_cmd_rc_t absi_iom_cmd (uint iomUnitIdx, uint chan)
340 {
341 iom_chan_data_t * p = & iom_chan_data[iomUnitIdx][chan];
342
343
344 if (IS_IDCW (p))
345 {
346 return absi_cmd (iomUnitIdx, chan);
347 }
348 sim_printf ("%s expected IDCW\n", __func__);
349 return IOM_CMD_ERROR;
350 }
351
352 void absi_process_event (void)
353 {
354 # define psz 17000
355 uint16_t pkt[psz];
356 for (uint32 unit = 0; unit < absi_dev.numunits; unit ++)
357 {
358 if (absi_state[unit].link == NOLINK)
359 continue;
360
361 int sz = udp_receive (absi_state[unit].link, pkt, psz);
362 if (sz < 0)
363 {
364 fprintf (stderr, "udp_receive failed\n");
365 }
366 else if (sz == 0)
367 {
368
369 }
370 else
371 {
372 for (int i = 0; i < sz; i ++)
373 {
374 fprintf (stderr, " %06o %04x ", pkt[i], pkt[i]);
375 for (int b = 0; b < 16; b ++)
376 fprintf (stderr, "%c", pkt[i] & (1 << (16 - b)) ? '1' : '0');
377 fprintf (stderr, "\n");
378 }
379
380
381 int rc = udp_send (absi_state[unit].link, pkt, (uint16_t) sz,
382 PFLG_FINAL);
383 if (rc < 0)
384 {
385 fprintf (stderr, "udp_send failed\n");
386 }
387 }
388 }
389 }
390 #endif