1 /* TAPECCWS.C   (c) Copyright Roger Bowler, 1999-2009                */
2 /*              Hercules Tape Device Handler CCW Processing          */
3 
4 /* Original Author: Roger Bowler                                     */
5 /* Prime Maintainer: Ivan Warren                                     */
6 /* Secondary Maintainer: "Fish" (David B. Trout)                     */
7 
8 /*-------------------------------------------------------------------*/
9 /* This module contains the CCW handling functions for tape devices. */
10 /*                                                                   */
11 /* The subroutines in this module are called by the general tape     */
12 /* device handler (tapedev.c) when the tape format is AWSTAPE.       */
13 /*                                                                   */
14 /* Messages issued by this module are prefixed HHCTA0nn              */
15 /*-------------------------------------------------------------------*/
16 
17 /*-------------------------------------------------------------------*/
18 /* Reference information:                                            */
19 /* SG24-2506 IBM 3590 Tape Subsystem Technical Guide                 */
20 /* GA32-0331 IBM 3590 Hardware Reference                             */
21 /* GA32-0329 IBM 3590 Introduction and Planning Guide                */
22 /* SG24-2594 IBM 3590 Multiplatform Implementation                   */
23 /* ANSI INCITS 131-1994 (R1999) SCSI-2 Reference                     */
24 /* GA32-0127 IBM 3490E Hardware Reference                            */
25 /* GC35-0152 EREP Release 3.5.0 Reference                            */
26 /* SA22-7204 ESA/390 Common I/O-Device Commands                      */
27 /*-------------------------------------------------------------------*/
28 
29 #include "hstdinc.h"
30 #include "hercules.h"  /* need Hercules control blocks               */
31 #include "tapedev.h"   /* Main tape handler header file              */
32 
33 //#define  ENABLE_TRACING_STMTS     // (Fish: DEBUGGING)
34 
35 #ifdef ENABLE_TRACING_STMTS
36   #if !defined(DEBUG)
37     #warning DEBUG required for ENABLE_TRACING_STMTS
38   #endif
39   // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h)
40 #else
41   #undef  TRACE
42   #undef  ASSERT
43   #undef  VERIFY
44   #define TRACE       1 ? ((void)0) : logmsg
45   #define ASSERT(a)
46   #define VERIFY(a)   ((void)(a))
47 #endif
48 
49 /*-------------------------------------------------------------------*/
50 /*         (forward declarations needed by below tables)             */
51 /*-------------------------------------------------------------------*/
52 
53 extern  BYTE           TapeCommands3410 [];
54 extern  BYTE           TapeCommands3420 [];
55 extern  BYTE           TapeCommands3422 [];
56 extern  BYTE           TapeCommands3430 [];
57 extern  BYTE           TapeCommands3480 [];
58 extern  BYTE           TapeCommands3490 [];
59 extern  BYTE           TapeCommands3590 [];
60 extern  BYTE           TapeCommands9347 [];
61 
62 extern  TapeSenseFunc  build_sense_3410;
63 extern  TapeSenseFunc  build_sense_3420;
64         #define        build_sense_3422         build_sense_3420
65         #define        build_sense_3430         build_sense_3420
66 extern  TapeSenseFunc  build_sense_3480_etal;
67 extern  TapeSenseFunc  build_sense_3490;
68 extern  TapeSenseFunc  build_sense_3590;
69 extern  TapeSenseFunc  build_sense_Streaming;
70 
71 /*-------------------------------------------------------------------*/
72 /*                     TapeDevtypeList                               */
73 /* Format:                                                           */
74 /*                                                                   */
75 /*    A:    Supported Device Type,                                   */
76 /*    B:      Command table index, (TapeCommandTable)                */
77 /*    C:      UC on RewUnld,   (1/0 = true/false)                    */
78 /*    D:      CUE on RewUnld,  (1/0 = true/false)                    */
79 /*    E:      Sense Build Function table index (TapeSenseTable)      */
80 /*                                                                   */
81 /*-------------------------------------------------------------------*/
82 
83 int  TapeDevtypeList [] =
84 {
85    /*   A   B  C  D  E  */
86     0x3410, 0, 1, 0, 0,
87     0x3411, 0, 1, 0, 0,
88     0x3420, 1, 1, 1, 1,
89     0x3422, 2, 0, 0, 2,
90     0x3430, 3, 0, 0, 3,
91     0x3480, 4, 0, 0, 4,
92     0x3490, 5, 0, 0, 5,
93     0x3590, 6, 0, 0, 6,
94     0x9347, 7, 0, 0, 7,
95     0x9348, 7, 0, 0, 7,
96     0x8809, 7, 0, 0, 7,
97     0x0000, 0, 0, 0, 0      /* (end of table marker) */
98 };
99 
100 /*-------------------------------------------------------------------*/
101 /*                       TapeCommandTable                            */
102 /*                                                                   */
103 /*  Specific supported CCW codes for each device type. Index is      */
104 /*  fetched by TapeCommandIsValid from "TapeDevtypeList[ n+1 ]".     */
105 /*                                                                   */
106 /*-------------------------------------------------------------------*/
107 
108 BYTE*  TapeCommandTable [] =
109 {
110      TapeCommands3410,      /*  0   3410/3411                        */
111      TapeCommands3420,      /*  1   3420                             */
112      TapeCommands3422,      /*  2   3422                             */
113      TapeCommands3430,      /*  3   3430                             */
114      TapeCommands3480,      /*  4   3480 (Maybe all 38K Tapes)       */
115      TapeCommands3490,      /*  5   3490                             */
116      TapeCommands3590,      /*  6   3590                             */
117      TapeCommands9347,      /*  7   9347 (Maybe all streaming tapes) */
118      NULL
119 };
120 
121 /*-------------------------------------------------------------------*/
122 /*                       TapeSenseTable                              */
123 /*                                                                   */
124 /* SENSE function routing table. Index is fetched by 'build_senseX'  */
125 /* function from table entry "TapeDevtypeList[ i+4 ]".               */
126 /*-------------------------------------------------------------------*/
127 
128 TapeSenseFunc*  TapeSenseTable  [] =
129 {
130     build_sense_3410,       /*  0   3410/3411                        */
131     build_sense_3420,       /*  1   3420                             */
132     build_sense_3422,       /*  2   3422                             */
133     build_sense_3430,       /*  3   3430                             */
134     build_sense_3480_etal,  /*  4   3480 (Maybe all 38K Tapes)       */
135     build_sense_3490,       /*  5   3490                             */
136     build_sense_3590,       /*  6   3590                             */
137     build_sense_Streaming,  /*  7   9347 (Maybe all streaming tapes) */
138     NULL
139 };
140 
141 /*-------------------------------------------------------------------*/
142 /*           CCW opcode Validity Tables by Device Type               */
143 /*-------------------------------------------------------------------*/
144 /*                                                                   */
145 /* The below tables are used by 'TapeCommandIsValid' to determine    */
146 /* if a CCW code is initially valid or not for the given device.     */
147 /*                                                                   */
148 /*    0: Command is NOT valid                                        */
149 /*  * 1: Command is Valid, Tape MUST be loaded                       */
150 /*  * 2: Command is Valid, Tape NEED NOT be loaded                   */
151 /*    3: Command is Valid, But is a NO-OP (return CE+DE now)         */
152 /*    4: Command is Valid, But is a NO-OP (for virtual tapes)        */
153 /*  * 5: Command is Valid, Tape MUST be loaded (add DE to status)    */
154 /*                                                                   */
155 /*  * Note that CCWs codes marked as valid might still get rejected  */
156 /*    upon more stringent validity testing done by the actual CCW    */
157 /*    processing function itself.                                    */
158 /*                                                                   */
159 /* SOURCES:                                                          */
160 /*                                                                   */
161 /*   GX20-1850-2 "S/370 Reference Summary"  (3410/3411/3420)         */
162 /*   GX20-0157-1 "370/XA Reference Summary" (3420/3422/3430/3480)    */
163 /*   GA33-1510-0 "S/370 Model 115 FC"       (3410/3411)              */
164 /*                                                                   */
165 /* Ivan Warren, 2003-02-24                                           */
166 /*-------------------------------------------------------------------*/
167 
168 BYTE  TapeCommands3410 [256] =
169 {
170 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
171    0,1,1,1,2,0,0,5,0,0,0,0,1,0,0,5, /* 00 */
172    0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */
173    0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 20 */
174    0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 30 */
175    0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */
176    0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
177    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 60 */
178    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 70 */
179    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */
180    0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */
181    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* A0 */
182    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* B0 */
183    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* C0 */
184    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* D0 */
185    0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */
186    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0  /* F0 */
187 };
188 
189 BYTE  TapeCommands3420 [256] =
190 {
191 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
192    0,1,1,1,2,0,0,5,0,0,0,2,1,0,0,5, /* 00 */
193    0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */
194    0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 20 */
195    0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 30 */
196    0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */
197    0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
198    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 60 */
199    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 70 */
200    0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 80 */
201    0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */
202    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* A0 */
203    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* B0 */
204    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* C0 */
205    0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0, /* D0 */
206    0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */
207    0,0,0,2,4,0,0,0,0,0,0,0,0,2,0,0  /* F0 */
208 };
209 
210 BYTE  TapeCommands3422 [256] =
211 {
212 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
213    0,1,1,1,2,0,0,5,0,0,0,2,1,0,0,5, /* 00 */
214    0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 10 */
215    0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 20 */
216    0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 30 */
217    0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */
218    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
219    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */
220    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
221    0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, /* 80 */
222    0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */
223    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0 */
224    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */
225    0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */
226    0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0, /* D0 */
227    0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */
228    0,0,0,2,4,0,0,0,0,0,0,0,0,2,0,0  /* F0 */
229 };
230 
231 BYTE  TapeCommands3430 [256] =
232 {
233 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
234    0,1,1,1,2,0,0,5,0,0,0,2,1,0,0,5, /* 00 */
235    0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */
236    0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 20 */
237    0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 30 */
238    0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */
239    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
240    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */
241    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
242    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */
243    0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */
244    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0 */
245    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */
246    0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */
247    0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0, /* D0 */
248    0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */
249    0,0,0,2,4,0,0,0,0,0,0,0,0,2,0,0  /* F0 */
250 };
251 
252 BYTE  TapeCommands3480 [256] =
253 {
254 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
255    3,1,1,1,2,0,0,5,0,0,0,0,1,0,0,5, /* 00 */
256    0,0,1,3,0,0,0,1,0,0,0,0,0,0,0,1, /* 10 */
257    0,0,1,3,2,0,0,1,0,0,0,3,0,0,0,1, /* 20 */
258    0,0,0,3,2,0,0,1,0,0,0,3,0,0,0,1, /* 30 */
259    0,0,0,1,0,0,0,0,0,0,0,2,0,0,0,1, /* 40 */
260    0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0, /* 50 */
261    0,0,0,3,2,0,0,0,0,0,0,3,0,0,0,0, /* 60 */
262    0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* 70 */
263    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */
264    0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,2, /* 90 */
265    0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,2, /* A0 */
266    0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* B0 */
267    0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,0, /* C0 */
268    0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* D0 */
269    0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0, /* E0 */
270    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0  /* F0 */
271 };
272 
273 BYTE  TapeCommands3490 [256] =
274 {
275 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
276    3,1,1,1,2,0,0,5,0,0,0,0,1,0,0,5, /* 00 */
277    0,0,1,3,0,0,0,1,0,0,0,0,0,0,0,1, /* 10 */
278    0,0,1,3,2,0,0,1,0,0,0,3,0,0,0,1, /* 20 */
279    0,0,0,3,2,0,0,1,0,0,0,3,0,0,2,1, /* 30 */
280    0,0,0,1,0,0,0,0,0,0,0,2,0,0,2,1, /* 40 */
281    0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* 50 */
282    0,0,0,3,2,0,0,0,0,0,0,3,0,0,0,0, /* 60 */
283    0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* 70 */
284    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */
285    0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,2, /* 90 */
286    0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,2, /* A0 */
287    0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* B0 */
288    0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0, /* C0 */
289    0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* D0 */
290    0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0, /* E0 */
291    0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0  /* F0 */
292 };
293 
294 BYTE  TapeCommands3590 [256] =
295 {
296 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
297    3,1,1,1,2,0,1,5,0,0,1,0,1,0,0,5, /* 00 */
298    0,0,1,3,0,0,0,1,0,0,0,0,0,0,0,1, /* 10 */
299    0,0,1,3,2,0,0,1,0,0,0,3,0,0,0,1, /* 20 */
300    0,0,0,3,2,0,0,1,0,0,0,3,0,0,2,1, /* 30 */
301    0,0,0,1,0,0,0,0,0,0,0,2,0,0,2,1, /* 40 */
302    0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* 50 */
303    0,0,1,3,2,0,0,0,0,0,0,3,0,0,0,0, /* 60 */
304    0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* 70 */
305    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */
306    0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,2, /* 90 */
307    0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,2, /* A0 */
308    0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* B0 */
309    0,0,2,2,0,0,0,2,0,0,0,0,0,0,0,2, /* C0 */
310    0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* D0 */
311    0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0, /* E0 */
312    0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0  /* F0 */
313 };
314 
315 BYTE  TapeCommands9347 [256] =
316 {
317 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
318    0,1,1,1,2,0,0,5,0,0,0,2,1,0,0,5, /* 00 */
319    0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */
320    0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 20 */
321    0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 30 */
322    0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */
323    0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
324    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 60 */
325    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 70 */
326    0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 80 */
327    0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */
328    0,0,0,4,2,0,0,0,0,0,0,4,0,0,0,0, /* A0 */
329    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* B0 */
330    0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* C0 */
331    0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0, /* D0 */
332    0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */
333    0,0,0,2,4,0,0,0,0,0,0,0,0,2,0,0  /* F0 */
334 };
335 
336 /*-------------------------------------------------------------------*/
337 /* Ivan Warren 20040227                                              */
338 /*                                                                   */
339 /* This table is used by channel.c to determine if a CCW code        */
340 /* is an immediate command or not.                                   */
341 /*                                                                   */
342 /* The tape is addressed in the DEVHND structure as 'DEVIMM immed'   */
343 /*                                                                   */
344 /*     0:  ("false")  Command is *NOT* an immediate command          */
345 /*     1:  ("true")   Command *IS* an immediate command              */
346 /*                                                                   */
347 /* Note: An immediate command is defined as a command which returns  */
348 /* CE (channel end) during initialization (that is, no data is       */
349 /* actually transfered). In this case, IL is not indicated for a     */
350 /* Format 0 or Format 1 CCW when IL Suppression Mode is in effect.   */
351 /*                                                                   */
352 /*-------------------------------------------------------------------*/
353 
354 BYTE  TapeImmedCommands [256] =
355 {
356 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
357    0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1, /* 00 */
358    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */
359    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 20 */
360    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 30 */
361    0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, /* 40 */
362    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 50 */
363    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 60 */
364    0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1, /* 70 */ /* Adrian Trenkwalder - 77 was 1 */
365    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 80 */
366    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0, /* 90 */
367    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0, /* A0 */
368    0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1, /* B0 */
369    0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1, /* C0 */
370    0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1, /* D0 */
371    0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1, /* E0 */
372    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1  /* F0 */
373 };
374 
375 /*-------------------------------------------------------------------*/
376 /*                   TapeCommandIsValid      (Ivan Warren 20030224)  */
377 /*-------------------------------------------------------------------*/
378 /*                                                                   */
379 /* Determine if a CCW code is valid for the Device                   */
380 /*                                                                   */
381 /*   rc 0:   is *NOT* valid                                          */
382 /*   rc 1:   is Valid, tape MUST be loaded                           */
383 /*   rc 2:   is Valid, tape NEED NOT be loaded                       */
384 /*   rc 3:   is Valid, But is a NO-OP (Return CE+DE now)             */
385 /*   rc 4:   is Valid, But is a NO-OP for virtual tapes              */
386 /*   rc 5:   is Valid, Tape Must be loaded - Add DE to status        */
387 /*   rc 6:   is Valid, Tape load attempted - but not an error        */
388 /*           (used for sense and no contingency allegiance exists)   */
389 /*                                                                   */
390 /*-------------------------------------------------------------------*/
TapeCommandIsValid(BYTE code,U16 devtype,BYTE * rustat)391 int TapeCommandIsValid (BYTE code, U16 devtype, BYTE *rustat)
392 {
393 int i, rc, tix = 0, devtfound = 0;
394 
395     /*
396     **  Find the D/T in the table
397     **  If not found, treat as invalid CCW code
398     */
399 
400     *rustat = 0;
401 
402     for (i = 0; TapeDevtypeList[i] != 0; i += TAPEDEVTYPELIST_ENTRYSIZE)
403     {
404         if (TapeDevtypeList[i] == devtype)
405         {
406            devtfound = 1;
407            tix = TapeDevtypeList[i+1];
408 
409            if (TapeDevtypeList[i+2])
410            {
411                *rustat |= CSW_UC;
412            }
413            if (TapeDevtypeList[i+3])
414            {
415                *rustat |= CSW_CUE;
416            }
417            break;
418         }
419     }
420 
421     if (!devtfound)
422         return 0;
423 
424     rc = TapeCommandTable[tix][code];
425 
426     return rc;
427 
428 } /* end function TapeCommandIsValid */
429 
430 
431 /*********************************************************************/
432 /*********************************************************************/
433 /**                                                                 **/
434 /**               MAIN TAPE CCW PROCESSING FUNCTION                 **/
435 /**                                                                 **/
436 /*********************************************************************/
437 /*********************************************************************/
438 
439 #if defined( OPTION_TAPE_AUTOMOUNT )
440 static TAMDIR* findtamdir( int rej, int minlen, const char* pszDir );
441 #endif
442 
tapedev_execute_ccw(DEVBLK * dev,BYTE code,BYTE flags,BYTE chained,U16 count,BYTE prevcode,int ccwseq,BYTE * iobuf,BYTE * more,BYTE * unitstat,U16 * residual)443 void tapedev_execute_ccw (DEVBLK *dev, BYTE code, BYTE flags,
444         BYTE chained, U16 count, BYTE prevcode, int ccwseq,
445         BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual)
446 {
447 int             rc;                     /* Return code               */
448 int             len;                    /* Length of data block      */
449 long            num;                    /* Number of bytes to read   */
450 int             drc;                    /* code disposition          */
451 BYTE            rustat;                 /* Addl CSW stat on Rewind Unload */
452 
453     UNREFERENCED(ccwseq);
454 
455     /* Reset flags at start of CCW chain */
456     if (dev->ccwseq == 0)
457     {
458         dev->supvr_inhibit = 0;         /* (reset to default mode)   */
459         dev->write_immed   = 0;         /* (reset to default mode)   */
460         dev->tapssdlen     = 0;         /* (clear all subsys data)   */
461     }
462 
463     /* If this is a data-chained READ, then return any data remaining
464        in the buffer which was not used by the previous CCW */
465     if (chained & CCW_FLAGS_CD)
466     {
467         if (IS_CCW_RDBACK(code))
468         {
469             /* We don't need to move anything in this case - just set length */
470         }
471         else
472         {
473             memmove (iobuf, iobuf + dev->curbufoff, dev->curblkrem);
474         }
475         RESIDUAL_CALC (dev->curblkrem);
476         dev->curblkrem -= num;
477         dev->curbufoff = num;
478         *unitstat = CSW_CE | CSW_DE;
479         return;
480     }
481 
482     /* Command reject if data chaining and command is not a read type */
483     if ((flags & CCW_FLAGS_CD) &&
484         !(IS_CCW_READ(code) || IS_CCW_RDBACK(code)))
485     {
486         logmsg(_("HHCTA072E Data chaining not supported for CCW %2.2X\n"),
487                 code);
488         build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
489         return;
490     }
491 
492     /* Command reject if command is not Read Subsystem Data command
493        if the previous one was a Perform Subsystem Function command
494        that prepared some subsystem data for subsequent reading
495     */
496     if (0x77 == prevcode && dev->tapssdlen && 0x3E != code)
497     {
498         build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
499         return;
500     }
501 
502     /* Early determination of CCW validity via TapeCommandTable lookup... */
503 
504     drc = TapeCommandIsValid (code, dev->devtype, &rustat);
505 
506     switch (drc)
507     {
508         default:    /* Should NOT occur! */
509 
510             ASSERT(0);  // (fall thru to case 0 = unsupported)
511 
512         case 0:     /* Unsupported CCW code for given device-type */
513 
514             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
515             return;
516 
517         case 1:     /* Valid - Tape MUST be loaded                    */
518             break;
519 
520         case 2:     /* Valid - Tape NEED NOT be loaded                */
521             break;
522 
523         case 3:     /* Valid - But is a NO-OP (return CE+DE now) */
524 
525             /* Command reject if the volume is currently fenced */
526             if (dev->fenced)
527             {
528                 build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
529                 return;
530             }
531 
532             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
533             return;
534 
535         case 4:     /* Valid, But is a NO-OP (for virtual tapes) */
536 
537             /* Command reject if the volume is currently fenced */
538             if (dev->fenced)
539             {
540                 build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
541                 return;
542             }
543 
544             /* If non-virtual (SCSI) then further processing required */
545             if (dev->tapedevt == TAPEDEVT_SCSITAPE)
546                 break;
547 
548             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
549             return;
550 
551         case 5:     /* Valid - Tape MUST be loaded (add DE to status) */
552             break;
553     }
554     // end switch (drc)
555 
556     /* Verify a tape is loaded if that is required for this CCW... */
557 
558     if ((1 == drc || 5 == drc) &&                               // (tape MUST be loaded?)
559         (dev->fd < 0 || TAPEDEVT_SCSITAPE == dev->tapedevt))    // (no tape loaded or non-virtual?)
560     {
561         *residual = count;
562 
563         /* Error if tape unloaded */
564         if (!strcmp (dev->filename, TAPE_UNLOADED))
565         {
566             build_senseX (TAPE_BSENSE_TAPEUNLOADED, dev, unitstat, code);
567             return;
568         }
569 
570         /* Open the device file if necessary */
571         if (dev->fd < 0)
572         {
573             rc = dev->tmh->open( dev, unitstat, code );
574 
575             if (rc < 0)     /* Did open fail? */
576             {
577                 return;     /* Yes, exit with unit status */
578             }
579         }
580 
581         /* Error if tape is not loaded */
582         if (!dev->tmh->tapeloaded( dev, unitstat, code ))
583         {
584             build_senseX (TAPE_BSENSE_TAPEUNLOADED, dev, unitstat, code);
585             return;
586         }
587     }
588 
589     /* Process depending on CCW opcode */
590     switch (code) {
591 
592     /*---------------------------------------------------------------*/
593     /* MODE SET   (pre-3480 and earlier drives)                      */
594     /*---------------------------------------------------------------*/
595         /* Patch to no-op modeset 1 (7-track) commands -             */
596         /*   causes VM problems                                      */
597         /* Andy Norrie 2002/10/06                                    */
598     case 0x13:
599     case 0x23:
600     case 0x33:
601     case 0x3B:
602     case 0x53:
603     case 0x63:
604     case 0x6B:
605 //  case 0x73:  // Mode Set (7-track 556/Odd/Normal) for 3420-3/5/7
606                 // with 7-track feature installed, No-op for 3420-2/4/6
607                 // and 3480, Invalid for 3422/3430, "Set Interface
608                 // Identifier" for 3490 and later. NOTE: 3480 and earlier
609                 // interpretation handled by command-table; 3490 and
610                 // and later handled further below.
611     case 0x7B:
612     case 0x93:
613     case 0xA3:
614     case 0xAB:
615     case 0xB3:
616     case 0xBB:
617 //  case 0xC3:  // Mode Set (9-track 1600 bpi) for models earlier than
618                 // 3480, "Set Tape-Write-Immediate" for 3480 and later.
619                 // NOTE: handled by command-table for all models earlier
620                 // than 3480; 3480 and later handled further below.
621     case 0xCB: /* 9-track 800 bpi */
622     case 0xD3: /* 9-track 6250 bpi */
623     case 0xEB: /* invalid mode set issued by DOS/VS */
624     {
625         build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code);
626         break;
627     }
628 
629     /*---------------------------------------------------------------*/
630     /* WRITE                                                         */
631     /*---------------------------------------------------------------*/
632     case 0x01:
633     {
634         /* Command reject if the volume is currently fenced */
635         if (dev->fenced)
636         {
637             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
638             break;
639         }
640 
641         /* Unit check if tape is write-protected */
642         if (dev->readonly || dev->tdparms.logical_readonly)
643         {
644             build_senseX (TAPE_BSENSE_WRITEPROTECT, dev, unitstat, code);
645             break;
646         }
647 
648         /* Update matrix display if needed */
649         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
650         {
651             dev->tapedisptype = TAPEDISPTYP_IDLE;
652             UpdateDisplay( dev );
653         }
654 
655         /* Assign a unique Message Id for this I/O if needed */
656         INCREMENT_MESSAGEID(dev);
657 
658         /* Write a block to the tape according to device type */
659         if ((rc = dev->tmh->write( dev, iobuf, count, unitstat, code)) < 0)
660             break;      // (error)
661 
662         *residual = 0;
663 
664         /* Perform flush/sync and/or set normal completion status */
665         if (0
666             || !dev->write_immed
667             || (rc = dev->tmh->sync( dev, unitstat, code )) == 0
668         )
669             build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code );
670 
671         break;
672     }
673 
674     /*---------------------------------------------------------------*/
675     /* READ FORWARD  (3590 only)                                     */
676     /*---------------------------------------------------------------*/
677     case 0x06:
678     {
679         /*   SG24-2506 IBM 3590 Tape Subsystem Technical Guide
680 
681         5.2.1 Separate Channel Commands for IPL Read and Normal Read
682 
683         On IBM 3480/3490 tape devices there is only one Read Forward
684         CCW, the X'02' command code.  This CCW is used to perform
685         not only normal read operations but also an IPL Read from
686         tape, for example, DFSMSdss Stand-Alone Restore.  When the
687         CCW is used as an IPL Read, it is not subject to resetting
688         event notification, by definition.  Because there is only
689         one Read Forward CCW, it cannot be subject to resetting event
690         notification on IBM 3480 and 3490 devices.
691 
692         To differentiate between an IPL Read and a normal read
693         forward operation, the X'02' command code has been redefined
694         to be the IPL Read CCW, and a new X'06' command code has been
695         defined to be the Read Forward CCW.  The new Read Forward
696         CCW, X'06', is subject to resetting event notification, as
697         should be the case for normal read CCWs issued by applications
698         or other host software.
699         */
700 
701         // PROGRAMMING NOTE: I'm not sure what they mean by "resetting
702         // event notification" above, but for now we'll just FALL THROUGH
703         // to the below IPL READ logic...
704     }
705 
706     // (purposely FALL THROUGH to below IPL READ logic for now)
707 
708     /*---------------------------------------------------------------*/
709     /* IPL READ  (non-3590)                                          */
710     /*---------------------------------------------------------------*/
711     case 0x02:
712     {
713         /* Command reject if the volume is currently fenced */
714         if (dev->fenced)
715         {
716             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
717             break;
718         }
719 
720         /* Update matrix display if needed */
721         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
722         {
723             dev->tapedisptype = TAPEDISPTYP_IDLE;
724             UpdateDisplay( dev );
725         }
726 
727         /* Assign a unique Message Id for this I/O if needed */
728         INCREMENT_MESSAGEID(dev);
729 
730         /* Read a block from the tape according to device type */
731         /* Exit with unit check status if read error condition */
732         if ((len = dev->tmh->read( dev, iobuf, unitstat, code)) < 0)
733             break;      // (error)
734 
735         /* Calculate number of bytes to read and residual byte count */
736         RESIDUAL_CALC (len);
737 
738         /* Save size and offset of data not used by this CCW */
739         dev->curblkrem = len - num;
740         dev->curbufoff = num;
741 
742         /* Exit with unit exception status if tapemark was read */
743         if (len == 0)
744             build_senseX (TAPE_BSENSE_READTM, dev, unitstat, code);
745         else
746             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
747 
748         break;
749     }
750 
751     /*---------------------------------------------------------------*/
752     /* CONTROL NO-OPERATION                                          */
753     /*---------------------------------------------------------------*/
754     case 0x03:
755     {
756         /* Command reject if the volume is currently fenced */
757         if (dev->fenced)
758         {
759             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
760             break;
761         }
762 
763         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
764         break;
765     }
766 
767     /*---------------------------------------------------------------*/
768     /* SENSE                                                         */
769     /*---------------------------------------------------------------*/
770     case 0x04:
771     {
772         /* Calculate residual byte count */
773         RESIDUAL_CALC (dev->numsense);
774 
775         /* If we don't already have some sense already pre-built
776            and ready and waiting, then we'll have to build it fresh
777            for this call...  Otherwise, we use whatever we already
778            have waiting for them pre-built from a previous call...
779         */
780         if (!dev->sns_pending)
781             build_senseX (TAPE_BSENSE_UNSOLICITED, dev, unitstat, code);
782 
783         *unitstat = CSW_CE|CSW_DE;  /* Need to do this ourselves as  */
784                                     /* we might not have gone thru   */
785                                     /* build_senseX...               */
786 
787         /* Copy device sense bytes to channel I/O buffer, clear
788            them for the next time, and then finally, reset the
789            Contengent Allegiance condition... */
790         memcpy (iobuf, dev->sense, num);
791         memset (dev->sense, 0, sizeof(dev->sense));
792         dev->sns_pending = 0;
793 
794         break;
795     }
796 
797     /*---------------------------------------------------------------*/
798     /* READ FORWARD  (3590 only)                                     */
799     /*---------------------------------------------------------------*/
800 //  case 0x06:
801 //  {
802         // (handled by case 0x02: IPL READ)
803 //  }
804 
805     /*---------------------------------------------------------------*/
806     /* REWIND                                                        */
807     /*---------------------------------------------------------------*/
808     case 0x07:
809     {
810         /* Update matrix display if needed */
811         if ( TAPEDISPTYP_IDLE    == dev->tapedisptype ||
812              TAPEDISPTYP_WAITACT == dev->tapedisptype )
813         {
814             dev->tapedisptype = TAPEDISPTYP_REWINDING;
815             UpdateDisplay( dev );
816         }
817 
818         /* Assign a unique Message Id for this I/O if needed */
819         INCREMENT_MESSAGEID(dev);
820 
821         /* Do the rewind */
822         rc = dev->tmh->rewind( dev, unitstat, code);
823 
824         /* Update matrix display if needed */
825         if ( TAPEDISPTYP_REWINDING == dev->tapedisptype )
826         {
827             dev->tapedisptype = TAPEDISPTYP_IDLE;
828             UpdateDisplay( dev );
829         }
830 
831         /* Check for error */
832         if (rc < 0)
833         {
834             dev->fenced = 1;
835             break;
836         }
837 
838         dev->eotwarning = 0;
839         dev->fenced = 0;
840 
841         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
842         break;
843     }
844 
845     /*---------------------------------------------------------------*/
846     /* READ PREVIOUS  (3590)                                         */
847     /*---------------------------------------------------------------*/
848     case 0x0A:
849     {
850         /*    SG24-2506 IBM 3590 Tape Subsystem Technical Guide
851 
852         5.2.2 Read Previous to Replace Read Backward:
853 
854         The ESCON-attached Magstar tape drive does not support the
855         Read Backward CCW (command code, X'0C').  It supports a new
856         Read Previous CCW that allows processing of an IBM 3590 High
857         Performance Tape Cartridge in the backward direction without
858         the performance penalties that exist with the Read Backward
859         CCW.  IBM 3480 and 3490 devices had to reread the physical
860         block from the medium for each request of a logical block.
861         The Magstar tape drive retains the physical block in the
862         device buffer and satisfies any subsequent Read Previous from
863         the buffer, similar to how Read Forward operates.  The Read
864         Previous CCW operates somewhat like the Read Backward CCW
865         in that it can be used to process the volumes in the backward
866         direction.  It is different from the Read Backward, however,
867         because the data is transferred to the host in the same order
868         in which it was written, rather than in reverse order like
869         Read Backward.
870         */
871 
872         /*   SG24-2594 IBM 3590 Multiplatform Implementation
873 
874         5.1.2 New and Changed Read Channel Commands
875 
876         [...] That is, the Read Backward command's data address
877         will point to the end of the storage area, while a Read
878         Previous command points to the beginning of the storage
879         area...
880         */
881 
882         // PROGRAMMING NOTE: luckily, channel.c's buffer handling
883         // causes transparent handling of Read Backward/Reverse,
884         // so the above buffer alignment and data transfer order
885         // is not a concern for us here.
886 
887         // PROGRAMMING NOTE: until we can add support to Hercules
888         // allowing direct SCSI i/o (so that we can issue the 'Read
889         // Reverse' command directly to the SCSI device), we will
890         // simply FALL THROUGH to our existing "Read Backward" logic.
891     }
892 
893     // (purposely FALL THROUGH to the 'READ BACKWARD' logic below)
894 
895     /*---------------------------------------------------------------*/
896     /* READ BACKWARD                                                 */
897     /*---------------------------------------------------------------*/
898     case 0x0C:
899     {
900         /* Update matrix display if needed */
901         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
902         {
903             dev->tapedisptype = TAPEDISPTYP_IDLE;
904             UpdateDisplay( dev );
905         }
906 
907         /* Backspace to previous block according to device type */
908         /* Exit with unit check status if error condition */
909         if ((rc = dev->tmh->bsb( dev, unitstat, code )) < 0)
910             break;      // (error)
911 
912         /* Exit with unit exception status if tapemark was sensed */
913         if (rc == 0)
914         {
915             *residual = 0;
916             build_senseX (TAPE_BSENSE_READTM, dev, unitstat, code);
917             break;
918         }
919 
920         /* Assign a unique Message Id for this I/O if needed */
921         INCREMENT_MESSAGEID(dev);
922 
923         /* Now read in a forward direction the actual data block
924            we just backspaced over, and exit with unit check status
925            on any read error condition
926         */
927         if ((len = dev->tmh->read( dev, iobuf, unitstat, code )) < 0)
928             break;      // (error)
929 
930         /* Calculate number of bytes to read and residual byte count */
931         RESIDUAL_CALC (len);
932 
933         /* Save size and offset of data not used by this CCW */
934         dev->curblkrem = len - num;
935         dev->curbufoff = num;
936 
937         /* Backspace to previous block according to device type,
938            and exit with unit check status if error condition */
939         if ((rc = dev->tmh->bsb( dev, unitstat, code )) < 0)
940             break;      // (error)
941 
942         /* Set normal status */
943         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
944         break;
945 
946     } /* End case 0x0C: READ BACKWARD */
947 
948     /*---------------------------------------------------------------*/
949     /* REWIND UNLOAD                                                 */
950     /*---------------------------------------------------------------*/
951     case 0x0F:
952     {
953         /* Update matrix display if needed */
954         if ( dev->tdparms.displayfeat )
955         {
956             if ( TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype )
957             {
958                 dev->tapedisptype   = TAPEDISPTYP_MOUNT;
959                 dev->tapedispflags |= TAPEDISPFLG_REQAUTOMNT;
960                 strlcpy( dev->tapemsg1, dev->tapemsg2, sizeof(dev->tapemsg1) );
961             }
962             else if ( TAPEDISPTYP_UNMOUNT == dev->tapedisptype )
963             {
964                 dev->tapedisptype = TAPEDISPTYP_IDLE;
965             }
966         }
967 
968         if ( TAPEDISPTYP_IDLE    == dev->tapedisptype ||
969              TAPEDISPTYP_WAITACT == dev->tapedisptype )
970         {
971             dev->tapedisptype = TAPEDISPTYP_UNLOADING;
972             UpdateDisplay( dev );
973         }
974 
975         /* Assign a unique Message Id for this I/O if needed */
976         INCREMENT_MESSAGEID(dev);
977 
978         /* Do the Rewind-Unload */
979 #if defined(OPTION_SCSI_TAPE)
980         if ( TAPEDEVT_SCSITAPE == dev->tapedevt )
981             int_scsi_rewind_unload( dev, unitstat, code );
982         else
983 #endif
984         {
985             dev->tmh->close(dev);
986             *unitstat=0;
987         }
988 
989         /* Update matrix display if needed */
990         if ( TAPEDISPTYP_UNLOADING == dev->tapedisptype )
991         {
992             dev->tapedisptype = TAPEDISPTYP_IDLE;
993             UpdateDisplay( dev );
994         }
995 
996         if ((*unitstat & CSW_UC) != 0)      // (did it work?)
997             break;                          // (no it didn't)
998 
999         dev->curfilen = 1;
1000         dev->nxtblkpos = 0;
1001         dev->prvblkpos = -1;
1002         dev->eotwarning = 0;
1003 //      dev->fenced = 0;        // (handler already did this)
1004 
1005         /* Update matrix display */
1006         UpdateDisplay( dev );
1007 
1008         build_senseX(TAPE_BSENSE_RUN_SUCCESS,dev,unitstat,code);
1009 
1010         if ( dev->als )
1011         {
1012             TID dummy_tid;
1013             char thread_name[64];
1014             snprintf(thread_name,sizeof(thread_name),
1015                 "autoload wait for %4.4X tapemount thread",
1016                 dev->devnum);
1017             thread_name[sizeof(thread_name)-1] = 0;
1018             create_thread( &dummy_tid, DETACHED,
1019                 autoload_wait_for_tapemount_thread,
1020                 dev, thread_name );
1021         }
1022 
1023         ReqAutoMount( dev );
1024         break;
1025 
1026     } /* End case 0x0F: REWIND UNLOAD */
1027 
1028     /*---------------------------------------------------------------*/
1029     /* READ BUFFER  (3480 and later)                                 */
1030     /*---------------------------------------------------------------*/
1031     case 0x12:
1032     {
1033         /*    GA32-0127 IBM 3490E Hardware Reference
1034 
1035         Read Buffer (X'12')
1036 
1037         The Read Buffer command transfers data from the control unit
1038         to the channel if any buffered write data is in the control
1039         unit's buffer.  For each Read Buffer command completed, the
1040         controlling computer retrieves one block of data in last-in/
1041         first-out (LIFO) sequence until the buffer for the addressed
1042         tape drive is empty.  The controlling computer usually issues
1043         this command when the tape drive or subsystem malfunctions
1044         and cannot write data from the buffer to the tape.
1045         */
1046 
1047         /* Command reject if the volume is currently fenced */
1048         if (dev->fenced)
1049         {
1050             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1051             break;
1052         }
1053 
1054         // PROGRAMMING NOTE: until we can add support for performing
1055         // SCSI i/o directly to the actual real device, we simply do
1056         // the same thing for non-virtual devices as we do for virtual
1057         // ones: we force-flush the data to the device (i.e. sync)
1058         // and then tell the truth: that there's zero bytes of data
1059         // still buffered (which is true if we just flushed it all)
1060 
1061         // Once we add direct SCSI i/o support though, we can change
1062         // the below to do an actual read-buffer SCSI command for
1063         // non-virtual devices. (We will still always need the below
1064         // for virtual devices though)
1065 
1066         /* Assign a unique Message Id for this I/O if needed */
1067         INCREMENT_MESSAGEID(dev);
1068 
1069         // Perform flush/sync; exit on error...
1070         if ((rc = dev->tmh->sync( dev, unitstat, code )) < 0)
1071             break;      // (i/o error)
1072 
1073         // Flush complete. Our buffer is now empty. Tell them that.
1074         RESIDUAL_CALC (0);
1075         dev->curblkrem = 0;
1076         dev->curbufoff = 0;
1077         break;
1078     }
1079 
1080     /*---------------------------------------------------------------*/
1081     /* ERASE GAP                                                     */
1082     /*---------------------------------------------------------------*/
1083     case 0x17:
1084     {
1085         /* Command reject if the volume is currently fenced */
1086         if (dev->fenced)
1087         {
1088             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1089             break;
1090         }
1091 
1092         /* Unit check if tape is write-protected */
1093         if (dev->readonly || dev->tdparms.logical_readonly)
1094         {
1095             build_senseX (TAPE_BSENSE_WRITEPROTECT, dev, unitstat, code);
1096             break;
1097         }
1098 
1099         /* Update matrix display if needed */
1100         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
1101         {
1102             dev->tapedisptype = TAPEDISPTYP_IDLE;
1103             UpdateDisplay( dev );
1104         }
1105 
1106         /* Assign a unique Message Id for this I/O if needed */
1107         INCREMENT_MESSAGEID(dev);
1108 
1109         /* Do the ERG; exit if error */
1110         if ((rc = dev->tmh->erg( dev, unitstat, code )) < 0)
1111             break;      // (error)
1112 
1113         /* Perform flush/sync and/or set normal completion status */
1114         if (0
1115             || !dev->write_immed
1116             || (rc = dev->tmh->sync( dev, unitstat, code )) == 0
1117         )
1118             build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code );
1119 
1120         break;
1121     }
1122 
1123     /*---------------------------------------------------------------*/
1124     /* WRITE TAPE MARK                                               */
1125     /*---------------------------------------------------------------*/
1126     case 0x1F:
1127     {
1128         /* Command reject if the volume is currently fenced */
1129         if (dev->fenced)
1130         {
1131             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1132             break;
1133         }
1134 
1135         /* Unit check if tape is write-protected */
1136         if (dev->readonly || dev->tdparms.logical_readonly)
1137         {
1138             build_senseX (TAPE_BSENSE_WRITEPROTECT, dev, unitstat, code);
1139             break;
1140         }
1141 
1142         /* Update matrix display if needed */
1143         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
1144         {
1145             dev->tapedisptype = TAPEDISPTYP_IDLE;
1146             UpdateDisplay( dev );
1147         }
1148 
1149         /* Assign a unique Message Id for this I/O if needed */
1150         INCREMENT_MESSAGEID(dev);
1151 
1152         /* Do the WTM; exit if error */
1153         if ((rc = dev->tmh->wtm(dev,unitstat,code)) < 0)
1154             break;      // (error)
1155 
1156         dev->curfilen++;
1157 
1158         /* Perform flush/sync and/or set normal completion status */
1159         if (0
1160             || !dev->write_immed
1161             || (rc = dev->tmh->sync( dev, unitstat, code )) == 0
1162         )
1163             build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code );
1164 
1165         break;
1166     }
1167 
1168     /*---------------------------------------------------------------*/
1169     /* READ BLOCK ID                                                 */
1170     /*---------------------------------------------------------------*/
1171     case 0x22:
1172     {
1173         BYTE  log_blockid  [4];     // (temp; BIG-ENDIAN format)
1174         BYTE  phys_blockid [4];     // (temp; BIG-ENDIAN format)
1175 
1176         int   errcode   = TAPE_BSENSE_STATUSONLY; // (presume success)
1177 
1178         /* Command reject if the volume is currently fenced */
1179         if (dev->fenced)
1180         {
1181             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1182             break;
1183         }
1184 
1185         /* Assign a unique Message Id for this I/O if needed */
1186         INCREMENT_MESSAGEID(dev);
1187 
1188         /* Calculate number of bytes and residual byte count */
1189         RESIDUAL_CALC( 2 * sizeof(dev->blockid) );
1190 
1191         /* Ask media handler for actual value(s)... */
1192         if ((rc = dev->tmh->readblkid( dev, log_blockid, phys_blockid )) < 0)
1193             errcode = TAPE_BSENSE_LOCATEERR;
1194         else
1195         {
1196             /* Copy results to channel I/O buffer... */
1197             memcpy( &iobuf[0], log_blockid,  4 );
1198             memcpy( &iobuf[4], phys_blockid, 4 );
1199         }
1200 
1201         /* Set completion status... */
1202         build_senseX( errcode, dev, unitstat, code );
1203         break;
1204     }
1205 
1206     /*---------------------------------------------------------------*/
1207     /* READ BUFFERED LOG                                             */
1208     /*---------------------------------------------------------------*/
1209     case 0x24:
1210     {
1211         /* Calculate residual byte count... */
1212 
1213         // PROGRAMMING NOTE: technically we *should* have up to
1214         // 64 bytes to give them, but we may not have that many.
1215 
1216         /* How many bytes we SHOULD have depends on whether
1217            Extended Buffered Log support is enabled or not */
1218         len = (dev->devchar[8] & 0x01) ? 64 : 32;
1219         RESIDUAL_CALC (len);
1220 
1221         /* Clear the device sense bytes */
1222         memset (iobuf, 0, num);
1223 
1224         /* Copy device sense bytes to channel I/O buffer */
1225         memcpy (iobuf, dev->sense,
1226                 dev->numsense < (U32)num ? dev->numsense : (U32)num);
1227 
1228         /* Return unit status */
1229         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
1230         break;
1231     }
1232 
1233     /*---------------------------------------------------------------*/
1234     /* BACKSPACE BLOCK                                               */
1235     /*---------------------------------------------------------------*/
1236     case 0x27:
1237     {
1238         /* Command reject if the volume is currently fenced */
1239         if (dev->fenced)
1240         {
1241             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1242             break;
1243         }
1244 
1245         /* Update matrix display if needed */
1246         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
1247         {
1248             dev->tapedisptype = TAPEDISPTYP_IDLE;
1249             UpdateDisplay( dev );
1250         }
1251 
1252         /* Assign a unique Message Id for this I/O if needed */
1253         INCREMENT_MESSAGEID(dev);
1254 
1255         /* Backspace to previous block according to device type,
1256            and exit with unit check status on error condition */
1257         if ((rc = dev->tmh->bsb( dev, unitstat, code )) < 0)
1258             break;
1259 
1260         /* Exit with unit exception status if tapemark was sensed */
1261         if (rc == 0)
1262         {
1263             build_senseX (TAPE_BSENSE_READTM, dev, unitstat, code);
1264             break;
1265         }
1266 
1267         /* Set normal status */
1268         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
1269         break;
1270     }
1271 
1272     /*---------------------------------------------------------------*/
1273     /* BACKSPACE FILE                                                */
1274     /*---------------------------------------------------------------*/
1275     case 0x2F:
1276     {
1277         /* Command reject if the volume is currently fenced */
1278         if (dev->fenced)
1279         {
1280             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1281             break;
1282         }
1283 
1284         /* Update matrix display if needed */
1285         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
1286         {
1287             dev->tapedisptype = TAPEDISPTYP_IDLE;
1288             UpdateDisplay( dev );
1289         }
1290 
1291         /* Assign a unique Message Id for this I/O if needed */
1292         INCREMENT_MESSAGEID(dev);
1293 
1294         /* Backspace to previous file according to device type,
1295            and exit with unit check status on error condition */
1296         if ((rc = dev->tmh->bsf( dev, unitstat, code )) < 0)
1297             break;
1298 
1299         /* Set normal status */
1300         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
1301         break;
1302     }
1303 
1304     /*---------------------------------------------------------------*/
1305     /* SENSE PATH GROUP ID                                           */
1306     /*---------------------------------------------------------------*/
1307     case 0x34:
1308     {
1309         /*    GA32-0127 IBM 3490E Hardware Reference
1310 
1311         Sense Path Group ID (X'34')
1312 
1313         The Sense Path Group ID command transfers 12 bytes of information
1314         from the control unit to the channel.  The first byte (byte 0)
1315         is the path state byte, and the remaining 11 bytes (bytes 1-11)
1316         contain the path-group ID.
1317 
1318         The bit assignments in the path state byte (byte 0) are:
1319 
1320          ________ ________ ____________________________________
1321         | Bit    |  Value | Description                        |
1322         |________|________|____________________________________|
1323         | 0, 1   |        | Pathing Status                     |
1324         |________|________|____________________________________|
1325         |        |   00   | Reset                              |
1326         |________|________|____________________________________|
1327         |        |   01   | Reserved                           |
1328         |________|________|____________________________________|
1329         |        |   10   | Ungrouped                          |
1330         |________|________|____________________________________|
1331         |        |   11   | Grouped                            |
1332         |________|________|____________________________________|
1333         | 2, 3   |        | Partitioning State                 |
1334         |________|________|____________________________________|
1335         |        |   00   | Implicitly Enabled                 |
1336         |________|________|____________________________________|
1337         |        |   01   | Reserved                           |
1338         |________|________|____________________________________|
1339         |        |   10   | Disabled                           |
1340         |________|________|____________________________________|
1341         |        |   11   | Explicitly Enabled                 |
1342         |________|________|____________________________________|
1343         | 4      |        | Path Mode                          |
1344         |________|________|____________________________________|
1345         |        |    0   | Single path mode.                  |
1346         |        |    1   | Reserved, invalid for this device. |
1347         |________|________|____________________________________|
1348         | 5-7    |   000  | Reserved                           |
1349         |________|________|____________________________________|
1350         */
1351 
1352         /* Command Reject if Supervisor-Inhibit */
1353         if (dev->supvr_inhibit)
1354         {
1355             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1356             break;
1357         }
1358 
1359         /* Command reject if the command is not the ONLY command
1360            in the channel program */
1361         if (chained & CCW_FLAGS_CC)
1362         {
1363             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1364             break;
1365         }
1366 
1367         /* Calculate residual byte count */
1368         RESIDUAL_CALC (12);
1369 
1370         /* Byte 0 is the path group state byte */
1371         iobuf[0] = dev->pgstat;
1372 
1373         /* Bytes 1-11 contain the path group identifier */
1374         if (num > 1)
1375             memcpy (iobuf+1, dev->pgid, num-1);
1376 
1377         /* Return unit status */
1378         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
1379         break;
1380 
1381     } /* End case 0x34: SENSE PATH GROUP ID */
1382 
1383     /*---------------------------------------------------------------*/
1384     /* FORWARD SPACE BLOCK                                           */
1385     /*---------------------------------------------------------------*/
1386     case 0x37:
1387     {
1388         /* Command reject if the volume is currently fenced */
1389         if (dev->fenced)
1390         {
1391             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1392             break;
1393         }
1394 
1395         /* Update matrix display if needed */
1396         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
1397         {
1398             dev->tapedisptype = TAPEDISPTYP_IDLE;
1399             UpdateDisplay( dev );
1400         }
1401 
1402         /* Assign a unique Message Id for this I/O if needed */
1403         INCREMENT_MESSAGEID(dev);
1404 
1405         /* Forward to next block according to device type  */
1406         /* Exit with unit check status if error condition  */
1407         if ((rc = dev->tmh->fsb( dev, unitstat, code )) < 0)
1408             break;
1409 
1410         /* Exit with unit exception status if tapemark was sensed */
1411         if (rc == 0)
1412         {
1413             build_senseX (TAPE_BSENSE_READTM, dev, unitstat, code);
1414             break;
1415         }
1416 
1417         /* Set normal status */
1418         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
1419         break;
1420     }
1421 
1422     /*---------------------------------------------------------------*/
1423     /* READ SUBSYSTEM DATA  (3490/3590)                              */
1424     /*---------------------------------------------------------------*/
1425     case 0x3E:
1426     {
1427         /*       GA32-0127 IBM 3490E Hardware Reference
1428 
1429         Read Subsystem Data (X'3E')
1430 
1431         The Read Subsystem Data command obtains various types of
1432         information from the 3480/3490 subsystem.  The data presented
1433         is dependent on the command immediately preceding the Read
1434         Subsystem Data command in the command chain.
1435 
1436         If the preceding command in the command chain is a Perform
1437         Subsystem Function command with the Prepare for Read Subsystem
1438         Data order, the data presented is a function of the sub-order
1439         in the data transferred with the order.
1440         */
1441 
1442         /* Command reject if not chained from either a Set Interface
1443            Identifier or Perform Subsystem Function command */
1444         if (!((chained & CCW_FLAGS_CC) && (0x77 == prevcode || 0x73 == prevcode)))
1445         {
1446             build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
1447             break;
1448         }
1449 
1450         /* Command reject if no subsystem data was prepared
1451            by a previous Perform Subsystem Function command */
1452         if (!dev->tapssdlen)      // (any subsystem data?)
1453         {
1454             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1455             break;
1456         }
1457 
1458         /* Calculate residual byte count */
1459         RESIDUAL_CALC (dev->tapssdlen);
1460 
1461         /* PROGRAMMING NOTE: the Prepare for Read Subsystem Data
1462            order of the previous Perform Subsystem Function command
1463            has already prepared the subsystem data directly in the
1464            channel buffer itself (iobuf), so there isn't any data
1465            that actually needs to be moved/copied; the data is
1466            already sitting in the channel buffer. All we need do
1467            is return a normal status.
1468         */
1469         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
1470         break;
1471 
1472     } /* End case 0x3E: READ SUBSYSTEM DATA */
1473 
1474     /*---------------------------------------------------------------*/
1475     /* FORWARD SPACE FILE                                            */
1476     /*---------------------------------------------------------------*/
1477     case 0x3F:
1478     {
1479         /* Command reject if the volume is currently fenced */
1480         if (dev->fenced)
1481         {
1482             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1483             break;
1484         }
1485 
1486         /* Update matrix display if needed */
1487         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
1488         {
1489             dev->tapedisptype = TAPEDISPTYP_IDLE;
1490             UpdateDisplay( dev );
1491         }
1492 
1493         /* Assign a unique Message Id for this I/O if needed */
1494         INCREMENT_MESSAGEID(dev);
1495 
1496         /* Forward to next file according to device type  */
1497         /* Exit with unit check status if error condition */
1498         if ((rc = dev->tmh->fsf( dev, unitstat, code )) < 0)
1499             break;
1500 
1501         /* Set normal status */
1502         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
1503         break;
1504     }
1505 
1506     /*---------------------------------------------------------------*/
1507     /* SYNCHRONIZE  (3480 or later)                                  */
1508     /*---------------------------------------------------------------*/
1509     case 0x43:
1510     {
1511         /* Command reject if the volume is currently fenced */
1512         if (dev->fenced)
1513         {
1514             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1515             break;
1516         }
1517 
1518         /* Update matrix display if needed */
1519         if ( TAPEDISPTYP_WAITACT == dev->tapedisptype )
1520         {
1521             dev->tapedisptype = TAPEDISPTYP_IDLE;
1522             UpdateDisplay( dev );
1523         }
1524 
1525         /* Assign a unique Message Id for this I/O if needed */
1526         INCREMENT_MESSAGEID(dev);
1527 
1528         /* Do the sync */
1529         if ((rc = dev->tmh->sync( dev, unitstat, code )) == 0)
1530             build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code );
1531 
1532         break;
1533     }
1534 
1535 #if defined( OPTION_TAPE_AUTOMOUNT )
1536     /*---------------------------------------------------------------*/
1537     /* SET DIAGNOSE      --  Special AUTOMOUNT support  --           */
1538     /*---------------------------------------------------------------*/
1539     case 0x4B:
1540     {
1541         int     argc, i;                                     /* work */
1542         char  **argv;                                        /* work */
1543         char    newfile [ sizeof(dev->filename) ];           /* work */
1544         char    lcss[8];                                     /* work */
1545 
1546         /* Command reject if AUTOMOUNT support not enabled */
1547         if (0
1548             || dev->tapedevt == TAPEDEVT_SCSITAPE
1549             || sysblk.tamdir == NULL
1550             || dev->noautomount
1551         )
1552         {
1553             build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
1554             break;
1555         }
1556 
1557         /* Command Reject if Supervisor-Inhibit */
1558         if (dev->supvr_inhibit)
1559         {
1560             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1561             break;
1562         }
1563 
1564         /* Command Reject if command-chained and i/o length not 1 */
1565         if (flags & CCW_FLAGS_CC)
1566         {
1567             if (count != 1)
1568             {
1569                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1570                 break;
1571             }
1572 
1573             /* AUTOMOUNT QUERY - part 1 (chained 0xE4 SENSE ID = part 2) */
1574 
1575             /* Set normal status but do nothing else; the next CCW
1576                should be a SENSE ID (0xE4) which will do the query */
1577             build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code );
1578             break;
1579         }
1580 
1581         /* AUTOMOUNT MOUNT... */
1582 
1583         /* Calculate residual byte count */
1584         RESIDUAL_CALC (sizeof(newfile)-1);   /* (minus-1 for NULL) */
1585 
1586         /* Copy the device's new filename from guest storage */
1587         for (i=0; i < num; i++)
1588             newfile[i] = guest_to_host( iobuf[i] );
1589         newfile[num] = 0;
1590 
1591         /* Change "OFFLINE" to "*" (tape unloaded) */
1592         if (strcasecmp (newfile, "OFFLINE") == 0)
1593             strlcpy (newfile, TAPE_UNLOADED, sizeof(newfile));
1594 
1595         /* (messages looks better without LCSS if not needed) */
1596         lcss[0] = 0;
1597         if (SSID_TO_LCSS(dev->ssid) != 0)
1598             snprintf( lcss, sizeof(lcss), "%u:", SSID_TO_LCSS(dev->ssid) );
1599         lcss[sizeof(lcss)-1] = 0;
1600 
1601         /* Obtain the device lock */
1602         obtain_lock (&dev->lock);
1603 
1604         /* Validate the given path... */
1605         if ( strcmp( newfile, TAPE_UNLOADED ) != 0 )
1606         {
1607             TAMDIR *tamdir = NULL;
1608             int minlen = 0;
1609             int rej = 0;
1610 
1611             /* (because i hate typing) */
1612 #define  HHCTA090E(_file,_reason) \
1613             { \
1614                 logmsg(_("HHCTA090E Auto-mount of file \"%s\" on drive %s%4.4X failed: " \
1615                     "%s\n"), _file, lcss, dev->devnum, _reason); \
1616                 build_senseX (TAPE_BSENSE_TAPELOADFAIL, dev, unitstat, code); \
1617                 release_lock (&dev->lock); \
1618                 break; \
1619             }
1620 
1621             // Resolve given path...
1622             {
1623                 char  resolve_in [ MAX_PATH ] = {0};  /* (work) */
1624                 char  resolve_out[ MAX_PATH ] = {0};  /* (work) */
1625 
1626                 /* (build path to be resolved...) */
1627                 if (0
1628 #if defined(_MSVC_)
1629                     || newfile[1] == ':'        /* (fullpath given?) */
1630 #else /* !_MSVC_ */
1631                     || newfile[0] == '/'        /* (fullpath given?) */
1632 #endif /* _MSVC_ */
1633                     || newfile[0] == '.'        /* (relative path given?) */
1634                 )
1635                     resolve_in[0] = 0;          /* (then use just given spec) */
1636                 else                            /* (else prepend with default) */
1637                     strlcpy( resolve_in, sysblk.defdir, sizeof(resolve_in) );
1638 
1639                 /* (finish building path to be resolved) */
1640                 strlcat( resolve_in, newfile, sizeof(resolve_in) );
1641 
1642                 /* (fully resolvable path?) */
1643                 if (realpath( resolve_in, resolve_out ) == NULL)
1644                     HHCTA090E( resolve_in, "unresolvable path" );
1645 
1646                 /* Switch to fully resolved path */
1647                 strlcpy( newfile, resolve_out, sizeof(newfile) );
1648             }
1649 
1650             /* Verify file is in an allowable directory... */
1651             rej = 0; minlen = 0;
1652             while ((tamdir = findtamdir( rej, minlen, newfile )) != NULL)
1653             {
1654                 rej = !rej;
1655                 minlen = tamdir->len;
1656             }
1657 
1658             /* Error if "allowable" directory not found... */
1659             if (!rej)
1660                 HHCTA090E( newfile, "impermissible directory" );
1661 
1662             /* Verify file exists... */
1663             if (access( newfile, R_OK ) != 0)
1664                 HHCTA090E( newfile, "file not found" );
1665         }
1666 
1667         /* Prevent accidental re-init'ing of an already loaded tape drive */
1668         if (1
1669             && sysblk.nomountedtapereinit
1670             && strcmp (newfile,       TAPE_UNLOADED) != 0
1671             && strcmp (dev->filename, TAPE_UNLOADED) != 0
1672         )
1673         {
1674             logmsg(_("HHCTA091E Tape file auto-mount for drive %s%4.4X rejected: "
1675                 "drive not empty\n"),
1676                 lcss, dev->devnum);
1677             build_senseX (TAPE_BSENSE_TAPELOADFAIL, dev, unitstat, code);
1678             release_lock (&dev->lock);
1679             break;
1680         }
1681 
1682         /* Build re-initialization parameters using new filename */
1683         argc = dev->argc;
1684         argv = malloc (dev->argc * sizeof(char*));
1685 
1686         for (i=0; i < argc; i++)
1687         {
1688             if (dev->argv[i])
1689                 argv[i] = strdup(dev->argv[i]);
1690             else
1691                 argv[i] = NULL;
1692         }
1693 
1694         /* (replace filename argument with new filename) */
1695         free( argv[0] );
1696         argv[0] = strdup( newfile );
1697 
1698         /* Attempt reinitializing the device using the new filename... */
1699         rc = (int)(dev->hnd->init)( dev, argc, argv );
1700 
1701         /* (free temp copy of parms to prevent memory leak) */
1702         for (i=0; i < argc; i++)
1703             if (argv[i])
1704                 free(argv[i]);
1705 
1706         /* Issue message and set status based on whether it worked or not... */
1707         if (0
1708             || rc < 0
1709             || strfilenamecmp( dev->filename, newfile ) != 0
1710         )
1711         {
1712             // (failure)
1713 
1714             if (strcmp( newfile, TAPE_UNLOADED ) == 0)
1715             {
1716                 /* (an error message explaining the reason for the
1717                     failure should hopefully already have been issued) */
1718                 logmsg(_("HHCTA092E Tape file auto-unmount for drive %s%4.4X failed\n"),
1719                     lcss, dev->devnum);
1720             }
1721             else
1722                 HHCTA090E( newfile, "file not found" ); // (presumed)
1723 
1724             /* (the load or unload attempt failed) */
1725             build_senseX (TAPE_BSENSE_TAPELOADFAIL, dev, unitstat, code);
1726         }
1727         else
1728         {
1729             // (success)
1730 
1731             if (strcmp( newfile, TAPE_UNLOADED ) == 0)
1732                 logmsg(_("HHCTA093I Tape file on drive %s%4.4X auto-unmounted\n"),
1733                     lcss, dev->devnum);
1734             else
1735                 logmsg(_("HHCTA094I Tape file \"%s\" auto-mounted onto drive %s%4.4X\n"),
1736                     dev->filename, lcss, dev->devnum);
1737 
1738             /* (save new parms for next time) */
1739             free( dev->argv[0] );
1740             dev->argv[0] = strdup( newfile );
1741 
1742             /* (set normal status for this ccw) */
1743             build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code );
1744         }
1745 
1746         /* Release the device lock and exit function... */
1747         release_lock (&dev->lock);
1748         break;
1749 
1750     } /* End case 0x4B: SET DIAGNOSE */
1751 #endif /* OPTION_TAPE_AUTOMOUNT */
1752 
1753     /*---------------------------------------------------------------*/
1754     /* READ MESSAGE ID                                               */
1755     /*---------------------------------------------------------------*/
1756     case 0x4E:
1757     {
1758         /*       GA32-0127 IBM 3490E Hardware Reference
1759 
1760         Read Message ID (X'4E')
1761 
1762         The Read Message ID command is used to read the message identifier
1763         that was assigned by the control unit to commands that indicated
1764         the message-required flag requesting notification when an asynchronous
1765         operation is complete.  The Read Message ID command must be chained
1766         directly from the specific command that requested the message
1767         notification or the command will be presented unit check status
1768         with associated sense indicating ERA code 27.
1769 
1770         If the Read Message ID command is chained to a specific command
1771         that requests notification, but the command does not result in an
1772         asynchronous operation, the message identifier field returned
1773         will be all zeroes.
1774 
1775         The data returned has the following format:
1776 
1777          ________ ____________________________________________________
1778         | Byte   | Description                                        |
1779         |________|____________________________________________________|
1780         | 0,1    | Length (set to X'000A')                            |
1781         |________|____________________________________________________|
1782         | 2      | Format (set to X'02')                              |
1783         |________|____________________________________________________|
1784         | 3      | Message Code                                       |
1785         |        |                                                    |
1786         |        | Value Description                                  |
1787         |        |                                                    |
1788         |        | X'01' Delayed-Response Message                     |
1789         |________|____________________________________________________|
1790         | 4-7    | Message ID                                         |
1791         |        |                                                    |
1792         |        | This field contains the message identifier         |
1793         |        | assigned by the control unit to the requested      |
1794         |        | operation.  If the operation was executed by       |
1795         |        | the subsystem as an immediate operation, this      |
1796         |        | field contains all zeroes and a later delayed-     |
1797         |        | response message is not generated.                 |
1798         |________|____________________________________________________|
1799         | 8      | Flags (set to X'00')                               |
1800         |________|____________________________________________________|
1801         | 9      | Reserved (set to X'00')                            |
1802         |________|____________________________________________________|
1803         */
1804 
1805         /* Command reject if not chained from a write command */
1806         if (!((chained & CCW_FLAGS_CC) && IS_CCW_WRITE(prevcode)))
1807         {
1808             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1809             break;
1810         }
1811 
1812         /* Calculate residual byte count */
1813         RESIDUAL_CALC( 10 );
1814 
1815         // PROGRAMMING NOTE: at the moment all of our i/o's are synchronous.
1816         // Thus we always return zero indicating the i/o was not asynchronous.
1817 
1818         STORE_HW ( &iobuf[0],   10 );       // 0-1
1819                     iobuf[2] = 0x02;        // 2
1820                     iobuf[3] = 0x01;        // 3
1821         STORE_FW ( &iobuf[4],    0 );       // 4-7  (Message Id)
1822                     iobuf[8] = 0x00;        // 8
1823                     iobuf[9] = 0x00;        // 9
1824 
1825         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat,code);
1826         break;
1827 
1828     } /* End case 0x4E: READ MESSAGE ID */
1829 
1830     /*---------------------------------------------------------------*/
1831     /* LOCATE BLOCK                                                  */
1832     /*---------------------------------------------------------------*/
1833     case 0x4F:
1834     {
1835         U32  locblock;                 /* Block Id for Locate Block */
1836         int  errcode = TAPE_BSENSE_STATUSONLY;  /* Presumed success */
1837 
1838         /* Command reject if the volume is currently fenced */
1839         if (dev->fenced)
1840         {
1841             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
1842             break;
1843         }
1844 
1845         /* Check for minimum count field */
1846         if (count < sizeof(dev->blockid))
1847         {
1848             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1849             break;
1850         }
1851 
1852         /* Block to seek */
1853         ASSERT( count >= sizeof(locblock) );
1854         FETCH_FW(locblock, iobuf);
1855 
1856         /* Check for invalid/reserved Format Mode bits */
1857         if (0x3590 != dev->devtype)
1858         {
1859             if (0x00C00000 == (locblock & 0x00C00000))
1860             {
1861                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1862                 break;
1863             }
1864 
1865             /* We only want the Block Number in the low-order 22 bits */
1866             locblock &= 0x003FFFFF;
1867         }
1868 
1869         /* Calculate residual byte count */
1870         RESIDUAL_CALC( sizeof(locblock) );
1871 
1872         /* Informative message if tracing */
1873         if ( dev->ccwtrace || dev->ccwstep )
1874             logmsg(_("HHCTA081I Locate block 0x%8.8"I32_FMT"X on %s%s%4.4X\n")
1875                 ,locblock
1876                 ,TAPEDEVT_SCSITAPE == dev->tapedevt ? (char*)dev->filename : ""
1877                 ,TAPEDEVT_SCSITAPE == dev->tapedevt ?             " = "    : ""
1878                 ,dev->devnum
1879                 );
1880 
1881         /* Update display if needed */
1882         if ( TAPEDISPTYP_IDLE    == dev->tapedisptype ||
1883              TAPEDISPTYP_WAITACT == dev->tapedisptype )
1884         {
1885             dev->tapedisptype = TAPEDISPTYP_LOCATING;
1886             UpdateDisplay( dev );
1887         }
1888 
1889         /* Assign a unique Message Id for this I/O if needed */
1890         INCREMENT_MESSAGEID(dev);
1891 
1892         /* Ask media handler to perform the locate... */
1893         if ((rc = dev->tmh->locateblk( dev, locblock, unitstat, code )) < 0)
1894         {
1895             errcode = TAPE_BSENSE_LOCATEERR;
1896             dev->fenced = 1;  // (position lost; fence the volume)
1897         }
1898 
1899         /* Update display if needed */
1900         if ( TAPEDISPTYP_LOCATING == dev->tapedisptype )
1901         {
1902             dev->tapedisptype = TAPEDISPTYP_IDLE;
1903             UpdateDisplay( dev );
1904         }
1905 
1906         /* Set completion status... */
1907         build_senseX( errcode, dev, unitstat, code );
1908         break;
1909 
1910     } /* End case 0x4F: LOCATE BLOCK */
1911 
1912     /*---------------------------------------------------------------*/
1913     /* SUSPEND MULTIPATH RECONNECTION  (3480 and later)              */
1914     /*---------------------------------------------------------------*/
1915     case 0x5B:
1916     {
1917         /*       GA32-0127 IBM 3490E Hardware Reference
1918 
1919         Suspend Multipath Reconnection (X'5B')
1920 
1921         The Suspend Multipath Reconnection command performs as a
1922         No-Operation command because all controlling-computer-to-
1923         subsystem operations occur in single-path status.
1924         */
1925 
1926         /* Command Reject if Supervisor-Inhibit */
1927         if (dev->supvr_inhibit)
1928         {
1929             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1930             break;
1931         }
1932 
1933         /* Set normal status */
1934         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
1935         break;
1936     }
1937 
1938     /*---------------------------------------------------------------*/
1939     /* READ MEDIA CHARACTERISTICS  (3590 only)                       */
1940     /*---------------------------------------------------------------*/
1941     case 0x62:
1942     {
1943         /*    SG24-2506 IBM 3590 Tape Subsystem Technical Guide
1944 
1945         5.2.3 New Read Media Characteristics
1946 
1947         The new Read Media Characteristics CCW (command code x'62')
1948         provides up to 256 bytes of information about the media and
1949         formats supported by the Magstar tape drive."
1950         */
1951 
1952         // ZZ FIXME: not coded yet.
1953 
1954         /* Set command reject sense byte, and unit check status */
1955         build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1956         break;
1957     }
1958 
1959     /*---------------------------------------------------------------*/
1960     /* READ DEVICE CHARACTERISTICS                                   */
1961     /*---------------------------------------------------------------*/
1962     case 0x64:
1963     {
1964         /* Command reject if device characteristics not available */
1965         if (dev->numdevchar == 0)
1966         {
1967             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
1968             break;
1969         }
1970 
1971         /* Calculate residual byte count */
1972         RESIDUAL_CALC (dev->numdevchar);
1973 
1974         /* Copy device characteristics bytes to channel buffer */
1975         memcpy (iobuf, dev->devchar, num);
1976 
1977         /* Return unit status */
1978         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
1979         break;
1980     }
1981 
1982 #if 0
1983     /*---------------------------------------------------------------*/
1984     /* SET INTERFACE IDENTIFIER  (3490 and later)                    */
1985     /*---------------------------------------------------------------*/
1986     case 0x73:
1987     {
1988         // PROGRAMMING NOTE: the 3480 and earlier "Mode Set" interpretation
1989         // of this CCW is handled in the command-table as a no-op; the "Set
1990         // Interface Identifier" interpretation of this CCW for 3490 and
1991         // later model tape drives is *ALSO* handled in the command-table
1992         // as a no-op as well, so there's really no reason for this switch
1993         // case to even exist until such time as we need to support a model
1994         // that happens to require special handling (which is unlikely).
1995 
1996         // I'm keeping the code here however for documentation purposes
1997         // only, but of course disabling it from compilation via #if 0.
1998 
1999         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
2000         break;
2001     }
2002 #endif
2003 
2004     /*---------------------------------------------------------------*/
2005     /* PERFORM SUBSYSTEM FUNCTION                                    */
2006     /*---------------------------------------------------------------*/
2007     case 0x77:
2008     {
2009         BYTE  order  = iobuf[0];
2010         BYTE  flag   = iobuf[1];
2011         BYTE  parm   = iobuf[2];
2012 
2013         /* Command Reject if Supervisor-Inhibit */
2014         if (dev->supvr_inhibit)
2015         {
2016             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2017             break;
2018         }
2019 
2020         /* The flag byte must be zero for all orders because
2021            none of our supported orders supports a flag byte */
2022         if (PSF_FLAG_ZERO != flag)
2023         {
2024             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2025             break;
2026         }
2027 
2028         /* Byte 0 is the PSF order */
2029         switch (order)
2030         {
2031         /*-----------------------------------------------------------*/
2032         /* Activate/Deactivate Forced Error Logging                  */
2033         /* 0x8000nn / 0x8100nn                                       */
2034         /*-----------------------------------------------------------*/
2035         case PSF_ORDER_AFEL:
2036         case PSF_ORDER_DFEL:
2037         {
2038             BYTE  bEnable  = (PSF_ORDER_AFEL == order) ? 1 : 0;
2039 
2040             /* Calculate residual byte count */
2041             RESIDUAL_CALC (3);
2042 
2043             /* Control information length must be 3 bytes long */
2044             /* and the parameter byte must be one or the other */
2045             if ( (count < len)
2046                 || ((PSF_ACTION_FEL_IMPLICIT != parm) &&
2047                     (PSF_ACTION_FEL_EXPLICIT != parm))
2048             )
2049             {
2050                build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
2051                break;
2052             }
2053 
2054             /* Enable/Disabled Forced Error Logging as requested... */
2055 
2056 #if 0 // (implicit enabling for all devices not currently supported; treat as explicit instead)
2057             if (PSF_ACTION_FEL_IMPLICIT == parm)
2058             {
2059                 // Implicit: for ALL devices...
2060                 dev->forced_logging = bEnable ? 1 : 0;
2061             }
2062             else // (PSF_ACTION_FEL_EXPLICIT == parm)
2063 #endif // (implicit not supported)
2064             {
2065                 // Explicit: for only THIS device...
2066                 dev->forced_logging = bEnable ? 1 : 0;
2067             }
2068 
2069             build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code);
2070             break;
2071         }
2072 
2073         /*-----------------------------------------------------------*/
2074         /* Activate/Deactivate Access Control                        */
2075         /* 0x8200nn00 / 0x8300nn00                                   */
2076         /*-----------------------------------------------------------*/
2077         case PSF_ORDER_AAC:     // (Activate)
2078         case PSF_ORDER_DAC:     // (Dectivate)
2079         {
2080             BYTE  bEnable  = (PSF_ORDER_AAC == order) ? 1 : 0;
2081 
2082             /* Calculate residual byte count */
2083             RESIDUAL_CALC (4);
2084 
2085             /* Control information length must be 4 bytes long */
2086             /* and the parameter byte must not be invalid      */
2087             if (0
2088                 || (count < len)
2089                 || (parm  & ~(PSF_ACTION_AC_LWP | PSF_ACTION_AC_DCD |   // (bits on that shouldn't be)
2090                               PSF_ACTION_AC_DCR | PSF_ACTION_AC_ER))
2091                 || !(parm &  (PSF_ACTION_AC_LWP | PSF_ACTION_AC_DCD |   // (bits on that should be)
2092                               PSF_ACTION_AC_DCR | PSF_ACTION_AC_ER))
2093             )
2094             {
2095                 build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
2096                 break;
2097             }
2098 
2099             /* Enable/Disable Logical Write Protect if requested */
2100             if (parm & PSF_ACTION_AC_LWP)
2101                 dev->tdparms.logical_readonly = bEnable ? 1 : 0;
2102 
2103             /* Enable/Disable Data Compaction (compression) if requested */
2104             if (parm & PSF_ACTION_AC_DCD)
2105             {
2106                 if (TAPEDEVT_HETTAPE == dev->tapedevt)
2107                 {
2108                     rc = het_cntl( dev->hetb, HETCNTL_SET | HETCNTL_COMPRESS,
2109                                    bEnable ? TRUE : FALSE );
2110                 }
2111 #if defined(OPTION_SCSI_TAPE)
2112                 else if (TAPEDEVT_SCSITAPE == dev->tapedevt)
2113                 {
2114                     // ZZ FIXME: future place for direct SCSI i/o
2115                     // to enable/disable compression for 3480/later.
2116                 }
2117 #endif
2118             }
2119 
2120             build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code);
2121             break;
2122         }
2123 
2124         /*-----------------------------------------------------------*/
2125         /* Reset Volume Fenced                                       */
2126         /* 0x9000                                                    */
2127         /*-----------------------------------------------------------*/
2128         case PSF_ORDER_RVF:
2129         {
2130             /*       GA32-0127 IBM 3490E Hardware Reference
2131 
2132             Volume Fencing
2133 
2134             When a condition results in a volume integrity exposure,
2135             the control unit will prevent further access to the volume.
2136             This process is called Volume Fencing and is primarily
2137             related to loss of buffered write data, tape positioning,
2138             or assignment protection.
2139 
2140             The control unit prevents further access to the tape volume
2141             by conditioning itself to generate deferred unit checks with
2142             associated sense data indicating ERA code 47, for all commands
2143             that are eligible to receive the deferred unit check until
2144             the condition is reset or until the cartridge is unloaded.
2145             The condition that caused the fencing to occur has already
2146             been indicated by the previous unit check and associated sense
2147             data.
2148             */
2149 
2150             /* Calculate residual byte count */
2151             RESIDUAL_CALC (2);
2152 
2153             /* Control information length must be 2 bytes long */
2154             if (count < len)
2155             {
2156               build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
2157               break;
2158             }
2159 
2160             dev->fenced = 0;        // (as requested!)
2161 
2162             build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code);
2163             break;
2164         }
2165 
2166         /*-----------------------------------------------------------*/
2167         /* Pin Device                                                */
2168         /* 0xA100nn                                                  */
2169         /*-----------------------------------------------------------*/
2170         case PSF_ORDER_PIN_DEV:
2171         {
2172             /* Calculate residual byte count */
2173             RESIDUAL_CALC (3);
2174 
2175             /* Control information length must be 3 bytes long
2176                and the parameter byte must not be invalid */
2177             if ( (count < len)
2178                   || ((parm != PSF_ACTION_PIN_CU0) &&
2179                       (parm != PSF_ACTION_PIN_CU1))
2180             )
2181             {
2182                 build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
2183                 break;
2184             }
2185 
2186             /* Not currently supported; treat as no-op */
2187             build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code);
2188             break;
2189         }
2190 
2191         /*-----------------------------------------------------------*/
2192         /* Unpin Device                                              */
2193         /* 0xA200                                                    */
2194         /*-----------------------------------------------------------*/
2195         case PSF_ORDER_UNPIN_DEV:
2196         {
2197             /* Calculate residual byte count */
2198             RESIDUAL_CALC (2);
2199 
2200             /* Control information length must be 2 bytes long */
2201             if (count < len)
2202             {
2203                 build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
2204                 break;
2205             }
2206 
2207             /* Not currently supported; treat as no-op */
2208             build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code);
2209             break;
2210         }
2211 
2212         /*-----------------------------------------------------------*/
2213         /* Prepare for Read Subsystem Data                           */
2214         /* 0x180000000000mm00iiiiiiii                                */
2215         /*-----------------------------------------------------------*/
2216         case PSF_ORDER_PRSD:
2217         {
2218             /*       GA32-0127 IBM 3490E Hardware Reference
2219 
2220             Prepare for Read Subsystem Data (X'18')
2221 
2222             The order transfers 12 bytes of data used for processing a
2223             Read Subsystem Data command that immediately follows the
2224             Perform Subsystem Function command specifying this order in
2225             the command chain.  If a Read Subsystem Data command is not
2226             issued as the next command in the command chain, the data is
2227             discarded and no other action is performed.  If a Read Subsystem
2228             Data command is issued as the next command in the command chain,
2229             the data determines what type of information is presented to
2230             the Read Subsystem Data command.
2231 
2232             When the Prepare for Subsystem Data order with the attention
2233             message sub-order is specified in a Perform Subsystem Function
2234             command, the command is treated as a global command.  If the
2235             command is issued while the Special Intercept Condition is
2236             active, a unit check status is presented with the associated
2237             sense data indicating ERA code 53.
2238 
2239             The Prepare for Read Subsystem Data order requires an order
2240             byte (byte 0), a flag byte (byte 1), and parameter bytes.
2241             The flag byte is set to 0. The parameter bytes are defined
2242             as follows:
2243 
2244              ________ ___________________________________________________
2245             | Byte   | Description                                       |
2246             |________|___________________________________________________|
2247             | 2-5    | Reserved (X'00')                                  |
2248             |________|___________________________________________________|
2249             | 6      | Attention Message (X'03')                         |
2250             |        |                                                   |
2251             |        | When active and bytes 8-11 contain X'00000000',   |
2252             |        | the program is requesting the control unit        |
2253             |        | to present any pending attention message or       |
2254             |        | unsolicited unit check condition that is          |
2255             |        | associated with the addressed device-path pair.   |
2256             |        | If there is no message or unit check condition    |
2257             |        | present, the subsystem displays the "No Message"  |
2258             |        | message.                                          |
2259             |        |                                                   |
2260             |        | When active and bytes 8-11 contain anything       |
2261             |        | other than X'00000000', the program is re-        |
2262             |        | questing the control unit to present the status   |
2263             |        | of the asynchronous operation as identified by    |
2264             |        | the contents of bytes 8-11.                       |
2265             |________|___________________________________________________|
2266             | 7      | Reserved (X'00')                                  |
2267             |________|___________________________________________________|
2268             | 8-11   | Message ID                                        |
2269             |________|___________________________________________________|
2270             */
2271 
2272             /* Calculate residual byte count */
2273             RESIDUAL_CALC (12);
2274 
2275             /* Control information length must be 12 bytes long the */
2276             /* parameter must be valid and all reserved bytes zero. */
2277             /* Also note that the only sub-order we support is the  */
2278             /* only sub-order that is defined: attention message.   */
2279             if (0
2280                 || (count < len)
2281                 || (iobuf[6] != PSF_ACTION_SSD_ATNMSG)
2282                 || (memcmp( &iobuf[2], "\00\00\00\00", 4 ) != 0)
2283                 || (iobuf[7] != 0x00)
2284             )
2285             {
2286                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2287                 break;
2288             }
2289 
2290             /* If the Special Intercept Condition is active, present
2291                unit check status with sense indicating ERA code 53 */
2292             if (dev->SIC_active)
2293             {
2294                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2295                 dev->SIC_active = 0;
2296                 break;
2297             }
2298 
2299             // Build the requested Subsystem Data...
2300 
2301             // PROGRAMMING NOTE: note that we build the requested data
2302             // directly in the channel i/o buffer itself (iobuf). This
2303             // relieves us from having to allocate/maintain a separate
2304             // buffer for it somewhere, and relieves the READ SUBSYSTEM
2305             // DATA command (0x3E) from having to copy the data into
2306             // the channel buffer from somewhere. Instead it can return
2307             // immediately since the data is already in the buffer. (See
2308             // the 0x3E: READ SUBSYSTEM DATA command for information).
2309 
2310             // PROGRAMMING NOTE: since at the moment we don't support
2311             // asynchronous i/o (all of our i/o's are synchronous), we
2312             // return either a Format x'00' (No Message) response if the
2313             // Message Id they specified was x'00000000' or, if they
2314             // requested the status for a specific Message Id, a format
2315             // x'02' (Message Id Status) response with x'00' Operation
2316             // Completion Status (I/O Completed).
2317 
2318             if (memcmp( &iobuf[8], "\00\00\00\00", 4 ) == 0)
2319             {
2320                 /* Format x'00': "No Message" */
2321                 dev->tapssdlen = 9;                     // (Length)
2322                 STORE_HW ( &iobuf[0], dev->tapssdlen ); // (Length = 9 bytes)
2323                 iobuf[2] = 0x00;                        // (Format = x'00': "No Message")
2324                 iobuf[3] = 0x00;                        // (Message Code = none)
2325                 memcpy( &iobuf[4], &iobuf[8], 4 );      // (Message Id = same as requested)
2326                 iobuf[8] = 0x00;                        // (Flags = none)
2327             }
2328             else
2329             {
2330                 /* Format x'02': "Message Id Status" */
2331                 dev->tapssdlen = 10;                    // (Length)
2332                 STORE_HW ( &iobuf[0], dev->tapssdlen ); // (Length = 10 bytes)
2333                 iobuf[2] = 0x02;                        // (Format = x'01: Message Id Status)
2334                 iobuf[3] = 0x01;                        // (Message Code = Delayed Response)
2335                 memcpy( &iobuf[4], &iobuf[8], 4 );      // (Message Id = same as requested)
2336                 iobuf[8] = 0x00;                        // (Reserved)
2337                 iobuf[9] = 0x00;                        // (Status = "I/O Completed")
2338             }
2339             break;
2340 
2341         } /* End case PSF_ORDER_PRSD */
2342 
2343         /*-----------------------------------------------------------*/
2344         /* Set Special Intercept Condition                           */
2345         /* 0x1B00                                                    */
2346         /*-----------------------------------------------------------*/
2347         case PSF_ORDER_SSIC:
2348         {
2349             /*       GA32-0127 IBM 3490E Hardware Reference
2350 
2351             Set Special Intercept Condition (X'1B')
2352 
2353             The order controls the activation or deactivation of the
2354             special intercept condition associated with the device-path
2355             group pair to which the command is issued.  The order is
2356             supported by the model if byte 8 bit 4 is active in the data
2357             presented to the Read Device Characteristics command.  The
2358             order requires an order byte (byte 0) and a flag byte (byte 1).
2359             The flag byte is set to 0.
2360 
2361             When processed, the command activates the special intercept
2362             condition for the device on each channel path that has the
2363             same path group ID as the issuing channel path.  The path
2364             group ID is considered valid on a given channel path if it
2365             is valid for any device on the channel path.  The special
2366             intercept condition controls the presentation of attention-
2367             intercept status.  The sense data associated with the
2368             attention-intercept status indicates ERA code 57.  The special
2369             intercept condition also causes the next global command
2370             issued to the device-path group pair to be presented unit check
2371             status with associated sense data indicating ERA code 53.
2372 
2373             The special intercept condition is deactivated on a channel
2374             path if a reset signal is received on the channel path.  The
2375             special intercept condition is deactivated for the device-group
2376             pair if a global command is presented unit check status with
2377             associated sense data indicating ERA code 53, or if the last
2378             path in the associated set of channel paths (that is, with the
2379             same valid path group ID) is reset.
2380 
2381             After the Set Special Intercept Condition order is specified
2382             in a Perform Subsystem Function command, the command is treated
2383             as a global command. If the command is issued while the special
2384             intercept condition is active, a unit check status is presented
2385             with associated sense data indicating ERA code 53.
2386 
2387             If a command is issued to a channel path without a valid path
2388             group ID (that is, all devices in the reset state), unit check
2389             status is presented with associated sense data indicating ERA
2390             code 27.
2391             */
2392 
2393             /* Command reject if Special Intercept Condition not supported */
2394             if (!dev->SIC_supported)      // (not supported?)
2395             {
2396                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2397                 break;
2398             }
2399 
2400             /* If the command is issued while the Special Intercept  */
2401             /* Condition is active, a unit check status is presented */
2402             /* with associated sense data indicating ERA code 53.    */
2403             if (dev->SIC_active)        // (already active?)
2404             {
2405                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2406                 dev->SIC_active = 0;      // (reset after UC)
2407                 break;
2408             }
2409 
2410             /* Activate Special Intercept Condition */
2411             dev->SIC_active = 1;
2412             break;
2413 
2414         } /* End case PSF_ORDER_SSIC */
2415 
2416         /*-----------------------------------------------------------*/
2417         /* Message Not Supported                                     */
2418         /* 0x1C00xxccnnnn0000iiiiii...                               */
2419         /*-----------------------------------------------------------*/
2420         case PSF_ORDER_MNS:
2421         {
2422             /*       GA32-0127 IBM 3490E Hardware Reference
2423 
2424             Message Not Supported (X'1C')
2425 
2426             The order transfers 20 bytes of data that identify the host
2427             that does not support a prior attention message containing
2428             the Notify Nonsupport flag. The order requires an order byte
2429             (byte 0), a flag byte (byte 1), and parameter bytes.  The
2430             flag byte is set to 0.  The parameter bytes are defined as
2431             follows:
2432 
2433              ________ ________ ____________________________________________
2434             | Byte   | Value  | Description                                |
2435             |________|________|____________________________________________|
2436             | 2      |        | Response Code                              |
2437             |________|________|____________________________________________|
2438             |        | 0      | Reserved (invalid).                        |
2439             |________|________|____________________________________________|
2440             |        | 1      | Message rejected.  Unknown format.         |
2441             |________|________|____________________________________________|
2442             |        | 2      | Message rejected.  Function not supported. |
2443             |________|________|____________________________________________|
2444             |        | 3-255  | Reserved (invalid).                        |
2445             |________|________|____________________________________________|
2446             | 3      |        | Channel Path ID (CHPID)                    |
2447             |        |        |                                            |
2448             |        |        | The byte identifies the channel path that  |
2449             |        |        | received the attention message.            |
2450             |________|________|____________________________________________|
2451             | 4, 5   |        | Device Number                              |
2452             |        |        |                                            |
2453             |        |        | The bytes identify the device number of    |
2454             |        |        | the device that received the attention     |
2455             |        |        | message.                                   |
2456             |________|________|____________________________________________|
2457             | 6, 7   |        | Reserved (must be X'00').                  |
2458             |________|________|____________________________________________|
2459             | 8-11   |        | Message ID                                 |
2460             |        |        |                                            |
2461             |        |        | The field contains the message ID that     |
2462             |        |        | was presented to the host in the attention |
2463             |        |        | message.                                   |
2464             |________|________|____________________________________________|
2465             | 12-19  |        | System ID                                  |
2466             |        |        |                                            |
2467             |        |        | The field contains an 8-byte system ID     |
2468             |        |        | that identifies the host or host partition |
2469             |        |        | responding to the attention message.       |
2470             |________|________|____________________________________________|
2471             */
2472 
2473             // PROGRAMMING NOTE: none of our responses to the Perform Sub-
2474             // System Function order Attention Message sub-order (see the
2475             // PSF_ORDER_PRSD case further above) support any flags. Thus
2476             // because we never set/request the "Notify Nonsupport" flag
2477             // in our Attention Message sub-order response, the host should
2478             // never actually ever be issuing this particular order of the
2479             // Perform Subsystem Functon command since it shouldn't be
2480             // trying to tell us what we never asked it to. Nevertheless
2481             // we should probably support it anyway just in case it does
2482             // by treating it as a no-op (as long as it's valid of course).
2483 
2484             /* Check for valid data (Note: we don't bother validating the
2485                Channel Path ID, Device Number, Message ID or System ID) */
2486             if (0
2487             //  ||  flag != 0x00                      // (flag byte) (note: already checked)
2488                 || (parm != 0x01 && parm != 0x02)     // (response code)
2489                 ||  iobuf[6] != 0x00                  // (reserved)
2490                 ||  iobuf[7] != 0x00                  // (reserved)
2491             )
2492             {
2493                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2494                 break;
2495             }
2496 
2497             /* Calculate residual byte count */
2498             RESIDUAL_CALC (20);
2499 
2500             /* Treat as No-op */
2501             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
2502             break;
2503 
2504         } /* End case PSF_ORDER_MNS */
2505 
2506         /*-----------------------------------------------------------*/
2507         /* Unknown/Supported PSF order                               */
2508         /*-----------------------------------------------------------*/
2509         default:
2510         {
2511             build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
2512             break;
2513         }
2514 
2515         } /* End PSF switch (order) */
2516 
2517         break;
2518 
2519     } /* End case 0x77: PERFORM SUBSYSTEM FUNCTION */
2520 
2521     /*---------------------------------------------------------------*/
2522     /* DATA SECURITY ERASE                                           */
2523     /*---------------------------------------------------------------*/
2524     case 0x97:
2525     {
2526         /*      GA32-0127 IBM 3490E Hardware Reference
2527 
2528         Data Security Erase (X'97')
2529 
2530         The Data Security Erase command writes a random pattern
2531         from the position of the tape where the command is issued
2532         to the physical end of tape.
2533 
2534         The Data Security Erase command must be command-chained
2535         from an Erase Gap command.  Most operating systems signal
2536         that the channel program is complete when the channel ending
2537         status is returned for the final command in the chain.  If
2538         the Data Security Erase command is the last command in a
2539         channel program, another command should be chained after the
2540         Data Security Erase command.  (The No-Operation command is
2541         appropriate.)  This practice ensures that any error status
2542         returns with device ending status after the Data Security
2543         Erase command is completed.
2544         */
2545 
2546         /* Command reject if not chained from Erase Gap command */
2547         if (!((chained & CCW_FLAGS_CC) && 0x17 == prevcode))
2548         {
2549             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2550             break;
2551         }
2552 
2553         /* Command reject if the volume is currently fenced */
2554         if (dev->fenced)
2555         {
2556             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
2557             break;
2558         }
2559 
2560         /* Command reject if tape is write-protected */
2561         if (dev->readonly || dev->tdparms.logical_readonly)
2562         {
2563             build_senseX (TAPE_BSENSE_WRITEPROTECT, dev, unitstat, code);
2564             break;
2565         }
2566 
2567         /* Update matrix display if needed */
2568         if ( TAPEDISPTYP_IDLE    == dev->tapedisptype ||
2569              TAPEDISPTYP_WAITACT == dev->tapedisptype )
2570         {
2571             dev->tapedisptype = TAPEDISPTYP_ERASING;
2572             UpdateDisplay( dev );
2573         }
2574 
2575         /* Assign a unique Message Id for this I/O if needed */
2576         INCREMENT_MESSAGEID(dev);
2577 
2578         /* Do the DSE; exit if error */
2579         if ((rc = dev->tmh->dse( dev, unitstat, code )) < 0)
2580             break;      // (error)
2581 
2582         /* Update matrix display if needed */
2583         if ( TAPEDISPTYP_ERASING == dev->tapedisptype )
2584         {
2585             dev->tapedisptype = TAPEDISPTYP_IDLE;
2586             UpdateDisplay( dev );
2587         }
2588 
2589         /* Perform flush/sync and/or set normal completion status */
2590         if (0
2591             || !dev->write_immed
2592             || (rc = dev->tmh->sync( dev, unitstat, code )) == 0
2593         )
2594             build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code );
2595 
2596         break;
2597 
2598     } /* End case 0x97: DATA SECURITY ERASE */
2599 
2600     /*---------------------------------------------------------------*/
2601     /* LOAD DISPLAY                                                  */
2602     /*---------------------------------------------------------------*/
2603     case 0x9F:
2604     {
2605         /* Command Reject if Supervisor-Inhibit */
2606         if (dev->supvr_inhibit)
2607         {
2608             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2609             break;
2610         }
2611 
2612         /* Calculate residual byte count */
2613         RESIDUAL_CALC (17);
2614 
2615         /* Issue message on 3480 matrix display */
2616         load_display (dev, iobuf, count);
2617 
2618         /* Return unit status */
2619         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
2620         break;
2621     }
2622 
2623     /*---------------------------------------------------------------*/
2624     /* Read and Reset Buffered Log (9347)                            */
2625     /*---------------------------------------------------------------*/
2626     case 0xA4:
2627     {
2628         /* Calculate residual byte count */
2629         RESIDUAL_CALC (dev->numsense);
2630 
2631         /* Reset SENSE Data */
2632         memset (dev->sense, 0, sizeof(dev->sense));
2633         *unitstat = CSW_CE|CSW_DE;
2634 
2635         /* Copy device Buffered log data (Bunch of 0s for now) */
2636         memcpy (iobuf, dev->sense, num);
2637 
2638         /* Indicate Contengency Allegiance has been cleared */
2639         dev->sns_pending = 0;
2640         break;
2641     }
2642 
2643     /*---------------------------------------------------------------*/
2644     /* SET PATH GROUP ID                                             */
2645     /*---------------------------------------------------------------*/
2646     case 0xAF:
2647     {
2648         /*      GA32-0127 IBM 3490E Hardware Reference
2649 
2650         Set Path Group ID (X'AF')
2651 
2652         The Set Path Group ID command identifies a controlling computer
2653         and specific channel path to the addressed control unit and
2654         tape drive.
2655 
2656         The Set Path Group ID command transfers 12 bytes of path group
2657         ID information to the subsystem.  The first byte (byte 0) is a
2658         function control byte, and the remaining 11 bytes (bytes 1-11)
2659         contain the path-group ID.
2660 
2661         The bit assignments in the function control byte (byte 0) are:
2662 
2663          ________ ________ ___________________________________________
2664         | Bit    |  Value | Description                               |
2665         |________|________|___________________________________________|
2666         | 0      |        | Path Mode                                 |
2667         |________|________|___________________________________________|
2668         |        |    0   | Single-path Mode                          |
2669         |________|________|___________________________________________|
2670         |        |    1   | Multipath Mode (not supported by Models   |
2671         |        |        | C10, C11, and C22)                        |
2672         |________|________|___________________________________________|
2673         | 1, 2   |        | Group Code                                |
2674         |________|________|___________________________________________|
2675         |        |   00   | Establish Group                           |
2676         |________|________|___________________________________________|
2677         |        |   01   | Disband Group                             |
2678         |________|________|___________________________________________|
2679         |        |   10   | Resign from Group                         |
2680         |________|________|___________________________________________|
2681         |        |   11   | Reserved                                  |
2682         |________|________|___________________________________________|
2683         | 3-7    |  00000 | Reserved                                  |
2684         |________|________|___________________________________________|
2685 
2686 
2687         The final 11 bytes of the Set Path Group ID command identify
2688         the path group ID.  The path group ID identifies the channel
2689         paths that belong to the same controlling computer.  Path group
2690         ID bytes must be the same for all devices in a control unit
2691         on a given path.  The Path Group ID bytes cannot be all zeroes.
2692         */
2693 
2694         /* Command Reject if Supervisor-Inhibit */
2695         if (dev->supvr_inhibit)
2696         {
2697             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2698             break;
2699         }
2700 
2701         /* Command reject if the command is not the ONLY command
2702            in the channel program */
2703         if (chained & CCW_FLAGS_CC)
2704         {
2705             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2706             break;
2707         }
2708 
2709         /* Calculate residual byte count */
2710         RESIDUAL_CALC (12);
2711 
2712         /* Control information length must be at least 12 bytes */
2713         if (count < 12)
2714         {
2715             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2716             break;
2717         }
2718 
2719         /* Byte 0 is the path group state byte */
2720         switch((iobuf[0] & SPG_SET_COMMAND))
2721         {
2722         case SPG_SET_ESTABLISH:
2723             /* Only accept the new pathgroup id when
2724                1) it has not yet been set (ie contains zeros) or
2725                2) It is set, but we are setting the same value */
2726             if(memcmp(dev->pgid,
2727                  "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 11)
2728               && memcmp(dev->pgid, iobuf+1, 11))
2729             {
2730                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2731                 break;
2732             }
2733 
2734             /* Bytes 1-11 contain the path group identifier */
2735             memcpy (dev->pgid, iobuf+1, 11); // (set initial value)
2736             dev->pgstat = SPG_PATHSTAT_GROUPED | SPG_PARTSTAT_IENABLED;
2737             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
2738             break;
2739 
2740         case SPG_SET_DISBAND:
2741             dev->pgstat = 0;
2742             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
2743             break;
2744 
2745         default:
2746         case SPG_SET_RESIGN:
2747             dev->pgstat = 0;
2748             memset (dev->pgid, 0, 11);  // (reset to zero)
2749             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
2750             break;
2751 
2752         } // end switch((iobuf[0] & SPG_SET_COMMAND))
2753 
2754         break;
2755 
2756     } /* End case 0xAF: SET PATH GROUP ID */
2757 
2758     /*---------------------------------------------------------------*/
2759     /* ASSIGN                                                        */
2760     /*---------------------------------------------------------------*/
2761     case 0xB7:
2762     {
2763         /* Command Reject if Supervisor-Inhibit */
2764         if (dev->supvr_inhibit)
2765         {
2766             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2767             break;
2768         }
2769 
2770         /* Calculate residual byte count */
2771         RESIDUAL_CALC (11);
2772 
2773         /* Control information length must be at least 11 bytes */
2774         if (count < len)
2775         {
2776             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2777             break;
2778         }
2779 
2780         if((memcmp(iobuf,"\00\00\00\00\00\00\00\00\00\00",11)==0)
2781             || (memcmp(iobuf,dev->pgid,11)==0))
2782         {
2783             dev->pgstat |= SPG_PARTSTAT_XENABLED; /* Set Explicit Partition Enabled */
2784         }
2785         else
2786         {
2787             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2788             break;
2789         }
2790 
2791         /* Return unit status */
2792         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
2793         break;
2794     }
2795 
2796     /*---------------------------------------------------------------*/
2797     /* MEDIUM SENSE   (3590)                                         */
2798     /*---------------------------------------------------------------*/
2799     case 0xC2:
2800     {
2801         /*      GA32-0331 IBM 3590 Hardware Reference
2802 
2803         The 3590 Hardware Reference manual lists many different
2804         "Mode Sense" Pages that the 3590 supports, with one of
2805         the supported pages being Mode Page X'23': the "Medium
2806         Sense" mode page:
2807 
2808            The Medium Sense page provides information about
2809            the state of the medium currently associated with
2810            the device, if any.
2811         */
2812 
2813 #if 0 //  ZZ FIXME: not coded yet
2814 
2815         // PROGRAMMING NOTE: until we can add support to Hercules
2816         // allowing direct SCSI i/o (so that we can issue the 10-byte
2817         // Mode Sense (X'5A') command to ask for Mode Page x'23' =
2818         // Medium Sense) we have no choice but to reject the command.
2819 
2820         // ZZ FIXME: not written yet.
2821 
2822         build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2823 
2824 #else //  ++++  BEGIN MEDIUM SENSE HACK  ++++
2825 
2826         /* ZZ FIXME: ***  TEMPORARY(?) HACK  ***
2827 
2828             The following clues were gleaned from Linux 390 source:
2829 
2830                 struct tape_3590_med_sense
2831                 {
2832                     unsigned int macst:4;
2833                     unsigned int masst:4;
2834 
2835                     char pad[127];
2836                 }
2837 
2838                 #define  MSENSE_UNASSOCIATED       0x00
2839                 #define  MSENSE_ASSOCIATED_MOUNT   0x01
2840                 #define  MSENSE_ASSOCIATED_UMOUNT  0x02
2841 
2842                 case TO_MSEN:
2843 
2844                     sense = (struct tape_3590_med_sense *) request->cpdata;
2845 
2846                     if (sense->masst == MSENSE_UNASSOCIATED)
2847                             tape_med_state_set(device, MS_UNLOADED);
2848 
2849                     if (sense->masst == MSENSE_ASSOCIATED_MOUNT)
2850                             tape_med_state_set(device, MS_LOADED);
2851                     break;
2852         */
2853 
2854         /* Calculate residual byte count */
2855         RESIDUAL_CALC (128);
2856 
2857         /* Return Media Sense data... */
2858 
2859         memset( iobuf, 0, num );          // (init to all zeroes first)
2860 
2861         if (dev->tmh->tapeloaded( dev, unitstat, code ))
2862             iobuf[0] |= (0x01 & 0x0F);    // MSENSE_ASSOCIATED_MOUNT
2863 //      else
2864 //          iobuf[0] |= (0x00 & 0x0F);    // MSENSE_UNASSOCIATED
2865 
2866         /* Return unit status */
2867         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
2868 
2869 #endif //  ++++  END MEDIUM SENSE HACK  ++++
2870 
2871         break;
2872 
2873     } /* End case 0xC2: MEDIUM SENSE */
2874 
2875     /*---------------------------------------------------------------*/
2876     /* SET TAPE-WRITE IMMEDIATE  (3480 and later)                    */
2877     /*---------------------------------------------------------------*/
2878     case 0xC3:
2879     {
2880         // NOTE: the "Mode Set" interpretation of this CCW for all
2881         // models earlier than 3480 are handled by the command-table;
2882         // the "Set Tape-Write Immediate" interpretation of this CCW
2883         // for 3480 and later models is handled below.
2884 
2885         /* Command reject if the volume is currently fenced */
2886         if (dev->fenced)
2887         {
2888             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
2889             break;
2890         }
2891 
2892         /*      GA32-0127 IBM 3490E Hardware Reference
2893 
2894         Set Tape-Write-Immediate (X'C3')
2895 
2896         The Set Tape-Write-Immediate command causes all subsequent
2897         Write commands in the channel program to perform as write-
2898         immediate commands.
2899 
2900         The tape-write-immediate command is explicitly requested by a
2901         Mode Set or Set Tape-Write-Immediate command.  The subsystem
2902         forces the tape-write-immediate command while the tape is
2903         positioned beyond logical end of volume.  This prevents more
2904         than one record from being in the buffer if the physical end of
2905         volume is reached.  It may also be forced when load balancing
2906         is performed or on drives that write the 3480-2 XF format just
2907         before end of wrap processing.
2908         */
2909 
2910         /*     GA32-0329 3590 Introduction and Planning Guide
2911 
2912         When data is physically transferred to the tape medium it is
2913         always immediately reread and verified. The writing of data
2914         is normally buffered, however, which defers the physical
2915         transfer of the logical blocks to the tape until the buffer
2916         conditions require the offloading of the data or until a
2917         synchronizing command requires the transfer. If immediate
2918         validation of a successful transfer of data to the tape is
2919         required at the time that each logical block is written,
2920         then Tape Write Immediate mode may be programmatically invoked.
2921         This results in block-by-block synchronization and verification
2922         of successful transfer all the way to the medium, but at a
2923         very substantial cost in application performance.
2924         */
2925 
2926         /* Assign a unique Message Id for this I/O if needed */
2927         INCREMENT_MESSAGEID(dev);
2928 
2929         /* set write-immedediate mode and perform sync function */
2930         dev->write_immed = 1;
2931         if ((rc = dev->tmh->sync( dev, unitstat, code )) == 0)
2932             build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code );
2933         break;
2934 
2935     } /* End case 0xC3: SET TAPE-WRITE IMMEDIATE */
2936 
2937     /*---------------------------------------------------------------*/
2938     /* UNASSIGN                                                      */
2939     /*---------------------------------------------------------------*/
2940     case 0xC7:
2941     {
2942         /* Command Reject if Supervisor-Inhibit */
2943         if (dev->supvr_inhibit)
2944         {
2945             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2946             break;
2947         }
2948 
2949         /* Calculate residual byte count */
2950         RESIDUAL_CALC (11);
2951 
2952         /* Control information length must be at least 11 bytes */
2953         if (count < len)
2954         {
2955             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2956             break;
2957         }
2958 
2959         /* Reset to All Implicitly enabled */
2960         dev->pgstat=0;
2961 
2962         /* Reset Path group ID password */
2963         memset(dev->pgid,0,11);
2964 
2965         /* Reset drive password */
2966         memset(dev->drvpwd,0,sizeof(dev->drvpwd));
2967 
2968         /* Return unit status */
2969         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
2970         break;
2971     }
2972 
2973     /*---------------------------------------------------------------*/
2974     /* MODE SENSE   (3590)                                           */
2975     /*---------------------------------------------------------------*/
2976     case 0xCF:
2977     {
2978         /*     ANSI INCITS 131-1994 (R1999) SCSI-2 Reference
2979 
2980         The MODE SENSE command provides a means for a target to
2981         report parameters to the initiator. It is a complementary
2982         command to the MODE SELECT command.
2983         */
2984 
2985         /*      GA32-0331 IBM 3590 Hardware Reference
2986 
2987         The 3590 Hardware Reference manual lists many different
2988         "Mode Sense" Pages that the 3590 supports.
2989         */
2990 
2991         // ZZ FIXME: not written yet.
2992 
2993         /* Set command reject sense byte, and unit check status */
2994         build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
2995         break;
2996     }
2997 
2998     /*---------------------------------------------------------------*/
2999     /* MODE SET  (3480 or later)                                     */
3000     /*---------------------------------------------------------------*/
3001     case 0xDB:
3002     {
3003         /*          GA32-0127 IBM 3490E Hardware Reference
3004 
3005         Mode Set (X'DB')
3006 
3007         The Mode Set command controls specific aspects of command
3008         processing within a given command chain.
3009 
3010         The Mode Set command requires one byte of information from the channel.
3011         The format of the byte is:
3012 
3013          ________ __________________________________________________________
3014         | Bit    | Description                                              |
3015         |________|__________________________________________________________|
3016         | 0,1    | Reserved                                                 |
3017         |________|__________________________________________________________|
3018         | 2      | Tape-Write-Immediate Mode                                |
3019         |        |                                                          |
3020         |        | If active, any subsequent Write commands within the      |
3021         |        | current command chain are processed in tape-write-       |
3022         |        | immediate mode if no other conditions preclude this      |
3023         |        | mode.  If inactive, Write commands are processed in      |
3024         |        | buffered mode if no other conditions preclude this       |
3025         |        | mode.  The default is inactivate.                        |
3026         |________|__________________________________________________________|
3027         | 3      | Supervisor Inhibit                                       |
3028         |        |                                                          |
3029         |        | If active, any subsequent supervisor command within      |
3030         |        | the current command chain is presented unit check        |
3031         |        | status with associated sense data indicating ERA code    |
3032         |        | 27.  The supervisor inhibit control also determines      |
3033         |        | if pending buffered log data is reset when a Read        |
3034         |        | Buffered Log command is issued.  The default is          |
3035         |        | inactivate.                                              |
3036         |________|__________________________________________________________|
3037         | 4      | Improved Data Recording Capability (IDRC)                |
3038         |        |                                                          |
3039         |        | If active, IDRC is invoked for any subsequent Write      |
3040         |        | commands within the current command chain.  See Table    |
3041         |        | 7 in topic 1.16.6 for the default settings.              |
3042         |________|__________________________________________________________|
3043         | 5-7    | Reserved                                                 |
3044         |________|__________________________________________________________|
3045 
3046         The Mode Set command is a supervisor command and cannot be performed
3047         if preceded by a Mode Set command that inhibits supervisor commands.
3048         */
3049 
3050         /* Command reject if the volume is currently fenced */
3051         if (dev->fenced)
3052         {
3053             build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code);
3054             break;
3055         }
3056 
3057         /* Calculate residual byte count */
3058         RESIDUAL_CALC (1);
3059 
3060         /* Check for count field of at least 1 byte, and that
3061            supvr-inhibit mode hasn't already been established */
3062         if (0
3063             || count < len
3064             || dev->supvr_inhibit
3065         )
3066         {
3067             build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code);
3068             break;
3069         }
3070 
3071         /* Assign a unique Message Id for this I/O if needed */
3072         INCREMENT_MESSAGEID(dev);
3073 
3074         /* Process request */
3075         if (iobuf[0] & MSET_SUPVR_INHIBIT)
3076             dev->supvr_inhibit = 1;         /* set supvr-inhibit mode*/
3077 
3078         if (iobuf[0] & MSET_WRITE_IMMED)
3079             dev->write_immed = 1;           /* set write-immed. mode */
3080 
3081         build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code);
3082         break;
3083 
3084     } /* End case 0xDB: MODE SET */
3085 
3086     /*---------------------------------------------------------------*/
3087     /* CONTROL ACCESS                                                */
3088     /*---------------------------------------------------------------*/
3089     case 0xE3:
3090     {
3091         /*          GA32-0127 IBM 3490E Hardware Reference
3092 
3093         Control Access (X'E3')
3094 
3095         The Control Access command is used to perform the set-password,
3096         conditional-enable, and conditional-disable functions of dynamic
3097         partitioning.
3098 
3099         The command requires 12 bytes of data to be transferred from the
3100         channel to the control unit which is defined as follows:
3101 
3102          ________ ________ ___________________________________________
3103         | Byte   | Bit    | Description                               |
3104         |________|________|___________________________________________|
3105         | 0      |        | Function Control                          |
3106         |________|________|___________________________________________|
3107         |        | 0,1    | 0  (x'00')  Set Password                  |
3108         |        |        | 1  (x'40')  Conditional Disable           |
3109         |        |        | 2  (x'80')  Conditional Enable            |
3110         |        |        | 3  (x'C0')  Reserved (Invalid)            |
3111         |________|________|___________________________________________|
3112         |        | 2-7    | Reserved (must be B'0')                   |
3113         |________|________|___________________________________________|
3114         | 1-11   |        | Password                                  |
3115         |________|________|___________________________________________|
3116         */
3117 
3118         /* Command Reject if Supervisor-Inhibit */
3119         if (dev->supvr_inhibit)
3120         {
3121             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
3122             break;
3123         }
3124 
3125         /* Calculate residual byte count */
3126         RESIDUAL_CALC (12);
3127 
3128         /* Control information length must be at least 12 bytes */
3129         if (count < len)
3130         {
3131             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
3132             break;
3133         }
3134 
3135         /* Byte 0 is the CAC mode-of-use */
3136         switch (iobuf[0])
3137         {
3138         /*-----------------------------------------------------------*/
3139         /* Set Password                                              */
3140         /* 0x00nnnnnnnnnnnnnnnnnnnnnn                                */
3141         /*-----------------------------------------------------------*/
3142         case CAC_SET_PASSWORD:
3143         {
3144             /* Password must not be zero
3145                and the device path must be Explicitly Enabled */
3146             if (0
3147                 || memcmp( iobuf+1, "\00\00\00\00\00\00\00\00\00\00\00", 11 ) == 0
3148                 || (dev->pgstat & SPG_PARTSTAT_XENABLED) == 0
3149             )
3150             {
3151                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
3152                 break;
3153             }
3154 
3155             /* Set Password if none set yet */
3156             if (memcmp( dev->drvpwd, "\00\00\00\00\00\00\00\00\00\00\00", 11 ) == 0)
3157             {
3158                 memcpy (dev->drvpwd, iobuf+1, 11);
3159             }
3160             else /* Password already set - they must match */
3161             {
3162                 if (memcmp( dev->drvpwd, iobuf+1, 11 ) != 0)
3163                 {
3164                     build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
3165                     break;
3166                 }
3167             }
3168             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
3169             break;
3170         }
3171 
3172         /*-----------------------------------------------------------*/
3173         /* Conditional Enable                                        */
3174         /* 0x80nnnnnnnnnnnnnnnnnnnnnn                                */
3175         /*-----------------------------------------------------------*/
3176         case CAC_COND_ENABLE:
3177         {
3178             /* A drive password must be set and it must match the one given as input */
3179             if (0
3180                 || memcmp( dev->drvpwd, "\00\00\00\00\00\00\00\00\00\00\00", 11 ) == 0
3181                 || memcmp( dev->drvpwd, iobuf+1, 11 ) != 0
3182             )
3183             {
3184                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
3185                 break;
3186             }
3187             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
3188             break;
3189         }
3190 
3191         /*-----------------------------------------------------------*/
3192         /* Conditional Disable                                       */
3193         /* 0x40nnnnnnnnnnnnnnnnnnnnnn                                */
3194         /*-----------------------------------------------------------*/
3195         case CAC_COND_DISABLE:
3196         {
3197             /* A drive password is set, it must match the one given as input */
3198             if (1
3199                 && memcmp (dev->drvpwd, "\00\00\00\00\00\00\00\00\00\00\00", 11) != 0
3200                 && memcmp (dev->drvpwd, iobuf+1, 11) != 0
3201             )
3202             {
3203                 build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
3204                 break;
3205             }
3206 
3207             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
3208             break;
3209         }
3210 
3211         default:    /* Unsupported Control Access Function */
3212         {
3213             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
3214             break;
3215         }
3216 
3217         } /* End switch (iobuf[0]) */
3218 
3219         break;
3220 
3221     } /* End case 0xE3 CONTROL ACCESS */
3222 
3223     /*---------------------------------------------------------------*/
3224     /* SENSE ID    (3422 and later)                                  */
3225     /*---------------------------------------------------------------*/
3226     case 0xE4:
3227     {
3228 #if defined( OPTION_TAPE_AUTOMOUNT )
3229         /* AUTOMOUNT QUERY - part 2 (if command-chained from prior 0x4B) */
3230         if (1
3231             && dev->tapedevt != TAPEDEVT_SCSITAPE
3232             && sysblk.tamdir != NULL
3233             && !dev->noautomount
3234             && (chained & CCW_FLAGS_CC)
3235             && 0x4B == prevcode
3236         )
3237         {
3238             int  i;   // (work)
3239 
3240             /* Calculate residual byte count */
3241             RESIDUAL_CALC (strlen(dev->filename));
3242 
3243             /* Copy device filename to guest storage */
3244             for (i=0; i < num; i++)
3245                 iobuf[i] = host_to_guest( dev->filename[i] );
3246 
3247             /* Return normal status */
3248             build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
3249             break;
3250         }
3251 #endif /* OPTION_TAPE_AUTOMOUNT */
3252 
3253         /* SENSE ID did not exist on the 3803 */
3254         /* If numdevid is 0, then 0xE4 not supported */
3255         if (dev->numdevid==0)
3256         {
3257             build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
3258             break;
3259         }
3260 
3261         /* Calculate residual byte count */
3262         RESIDUAL_CALC (dev->numdevid);
3263 
3264         /* Copy device identifier bytes to channel I/O buffer */
3265         memcpy (iobuf, dev->devid, num);
3266 
3267         /* Return unit status */
3268         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
3269         break;
3270     }
3271 
3272     /*---------------------------------------------------------------*/
3273     /* READ CONFIGURATION DATA   (3490 and later)                    */
3274     /*---------------------------------------------------------------*/
3275     case 0xFA:
3276     {
3277         /*          GA32-0127 IBM 3490E Hardware Reference
3278 
3279         Read Configuration Data (X'FA')
3280 
3281         A Read Configuration Data command causes 160 bytes of data to
3282         be transferred from the control unit to the channel.  The data
3283         transferred by this command is referred to as a configuration
3284         record and is associated with the addressed device-path pair.
3285         The configuration record from each device-path pair provides the
3286         host with identifiers of node elements internal to the subsystem.
3287         */
3288 
3289         static const BYTE cfgdata[] =       // (prototype data)
3290         {
3291         // ---------------- Device NED ---------------------------------------------------
3292         0xCC,                               // 0:      NED code
3293         0x01,                               // 1:      Type  (X'01' = I/O Device)
3294         0x02,                               // 2:      Class (X'02' = Magnetic Tape)
3295         0x00,                               // 3:      (Reserved)
3296         0xF0,0xF0,0xF3,0xF4,0xF9,0xF0,      // 4-9:    Type  ('003490')
3297         0xC3,0xF1,0xF0,                     // 10-12:  Model ('C10')
3298         0xC8,0xD9,0xC3,                     // 13-15:  Manufacturer ('HRC' = Hercules)
3299         0xE9,0xE9,                          // 16-17:  Plant of Manufacture ('ZZ' = Herc)
3300         0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,      // 18-29:  Sequence Number
3301         0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,      //
3302         0x00, 0x00,                         // 30-31: Tag (x'000n', n = Logical Drive Address)
3303         // ---------------- Control Unit NED ---------------------------------------------
3304         0xC4,                               // 32:     NED code
3305         0x02,                               // 33:     Type  (X'02' = Control Unit)
3306         0x00,                               // 34:     Class (X'00' = Undefined)
3307         0x00,                               // 35:     (Reserved)
3308         0xF0,0xF0,0xF3,0xF4,0xF9,0xF0,      // 36-41:  Type  ('003490')
3309         0xC3,0xF1,0xF0,                     // 42-44:  Model ('C10')
3310         0xC8,0xD9,0xC3,                     // 45-47:  Manufacturer ('HRC' = Hercules)
3311         0xE9,0xE9,                          // 48-49:  Plant of Manufacture ('ZZ' = Herc)
3312         0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,      // 50-61:  Sequence Number
3313         0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,      //
3314         0x00, 0x00,                         // 62-63:  Tag (x'0000')
3315         // ---------------- Library NED --------------------------------------------------
3316         0x00,                               // 64:     NED code   (x'00' = Not Used)
3317         0x00,                               // 65:     Type
3318         0x00,                               // 66:     Class
3319         0x00,                               // 67:     (Reserved)
3320         0x00,0x00,0x00,0x00,0x00,0x00,      // 68-73:  Type
3321         0x00,0x00,0x00,                     // 74-76:  Model
3322         0x00,0x00,0x00,                     // 77-79:  Manufacturer
3323         0x00,0x00,                          // 80-81:  Plant of Manufacture
3324         0x00,0x00,0x00,0x00,0x00,0x00,      // 82-93:  Sequence Number
3325         0x00,0x00,0x00,0x00,0x00,0x00,      //
3326         0x00, 0x00,                         // 94-95:  Tag
3327         // ---------------- Token NED ---------------------------------------------------
3328         0xEC,                               // 96:       NED code
3329         0x00,                               // 97:       Type  (X'00' = Unspecified)
3330         0x00,                               // 98:       Class (X'00' = Undefined)
3331         0x00,                               // 99:       (Reserved)
3332         0xF0,0xF0,0xF3,0xF4,0xF9,0xF0,      // 100-105:  Type  ('003490')
3333         0xC3,0xF1,0xF0,                     // 106-108:  Model ('C10')
3334         0xC8,0xD9,0xC3,                     // 109-111:  Manufacturer ('HRC' = Hercules)
3335         0xE9,0xE9,                          // 112-113:  Plant of Manufacture ('ZZ' = Herc)
3336         0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,      // 114-125:  Sequence Number
3337         0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,      //
3338         0x00, 0x00,                         // 126-127:  Tag (x'0000')
3339         // ---------------- General NEQ --------------------------------------------------
3340         0x80,                               // 128:      NED code
3341         0x80,                               // 129:      Record Selector:
3342                                             //           x'80' = Control Unit 0
3343                                             //           x'81' = Control Unit 1
3344         0x00,0x80,                          // 130-131:  Interface Id:
3345                                             //           x'0080' = CU Channel Adapter A
3346                                             //           x'0040' = CU Channel Adapter B
3347         0x00,                               // 132:      Device-Dependent Timeout
3348         0x00,0x00,0x00,                     // 133-135:  (Reserved)
3349         0x00,                               // 136:      Extended Information:
3350                                             //           x'00' for Logical Drive Addresses 0-7
3351                                             //           x'01' for Logical Drive Addresses 8-F
3352         0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 137-159:  (Reserved)
3353         0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3354         0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3355         0x00,0x00,
3356         };
3357 
3358         ASSERT( sizeof(cfgdata) == 160 );
3359 
3360         /* Calculate residual byte count */
3361         RESIDUAL_CALC (160);
3362 
3363         /* Copy prototype Configuration Data to channel I/O buffer */
3364         memcpy (iobuf, cfgdata, sizeof(cfgdata));
3365 
3366         /* Fixup values for this particular device/type...  NOTE: we
3367            only fixup the Device and Control Unit NEDs here. The Token
3368            NED's type/model values come from the Device NED's values.
3369         */
3370         if (0x3480 == dev->devtype)
3371         {
3372             memcpy (&iobuf[7],  "\xF4\xF8",     2);     // '48'
3373             memcpy (&iobuf[39], "\xF4\xF8",     2);     // '48'
3374 
3375             memcpy (&iobuf[10], "\xC4\xF3\xF1", 3);     // 'D31'
3376             memcpy (&iobuf[42], "\xC4\xF3\xF1", 3);     // 'D31'
3377         }
3378         else if (0x3490 == dev->devtype)
3379         {
3380 //          memcpy (&iobuf[7],  "\xF4\xF9",     2);     // '49'
3381 //          memcpy (&iobuf[39], "\xF4\xF9",     2);     // '49'
3382 
3383 //          memcpy (&iobuf[10], "\xC3\xF1\xF0", 3);     // 'C10'
3384 //          memcpy (&iobuf[42], "\xC3\xF1\xF0", 3);     // 'C10'
3385         }
3386         else if (0x3590 == dev->devtype)
3387         {
3388             memcpy (&iobuf[7],  "\xF5\xF9",     2);     // '59'
3389             memcpy (&iobuf[39], "\xF5\xF9",     2);     // '59'
3390 
3391             memcpy (&iobuf[10], "\xC2\xF1\xC1", 3);     // 'B1A'
3392             memcpy (&iobuf[42], "\xC1\xF5\xF0", 3);     // 'A50'
3393         }
3394 
3395         memcpy (&iobuf[100], &iobuf[4], 9);     // (set Token NED Type/Model from Device NED)
3396 
3397         iobuf[31] |= (dev->devnum & 0x0F);      // (set Logical Drive Address)
3398 
3399         if ((dev->devnum & 0x0F) > 7)
3400             iobuf[136] = 0x01;                  // (set Extended Information)
3401 
3402         /* Return normal status */
3403         build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code);
3404         break;
3405 
3406     } /* End case 0xFA: READ CONFIGURATION DATA */
3407 
3408     /*---------------------------------------------------------------*/
3409     /* INVALID OPERATION                                             */
3410     /*---------------------------------------------------------------*/
3411     default:
3412     {
3413         /* Set command reject sense byte, and unit check status */
3414         build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code);
3415     }
3416 
3417     } /* end switch (code) */
3418 
3419 } /* end function tapedev_execute_ccw */
3420 
3421 #if defined( OPTION_TAPE_AUTOMOUNT )
3422 /*-------------------------------------------------------------------*/
3423 /* Find next more-restrictive TAMDIR subdirectory entry...           */
3424 /*-------------------------------------------------------------------*/
findtamdir(int rej,int minlen,const char * pszDir)3425 static TAMDIR* findtamdir( int rej, int minlen, const char* pszDir )
3426 {
3427     TAMDIR *pTAMDIR = sysblk.tamdir;    /* always search entire list */
3428     do
3429         if (1
3430             && pTAMDIR->rej == rej
3431             && pTAMDIR->len > minlen
3432             && strnfilenamecmp( pszDir, pTAMDIR->dir, pTAMDIR->len ) == 0
3433         )
3434             return pTAMDIR;
3435     while ((pTAMDIR = pTAMDIR->next) != NULL);
3436     return NULL;
3437 }
3438 #endif // defined( OPTION_TAPE_AUTOMOUNT )
3439 
3440 /*-------------------------------------------------------------------*/
3441 /* Load Display channel command processing...                        */
3442 /*-------------------------------------------------------------------*/
load_display(DEVBLK * dev,BYTE * buf,U16 count)3443 void load_display (DEVBLK *dev, BYTE *buf, U16 count)
3444 {
3445 U16             i;                      /* Array subscript           */
3446 char            msg1[9], msg2[9];       /* Message areas (ASCIIZ)    */
3447 BYTE            fcb;                    /* Format Control Byte       */
3448 BYTE            tapeloaded;             /* (boolean true/false)      */
3449 BYTE*           msg;                    /* (work buf ptr)            */
3450 
3451     if ( !count )
3452         return;
3453 
3454     /* Pick up format control byte */
3455     fcb = *buf;
3456 
3457     /* Copy and translate messages... */
3458 
3459     memset( msg1, 0, sizeof(msg1) );
3460     memset( msg2, 0, sizeof(msg2) );
3461 
3462     msg = buf+1;
3463 
3464     for (i=0; *msg && i < 8 && ((i+1)+0) < count; i++)
3465         msg1[i] = guest_to_host(*msg++);
3466 
3467     msg = buf+1+8;
3468 
3469     for (i=0; *msg && i < 8 && ((i+1)+8) < count; i++)
3470         msg2[i] = guest_to_host(*msg++);
3471 
3472     msg1[ sizeof(msg1) - 1 ] = 0;
3473     msg2[ sizeof(msg2) - 1 ] = 0;
3474 
3475     tapeloaded = dev->tmh->tapeloaded( dev, NULL, 0 );
3476 
3477     switch ( fcb & FCB_FS )  // (high-order 3 bits)
3478     {
3479     case FCB_FS_READYGO:     // 0x00
3480 
3481         /*
3482         || 000b: "The message specified in bytes 1-8 and 9-16 is
3483         ||       maintained until the tape drive next starts tape
3484         ||       motion, or until the message is updated."
3485         */
3486 
3487         dev->tapedispflags = 0;
3488 
3489         strlcpy( dev->tapemsg1, msg1, sizeof(dev->tapemsg1) );
3490         strlcpy( dev->tapemsg2, msg2, sizeof(dev->tapemsg2) );
3491 
3492         dev->tapedisptype  = TAPEDISPTYP_WAITACT;
3493 
3494         break;
3495 
3496     case FCB_FS_UNMOUNT:     // 0x20
3497 
3498         /*
3499         || 001b: "The message specified in bytes 1-8 is maintained
3500         ||       until the tape cartridge is physically removed from
3501         ||       the tape drive, or until the next unload/load cycle.
3502         ||       If the drive does not contain a cartridge when the
3503         ||       Load Display command is received, the display will
3504         ||       contain the message that existed prior to the receipt
3505         ||       of the command."
3506         */
3507 
3508         dev->tapedispflags = 0;
3509 
3510         if ( tapeloaded )
3511         {
3512             dev->tapedisptype  = TAPEDISPTYP_UNMOUNT;
3513             dev->tapedispflags = TAPEDISPFLG_REQAUTOMNT;
3514 
3515             strlcpy( dev->tapemsg1, msg1, sizeof(dev->tapemsg1) );
3516 
3517             if ( dev->ccwtrace || dev->ccwstep )
3518                 logmsg(_("HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted\n"),
3519                     dev->devnum, dev->tapemsg1 );
3520         }
3521 
3522         break;
3523 
3524     case FCB_FS_MOUNT:       // 0x40
3525 
3526         /*
3527         || 010b: "The message specified in bytes 1-8 is maintained
3528         ||       until the drive is next loaded. If the drive is
3529         ||       loaded when the Load Display command is received,
3530         ||       the display will contain the message that existed
3531         ||       prior to the receipt of the command."
3532         */
3533 
3534         dev->tapedispflags = 0;
3535 
3536         if ( !tapeloaded )
3537         {
3538             dev->tapedisptype  = TAPEDISPTYP_MOUNT;
3539             dev->tapedispflags = TAPEDISPFLG_REQAUTOMNT;
3540 
3541             strlcpy( dev->tapemsg1, msg1, sizeof(dev->tapemsg1) );
3542 
3543             if ( dev->ccwtrace || dev->ccwstep )
3544                 logmsg(_("HHCTA099I %4.4X: Tape Display \"%s\" Until Mounted\n"),
3545                     dev->devnum, dev->tapemsg1 );
3546         }
3547 
3548         break;
3549 
3550     case FCB_FS_NOP:         // 0x60
3551     default:
3552 
3553         /*
3554         || 011b: "This value is used to physically access a drive
3555         ||       without changing the message display. This option
3556         ||       can be used to test whether a control unit can
3557         ||       physically communicate with a drive."
3558         */
3559 
3560         return;
3561 
3562     case FCB_FS_RESET_DISPLAY: // 0x80
3563 
3564         /*
3565         || 100b: "The host message being displayed is cancelled and
3566         ||       a unit message is displayed instead."
3567         */
3568 
3569         dev->tapedispflags = 0;
3570         dev->tapedisptype  = TAPEDISPTYP_IDLE;
3571 
3572         break;
3573 
3574     case FCB_FS_UMOUNTMOUNT: // 0xE0
3575 
3576         /*
3577         || 111b: "The message in bytes 1-8 is displayed until a tape
3578         ||       cartridge is physically removed from the tape drive,
3579         ||       or until the drive is next loaded. The message in
3580         ||       bytes 9-16 is displayed until the drive is next loaded.
3581         ||       If no cartridge is present in the drive, the first
3582         ||       message is ignored and only the second message is
3583         ||       displayed until the drive is next loaded."
3584         */
3585 
3586         dev->tapedispflags = 0;
3587 
3588         strlcpy( dev->tapemsg1, msg1, sizeof(dev->tapemsg1) );
3589         strlcpy( dev->tapemsg2, msg2, sizeof(dev->tapemsg2) );
3590 
3591         if ( tapeloaded )
3592         {
3593             dev->tapedisptype  = TAPEDISPTYP_UMOUNTMOUNT;
3594             dev->tapedispflags = TAPEDISPFLG_REQAUTOMNT;
3595 
3596             if ( dev->ccwtrace || dev->ccwstep )
3597                 logmsg(_("HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted, then \"%s\" Until Mounted\n"),
3598                     dev->devnum, dev->tapemsg1, dev->tapemsg2 );
3599         }
3600         else
3601         {
3602             dev->tapedisptype  = TAPEDISPTYP_MOUNT;
3603             dev->tapedispflags = TAPEDISPFLG_MESSAGE2 | TAPEDISPFLG_REQAUTOMNT;
3604 
3605             if ( dev->ccwtrace || dev->ccwstep )
3606                 logmsg(_("HHCTA099I %4.4X: Tape \"%s\" Until Mounted\n"),
3607                     dev->devnum, dev->tapemsg2 );
3608         }
3609 
3610         break;
3611     }
3612 
3613     /* Set the flags... */
3614 
3615     /*
3616         "When bit 7 (FCB_AL) is active and bits 0-2 (FCB_FS) specify
3617         a Mount Message, then only the first eight characters of the
3618         message are displayed and bits 3-5 (FCB_AM, FCB_BM, FCB_M2)
3619         are ignored."
3620     */
3621     if (1
3622         &&   ( fcb & FCB_AL )
3623         && ( ( fcb & FCB_FS ) == FCB_FS_MOUNT )
3624     )
3625     {
3626         fcb  &=  ~( FCB_AM | FCB_BM | FCB_M2 );
3627         dev->tapedispflags &= ~TAPEDISPFLG_MESSAGE2;
3628     }
3629 
3630     /*
3631         "When bit 7 (FCB_AL) is active and bits 0-2 (FCB_FS) specify
3632         a Demount/Mount message, then only the last eight characters
3633         of the message are displayed. Bits 3-5 (FCB_AM, FCB_BM, FCB_M2)
3634         are ignored."
3635     */
3636     if (1
3637         &&   ( fcb & FCB_AL )
3638         && ( ( fcb & FCB_FS ) == FCB_FS_UMOUNTMOUNT )
3639     )
3640     {
3641         fcb  &=  ~( FCB_AM | FCB_BM | FCB_M2 );
3642         dev->tapedispflags |= TAPEDISPFLG_MESSAGE2;
3643     }
3644 
3645     /*
3646         "When bit 3 (FCB_AM) is set to 1, then bits 4 (FCB_BM) and 5
3647         (FCB_M2) are ignored."
3648     */
3649     if ( fcb & FCB_AM )
3650         fcb  &=  ~( FCB_BM | FCB_M2 );
3651 
3652     dev->tapedispflags |= (((fcb & FCB_AM) ? TAPEDISPFLG_ALTERNATE  : 0 ) |
3653                           ( (fcb & FCB_BM) ? TAPEDISPFLG_BLINKING   : 0 ) |
3654                           ( (fcb & FCB_M2) ? TAPEDISPFLG_MESSAGE2   : 0 ) |
3655                           ( (fcb & FCB_AL) ? TAPEDISPFLG_AUTOLOADER : 0 ));
3656 
3657     UpdateDisplay( dev );
3658     ReqAutoMount( dev );
3659 
3660 } /* end function load_display */
3661 
3662 
3663 /*********************************************************************/
3664 /*********************************************************************/
3665 /**                                                                 **/
3666 /**                 SENSE CCW HANDLING FUNCTIONS                    **/
3667 /**                                                                 **/
3668 /*********************************************************************/
3669 /*********************************************************************/
3670 
3671 /*-------------------------------------------------------------------*/
3672 /*                        build_senseX                               */
3673 /*-------------------------------------------------------------------*/
3674 /*  Construct sense bytes and unit status                            */
3675 /*  Note: name changed because semantic changed                      */
3676 /*  ERCode is our internal ERror-type code                           */
3677 /*                                                                   */
3678 /*  Uses the 'TapeSenseTable' table index                            */
3679 /*  from the 'TapeDevtypeList' table to route call to                */
3680 /*  one of the below device-specific sense functions                 */
3681 /*-------------------------------------------------------------------*/
build_senseX(int ERCode,DEVBLK * dev,BYTE * unitstat,BYTE ccwcode)3682 void build_senseX (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode)
3683 {
3684 int i;
3685 BYTE usr;
3686 int sense_built;
3687     sense_built = 0;
3688     if(unitstat==NULL)
3689     {
3690         unitstat = &usr;
3691     }
3692     for(i = 0;TapeDevtypeList[i] != 0; i += TAPEDEVTYPELIST_ENTRYSIZE)
3693     {
3694         if (TapeDevtypeList[i] == dev->devtype)
3695         {
3696             // Clear old sense if we're going to completely rebuild it...
3697 
3698             if (TAPE_BSENSE_STATUSONLY != ERCode)
3699             {
3700                 memset( dev->sense, 0, sizeof(dev->sense) );
3701                 dev->sns_pending = 0;
3702             }
3703 
3704             // Call the primary sense function (e.g. "build_sense_3480_etal")...
3705 
3706             TapeSenseTable[TapeDevtypeList[i+4]](ERCode,dev,unitstat,ccwcode);
3707             sense_built = 1;
3708 
3709             // Unit-exception s/b signalled for all write operations
3710             // once the end-of-tape (EOT) reflector has been passed...
3711 
3712             if (1
3713                 && TAPE_BSENSE_STATUSONLY == ERCode
3714                 &&
3715                 (0
3716                     || 0x01 == ccwcode      // write
3717                     || 0x17 == ccwcode      // erase gap
3718                     || 0x1F == ccwcode      // write tapemark
3719                 )
3720                 && dev->tmh->passedeot(dev)
3721             )
3722             {
3723                 // We're still in the "Early Warning Zone",
3724                 // so keep warning them...
3725 
3726                 *unitstat |= CSW_UX;        // ("Warning!")
3727             }
3728             break;
3729         }
3730     }
3731     if (!sense_built)
3732     {
3733         memset( dev->sense, 0, sizeof(dev->sense) );
3734         dev->sense[0]=SENSE_EC;
3735         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3736     }
3737     if (*unitstat & CSW_UC)
3738     {
3739         dev->sns_pending = 1;
3740     }
3741     return;
3742 
3743 } /* end function build_senseX */
3744 
3745 /*-------------------------------------------------------------------*/
3746 /*                  build_sense_3410_3420                            */
3747 /*-------------------------------------------------------------------*/
build_sense_3410_3420(int ERCode,DEVBLK * dev,BYTE * unitstat,BYTE ccwcode)3748 void build_sense_3410_3420 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode)
3749 {
3750     UNREFERENCED(ccwcode);
3751 
3752     // NOTE: caller should have cleared sense area to zeros
3753     //       if this isn't a 'TAPE_BSENSE_STATUSONLY' call
3754 
3755     switch(ERCode)
3756     {
3757     case TAPE_BSENSE_TAPEUNLOADED:
3758         *unitstat = CSW_UC;
3759         dev->sense[0] = SENSE_IR;
3760         dev->sense[1] = SENSE1_TAPE_TUB;
3761         break;
3762     case TAPE_BSENSE_RUN_SUCCESS: /* RewUnld op */
3763         /* FIXME : CE Should have been presented before */
3764         /*         Same as for 348x drives */
3765         *unitstat = CSW_CE | CSW_UC | CSW_DE | CSW_CUE;
3766         /*
3767         *unitstat = CSW_UC | CSW_DE | CSW_CUE;
3768         */
3769         dev->sense[0] = SENSE_IR;
3770         dev->sense[1] = SENSE1_TAPE_TUB;
3771         break;
3772     case TAPE_BSENSE_REWINDFAILED:
3773     case TAPE_BSENSE_FENCED:
3774     case TAPE_BSENSE_EMPTYTAPE:
3775     case TAPE_BSENSE_ENDOFTAPE:
3776     case TAPE_BSENSE_BLOCKSHORT:
3777         /* On 3411/3420 the tape runs off the reel in that case */
3778         /* this will cause pressure loss in both columns */
3779     case TAPE_BSENSE_LOCATEERR:
3780         /* Locate error: This is more like improperly formatted tape */
3781         /* i.e. the tape broke inside the drive                       */
3782         /* So EC instead of DC                                        */
3783     case TAPE_BSENSE_TAPELOADFAIL:
3784         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3785         dev->sense[0] = SENSE_EC;
3786         dev->sense[1] = SENSE1_TAPE_TUB;
3787         dev->sense[7] = 0x60;
3788         break;
3789     case TAPE_BSENSE_ITFERROR:
3790         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3791         dev->sense[0] = SENSE_EC;
3792         dev->sense[1] = SENSE1_TAPE_TUB;
3793         dev->sense[4] = 0x80; /* Tape Unit Reject */
3794         break;
3795     case TAPE_BSENSE_READFAIL:
3796     case TAPE_BSENSE_BADALGORITHM:
3797         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3798         dev->sense[0] = SENSE_DC;
3799         dev->sense[3] = 0xC0; /* Vertical CRC check & Multitrack error */
3800         break;
3801     case TAPE_BSENSE_WRITEFAIL:
3802         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3803         dev->sense[0] = SENSE_DC;
3804         dev->sense[3] = 0x60; /* Longitudinal CRC check & Multitrack error */
3805         break;
3806     case TAPE_BSENSE_BADCOMMAND:
3807     case TAPE_BSENSE_INCOMPAT:
3808         *unitstat = CSW_UC;
3809         dev->sense[0] = SENSE_CR;
3810         dev->sense[4] = 0x01;
3811         break;
3812     case TAPE_BSENSE_WRITEPROTECT:
3813         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3814         dev->sense[0] = SENSE_CR;
3815         break;
3816     case TAPE_BSENSE_LOADPTERR:
3817         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3818         dev->sense[0] = 0;
3819         break;
3820     case TAPE_BSENSE_READTM:
3821         *unitstat = CSW_CE|CSW_DE|CSW_UX;
3822         break;
3823     case TAPE_BSENSE_UNSOLICITED:
3824         *unitstat = CSW_CE|CSW_DE;
3825         break;
3826     case TAPE_BSENSE_STATUSONLY:
3827         *unitstat = CSW_CE|CSW_DE;
3828         break;
3829     } // end switch(ERCode)
3830 
3831     if (TAPE_BSENSE_STATUSONLY == ERCode)
3832         return; // (mission accomplished)
3833 
3834     /* Fill in the common sense information */
3835 
3836     if (strcmp(dev->filename,TAPE_UNLOADED) == 0
3837         || !dev->tmh->tapeloaded(dev,NULL,0))
3838     {
3839         dev->sense[0] |= SENSE_IR;
3840         dev->sense[1] |= SENSE1_TAPE_FP;
3841         dev->sense[1] &= ~SENSE1_TAPE_TUA;
3842         dev->sense[1] |= SENSE1_TAPE_TUB;
3843     }
3844     else
3845     {
3846         dev->sense[0] &= ~SENSE_IR;
3847         dev->sense[1] |= IsAtLoadPoint( dev ) ? SENSE1_TAPE_LOADPT : 0;
3848         dev->sense[1] |= dev->readonly || dev->tdparms.logical_readonly ?
3849             SENSE1_TAPE_FP : 0;
3850         dev->sense[1] |= SENSE1_TAPE_TUA;
3851         dev->sense[1] &= ~SENSE1_TAPE_TUB;
3852     }
3853     if (dev->tmh->passedeot(dev))
3854     {
3855         dev->sense[4] |= 0x40;
3856     }
3857 
3858 } /* end function build_sense_3410_3420 */
3859 
3860 /*-------------------------------------------------------------------*/
3861 /*                     build_sense_3410                              */
3862 /*-------------------------------------------------------------------*/
build_sense_3410(int ERCode,DEVBLK * dev,BYTE * unitstat,BYTE ccwcode)3863 void build_sense_3410 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode)
3864 {
3865     build_sense_3410_3420(ERCode,dev,unitstat,ccwcode);
3866 
3867     dev->sense[5] &= 0x80;
3868     dev->sense[5] |= 0x40;
3869     dev->sense[6] = 0x22; /* Dual Dens - 3410/3411 Model 2 */
3870     dev->numsense = 9;
3871 
3872 } /* end function build_sense_3410 */
3873 
3874 /*-------------------------------------------------------------------*/
3875 /*                     build_sense_3420                              */
3876 /*-------------------------------------------------------------------*/
build_sense_3420(int ERCode,DEVBLK * dev,BYTE * unitstat,BYTE ccwcode)3877 void build_sense_3420 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode)
3878 {
3879     build_sense_3410_3420(ERCode,dev,unitstat,ccwcode);
3880 
3881     /* Following stripped from original 'build_sense' */
3882     dev->sense[5] |= 0xC0;
3883     dev->sense[6] |= 0x03;
3884     dev->sense[13] = 0x80;
3885     dev->sense[14] = 0x01;
3886     dev->sense[15] = 0x00;
3887     dev->sense[16] = 0x01;
3888     dev->sense[19] = 0xFF;
3889     dev->sense[20] = 0xFF;
3890     dev->numsense = 24;
3891 
3892 } /* end function build_sense_3420 */
3893 
3894 /*-------------------------------------------------------------------*/
3895 /*                     build_sense_3480_etal                         */
3896 /*-------------------------------------------------------------------*/
build_sense_3480_etal(int ERCode,DEVBLK * dev,BYTE * unitstat,BYTE ccwcode)3897 void build_sense_3480_etal (int ERCode,DEVBLK *dev,BYTE *unitstat,BYTE ccwcode)
3898 {
3899 int sns4mat = TAPE_SNS7_FMT_20_3480;
3900 
3901     // NOTE: caller should have cleared sense area to zeros
3902     //       if this isn't a 'TAPE_BSENSE_STATUSONLY' call
3903 
3904     switch(ERCode)
3905     {
3906     case TAPE_BSENSE_TAPEUNLOADED:
3907         dev->sense[0] = TAPE_SNS0_INTVREQ;
3908         dev->sense[3] = TAPE_ERA_DRIVE_NOT_READY; /* ERA 43 = Int Req */
3909         *unitstat = CSW_UC;
3910         break;
3911     case TAPE_BSENSE_RUN_SUCCESS:        /* Not an error */
3912         /* NOT an error, But according to GA32-0219-02 2.1.2.2
3913            Rewind Unload always ends with with DE+UC on secondary status */
3914         /* FIXME! */
3915         /* Note that Initial status & Secondary statuses are merged here */
3916         /* when they should be presented separatly */
3917         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3918         dev->sense[0] = TAPE_SNS0_INTVREQ;
3919         dev->sense[3] = TAPE_ERA_ENVIRONMENTAL_DATA_PRESENT;
3920         sns4mat = TAPE_SNS7_FMT_22_3480_EOV_STATS;
3921         break;
3922     case TAPE_BSENSE_TAPELOADFAIL:
3923         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3924         dev->sense[0] = TAPE_SNS0_INTVREQ|TAPE_SNS0_DEFUNITCK;
3925         dev->sense[3] = TAPE_ERA_LOAD_FAILURE; /* ERA 33 = Load Failed */
3926         break;
3927     case TAPE_BSENSE_READFAIL:
3928         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3929         dev->sense[0] = TAPE_SNS0_DATACHK;
3930         dev->sense[3] = TAPE_ERA_READ_DATA_CHECK;
3931         break;
3932     case TAPE_BSENSE_WRITEFAIL:
3933         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3934         dev->sense[0] = TAPE_SNS0_DATACHK;
3935         dev->sense[3] = TAPE_ERA_WRITE_DATA_CHECK;
3936         break;
3937     case TAPE_BSENSE_BADCOMMAND:
3938         *unitstat = CSW_UC;
3939         dev->sense[0] = TAPE_SNS0_CMDREJ;
3940         dev->sense[3] = TAPE_ERA_COMMAND_REJECT;
3941         break;
3942     case TAPE_BSENSE_INCOMPAT:
3943         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3944         dev->sense[0] = TAPE_SNS0_CMDREJ;
3945         dev->sense[3] = TAPE_ERA_FUNCTION_INCOMPATIBLE;
3946         break;
3947     case TAPE_BSENSE_WRITEPROTECT:
3948         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3949         dev->sense[0] = TAPE_SNS0_CMDREJ;
3950         dev->sense[3] = TAPE_ERA_WRITE_PROTECTED;
3951         break;
3952     case TAPE_BSENSE_EMPTYTAPE:
3953         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3954         dev->sense[0] = TAPE_SNS0_DATACHK;
3955         dev->sense[3] = TAPE_ERA_TAPE_VOID;
3956         break;
3957     case TAPE_BSENSE_ENDOFTAPE:
3958         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3959         dev->sense[0] = TAPE_SNS0_EQUIPCHK;
3960         dev->sense[3] = TAPE_ERA_PHYSICAL_END_OF_TAPE;
3961         break;
3962     case TAPE_BSENSE_LOADPTERR:
3963         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3964         dev->sense[0] = 0;
3965         dev->sense[3] = TAPE_ERA_BACKWARD_AT_BOT;
3966         break;
3967     case TAPE_BSENSE_FENCED:
3968         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3969         dev->sense[0] = TAPE_SNS0_EQUIPCHK|TAPE_SNS0_DEFUNITCK; /* Deffered UC */
3970         dev->sense[3] = TAPE_ERA_VOLUME_FENCED;
3971         break;
3972     case TAPE_BSENSE_BADALGORITHM:
3973         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3974         dev->sense[0] = TAPE_SNS0_EQUIPCHK;
3975         if (dev->devtype==0x3480)
3976         {
3977             dev->sense[3] = TAPE_ERA_VOLUME_FENCED;   // (volume fenced)
3978         }
3979         else // 3490, 3590, etc.
3980         {
3981             dev->sense[3] = TAPE_ERA_COMPACT_ALGORITHM_INCOMPAT;   // (bad compaction algorithm)
3982         }
3983         break;
3984     case TAPE_BSENSE_LOCATEERR:
3985         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3986         dev->sense[0] = TAPE_SNS0_EQUIPCHK;
3987         dev->sense[3] = TAPE_ERA_LOCATE_BLOCK_FAILED;
3988         break;
3989     case TAPE_BSENSE_BLOCKSHORT:
3990         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3991         dev->sense[0] = TAPE_SNS0_EQUIPCHK;
3992         dev->sense[3] = TAPE_ERA_END_OF_DATA;
3993         break;
3994     case TAPE_BSENSE_ITFERROR:
3995         *unitstat = CSW_CE|CSW_DE|CSW_UC;
3996         dev->sense[0] = TAPE_SNS0_EQUIPCHK;
3997         dev->sense[3] = TAPE_ERA_PATH_EQUIPMENT_CHECK;
3998         break;
3999     case TAPE_BSENSE_REWINDFAILED:
4000         *unitstat = CSW_CE|CSW_DE|CSW_UC;
4001         dev->sense[0] = TAPE_SNS0_EQUIPCHK;
4002         dev->sense[3] = TAPE_ERA_PERMANENT_EQUIPMENT_CHECK; /* Generic Equipment Malfunction ERP code */
4003         break;
4004     case TAPE_BSENSE_READTM:
4005         *unitstat = CSW_CE|CSW_DE|CSW_UX;
4006         break;
4007     case TAPE_BSENSE_UNSOLICITED:
4008         *unitstat = CSW_CE|CSW_DE;
4009         dev->sense[3] = TAPE_ERA_UNSOLICITED_SENSE;
4010         break;
4011     case TAPE_BSENSE_STATUSONLY:
4012     default:
4013         if ( ccwcode == 0x24 )      // READ BUFFERED LOG
4014         {
4015             if ( dev->tdparms.compress == 0 )
4016                 sns4mat = TAPE_SNS7_FMT_21_3480_READ_BUF_LOG;
4017             else
4018                 sns4mat = TAPE_SNS7_FMT_30_3480_READ_BUF_LOG;
4019         }
4020         *unitstat = CSW_CE|CSW_DE;
4021         break;
4022     } // end switch(ERCode)
4023 
4024     if (TAPE_BSENSE_STATUSONLY == ERCode)
4025         return; // (mission accomplished)
4026 
4027     /* Fill in the common sense information */
4028 
4029     if ( sns4mat == TAPE_SNS7_FMT_20_3480              ||
4030          sns4mat == TAPE_SNS7_FMT_21_3480_READ_BUF_LOG ||
4031          sns4mat == TAPE_SNS7_FMT_22_3480_EOV_STATS    ||
4032          sns4mat == TAPE_SNS7_FMT_30_3480_READ_BUF_LOG )
4033     {
4034         dev->sense[7] = sns4mat;
4035         memset(&dev->sense[8],0,31-8);
4036 
4037         if ( sns4mat == TAPE_SNS7_FMT_20_3480 )
4038         {
4039             dev->sense[25] = 0x06;                  // IDRC Installed & Upgraded Buffer
4040             if ( sysblk.tamdir != NULL )            // is AUTOLOADER ENABLED
4041             {
4042                 dev->sense[25] |= 0x01;             // ACL is installed
4043             }
4044         }
4045 
4046         if ( dev->devtype == 0x3480 )
4047         {
4048             dev->sense[27] = 0xf0;                  // indicate 3480-A22/B22
4049         }
4050         else if ( dev->devtype==0x3490 )
4051         {
4052             dev->sense[27] = 0xe0;                  // indicate 3490-D31/D32
4053         }
4054         else if ( dev->devtype==0x3590 )
4055         {
4056             dev->sense[27] = 0xe0;                  // indicate same as 3490 for now
4057         }
4058 
4059         /* create a serial Number */
4060         dev->sense[27] |= 0x0C;
4061         dev->sense[28] = (BYTE)( ( dev->devnum >> 12 ) & 0xFF );
4062         dev->sense[29] = (BYTE)( ( dev->devnum >>  4 ) & 0xFF );
4063 
4064         dev->sense[30] = (BYTE)( dev->devnum & 0x000F ) | ( (BYTE)((BYTE)( dev->devnum & 0x000F )) << 4 );
4065     }
4066 
4067     if (strcmp(dev->filename,TAPE_UNLOADED) == 0
4068         || !dev->tmh->tapeloaded(dev,NULL,0))
4069     {
4070         dev->sense[0] |= TAPE_SNS0_INTVREQ;
4071         dev->sense[1] |= TAPE_SNS1_FILEPROT;
4072     }
4073     else
4074     {
4075         dev->sense[0] &= ~TAPE_SNS0_INTVREQ;
4076         dev->sense[1] &= ~(TAPE_SNS1_BOT|TAPE_SNS1_FILEPROT);
4077         dev->sense[1] |= IsAtLoadPoint( dev ) ? TAPE_SNS1_BOT : 0;
4078         dev->sense[1] |= dev->readonly || dev->tdparms.logical_readonly ?
4079             TAPE_SNS1_FILEPROT : 0;
4080     }
4081 
4082     dev->sense[1] |= TAPE_SNS1_ONLINE;
4083     dev->sense[2] |= TAPE_SNS2_REPORTING_CHAN_A;
4084 
4085 } /* end function build_sense_3480_etal */
4086 
4087 /*-------------------------------------------------------------------*/
4088 /*                     build_sense_3490                              */
4089 /*-------------------------------------------------------------------*/
build_sense_3490(int ERCode,DEVBLK * dev,BYTE * unitstat,BYTE ccwcode)4090 void build_sense_3490 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode)
4091 {
4092     // Until we know for sure that we have to do something different,
4093     // we should be able to safely use the 3480 sense function here...
4094 
4095     build_sense_3480_etal( ERCode, dev, unitstat, ccwcode );
4096 }
4097 
4098 /*-------------------------------------------------------------------*/
4099 /*                     build_sense_3590                              */
4100 /*-------------------------------------------------------------------*/
build_sense_3590(int ERCode,DEVBLK * dev,BYTE * unitstat,BYTE ccwcode)4101 void build_sense_3590 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode)
4102 {
4103     unsigned char ERA;
4104     // Until we know for sure that we have to do something different,
4105     // we should be able to safely use the 3480 sense function here...
4106 
4107     build_sense_3480_etal( ERCode, dev, unitstat, ccwcode );
4108 
4109     ERA = dev->sense[3];
4110     switch ( ERA )
4111     {
4112     case TAPE_ERA_LOAD_DISPLAY_CHECK:
4113     case TAPE_ERA_ENVIRONMENTAL_DATA_PRESENT:
4114     case TAPE_ERA_READ_BUFFERED_LOG:
4115     case TAPE_ERA_END_OF_VOLUME_PROCESSING:
4116     case TAPE_ERA_END_OF_VOLUME_COMPLETE:
4117         dev->sense[2] |= TAPE_SNS2_NTP_BRAC_01_CONTINUE;
4118         break;
4119     case TAPE_ERA_DATA_STREAMING_NOT_OPER:
4120     case TAPE_ERA_UNSOL_ENVIRONMENTAL_DATA:
4121     case TAPE_ERA_DEGRADED_MODE:
4122     case TAPE_ERA_RECOVERED_CHECKONE_FAILURE:
4123     case TAPE_ERA_CONTROLLING_COMP_RETRY_REQ:
4124         dev->sense[2] |= TAPE_SNS2_NTP_BRAC_10_REISSUE;
4125         break;
4126     default:
4127         dev->sense[2] |= TAPE_SNS2_NTP_BRAC_00_PERM_ERR;
4128         break;
4129     }
4130 }
4131 
4132 /*-------------------------------------------------------------------*/
4133 /*                    build_sense_Streaming                          */
4134 /*                      (8809, 9347, 9348)                           */
4135 /*-------------------------------------------------------------------*/
build_sense_Streaming(int ERCode,DEVBLK * dev,BYTE * unitstat,BYTE ccwcode)4136 void build_sense_Streaming (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode)
4137 {
4138     UNREFERENCED(ccwcode);
4139 
4140     // NOTE: caller should have cleared sense area to zeros
4141     //       if this isn't a 'TAPE_BSENSE_STATUSONLY' call
4142 
4143     switch(ERCode)
4144     {
4145     case TAPE_BSENSE_TAPEUNLOADED:
4146         *unitstat = CSW_UC;
4147         dev->sense[0] = SENSE_IR;
4148         dev->sense[3] = 6;        /* Int Req ERAC */
4149         break;
4150     case TAPE_BSENSE_RUN_SUCCESS: /* RewUnld op */
4151         *unitstat = CSW_UC | CSW_CE | CSW_DE | CSW_CUE;
4152         /*
4153         *unitstat = CSW_CE | CSW_UC | CSW_DE | CSW_CUE;
4154         */
4155         dev->sense[0] = SENSE_IR;
4156         dev->sense[3] = 6;        /* Int Req ERAC */
4157         break;
4158     case TAPE_BSENSE_REWINDFAILED:
4159     case TAPE_BSENSE_ITFERROR:
4160         dev->sense[0] = SENSE_EC;
4161         dev->sense[3] = 0x03;     /* Perm Equip Check */
4162         *unitstat = CSW_CE|CSW_DE|CSW_UC;
4163         break;
4164     case TAPE_BSENSE_TAPELOADFAIL:
4165     case TAPE_BSENSE_LOCATEERR:
4166     case TAPE_BSENSE_ENDOFTAPE:
4167     case TAPE_BSENSE_EMPTYTAPE:
4168     case TAPE_BSENSE_FENCED:
4169     case TAPE_BSENSE_BLOCKSHORT:
4170     case TAPE_BSENSE_INCOMPAT:
4171         dev->sense[0] = SENSE_EC;
4172         dev->sense[3] = 0x10; /* PE-ID Burst Check */
4173         *unitstat = CSW_CE|CSW_DE|CSW_UC;
4174         break;
4175     case TAPE_BSENSE_BADALGORITHM:
4176     case TAPE_BSENSE_READFAIL:
4177         dev->sense[0] = SENSE_DC;
4178         dev->sense[3] = 0x09;     /* Read Data Check */
4179         *unitstat = CSW_CE|CSW_DE|CSW_UC;
4180         break;
4181     case TAPE_BSENSE_WRITEFAIL:
4182         dev->sense[0] = SENSE_DC;
4183         dev->sense[3] = 0x07;     /* Write Data Check (Media Error) */
4184         *unitstat = CSW_CE|CSW_DE|CSW_UC;
4185         break;
4186     case TAPE_BSENSE_BADCOMMAND:
4187         dev->sense[0] = SENSE_CR;
4188         dev->sense[3] = 0x0C;     /* Bad Command */
4189         *unitstat = CSW_UC;
4190         break;
4191     case TAPE_BSENSE_WRITEPROTECT:
4192         dev->sense[0] = SENSE_CR;
4193         dev->sense[3] = 0x0B;     /* File Protect */
4194         *unitstat = CSW_CE|CSW_DE|CSW_UC;
4195         break;
4196     case TAPE_BSENSE_LOADPTERR:
4197         dev->sense[0] = SENSE_CR;
4198         dev->sense[3] = 0x0D;     /* Backspace at Load Point */
4199         *unitstat = CSW_CE|CSW_DE|CSW_UC;
4200         break;
4201     case TAPE_BSENSE_READTM:
4202         *unitstat = CSW_CE|CSW_DE|CSW_UX;
4203         break;
4204     case TAPE_BSENSE_UNSOLICITED:
4205         *unitstat = CSW_CE|CSW_DE;
4206         break;
4207     case TAPE_BSENSE_STATUSONLY:
4208         *unitstat = CSW_CE|CSW_DE;
4209         break;
4210     } // end switch(ERCode)
4211 
4212     if (TAPE_BSENSE_STATUSONLY == ERCode)
4213         return; // (mission accomplished)
4214 
4215     /* Fill in the common sense information */
4216 
4217     if (strcmp(dev->filename,TAPE_UNLOADED) == 0
4218         || !dev->tmh->tapeloaded(dev,NULL,0))
4219     {
4220         dev->sense[0] |= SENSE_IR;
4221         dev->sense[1] |= SENSE1_TAPE_FP;
4222         dev->sense[1] &= ~SENSE1_TAPE_TUA;
4223         dev->sense[1] |= SENSE1_TAPE_TUB;
4224     }
4225     else
4226     {
4227         dev->sense[0] &= ~SENSE_IR;
4228         dev->sense[1] |= IsAtLoadPoint( dev ) ? SENSE1_TAPE_LOADPT : 0;
4229         dev->sense[1] |= dev->readonly || dev->tdparms.logical_readonly ?
4230             SENSE1_TAPE_FP : 0;
4231         dev->sense[1] |= SENSE1_TAPE_TUA;
4232         dev->sense[1] &= ~SENSE1_TAPE_TUB;
4233     }
4234     if (dev->tmh->passedeot(dev))
4235     {
4236         dev->sense[4] |= 0x40;
4237     }
4238 
4239 } /* end function build_sense_Streaming */
4240 
4241 
4242 /*********************************************************************/
4243 /*********************************************************************/
4244 /**                                                                 **/
4245 /**               ((  I N C O M P L E T E  ))                       **/
4246 /**                                                                 **/
4247 /**      (experimental possible new sense handling function)        **/
4248 /**                                                                 **/
4249 /*********************************************************************/
4250 /*********************************************************************/
4251 
4252 #if 0 //  ZZ FIXME:  To Do...
4253 
4254 /*-------------------------------------------------------------------*/
4255 /*                 Error Recovery Action codes                       */
4256 /*-------------------------------------------------------------------*/
4257 /*
4258     Even though ERA codes are, technically, only applicable for
4259     model 3480/3490/3590 tape drives (the sense information that
4260     is returned for model 3480/3490/3590 tape drives include the
4261     ERA code in them), we can nonetheless still use them as an
4262     argument for our 'BuildTapeSense' function even for other
4263     model tape drives (e.g. 3420's for example). That is to say,
4264     even though model 3420's for example, don't have an ERA code
4265     anywhere in their sense information, we can still use the
4266     ERA code as an argument in our call to our 'BuildTapeSense'
4267     function without actually using it anywhere in our sense info.
4268     In such a case we would be just using it as an internal value
4269     to tell us what type of sense information to build for the
4270     model 3420, but not for any other purpose. For 3480/3490/3590
4271     model drives however, we not only use it for the same purpose
4272     (i.e. as an internal value to tell us what format of sense
4273     we need to build) but ALSO as an actual value to be placed
4274     into the actual formatted sense information itself too.
4275 */
4276 
4277 #define  TAPE_ERA_UNSOLICITED_SENSE           0x00
4278 
4279 #define  TAPE_ERA_DATA_STREAMING_NOT_OPER     0x21
4280 #define  TAPE_ERA_PATH_EQUIPMENT_CHECK        0x22
4281 #define  TAPE_ERA_READ_DATA_CHECK             0x23
4282 #define  TAPE_ERA_LOAD_DISPLAY_CHECK          0x24
4283 #define  TAPE_ERA_WRITE_DATA_CHECK            0x25
4284 #define  TAPE_ERA_READ_OPPOSITE               0x26
4285 #define  TAPE_ERA_COMMAND_REJECT              0x27
4286 #define  TAPE_ERA_WRITE_ID_MARK_CHECK         0x28
4287 #define  TAPE_ERA_FUNCTION_INCOMPATIBLE       0x29
4288 #define  TAPE_ERA_UNSOL_ENVIRONMENTAL_DATA    0x2A
4289 #define  TAPE_ERA_ENVIRONMENTAL_DATA_PRESENT  0x2B
4290 #define  TAPE_ERA_PERMANENT_EQUIPMENT_CHECK   0x2C
4291 #define  TAPE_ERA_DATA_SECURE_ERASE_FAILURE   0x2D
4292 #define  TAPE_ERA_NOT_CAPABLE_BOT_ERROR       0x2E
4293 
4294 #define  TAPE_ERA_WRITE_PROTECTED             0x30
4295 #define  TAPE_ERA_TAPE_VOID                   0x31
4296 #define  TAPE_ERA_TENSION_LOST                0x32
4297 #define  TAPE_ERA_LOAD_FAILURE                0x33
4298 #define  TAPE_ERA_UNLOAD_FAILURE              0x34
4299 #define  TAPE_ERA_DRIVE_EQUIPMENT_CHECK       0x35
4300 #define  TAPE_ERA_END_OF_DATA                 0x36
4301 #define  TAPE_ERA_TAPE_LENGTH_ERROR           0x37
4302 #define  TAPE_ERA_PHYSICAL_END_OF_TAPE        0x38
4303 #define  TAPE_ERA_BACKWARD_AT_BOT             0x39
4304 #define  TAPE_ERA_DRIVE_SWITCHED_NOT_READY    0x3A
4305 #define  TAPE_ERA_MANUAL_REWIND_OR_UNLOAD     0x3B
4306 
4307 #define  TAPE_ERA_OVERRUN                     0x40
4308 #define  TAPE_ERA_RECORD_SEQUENCE_ERROR       0x41
4309 #define  TAPE_ERA_DEGRADED_MODE               0x42
4310 #define  TAPE_ERA_DRIVE_NOT_READY             0x43
4311 #define  TAPE_ERA_LOCATE_BLOCK_FAILED         0x44
4312 #define  TAPE_ERA_DRIVE_ASSIGNED_ELSEWHERE    0x45
4313 #define  TAPE_ERA_DRIVE_NOT_ONLINE            0x46
4314 #define  TAPE_ERA_VOLUME_FENCED               0x47
4315 #define  TAPE_ERA_UNSOL_INFORMATIONAL_DATA    0x48
4316 #define  TAPE_ERA_BUS_OUT_CHECK               0x49
4317 #define  TAPE_ERA_CONTROL_UNIT_ERP_FAILURE    0x4A
4318 #define  TAPE_ERA_CU_AND_DRIVE_INCOMPATIBLE   0x4B
4319 #define  TAPE_ERA_RECOVERED_CHECKONE_FAILED   0x4C
4320 #define  TAPE_ERA_RESETTING_EVENT             0x4D
4321 #define  TAPE_ERA_MAX_BLOCKSIZE_EXCEEDED      0x4E
4322 
4323 #define  TAPE_ERA_BUFFERED_LOG_OVERFLOW       0x50
4324 #define  TAPE_ERA_BUFFERED_LOG_END_OF_VOLUME  0x51
4325 #define  TAPE_ERA_END_OF_VOLUME_COMPLETE      0x52
4326 #define  TAPE_ERA_GLOBAL_COMMAND_INTERCEPT    0x53
4327 #define  TAPE_ERA_TEMP_CHANN_INTFACE_ERROR    0x54
4328 #define  TAPE_ERA_PERM_CHANN_INTFACE_ERROR    0x55
4329 #define  TAPE_ERA_CHANN_PROTOCOL_ERROR        0x56
4330 #define  TAPE_ERA_GLOBAL_STATUS_INTERCEPT     0x57
4331 #define  TAPE_ERA_TAPE_LENGTH_INCOMPATIBLE    0x5A
4332 #define  TAPE_ERA_FORMAT_3480_XF_INCOMPAT     0x5B
4333 #define  TAPE_ERA_FORMAT_3480_2_XF_INCOMPAT   0x5C
4334 #define  TAPE_ERA_TAPE_LENGTH_VIOLATION       0x5D
4335 #define  TAPE_ERA_COMPACT_ALGORITHM_INCOMPAT  0x5E
4336 
4337 // Sense byte 0
4338 
4339 #define  TAPE_SNS0_CMDREJ     0x80          // Command Reject
4340 #define  TAPE_SNS0_INTVREQ    0x40          // Intervention Required
4341 #define  TAPE_SNS0_BUSCHK     0x20          // Bus-out Check
4342 #define  TAPE_SNS0_EQUIPCHK   0x10          // Equipment Check
4343 #define  TAPE_SNS0_DATACHK    0x08          // Data check
4344 #define  TAPE_SNS0_OVERRUN    0x04          // Overrun
4345 #define  TAPE_SNS0_DEFUNITCK  0x02          // Deferred Unit Check
4346 #define  TAPE_SNS0_ASSIGNED   0x01          // Assigned Elsewhere
4347 
4348 // Sense byte 1
4349 
4350 #define  TAPE_SNS1_LOCFAIL    0x80          // Locate Failure
4351 #define  TAPE_SNS1_ONLINE     0x40          // Drive Online to CU
4352 #define  TAPE_SNS1_RSRVD      0x20          // Reserved
4353 #define  TAPE_SNS1_RCDSEQ     0x10          // Record Sequence Error
4354 #define  TAPE_SNS1_BOT        0x08          // Beginning of Tape
4355 #define  TAPE_SNS1_WRTMODE    0x04          // Write Mode
4356 #define  TAPE_SNS1_FILEPROT   0x02          // Write Protect
4357 #define  TAPE_SNS1_NOTCAPBL   0x01          // Not Capable
4358 
4359 // Sense byte 2
4360 
4361 //efine  TAPE_SNS2_XXXXXXX    0x80-0x04     // (not defined)
4362 #define  TAPE_SNS2_SYNCMODE   0x02          // Tape Synchronous Mode
4363 #define  TAPE_SNS2_POSITION   0x01          // Tape Positioning
4364 
4365 #define  BUILD_TAPE_SENSE( _era )   BuildTapeSense( _era, dev, unitstat, code )
4366 //    BUILD_TAPE_SENSE( TAPE_ERA_COMMAND_REJECT );
4367 
4368 
4369 /*-------------------------------------------------------------------*/
4370 /*                        BuildTapeSense                             */
4371 /*-------------------------------------------------------------------*/
4372 /* Build appropriate sense information based on passed ERA code...   */
4373 /*-------------------------------------------------------------------*/
4374 
4375 void BuildTapeSense( BYTE era, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode )
4376 {
4377     BYTE fmt;
4378 
4379     // ---------------- Determine Sense Format -----------------------
4380 
4381     switch (era)
4382     {
4383     default:
4384 
4385         fmt = 0x20;
4386         break;
4387 
4388     case TAPE_ERA_UNSOL_ENVIRONMENTAL_DATA:     // ERA 2A
4389 
4390         fmt = 0x21;
4391         break;
4392 
4393     case TAPE_ERA_ENVIRONMENTAL_DATA_PRESENT:   // ERA 2B
4394 
4395         if (dev->devchar[8] & 0x01)             // Extended Buffered Log support enabled?
4396             fmt = 0x30;                         // Yes, IDRC; 64-bytes of sense data
4397         else
4398             fmt = 0x21;                         // No, no IDRC; only 32-bytes of sense
4399         break;
4400 
4401     case TAPE_ERA_UNSOL_INFORMATIONAL_DATA:     // ERA 48
4402 
4403         if (dev->forced_logging)                // Forced Error Logging enabled?
4404             fmt = 0x19;                         // Yes, Forced Error Logging sense
4405         else
4406             fmt = 0x20;                         // No, Normal Informational sense
4407         break;
4408 
4409     case TAPE_ERA_END_OF_VOLUME_COMPLETE:       // ERA 52
4410 
4411         fmt = 0x22;
4412         break;
4413 
4414     case TAPE_ERA_FORMAT_3480_2_XF_INCOMPAT:    // ERA 5C
4415 
4416         fmt = 0x24;
4417         break;
4418 
4419     } // End switch (era)
4420 
4421     // ---------------- Build Sense Format -----------------------
4422 
4423     switch (fmt)
4424     {
4425     case 0x19:
4426         break;
4427 
4428     default:
4429     case 0x20:
4430         break;
4431 
4432     case 0x21:
4433         break;
4434 
4435     case 0x22:
4436         break;
4437 
4438     case 0x24:
4439         break;
4440 
4441     case 0x30:
4442         break;
4443 
4444     } // End switch (fmt)
4445 
4446 } /* end function BuildTapeSense */
4447 
4448 
4449 #endif //  ZZ FIXME:  To Do...
4450 
4451 
4452 /*********************************************************************/
4453 /*********************************************************************/
4454