1 /* VMD250.C     (c) Copyright Harold Grovesteen, 2009                */
2 /*              z/VM 5.4 DIAGNOSE code X'250'                        */
3 
4 /*-------------------------------------------------------------------*/
5 /* This module implements DIAGNOSE code X'250'                       */
6 /* described in SC24-6084 z/VM 5.4 CP Programming Services.          */
7 /*-------------------------------------------------------------------*/
8 /* Hercules extends the use to System/370 with 4K pages and 2K pages */
9 /* with recommended constraints                                      */
10 
11 /* Unconditional log messages generated */
12 /* HHCVM006E - Could not allocate storage for Block I/O environment   */
13 /* HHCVM009E - Invalid list processor status code returned            */
14 /* HHCVM010E - Error creating asynchronous thread                     */
15 /* HHCVM011E - Could not allocate storage for asynchronous I/O request*/
16 
17 /* Conditional log messages when device tracing is enabled */
18 /* HHCVM007I - BLKTAB information used when device tracing is enabled */
19 /* HHCVM008I - Established environment when device tracing is enabled */
20 /* HHCVM012I - Block I/O owns device                                  */
21 /* HHCVM013I - Block I/O returned device                              */
22 /* HHCVM014I - BIOE status returned                                   */
23 /* HHCVM015I - List processor parameters                              */
24 /* HHCVM016I - BIOE operation being performed                         */
25 /* HHCVM017I - List processor status code                             */
26 /* HHCVM018I - Read/Write I/O operation                               */
27 /* HHCVM019I - Syncronous or asynchronous request information         */
28 /* HHCVM020I - Address checking results                               */
29 /* HHCVM021I - Device driver results                                  */
30 /* HHCVM022I - Block I/O environment removed                          */
31 /* HHCVM023I - Triggered Block I/O interrupt                          */
32 
33 
34 /* The following structure exists between the different functions     */
35 /*                                                                    */
36 /* From diagnose.c                                                    */
37 /*                                                                    */
38 /* AD:vm_blockio                                                      */
39 /*    |                                                               */
40 /*   INIT:                                                            */
41 /*    +---> d250_init32---+                                           */
42 /*    |                   +---> d250_init                             */
43 /*    +---> d250_init64---+                                           */
44 /*    |                                                               */
45 /*   IOREQ:                                                           */
46 /*    +-> AD:d250_iorq32--+---SYNC----> d250_list32--+                */
47 /*    |                   V                   ^      |                */
48 /*    |               ASYNC Thread            |      |    d250_read   */
49 /*    |                   +-> AD:d250_async32-+      +--> d250_write  */
50 /*    |                       d250_bio_interrupt     |    (calls      */
51 /*    |                                              |    drivers)    */
52 /*    +-> AD:d250_iorq64--+----SYNC---> d250_list64--+                */
53 /*    |                   V                   ^                       */
54 /*    |               ASYNC Thread            |                       */
55 /*    |                   +-> AD:d250_async64-+                       */
56 /*    |                       d250_bio_interrupt                      */
57 /*   REMOVE:                                                          */
58 /*    +---> d250_remove                                               */
59 /*                                                                    */
60 /*  Function         ARCH_DEP   On CPU   On Async    Owns             */
61 /*                              thread    thread     device           */
62 /*                                                                    */
63 /*  vm_blockio          Yes      Yes        No         No             */
64 /*  d250_init32/64      No       Yes        No         No             */
65 /*  d250_init           No       Yes        No         No             */
66 /*  d250_iorq32/64      Yes      Yes        No         No             */
67 /*  d250_async32/64     Yes      No         Yes        No             */
68 /*  d250_list32/64      Yes      Yes        Yes       Yes             */
69 /*  d250_bio_interrup   No       No         Yes       N/A             */
70 /*  d250_read           No       Yes        Yes       Yes             */
71 /*  d250_write          No       Yes        Yes       Yes             */
72 /*  d250_remove         No       Yes        No         No             */
73 /*  d250_addrck         Yes      Yes        Yes        No             */
74 
75 #include "hstdinc.h"
76 
77 #if !defined(_HENGINE_DLL_)
78 #define _HENGINE_DLL_
79 #endif /*_HENGINE_DLL_*/
80 
81 #if !defined(_VMD250_C_)
82 #define _VMD250_C_
83 #endif /* !defined(_VMD250_C_) */
84 
85 #include "hercules.h"
86 #include "opcode.h"
87 #include "inline.h"
88 #include "vmd250.h"
89 
90 #if defined(FEATURE_VM_BLOCKIO)
91 
92 #if !defined(_VMD250_C)
93 #define _VMD250_C
94 
95 #if !defined(_VMD250_H)
96 #define _VMD250_H
97 /*-------------------------------------------------------------------*/
98 /* Internal macro definitions                                        */
99 /*-------------------------------------------------------------------*/
100 
101 /*-------------------------------------------------------------------*/
102 /* Block I/O Function, Condition and Return Codes                    */
103 /*-------------------------------------------------------------------*/
104 
105 /* Function Codes (Ry)                                               */
106 #define INIT   0x00              /* Initialize Block I/O environment */
107 #define IOREQ  0x01              /* Perform I/O request              */
108 #define REMOVE 0x02              /* Remove the Block I/O environment */
109 
110 /* Condition Codes (cc)                                              */
111 #define CC_SUCCESS 0             /* Function completed successfully  */
112 #define CC_PARTIAL 1             /* Function partially completed     */
113 #define CC_FAILED  2             /* Function failed                  */
114 /* Note: cc 3 is not returned by Block I/O                           */
115 
116 /* General Return Codes (Rx+1)- All functions                        */
117 #define RC_SUCCESS   0           /* Function competed successfully   */
118 #define RC_NODEV    16           /* Device not defined               */
119 #define RC_STATERR  28           /* Env. state error                 */
120 #define RC_ERROR   255           /* Irrecoverable error              */
121 /* Note: RC_ERROR is used to indicate an internal Hercules error     */
122 /*       and it should be accompanied by a log message               */
123 
124 /* INIT Return Codes (Rx+1)                                          */
125 #define RC_READONLY  4           /* Successful for R/O device        */
126 #define RC_NOSUPP   20           /* Not a supported DASD device      */
127 #define RC_BADBLKSZ 24           /* Unsupported block size           */
128 
129 /* IOREQ Return Codes (Rx+1)                                         */
130 #define RC_ASYNC     8           /* Asynchronous request initiated   */
131 #define RC_SYN_PART 12  /* Synchronous request partially successful  */
132 #define RC_CNT_ERR  36  /* Block count not between 1 and 256         */
133 #define RC_ALL_BAD  40  /* All blocks unsuccessful                   */
134 #define RC_REM_PART 44  /* Remove aborted request - should not occur */
135 #define RC_EXI_PART 48  /* Exigent aborted req. - should not occur   */
136 /* Note: Because the DEVBLK lock is held RC_REM_PART and RC_EXI_PART */
137 /*       should not occur in Hercules                                */
138 
139 
140 /*-------------------------------------------------------------------*/
141 /* Block I/O Parameter List Formats (BIOPL)                          */
142 /*-------------------------------------------------------------------*/
143 #define INIT32R1_LEN 21
144 #define INIT32R2_LEN 24
145 typedef struct _BIOPL_INIT32 {
146         HWORD   devnum;              /* Device number                */
147         BYTE    flaga;               /* Addressing mode flag         */
148         BYTE    resv1[INIT32R1_LEN]; /* reserved - must be zeros     */
149         FWORD   blksize;             /* Block size                   */
150         FWORD   offset;              /* Physical block 1 offset      */
151         FWORD   startblk;            /* First physical block number  */
152         FWORD   endblk;              /* Last physical block number   */
153         BYTE    resv2[INIT32R2_LEN]; /* reserved - must be zeros     */
154     } BIOPL_INIT32;
155 
156 #define INIT64R1_LEN 21
157 #define INIT64R2_LEN 4
158 #define INIT64R3_LEN 8
159 typedef struct _BIOPL_INIT64 {
160         HWORD   devnum;              /* Device number                */
161         BYTE    flaga;               /* Addressing mode flag         */
162         BYTE    resv1[INIT64R1_LEN]; /* reserved - must be zeros     */
163         FWORD   blksize;             /* Block size                   */
164         BYTE    resv2[INIT64R2_LEN]; /* Physical block 1 offset      */
165         DBLWRD  offset;              /* Physical block 1 offset      */
166         DBLWRD  startblk;            /* First physical block number  */
167         DBLWRD  endblk;              /* Last physical block number   */
168         BYTE    resv3[INIT64R3_LEN]; /* reserved - must be zeros     */
169     } BIOPL_INIT64;
170 
171 #define IORQ32R1_LEN 21
172 #define IORQ32R2_LEN 2
173 #define IORQ32R3_LEN 20
174 typedef struct _BIOPL_IORQ32 {
175         HWORD   devnum;              /* Device number                */
176         BYTE    flaga;               /* Addressing mode flag         */
177         BYTE    resv1[IORQ32R1_LEN]; /* reserved - must be zeros     */
178         BYTE    key;                 /* Storage key                  */
179         BYTE    flags;               /* I/O request flags            */
180         BYTE    resv2[IORQ32R2_LEN]; /* reserved - must be zeros     */
181         FWORD   blkcount;            /* Block count of request       */
182         FWORD   bioealet;            /* BIOE list ALET               */
183         FWORD   bioeladr;            /* BIOE list address            */
184         FWORD   intparm;             /* Interrupt parameter          */
185         BYTE    resv3[IORQ32R3_LEN]; /* reserved - must be zeros     */
186     } BIOPL_IORQ32;
187 
188 #define IORQ64R1_LEN 21
189 #define IORQ64R2_LEN 2
190 #define IORQ64R3_LEN 4
191 #define IORQ64R4_LEN 8
192 typedef struct _BIOPL_IORQ64 {
193         HWORD   devnum;              /* Device number                */
194         BYTE    flaga;               /* Addressing mode flag         */
195         BYTE    resv1[IORQ64R1_LEN]; /* reserved - must be zeros     */
196         BYTE    key;                 /* Storage key                  */
197         BYTE    flags;               /* I/O request flags            */
198         BYTE    resv2[IORQ64R2_LEN]; /* reserved - must be zeros     */
199         FWORD   blkcount;            /* Block count of request       */
200         FWORD   bioealet;            /* BIOE list ALET               */
201         BYTE    resv3[IORQ64R3_LEN]; /* reserved - must be zeros     */
202         DBLWRD  intparm;             /* Interrupt parameter          */
203         DBLWRD  bioeladr;            /* BIOE list address            */
204         BYTE    resv4[IORQ64R4_LEN]; /* reserved - must be zeros     */
205     } BIOPL_IORQ64;
206 
207 #define REMOVER1_LEN 62
208 typedef struct _BIOPL_REMOVE {
209         HWORD   devnum;              /* Device number                */
210         BYTE    resv1[REMOVER1_LEN]; /* reserved - must be zeros     */
211     } BIOPL_REMOVE;
212 
213 typedef struct _BIOPL {
214         HWORD devnum;                /* Device number                */
215         BYTE  flaga;                 /* Addressing mode flag         */
216         BYTE resv1[61];              /* Additional Parameters        */
217     } BIOPL;
218 
219 /* BIOPL flaga field related values                                  */
220 #define BIOPL_FLAGARSV 0x7F         /* Reserved bits must be zero    */
221 #define BIOPL_FLAGAMSK 0x80         /* Addressing flag               */
222 #define BIOPL_32BIT    0x00         /* 32-bit BIOPL/BIOE Formats     */
223 #define BIOPL_64BIT    0x80         /* 64-bit BIOPL/BIOE Formats     */
224 
225 /* BIOPL flags field related values                                  */
226 #define BIOPL_FLAGSRSV 0xFC         /* Reserved bits must be zero    */
227 #define BIOPL_ASYNC    0x02         /* Asynchronous request          */
228 #define BIOPL_CACHE    0x01         /* Not used - z/VM specific      */
229 
230 /* BIOPL key field values                                            */
231 #define BIOPL_KEYRSV   0x0F         /* Reserved bits must be zero    */
232 
233 /*-------------------------------------------------------------------*/
234 /* Block I/O Entry Formats (BIOE)                                    */
235 /*-------------------------------------------------------------------*/
236 
237 typedef struct _BIOE32 {
238         BYTE    type;               /* Type of I/O request           */
239         BYTE    status;             /* Status of I/O request         */
240         BYTE    resv1[2];           /* reserved - must be zeros      */
241         FWORD   blknum;             /* Requested block number        */
242         FWORD   bufalet;            /* Data buffer ALET              */
243         FWORD   bufaddr;            /* Data buffer absolute address  */
244     } BIOE32;
245 
246 typedef struct _BIOE64 {
247         BYTE    type;               /* Type of I/O request           */
248         BYTE    status;             /* Status of I/O request         */
249         BYTE    resv1[2];           /* reserved - must be zeros      */
250         FWORD   bufalet;            /* Data buffer ALET              */
251         DBLWRD  blknum;             /* Requested block number        */
252         DBLWRD  bufaddr;            /* Data buffer absolute address  */
253     } BIOE64;
254 
255 /* BIOE type field values                                            */
256 #define BIOE_WRITE     0x01         /* Write block request type      */
257 #define BIOE_READ      0x02         /* Read block request type       */
258 
259 /* BIOE status field values                                          */
260 #define BIOE_SUCCESS   0x00     /* Request successful                */
261 #define BIOE_BADBLOCK  0x01     /* Invalid block specified           */
262 #define BIOE_ADDREXC   0x02     /* Data buffer address exception     */
263 #define BIOE_DASDRO    0x03     /* Write request to read-only device */
264 #define BIOE_CKDRECL   0x04     /* CKD record size not block size    */
265 #define BIOE_IOERROR   0x05     /* I/O error on device               */
266 #define BIOE_BADREQ    0x06     /* Request type invalid              */
267 #define BIOE_PROTEXC   0x07     /* A protection exception occurred   */
268 #define BIOE_ADRCAP    0x08     /* Not used - z/VM specific          */
269 #define BIOE_ALENEXC   0x09     /* Not used - z/VM specific          */
270 #define BIOE_ALETEXC   0x0A     /* Not used - z/VM specific          */
271 #define BIOE_NOTZERO   0x0B     /* Reserved fields not zero          */
272 #define BIOE_ABORTED   0x0C     /* Request aborted                   */
273 
274 /*-------------------------------------------------------------------*/
275 /* I/O Request Control Structures and Flags                          */
276 /*-------------------------------------------------------------------*/
277 
278 #if 0
279 #define ADDR32 0  /* 32-bit addressing fields being used  */
280 #define ADDR64 1  /* 64-bit addressing fields being used  */
281 #endif
282 
283 #define SYNC   0  /* Synchronous request being processed  */
284 #define ASYNC  1  /* Asynchronous request being processed */
285 
286 /* Synchronous or asynchronous processing status codes     */
287 #define PSC_SUCCESS 0x00  /* Successful processing         */
288 #define PSC_PARTIAL 0x01  /* Partial success               */
289 #define PSC_STGERR  0x02  /* Error on storage of BIOE      */
290 #define PSC_REMOVED 0x03  /* Block I/O environment removed */
291 
292 /* Structure passed to the asynchronous thread */
293 typedef struct _IOCTL32 {
294         /* Hercules structures involved in the request */
295         REGS   *regs;                /* CPU register structure       */
296         DEVBLK *dev;                 /* Device block                 */
297         /* External interrupt related values */
298         BYTE    subintcod;           /* Sub-interruption code        */
299         BYTE    statuscod;           /* Interruption status code     */
300         U32     intrparm;            /* 32-bit interrupt parm        */
301         /* List control structure */
302         S32     blkcount;            /* Block count                  */
303         U32     listaddr;            /* BIOE list address            */
304         BYTE    key;                 /* Storage Key                  */
305         int     goodblks;            /* Number of successful I/O's   */
306         int     badblks;             /* Number of unsuccessful I/O's */
307     } IOCTL32;
308 
309 /* Structure passed to the asynchronous thread */
310 typedef struct _IOCTL64 {
311         /* Hercules structures involved in the request */
312         REGS   *regs;                /* CPU register structure       */
313         DEVBLK *dev;                 /* Device block                 */
314         /* External interrupt related values related values */
315         BYTE    subintcod;           /* Sub-interruption code        */
316         BYTE    statuscod;           /* Interruption status code     */
317         U64     intrparm;            /* 64-bit interrupt parm        */
318         /* List control structure */
319         S64     blkcount;            /* Block count                  */
320         U64     listaddr;            /* BIOE list address            */
321         BYTE    key;                 /* Storage Key                  */
322         int     goodblks;            /* Number of successful I/O's   */
323         int     badblks;             /* Number of unsuccessful I/O's */
324     } IOCTL64;
325 
326 #endif /* !defined(_VMD250_H) */
327 
328 /*-------------------------------------------------------------------*/
329 /* Internal Architecture Independent Function Prototypes             */
330 /*-------------------------------------------------------------------*/
331 /* Initialization Functions */
332 int  d250_init32(DEVBLK *, int *, BIOPL_INIT32 *, REGS *);
333 int  d250_init64(DEVBLK *, int *, BIOPL_INIT64 *, REGS *);
334 struct VMBIOENV* d250_init(DEVBLK *, U32, S64, int *, int *);
335 
336 /* Input/Output Request Functions */
337 void d250_preserve(DEVBLK *);
338 void d250_restore(DEVBLK *);
339 int d250_read(DEVBLK *, S64, S32, void *);
340 int d250_write(DEVBLK *, S64, S32, void *);
341 /* Note: some I/O request functions are architecture dependent */
342 
343 /* Removal Function */
344 int  d250_remove(DEVBLK *, int *, BIOPL_REMOVE *, REGS *);
345 
346 /* Asynchronous Interrupt Generation */
347 void d250_bio_interrupt(DEVBLK *, U64 intparm, BYTE status, BYTE code);
348 
349 /*-------------------------------------------------------------------*/
350 /*  Trigger Block I/O External Interrupt                             */
351 /*-------------------------------------------------------------------*/
d250_bio_interrupt(DEVBLK * dev,U64 intparm,BYTE status,BYTE subcode)352 void d250_bio_interrupt(DEVBLK *dev, U64 intparm, BYTE status, BYTE subcode)
353 {
354 
355    OBTAIN_INTLOCK(NULL);
356 
357    /* This is inspired by sclp_attn_thread function in service.c */
358    /* Make sure a service signal interrupt is not pending */
359    while(IS_IC_SERVSIG)
360    {
361        RELEASE_INTLOCK(NULL);
362        sched_yield();
363        OBTAIN_INTLOCK(NULL);
364    }
365 
366    /* Can now safely store my interrupt information */
367    sysblk.bioparm  = intparm;   /* Trigger with the interrupt parameter */
368    sysblk.biostat  = status;    /* Trigger with the status */
369    sysblk.biosubcd = subcode;   /* Trigger with the subcode */
370    sysblk.biodev   = dev;       /* Trigger for this device  */
371    sysblk.servcode = EXT_BLOCKIO_INTERRUPT;
372 
373    /* The Block I/O external interrupt is enabled by the same CR0 bit */
374    /* as are service signal interrupts.  This means the guest will    */
375    /* be interrupted when it has enabled service signals.  For this   */
376    /* reason the Block I/O is being treated like a service signal and */
377    /* handled by the service signal handling logic in external.c      */
378 
379    /* Make the "service signal" interrupt pending                     */
380    ON_IC_SERVSIG;
381    /* Wake up any waiters */
382    WAKEUP_CPUS_MASK (sysblk.waiting_mask);
383 
384    if (dev->ccwtrace)
385    {
386       logmsg (_("%4.4X:HHCVM023I Triggered Block I/O interrupt: "
387                 "code=%4.4X parm=%16.16X status=%2.2X subcode=%2.2X\n"),
388               sysblk.biodev->devnum,
389               sysblk.servcode,
390               sysblk.bioparm,
391               sysblk.biostat,
392               sysblk.biosubcd
393            );
394    }
395 
396    /* Free the interrupt lock */
397    RELEASE_INTLOCK(NULL);
398 }
399 
400 /*-------------------------------------------------------------------*/
401 /*  Initialize Environment - 32-bit Addressing                       */
402 /*-------------------------------------------------------------------*/
d250_init32(DEVBLK * dev,int * diag_rc,BIOPL_INIT32 * biopl,REGS * regs)403 int  d250_init32(DEVBLK *dev, int *diag_rc, BIOPL_INIT32 *biopl,
404                  REGS *regs)
405 {
406 BIOPL_INIT32   bioplx00;             /* Use to check reserved fields */
407 
408 /* Passed to the generic INIT function */
409 U32     blksize;                     /* Blocksize                    */
410 S32     offset;                      /* Offset                       */
411 
412 /* Returned by generic INIT function */
413 struct VMBIOENV *bioenv;            /* -->allocated environement     */
414 int     rc;                         /* return code                   */
415 int     cc;                         /* Condition code to return      */
416 
417    /* Clear the reserved BIOPL */
418    memset(&bioplx00,0x00,sizeof(BIOPL_INIT32));
419 
420    /* Make sure reserved fields are binary zeros                     */
421    if ((memcmp(&biopl->resv1,&bioplx00,INIT32R1_LEN)!=0) ||
422        (memcmp(&biopl->resv2,&bioplx00,INIT32R2_LEN)!=0))
423    {
424        ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
425    }
426 
427    /* Fetch the block size from the BIOPL */
428    FETCH_FW(blksize,&biopl->blksize);
429 
430    /* Fetch the offset from the BIOPL provided by the guest */
431    FETCH_FW(offset,&biopl->offset);
432 
433    /* Call the addressing independent initialization function */
434    bioenv=d250_init(dev, blksize, (S64)offset, &cc, &rc);
435 
436    if (bioenv)
437    {
438       /* Save the values in the BIOPL for return to guest */
439       STORE_FW(&biopl->startblk,(U32)bioenv->begblk);
440       STORE_FW(&biopl->endblk,(U32)bioenv->endblk);
441       if (dev->ccwtrace)
442       {
443          logmsg ("%4.4X:HHCVM008I d250_init32 s=%i,o=%i,b=%i,e=%i\n",
444               dev->devnum,
445               blksize,
446               offset,
447               bioenv->begblk,
448               bioenv->endblk
449              );
450       }
451    }
452    *diag_rc = rc;
453    return cc;
454 } /* end function d250_init32 */
455 
456 /*-------------------------------------------------------------------*/
457 /*  Initialize Environment - 64-bit Addressing                       */
458 /*-------------------------------------------------------------------*/
d250_init64(DEVBLK * dev,int * diag_rc,BIOPL_INIT64 * biopl,REGS * regs)459 int d250_init64(DEVBLK *dev, int *diag_rc, BIOPL_INIT64 *biopl,
460                 REGS *regs)
461 {
462 BIOPL_INIT64   bioplx00;             /* Use to check reserved fields */
463 
464 /* Passed to the generic INIT function */
465 U32     blksize;                     /* Blocksize                    */
466 S64     offset;                      /* Offset                       */
467 
468 /* Returned by generic INIT function */
469 struct VMBIOENV *bioenv;             /* -->allocated environement    */
470 int     rc;                          /* return code                  */
471 int     cc;                          /* condition code               */
472 
473    /* Clear the reserved BIOPL */
474    memset(&bioplx00,0x00,sizeof(BIOPL_INIT64));
475 
476    /* Make sure reserved fields are binary zeros  */
477    if ((memcmp(&biopl->resv1,&bioplx00,INIT64R1_LEN)!=0) ||
478        (memcmp(&biopl->resv2,&bioplx00,INIT64R2_LEN)!=0) ||
479        (memcmp(&biopl->resv3,&bioplx00,INIT64R3_LEN)!=0))
480    {
481        ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
482    }
483 
484    /* Fetch the block size from the BIOPL */
485    FETCH_FW(blksize,&biopl->blksize);
486 
487    /* Fetch the offset from the BIOPL provided by the guest */
488    FETCH_DW(offset,&biopl->offset);
489 
490    bioenv=d250_init(dev, blksize, offset, &cc, &rc);
491 
492    if (bioenv)
493    {
494       /* Save the values in the BIOPL for return to guest */
495       STORE_DW(&biopl->startblk,bioenv->begblk);
496       STORE_DW(&biopl->endblk,bioenv->endblk);
497       if (dev->ccwtrace)
498       {
499          logmsg ("%4.4X:HHCVM008I d250_init64 s=%i,o=%lli,b=%lli,e=%lli\n",
500               dev->devnum,
501               blksize,
502               offset,
503               bioenv->begblk,
504               bioenv->endblk
505              );
506       }
507    }
508    *diag_rc = rc;
509    return cc;
510 } /* end function d250_init64 */
511 
512 /*-------------------------------------------------------------------*/
513 /*  Initialize Environment - Addressing Independent                  */
514 /*-------------------------------------------------------------------*/
d250_init(DEVBLK * dev,U32 blksize,S64 offset,int * cc,int * rc)515 struct VMBIOENV* d250_init(DEVBLK *dev, U32 blksize, S64 offset,
516                     int *cc, int *rc )
517 {
518 int      isCKD;         /* Flag for CKD device                       */
519 int      isRO;          /* Flag for readonly device                  */
520 int      seccyl;/* Number of sectors/block or records/track for dev. */
521 int      numblks;       /* Number of blocks on the device            */
522 S32      begblk;        /* Starting block number                     */
523 S32      endblk;        /* Ending block number                       */
524 BLKTAB  *blktab;     /* Pointer to device std block-to-physical info */
525 /* Established environement                                          */
526 struct VMBIOENV *bioenv;  /* -->allocated environement               */
527 
528    /* Return with an error if the device does not exist */
529    if (!dev)
530    {
531       *rc = RC_NODEV;  /* Set the return code for no device */
532       *cc = CC_FAILED; /* Indicate the function failed      */
533       return 0;
534    }
535 
536    /* Look up the block-to-phyical mapping information */
537    blktab=dasd_lookup(DASD_STDBLK,NULL,(U32)dev->devtype,0);
538    if (!blktab)
539    {
540        *rc = RC_NOSUPP; /* Set the return code for unsuppored device */
541        *cc = CC_FAILED; /* Indicate the function failed      */
542        return NULL;
543    }
544 
545    if (dev->ccwtrace)
546    {
547       logmsg (_("%4.4X:HHCVM007I d250_init BLKTAB: "
548                 "type=%4.4X arch=%i,512=%i,1024=%i,2048=%i,4096=%i\n"),
549               dev->devnum,
550               blktab->devt,
551               blktab->darch,
552               blktab->phys512,
553               blktab->phys1024,
554               blktab->phys2048,
555               blktab->phys4096
556              );
557    }
558 
559    /* Save the device architecture */
560    isCKD = blktab->darch;
561 
562    /* Determine if the blocksize is valid and its physical/block value */
563    switch(blksize)
564    {
565       case 4096:
566          seccyl=blktab->phys4096;
567          break;
568       case 512:
569          seccyl=blktab->phys512;
570          break;
571       case 1024:
572          seccyl=blktab->phys1024;
573          break;
574       case 2048:
575          seccyl=blktab->phys2048;
576          break;
577       default:
578          *rc = RC_BADBLKSZ;
579          *cc = CC_FAILED;
580          return NULL;
581    }
582 
583    isRO = 0;  /* Assume device is read-write */
584    if (isCKD)
585    {
586       /* Number of standard blocks is based upon number of primary */
587       /* cylinders                                                 */
588       numblks=(dev->ckdtab->cyls * dev->ckdtab->heads * seccyl);
589       if (dev->ckdrdonly)
590       {
591          isRO = 1;
592       }
593    }
594    else
595    {
596       numblks=(dev->fbanumblk*dev->fbablksiz)/blksize;
597       /* FBA devices are never read only */
598    }
599 
600    /* Establish the environment's beginning and ending block numbers */
601    /* Block numbers in the environment are relative to 1, not zero   */
602    begblk=1-offset;
603    endblk=numblks-offset;
604 
605    if (!(bioenv=(struct VMBIOENV *)malloc(sizeof(struct VMBIOENV))))
606    {
607       logmsg (_("HHCVM006E VM BLOCK I/O environment malloc failed\n"));
608       *rc = RC_ERROR;  /* Indicate an irrecoverable error occurred */
609       *cc = CC_FAILED;
610       return NULL;
611    }
612 
613    /* Set the fields in the environment structure                */
614    bioenv->dev     = dev     ; /* Set device block pointer       */
615    bioenv->blksiz  = blksize ; /* Pass the block size            */
616    bioenv->offset  = offset  ; /* Pass the offset                */
617    bioenv->begblk  = begblk  ; /* Save the starting block        */
618    bioenv->endblk  = endblk  ; /* Save the ending block          */
619    bioenv->isCKD   = isCKD   ; /* Save the device type           */
620    bioenv->isRO    = isRO    ; /* Save the read/write status     */
621    bioenv->blkphys = seccyl  ; /* Save the block-to-phys mapping */
622 
623    /* Attach the environment to the DEVBLK */
624    /* Lock the DEVBLK in case another thread wants it */
625    obtain_lock (&dev->lock);
626    if (dev->vmd250env == NULL)
627    {
628        /* If an environment does not exist, establish it */
629        dev->vmd250env = bioenv ;
630        /* No need to hold the device lock now, environment is set */
631        release_lock (&dev->lock);
632 
633        /* Set the appropriate successful return and condition codes */
634        if (isRO)
635        {
636            *rc = RC_READONLY ; /* Set READ ONLY success return code */
637        }
638        else
639        {
640            *rc = RC_SUCCESS  ; /* Set the READ/WRITE success return code */
641        }
642        *cc = CC_SUCCESS ; /* Set that the function has succeeded */
643    }
644    else
645    {
646        /* If an environment already exists, this is an error:    */
647        /*   1. Release the device block                          */
648        /*   2. free the environment just built                   */
649        /*   3. Reset the retuned environment to NULL and         */
650        /*   4. Reset return and condition codes to reflect       */
651        /*      the error condition                               */
652        release_lock (&dev->lock);
653        free(bioenv);
654        bioenv = NULL ;
655        *rc = RC_STATERR;
656        *cc = CC_FAILED;
657    }
658 
659    /* Return the bioenv so that the start and end blocks can     */
660    /* be returned to the guest in the addressing mode specific   */
661    /* BIOPL format                                               */
662    return bioenv ;
663 
664 } /* end function d250_init */
665 
666 /*-------------------------------------------------------------------*/
667 /* Preserve Device Status                                            */
668 /*-------------------------------------------------------------------*/
669 /* WARNING: This function must NOT be called with the device lock held */
670 
671 /* From the perspective of Hercules, Block I/O is occurring at the */
672 /* level of the device, NOT the channel or channel subsystem.  For */
673 /* the channel subsytem or other CPU's, the device is made to      */
674 /* appear busy and reserved if shared.                             */
675 /*                                                                 */
676 /* It is possible for block I/O to take control between the        */
677 /* completion of a CCW chain and the presentation by the device of */
678 /* related sense information.  The device related sense information*/
679 /* is therefore stored in the Block I/O environment and restored   */
680 /* upon completion.  This also allows the device drivers to set    */
681 /* sense information during Block I/O operations, which they do.   */
682 /* A pointer is used by the device drivers for unit status, so     */
683 /* this can be redirected to a Block I/O location.                 */
684 /*                                                                 */
685 /* A cleaner but more intrusive change would be to have the        */
686 /* the drivers use a pointer for where sense is stored rather than */
687 /* assume the device block.  This is deferred for a possible future*/
688 /* enhancement.                                                    */
d250_preserve(DEVBLK * dev)689 void d250_preserve(DEVBLK *dev)
690 {
691     /* Note: this logic comes from the beginning of */
692     /* channel.c ARCH_DEP(execute_ccw_chain)        */
693     obtain_lock(&dev->lock);
694     if ( dev->shared )
695     {
696         while (dev->ioactive != DEV_SYS_NONE
697             && dev->ioactive != DEV_SYS_LOCAL)
698         {
699             dev->iowaiters++;
700             wait_condition(&dev->iocond, &dev->lock);
701             dev->iowaiters--;
702         }
703         dev->ioactive = DEV_SYS_LOCAL;
704     }
705     else
706     {
707         dev->ioactive = DEV_SYS_LOCAL;
708     }
709     dev->busy = 1;
710     dev->startpending = 0;
711     if (dev->sns_pending)
712     {
713        /* Save the pending sense */
714        memcpy(&dev->vmd250env->sense,&dev->sense,sizeof(dev->sense));
715        if (dev->ccwtrace)
716        {  logmsg(_("%4.4X:HHCVM012I d250_preserve pending sense preserved\n"),
717               dev->devnum);
718        }
719     }
720 
721     /* Both fbadasd.c and ckddasd.c set the local reserved flag before  */
722     /* calling the shared device client                                 */
723     dev->reserved = 1;
724     if (dev->hnd->reserve)
725     {
726        release_lock(&dev->lock);
727        (dev->hnd->reserve)(dev);
728     }
729     else
730     {
731        release_lock(&dev->lock);
732     }
733 }
734 
735 /*-------------------------------------------------------------------*/
736 /* Restore Device Status                                             */
737 /*-------------------------------------------------------------------*/
738 /* WARNING: This function MUST not be called with the device lock held */
d250_restore(DEVBLK * dev)739 void d250_restore(DEVBLK *dev)
740 {
741     obtain_lock(&dev->lock);
742     if (dev->hnd->release)
743     {
744        release_lock(&dev->lock);
745        (dev->hnd->release)(dev);
746        obtain_lock(&dev->lock);
747     }
748     /* Both fbadasd.c and ckddasd.c reset the local reserved flag     */
749     /* after calling the shared device client                         */
750     dev->reserved = 0;
751     if (dev->sns_pending)
752     {
753        /* Restore the pending sense */
754        memcpy(&dev->sense,&dev->vmd250env->sense,sizeof(dev->sense));
755        if (dev->ccwtrace)
756        {  logmsg (_("%4.4X:HHCVM013I d250_restore pending sense restored\n"),
757               dev->devnum);
758        }
759     }
760     dev->ioactive = DEV_SYS_NONE;
761     dev->busy = 0;
762     release_lock(&dev->lock);
763 }
764 
765 /*-------------------------------------------------------------------*/
766 /*  Environment Remove - Any Addressing                              */
767 /*-------------------------------------------------------------------*/
d250_remove(DEVBLK * dev,int * rc,BIOPL_REMOVE * biopl,REGS * regs)768 int d250_remove(DEVBLK *dev, int *rc, BIOPL_REMOVE * biopl, REGS *regs)
769 {
770 BIOPL_REMOVE bioplx00;               /* Use to check reserved fields */
771 struct VMBIOENV *bioenv;             /* -->allocated environement    */
772 int       cc;                        /* Condition code to return     */
773 
774    /* Clear the reserved BIOPL */
775    memset(&bioplx00,0x00,sizeof(BIOPL_REMOVE));
776 
777 
778    /* Make sure reserved fields are binary zeros  */
779    if (memcmp(&biopl->resv1,&bioplx00,REMOVER1_LEN)!=0)
780    {
781        ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
782    }
783 
784    /* Return with an error if the device does not exist */
785    if (!dev)
786    {
787       *rc = RC_NODEV;  /* Set the return code for no device */
788       return CC_FAILED; /* Indicate the function failed     */
789    }
790 
791    /* Attach the environment to the DEVBLK */
792    /* Lock the DEVBLK in case another CPU is trying something */
793    obtain_lock (&dev->lock);
794    bioenv=dev->vmd250env;
795    if (dev->vmd250env == NULL)
796    {
797        /* If an environment does not exist, it should be */
798        /* Return the environment state error return code */
799        /* and failed condition code                      */
800        release_lock (&dev->lock);
801        *rc = RC_STATERR;
802        cc = CC_FAILED;
803    }
804    else
805    {
806        /*   1. Restore pending sense, if any                     */
807        /*   2. Free the environment previously established       */
808        /*   3. Set the device environment pointer to NULL,       */
809        /*      telling others that the environment doesn't exist */
810        /*   4. Release the device block                          */
811        /*   5. Free the environment previously established       */
812        /*   6. Return successful return and condition codes      */
813        if (dev->sns_pending)
814        {
815            memcpy(&dev->sense,dev->vmd250env->sense,sizeof(dev->sense));
816        }
817        dev->vmd250env = NULL ;
818        /* No need to hold the device lock while freeing the environment */
819        release_lock (&dev->lock);
820        free(bioenv);
821        if (dev->ccwtrace)
822        {
823            logmsg(_("%4.4X:HHCVM022I d250_remove Block I/O environment removed\n"),
824               dev->devnum);
825        }
826        *rc = RC_SUCCESS;
827        cc = CC_SUCCESS ; /* Set that the function has succeeded */
828    }
829    return cc ;
830 } /* end function d250_remove */
831 
832 /*-------------------------------------------------------------------*/
833 /*  Device Independent Read Block                                    */
834 /*-------------------------------------------------------------------*/
d250_read(DEVBLK * dev,S64 pblknum,S32 blksize,void * buffer)835 int d250_read(DEVBLK *dev, S64 pblknum, S32 blksize, void *buffer)
836 {
837 BYTE unitstat;     /* Device unit status */
838 U16  residual;     /* Residual byte count */
839 
840 /* Note: Not called with device lock held */
841 
842     obtain_lock(&dev->lock);
843     if (dev->ccwtrace)
844     {
845        logmsg(_("%4.4X:HHCVM018I d250_read %d-byte block (rel. to 0): %d\n"),
846                 dev->devnum, blksize, pblknum);
847     }
848 
849     if (dev->vmd250env->isCKD)
850     {
851        release_lock(&dev->lock);
852        /* Do CKD I/O */
853 
854        /* CKD to be supplied */
855 
856        return BIOE_IOERROR;
857     }
858     else
859     {
860        /* Do FBA I/O */
861 
862        /* Call the I/O start exit */
863        if (dev->hnd->start) (dev->hnd->start) (dev);
864 
865        unitstat = 0;
866 
867        /* Call the FBA driver's read standard block routine */
868        fbadasd_read_block(dev, (int)pblknum, (int)blksize,
869                           dev->vmd250env->blkphys,
870                           buffer, &unitstat, &residual );
871 
872        if (dev->ccwtrace)
873        {
874           logmsg(_("%4.4X:HHCVM021I d250_read "
875                    "FBA unit status=%2.2X residual=%d\n"),
876                  dev->devnum, unitstat, residual );
877        }
878 
879        /* Call the I/O end exit */
880        if (dev->hnd->end) (dev->hnd->end) (dev);
881 
882        release_lock(&dev->lock);
883     }
884     /* If an I/O error occurred, return status of I/O Error */
885     if ( unitstat != ( CSW_CE | CSW_DE ) )
886     {
887        return BIOE_IOERROR;
888     }
889 
890     /* If there was a residual count, block size error, return status of 2 */
891     /* Note: This can only happen for CKD devices                          */
892     if ( residual != 0 )
893     {
894        return BIOE_CKDRECL;
895     }
896 
897     /* Success! return 0 status */
898     return BIOE_SUCCESS;
899 }
900 
901 /*-------------------------------------------------------------------*/
902 /*  Device Independent Write Block                                   */
903 /*-------------------------------------------------------------------*/
d250_write(DEVBLK * dev,S64 pblknum,S32 blksize,void * buffer)904 int d250_write(DEVBLK *dev, S64 pblknum, S32 blksize, void *buffer)
905 {
906 BYTE unitstat;     /* Device unit status */
907 U16  residual;     /* Residual byte count */
908 
909     obtain_lock(&dev->lock);
910     if (dev->ccwtrace)
911     {
912        logmsg(_("%4.4X:HHCVM018I d250_write %d-byte block (rel. to 0): %d\n"),
913               dev->devnum, blksize, pblknum);
914     }
915 
916     if (!dev->vmd250env)
917     {
918        release_lock(&dev->lock);
919        return BIOE_ABORTED;
920     }
921     if (dev->vmd250env->isCKD)
922     {
923         release_lock(&dev->lock);
924         /* Do CKD I/O */
925 
926         /* CKD to be supplied */
927 
928         return BIOE_IOERROR;
929     }
930     else
931     {
932        /* Do FBA I/O */
933 
934        /* Call the I/O start exit */
935        if (dev->hnd->start) (dev->hnd->start) (dev);
936 
937        unitstat = 0;
938 
939        /* Call the FBA driver's write standard block routine */
940        fbadasd_write_block(dev, (int)pblknum, (int)blksize,
941                            dev->vmd250env->blkphys,
942                            buffer, &unitstat, &residual );
943        if (dev->ccwtrace)
944        {
945           logmsg(_("%4.4X:HHCVM021I d250_write "
946                    "FBA unit status=%2.2X residual=%d\n"),
947                    dev->devnum, unitstat, residual );
948        }
949 
950        /* Call the I/O end exit */
951        if (dev->hnd->end) (dev->hnd->end) (dev);
952 
953        release_lock(&dev->lock);
954     }
955 
956     /* If an I/O error occurred, return status of 1 */
957     if ( unitstat != ( CSW_CE | CSW_DE ) )
958     {
959        return BIOE_IOERROR;
960     }
961 
962     /* If there was a residual count, block size error, return status of 2 */
963     /* Note: This can only happen for CKD devices                          */
964     if ( residual != 0 )
965     {
966        return BIOE_CKDRECL;
967     }
968 
969     /* Success! */
970     return BIOE_SUCCESS;
971 }
972 
973 #endif /*!defined(_VMD250_C)*/
974 
975 /*-------------------------------------------------------------------*/
976 /* Internal Architecture Dependent Function Prototypes               */
977 /*-------------------------------------------------------------------*/
978 /* Input/Output Request Functions */
979 int   ARCH_DEP(d250_iorq32)(DEVBLK *, int *, BIOPL_IORQ32 *, REGS *);
980 int   ARCH_DEP(d250_list32)(IOCTL32 *, int);
981 U16   ARCH_DEP(d250_addrck)(RADR, RADR, int, BYTE, REGS *);
982 
983 #if defined(FEATURE_ESAME)
984 int   ARCH_DEP(d250_iorq64)(DEVBLK *, int *, BIOPL_IORQ64 *, REGS *);
985 /* void *ARCH_DEP(d250_async64)(void *); */
986 int   ARCH_DEP(d250_list64)(IOCTL64 *, int);
987 #endif /* defined(FEATURE_ESAME) */
988 
989 /*-------------------------------------------------------------------*/
990 /* Process Standard Block I/O (Function code 0x250)                  */
991 /*-------------------------------------------------------------------*/
ARCH_DEP(vm_blockio)992 int ARCH_DEP(vm_blockio) (int r1, int r2, REGS *regs)
993 {
994 /* Guest related paramters and values                                */
995 RADR    biopaddr;                      /* BIOPL address              */
996 
997 union   parmlist{                      /* BIOPL formats that         */
998         BIOPL biopl;                   /* May be supplied by the     */
999         BIOPL_INIT32 init32;           /* guest                      */
1000         BIOPL_IORQ32 iorq32;
1001         BIOPL_REMOVE remove;
1002 #if defined(FEATURE_ESAME)
1003         BIOPL_INIT64 init64;
1004         BIOPL_IORQ64 iorq64;
1005 #endif /* defined(FEATURE_ESAME) */
1006         };
1007 union   parmlist bioplin;              /* BIOPL from/to guest        */
1008 
1009 U16     devnum;                        /* Device number              */
1010 DEVBLK *dev;                           /* --> Device block           */
1011 int     rc;                            /* return code in Rx+1        */
1012 int     cc;                            /* condition code             */
1013 
1014     rc = RC_ERROR; /* Initialize the return code to error */
1015     cc = CC_FAILED; /* Failure assumed unless otherwise successful */
1016 
1017 #if 0
1018     if (sizeof(BIOPL) != 64)
1019     {
1020             logmsg("BIOPL size not 64: %d\n",sizeof(BIOPL));
1021     }
1022     if (sizeof(BIOPL_INIT32) != 64)
1023     {
1024             logmsg("BIOPL_INIT32 size not 64: %d\n",sizeof(BIOPL_INIT32));
1025     }
1026     if (sizeof(BIOPL_INIT64) != 64)
1027     {
1028             logmsg("BIOPL_INIT64 size not 64: %d\n",sizeof(BIOPL_INIT64));
1029     }
1030     if (sizeof(BIOPL_IORQ32) != 64)
1031     {
1032             logmsg("BIOPL_IORQ32 size not 64: %d\n",sizeof(BIOPL_IORQ32));
1033     }
1034     if (sizeof(BIOPL_REMOVE) != 64)
1035     {
1036             logmsg("BIOPL_REMOVE size not 64: %d\n",sizeof(BIOPL_REMOVE));
1037     }
1038     if (sizeof(BIOPL_IORQ64) != 64)
1039     {
1040             logmsg("BIOPL_IORQ64 size not 64: %d\n",sizeof(BIOPL_IORQ64));
1041     }
1042     if (sizeof(BIOE32) != 16)
1043     {
1044             logmsg("BIOE32 size not 16: %d\n",sizeof(BIOE32));
1045     }
1046     if (sizeof(BIOE64) != 24)
1047     {
1048             logmsg("BIOE64 size not 24: %d\n",sizeof(BIOE64));
1049     }
1050 #endif
1051 
1052     /* Retrieve the BIOPL address from R1 */
1053     biopaddr = regs->GR(r1);
1054 
1055     /* Specification exception if the BIOPL is not on a doubleword boundary */
1056     if (biopaddr & 0x00000007)
1057     {
1058         ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
1059     }
1060 
1061     /* Fetch the BIOPL from guest storage */
1062     ARCH_DEP(wfetchc) (&bioplin, sizeof(bioplin)-1,
1063                        biopaddr, USE_REAL_ADDR, regs);
1064 
1065     /* Access the targeted device number from the BIOPL*/
1066     FETCH_HW(devnum,&bioplin.biopl.devnum);
1067 
1068     /* Locate the device by the number */
1069     dev = find_device_by_devnum (0,devnum);
1070     /* Device not found will be checked by the called function */
1071 
1072     switch(regs->GR_L(r2))
1073     {
1074 
1075 /*--------------------------------------------------------*/
1076 /* Initialize the Block I/O Device Environment            */
1077 /*--------------------------------------------------------*/
1078     case INIT:
1079 
1080 #if !defined(FEATURE_ESAME)
1081          /* 64-bit formats not supported for S/370 or ESA/390 */
1082          /* and bits 1-7 must be zero                         */
1083          if (bioplin.biopl.flaga != 0x00)
1084          {
1085              ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
1086          }
1087 
1088          /* Call the 32-bit addressing function */
1089          cc = d250_init32(dev,&rc,&bioplin.init32,regs);
1090 #else
1091          /* Bits 1-7 must be zero for z/Architecture */
1092          if (bioplin.biopl.flaga & BIOPL_FLAGARSV)
1093          {
1094              ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
1095          }
1096          /* Call the addressing sensitive function */
1097          if (bioplin.biopl.flaga & BIOPL_FLAGAMSK)
1098          {
1099             cc = d250_init64(dev,&rc,&bioplin.init64,regs);
1100          }
1101          else
1102          {
1103             cc = d250_init32(dev,&rc,&bioplin.init32,regs);
1104          }
1105 #endif /* !FEATURE_ESAME */
1106          break;
1107 
1108 /*--------------------------------------------------------*/
1109 /* Perform block I/O read/write requests to the device    */
1110 /*--------------------------------------------------------*/
1111     case IOREQ:
1112 
1113 #if !defined(FEATURE_ESAME)
1114          /* 64-bit formats not supported for S/370 or ESA/390 */
1115          /* and bits 1-7 must be zero                         */
1116          if (bioplin.biopl.flaga != 0x00)
1117          {
1118              ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
1119          }
1120          cc = ARCH_DEP(d250_iorq32)(dev,&rc,&bioplin.iorq32,regs);
1121 #else
1122          /* Bits 1-7 must be zero for z/Architecture */
1123          if (bioplin.biopl.flaga & BIOPL_FLAGARSV)
1124          {
1125              ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
1126          }
1127 
1128          if (bioplin.biopl.flaga & BIOPL_FLAGAMSK)
1129          {
1130             cc = ARCH_DEP(d250_iorq64)(dev,&rc,&bioplin.iorq64,regs);
1131          }
1132          else
1133          {
1134             cc = ARCH_DEP(d250_iorq32)(dev,&rc,&bioplin.iorq32,regs);
1135          }
1136 #endif /* !FEATURE_ESAME */
1137          break;
1138 
1139 /*--------------------------------------------------------*/
1140 /* Remove the Block I/O Device Environment                */
1141 /*--------------------------------------------------------*/
1142     case REMOVE:
1143          cc = d250_remove(dev,&rc,&bioplin.remove,regs);
1144          break;
1145     default:
1146          ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
1147     } /* end switch(regs->GR_L(r2)) */
1148 
1149     /* Update the BIOPL in main storage */
1150     ARCH_DEP(wstorec) (&bioplin, sizeof(bioplin)-1,
1151                        biopaddr, USE_REAL_ADDR, regs);
1152 
1153     /* Set the return code in Rx+1 */
1154     regs->GR_L((r1+1)&0xF) = rc;
1155 
1156     /* Return the condition code */
1157     return cc;
1158 
1159 } /* end function vm_blockio */
1160 
1161 /*-------------------------------------------------------------------*/
1162 /*  Asynchronous Input/Outut 32-bit Driver Thread                    */
1163 /*-------------------------------------------------------------------*/
ARCH_DEP(d250_async32)1164 static void *ARCH_DEP(d250_async32)(void *ctl)
1165 {
1166 IOCTL32 *ioctl;    /* 32-bit IO request controls    */
1167 BYTE    psc;       /* List processing status code   */
1168 
1169    /* Fetch the IO request control structure */
1170    ioctl=(IOCTL32 *)ctl;
1171 
1172    /* Call the 32-bit BIOE request processor on this async thread*/
1173    psc=ARCH_DEP(d250_list32)(ioctl, ASYNC);
1174 
1175    /* Trigger the external interrupt here */
1176 
1177    d250_bio_interrupt(ioctl->dev, ioctl->intrparm, psc, 0x03);
1178 
1179    free(ioctl);
1180    return NULL;
1181 } /* end function ARCH_DEP(d250_async32) */
1182 
1183 /*-------------------------------------------------------------------*/
1184 /*  Input/Output Request - 32-bit Addressing                         */
1185 /*-------------------------------------------------------------------*/
ARCH_DEP(d250_iorq32)1186 int ARCH_DEP(d250_iorq32)(DEVBLK *dev, int *rc, BIOPL_IORQ32 *biopl,
1187                 REGS *regs)
1188 {
1189 BIOPL_IORQ32   bioplx00;  /* Used to check reserved fields */
1190 IOCTL32 ioctl;            /* Request information */
1191 BYTE    psc;              /* List processing status code */
1192 
1193 /* Asynchronous request related fields */
1194 TID     tid;         /* Asynchronous thread ID */
1195 char    tname[32];   /* Thread name */
1196 IOCTL32 *asyncp;     /* Pointer to async thread's storage */
1197 
1198    /* Clear the reserved BIOPL */
1199    memset(&bioplx00,0x00,sizeof(BIOPL_IORQ32));
1200 
1201    /* Make sure reserved fields and bits are binary zeros  */
1202    if ((memcmp(&biopl->resv1,&bioplx00,IORQ32R1_LEN)!=0) ||
1203        (memcmp(&biopl->resv2,&bioplx00,IORQ32R2_LEN)!=0) ||
1204        (memcmp(&biopl->resv3,&bioplx00,IORQ32R3_LEN)!=0) ||
1205        (biopl->flags & BIOPL_FLAGSRSV) ||
1206        (biopl->key & BIOPL_KEYRSV)
1207       )
1208    {
1209        ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
1210    }
1211 
1212    /* Return with an error return code if the device does not exist */
1213    if (!dev)
1214    {
1215       *rc = RC_NODEV;  /* Set the return code for no device */
1216       return CC_FAILED; /* Indicate the function failed     */
1217    }
1218 
1219    /* If no environment, return with an error */
1220    if (!(dev->vmd250env))
1221    {
1222       *rc = RC_STATERR;
1223       return CC_FAILED;
1224    }
1225 
1226    /* Fetch the block count from the BIOPL */
1227    FETCH_FW(ioctl.blkcount,&biopl->blkcount);
1228 
1229    /* Block count must be between 1 and 256, inclusive */
1230    if ((ioctl.blkcount<1) || (ioctl.blkcount>256))
1231    {
1232        *rc = RC_CNT_ERR;
1233        return CC_FAILED;
1234    }
1235 
1236    /* Fetch the address of the BIO entry list from the BIOPL */
1237    FETCH_FW(ioctl.listaddr,&biopl->bioeladr);
1238 
1239    /* Extract the storage key from the BIOPL */
1240    ioctl.key=biopl->key;
1241 
1242    /* Set the structures that are involved in this request */
1243    ioctl.dev = dev;
1244    ioctl.regs = regs;
1245 
1246    /* Set I/O success/failure counts to zero */
1247    ioctl.goodblks = 0;
1248    ioctl.badblks = 0;
1249 
1250    if (biopl->flags & BIOPL_ASYNC)
1251    {
1252        /* Build the request structure */
1253 
1254        /* Extract the 32-bit interrupt parameter from the BIOPL */
1255        FETCH_FW(ioctl.intrparm,biopl->intparm);
1256 
1257        if (dev->ccwtrace)
1258        {
1259           logmsg(_("%4.4X:HHCVM019I ASYNC BIOEL=%8.8X, "
1260                    "Entries=%d, Key=%2.2X, Intp=%8.8X\n"),
1261                    dev->devnum,
1262                    ioctl.listaddr,
1263                    ioctl.blkcount,
1264                    ioctl.key,
1265                    ioctl.intrparm);
1266        }
1267 
1268        /* Set the default status code to an aborted list */
1269        /* Note: This should be set correctly from the returned PSC */
1270        ioctl.statuscod = PSC_STGERR;
1271 
1272        /* Get the storage for the thread's parameters */
1273        if (!(asyncp=(IOCTL32 *)malloc(sizeof(IOCTL32))))
1274        {
1275           logmsg (_("HHCVM011E VM BLOCK I/O request malloc failed\n"));
1276           *rc = RC_ERROR;
1277           return CC_FAILED;
1278        }
1279 
1280        /* Copy the thread's parameters to its own storage */
1281        memcpy(asyncp,&ioctl,sizeof(IOCTL32));
1282 
1283        /* Launch the asynchronous request on a separate thread */
1284        snprintf(tname,sizeof(tname),"d250_async %4.4X",dev->devnum);
1285        tname[sizeof(tname)-1]=0;
1286        if ( create_thread (&tid, DETACHED, ARCH_DEP(d250_async32),
1287                asyncp, tname)
1288           )
1289        {
1290           logmsg (_("%4.4X:HHCVM010E Block I/O create_thread error: %s"),
1291                   dev->devnum, strerror(errno));
1292           release_lock (&dev->lock);
1293           *rc = RC_ERROR;
1294           return CC_FAILED;
1295        }
1296        /* Launched the async request successfully */
1297        *rc = RC_ASYNC;
1298        return CC_SUCCESS;
1299    }
1300    else
1301    {
1302        /* Perform the I/O request synchronously on this thread */
1303        /* Call the 32-bit BIOE request processor */
1304        if (dev->ccwtrace)
1305        {
1306           logmsg(_("%4.4X:HHCVM019I d250_iorq32 SYNC BIOEL=%8.8X, "
1307                    "Entries=%d, Key=%2.2X\n"),
1308                    dev->devnum,
1309                    ioctl.listaddr,
1310                    ioctl.blkcount,
1311                    ioctl.key);
1312        }
1313 
1314        psc=ARCH_DEP(d250_list32)(&ioctl, SYNC);
1315 
1316        if (dev->ccwtrace)
1317        {
1318           logmsg(_("%4.4X:HHCVM017I d250_iorq32 "
1319                     "PSC=%d, succeeded=%d, failed=%d\n"),
1320                    dev->devnum,psc,ioctl.goodblks,ioctl.badblks);
1321        }
1322 
1323    }
1324 
1325    /* Processor status used to determine return and condition codes */
1326    switch(psc)
1327    {
1328       case PSC_SUCCESS:
1329          *rc = RC_SUCCESS;
1330          return CC_SUCCESS;
1331       case PSC_PARTIAL:
1332          if (ioctl.goodblks == 0)
1333          {
1334             *rc = RC_ALL_BAD;
1335             return CC_FAILED;
1336          }
1337          else
1338          {
1339             *rc = RC_SYN_PART;
1340             return CC_PARTIAL;
1341          }
1342       case PSC_REMOVED:
1343          *rc = RC_REM_PART;
1344          return CC_PARTIAL;
1345       default:
1346          logmsg (_("HHCVM009E d250_list32 error: PSC=%i\n"),
1347                  psc);
1348          *rc = RC_ERROR;
1349          return CC_FAILED;
1350    }
1351 
1352 } /* end function ARCH_DEP(d250_iorq32) */
1353 
1354 
1355 /* BIOE Address and Status Handling (32-bit and 64-bit formats)     */
1356 /*                                                                  */
1357 /* The entire BIOE is fetched from storage, but only the status     */
1358 /* field will be updated.  BIOE addresses and block addresses are   */
1359 /* handled the same.  Only key protection and addressing            */
1360 /* exceptions are recognized for these absolute addresses.          */
1361 /* Architecture will determine the maximum address allowed not the  */
1362 /* addressing mode specified in the PSW.  An addressing exception   */
1363 /* will be recognized if a BIOE extends beyond the architecture     */
1364 /* maximum address.                                                 */
1365 /*                                                                  */
1366 /* Setting of reference bit in a storage key is based upon          */
1367 /* inline.h ARCH_DEP(fetch_xxx_absolute) functions                  */
1368 /* Setting of changed bit in a storage key is based upon            */
1369 /* inline.h ARCH_DEP(store_xxx_absolute) functions                  */
1370 
1371 /*-------------------------------------------------------------------*/
1372 /*  Input/Outut 32-bit List Processor - Sychronicity Independent     */
1373 /*-------------------------------------------------------------------*/
ARCH_DEP(d250_list32)1374 int ARCH_DEP(d250_list32)(IOCTL32* ioctl, int async)
1375 /* WARNING: Device Block lock must be released before returning */
1376 {
1377 BIOE32 bioe;      /* 32-bit BIOE fetched from absolute storage */
1378 RADR   bioebeg;   /* Starting address of the BIOE              */
1379 RADR   bioeend;   /* Address of last byte of BIOE              */
1380 U16    xcode;     /* Detected exception condition              */
1381 int    blocks;    /* Number of blocks being processed          */
1382 int    block;     /* counter used in block I/O loop            */
1383 S32    blknum;    /* Block number of the request               */
1384 BYTE   status;    /* Returned BIOE status                      */
1385 /* Passed to generic block I/O function                        */
1386 int    physblk;   /* Physical block number                     */
1387 RADR   bufbeg;    /* Address where the read/write will occur   */
1388 RADR   bufend;    /* Last byte read or written                 */
1389 
1390    xcode = 0;   /* Initialize the address check exception code */
1391    status = 0xFF;  /* Set undefined status */
1392 
1393    /* Preserve pending sense if any and establish my ownership */
1394    /* of the device by reserving it if shared and locking it   */
1395    if (ioctl->dev->ccwtrace)
1396    {
1397       logmsg ("%4.4X:HHCVM015I d250_list32 BIOE's=%i A:"
1398                   F_RADR " I/O key=%2.2X\n",
1399                ioctl->dev->devnum,
1400                ioctl->blkcount,
1401                ioctl->listaddr,
1402                ioctl->key
1403                );
1404    }
1405 
1406    /* Take ownership of the device */
1407    d250_preserve(ioctl->dev);
1408    /* Note: the DEVBLK is now locked */
1409 
1410    if (!ioctl->dev->vmd250env)
1411    {
1412        d250_restore(ioctl->dev);
1413        /* Note: the device lock is now released */
1414        return PSC_REMOVED;
1415    }
1416 
1417    blocks=(int)ioctl->blkcount;
1418    bioebeg=ioctl->listaddr & AMASK31 ;
1419 
1420    /* Process each of the BIOE's supplied by the BIOPL count field */
1421    for ( block = 0 ; block < blocks ; block++ )
1422    {
1423       status = 0xFF;  /* Set undefined status */
1424 
1425       bioeend=( bioebeg + sizeof(BIOE32) - 1 ) & AMASK31;
1426       xcode=ARCH_DEP(d250_addrck)
1427             (bioebeg,bioeend,ACCTYPE_READ,ioctl->key,ioctl->regs);
1428       if (ioctl->dev->ccwtrace)
1429       {
1430          logmsg(_("%4.4X:HHCVM020I d250_list32 xcode=%4.4X "
1431                   "BIOE32=%8.8X-%8.8X FETCH key=%2.2X\n"),
1432                   ioctl->dev->devnum,xcode,bioebeg,bioeend,ioctl->key);
1433       }
1434       if ( xcode )
1435       {
1436          break;
1437       }
1438 
1439       /* Fetch the BIOE from storage */
1440       memcpy(&bioe,ioctl->regs->mainstor+bioebeg,sizeof(BIOE32));
1441       STORAGE_KEY(bioebeg, ioctl->regs) |= (STORKEY_REF);
1442       STORAGE_KEY(bioeend, ioctl->regs) |= (STORKEY_REF);
1443 
1444       /* Process a single BIOE */
1445       do
1446       {
1447 
1448          /* Make sure reserved field is zeros */
1449          if ( bioe.resv1[0]!=0x00 || bioe.resv1[1]!=0x00 )
1450          {
1451             status=BIOE_NOTZERO;
1452             continue;
1453          }
1454 
1455          /* Fetch and validate block number */
1456          FETCH_FW(blknum,&bioe.blknum);
1457          if ( (blknum < ioctl->dev->vmd250env->begblk) ||
1458               (blknum > ioctl->dev->vmd250env->endblk)
1459             )
1460          {
1461             status=BIOE_BADBLOCK;
1462             continue;
1463          }
1464 
1465          /* Fetch the storage address used for I/O */
1466          FETCH_FW(bufbeg,&bioe.bufaddr);
1467          bufbeg &= AMASK31;
1468 
1469          /* Ensure the environment still exists */
1470          if (!ioctl->dev->vmd250env)
1471          {
1472             d250_restore(ioctl->dev);
1473             /* Note: the device lock is now released */
1474             status=BIOE_ABORTED;
1475             return PSC_REMOVED;
1476          }
1477 
1478          /* The I/O handler routines are normally called without the  */
1479          /* device lock being held.  The device is reserved by the    */
1480          /* busy status.                                              */
1481 
1482          /* Determine the last byte of the I/O buffer */
1483          bufend=( bufbeg + ioctl->dev->vmd250env->blksiz -1 ) & AMASK31 ;
1484 
1485          if (ioctl->dev->ccwtrace)
1486          {
1487             logmsg (_("%4.4X:HHCVM016I d250_list32 BIOE %8.8X"
1488                        ", oper=%2.2X, block=%i"
1489                        ", buffer=%8.8X\n"),
1490                      ioctl->dev->devnum,
1491                      bioebeg,
1492                      bioe.type,
1493                      blknum,
1494                      bufbeg
1495                     );
1496          }
1497 
1498          /* Determine the physical block on the device relative to zero */
1499          physblk=(S64)blknum+ioctl->dev->vmd250env->offset-1;
1500          /* The read/write routines will convert this to a physical disk */
1501          /* location for reading or writing                              */
1502 
1503          if (bioe.type == BIOE_READ)
1504          {
1505             xcode=ARCH_DEP(d250_addrck)
1506                   (bufbeg,bufend,ACCTYPE_READ,ioctl->key,ioctl->regs);
1507             if (ioctl->dev->ccwtrace)
1508             {
1509                logmsg(_("%4.4X:HHCVM020I d250_list32 xcode=%4.4X "
1510                        "Rd Buf=%8.8X-%8.8X FETCH key=%2.2X\n"),
1511                        ioctl->dev->devnum,xcode,bufbeg,bufend,ioctl->key);
1512             }
1513             switch ( xcode )
1514             {
1515                case PGM_ADDRESSING_EXCEPTION:
1516                   status=BIOE_ADDREXC;
1517                   continue;
1518                case PGM_PROTECTION_EXCEPTION:
1519                   status=BIOE_PROTEXC;
1520                   continue;
1521             }
1522             /* At this point, the block number has been validated */
1523             /* and the buffer is addressable and accessible       */
1524             status=d250_read(ioctl->dev,
1525                                physblk,
1526                                ioctl->dev->vmd250env->blksiz,
1527                                ioctl->regs->mainstor+bufbeg);
1528 
1529             /* Set I/O storage key references if successful */
1530             if (!status)
1531             {
1532                STORAGE_KEY(bufbeg, ioctl->regs) |= (STORKEY_REF);
1533                STORAGE_KEY(bufend, ioctl->regs) |= (STORKEY_REF);
1534 #if defined(FEATURE_2K_STORAGE_KEYS)
1535                if ( ioctl->dev->vmd250env->blksiz == 4096 )
1536                {
1537                   STORAGE_KEY(bufbeg+2048, ioctl->regs) |= (STORKEY_REF);
1538                }
1539 #endif
1540             }
1541 
1542             continue;
1543          }  /* end of BIOE_READ */
1544          else
1545          {  if (bioe.type == BIOE_WRITE)
1546             {
1547                xcode=ARCH_DEP(d250_addrck)
1548                      (bufbeg,bufend,ACCTYPE_WRITE,ioctl->key,ioctl->regs);
1549                if (ioctl->dev->ccwtrace)
1550                {
1551                   logmsg(_("%4.4X:HHCVM020I d250_list32 xcode=%4.4X "
1552                            "Wr Buf=%8.8X-%8.8X STORE key=%2.2X\n"),
1553                            ioctl->dev->devnum,
1554                            xcode,bufbeg,
1555                            bufend,
1556                            ioctl->key);
1557                }
1558 
1559                switch ( xcode )
1560                {
1561                   case PGM_ADDRESSING_EXCEPTION:
1562                      status=BIOE_ADDREXC;
1563                      continue;
1564                   case PGM_PROTECTION_EXCEPTION:
1565                      status=BIOE_PROTEXC;
1566                      continue;
1567                }
1568 
1569                if (ioctl->dev->vmd250env->isRO)
1570                {
1571                   status=BIOE_DASDRO;
1572                   continue;
1573                }
1574                status=d250_write(ioctl->dev,
1575                                    physblk,
1576                                    ioctl->dev->vmd250env->blksiz,
1577                                    ioctl->regs->mainstor+bufbeg);
1578 
1579                /* Set I/O storage key references if good I/O */
1580                if (!status)
1581                {
1582                   STORAGE_KEY(bufbeg, ioctl->regs)
1583                            |= (STORKEY_REF | STORKEY_CHANGE);
1584                   STORAGE_KEY(bufend, ioctl->regs)
1585                            |= (STORKEY_REF | STORKEY_CHANGE);
1586 #if defined(FEATURE_2K_STORAGE_KEYS)
1587                   if ( ioctl->dev->vmd250env->blksiz == 4096 )
1588                   {
1589                   STORAGE_KEY(bufbeg+2048, ioctl->regs)
1590                              |= (STORKEY_REF | STORKEY_CHANGE);
1591                   }
1592 #endif
1593                }
1594 
1595                continue;
1596             } /* end of if BIOE_WRITE */
1597             else
1598             {
1599                status=BIOE_BADREQ;
1600                continue;
1601             } /* end of else BIOE_WRITE */
1602          } /* end of else BIOE_READ */
1603       }while(0); /* end of do */
1604 
1605       /* Determine if we can store the status in the BIOE */
1606       xcode=ARCH_DEP(d250_addrck)
1607             (bioebeg+1,bioebeg+1,ACCTYPE_WRITE,ioctl->key,ioctl->regs);
1608       if (ioctl->dev->ccwtrace)
1609       {
1610          logmsg(_("%4.4X:HHCVM020I d250_list32 xcode=%4.4X "
1611                   "Status=%8.8X-%8.8X STORE key=%2.2X\n"),
1612                   ioctl->dev->devnum,xcode,bioebeg+1,bioebeg+1,ioctl->key);
1613       }
1614 
1615       /* If the status byte is store protected, give up on processing any */
1616       /* more BIOE's.  Leave the BIOE list process for loop               */
1617       if ( xcode )
1618       {
1619          break;
1620       }
1621 
1622       /* Store the status in the BIOE */
1623       memcpy(ioctl->regs->mainstor+bioebeg+1,&status,1);
1624 
1625       /* Set the storage key change bit */
1626       STORAGE_KEY(bioebeg+1, ioctl->regs)
1627                  |= (STORKEY_REF | STORKEY_CHANGE);
1628 
1629       if (ioctl->dev->ccwtrace)
1630       {
1631          logmsg (_("%4.4X:HHCVM014I d250_list32 BIOE=%8.8X status=%2.2X\n"),
1632                  ioctl->dev->devnum,bioebeg,status);
1633       }
1634 
1635       /* Count if this BIOE was a success or failure */
1636       if ( status )
1637       {
1638          ioctl->badblks+=1;
1639          if ( status == BIOE_ABORTED )
1640          {
1641              break;
1642          }
1643       }
1644       else
1645       {
1646          ioctl->goodblks+=1;
1647       }
1648 
1649       /* Determine the address of the next BIOE */
1650       bioebeg += sizeof(BIOE32);
1651       bioebeg &= AMASK31;
1652    } /* end of for loop */
1653 
1654 
1655 #if 0
1656    logmsg(_("(d250_list32) BIOE's processed: %d\n"),block);
1657 #endif
1658 
1659    /* Restore device to guest ownership */
1660    d250_restore(ioctl->dev);
1661    /* Note: device lock not held */
1662 
1663    /* If an access exception occurred:                                 */
1664    /*   If this is a synchronous request, generate a program exception */
1665    /*   or if this is asynchrnous, just return with a storage error    */
1666    if ( xcode )
1667    {
1668       if (async)
1669           return PSC_STGERR;
1670       else
1671           ARCH_DEP(program_interrupt)(ioctl->regs, xcode);
1672    }
1673 
1674    if ( status == BIOE_ABORTED )
1675    {
1676       return PSC_REMOVED;
1677    }
1678 
1679    /* Determine if we were completely successful or only partially     */
1680    /* successful.  'Partial' includes none successful.                 */
1681    /* Synchronous and asynchronous requests handle all failed          */
1682    /* differently. The good and bad blocks field are used by the       */
1683    /* caller                                                           */
1684    if (ioctl->goodblks < blocks)
1685    {
1686       return PSC_PARTIAL;
1687    }
1688    return PSC_SUCCESS;
1689 
1690 } /* end function d250_list32 */
1691 
1692 /*-------------------------------------------------------------------*/
1693 /*  Absolue Address Checking without Reference and Change Recording  */
1694 /*-------------------------------------------------------------------*/
ARCH_DEP(d250_addrck)1695 U16 ARCH_DEP(d250_addrck)
1696             (RADR beg, RADR end, int acctype, BYTE key, REGS *regs)
1697 /* Note: inline.h and vstore.c functions are not used because they      */
1698 /* will generate program exceptions automatically.  DIAGNOSE X'250' in  */
1699 /* the asynchronous case, must not do that, but rather reflect the      */
1700 /* error in the interrupt status code or BIOE status field.  So this    */
1701 /* function only detects and reports the error.                         */
1702 /* The caller must decide whether to generate a program interrupt or    */
1703 /* just report the encountered error without a program interruption     */
1704 /* and must set the reference and change bit as appropriate             */
1705 {
1706 BYTE   sk1;      /* Storage key of first byte of area         */
1707 BYTE   sk2;      /* Storage key of last byte of area          */
1708 #if defined(FEATURE_2K_STORAGE_KEYS)
1709 BYTE   skmid;    /* Storage key of middle byte of area        */
1710 #endif /* defined(FEATURE_2K_STORAGE_KEYS) */
1711 
1712 
1713     if ( (end > regs->mainlim) || (end > MAXADDRESS) || end < beg )
1714     {
1715        return PGM_ADDRESSING_EXCEPTION;
1716     }
1717 
1718     /* Note this logic is inspired by        */
1719     /* inline.h ARCH_DEP(is_fetch_protected) */
1720     /* inline.h ARCH_DEP(is_store_protected) */
1721 
1722     if (key == 0)
1723     {
1724        return 0;
1725     }
1726 
1727     sk1=STORAGE_KEY(beg,regs);
1728     sk2=STORAGE_KEY(end,regs);
1729 
1730 #if defined(FEATURE_2K_STORAGE_KEYS)
1731     if ( ( end - beg ) > 2048 )
1732     {
1733        skmid=STORAGE_KEY(beg + 2048,regs);
1734     }
1735     else
1736     {
1737        skmid = sk2;
1738     }
1739 #endif /* defined(FEATURE_2K_STORAGE_KEYS) */
1740 
1741     if (acctype == ACCTYPE_READ)
1742     {  /* Check for fetch protection  */
1743        if (  ((sk1 & STORKEY_FETCH) && (key != (sk1 & STORKEY_KEY)))
1744            ||((sk2 & STORKEY_FETCH) && (key != (sk2 & STORKEY_KEY)))
1745 #if defined(FEATURE_2K_STORAGE_KEYS)
1746            ||((skmid & STORKEY_FETCH) && (key != (skmid & STORKEY_KEY)))
1747 #endif /* defined(FEATURE_2K_STORAGE_KEYS) */
1748           )
1749        {
1750           return PGM_PROTECTION_EXCEPTION;
1751        }
1752     }
1753     else /* assume ACCTYPE_WRITE */
1754     {  /* Check for store protection */
1755        if (  (key != (sk1 & STORKEY_KEY))
1756            ||(key != (sk2 & STORKEY_KEY))
1757 #if defined(FEATURE_2K_STORAGE_KEYS)
1758            ||(key != (skmid & STORKEY_KEY))
1759 #endif /* defined(FEATURE_2K_STORAGE_KEYS) */
1760           )
1761        {
1762           return PGM_PROTECTION_EXCEPTION;
1763        }
1764     }
1765     return 0;
1766 } /* end of function ARCH_DEP(d250_addrck) */
1767 
1768 
1769 #if defined(FEATURE_ESAME)
1770 
1771 /*-------------------------------------------------------------------*/
1772 /*  Asynchronous Input/Output 64-bit Driver Thread                   */
1773 /*-------------------------------------------------------------------*/
ARCH_DEP(d250_async64)1774 void ARCH_DEP(d250_async64)(void *ctl)
1775 {
1776 IOCTL64 *ioctl;    /* 64-bit IO request controls  */
1777 BYTE     psc;      /* List processing status code */
1778 
1779    /* Fetch the IO request control structure */
1780    ioctl=(IOCTL64 *)ctl;
1781 
1782    /* Call the 32-bit BIOE request processor on this async thread*/
1783    psc=ARCH_DEP(d250_list64)(ioctl, ASYNC);
1784 
1785    d250_bio_interrupt(ioctl->dev, ioctl->intrparm, psc, 0x07);
1786 
1787    free(ioctl);
1788 
1789 } /* end function ARCH_DEP(d250_async64) */
1790 
1791 /*-------------------------------------------------------------------*/
1792 /*  Input/Output Request - 64-bit Addressing                         */
1793 /*-------------------------------------------------------------------*/
ARCH_DEP(d250_iorq64)1794 int ARCH_DEP(d250_iorq64)(DEVBLK *dev, int *rc, BIOPL_IORQ64 *biopl,
1795              REGS *regs)
1796 {
1797 BIOPL_IORQ64   bioplx00;   /* Used to check reserved fields */
1798 IOCTL64 ioctl;             /* Request information */
1799 BYTE    psc;               /* List processing status code   */
1800 
1801 /* Asynchronous request related fields */
1802 TID     tid;         /* Asynchronous thread ID */
1803 char    tname[32];   /* Thread name */
1804 IOCTL64 *asyncp;     /* Pointer to async thread's free standing storage */
1805 
1806 #if 0
1807    logmsg("(d250_iorq64) Entered\n");
1808 #endif
1809 
1810    /* Clear the reserved BIOPL */
1811    memset(&bioplx00,0x00,sizeof(BIOPL_IORQ64));
1812 
1813    /* Make sure reserved fields are binary zeros  */
1814    if ((memcmp(&biopl->resv1,&bioplx00,IORQ64R1_LEN)!=0) ||
1815        (memcmp(&biopl->resv2,&bioplx00,IORQ64R2_LEN)!=0) ||
1816        (memcmp(&biopl->resv3,&bioplx00,IORQ64R3_LEN)!=0) ||
1817        (memcmp(&biopl->resv4,&bioplx00,IORQ64R4_LEN)!=0) ||
1818        (biopl->flags & BIOPL_FLAGSRSV) ||
1819        (biopl->key & BIOPL_KEYRSV)
1820       )
1821    {
1822        ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
1823    }
1824 
1825    /* Return with an error return code if the device does not exist */
1826    if (!dev)
1827    {
1828       *rc = RC_NODEV;  /* Set the return code for no device */
1829       return CC_FAILED; /* Indicate the function failed     */
1830    }
1831 
1832    /* If no environment, return with an error */
1833    if (!dev->vmd250env)
1834    {
1835       *rc = RC_STATERR;
1836       return CC_FAILED;
1837    }
1838 
1839    /* Fetch the block count from the BIOPL */
1840    FETCH_FW(ioctl.blkcount,&biopl->blkcount);
1841 #if 0
1842    logmsg("(d250_iorq64) ioctl.blkcount=%d,\n",
1843            ioctl.blkcount);
1844 #endif
1845 
1846    /* Block count must be between 1 and 256, inclusive */
1847    if ((ioctl.blkcount<1) || (ioctl.blkcount>256))
1848    {
1849        *rc = RC_CNT_ERR;
1850        return CC_FAILED;
1851    }
1852 
1853    /* Fetch the address of the BIO entry list from the BIOPL */
1854    FETCH_DW(ioctl.listaddr,&biopl->bioeladr);
1855 #if 0
1856    logmsg (_("(d250_iorq64) ioctl.listaddr=%16.16X,\n"),
1857            ioctl.listaddr);
1858 #endif
1859 
1860    /* Extract the storage key from the BIOPL */
1861    ioctl.key=biopl->key;
1862 
1863    /* Set the structures that are involved in this request */
1864    ioctl.dev = dev;
1865    ioctl.regs = regs;
1866 
1867    /* Set I/O success/failure counts to zero */
1868    ioctl.goodblks = 0;
1869    ioctl.badblks = 0;
1870 
1871    /* Determine if request is an asynchronous or synchronous */
1872    if (biopl->flags & BIOPL_ASYNC)
1873    {
1874        /* Build the request structure */
1875 
1876        /* Extract the 64-bit interrupt parameter from the BIOPL */
1877        FETCH_DW(ioctl.intrparm,&biopl->intparm);
1878 
1879        if (dev->ccwtrace)
1880        {
1881           logmsg(_("%4.4X:HHCVM019I ASYNC BIOEL=%16.16X, "
1882                    "Entries=%d, Key=%2.2X, Intp=%16.16X\n"),
1883                    dev->devnum,
1884                    ioctl.listaddr,
1885                    ioctl.blkcount,
1886                    ioctl.key,
1887                    ioctl.intrparm);
1888        }
1889 
1890        /* Set the default status code to an aborted list */
1891        /* Note: This should be set correctly from the returned PSC */
1892        ioctl.statuscod = PSC_STGERR;
1893 
1894        /* Get the storage for the thread's parameters */
1895        if (!(asyncp=(IOCTL64 *)malloc(sizeof(IOCTL64))))
1896        {
1897           logmsg (_("HHCVM011E VM BLOCK I/O request malloc failed\n"));
1898           *rc = RC_ERROR;
1899           return CC_FAILED;
1900        }
1901 
1902        /* Copy the thread's parameters to its own storage */
1903        memcpy(asyncp,&ioctl,sizeof(IOCTL64));
1904 
1905        /* Launch the asynchronous request on a separate thread */
1906        snprintf(tname,sizeof(tname),"d250_async %4.4X",dev->devnum);
1907        tname[sizeof(tname)-1]=0;
1908        if ( create_thread (&tid, DETACHED, ARCH_DEP(d250_async64),
1909                asyncp, tname)
1910           )
1911        {
1912           logmsg (_("%4.4X:HHCVM010E create_thread error: %s"),
1913                   dev->devnum, strerror(errno));
1914           release_lock (&dev->lock);
1915           *rc = RC_ERROR;
1916           return CC_FAILED;
1917        }
1918        /* Launched the async request successfully */
1919        *rc = RC_ASYNC;
1920        return CC_SUCCESS;
1921    }
1922    else
1923    {
1924        if (dev->ccwtrace)
1925        {
1926           logmsg(_("%4.4X:HHCVM019I d250_iorq64 SYNC BIOEL=%16.16X, "
1927                    "Entries=%d, Key=%2.2X\n"),
1928                    dev->devnum,
1929                    ioctl.listaddr,
1930                    ioctl.blkcount,
1931                    ioctl.key);
1932        }
1933 
1934        psc=ARCH_DEP(d250_list64)(&ioctl, SYNC);
1935 
1936        if (dev->ccwtrace)
1937        {
1938           logmsg(_("%4.4X:HHCVM017I d250_iorq64 "
1939                    "PSC=%d, succeeded=%d, failed=%d\n"),
1940                    dev->devnum,psc,ioctl.goodblks,ioctl.badblks);
1941        }
1942    }
1943 
1944    /* Processor status used to determine return and condition codes */
1945    switch(psc)
1946    {
1947       case PSC_SUCCESS:
1948          *rc = RC_SUCCESS;
1949          return CC_SUCCESS;
1950       case PSC_PARTIAL:
1951          if (ioctl.goodblks == 0)
1952          {
1953             *rc = RC_ALL_BAD;
1954             return CC_FAILED;
1955          }
1956          else
1957          {
1958             *rc = RC_SYN_PART;
1959             return CC_PARTIAL;
1960          }
1961       case PSC_REMOVED:
1962          *rc = RC_REM_PART;
1963          return CC_PARTIAL;
1964       default:
1965          logmsg (_("HHCVM009E d250_list64 error: PSC=%i\n"),
1966                  psc);
1967          *rc = RC_ERROR;
1968          return CC_FAILED;
1969    } /* end switch(psc) */
1970 
1971 } /* end function d250_iorq64 */
1972 
1973 /*-------------------------------------------------------------------*/
1974 /*  Input/Outut 64-bit List Processor - Sychronicity Independent     */
1975 /*-------------------------------------------------------------------*/
ARCH_DEP(d250_list64)1976 int ARCH_DEP(d250_list64)(IOCTL64* ioctl, int async)
1977 /* WARNING: Device Block lock must be released before returning */
1978 {
1979 BIOE64 bioe;      /* 32-bit BIOE fetched from absolute storage */
1980 RADR   bioebeg;   /* Starting address of the BIOE              */
1981 RADR   bioeend;   /* Address of last byte of BIOE              */
1982 U16    xcode;     /* Detected exception condition              */
1983 int    blocks;    /* Number of blocks being processed          */
1984 int    block;     /* counter used in block I/O loop            */
1985 S64    blknum;    /* Block number of the request               */
1986 BYTE   status;    /* Returned BIOE status                      */
1987 /* Passed to generic block I/O function                        */
1988 int    physblk;   /* Physical block number                     */
1989 RADR   bufbeg;    /* Address where the read/write will occur   */
1990 RADR   bufend;    /* Last byte read or written                 */
1991 
1992    xcode = 0;   /* Initialize the address check exception code */
1993    status = 0xFF;  /* Set undefined status */
1994 
1995    /* Preserve pending sense if any and establish my ownership */
1996    /* of the device by reserving it if shared and locking it   */
1997    if (ioctl->dev->ccwtrace)
1998    {
1999       logmsg (_("%4.4X:HHCVM015I d250_list64 BIOE's=%i A:"
2000                   F_RADR " I/O key=%2.2X\n"),
2001                ioctl->dev->devnum,
2002                ioctl->blkcount,
2003                ioctl->listaddr,
2004                ioctl->key
2005                );
2006    }
2007 
2008    /* Take ownership of the device */
2009    d250_preserve(ioctl->dev);
2010    /* Note: the DEVBLK is now locked */
2011 
2012    if (!ioctl->dev->vmd250env)
2013    {
2014        d250_restore(ioctl->dev);
2015        /* Note: the device lock is now released */
2016        return PSC_REMOVED;
2017    }
2018 
2019    blocks=(int)ioctl->blkcount;
2020    bioebeg=ioctl->listaddr & AMASK64 ;
2021 
2022    /* Process each of the BIOE's supplied by the BIOPL count field */
2023    for ( block = 0 ; block < blocks ; block++ )
2024    {
2025       status = 0xFF;  /* Set undefined status */
2026 
2027       bioeend=( bioebeg + sizeof(BIOE32) - 1 ) & AMASK31;
2028       xcode=ARCH_DEP(d250_addrck)
2029             (bioebeg,bioeend,ACCTYPE_READ,ioctl->key,ioctl->regs);
2030       if (ioctl->dev->ccwtrace)
2031       {
2032          logmsg(_("%4.4X:HHCVM020I d250_list64 xcode=%4.4X "
2033                   "BIOE64=%8.8X-%8.8X FETCH key=%2.2X\n"),
2034                   ioctl->dev->devnum,xcode,bioebeg,bioeend,ioctl->key);
2035       }
2036       if ( xcode )
2037       {
2038          break;
2039       }
2040 
2041       /* Fetch the BIOE from storage */
2042       memcpy(&bioe,ioctl->regs->mainstor+bioebeg,sizeof(BIOE64));
2043       STORAGE_KEY(bioebeg, ioctl->regs) |= (STORKEY_REF);
2044       STORAGE_KEY(bioeend, ioctl->regs) |= (STORKEY_REF);
2045 
2046       /* Process a single BIOE */
2047       do
2048       {
2049 
2050          /* Make sure reserved field is zeros */
2051          if ( bioe.resv1[0]!=0x00 || bioe.resv1[1]!=0x00 )
2052          {
2053             status=BIOE_NOTZERO;
2054             continue;
2055          }
2056 
2057          /* Fetch and validate block number */
2058          FETCH_DW(blknum,&bioe.blknum);
2059          if ( (blknum < ioctl->dev->vmd250env->begblk) ||
2060               (blknum > ioctl->dev->vmd250env->endblk)
2061             )
2062          {
2063             status=BIOE_BADBLOCK;
2064             continue;
2065          }
2066 
2067          /* Fetch the storage address used for I/O */
2068          FETCH_DW(bufbeg,&bioe.bufaddr);
2069          bufbeg &= AMASK64;
2070 
2071          /* Ensure the environment still exists */
2072          if (!ioctl->dev->vmd250env)
2073          {
2074             d250_restore(ioctl->dev);
2075             /* Note: the device lock is now released */
2076             status=BIOE_ABORTED;
2077             return PSC_REMOVED;
2078          }
2079 
2080          /* The I/O handler routines are normally called without the  */
2081          /* device lock being held.  The device is reserved by the    */
2082          /* busy status.                                              */
2083 
2084          /* Determine the last byte of the I/O buffer */
2085          bufend=( bufbeg + ioctl->dev->vmd250env->blksiz -1 ) & AMASK64 ;
2086 
2087          if (ioctl->dev->ccwtrace)
2088          {
2089             logmsg (_("%4.4X:HHCVM016I d250_list64 BIOE %16.16X"
2090                        ", oper=%2.2X, block=%i"
2091                        ", buffer=%16.16X\n"),
2092                      ioctl->dev->devnum,
2093                      bioebeg,
2094                      bioe.type,
2095                      blknum,
2096                      bufbeg
2097                     );
2098          }
2099 
2100          /* Determine the physical block on the device relative to zero */
2101          physblk=(S64)blknum+ioctl->dev->vmd250env->offset-1;
2102          /* The read/write routines will convert this to a physical disk */
2103          /* location for reading or writing                              */
2104 
2105          if (bioe.type == BIOE_READ)
2106          {
2107             xcode=ARCH_DEP(d250_addrck)
2108                   (bufbeg,bufend,ACCTYPE_READ,ioctl->key,ioctl->regs);
2109             if (ioctl->dev->ccwtrace)
2110             {
2111                logmsg(_("%4.4X:HHCVM020I d250_list64 xcode=%4.4X "
2112                        "Rd Buf=%16.16X-%16.16X FETCH key=%2.2X\n"),
2113                        ioctl->dev->devnum,xcode,bufbeg,bufend,ioctl->key);
2114             }
2115             switch ( xcode )
2116             {
2117                case PGM_ADDRESSING_EXCEPTION:
2118                   status=BIOE_ADDREXC;
2119                   continue;
2120                case PGM_PROTECTION_EXCEPTION:
2121                   status=BIOE_PROTEXC;
2122                   continue;
2123             }
2124             /* At this point, the block number has been validated */
2125             /* and the buffer is addressable and accessible       */
2126             status=d250_read(ioctl->dev,
2127                                physblk,
2128                                ioctl->dev->vmd250env->blksiz,
2129                                ioctl->regs->mainstor+bufbeg);
2130 
2131             /* Set I/O storage key references if successful */
2132             if (!status)
2133             {
2134                STORAGE_KEY(bufbeg, ioctl->regs) |= (STORKEY_REF);
2135                STORAGE_KEY(bufend, ioctl->regs) |= (STORKEY_REF);
2136             }
2137 
2138             continue;
2139          }  /* end of BIOE_READ */
2140          else
2141          {  if (bioe.type == BIOE_WRITE)
2142             {
2143                xcode=ARCH_DEP(d250_addrck)
2144                      (bufbeg,bufend,ACCTYPE_WRITE,ioctl->key,ioctl->regs);
2145                if (ioctl->dev->ccwtrace)
2146                {
2147                   logmsg(_("%4.4X:HHCVM020I d250_list64 xcode=%4.4X "
2148                            "Wr Buf=%16.16X-%16.16X STORE key=%2.2X\n"),
2149                            ioctl->dev->devnum,
2150                            xcode,bufbeg,
2151                            bufend,
2152                            ioctl->key);
2153                }
2154 
2155                switch ( xcode )
2156                {
2157                   case PGM_ADDRESSING_EXCEPTION:
2158                      status=BIOE_ADDREXC;
2159                      continue;
2160                   case PGM_PROTECTION_EXCEPTION:
2161                      status=BIOE_PROTEXC;
2162                      continue;
2163                }
2164 
2165                if (ioctl->dev->vmd250env->isRO)
2166                {
2167                   status=BIOE_DASDRO;
2168                   continue;
2169                }
2170                status=d250_write(ioctl->dev,
2171                                    physblk,
2172                                    ioctl->dev->vmd250env->blksiz,
2173                                    ioctl->regs->mainstor+bufbeg);
2174                /* Set I/O storage key references if good I/O */
2175                if (!status)
2176                {
2177                   STORAGE_KEY(bufbeg, ioctl->regs)
2178                            |= (STORKEY_REF | STORKEY_CHANGE);
2179                   STORAGE_KEY(bufend, ioctl->regs)
2180                            |= (STORKEY_REF | STORKEY_CHANGE);
2181                }
2182                continue;
2183             } /* end of if BIOE_WRITE */
2184             else
2185             {
2186                status=BIOE_BADREQ;
2187                continue;
2188             } /* end of else BIOE_WRITE */
2189          } /* end of else BIOE_READ */
2190       }while(0); /* end of do */
2191 
2192       /* Determine if we can store the status in the BIOE */
2193       xcode=ARCH_DEP(d250_addrck)
2194             (bioebeg+1,bioebeg+1,ACCTYPE_WRITE,ioctl->key,ioctl->regs);
2195       if (ioctl->dev->ccwtrace)
2196       {
2197          logmsg(_("%4.4X:HHCVM020I d250_list64 xcode=%4.4X "
2198                   "Status=%16.16X-%16.16X STORE key=%2.2X\n"),
2199                   ioctl->dev->devnum,xcode,bioebeg+1,bioebeg+1,ioctl->key);
2200       }
2201 
2202       /* If the status byte is store protected, give up on processing any */
2203       /* more BIOE's.  Leave the BIOE list process for loop               */
2204       if ( xcode )
2205       {
2206          break;
2207       }
2208 
2209       /* Store the status in the BIOE */
2210       memcpy(ioctl->regs->mainstor+bioebeg+1,&status,1);
2211 
2212       /* Set the storage key change bit */
2213       STORAGE_KEY(bioebeg+1, ioctl->regs)
2214                  |= (STORKEY_REF | STORKEY_CHANGE);
2215 
2216       if (ioctl->dev->ccwtrace)
2217       {
2218          logmsg (_("%4.4X:HHCVM014I d250_list64 BIOE=%16.16X status=%2.2X\n"),
2219                  ioctl->dev->devnum,bioebeg,status);
2220       }
2221 
2222       /* Count if this BIOE was a success or failure */
2223       if ( status )
2224       {
2225          ioctl->badblks+=1;
2226          if ( status == BIOE_ABORTED )
2227          {
2228              break;
2229          }
2230       }
2231       else
2232       {
2233          ioctl->goodblks+=1;
2234       }
2235 
2236       /* Determine the address of the next BIOE */
2237       bioebeg += sizeof(BIOE64);
2238       bioebeg &= AMASK64;
2239    } /* end of for loop */
2240 
2241 #if 0
2242    /* remove after testing */
2243    logmsg(_("(d250_list64) BIOE's processed: %d\n"),block);
2244 #endif
2245 
2246    /* Restore device to guest ownership */
2247    d250_restore(ioctl->dev);
2248    /* Note: device lock not held */
2249 
2250    /* If an access exception occurred:                                 */
2251    /*   If this is a synchronous request, generate a program exception */
2252    /*   or if this is asynchrnous, just return with a storage error    */
2253    if ( xcode )
2254    {
2255       if (async)
2256           return PSC_STGERR;
2257       else
2258           ARCH_DEP(program_interrupt)(ioctl->regs, xcode);
2259    }
2260 
2261    if ( status == BIOE_ABORTED )
2262    {
2263       return PSC_REMOVED;
2264    }
2265 
2266    /* Determine if we were completely successful or only partially     */
2267    /* successful.  'Partial' includes none successful.                 */
2268    /* Synchronous and asynchronous requests handle all failed          */
2269    /* differently. The good and bad blocks field are used by the       */
2270    /* caller                                                           */
2271    if (ioctl->goodblks < blocks)
2272    {
2273       return PSC_PARTIAL;
2274    }
2275    return PSC_SUCCESS;
2276 
2277 } /* end function ARCH_DEP(d250_list64) */
2278 
2279 #endif /* defined(FEATURE_ESAME) */
2280 
2281 #endif /*FEATURE_VM_BLOCKIO*/
2282 
2283 #if !defined(_GEN_ARCH)
2284 
2285 #if defined(_ARCHMODE2)
2286  #define  _GEN_ARCH _ARCHMODE2
2287  #include "vmd250.c"
2288 #endif
2289 
2290 #if defined(_ARCHMODE3)
2291  #undef   _GEN_ARCH
2292  #define  _GEN_ARCH _ARCHMODE3
2293  #include "vmd250.c"
2294 #endif
2295 
2296 #endif /*!defined(_GEN_ARCH)*/
2297