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