This source file includes following definitions.
- sk_show_nunits
- sk_set_nunits
- skc_show_device_name
- skc_set_device_name
- sk_reset
- sk_init
- set_error_str
- set_error
- skt_socket
- skt_gethostbyname
- skt_bind
- skt_listen
- skt_accept
- skt_close
- skt_read8
- skt_write8
- get_ddcw
- sk_cmd
- skc_iom_cmd
- do_try_accept
- do_try_read
- sk_process_event
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <stdio.h>
20 #include <ctype.h>
21 #include <netdb.h>
22 #include <sys/ioctl.h>
23 #include <unistd.h>
24
25 #if defined(__sun__) || defined(_AIX)
26 # include <strings.h>
27 #endif
28
29 #include "dps8.h"
30 #include "dps8_sys.h"
31 #include "dps8_iom.h"
32 #include "dps8_socket_dev.h"
33 #include "dps8_cable.h"
34 #include "dps8_cpu.h"
35 #include "dps8_faults.h"
36 #include "dps8_utils.h"
37
38 #define DBG_CTR 1
39
40 #if !defined(bzero)
41 # define bzero(b,len) ((void)memset((b), '\0', (len)), (void) 0)
42 #endif
43
44 static struct {
45 const char *name;
46 int code;
47 } errnos[] = {
48 {" ", 0},
49 #include "errnos.h"
50 };
51 #define N_ERRNOS (sizeof (errnos) / sizeof (errnos[0]))
52
53 #if defined(WITH_SOCKET_DEV)
54 # define SKC_UNIT_IDX(uptr) ((uptr) - sk_unit)
55
56 struct skc_state_s
57 {
58 char device_name [MAX_DEV_NAME_LEN];
59 };
60 static struct skc_state_s skc_state[N_SKC_UNITS_MAX];
61
62 # define N_FDS 1024
63
64 static struct
65 {
66 int fd_unit[N_FDS];
67 word6 fd_dev_code[N_FDS];
68 bool fd_nonblock[N_FDS];
69 struct
70 {
71 enum
72 {
73 unit_idle = 0,
74 unit_accept,
75 unit_read
76 } unit_state;
77
78 int accept_fd;
79 int read_fd;
80 uint read_buffer_sz;
81 uint words_processed;
82 } unit_data[N_SKC_UNITS_MAX][N_DEV_CODES];
83 } sk_data;
84
85 # define N_SKC_UNITS 64
86
87 static t_stat sk_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr,
88 UNUSED int val, UNUSED const void * desc)
89 {
90 sim_printf("Number of socket units in system is %d\n", skc_dev.numunits);
91 return SCPE_OK;
92 }
93
94 static t_stat sk_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value,
95 const char * cptr, UNUSED void * desc)
96 {
97 if (! cptr)
98 return SCPE_ARG;
99 int n = atoi (cptr);
100 if (n < 1 || n > N_SKC_UNITS_MAX)
101 return SCPE_ARG;
102 skc_dev.numunits = (uint32) n;
103 return SCPE_OK;
104 }
105
106 static t_stat skc_show_device_name (UNUSED FILE * st, UNIT * uptr,
107 UNUSED int val, UNUSED const void * desc)
108 {
109 int n = (int) SKC_UNIT_IDX (uptr);
110 if (n < 0 || n >= N_SKC_UNITS_MAX)
111 return SCPE_ARG;
112 if (skc_state[n].device_name[1] != 0)
113 sim_printf("Name: %s", skc_state[n].device_name);
114 return SCPE_OK;
115 }
116
117 static t_stat skc_set_device_name (UNIT * uptr, UNUSED int32 value,
118 const char * cptr, UNUSED void * desc)
119 {
120 int n = (int) SKC_UNIT_IDX (uptr);
121 if (n < 0 || n >= N_SKC_UNITS_MAX)
122 return SCPE_ARG;
123 if (cptr)
124 {
125 strncpy (skc_state[n].device_name, cptr, MAX_DEV_NAME_LEN-1);
126 skc_state[n].device_name[MAX_DEV_NAME_LEN-1] = 0;
127 }
128 else
129 skc_state[n].device_name[0] = 0;
130 return SCPE_OK;
131 }
132
133 static MTAB sk_mod [] =
134 {
135 {
136 MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_VALR,
137 0,
138 "NUNITS",
139 "NUNITS",
140 sk_set_nunits,
141 sk_show_nunits,
142 "Number of socket units in the system",
143 NULL
144 },
145 {
146 MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,
147 0,
148 "NAME",
149 "NAME",
150 skc_set_device_name,
151 skc_show_device_name,
152 "Set the device name",
153 NULL
154 },
155 MTAB_eol
156 };
157
158 UNIT sk_unit [N_SKC_UNITS_MAX] = {
159 # if defined(NO_C_ELLIPSIS)
160 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
161 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
162 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
163 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
164 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
165 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
166 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
167 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
168 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
169 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
170 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
171 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
172 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
173 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
174 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
175 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
176 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
177 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
178 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
179 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
180 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
181 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
182 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
183 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
184 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
185 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
186 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
187 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
188 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
189 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
190 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
191 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
192 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
193 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
194 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
195 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
196 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
197 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
198 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
199 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
200 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
201 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
202 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
203 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
204 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
205 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
206 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
207 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
208 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
209 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
210 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
211 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
212 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
213 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
214 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
215 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
216 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
217 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
218 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
219 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
220 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
221 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
222 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
223 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
224 # else
225 [0 ... (N_SKC_UNITS_MAX -1)] = {
226 UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
227 },
228 # endif
229 };
230
231 static DEBTAB sk_dt [] =
232 {
233 { "NOTIFY", DBG_NOTIFY, NULL },
234 { "INFO", DBG_INFO, NULL },
235 { "ERR", DBG_ERR, NULL },
236 { "WARN", DBG_WARN, NULL },
237 { "DEBUG", DBG_DEBUG, NULL },
238 { "ALL", DBG_ALL, NULL },
239 { NULL, 0, NULL }
240 };
241
242 static t_stat sk_reset (UNUSED DEVICE * dptr)
243 {
244 return SCPE_OK;
245 }
246
247 DEVICE skc_dev = {
248 "SKC",
249 sk_unit,
250 NULL,
251 sk_mod,
252 N_SKC_UNITS,
253 10,
254 31,
255 1,
256 8,
257 9,
258 NULL,
259 NULL,
260 sk_reset,
261 NULL,
262 NULL,
263 NULL,
264 NULL,
265 DEV_DEBUG,
266 0,
267 sk_dt,
268 NULL,
269 NULL,
270 NULL,
271 NULL,
272 NULL,
273 NULL,
274 NULL
275 };
276
277 void sk_init(void)
278 {
279
280 (void)memset(& sk_data, 0, sizeof(sk_data));
281 for (uint i = 0; i < N_FDS; i ++)
282 sk_data.fd_unit[i] = -1;
283
284
285
286 }
287
288 static void set_error_str (word36 * error_str, const char * str)
289 {
290 char work [8];
291
292
293 for (uint i = 0; i < 8; i ++)
294 work[i] = ' ';
295 size_t l = strlen (str);
296 if (l > 8)
297 l = 8;
298 for (uint i = 0; i < l; i ++)
299 work[i] = str[i];
300 error_str[0] = 0;
301 error_str[1] = 0;
302 putbits36_8 (error_str + 0, 1, (word8) work [0]);
303 putbits36_8 (error_str + 0, 10, (word8) work [1]);
304 putbits36_8 (error_str + 0, 19, (word8) work [2]);
305 putbits36_8 (error_str + 0, 28, (word8) work [3]);
306 putbits36_8 (error_str + 1, 1, (word8) work [4]);
307 putbits36_8 (error_str + 1, 10, (word8) work [5]);
308 putbits36_8 (error_str + 1, 19, (word8) work [6]);
309 putbits36_8 (error_str + 1, 28, (word8) work [7]);
310 }
311
312 static void set_error (word36 * error_str, int _errno)
313 {
314 if (errno == 0)
315 return;
316 for (uint i = 0; i < N_ERRNOS; i ++)
317 {
318 if (errnos[i].code == _errno)
319 {
320 set_error_str (error_str, errnos[i].name);
321 return;
322 }
323 }
324 char huh [256];
325 (void)sprintf (huh, "E%d", _errno);
326 huh[8] = 0;
327 set_error_str (error_str, huh);
328 }
329
330 static void skt_socket (uint unit_idx, word5 dev_code, word36 * buffer)
331 {
332
333
334
335
336
337
338
339
340 int domain = (int) buffer[0];
341 int type = (int) buffer[1];
342 int protocol = (int) buffer[2];
343
344 sim_printf ("socket() domain %d\n", domain);
345 sim_printf ("socket() type %d\n", type);
346 sim_printf ("socket() protocol %d\n", protocol);
347
348 int _errno = 0;
349 int fd = -1;
350
351 if (domain != AF_INET)
352 {
353 sim_printf ("socket() domain EAFNOSUPPORT\n");
354 _errno = EAFNOSUPPORT;
355 }
356 # if defined(__APPLE__) || defined(_AIX) || defined(__HAIKU__)
357 else if (type != SOCK_STREAM && type != (SOCK_STREAM))
358 # else
359 else if (type != SOCK_STREAM && type != (SOCK_STREAM|SOCK_NONBLOCK))
360 # endif
361 {
362 sim_printf ("socket() type EPROTOTYPE\n");
363 _errno = EPROTOTYPE;
364 }
365 else if (protocol != 0)
366 {
367 sim_printf ("socket() protocol EPROTONOSUPPORT\n");
368 _errno = EPROTONOSUPPORT;
369 }
370 else
371 {
372 fd = socket ((int) buffer[0], (int) buffer[1], (int) buffer[2]);
373 sim_printf ("socket() returned %d\n", fd);
374 if (fd < 0)
375 {
376 sim_printf ("errno %d\n", errno);
377 _errno = errno;
378 }
379 else if (fd < N_FDS)
380 {
381 sk_data.fd_unit[fd] = (int) unit_idx;
382 sk_data.fd_dev_code[fd] = dev_code;
383 # if defined(__APPLE__) || defined(_AIX) || defined(__HAIKU__)
384 sk_data.fd_nonblock[fd] = 0;
385 # else
386 sk_data.fd_nonblock[fd] = !! (type & SOCK_NONBLOCK);
387 # endif
388 }
389 else
390 {
391 close (fd);
392 fd = -1;
393 _errno = EMFILE;
394 }
395 }
396
397 buffer[3] = ((word36) ((word36s) fd)) & MASK36;
398
399 set_error (& buffer[4], _errno);
400 }
401
402 static void skt_gethostbyname (word36 * buffer)
403 {
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418 word9 cnt = getbits36_9 (buffer [0], 27);
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436 if (cnt > 256)
437 {
438 sim_warn ("socket$gethostbyname() clipping cnt from %u to 256\n", cnt);
439 cnt = 256;
440 }
441
442 unsigned char name [257];
443 for (uint i = 0; i < cnt; i ++)
444 {
445 uint wordno = (i+4) / 4;
446 uint offset = ((i+4) % 4) * 9;
447 word9 ch = getbits36_9 (buffer[wordno], offset);
448 name [i] = (unsigned char) (ch & 255);
449 }
450 name[cnt] = 0;
451
452 struct hostent * hostent = gethostbyname ((char *)name);
453 sim_printf ("gethostbyname returned %p\n", (void *) hostent);
454 if (hostent)
455 {
456 sim_printf ("addr_len %d\n", hostent->h_length);
457 sim_printf ("%hhu.%hhu.%hhu.%hhu\n",
458 hostent->h_addr_list[0][0],
459 hostent->h_addr_list[0][1],
460 hostent->h_addr_list[0][2],
461 hostent->h_addr_list[0][3]);
462
463 uint32_t addr = * ((uint32_t *) & hostent->h_addr_list[0][0]);
464 sim_printf ("addr %08x\n", addr);
465 addr = ntohl (addr);
466 sim_printf ("addr %08x\n", addr);
467 buffer[65] = ((word36) addr) << 4;
468
469
470
471
472
473 set_error (& buffer[66], 0);
474 }
475 else
476 {
477 sim_printf ("h_errno %d\n", h_errno);
478 switch (h_errno)
479 {
480 case HOST_NOT_FOUND: set_error_str (& buffer[66], "HOST_NOT_FOUND"); break;
481 case NO_DATA: set_error_str (& buffer[66], "NO_DATA"); break;
482 case NO_RECOVERY: set_error_str (& buffer[66], "NO_RECOVERY"); break;
483 case TRY_AGAIN: set_error_str (& buffer[66], "TRY_AGAIN"); break;
484 default: set_error_str (& buffer[66], "EHUH"); break;
485 }
486 }
487 }
488
489 static void skt_bind (uint unit_idx, word6 dev_code, word36 * buffer)
490 {
491
492
493
494
495
496
497
498
499
500
501
502
503
504 int socket_fd = (int) buffer[0];
505 int sin_family = (int) buffer[1];
506 unsigned short sin_port = (unsigned short) getbits36_16 (buffer [2], 0);
507 word8 octet [4] = { getbits36_8 (buffer [3], 0),
508 getbits36_8 (buffer [3], 8),
509 getbits36_8 (buffer [3], 16),
510 getbits36_8 (buffer [3], 24)};
511 uint32_t addr = (uint32_t) octet[0];
512 addr <<= 8;
513 addr |= (uint32_t) octet[1];
514 addr <<= 8;
515 addr |= (uint32_t) octet[2];
516 addr <<= 8;
517 addr |= (uint32_t) octet[3];
518
519 sim_printf ("bind() socket %d\n", socket_fd);
520 sim_printf ("bind() sin_family %d\n", sin_family);
521 sim_printf ("bind() sin_port %u\n", sin_port);
522 sim_printf ("bind() s_addr %hhu.%hhu.%hhu.%hhu\n", octet[0], octet[1], octet[2], octet[3]);
523 sim_printf ("bind() s_addr %08x\n", addr);
524
525
526
527
528
529
530 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
531 {
532 set_error (& buffer[4], EBADF);
533 return;
534 }
535
536 struct sockaddr_in serv_addr;
537 bzero ((char *) & serv_addr, sizeof(serv_addr));
538 serv_addr.sin_family = AF_INET;
539 serv_addr.sin_addr.s_addr = htonl (addr);
540 serv_addr.sin_port = htons (sin_port);
541
542 int _errno = 0;
543 int rc = bind (socket_fd, (struct sockaddr *) & serv_addr, sizeof (serv_addr));
544 sim_printf ("bind() returned %d\n", rc);
545
546 if (rc < 0)
547 {
548 sim_printf ("errno %d\n", errno);
549 _errno = errno;
550 }
551 set_error (& buffer[4], _errno);
552 }
553
554 static void skt_listen (uint unit_idx, word6 dev_code, word36 * buffer)
555 {
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570 int socket_fd = (int) buffer[0];
571 int backlog = (int) buffer[1];
572 sim_printf ("listen() socket %d\n", socket_fd);
573 sim_printf ("listen() backlog %d\n", backlog );
574
575 int rc = 0;
576 int _errno = 0;
577
578 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
579 {
580 sim_printf ("listen() socket doesn't belong to us\n");
581 sim_printf ("socket_fd %u fd_unit %d fd_dev_code %u unit_idx %u dev_code %u\n",
582 socket_fd, sk_data.fd_unit[socket_fd], sk_data.fd_dev_code[socket_fd], unit_idx, dev_code);
583 _errno = EBADF;
584 goto done;
585 }
586
587 int on = 1;
588 rc = setsockopt (socket_fd, SOL_SOCKET, SO_REUSEADDR,
589 (char *) & on, sizeof (on));
590 sim_printf ("listen() setsockopt returned %d\n", rc);
591 if (rc < 0)
592 {
593 _errno = errno;
594 goto done;
595 }
596
597 # if defined(FIONBIO)
598 rc = ioctl (socket_fd, FIONBIO, (char *) & on);
599 sim_printf ("listen() ioctl returned %d\n", rc);
600 if (rc < 0)
601 {
602 _errno = errno;
603 goto done;
604 }
605 # endif
606
607 rc = listen (socket_fd, backlog);
608 sim_printf ("listen() returned %d\n", rc);
609
610 if (rc < 0)
611 {
612 sim_printf ("errno %d\n", errno);
613 _errno = errno;
614 goto done;
615 }
616
617 done:
618 buffer[2] = ((word36) ((word36s) rc)) & MASK36;
619 set_error (& buffer[3], _errno);
620 }
621
622 static int skt_accept (uint unit_idx, word6 dev_code, word36 * buffer)
623 {
624
625
626
627
628
629
630
631
632
633
634 int socket_fd = (int) buffer[0];
635 sim_printf ("accept() socket %d\n", socket_fd);
636
637 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
638 {
639 set_error (& buffer[4], EBADF);
640 return IOM_CMD_DISCONNECT;
641 }
642
643 sk_data.unit_data[unit_idx][dev_code].accept_fd = socket_fd;
644 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_accept;
645 return IOM_CMD_DISCONNECT;
646 }
647
648 static void skt_close (uint unit_idx, word6 dev_code, word36 * buffer)
649 {
650
651
652
653
654
655
656
657
658
659
660
661
662 int socket_fd = (int) buffer[0];
663 sim_printf ("close() socket %d\n", socket_fd);
664
665 int rc = 0;
666 int _errno = 0;
667
668 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
669 {
670 sim_printf ("close() socket doesn't belong to us\n");
671 _errno = EBADF;
672 goto done;
673 }
674 sk_data.fd_unit[socket_fd] = -1;
675
676 if (sk_data.unit_data[unit_idx][dev_code].unit_state == unit_accept &&
677 sk_data.unit_data[unit_idx][dev_code].accept_fd == socket_fd)
678 {
679 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_idle;
680 sk_data.unit_data[unit_idx][dev_code].accept_fd = -1;
681 }
682 rc = close (socket_fd);
683
684 sim_printf ("close() close returned %d\n", rc);
685 if (rc < 0)
686 {
687 _errno = errno;
688 goto done;
689 }
690
691 done:
692 buffer[1] = ((word36) ((word36s) rc)) & MASK36;
693 set_error (& buffer[2], _errno);
694 }
695
696 static int skt_read8 (uint unit_idx, word6 dev_code, UNUSED uint tally, word36 * buffer)
697 {
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713 int socket_fd = (int) buffer[0];
714 uint count = (uint) buffer[1];
715 sim_printf ("read8() socket %d\n", socket_fd);
716
717
718 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
719 {
720 sim_printf ("read8() socket doesn't belong to us\n");
721 set_error (& buffer[4], EBADF);
722 return IOM_CMD_DISCONNECT;
723 }
724 sk_data.unit_data[unit_idx][dev_code].read_fd = socket_fd;
725 sk_data.unit_data[unit_idx][dev_code].read_buffer_sz = count;
726 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_read;
727 return IOM_CMD_DISCONNECT;
728 }
729
730 static int skt_write8 (uint iom_unit_idx, uint chan, uint unit_idx, word6 dev_code, uint tally, word36 * buffer)
731 {
732 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
733
734
735
736
737
738
739
740 if (tally < 5)
741 {
742 p->stati = 050012;
743 return IOM_CMD_ERROR;
744 }
745
746
747
748
749
750
751
752
753
754
755 int socket_fd = (int) buffer[0];
756 sim_printf ("write8() socket %d\n", socket_fd);
757
758 ssize_t rc = 0;
759 int _errno = 0;
760
761 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
762 {
763 sim_printf ("write8() socket doesn't belong to us\n");
764 set_error (& buffer[3], EBADF);
765 return IOM_CMD_DISCONNECT;
766 }
767
768
769
770 word36 count36 = buffer[1];
771 if (count36 > (4091 * 4))
772 {
773 p->stati = 050012;
774 return IOM_CMD_ERROR;
775 }
776 uint count = (uint) count36;
777
778 uint count_words = (count + 3) / 4;
779 if ((count_words + 5) > tally)
780 {
781 p->stati = 050012;
782 return IOM_CMD_ERROR;
783 }
784
785 uint8_t netdata [count];
786 for (uint n = 0; n < count; n ++)
787 {
788 uint wordno = (uint) n / 4;
789 uint charno = (uint) n % 4;
790 netdata[n] = getbits36_8 (buffer [5 + wordno], charno * 9 + 1);
791
792 }
793
794 rc = write (socket_fd, netdata, count);
795 if (rc == -1)
796 _errno = errno;
797
798 buffer[2] = ((word36) ((word36s) rc)) & MASK36;
799 set_error (& buffer[3], _errno);
800 return IOM_CMD_DISCONNECT;
801 }
802
803 static int get_ddcw (iom_chan_data_t * p, uint iom_unit_idx, uint chan, bool * ptro, uint expected_tally, uint * tally)
804 {
805 bool send, uff;
806 int rc = iom_list_service (iom_unit_idx, chan, ptro, & send, & uff);
807 if (rc < 0)
808 {
809 p->stati = 05001;
810 sim_warn ("%s list service failed\n", __func__);
811 return IOM_CMD_ERROR;
812 }
813 if (uff)
814 {
815 sim_warn ("%s ignoring uff\n", __func__);
816 }
817 if (! send)
818 {
819 sim_warn ("%s nothing to send\n", __func__);
820 p->stati = 05001;
821 return IOM_CMD_ERROR;
822 }
823 if (IS_IDCW (p) || IS_TDCW (p))
824 {
825 sim_warn ("%s expected DDCW\n", __func__);
826 p->stati = 05001;
827 return IOM_CMD_ERROR;
828 }
829
830 * tally = p->DDCW_TALLY;
831 if (* tally == 0)
832 {
833 sim_debug (DBG_DEBUG, & skc_dev,
834 "%s: Tally of zero interpreted as 010000(4096)\n",
835 __func__);
836 * tally = 4096;
837 }
838
839 sim_debug (DBG_DEBUG, & skc_dev,
840 "%s: Tally %d (%o)\n", __func__, * tally, * tally);
841
842 if (expected_tally && * tally && * tally != expected_tally)
843 {
844 sim_warn ("socket_dev socket call expected tally of %d; got %d\n", expected_tally, * tally);
845 p->stati = 05001;
846 return IOM_CMD_ERROR;
847 }
848 return IOM_CMD_PROCEED;
849 }
850
851 static int sk_cmd (uint iom_unit_idx, uint chan)
852 {
853 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
854
855 sim_debug (DBG_DEBUG, & skc_dev, "IDCW_DEV_CODE %d\n", p->IDCW_DEV_CODE);
856 uint unit_idx = get_ctlr_idx (iom_unit_idx, chan);
857 sim_printf ("device %u\n", p->IDCW_DEV_CODE);
858 bool ptro;
859 switch (p->IDCW_DEV_CMD)
860 {
861 case 0:
862 {
863 p->stati = 04000;
864 sim_debug (DBG_DEBUG, & skc_dev,
865 "%s: Request status: %04o\n", __func__, p->stati);
866 sim_debug (DBG_DEBUG, & skc_dev,
867 "%s: Request status control: %o\n", __func__, p->IDCW_CHAN_CTRL);
868 sim_debug (DBG_DEBUG, & skc_dev,
869 "%s: Request status channel command: %o\n", __func__, p->IDCW_CHAN_CMD);
870 }
871 break;
872
873 case 01:
874 {
875 sim_debug (DBG_DEBUG, & skc_dev,
876 "%s: socket_dev_$socket\n", __func__);
877 const uint expected_tally = 6;
878 uint tally;
879 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
880 if (rc)
881 return rc;
882
883
884
885 word36 buffer [expected_tally];
886 uint words_processed;
887 iom_indirect_data_service (iom_unit_idx, chan, buffer,
888 & words_processed, false);
889
890 skt_socket (unit_idx, p->IDCW_DEV_CODE, buffer);
891
892 iom_indirect_data_service (iom_unit_idx, chan, buffer,
893 & words_processed, true);
894 }
895 break;
896
897 case 02:
898 {
899 sim_debug (DBG_DEBUG, & skc_dev,
900 "%s: socket_dev_$bind\n", __func__);
901
902 const uint expected_tally = 6;
903 uint tally;
904 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
905 if (rc)
906 return rc;
907
908
909
910 word36 buffer [expected_tally];
911 uint words_processed;
912 iom_indirect_data_service (iom_unit_idx, chan, buffer,
913 & words_processed, false);
914
915 skt_bind (unit_idx, p->IDCW_DEV_CODE, buffer);
916
917 iom_indirect_data_service (iom_unit_idx, chan, buffer,
918 & words_processed, true);
919
920 }
921 break;
922
923 case 03:
924 {
925 sim_printf ("socket_dev received command 3\r\n");
926 p->stati = 04000;
927 }
928 break;
929
930 case 04:
931 {
932 sim_debug (DBG_DEBUG, & skc_dev,
933 "%s: socket_dev_$gethostbyname\n", __func__);
934
935 const uint expected_tally = 68;
936 uint tally;
937 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
938 if (rc)
939 return rc;
940
941
942
943 word36 buffer [expected_tally];
944 uint words_processed;
945 iom_indirect_data_service (iom_unit_idx, chan, buffer,
946 & words_processed, false);
947
948 skt_gethostbyname (buffer);
949
950 iom_indirect_data_service (iom_unit_idx, chan, buffer,
951 & words_processed, true);
952
953 }
954 break;
955
956 case 05:
957 {
958 sim_debug (DBG_DEBUG, & skc_dev,
959 "%s: socket_dev_$listen\n", __func__);
960
961 const uint expected_tally = 5;
962 uint tally;
963 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
964 if (rc)
965 return rc;
966
967
968
969 word36 buffer [expected_tally];
970 uint words_processed;
971 iom_indirect_data_service (iom_unit_idx, chan, buffer,
972 & words_processed, false);
973
974 skt_listen (unit_idx, p->IDCW_DEV_CODE, buffer);
975
976 iom_indirect_data_service (iom_unit_idx, chan, buffer,
977 & words_processed, true);
978
979 }
980 break;
981
982 case 06:
983 {
984 sim_debug (DBG_DEBUG, & skc_dev,
985 "%s: socket_dev_$accept\n", __func__);
986
987 const uint expected_tally = 7;
988 uint tally;
989 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
990 if (rc)
991 return rc;
992
993
994
995 word36 buffer [expected_tally];
996 uint words_processed;
997 iom_indirect_data_service (iom_unit_idx, chan, buffer,
998 & words_processed, false);
999 sk_data.unit_data[unit_idx][p->IDCW_DEV_CODE].words_processed = words_processed;
1000
1001 rc = skt_accept (unit_idx, p->IDCW_DEV_CODE, buffer);
1002
1003 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1004 & words_processed, true);
1005
1006 return rc;
1007
1008 }
1009
1010 break;
1011
1012 case 07:
1013 {
1014 sim_debug (DBG_DEBUG, & skc_dev,
1015 "%s: socket_dev_$close\n", __func__);
1016
1017 const uint expected_tally = 4;
1018 uint tally;
1019 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
1020 if (rc)
1021 return rc;
1022
1023
1024
1025 word36 buffer [expected_tally];
1026 uint words_processed;
1027 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1028 & words_processed, false);
1029
1030 skt_close (unit_idx, p->IDCW_DEV_CODE, buffer);
1031
1032 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1033 & words_processed, true);
1034 }
1035 break;
1036
1037 case 8:
1038 {
1039 sim_debug (DBG_DEBUG, & skc_dev,
1040 "%s: socket_dev_$read8\n", __func__);
1041
1042 const uint expected_tally = 0;
1043 uint tally;
1044 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
1045 if (rc)
1046 return rc;
1047
1048
1049
1050 word36 buffer[4096];
1051 uint words_processed;
1052 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1053 & words_processed, false);
1054 sk_data.unit_data[unit_idx][p->IDCW_DEV_CODE].words_processed = words_processed;
1055
1056 rc = skt_read8 (unit_idx, p->IDCW_DEV_CODE, tally, buffer);
1057
1058 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1059 & words_processed, true);
1060 return rc;
1061
1062 }
1063
1064 break;
1065
1066 case 9:
1067 {
1068 sim_debug (DBG_DEBUG, & skc_dev,
1069 "%s: socket_dev_$write8\n", __func__);
1070
1071 const uint expected_tally = 0;
1072 uint tally;
1073 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
1074 if (rc)
1075 return rc;
1076
1077
1078
1079 word36 buffer[4096];
1080 uint words_processed;
1081 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1082 & words_processed, false);
1083
1084 rc = skt_write8 (iom_unit_idx, chan, unit_idx, p->IDCW_DEV_CODE, tally, buffer);
1085
1086 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1087 & words_processed, true);
1088 return rc;
1089 }
1090
1091 break;
1092
1093 case 040:
1094 {
1095 p->stati = 04000;
1096 sim_debug (DBG_DEBUG, & skc_dev,
1097 "%s: Reset status is %04o.\n",
1098 __func__, p->stati);
1099 return IOM_CMD_PROCEED;
1100 }
1101
1102 default:
1103 {
1104 p->stati = 04501;
1105 p->chanStatus = chanStatIncorrectDCW;
1106 if (p->IDCW_DEV_CMD != 051)
1107 sim_warn ("%s: Unknown command 0%o\n", __func__, p->IDCW_DEV_CMD);
1108 }
1109 return IOM_CMD_ERROR;
1110
1111 }
1112
1113 sim_debug (DBG_DEBUG, & skc_dev, "stati %04o\n", p->stati);
1114
1115
1116
1117
1118
1119
1120
1121 return IOM_CMD_DISCONNECT;
1122 }
1123
1124 iom_cmd_rc_t skc_iom_cmd (uint iom_unit_idx, uint chan)
1125 {
1126 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx] [chan];
1127
1128
1129 int rc = 0;
1130 if (IS_IDCW (p))
1131 {
1132 rc = sk_cmd (iom_unit_idx, chan);
1133 }
1134 else
1135 {
1136 sim_warn ("%s expected IDCW\n", __func__);
1137 return IOM_CMD_ERROR;
1138 }
1139 return rc;
1140 }
1141
1142 static void do_try_accept (uint unit_idx, word6 dev_code)
1143 {
1144 struct sockaddr_in from = { .sin_family = AF_INET };
1145 socklen_t size = sizeof (from);
1146 int _errno = 0;
1147 int fd = accept (sk_data.unit_data[unit_idx][dev_code].accept_fd, (struct sockaddr *) & from, & size);
1148 if (fd == -1)
1149 {
1150 if (errno == EAGAIN || errno == EWOULDBLOCK)
1151 return;
1152 _errno = errno;
1153 }
1154 else if (fd < N_FDS)
1155 {
1156 sk_data.fd_unit[fd] = (int) unit_idx;
1157 sk_data.fd_dev_code[fd] = dev_code;
1158 sk_data.fd_nonblock[fd] = false ;
1159 }
1160 else
1161 {
1162 close (fd);
1163 fd = -1;
1164 _errno = EMFILE;
1165 }
1166 word36 buffer [7];
1167
1168 buffer[0] = ((word36) ((word36s) sk_data.unit_data[unit_idx][dev_code].accept_fd)) & MASK36;
1169 buffer[1] = ((word36) ((word36s) fd)) & MASK36;
1170 buffer[2] = ((word36) ((word36s) from.sin_family)) & MASK36;
1171 uint16_t port = ntohs (from.sin_port);
1172 putbits36_16 (& buffer[3], 0, port);
1173 uint32_t addr = ntohl (from.sin_addr.s_addr);
1174 buffer[4] = ((word36) addr) << 4;
1175 set_error (& buffer[5], _errno);
1176
1177
1178 uint iom_unit_idx = (uint) cables->sk_to_iom[unit_idx][0].iom_unit_idx;
1179 uint chan = (uint) cables->sk_to_iom[unit_idx][0].chan_num;
1180 uint words_processed = sk_data.unit_data[unit_idx][dev_code].words_processed;
1181 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1182 & words_processed, true);
1183 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1184 p->stati = 04000;
1185 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_idle;
1186 send_terminate_interrupt (iom_unit_idx, chan);
1187 }
1188
1189 static void do_try_read (uint unit_idx, word6 dev_code)
1190 {
1191 int _errno = 0;
1192 uint count = sk_data.unit_data[unit_idx][dev_code].read_buffer_sz;
1193 uint buffer_size_wds = (count + 3) / 4;
1194 word36 buffer [buffer_size_wds];
1195
1196 (void)memset (buffer, 0, sizeof (word36) * buffer_size_wds);
1197 uint8_t netdata [count];
1198 ssize_t nread = read (sk_data.unit_data[unit_idx][dev_code].read_fd, & netdata, count);
1199 if (nread == -1)
1200 {
1201 if (errno == EAGAIN || errno == EWOULDBLOCK)
1202 return;
1203 _errno = errno;
1204 nread = 0;
1205 }
1206
1207
1208 buffer[0] = ((word36) ((word36s) sk_data.unit_data[unit_idx][dev_code].read_fd)) & MASK36;
1209 buffer[1] = ((word36) (sk_data.unit_data[unit_idx][dev_code].read_buffer_sz)) & MASK36;
1210 buffer[2] = ((word36) ((word36s) nread)) & MASK36;
1211 set_error (& buffer[3], _errno);
1212
1213 for (ssize_t n = 0; n < nread; n ++)
1214 {
1215 uint wordno = (uint) n / 4;
1216 uint charno = (uint) n % 4;
1217 putbits36_9 (& buffer [5 + wordno], charno * 9, (word9) netdata [n]);
1218 }
1219
1220
1221
1222 uint iom_unit_idx = (uint) cables->sk_to_iom[unit_idx][0].iom_unit_idx;
1223 uint chan = (uint) cables->sk_to_iom[unit_idx][0].chan_num;
1224 uint words_processed = sk_data.unit_data[unit_idx][dev_code].words_processed;
1225 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1226 & words_processed, true);
1227 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_idle;
1228 send_terminate_interrupt (iom_unit_idx, chan);
1229 }
1230
1231 void sk_process_event (void)
1232 {
1233
1234 for (uint unit_idx = 0; unit_idx < N_SKC_UNITS_MAX; unit_idx ++)
1235 {
1236 for (word6 dev_code = 0; dev_code < N_DEV_CODES; dev_code ++)
1237 {
1238 if (sk_data.unit_data[unit_idx][dev_code].unit_state == unit_accept)
1239 {
1240 do_try_accept (unit_idx, dev_code);
1241 }
1242 else if (sk_data.unit_data[unit_idx][dev_code].unit_state == unit_read)
1243 {
1244 do_try_read (unit_idx, dev_code);
1245 }
1246 }
1247 }
1248 }
1249 #endif