cds.txt

来自「Linux Kernel 2.6.9 for OMAP1710」· 文本 代码 · 共 514 行 · 第 1/2 页

TXT
514
字号
Linux for S/390 and zSeriesCommon Device Support (CDS)Device Driver I/O Support RoutinesAuthors : Ingo Adlung	  Cornelia HuckCopyright, IBM Corp. 1999-2002IntroductionThis document describes the common device support routines for Linux/390.Different than other hardware architectures, ESA/390 has defined a unifiedI/O access method. This gives relief to the device drivers as they don'thave to deal with different bus types, polling versus interruptprocessing, shared versus non-shared interrupt processing, DMA versus portI/O (PIO), and other hardware features more. However, this implies thateither every single device driver needs to implement the hardware I/Oattachment functionality itself, or the operating system provides for aunified method to access the hardware, providing all the functionality thatevery single device driver would have to provide itself.The document does not intend to explain the ESA/390 hardware architecture inevery detail.This information can be obtained from the ESA/390 Principles ofOperation manual (IBM Form. No. SA22-7201).In order to build common device support for ESA/390 I/O interfaces, afunctional layer was introduced that provides generic I/O access methods tothe 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.Note:In order to write a driver for S/390, you also need to look into the interfacedescribed in Documentation/s390/driver-model.txt.Note for porting drivers from 2.4:The major changes are:* The functions use a ccw_device instead of an irq (subchannel).* All drivers must define a ccw_driver (see driver-model.txt) and the associated  functions.* request_irq() and free_irq() are no longer done by the driver.* The oper_handler is (kindof) replaced by the probe() and set_online() functions  of the ccw_driver.* The not_oper_handler is (kindof) replaced by the remove() and set_offline()  functions of the ccw_driver.* The channel device layer is gone.* The interrupt handlers must be adapted to use a ccw_device as argument.  Moreover, they don't return a devstat, but an irb.* Before initiating an io, the options must be set via ccw_device_set_options().read_dev_chars()	   read device characteristics   read_conf_data()   read configuration data.ccw_device_get_ciw()   get commands from extended sense data.ccw_device_start()	   initiate an I/O request.ccw_device_resume()   resume channel program execution.ccw_device_halt()	   terminate the current I/O request processed on the device.do_IRQ()	   generic interrupt routine. This function is called by the interrupt entry   routine whenever an I/O interrupt is presented to the system. The do_IRQ()   routine determines the interrupt status and calls the device specific   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 do_IRQ() interface is not described, as it is called from the Linux/390first level interrupt handler only and does not comprise a device drivercallable interface. Instead, the functional description of do_IO() alsodescribes 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 DriversGeneral InformationThe following chapters describe the I/O related interface routines theLinux/390 common device support (CDS) provides to allow for device specificdriver implementations on the IBM ESA/390 hardware platform. Those interfacesintend to provide the functionality required by every device driverimplementaion to allow to drive a specific hardware device on the ESA/390platform. Some of the interface routines are specific to Linux/390 and someof them can be found on other Linux platforms implementations too.Miscellaneous function prototypes, data declarations, and macro definitionscan be found in the architecture specific C header filelinux/include/asm-s390/irq.h.Overview of CDS interface conceptsDifferent to other hardware platforms, the ESA/390 architecture doesn't defineinterrupt lines managed by a specific interrupt controller and bus systemsthat may or may not allow for shared interrupts, DMA processing, etc.. Instead,the ESA/390 architecture has implemented a so called channel subsystem, thatprovides a unified view of the devices physically attached to the systems.Though the ESA/390 hardware platform knows about a huge variety of differentperipheral attachments like disk devices (aka. DASDs), tapes, communicationcontrollers, etc. they can all by accessed by a well defined access method andthey are presenting I/O completion a unified way : I/O interruptions. Everysingle 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 twocascaded 8259 programmable interrupt controllers (PICs), that allow for amaximum of 15 different interrupt lines. All devices attached to such a systemshare those 15 interrupt levels. Devices attached to the ISA bus system mustnot share interrupt levels (aka. IRQs), as the ISA bus bases on edge triggeredinterrupts. MCA, EISA, PCI and other bus systems base on level triggeredinterrupts, and therewith allow for shared IRQs. However, if multiple devicespresent their hardware status by the same (shared) IRQ, the operating systemhas to call every single device driver registered on this IRQ in order todetermine the device driver owning the device that raised the interrupt.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/390subchannels to Linux as IRQs. This allows Linux/390 to support up to 64kdifferent IRQs, uniquely representig a single device each.Up to kernel 2.4, Linux/390 used to provide interfaces via the IRQ (subchannel).For internal use of the common I/O layer, these are still there. However, device drivers should use the new calling interface via the ccw_device only.During its startup the Linux/390 system checks for peripheral devices. Eachof those devices is uniquely defined by a so called subchannel by the ESA/390channel subsystem. While the subchannel numbers are system generated, eachsubchannel also takes a user defined attribute, the so called device number.Both subchannel number and device number can not exceed 65535. During driverfsinitialisation, the information about control unit type and device types that imply specific I/O commands (channel command words - CCWs) in order to operatethe device are gathered. Device drivers can retrieve this set of hardwareinformation during their initialization step to recognize the devices theysupport using the information saved in the struct ccw_device given to them.This methods implies that Linux/390 doesn't require to probe for free (notarmed) interrupt request lines (IRQs) to drive its devices with. Whereapplicable, the device drivers can use the read_dev_chars() to retrieve devicecharacteristics. This can be done without having to request device ownershippreviously.In order to allow for easy I/O initiation the CDS layer provides accw_device_start() interface that takes a device specific channel program (oneor more CCWs) as input sets up the required architecture specific control blocksand initiates an I/O request on behalf of the device driver. Theccw_device_start() routine allows to specify whether it expects the CDS layerto notify the device driver for every interrupt it observes, or with final statusonly. See ccw_device_start() for more details. A device driver must never issueESA/390 I/O commands itself, but must use the Linux/390 CDS interfaces instead.For long running I/O request to be canceled, the CDS layer provides theccw_device_halt() function. Some devices require to initially issue a HALTSUBCHANNEL (HSCH) command without having pending I/O requests. This function isalso covered by ccw_device_halt().read_dev_chars() - Read Device CharacteristicsThis routine returns the characteristics for the device specified.The function is meant to be called with an irq handler in place; that is,at earliest during set_online() processing.While the request is procesed synchronously, the device interrupthandler is called for final ending status. In case of error situations theinterrupt handler may recover appropriately. The device irq handler canrecognize the corresponding interrupts by the interruption parameter be0x00524443.The ccw_device must not be locked prior to calling read_dev_chars().The function may be called enabled or disabled.int read_dev_chars(struct ccw_device *cdev, void **buffer, int length );cdev   - the ccw_device the information is requested for.buffer - pointer to a buffer pointer. The buffer pointer itself         must contain a valid buffer area.length - length of the buffer provided.The read_dev_chars() function returns :      0 - successful completion-ENODEV - cdev invalid-EINVAL - an invalid parameter was detected, or the function was called early.-EBUSY  - an irrecoverable I/O error occurred or the device is not          operational.read_conf_data() - Read Configuration DataRetrieve 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 with an irq handler in place; that is,at earliest during set_online() processing.The function may be called enabled or disabled, but the device must not belockedint read_conf_data(struct ccw_device, void **buffer, int *length, __u8 lpm);cdev   - the ccw_device the data is requested 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 responsibility 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     - cdev invalid.-EINVAL     - An invalid parameter was detected, or the function was called early.-EIO        - An irrecoverable I/O error occurred 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.get_ciw() - get command information wordThis call enables a device driver to get information about supported commandsfrom the extended SenseID data.struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 cmd);cdev - The ccw_device for which the command is to be retrieved.cmd  - The command type to be retrieved.ccw_device_get_ciw() returns:NULL    - No extended data available, invalid device or command not found.!NULL   - The command requested.ccw_device_start() - Initiate I/O RequestThe ccw_device_start() routines is the I/O request front-end processor. Alldevice driver I/O requests must be issued using this routine. A device drivermust not issue ESA/390 I/O commands itself. Instead the ccw_device_start()routine provides all interfaces required to drive arbitrary devices.This description also covers the status information passed to the device

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?