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