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