📄 cds.txt
字号:
int read_dev_chars( int irq, void **buffer, int length );irq - specifies the subchannel the device characteristic retrieval is requested forbuffer - pointer to a buffer pointer. The buffer pointer itself may be NULL to have the function allocate a buffer or must contain a valid buffer area.length - length of the buffer provided or to be allocated.The read_dev_chars() function returns : 0 - successful completion-ENODEV - irq doesn't specify a valid subchannel number-EINVAL - an invalid parameter was detected-EBUSY - an irrecoverable I/O error occurred or the device is not operational.Usage Notes :The function can be used in two ways :If the caller doesn't provide a data buffer, read_dev_chars() allocates adata buffer and provides the device characteristics together. It's thecaller's responsability to release the kernel memory if not longer needed.This behaviour is triggered by specifying a NULL buffer area (*buffer == NULL).Alternatively, if the user specifies a buffer area himself, nothing isallocated.In either case the caller must provide the data area length - for the bufferhe specifies, or the buffer he wants to be allocated.request_irq() - Request Device OwnershipAs previously discussed a device driver will scan for the devices its supportsby calling get_dev_info(). Once it has found a device it will callrequest_irq() to request ownership for it. This call causes the subchannel tobe enabled for interrupts if it was found operational.int request_irq( unsigned int irq, int (*handler)( int, void *, struct pt_regs *), unsigned long irqflags, const char *devname, void *dev_id);irq : specifies the subchannel the ownership is requested forhandler : specifies the device driver's interrupt handler to be called for interrupt processingirqflags : IRQ flags, must be 0 (zero) or SA_SAMPLE_RANDOMdevname : device namedev_id : required pointer to a device specific buffer of type devstat_ttypedef 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 */ 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 itwon't be used during request_irq() processing. See do_IO() for a functionaldescription of its usage.The request_irq() 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 requestUsage Notes :While Linux for Intel defines dev_id as a unique identifier for sharedinterrupt lines it has a totally different purpose on Linux/390. Here itserves as a shared interrupt status area between the generic device supportlayer, and the device specific driver. The value passed to request_irq()must therefore point to a valid devstat_t type buffer area the device drivermust preserve for later usage. I.e. it must not be released prior to a callto free_irq()The only value parameter irqflags supports is SA_SAMPLE_RANDOM if appropriate.The Linux/390 kernel does neither know about "fast" interrupt handlers, nordoes it allow for interrupt sharing. Remember, the term interrupt level (irq),device, and subchannel are used interchangeably in Linux/390.If request_irq() was called in enabled state, or if multiple CPUs are present,the device may present an interrupt to the specified handler prior torequest_irq() return to the caller already ! This includes the possibilityof unsolicited interrupts or a pending interrupt status from an earliersolicited I/O request. The device driver must be able to handle this situationproperly or the device may become unoperational otherwise !Although the interrupt handler is defined to be called with a pointer to astruct pt_regs buffer area, this is not implemented by the Linux/390 genericI/O device driver support layer. The device driver's interrupt handler musttherefore not rely on this parameter on function entry.free_irq() - Release Device OwnershipA device driver may call free_irq() to release ownership of a previouslyacquired device.void free_irq( unsigned int irq, void *dev_id);irq : specifies the subchannel the ownership is requested fordev_id : required pointer to a device specific buffer of type devstat_t. This must be the same as the one specified during a previous call to request_irq().Usage Notes :Unfortunately the free_irq() is defined not to return error codes. I.e. ifcalled with wrong parameters a device may still be operational although thereis no device driver available to handle its interrupts. Further, duringfree_irq() processing we may possibly find pending interrupt conditions. Asthose need to be processed, we have to delay free_irq() returning until aclean device status is found by synchronously handling them.The call to free_irq() will also cause the device (subchannel) be disabled forinterrupts. The device driver must not release any data areas required forinterrupt processing prior to free_irq() return to the caller as interruptscan occur prior to free_irq() returning. This is also true when called indisabled state if either multiple CPUs are presents or a pending interruptstatus was found during free_irq() processing.disable_irq() - Disable Interrupts for a given DeviceThis function may be called at any time to disable interrupt processing forthe specified irq. However, as Linux/390 maps irqs to the device (subchannel)one-to-one, this may require more extensive I/O processing than anticipated,especially if an interrupt status is found pending on the subchannel thatrequires synchronous error processing.int disable_irq( unsigned int irq );irq : specifies the subchannel to be disabledThe disable-irq() routine may return : 0 - successful completion-EBUSY - device (subchannel) is currently processing an I/O request-ENODEV - the device is not-operational or irq doesn't specify a valid subchannelUsage Notes :Unlike the Intel based hardware architecture the ESA/390 architecture doesnot have a programmable interrupt controller (PIC) where a specific interruptline can be disabled. Instead the subchannel logically representing the devicein the channel subsystem must be disabled for interrupts. However, if thereare still inetrrupt conditions pending they must be processed first in orderto allow for proper processing after reenabling the device at a later time.This may lead to delayed disable processing.As described above the disable processing may require extensive processing.Therefore disabling and re-enabling the device using disable_irq() /enable_irq() should be avoided and is not suitable for high frequencyoperations.Linux for Intel defines this functionvoid disable_irq( int irq);This is suitable for the Intel PC architecture as this only causes to maskthe requested irq line in the PIC which is not applicable for the ESA/390architecture. Therefore we allow for returning error codes.enable_irq() - Enable Interrupts for a given DeviceThis function is used to enable a previously disabled device (subchannel).See disable_irq() for more details.int enable_irq( unsigned int irq );irq : specifies the subchannel to be enabledThe enable-irq() routine may return : 0 - successful completion-EBUSY - device (subchannel) is currently processing an I/O request. This implies the device is already in enabled state-ENODEV - the device is not-operational or irq doesn't specify a valid subchanneldo_IO() - Initiate I/O RequestThe do_IO() routines is the I/O request front-end processor. All device driverI/O requests must be issued using this routine. A device driver must not issueESA/390 I/O commands itself. Instead the do_IO() routine provides allinterfaces required to drive arbitrary devices.This description also covers the status information passed to the devicedriver's interrupt handler as this is related to the rules (flags) definedwith the associated I/O request when calling do_IO().int do_IO( int irq, ccw1_t *cpa, unsigned long intparm, unsigned int lpm, unsigned long flag);irq : irq (subchannel) the I/O request is destined forcpa : logical start address of channel programintparm : 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 processingPossible flag values are :DOIO_EARLY_NOTIFICATION - allow for early interrupt notificationDOIO_VALID_LPM - LPM input parameter is valid (see usage notes below for details)DOIO_WAIT_FOR_INTERRUPT - wait synchronously for final statusDOIO_REPORT_ALL - report all interrupt conditionsThe 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)));with the following CCW flags values defined :CCW_FLAG_DC - data chainingCCW_FLAG_CC - command chainingCCW_FLAG_SLI - suppress incorrct lengthCCW_FLAG_SKIP - skipCCW_FLAG_PCI - PCICCW_FLAG_IDA - indirect addressingCCW_FLAG_SUSPEND - suspendThe do_IO() function returns : 0 - successful completion or request successfully initiated-EBUSY - the do_io() function was caled out of sequence. The device is currently processing a previous I/O request-ENODEV - irq doesn't specify a valid subchannel, the device is not operational (check dev_id.flags) or the irq is not owned.-EINVAL - both, DOIO_EARLY_NOTIFICATION and DOIO_REORT_ALL flags have been specified. The usage of those flags is mutual exclusive.When the I/O request completes, the CDS first level interrupt handler willsetup the dev_id buffer of type devstat_t defined during request_irq()processing. See request_irq() for the devstat_t data layout. Thedev_id->intparm field in the device status area will contain the value thedevice driver has associated with a particular I/O request. If a pendingdevice status was recognized dev_id->intparm will be set to 0 (zero). Thismay happen during I/O initiation or delayed by an alert status notification.In any case this status is not related to the current (last) I/O request. Incase of a delayed status notification no special interrupt will be presentedto indicate I/O completion as the I/O request was never started, even thoughdo_IO() returned with successful completion.Possible dev_id->flag values are :DEVSTAT_FLAG_SENSE_AVAIL - sense data is availableDEVSTAT_NOT_OPER - device is not-operationalDEVSTAT_START_FUNCTION - interrupt is presented as result of a call to do_IO()DEVSTAT_HALT_FUNCTION - interrupt is presented as result of a call to halt_IO()DEVSTAT_STATUS_PENDING - a pending status was found. The I/O resquest (if any) was not initiated. This status might have been presented delayed, after do_IO() or halt_IO() have successfully be started previously.DEVSTAT_FINAL_STATUS - This is a final interrupt status for the I/O requst identified by intparm.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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -