1 /* SHARED.C (c) Copyright Greg Smith, 2002-2009 */
2 /* Shared Device Server */
3
4 #include "hstdinc.h"
5
6 #define _HERCULES_SHARED_C
7 #define _SHARED_C_
8 #define _HDASD_DLL_
9 #include "hercules.h"
10 #include "opcode.h"
11 #include "devtype.h"
12
13 #define FBA_BLKGRP_SIZE (120*512)
14
15 /* Change the following to "define" when Shared FBA support is implemented */
16 #undef FBA_SHARED
17
18 /*-------------------------------------------------------------------*/
19 /* Definitions for sense data format codes and message codes */
20 /*-------------------------------------------------------------------*/
21 #define FORMAT_0 0 /* Program or System Checks */
22 #define FORMAT_1 1 /* Device Equipment Checks */
23 #define FORMAT_2 2 /* 3990 Equipment Checks */
24 #define FORMAT_3 3 /* 3990 Control Checks */
25 #define FORMAT_4 4 /* Data Checks */
26 #define FORMAT_5 5 /* Data Check + Displacement */
27 #define FORMAT_6 6 /* Usage Stats/Overrun Errors*/
28 #define FORMAT_7 7 /* Device Control Checks */
29 #define FORMAT_8 8 /* Device Equipment Checks */
30 #define FORMAT_9 9 /* Device Rd/Wrt/Seek Checks */
31 #define FORMAT_F 15 /* Cache Storage Checks */
32 #define MESSAGE_0 0 /* Message 0 */
33 #define MESSAGE_1 1 /* Message 1 */
34 #define MESSAGE_2 2 /* Message 2 */
35 #define MESSAGE_3 3 /* Message 3 */
36 #define MESSAGE_4 4 /* Message 4 */
37 #define MESSAGE_5 5 /* Message 5 */
38 #define MESSAGE_6 6 /* Message 6 */
39 #define MESSAGE_7 7 /* Message 7 */
40 #define MESSAGE_8 8 /* Message 8 */
41 #define MESSAGE_9 9 /* Message 9 */
42 #define MESSAGE_A 10 /* Message A */
43 #define MESSAGE_B 11 /* Message B */
44 #define MESSAGE_C 12 /* Message C */
45 #define MESSAGE_D 13 /* Message D */
46 #define MESSAGE_E 14 /* Message E */
47 #define MESSAGE_F 15 /* Message F */
48
49 #if defined(OPTION_SHARED_DEVICES)
50
51 DEVHND shared_ckd_device_hndinfo;
52 DEVHND shared_fba_device_hndinfo;
53
54 static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
55
56 /*-------------------------------------------------------------------
57 * Update notify - called by device handlers for sharable devices
58 *-------------------------------------------------------------------*/
shared_update_notify(DEVBLK * dev,int block)59 int shared_update_notify (DEVBLK *dev, int block)
60 {
61 int i, j; /* Indexes */
62
63 /* Return if no remotes are connected */
64 if (dev->shrdconn == 0)
65 return 0;
66
67 for (i = 0; i < SHARED_MAX_SYS; i++)
68 {
69
70 /* Ignore the entry if it doesn't exist or if it's ours
71 our if it's already maxed out */
72 if (dev->shrd[i] == NULL || dev->shrd[i]->id == dev->ioactive
73 || dev->shrd[i]->purgen < 0)
74 continue;
75
76 /* Check if the block is already entered */
77 for (j = 0; j < dev->shrd[i]->purgen; j++)
78 if (fetch_fw(dev->shrd[i]->purge[j]) == (U32)block) break;
79
80 /* Add the block if it's not already there */
81 if (j >= dev->shrd[i]->purgen)
82 {
83 if (dev->shrd[i]->purgen >= SHARED_PURGE_MAX)
84 dev->shrd[i]->purgen = -1;
85 else
86 store_fw (dev->shrd[i]->purge[dev->shrd[i]->purgen++],
87 block);
88 shrdtrc(dev,"notify %d added for id=%d, n=%d\n",
89 block, dev->shrd[i]->id, dev->shrd[i]->purgen);
90 }
91
92 } /* for each possible remote system */
93
94 return 0;
95
96 } /* shared_update_notify */
97
98
99 /*-------------------------------------------------------------------
100 * CKD init exit (client side)
101 *-------------------------------------------------------------------*/
shared_ckd_init(DEVBLK * dev,int argc,char * argv[])102 int shared_ckd_init (DEVBLK *dev, int argc, char *argv[] )
103 {
104 int rc; /* Return code */
105 int i; /* Loop index */
106 int retry; /* 1=Connection being retried*/
107 char *ipname; /* Remote name or address */
108 char *port = NULL; /* Remote port */
109 char *rmtnum = NULL; /* Remote device number */
110 struct hostent *he; /* -> hostent structure */
111 char *kw; /* Argument keyword */
112 char *op; /* Argument operand */
113 BYTE c; /* Used for parsing */
114 char *cu = NULL; /* Specified control unit */
115 FWORD cyls; /* Remote number cylinders */
116 char *p, buf[1024]; /* Work buffer */
117
118 retry = dev->connecting;
119
120 /* Process the arguments */
121 if (!retry)
122 {
123 if (argc < 1 || strlen(argv[0]) >= sizeof(buf))
124 return -1;
125 strcpy (buf, argv[0]);
126
127 /* First argument is `ipname:port:devnum' */
128 ipname = buf;
129 if (strchr(ipname,'/') || strchr(ipname,'\\'))
130 return -1;
131 p = strchr (buf, ':');
132 if (p)
133 {
134 *p = '\0';
135 port = p + 1;
136 p = strchr (port, ':');
137 }
138 if (p)
139 {
140 *p = '\0';
141 rmtnum = p + 1;
142 }
143
144 #if defined( HAVE_SYS_UN_H )
145 if ( strcmp (ipname, "localhost") == 0)
146 dev->localhost = 1;
147 else
148 #endif
149 {
150 if ( (he = gethostbyname (ipname)) == NULL )
151 return -1;
152 memcpy(&dev->rmtaddr, he->h_addr_list[0], sizeof(dev->rmtaddr));
153 }
154
155 if (port && strlen(port))
156 {
157 if (sscanf(port, "%hu%c", &dev->rmtport, &c) != 1)
158 return -1;
159 }
160 else
161 dev->rmtport = SHARED_DEFAULT_PORT;
162
163 if (rmtnum && strlen(rmtnum))
164 {
165 if (strlen (rmtnum) > 4
166 || sscanf (rmtnum, "%hx%c", &dev->rmtnum, &c) != 1)
167 return -1;
168 }
169 else
170 dev->rmtnum = dev->devnum;
171
172 /* Process the remaining arguments */
173 for (i = 1; i < argc; i++)
174 {
175 if (strcasecmp ("readonly", argv[i]) == 0 ||
176 strcasecmp ("rdonly", argv[i]) == 0 ||
177 strcasecmp ("ro", argv[i]) == 0)
178 {
179 dev->ckdrdonly = 1;
180 continue;
181 }
182 if (strcasecmp ("fakewrite", argv[i]) == 0 ||
183 strcasecmp ("fakewrt", argv[i]) == 0 ||
184 strcasecmp ("fw", argv[i]) == 0)
185 {
186 dev->ckdfakewr = 1;
187 continue;
188 }
189 if (strlen (argv[i]) > 3
190 && memcmp("cu=", argv[i], 3) == 0)
191 {
192 kw = strtok (argv[i], "=");
193 op = strtok (NULL, " \t");
194 cu = op;
195 continue;
196 }
197 #ifdef HAVE_LIBZ
198 if (strlen (argv[i]) > 5
199 && memcmp("comp=", argv[i], 5) == 0)
200 {
201 kw = strtok (argv[i], "=");
202 op = strtok (NULL, " \t");
203 dev->rmtcomp = atoi (op);
204 if (dev->rmtcomp < 0 || dev->rmtcomp > 9)
205 dev->rmtcomp = 0;
206 continue;
207 }
208 #endif
209 logmsg (_("HHCSH001S parameter %d is invalid: %s\n"),
210 i + 1, argv[i]);
211 return -1;
212 }
213 }
214
215 /* Set suported compression */
216 dev->rmtcomps = 0;
217 #ifdef HAVE_LIBZ
218 dev->rmtcomps |= SHRD_LIBZ;
219 #endif
220 #ifdef CCKD_BZIP2
221 dev->rmtcomps |= SHRD_BZIP2;
222 #endif
223
224 /* Update the device handler vector */
225 dev->hnd = &shared_ckd_device_hndinfo;
226
227 dev->connecting = 1;
228
229 init_retry:
230
231 do {
232 rc = clientConnect (dev, retry);
233 if (rc < 0)
234 {
235 logmsg (_("HHCSH002W %4.4X connect pending to %s\n"),
236 dev->devnum, dev->filename);
237 if (retry) SLEEP(5);
238 }
239 } while (retry && rc < 0);
240
241 /* Return if unable to connect */
242 if (rc < 0) return 0;
243
244 dev->ckdnumfd = 1;
245 dev->ckdfd[0] = dev->fd;
246
247 /* Get the number of cylinders */
248 rc = clientRequest (dev, cyls, 4, SHRD_QUERY, SHRD_CKDCYLS, NULL, NULL);
249 if (rc < 0)
250 goto init_retry;
251 else if (rc != 4)
252 {
253 logmsg (_("HHCSH003S %4.4X Error retrieving cylinders\n"),
254 dev->devnum);
255 return -1;
256 }
257 dev->ckdcyls = fetch_fw (cyls);
258
259 /* Get the device characteristics */
260 rc = clientRequest (dev, dev->devchar, sizeof(dev->devchar),
261 SHRD_QUERY, SHRD_DEVCHAR, NULL, NULL);
262 if (rc < 0)
263 goto init_retry;
264 else if (rc == 0 || rc > (int)sizeof(dev->devchar))
265 {
266 logmsg (_("HHCSH004S %4.4X Error retrieving device"
267 " characteristics\n"), dev->devnum);
268 return -1;
269 }
270 dev->numdevchar = rc;
271
272 /* Get number of heads from devchar */
273 dev->ckdheads = fetch_hw (dev->devchar + 14);
274
275 /* Calculate number of tracks */
276 dev->ckdtrks = dev->ckdcyls * dev->ckdheads;
277 dev->ckdhitrk[0] = dev->ckdtrks;
278
279 /* Check the device type */
280 if (dev->devtype == 0)
281 dev->devtype = fetch_hw (dev->devchar + 3);
282 else if (dev->devtype != fetch_hw (dev->devchar + 3))
283 {
284 logmsg (_("HHCSH005S %4.4X Remote device %4.4X is a %4.4X\n"),
285 dev->devnum, dev->rmtnum, fetch_hw (dev->devchar + 3));
286 return -1;
287 }
288
289 /* Get the device id */
290 rc = clientRequest (dev, dev->devid, sizeof(dev->devid),
291 SHRD_QUERY, SHRD_DEVID, NULL, NULL);
292 if (rc < 0)
293 goto init_retry;
294 else if (rc == 0 || rc > (int)sizeof(dev->devid))
295 {
296 logmsg (_("HHCSH006S %4.4X Error retrieving device id\n"),
297 dev->devnum);
298 return -1;
299 }
300 dev->numdevid = rc;
301
302 /* Indicate no active track */
303 dev->cache = dev->bufcur = -1;
304 dev->buf = NULL;
305
306 /* Set number of sense bytes */
307 dev->numsense = 32;
308
309 /* Locate the CKD dasd table entry */
310 dev->ckdtab = dasd_lookup (DASD_CKDDEV, NULL, dev->devtype, dev->ckdcyls);
311 if (dev->ckdtab == NULL)
312 {
313 logmsg (_("HHCSH007S %4.4X device type %4.4X not found in dasd table\n"),
314 dev->devnum, dev->devtype);
315 return -1;
316 }
317
318 /* Set the track size */
319 dev->ckdtrksz = (dev->ckdtab->r1 + 511) & ~511;
320
321 /* Locate the CKD control unit dasd table entry */
322 dev->ckdcu = dasd_lookup (DASD_CKDCU, cu ? cu : dev->ckdtab->cu, 0, 0);
323 if (dev->ckdcu == NULL)
324 {
325 logmsg (_("HHCSH008S %4.4X control unit %s not found in dasd table\n"),
326 dev->devnum, cu ? cu : dev->ckdtab->cu);
327 return -1;
328 }
329
330 /* Set flag bit if 3990 controller */
331 if (dev->ckdcu->devt == 0x3990)
332 dev->ckd3990 = 1;
333
334 /* Clear the DPA */
335 memset(dev->pgid, 0, sizeof(dev->pgid));
336
337 /* Request the channel to merge data chained write CCWs into
338 a single buffer before passing data to the device handler */
339 dev->cdwmerge = 1;
340
341 /* Purge the cache */
342 clientPurge (dev, 0, NULL);
343
344 /* Log the device geometry */
345 if (!dev->batch)
346 logmsg (_("HHCSH009I %s cyls=%d heads=%d tracks=%d trklen=%d\n"),
347 dev->filename, dev->ckdcyls,
348 dev->ckdheads, dev->ckdtrks, dev->ckdtrksz);
349
350 dev->connecting = 0;
351
352 return 0;
353 } /* shared_ckd_init */
354
355 /*-------------------------------------------------------------------
356 * CKD close exit (client side)
357 *-------------------------------------------------------------------*/
shared_ckd_close(DEVBLK * dev)358 static int shared_ckd_close ( DEVBLK *dev )
359 {
360 /* Purge the cached entries */
361 clientPurge (dev, 0, NULL);
362
363 /* Disconnect and close */
364 if (dev->fd >= 0)
365 {
366 clientRequest (dev, NULL, 0, SHRD_DISCONNECT, 0, NULL, NULL);
367 close_socket (dev->fd);
368 dev->fd = -1;
369 }
370
371 return 0;
372 } /* shared_ckd_close */
373
374 /*-------------------------------------------------------------------
375 * FBA init exit (client side)
376 *-------------------------------------------------------------------*/
shared_fba_init(DEVBLK * dev,int argc,char * argv[])377 int shared_fba_init (DEVBLK *dev, int argc, char *argv[] )
378 {
379 int rc; /* Return code */
380 int i; /* Loop index */
381 int retry; /* 1=Connection being retried*/
382 char *ipname; /* Remote name or address */
383 char *port = NULL; /* Remote port */
384 char *rmtnum = NULL; /* Remote device number */
385 struct hostent *he; /* -> hostent structure */
386 char *kw; /* Argument keyword */
387 char *op; /* Argument operand */
388 char c; /* Work for sscanf */
389 FWORD origin; /* FBA origin */
390 FWORD numblks; /* FBA number blocks */
391 FWORD blksiz; /* FBA block size */
392 char *p, buf[1024]; /* Work buffer */
393
394 retry = dev->connecting;
395
396 /* Process the arguments */
397 if (!retry)
398 {
399
400 kw = op = NULL;
401
402 if (argc < 1 || strlen(argv[0]) >= sizeof(buf))
403 return -1;
404 strcpy (buf, argv[0]);
405
406 /* First argument is `ipname:port:devnum' */
407 ipname = buf;
408 p = strchr (buf, ':');
409 if (p)
410 {
411 *p = '\0';
412 port = p + 1;
413 p = strchr (port, ':');
414 }
415 if (p)
416 {
417 *p = '\0';
418 rmtnum = p + 1;
419 }
420
421 if ( (he = gethostbyname (ipname)) == NULL )
422 return -1;
423 memcpy(&dev->rmtaddr, he->h_addr_list[0], sizeof(dev->rmtaddr));
424
425 if (port)
426 {
427 if (sscanf(port, "%hu%c", &dev->rmtport, &c) != 1)
428 return -1;
429 }
430 else
431 dev->rmtport = SHARED_DEFAULT_PORT;
432
433 if (rmtnum)
434 {
435 if (strlen (rmtnum) > 4
436 || sscanf (rmtnum, "%hx%c", &dev->rmtnum, &c) != 0)
437 return -1;
438 }
439 else
440 dev->rmtnum = dev->devnum;
441
442 /* Process the remaining arguments */
443 for (i = 1; i < argc; i++)
444 {
445 #ifdef HAVE_LIBZ
446 if (strlen (argv[i]) > 5
447 && memcmp("comp=", argv[i], 5) == 0)
448 {
449 kw = strtok (argv[i], "=");
450 op = strtok (NULL, " \t");
451 dev->rmtcomp = atoi (op);
452 if (dev->rmtcomp < 0 || dev->rmtcomp > 9)
453 dev->rmtcomp = 0;
454 continue;
455 }
456 #endif
457 logmsg (_("HHCSH010S parameter %d is invalid: %s\n"),
458 i + 1, argv[i]);
459 return -1;
460 }
461 }
462
463 /* Set suported compression */
464 dev->rmtcomps = 0;
465 #ifdef HAVE_LIBZ
466 dev->rmtcomps |= SHRD_LIBZ;
467 #endif
468 #ifdef CCKD_BZIP2
469 dev->rmtcomps |= SHRD_BZIP2;
470 #endif
471
472 /* Update the device handler vector */
473 dev->hnd = &shared_fba_device_hndinfo;
474
475 dev->connecting = 1;
476
477 init_retry:
478
479 do {
480 rc = clientConnect (dev, retry);
481 if (rc < 0)
482 {
483 logmsg (_("HHCSH011I %4.4X connect pending to %s\n"),
484 dev->devnum, dev->filename);
485 if (retry) SLEEP(5);
486 }
487 } while (retry && rc < 0);
488
489 /* Return if unable to connect */
490 if (rc < 0) return 0;
491
492 /* Get the fba origin */
493 rc = clientRequest (dev, origin, 4, SHRD_QUERY, SHRD_FBAORIGIN, NULL, NULL);
494 if (rc < 0)
495 goto init_retry;
496 else if (rc != 4)
497 {
498 logmsg (_("HHCSH012S %4.4X Error retrieving fba origin\n"),
499 dev->devnum);
500 return -1;
501 }
502 dev->fbaorigin = fetch_fw (origin);
503
504 /* Get the number of blocks */
505 rc = clientRequest (dev, numblks, 4, SHRD_QUERY, SHRD_FBANUMBLK, NULL, NULL);
506 if (rc < 0)
507 goto init_retry;
508 else if (rc != 4)
509 {
510 logmsg (_("HHCSH013S %4.4X Error retrieving fba number blocks\n"),
511 dev->devnum);
512 return -1;
513 }
514 dev->fbanumblk = fetch_fw (numblks);
515
516 /* Get the block size */
517 rc = clientRequest (dev, blksiz, 4, SHRD_QUERY, SHRD_FBABLKSIZ, NULL, NULL);
518 if (rc < 0)
519 goto init_retry;
520 else if (rc != 4)
521 {
522 logmsg (_("HHCSH014S %4.4X Error retrieving fba block size\n"),
523 dev->devnum);
524 return -1;
525 }
526 dev->fbablksiz = fetch_fw (blksiz);
527 dev->fbaend = (dev->fbaorigin + dev->fbanumblk) * dev->fbablksiz;
528
529 /* Get the device id */
530 rc = clientRequest (dev, dev->devid, sizeof(dev->devid),
531 SHRD_QUERY, SHRD_DEVID, NULL, NULL);
532 if (rc < 0)
533 goto init_retry;
534 else if (rc == 0 || rc > (int)sizeof(dev->devid))
535 {
536 logmsg (_("HHCSH015S %4.4X Error retrieving device id\n"),
537 dev->devnum);
538 return -1;
539 }
540 dev->numdevid = rc;
541
542 /* Check the device type */
543 if (dev->devtype != fetch_hw (dev->devid + 4))
544 {
545 logmsg (_("HHCSH016S %4.4X Remote device %4.4X is a %4.4X\n"),
546 dev->devnum, dev->rmtnum, fetch_hw (dev->devid + 4));
547 return -1;
548 }
549
550 /* Get the device characteristics */
551 rc = clientRequest (dev, dev->devchar, sizeof(dev->devchar),
552 SHRD_QUERY, SHRD_DEVCHAR, NULL, NULL);
553 if (rc < 0)
554 goto init_retry;
555 else if (rc == 0 || rc > (int)sizeof(dev->devchar))
556 {
557 logmsg (_("HHCSH017S %4.4X Error retrieving device"
558 " characteristics\n"), dev->devnum);
559 return -1;
560 }
561 dev->numdevchar = rc;
562
563 /* Indicate no active track */
564 dev->cache = dev->bufcur = -1;
565 dev->buf = NULL;
566
567 /* Set number of sense bytes */
568 dev->numsense = 32;
569
570 /* Locate the FBA dasd table entry */
571 dev->fbatab = dasd_lookup (DASD_FBADEV, NULL, dev->devtype, dev->fbanumblk);
572 if (dev->fbatab == NULL)
573 {
574 logmsg (_("HHCSH018S %4.4X device type %4.4X not found in dasd table\n"),
575 dev->devnum, dev->devtype);
576 return -1;
577 }
578
579 /* Purge the cache */
580 clientPurge (dev, 0, NULL);
581
582 /* Log the device geometry */
583 logmsg (_("HHCSH019I %s origin=%d blks=%d\n"),
584 dev->filename, dev->fbaorigin, dev->fbanumblk);
585
586 dev->connecting = 0;
587
588 return 0;
589 }
590
591 /*-------------------------------------------------------------------
592 * FBA close exit (client side)
593 *-------------------------------------------------------------------*/
shared_fba_close(DEVBLK * dev)594 static int shared_fba_close (DEVBLK *dev)
595 {
596 /* Purge the cached entries */
597 clientPurge (dev, 0, NULL);
598
599 /* Disconnect and close */
600 if (dev->fd >= 0)
601 {
602 clientRequest (dev, NULL, 0, SHRD_DISCONNECT, 0, NULL, NULL);
603 close_socket (dev->fd);
604 dev->fd = -1;
605 }
606
607 return 0;
608 }
609
610 /*-------------------------------------------------------------------
611 * Start I/O exit (client side)
612 *-------------------------------------------------------------------*/
shared_start(DEVBLK * dev)613 static void shared_start(DEVBLK *dev)
614 {
615 int rc; /* Return code */
616 U16 devnum; /* Cache device number */
617 int trk; /* Cache track number */
618 int code; /* Response code */
619 BYTE buf[SHARED_PURGE_MAX * 4]; /* Purge list */
620
621 shrdtrc(dev,"start cur %d cache %d\n",dev->bufcur,dev->cache);
622
623 /* Send the START request */
624 rc = clientRequest (dev, buf, sizeof(buf),
625 SHRD_START, 0, &code, NULL);
626 if (rc < 0)
627 {
628 logmsg(_("HHCSH020E %4.4X error during channel program start\n"),
629 dev->devnum);
630 clientPurge (dev, 0, NULL);
631 dev->cache = dev->bufcur = -1;
632 dev->buf = NULL;
633 return;
634 }
635
636 /* Check for purge */
637 if (code & SHRD_PURGE)
638 {
639 if (rc / 4 > SHARED_PURGE_MAX) rc = 0;
640 clientPurge (dev, rc / 4, buf);
641 }
642
643 /* Make previous active entry active again */
644 if (dev->cache >= 0)
645 {
646 cache_lock (CACHE_DEVBUF);
647 SHRD_CACHE_GETKEY (dev->cache, devnum, trk);
648 if (dev->devnum == devnum && dev->bufcur == trk)
649 cache_setflag(CACHE_DEVBUF, dev->cache, ~0, SHRD_CACHE_ACTIVE);
650 else
651 {
652 dev->cache = dev->bufcur = -1;
653 dev->buf = NULL;
654 }
655 cache_unlock (CACHE_DEVBUF);
656 }
657 } /* shared_start */
658
659 /*-------------------------------------------------------------------
660 * End I/O exit (client side)
661 *-------------------------------------------------------------------*/
shared_end(DEVBLK * dev)662 static void shared_end (DEVBLK *dev)
663 {
664 int rc; /* Return code */
665
666 shrdtrc(dev,"end cur %d cache %d\n",dev->bufcur,dev->cache);
667
668 /* Write the previous active entry if it was updated */
669 if (dev->bufupd)
670 clientWrite (dev, dev->bufcur);
671 dev->bufupd = 0;
672
673 /* Mark the active entry inactive */
674 if (dev->cache >= 0)
675 {
676 cache_lock (CACHE_DEVBUF);
677 cache_setflag (CACHE_DEVBUF, dev->cache, ~SHRD_CACHE_ACTIVE, 0);
678 cache_unlock (CACHE_DEVBUF);
679 }
680
681 /* Send the END request */
682 rc = clientRequest (dev, NULL, 0, SHRD_END, 0, NULL, NULL);
683 if (rc < 0)
684 {
685 logmsg(_("HHCSH021E %4.4X error during channel program end\n"),
686 dev->devnum);
687 clientPurge (dev, 0, NULL);
688 dev->cache = dev->bufcur = -1;
689 dev->buf = NULL;
690 return;
691 }
692 } /* shared_end */
693
694 /*-------------------------------------------------------------------
695 * Shared ckd read track exit (client side)
696 *-------------------------------------------------------------------*/
shared_ckd_read(DEVBLK * dev,int trk,BYTE * unitstat)697 static int shared_ckd_read (DEVBLK *dev, int trk, BYTE *unitstat)
698 {
699 int rc; /* Return code */
700 int retries = 10; /* Number read retries */
701 int cache; /* Lookup index */
702 int lru; /* Available index */
703 int len; /* Response length */
704 int id; /* Response id */
705 BYTE *buf; /* Cache buffer */
706 BYTE code; /* Response code */
707 U16 devnum; /* Response device number */
708 BYTE hdr[SHRD_HDR_SIZE + 4]; /* Read request header */
709
710 /* Initialize the unit status */
711 *unitstat = 0;
712
713 /* Return if reading the same track image */
714 if (trk == dev->bufcur && dev->cache >= 0)
715 {
716 dev->bufoff = 0;
717 dev->bufoffhi = dev->ckdtrksz;
718 return 0;
719 }
720
721 shrdtrc(dev,"ckd_read trk %d\n",trk);
722
723 /* Write the previous active entry if it was updated */
724 if (dev->bufupd)
725 clientWrite (dev, dev->bufcur);
726 dev->bufupd = 0;
727
728 /* Reset buffer offsets */
729 dev->bufoff = 0;
730 dev->bufoffhi = dev->ckdtrksz;
731
732 cache_lock (CACHE_DEVBUF);
733
734 /* Inactivate the previous image */
735 if (dev->cache >= 0)
736 cache_setflag (CACHE_DEVBUF, dev->cache, ~SHRD_CACHE_ACTIVE, 0);
737 dev->cache = dev->bufcur = -1;
738
739 cache_retry:
740
741 /* Lookup the track in the cache */
742 cache = cache_lookup (CACHE_DEVBUF, SHRD_CACHE_SETKEY(dev->devnum, trk), &lru);
743
744 /* Process cache hit */
745 if (cache >= 0)
746 {
747 cache_setflag (CACHE_DEVBUF, cache, ~0, SHRD_CACHE_ACTIVE);
748 cache_unlock (CACHE_DEVBUF);
749 dev->cachehits++;
750 dev->cache = cache;
751 dev->buf = cache_getbuf (CACHE_DEVBUF, cache, 0);
752 dev->bufcur = trk;
753 dev->bufoff = 0;
754 dev->bufoffhi = dev->ckdtrksz;
755 dev->buflen = shared_ckd_trklen (dev, dev->buf);
756 dev->bufsize = cache_getlen (CACHE_DEVBUF, cache);
757 shrdtrc(dev,"ckd_read trk %d cache hit %d\n",trk,dev->cache);
758 return 0;
759 }
760
761 /* Special processing if no available cache entry */
762 if (lru < 0)
763 {
764 shrdtrc(dev,"ckd_read trk %d cache wait\n",trk);
765 dev->cachewaits++;
766 cache_wait (CACHE_DEVBUF);
767 goto cache_retry;
768 }
769
770 /* Process cache miss */
771 shrdtrc(dev,"ckd_read trk %d cache miss %d\n",trk,dev->cache);
772 dev->cachemisses++;
773 cache_setflag (CACHE_DEVBUF, lru, 0, SHRD_CACHE_ACTIVE|DEVBUF_TYPE_SCKD);
774 cache_setkey (CACHE_DEVBUF, lru, SHRD_CACHE_SETKEY(dev->devnum, trk));
775 cache_setage (CACHE_DEVBUF, lru);
776 buf = cache_getbuf (CACHE_DEVBUF, lru, dev->ckdtrksz);
777
778 cache_unlock (CACHE_DEVBUF);
779
780 read_retry:
781
782 /* Send the read request for the track to the remote host */
783 SHRD_SET_HDR (hdr, SHRD_READ, 0, dev->rmtnum, dev->rmtid, 4);
784 store_fw (hdr + SHRD_HDR_SIZE, trk);
785 rc = clientSend (dev, hdr, NULL, 0);
786 if (rc < 0)
787 {
788 ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0);
789 *unitstat = CSW_CE | CSW_DE | CSW_UC;
790 logmsg(_("HHCSH022E %4.4X error reading track %d\n"), dev->devnum, trk);
791 return -1;
792 }
793
794 /* Read the track from the remote host */
795 rc = clientRecv (dev, hdr, buf, dev->ckdtrksz);
796 SHRD_GET_HDR (hdr, code, *unitstat, devnum, id, len);
797 if (rc < 0 || code & SHRD_ERROR)
798 {
799 if (rc < 0 && retries--) goto read_retry;
800 ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0);
801 *unitstat = CSW_CE | CSW_DE | CSW_UC;
802 logmsg(_("HHCSH023E %4.4X error reading track %d\n"),
803 dev->devnum, trk);
804 return -1;
805 }
806
807 /* Read the sense data if an i/o error occurred */
808 if (code & SHRD_IOERR)
809 clientRequest (dev, dev->sense, dev->numsense,
810 SHRD_SENSE, 0, NULL, NULL);
811
812 /* Read complete */
813 dev->cache = lru;
814 dev->buf = cache_getbuf (CACHE_DEVBUF, lru, 0);
815 dev->bufcur = trk;
816 dev->bufoff = 0;
817 dev->bufoffhi = dev->ckdtrksz;
818 dev->buflen = shared_ckd_trklen (dev, dev->buf);
819 dev->bufsize = cache_getlen (CACHE_DEVBUF, lru);
820 dev->buf[0] = 0;
821
822 return 0;
823 } /* shared_ckd_read */
824
825 /*-------------------------------------------------------------------
826 * Shared ckd write track exit (client side)
827 *-------------------------------------------------------------------*/
shared_ckd_write(DEVBLK * dev,int trk,int off,BYTE * buf,int len,BYTE * unitstat)828 static int shared_ckd_write (DEVBLK *dev, int trk, int off,
829 BYTE *buf, int len, BYTE *unitstat)
830 {
831 int rc; /* Return code */
832
833 /* Immediately return if fake writing */
834 if (dev->ckdfakewr)
835 return len;
836
837 /* Error if opened read-only */
838 if (dev->ckdrdonly)
839 {
840 ckd_build_sense (dev, SENSE_EC, SENSE1_WRI, 0,
841 FORMAT_1, MESSAGE_0);
842 *unitstat = CSW_CE | CSW_DE | CSW_UC;
843 return -1;
844 }
845
846 shrdtrc(dev,"ckd_write trk %d off %d len %d\n",trk,off,len);
847
848 /* If the track is not current then read it */
849 if (trk != dev->bufcur)
850 {
851 rc = (dev->hnd->read) (dev, trk, unitstat);
852 if (rc < 0)
853 {
854 dev->bufcur = dev->cache = -1;
855 return -1;
856 }
857 }
858
859 /* Invalid track format if going past buffer end */
860 if (off + len > dev->bufoffhi)
861 {
862 ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0);
863 *unitstat = CSW_CE | CSW_DE | CSW_UC;
864 return -1;
865 }
866
867 /* Copy the data into the buffer */
868 if (buf) memcpy (dev->buf + off, buf, len);
869
870 /* Set low and high updated offsets */
871 if (!dev->bufupd || off < dev->bufupdlo)
872 dev->bufupdlo = off;
873 if (dev->bufoff + len > dev->bufupdhi)
874 dev->bufupdhi = off + len;
875
876 /* Indicate track image has been modified */
877 if (!dev->bufupd)
878 {
879 dev->bufupd = 1;
880 shared_update_notify (dev, trk);
881 }
882
883 return len;
884 } /* shared_ckd_write */
885
886 /*-------------------------------------------------------------------
887 * Return track image length
888 *-------------------------------------------------------------------*/
shared_ckd_trklen(DEVBLK * dev,BYTE * buf)889 static int shared_ckd_trklen (DEVBLK *dev, BYTE *buf)
890 {
891 int sz; /* Size so far */
892
893 for (sz = CKDDASD_TRKHDR_SIZE;
894 memcmp (buf + sz, &eighthexFF, 8) != 0; )
895 {
896 /* add length of count, key, and data fields */
897 sz += CKDDASD_RECHDR_SIZE +
898 buf[sz+5] +
899 (buf[sz+6] << 8) + buf[sz+7];
900 if (sz > dev->ckdtrksz - 8) break;
901 }
902
903 /* add length for end-of-track indicator */
904 sz += CKDDASD_RECHDR_SIZE;
905
906 if (sz > dev->ckdtrksz)
907 sz = dev->ckdtrksz;
908
909 return sz;
910 }
911
912 #if defined(FBA_SHARED)
913 /*-------------------------------------------------------------------
914 * Shared fba read block exit (client side)
915 *-------------------------------------------------------------------*/
shared_fba_read(DEVBLK * dev,int blkgrp,BYTE * unitstat)916 static int shared_fba_read (DEVBLK *dev, int blkgrp, BYTE *unitstat)
917 {
918 int rc; /* Return code */
919 int retries = 10; /* Number read retries */
920 int i, o; /* Cache indexes */
921 BYTE code; /* Response code */
922 U16 devnum; /* Response device number */
923 int len; /* Response length */
924 int id; /* Response id */
925 BYTE hdr[SHRD_HDR_SIZE + 4]; /* Read request header */
926
927
928 /* Return if reading the same block group */
929 if (blkgrp >= 0 && blkgrp == dev->bufcur)
930 return 0;
931
932 shrdtrc(dev,"fba_read blkrp %d\n",blkgrp);
933
934 /* Write the previous active entry if it was updated */
935 if (dev->bufupd)
936 clientWrite (dev, dev->bufcur);
937 dev->bufupd = 0;
938
939 /* Reset buffer offsets */
940 dev->bufoff = 0;
941 dev->bufoffhi = FBA_BLKGRP_SIZE;
942
943 cache_lock (CACHE_DEVBUF);
944
945 /* Make the previous cache entry inactive */
946 if (dev->cache >= 0)
947 cache_setflag(CACHE_DEVBUF, dev->cache, ~FBA_CACHE_ACTIVE, 0);
948 dev->bufcur = dev->cache = -1;
949
950 cache_retry:
951
952 /* Search the cache */
953 i = cache_lookup (CACHE_DEVBUF, FBA_CACHE_SETKEY(dev->devnum, blkgrp), &o);
954
955 /* Cache hit */
956 if (i >= 0)
957 {
958 cache_setflag(CACHE_DEVBUF, dev->cache, ~0, FBA_CACHE_ACTIVE);
959 cache_setage(CACHE_DEVBUF, dev->cache);
960 cache_unlock(CACHE_DEVBUF);
961 dev->cachehits++;
962 dev->cache = i;
963 dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0);
964 dev->bufcur = blkgrp;
965 dev->bufoff = 0;
966 dev->bufoffhi = shared_fba_blkgrp_len (dev, blkgrp);
967 dev->buflen = shared_fba_blkgrp_len (dev, blkgrp);
968 dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache);
969 shrdtrc(dev,"fba_read blkgrp %d cache hit %d\n",blkgrp,dev->cache);
970 return 0;
971 }
972
973 /* Wait if no available cache entry */
974 if (o < 0)
975 {
976 shrdtrc(dev,"fba_read blkgrp %d cache wait\n",blkgrp);
977 dev->cachewaits++;
978 cache_wait(CACHE_DEVBUF);
979 goto cache_retry;
980 }
981
982 /* Cache miss */
983 shrdtrc(dev,"fba_read blkgrp %d cache miss %d\n",blkgrp,dev->cache);
984 dev->cachemisses++;
985 cache_setflag(CACHE_DEVBUF, o, 0, FBA_CACHE_ACTIVE|DEVBUF_TYPE_SFBA);
986 cache_setkey (CACHE_DEVBUF, o, FBA_CACHE_SETKEY(dev->devnum, blkgrp));
987 cache_setage (CACHE_DEVBUF, o);
988 dev->buf = cache_getbuf(CACHE_DEVBUF, o, FBA_BLKGRP_SIZE);
989
990 cache_unlock (CACHE_DEVBUF);
991
992 read_retry:
993
994 /* Send the read request for the blkgrp to the remote host */
995 SHRD_SET_HDR (hdr, SHRD_READ, 0, dev->rmtnum, dev->rmtid, 4);
996 store_fw (hdr + SHRD_HDR_SIZE, blkgrp);
997 rc = clientSend (dev, hdr, NULL, 0);
998 if (rc < 0)
999 {
1000 dev->sense[0] = SENSE_EC;
1001 *unitstat = CSW_CE | CSW_DE | CSW_UC;
1002 logmsg(_("HHCSH024E %4.4X error reading block group %d\n"),
1003 dev->devnum, blkgrp);
1004 return -1;
1005 }
1006
1007 /* Read the blkgrp from the remote host */
1008 rc = clientRecv (dev, hdr, dev->buf, FBA_BLKGRP_SIZE);
1009 SHRD_GET_HDR (hdr, code, *unitstat, devnum, id, len);
1010 if (rc < 0 || code & SHRD_ERROR)
1011 {
1012 if (rc < 0 && retries--) goto read_retry;
1013 dev->sense[0] = SENSE_EC;
1014 *unitstat = CSW_CE | CSW_DE | CSW_UC;
1015 logmsg(_("HHCSH025E %4.4X error reading block group %d\n"),
1016 dev->devnum, blkgrp);
1017 return -1;
1018 }
1019
1020 /* Read the sense data if an i/o error occurred */
1021 if (code & SHRD_IOERR)
1022 clientRequest (dev, dev->sense, dev->numsense,
1023 SHRD_SENSE, 0, NULL, NULL);
1024
1025 dev->cache = o;
1026 dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0);
1027 dev->buf[0] = 0;
1028 dev->bufcur = blkgrp;
1029 dev->bufoff = 0;
1030 dev->bufoffhi = shared_fba_blkgrp_len (dev, blkgrp);
1031 dev->buflen = shared_fba_blkgrp_len (dev, blkgrp);
1032 dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache);
1033
1034 return 0;
1035 }
1036
1037 /*-------------------------------------------------------------------
1038 * Shared fba write block exit (client side)
1039 *-------------------------------------------------------------------*/
shared_fba_write(DEVBLK * dev,int blkgrp,int off,BYTE * buf,int len,BYTE * unitstat)1040 static int shared_fba_write (DEVBLK *dev, int blkgrp, int off,
1041 BYTE *buf, int len, BYTE *unitstat)
1042 {
1043 int rc; /* Return code */
1044
1045 /* Read the block group */
1046 if (blkgrp != dev->bufcur)
1047 {
1048 rc = (dev->hnd->read) (dev, blkgrp, unitstat);
1049 if (rc < 0) {
1050 dev->bufcur = dev->cache = -1;
1051 return -1;
1052 }
1053 }
1054
1055 /* Copy to the device buffer */
1056 if (buf) memcpy (dev->buf + off, buf, len);
1057
1058 /* Update high/low offsets */
1059 if (!dev->bufupd || off < dev->bufupdlo)
1060 dev->bufupdlo = off;
1061 if (off + len > dev-> bufupdhi)
1062 dev->bufupdhi = off + len;
1063
1064 /* Indicate block group has been modified */
1065 if (!dev->bufupd)
1066 {
1067 dev->bufupd = 1;
1068 shared_update_notify (dev, blkgrp);
1069 }
1070
1071 return len;
1072 }
1073
1074
1075 /*-------------------------------------------------------------------*/
1076 /* Calculate length of an FBA block group */
1077 /*-------------------------------------------------------------------*/
shared_fba_blkgrp_len(DEVBLK * dev,int blkgrp)1078 static int shared_fba_blkgrp_len (DEVBLK *dev, int blkgrp)
1079 {
1080 off_t offset; /* Offset of block group */
1081
1082 offset = blkgrp * FBA_BLKGRP_SIZE;
1083 if (dev->fbaend - offset < FBA_BLKGRP_SIZE)
1084 return (int)(dev->fbaend - offset);
1085 else
1086 return FBA_BLKGRP_SIZE;
1087 }
1088
1089 #endif /* FBA_SHARED */
1090
1091 /*-------------------------------------------------------------------
1092 * Shared usage exit (client side)
1093 *-------------------------------------------------------------------*/
shared_used(DEVBLK * dev)1094 static int shared_used (DEVBLK *dev)
1095 {
1096 int rc; /* Return code */
1097 FWORD usage; /* Usage buffer */
1098
1099 /* Get usage information */
1100 rc = clientRequest (dev, usage, 4, SHRD_USED, 0, NULL, NULL);
1101 if (rc != 4)
1102 {
1103 logmsg (_("HHCSH026E %4.4X Error retrieving usage information\n"),
1104 dev->devnum);
1105 return -1;
1106 }
1107 return fetch_fw (usage);
1108 } /* shared_used */
1109
1110 /*-------------------------------------------------------------------
1111 * Shared reserve exit (client side)
1112 *-------------------------------------------------------------------*/
shared_reserve(DEVBLK * dev)1113 static void shared_reserve (DEVBLK *dev)
1114 {
1115 int rc; /* Return code */
1116
1117 /* Issue reserve request */
1118 rc = clientRequest (dev, NULL, 0, SHRD_RESERVE, 0, NULL, NULL);
1119
1120 } /* shared_reserve */
1121
1122 /*-------------------------------------------------------------------
1123 * Shared release exit (client side)
1124 *-------------------------------------------------------------------*/
shared_release(DEVBLK * dev)1125 static void shared_release (DEVBLK *dev)
1126 {
1127 int rc; /* Return code */
1128
1129 /* Issue release request */
1130 rc = clientRequest (dev, NULL, 0, SHRD_RELEASE, 0, NULL, NULL);
1131
1132 } /* shared_release */
1133
1134 /*-------------------------------------------------------------------
1135 * Write to host
1136 *
1137 * NOTE - writes are deferred until a switch occurs or the
1138 * channel program ends. We are called from either the
1139 * read exit or the end channel program exit.
1140 *-------------------------------------------------------------------*/
clientWrite(DEVBLK * dev,int block)1141 static int clientWrite (DEVBLK *dev, int block)
1142 {
1143 int rc; /* Return code */
1144 int retries = 10; /* Number write retries */
1145 int len; /* Data length */
1146 BYTE hdr[SHRD_HDR_SIZE + 2 + 4]; /* Write header */
1147 BYTE code; /* Response code */
1148 int status; /* Response status */
1149 int id; /* Response identifier */
1150 U16 devnum; /* Response device number */
1151 BYTE errmsg[SHARED_MAX_MSGLEN+1];/* Error message */
1152
1153 /* Calculate length to write */
1154 len = dev->bufupdhi - dev->bufupdlo;
1155 if (len <= 0 || dev->bufcur < 0)
1156 {
1157 dev->bufupdlo = dev->bufupdhi = 0;
1158 return 0;
1159 }
1160
1161 shrdtrc(dev,"write rcd %d off %d len %d\n",block,dev->bufupdlo,len);
1162
1163 write_retry:
1164
1165 /* The write request contains a 2 byte offset and 4 byte id,
1166 followed by the data */
1167 SHRD_SET_HDR (hdr, SHRD_WRITE, 0, dev->rmtnum, dev->rmtid, len + 6);
1168 store_hw (hdr + SHRD_HDR_SIZE, dev->bufupdlo);
1169 store_fw (hdr + SHRD_HDR_SIZE + 2, block);
1170
1171 rc = clientSend (dev, hdr, dev->buf + dev->bufupdlo, len);
1172 if (rc < 0)
1173 {
1174 logmsg(_("HHCSH027E %4.4X error writing track %d\n"),
1175 dev->devnum, dev->bufcur);
1176 dev->bufupdlo = dev->bufupdhi = 0;
1177 clientPurge (dev, 0, NULL);
1178 return -1;
1179 }
1180
1181 /* Get the response */
1182 rc = clientRecv (dev, hdr, errmsg, sizeof(errmsg));
1183 SHRD_GET_HDR (hdr, code, status, devnum, id, len);
1184 if (rc < 0 || (code & SHRD_ERROR) || (code & SHRD_IOERR))
1185 {
1186 if (rc < 0 && retries--) goto write_retry;
1187 logmsg(_("HHCSH028E %4.4X remote error writing track %d: "
1188 "%2.2X-%2.2X\n"), dev->devnum, dev->bufcur, code, status);
1189 dev->bufupdlo = dev->bufupdhi = 0;
1190 clientPurge (dev, 0, NULL);
1191 return -1;
1192 }
1193
1194 dev->bufupdlo = dev->bufupdhi = 0;
1195 return rc;
1196 } /* clientWrite */
1197
1198 /*-------------------------------------------------------------------
1199 * Purge cache entries (client side)
1200 *-------------------------------------------------------------------*/
clientPurge(DEVBLK * dev,int n,void * buf)1201 static void clientPurge (DEVBLK *dev, int n, void *buf)
1202 {
1203 cache_lock(CACHE_DEVBUF);
1204 dev->rmtpurgen = n;
1205 dev->rmtpurge = (FWORD *)buf;
1206 cache_scan (CACHE_DEVBUF, clientPurgescan, dev);
1207 cache_unlock(CACHE_DEVBUF);
1208 }
clientPurgescan(int * answer,int ix,int i,void * data)1209 static int clientPurgescan (int *answer, int ix, int i, void *data)
1210 {
1211 U16 devnum; /* Cached device number */
1212 int trk; /* Cached track */
1213 int p; /* Purge index */
1214 DEVBLK *dev = data; /* -> device block */
1215
1216 UNREFERENCED(answer);
1217 SHRD_CACHE_GETKEY(i, devnum, trk);
1218 if (devnum == dev->devnum)
1219 {
1220 if (dev->rmtpurgen == 0) {
1221 cache_release (ix, i, 0);
1222 shrdtrc(dev,"purge %d\n",trk);
1223 }
1224 else
1225 {
1226 for (p = 0; p < dev->rmtpurgen; p++)
1227 {
1228 if (trk == (int)fetch_fw (dev->rmtpurge[p]))
1229 {
1230 shrdtrc(dev,"purge %d\n",trk);
1231 cache_release (ix, i, 0);
1232 break;
1233 }
1234 }
1235 }
1236 }
1237 return 0;
1238 } /* clientPurge */
1239
1240 /*-------------------------------------------------------------------
1241 * Connect to the server (client side)
1242 *-------------------------------------------------------------------*/
clientConnect(DEVBLK * dev,int retry)1243 static int clientConnect (DEVBLK *dev, int retry)
1244 {
1245 int rc; /* Return code */
1246 struct sockaddr *server; /* -> server descriptor */
1247 int flag; /* Flags (version | release) */
1248 int len; /* Length server descriptor */
1249 struct sockaddr_in iserver; /* inet server descriptor */
1250 #if defined( HAVE_SYS_UN_H )
1251 struct sockaddr_un userver; /* unix server descriptor */
1252 #endif
1253 int retries = 10; /* Number of retries */
1254 HWORD id; /* Returned identifier */
1255 HWORD comp; /* Returned compression parm */
1256
1257 do {
1258
1259 /* Close previous connection */
1260 if (dev->fd >= 0) close_socket (dev->fd);
1261
1262 /* Get a socket */
1263 if (dev->localhost)
1264 {
1265 #if defined( HAVE_SYS_UN_H )
1266 dev->fd = dev->ckdfd[0] = socket (AF_UNIX, SOCK_STREAM, 0);
1267 #else // !defined( HAVE_SYS_UN_H )
1268 dev->fd = dev->ckdfd[0] = -1;
1269 #endif // defined( HAVE_SYS_UN_H )
1270 if (dev->fd < 0)
1271 {
1272 logmsg (_("HHCSH029E %4.4X socket failed: %s\n"),
1273 dev->devnum, strerror(HSO_errno));
1274 return -1;
1275 }
1276 #if defined( HAVE_SYS_UN_H )
1277 userver.sun_family = AF_UNIX;
1278 sprintf(userver.sun_path, "/tmp/hercules_shared.%d", dev->rmtport);
1279 server = (struct sockaddr *)&userver;
1280 len = sizeof(userver);
1281 #endif // !defined( HAVE_SYS_UN_H )
1282 }
1283 else
1284 {
1285 dev->fd = dev->ckdfd[0] = socket (AF_INET, SOCK_STREAM, 0);
1286 if (dev->fd < 0)
1287 {
1288 logmsg (_("HHCSH030E %4.4X socket failed: %s\n"),
1289 dev->devnum, strerror(HSO_errno));
1290 return -1;
1291 }
1292 iserver.sin_family = AF_INET;
1293 iserver.sin_port = htons(dev->rmtport);
1294 memcpy(&iserver.sin_addr.s_addr,&dev->rmtaddr,sizeof(struct in_addr));
1295 server = (struct sockaddr *)&iserver;
1296 len = sizeof(iserver);
1297 }
1298
1299 /* Connect to the server */
1300 store_hw (id, dev->rmtid);
1301 rc = connect (dev->fd, server, len);
1302 shrdtrc(dev,"connect rc=%d errno=%d\n",rc, HSO_errno);
1303 if (rc >= 0)
1304 {
1305 if (!dev->batch)
1306 logmsg(_("HHCSH031I %4.4X Connected to %s\n"),
1307 dev->devnum, dev->filename);
1308
1309 /* Request device connection */
1310 flag = (SHARED_VERSION << 4) | SHARED_RELEASE;
1311 rc = clientRequest (dev, id, 2, SHRD_CONNECT, flag, NULL, &flag);
1312 if (rc >= 0)
1313 {
1314 dev->rmtid = fetch_hw (id);
1315 dev->rmtrel = flag & 0x0f;
1316 }
1317
1318 /*
1319 * Negotiate compression - top 4 bits have the compression
1320 * algorithms we support (00010000 -> libz; 00100000 ->bzip2,
1321 * 00110000 -> both) and the bottom 4 bits indicates the
1322 * libz parm we want to use when sending data back & forth.
1323 * If the server returns `0' back, then we won't use libz to
1324 * compress data to the server. What the `compression
1325 * algorithms we support' means is that if the data source is
1326 * cckd or cfba then the server doesn't have to uncompress
1327 * the data for us if we support the compression algorithm.
1328 */
1329
1330 if (rc >= 0 && (dev->rmtcomp || dev->rmtcomps))
1331 {
1332 rc = clientRequest (dev, comp, 2, SHRD_COMPRESS,
1333 (dev->rmtcomps << 4) | dev->rmtcomp, NULL, NULL);
1334 if (rc >= 0)
1335 dev->rmtcomp = fetch_hw (comp);
1336 }
1337
1338 }
1339 else if (!retry)
1340 logmsg(_("HHCSH032E %4.4X Connect %s %d: %s\n"),
1341 dev->devnum, dev->filename, HSO_errno, strerror(HSO_errno));
1342
1343 if (rc < 0 && retry) usleep (20000);
1344
1345 } while (retry && retries-- && rc < 0);
1346
1347 return rc;
1348
1349 } /* clientConnect */
1350
1351 /*-------------------------------------------------------------------
1352 * Send request to host and get the response
1353 *
1354 * No data is sent on the request, buf gets the response.
1355 * If an uncorrectable connection error occurs -1 is returned.
1356 * Otherwise *code and *status is set from the response header
1357 *
1358 * Since `buf' may be NULL or not very long, response data is
1359 * received in a temporary buffer. This enables us to receive
1360 * an error message from the remote system.
1361 *-------------------------------------------------------------------*/
clientRequest(DEVBLK * dev,BYTE * buf,int len,int cmd,int flags,int * code,int * status)1362 static int clientRequest (DEVBLK *dev, BYTE *buf, int len, int cmd,
1363 int flags, int *code, int *status)
1364 {
1365 int rc; /* Return code */
1366 int retries = 10; /* Number retries */
1367 BYTE rcode; /* Request return code */
1368 BYTE rstatus; /* Request return status */
1369 U16 rdevnum; /* Request return devnum */
1370 int rid; /* Request return id */
1371 int rlen; /* Request return length */
1372 BYTE hdr[SHRD_HDR_SIZE]; /* Header */
1373 BYTE temp[256]; /* Temporary buffer */
1374
1375 retry :
1376
1377 /* Send the request */
1378 SHRD_SET_HDR(hdr, cmd, flags, dev->rmtnum, dev->rmtid, 0);
1379 shrdtrc(dev,"client_request %2.2x %2.2x %2.2x %d\n",
1380 cmd,flags,dev->rmtnum,dev->rmtid);
1381 rc = clientSend (dev, hdr, NULL, 0);
1382 if (rc < 0) return rc;
1383
1384 /* Receive the response */
1385 rc = clientRecv (dev, hdr, temp, sizeof(temp));
1386
1387 /* Retry recv errors */
1388 if (rc < 0)
1389 {
1390 if (cmd != SHRD_CONNECT && retries--)
1391 {
1392 SLEEP (1);
1393 clientConnect (dev, 1);
1394 goto retry;
1395 }
1396 return -1;
1397 }
1398
1399 /* Set code and status */
1400 SHRD_GET_HDR(hdr, rcode, rstatus, rdevnum, rid, rlen);
1401 shrdtrc(dev,"client_response %2.2x %2.2x %2.2x %d %d\n",
1402 rcode,rstatus,rdevnum,rid,rlen);
1403 if (code) *code = rcode;
1404 if (status) *status = rstatus;
1405
1406 /* Copy the data into the caller's buffer */
1407 if (buf && len > 0 && rlen > 0)
1408 memcpy (buf, temp, len < rlen ? len : rlen);
1409
1410 return rlen;
1411 } /* clientRequest */
1412
1413 /*-------------------------------------------------------------------
1414 * Send a request to the host
1415 *
1416 * `buf' may be NULL
1417 * `buflen' is the length in `buf' (should be 0 if `buf' is NULL)
1418 * `hdr' may contain additional data; this is detected by the
1419 * difference between `buflen' and the length in the header
1420 *
1421 * If `buf' is adjacent to `hdr' then `buf' should be NULL
1422 *
1423 *-------------------------------------------------------------------*/
clientSend(DEVBLK * dev,BYTE * hdr,BYTE * buf,int buflen)1424 static int clientSend (DEVBLK *dev, BYTE *hdr, BYTE *buf, int buflen)
1425 {
1426 int rc; /* Return code */
1427 BYTE cmd; /* Header command */
1428 BYTE flag; /* Header flags */
1429 U16 devnum; /* Header device nu */
1430 int len; /* Header length */
1431 int id; /* Header identifier */
1432 int hdrlen; /* Header length + other data*/
1433 int off; /* Offset to buffer data */
1434 BYTE *sendbuf; /* Send buffer */
1435 int sendlen; /* Send length */
1436 BYTE cbuf[SHRD_HDR_SIZE + 65536]; /* Combined buffer */
1437
1438 /* Make buf, buflen consistent if no additional data to be sent */
1439 if (buf == NULL) buflen = 0;
1440 else if (buflen == 0) buf = NULL;
1441
1442 /* Calculate length of header, may contain additional data */
1443 SHRD_GET_HDR(hdr, cmd, flag, devnum, id, len);
1444 shrdtrc(dev,"client_send %2.2x %2.2x %2.2x %d %d\n",
1445 cmd,flag,devnum,id,len);
1446 hdrlen = SHRD_HDR_SIZE + (len - buflen);
1447 off = len - buflen;
1448
1449 if (dev->fd < 0)
1450 {
1451 rc = clientConnect (dev, 1);
1452 if (rc < 0) return -1;
1453 }
1454
1455 #ifdef HAVE_LIBZ
1456 /* Compress the buf */
1457 if (dev->rmtcomp != 0
1458 && flag == 0 && off <= SHRD_COMP_MAX_OFF
1459 && buflen >= SHARED_COMPRESS_MINLEN)
1460 {
1461 unsigned long newlen;
1462 newlen = 65536 - hdrlen;
1463 memcpy (cbuf, hdr, hdrlen);
1464 rc = compress2 (cbuf + hdrlen, &newlen,
1465 buf, buflen, dev->rmtcomp);
1466 if (rc == Z_OK && (int)newlen < buflen)
1467 {
1468 cmd |= SHRD_COMP;
1469 flag = (SHRD_LIBZ << 4) | off;
1470 hdr = cbuf;
1471 hdrlen += newlen;
1472 buf = NULL;
1473 buflen = 0;
1474 }
1475 }
1476 #endif
1477
1478 /* Combine header and data unless there's no buffer */
1479 if (buflen == 0)
1480 {
1481 sendbuf = hdr;
1482 sendlen = hdrlen;
1483 }
1484 else
1485 {
1486 memcpy (cbuf, hdr, hdrlen);
1487 memcpy (cbuf + hdrlen, buf, buflen);
1488 sendbuf = cbuf;
1489 sendlen = hdrlen + buflen;
1490 }
1491
1492 SHRD_SET_HDR(sendbuf, cmd, flag, devnum, id, (U16)(sendlen - SHRD_HDR_SIZE));
1493
1494 if (cmd & SHRD_COMP)
1495 shrdtrc(dev,"client_send %2.2x %2.2x %2.2x %d %d (compressed)\n",
1496 cmd, flag, devnum, id, (int)(sendlen - SHRD_HDR_SIZE));
1497
1498 retry:
1499
1500 /* Send the header and data */
1501 rc = send (dev->fd, sendbuf, sendlen, 0);
1502 if (rc < 0)
1503 {
1504 rc = clientConnect (dev, 0);
1505 if (rc >= 0) goto retry;
1506 }
1507
1508 /* Process return code */
1509 if (rc < 0)
1510 {
1511 logmsg(_("HHCSH033E %4.4X send error %d for %2.2X-%2.2X: %s\n"),
1512 dev->devnum, HSO_errno, cmd, flag, strerror(HSO_errno));
1513 return -1;
1514 }
1515
1516 return rc;
1517
1518 } /* clientSend */
1519
1520 /*-------------------------------------------------------------------
1521 * Receive a response (client side)
1522 *-------------------------------------------------------------------*/
clientRecv(DEVBLK * dev,BYTE * hdr,BYTE * buf,int buflen)1523 static int clientRecv (DEVBLK *dev, BYTE *hdr, BYTE *buf, int buflen)
1524 {
1525 int rc; /* Return code */
1526 BYTE code; /* Response code */
1527 BYTE status; /* Response status */
1528 U16 devnum; /* Response device number */
1529 int id; /* Response identifier */
1530 int len; /* Response length */
1531
1532 /* Clear the header to zeroes */
1533 memset (hdr, 0, SHRD_HDR_SIZE);
1534
1535 /* Return error if not connected */
1536 if (dev->fd < 0)
1537 {
1538 logmsg(_("HHCSH034E %4.4X Not connected to %s\n"),
1539 dev->devnum, dev->filename);
1540 return -1;
1541 }
1542
1543 /* Receive the header */
1544 rc = recvData (dev->fd, hdr, buf, buflen, 0);
1545 if (rc < 0)
1546 {
1547 if (rc != -ENOTCONN)
1548 logmsg(_("HHCSH035E %4.4X recv error %d: %s\n"),
1549 dev->devnum, -rc, strerror(-rc));
1550 return rc;
1551 }
1552 SHRD_GET_HDR(hdr, code, status, devnum, id, len);
1553
1554 shrdtrc(dev,"client_recv %2.2x %2.2x %2.2x %d %d\n",
1555 code,status,devnum,id,len);
1556
1557 /* Handle remote logical error */
1558 if (code & SHRD_ERROR)
1559 {
1560 logmsg(_("HHCSH036E %4.4X Remote error %2.2X-%2.2X: %s\n"),
1561 dev->devnum, code, status, buf);
1562 len = 0;
1563 }
1564
1565 /* Reset code/status if response was compressed */
1566 if (len > 0 && code == SHRD_COMP)
1567 {
1568 code = SHRD_OK;
1569 status = 0;
1570 }
1571
1572 /* Reset the header */
1573 SHRD_SET_HDR(hdr, code, status, devnum, id, len);
1574
1575 return len;
1576 } /* clientRecv */
1577
1578 /*-------------------------------------------------------------------
1579 * Receive data (server or client)
1580 *-------------------------------------------------------------------*/
recvData(int sock,BYTE * hdr,BYTE * buf,int buflen,int server)1581 static int recvData(int sock, BYTE *hdr, BYTE *buf, int buflen, int server)
1582 {
1583 int rc; /* Return code */
1584 int rlen; /* Data length to recv */
1585 int recvlen; /* Total length */
1586 BYTE *recvbuf; /* Receive buffer */
1587 BYTE cmd; /* Header command */
1588 BYTE flag; /* Header flags */
1589 U16 devnum; /* Header device number */
1590 int id; /* Header identifier */
1591 int len; /* Header length */
1592 int comp = 0; /* Compression type */
1593 int off = 0; /* Offset to compressed data */
1594 DEVBLK *dev = NULL; /* For `shrdtrc' */
1595 BYTE cbuf[65536]; /* Compressed buffer */
1596
1597
1598 /* Receive the header */
1599 for (recvlen = 0; recvlen < (int)SHRD_HDR_SIZE; recvlen += rc)
1600 {
1601 rc = recv (sock, hdr + recvlen, SHRD_HDR_SIZE - recvlen, 0);
1602 if (rc < 0)
1603 return -HSO_errno;
1604 else if (rc == 0)
1605 return -HSO_ENOTCONN;
1606 }
1607 SHRD_GET_HDR (hdr, cmd, flag, devnum, id, len);
1608
1609 shrdtrc(dev,"recvData %2.2x %2.2x %2.2x %d %d\n",
1610 cmd, flag, devnum, id, len);
1611
1612 /* Return if no data */
1613 if (len == 0) return 0;
1614
1615 /* Check for compressed data */
1616 if ((server && (cmd & SHRD_COMP))
1617 || (!server && cmd == SHRD_COMP))
1618 {
1619 comp = (flag & SHRD_COMP_MASK) >> 4;
1620 off = flag & SHRD_COMP_OFF;
1621 cmd &= ~SHRD_COMP;
1622 flag = 0;
1623 recvbuf = cbuf;
1624 rlen = len;
1625 }
1626 else
1627 {
1628 recvbuf = buf;
1629 rlen = buflen < len ? buflen : len;
1630 }
1631
1632 /* Receive the data */
1633 for (recvlen = 0; recvlen < rlen; recvlen += rc)
1634 {
1635 rc = recv (sock, recvbuf + recvlen, len - recvlen, 0);
1636 if (rc < 0)
1637 return -HSO_errno;
1638 else if (rc == 0)
1639 return -HSO_ENOTCONN;
1640 }
1641
1642 /* Flush any remaining data */
1643 for (; rlen < len; rlen += rc)
1644 {
1645 BYTE buf[256];
1646 rc = recv (sock, buf, len - rlen < 256 ? len - rlen : 256, 0);
1647 if (rc < 0)
1648 return -HSO_errno;
1649 else if (rc == 0)
1650 return -HSO_ENOTCONN;
1651 }
1652
1653 /* Check for compression */
1654 if (comp == SHRD_LIBZ) {
1655 #ifdef HAVE_LIBZ
1656 unsigned long newlen;
1657
1658 if (off > 0)
1659 memcpy (buf, cbuf, off);
1660 newlen = buflen - off;
1661 rc = uncompress(buf + off, &newlen, cbuf + off, len - off);
1662 if (rc == Z_OK)
1663 recvlen = (int)newlen + off;
1664 else
1665 {
1666 logmsg(_("HHCSH037E uncompress error %d, off %d len %d\n"),
1667 rc, off, len - off);
1668 recvlen = -1;
1669 }
1670 #else
1671 logmsg(_("HHCSH038E data compressed using libz, unsupported\n"));
1672 recvlen = -1;
1673 #endif
1674 }
1675 else if (comp == SHRD_BZIP2)
1676 {
1677 #ifdef CCKD_BZIP2
1678 unsigned int newlen;
1679
1680 if (off > 0)
1681 memcpy (buf, cbuf, off);
1682
1683 newlen = buflen - off;
1684 rc = BZ2_bzBuffToBuffDecompress((void *)(buf + off), &newlen, (void *)(cbuf + off), len - off, 0, 0);
1685 if (rc == BZ_OK)
1686 recvlen = (int)newlen + off;
1687 else
1688 {
1689 logmsg(_("HHCSH039E decompress error %d, off %d len %d\n"),
1690 rc, off, len - off);
1691 recvlen = -1;
1692 }
1693 #else
1694 logmsg(_("HHCSH040E data compressed using bzip2, unsupported\n"));
1695 recvlen = -1;
1696 #endif
1697 }
1698
1699 if (recvlen > 0)
1700 {
1701 SHRD_SET_HDR (hdr, cmd, flag, devnum, id, recvlen);
1702 if (comp)
1703 shrdtrc(dev,"recvData %2.2x %2.2x %2.2x %d %d (uncompressed)\n",
1704 cmd, flag, devnum, id, recvlen);
1705 }
1706
1707 return recvlen;
1708
1709 } /* recvData */
1710
1711 /*-------------------------------------------------------------------
1712 * Process a request (server side)
1713 *-------------------------------------------------------------------*/
serverRequest(DEVBLK * dev,int ix,BYTE * hdr,BYTE * buf)1714 static void serverRequest (DEVBLK *dev, int ix, BYTE *hdr, BYTE *buf)
1715 {
1716 int rc; /* Return code */
1717 int i; /* Loop index */
1718 BYTE cmd; /* Header command */
1719 BYTE flag; /* Header flags */
1720 U16 devnum; /* Header device number */
1721 int id; /* Header identifier */
1722 int len; /* Header length */
1723 int code; /* Response code */
1724 int rcd; /* Record to read/write */
1725 int off; /* Offset into record */
1726
1727 /* Extract header information */
1728 SHRD_GET_HDR (hdr, cmd, flag, devnum, id, len);
1729
1730 shrdtrc(dev,"server_request [%d] %2.2x %2.2x %2.2x %d %d\n",
1731 ix, cmd, flag, devnum, id, len);
1732
1733 dev->shrd[ix]->time = time (NULL);
1734
1735 switch (cmd) {
1736
1737 case SHRD_CONNECT:
1738 if (dev->connecting)
1739 {
1740 serverError (dev, ix, SHRD_ERROR_NOTINIT, cmd,
1741 "device not initialized");
1742 break;
1743 }
1744 if ((flag >> 4) != SHARED_VERSION)
1745 {
1746 serverError (dev, ix, SHRD_ERROR_BADVERS, cmd,
1747 "shared version mismatch");
1748 break;
1749 }
1750 dev->shrd[ix]->release = flag & 0x0f;
1751 SHRD_SET_HDR (hdr, 0, (SHARED_VERSION << 4) | SHARED_RELEASE, dev->devnum, id, 2);
1752 store_hw (buf, id);
1753 serverSend (dev, ix, hdr, buf, 2);
1754 break;
1755
1756 case SHRD_DISCONNECT:
1757 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0);
1758 serverSend (dev, ix, hdr, NULL, 0);
1759 dev->shrd[ix]->disconnect = 1;
1760
1761 obtain_lock (&dev->lock);
1762
1763 /* Make the device available if this system active on it */
1764 if (dev->ioactive == id)
1765 {
1766 if (!dev->suspended)
1767 {
1768 dev->busy = 0;
1769 dev->ioactive = DEV_SYS_NONE;
1770 }
1771 else
1772 dev->ioactive = DEV_SYS_LOCAL;
1773 if (dev->iowaiters)
1774 signal_condition (&dev->iocond);
1775 }
1776
1777 release_lock (&dev->lock);
1778 break;
1779
1780 case SHRD_START:
1781 case SHRD_RESUME:
1782
1783 obtain_lock (&dev->lock);
1784
1785 /* If the device is suspended locally then grab it */
1786 if (dev->ioactive == DEV_SYS_LOCAL && dev->suspended && !dev->reserved)
1787 dev->ioactive = id;
1788
1789 /* Check if the device is busy */
1790 if (dev->ioactive != id && dev->ioactive != DEV_SYS_NONE)
1791 {
1792 shrdtrc(dev,"server_request busy id=%d ioactive=%d reserved=%d\n",
1793 id,dev->ioactive,dev->reserved);
1794 /* If the `nowait' bit is on then respond `busy' */
1795 if (flag & SHRD_NOWAIT)
1796 {
1797 release_lock (&dev->lock);
1798 SHRD_SET_HDR (hdr, SHRD_BUSY, 0, dev->devnum, id, 0);
1799 serverSend (dev, ix, hdr, NULL, 0);
1800 break;
1801 }
1802
1803 dev->shrd[ix]->waiting = 1;
1804
1805 /* Wait while the device is busy by the local system */
1806 while (dev->ioactive == DEV_SYS_LOCAL && !dev->suspended)
1807 {
1808 dev->iowaiters++;
1809 wait_condition (&dev->iocond, &dev->lock);
1810 dev->iowaiters--;
1811 }
1812
1813 /* Return with the `waiting' bit on if busy by a remote system */
1814 if (dev->ioactive != DEV_SYS_NONE && dev->ioactive != DEV_SYS_LOCAL)
1815 {
1816 release_lock (&dev->lock);
1817 break;
1818 }
1819
1820 dev->shrd[ix]->waiting = 0;
1821 }
1822
1823 /* Make this system active on the device */
1824 dev->ioactive = id;
1825 dev->busy = 1;
1826 dev->syncio_active = dev->syncio_retry = 0;
1827 sysblk.shrdcount++;
1828 shrdtrc(dev,"server_request active id=%d\n", id);
1829
1830 release_lock(&dev->lock);
1831
1832 /* Call the i/o start or resume exit */
1833 if (cmd == SHRD_START && dev->hnd->start)
1834 (dev->hnd->start) (dev);
1835 else if (cmd == SHRD_RESUME && dev->hnd->resume)
1836 (dev->hnd->resume) (dev);
1837
1838 /* Get the purge list */
1839 if (dev->shrd[ix]->purgen == 0)
1840 code = len = 0;
1841 else
1842 {
1843 code = SHRD_PURGE;
1844 if (dev->shrd[ix]->purgen < 0)
1845 len = 0;
1846 else
1847 len = 4 * dev->shrd[ix]->purgen;
1848 }
1849
1850 /* Send the response */
1851 SHRD_SET_HDR (hdr, code, 0, dev->devnum, id, len);
1852 rc = serverSend (dev, ix, hdr, (BYTE *)dev->shrd[ix]->purge, len);
1853 if (rc >= 0)
1854 dev->shrd[ix]->purgen = 0;
1855 break;
1856
1857 case SHRD_END:
1858 case SHRD_SUSPEND:
1859 /* Must be active on the device for this command */
1860 if (dev->ioactive != id)
1861 {
1862 serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1863 "not active on this device");
1864 break;
1865 }
1866
1867 /* Call the I/O end/suspend exit */
1868 if (cmd == SHRD_END && dev->hnd->end)
1869 (dev->hnd->end) (dev);
1870 else if (cmd == SHRD_SUSPEND && dev->hnd->suspend)
1871 (dev->hnd->suspend) (dev);
1872
1873 obtain_lock (&dev->lock);
1874
1875 /* Make the device available if it's not reserved */
1876 if (!dev->reserved)
1877 {
1878 /* If locally suspended then return the device to local */
1879 if (dev->suspended)
1880 {
1881 dev->ioactive = DEV_SYS_LOCAL;
1882 dev->busy = 1;
1883 }
1884 else
1885 {
1886 dev->ioactive = DEV_SYS_NONE;
1887 dev->busy = 0;
1888 }
1889
1890 /* Reset any `waiting' bits */
1891 for (i = 0; i < SHARED_MAX_SYS; i++)
1892 if (dev->shrd[i])
1893 dev->shrd[i]->waiting = 0;
1894
1895 /* Notify any waiters */
1896 if (dev->iowaiters)
1897 signal_condition (&dev->iocond);
1898 }
1899 shrdtrc(dev,"server_request inactive id=%d\n", id);
1900
1901 release_lock (&dev->lock);
1902
1903 /* Send response back */
1904 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0);
1905 serverSend (dev, ix, hdr, NULL, 0);
1906 break;
1907
1908 case SHRD_RESERVE:
1909 /* Must be active on the device for this command */
1910 if (dev->ioactive != id)
1911 {
1912 serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1913 "not active on this device");
1914 break;
1915 }
1916
1917 obtain_lock (&dev->lock);
1918 dev->reserved = 1;
1919 release_lock (&dev->lock);
1920
1921 shrdtrc(dev,"server_request reserved id=%d\n", id);
1922
1923 /* Call the I/O reserve exit */
1924 if (dev->hnd->reserve) (dev->hnd->reserve) (dev);
1925
1926 /* Send response back */
1927 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0);
1928 serverSend (dev, ix, hdr, NULL, 0);
1929
1930 break;
1931
1932 case SHRD_RELEASE:
1933 /* Must be active on the device for this command */
1934 if (dev->ioactive != id)
1935 {
1936 serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1937 "not active on this device");
1938 break;
1939 }
1940
1941 /* Call the I/O release exit */
1942 if (dev->hnd->release) (dev->hnd->release) (dev);
1943
1944 obtain_lock (&dev->lock);
1945 dev->reserved = 0;
1946 release_lock (&dev->lock);
1947
1948 shrdtrc(dev,"server_request released id=%d\n", id);
1949
1950 /* Send response back */
1951 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0);
1952 serverSend (dev, ix, hdr, NULL, 0);
1953
1954 break;
1955
1956 case SHRD_READ:
1957 /* Must be active on the device for this command */
1958 if (dev->ioactive != id)
1959 {
1960 serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1961 "not active on this device");
1962 break;
1963 }
1964
1965 /* Set the compressions client is willing to accept */
1966 dev->comps = dev->shrd[ix]->comps;
1967 dev->comp = dev->compoff = 0;
1968
1969 /* Call the I/O read exit */
1970 rcd = (int)fetch_fw (buf);
1971 rc = (dev->hnd->read) (dev, rcd, &flag);
1972 shrdtrc(dev,"server_request read rcd %d flag %2.2x rc=%d\n",
1973 rcd, flag, rc);
1974
1975 if (rc < 0)
1976 code = SHRD_IOERR;
1977 else
1978 {
1979 code = dev->comp ? SHRD_COMP : 0;
1980 flag = (dev->comp << 4) | dev->compoff;
1981 }
1982
1983 /* Reset compression stuff */
1984 dev->comps = dev->comp = dev->compoff = 0;
1985
1986 SHRD_SET_HDR (hdr, code, flag, dev->devnum, id, dev->buflen);
1987 serverSend (dev, ix, hdr, dev->buf, dev->buflen);
1988
1989 break;
1990
1991 case SHRD_WRITE:
1992 /* Must be active on the device for this command */
1993 if (dev->ioactive != id)
1994 {
1995 serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1996 "not active on this device");
1997 break;
1998 }
1999
2000 /* Call the I/O write exit */
2001 off = fetch_hw (buf);
2002 rcd = fetch_fw (buf + 2);
2003
2004 rc = (dev->hnd->write) (dev, rcd, off, buf + 6, len - 6, &flag);
2005 shrdtrc(dev,"server_request write rcd %d off %d len %d flag %2.2x rc=%d\n",
2006 rcd, off, len - 6, flag, rc);
2007
2008 if (rc < 0)
2009 code = SHRD_IOERR;
2010 else
2011 code = 0;
2012
2013 /* Send response back */
2014 SHRD_SET_HDR (hdr, code, flag, dev->devnum, id, 0);
2015 serverSend (dev, ix, hdr, NULL, 0);
2016
2017 break;
2018
2019 case SHRD_SENSE:
2020 /* Must be active on the device for this command */
2021 if (dev->ioactive != id)
2022 {
2023 serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
2024 "not active on this device");
2025 break;
2026 }
2027
2028 /* Send the sense */
2029 SHRD_SET_HDR (hdr, 0, CSW_CE | CSW_DE, dev->devnum, id, dev->numsense);
2030 serverSend (dev, ix, hdr, dev->sense, dev->numsense);
2031 memset (dev->sense, 0, sizeof(dev->sense));
2032 dev->sns_pending = 0;
2033 break;
2034
2035 case SHRD_QUERY:
2036 switch (flag) {
2037
2038 case SHRD_USED:
2039 if (dev->hnd->used)
2040 rc = (dev->hnd->used) (dev);
2041 else
2042 rc = 0;
2043 store_fw (buf, rc);
2044 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2045 serverSend (dev, ix, hdr, buf, 4);
2046 break;
2047
2048 case SHRD_DEVCHAR:
2049 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, dev->numdevchar);
2050 serverSend (dev, ix, hdr, dev->devchar, dev->numdevchar);
2051 break;
2052
2053 case SHRD_DEVID:
2054 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, dev->numdevid);
2055 serverSend (dev, ix, hdr, dev->devid, dev->numdevid);
2056 break;
2057
2058 case SHRD_CKDCYLS:
2059 store_fw (buf, dev->ckdcyls);
2060 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2061 serverSend (dev, ix, hdr, buf, 4);
2062 break;
2063
2064 case SHRD_FBAORIGIN:
2065 store_fw (buf, dev->fbaorigin);
2066 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2067 serverSend (dev, ix, hdr, buf, 4);
2068 break;
2069
2070 case SHRD_FBANUMBLK:
2071 store_fw (buf, dev->fbanumblk);
2072 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2073 serverSend (dev, ix, hdr, buf, 4);
2074 break;
2075
2076 case SHRD_FBABLKSIZ:
2077 store_fw (buf, dev->fbablksiz);
2078 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2079 serverSend (dev, ix, hdr, buf, 4);
2080 break;
2081
2082 default:
2083 serverError (dev, ix, SHRD_ERROR_INVALID, cmd,
2084 "invalid query request");
2085 break;
2086 } /* switch (flag) for SHRD_QUERY */
2087 break;
2088
2089 case SHRD_COMPRESS:
2090 #ifdef HAVE_LIBZ
2091 dev->shrd[ix]->comp = (flag & 0x0f);
2092 store_hw (buf, dev->shrd[ix]->comp);
2093 #else
2094 store_hw (buf, 0);
2095 #endif
2096 dev->shrd[ix]->comps = (flag & 0xf0) >> 4;
2097 SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 2);
2098 serverSend (dev, ix, hdr, buf, 2);
2099 break;
2100
2101 default:
2102 serverError (dev, ix, SHRD_ERROR_INVALID, cmd,
2103 "invalid request");
2104 break;
2105 } /* switch (cmd) */
2106 } /* serverRequest */
2107
2108 /*-------------------------------------------------------------------
2109 * Locate the SHRD block for a socket (server side)
2110 *-------------------------------------------------------------------*/
serverLocate(DEVBLK * dev,int id,int * avail)2111 static int serverLocate (DEVBLK *dev, int id, int *avail)
2112 {
2113 int i; /* Loop index */
2114
2115 if (avail) *avail = -1;
2116 for (i = 0; i < SHARED_MAX_SYS; i++)
2117 {
2118 if (dev->shrd[i])
2119 {
2120 if (dev->shrd[i]->id == id)
2121 return i;
2122 }
2123 else if (avail && *avail < 0)
2124 *avail = i;
2125 }
2126 return -1;
2127 } /* serverLocate */
2128
2129 /*-------------------------------------------------------------------
2130 * Return a new Identifier (server side)
2131 *-------------------------------------------------------------------*/
serverId(DEVBLK * dev)2132 static int serverId (DEVBLK *dev)
2133 {
2134 int i; /* Loop index */
2135 int id; /* Identifier */
2136
2137 do {
2138 ++dev->shrdid;
2139 dev->shrdid &= 0xffff;
2140 if (dev->shrdid == DEV_SYS_LOCAL
2141 || dev->shrdid == DEV_SYS_NONE)
2142 dev->shrdid = 1;
2143 id = dev->shrdid;
2144
2145 for (i = 0; i < SHARED_MAX_SYS; i++)
2146 if (dev->shrd[i] && dev->shrd[i]->id == id)
2147 break;
2148
2149 } while (i < SHARED_MAX_SYS);
2150
2151 return id;
2152 } /* serverId */
2153
2154 /*-------------------------------------------------------------------
2155 * Respond with an error message (server side)
2156 *-------------------------------------------------------------------*/
serverError(DEVBLK * dev,int ix,int code,int status,char * msg)2157 static int serverError (DEVBLK *dev, int ix, int code, int status,
2158 char *msg)
2159 {
2160 int rc; /* Return code */
2161 size_t len; /* Message length */
2162 BYTE hdr[SHRD_HDR_SIZE]; /* Header */
2163
2164 /* Get message length */
2165 len = strlen(msg) + 1;
2166 if (len > SHARED_MAX_MSGLEN)
2167 len = SHARED_MAX_MSGLEN;
2168
2169 SHRD_SET_HDR (hdr, code, status, dev ? dev->devnum : 0,
2170 ix < 0 ? 0 : dev->shrd[ix]->id, (U16)len);
2171
2172 shrdtrc(dev,"server_error %2.2x %2.2x: %s\n", code, status, msg);
2173
2174 rc = serverSend (dev, ix, hdr, (BYTE *)msg, (int)len);
2175 return rc;
2176
2177 } /* serverError */
2178
2179 /*-------------------------------------------------------------------
2180 * Send data (server side)
2181 *-------------------------------------------------------------------*/
serverSend(DEVBLK * dev,int ix,BYTE * hdr,BYTE * buf,int buflen)2182 static int serverSend (DEVBLK *dev, int ix, BYTE *hdr, BYTE *buf,
2183 int buflen)
2184 {
2185 int rc; /* Return code */
2186 int sock; /* Socket number */
2187 BYTE code; /* Header code */
2188 BYTE status; /* Header status */
2189 U16 devnum; /* Header device number */
2190 int id; /* Header identifier */
2191 int len; /* Header length */
2192 int hdrlen; /* Header length + other data*/
2193 BYTE *sendbuf = NULL; /* Send buffer */
2194 int sendlen; /* Send length */
2195 BYTE cbuf[SHRD_HDR_SIZE + 65536]; /* Combined buffer */
2196
2197 /* Make buf, buflen consistent if no additional data to be sent */
2198 if (buf == NULL) buflen = 0;
2199 else if (buflen == 0) buf = NULL;
2200
2201 /* Calculate length of header, may contain additional data */
2202 SHRD_GET_HDR(hdr, code, status, devnum, id, len);
2203 hdrlen = SHRD_HDR_SIZE + (len - buflen);
2204 sendlen = hdrlen + buflen;
2205
2206 /* Check if buf is adjacent to the header */
2207 if (buf && hdr + hdrlen == buf)
2208 {
2209 hdrlen += buflen;
2210 buf = NULL;
2211 buflen = 0;
2212 }
2213
2214 /* Send only the header buffer if `buf' is empty */
2215 if (buflen == 0) sendbuf = hdr;
2216
2217 /* Get socket number; if `ix' < 0 we don't have a device yet */
2218 if (ix >= 0)
2219 sock = dev->shrd[ix]->fd;
2220 else
2221 {
2222 sock = -ix;
2223 dev = NULL;
2224 }
2225
2226 shrdtrc(dev,"server_send %2.2x %2.2x %2.2x %d %d\n",
2227 code, status, devnum, id, len);
2228
2229 #ifdef HAVE_LIBZ
2230 /* Compress the buf */
2231 if (ix >= 0 && dev->shrd[ix]->comp != 0
2232 && code == SHRD_OK && status == 0
2233 && hdrlen - SHRD_HDR_SIZE <= SHRD_COMP_MAX_OFF
2234 && buflen >= SHARED_COMPRESS_MINLEN)
2235 {
2236 unsigned long newlen;
2237 int off = hdrlen - SHRD_HDR_SIZE;
2238 sendbuf = cbuf;
2239 newlen = sizeof(cbuf) - hdrlen;
2240 memcpy (cbuf, hdr, hdrlen);
2241 rc = compress2 (cbuf + hdrlen, &newlen,
2242 buf, buflen, dev->shrd[ix]->comp);
2243 if (rc == Z_OK && (int)newlen < buflen)
2244 {
2245 /* Setup to use the compressed buffer */
2246 sendlen = hdrlen + newlen;
2247 buflen = 0;
2248 code = SHRD_COMP;
2249 status = (SHRD_LIBZ << 4) | off;
2250 SHRD_SET_HDR (cbuf, code, status, devnum, id, newlen + off);
2251 shrdtrc(dev,"server_send %2.2x %2.2x %2.2x %d %d (compressed)\n",
2252 code,status,devnum,id,(int)newlen+off);
2253 }
2254 }
2255 #endif
2256
2257 /* Build combined (hdr + data) buffer */
2258 if (buflen > 0)
2259 {
2260 sendbuf = cbuf;
2261 memcpy (cbuf, hdr, hdrlen);
2262 memcpy (cbuf + hdrlen, buf, buflen);
2263 }
2264
2265 /* Send the combined header and data */
2266 rc = send (sock, sendbuf, sendlen, 0);
2267
2268 /* Process return code */
2269 if (rc < 0)
2270 {
2271 logmsg(_("HHCSH041E %4.4X send error %d id=%d: %s\n"),
2272 dev->devnum, HSO_errno, id, strerror(HSO_errno));
2273 dev->shrd[ix]->disconnect = 1;
2274 }
2275
2276 return rc;
2277
2278 } /* serverSend */
2279
2280 /*-------------------------------------------------------------------
2281 * Determine if a client can be disconnected (server side)
2282 *-------------------------------------------------------------------*/
serverDisconnectable(DEVBLK * dev,int ix)2283 static int serverDisconnectable (DEVBLK *dev, int ix) {
2284
2285 if (dev->shrd[ix]->waiting || dev->shrd[ix]->pending
2286 || dev->ioactive == dev->shrd[ix]->id)
2287 return 0;
2288 else
2289 return 1;
2290 } /* serverDisconnectable */
2291
2292 /*-------------------------------------------------------------------
2293 * Disconnect a client (server side)
2294 * dev->lock *must* be held
2295 *-------------------------------------------------------------------*/
serverDisconnect(DEVBLK * dev,int ix)2296 static void serverDisconnect (DEVBLK *dev, int ix) {
2297 int id; /* Client identifier */
2298 int i; /* Loop index */
2299
2300 id = dev->shrd[ix]->id;
2301
2302 //FIXME: Handle a disconnected busy client better
2303 // Perhaps a disconnect timeout value... this will
2304 // give the client time to reconnect.
2305
2306 /* If the device is active by the client then extricate it.
2307 This is *not* a good situation */
2308 if (dev->ioactive == id)
2309 {
2310 logmsg(_("HHCSH042W %4.4X busy client being removed id=%d %s\n"),
2311 dev->devnum, id, dev->reserved ? "reserved" : "");
2312
2313 /* Call the I/O release exit if reserved by this client */
2314 if (dev->reserved && dev->hnd->release)
2315 (dev->hnd->release) (dev);
2316
2317 /* Call the channel program end exit */
2318 if (dev->hnd->end)
2319 (dev->hnd->end) (dev);
2320
2321 /* Reset any `waiting' bits */
2322 for (i = 0; i < SHARED_MAX_SYS; i++)
2323 if (dev->shrd[i])
2324 dev->shrd[i]->waiting = 0;
2325
2326 /* Make the device available */
2327 if (dev->suspended) {
2328 dev->ioactive = DEV_SYS_LOCAL;
2329 dev->busy = 1;
2330 }
2331 else
2332 {
2333 dev->ioactive = DEV_SYS_NONE;
2334 dev->busy = 0;
2335 }
2336
2337 /* Notify any waiters */
2338 if (dev->iowaiters)
2339 signal_condition (&dev->iocond);
2340 }
2341
2342 logmsg(_("HHCSH043I %s disconnected from %4.4X id=%d\n"),
2343 dev->shrd[ix]->ipaddr, dev->devnum, id);
2344
2345 /* Release the SHRD block */
2346 close_socket (dev->shrd[ix]->fd);
2347 free (dev->shrd[ix]->ipaddr);
2348 free (dev->shrd[ix]);
2349 dev->shrd[ix] = NULL;
2350
2351 dev->shrdconn--;
2352 } /* serverDisconnect */
2353
2354 /*-------------------------------------------------------------------
2355 * Return client ip
2356 *-------------------------------------------------------------------*/
clientip(int sock)2357 static char *clientip (int sock)
2358 {
2359 int rc; /* Return code */
2360 struct sockaddr_in client; /* Client address structure */
2361 socklen_t namelen; /* Length of client structure*/
2362
2363 namelen = sizeof(client);
2364 rc = getpeername (sock, (struct sockaddr *)&client, &namelen);
2365 return inet_ntoa(client.sin_addr);
2366
2367 } /* clientip */
2368
2369 /*-------------------------------------------------------------------
2370 * Find device by device number
2371 *-------------------------------------------------------------------*/
findDevice(U16 devnum)2372 static DEVBLK *findDevice (U16 devnum)
2373 {
2374 DEVBLK *dev; /* -> Device block */
2375
2376 for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
2377 if (dev->devnum == devnum) break;
2378 return dev;
2379
2380 } /* findDevice */
2381
2382 /*-------------------------------------------------------------------
2383 * Connect a new client
2384 *-------------------------------------------------------------------*/
serverConnect(int * psock)2385 static void *serverConnect (int *psock)
2386 {
2387 int csock; /* Connection socket */
2388 int rc; /* Return code */
2389 BYTE cmd; /* Request command */
2390 BYTE flag; /* Request flag */
2391 U16 devnum; /* Request device number */
2392 int id; /* Request id */
2393 int len; /* Request data length */
2394 int ix; /* Client index */
2395 DEVBLK *dev=NULL; /* -> Device block */
2396 time_t now; /* Current time */
2397 fd_set selset; /* Read bit map for select */
2398 int maxfd; /* Max fd for select */
2399 struct timeval wait; /* Wait time for select */
2400 BYTE hdr[SHRD_HDR_SIZE + 65536]; /* Header + buffer */
2401 BYTE *buf = hdr + SHRD_HDR_SIZE; /* Buffer */
2402 char *ipaddr = NULL; /* IP addr of connected peer */
2403
2404 csock = *psock;
2405 free (psock);
2406 ipaddr = clientip(csock);
2407
2408 shrdtrc(dev,"server_connect %s sock %d\n",ipaddr,csock);
2409
2410 rc = recvData(csock, hdr, buf, 65536, 1);
2411 if (rc < 0)
2412 {
2413 logmsg(_("HHCSH0474 %s connect failed\n"), ipaddr);
2414 close_socket (csock);
2415 return NULL;
2416 }
2417 SHRD_GET_HDR (hdr, cmd, flag, devnum, id, len);
2418
2419 /* Error if not a connect request */
2420 if (id == 0 && cmd != SHRD_CONNECT)
2421 {
2422 serverError (NULL, -csock, SHRD_ERROR_NOTCONN, cmd,
2423 "not a connect request");
2424 close_socket (csock);
2425 return NULL;
2426 }
2427
2428 /* Locate the device */
2429 dev = findDevice (devnum);
2430
2431 /* Error if device not found */
2432 if (dev == NULL)
2433 {
2434 serverError (NULL, -csock, SHRD_ERROR_NODEVICE, cmd,
2435 "device not found");
2436 close_socket (csock);
2437 return NULL;
2438 }
2439
2440 /* Obtain the device lock */
2441 obtain_lock (&dev->lock);
2442
2443 /* Find an available slot for the connection */
2444 rc = serverLocate (dev, id, &ix);
2445
2446 /* Error if already connected */
2447 if (rc >= 0)
2448 {
2449 release_lock (&dev->lock);
2450 serverError (NULL, -csock, SHRD_ERROR_NODEVICE, cmd,
2451 "already connected");
2452 close_socket (csock);
2453 return NULL;
2454 }
2455
2456 /* Error if no available slot */
2457 if (ix < 0)
2458 {
2459 release_lock (&dev->lock);
2460 serverError (NULL, -csock, SHRD_ERROR_NOTAVAIL, cmd,
2461 "too many connections");
2462 close_socket (csock);
2463 return NULL;
2464 }
2465
2466 /* Obtain SHRD block */
2467 dev->shrd[ix] = calloc (sizeof(SHRD), 1);
2468
2469 /* Error if not obtained */
2470 if (dev->shrd[ix] == NULL)
2471 {
2472 release_lock (&dev->lock);
2473 serverError (NULL, -csock, SHRD_ERROR_NOMEM, cmd,
2474 "calloc() failure");
2475 close_socket (csock);
2476 return NULL;
2477 }
2478
2479 /* Initialize the SHRD block */
2480 dev->shrd[ix]->pending = 1;
2481 dev->shrd[ix]->havehdr = 1;
2482 if (id == 0) id = serverId (dev);
2483 dev->shrd[ix]->id = id;
2484 dev->shrd[ix]->fd = csock;
2485 dev->shrd[ix]->ipaddr = strdup(ipaddr);
2486 dev->shrd[ix]->time = time (NULL);
2487 dev->shrd[ix]->purgen = -1;
2488 dev->shrdconn++;
2489 SHRD_SET_HDR (dev->shrd[ix]->hdr, cmd, flag, devnum, id, len);
2490
2491 logmsg (_("HHCSH053I %s connected to %4.4X id=%d\n"),
2492 ipaddr, devnum, id);
2493
2494 /* Return if device thread already active */
2495 if (dev->shrdtid)
2496 {
2497 if (dev->shrdwait)
2498 {
2499 signal_thread (dev->shrdtid, SIGUSR2);
2500 }
2501 release_lock (&dev->lock);
2502 return NULL;
2503 }
2504 dev->shrdtid = thread_id();
2505
2506 /* This thread will be the shared device thread */
2507 logmsg (_("HHCSH045I Shared device %4.4X thread started: "
2508 "tid="TIDPAT", pid=%d\n"),
2509 dev->devnum, thread_id(), getpid());
2510
2511 while (dev->shrdconn)
2512 {
2513 FD_ZERO (&selset);
2514 maxfd = -1;
2515
2516 /* Get the current time */
2517 now = time (NULL);
2518
2519 for (ix = 0; ix < SHARED_MAX_SYS; ix++)
2520 {
2521 if (dev->shrd[ix])
2522 {
2523 /* Exit loop if pending and not waiting */
2524 if (dev->shrd[ix]->pending && !dev->shrd[ix]->waiting)
2525 break;
2526
2527 /* Disconnect if not a valid socket */
2528 if ( !socket_is_socket( dev->shrd[ix]->fd ) )
2529 dev->shrd[ix]->disconnect = 1;
2530
2531 /* See if the connection can be timed out */
2532 else if (now - dev->shrd[ix]->time > SHARED_TIMEOUT
2533 && serverDisconnectable (dev, ix))
2534 dev->shrd[ix]->disconnect = 1;
2535
2536 /* Disconnect if the disconnect bit is set */
2537 if (dev->shrd[ix]->disconnect)
2538 serverDisconnect (dev, ix);
2539
2540 /* Otherwise set the fd if not waiting */
2541 else if (!dev->shrd[ix]->waiting)
2542 {
2543 FD_SET (dev->shrd[ix]->fd, &selset);
2544 if (dev->shrd[ix]->fd >= maxfd)
2545 maxfd = dev->shrd[ix]->fd + 1;
2546 shrdtrc(dev,"select set %d id=%d\n",dev->shrd[ix]->fd,dev->shrd[ix]->id);
2547 }
2548 }
2549
2550 }
2551
2552 /* Wait for a request if no pending requests */
2553 if (ix >= SHARED_MAX_SYS)
2554 {
2555 /* Exit thread if nothing to select */
2556 if (maxfd < 0) continue;
2557
2558 /* Wait for a file descriptor to become busy */
2559 wait.tv_sec = 10; /*SHARED_SELECT_WAIT;*/
2560 wait.tv_usec = 0;
2561 release_lock (&dev->lock);
2562
2563 dev->shrdwait = 1;
2564 rc = select ( maxfd, &selset, NULL, NULL, &wait );
2565 dev->shrdwait = 0;
2566
2567 obtain_lock (&dev->lock);
2568
2569 shrdtrc(dev,"select rc %d\n",rc);
2570
2571 if (rc == 0) continue;
2572
2573 if (rc < 0 )
2574 {
2575 if (HSO_errno == HSO_EINTR || HSO_errno == HSO_EBADF) continue;
2576 logmsg(_("HHCSH046E select: %s\n"), strerror(HSO_errno));
2577 break;
2578 }
2579
2580 /* Find any pending requests */
2581 for (ix = 0; ix < SHARED_MAX_SYS; ix++)
2582 {
2583 if (dev->shrd[ix]
2584 && FD_ISSET(dev->shrd[ix]->fd, &selset))
2585 {
2586 dev->shrd[ix]->pending = 1;
2587 shrdtrc(dev,"select isset %d id=%d\n",dev->shrd[ix]->fd,dev->shrd[ix]->id);
2588 }
2589 }
2590 continue;
2591 }
2592
2593 /* Found a pending request */
2594 release_lock (&dev->lock);
2595
2596 shrdtrc(dev,"select ready %d id=%d\n",dev->shrd[ix]->fd,dev->shrd[ix]->id);
2597
2598 if (dev->shrd[ix]->havehdr)
2599 {
2600 /* Copy the saved start/resume packet */
2601 memcpy (hdr, dev->shrd[ix]->hdr, SHRD_HDR_SIZE);
2602 dev->shrd[ix]->havehdr = dev->shrd[ix]->waiting = 0;
2603 }
2604 else
2605 {
2606 /* Read the request packet */
2607 rc = recvData (dev->shrd[ix]->fd, hdr, buf, 65536, 1);
2608 if (rc < 0)
2609 {
2610 logmsg(_("HHCSH047E %4.4X %s recv error id=%d\n"),
2611 dev->devnum, dev->shrd[ix]->ipaddr, dev->shrd[ix]->id);
2612 dev->shrd[ix]->disconnect = 1;
2613 dev->shrd[ix]->pending = 0;
2614 obtain_lock (&dev->lock);
2615 continue;
2616 }
2617 }
2618
2619 /* Process the request */
2620 serverRequest (dev, ix, hdr, buf);
2621
2622 obtain_lock (&dev->lock);
2623
2624 /* If the `waiting' bit is on then the start/resume request
2625 failed because the device is busy on some other remote
2626 system. We only need to save the header because the data
2627 is ignored for start/resume.
2628 */
2629 if (dev->shrd[ix]->waiting)
2630 {
2631 memcpy (dev->shrd[ix]->hdr, hdr, SHRD_HDR_SIZE);
2632 dev->shrd[ix]->havehdr = 1;
2633 }
2634 else
2635 dev->shrd[ix]->pending = 0;
2636 }
2637
2638 dev->shrdtid = 0;
2639 release_lock (&dev->lock);
2640
2641 logmsg (_("HHCSH048I Shared device %4.4X thread stopping\n"),
2642 dev->devnum);
2643
2644 return NULL;
2645
2646 } /* serverConnect */
2647
2648 /*-------------------------------------------------------------------
2649 * General trace routine for shared devices
2650 *-------------------------------------------------------------------*/
shrdtrc(DEVBLK * dev,char * msg,...)2651 static void shrdtrc (DEVBLK *dev, char *msg, ...)
2652 {
2653 int dt;
2654 struct timeval tv;
2655 SHRD_TRACE s;
2656 va_list vl;
2657
2658 dt = (dev != NULL && (dev->ccwtrace||dev->ccwstep));
2659 if (dt == 0 && sysblk.shrdtrace == 0) return;
2660
2661 va_start(vl,msg);
2662 gettimeofday(&tv, NULL);
2663 sprintf ((char *)s,
2664 "%6.6ld" "." "%6.6ld %4.4X:",
2665 tv.tv_sec, (long)(tv.tv_usec), dev ? dev->devnum : 0);
2666 vsnprintf ((char *)s + strlen(s), sizeof(s) - strlen(s),
2667 msg, vl);
2668 if (dt)
2669 {
2670 logmsg (s+14);
2671 }
2672 if (sysblk.shrdtrace)
2673 {
2674 SHRD_TRACE *p = sysblk.shrdtracep++;
2675 if (p >= sysblk.shrdtracex)
2676 {
2677 p = sysblk.shrdtrace;
2678 sysblk.shrdtracep = p + 1;
2679 }
2680 if (p) memcpy(p, s, sizeof(*p));
2681 }
2682
2683 } /* shrdtrc */
2684
2685 /*-------------------------------------------------------------------
2686 * Shared device server
2687 *-------------------------------------------------------------------*/
shared_server(void * arg)2688 DLL_EXPORT void *shared_server (void *arg)
2689 {
2690 int rc; /* Return code */
2691 int hi; /* Hi fd for select */
2692 int lsock; /* inet socket for listening */
2693 int usock; /* unix socket for listening */
2694 int rsock; /* Ready socket */
2695 int csock; /* Socket for conversation */
2696 int *psock; /* Pointer to socket */
2697 struct sockaddr_in server; /* Server address structure */
2698 #if defined( HAVE_SYS_UN_H )
2699 struct sockaddr_un userver; /* Unix address structure */
2700 #endif
2701 int optval; /* Argument for setsockopt */
2702 fd_set selset; /* Read bit map for select */
2703 TID tid; /* Negotiation thread id */
2704
2705 UNREFERENCED(arg);
2706
2707 /* Display thread started message on control panel */
2708 logmsg (_("HHCSH049I Shared device %d" "." "%d thread started: "
2709 "tid="TIDPAT", pid=%d\n"),
2710 SHARED_VERSION, SHARED_RELEASE, thread_id(), getpid());
2711
2712 /* Obtain a internet socket */
2713 lsock = socket (AF_INET, SOCK_STREAM, 0);
2714
2715 if (lsock < 0)
2716 {
2717 logmsg(_("HHCSH050E inet socket: %s\n"), strerror(HSO_errno));
2718 return NULL;
2719 }
2720
2721 /* Obtain a unix socket */
2722 #if defined( HAVE_SYS_UN_H )
2723 usock = socket (AF_UNIX, SOCK_STREAM, 0);
2724 if (usock < 0)
2725 {
2726 logmsg(_("HHCSH051W unix socket: %s\n"), strerror(HSO_errno));
2727 }
2728 #else
2729 usock = -1;
2730 #endif
2731
2732 /* Allow previous instance of socket to be reused */
2733 optval = 1;
2734 setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR,
2735 (GETSET_SOCKOPT_T*)&optval, sizeof(optval));
2736
2737 /* Prepare the sockaddr structure for the bind */
2738 memset (&server, 0, sizeof(server));
2739 server.sin_family = AF_INET;
2740 server.sin_addr.s_addr = INADDR_ANY;
2741 server.sin_port = sysblk.shrdport;
2742 server.sin_port = htons(server.sin_port);
2743
2744 /* Attempt to bind the internet socket to the port */
2745 while (1)
2746 {
2747 rc = bind (lsock, (struct sockaddr *)&server, sizeof(server));
2748 if (rc == 0 || HSO_errno != HSO_EADDRINUSE) break;
2749 logmsg (_("HHCSH052W Waiting for port %u to become free\n"),
2750 sysblk.shrdport);
2751 SLEEP(10);
2752 } /* end while */
2753
2754 if (rc != 0)
2755 {
2756 logmsg(_("HHCSH053E inet bind: %s\n"), strerror(HSO_errno));
2757 close_socket(lsock); close_socket(usock);
2758 return NULL;
2759 }
2760
2761 #if defined( HAVE_SYS_UN_H )
2762 /* Bind the unix socket */
2763 if (usock >= 0)
2764 {
2765 userver.sun_family = AF_UNIX;
2766 sprintf(userver.sun_path, "/tmp/hercules_shared.%d", sysblk.shrdport);
2767 unlink(userver.sun_path);
2768 fchmod (usock, 0700);
2769
2770 rc = bind (usock, (struct sockaddr *)&userver, sizeof(userver));
2771
2772 if (rc < 0)
2773 {
2774 logmsg(_("HHCSH054W unix bind: %s\n"), strerror(errno));
2775 close(usock);
2776 usock = -1;
2777 }
2778 }
2779 #endif // defined( HAVE_SYS_UN_H )
2780
2781 /* Put the sockets into listening state */
2782 rc = listen (lsock, SHARED_MAX_SYS);
2783
2784 if (rc < 0)
2785 {
2786 logmsg(_("HHCSH055E inet listen: %s\n"), strerror(HSO_errno));
2787 close_socket(lsock); close_socket(usock);
2788 return NULL;
2789 }
2790
2791 if (usock >= 0)
2792 {
2793 rc = listen (usock, SHARED_MAX_SYS);
2794
2795 if (rc < 0)
2796 {
2797 logmsg(_("HHCSH056W unix listen: %s\n"), strerror(HSO_errno));
2798 close_socket(usock);
2799 usock = -1;
2800 }
2801 }
2802
2803 sysblk.shrdtid = thread_id();
2804 csock = -1;
2805 if (lsock < usock)
2806 hi = usock + 1;
2807 else
2808 hi = lsock + 1;
2809
2810 logmsg(_("HHCSH057I Waiting for shared device requests on port %u\n"),
2811 sysblk.shrdport);
2812
2813 /* Handle connection requests and attention interrupts */
2814 while (!sysblk.shutdown)
2815 {
2816 /* Initialize the select parameters */
2817 FD_ZERO (&selset);
2818 FD_SET (lsock, &selset);
2819 if (usock >= 0)
2820 FD_SET (usock, &selset);
2821
2822 /* Wait for a file descriptor to become ready */
2823 rc = select ( hi, &selset, NULL, NULL, NULL );
2824
2825 if (rc == 0) continue;
2826
2827 if (rc < 0 )
2828 {
2829 if (HSO_errno == HSO_EINTR) continue;
2830 logmsg(_("HHCSH058E select: %s\n"), strerror(HSO_errno));
2831 break;
2832 }
2833
2834 /* If a client connection request has arrived then accept it */
2835 if (FD_ISSET(lsock, &selset))
2836 rsock = lsock;
2837 else if (usock >= 0 && FD_ISSET(usock, &selset))
2838 rsock = usock;
2839 else
2840 rsock = -1;
2841
2842 if (rsock > 0)
2843 {
2844 /* Accept a connection and create conversation socket */
2845 csock = accept (rsock, NULL, NULL);
2846 if (csock < 0)
2847 {
2848 logmsg(_("HHCSH059E accept: %s\n"), strerror(HSO_errno));
2849 continue;
2850 }
2851
2852 psock = malloc (sizeof (csock));
2853 if (psock == NULL)
2854 {
2855 logmsg(_("HHCSH060E malloc size %d: %s\n"),
2856 sizeof(csock), strerror(HSO_errno));
2857 close_socket (csock);
2858 continue;
2859 }
2860 *psock = csock;
2861
2862 /* Create a thread to complete the client connection */
2863 if ( create_thread (&tid, DETACHED,
2864 serverConnect, psock, "serverConnect") )
2865 {
2866 logmsg(_("HHCSH061E serverConnect create_thread: %s\n"),
2867 strerror(HSO_errno));
2868 close_socket (csock);
2869 }
2870
2871 } /* end if(rsock) */
2872
2873
2874 } /* end while */
2875
2876 /* Close the listening sockets */
2877 close_socket (lsock);
2878 #if defined( HAVE_SYS_UN_H )
2879 if (usock >= 0)
2880 {
2881 close_socket (usock);
2882 unlink(userver.sun_path);
2883 }
2884 #endif
2885
2886 sysblk.shrdtid = 0;
2887
2888 return NULL;
2889
2890 } /* end function shared_server */
2891
2892 /*-------------------------------------------------------------------
2893 * Shared device command processor
2894 *-------------------------------------------------------------------*/
shared_cmd(int argc,char * argv[],char * cmdline)2895 DLL_EXPORT int shared_cmd(int argc, char *argv[], char *cmdline)
2896 {
2897 char buf[256];
2898 char *kw, *op, c;
2899
2900 UNREFERENCED(cmdline);
2901
2902 /* Get keyword and operand */
2903 if (argc != 2 || strlen(argv[1]) > 255)
2904 {
2905 logmsg (_("HHCSH062E Invalid or missing argument 1\n"));
2906 return 0;
2907 }
2908 strcpy (buf, argv[1]);
2909 kw = strtok (buf, "=");
2910 op = strtok (NULL, " \t");
2911
2912 if (kw == NULL)
2913 {
2914 logmsg (_("HHCSH063E Invalid or missing keyword 2\n"));
2915 return 0;
2916 }
2917
2918 if (strcasecmp(kw, "trace") == 0)
2919 {
2920 int n;
2921 SHRD_TRACE *s, *p, *x, *i;
2922 s = sysblk.shrdtrace;
2923 p = sysblk.shrdtracep;
2924 x = sysblk.shrdtracex;
2925 n = sysblk.shrdtracen;
2926
2927 /* Get a new trace table if an operand was specified */
2928 if (op)
2929 {
2930 if (sscanf (op, "%d%c", &n, &c) != 1)
2931 {
2932 logmsg (_("HHCSH064E Invalid or missing value %s\n"),op);
2933 return 0;
2934 }
2935 if (s != NULL)
2936 {
2937 sysblk.shrdtrace = sysblk.shrdtracex = sysblk.shrdtracep = NULL;
2938 SLEEP (1);
2939 free (s);
2940 }
2941 sysblk.shrdtrace = sysblk.shrdtracex = sysblk.shrdtracep = NULL;
2942 sysblk.shrdtracen = 0;
2943 if (n > 0)
2944 {
2945 s = calloc (sizeof(SHRD_TRACE), n);
2946 if (s == NULL)
2947 {
2948 logmsg (_("HHCSH065E calloc() size=%d: %s\n"),
2949 sizeof(SHRD_TRACE) * n, strerror(errno));
2950 return 0;
2951 }
2952 sysblk.shrdtracen = n;
2953 sysblk.shrdtrace = sysblk.shrdtracep = s;
2954 sysblk.shrdtracex = s + n;
2955 }
2956 return 0;
2957 }
2958 /* Print the trace table */
2959 sysblk.shrdtrace = sysblk.shrdtracex = sysblk.shrdtracep = NULL;
2960 i = p;
2961 SLEEP(1);
2962 do {
2963 if (i[0] != '\0') logmsg ("%s",(char *)i);
2964 if (++i >= x) i = s;
2965 } while (i != p);
2966 memset (s, 0, n * sizeof(SHRD_TRACE));
2967 sysblk.shrdtrace = s;
2968 sysblk.shrdtracep = s;
2969 sysblk.shrdtracex = x;
2970 sysblk.shrdtracen = n;
2971 }
2972 else
2973 {
2974 logmsg (_("HHCSH066E Invalid or missing keyword %s\n"), kw);
2975 return 0;
2976 }
2977 return 0;
2978 }
2979
2980 DEVHND shared_ckd_device_hndinfo = {
2981 &shared_ckd_init, /* Device Initialisation */
2982 &ckddasd_execute_ccw, /* Device CCW execute */
2983 &shared_ckd_close, /* Device Close */
2984 &ckddasd_query_device, /* Device Query */
2985 &shared_start, /* Device Start channel pgm */
2986 &shared_end, /* Device End channel pgm */
2987 &shared_start, /* Device Resume channel pgm */
2988 &shared_end, /* Device Suspend channel pgm */
2989 &shared_ckd_read, /* Device Read */
2990 &shared_ckd_write, /* Device Write */
2991 &shared_used, /* Device Query used */
2992 &shared_reserve, /* Device Reserve */
2993 &shared_release, /* Device Release */
2994 NULL, /* Device Attention */
2995 NULL, /* Immediate CCW Codes */
2996 NULL, /* Signal Adapter Input */
2997 NULL, /* Signal Adapter Output */
2998 &ckddasd_hsuspend, /* Hercules suspend */
2999 &ckddasd_hresume /* Hercules resume */
3000 };
3001
3002 DEVHND shared_fba_device_hndinfo = {
3003 &shared_fba_init, /* Device Initialisation */
3004 &fbadasd_execute_ccw, /* Device CCW execute */
3005 &shared_fba_close, /* Device Close */
3006 &fbadasd_query_device, /* Device Query */
3007 &shared_start, /* Device Start channel pgm */
3008 &shared_end, /* Device End channel pgm */
3009 &shared_start, /* Device Resume channel pgm */
3010 &shared_end, /* Device Suspend channel pgm */
3011 &shared_ckd_read, /* Device Read */
3012 &shared_ckd_write, /* Device Write */
3013 &shared_used, /* Device Query used */
3014 &shared_reserve, /* Device Reserve */
3015 &shared_release, /* Device Release */
3016 NULL, /* Device Attention */
3017 NULL, /* Immediate CCW Codes */
3018 NULL, /* Signal Adapter Input */
3019 NULL, /* Signal Adapter Output */
3020 &fbadasd_hsuspend, /* Hercules suspend */
3021 &fbadasd_hresume /* Hercules resume */
3022 };
3023
3024 #else
3025
shared_update_notify(DEVBLK * dev,int block)3026 int shared_update_notify (DEVBLK *dev, int block)
3027 {
3028 UNREFERENCED(dev);
3029 UNREFERENCED(block);
3030 return 0;
3031 }
shared_ckd_init(DEVBLK * dev,int argc,BYTE * argv[])3032 int shared_ckd_init (DEVBLK *dev, int argc, BYTE *argv[] )
3033 {
3034 UNREFERENCED(dev);
3035 UNREFERENCED(argc);
3036 UNREFERENCED(argv);
3037 return -1;
3038 }
shared_fba_init(DEVBLK * dev,int argc,BYTE * argv[])3039 int shared_fba_init (DEVBLK *dev, int argc, BYTE *argv[] )
3040 {
3041 UNREFERENCED(dev);
3042 UNREFERENCED(argc);
3043 UNREFERENCED(argv);
3044 return -1;
3045 }
shared_server(void * arg)3046 void *shared_server (void *arg)
3047 {
3048 UNREFERENCED(arg);
3049 logmsg (_("HHCSH999E OPTION_SHARED_DEVICES not defined"));
3050 return NULL;
3051 }
3052 int shared_cmd(int argc, char *argv[], char *cmdline);
3053 UNREFERENCED(cmdline);
3054 UNREFERENCED(argc);
3055 UNREFERENCED(argv);
3056 logmsg (_("HHCSH999E OPTION_SHARED_DEVICES not defined"));
3057 return 0;
3058 }
3059 #endif /*defined(OPTION_SHARED_DEVICES)*/
3060