1 /* TAPEDEV.C    (c) Copyright Roger Bowler, 1999-2009                */
2 /*              Hercules Tape Device Handler                         */
3 
4 /* Original Author: Roger Bowler                                     */
5 /* Prime Maintainer: Ivan Warren                                     */
6 /* Secondary Maintainer: "Fish" (David B. Trout)                     */
7 
8 /*-------------------------------------------------------------------*/
9 /* This module contains device handling functions for emulated       */
10 /* magnetic tape devices for the Hercules ESA/390 emulator.          */
11 /*-------------------------------------------------------------------*/
12 /* Messages issued by the TAPEDEV.C module are prefixed HHCTA0nn     */
13 /* CCW processing functions have been moved to module TAPECCW.C      */
14 /*                                                                   */
15 /* Five emulated tape formats are supported:                         */
16 /*                                                                   */
17 /* 1. AWSTAPE   This is the format used by the P/390.                */
18 /*              The entire tape is contained in a single flat file.  */
19 /*              A tape block consists of one or more block segments. */
20 /*              Each block segment is preceded by a 6-byte header.   */
21 /*              Files are separated by tapemarks, which consist      */
22 /*              of headers with zero block length.                   */
23 /*              AWSTAPE files are readable and writable.             */
24 /*                                                                   */
25 /*              Support for AWSTAPE is in the "AWSTAPE.C" member.    */
26 /*                                                                   */
27 /* 2. OMATAPE   This is the Optical Media Attach device format.      */
28 /*              Each physical file on the tape is represented by     */
29 /*              a separate flat file.  The collection of files that  */
30 /*              make up the physical tape is obtained from an ASCII  */
31 /*              text file called the "tape description file", whose  */
32 /*              file name is always tapes/xxxxxx.tdf (where xxxxxx   */
33 /*              is the volume serial number of the tape).            */
34 /*              Three formats of tape files are supported:           */
35 /*              * FIXED files contain fixed length EBCDIC blocks     */
36 /*                with no headers or delimiters. The block length    */
37 /*                is specified in the TDF file.                      */
38 /*              * TEXT files contain variable length ASCII blocks    */
39 /*                delimited by carriage return line feed sequences.  */
40 /*                The data is translated to EBCDIC by this module.   */
41 /*              * HEADER files contain variable length blocks of     */
42 /*                EBCDIC data prefixed by a 16-byte header.          */
43 /*              The TDF file and all of the tape files must reside   */
44 /*              reside under the same directory which is normally    */
45 /*              on CDROM but can be on disk.                         */
46 /*              OMATAPE files are supported as read-only media.      */
47 /*                                                                   */
48 /*              OMATAPE tape Support is in the "OMATAPE.C" member.   */
49 /*                                                                   */
50 /* 3. SCSITAPE  This format allows reading and writing of 4mm or     */
51 /*              8mm DAT tape, 9-track open-reel tape, or 3480-type   */
52 /*              cartridge on an appropriate SCSI-attached drive.     */
53 /*              All SCSI tapes are processed using the generalized   */
54 /*              SCSI tape driver (st.c) which is controlled using    */
55 /*              the MTIOCxxx set of IOCTL commands.                  */
56 /*              PROGRAMMING NOTE: the 'tape' portability macros for  */
57 /*              physical (SCSI) tapes MUST be used for all tape i/o! */
58 /*                                                                   */
59 /*              SCSI tape Support is in the "SCSITAPE.C" member.     */
60 /*                                                                   */
61 /* 4. HET       This format is based on the AWSTAPE format but has   */
62 /*              been extended to support compression.  Since the     */
63 /*              basic file format has remained the same, AWSTAPEs    */
64 /*              can be read/written using the HET routines.          */
65 /*                                                                   */
66 /*              Support for HET is in the "HETTAPE.C" member.        */
67 /*                                                                   */
68 /* 5. FAKETAPE  This is the format used by Fundamental Software      */
69 /*              on their FLEX-ES systems. It it similar to the AWS   */
70 /*              format. The entire tape is contained in a single     */
71 /*              flat file. A tape block is preceded by a 12-ASCII-   */
72 /*              hex-characters header which indicate the size of     */
73 /*              the previous and next blocks. Files are separated    */
74 /*              by tapemarks which consist of headers with a zero    */
75 /*              current block length. FakeTapes are both readable    */
76 /*              and writable.                                        */
77 /*                                                                   */
78 /*              Support for FAKETAPE is in the "FAKETAPE.C" member.  */
79 /*                                                                   */
80 /*-------------------------------------------------------------------*/
81 
82 /*-------------------------------------------------------------------*/
83 /* Additional credits:                                               */
84 /*      3480 commands contributed by Jan Jaeger                      */
85 /*      Sense byte improvements by Jan Jaeger                        */
86 /*      3480 Read Block ID and Locate CCWs by Brandon Hill           */
87 /*      Unloaded tape support by Brandon Hill                    v209*/
88 /*      HET format support by Leland Lucius                      v209*/
89 /*      JCS - minor changes by John Summerfield                  2003*/
90 /*      PERFORM SUBSYSTEM FUNCTION / CONTROL ACCESS support by       */
91 /*      Adrian Trenkwalder (with futher enhancements by Fish)        */
92 /*      **INCOMPLETE** 3590 support by Fish (David B. Trout)         */
93 /*-------------------------------------------------------------------*/
94 
95 /*-------------------------------------------------------------------*/
96 /* Reference information:                                            */
97 /* SC53-1200 S/370 and S/390 Optical Media Attach/2 User's Guide     */
98 /* SC53-1201 S/370 and S/390 Optical Media Attach/2 Technical Ref    */
99 /* SG24-2506 IBM 3590 Tape Subsystem Technical Guide                 */
100 /* GA32-0331 IBM 3590 Hardware Reference                             */
101 /* GA32-0329 IBM 3590 Introduction and Planning Guide                */
102 /* SG24-2594 IBM 3590 Multiplatform Implementation                   */
103 /* ANSI INCITS 131-1994 (R1999) SCSI-2 Reference                     */
104 /* GA32-0127 IBM 3490E Hardware Reference                            */
105 /* GC35-0152 EREP Release 3.5.0 Reference                            */
106 /* SA22-7204 ESA/390 Common I/O-Device Commands                      */
107 /*-------------------------------------------------------------------*/
108 
109 #include "hstdinc.h"
110 #include "hercules.h"  /* need Hercules control blocks               */
111 #include "tapedev.h"   /* Main tape handler header file              */
112 
113 //#define  ENABLE_TRACING_STMTS     // (Fish: DEBUGGING)
114 
115 #ifdef ENABLE_TRACING_STMTS
116   #if !defined(DEBUG)
117     #warning DEBUG required for ENABLE_TRACING_STMTS
118   #endif
119   // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h)
120 #else
121   #undef  TRACE
122   #undef  ASSERT
123   #undef  VERIFY
124   #define TRACE       1 ? ((void)0) : logmsg
125   #define ASSERT(a)
126   #define VERIFY(a)   ((void)(a))
127 #endif
128 
129 /*-------------------------------------------------------------------*/
130 
131 #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_)
132   SYSBLK *psysblk;
133   #define sysblk (*psysblk)
134 #endif
135 
136 /*-------------------------------------------------------------------*/
137 
138 DEVHND  tapedev_device_hndinfo   =
139 {
140     &tapedev_init_handler,             /* Device Initialisation      */
141     &tapedev_execute_ccw,              /* Device CCW execute         */
142     &tapedev_close_device,             /* Device Close               */
143     &tapedev_query_device,             /* Device Query               */
144     NULL,                              /* Device Start channel pgm   */
145     NULL,                              /* Device End channel pgm     */
146     NULL,                              /* Device Resume channel pgm  */
147     NULL,                              /* Device Suspend channel pgm */
148     NULL,                              /* Device Read                */
149     NULL,                              /* Device Write               */
150     NULL,                              /* Device Query used          */
151     NULL,                              /* Device Reserve             */
152     NULL,                              /* Device Release             */
153     NULL,                              /* Device Attention           */
154     TapeImmedCommands,                 /* Immediate CCW Codes        */
155     NULL,                              /* Signal Adapter Input       */
156     NULL,                              /* Signal Adapter Output      */
157     NULL,                              /* Hercules suspend           */
158     NULL                               /* Hercules resume            */
159 };
160 
161 /*-------------------------------------------------------------------*/
162 /* Libtool static name colision resolution...                        */
163 /* Note: lt_dlopen will look for symbol & modulename_LTX_symbol      */
164 /*-------------------------------------------------------------------*/
165 
166 #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL)
167 
168   #define  hdl_ddev   hdt3420_LTX_hdl_ddev
169   #define  hdl_depc   hdt3420_LTX_hdl_depc
170   #define  hdl_reso   hdt3420_LTX_hdl_reso
171   #define  hdl_init   hdt3420_LTX_hdl_init
172   #define  hdl_fini   hdt3420_LTX_hdl_fini
173 
174 #endif
175 
176 /*-------------------------------------------------------------------*/
177 
178 #if defined(OPTION_DYNAMIC_LOAD)
179 
180 HDL_DEPENDENCY_SECTION;
181 {
182     HDL_DEPENDENCY ( HERCULES );
183     HDL_DEPENDENCY ( DEVBLK   );
184     HDL_DEPENDENCY ( SYSBLK   );
185 }
186 END_DEPENDENCY_SECTION
187 
188 /*-------------------------------------------------------------------*/
189 
190 HDL_DEVICE_SECTION;
191 {
192     HDL_DEVICE ( 3410, tapedev_device_hndinfo );
193     HDL_DEVICE ( 3411, tapedev_device_hndinfo );
194     HDL_DEVICE ( 3420, tapedev_device_hndinfo );
195     HDL_DEVICE ( 3422, tapedev_device_hndinfo );
196     HDL_DEVICE ( 3430, tapedev_device_hndinfo );
197     HDL_DEVICE ( 3480, tapedev_device_hndinfo );
198     HDL_DEVICE ( 3490, tapedev_device_hndinfo );
199     HDL_DEVICE ( 3590, tapedev_device_hndinfo );
200     HDL_DEVICE ( 8809, tapedev_device_hndinfo );
201     HDL_DEVICE ( 9347, tapedev_device_hndinfo );
202     HDL_DEVICE ( 9348, tapedev_device_hndinfo );
203 }
204 END_DEVICE_SECTION
205 
206 /*-------------------------------------------------------------------*/
207 
208 #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_)
209 
210   #undef sysblk
211 
212   HDL_RESOLVER_SECTION;
213   {
214     HDL_RESOLVE_PTRVAR ( psysblk, sysblk );
215   }
216   END_RESOLVER_SECTION
217 
218 #endif // defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_)
219 
220 #endif // defined(OPTION_DYNAMIC_LOAD)
221 
222 /*-------------------------------------------------------------------*/
223 /*  (see 'tapedev.h' for layout of TAPEMEDIA_HANDLER structure)      */
224 /*-------------------------------------------------------------------*/
225 
226 TAPEMEDIA_HANDLER  tmh_aws  =
227 {
228     &generic_tmhcall,
229     &open_awstape,
230     &close_awstape,
231     &read_awstape,
232     &write_awstape,
233     &rewind_awstape,
234     &bsb_awstape,
235     &fsb_awstape,
236     &bsf_awstape,
237     &fsf_awstape,
238     &write_awsmark,
239     &sync_awstape,
240     &no_operation,              // (DSE)    ZZ FIXME: not coded yet
241     &no_operation,              // (ERG)
242     &is_tapeloaded_filename,
243     &passedeot_awstape,
244     &readblkid_virtual,
245     &locateblk_virtual
246 };
247 
248 /*-------------------------------------------------------------------*/
249 
250 TAPEMEDIA_HANDLER  tmh_het   =
251 {
252     &generic_tmhcall,
253     &open_het,
254     &close_het,
255     &read_het,
256     &write_het,
257     &rewind_het,
258     &bsb_het,
259     &fsb_het,
260     &bsf_het,
261     &fsf_het,
262     &write_hetmark,
263     &sync_het,
264     &no_operation,              // (DSE)    ZZ FIXME: not coded yet
265     &no_operation,              // (ERG)
266     &is_tapeloaded_filename,
267     &passedeot_het,
268     &readblkid_virtual,
269     &locateblk_virtual
270 };
271 
272 /*-------------------------------------------------------------------*/
273 
274 TAPEMEDIA_HANDLER  tmh_fake  =
275 {
276     &generic_tmhcall,
277     &open_faketape,
278     &close_faketape,
279     &read_faketape,
280     &write_faketape,
281     &rewind_faketape,
282     &bsb_faketape,
283     &fsb_faketape,
284     &bsf_faketape,
285     &fsf_faketape,
286     &write_fakemark,
287     &sync_faketape,
288     &no_operation,              // (DSE)    ZZ FIXME: not coded yet
289     &no_operation,              // (ERG)
290     &is_tapeloaded_filename,
291     &passedeot_faketape,
292     &readblkid_virtual,
293     &locateblk_virtual
294 };
295 
296 /*-------------------------------------------------------------------*/
297 
298 TAPEMEDIA_HANDLER  tmh_oma   =
299 {
300     &generic_tmhcall,
301     &open_omatape,
302     &close_omatape,
303     &read_omatape,
304     &write_READONLY5,           // WRITE
305     &rewind_omatape,
306     &bsb_omatape,
307     &fsb_omatape,
308     &bsf_omatape,
309     &fsf_omatape,
310     &write_READONLY,            // WTM
311     &write_READONLY,            // SYNC
312     &write_READONLY,            // DSE
313     &write_READONLY,            // ERG
314     &is_tapeloaded_filename,
315     &return_false1,             // passedeot
316     &readblkid_virtual,
317     &locateblk_virtual
318 };
319 
320 /*-------------------------------------------------------------------*/
321 
322 #if defined(OPTION_SCSI_TAPE)
323 
324 TAPEMEDIA_HANDLER  tmh_scsi   =
325 {
326     &generic_tmhcall,
327     &open_scsitape,
328     &close_scsitape,
329     &read_scsitape,
330     &write_scsitape,
331     &rewind_scsitape,
332     &bsb_scsitape,
333     &fsb_scsitape,
334     &bsf_scsitape,
335     &fsf_scsitape,
336     &write_scsimark,
337     &sync_scsitape,
338     &dse_scsitape,
339     &erg_scsitape,
340     &is_tape_mounted_scsitape,
341     &passedeot_scsitape,
342     &readblkid_scsitape,
343     &locateblk_scsitape
344 };
345 
346 #endif /* defined(OPTION_SCSI_TAPE) */
347 
348 /*-------------------------------------------------------------------*/
349 /* Device-Type Initialization Table    (DEV/CU MODEL, FEATURES, ETC) */
350 /*-------------------------------------------------------------------*/
351 /*
352    PROGRAMMING NOTE: the MDR/OBR code (Device Characteristics bytes
353    40-41) are apparently CRITICALLY IMPORTANT for proper tape drive
354    functioning for certain operating systems. If the bytes are not
355    provided (set to zero) or are set incorrectly, certain operating
356    systems end up using unusual/undesirable Mode Set values in their
357    Channel Programs (such as x'20' Write Immediate for example). I
358    only note it here because these two particular bytes are rather
359    innocuous looking based upon their name and sparsely documented
360    and largely unexplained values, thereby possibly misleading one
361    into believing they weren't important and thus could be safely
362    set to zero if their values were unknown. Rest assured they are
363    NOT unimportant! Quite the opposite: the are, for some operating
364    systems, CRITICALLY IMPORTANT and must NOT be returned as zeros.
365 
366    The following were obtained from "EREP Release 3.5.0 Reference"
367    (GC35-0152-03):
368 
369        Model                        MDR          OBR
370       -------                      -----        -----
371 
372        3480                         0x41         0x80
373        3490                         0x42         0x81
374 
375        3590                         0x46         0x83
376        3590 (3591/3490 EMU)         0x47         0x84
377        3590 (3590/3490 EMU)         0x48         0x85
378 
379 
380    NOTE: only models 3480, 3490 and 3590 support the RDC (Read
381    Device Characteristics) channel command, and thus they're the
382    only ones we must know the MDR/OBR codes for (since the MDR/OBR
383    codes are only used in the RDC CCW and not anwhere else). That
384    is to say, NONE of the Channel Commands (CCWs) that all the
385    OTHER models happen to support have an MDR/OBR code anywhere
386    in their data. Only models 3480, 3490 and 3590 have MDR/OBR
387    codes buried in their CCW data (specifically the RDC CCW data).
388 
389    Also note that, at the moment, we do not support emulating 3590's
390    or 3591's running in 3490 Emulation Mode (i.e. 3591/3490 EMU or
391    3590/3490 EMU). The user is free to use such a device with Herc-
392    ules however, but if they do, it should be specified as a 3490.
393 
394 ---------------------------------------------------------------------*/
395 
396 typedef struct DEVINITTAB               /* Initialization values     */
397 {
398     U16         devtype;                /* Device type               */
399     BYTE        devmodel;               /* Device model number       */
400     U16         cutype;                 /* Control unit type         */
401     BYTE        cumodel;                /* Control unit model number */
402     U32         sctlfeat;               /* Storage control features  */
403     BYTE        devclass;               /* Device class code         */
404     BYTE        devtcode;               /* Device type code          */
405     BYTE        MDR;                    /* Misc. Data Record ID      */
406     BYTE        OBR;                    /* Outboard Recorder ID      */
407     int         numdevid;               /* #of SNSID bytes (see NOTE)*/
408     int         numsense;               /* #of SENSE bytes           */
409     int         haverdc;                /* RDC Supported             */
410     int         displayfeat;            /* Has LCD display           */
411 }
412 DEVINITTAB;
413 DEVINITTAB      DevInitTab[]  =         /* Initialization table      */
414 {
415 // PROGRAMMING NOTE: we currently do not support a #of Sense-ID bytes
416 // value (numdevid) greater than 7 since our current channel-subsystem
417 // design does not support the concept of hardware physical attachment
418 // "Nodes" (i.e. separate control-unit, device and interface elements).
419 // Supporting more than 7 bytes of Sense-ID information would require
420 // support for Node Descriptors (ND) and Node Element Descriptors (NED)
421 // and the associated commands (CCWs) to query them (Read Configuration
422 // Data (0xFA) , Set Interface Identifier (0x73) and associated support
423 // in the Read Subsystem Data (0x3E) command), which is vast overkill
424 // and a complete waste of time given our current overly-simple channel
425 // subsystem design.
426 //
427 //--------------------------------------------------------------------
428 //            3410/3411/3420/3422/3430/8809/9347/9348
429 //--------------------------------------------------------------------
430 //
431 // devtype/mod  cutype/mod    sctlfeat  cls typ MDR OBR sid sns rdc dsp
432  { 0x3410,0x01, 0x3115,0x01, 0x00000000, 0,  0,  0,  0,  0,  9,  0,  0 },
433  { 0x3411,0x01, 0x3115,0x01, 0x00000000, 0,  0,  0,  0,  0,  9,  0,  0 },
434  { 0x3420,0x06, 0x3803,0x02, 0x00000000, 0,  0,  0,  0,  0, 24,  0,  0 }, // (DEFAULT: 3420)
435  { 0x3422,0x01, 0x3422,0x01, 0x00000000, 0,  0,  0,  0,  7, 32,  0,  0 },
436  { 0x3430,0x01, 0x3422,0x01, 0x00000000, 0,  0,  0,  0,  7, 32,  0,  0 },
437  { 0x8809,0x01, 0x8809,0x01, 0x00000000, 0,  0,  0,  0,  0, 32,  0,  0 },
438  { 0x9347,0x01, 0x9347,0x01, 0x00000000, 0,  0,  0,  0,  7, 32,  0,  0 },
439  { 0x9348,0x01, 0x9348,0x01, 0x00000000, 0,  0,  0,  0,  7, 32,  0,  0 },
440 
441 //--------------------------------------------------------------------
442 //                          3480/3490/3590
443 //--------------------------------------------------------------------
444 //
445 // PROGRAMMING NOTE: we currently do not support a #of Sense-ID bytes
446 // value (numdevid) greater than 7 since our current channel-subsystem
447 // design does not support the concept of hardware physical attachment
448 // "Nodes" (i.e. separate control-unit, device and interface elements).
449 // Supporting more than 7 bytes of Sense-ID information would require
450 // support for Node Descriptors (ND) and Node Element Descriptors (NED)
451 // and the associated commands (CCWs) to query them (Read Configuration
452 // Data (0xFA) , Set Interface Identifier (0x73) and associated support
453 // in the Read Subsystem Data (0x3E) command), which is vast overkill
454 // and a complete waste of time given our current overly-simple channel
455 // subsystem design.
456 //
457 // PROGRAMMING NOTE: if you change the below devtype/mod or cutype/mod
458 // values, be sure to ALSO change tapeccws.c's READ CONFIGURATION DATA
459 // (CCW opcode 0xFA) values as well!
460 //
461 // PROGRAMMING NOTE: the bit values of the 'sctlfeat' field are:
462 //
463 //     ....40..   (unknown)
464 //     ....08..   Set Special Intercept Condition (SIC) supported
465 //     ....04..   Channel Path No-Operation supported (always
466 //                on if Library Attachment Facility installed)
467 //     ....02..   Logical Write-Protect supported (always on
468 //                if Read Device Characteristics is supported)
469 //     ....01..   Extended Buffered Log support enabled (if 64
470 //                bytes of buffered log data, else 32 bytes)
471 //     ......80   Automatic Cartridge Loader installed/enabled
472 //     ......40   Improved Data Recording Capability (i.e.
473 //                compression support) installed/enabled
474 //     ......20   Suppress Volume Fencing
475 //     ......10   Library Interface online/enabled
476 //     ......08   Library Attachment Facility installed
477 //     ......04   (unknown)
478 //
479 // PROGRAMMING NOTE: the below "0x00004EC4" value for the 'sctlfeat'
480 // field for Model 3590 was determined empirically on a real machine.
481 //
482 // devtype/mod  cutype/mod    sctlfeat   cls  typ   MDR  OBR  sid sns  rdc dsp
483  { 0x3480,0x31, 0x3480,0x31, 0x000002C0, 0x80,0x80, 0x41,0x80,  7, 24,  1,  1 },  // 0x31 = D31
484  { 0x3490,0x50, 0x3490,0x50, 0x000002C0, 0x80,0x80, 0x42,0x81,  7, 32,  1,  1 },  // 0x50 = C10
485  { 0x3590,0x10, 0x3590,0x50, 0x00004EC4, 0x80,0x80, 0x46,0x83,  7, 32,  1,  1 },  // 0x10 = B1A, 0x50 = A50
486  { 0xFFFF,0xFF, 0xFFFF,0xFF, 0xFFFFFFFF, 0xFF,0xFF, 0xFF,0xFF, -1, -1, -1, -1 },  //**** END OF TABLE ****
487  { 0x3420,0x06, 0x3803,0x02, 0x00000000,   0,   0,    0,   0,   0, 24,  0,  0 },  // (DEFAULT: 3420)
488 };
489 
490 /*-------------------------------------------------------------------*/
491 /* Initialize the device handler                                     */
492 /*-------------------------------------------------------------------*/
tapedev_init_handler(DEVBLK * dev,int argc,char * argv[])493 int tapedev_init_handler (DEVBLK *dev, int argc, char *argv[])
494 {
495 int             rc;
496 DEVINITTAB*     pDevInitTab;
497 int             attn = 0;
498 
499     /* Set flag so attention will be raised for re-init */
500     if(dev->devtype)
501     {
502         attn = 1;
503     }
504 
505     /* Close current tape */
506     if(dev->fd>=0)
507     {
508         /* Prevent accidental re-init'ing of already loaded tape drives */
509         if (sysblk.nomountedtapereinit)
510         {
511             char*  devclass;
512 
513             tapedev_query_device(dev, &devclass, 0, NULL);
514 
515             if (1
516                 && strcmp(devclass,"TAPE") == 0
517                 && (0
518                     || TAPEDEVT_SCSITAPE == dev->tapedevt
519                     || (argc >= 3 && strcmp(argv[2], TAPE_UNLOADED) != 0)
520                    )
521             )
522             {
523                 ASSERT( dev->tmh && dev->tmh->tapeloaded );
524                 if (dev->tmh->tapeloaded( dev, NULL, 0 ))
525                 {
526                     release_lock (&dev->lock);
527                     logmsg(_("HHCPN183E Reinit rejected for drive %u:%4.4X; drive not empty\n"),
528                         SSID_TO_LCSS(dev->ssid), dev->devnum);
529                     return -1;
530                 }
531             }
532         }
533 
534         dev->tmh->close(dev);
535         dev->fd=-1;
536     }
537 
538     autoload_close(dev);
539     dev->tdparms.displayfeat=0;
540 
541     /* Determine the control unit type and model number */
542     /* Support for 3490/3422/3430/8809/9347, etc.. */
543     if (!sscanf( dev->typname, "%hx", &dev->devtype ))
544         dev->devtype = 0x3420;
545 
546     // PROGAMMING NOTE: we use hard-coded values from our DevInitTab
547     // for virtual (non-SCSI) devices and, for the time being, for non-
548     // virtual (SCSI) devices too. Once we add direct SCSI I/O support
549     // we will need to add code to get this information directly from
550     // the actual SCSI device itself.
551     for
552     (
553         pDevInitTab = &DevInitTab[0];
554         pDevInitTab->devtype != 0xFFFF && pDevInitTab->devtype != dev->devtype;
555         pDevInitTab++
556     );
557 
558     if (pDevInitTab->devtype == 0xFFFF)         /* (entry not found?) */
559     {
560         logmsg ( _("Unsupported device type specified %4.4x\n"), dev->devtype );
561 
562         pDevInitTab++;                          /* (default entry; s/b same as 0x3420) */
563         pDevInitTab->devtype = dev->devtype;    /* (don't know what else to do really) */
564         pDevInitTab->cutype  = dev->devtype;    /* (don't know what else to do really) */
565     }
566 
567     /* Allow SENSE ID for certain specific legacy devices if requested */
568 
569     dev->numdevid = pDevInitTab->numdevid;  // (default == from table)
570 
571     if (1
572         && sysblk.legacysenseid             // (if option requested, AND is)
573         && (0                               // (for allowable legacy device)
574             || 0x3410 == dev->devtype
575             || 0x3411 == dev->devtype
576             || 0x3420 == dev->devtype
577             || 0x8809 == dev->devtype
578            )
579     )
580     {
581         dev->numdevid = 7;                  // (allow for this legacy device)
582     }
583 
584     /* Initialize the Sense-Id bytes if needed... */
585     if (dev->numdevid > 0)
586     {
587         dev->devid[0] = 0xFF;
588 
589         dev->devid[1] = (pDevInitTab->cutype >> 8) & 0xFF;
590         dev->devid[2] = (pDevInitTab->cutype >> 0) & 0xFF;
591         dev->devid[3] =  pDevInitTab->cumodel;
592 
593         dev->devid[4] = (pDevInitTab->devtype >> 8) & 0xFF;
594         dev->devid[5] = (pDevInitTab->devtype >> 0) & 0xFF;
595         dev->devid[6] =  pDevInitTab->devmodel;
596 
597         /* Initialize the CIW information if needed... */
598         if (dev->numdevid > 7)
599         {
600             // PROGRAMMING NOTE: see note near 'DEVINITTAB'
601             // struct definition regarding requirements for
602             // supporting more than 7 bytes of SNSID info.
603 
604             memcpy (&dev->devid[8],  "\x40\xFA\x00\xA0", 4);  // CIW Read Configuration Data  (0xFA)
605             memcpy (&dev->devid[12], "\x41\x73\x00\x04", 4);  // CIW Set Interface Identifier (0x73)
606             memcpy (&dev->devid[16], "\x42\x3E\x00\x60", 4);  // CIW Read Subsystem Data      (0x3E)
607         }
608     }
609 
610     /* Initialize the Read Device Characteristics (RDC) bytes... */
611     if (pDevInitTab->haverdc)
612     {
613         dev->numdevchar = 64;
614 
615         memset (dev->devchar, 0, sizeof(dev->devchar));
616         memcpy (dev->devchar, dev->devid+1, 6);
617 
618         // Bytes 6-9: Subsystem Facilities...
619 
620         dev->devchar[6] = (pDevInitTab->sctlfeat >> 24) & 0xFF;
621         dev->devchar[7] = (pDevInitTab->sctlfeat >> 16) & 0xFF;
622         dev->devchar[8] = (pDevInitTab->sctlfeat >>  8) & 0xFF;
623         dev->devchar[9] = (pDevInitTab->sctlfeat >>  0) & 0xFF;
624 
625         // Bytes 10/11: Device Class/Type ...
626 
627         dev->devchar[10] = pDevInitTab->devclass;
628         dev->devchar[11] = pDevInitTab->devtcode;
629 
630         // Bytes 24-29: cutype/model & devtype/model ...
631         // (Note: undocumented; determined empirically)
632 
633         dev->devchar[24] = (pDevInitTab->cutype >> 8) & 0xFF;
634         dev->devchar[25] = (pDevInitTab->cutype >> 0) & 0xFF;
635         dev->devchar[26] =  pDevInitTab->cumodel;
636 
637         dev->devchar[27] = (pDevInitTab->devtype >> 8) & 0xFF;
638         dev->devchar[28] = (pDevInitTab->devtype >> 0) & 0xFF;
639         dev->devchar[29] =  pDevInitTab->devmodel;
640 
641         // Bytes 40-41: MDR/OBR code...
642 
643         dev->devchar[40] = pDevInitTab->MDR;
644         dev->devchar[41] = pDevInitTab->OBR;
645     }
646 
647     /* Initialize other fields */
648 //  dev->numdevid            = pDevInitTab->numdevid;   // (handled above)
649     dev->numsense            = pDevInitTab->numsense;
650     dev->tdparms.displayfeat = pDevInitTab->displayfeat;
651 
652     dev->fenced              = 0;   // (always, initially)
653     dev->SIC_active          = 0;   // (always, initially)
654     dev->SIC_supported       = 0;   // (until we're sure)
655     dev->forced_logging      = 0;   // (always, initially)
656 #if defined( OPTION_TAPE_AUTOMOUNT )
657     dev->noautomount         = 0;   // (always, initially)
658 #endif
659 
660     /* Initialize SCSI tape control fields */
661 #if defined(OPTION_SCSI_TAPE)
662     dev->sstat = GMT_DR_OPEN(-1);
663 #endif
664 
665     /* Clear the DPA */
666     memset (dev->pgid, 0, sizeof(dev->pgid));
667     /* Clear Drive password - Adrian */
668     memset (dev->drvpwd, 0, sizeof(dev->drvpwd));
669 
670     /* Request the channel to merge data chained write CCWs into
671        a single buffer before passing data to the device handler */
672     dev->cdwmerge = 1;
673 
674     /* ISW */
675     /* Build a 'clear' sense */
676     memset (dev->sense, 0, sizeof(dev->sense));
677     dev->sns_pending = 0;
678 
679     // Initialize the [non-SCSI] auto-loader...
680 
681     // PROGRAMMING NOTE: we don't [yet] know at this early stage
682     // what type of tape device we're dealing with (SCSI (non-virtual)
683     // or non-SCSI (virtual)) since 'mountnewtape' hasn't been called
684     // yet (which is the function that determines which media handler
685     // should be used and is the one that initializes dev->tapedevt)
686 
687     // The only thing we know (or WILL know once 'autoload_init'
688     // is called) is whether or not there was a [non-SCSI] auto-
689     // loader defined for the device. That's it and nothing more.
690 
691     autoload_init( dev, argc, argv );
692 
693     // Was an auto-loader defined for this device?
694     if ( !dev->als )
695     {
696         // No. Just mount whatever tape there is (if any)...
697         rc = mountnewtape( dev, argc, argv );
698     }
699     else
700     {
701         // Yes. Try mounting the FIRST auto-loader slot...
702         if ( (rc = autoload_mount_first( dev )) != 0 )
703         {
704             // If that doesn't work, try subsequent slots...
705             while
706             (
707                 dev->als
708                 &&
709                 (rc = autoload_mount_next( dev )) != 0
710             )
711             {
712                 ;  // (nop; just go on to next slot)
713             }
714             rc = dev->als ? rc : -1;
715         }
716     }
717 
718     if (dev->devchar[8] & 0x08)     // SIC supported?
719         dev->SIC_supported = 1;     // remember that fact
720 
721     if (dev->tapedevt == TAPEDEVT_SCSITAPE)
722         dev->syncio = 0;  // (SCSI i/o too slow; causes Machine checks)
723     else
724         dev->syncio = 2;  // (aws/het/etc are fast; syncio likely safe)
725 
726     /* Make attention pending if necessary */
727     if(attn)
728     {
729         release_lock (&dev->lock);
730         device_attention (dev, CSW_DE);
731         obtain_lock (&dev->lock);
732     }
733 
734     return rc;
735 
736 } /* end function tapedev_init_handler */
737 
738 
739 /*-------------------------------------------------------------------*/
740 /* Close the device                                                  */
741 /*-------------------------------------------------------------------*/
tapedev_close_device(DEVBLK * dev)742 int tapedev_close_device ( DEVBLK *dev )
743 {
744     autoload_close(dev);
745     dev->tmh->close(dev);
746     ASSERT( dev->fd < 0 );
747 
748     dev->curfilen  = 1;
749     dev->nxtblkpos = 0;
750     dev->prvblkpos = -1;
751     dev->curblkrem = 0;
752     dev->curbufoff = 0;
753     dev->blockid   = 0;
754     dev->fenced = 0;
755 
756     return 0;
757 } /* end function tapedev_close_device */
758 
759 
760 /*-------------------------------------------------------------------*/
761 /*  Tape format determination REGEXPS. Used by gettapetype below     */
762 /*-------------------------------------------------------------------*/
763 
764 struct tape_format_entry                    /*   (table layout)      */
765 {
766     char*               fmtreg;             /* A regular expression  */
767     int                 fmtcode;            /* the device code       */
768     TAPEMEDIA_HANDLER*  tmh;                /* The media dispatcher  */
769     char*               descr;              /* readable description  */
770     char*               short_descr;        /* (same but shorter)    */
771 };
772 
773 /*-------------------------------------------------------------------*/
774 /*  Tape format determination REGEXPS. Used by gettapetype below     */
775 /*-------------------------------------------------------------------*/
776 
777 struct  tape_format_entry   fmttab   [] =   /*    (table itself)     */
778 {
779     /* This entry matches a filename ending with .aws    */
780 #define  AWSTAPE_FMTENTRY   0
781 #define  DEFAULT_FMTENTRY   AWSTAPE_FMTENTRY
782     {
783         "\\.aws$",
784         TAPEDEVT_AWSTAPE,
785         &tmh_aws,
786         "AWS Format tape file",
787         "AWS tape"
788     },
789 
790     /* This entry matches a filename ending with .het    */
791 #define  HETTAPE_FMTENTRY   1
792     {
793         "\\.het$",
794         TAPEDEVT_HETTAPE,
795         &tmh_het,
796         "Hercules Emulated Tape file",
797         "HET tape"
798     },
799 
800     /* This entry matches a filename ending with .tdf    */
801 #define  OMATAPE_FMTENTRY   2
802     {
803         "\\.tdf$",
804         TAPEDEVT_OMATAPE,
805         &tmh_oma,
806         "Optical Media Attachment (OMA) tape",
807         "OMA tape"
808     },
809 
810     /* This entry matches a filename ending with .fkt    */
811 #define  FAKETAPE_FMTENTRY  3
812     {
813         "\\.fkt$",
814         TAPEDEVT_FAKETAPE,
815         &tmh_fake,
816         "Flex FakeTape file",
817         "FakeTape"
818     },
819 
820 #if defined(OPTION_SCSI_TAPE)
821 
822     /* This entry matches a filename starting with /dev/ */
823 #define  SCSITAPE_FMTENTRY  4
824     {
825         "^/dev/",
826         TAPEDEVT_SCSITAPE,
827         &tmh_scsi,
828         "SCSI attached tape drive",
829         "SCSI tape"
830     },
831 
832 #if defined(_MSVC_)
833 
834     /* (same idea but for Windows SCSI tape device names) */
835 #undef   SCSITAPE_FMTENTRY
836 #define  SCSITAPE_FMTENTRY  5
837     {
838         "^\\\\\\\\\\.\\\\\\w",
839         TAPEDEVT_SCSITAPE,
840         &tmh_scsi,
841         "SCSI attached tape drive",
842         "SCSI tape"
843     },
844 
845 #endif // _MSVC_
846 #endif // OPTION_SCSI_TAPE
847 };
848 
849 
850 /*-------------------------------------------------------------------*/
851 /*  gettapetype_byname        determine tape device type by filename */
852 /*-------------------------------------------------------------------*/
853 /* returns fmttab entry# on success, -1 on error/unable to determine */
854 /*-------------------------------------------------------------------*/
gettapetype_byname(DEVBLK * dev)855 int gettapetype_byname (DEVBLK *dev)
856 {
857 #if defined(HAVE_REGEX_H) || defined(HAVE_PCRE)
858     regex_t     regwrk;                 /* REGEXP work area          */
859     regmatch_t  regwrk2;                /* REGEXP match area         */
860     char        errbfr[1024];           /* Working storage           */
861     int         i;                      /* Loop control              */
862 #endif // HAVE_REGEX_H
863     int         rc;                     /* various rtns return codes */
864 
865     /* Use the file name to determine the device type */
866 
867 #if defined(HAVE_REGEX_H) || defined(HAVE_PCRE)
868 
869     for (i=0; i < (int)arraysize( fmttab ); i++)
870     {
871         rc = regcomp (&regwrk, fmttab[i].fmtreg, REG_ICASE);
872         if (rc < 0)
873         {
874             regerror (rc, &regwrk, errbfr, 1024);
875             logmsg (_("HHCTA001E %4.4X: Unable to determine tape format type for %s: Internal error: Regcomp error %s on index %d\n"),
876                 dev->devnum, dev->filename, errbfr, i);
877             return -1;
878         }
879 
880         rc = regexec (&regwrk, dev->filename, 1, &regwrk2, 0);
881         if (rc < 0)
882         {
883             regerror (rc, &regwrk, errbfr, 1024);
884             regfree ( &regwrk );
885             logmsg (_("HHCTA002E %4.4X: Unable to determine tape format type for %s: Internal error: Regexec error %s on index %d\n"),
886                 dev->devnum, dev->filename, errbfr, i);
887             return -1;
888         }
889 
890         regfree (&regwrk);
891 
892         if (rc == 0)  /* MATCH? */
893             return i;
894 
895         ASSERT( rc == REG_NOMATCH );
896     }
897 
898 #else // !HAVE_REGEX_H
899 
900     if (1
901         && (rc = strlen(dev->filename)) > 4
902         && (rc = strcasecmp( &dev->filename[rc-4], ".aws" )) == 0
903     )
904     {
905         return AWSTAPE_FMTENTRY;
906     }
907 
908     if (1
909         && (rc = strlen(dev->filename)) > 4
910         && (rc = strcasecmp( &dev->filename[rc-4], ".het" )) == 0
911     )
912     {
913         return HETTAPE_FMTENTRY;
914     }
915 
916     if (1
917         && (rc = strlen(dev->filename)) > 4
918         && (rc = strcasecmp( &dev->filename[rc-4], ".tdf" )) == 0
919     )
920     {
921         return OMATAPE_FMTENTRY;
922     }
923 
924     if (1
925         && (rc = strlen(dev->filename)) > 4
926         && (rc = strcasecmp( &dev->filename[rc-4], ".fkt" )) == 0
927     )
928     {
929         return FAKETAPE_FMTENTRY;
930     }
931 
932 #if defined(OPTION_SCSI_TAPE)
933     if (1
934         && (rc = strlen(dev->filename)) > 5
935         && (rc = strncasecmp( dev->filename, "/dev/", 5 )) == 0
936     )
937     {
938         if (strncasecmp( dev->filename+5, "st", 2 ) == 0)
939             dev->stape_close_rewinds = 1; // (rewind at close)
940         else
941             dev->stape_close_rewinds = 0; // (otherwise don't)
942 
943         return SCSITAPE_FMTENTRY;
944     }
945 #if defined(_MSVC_)
946     if (1
947         && strncasecmp(dev->filename, "\\\\.\\", 4) == 0
948         &&           *(dev->filename        +    4) != 0
949     )
950     {
951         return SCSITAPE_FMTENTRY;
952     }
953 #endif // _MSVC_
954 #endif // OPTION_SCSI_TAPE
955 #endif // HAVE_REGEX_H
956 
957     return -1;      /* -1 == "unable to determine" */
958 
959 } /* end function gettapetype_byname */
960 
961 
962 /*-------------------------------------------------------------------*/
963 /*  gettapetype_bydata       determine tape device type by file data */
964 /*-------------------------------------------------------------------*/
965 /* returns fmttab entry# on success, -1 on error/unable to determine */
966 /*-------------------------------------------------------------------*/
gettapetype_bydata(DEVBLK * dev)967 int gettapetype_bydata (DEVBLK *dev)
968 {
969     char        pathname[MAX_PATH];     /* file path in host format  */
970     int         rc;                     /* various rtns return codes */
971 
972     /* Try to determine the type based on actual file contents */
973     hostpath( pathname, dev->filename, sizeof(pathname) );
974     rc = hopen( pathname, O_RDONLY | O_BINARY );
975     if (rc >= 0)
976     {
977         BYTE hdr[6];                    /* block header i/o buffer   */
978         int fd = rc;                    /* save file descriptor      */
979 
980         /* Read the header. If bytes 0-3 are ASCII "0000", then the
981          * tape is likely a Flex FakeTape. Otherwise if bytes 2-3 are
982          * binary zero (x'0000'), it's likely an AWS type tape. If byte
983          * 4 (first flag byte) has either of the ZLIB or BZIP2 flags on,
984          * then it's a HET tape. Otherwise it's just an ordinary AWS tape.
985          */
986         rc = read (fd, hdr, sizeof(hdr));
987              close(fd);
988         if (rc >= 6)
989         {
990             /* Use the data to make the possible determination */
991             if (memcmp(hdr, "@TDF", 4) == 0)
992                 return OMATAPE_FMTENTRY;
993 
994             if (1
995                 && hdr[0] == 0x30           /* "ASCII"-zero len prev block? */
996                 && hdr[1] == 0x30
997                 && hdr[2] == 0x30
998                 && hdr[3] == 0x30
999             )
1000                 return FAKETAPE_FMTENTRY;   /* Then obviously Flex FakeTape */
1001 
1002             if (hdr[2] == 0 && hdr[3] == 0)             /* 0 len prev blk?  */
1003             {
1004                 if (hdr[4] & HETHDR_FLAGS1_TAPEMARK)    /* If tapemark then */
1005                     return -1;                          /* can't tell type. */
1006                 if (hdr[4] & HETHDR_FLAGS1_COMPRESS ||  /* ZLIB or BZIP2 or */
1007                     hdr[5] & HETHDR_FLAGS2_COMPRESS)    /* Bus-Tech ZLIB?   */
1008                     return HETTAPE_FMTENTRY;            /* Then HET format. */
1009                 else
1010                     return AWSTAPE_FMTENTRY;            /* Else default AWS */
1011             }
1012         }
1013     }
1014     return -1;      /* -1 == "unable to determine" */
1015 
1016 } /* end function gettapetype_bydata */
1017 
1018 
1019 /*-------------------------------------------------------------------*/
1020 /*  gettapetype              determine tape device type              */
1021 /*-------------------------------------------------------------------*/
1022 /* returns fmttab entry# on success, -1 on error/unable to determine */
1023 /*-------------------------------------------------------------------*/
gettapetype(DEVBLK * dev,char ** short_descr)1024 int gettapetype (DEVBLK *dev, char **short_descr)
1025 {
1026     char*       descr;                  /* Device descr from fmttab  */
1027     int         i;                      /* fmttab entry#             */
1028 
1029     i = gettapetype_byname( dev );      /* Get type based on name    */
1030 
1031 #if defined(OPTION_SCSI_TAPE)
1032     if (i != SCSITAPE_FMTENTRY)         /* If not SCSI tape...       */
1033 #endif
1034     {
1035         int i2 = gettapetype_bydata( dev ); // Get type based on data..
1036 
1037         if (i2 >= 0 &&                      // If valid type by data, AND
1038            (i2 != AWSTAPE_FMTENTRY ||       // *not* AWS by data (or if it
1039             i  != HETTAPE_FMTENTRY)         // is, if it's not HET by name)..
1040         )
1041             i = i2;                         // ..Use type based on data.
1042     }
1043 
1044     /* If file type still unknown, use a reasonable default value... */
1045     if (i < 0)
1046     {
1047         i = DEFAULT_FMTENTRY;
1048         if (strcmp (dev->filename, TAPE_UNLOADED) != 0)
1049             logmsg (_("HHCTA003W %4.4X: Unable to determine tape format type for %s; presuming %s.\n"),
1050                  dev->devnum, dev->filename, fmttab[i].short_descr );
1051     }
1052 
1053     dev->tapedevt = fmttab[i].fmtcode;
1054     dev->tmh      = fmttab[i].tmh;
1055     descr         = fmttab[i].descr;
1056     *short_descr  = fmttab[i].short_descr;
1057 
1058     if (strcmp (dev->filename, TAPE_UNLOADED) != 0)
1059         logmsg (_("HHCTA004I %4.4X: %s is a %s\n"),
1060             dev->devnum, dev->filename, descr);
1061 
1062     return 0;   // (success)
1063 
1064 } /* end function gettapetype */
1065 
1066 
1067 /*-------------------------------------------------------------------*/
1068 /*  The following table goes hand-in-hand with the 'enum' values     */
1069 /*  that immediately follow.  Used by 'mountnewtape' function.       */
1070 /*-------------------------------------------------------------------*/
1071 
1072 PARSER  ptab  [] =
1073 {
1074     { "awstape",    NULL },
1075     { "idrc",       "%d" },
1076     { "compress",   "%d" },
1077     { "method",     "%d" },
1078     { "level",      "%d" },
1079     { "chunksize",  "%d" },
1080     { "maxsize",    "%d" },
1081     { "maxsizeK",   "%d" },
1082     { "maxsizeM",   "%d" },
1083     { "eotmargin",  "%d" },
1084     { "strictsize", "%d" },
1085     { "readonly",   "%d" },
1086     { "ro",         NULL },
1087     { "noring",     NULL },
1088     { "rw",         NULL },
1089     { "ring",       NULL },
1090     { "deonirq",    "%d" },
1091 #if defined( OPTION_TAPE_AUTOMOUNT )
1092     { "noautomount",NULL },
1093 #endif
1094     { "--blkid-22", NULL },
1095     { "--blkid-24", NULL },   /* (synonym for --blkid-22) */
1096     { "--blkid-32", NULL },
1097     { "--no-erg",   NULL },
1098     { NULL,         NULL },   /* (end of table) */
1099 };
1100 
1101 /*-------------------------------------------------------------------*/
1102 /*  The following table goes hand-in-hand with the 'ptab' PARSER     */
1103 /*  table immediately above. Used by 'mountnewtape' function.        */
1104 /*-------------------------------------------------------------------*/
1105 
1106 enum
1107 {
1108     TDPARM_NONE,
1109     TDPARM_AWSTAPE,
1110     TDPARM_IDRC,
1111     TDPARM_COMPRESS,
1112     TDPARM_METHOD,
1113     TDPARM_LEVEL,
1114     TDPARM_CHKSIZE,
1115     TDPARM_MAXSIZE,
1116     TDPARM_MAXSIZEK,
1117     TDPARM_MAXSIZEM,
1118     TDPARM_EOTMARGIN,
1119     TDPARM_STRICTSIZE,
1120     TDPARM_READONLY,
1121     TDPARM_RO,
1122     TDPARM_NORING,
1123     TDPARM_RW,
1124     TDPARM_RING,
1125     TDPARM_DEONIRQ,
1126 #if defined( OPTION_TAPE_AUTOMOUNT )
1127     TDPARM_NOAUTOMOUNT,
1128 #endif
1129     TDPARM_BLKID22,
1130     TDPARM_BLKID24,
1131     TDPARM_BLKID32,
1132     TDPARM_NOERG
1133 };
1134 
1135 /*-------------------------------------------------------------------*/
1136 /*        mountnewtape     --     mount a tape in the drive          */
1137 /*-------------------------------------------------------------------*/
1138 /*                                                                   */
1139 /*  Syntax:       filename [options]                                 */
1140 /*                                                                   */
1141 /*  where options are any of the entries in the 'ptab' PARSER        */
1142 /*  table defined further above. Some commonly used options are:     */
1143 /*                                                                   */
1144 /*    awstape          sets the HET parms to be compatible with the  */
1145 /*                     R|P/390|'s tape file Format (HET files)       */
1146 /*                                                                   */
1147 /*    idrc|compress    0|1: Write tape blocks with compression       */
1148 /*                     (std deviation: Read backward allowed on      */
1149 /*                     compressed HET tapes while it is not on       */
1150 /*                     IDRC formated 3480 tapes)                     */
1151 /*                                                                   */
1152 /*    --no-erg         for SCSI tape only, means the hardware does   */
1153 /*                     not support the "Erase Gap" command and all   */
1154 /*                     such i/o's should return 'success' instead.   */
1155 /*                                                                   */
1156 /*    --blkid-32       for SCSI tape only, means the hardware        */
1157 /*                     only supports full 32-bit block-ids.          */
1158 /*                                                                   */
1159 /*-------------------------------------------------------------------*/
mountnewtape(DEVBLK * dev,int argc,char ** argv)1160 int  mountnewtape ( DEVBLK *dev, int argc, char **argv )
1161 {
1162     char*       short_descr;            /* Short descr from fmttab   */
1163     int         i;                      /* Loop control              */
1164     int         rc, optrc;              /* various rtns return codes */
1165     union {                             /* Parser results            */
1166         U32     num;                    /* Parser results            */
1167         BYTE    str[ 80 ];              /* Parser results            */
1168     } res;                              /* Parser results            */
1169 
1170     /* Release the previous OMA descriptor array if allocated */
1171     if (dev->omadesc != NULL)
1172     {
1173         free (dev->omadesc);
1174         dev->omadesc = NULL;
1175     }
1176 
1177     /* The first argument is the file name */
1178     if (argc == 0 || strlen(argv[0]) > sizeof(dev->filename)-1)
1179         strcpy (dev->filename, TAPE_UNLOADED);
1180     else
1181         /* Save the file name in the device block */
1182         strcpy (dev->filename, argv[0]);
1183 
1184     /* Determine tape device type... */
1185     VERIFY( gettapetype( dev, &short_descr ) == 0 );
1186 
1187     /* (sanity check) */
1188     ASSERT(dev->tapedevt != TAPEDEVT_UNKNOWN);
1189     ASSERT(dev->tmh != NULL);
1190     ASSERT(short_descr != NULL);
1191 
1192     /* Initialize device dependent fields */
1193     dev->fd                = -1;
1194 #if defined(OPTION_SCSI_TAPE)
1195     dev->sstat             = GMT_DR_OPEN(-1);
1196 #endif
1197     dev->omadesc           = NULL;
1198     dev->omafiles          = 0;
1199     dev->curfilen          = 1;
1200     dev->nxtblkpos         = 0;
1201     dev->prvblkpos         = -1;
1202     dev->curblkrem         = 0;
1203     dev->curbufoff         = 0;
1204     dev->readonly          = 0;
1205     dev->hetb              = NULL;
1206     dev->tdparms.compress  = HETDFLT_COMPRESS;
1207     dev->tdparms.method    = HETDFLT_METHOD;
1208     dev->tdparms.level     = HETDFLT_LEVEL;
1209     dev->tdparms.chksize   = HETDFLT_CHKSIZE;
1210     dev->tdparms.maxsize   = 0;        // no max size     (default)
1211     dev->eotmargin         = 128*1024; // 128K EOT margin (default)
1212     dev->tdparms.logical_readonly = 0; // read/write      (default)
1213 #if defined( OPTION_TAPE_AUTOMOUNT )
1214     dev->noautomount       = 0;
1215 #endif
1216 
1217 #if defined(OPTION_SCSI_TAPE)
1218     // Real 3590's support Erase Gap and use 32-bit blockids.
1219 
1220     if (TAPEDEVT_SCSITAPE == dev->tapedevt
1221         &&     0x3590     == dev->devtype)
1222     {
1223         dev->stape_no_erg   = 0;        // (default for 3590 SCSI)
1224         dev->stape_blkid_32 = 1;        // (default for 3590 SCSI)
1225     }
1226 #endif
1227 
1228 #define  HHCTA078E()  logmsg (_("HHCTA078E %4.4X: option '%s' not valid for %s\n"), \
1229                               dev->devnum, argv[i], short_descr)
1230 
1231     /* Process remaining options */
1232     rc = 0;
1233     for (i = 1; i < argc; i++)
1234     {
1235         optrc = 0;
1236         switch (parser (&ptab[0], argv[i], &res))
1237         {
1238         case TDPARM_NONE:
1239             logmsg (_("HHCTA067E %4.4X: option '%s' unrecognized\n"),
1240                 dev->devnum, argv[i]);
1241             optrc = -1;
1242             break;
1243 
1244         case TDPARM_AWSTAPE:
1245             if (0
1246                 || TAPEDEVT_SCSITAPE == dev->tapedevt
1247                 || TAPEDEVT_FAKETAPE == dev->tapedevt
1248             )
1249             {
1250                 HHCTA078E(); optrc = -1; break;
1251             }
1252             dev->tdparms.compress = FALSE;
1253             dev->tdparms.chksize = 4096;
1254             break;
1255 
1256         case TDPARM_IDRC:
1257         case TDPARM_COMPRESS:
1258             if (0
1259                 || TAPEDEVT_SCSITAPE == dev->tapedevt
1260                 || TAPEDEVT_FAKETAPE == dev->tapedevt
1261             )
1262             {
1263                 HHCTA078E(); optrc = -1; break;
1264             }
1265             dev->tdparms.compress = (res.num ? TRUE : FALSE);
1266             break;
1267 
1268         case TDPARM_METHOD:
1269             if (0
1270                 || TAPEDEVT_SCSITAPE == dev->tapedevt
1271                 || TAPEDEVT_FAKETAPE == dev->tapedevt
1272             )
1273             {
1274                 HHCTA078E(); optrc = -1; break;
1275             }
1276             if (res.num < HETMIN_METHOD || res.num > HETMAX_METHOD)
1277             {
1278                 logmsg(_("HHCTA068E %4.4X: option '%s': method must be within %u-%u\n"),
1279                     dev->devnum, argv[i], HETMIN_METHOD, HETMAX_METHOD);
1280                 optrc = -1;
1281                 break;
1282             }
1283             dev->tdparms.method = res.num;
1284             break;
1285 
1286         case TDPARM_LEVEL:
1287             if (0
1288                 || TAPEDEVT_SCSITAPE == dev->tapedevt
1289                 || TAPEDEVT_FAKETAPE == dev->tapedevt
1290             )
1291             {
1292                 HHCTA078E(); optrc = -1; break;
1293             }
1294             if (res.num < HETMIN_LEVEL || res.num > HETMAX_LEVEL)
1295             {
1296                 logmsg(_("HHCTA069E %4.4X: option '%s': level must be within %u-%u\n"),
1297                     dev->devnum, argv[i], HETMIN_LEVEL, HETMAX_LEVEL);
1298                 optrc = -1;
1299                 break;
1300             }
1301             dev->tdparms.level = res.num;
1302             break;
1303 
1304         case TDPARM_CHKSIZE:
1305             if (0
1306                 || TAPEDEVT_SCSITAPE == dev->tapedevt
1307                 || TAPEDEVT_FAKETAPE == dev->tapedevt
1308             )
1309             {
1310                 HHCTA078E(); optrc = -1; break;
1311             }
1312             if (res.num < HETMIN_CHUNKSIZE || res.num > HETMAX_CHUNKSIZE)
1313             {
1314                 logmsg (_("HHCTA070E %4.4X: option '%s': chunksize must be within %u-%u\n"),
1315                     dev->devnum, argv[i], HETMIN_CHUNKSIZE, HETMAX_CHUNKSIZE);
1316                 optrc = -1;
1317                 break;
1318             }
1319             dev->tdparms.chksize = res.num;
1320             break;
1321 
1322         case TDPARM_MAXSIZE:
1323             if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1324             {
1325                 HHCTA078E(); optrc = -1; break;
1326             }
1327             dev->tdparms.maxsize=res.num;
1328             break;
1329 
1330         case TDPARM_MAXSIZEK:
1331             if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1332             {
1333                 HHCTA078E(); optrc = -1; break;
1334             }
1335             dev->tdparms.maxsize=res.num*1024;
1336             break;
1337 
1338         case TDPARM_MAXSIZEM:
1339             if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1340             {
1341                 HHCTA078E(); optrc = -1; break;
1342             }
1343             dev->tdparms.maxsize=res.num*1024*1024;
1344             break;
1345 
1346         case TDPARM_EOTMARGIN:
1347             dev->eotmargin=res.num;
1348             break;
1349 
1350         case TDPARM_STRICTSIZE:
1351             if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1352             {
1353                 HHCTA078E(); optrc = -1; break;
1354             }
1355             dev->tdparms.strictsize=res.num;
1356             break;
1357 
1358         case TDPARM_READONLY:
1359             if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1360             {
1361                 HHCTA078E(); optrc = -1; break;
1362             }
1363             dev->tdparms.logical_readonly=(res.num ? 1 : 0 );
1364             break;
1365 
1366         case TDPARM_RO:
1367         case TDPARM_NORING:
1368             if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1369             {
1370                 HHCTA078E(); optrc = -1; break;
1371             }
1372             dev->tdparms.logical_readonly=1;
1373             break;
1374 
1375         case TDPARM_RW:
1376         case TDPARM_RING:
1377             if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1378             {
1379                 HHCTA078E(); optrc = -1; break;
1380             }
1381             dev->tdparms.logical_readonly=0;
1382             break;
1383 
1384         case TDPARM_DEONIRQ:
1385             if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1386             {
1387                 HHCTA078E(); optrc = -1; break;
1388             }
1389             dev->tdparms.deonirq=(res.num ? 1 : 0 );
1390             break;
1391 
1392 #if defined( OPTION_TAPE_AUTOMOUNT )
1393 
1394         case TDPARM_NOAUTOMOUNT:
1395             if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1396             {
1397                 HHCTA078E(); optrc = -1; break;
1398             }
1399             dev->noautomount = 1;
1400             break;
1401 
1402 #endif /* OPTION_TAPE_AUTOMOUNT */
1403 
1404 #if defined(OPTION_SCSI_TAPE)
1405         case TDPARM_BLKID22:
1406         case TDPARM_BLKID24:
1407             if (TAPEDEVT_SCSITAPE != dev->tapedevt)
1408             {
1409                 HHCTA078E(); optrc = -1; break;
1410             }
1411             dev->stape_blkid_32 = 0;
1412             break;
1413 
1414         case TDPARM_BLKID32:
1415             if (TAPEDEVT_SCSITAPE != dev->tapedevt)
1416             {
1417                 HHCTA078E(); optrc = -1; break;
1418             }
1419             dev->stape_blkid_32 = 1;
1420             break;
1421 
1422         case TDPARM_NOERG:
1423             if (TAPEDEVT_SCSITAPE != dev->tapedevt)
1424             {
1425                 HHCTA078E(); optrc = -1; break;
1426             }
1427             dev->stape_no_erg = 1;
1428             break;
1429 #endif /* defined(OPTION_SCSI_TAPE) */
1430 
1431         default:
1432             logmsg(_("HHCTA071E %4.4X: option '%s': parse error\n"),
1433                 dev->devnum, argv[i]);
1434             optrc = -1;
1435             break;
1436 
1437         } // end switch (parser (&ptab[0], argv[i], &res))
1438 
1439         if (optrc < 0)
1440             rc = -1;
1441         else
1442             logmsg (_("HHCTA066I %4.4X: option '%s' accepted.\n"),
1443                 dev->devnum, argv[i]);
1444 
1445     } // end for (i = 1; i < argc; i++)
1446 
1447     if (0 != rc)
1448         return -1;
1449 
1450     /* Adjust the display if necessary */
1451     if(dev->tdparms.displayfeat)
1452     {
1453         if(strcmp(dev->filename,TAPE_UNLOADED)==0)
1454         {
1455             /* NO tape is loaded */
1456             if(TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype)
1457             {
1458                 /* A new tape SHOULD be mounted */
1459                 dev->tapedisptype   = TAPEDISPTYP_MOUNT;
1460                 dev->tapedispflags |= TAPEDISPFLG_REQAUTOMNT;
1461                 strlcpy( dev->tapemsg1, dev->tapemsg2, sizeof(dev->tapemsg1) );
1462             }
1463             else if(TAPEDISPTYP_UNMOUNT == dev->tapedisptype)
1464             {
1465                 dev->tapedisptype = TAPEDISPTYP_IDLE;
1466             }
1467         }
1468         else
1469         {
1470             /* A tape IS already loaded */
1471             dev->tapedisptype = TAPEDISPTYP_IDLE;
1472         }
1473     }
1474     UpdateDisplay(dev);
1475     ReqAutoMount(dev);
1476     return 0;
1477 
1478 } /* end function mountnewtape */
1479 
1480 
1481 /*-------------------------------------------------------------------*/
1482 /* Query the device definition                                       */
1483 /*-------------------------------------------------------------------*/
tapedev_query_device(DEVBLK * dev,char ** class,int buflen,char * buffer)1484 void tapedev_query_device ( DEVBLK *dev, char **class,
1485                 int buflen, char *buffer )
1486 {
1487     char devparms[ MAX_PATH+1 + 128 ];
1488     char dispmsg [ 256 ];
1489 
1490     BEGIN_DEVICE_CLASS_QUERY( "TAPE", dev, class, buflen, buffer );
1491 
1492     *buffer = 0;
1493     devparms[0]=0;
1494     dispmsg [0]=0;
1495 
1496     GetDisplayMsg( dev, dispmsg, sizeof(dispmsg) );
1497 
1498     if (strchr(dev->filename,' ')) strlcat( devparms, "\"",          sizeof(devparms));
1499                                    strlcat( devparms, dev->filename, sizeof(devparms));
1500     if (strchr(dev->filename,' ')) strlcat( devparms, "\"",          sizeof(devparms));
1501 
1502 #if defined( OPTION_TAPE_AUTOMOUNT )
1503 
1504     if (dev->noautomount)
1505         strlcat( devparms, " noautomount", sizeof(devparms));
1506 
1507 #endif /* OPTION_TAPE_AUTOMOUNT */
1508 
1509     if ( strcmp( dev->filename, TAPE_UNLOADED ) == 0 )
1510     {
1511 #if defined(OPTION_SCSI_TAPE)
1512         if ( TAPEDEVT_SCSITAPE == dev->tapedevt )
1513         {
1514             if (0x3590 == dev->devtype) // emulating 3590
1515             {
1516                 if (!dev->stape_blkid_32 ) strlcat( devparms, " --blkid-22", sizeof(devparms) );
1517             }
1518             else // emulating 3480, 3490
1519             {
1520                 if ( dev->stape_blkid_32 ) strlcat( devparms, " --blkid-32", sizeof(devparms) );
1521             }
1522             if ( dev->stape_no_erg ) strlcat( devparms, " --no-erg", sizeof(devparms) );
1523         }
1524 #endif
1525         snprintf(buffer, buflen, "%s%s%s",
1526             devparms,
1527             dev->tdparms.displayfeat ? ", Display: " : "",
1528             dev->tdparms.displayfeat ?    dispmsg    : "");
1529     }
1530     else // (filename was specified)
1531     {
1532         char tapepos[64]; tapepos[0]=0;
1533 
1534         if ( TAPEDEVT_SCSITAPE != dev->tapedevt )
1535         {
1536             snprintf( tapepos, sizeof(tapepos), "[%d:%08"I64_FMT"X] ",
1537                 dev->curfilen, dev->nxtblkpos );
1538             tapepos[sizeof(tapepos)-1] = 0;
1539         }
1540 #if defined(OPTION_SCSI_TAPE)
1541         else // (this is a SCSI tape drive)
1542         {
1543             if (STS_BOT( dev ))
1544             {
1545                 dev->eotwarning = 0;
1546                 strlcat(tapepos,"*BOT* ",sizeof(tapepos));
1547             }
1548 
1549             // If tape has a display, then GetDisplayMsg already
1550             // appended *FP* for us. Otherwise we need to do it.
1551 
1552             if ( !dev->tdparms.displayfeat )
1553                 if (STS_WR_PROT( dev ))
1554                     strlcat(tapepos,"*FP* ",sizeof(tapepos));
1555 
1556             if (0x3590 == dev->devtype) // emulating 3590
1557             {
1558                 if (!dev->stape_blkid_32 ) strlcat( devparms, " --blkid-22", sizeof(devparms) );
1559             }
1560             else // emulating 3480, 3490
1561             {
1562                 if ( dev->stape_blkid_32 ) strlcat( devparms, " --blkid-32", sizeof(devparms) );
1563             }
1564             if ( dev->stape_no_erg ) strlcat( devparms, " --no-erg", sizeof(devparms) );
1565         }
1566 #endif
1567 
1568         if ( TAPEDEVT_SCSITAPE != dev->tapedevt
1569 #if defined(OPTION_SCSI_TAPE)
1570             || STS_MOUNTED(dev)
1571 #endif
1572         )
1573         {
1574             // Not a SCSI tape,  -or-  mounted SCSI tape...
1575 
1576             snprintf (buffer, buflen, "%s%s %s%s%s",
1577 
1578                 devparms, (dev->readonly ? " ro" : ""),
1579 
1580                 tapepos,
1581                 dev->tdparms.displayfeat ? "Display: " : "",
1582                 dev->tdparms.displayfeat ?  dispmsg    : "");
1583         }
1584         else /* ( TAPEDEVT_SCSITAPE == dev->tapedevt && STS_NOT_MOUNTED(dev) ) */
1585         {
1586             // UNmounted SCSI tape...
1587 
1588             snprintf (buffer, buflen, "%s%s (%sNOTAPE)%s%s",
1589 
1590                 devparms, (dev->readonly ? " ro" : ""),
1591 
1592                 dev->fd < 0              ?   "closed; "  : "",
1593                 dev->tdparms.displayfeat ? ", Display: " : "",
1594                 dev->tdparms.displayfeat ?    dispmsg    : ""  );
1595         }
1596     }
1597 
1598     buffer[buflen-1] = 0;
1599 
1600 } /* end function tapedev_query_device */
1601 
1602 
1603 /*-------------------------------------------------------------------*/
1604 /* Issue a message on the console indicating the display status      */
1605 /*-------------------------------------------------------------------*/
UpdateDisplay(DEVBLK * dev)1606 void UpdateDisplay( DEVBLK *dev )
1607 {
1608     if ( dev->tdparms.displayfeat )
1609     {
1610         char msgbfr[256];
1611 
1612         GetDisplayMsg( dev, msgbfr, sizeof(msgbfr) );
1613 
1614         if ( dev->prev_tapemsg )
1615         {
1616             if ( strcmp( msgbfr, dev->prev_tapemsg ) == 0 )
1617                 return;
1618             free( dev->prev_tapemsg );
1619             dev->prev_tapemsg = NULL;
1620         }
1621 
1622         dev->prev_tapemsg = strdup( msgbfr );
1623 
1624         logmsg(_("HHCTA010I %4.4X: Now Displays: %s\n"),
1625             dev->devnum, msgbfr );
1626     }
1627 #if defined(OPTION_SCSI_TAPE)
1628     else
1629         if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1630             int_scsi_status_update( dev, 1 );
1631 #endif
1632 }
1633 
1634 
1635 /*-------------------------------------------------------------------*/
1636 /* Issue Automatic Mount Requests as defined by the display          */
1637 /*-------------------------------------------------------------------*/
ReqAutoMount(DEVBLK * dev)1638 void ReqAutoMount( DEVBLK *dev )
1639 {
1640     char   volser[7];
1641     BYTE   tapeloaded, autoload, mountreq, unmountreq, stdlbled, ascii, scratch;
1642     char*  lbltype;
1643     char*  tapemsg = "";
1644 
1645     ///////////////////////////////////////////////////////////////////
1646 
1647     // The Automatic Cartridge Loader or "ACL" (sometimes also referred
1648     // to as an "Automatic Cartridge Feeder" (ACF) too) automatically
1649     // loads the next cartridge [from the magazine] whenever a tape is
1650     // unloaded, BUT ONLY IF the 'Index Automatic Load' bit (bit 7) of
1651     // the FCB (Format Control Byte, byte 0) was on whenever the Load
1652     // Display ccw was sent to the drive. If the bit was not on when
1653     // the Load Display ccw was issued, then the requested message (if
1654     // any) is displayed until the next tape mount/dismount and the ACL
1655     // is NOT activated (i.e. the next tape is NOT automatically loaded).
1656     // If the bit was on however, then, as stated, the ACF component of
1657     // the drive will automatically load the next [specified] cartridge.
1658 
1659     // Whenever the ACL facility is activated (via bit 7 of byte 0 of
1660     // the Load Display ccw), then only bytes 1-8 of the "Display Until
1661     // Mounted" message (or bytes 9-17 of a "Display Until Dismounted
1662     // Then Mounted" message) are displayed to let the operator know
1663     // which tape is currently being processed by the autoloader and
1664     // thus is basically for informational purposes only (the operator
1665     // does NOT need to do anything since the auto-loader is handling
1666     // tape mounts for them automatically; i.e. the message is NOT an
1667     // operator mount/dismount request).
1668 
1669     // If the 'Index Automatic Load' bit was not set in the Load Display
1670     // CCW however, then the specified "Display Until Mounted", "Display
1671     // Until Unmounted" or "Display Until Unmounted Then Display Until
1672     // Mounted" message is meant as a mount, unmount, or unmount-then-
1673     // mount request for the actual [human being] operator, and thus
1674     // they DO need to take some sort of action (since the ACL automatic
1675     // loader facility is not active; i.e. the message is a request to
1676     // the operator to manually unload, load or unload then load a tape).
1677 
1678     // THUS... If the TAPEDISPFLG_AUTOLOADER flag is set (indicating
1679     // the autoloader is (or should be) active), then the message we
1680     // issue is simply for INFORMATIONAL purposes only (i.e. "FYI: the
1681     // following tape is being *automatically* loaded; you don't need
1682     // to actually do anything")
1683 
1684     // If the TAPEDISPFLG_AUTOLOADER is flag is NOT set however, then
1685     // we need to issue a message notifying the operator of what they
1686     // are *expected* to do (e.g. either unload, load or unload/load
1687     // the specified tape volume).
1688 
1689     // Also please note that while there are no formally established
1690     // standards regarding the format of the Load Display CCW message
1691     // text, there are however certain established conventions (estab-
1692     // lished by IBM naturally). If the first character is an 'M', it
1693     // means "Please MOUNT the indicated volume". An 'R' [apparently]
1694     // means "Retain", and, similarly, 'K' means "Keep" (same thing as
1695     // "Retain"). If the LAST character is an 'S', then it means that
1696     // a Standard Labeled volume is being requested, whereas an 'N'
1697     // (or really, anything OTHER than an 'S' (except 'A')) means an
1698     // unlabeled (or non-labeled) tape volume is being requested. An
1699     // 'A' as the last character means a Standard Labeled ASCII tape
1700     // is being requested. If the message is "SCRTCH" (or something
1701     // similar), then a either a standard labeled or unlabeled scratch
1702     // tape is obviously being requested (there doesn't seem to be any
1703     // convention/consensus regarding the format for requesting scratch
1704     // tapes; some shops for example use 'XXXSCR' to indicate that a
1705     // scratch tape from tape pool 'XXX' should be mounted).
1706 
1707     ///////////////////////////////////////////////////////////////////
1708 
1709     /* Open the file/drive if needed (kick off auto-mount if needed) */
1710     if (dev->fd < 0)
1711     {
1712         BYTE unitstat = 0, code = 0;
1713         BYTE *sensebkup;
1714 
1715         /* Save any pending sense */
1716         sensebkup=malloc(dev->numsense);
1717         memcpy(sensebkup,dev->sense,dev->numsense);
1718 
1719         dev->tmh->open( dev, &unitstat, code );
1720 
1721         /* Restore pending sense */
1722         memcpy(dev->sense,sensebkup,dev->numsense);
1723         free(sensebkup);
1724 
1725 #if defined(OPTION_SCSI_TAPE)
1726         if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1727         {
1728             // PROGRAMMING NOTE: it's important to do TWO refreshes here
1729             // to cause the auto-mount thread to get created. Doing only
1730             // one doesn't work and doing two shouldn't cause any harm.
1731 
1732             GENTMH_PARMS  gen_parms;
1733 
1734             gen_parms.action  = GENTMH_SCSI_ACTION_UPDATE_STATUS;
1735             gen_parms.dev     = dev;
1736 
1737             // (refresh potentially stale status)
1738             VERIFY( dev->tmh->generic( &gen_parms ) == 0 );
1739 
1740             // (force auto-mount thread creation)
1741             VERIFY( dev->tmh->generic( &gen_parms ) == 0 );
1742         }
1743 #endif /* defined(OPTION_SCSI_TAPE) */
1744     }
1745 
1746     /* Disabled when [non-SCSI] ACL in use */
1747     if ( dev->als )
1748         return;
1749 
1750     /* Do we actually have any work to do? */
1751     if ( !( dev->tapedispflags & TAPEDISPFLG_REQAUTOMNT ) )
1752         return;     // (nothing to do!)
1753 
1754     /* Reset work flag */
1755     dev->tapedispflags &= ~TAPEDISPFLG_REQAUTOMNT;
1756 
1757     /* If the drive doesn't have a display,
1758        then it can't have an auto-loader either */
1759     if ( !dev->tdparms.displayfeat )
1760         return;
1761 
1762     /* Determine if mount or unmount request
1763        and get pointer to correct message */
1764 
1765     tapeloaded = dev->tmh->tapeloaded( dev, NULL, 0 ) ? TRUE : FALSE;
1766 
1767     mountreq   = FALSE;     // (default)
1768     unmountreq = FALSE;     // (default)
1769 
1770     if (tapeloaded)
1771     {
1772         // A tape IS already loaded...
1773 
1774         // 1st byte of message1 non-blank, *AND*,
1775         // unmount request or,
1776         // unmountmount request and not message2-only flag?
1777 
1778         if (' ' != *(tapemsg = dev->tapemsg1) &&
1779             (0
1780                 || TAPEDISPTYP_UNMOUNT == dev->tapedisptype
1781                 || (1
1782                     && TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype
1783                     && !(dev->tapedispflags & TAPEDISPFLG_MESSAGE2)
1784                    )
1785             )
1786         )
1787             unmountreq = TRUE;
1788     }
1789     else
1790     {
1791         // NO TAPE is loaded yet...
1792 
1793         // mount request and 1st byte of msg1 non-blank, *OR*,
1794         // unmountmount request and 1st byte of msg2 non-blank?
1795 
1796         if (
1797         (1
1798             && TAPEDISPTYP_MOUNT == dev->tapedisptype
1799             && ' ' != *(tapemsg = dev->tapemsg1)
1800         )
1801         ||
1802         (1
1803             && TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype
1804             && ' ' != *(tapemsg = dev->tapemsg2)
1805         ))
1806             mountreq = TRUE;
1807     }
1808 
1809     /* Extract volser from message */
1810     strncpy( volser, tapemsg+1, 6 ); volser[6]=0;
1811 
1812     /* Set some boolean flags */
1813     autoload = ( dev->tapedispflags & TAPEDISPFLG_AUTOLOADER )    ?  TRUE  :  FALSE;
1814     stdlbled = ( 'S' == tapemsg[7] )                              ?  TRUE  :  FALSE;
1815     ascii    = ( 'A' == tapemsg[7] )                              ?  TRUE  :  FALSE;
1816     scratch  = ( 'S' == tapemsg[0] )                              ?  TRUE  :  FALSE;
1817 
1818     lbltype = stdlbled ? "SL" : "UL";
1819 
1820 #if defined(OPTION_SCSI_TAPE)
1821 #if 1
1822     // ****************************************************************
1823     // ZZ FIXME: ZZ TODO:   ***  Programming Note  ***
1824 
1825     // Since we currently don't have any way of activating a SCSI tape
1826     // drive's REAL autoloader mechanism whenever we receive an auto-
1827     // mount message [from the guest o/s via the Load Display CCW], we
1828     // leave it to the operator to action the mount message displayed
1829 
1830     // Once ASPI code eventually gets added to Herc (and/or something
1831     // similar for the Linux world), then the following workaround can
1832     // be safely removed.
1833 
1834     autoload = FALSE;       // (temporarily forced; see above)
1835 
1836     // ****************************************************************
1837 #endif
1838 #endif /* defined(OPTION_SCSI_TAPE) */
1839 
1840     if ( autoload )
1841     {
1842         // ZZ TODO: Here is where we'd issue i/o (ASPI?) to the actual
1843         // hardware autoloader facility (i.e. the SCSI medium changer)
1844         // to unload and/or load the tape(s) if this were a SCSI auto-
1845         // loading tape drive.
1846 
1847         if ( unmountreq )
1848         {
1849             if ( scratch )
1850                 logmsg(_("AutoMount: %s%s scratch tape being auto-unloaded on %4.4X = %s\n"),
1851                     ascii ? "ASCII " : "",lbltype,
1852                     dev->devnum, dev->filename);
1853             else
1854                 logmsg(_("AutoMount: %s%s tape volume \"%s\" being auto-unloaded on %4.4X = %s\n"),
1855                     ascii ? "ASCII " : "",lbltype,
1856                     volser, dev->devnum, dev->filename);
1857         }
1858         if ( mountreq )
1859         {
1860             if ( scratch )
1861                 logmsg(_("AutoMount: %s%s scratch tape being auto-loaded on %4.4X = %s\n"),
1862                     ascii ? "ASCII " : "",lbltype,
1863                     dev->devnum, dev->filename);
1864             else
1865                 logmsg(_("AutoMount: %s%s tape volume \"%s\" being auto-loaded on %4.4X = %s\n"),
1866                     ascii ? "ASCII " : "",lbltype,
1867                     volser, dev->devnum, dev->filename);
1868         }
1869     }
1870 
1871 
1872 } /* end function ReqAutoMount */
1873 
1874 
1875 /*-------------------------------------------------------------------*/
1876 /*      Get 3480/3490/3590 Display text in 'human' form              */
1877 /* If not a 3480/3490/3590, then just update status if a SCSI tape   */
1878 /*-------------------------------------------------------------------*/
GetDisplayMsg(DEVBLK * dev,char * msgbfr,size_t lenbfr)1879 void GetDisplayMsg( DEVBLK *dev, char *msgbfr, size_t  lenbfr )
1880 {
1881     msgbfr[0]=0;
1882 
1883     if ( !dev->tdparms.displayfeat )
1884     {
1885         // (drive doesn't have a display)
1886 #if defined(OPTION_SCSI_TAPE)
1887         if (TAPEDEVT_SCSITAPE == dev->tapedevt)
1888             int_scsi_status_update( dev, 1 );
1889 #endif
1890         return;
1891     }
1892 
1893     if ( !IS_TAPEDISPTYP_SYSMSG( dev ) )
1894     {
1895         // -------------------------
1896         //   Display Host message
1897         // -------------------------
1898 
1899         // "When bit 3 (alternate) is set to 1, then
1900         //  bits 4 (blink) and 5 (low/high) are ignored."
1901 
1902         strlcpy( msgbfr, "\"", lenbfr );
1903 
1904         if ( dev->tapedispflags & TAPEDISPFLG_ALTERNATE )
1905         {
1906             char  msg1[9];
1907             char  msg2[9];
1908 
1909             strlcpy ( msg1,   dev->tapemsg1, sizeof(msg1) );
1910             strlcat ( msg1,   "        ",    sizeof(msg1) );
1911             strlcpy ( msg2,   dev->tapemsg2, sizeof(msg2) );
1912             strlcat ( msg2,   "        ",    sizeof(msg2) );
1913 
1914             strlcat ( msgbfr, msg1,             lenbfr );
1915             strlcat ( msgbfr, "\" / \"",        lenbfr );
1916             strlcat ( msgbfr, msg2,             lenbfr );
1917             strlcat ( msgbfr, "\"",             lenbfr );
1918             strlcat ( msgbfr, " (alternating)", lenbfr );
1919         }
1920         else
1921         {
1922             if ( dev->tapedispflags & TAPEDISPFLG_MESSAGE2 )
1923                 strlcat( msgbfr, dev->tapemsg2, lenbfr );
1924             else
1925                 strlcat( msgbfr, dev->tapemsg1, lenbfr );
1926 
1927             strlcat ( msgbfr, "\"",          lenbfr );
1928 
1929             if ( dev->tapedispflags & TAPEDISPFLG_BLINKING )
1930                 strlcat ( msgbfr, " (blinking)", lenbfr );
1931         }
1932 
1933         if ( dev->tapedispflags & TAPEDISPFLG_AUTOLOADER )
1934             strlcat( msgbfr, " (AUTOLOADER)", lenbfr );
1935 
1936         return;
1937     }
1938 
1939     // ----------------------------------------------
1940     //   Display SYS message (Unit/Device message)
1941     // ----------------------------------------------
1942 
1943     // First, build the system message, then move it into
1944     // the caller's buffer...
1945 
1946     strlcpy( dev->tapesysmsg, "\"", sizeof(dev->tapesysmsg) );
1947 
1948     switch ( dev->tapedisptype )
1949     {
1950     case TAPEDISPTYP_IDLE:
1951     case TAPEDISPTYP_WAITACT:
1952     default:
1953         // Blank display if no tape loaded...
1954         if ( !dev->tmh->tapeloaded( dev, NULL, 0 ) )
1955         {
1956             strlcat( dev->tapesysmsg, "        ", sizeof(dev->tapesysmsg) );
1957             break;
1958         }
1959 
1960         // " NT RDY " if tape IS loaded, but not ready...
1961         // (IBM docs say " NT RDY " means "Loaded but not ready")
1962 
1963         ASSERT( dev->tmh->tapeloaded( dev, NULL, 0 ) );
1964 
1965         if (0
1966             || dev->fd < 0
1967 #if defined(OPTION_SCSI_TAPE)
1968             || (1
1969                 && TAPEDEVT_SCSITAPE == dev->tapedevt
1970                 && !STS_ONLINE( dev )
1971                )
1972 #endif
1973         )
1974         {
1975             strlcat( dev->tapesysmsg, " NT RDY ", sizeof(dev->tapesysmsg) );
1976             break;
1977         }
1978 
1979         // Otherwise tape is loaded and ready  -->  "READY"
1980 
1981         ASSERT( dev->tmh->tapeloaded( dev, NULL, 0 ) );
1982 
1983         strlcat ( dev->tapesysmsg, " READY  ", sizeof(dev->tapesysmsg) );
1984         strlcat( dev->tapesysmsg, "\"", sizeof(dev->tapesysmsg) );
1985 
1986         if (0
1987             || dev->readonly
1988 #if defined(OPTION_SCSI_TAPE)
1989             || (1
1990                 &&  TAPEDEVT_SCSITAPE == dev->tapedevt
1991                 &&  STS_WR_PROT( dev )
1992                )
1993 #endif
1994         )
1995             // (append "file protect" indicator)
1996             strlcat ( dev->tapesysmsg, " *FP*", sizeof(dev->tapesysmsg) );
1997 
1998         // Copy system message to caller's buffer
1999         strlcpy( msgbfr, dev->tapesysmsg, lenbfr );
2000         return;
2001 
2002     case TAPEDISPTYP_ERASING:
2003         strlcat ( dev->tapesysmsg, " ERASING", sizeof(dev->tapesysmsg) );
2004         break;
2005 
2006     case TAPEDISPTYP_REWINDING:
2007         strlcat ( dev->tapesysmsg, "REWINDNG", sizeof(dev->tapesysmsg) );
2008         break;
2009 
2010     case TAPEDISPTYP_UNLOADING:
2011         strlcat ( dev->tapesysmsg, "UNLOADNG", sizeof(dev->tapesysmsg) );
2012         break;
2013 
2014     case TAPEDISPTYP_CLEAN:
2015         strlcat ( dev->tapesysmsg, "*CLEAN  ", sizeof(dev->tapesysmsg) );
2016         break;
2017     }
2018 
2019     strlcat( dev->tapesysmsg, "\"", sizeof(dev->tapesysmsg) );
2020 
2021     // Copy system message to caller's buffer
2022     strlcpy( msgbfr, dev->tapesysmsg, lenbfr );
2023 
2024 } /* end function GetDisplayMsg */
2025 
2026 
2027 /*-------------------------------------------------------------------*/
2028 /*                         IsAtLoadPoint                             */
2029 /*-------------------------------------------------------------------*/
2030 /* Called by the device-type-specific 'build_sense_xxxx' functions   */
2031 /* (indirectly via the 'build_senseX' function) when building sense  */
2032 /* for any i/o error (non-"TAPE_BSENSE_STATUSONLY" type call)       */
2033 /*-------------------------------------------------------------------*/
IsAtLoadPoint(DEVBLK * dev)2034 int IsAtLoadPoint (DEVBLK *dev)
2035 {
2036 int ldpt=0;
2037     if ( dev->fd >= 0 )
2038     {
2039         /* Set load point indicator if tape is at load point */
2040         switch (dev->tapedevt)
2041         {
2042         default:
2043         case TAPEDEVT_AWSTAPE:
2044             if (dev->nxtblkpos==0)
2045             {
2046                 ldpt=1;
2047             }
2048             break;
2049 
2050         case TAPEDEVT_HETTAPE:
2051             if (dev->hetb->cblk == 0)
2052             {
2053                 ldpt=1;
2054             }
2055             break;
2056 
2057 #if defined(OPTION_SCSI_TAPE)
2058         case TAPEDEVT_SCSITAPE:
2059             int_scsi_status_update( dev, 0 );
2060             if ( STS_BOT( dev ) )
2061             {
2062                 dev->eotwarning = 0;
2063                 ldpt=1;
2064             }
2065             break;
2066 #endif /* defined(OPTION_SCSI_TAPE) */
2067 
2068         case TAPEDEVT_OMATAPE:
2069             if (dev->nxtblkpos == 0 && dev->curfilen == 1)
2070             {
2071                 ldpt=1;
2072             }
2073             break;
2074         } /* end switch(dev->tapedevt) */
2075     }
2076     else // ( dev->fd < 0 )
2077     {
2078         if ( TAPEDEVT_SCSITAPE == dev->tapedevt )
2079             ldpt=0; /* (tape cannot possibly be at loadpoint
2080                         if the device cannot even be opened!) */
2081         else if ( strcmp( dev->filename, TAPE_UNLOADED ) != 0 )
2082         {
2083             /* If the tape has a filename but the tape is not yet */
2084             /* opened, then we are at loadpoint                   */
2085             ldpt=1;
2086         }
2087     }
2088     return ldpt;
2089 
2090 } /* end function IsAtLoadPoint */
2091 
2092 
2093 /*********************************************************************/
2094 /*********************************************************************/
2095 /**                                                                 **/
2096 /**                   AUTOLOADER FUNCTIONS                          **/
2097 /**                                                                 **/
2098 /*********************************************************************/
2099 /*********************************************************************/
2100 
2101 /*-------------------------------------------------------------------*/
2102 /*                         autoload_init                             */
2103 /*-------------------------------------------------------------------*/
2104 /*  initialise the Autoloader feature                                */
2105 /*-------------------------------------------------------------------*/
autoload_init(DEVBLK * dev,int ac,char ** av)2106 void autoload_init(DEVBLK *dev,int ac,char **av)
2107 {
2108     char        bfr[4096];
2109     char    *rec;
2110     FILE        *aldf;
2111     char    *verb;
2112     int        i;
2113     char    *strtokw;
2114     char     pathname[MAX_PATH];
2115 
2116     autoload_close(dev);
2117     if(ac<1)
2118     {
2119         return;
2120     }
2121     if(av[0][0]!='@')
2122     {
2123         return;
2124     }
2125     logmsg(_("TAPE: Autoloader file request fn=%s\n"),&av[0][1]);
2126     hostpath(pathname, &av[0][1], sizeof(pathname));
2127     if(!(aldf=fopen(pathname,"r")))
2128     {
2129         return;
2130     }
2131     for(i=1;i<ac;i++)
2132     {
2133         autoload_global_parms(dev,av[i]);
2134     }
2135     while((rec=fgets(bfr,4096,aldf)))
2136     {
2137         for(i=(strlen(rec)-1);isspace(rec[i]) && i>=0;i--)
2138         {
2139             rec[i]=0;
2140         }
2141         if(strlen(rec)==0)
2142         {
2143             continue;
2144         }
2145         verb=strtok_r(rec," \t",&strtokw);
2146         if(verb==NULL)
2147         {
2148             continue;
2149         }
2150         if(verb[0]==0)
2151         {
2152             continue;
2153         }
2154         if(verb[0]=='#')
2155         {
2156             continue;
2157         }
2158         if(strcmp(verb,"*")==0)
2159         {
2160             while((verb=strtok_r(NULL," \t",&strtokw)))
2161             {
2162                 autoload_global_parms(dev,verb);
2163             }
2164             continue;
2165         }
2166         autoload_tape_entry(dev,verb,&strtokw);
2167     } // end while((rec=fgets(bfr,4096,aldf)))
2168     fclose(aldf);
2169     return;
2170 
2171 } /* end function autoload_init */
2172 
2173 
2174 /*-------------------------------------------------------------------*/
2175 /*                      autoload_close                               */
2176 /*-------------------------------------------------------------------*/
2177 /*  terminate autoloader operations: release all storage that        */
2178 /*  was allocated by the autoloader facility                         */
2179 /*-------------------------------------------------------------------*/
autoload_close(DEVBLK * dev)2180 void autoload_close(DEVBLK *dev)
2181 {
2182     int        i;
2183     if(dev->al_argv!=NULL)
2184     {
2185         for(i=0;i<dev->al_argc;i++)
2186         {
2187             free(dev->al_argv[i]);
2188             dev->al_argv[i]=NULL;
2189         }
2190         free(dev->al_argv);
2191         dev->al_argv=NULL;
2192         dev->al_argc=0;
2193     }
2194     dev->al_argc=0;
2195     if(dev->als!=NULL)
2196     {
2197         for(i=0;i<dev->alss;i++)
2198         {
2199             autoload_clean_entry(dev,i);
2200         }
2201         free(dev->als);
2202         dev->als=NULL;
2203         dev->alss=0;
2204     }
2205 } /* end function autoload_close */
2206 
2207 
2208 /*-------------------------------------------------------------------*/
2209 /*                    autoload_clean_entry                           */
2210 /*-------------------------------------------------------------------*/
2211 /*  release storage allocated for an autoloader slot                 */
2212 /*  (except the slot itself)                                         */
2213 /*-------------------------------------------------------------------*/
autoload_clean_entry(DEVBLK * dev,int ix)2214 void autoload_clean_entry(DEVBLK *dev,int ix)
2215 {
2216     int i;
2217     for(i=0;i<dev->als[ix].argc;i++)
2218     {
2219         free(dev->als[ix].argv[i]);
2220         dev->als[ix].argv[i]=NULL;
2221     }
2222     dev->als[ix].argc=0;
2223     if(dev->als[ix].filename!=NULL)
2224     {
2225         free(dev->als[ix].filename);
2226         dev->als[ix].filename=NULL;
2227     }
2228 } /* end function autoload_clean_entry */
2229 
2230 
2231 /*-------------------------------------------------------------------*/
2232 /*                    autoload_global_parms                          */
2233 /*-------------------------------------------------------------------*/
2234 /*  Appends a blank delimited word to the list of parameters         */
2235 /*  that will be passed for every tape mounted by the autoloader     */
2236 /*-------------------------------------------------------------------*/
autoload_global_parms(DEVBLK * dev,char * par)2237 void autoload_global_parms(DEVBLK *dev,char *par)
2238 {
2239     logmsg(_("TAPE Autoloader - Adding global parm %s\n"),par);
2240     if(dev->al_argv==NULL)
2241     {
2242         dev->al_argv=malloc(sizeof(char *)*256);
2243         dev->al_argc=0;
2244     }
2245     dev->al_argv[dev->al_argc]=(char *)malloc(strlen(par)+sizeof(char));
2246     strcpy(dev->al_argv[dev->al_argc],par);
2247     dev->al_argc++;
2248 
2249 } /* end function autoload_global_parms */
2250 
2251 
2252 /*-------------------------------------------------------------------*/
2253 /*                    autoload_tape_entry                            */
2254 /*-------------------------------------------------------------------*/
2255 /*  populate an autoloader slot  (creates new slot if needed)        */
2256 /*-------------------------------------------------------------------*/
autoload_tape_entry(DEVBLK * dev,char * fn,char ** strtokw)2257 void autoload_tape_entry(DEVBLK *dev,char *fn,char **strtokw)
2258 {
2259     char *p;
2260     TAPEAUTOLOADENTRY tae;
2261     logmsg(_("TAPE Autoloader: Adding tape entry %s\n"),fn);
2262     memset(&tae,0,sizeof(tae));
2263     tae.filename=malloc(strlen(fn)+sizeof(char)+1);
2264     strcpy(tae.filename,fn);
2265     while((p=strtok_r(NULL," \t",strtokw)))
2266     {
2267         if(tae.argv==NULL)
2268         {
2269             tae.argv=malloc(sizeof(char *)*256);
2270         }
2271         tae.argv[tae.argc]=malloc(strlen(p)+sizeof(char)+1);
2272         strcpy(tae.argv[tae.argc],p);
2273         tae.argc++;
2274     }
2275     if(dev->als==NULL)
2276     {
2277         dev->als=malloc(sizeof(tae));
2278         dev->alss=0;
2279     }
2280     else
2281     {
2282         dev->als=realloc(dev->als,sizeof(tae)*(dev->alss+1));
2283     }
2284     memcpy(&dev->als[dev->alss],&tae,sizeof(tae));
2285     dev->alss++;
2286 
2287 } /* end function autoload_tape_entry */
2288 
2289 
2290 /*-------------------------------------------------------------------*/
2291 /*             autoload_wait_for_tapemount_thread                    */
2292 /*-------------------------------------------------------------------*/
autoload_wait_for_tapemount_thread(void * db)2293 void *autoload_wait_for_tapemount_thread(void *db)
2294 {
2295 int     rc  = -1;
2296 DEVBLK *dev = (DEVBLK*) db;
2297 
2298     obtain_lock(&dev->lock);
2299     {
2300         while
2301         (
2302             dev->als
2303             &&
2304             (rc = autoload_mount_next( dev )) != 0
2305         )
2306         {
2307             release_lock( &dev->lock );
2308             SLEEP(AUTOLOAD_WAIT_FOR_TAPEMOUNT_INTERVAL_SECS);
2309             obtain_lock( &dev->lock );
2310         }
2311     }
2312     release_lock(&dev->lock);
2313     if ( rc == 0 )
2314         device_attention(dev,CSW_DE);
2315     return NULL;
2316 
2317 } /* end function autoload_wait_for_tapemount_thread */
2318 
2319 
2320 /*-------------------------------------------------------------------*/
2321 /*                     autoload_mount_first                          */
2322 /*-------------------------------------------------------------------*/
2323 /*  mount in the drive the tape which is                             */
2324 /*  positionned in the 1st autoloader slot                           */
2325 /*-------------------------------------------------------------------*/
autoload_mount_first(DEVBLK * dev)2326 int autoload_mount_first(DEVBLK *dev)
2327 {
2328     dev->alsix=0;
2329     return(autoload_mount_tape(dev,0));
2330 }
2331 
2332 
2333 /*-------------------------------------------------------------------*/
2334 /*                     autoload_mount_next                           */
2335 /*-------------------------------------------------------------------*/
2336 /*  mount in the drive the tape whch is                              */
2337 /*  positionned in the slot after the currently mounted tape.        */
2338 /*  if this is the last tape, close the autoloader                   */
2339 /*-------------------------------------------------------------------*/
autoload_mount_next(DEVBLK * dev)2340 int autoload_mount_next(DEVBLK *dev)
2341 {
2342     if(dev->alsix>=dev->alss)
2343     {
2344         autoload_close(dev);
2345         return -1;
2346     }
2347     dev->alsix++;
2348     return(autoload_mount_tape(dev,dev->alsix));
2349 }
2350 
2351 
2352 /*-------------------------------------------------------------------*/
2353 /*                     autoload_mount_tape                           */
2354 /*-------------------------------------------------------------------*/
2355 /*  mount in the drive the tape which is                             */
2356 /*  positionned in the autoloader slot #alix                         */
2357 /*-------------------------------------------------------------------*/
autoload_mount_tape(DEVBLK * dev,int alix)2358 int autoload_mount_tape(DEVBLK *dev,int alix)
2359 {
2360     char        **pars;
2361     int        pcount=1;
2362     int        i;
2363     int        rc;
2364     if(alix>=dev->alss)
2365     {
2366         return -1;
2367     }
2368     pars=malloc(sizeof(BYTE *)*256);
2369     pars[0]=dev->als[alix].filename;
2370     for(i=0;i<dev->al_argc;i++,pcount++)
2371     {
2372         pars[pcount]=malloc(strlen(dev->al_argv[i])+10);
2373         strcpy(pars[pcount],dev->al_argv[i]);
2374         if(pcount>255)
2375         {
2376             break;
2377         }
2378     }
2379     for(i=0;i<dev->als[alix].argc;i++,pcount++)
2380     {
2381         pars[pcount]=malloc(strlen(dev->als[alix].argv[i])+10);
2382         strcpy(pars[pcount],dev->als[alix].argv[i]);
2383         if(pcount>255)
2384         {
2385             break;
2386         }
2387     }
2388     rc=mountnewtape(dev,pcount,pars);
2389     for(i=1;i<pcount;i++)
2390     {
2391         free(pars[i]);
2392     }
2393     free(pars);
2394     return(rc);
2395 
2396 } /* end function autoload_mount_tape */
2397 
2398 
2399 /*-------------------------------------------------------------------*/
2400 /* is_tapeloaded_filename                                            */
2401 /*-------------------------------------------------------------------*/
is_tapeloaded_filename(DEVBLK * dev,BYTE * unitstat,BYTE code)2402 int is_tapeloaded_filename ( DEVBLK *dev, BYTE *unitstat, BYTE code )
2403 {
2404     UNREFERENCED(unitstat);
2405     UNREFERENCED(code);
2406     // true 1 == tape loaded, false 0 == tape not loaded
2407     return strcmp( dev->filename, TAPE_UNLOADED ) != 0 ? 1 : 0;
2408 }
2409 
2410 /*-------------------------------------------------------------------*/
2411 /* return_false1                                                     */
2412 /*-------------------------------------------------------------------*/
return_false1(DEVBLK * dev)2413 int return_false1 ( DEVBLK *dev )
2414 {
2415     UNREFERENCED(dev);
2416     return 0;
2417 }
2418 
2419 /*-------------------------------------------------------------------*/
2420 /* write_READONLY                                                    */
2421 /*-------------------------------------------------------------------*/
write_READONLY(DEVBLK * dev,BYTE * unitstat,BYTE code)2422 int write_READONLY ( DEVBLK *dev, BYTE *unitstat, BYTE code )
2423 {
2424     build_senseX(TAPE_BSENSE_WRITEPROTECT,dev,unitstat,code);
2425     return -1;
2426 }
2427 
2428 /*-------------------------------------------------------------------*/
2429 /* write_READONLY5                                                   */
2430 /*-------------------------------------------------------------------*/
write_READONLY5(DEVBLK * dev,BYTE * bfr,U16 blklen,BYTE * unitstat,BYTE code)2431 int write_READONLY5 ( DEVBLK *dev, BYTE *bfr, U16 blklen, BYTE *unitstat, BYTE code )
2432 {
2433     UNREFERENCED(bfr);
2434     UNREFERENCED(blklen);
2435     build_senseX(TAPE_BSENSE_WRITEPROTECT,dev,unitstat,code);
2436     return -1;
2437 }
2438 
2439 /*-------------------------------------------------------------------*/
2440 /* no_operation                                                      */
2441 /*-------------------------------------------------------------------*/
no_operation(DEVBLK * dev,BYTE * unitstat,BYTE code)2442 int no_operation ( DEVBLK *dev, BYTE *unitstat, BYTE code )
2443 {
2444     build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code );
2445     return 0;
2446 }
2447 
2448 /*-------------------------------------------------------------------*/
2449 /* readblkid_virtual                                                 */
2450 /*-------------------------------------------------------------------*/
readblkid_virtual(DEVBLK * dev,BYTE * logical,BYTE * physical)2451 int readblkid_virtual ( DEVBLK* dev, BYTE* logical, BYTE* physical )
2452 {
2453     // NOTE: returned value is always in guest BIG-ENDIAN format...
2454 
2455     BYTE  blockid[4];
2456 
2457     if (0x3590 == dev->devtype)
2458     {
2459         // Full 32-bit block-id...
2460 
2461         blockid[0] = (dev->blockid >> 24) & 0xFF;
2462         blockid[1] = (dev->blockid >> 16) & 0xFF;
2463         blockid[2] = (dev->blockid >> 8 ) & 0xFF;
2464         blockid[3] = (dev->blockid      ) & 0xFF;
2465     }
2466     else // (3480 et. al)
2467     {
2468         // "22-bit" block-id...
2469 
2470         blockid[0] = 0x01;  // ("wrap" value)
2471         blockid[1] = (dev->blockid >> 16) & 0x3F;
2472         blockid[2] = (dev->blockid >> 8 ) & 0xFF;
2473         blockid[3] = (dev->blockid      ) & 0xFF;
2474     }
2475 
2476     // NOTE: For virtual tape devices, we return the same value
2477     // for both the logical "Channel block ID" value as well as
2478     // the physical "Device block ID" value...
2479 
2480     if (logical)  memcpy( logical,  &blockid[0], 4 );
2481     if (physical) memcpy( physical, &blockid[0], 4 );
2482 
2483     return 0;
2484 }
2485 
2486 /*-------------------------------------------------------------------*/
2487 /* locateblk_virtual                                                 */
2488 /*-------------------------------------------------------------------*/
locateblk_virtual(DEVBLK * dev,U32 blockid,BYTE * unitstat,BYTE code)2489 int locateblk_virtual ( DEVBLK* dev, U32 blockid, BYTE *unitstat, BYTE code )
2490 {
2491     // NOTE: 'blockid' passed in host (little-endian) format...
2492 
2493     int rc;
2494 
2495     /* Do it the hard way: rewind to load-point and then
2496        keep doing fsb, fsb, fsb... until we find our block
2497     */
2498     if ((rc = dev->tmh->rewind( dev, unitstat, code)) >= 0)
2499     {
2500         /* Reset position counters to start of file */
2501 
2502         dev->curfilen   =  1;
2503         dev->nxtblkpos  =  0;
2504         dev->prvblkpos  = -1;
2505         dev->blockid    =  0;
2506 
2507         /* Do it the hard way */
2508 
2509         while ( dev->blockid < blockid && ( rc >= 0 ) )
2510             rc = dev->tmh->fsb( dev, unitstat, code );
2511     }
2512 
2513     return rc;
2514 }
2515 
2516 /*-------------------------------------------------------------------*/
2517 /* generic_tmhcall              generic media-type-handler call...   */
2518 /*-------------------------------------------------------------------*/
generic_tmhcall(GENTMH_PARMS * pGenParms)2519 int generic_tmhcall ( GENTMH_PARMS* pGenParms )
2520 {
2521     if (!pGenParms)
2522     {
2523         errno = EINVAL;             // (invalid arguments)
2524         return -1;                  // (return failure)
2525     }
2526 
2527     switch (pGenParms->action)
2528     {
2529 #if defined(OPTION_SCSI_TAPE)
2530         case GENTMH_SCSI_ACTION_UPDATE_STATUS:
2531         {
2532             return update_status_scsitape( pGenParms->dev );
2533         }
2534 #endif /* defined(OPTION_SCSI_TAPE) */
2535 
2536         default:
2537         {
2538             errno = EINVAL;         // (invalid arguments)
2539             return -1;              // (return failure)
2540         }
2541     }
2542 
2543     return -1;      // (never reached)
2544 }
2545