1 /* SCSITAPE.C (c) Copyright "Fish" (David B. Trout), 2005-2012 */
2 /* Hercules SCSI tape handling module */
3
4 // (c) Copyright "Fish" (David B. Trout), 2005-2009. Released under
5 // the Q Public License (http://www.hercules-390.org/herclic.html)
6 // as modifications to Hercules.
7
8 /*-------------------------------------------------------------------*/
9 /* This module contains only the support for SCSI tapes. Please see */
10 /* the 'tapedev.c' (and possibly other) source module(s) for infor- */
11 /* mation regarding other supported emulated tape/media formats. */
12 /*-------------------------------------------------------------------*/
13
14 /*-------------------------------------------------------------------*/
15 /* Messages issued by this module are prefixed HHCTA3nn */
16 /*-------------------------------------------------------------------*/
17
18 #include "hstdinc.h"
19 #include "hercules.h"
20 #include "scsitape.h"
21
22 #if defined(OPTION_SCSI_TAPE)
23
24 //#define ENABLE_TRACING_STMTS // (Fish: DEBUGGING)
25
26 #ifdef ENABLE_TRACING_STMTS
27 #if !defined(DEBUG)
28 #warning DEBUG required for ENABLE_TRACING_STMTS
29 #endif
30 // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h)
31 #else
32 #undef TRACE
33 #define TRACE 1 ? ((void)0) : logmsg
34 #undef ASSERT
35 #define ASSERT(a)
36 #undef VERIFY
37 #define VERIFY(a) ((void)(a))
38 #endif
39
40 // (the following is just a [slightly] shorter name for our own internal use)
41 #define SLOW_UPDATE_STATUS_TIMEOUT MAX_NORMAL_SCSI_DRIVE_QUERY_RESPONSE_TIMEOUT_USECS
42 #define MAX_GSTAT_FREQ_USECS 1000000 // (once per second max)
43
44 /*-------------------------------------------------------------------*/
45 /* Open a SCSI tape device */
46 /* */
47 /* If successful, the file descriptor is stored in the device block */
48 /* and the return value is zero. Otherwise the return value is -1. */
49 /* */
50 /* Note that not having a tape mounted is a non-fatal error (rc==0)) */
51 /* */
52 /* If the status indicates the tape is not mounted or a good status */
53 /* cannot otherwise be obtained, the file descriptor is CLOSED but */
54 /* THE RETURN CODE IS STILL == 0 !!!! */
55 /* */
56 /* ** WARNING! ** */
57 /* */
58 /* The caller MUST check for a valid (non-negative) file descriptor */
59 /* before trying to use it if this function returns 0 == success!! */
60 /* */
61 /* A success == 0 return means the device filename CAN be opened, */
62 /* but not necessarily that the file can be used! If the file cannot */
63 /* be used (i.e. no tape mounted), the file is CLOSED but the return */
64 /* code is still == 0. */
65 /* */
66 /* The return code is -1 ONLY when the filename itself is invalid */
67 /* and the device file thus cannot even be opened. */
68 /* */
69 /*-------------------------------------------------------------------*/
open_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)70 int open_scsitape (DEVBLK *dev, BYTE *unitstat, BYTE code)
71 {
72 int rc;
73
74 /* Is an open for this device already in progress? */
75 if (dev->stape_mntdrq.link.Flink)
76 {
77 /* Yes. Device is good but no tape is mounted (yet) */
78 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
79 return 0; // (quick exit; in progress == open success)
80 }
81
82 ASSERT( dev->fd < 0 ); // (sanity check)
83 dev->fd = -1;
84 dev->sstat = GMT_DR_OPEN( -1 );
85
86 /* Open the SCSI tape device */
87 dev->readonly = 0;
88 rc = open_tape (dev->filename, O_RDWR | O_BINARY | O_NONBLOCK);
89 if (rc < 0 && EROFS == errno )
90 {
91 dev->readonly = 1;
92 rc = open_tape (dev->filename, O_RDONLY | O_BINARY | O_NONBLOCK);
93 }
94
95 /* Check for successful open */
96 if (rc < 0)
97 {
98 logmsg (_("HHCTA324E Error opening %u:%4.4X=%s; errno=%d: %s\n"),
99 SSID_TO_LCSS(dev->ssid), dev->devnum,
100 dev->filename, errno, strerror(errno));
101 build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code);
102 return -1; // (FATAL error; device cannot be opened)
103 }
104
105 define_BOT_pos( dev ); // (always after successful open)
106
107 /* Store the file descriptor in the device block */
108 dev->fd = rc;
109
110 /* Obtain the initial tape device/media status information */
111 /* and start the mount-monitoring thread if option enabled */
112 int_scsi_status_update( dev, 0 );
113
114 /* Asynchronous open now in progress? */
115 if (dev->stape_mntdrq.link.Flink)
116 {
117 /* Yes. Device is good but no tape is mounted (yet) */
118 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
119 return 0; // (quick exit; in progress == open success)
120 }
121
122 /* Finish up the open process... */
123 if ( STS_NOT_MOUNTED( dev ) )
124 {
125 /* Intervention required if no tape is currently mounted.
126 Note: we return "success" because the filename is good
127 (device CAN be opened) but close the file descriptor
128 since there's no tape currently mounted on the drive.*/
129 #if !defined( _MSVC_ )
130 int fd = dev->fd;
131 dev->fd = -1;
132 close_tape( fd );
133 #endif // !_MSVC_
134 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
135 return 0; // (because device file IS valid and CAN be opened)
136 }
137
138 /* Set variable length block processing to complete the open */
139 if ( finish_scsitape_open( dev, unitstat, code ) != 0 )
140 {
141 /* We cannot use this device; fail the open.
142 'finish_scsitape_open' has already issued
143 the error message and closed the device. */
144 return -1; // (open failure)
145 }
146 return 0; // (open success)
147
148 } /* end function open_scsitape */
149
150 /*-------------------------------------------------------------------*/
151 /* Finish SCSI Tape open: sets variable length block i/o mode... */
152 /* Returns 0 == success, -1 = failure. */
153 /*-------------------------------------------------------------------*/
154 /* THIS FUNCTION IS AN INTEGRAL PART OF TAPE OPEN PROCESSING! */
155 /* If this function fails then the overall tape device open fails! */
156 /*-------------------------------------------------------------------*/
finish_scsitape_open(DEVBLK * dev,BYTE * unitstat,BYTE code)157 int finish_scsitape_open( DEVBLK *dev, BYTE *unitstat, BYTE code )
158 {
159 int rc; /* Return code */
160 int oflags; /* re-open flags */
161 struct mtop opblk; /* Area for MTIOCTOP ioctl */
162
163 /* Switch drive over to BLOCKING-mode i/o... */
164
165 close_tape( dev->fd );
166 oflags = O_BINARY | (dev->readonly ? O_RDONLY : O_RDWR);
167 VERIFY( (dev->fd = open_tape (dev->filename, oflags)) > 0);
168
169 /* Since a tape was just mounted, reset the blockid back to zero */
170
171 dev->blockid = 0;
172 dev->fenced = 0;
173
174 /* Set the tape device to process variable length blocks */
175
176 if (!STS_WR_PROT( dev ))
177 {
178 opblk.mt_op = MTSETBLK;
179 opblk.mt_count = 0;
180
181 rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk);
182
183 if (rc < 0)
184 {
185 /* Device cannot be used; fail the open */
186 int save_errno = errno;
187 rc = dev->fd;
188 dev->fd = -1;
189 close_tape( rc );
190 errno = save_errno;
191 logmsg (_("HHCTA330E Error setting attributes for %u:%4.4X=%s; errno=%d: %s\n"),
192 SSID_TO_LCSS(dev->ssid), dev->devnum,
193 dev->filename, errno, strerror(errno));
194 build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code);
195 return -1; /* (fatal error) */
196 }
197 }
198
199 #if defined( HAVE_DECL_MTEWARN ) && HAVE_DECL_MTEWARN
200
201 // Try to request EOM/EOT (end-of-media/tape) early-warning
202
203 // Note: if it fails, oh well. There's no need to scare the
204 // user with a warning message. We'll either get the warning
205 // or we won't. Either way there's nothing we can do about it.
206 // We did the best we could.
207
208 if (!STS_WR_PROT( dev ))
209 {
210 opblk.mt_op = MTEWARN;
211 opblk.mt_count = dev->eotmargin;
212
213 ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk);
214
215 // (ignore any error; it either worked or it didn't)
216 }
217
218 #endif // defined( HAVE_DECL_MTEWARN ) && HAVE_DECL_MTEWARN
219
220 return 0; /* (success) */
221
222 } /* end function finish_scsitape_open */
223
224 /*-------------------------------------------------------------------*/
225 /* Close SCSI tape device file */
226 /*-------------------------------------------------------------------*/
close_scsitape(DEVBLK * dev)227 void close_scsitape(DEVBLK *dev)
228 {
229 int rc = 0;
230
231 obtain_lock( &sysblk.stape_lock );
232
233 // Remove drive from SCSIMOUNT thread's work queue...
234
235 if (dev->stape_mntdrq.link.Flink) {
236 RemoveListEntry( &dev->stape_mntdrq.link );
237 InitializeListLink( &dev->stape_mntdrq.link );
238 }
239
240 // Remove drive from the STATUS thread's work queue...
241
242 if (dev->stape_statrq.link.Flink) {
243 RemoveListEntry( &dev->stape_statrq.link );
244 InitializeListLink( &dev->stape_statrq.link );
245 }
246
247 // Close the file if it's open...
248 if (dev->fd >= 0)
249 {
250 if (dev->stape_close_rewinds)
251 {
252 struct mtop opblk;
253 // opblk.mt_op = MTLOAD; // (not sure which is more correct)
254 opblk.mt_op = MTREW;
255 opblk.mt_count = 1;
256
257 if ((rc = ioctl_tape ( dev->fd, MTIOCTOP, (char*)&opblk)) != 0)
258 {
259 logmsg (_("HHCTA373W Error rewinding %u:%4.4X=%s; errno=%d: %s\n"),
260 SSID_TO_LCSS(dev->ssid), dev->devnum,
261 dev->filename, errno, strerror(errno));
262 }
263 }
264
265 // Close tape drive...
266 close_tape( dev->fd );
267
268 dev->fd = -1;
269 dev->blockid = -1;
270 dev->curfilen = 0;
271 dev->nxtblkpos = 0;
272 dev->prvblkpos = -1;
273 }
274
275 dev->sstat = GMT_DR_OPEN(-1); // (forced)
276 dev->fenced = (rc >= 0) ? 0 : 1;
277
278 release_lock( &sysblk.stape_lock );
279
280 } /* end function close_scsitape */
281
282 /*-------------------------------------------------------------------*/
283 /* Read a block from a SCSI tape device */
284 /* */
285 /* If successful, return value is block length read. */
286 /* If a tapemark was read, the return value is zero, and the */
287 /* current file number in the device block is incremented. */
288 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
289 /*-------------------------------------------------------------------*/
read_scsitape(DEVBLK * dev,BYTE * buf,BYTE * unitstat,BYTE code)290 int read_scsitape (DEVBLK *dev, BYTE *buf, BYTE *unitstat,BYTE code)
291 {
292 int rc;
293 /* int save_errno; */
294
295 rc = read_tape (dev->fd, buf, MAX_BLKLEN);
296
297 if (rc >= 0)
298 {
299 dev->blockid++;
300
301 /* Increment current file number if tapemark was read */
302 if (rc == 0)
303 dev->curfilen++;
304
305 /* Return block length or zero if tapemark */
306 return rc;
307 }
308
309 /* Handle read error condition */
310
311 logmsg (_("HHCTA332E Error reading data block from %u:%4.4X=%s; errno=%d: %s\n"),
312 SSID_TO_LCSS(dev->ssid), dev->devnum,
313 dev->filename, errno, strerror(errno));
314
315 if ( STS_NOT_MOUNTED( dev ) )
316 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
317 else
318 build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code);
319
320 return -1;
321
322 } /* end function read_scsitape */
323
324 /*-------------------------------------------------------------------*/
325 /* Write a block to a SCSI tape device */
326 /* */
327 /* If successful, return value is zero. */
328 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
329 /*-------------------------------------------------------------------*/
write_scsitape(DEVBLK * dev,BYTE * buf,U16 len,BYTE * unitstat,BYTE code)330 int write_scsitape (DEVBLK *dev, BYTE *buf, U16 len,
331 BYTE *unitstat, BYTE code)
332 {
333 int rc;
334 int save_errno;
335
336 /* Write data block to SCSI tape device */
337
338 rc = write_tape (dev->fd, buf, len);
339
340 #if defined( _MSVC_ )
341 if (errno == ENOSPC)
342 dev->eotwarning = 1;
343 #endif
344
345 if (rc >= len)
346 {
347 dev->blockid++;
348 return 0;
349 }
350
351 /* LINUX EOM BEHAVIOUR WHEN WRITING
352
353 When the end of medium early warning is encountered,
354 the current write is finished and the number of bytes
355 is returned. The next write returns -1 and errno is
356 set to ENOSPC. To enable writing a trailer, the next
357 write is allowed to proceed and, if successful, the
358 number of bytes is returned. After this, -1 and the
359 number of bytes are alternately returned until the
360 physical end of medium (or some other error) occurs.
361 */
362
363 if (errno == ENOSPC)
364 {
365 int_scsi_status_update( dev, 0 );
366
367 rc = write_tape (dev->fd, buf, len);
368
369 if (rc >= len)
370 {
371 dev->eotwarning = 1;
372 dev->blockid++;
373 return 0;
374 }
375 }
376
377 /* Handle write error condition... */
378
379 save_errno = errno;
380 {
381 logmsg (_("HHCTA333E Error writing data block to %u:%4.4X=%s; errno=%d: %s\n"),
382 SSID_TO_LCSS(dev->ssid), dev->devnum,
383 dev->filename, errno, strerror(errno));
384
385 int_scsi_status_update( dev, 0 );
386 }
387 errno = save_errno;
388
389 if ( STS_NOT_MOUNTED( dev ) )
390 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
391 else
392 {
393 if (errno == EIO)
394 {
395 if(STS_EOT(dev))
396 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
397 else
398 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
399 }
400 else
401 build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code);
402 }
403
404 return -1;
405
406 } /* end function write_scsitape */
407
408 /*-------------------------------------------------------------------*/
409 /* Write a tapemark to a SCSI tape device */
410 /* */
411 /* If successful, return value is zero. */
412 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
413 /*-------------------------------------------------------------------*/
write_scsimark(DEVBLK * dev,BYTE * unitstat,BYTE code)414 int write_scsimark (DEVBLK *dev, BYTE *unitstat,BYTE code)
415 {
416 int rc, save_errno;
417
418 /* Write tape mark to SCSI tape */
419
420 rc = int_write_scsimark( dev );
421
422 #if defined( _MSVC_ )
423 if (errno == ENOSPC)
424 dev->eotwarning = 1;
425 #endif
426
427 if (rc >= 0)
428 return 0;
429
430 /* LINUX EOM BEHAVIOUR WHEN WRITING
431
432 When the end of medium early warning is encountered,
433 the current write is finished and the number of bytes
434 is returned. The next write returns -1 and errno is
435 set to ENOSPC. To enable writing a trailer, the next
436 write is allowed to proceed and, if successful, the
437 number of bytes is returned. After this, -1 and the
438 number of bytes are alternately returned until the
439 physical end of medium (or some other error) occurs.
440 */
441
442 if (errno == ENOSPC)
443 {
444 int_scsi_status_update( dev, 0 );
445
446 if (int_write_scsimark( dev ) >= 0)
447 {
448 dev->eotwarning = 1;
449 return 0;
450 }
451 }
452
453 /* Handle write error condition... */
454
455 save_errno = errno;
456 {
457 logmsg (_("HHCTA334E Error writing tapemark to %u:%4.4X=%s; errno=%d: %s\n"),
458 SSID_TO_LCSS(dev->ssid), dev->devnum,
459 dev->filename, errno, strerror(errno));
460
461 int_scsi_status_update( dev, 0 );
462 }
463 errno = save_errno;
464
465 if ( STS_NOT_MOUNTED( dev ) )
466 {
467 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
468 }
469 else
470 {
471 switch(errno)
472 {
473 case EIO:
474 if(STS_EOT(dev))
475 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
476 else
477 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
478 break;
479 case ENOSPC:
480 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
481 break;
482 default:
483 build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code);
484 break;
485 }
486 }
487
488 return -1;
489
490 } /* end function write_scsimark */
491
492 /*-------------------------------------------------------------------*/
493 /* (internal 'write_scsimark' helper function) */
494 /*-------------------------------------------------------------------*/
int_write_scsimark(DEVBLK * dev)495 int int_write_scsimark (DEVBLK *dev) // (internal function)
496 {
497 int rc;
498 struct mtop opblk;
499
500 opblk.mt_op = MTWEOF;
501 opblk.mt_count = 1;
502
503 rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk);
504
505 if (rc >= 0)
506 {
507 /* Increment current file number since tapemark was written */
508 /*dev->curfilen++;*/ /* (CCW processor handles this automatically
509 so there's no need for us to do it here) */
510
511 /* (tapemarks count as block identifiers too!) */
512 dev->blockid++;
513 }
514
515 return rc;
516 }
517
518 /*-------------------------------------------------------------------*/
519 /* Synchronize a SCSI tape device (i.e. commit its data to tape) */
520 /* */
521 /* If successful, return value is zero. */
522 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
523 /*-------------------------------------------------------------------*/
sync_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)524 int sync_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code)
525 {
526 int rc;
527 int save_errno;
528 struct mtop opblk;
529
530 /*
531 GA32-0566-02 ("IBM Tape Device Drivers - Programming
532 Reference"):
533
534 STIOCQRYPOS
535
536 "[...] A write filemark of count 0 is always issued to
537 the drive, which flushes all data from the buffers to
538 the tape media. After the write filemark completes, the
539 query is issued."
540
541 Write Tapemark
542
543 "[...] The WriteTapemark entry point may also be called
544 with the dwTapemarkCount parameter set to 0 and the
545 bImmediate parameter set to FALSE. This has the effect
546 of committing any uncommitted data written by previous
547 WriteFile calls ... to the media."
548 */
549
550 opblk.mt_op = MTWEOF;
551 opblk.mt_count = 0; // (zero to force a commit)
552
553 if ((rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk)) >= 0)
554 {
555 #if defined( _MSVC_ )
556 if (errno == ENOSPC)
557 dev->eotwarning = 1;
558 #endif
559 return 0; // (success)
560 }
561
562 /* LINUX EOM BEHAVIOUR WHEN WRITING
563
564 When the end of medium early warning is encountered,
565 the current write is finished and the number of bytes
566 is returned. The next write returns -1 and errno is
567 set to ENOSPC. To enable writing a trailer, the next
568 write is allowed to proceed and, if successful, the
569 number of bytes is returned. After this, -1 and the
570 number of bytes are alternately returned until the
571 physical end of medium (or some other error) occurs.
572 */
573
574 if (errno == ENOSPC)
575 {
576 int_scsi_status_update( dev, 0 );
577
578 opblk.mt_op = MTWEOF;
579 opblk.mt_count = 0; // (zero to force a commit)
580
581 if ((rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk)) >= 0)
582 {
583 dev->eotwarning = 1;
584 return 0;
585 }
586 }
587
588 /* Handle write error condition... */
589
590 save_errno = errno;
591 {
592 logmsg (_("HHCTA389E Synchronize error on "
593 "%u:%4.4X=%s; errno=%d: %s\n"),
594 SSID_TO_LCSS(dev->ssid), dev->devnum,
595 dev->filename, errno, strerror(errno));
596
597 int_scsi_status_update( dev, 0 );
598 }
599 errno = save_errno;
600
601 if ( STS_NOT_MOUNTED( dev ) )
602 {
603 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
604 }
605 else
606 {
607 switch(errno)
608 {
609 case EIO:
610 if(STS_EOT(dev))
611 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
612 else
613 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
614 break;
615 case ENOSPC:
616 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
617 break;
618 default:
619 build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code);
620 break;
621 }
622 }
623
624 return -1;
625
626 } /* end function sync_scsitape */
627
628 /*-------------------------------------------------------------------*/
629 /* Forward space over next block of SCSI tape device */
630 /* */
631 /* If successful, return value is +1. */
632 /* If the block skipped was a tapemark, the return value is zero, */
633 /* and the current file number in the device block is incremented. */
634 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
635 /*-------------------------------------------------------------------*/
fsb_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)636 int fsb_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code)
637 {
638 int rc;
639 int save_errno;
640 struct mtop opblk;
641
642 /* Forward space block on SCSI tape */
643
644 opblk.mt_op = MTFSR;
645 opblk.mt_count = 1;
646
647 rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk);
648
649 if ( rc >= 0 )
650 {
651 dev->blockid++;
652 /* Return +1 to indicate forward space successful */
653 return +1;
654 }
655
656 /* Check for spacing over a tapemark... */
657
658 save_errno = errno;
659 {
660 int_scsi_status_update( dev, 0 );
661 }
662 errno = save_errno;
663
664 // PROGRAMMING NOTE: please see the "Programming Note" in the
665 // 'bsb_scsitape' function regarding usage of the 'EOF' status
666 // to detect spacing over tapemarks.
667
668 if ( EIO == errno && STS_EOF(dev) ) // (fwd-spaced over tapemark?)
669 {
670 dev->curfilen++;
671 dev->blockid++;
672 /* Return 0 to indicate tapemark was spaced over */
673 return 0;
674 }
675
676 /* Bona fide forward space block error ... */
677
678 save_errno = errno;
679 {
680 logmsg (_("HHCTA335E Forward space block error on %u:%4.4X=%s; errno=%d: %s\n"),
681 SSID_TO_LCSS(dev->ssid), dev->devnum,
682 dev->filename, errno, strerror(errno));
683 }
684 errno = save_errno;
685
686 if ( STS_NOT_MOUNTED( dev ) )
687 {
688 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
689 }
690 else
691 {
692 switch(errno)
693 {
694 case EIO:
695 if(STS_EOT(dev))
696 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
697 else
698 build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code);
699 break;
700 case ENOSPC:
701 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
702 break;
703 default:
704 build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code);
705 break;
706 }
707 }
708
709 return -1;
710
711 } /* end function fsb_scsitape */
712
713 /*-------------------------------------------------------------------*/
714 /* Backspace to previous block of SCSI tape device */
715 /* */
716 /* If successful, return value is +1. */
717 /* If the block is a tapemark, the return value is zero, */
718 /* and the current file number in the device block is decremented. */
719 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
720 /*-------------------------------------------------------------------*/
bsb_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)721 int bsb_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code)
722 {
723 int rc;
724 int save_errno;
725 struct mtop opblk;
726 struct mtget starting_mtget;
727
728 /* PROGRAMMING NOTE: There is currently no way to distinguish
729 ** between a "normal" backspace-block error and a "backspaced-
730 ** into-loadpoint" i/o error, since the only error indication
731 ** we get [in response to a backspace block attempt] is simply
732 ** 'EIO'. (Interrogating the status AFTER the fact (to see if
733 ** we're positioned at loadpoint) doesn't tell us whether we
734 ** were already positioned at loadpoint *before* the error was
735 ** was encountered or whether we're only positioned at load-
736 ** point because we *did* in fact backspace over the very first
737 ** block on the tape (and are thus now, after the fact, sitting
738 ** at loadpoint because we *did* backspace over a block but it
739 ** just got an error for some reason).
740 **
741 ** Thus, we have absolutely no choice here but to retrieve the
742 ** status BEFORE we attempt the i/o to see if we're ALREADY at
743 ** loadpoint. If we are, then we immediately return an error
744 ** ("backspaced-into-loadpoint") *without* even attemting the
745 ** i/o at all. If we're *not* already sitting at loadpoint how-
746 ** ever, then we go ahead an attempt the i/o and then check for
747 ** an error afterwards.
748 */
749
750 /* Obtain tape status before backward space... */
751 int_scsi_status_update( dev, 0 );
752
753 /* (save the current status before the i/o in case of error) */
754 memcpy( &starting_mtget, &dev->mtget, sizeof( struct mtget ) );
755
756 /* Unit check if already at start of tape */
757 if ( STS_BOT( dev ) )
758 {
759 dev->eotwarning = 0;
760 build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code);
761 return -1;
762 }
763
764 /* Attempt the backspace i/o...*/
765 opblk.mt_op = MTBSR;
766 opblk.mt_count = 1;
767
768 rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk);
769
770 if ( rc >= 0 )
771 {
772 dev->blockid--;
773 /* Return +1 to indicate backspace successful */
774 return +1;
775 }
776
777 /* Retrieve new status after the [supposed] i/o error... */
778 save_errno = errno;
779 {
780 int_scsi_status_update( dev, 0 );
781 }
782 errno = save_errno;
783
784 /* Check for backspacing over tapemark... */
785
786 /* PROGRAMMING NOTE: on Windows, our scsi tape driver (w32stape.c)
787 ** sets 'EOF' status whenever a tapemark is spaced over in EITHER
788 ** direction (forward OR backward), whereas *nix operating systems
789 ** do not. They set 'EOF' status only when FORWARD spacing over a
790 ** tapemark but not when BACKSPACING over one.
791 **
792 ** (Apparently the EOF status was actually meant to mean that the
793 ** tape is "PHYSICALLY POSITIONED PAST [physical] eof" (i.e. past
794 ** an "eof marker" (i.e. a tapemark)) and nothing more. That is to
795 ** say, it is apparently NOT meant to mean a tapemark was passed
796 ** over, but rather only that you're "POSITIONED PAST" a tapemark.)
797 **
798 ** Therefore since 'EOF' status will thus *NEVER* be set whenever
799 ** a tapemark is spaced over in the *BACKWARD* direction [on non-
800 ** Windows operating systems], we need some other means of distin-
801 ** guishing between true backspace-block i/o errors and ordinary
802 ** spacing over a tapemark (which is NOT an i/o error but which
803 ** *is* an "out of the ordinary" (unit exception) type of event).
804 **
805 ** Extensive research on this issue has revealed the *ONLY* semi-
806 ** reliable means of distinguishing between them is by checking
807 ** the "file#" and "block#" fields of the status structure after
808 ** the supposed i/o error. If the file# is one less than it was
809 ** before and the block# is -1, then a tapemark was simply spaced
810 ** over. If the file# and block# is anything else however, then
811 ** the originally reported error was a bona-fide i/o error (i.e.
812 ** the original backspace-block (MTBSR) actually *failed*).
813 **
814 ** I say "semi-reliable" because comments seem to indicate that
815 ** the "file#" and "block#" fields of the mtget status structure
816 ** "are not always used". The best that I can tell however, is
817 ** most *nix operating systems *do* seem to maintain them. Thus,
818 ** for now, we're going to rely on their accuracy since without
819 ** them there's really no way whatsoever to distingish between
820 ** a normal backspacing over a tapemark unit exception condition
821 ** and a bona-fide i/o error (other than doing our own SCSI i/o
822 ** of course (which we don't support (yet))). -- Fish, May 2008
823 */
824 if ( EIO == errno )
825 {
826 #if defined( _MSVC_ )
827
828 /* Windows always sets 'EOF' status whenever a tapemark is
829 spaced over in EITHER direction (forward OR backward) */
830
831 if ( STS_EOF(dev) ) /* (passed over tapemark?) */
832
833 #else // !defined( _MSVC_ )
834
835 /* Unix-type systems unfortunately do NOT set 'EOF' whenever
836 backspacing over a tapemark (see PROGRAMMING NOTE above),
837 so we need to check the status struct's file# and block#
838 fields instead... */
839
840 /* (passed over tapemark?) */
841 if (1
842 && dev->mtget.mt_fileno == (starting_mtget.mt_fileno - 1)
843 && dev->mtget.mt_blkno == -1
844 )
845 #endif // defined( _MSVC_ )
846 {
847 dev->curfilen--;
848 dev->blockid--;
849 /* Return 0 to indicate tapemark was spaced over */
850 return 0;
851 }
852 }
853
854 /* Bona fide backspace block i/o error ... */
855 save_errno = errno;
856 {
857 logmsg (_("HHCTA336E Backspace block error on %u:%4.4X=%s; errno=%d: %s\n"),
858 SSID_TO_LCSS(dev->ssid), dev->devnum,
859 dev->filename, errno, strerror(errno));
860 }
861 errno = save_errno;
862
863 if ( STS_NOT_MOUNTED( dev ) )
864 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
865 else
866 {
867 if ( EIO == errno && STS_BOT(dev) )
868 {
869 dev->eotwarning = 0;
870 build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code);
871 }
872 else
873 build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code);
874 }
875
876 return -1;
877
878 } /* end function bsb_scsitape */
879
880 /*-------------------------------------------------------------------*/
881 /* Forward space to next file of SCSI tape device */
882 /* */
883 /* If successful, the return value is zero, and the current file */
884 /* number in the device block is incremented. */
885 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
886 /*-------------------------------------------------------------------*/
fsf_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)887 int fsf_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code)
888 {
889 int rc;
890 int save_errno;
891 struct mtop opblk;
892
893 /* Forward space file on SCSI tape */
894
895 opblk.mt_op = MTFSF;
896 opblk.mt_count = 1;
897
898 rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk);
899
900 /* Since we have no idea how many blocks we've skipped over
901 (as a result of doing the forward-space file), we now have
902 no clue as to what the proper current blockid should be.
903 */
904 dev->blockid = -1; // (actual position now unknown!)
905
906 if ( rc >= 0 )
907 {
908 dev->curfilen++;
909 return 0;
910 }
911
912 /* Handle error condition */
913
914 dev->fenced = 1; // (actual position now unknown!)
915
916 save_errno = errno;
917 {
918 logmsg (_("HHCTA337E Forward space file error on %u:%4.4X=%s; errno=%d: %s\n"),
919 SSID_TO_LCSS(dev->ssid), dev->devnum,
920 dev->filename, errno, strerror(errno));
921 }
922 errno = save_errno;
923
924 if ( STS_NOT_MOUNTED( dev ) )
925 {
926 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
927 }
928 else
929 {
930 switch(errno)
931 {
932 case EIO:
933 if(STS_EOT(dev))
934 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
935 else
936 build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code);
937 break;
938 case ENOSPC:
939 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
940 break;
941 default:
942 build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code);
943 break;
944 }
945 }
946
947 return -1;
948
949 } /* end function fsf_scsitape */
950
951 /*-------------------------------------------------------------------*/
952 /* Backspace to previous file of SCSI tape device */
953 /* */
954 /* If successful, the return value is zero, and the current file */
955 /* number in the device block is decremented. */
956 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
957 /*-------------------------------------------------------------------*/
bsf_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)958 int bsf_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code)
959 {
960 int rc;
961 int save_errno;
962 struct mtop opblk;
963
964 /* PROGRAMMING NOTE: There is currently no way to distinguish
965 ** between a "normal" backspace-file error and a "backspaced-
966 ** into-loadpoint" i/o error, since the only error indication
967 ** we get [in response to a backspace file attempt] is simply
968 ** 'EIO'. (Interrogating the status AFTER the fact (to see if
969 ** we're positioned at loadpoint) doesn't tell us whether we
970 ** were already positioned at loadpoint *before* the error was
971 ** was encountered or whether we're only positioned ar load-
972 ** point because we *did* in fact backspace over a BOT tape-
973 ** mark on the tape (and are thus now, after the fact, sitting
974 ** at loadpoint because we *did* backspace over a tape-mark
975 ** but it just got an error for some reason).
976 **
977 ** Thus, we have absolutely no choice here but to retrieve the
978 ** status BEFORE we attempt the i/o to see if we're ALREADY at
979 ** loadpoint. If we are, then we immediately return an error
980 ** ("backspaced-into-loadpoint") *without* even attemting the
981 ** i/o at all. If we're *not* already sitting at loadpoint how-
982 ** ever, then we go ahead an attempt the i/o and then check for
983 ** an error afterwards.
984 */
985
986 /* Obtain tape status before backward space... (no choice!) */
987 int_scsi_status_update( dev, 0 );
988
989 /* Unit check if already at start of tape */
990 if ( STS_BOT( dev ) )
991 {
992 dev->eotwarning = 0;
993 build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code);
994 return -1;
995 }
996
997 /* Attempt the backspace i/o...*/
998
999 opblk.mt_op = MTBSF;
1000 opblk.mt_count = 1;
1001
1002 rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk);
1003
1004 /* Since we have no idea how many blocks we've skipped over
1005 (as a result of doing the back-space file), we now have
1006 no clue as to what the proper current blockid should be.
1007 */
1008 dev->blockid = -1; // (actual position now unknown!)
1009
1010 if ( rc >= 0 )
1011 {
1012 dev->curfilen--;
1013 return 0;
1014 }
1015
1016 /* Handle error condition */
1017
1018 dev->fenced = 1; // (actual position now unknown!)
1019
1020 save_errno = errno;
1021 {
1022 logmsg (_("HHCTA338E Backspace file error on %u:%4.4X=%s; errno=%d: %s\n"),
1023 SSID_TO_LCSS(dev->ssid), dev->devnum,
1024 dev->filename, errno, strerror(errno));
1025 }
1026 errno = save_errno;
1027
1028 if ( STS_NOT_MOUNTED( dev ) )
1029 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
1030 else
1031 {
1032 if ( EIO == errno && STS_BOT(dev) )
1033 {
1034 dev->eotwarning = 0;
1035 build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code);
1036 }
1037 else
1038 build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code);
1039 }
1040
1041 return -1;
1042
1043 } /* end function bsf_scsitape */
1044
1045 /*-------------------------------------------------------------------*/
1046 /* Rewind an SCSI tape device */
1047 /*-------------------------------------------------------------------*/
rewind_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)1048 int rewind_scsitape(DEVBLK *dev,BYTE *unitstat,BYTE code)
1049 {
1050 int rc;
1051 /* int save_errno; */
1052 struct mtop opblk;
1053
1054 // opblk.mt_op = MTLOAD; // (not sure which is more correct)
1055 opblk.mt_op = MTREW;
1056 opblk.mt_count = 1;
1057
1058 rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk);
1059
1060 if ( rc >= 0 )
1061 {
1062 dev->sstat |= GMT_BOT( -1 ); // (forced)
1063 dev->blockid = 0;
1064 dev->curfilen = 0;
1065 dev->fenced = 0;
1066 return 0;
1067 }
1068
1069 dev->fenced = 1; // (because the rewind failed)
1070 dev->blockid = -1; // (because the rewind failed)
1071 dev->curfilen = -1; // (because the rewind failed)
1072
1073 logmsg (_("HHCTA373E Error rewinding %u:%4.4X=%s; errno=%d: %s\n"),
1074 SSID_TO_LCSS(dev->ssid), dev->devnum,
1075 dev->filename, errno, strerror(errno));
1076
1077 if ( STS_NOT_MOUNTED( dev ) )
1078 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
1079 else
1080 build_senseX(TAPE_BSENSE_REWINDFAILED,dev,unitstat,code);
1081
1082 return -1;
1083
1084 } /* end function rewind_scsitape */
1085
1086 /*-------------------------------------------------------------------*/
1087 /* Rewind Unload a SCSI tape device (and CLOSE it too!) */
1088 /*-------------------------------------------------------------------*/
int_scsi_rewind_unload(DEVBLK * dev,BYTE * unitstat,BYTE code)1089 void int_scsi_rewind_unload(DEVBLK *dev, BYTE *unitstat, BYTE code )
1090 {
1091 int rc;
1092 struct mtop opblk;
1093
1094 // opblk.mt_op = MTUNLOAD; // (not sure which is more correct)
1095 opblk.mt_op = MTOFFL;
1096 opblk.mt_count = 1;
1097
1098 rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk);
1099
1100 if ( rc >= 0 )
1101 {
1102 dev->fenced = 0;
1103
1104 if ( dev->ccwtrace || dev->ccwstep )
1105 logmsg (_("HHCTA377I Tape %u:%4.4X unloaded\n"),
1106 SSID_TO_LCSS(dev->ssid), dev->devnum);
1107
1108 // PR# tape/88: no sense with 'close_scsitape'
1109 // attempting a rewind if the tape is unloaded!
1110
1111 dev->stape_close_rewinds = 0; // (skip rewind attempt)
1112
1113 close_scsitape( dev ); // (required for REW UNLD)
1114 return;
1115 }
1116
1117 dev->fenced = 1; // (because the rewind-unload failed)
1118 dev->curfilen = -1; // (because the rewind-unload failed)
1119 dev->blockid = -1; // (because the rewind-unload failed)
1120
1121 logmsg ( _("HHCTA376E Error unloading %u:%4.4X=%s; errno=%d: %s\n" ),
1122 SSID_TO_LCSS(dev->ssid), dev->devnum,
1123 dev->filename, errno, strerror( errno ) );
1124
1125 if ( STS_NOT_MOUNTED( dev ) )
1126 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
1127 else
1128 build_senseX(TAPE_BSENSE_REWINDFAILED,dev,unitstat,code);
1129
1130 } /* end function int_scsi_rewind_unload */
1131
1132 /*-------------------------------------------------------------------*/
1133 /* Erase Gap */
1134 /*-------------------------------------------------------------------*/
erg_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)1135 int erg_scsitape( DEVBLK *dev, BYTE *unitstat, BYTE code )
1136 {
1137 #if defined( OPTION_SCSI_ERASE_GAP )
1138 int rc;
1139
1140 if (!dev->stape_no_erg)
1141 {
1142 struct mtop opblk;
1143
1144 opblk.mt_op = MTERASE;
1145 opblk.mt_count = 0; // (zero means "short" erase-gap)
1146
1147 rc = ioctl_tape( dev->fd, MTIOCTOP, (char*)&opblk );
1148
1149 #if defined( _MSVC_ )
1150 if (errno == ENOSPC)
1151 dev->eotwarning = 1;
1152 #endif
1153
1154 if ( rc < 0 )
1155 {
1156 /* LINUX EOM BEHAVIOUR WHEN WRITING
1157
1158 When the end of medium early warning is encountered,
1159 the current write is finished and the number of bytes
1160 is returned. The next write returns -1 and errno is
1161 set to ENOSPC. To enable writing a trailer, the next
1162 write is allowed to proceed and, if successful, the
1163 number of bytes is returned. After this, -1 and the
1164 number of bytes are alternately returned until the
1165 physical end of medium (or some other error) occurs.
1166 */
1167
1168 if (errno == ENOSPC)
1169 {
1170 int_scsi_status_update( dev, 0 );
1171
1172 opblk.mt_op = MTERASE;
1173 opblk.mt_count = 0; // (zero means "short" erase-gap)
1174
1175 if ( (rc = ioctl_tape( dev->fd, MTIOCTOP, (char*)&opblk )) >= 0 )
1176 dev->eotwarning = 1;
1177 }
1178
1179 if ( rc < 0)
1180 {
1181 logmsg (_("HHCTA380E Erase Gap error on %u:%4.4X=%s; errno=%d: %s\n"),
1182 SSID_TO_LCSS(dev->ssid), dev->devnum,
1183 dev->filename, errno, strerror(errno));
1184 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
1185 return -1;
1186 }
1187 }
1188 }
1189
1190 return 0; // (success)
1191
1192 #else // !defined( OPTION_SCSI_ERASE_GAP )
1193
1194 UNREFERENCED ( dev );
1195 UNREFERENCED ( code );
1196 UNREFERENCED ( unitstat );
1197
1198 return 0; // (treat as nop)
1199
1200 #endif // defined( OPTION_SCSI_ERASE_GAP )
1201
1202 } /* end function erg_scsitape */
1203
1204 /*-------------------------------------------------------------------*/
1205 /* Data Security Erase */
1206 /*-------------------------------------------------------------------*/
dse_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)1207 int dse_scsitape( DEVBLK *dev, BYTE *unitstat, BYTE code )
1208 {
1209 #if defined( OPTION_SCSI_ERASE_TAPE )
1210
1211 struct mtop opblk;
1212
1213 opblk.mt_op = MTERASE;
1214 opblk.mt_count = 1; // (one means "long" erase-tape)
1215
1216 if ( ioctl_tape( dev->fd, MTIOCTOP, (char*)&opblk ) < 0 )
1217 {
1218 logmsg (_("HHCTA381E Data Security Erase error on %u:%4.4X=%s; errno=%d: %s\n"),
1219 SSID_TO_LCSS(dev->ssid), dev->devnum,
1220 dev->filename, errno, strerror(errno));
1221 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
1222 return -1;
1223 }
1224
1225 return 0; // (success)
1226
1227 #else // !defined( OPTION_SCSI_ERASE_TAPE )
1228
1229 UNREFERENCED ( dev );
1230 UNREFERENCED ( code );
1231 UNREFERENCED ( unitstat );
1232
1233 return 0; // (treat as nop)
1234
1235 #endif // defined( OPTION_SCSI_ERASE_TAPE )
1236
1237 } /* end function dse_scsitape */
1238
1239 /*-------------------------------------------------------------------*/
1240 /* readblkid_scsitape */
1241 /*-------------------------------------------------------------------*/
1242 /* Output values are returned in BIG-ENDIAN guest format... */
1243 /*-------------------------------------------------------------------*/
readblkid_scsitape(DEVBLK * dev,BYTE * logical,BYTE * physical)1244 int readblkid_scsitape ( DEVBLK* dev, BYTE* logical, BYTE* physical )
1245 {
1246 // ZZ FIXME: The two blockid fields that READ BLOCK ID
1247 // are returning are the "Channel block ID" and "Device
1248 // block ID" fields, which correspond directly to the
1249 // SCSI "First block location" and "Last block location"
1250 // fields (as returned by a READ POSITION scsi command),
1251 // so we really SHOULD be doing our own direct scsi i/o
1252 // for ourselves so we can retrieve BOTH of those values
1253 // directly from the real/actual physical device itself,
1254 // but until we can add code to Herc to do that, we must
1255 // return the same value for each since ioctl(MTIOCPOS)
1256 // only returns us one value (the logical position) and
1257 // not both that we really prefer...
1258
1259 // (And for the record, we want the "Channel block ID"
1260 // value, also known as the SCSI "First block location"
1261 // value, also known as the >>LOGICAL<< value and *NOT*
1262 // the absolute/physical device-relative value)
1263
1264 struct mtpos mtpos;
1265 BYTE blockid[4];
1266
1267 if (ioctl_tape( dev->fd, MTIOCPOS, (char*) &mtpos ) < 0 )
1268 {
1269 /* Informative ERROR message if tracing */
1270
1271 int save_errno = errno;
1272 {
1273 if ( dev->ccwtrace || dev->ccwstep )
1274 logmsg(_("HHCTA382W ioctl_tape(MTIOCPOS=MTTELL) failed on %4.4X = %s: %s\n")
1275 ,dev->devnum
1276 ,dev->filename
1277 ,strerror(errno)
1278 );
1279 }
1280 errno = save_errno;
1281
1282 return -1; // (errno should already be set)
1283 }
1284
1285 // Convert MTIOCPOS value to guest BIG-ENDIAN format...
1286
1287 mtpos.mt_blkno = CSWAP32( mtpos.mt_blkno ); // (guest <- host)
1288
1289 // Handle emulated vs. physical tape-device block-id format issue...
1290
1291 blockid_actual_to_emulated( dev, (BYTE*)&mtpos.mt_blkno, blockid );
1292
1293 // Until we can add code to Herc to do direct SCSI i/o (so that
1294 // we can retrieve BOTH values directly from the device itself),
1295 // we have no choice but to return the same value for each since
1296 // the ioctl(MTIOCPOS) call only returns the logical value and
1297 // not also the physical value that we wish it would...
1298
1299 if (logical) memcpy( logical, &blockid[0], 4 );
1300 if (physical) memcpy( physical, &blockid[0], 4 );
1301
1302 return 0; // (success)
1303
1304 } /* end function readblkid_scsitape */
1305
1306 /*-------------------------------------------------------------------*/
1307 /* locateblk_scsitape */
1308 /*-------------------------------------------------------------------*/
1309 /* Input value is passed in little-endian host format... */
1310 /*-------------------------------------------------------------------*/
locateblk_scsitape(DEVBLK * dev,U32 blockid,BYTE * unitstat,BYTE code)1311 int locateblk_scsitape ( DEVBLK* dev, U32 blockid, BYTE *unitstat, BYTE code )
1312 {
1313 int rc;
1314 struct mtop mtop;
1315
1316 UNREFERENCED( unitstat ); // (not used)
1317 UNREFERENCED( code ); // (not used)
1318
1319 // Convert the passed host-format blockid value into the proper
1320 // 32-bit vs. 22-bit guest-format the physical device expects ...
1321
1322 blockid = CSWAP32( blockid ); // (guest <- host)
1323
1324 blockid_emulated_to_actual( dev, (BYTE*)&blockid, (BYTE*)&mtop.mt_count );
1325
1326 mtop.mt_count = CSWAP32( mtop.mt_count ); // (host <- guest)
1327 mtop.mt_op = MTSEEK;
1328
1329 // Ask the actual hardware to do an actual physical locate...
1330
1331 if ((rc = ioctl_tape( dev->fd, MTIOCTOP, (char*)&mtop )) < 0)
1332 {
1333 int save_errno = errno;
1334 {
1335 if ( dev->ccwtrace || dev->ccwstep )
1336 logmsg(_("HHCTA383W ioctl_tape(MTIOCTOP=MTSEEK) failed on %4.4X = %s: %s\n")
1337 ,dev->devnum
1338 ,dev->filename
1339 ,strerror(errno)
1340 );
1341 }
1342 errno = save_errno;
1343 }
1344
1345 return rc;
1346 }
1347
1348 /*********************************************************************/
1349 /** **/
1350 /** BLOCK-ID ADJUSTMENT FUNCTIONS **/
1351 /** **/
1352 /*********************************************************************/
1353 /*
1354 The following conversion functions compensate for the fact that
1355 the emulated device type might actually be completely different
1356 from the actual real [SCSI] device being used for the emulation.
1357
1358 That is to say, the actual SCSI device being used may actually
1359 be a 3590 type device but is defined in Hercules as a 3480 (or
1360 vice-versa). Thus while the device actually behaves as a 3590,
1361 we need to emulate 3480 functionality instead (and vice-versa).
1362
1363 For 3480/3490 devices, the block ID has the following format:
1364
1365 __________ ________________________________________________
1366 | Bit | Description |
1367 |__________|________________________________________________|
1368 | 0 | Direction Bit |
1369 | | |
1370 | | 0 Wrap 1 |
1371 | | 1 Wrap 2 |
1372 |__________|________________________________________________|
1373 | 1-7 | Segment Number |
1374 |__________|________________________________________________|
1375 | 8-9 | Format Mode |
1376 | | |
1377 | | 00 3480 format |
1378 | | 01 3480-2 XF format |
1379 | | 10 3480 XF format |
1380 | | 11 Reserved |
1381 | | |
1382 | | Note: The 3480 format does not support IDRC. |
1383 |__________|________________________________________________|
1384 | 10-31 | Logical Block Number |
1385 |__________|________________________________________________|
1386
1387 For 3480's and 3490's, first block recorded on the tape has
1388 a block ID value of X'01000000', whereas for 3590 devices the
1389 block ID is a full 32 bits and the first block on the tape is
1390 block ID x'00000000'.
1391
1392 For the 32-bit to 22-bit (and vice versa) conversion, we're
1393 relying on (hoping really!) that an actual 32-bit block-id value
1394 will never actually exceed 30 bits (1-bit wrap + 7-bit segment#
1395 + 22-bit block-id) since we perform the conversion by simply
1396 splitting the low-order 30 bits of a 32-bit block-id into a sep-
1397 arate 8-bit (wrap and segment#) and 22-bit (block-id) fields,
1398 and then shifting them into their appropriate position (and of
1399 course combining/appending them for the opposite conversion).
1400
1401 As such, this of course implies that we are thus treating the
1402 wrap bit and 7-bit segment number values of a 3480/3490 "22-bit
1403 format" blockid as simply the high-order 8 bits of an actual
1404 30-bit physical blockid (which may or may not work properly on
1405 actual SCSI hardware depending on how[*] it handles inaccurate
1406 blockid values).
1407
1408
1409 -----------------
1410
1411 [*] Most(?) [SCSI] devices treat the blockid value used in a
1412 Locate CCW as simply an "approximate location" of where the
1413 block in question actually resides on the physical tape, and
1414 will, after positioning itself to the *approximate* physical
1415 location of where the block is *believed* to reside, proceed
1416 to then perform the final positioning at low-speed based on
1417 its reading of its actual internally-recorded blockid values.
1418
1419 Thus, even when the supplied Locate block-id value is wrong,
1420 the Locate should still succeed, albeit less efficiently since
1421 it may be starting at a physical position quite distant from
1422 where the actual block is actually physically located on the
1423 actual media.
1424 */
1425
1426 /*-------------------------------------------------------------------*/
1427 /* blockid_emulated_to_actual */
1428 /*-------------------------------------------------------------------*/
1429 /* Locate CCW helper: convert guest-supplied 3480 or 3590 blockid */
1430 /* to the actual SCSI hardware blockid format */
1431 /* Both I/P AND O/P are presumed to be in BIG-ENDIAN guest format */
1432 /*-------------------------------------------------------------------*/
blockid_emulated_to_actual(DEVBLK * dev,BYTE * emu_blkid,BYTE * act_blkid)1433 void blockid_emulated_to_actual
1434 (
1435 DEVBLK *dev, // ptr to Hercules device
1436 BYTE *emu_blkid, // ptr to i/p 4-byte block-id in guest storage
1437 BYTE *act_blkid // ptr to o/p 4-byte block-id for actual SCSI i/o
1438 )
1439 {
1440 if ( TAPEDEVT_SCSITAPE != dev->tapedevt )
1441 {
1442 memcpy( act_blkid, emu_blkid, 4 );
1443 return;
1444 }
1445
1446 #if defined(OPTION_SCSI_TAPE)
1447 if (0x3590 == dev->devtype)
1448 {
1449 // 3590 being emulated; guest block-id is full 32-bits...
1450
1451 if (dev->stape_blkid_32)
1452 {
1453 // SCSI using full 32-bit block-ids too. Just copy as-is...
1454
1455 memcpy( act_blkid, emu_blkid, 4 );
1456 }
1457 else
1458 {
1459 // SCSI using 22-bit block-ids. Use low-order 30 bits
1460 // of 32-bit guest-supplied blockid and convert it
1461 // into a "22-bit format" blockid value for SCSI...
1462
1463 blockid_32_to_22 ( emu_blkid, act_blkid );
1464 }
1465 }
1466 else // non-3590 being emulated; guest block-id is 22-bits...
1467 {
1468 if (dev->stape_blkid_32)
1469 {
1470 // SCSI using full 32-bit block-ids. Extract the wrap,
1471 // segment# and 22-bit blockid bits from the "22-bit
1472 // format" guest-supplied blockid value and combine
1473 // (append) them into a contiguous low-order 30 bits
1474 // of a 32-bit blockid value for SCSI to use...
1475
1476 blockid_22_to_32 ( emu_blkid, act_blkid );
1477 }
1478 else
1479 {
1480 // SCSI using 22-bit block-ids too. Just copy as-is...
1481
1482 memcpy( act_blkid, emu_blkid, 4 );
1483 }
1484 }
1485 #endif /* defined(OPTION_SCSI_TAPE) */
1486
1487 } /* end function blockid_emulated_to_actual */
1488
1489 /*-------------------------------------------------------------------*/
1490 /* blockid_actual_to_emulated */
1491 /*-------------------------------------------------------------------*/
1492 /* Read Block Id CCW helper: convert an actual SCSI block-id */
1493 /* to guest emulated 3480/3590 format */
1494 /* Both i/p and o/p are presumed to be in big-endian guest format */
1495 /*-------------------------------------------------------------------*/
blockid_actual_to_emulated(DEVBLK * dev,BYTE * act_blkid,BYTE * emu_blkid)1496 void blockid_actual_to_emulated
1497 (
1498 DEVBLK *dev, // ptr to Hercules device (for 'devtype')
1499 BYTE *act_blkid, // ptr to i/p 4-byte block-id from actual SCSI i/o
1500 BYTE *emu_blkid // ptr to o/p 4-byte block-id in guest storage
1501 )
1502 {
1503 if ( TAPEDEVT_SCSITAPE != dev->tapedevt )
1504 {
1505 memcpy( emu_blkid, act_blkid, 4 );
1506 return;
1507 }
1508
1509 #if defined(OPTION_SCSI_TAPE)
1510 if (dev->stape_blkid_32)
1511 {
1512 // SCSI using full 32-bit block-ids...
1513 if (0x3590 == dev->devtype)
1514 {
1515 // Emulated device is a 3590 too. Just copy as-is...
1516 memcpy( emu_blkid, act_blkid, 4 );
1517 }
1518 else
1519 {
1520 // Emulated device using 22-bit format. Convert...
1521 blockid_32_to_22 ( act_blkid, emu_blkid );
1522 }
1523 }
1524 else
1525 {
1526 // SCSI using 22-bit format block-ids...
1527 if (0x3590 == dev->devtype)
1528 {
1529 // Emulated device using full 32-bit format. Convert...
1530 blockid_22_to_32 ( act_blkid, emu_blkid );
1531 }
1532 else
1533 {
1534 // Emulated device using 22-bit format too. Just copy as-is...
1535 memcpy( emu_blkid, act_blkid, 4 );
1536 }
1537 }
1538 #endif /* defined(OPTION_SCSI_TAPE) */
1539
1540 } /* end function blockid_actual_to_emulated */
1541
1542 /*-------------------------------------------------------------------*/
1543 /* blockid_32_to_22 */
1544 /*-------------------------------------------------------------------*/
1545 /* Convert a 3590 32-bit blockid into 3480 "22-bit format" blockid */
1546 /* Both i/p and o/p are presumed to be in big-endian guest format */
1547 /*-------------------------------------------------------------------*/
blockid_32_to_22(BYTE * in_32blkid,BYTE * out_22blkid)1548 void blockid_32_to_22 ( BYTE *in_32blkid, BYTE *out_22blkid )
1549 {
1550 out_22blkid[0] = ((in_32blkid[0] << 2) & 0xFC) | ((in_32blkid[1] >> 6) & 0x03);
1551 out_22blkid[1] = in_32blkid[1] & 0x3F;
1552 out_22blkid[2] = in_32blkid[2];
1553 out_22blkid[3] = in_32blkid[3];
1554 }
1555
1556 /*-------------------------------------------------------------------*/
1557 /* blockid_22_to_32 */
1558 /*-------------------------------------------------------------------*/
1559 /* Convert a 3480 "22-bit format" blockid into a 3590 32-bit blockid */
1560 /* Both i/p and o/p are presumed to be in big-endian guest format */
1561 /*-------------------------------------------------------------------*/
blockid_22_to_32(BYTE * in_22blkid,BYTE * out_32blkid)1562 void blockid_22_to_32 ( BYTE *in_22blkid, BYTE *out_32blkid )
1563 {
1564 out_32blkid[0] = (in_22blkid[0] >> 2) & 0x3F;
1565 out_32blkid[1] = ((in_22blkid[0] << 6) & 0xC0) | (in_22blkid[1] & 0x3F);
1566 out_32blkid[2] = in_22blkid[2];
1567 out_32blkid[3] = in_22blkid[3];
1568 }
1569
1570 /*********************************************************************/
1571 /** **/
1572 /** INTERNAL STATUS & AUTOMOUNT FUNCTIONS **/
1573 /** **/
1574 /*********************************************************************/
1575
1576 /* Forward references... */
1577 static int int_scsi_status_wait ( DEVBLK* dev, int usecs );
1578 static void* get_stape_status_thread ( void* notused );
1579
1580 /*-------------------------------------------------------------------*/
1581 /* get_stape_status_thread */
1582 /*-------------------------------------------------------------------*/
1583 static
get_stape_status_thread(void * notused)1584 void* get_stape_status_thread( void* notused )
1585 {
1586 LIST_ENTRY* pListEntry;
1587 STSTATRQ* req;
1588 DEVBLK* dev = NULL;
1589 struct mtget mtget;
1590 int timeout;
1591
1592 UNREFERENCED(notused);
1593
1594 logmsg (_("HHCTA300I SCSI-Tape status monitoring thread started; "
1595 "tid="TIDPAT", pri=%d, pid=%d\n"),
1596 thread_id(), getpriority(PRIO_PROCESS,0), getpid());
1597
1598 // PROGRAMMING NOTE: it is EXTREMELY IMPORTANT that the status-
1599 // retrieval thread (i.e. ourselves) be set to a priority that
1600 // is AT LEAST one priority slot ABOVE what the device-threads
1601 // are currently set to in order to prevent their request for
1602 // new/updated status from erroneously timing out (thereby mis-
1603 // leading them to mistakenly believe no tape is mounted when
1604 // in acuality there is!). The issue is, the caller only waits
1605 // for so long for us to return the status to them so we better
1606 // ensure we return it to them in a timely fashion else they be
1607 // mislead to believe there's no tape mounted (since, by virtue
1608 // of their request having timed out, they presume no tape is
1609 // mounted since the retrieval took too long (which only occurs
1610 // whenever (duh!) there's no tape mounted!)). Thus, if there
1611 // *is* a tape mounted, we better be DARN sure to return them
1612 // the status as quickly as possible in order to prevent their
1613 // wait from timing out. We ensure this by setting our own pri-
1614 // ority HIGHER than theirs.
1615
1616 // PROGRAMMING NOTE: currently, it looks like each priority slot
1617 // differs from each other priority slot by '8' units, which is
1618 // why we use the value '10' here (to ensure OUR priority gets
1619 // set to the next higher slot). If this ever changes then the
1620 // below code will need to be adjusted appropriately. -- Fish
1621
1622 SETMODE( ROOT );
1623 {
1624 setpriority( PRIO_PROCESS, 0, (sysblk.devprio - 10) );
1625 }
1626 SETMODE( USER );
1627
1628 obtain_lock( &sysblk.stape_lock );
1629
1630 do
1631 {
1632 sysblk.stape_getstat_busy = 1;
1633 broadcast_condition( &sysblk.stape_getstat_cond );
1634
1635 // Process all work items currently in our queue...
1636
1637 while (!IsListEmpty( &sysblk.stape_status_link ) && !sysblk.shutdown)
1638 {
1639 pListEntry = RemoveListHead( &sysblk.stape_status_link );
1640 InitializeListLink( pListEntry );
1641 req = CONTAINING_RECORD( pListEntry, STSTATRQ, link );
1642 dev = req->dev;
1643
1644 // Status queries limited GLOBALLY to one per second,
1645 // since there's no way of knowing whether a drive is
1646 // on the same or different bus as the other drive(s).
1647
1648 for
1649 (
1650 timeout = 0
1651 ;
1652 1
1653 && !sysblk.shutdown
1654 && sysblk.stape_query_status_tod.tv_sec
1655 && !(timeout = timed_wait_condition_relative_usecs
1656 (
1657 &sysblk.stape_getstat_cond,
1658 &sysblk.stape_lock,
1659 MAX_GSTAT_FREQ_USECS,
1660 &sysblk.stape_query_status_tod
1661 ))
1662 ;
1663 );
1664
1665 if (!sysblk.shutdown)
1666 {
1667 // Query drive status...
1668
1669 // Since this may take quite a while to do if there's no tape
1670 // mounted, we release the lock before attempting to retrieve
1671 // the status and then re-acquire it afterwards...
1672
1673 release_lock( &sysblk.stape_lock );
1674 {
1675 define_BOT_pos( dev ); // (always before MTIOCGET)
1676
1677 // NOTE: the following may take up to *>10<* seconds to
1678 // complete on Windows whenever there's no tape mounted,
1679 // but apparently only with certain hardware. On a fast
1680 // quad-cpu Windows 2003 Server system with an Adaptec
1681 // AHA2944UW SCSI control for example, it completes right
1682 // away (i.e. IMMEDIATELY), whereas on a medium dual-proc
1683 // Windows 2000 Server system with TEKRAM SCSI controller
1684 // it takes *>> 10 <<* seconds!...
1685
1686 if (0 == ioctl_tape( dev->fd, MTIOCGET, (char*)&mtget ))
1687 {
1688 memcpy( &dev->mtget, &mtget, sizeof( mtget ));
1689 }
1690 }
1691 obtain_lock( &sysblk.stape_lock );
1692
1693 broadcast_condition( &dev->stape_sstat_cond );
1694 gettimeofday( &sysblk.stape_query_status_tod, NULL );
1695 }
1696
1697 } // end while (!IsListEmpty)...
1698
1699 if (!sysblk.shutdown)
1700 {
1701 // Sleep until more/new work arrives...
1702
1703 sysblk.stape_getstat_busy = 0;
1704 broadcast_condition( &sysblk.stape_getstat_cond );
1705 wait_condition( &sysblk.stape_getstat_cond,
1706 &sysblk.stape_lock );
1707 }
1708 }
1709 while (!sysblk.shutdown);
1710
1711 // (discard all work items since we're going away)
1712
1713 while (!IsListEmpty( &sysblk.stape_status_link ))
1714 {
1715 pListEntry = RemoveListHead( &sysblk.stape_status_link );
1716 InitializeListLink( pListEntry );
1717 }
1718
1719 logmsg (_("HHCTA301I SCSI-Tape status monitoring thread ended; "
1720 "tid="TIDPAT", pri=%d, pid=%d\n"),
1721 thread_id(), getpriority(PRIO_PROCESS,0), getpid());
1722
1723 sysblk.stape_getstat_busy = 0;
1724 sysblk.stape_getstat_tid = 0;
1725 broadcast_condition( &sysblk.stape_getstat_cond );
1726 release_lock( &sysblk.stape_lock );
1727
1728 return NULL;
1729
1730 } /* end function get_stape_status_thread */
1731
1732 /*-------------------------------------------------------------------*/
1733 /* int_scsi_status_wait */
1734 /*-------------------------------------------------------------------*/
1735 static
int_scsi_status_wait(DEVBLK * dev,int usecs)1736 int int_scsi_status_wait( DEVBLK* dev, int usecs )
1737 {
1738 int rc;
1739
1740 if (unlikely( dev->fd < 0 )) // (has drive been opened yet?)
1741 return -1; // (cannot proceed until it is)
1742
1743 obtain_lock( &sysblk.stape_lock );
1744
1745 // Create the status retrieval thread if it hasn't been yet.
1746 // We do the actual retrieval of the status in a worker thread
1747 // because retrieving the status from a drive that doesn't have
1748 // a tape mounted may take a long time (at least on Windows).
1749
1750 if (unlikely( !sysblk.stape_getstat_tid ))
1751 {
1752 VERIFY
1753 (
1754 create_thread
1755 (
1756 &sysblk.stape_getstat_tid,
1757 JOINABLE,
1758 get_stape_status_thread,
1759 NULL,
1760 "get_stape_status_thread"
1761 )
1762 == 0
1763 );
1764 }
1765
1766 // Add our request to its work queue if needed...
1767
1768 if (!dev->stape_statrq.link.Flink)
1769 {
1770 InsertListTail( &sysblk.stape_status_link, &dev->stape_statrq.link );
1771 }
1772
1773 // Wake up the status retrieval thread (if needed)...
1774
1775 if (!sysblk.stape_getstat_busy)
1776 {
1777 broadcast_condition( &sysblk.stape_getstat_cond );
1778 }
1779
1780 // Wait only so long for the status to be updated...
1781
1782 rc = timed_wait_condition_relative_usecs
1783 (
1784 &dev->stape_sstat_cond, // ptr to condition to wait on
1785 &sysblk.stape_lock, // ptr to controlling lock (must be held!)
1786 usecs, // max #of microseconds to wait
1787 NULL // [OPTIONAL] ptr to tod value (may be NULL)
1788 );
1789
1790 release_lock( &sysblk.stape_lock );
1791 return rc;
1792 } /* end function int_scsi_status_wait */
1793
1794 /*-------------------------------------------------------------------*/
1795 /* Check if a SCSI tape is positioned past the EOT reflector or not */
1796 /*-------------------------------------------------------------------*/
passedeot_scsitape(DEVBLK * dev)1797 int passedeot_scsitape( DEVBLK *dev )
1798 {
1799 return dev->eotwarning; // (1==past EOT reflector; 0==not)
1800 }
1801
1802 /*-------------------------------------------------------------------*/
1803 /* Determine if the tape is Ready (tape drive door status) */
1804 /* Returns: true/false: 1 = ready, 0 = NOT ready */
1805 /*-------------------------------------------------------------------*/
is_tape_mounted_scsitape(DEVBLK * dev,BYTE * unitstat,BYTE code)1806 int is_tape_mounted_scsitape( DEVBLK *dev, BYTE *unitstat, BYTE code )
1807 {
1808 UNREFERENCED(unitstat);
1809 UNREFERENCED(code);
1810
1811 /* Update tape mounted status */
1812 int_scsi_status_update( dev, 1 ); // (safe/fast internal call)
1813
1814 return ( STS_MOUNTED( dev ) );
1815 } /* end function driveready_scsitape */
1816
1817 /*-------------------------------------------------------------------*/
1818 /* Force a manual status refresh/update (DANGEROUS!) */
1819 /*-------------------------------------------------------------------*/
update_status_scsitape(DEVBLK * dev)1820 int update_status_scsitape( DEVBLK *dev ) // (external tmh call)
1821 {
1822 // * * WARNING! * *
1823
1824 // PROGRAMMING NOTE: do NOT call this function indiscriminately,
1825 // as doing so COULD cause improper functioning of the guest o/s!
1826
1827 // How? Simple: if there's already a tape job running on the guest
1828 // using the tape drive and we just so happen to request a status
1829 // update at the precise moment a guest i/o encounters a tapemark,
1830 // it's possible for US to receive the "tapemark" status and thus
1831 // cause the guest to end up NOT SEEING the tapemark! Therefore,
1832 // you should ONLY call this function whenever the current status
1833 // indicates there's no tape mounted. If the current status says
1834 // there *is* a tape mounted, you must NOT call this function!
1835
1836 // If the current status says there's a tape mounted and the user
1837 // knows this to be untrue (e.g. they manually unloaded it maybe)
1838 // then to kick off the auto-scsi-mount thread they must manually
1839 // issue the 'devinit' command themselves. We CANNOT presume that
1840 // a "mounted" status is bogus. We can ONLY safely presume that a
1841 // "UNmounted" status may possibly be bogus. Thus we only ask for
1842 // a status refresh if the current status is "not mounted" but we
1843 // purposely do NOT force a refresh if the status is "mounted"!!
1844
1845 if ( STS_NOT_MOUNTED( dev ) ) // (if no tape mounted)
1846 int_scsi_status_update( dev, 0 ); // (then probably safe)
1847
1848 return 0;
1849 } /* end function update_status_scsitape */
1850
1851 /*-------------------------------------------------------------------*/
1852 /* Update SCSI tape status (and display it if CCW tracing is active) */
1853 /*-------------------------------------------------------------------*/
int_scsi_status_update(DEVBLK * dev,int mountstat_only)1854 void int_scsi_status_update( DEVBLK* dev, int mountstat_only )
1855 {
1856 create_automount_thread( dev ); // (only if needed of course)
1857
1858 // PROGRAMMING NOTE: only normal i/o requests (as well as the
1859 // scsi_tapemountmon_thread thread whenever AUTO_SCSI_MOUNT is
1860 // enabled and active) ever actually call us with mountstat_only
1861 // set to zero (in order to update our actual status value).
1862 //
1863 // Thus if we're called with a non-zero mountstat_only argument
1864 // (meaning all the caller is interested in is whether or not
1865 // there's a tape mounted on the drive (which only the panel
1866 // and GUI threads normally do (and which they do continuously
1867 // whenever they do do it!))) then we simply return immediately
1868 // so as to cause the caller to continue using whatever status
1869 // happens to already be set for the drive (which should always
1870 // be accurate).
1871 //
1872 // This prevents us from continuously "banging on the drive"
1873 // asking for the status when in reality the status we already
1874 // have should already be accurate (since it is updated after
1875 // every i/o or automatically by the auto-mount thread)
1876
1877 if (likely(mountstat_only)) // (if only want mount status)
1878 return; // (then current should be ok)
1879
1880 // Update status...
1881
1882 if (likely(STS_MOUNTED( dev )))
1883 {
1884 // According to our current status value there is a tape mounted,
1885 // so we should wait for a full/complete/accurate status update,
1886 // regardless of however long that may take...
1887
1888 int rc;
1889 while (ETIMEDOUT == (rc = int_scsi_status_wait( dev,
1890 MAX_GSTAT_FREQ_USECS + (2 * SLOW_UPDATE_STATUS_TIMEOUT) )))
1891 {
1892 if ( dev->ccwtrace || dev->ccwstep )
1893 {
1894 logmsg (_("HHCTA343W %u:%4.4X Tape status retrieval timeout\n"),
1895 SSID_TO_LCSS(dev->ssid), dev->devnum);
1896 }
1897 }
1898 }
1899 else
1900 {
1901 // No tape is mounted (or so we believe). Attempt to retrieve
1902 // an updated tape status value, but if we cannot do so within
1903 // a reasonable period of time (SLOW_UPDATE_STATUS_TIMEOUT),
1904 // then continue using whatever our current tape status is...
1905
1906 int_scsi_status_wait( dev, SLOW_UPDATE_STATUS_TIMEOUT );
1907 }
1908
1909 create_automount_thread( dev ); // (in case status changed)
1910
1911 /* Display tape status if tracing is active */
1912 if (unlikely( dev->ccwtrace || dev->ccwstep ))
1913 {
1914 char buf[256];
1915
1916 snprintf
1917 (
1918 buf, sizeof(buf),
1919
1920 "%u:%4.4X filename=%s (%s), sstat=0x%8.8lX: %s %s"
1921
1922 ,SSID_TO_LCSS(dev->ssid)
1923 ,dev->devnum
1924 ,( (dev->filename[0]) ? (dev->filename) : ("(undefined)") )
1925 ,( (dev->fd < 0 ) ? ("closed") : ( "opened" ) )
1926 ,dev->sstat
1927 ,STS_ONLINE(dev) ? "ON-LINE" : "OFF-LINE"
1928 ,STS_MOUNTED(dev) ? "READY" : "NO-TAPE"
1929 );
1930
1931 if ( STS_TAPEMARK(dev) ) strlcat ( buf, " TAPE-MARK" , sizeof(buf) );
1932 if ( STS_EOF (dev) ) strlcat ( buf, " END-OF-FILE" , sizeof(buf) );
1933 if ( STS_BOT (dev) ) strlcat ( buf, " LOAD-POINT" , sizeof(buf) );
1934 if ( STS_EOT (dev) ) strlcat ( buf, " END-OF-TAPE" , sizeof(buf) );
1935 if ( STS_EOD (dev) ) strlcat ( buf, " END-OF-DATA" , sizeof(buf) );
1936 if ( STS_WR_PROT (dev) ) strlcat ( buf, " WRITE-PROTECT", sizeof(buf) );
1937
1938 if ( STS_BOT(dev) )
1939 dev->eotwarning = 0;
1940
1941 logmsg ( _("HHCTA323I %s\n"), buf );
1942 }
1943
1944 } /* end function int_scsi_status_update */
1945
1946 /*-------------------------------------------------------------------*/
1947 /* ASYNCHRONOUS TAPE OPEN */
1948 /* SCSI tape tape-mount monitoring thread (monitors for tape mounts) */
1949 /* Auto-started by 'int_scsi_status_update' when it notices there is */
1950 /* no tape mounted on whatever device it's checking the status of, */
1951 /* or by the ReqAutoMount function for unsatisfied mount requests. */
1952 /*-------------------------------------------------------------------*/
create_automount_thread(DEVBLK * dev)1953 void create_automount_thread( DEVBLK* dev )
1954 {
1955 // AUTO-SCSI-MOUNT
1956 //
1957 // If no tape is currently mounted on this device,
1958 // kick off the tape mount monitoring thread that
1959 // will monitor for tape mounts (if it doesn't al-
1960 // ready still exist)...
1961
1962 obtain_lock( &sysblk.stape_lock );
1963
1964 // Is scsimount enabled?
1965
1966 if (likely( sysblk.auto_scsi_mount_secs ))
1967 {
1968 // Create thread if needed...
1969
1970 if (unlikely( !sysblk.stape_mountmon_tid ))
1971 {
1972 int rc;
1973 VERIFY
1974 (
1975 (rc = create_thread
1976 (
1977 &sysblk.stape_mountmon_tid,
1978 DETACHED,
1979 scsi_tapemountmon_thread,
1980 NULL,
1981 "scsi_tapemountmon_thread"
1982 ))
1983 == 0
1984 );
1985 }
1986
1987 // Enable it for our drive if needed...
1988
1989 if (STS_NOT_MOUNTED( dev ))
1990 {
1991 if (!dev->stape_mntdrq.link.Flink)
1992 {
1993 InsertListTail( &sysblk.stape_mount_link, &dev->stape_mntdrq.link );
1994 }
1995 }
1996 }
1997
1998 release_lock( &sysblk.stape_lock );
1999 }
2000
2001 /*-------------------------------------------------------------------*/
2002 /* ASYNCHRONOUS TAPE OPEN */
2003 /*-------------------------------------------------------------------*/
2004 /* AUTO_SCSI_MOUNT thread... */
2005 /*-------------------------------------------------------------------*/
scsi_tapemountmon_thread(void * notused)2006 void *scsi_tapemountmon_thread( void *notused )
2007 {
2008
2009 struct timeval now;
2010 int timeout, fd;
2011 LIST_ENTRY* pListEntry;
2012 STMNTDRQ* req;
2013 DEVBLK* dev = NULL;
2014
2015 UNREFERENCED(notused);
2016
2017 logmsg
2018 (
2019 _( "HHCTA300I SCSI-Tape mount-monitoring thread started;\n"
2020 " dev=%u:%4.4X, tid="TIDPAT", pri=%d, pid=%d\n" )
2021
2022 ,SSID_TO_LCSS(dev->ssid)
2023 ,dev->devnum
2024 ,thread_id()
2025 ,getpriority(PRIO_PROCESS,0)
2026 ,getpid()
2027 );
2028
2029 obtain_lock( &sysblk.stape_lock );
2030
2031 while (sysblk.auto_scsi_mount_secs && !sysblk.shutdown)
2032 {
2033 // Wait for automount interval to expire...
2034
2035 gettimeofday( &now, NULL );
2036
2037 for
2038 (
2039 timeout = 0
2040 ;
2041 1
2042 && !sysblk.shutdown
2043 && sysblk.auto_scsi_mount_secs
2044 && !(timeout = timed_wait_condition_relative_usecs
2045 (
2046 &sysblk.stape_getstat_cond,
2047 &sysblk.stape_lock,
2048 sysblk.auto_scsi_mount_secs * 1000000,
2049 &now
2050 ))
2051 ;
2052 );
2053
2054 if (sysblk.auto_scsi_mount_secs && !sysblk.shutdown)
2055 {
2056 // Process all work items...
2057
2058 pListEntry = sysblk.stape_mount_link.Flink;
2059
2060 while (pListEntry != &sysblk.stape_mount_link)
2061 {
2062 req = CONTAINING_RECORD( pListEntry, STMNTDRQ, link );
2063 dev = req->dev;
2064 pListEntry = pListEntry->Flink;
2065
2066 // Open drive if needed...
2067
2068 if ((fd = dev->fd) < 0)
2069 {
2070 dev->readonly = 0;
2071 fd = open_tape( dev->filename, O_RDWR | O_BINARY | O_NONBLOCK );
2072 if (fd < 0 && EROFS == errno )
2073 {
2074 dev->readonly = 1;
2075 fd = open_tape( dev->filename, O_RDONLY | O_BINARY | O_NONBLOCK );
2076 }
2077
2078 // Check for successful open
2079
2080 if (fd < 0)
2081 {
2082 logmsg (_("HHCTA324E Error opening SCSI device %u:%4.4X=%s; errno=%d: %s\n"),
2083 SSID_TO_LCSS(dev->ssid), dev->devnum,
2084 dev->filename, errno, strerror(errno));
2085 continue; // (go on to next drive)
2086 }
2087
2088 define_BOT_pos( dev ); // (always after successful open)
2089 dev->fd = fd; // (so far so good)
2090 }
2091
2092 // Retrieve the current status...
2093
2094 // PLEASE NOTE that we must do this WITHOUT holding the stape_lock
2095 // since the 'int_scsi_status_update' and sub-functions all expect
2096 // the lock to NOT be held so that THEY can then attempt to acquire
2097 // it when needed...
2098
2099 release_lock( &sysblk.stape_lock );
2100 {
2101 int_scsi_status_update( dev, 0 );
2102 }
2103 obtain_lock( &sysblk.stape_lock );
2104
2105 // (check again for shutdown)
2106
2107 if (sysblk.shutdown || !sysblk.auto_scsi_mount_secs)
2108 break;
2109
2110 // Has a tape [finally] been mounted yet??
2111
2112 if (STS_NOT_MOUNTED( dev ))
2113 {
2114 #if !defined( _MSVC_ )
2115 dev->fd = -1;
2116 close_tape( fd );
2117 #endif
2118 continue; // (go on to next drive)
2119 }
2120
2121 // Yes, remove completed work item...
2122
2123 RemoveListEntry( &dev->stape_mntdrq.link );
2124 InitializeListLink( &dev->stape_mntdrq.link );
2125
2126 // Finish the open drive process (set drive to variable length
2127 // block processing mode, etc)...
2128
2129 // PLEASE NOTE that we must do this WITHOUT holding the stape_lock
2130 // since the 'finish_scsitape_open' and sub-functions all expect
2131 // the lock to NOT be held so that THEY can then attempt to acquire
2132 // it when needed...
2133
2134 release_lock( &sysblk.stape_lock );
2135 {
2136 if ( finish_scsitape_open( dev, NULL, 0 ) == 0 )
2137 {
2138 // Notify the guest that the tape has now been loaded by
2139 // presenting an unsolicited device attention interrupt...
2140
2141 device_attention( dev, CSW_DE );
2142 }
2143 }
2144 obtain_lock( &sysblk.stape_lock );
2145
2146 } // end for (all work items)...
2147
2148 } // end if (sysblk.auto_scsi_mount_secs && !sysblk.shutdown)
2149
2150 } // end while (sysblk.auto_scsi_mount_secs && !sysblk.shutdown)
2151
2152 // (discard all work items since we're going away)
2153
2154 while (!IsListEmpty( &sysblk.stape_mount_link ))
2155 {
2156 pListEntry = RemoveListHead( &sysblk.stape_mount_link );
2157 InitializeListLink( pListEntry );
2158
2159 // (remove from the STATUS thread's work queue too!)
2160
2161 req = CONTAINING_RECORD( pListEntry, STMNTDRQ, link );
2162 dev = req->dev;
2163
2164 if ( dev->stape_statrq.link.Flink) {
2165 RemoveListEntry( &dev->stape_statrq.link );
2166 InitializeListLink( &dev->stape_statrq.link );
2167 }
2168 }
2169
2170 logmsg
2171 (
2172 _( "HHCTA301I SCSI-Tape mount-monitoring thread ended;\n"
2173 " dev=%u:%4.4X, tid="TIDPAT", pid=%d\n" )
2174
2175 ,SSID_TO_LCSS(dev->ssid)
2176 ,dev->devnum
2177 ,thread_id()
2178 ,getpid()
2179 );
2180
2181 sysblk.stape_mountmon_tid = 0; // (we're going away)
2182 release_lock( &sysblk.stape_lock );
2183 return NULL;
2184
2185 } /* end function scsi_tapemountmon_thread */
2186
2187 /*-------------------------------------------------------------------*/
2188 /* Tell driver (if needed) what a BOT position looks like... */
2189 /*-------------------------------------------------------------------*/
define_BOT_pos(DEVBLK * dev)2190 void define_BOT_pos( DEVBLK *dev )
2191 {
2192 #ifdef _MSVC_
2193
2194 // PROGRAMMING NOTE: Need to tell 'w32stape.c' here the
2195 // information it needs to detect physical BOT (load-point).
2196
2197 // This is not normally needed as most drivers determine
2198 // it for themselves based on the type (manufacturer/model)
2199 // of tape drive being used, but since I haven't added the
2200 // code to 'w32stape.c' to do that yet (involves talking
2201 // directly to the SCSI device itself) we thus, for now,
2202 // need to pass that information directly to 'w32stape.c'
2203 // ourselves...
2204
2205 U32 msk = 0xFF3FFFFF; // (3480/3490 default)
2206 U32 bot = 0x01000000; // (3480/3490 default)
2207
2208 if ( dev->stape_blkid_32 )
2209 {
2210 msk = 0xFFFFFFFF; // (3590 default)
2211 bot = 0x00000000; // (3590 default)
2212 }
2213
2214 VERIFY( 0 == w32_define_BOT( dev->fd, msk, bot ) );
2215
2216 #else
2217 UNREFERENCED(dev);
2218 #endif // _MSVC_
2219 }
2220
2221 #endif // defined(OPTION_SCSI_TAPE)
2222