patch-2.4.22 linux-2.4.22/Documentation/s390/cds.txt

Next file: linux-2.4.22/Documentation/sonypi.txt
Previous file: linux-2.4.22/Documentation/s390/c7000.txt
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/Documentation/s390/cds.txt linux-2.4.22/Documentation/s390/cds.txt
@@ -5,12 +5,14 @@
 
 Author : Ingo Adlung
 
-Copyright, IBM Corp. 1999
+Copyright, IBM Corp. 1999-2002
+
+ChangeLog: 02/01/2002   Cornelia Huck    brought up-to-date
 
 Introduction
 
 This document describes the common device support routines for Linux/390.
-Different than other hardware architectures, ESA/390 hasdefined a unified
+Different than other hardware architectures, ESA/390 has defined a unified
 I/O access method. This gives relief to the device drivers as they don't
 have to deal with different bus types, polling versus interrupt
 processing, shared versus non-shared interrupt processing, DMA versus port
@@ -26,14 +28,11 @@
 
 In order to build common device support for ESA/390 I/O interfaces, a
 functional layer was introduced that provides generic I/O access methods to
-the hardware. The following figure shows the usage of the common device support
-of Linux/390 using a TbCP/IP driven device access an example. Similar figures
-could be drawn for other access methods, e.g. file system access to disk
-devices.
-
-The common device support layer shown above comprises the I/O support routines
-defined below. Some of them implement common Linux device driver interfaces,
-while some of them are ESA/390 platform specific.
+the hardware. 
+
+The common device support layer comprises the I/O support routines defined 
+below. Some of them implement common Linux device driver interfaces, while 
+some of them are ESA/390 platform specific.
 
 get_dev_info_by_irq() / get_dev_info_by_devno()	
    allow a device driver to determine the devices attached (visible) to the
@@ -44,10 +43,17 @@
 
 read_dev_chars()	
    read device characteristics
+   
+read_conf_data()
+   read configuration data.
 
 request_irq()	
    obtain ownership for a specific device.
 
+s390_request_irq_special()
+   obtain ownership for a specific device. Similar to request_irq(), but
+   allows for device not operational notification too.
+
 free_irq()	
    release ownership for a specific device.
 
@@ -60,6 +66,9 @@
 do_IO()	
    initiate an I/O request.
 
+resume_IO()
+   resume channel program execution.
+
 halt_IO()	
    terminate the current I/O request processed on the device.
 
@@ -70,12 +79,14 @@
    interrupt handler according to the rules (flags) defined during I/O request
    initiation with do_IO().
 
-The next chapters describe the functions, other than do_IRQ() in more details.
+The next chapters describe the functions other than do_IRQ() in more details.
 The do_IRQ() interface is not described, as it is called from the Linux/390
 first level interrupt handler only and does not comprise a device driver
 callable interface. Instead, the functional description of do_IO() also
 describes the input to the device specific interrupt handler.
 
+Note: All explanations apply also to the 64 bit architecture s390x.
+
 
 Common Device Support (CDS) for Linux/390 Device Drivers
 
@@ -90,7 +101,7 @@
 of them can be found on other Linux platforms implementations too.
 Miscellaneous function prototypes, data declarations, and macro definitions
 can be found in the architecture specific C header file
-linux/arch/s390/kernel/irq.h.
+linux/include/asm-s390/irq.h.
 
 Overview of CDS interface concepts
 
@@ -106,7 +117,7 @@
 single device is uniquely identified to the system by a so called subchannel,
 where the ESA/390 architecture allows for 64k devices be attached.
 
-Linux, however was first built on the Intel PC architecture, with its two
+Linux, however, was first built on the Intel PC architecture, with its two
 cascaded 8259 programmable interrupt controllers (PICs), that allow for a
 maximum of 15 different interrupt lines. All devices attached to such a system
 share those 15 interrupt levels. Devices attached to the ISA bus system must
@@ -117,7 +128,7 @@
 has to call every single device driver registered on this IRQ in order to
 determine the device driver owning the device that raised the interrupt.
 
-In order to not introduce a new I/O concept to the common Linux code,
+In order not to introduce a new I/O concept to the common Linux code,
 Linux/390 preserves the IRQ concept and semantically maps the ESA/390
 subchannels to Linux as IRQs. This allows Linux/390 to support up to 64k
 different IRQs, uniquely representig a single device each.
@@ -126,7 +137,7 @@
 of those devices is uniquely defined by a so called subchannel by the ESA/390
 channel subsystem. While the subchannel numbers are system generated, each
 subchannel also takes a user defined attribute, the so called device number.
-Both, subchannel number and device number can not exceed 65535. The
+Both subchannel number and device number can not exceed 65535. The
 init_IRQ() routine gathers the information about control unit type and device
 types that imply specific I/O commands (channel command words - CCWs) in
 order to operate the device. Device drivers can retrieve this set of hardware
@@ -141,7 +152,7 @@
 When a device driver has recognized a device it wants to claim ownership for,
 it calls request_irq() with the device's subchannel id serving as pseudo irq
 line. One of the required parameters it has to specify is dev_id, defining a
-device status block, the CDS layer will use to notify the device driver's
+device status block which the CDS layer will use to notify the device driver's
 interrupt handler about interrupt information observed. It depends on the
 device driver to properly handle those interrupts.
 
@@ -169,6 +180,41 @@
 
 
 
+get_irq_first() / get_irq_next() - Retrieve Information about available IRQs 
+
+A device driver can use those interface routines to retrieve information for 
+those IRQs only that have valid device information available. As 
+Linux for S/390 supports a maximum of 65535 subchannels (devices), it might 
+be a waste of CPU to scan for the max number of  devices while a fraction is 
+available/usable only. get_irq_first() will retrieve the first usable IRQ. 
+Using this as input get_irq_next() will retrieve the next IRQ available, etc..
+
+int get_irq_first( void );
+int get_irq_next( int irq );
+
+irq - defines the subchannel to start scanning with. This must be
+      a valid subchannel or an error is returned. 
+
+The get_irq_first() / get_irq_next() functions return:
+
+non-negative value - next available IRQ
+          -ENODEV  - no more IRQs available
+
+Example : 
+
+ irq = get_irq_first();
+ while ( irq != -ENODEV) 
+ {
+  get_dev_info_by_irq( irq, &dinfo);
+  if (    dinfo.devno == devno_to_look_for 
+       || dinfo.sid_data.cu_type == cu_type_to_look_for )
+  {
+   do_some_action( irq, &dinfo ); 
+  } /* endif */
+    
+  irq = get_irq_next(irq);
+ }
+
 get_dev_info_by_irq() / get_dev_info_by_devno() - Retrieve Device Information
 
 During system startup - init_IRQ() processing - the generic I/O device support
@@ -176,60 +222,69 @@
 SenseID information. For those devices supporting the command it also obtains
 extended SenseID information.
 
-int get_dev_info_by_irq( int         irq,
-                         dev_info_t *devinfo);
+int get_dev_info_by_irq( int             irq,
+                         s390_dev_info_t *pdi);
 
-int get_dev_info_by_devno( unsigned int  irq,
-                           dev_info_t   *devinfo);
+int get_dev_info_by_devno( __u16           devno,
+                           s390_dev_info_t *pdi);
 
-irq     - defines the subchannel, status information is to be
+irq     - defines the subchannel status information is to be
           returned for.
 devno   - device number.
-devinfo - pointer to a user buffer of type dev_info_t that should
+pdi     - pointer to a user buffer of type s390_dev_info_t that should
           be filled with device specific information.
 
 typedef struct {
-     unsigned int devno;     /* device number */
-     unsigned int status;    /* device status */
-     senseid_t    sid_data;  /* senseID data  */
-} dev_info_t;
+     int          irq;                  /* irq, aka. subchannel */
+     __u16        devno;                /* device number */
+     unsigned int status;               /* device status */
+     senseid_t    sid_data;             /* senseID data */
+} s390_dev_info_t;			
 
+irq       - subchannel.
 devno     - device number as configured in the IOCDS.
 status    - device status
 sid_data  - data obtained by a SenseID call
 
 Possible status values are :
 
-DEVSTAT_NOT_OPER - device was found not-operational. In this case
-                   the caller should disregard the sid_data
-                   buffer content.
+DEVSTAT_NOT_OPER -       device was found not-operational. In this case
+                         the caller should disregard the sid_data
+                         buffer content.
+DEVSTAT_UNFRIENDLY_DEV - device is locked by someone else. The sid_data buffer
+		         doesn't contain valid data.
+DEVSTAT_UNKNOWN_DEV -    The device is unknown, and the sid_data buffer doesn't
+		         contain valid data.
+DEVSTAT_DEVICE_OWNED -   An interrupt handler is registered.
 
 //
-// SenseID response buffer layout
+// sense-id response buffer layout
 //
 typedef struct {
   /* common part */
-      unsigned char  reserved;     /* always 0x'FF' */
-      unsigned short cu_type;      /* control unit type */
-      unsigned char  cu_model;     /* control unit model */
-      unsigned short dev_type;     /* device type */
-      unsigned char  dev_model;    /* device model */
-      unsigned char  unused;       /* padding byte */
+      __u8           reserved;     /* always 0x'FF' */
+      __u16          cu_type;      /* control unit type */
+      __u8           cu_model;     /* control unit model */
+      __u16          dev_type;     /* device type */
+      __u8           dev_model;    /* device model */
+      __u8           unused;       /* padding byte */
   /* extended part */
-      ciw_t    ciw[62];            /* variable # of CIWs */
-} senseid_t;
+      ciw_t    ciw[MAX_CIWS];      /* variable # of CIWs */
+}  __attribute__ ((packed,aligned(4))) senseid_t;
+
+MAX_CIWS is currently defined as 8.
 
 The ESA/390 I/O architecture defines certain device specific I/O functions.
 The device returns the device specific command code together with the SenseID
 data in so called Command Information Words (CIW) :
 
 typedef struct _ciw {
-   unsigned int et       :  2;    // entry type
-   unsigned int reserved :  2;    // reserved
-   unsigned int ct       :  4;    // command type
-   unsigned int cmd      :  8;    // command
-   unsigned int count    : 16;    // count
-} ciw_t;
+   __u32        et       :  2; // entry type
+   __u32        reserved :  2; // reserved
+   __u32        ct       :  4; // command type
+   __u32        cmd      :  8; // command
+   __u32        count    : 16; // count
+} __attribute__ ((packed)) ciw_t;
 
 Possible CIW entry types are :
 
@@ -245,6 +300,7 @@
 -ENODEV - irq or devno don't specify a known subchannel or device
           number.
 -EINVAL - invalid devinfo value.
+-EUSERS - device is locked by someone else.
 
 Usage Notes :
 
@@ -252,7 +308,7 @@
 calling     get_dev_info() until it returns -ENODEV as there aren't any more
 available devices.
 
-If a device driver wants to request ownership for a specific device it must
+If a device driver wants to request ownership for a specific device, it must
 call request_irq() prior to be able to issue any I/O request for it, including
 above mentioned   device dependent commands.
 
@@ -269,7 +325,7 @@
 numbers configured in the IOCDS. The following routines serve the purpose to
 convert irq values into device numbers and vice versa.
 
-int get_irq_by_devno( unsigned int devno );
+int get_irq_by_devno( __u16 devno );
 
 unsigned int get_devno_by_irq( int irq );
 
@@ -336,6 +392,41 @@
 he specifies, or the buffer he wants to be allocated.
 
 
+read_conf_data() - Read Configuration Data
+
+Retrieve the device dependent configuration data. Please have a look at your 
+device dependent I/O commands for the device specific layout of the node 
+descriptor elements. 
+
+The function is meant to be called without an irq handler be in place. However,
+the irq for the requested device must not be locked or this will cause a 
+deadlock situation ! 
+
+The function may be called enabled or disabled.
+
+int read_conf_data( int irq, void **buffer, int *length, __u8 lpm);
+
+irq    - Specifies the subchannel the configuration data is to be
+         retrieved for.
+buffer - Pointer to a buffer pointer. The read_conf_data() routine
+         will allocate a buffer and initialize the buffer pointer
+         accordingly. It's the device driver's responsability to
+         release the kernel memory if no longer needed. 
+length - Length of the buffer allocated and retrieved.
+lpm    - Logical path mask to be used for retrieving the data. If
+         zero the data is retrieved on the next path available.
+
+The read_conf_data() function returns :
+          0 - Successful completion
+-ENODEV     - irq doesn't specify a valid subchannel number
+-EINVAL     - An invalid parameter was detected
+-EIO        - An irrecoverable I/O error occured or the device is
+              not operational.
+-ENOMEM     - The read_conf_data() routine couldn't obtain storage.
+-EOPNOTSUPP - The device doesn't support the read configuration 
+              data command.
+
+
 request_irq() - Request Device Ownership
 
 As previously discussed a device driver will scan for the devices its supports
@@ -343,6 +434,9 @@
 request_irq() to request ownership for it. This call causes the subchannel to
 be enabled for interrupts if it was found operational.
 
+Note: This function is obsolete and provided for compatibility purposes only. 
+Device drivers should use s390_request_irq_special() instead. 
+
 int request_irq( unsigned int   irq,
                  int          (*handler)( int,
                                           void *,
@@ -354,27 +448,28 @@
 irq      : specifies the subchannel the ownership is requested for
 handler  : specifies the device driver's interrupt handler to be
            called for interrupt processing
-irqflags : IRQ flags, must be 0 (zero) or SA_SAMPLE_RANDOM
+irqflags : IRQ flags, currently ignored
 devname  : device name
 dev_id   : required pointer to a device specific buffer of type
            devstat_t
 
 typedef struct {
-     unsigned int  devno;   /* device number from irb */
-     unsigned int  intparm; /* interrupt parameter */
-     unsigned char cstat;   /* channel status - accumulated */
-     unsigned char dstat;   /* device status - accumulated */
-     unsigned char lpum;    /* last path used mask from irb */
-     unsigned char unused;  /* not used - reserved */
-     unsigned int  flag;    /* flag : see below */
-     unsigned long cpa;     /* CCW addr from irb at prim. status */
-     unsigned int  rescnt;  /* count from irb at primary status */
-     unsigned int  scnt;    /* sense count, if available */
+     __u16         devno;    /* device number, aka. "cuu" from irb */
+     unsigned long intparm;  /* interrupt parameter */
+     __u8          cstat;    /* channel status - accumulated */
+     __u8          dstat;    /* device status - accumulated */
+     __u8          lpum;     /* last path used mask from irb */
+     __u8          unused;   /* not used - reserved */
+     unsigned int  flag;     /* flag : see below */
+     __u32         cpa;      /* CCW address from irb at primary status */
+     __u32         rescnt;   /* res. count from irb at primary status */
+     __u32         scnt;     /* sense count, if DEVSTAT_FLAG_SENSE_AVAIL */
      union {
-        irb_t   irb;        /* interruption response block */
-        sense_t sense;      /* sense information */
-        } ii;               /* interrupt information */
-  } devstat_t;
+        irb_t   irb;         /* interruption response block */
+        sense_t sense;       /* sense information */
+     } ii;                /* interrupt information */
+} devstat_t;
+
 
 During request_irq() processing, the devstat_t layout does not matter as it
 won't be used during request_irq() processing. See do_IO() for a functional
@@ -396,9 +491,9 @@
 layer, and the device specific driver. The value passed to request_irq()
 must therefore point to a valid devstat_t type buffer area the device driver
 must preserve for later usage. I.e. it must not be released prior to a call
-to free_irq()
+to free_irq().
 
-The only value parameter irqflags supports is SA_SAMPLE_RANDOM if appropriate.
+Irqflags are currently ignored by the cds layer.
 The Linux/390 kernel does neither know about "fast" interrupt handlers, nor
 does it allow for interrupt sharing. Remember, the term interrupt level (irq),
 device, and subchannel are used interchangeably in Linux/390.
@@ -416,6 +511,126 @@
 therefore not rely on this parameter on function entry.
 
 
+s390_request_irq_special() - Request Device Ownership 
+
+As previously discussed a device driver will scan for the devices its supports 
+by calling get_dev_info(). Once it has found a device it will call 
+request_irq() to request ownership.
+
+Note:  This function replaces request_irq() described previously.
+
+int s390_request_irq_special( 
+                     int                      irq,
+                     io_handler_func_t        io_handler,
+                     not_oper_handler_func_t  not_oper_handler,
+                     unsigned long            irqflags,
+                     const char              *devname,
+                     void                    *dev_id);
+
+irq              : specifies the subchannel the ownership is
+                    requested for
+io_handler       : specifies the device driver's interrupt handler
+                    to be called for interrupt processing
+not_oper_handler : specifies a device driver "not operational" handler
+irqflags         : IRQ flags, currently ignored
+devname          : device name
+dev_id           : required pointer to a device specific buffer of
+                    type devstat_t
+
+
+typedef struct {
+     __u16         devno;    /* device number, aka. "cuu" from irb */
+     unsigned long intparm;  /* interrupt parameter */
+     __u8          cstat;    /* channel status - accumulated */
+     __u8          dstat;    /* device status - accumulated */
+     __u8          lpum;     /* last path used mask from irb */
+     __u8          unused;   /* not used - reserved */
+     unsigned int  flag;     /* flag : see below */
+     __u32         cpa;      /* CCW address from irb at primary status */
+     __u32         rescnt;   /* res. count from irb at primary status */
+     __u32         scnt;     /* sense count, if DEVSTAT_FLAG_SENSE_AVAIL */
+     union {
+        irb_t   irb;         /* interruption response block */
+        sense_t sense;       /* sense information */
+     } ii;                   /* interrupt information */
+} devstat_t;
+
+During request_irq() processing, the devstat_t layout does not matter as it 
+won't be used during request_irq() processing. See do_IO() for a functional 
+description of its usage.
+
+typedef  void (* io_handler_func_t) ( int             irq,
+                                      void           *devstat,
+                                      struct pt_regs *rgs);
+
+irq     : IRQ the interrupt handler is called for
+devstat : device status block
+rgs     : obsolete
+
+typedef (void)(* not_oper_handler_func_t)( int irq, 
+                                           int status );
+
+irq    : IRQ the not operational status has been encountered for
+status : device status
+         DEVSTAT_NOT_OPER    - device is not operational
+         DEVSTAT_REVALIDATE  - revalidate device number
+         DEVSTAT_DEVICE_GONE - no such device (irq)  
+
+Note: Revalidate indicates that running under VM the device number has been 
+modified by means of a DEFINE xxxx [as] yyyy command. Therewith device number 
+xxxx was altered to yyyy. It's the device drivers responsibility to decide 
+whether device ownership can be retained.
+
+Gone indicates that the device was detached under VM, or the device number 
+became invalid (native, LPAR). In order to prevent further I/O the IRQ was 
+implicitly freed on behalf of the device driver. The driver must not call 
+free_irq itself.
+
+Not Oper indicates the device became not operational. It's the device driver's 
+responsibility whether it wants to maintain ownership for the IRQ, or not. 
+
+The s390_request_irq_special() function returns :
+      0 - successful completion
+-EINVAL - an invalid parameter was detected
+-EBUSY  - device (subchannel) already owned 
+-ENODEV - the device is not-operational
+-ENOMEM - not enough kernel memory to process request
+
+Usage Notes :
+ 
+While Linux for Intel defines dev_id as a unique identifier for shared 
+interrupt lines, it has a totally different purpose on Linux for S/390. Here 
+it serves as a shared interrupt status area between the generic device support 
+layer and the device specific driver. The value passed to request_irq() must 
+therefore point to a valid devstat_t type buffer area the device driver must 
+preserve for later usage. I.e. it must not be released prior to a call to 
+free_irq().
+ 
+Currently, the value of irqflags is ignored. The Linux for S/390 kernel does 
+neither know about "fast" interrupt handlers, nor does it allow for interrupt 
+sharing. Remember, the term interrupt level (irq), device, and subchannel are 
+used interchangeably in Linux for S/390.
+ 
+Other than request_irq(), this function does allow for a not operational 
+handler to be defined. This handler is called when a device either became not 
+operational, the last path to a device became not operational, or the device 
+was detached from the system. A detach could be a "detach" under VM or that 
+the device became unassigned by the Support Element (SE) or Hardware Management 
+Console (HMC). 
+ 
+If s390_request_irq_special() was called in enabled state, or if multiple CPUs 
+are present, the device may present an interrupt to the specified handler prior 
+to request_irq() return to the caller already ! This includes the possibility 
+of unsolicited interrupts or a pending interrupt status from an earlier 
+solicited I/O request. The device driver must be able to handle this situation 
+properly or the device may become unoperational otherwise !
+
+Although the interrupt handler is defined to be called with a pointer to a 
+struct pt_regs buffer area, this is not implemented by the Linux for S/390 
+platform specific common I/O support layer. The device driver's interrupt 
+handler must therefore not rely on this parameter on function entry.
+
+
 free_irq() - Release Device Ownership
 
 A device driver may call free_irq() to release ownership of a previously
@@ -523,19 +738,19 @@
 
 int do_IO( int            irq,
            ccw1_t        *cpa,
-           unsigned long  intparm,
+           unsigned long  user_intparm,
            unsigned int   lpm,
            unsigned long  flag);
 
-irq     : irq (subchannel) the I/O request is destined for
-cpa     : logical start address of channel program
-intparm : user specific interrupt information; will be presented
-          back to the device driver's interrupt handler. Allows a
-          device driver to associate the interrupt with a
-          particular I/O request.
-lpm     : defines the channel path to be used for a specific I/O
-          request. Valid with flag value DOIO_VALID_LPM only.
-flag    : defines the action to e parformed for I/O processing
+irq          : irq (subchannel) the I/O request is destined for
+cpa          : logical start address of channel program
+user_intparm : user specific interrupt information; will be presented
+	       back to the device driver's interrupt handler. Allows a
+               device driver to associate the interrupt with a
+               particular I/O request.
+lpm          : defines the channel path to be used for a specific I/O
+               request. Valid with flag value DOIO_VALID_LPM only.
+flag         : defines the action to e parformed for I/O processing
 
 Possible flag values are :
 
@@ -543,16 +758,25 @@
 DOIO_VALID_LPM           - LPM input parameter is valid (see usage
                            notes below for details)
 DOIO_WAIT_FOR_INTERRUPT  - wait synchronously for final status
+DOIO_TIMEOUT             - perform a loop while waiting for final status
+			   and fail after a timeout
 DOIO_REPORT_ALL          - report all interrupt conditions
+DOIO_ALLOW_SUSPEND       - channel program may become suspended
+DOIO_DENY_PREFETCH       - don't allow for CCW prefetch; usually
+                           this implies the channel program might
+                           become modified 
+DOIO_CANCEL_ON_TIMEOUT   - do a cancel_IO if there is a timeout waiting
+			   for the channel program to finish (see usage
+                           notes below for details)
 
 The cpa parameter points to the first format 1 CCW of a channel program :
 
 typedef struct {
-   char            cmd_code; /* command code */
-   char            flags;    /* flags, like IDA addressing, etc. */
-   unsigned short  count;    /* byte count */
-   void           *cda;      /* data address */
-} ccw1_t __attribute__ ((aligned(8)));
+      __u8  cmd_code;/* command code */
+      __u8  flags;   /* flags, like IDA adressing, etc. */
+      __u16 count;   /* byte count */
+      __u32 cda;     /* data address */
+} __attribute__ ((packed,aligned(8))) ccw1_t;
 
 with the following CCW flags values defined :
 
@@ -605,6 +829,9 @@
                            successfully be started previously.
 DEVSTAT_FINAL_STATUS     - This is a final interrupt status for the
                            I/O requst identified by intparm.
+DEVSTAT_PCI              - A PCI was received. 
+DEVSTAT_SUSPENDED        - A "suspended" intermediate status was
+                           received.  
 
 If device status DEVSTAT_FLAG_SENSE_AVAIL is indicated in field dev_id->flag,
 field dev_id->scnt describes the numer of device specific sense bytes
@@ -612,9 +839,9 @@
 driver itself is required.
 
 typedef struct {
-   unsigned char res[32];       /* reserved   */
-   unsigned char data[32];      /* sense data */
-} sense_t;
+      __u8          res[32];   /* reserved   */
+      __u8          data[32];  /* sense data */
+   } __attribute__ ((packed)) sense_t;
 
 The device interrupt handler can use the following definitions to investigate
 the primary unit check source coded in sense byte 0 :
@@ -625,6 +852,7 @@
 SNS0_EQUIPMENT_CHECK    0x10
 SNS0_DATA_CHECK         0x08
 SNS0_OVERRUN            0x04
+SNS0_INCOMPL_DOMAIN     0x01
 
 Depending on the device status, multiple of those values may be set together.
 Please refer to the device specific documentation for details.
@@ -661,12 +889,10 @@
 
 Usage Notes :
 
-Prior to call do_IO() the device driver must
-
-assure disabled state, i.e. the I/O mask value in the PSW must be disabled.
-This can be accomplished by calling __save_flags( flags). The current PSW
-flags are preserved and can be restored by __restore_flags( flags) at a
-later time.
+Prior to call do_IO() the device driver must assure disabled state, i.e. the 
+I/O mask value in the PSW must be disabled. This can be accomplished by calling 
+__save_flags( flags). The current PSW flags are preserved and can be restored 
+by __restore_flags( flags) at a later time.
 
 If the device driver violates this rule while running in a uni-processor
 environment an interrupt might be presented prior to the do_IO() routine
@@ -674,7 +900,7 @@
 deadlock situation as the interrupt handler will try to obtain the irq
 lock the device driver still owns (see below) !
 
-the driver must assure to hold the device specific lock. This can be
+The driver must assure to hold the device specific lock. This can be
 accomplished by
 
 (i)  s390irq_spin_lock( irq), or
@@ -705,6 +931,10 @@
 is therewith primarily meant to be used during device driver initialization
 for ease of device setup.
 
+If the device driver is using the DOIO_TIMEOUT parameter, it is a good idea
+also to specify DOIO_CANCEL_ON_TIMEOUT. Otherwise, the failing channel program
+may prevent the execution of any other channel program at the subchannel.
+
 The lpm input parameter might be used for multipath devices shared among
 multiple systems as the Linux/390 CDS isn't grouping channel paths. Therefore
 its use might be required if multiple access paths to a device are available
@@ -757,6 +987,34 @@
 and dev_id->dstat that represent the accumulated subchannel and device status
 information gathered since do_IO() request initiation.
 
+Channel programs that intend to set the suspend flag on a channel command word 
+(CCW)  must start the I/O operation with the DOIO_ALLOW_SUSPEND option or the 
+suspend flag will cause a channel program check. At the time the channel program 
+becomes suspended an intermediate interrupt will be generated by the channel 
+subsystem.
+
+resume_IO() - Resume Channel Program Execution 
+
+If a device driver chooses to suspend the current channel program execution by 
+setting the CCW suspend flag on a particular CCW, the channel program execution 
+is suspended. In order to resume channel program execution the CIO layer 
+provides the resume_IO() routine. 
+
+int resume_IO( int irq);
+
+irq     : irq (subchannel) the halt operation is requested for
+
+The resume_IO() function returns:
+
+        0  - suspended channel program is resumed
+-EBUSY     - status pending
+-ENODEV    - invalid or not-operational subchannel 
+-EINVAL    - resume function not applicable  
+-ENOTCONN  - there is no I/O request pending for completion 
+
+Usage Notes:
+Please have a look at the do_IO()  usage notes for more details on suspended 
+channel programs.
 
 halt_IO() - Halt I/O Request Processing
 
@@ -765,9 +1023,9 @@
 a halt subchannel (HSCH) I/O command. For those purposes the halt_IO() command
 is provided.
 
-int halt_IO( int          irq,     /* subchannel number */
-             int          intparm, /* dummy intparm */
-             unsigned int flag);   /* operation mode */
+int halt_IO( int           irq,     /* subchannel number */
+             unsigned long intparm, /* dummy intparm */
+             unsigned long flag);   /* operation mode */
 
 irq     : irq (subchannel) the halt operation is requested for
 intparm : interruption parameter; value is only used if no I/O
@@ -867,7 +1125,7 @@
 reset_cons_dev - Reset Console Device
 
 This routine allows for resetting the console device specification. See
-set_cons_dev() for details.
+wait_cons_dev() for details.
 
 int reset_cons_dev( int irq);
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)