]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] s390: dasd driver.
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 6 Dec 2002 08:19:39 +0000 (00:19 -0800)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Fri, 6 Dec 2002 08:19:39 +0000 (00:19 -0800)
Convert dasd driver to new channel subsystem driver

This makes the dasd driver work again after the changes to
the channel subsystem driver:
- handle device detection with standard driver model functions
- reduce use of dasd_devmap (devmap will die as soon as
  dasd configuration is handled from initramfs)
- some cleanups

Authors: Arnd Bergmann <arndb@de.ibm.com>
 Martin Schwidefsky <schwidefsky@de.ibm.com>

26 files changed:
arch/s390/defconfig
arch/s390x/defconfig
drivers/s390/Kconfig
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3370_erp.c
drivers/s390/block/dasd_3370_erp.h [deleted file]
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_3990_erp.h [deleted file]
drivers/s390/block/dasd_9336_erp.c
drivers/s390/block/dasd_9336_erp.h [deleted file]
drivers/s390/block/dasd_9343_erp.c
drivers/s390/block/dasd_9343_erp.h [deleted file]
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_diag.h
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_eckd.h
drivers/s390/block/dasd_erp.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_fba.h
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/dasd_proc.c
include/asm-s390/dasd.h
include/asm-s390x/dasd.h

index 365dec975822a874ea888df377408d8377689bf1..20ebed299095539624dbec4c1aeca5c530d31eaf 100644 (file)
@@ -79,6 +79,7 @@ CONFIG_BLK_DEV_XPRAM=m
 # S/390 block device drivers
 #
 CONFIG_DASD=y
+# CONFIG_DASD_PROFILE is not set
 CONFIG_DASD_ECKD=y
 CONFIG_DASD_FBA=y
 CONFIG_DASD_DIAG=y
index b14708f0af1987e707fe262fdaddd058d0a200c9..50d355e02d09287ba567759119497a2a2b8851c0 100644 (file)
@@ -137,6 +137,7 @@ CONFIG_BLK_DEV_XPRAM=m
 # S/390 block device drivers
 #
 CONFIG_DASD=y
+# CONFIG_DASD_PROFILE is not set
 CONFIG_DASD_ECKD=y
 CONFIG_DASD_FBA=y
 # CONFIG_DASD_DIAG is not set
index 5352eeb6b3dce35fcb707b578dc69f36804d1a4f..a778a90dbfaec4460d9d99d453c3b3dfcbccb7b3 100644 (file)
@@ -138,49 +138,34 @@ config DASD
          S/390s channel subsystem commands. This is necessary for running
          natively on a single image or an LPAR.
 
+config DASD_PROFILE
+       bool "Profiling support for dasd devices"
+       help
+         Enable this option if you want to see profiling information
+          in /proc/dasd/statistics.
+
 config DASD_ECKD
        tristate "Support for ECKD Disks"
        depends on DASD
        help
-         ECKD devices are the most commonly used devices. you should enable
+         ECKD devices are the most commonly used devices. You should enable
          this option unless you are very sure to have no ECKD device.
 
-config DASD_AUTO_ECKD
-       bool "Automatic activation of ECKD module"
-       depends on DASD && DASD_ECKD=m
-       help
-         Enable this option if you want your ECKD discipline module loaded
-         on DASD driver startup.
-
 config DASD_FBA
        tristate "Support for FBA  Disks"
        depends on DASD
        help
-         FBA devices are currently unsupported.
+         Select this option to be able to access FBA devices. It is safe to
+         say "Y".
 
-config DASD_AUTO_FBA
-       bool "Automatic activation of FBA  module"
-       depends on DASD && DASD_FBA=m
-       help
-         Enable this option if you want your FBA discipline module loaded
-         on DASD driver startup.
-
-#  dep_tristate '   Support for CKD  Disks' CONFIG_DASD_CKD $CONFIG_DASD
 config DASD_DIAG
        tristate "Support for DIAG access to CMS reserved Disks"
-       depends on !ARCH_S390X && DASD
+       depends on DASD
        help
          Select this option if you want to use CMS reserved Disks under VM
          with the Diagnose250 command.  If you are not running under VM or
          unsure what it is, say "N".
 
-config DASD_AUTO_DIAG
-       bool "Automatic activation of DIAG module"
-       depends on DASD && !ARCH_S390X && DASD_DIAG=m
-       help
-         Enable this option if you want your DIAG discipline module loaded
-         on DASD driver startup.
-
 endmenu
 
 source "drivers/md/Kconfig"
index c816c0a09e546aff208ab777819d0d9bef39f040..6f0cfa5c66bc857776a43ce97a59d708f37eb88c 100644 (file)
@@ -7,6 +7,8 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
+ * $Revision: 1.71 $
+ *
  * History of changes (starts July 2000)
  * 11/09/00 complete redesign after code review
  * 02/01/01 added dynamic registration of ioctls
@@ -51,7 +53,7 @@
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
 
-#include <asm/div64.h>
+#include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
 #include <asm/idals.h>
 #include <asm/todclk.h>
 #define PRINTK_HEADER "dasd:"
 
 #include "dasd_int.h"
-#include "dasd_eckd.h"
-#include "dasd_fba.h"
-#include "dasd_diag.h"
-
 /*
  * SECTION: Constant definitions to be used within this file
  */
@@ -80,116 +78,19 @@ MODULE_DESCRIPTION("Linux on S/390 DASD device driver,"
 MODULE_SUPPORTED_DEVICE("dasd");
 MODULE_PARM(dasd, "1-" __MODULE_STRING(256) "s");
 MODULE_PARM(dasd_disciplines, "1-" __MODULE_STRING(8) "s");
+MODULE_LICENSE("GPL");
 
 /*
  * SECTION: prototypes for static functions of dasd.c
  */
-static void dasd_enable_discipline(dasd_discipline_t *);
-static void dasd_disable_discipline(dasd_discipline_t *);
-static void dasd_not_oper_handler(int irq, int status);
 static int  dasd_setup_blkdev(dasd_device_t * device);
 static void dasd_disable_blkdev(dasd_device_t * device);
 static void dasd_flush_request_queue(dasd_device_t *);
-static void dasd_int_handler(int, void *, struct pt_regs *);
+static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 static void dasd_flush_ccw_queue(dasd_device_t *, int);
 static void dasd_tasklet(dasd_device_t *);
 static void do_kick_device(void *data);
-
-/*
- * Parameter parsing functions. There are two for the dasd driver:
- *   <dasd_disciplines> : <dasd_module>(,<dasd_module>)*
- */
-
-static char *dasd_disciplines[8];
-
-#ifndef MODULE
-/*
- * The parameter parsing functions for builtin-drivers are called
- * before kmalloc works. Store the pointers to the parameters strings
- * into dasd_disciplines[] for later processing.
- */
-static int __init
-dasd_disciplines_setup(char *str)
-{
-       static int count = 0;
-
-       if (count < 8)
-               dasd_disciplines[count++] = str;
-       return 1;
-}
-
-__setup ("dasd_disciplines=", dasd_disciplines_setup);
-#endif /* #ifndef MODULE */
-
-/*
- * SECTION: managing dasd disciplines
- */
-static struct list_head dasd_disc_head = LIST_HEAD_INIT(dasd_disc_head);
-static spinlock_t discipline_lock = SPIN_LOCK_UNLOCKED;
-
-/*
- * Add a discipline to the head of the discipline chain. The last added
- * discipline that matches a device is used. In particular disciplines
- * added by a module will have precedence over statically linked 
- * disciplines.
- */
-void
-dasd_discipline_add(dasd_discipline_t * discipline)
-{
-       MOD_INC_USE_COUNT;
-       spin_lock(&discipline_lock);
-       list_add(&discipline->list, &dasd_disc_head);
-       spin_unlock(&discipline_lock);
-       /* Setup devices for discipline. */
-       dasd_enable_discipline(discipline);
-}
-
-/*
- * Remove a discipline from the discipline list and disable all devices
- * that rely on that discipline.
- */
-void
-dasd_discipline_del(dasd_discipline_t * discipline)
-{
-       struct list_head *l;
-
-       spin_lock(&discipline_lock);
-       /* Check if the discipline was added. */
-       list_for_each(l, &dasd_disc_head) {
-               if (list_entry(l, dasd_discipline_t, list) == discipline) {
-                       list_del(&discipline->list);
-                       break;
-               }
-       }
-       spin_unlock(&discipline_lock);
-       /* Disable devices for discipline. */
-       dasd_disable_discipline(discipline);
-       MOD_DEC_USE_COUNT;
-}
-
-/*
- * Find the discipline for a device.
- */
-static inline int
-dasd_find_disc(dasd_device_t * device)
-{
-       struct list_head *l;
-       dasd_discipline_t *discipline, *tmp;
-
-       discipline = NULL;
-       spin_lock(&discipline_lock);
-       list_for_each(l, &dasd_disc_head) {
-               tmp = list_entry(l, dasd_discipline_t, list);
-               if (tmp->check_device(device) == 0) {
-                       /* Found a matching discipline. */
-                       discipline = tmp;
-                       break;
-               }
-       }
-       device->discipline = discipline;
-       spin_unlock(&discipline_lock);
-       return (discipline != NULL) ? 0 : -ENODEV;
-}
+static int  dasd_add_sysfs_files(struct ccw_device *cdev);
 
 /*
  * SECTION: Operations on the device structure.
@@ -204,22 +105,13 @@ dasd_alloc_device(dasd_devmap_t *devmap)
 {
        dasd_device_t *device;
        struct gendisk *gdp;
-       int rc;
 
        device = kmalloc(sizeof (dasd_device_t), GFP_ATOMIC);
        if (device == NULL)
                return ERR_PTR(-ENOMEM);
        memset(device, 0, sizeof (dasd_device_t));
 
-       /* Get devinfo from the common io layer. */
-       rc = get_dev_info_by_devno(devmap->devno, &device->devinfo);
-       if (rc) {
-               kfree(device);
-               return ERR_PTR(rc);
-       }
-       DBF_EVENT(DBF_NOTICE, "got devinfo CU-type %04x and dev-type %04x",
-                 device->devinfo.sid_data.cu_type,
-                 device->devinfo.sid_data.dev_type);
+       device->devno = devmap->devno;
 
        /* Get two pages for normal block device operations. */
        device->ccw_mem = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 1);
@@ -255,7 +147,7 @@ dasd_alloc_device(dasd_devmap_t *devmap)
                     (unsigned long) device);
        INIT_LIST_HEAD(&device->ccw_queue);
        init_timer(&device->timer);
-       INIT_WORK(&device->kick_work, do_kick_device, (void *) (addr_t) device->devinfo.devno);
+       INIT_WORK(&device->kick_work, do_kick_device, (void *) (addr_t) device->devno);
        device->state = DASD_STATE_NEW;
        device->target = DASD_STATE_NEW;
 
@@ -286,9 +178,13 @@ dasd_state_new_to_known(dasd_device_t *device)
        dasd_devmap_t *devmap;
        umode_t devfs_perm;
        devfs_handle_t dir;
-       int major, minor, rc;
+       int major, minor;
+
+       /* Increase reference count of bdev. */
+       if (bdget(MKDEV(device->gdp->major, device->gdp->first_minor)) == NULL)
+               return -ENODEV;
 
-       devmap = dasd_devmap_from_devno(device->devinfo.devno);
+       devmap = dasd_devmap_from_devno(device->devno);
        if (devmap == NULL)
                return -ENODEV;
        major = dasd_gendisk_index_major(devmap->devindex);
@@ -296,16 +192,11 @@ dasd_state_new_to_known(dasd_device_t *device)
                return -ENODEV;
        minor = devmap->devindex % DASD_PER_MAJOR;
 
-       /* Find a discipline for the device. */
-       rc = dasd_find_disc(device);
-       if (rc)
-               return rc;
-
        /* Add a proc directory and the dasd device entry to devfs. */
-       sprintf(buffer, "dasd/%04x", device->devinfo.devno);
-       dir = devfs_mk_dir(NULL, buffer, NULL);
+       sprintf(buffer, "dasd/%04x", device->devno);
+       dir = devfs_mk_dir(NULL, buffer, NULL);
        device->gdp->de = dir;
-       if (devmap->features & DASD_FEATURE_READONLY)
+       if (device->ro_flag)
                devfs_perm = S_IFBLK | S_IRUSR;
        else
                devfs_perm = S_IFBLK | S_IRUSR | S_IWUSR;
@@ -323,12 +214,7 @@ dasd_state_new_to_known(dasd_device_t *device)
 static inline void
 dasd_state_known_to_new(dasd_device_t * device)
 {
-       dasd_devmap_t *devmap;
        struct block_device *bdev;
-       int minor;
-
-       devmap = dasd_devmap_from_devno(device->devinfo.devno);
-       minor = devmap->devindex % DASD_PER_MAJOR;
 
        /* Remove device entry and devfs directory. */
        devfs_unregister(device->devfs_entry);
@@ -337,6 +223,11 @@ dasd_state_known_to_new(dasd_device_t * device)
        /* Forget the discipline information. */
        device->discipline = NULL;
        device->state = DASD_STATE_NEW;
+
+       /* Decrease reference count of bdev. */
+       bdev = bdget(MKDEV(device->gdp->major, device->gdp->first_minor));
+       bdput(bdev);
+       bdput(bdev);
 }
 
 /*
@@ -345,8 +236,6 @@ dasd_state_known_to_new(dasd_device_t * device)
 static inline int
 dasd_state_known_to_basic(dasd_device_t * device)
 {
-       int rc;
-
        /* register 'device' debug area, used for all DBF_DEV_XXX calls */
        device->debug_area = debug_register(device->gdp->disk_name, 0, 2,
                                            8 * sizeof (long));
@@ -354,19 +243,6 @@ dasd_state_known_to_basic(dasd_device_t * device)
        debug_set_level(device->debug_area, DBF_ERR);
        DBF_DEV_EVENT(DBF_EMERG, device, "%s", "debug area created");
 
-       /*
-        * We request the "official" irq line even for dasd diag device.
-        * The interrupts for dasd diag will arrive at dasd_ext_handler
-        * instead of dasd_int_handler so this is just a placeholder.
-        */
-       rc = s390_request_irq_special(device->devinfo.irq,
-                                     dasd_int_handler,
-                                     dasd_not_oper_handler,
-                                     0, "dasd", &device->dev_status);
-       if (rc) {
-               MESSAGE(KERN_ERR, "%s", "No request IRQ");
-               return rc;
-       }
        device->state = DASD_STATE_BASIC;
        return 0;
 }
@@ -378,7 +254,6 @@ static inline void
 dasd_state_basic_to_known(dasd_device_t * device)
 {
        dasd_flush_ccw_queue(device, 1);
-       free_irq(device->devinfo.irq, &device->dev_status);
        DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
        if (device->debug_area != NULL) {
                debug_unregister(device->debug_area);
@@ -428,15 +303,8 @@ dasd_state_accept_to_basic(dasd_device_t * device)
 static inline int
 dasd_state_accept_to_ready(dasd_device_t * device)
 {
-       dasd_devmap_t *devmap;
-       int rc, i;
+       int rc;
 
-       devmap = dasd_devmap_from_devno(device->devinfo.devno);
-       if (devmap->features & DASD_FEATURE_READONLY) {
-               device->ro_flag = 1;
-               DEV_MESSAGE (KERN_WARNING, device, "%s",
-                            "setting read-only mode ");
-       }
        rc = dasd_setup_blkdev(device);
        if (rc == 0) {
                dasd_setup_partitions(device);
@@ -559,7 +427,7 @@ dasd_change_state(dasd_device_t *device)
         if (rc && rc != -EAGAIN) {
                if (rc != -ENODEV)
                        MESSAGE (KERN_INFO, "giving up on dasd device with "
-                                "devno %04x", device->devinfo.devno);
+                                "devno %04x", device->devno);
                 device->target = device->state;
         }
 
@@ -622,255 +490,25 @@ dasd_set_target_state(dasd_device_t *device, int target)
  * Enable devices with device numbers in [from..to].
  */
 static inline int
-_wait_for_devices(int from, int to)
+_wait_for_device(dasd_device_t *device)
 {
-       dasd_devmap_t *devmap;
-       dasd_device_t *device;
-       int devno, rc;
-
-       rc = 0;
-       for (devno = from; devno <= to && rc == 0; devno++) {
-               devmap = dasd_devmap_from_devno(devno);
-               device = (devmap != NULL) ?
-                       dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-               if (IS_ERR(device))
-                       continue;
-               if (device->state != device->target)
-                       rc = 1;
-               dasd_put_device(devmap);
-       }
-       return rc;
+       return (device->state == device->target);
 }
 
+// FIXME: if called from dasd_devices_write discpline is not set -> oops.
 void
-dasd_enable_devices(int from, int to)
+dasd_enable_device(dasd_device_t *device)
 {
-       dasd_devmap_t *devmap;
-       dasd_device_t *device;
-       int devno;
-
-       for (devno = from; devno <= to; devno++) {
-               devmap = dasd_devmap_from_devno(devno);
-               device = (devmap != NULL) ?
-                       dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-               if (IS_ERR(device))
-                       continue;
-               dasd_set_target_state(device, DASD_STATE_ONLINE);
-               if (device->state <= DASD_STATE_KNOWN)
-                       /* No discipline for device found. */
-                       dasd_set_target_state(device, DASD_STATE_NEW);
-               dasd_put_device(devmap);
-       }
-       /* Now wait for the devices to come up. */
-       wait_event(dasd_init_waitq, _wait_for_devices(from, to) == 0);
-}
-
-/*
- * Disable devices with device numbers in [from..to].
- */
-void
-dasd_disable_devices(int from, int to)
-{
-       dasd_devmap_t *devmap;
-       dasd_device_t *device;
-       int devno;
-
-       for (devno = from; devno <= to; devno++) {
-               devmap = dasd_devmap_from_devno(devno);
-               device = (devmap != NULL) ?
-                       dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-               if (IS_ERR(device))
-                       continue;
+       dasd_set_target_state(device, DASD_STATE_ONLINE);
+       if (device->state <= DASD_STATE_KNOWN)
+               /* No discipline for device found. */
                dasd_set_target_state(device, DASD_STATE_NEW);
-               dasd_put_device(devmap);
-       }
-}
-
-/*
- * Enable devices that use a specific discipline.
- */
-static inline int
-_wait_for_disc_devices(dasd_discipline_t *discipline)
-{
-       dasd_devmap_t *devmap;
-       dasd_device_t *device;
-       int devindex, rc;
-
-       rc = 0;
-       for (devindex = 0; devindex < dasd_max_devindex; devindex++) {
-               devmap = dasd_devmap_from_devindex(devindex);
-               device = (devmap != NULL) ?
-                       dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-               if (IS_ERR(device))
-                       continue;
-               if (device->discipline == discipline &&
-                   device->state != device->target)
-                       rc = 1;
-               dasd_put_device(devmap);
-       }
-       return rc;
-}
-
-static void
-dasd_enable_discipline(dasd_discipline_t *discipline)
-{
-       dasd_devmap_t *devmap;
-       dasd_device_t *device;
-       int devindex;
-
-       for (devindex = 0; devindex < dasd_max_devindex; devindex++) {
-               devmap = dasd_devmap_from_devindex(devindex);
-               device = (devmap != NULL) ?
-                       dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-               if (IS_ERR(device))
-                       continue;
-               if (device->discipline != NULL &&
-                   device->discipline != discipline)
-                       continue;
-               dasd_set_target_state(device, DASD_STATE_ONLINE);
-               if (device->discipline == NULL)
-                       /* No discipline for device found. */
-                       dasd_set_target_state(device, DASD_STATE_NEW);
-               dasd_put_device(devmap);
-       }
        /* Now wait for the devices to come up. */
-       wait_event(dasd_init_waitq, _wait_for_disc_devices(discipline) == 0);
-}
-
-/*
- * Disable devices that use a specific discipline.
- */
-static void
-dasd_disable_discipline(dasd_discipline_t *discipline)
-{
-       dasd_devmap_t *devmap;
-       dasd_device_t *device;
-       int devindex;
-
-       /* Shutdown device that use the discipline. */
-       for (devindex = 0; devindex < dasd_max_devindex; devindex++) {
-               devmap = dasd_devmap_from_devindex(devindex);
-               device = (devmap != NULL) ?
-                       dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-               if (IS_ERR(device))
-                       continue;
-               if (device->discipline == discipline)
-                       dasd_set_target_state(device, DASD_STATE_NEW);
-               dasd_put_device(devmap);
-       }
+       wait_event(dasd_init_waitq, _wait_for_device(device));
 }
 
 /*
- * Deactivate a device that has vaninshed.
- */
-
-static void
-do_not_oper_handler(void *data)
-{
-       struct {
-               struct work_struct work;
-               int irq;
-       } *p;
-       dasd_device_t *device;
-       dasd_devmap_t *devmap;
-
-       /*
-        * find out devno of leaving device: CIO has already deleted
-        * this information so we need to find it by irq!
-        */
-       p = data;
-       devmap = dasd_devmap_from_irq(p->irq);
-       if (devmap == NULL) {
-               MESSAGE(KERN_WARNING,
-                       "not_oper_handler called on irq 0x%04x no devno!",
-                       p->irq);
-               return;
-       } else
-               DBF_EVENT(DBF_NOTICE, "called for devno %04x", devmap->devno);
-       device = dasd_get_device(devmap);
-       if (IS_ERR(device))
-               return;
-       dasd_set_target_state(device, DASD_STATE_NEW);
-       dasd_put_device(devmap);
-       kfree(p);
-}
-
-void
-dasd_not_oper_handler(int irq, int status)
-{
-       struct {
-               struct work_struct work;
-               int irq;
-       } *p;
-
-       p = kmalloc(sizeof(*p), GFP_ATOMIC);
-       if (p == NULL)
-               /* FIXME: No memory, we loose. */
-               return;
-       INIT_WORK(&p->work, (void *) do_not_oper_handler, p);
-       p->irq = irq;
-       /* queue call to do_not_oper_handler to the kernel event daemon. */
-       schedule_work(&p->work);
-}
-
-/*
- * Activate a device that appeared out of nowhere.
- */
-static void
-do_oper_handler(void *data)
-{
-       struct {
-               struct work_struct work;
-               int devno;
-       } *p;
-       dasd_devmap_t *devmap;
-       dasd_device_t *device;
-
-       p = data;
-       DBF_EVENT(DBF_NOTICE, "called for devno %04x", p->devno);
-
-       if (dasd_autodetect &&
-            dasd_add_range(p->devno, p->devno, DASD_FEATURE_DEFAULT) != 0)
-                return;
-
-       /* Get/create the device structure for devno. */
-       devmap = dasd_devmap_from_devno(p->devno);
-       if (devmap == NULL) {
-               DBF_EXC(DBF_ALERT, "no dasd: devno %04x", p->devno);
-               return;
-       }
-       device = dasd_get_device(devmap);
-       if (IS_ERR(device))
-               return;
-       dasd_enable_devices(p->devno, p->devno);
-       dasd_put_device(devmap);
-       kfree(p);
-}
-
-int
-dasd_oper_handler(int irq, devreg_t * devreg)
-{
-       struct {
-               struct work_struct work;
-               int devno;
-       } *p;
-
-       p = kmalloc(sizeof(*p), GFP_ATOMIC);
-       if (p == NULL)
-               /* FIXME: No memory, we loose. */
-               return -ENOMEM;
-       p->devno = get_devno_by_irq(irq);
-       if (p->devno == -ENODEV)
-               return -ENODEV;
-       INIT_WORK(&p->work, (void *) do_oper_handler, p);
-       /* queue call to do_oper_handler to the kernel event daemon. */
-       schedule_work(&p->work);
-        return 0;
-
-}
-
-/*
- * SECTION: device operation (interrupt handler, start_IO, term_IO ...)
+ * SECTION: device operation (interrupt handler, start i/o, term i/o ...)
  */
 #ifdef CONFIG_DASD_PROFILE
 
@@ -973,7 +611,7 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize,
 
        /* Sanity checks */
        if ( magic == NULL || datasize > PAGE_SIZE ||
-            (cplength*sizeof(ccw1_t)) > PAGE_SIZE)
+            (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
                BUG();
        debug_text_event ( dasd_debug_area, 1, "ALLC");
        debug_text_event ( dasd_debug_area, 1, magic);
@@ -986,13 +624,13 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize,
        memset(cqr, 0, sizeof(dasd_ccw_req_t));
        cqr->cpaddr = NULL;
        if (cplength > 0) {
-               cqr->cpaddr = kmalloc(cplength*sizeof(ccw1_t),
+               cqr->cpaddr = kmalloc(cplength*sizeof(struct ccw1),
                                      GFP_ATOMIC | GFP_DMA);
                if (cqr->cpaddr == NULL) {
                        kfree(cqr);
                        return ERR_PTR(-ENOMEM);
                }
-               memset(cqr->cpaddr, 0, cplength*sizeof(ccw1_t));
+               memset(cqr->cpaddr, 0, cplength*sizeof(struct ccw1));
        }
        cqr->data = NULL;
        if (datasize > 0) {
@@ -1022,7 +660,7 @@ dasd_smalloc_request(char *magic, int cplength, int datasize,
 
        /* Sanity checks */
        if ( magic == NULL || datasize > PAGE_SIZE ||
-            (cplength*sizeof(ccw1_t)) > PAGE_SIZE)
+            (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
                BUG();
        debug_text_event ( dasd_debug_area, 1, "ALLC");
        debug_text_event ( dasd_debug_area, 1, magic);
@@ -1031,7 +669,7 @@ dasd_smalloc_request(char *magic, int cplength, int datasize,
 
        size = (sizeof(dasd_ccw_req_t) + 7L) & -8L;
        if (cplength > 0)
-               size += cplength * sizeof(ccw1_t);
+               size += cplength * sizeof(struct ccw1);
        if (datasize > 0)
                size += datasize;
        spin_lock_irqsave(&device->mem_lock, flags);
@@ -1043,9 +681,9 @@ dasd_smalloc_request(char *magic, int cplength, int datasize,
        data = (char *) cqr + ((sizeof(dasd_ccw_req_t) + 7L) & -8L);
        cqr->cpaddr = NULL;
        if (cplength > 0) {
-               cqr->cpaddr = (ccw1_t *) data;
-               data += cplength*sizeof(ccw1_t);
-               memset(cqr->cpaddr, 0, cplength*sizeof(ccw1_t));
+               cqr->cpaddr = (struct ccw1 *) data;
+               data += cplength*sizeof(struct ccw1);
+               memset(cqr->cpaddr, 0, cplength*sizeof(struct ccw1));
        }
        cqr->data = NULL;
        if (datasize > 0) {
@@ -1067,7 +705,7 @@ void
 dasd_kfree_request(dasd_ccw_req_t * cqr, dasd_device_t * device)
 {
 #ifdef CONFIG_ARCH_S390X
-       ccw1_t *ccw;
+       struct ccw1 *ccw;
 
        /* Clear any idals used for the request. */
        ccw = cqr->cpaddr;
@@ -1126,7 +764,8 @@ dasd_check_cqr(dasd_ccw_req_t *cqr)
 
 /*
  * Terminate the current i/o and set the request to failed.
- * halt_IO/clear_IO can fail if the i/o subsystem is in a bad mood.
+ * ccw_device_halt/ccw_device_clear can fail if the i/o subsystem 
+ * is in a bad mood.
  */
 int
 dasd_term_IO(dasd_ccw_req_t * cqr)
@@ -1142,11 +781,9 @@ dasd_term_IO(dasd_ccw_req_t * cqr)
        device = (dasd_device_t *) cqr->device;
        while ((retries < 5) && (cqr->status == DASD_CQR_IN_IO)) {
                if (retries < 2)
-                       rc = halt_IO(device->devinfo.irq,
-                                    (long) cqr, cqr->options);
+                       rc = ccw_device_halt(device->cdev, (long) cqr);
                else
-                       rc = clear_IO(device->devinfo.irq,
-                                     (long) cqr, cqr->options);
+                       rc = ccw_device_clear(device->cdev, (long) cqr);
                switch (rc) {
                case 0: /* termination successful */
                        cqr->status = DASD_CQR_FAILED;
@@ -1172,6 +809,7 @@ dasd_term_IO(dasd_ccw_req_t * cqr)
                        BUG();
                        break;
                }
+               retries++;
        }
        dasd_schedule_bh(device);
        return rc;
@@ -1193,17 +831,11 @@ dasd_start_IO(dasd_ccw_req_t * cqr)
                return rc;
        device = (dasd_device_t *) cqr->device;
        cqr->startclk = get_clock();
-       rc = do_IO(device->devinfo.irq,
-                  cqr->cpaddr, (long) cqr, cqr->lpm, cqr->options);
+       rc = ccw_device_start(device->cdev, cqr->cpaddr, (long) cqr,
+                             cqr->lpm, 0);
        switch (rc) {
        case 0:
-               if (cqr->options & DOIO_WAIT_FOR_INTERRUPT) {
-                       /* request already finished (synchronous IO) */
-                       cqr->status = DASD_CQR_DONE;
-                       cqr->stopclk = cqr->startclk;
-                       dasd_schedule_bh(device);
-               } else
-                       cqr->status = DASD_CQR_IN_IO;
+               cqr->status = DASD_CQR_IN_IO;
                break;
        case -EBUSY:
                DBF_DEV_EVENT(DBF_ERR, device, "%s",
@@ -1244,14 +876,14 @@ dasd_timeout_device(unsigned long ptr)
        dasd_ccw_req_t *cqr;
 
        device = (dasd_device_t *) ptr;
-       spin_lock_irqsave(get_irq_lock(device->devinfo.irq), flags);
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        /* re-activate first request in queue */
        if (!list_empty(&device->ccw_queue)) {
                cqr = list_entry(device->ccw_queue.next, dasd_ccw_req_t, list);
                if (cqr->status == DASD_CQR_PENDING)
                        cqr->status = DASD_CQR_QUEUED;
        }
-       spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq), flags);
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
        dasd_schedule_bh(device);
 }
 
@@ -1264,18 +896,19 @@ dasd_set_timer(dasd_device_t *device, int expires)
        /* FIXME: timeouts are based on jiffies but the timeout
         * comparision in __dasd_check_expire is based on the
         * TOD clock. */
-       if (expires != 0) {
-               if (!timer_pending(&device->timer)) {
-                       device->timer.function = dasd_timeout_device;
-                       device->timer.data = (unsigned long) device;
-                       device->timer.expires = jiffies + expires;
-                       add_timer(&device->timer);
-               } else
-                       mod_timer(&device->timer, jiffies + expires);
-       } else {
+       if (expires == 0) {
                if (timer_pending(&device->timer))
                        del_timer(&device->timer);
+               return;
        }
+       if (timer_pending(&device->timer)) {
+               if (mod_timer(&device->timer, jiffies + expires))
+                       return;
+       }
+       device->timer.function = dasd_timeout_device;
+       device->timer.data = (unsigned long) device;
+       device->timer.expires = jiffies + expires;
+       add_timer(&device->timer);
 }
 
 /*
@@ -1300,33 +933,36 @@ do_state_change_pending(void *data)
 {
        struct {
                struct work_struct work;
-               unsigned short devno;
+               dasd_device_t *device;
        } *p;
        dasd_devmap_t *devmap;
        dasd_device_t *device;
        dasd_ccw_req_t *cqr;
+       int devno;
 
        p = data;
-       DBF_EVENT(DBF_NOTICE, "State change Interrupt: %04x", p->devno);
+       device = p->device;
+       DBF_EVENT(DBF_NOTICE, "State change Interrupt for bus_id %s",
+                 device->cdev->dev.bus_id);
 
-       devmap = dasd_devmap_from_devno(p->devno);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device)) {
-               MESSAGE(KERN_DEBUG,
-                       "unable to find device for state change pending "
-                       "interrupt: devno%04x", p->devno);
-               return;
-       }
-
-       spin_lock_irq(get_irq_lock(device->devinfo.irq));
+       // FIXME: get rid of devmap.
+       devno = _ccw_device_get_device_number(device->cdev);
+       devmap = dasd_devmap_from_devno(devno);
+       spin_lock_irq(get_ccwdev_lock(device->cdev));
        /* re-activate first request in queue */
        if (!list_empty(&device->ccw_queue)) {
                cqr = list_entry(device->ccw_queue.next, dasd_ccw_req_t, list);
+               if (cqr == NULL) {
+                       MESSAGE (KERN_DEBUG,
+                                "got state change pending interrupt on"
+                                "an idle device: bus_id %s",
+                                device->cdev->dev.bus_id);
+                       return;
+               }
                if (cqr->status == DASD_CQR_PENDING)
                        cqr->status = DASD_CQR_QUEUED;
        }
-       spin_unlock_irq(get_irq_lock(device->devinfo.irq));
+       spin_unlock_irq(get_ccwdev_lock(device->cdev));
        dasd_schedule_bh(device);
        dasd_put_device(devmap);
        kfree(p);
@@ -1334,11 +970,11 @@ do_state_change_pending(void *data)
 
 
 static void
-dasd_handle_state_change_pending(devstat_t * stat)
+dasd_handle_state_change_pending(dasd_device_t *device)
 {
        struct {
                struct work_struct work;
-               unsigned short devno;
+               dasd_device_t *device;
        } *p;
 
        p = kmalloc(sizeof(*p), GFP_ATOMIC);
@@ -1346,7 +982,8 @@ dasd_handle_state_change_pending(devstat_t * stat)
                /* No memory, let the timeout do the reactivation. */
                return;
        INIT_WORK(&p->work, (void *) do_state_change_pending, p);
-       p->devno = stat->devno;
+       p->device = device;
+       atomic_inc(&device->ref_count);
        /* queue call to do_state_change_pending to the kernel event daemon. */
        schedule_work(&p->work);
 }
@@ -1355,71 +992,61 @@ dasd_handle_state_change_pending(devstat_t * stat)
  * Interrupt handler for "normal" ssch-io based dasd devices.
  */
 void
-dasd_int_handler(int irq, void *ds, struct pt_regs *regs)
+dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
+                struct irb *irb)
 {
        dasd_ccw_req_t *cqr, *next;
        dasd_device_t *device;
        unsigned long long now;
        int expires;
        dasd_era_t era;
-       devstat_t *stat;
        char mask;
 
        now = get_clock();
-       stat = (devstat_t *) ds;
 
-       DBF_EVENT(DBF_DEBUG, "Interrupt: IRQ %02x, stat %02x, devno %04x",
-                 irq, stat->dstat, stat->devno);
+       DBF_EVENT(DBF_DEBUG, "Interrupt: stat %02x, bus_id %s",
+                 irb->scsw.dstat, cdev->dev.bus_id);
 
        /* first of all check for state change pending interrupt */
        mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
-       if ((stat->dstat & mask) == mask) {
-               dasd_handle_state_change_pending(stat);
-               return;
-       }
-
-       if (stat->intparm == 0) {       /* no intparm: unsolicited interrupt */
-               MESSAGE(KERN_DEBUG,
-                       "unsolicited interrupt: irq 0x%x devno %04x",
-                       irq, stat->devno);
+       if ((irb->scsw.dstat & mask) == mask) {
+               dasd_handle_state_change_pending(cdev->dev.driver_data);
                return;
        }
 
-       cqr = (dasd_ccw_req_t *) (unsigned long) stat->intparm;
+       cqr = (dasd_ccw_req_t *) intparm;
        /*
         * check status - the request might have been killed
         * because of dyn detach
         */
        if (cqr->status != DASD_CQR_IN_IO) {
                MESSAGE(KERN_DEBUG,
-                       "invalid status: irq 0x%x devno %04x, status %02x",
-                       irq, stat->devno, cqr->status);
+                       "invalid status: bus_id %s, status %02x",
+                       cdev->dev.bus_id, cqr->status);
                return;
        }
 
        device = (dasd_device_t *) cqr->device;
        if (device == NULL ||
-           device != ds - offsetof(dasd_device_t, dev_status) ||
-           device->devinfo.irq != irq ||
+           device != cdev->dev.driver_data ||
            strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
-               MESSAGE(KERN_DEBUG,
-                       "invalid device in request: irq 0x%x devno %04x",
-                       irq, stat->devno);
+               MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
+                       cdev->dev.bus_id);
                return;
        }
 
-       DBF_DEV_EVENT(DBF_DEBUG, device,
-                     "Int: CS/DS 0x%04x", ((stat->cstat << 8) | stat->dstat));
+       DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x",
+                     ((irb->scsw.cstat << 8) | irb->scsw.dstat));
 
        /* Find out the appropriate era_action. */
        era = dasd_era_none;
-       if (stat->flag & DEVSTAT_FLAG_SENSE_AVAIL ||
-           stat->dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) {
+       if (irb->scsw.dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END) ||
+           irb->esw.esw0.erw.cons) {
                /* The request did end abnormally. */
-               if (stat->flag & DEVSTAT_HALT_FUNCTION)
+               if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC)
                        era = dasd_era_fatal;
                else
-                       era = device->discipline->examine_error(cqr, stat);
+                       era = device->discipline->examine_error(cqr, irb);
                DBF_EVENT(DBF_NOTICE, "era_code %d", era);
        }
        expires = 0;
@@ -1440,9 +1067,9 @@ dasd_int_handler(int irq, void *ds, struct pt_regs *regs)
                }
        } else {                /* error */
                if (cqr->dstat == NULL)
-                       cqr->dstat = kmalloc(sizeof(devstat_t), GFP_ATOMIC);
+                       cqr->dstat = kmalloc(sizeof(struct irb), GFP_ATOMIC);
                if (cqr->dstat)
-                       memcpy(cqr->dstat, stat, sizeof (devstat_t));
+                       memcpy(cqr->dstat, irb, sizeof (struct irb));
                else
                        MESSAGE(KERN_ERR, "%s",
                                "no memory for dstat...ignoring");
@@ -1521,7 +1148,7 @@ restart:
                /*  Process requests with DASD_CQR_ERROR */
                if (cqr->status == DASD_CQR_ERROR) {
                        cqr->retries--;
-                       if (cqr->dstat->flag & DEVSTAT_HALT_FUNCTION) {
+                       if (cqr->dstat->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
                                cqr->status = DASD_CQR_FAILED;
                                cqr->stopclk = get_clock();
                        } else {
@@ -1536,7 +1163,7 @@ restart:
                        goto restart;
                }
 
-               /* Rechain request on device device request queue */
+               /* Rechain finished requests to final queue */
                cqr->endclk = get_clock();
                list_move_tail(&cqr->list, final_queue);
        }
@@ -1595,7 +1222,7 @@ __dasd_process_blk_queue(dasd_device_t * device)
                if (device->ro_flag && rq_data_dir(req) == WRITE) {
                        DBF_EVENT(DBF_ERR,
                                  "(%04x) Rejecting write request %p",
-                                 device->devinfo.devno, req);
+                                 device->devno, req);
                        blkdev_dequeue_request(req);
                        dasd_end_request(req, 0);
                        continue;
@@ -1606,7 +1233,7 @@ __dasd_process_blk_queue(dasd_device_t * device)
                                break;  /* terminate request queue loop */
                        DBF_EVENT(DBF_ERR,
                                  "(%04x) CCW creation failed on request %p",
-                                 device->devinfo.devno, req);
+                                 device->devno, req);
                        blkdev_dequeue_request(req);
                        dasd_end_request(req, 0);
                        continue;
@@ -1623,7 +1250,7 @@ __dasd_process_blk_queue(dasd_device_t * device)
 
 /*
  * Take a look at the first request on the ccw queue and check
- * if it reached its expire time.
+ * if it reached its expire time. If so, terminate the IO.
  */
 static inline void
 __dasd_check_expire(dasd_device_t * device)
@@ -1679,7 +1306,7 @@ dasd_flush_ccw_queue(dasd_device_t * device, int all)
        dasd_ccw_req_t *cqr;
 
        INIT_LIST_HEAD(&flush_queue);
-       spin_lock_irq(get_irq_lock(device->devinfo.irq));
+       spin_lock_irq(get_ccwdev_lock(device->cdev));
        list_for_each_safe(l, n, &device->ccw_queue) {
                cqr = list_entry(l, dasd_ccw_req_t, list);
                /* Flush all request or only block device requests? */
@@ -1701,7 +1328,7 @@ dasd_flush_ccw_queue(dasd_device_t * device, int all)
                cqr->endclk = get_clock();
                list_move_tail(&cqr->list, &flush_queue);
        }
-       spin_unlock_irq(get_irq_lock(device->devinfo.irq));
+       spin_unlock_irq(get_ccwdev_lock(device->cdev));
        /* Now call the callback function of flushed requests */
        list_for_each_safe(l, n, &flush_queue) {
                cqr = list_entry(l, dasd_ccw_req_t, list);
@@ -1722,12 +1349,12 @@ dasd_tasklet(dasd_device_t * device)
 
        atomic_set (&device->tasklet_scheduled, 0);
        INIT_LIST_HEAD(&final_queue);
-       spin_lock_irq(get_irq_lock(device->devinfo.irq));
+       spin_lock_irq(get_ccwdev_lock(device->cdev));
        /* Check expire time of first request on the ccw queue. */
        __dasd_check_expire(device);
        /* Finish off requests on ccw queue */
        __dasd_process_ccw_queue(device, &final_queue);
-       spin_unlock_irq(get_irq_lock(device->devinfo.irq));
+       spin_unlock_irq(get_ccwdev_lock(device->cdev));
        /* Now call the callback function of requests with final status */
        list_for_each_safe(l, n, &final_queue) {
                cqr = list_entry(l, dasd_ccw_req_t, list);
@@ -1736,19 +1363,19 @@ dasd_tasklet(dasd_device_t * device)
                        (cqr->callback)(cqr, cqr->callback_data);
        }
        spin_lock_irq(&device->request_queue_lock);
-       spin_lock(get_irq_lock(device->devinfo.irq));
+       spin_lock(get_ccwdev_lock(device->cdev));
        /* Get new request from the block device request queue */
        __dasd_process_blk_queue(device);
        /* Now check if the head of the ccw queue needs to be started. */
        __dasd_start_head(device);
-       spin_unlock(get_irq_lock(device->devinfo.irq));
+       spin_unlock(get_ccwdev_lock(device->cdev));
        spin_unlock_irq(&device->request_queue_lock);
        /* FIXME: what if ref_count == 0 && state == DASD_STATE_NEW ?? */
        atomic_dec(&device->ref_count);
 }
 
 /*
- * Schedules a call to dasd_process_queues over the device tasklet.
+ * Schedules a call to dasd_tasklet over the device tasklet.
  */
 void
 dasd_schedule_bh(dasd_device_t * device)
@@ -1771,13 +1398,13 @@ dasd_add_request_head(dasd_ccw_req_t *req)
        unsigned long flags;
 
        device = req->device;
-       spin_lock_irqsave(get_irq_lock(device->devinfo.irq), flags);
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        req->status = DASD_CQR_QUEUED;
        req->device = device;
        list_add(&req->list, &device->ccw_queue);
        /* let the bh start the request to keep them in order */
        dasd_schedule_bh(device);
-       spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq), flags);
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
 }
 
 /*
@@ -1791,13 +1418,13 @@ dasd_add_request_tail(dasd_ccw_req_t *req)
        unsigned long flags;
 
        device = req->device;
-       spin_lock_irqsave(get_irq_lock(device->devinfo.irq), flags);
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        req->status = DASD_CQR_QUEUED;
        req->device = device;
        list_add_tail(&req->list, &device->ccw_queue);
        /* let the bh start the request to keep them in order */
        dasd_schedule_bh(device);
-       spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq), flags);
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
 }
 
 /*
@@ -1816,9 +1443,9 @@ _wait_for_wakeup(dasd_ccw_req_t *cqr)
        int rc;
 
        device = cqr->device;
-       spin_lock_irq(get_irq_lock(device->devinfo.irq));
+       spin_lock_irq(get_ccwdev_lock(device->cdev));
        rc = cqr->status == DASD_CQR_DONE || cqr->status == DASD_CQR_FAILED;
-       spin_unlock_irq(get_irq_lock(device->devinfo.irq));
+       spin_unlock_irq(get_ccwdev_lock(device->cdev));
        return rc;
 }
 
@@ -1833,7 +1460,7 @@ dasd_sleep_on(dasd_ccw_req_t * cqr)
        int rc;
        
        device = cqr->device;
-       spin_lock_irq(get_irq_lock(device->devinfo.irq));
+       spin_lock_irq(get_ccwdev_lock(device->cdev));
        
        init_waitqueue_head (&wait_q);
        cqr->callback = dasd_wakeup_cb;
@@ -1844,7 +1471,7 @@ dasd_sleep_on(dasd_ccw_req_t * cqr)
        /* let the bh start the request to keep them in order */
        dasd_schedule_bh(device);
        
-       spin_unlock_irq(get_irq_lock(device->devinfo.irq));
+       spin_unlock_irq(get_ccwdev_lock(device->cdev));
 
        wait_event(wait_q, _wait_for_wakeup(cqr));
        
@@ -1865,7 +1492,7 @@ dasd_sleep_on_interruptible(dasd_ccw_req_t * cqr)
        int rc, finished;
 
        device = cqr->device;
-       spin_lock_irq(get_irq_lock(device->devinfo.irq));
+       spin_lock_irq(get_ccwdev_lock(device->cdev));
 
        init_waitqueue_head (&wait_q);
        cqr->callback = dasd_wakeup_cb;
@@ -1875,7 +1502,7 @@ dasd_sleep_on_interruptible(dasd_ccw_req_t * cqr)
 
        /* let the bh start the request to keep them in order */
        dasd_schedule_bh(device);
-       spin_unlock_irq(get_irq_lock(device->devinfo.irq));
+       spin_unlock_irq(get_ccwdev_lock(device->cdev));
 
        finished = 0;
        while (!finished) {
@@ -1885,13 +1512,13 @@ dasd_sleep_on_interruptible(dasd_ccw_req_t * cqr)
                        rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0;
                        break;
                }
-               spin_lock_irq(get_irq_lock(device->devinfo.irq));
+               spin_lock_irq(get_ccwdev_lock(device->cdev));
                if (cqr->status == DASD_CQR_IN_IO &&
                    device->discipline->term_IO(cqr) == 0) {
                        list_del(&cqr->list);
                        finished = 1;
                }
-               spin_unlock_irq(get_irq_lock(device->devinfo.irq));
+               spin_unlock_irq(get_ccwdev_lock(device->cdev));
        }
        return rc;
 }
@@ -1928,10 +1555,10 @@ dasd_sleep_on_immediatly(dasd_ccw_req_t * cqr)
        int rc;
        
        device = cqr->device;
-       spin_lock_irq(get_irq_lock(device->devinfo.irq));
+       spin_lock_irq(get_ccwdev_lock(device->cdev));
        rc = _dasd_term_running_cqr(device);
        if (rc) {
-               spin_unlock_irq(get_irq_lock(device->devinfo.irq));
+               spin_unlock_irq(get_ccwdev_lock(device->cdev));
                return rc;
        }
        
@@ -1944,7 +1571,7 @@ dasd_sleep_on_immediatly(dasd_ccw_req_t * cqr)
        /* let the bh start the request to keep them in order */
        dasd_schedule_bh(device);
        
-       spin_unlock_irq(get_irq_lock(device->devinfo.irq));
+       spin_unlock_irq(get_ccwdev_lock(device->cdev));
 
        wait_event(wait_q, _wait_for_wakeup(cqr));
        
@@ -1966,7 +1593,7 @@ int dasd_cancel_req(dasd_ccw_req_t *cqr)
        int rc;
 
        rc = 0;
-       spin_lock_irqsave(get_irq_lock(device->devinfo.irq), flags);
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        switch (cqr->status) {
        case DASD_CQR_QUEUED:
                /* request was not started - just set to failed */
@@ -1992,7 +1619,7 @@ int dasd_cancel_req(dasd_ccw_req_t *cqr)
                BUG();
 
        }
-       spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq), flags);
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
        dasd_schedule_bh(device);
        return rc;
 }
@@ -2010,12 +1637,12 @@ do_dasd_request(request_queue_t * queue)
        dasd_device_t *device;
 
        device = (dasd_device_t *) queue->queuedata;
-       spin_lock(get_irq_lock(device->devinfo.irq));
+       spin_lock(get_ccwdev_lock(device->cdev));
        /* Get new request from the block device request queue */
        __dasd_process_blk_queue(device);
        /* Now check if the head of the ccw queue needs to be started. */
        __dasd_start_head(device);
-       spin_unlock(get_irq_lock(device->devinfo.irq));
+       spin_unlock(get_ccwdev_lock(device->cdev));
 }
 
 /*
@@ -2088,7 +1715,6 @@ dasd_flush_request_queue(dasd_device_t * device)
 static int
 dasd_open(struct inode *inp, struct file *filp)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
        int rc;
        
@@ -2098,55 +1724,35 @@ dasd_open(struct inode *inp, struct file *filp)
                        major(inp->i_rdev), minor(inp->i_rdev));
                return -EPERM;
        }
-       devmap = dasd_devmap_from_bdev(inp->i_bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device)) {
-               MESSAGE(KERN_WARNING,
-                       "No device registered as (%d:%d)",
-                       major(inp->i_rdev), minor(inp->i_rdev));
-               return PTR_ERR(device);
-       }
+
+       device = inp->i_bdev->bd_disk->private_data;
        if (device->state < DASD_STATE_BASIC) {
                DBF_DEV_EVENT(DBF_ERR, device, " %s",
                              " Cannot open unrecognized device");
-               dasd_put_device(devmap);
                return -ENODEV;
        }
        rc = 0;
-       spin_lock(&discipline_lock);
-       if (atomic_inc_return(&device->open_count) == 1 &&
-           device->discipline->owner != NULL) {
+
+       if (atomic_inc_return(&device->open_count) == 1) {
                if (!try_inc_mod_count(device->discipline->owner)) {
                        /* Discipline is currently unloaded! */
                        atomic_dec(&device->open_count);
                        rc = -ENODEV;
                }
        }
-       spin_unlock(&discipline_lock);
-       dasd_put_device(devmap);
        return rc;
 }
 
 static int
 dasd_release(struct inode *inp, struct file *filp)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
 
-       devmap = dasd_devmap_from_bdev(inp->i_bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device)) {
-               MESSAGE(KERN_WARNING,
-                       "No device registered as %d:%d",
-                       major(inp->i_rdev), minor(inp->i_rdev));
-               return -EINVAL;
-       }
+       device = inp->i_bdev->bd_disk->private_data;
+
        if (device->state < DASD_STATE_ACCEPT) {
                DBF_DEV_EVENT(DBF_ERR, device, " %s",
                              " Cannot release unrecognized device");
-               dasd_put_device(devmap);
                return -EINVAL;
        }
        if (atomic_dec_return(&device->open_count) == 0) {
@@ -2154,7 +1760,6 @@ dasd_release(struct inode *inp, struct file *filp)
                if (device->discipline->owner)
                        __MOD_DEC_USE_COUNT(device->discipline->owner);
        }
-       dasd_put_device(devmap);
        return 0;
 }
 
@@ -2170,18 +1775,6 @@ block_device_operations dasd_device_operations = {
 static void
 dasd_exit(void)
 {
-       dasd_disable_devices(0, dasd_max_devindex);
-#ifdef CONFIG_DASD_DIAG
-       if (MACHINE_IS_VM)
-               dasd_diag_cleanup();
-#endif
-#ifdef CONFIG_DASD_FBA
-       dasd_fba_cleanup();
-#endif
-#ifdef CONFIG_DASD_ECKD
-       dasd_eckd_cleanup();
-#endif
-
 #ifdef CONFIG_PROC_FS
        dasd_proc_exit();
 #endif
@@ -2196,30 +1789,295 @@ dasd_exit(void)
 }
 
 /*
- * SECTION: Initializing the driver
+ * SECTION: common functions for ccw_driver use
  */
-static int
-dasd_request_module(void *name)
-{
-       int rc = -ERESTARTSYS;
-
-       strcpy(current->comm, name);
-       daemonize();
-       while (current->fs->root == NULL)       /* wait for root-FS */
-               schedule_timeout(HZ);   /* wait a second */
-       while ((rc = request_module(name)) != 0) {
-               MESSAGE(KERN_INFO, "request_module returned %d for %s",
-                       rc, (char *) name);
-               schedule_timeout(5 * HZ);       /* wait 5 seconds */
+
+/* initial attempt at a probe function. this can be simplified once
+ * the other detection code is gone */
+int
+dasd_generic_probe (struct ccw_device *cdev, dasd_discipline_t *discipline)
+{
+       int devno;
+       int ret = 0;
+
+       snprintf(cdev->dev.name, DEVICE_NAME_SIZE,
+                "Direct Access Storage Device");
+
+       devno = _ccw_device_get_device_number(cdev);
+       if (dasd_autodetect
+           && (ret = dasd_add_range(devno, devno, DASD_FEATURE_DEFAULT))) {
+               printk (KERN_WARNING
+                       "dasd_generic_probe: cannot autodetect %s\n",
+                       cdev->dev.bus_id);
+               return ret;
+       }
+
+       if (!ret && (ret = dasd_add_sysfs_files(cdev))) {
+               printk(KERN_WARNING
+                      "dasd_generic_probe: could not add driverfs entries"
+                      "for %s\n", cdev->dev.bus_id);
+       }
+
+       cdev->handler = &dasd_int_handler;
+
+       if (dasd_autodetect ||
+           dasd_devmap_from_devno(devno) != 0) {
+               /* => device was in dasd parameter line */
+               ccw_device_set_online(cdev);
+       }
+
+       return ret;
+}
+
+/* this will one day be called from a global not_oper handler.
+ * It is also used by driver_unregister during module unload */
+int
+dasd_generic_remove (struct ccw_device *cdev)
+{
+       struct dasd_device_t *device;
+
+       device = cdev->dev.driver_data;
+       cdev->dev.driver_data = NULL;
+       if (device)
+               kfree(device);
+       return 0;
+}
+
+/* activate a device. This is called from dasd_{eckd,fba}_probe() when either
+ * the device is detected for the first time and is supposed to be used
+ * or the user has started activation through sysfs */
+int
+dasd_generic_set_online (struct ccw_device *cdev,
+                        dasd_discipline_t *discipline)
+
+{
+       int devno;
+       dasd_devmap_t *devmap;
+       dasd_device_t *device;
+       int rc;
+
+       if (cdev->dev.driver_data != NULL) /* already enabled */
+               return 0;
+
+       devno = _ccw_device_get_device_number(cdev);
+       rc = dasd_add_range(devno, devno, DASD_FEATURE_DEFAULT);
+       if (rc)
+               return rc;
+
+       if (!(devmap = dasd_devmap_from_devno (devno)))
+               return 0; /* device is still disabled -> ignore it */
+
+       if (IS_ERR(device = dasd_get_device(devmap))) {
+               printk (KERN_WARNING "dasd_generic could not get %s\n",
+                               cdev->dev.bus_id);
+               return PTR_ERR(device);
+       }
+
+       device->gdp->driverfs_dev = &cdev->dev;
+       device->cdev = cdev;
+
+       if (device->use_diag_flag)
+               device->discipline = dasd_diag_discipline_pointer;
+
+       rc = 0;
+       if (!device->discipline ||
+           (rc = device->discipline->check_device(device))) {
+               pr_debug("device %s is not diag (%d)\n", 
+                        cdev->dev.bus_id, rc);
+               if (device->private != NULL) {
+                       kfree(device->private);
+                       device->private = NULL;
+               }
+               device->discipline = discipline;
+               rc = discipline->check_device(device);
+       }
+
+       if (rc) {
+               printk (KERN_WARNING "dasd_generic found a bad device %s\n", 
+                       cdev->dev.bus_id);
+               dasd_put_device(devmap);
+               return rc;
+       }
+
+       dasd_set_target_state(device, DASD_STATE_ONLINE);
+       if (device->state <= DASD_STATE_KNOWN) {
+               printk (KERN_WARNING
+                       "dasd_generic discipline not found for %s\n",
+                       cdev->dev.bus_id);
+               rc = -ENODEV;
+               dasd_set_target_state(device, DASD_STATE_NEW);
+       } else {
+               pr_debug("dasd_generic device %s found\n",
+                               cdev->dev.bus_id);
+               cdev->dev.driver_data = device;
        }
+
+       dasd_put_device(devmap);
+       /* FIXME: we have to wait for the root device but we don't want
+        * to wait for each single device but for all at once. */
+       wait_event(dasd_init_waitq, _wait_for_device(device));
        return rc;
 }
 
+int
+dasd_generic_set_offline (struct ccw_device *cdev)
+{
+       dasd_device_t *device;
+       dasd_devmap_t *devmap;
+       int devno;
+
+       devno = _ccw_device_get_device_number(cdev);
+       device = cdev->dev.driver_data;
+       devmap = dasd_devmap_from_devno(devno);
+       if (device == NULL || devmap == NULL)
+               return -ENODEV;
+
+       device = dasd_get_device(devmap);
+       if (IS_ERR(device))
+               return PTR_ERR(device);
+
+       dasd_set_target_state(device, DASD_STATE_NEW);
+       dasd_put_device(devmap);
+       
+       return 0;
+}
+
+/*
+ * SECTION: files in sysfs
+ */
+
+/*
+ * readonly controls the readonly status of a dasd
+ */
+static ssize_t
+dasd_ro_show(struct device *dev, char *buf, size_t count, loff_t off)
+{
+       dasd_device_t *device;
+
+       if (off)
+               return 0;
+
+       device = dev->driver_data;
+       if (!device)
+               return snprintf(buf, count, "n/a\n");
+
+       return snprintf(buf, count, device->ro_flag ? "1\n" : "0\n");
+}
+
+static ssize_t
+dasd_ro_store(struct device *dev, const char *buf, size_t count, loff_t off)
+{
+       dasd_device_t *device = dev->driver_data;
+
+       if (off)
+               return 0;
+
+       if (device)
+               device->ro_flag = (buf[0] == '1') ? 1 : 0;
+       return count;
+}
+
+static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
+
+/*
+ * use_diag controls whether the driver should use diag rather than ssch
+ * to talk to the device
+ */
+/* TODO: Implement */
+static ssize_t 
+dasd_use_diag_show(struct device *dev, char *buf, size_t count, loff_t off)
+{
+       dasd_device_t *device;
+
+       if (off)
+               return 0;
+
+       device = dev->driver_data;
+       if (!device)
+               return snprintf(buf, count, "n/a\n");
+
+       return snprintf(buf, count, device->use_diag_flag ? "1\n" : "0\n");
+}
+
+static ssize_t
+dasd_use_diag_store(struct device *dev, const char *buf, 
+                   size_t count, loff_t off)
+{
+       dasd_device_t *device = dev->driver_data;
+
+       if (off)
+               return 0;
+
+       if (device)
+               device->use_diag_flag = (buf[0] == '1') ? 1 : 0;
+       return count;
+}
+
+static
+DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
+
+#if 0
+/* this file shows the same information as /proc/dasd/devices using
+ * an inaccaptable interface */
+/* TODO: Split this up into smaller files! */
+static ssize_t
+dasd_devices_show(struct device *dev, char *buf, size_t count, loff_t off)
+{
+       
+       dasd_device_t *device;
+       dasd_devmap_t *devmap;
+
+       if (off)        /* ignore partial write */
+               return 0;
+
+       devmap = NULL;
+       device = dev->driver_data;
+       if (device)
+               devmap = dasd_devmap_from_devno(device->devno);
+
+       if (!devmap)
+               return snprintf(buf, count, "unused\n");
+
+       return min ((size_t) dasd_devices_print(devmap, buf), count);
+}
+
+static DEVICE_ATTR(dasd, 0444, dasd_devices_show, 0);
+#endif
+
+static ssize_t
+dasd_discipline_show(struct device *dev, char *buf, size_t count, loff_t off)
+{
+       dasd_device_t *device;
+
+       if (off)
+               return 0;
+       device = dev->driver_data;
+       if (!device || !device->discipline)
+               return snprintf(buf, count, "none\n");
+       return snprintf(buf, count, "%s\n", device->discipline->name);
+}
+
+static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, 0);
+
+static int
+dasd_add_sysfs_files(struct ccw_device *cdev)
+{
+       int ret;
+
+       if (/* (ret = device_create_file(&cdev->dev, &dev_attr_dasd)) || */
+           (ret = device_create_file(&cdev->dev, &dev_attr_readonly)) ||
+           (ret = device_create_file(&cdev->dev, &dev_attr_discipline)) ||
+           (ret = device_create_file(&cdev->dev, &dev_attr_use_diag))) {
+               device_remove_file(&cdev->dev, &dev_attr_discipline);
+               device_remove_file(&cdev->dev, &dev_attr_readonly);
+               /* device_remove_file(&cdev->dev, &dev_attr_dasd); */
+       }
+       return ret;
+}
+
 static int __init
 dasd_init(void)
 {
-       char **disc;
-       int irq, devno;
        int rc;
 
        init_waitqueue_head(&dasd_init_waitq);
@@ -2235,7 +2093,7 @@ dasd_init(void)
 
        DBF_EVENT(DBF_EMERG, "%s", "debug area created");
 
-       if (!devfs_mk_dir(NULL, "dasd", NULL)) {
+       if (devfs_mk_dir(NULL, "dasd", NULL)) {
                DBF_EVENT(DBF_ALERT, "%s", "no devfs");
                rc = -ENOSYS;
                goto failed;
@@ -2258,60 +2116,6 @@ dasd_init(void)
                goto failed;
 #endif
 
-       if (dasd_autodetect) {
-               /* update device range to all devices */
-               irq = get_irq_first();
-               while (irq != -ENODEV) {
-                       devno = get_devno_by_irq(irq);
-                       if (dasd_devmap_from_devno(devno) == NULL) {
-                               /* devno not included yet */
-                               DBF_EVENT(DBF_NOTICE, "add %04x to range",
-                                         devno);
-                               dasd_add_range(devno, devno,
-                                              DASD_FEATURE_DEFAULT);
-                       }
-                       irq = get_irq_next(irq);
-               }
-       }
-
-       if (MACHINE_IS_VM) {
-#ifdef CONFIG_DASD_DIAG
-               rc = dasd_diag_init();
-               if (rc != 0) {
-                       DBF_EVENT(DBF_ALERT, "%s",
-                                 "Register DIAG discipline failed");
-                       goto failed;
-               }
-#endif                         /* CONFIG_DASD_DIAG */
-#if defined(CONFIG_DASD_DIAG_MODULE) && defined(CONFIG_DASD_AUTO_DIAG)
-               kernel_thread(dasd_request_module, "dasd_diag_mod", SIGCHLD);
-#endif
-       }
-#ifdef CONFIG_DASD_ECKD
-       rc = dasd_eckd_init();
-       if (rc != 0) {
-               DBF_EVENT(DBF_ALERT, "%s", "Register ECKD discipline failed");
-               goto failed;
-       }
-#endif                         /* CONFIG_DASD_ECKD */
-#if defined(CONFIG_DASD_ECKD_MODULE) && defined(CONFIG_DASD_AUTO_ECKD)
-       kernel_thread(dasd_request_module, "dasd_eckd_mod", SIGCHLD);
-#endif
-#ifdef CONFIG_DASD_FBA
-       rc = dasd_fba_init();
-       if (rc != 0) {
-               DBF_EVENT(DBF_ALERT, "%s", "Register FBA discipline failed");
-               goto failed;
-       }
-#endif
-#if defined(CONFIG_DASD_FBA_MODULE) && defined(CONFIG_DASD_AUTO_FBA)
-       kernel_thread(dasd_request_module, "dasd_fba_mod", SIGCHLD);
-#endif                         /* CONFIG_DASD_AUTO_FBA */
-       disc = dasd_disciplines;
-       while (*disc) {
-               kernel_thread(dasd_request_module, *disc, SIGCHLD);
-               disc++;
-       }
        return 0;
 failed:
        MESSAGE(KERN_INFO, "%s", "initialization not performed due to errors");
@@ -2328,16 +2132,11 @@ EXPORT_SYMBOL(dasd_add_request_head);
 EXPORT_SYMBOL(dasd_add_request_tail);
 EXPORT_SYMBOL(dasd_cancel_req);
 EXPORT_SYMBOL(dasd_clear_timer);
-EXPORT_SYMBOL(dasd_disable_devices);
-EXPORT_SYMBOL(dasd_discipline_add);
-EXPORT_SYMBOL(dasd_discipline_del);
-EXPORT_SYMBOL(dasd_enable_devices);
+EXPORT_SYMBOL(dasd_enable_device);
 EXPORT_SYMBOL(dasd_int_handler);
 EXPORT_SYMBOL(dasd_kfree_request);
 EXPORT_SYMBOL(dasd_kick_device);
 EXPORT_SYMBOL(dasd_kmalloc_request);
-EXPORT_SYMBOL(dasd_not_oper_handler);
-EXPORT_SYMBOL(dasd_oper_handler);
 EXPORT_SYMBOL(dasd_schedule_bh);
 EXPORT_SYMBOL(dasd_set_target_state);
 EXPORT_SYMBOL(dasd_set_timer);
index e2cdce22434585d2edeeea635e65f9b4c68efe6f..69e8ab439a52d47d2ce3acd91873ad446e30bf58 100644 (file)
@@ -3,6 +3,11 @@
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ *
+ * $Revision: 1.7 $
+ *
+ * History of changes 
+ *
  */
 
 #define PRINTK_HEADER "dasd_erp(3370)"
  *   dasd_era_recover  for all others.
  */
 dasd_era_t
-dasd_3370_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
+dasd_3370_erp_examine(dasd_ccw_req_t * cqr, struct irb * irb)
 {
-       char *sense = stat->ii.sense.data;
+       char *sense = irb->ecw;
 
        /* check for successful execution first */
-       if (stat->cstat == 0x00 &&
-           stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+       if (irb->scsw.cstat == 0x00 &&
+           irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
                return dasd_era_none;
        if (sense[0] & 0x80) {  /* CMD reject */
                return dasd_era_fatal;
diff --git a/drivers/s390/block/dasd_3370_erp.h b/drivers/s390/block/dasd_3370_erp.h
deleted file mode 100644 (file)
index aca38bc..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* 
- * File...........: linux/drivers/s390/block/dasd_3370_erp.h
- * Author(s)......: Horst Hummel <Horst Hummel@de.ibm.com>
- * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
- *
- * History of changes (starts July 2000)
- */
-
-#ifndef DASD_3370_ERP_H
-#define DASD_3370_ERP_H
-
-dasd_era_t dasd_3370_erp_examine(dasd_ccw_req_t *, devstat_t *);
-
-#endif                         /* DASD_3990_ERP_H */
index 23a8998fdd3ea2bc3ed377dfe9e50af7aaff1433..7539b8a1d8c87bb8d5d89f703944febf5b7f95ae 100644 (file)
@@ -5,6 +5,8 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
  *
+ * $Revision: 1.19 $
+ *
  * History of changes:
  * 05/14/01 fixed PL030160GTO (BUG() in erp_action_5)
  * 05/04/02 code restructuring.
@@ -13,7 +15,6 @@
 #include <linux/timer.h>
 #include <linux/slab.h>
 #include <asm/idals.h>
-#include <asm/s390io.h>
 #include <asm/todclk.h>
 
 #define PRINTK_HEADER "dasd_erp(3990): "
@@ -148,16 +149,16 @@ dasd_3990_erp_examine_32(dasd_ccw_req_t * cqr, char *sense)
  *   dasd_era_recover  for all others.
  */
 dasd_era_t
-dasd_3990_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
+dasd_3990_erp_examine(dasd_ccw_req_t * cqr, struct irb * irb)
 {
 
-       char *sense = stat->ii.sense.data;
+       char *sense = irb->ecw;
        dasd_era_t era = dasd_era_recover;
        dasd_device_t *device = cqr->device;
 
        /* check for successful execution first */
-       if (stat->cstat == 0x00 &&
-           stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+       if (irb->scsw.cstat == 0x00 &&
+           irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
                return dasd_era_none;
 
        /* distinguish between 24 and 32 byte sense data */
@@ -172,8 +173,10 @@ dasd_3990_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
        }
 
        /* log the erp chain if fatal error occurred */
-       if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY))
-               dasd_log_ccw(cqr, 0, stat->cpa);
+       if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) {
+               dasd_log_sense(cqr, irb);
+               dasd_log_ccw(cqr, 0, irb->scsw.cpa);
+       }
 
        return era;
 
@@ -296,42 +299,39 @@ dasd_3990_erp_int_req(dasd_ccw_req_t * erp)
  *
  * RETURN VALUES
  *   erp               modified pointer to the ERP
- *
  */
 static void
 dasd_3990_erp_alternate_path(dasd_ccw_req_t * erp)
 {
-
        dasd_device_t *device = erp->device;
-       int irq = device->devinfo.irq;
+       __u8 opm;
 
        /* try alternate valid path */
-       erp->lpm &= ~(erp->dstat->lpum);
-       erp->options |= DOIO_VALID_LPM; /* use LPM for DO_IO */
+       opm = ccw_device_get_path_mask(device->cdev);
+       //FIXME: start with get_opm ?
+       if (erp->lpm == 0)
+               erp->lpm = LPM_ANYPATH & ~(erp->dstat->esw.esw0.sublog.lpum);
+       else
+               erp->lpm &= ~(erp->dstat->esw.esw0.sublog.lpum);
 
-       if ((erp->lpm & ioinfo[irq]->opm) != 0x00) {
+       if ((erp->lpm & opm) != 0x00) {
 
                DEV_MESSAGE(KERN_DEBUG, device,
                            "try alternate lpm=%x (lpum=%x / opm=%x)",
-                           erp->lpm, erp->dstat->lpum, ioinfo[irq]->opm);
+                           erp->lpm, erp->dstat->esw.esw0.sublog.lpum, opm);
 
                /* reset status to queued to handle the request again... */
                erp->status = DASD_CQR_QUEUED;
-
                erp->retries = 1;
-
        } else {
-
                DEV_MESSAGE(KERN_ERR, device,
                            "No alternate channel path left (lpum=%x / "
                            "opm=%x) -> permanent error",
-                           erp->dstat->lpum, ioinfo[irq]->opm);
+                           erp->dstat->esw.esw0.sublog.lpum, opm);
 
                /* post request with permanent error */
                erp->status = DASD_CQR_FAILED;
-
        }
-
 }                              /* end dasd_3990_erp_alternate_path */
 
 /*
@@ -355,7 +355,7 @@ dasd_3990_erp_DCTL(dasd_ccw_req_t * erp, char modifier)
 
        dasd_device_t *device = erp->device;
        DCTL_data_t *DCTL_data;
-       ccw1_t *ccw;
+       struct ccw1 *ccw;
        dasd_ccw_req_t *dctl_cqr;
 
        dctl_cqr = dasd_alloc_erp_request((char *) &erp->magic, 1,
@@ -373,7 +373,7 @@ dasd_3990_erp_DCTL(dasd_ccw_req_t * erp, char modifier)
        DCTL_data->modifier = modifier;
 
        ccw = dctl_cqr->cpaddr;
-       memset(ccw, 0, sizeof (ccw1_t));
+       memset(ccw, 0, sizeof (struct ccw1));
        ccw->cmd_code = CCW_CMD_DCTL;
        ccw->count = 4;
        ccw->cda = (__u32)(addr_t) DCTL_data;
@@ -381,7 +381,6 @@ dasd_3990_erp_DCTL(dasd_ccw_req_t * erp, char modifier)
        dctl_cqr->refers = erp;
        dctl_cqr->device = erp->device;
        dctl_cqr->magic = erp->magic;
-       dctl_cqr->lpm = LPM_ANYPATH;
        dctl_cqr->expires = 5 * 60 * HZ;
        dctl_cqr->retries = 2;
 
@@ -1122,6 +1121,9 @@ dasd_3990_handle_env_data(dasd_ccw_req_t * erp, char *sense)
                break;
 
        default:        /* unknown message format - should not happen */
+               DEV_MESSAGE (KERN_WARNING, device,
+                             "unknown message format %02x",
+                             msg_format);
                break;
        }                       /* end switch message format */
 
@@ -1650,7 +1652,7 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
        dasd_ccw_req_t *erp;
        DE_eckd_data_t *DE_data;
        char *LO_data;          /* LO_eckd_data_t */
-       ccw1_t *ccw;
+       struct ccw1 *ccw;
 
        DEV_MESSAGE(KERN_DEBUG, device, "%s",
                    "Write not finished because of unexpected condition");
@@ -1675,7 +1677,7 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
 
        /* determine the address of the CCW to be restarted */
        /* Imprecise ending is not set -> addr from IRB-SCSW */
-       cpa = default_erp->refers->dstat->cpa;
+       cpa = default_erp->refers->dstat->scsw.cpa;
 
        if (cpa == 0) {
 
@@ -1735,7 +1737,7 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
 
        /* create DE ccw */
        ccw = erp->cpaddr;
-       memset(ccw, 0, sizeof (ccw1_t));
+       memset(ccw, 0, sizeof (struct ccw1));
        ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
        ccw->flags = CCW_FLAG_CC;
        ccw->count = 16;
@@ -1743,7 +1745,7 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
 
        /* create LO ccw */
        ccw++;
-       memset(ccw, 0, sizeof (ccw1_t));
+       memset(ccw, 0, sizeof (struct ccw1));
        ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
        ccw->flags = CCW_FLAG_CC;
        ccw->count = 16;
@@ -1759,7 +1761,6 @@ dasd_3990_erp_action_1B_32(dasd_ccw_req_t * default_erp, char *sense)
        erp->refers = default_erp->refers;
        erp->device = device;
        erp->magic = default_erp->magic;
-       erp->lpm = 0xFF;
        erp->expires = 0;
        erp->retries = 256;
        erp->status = DASD_CQR_FILLED;
@@ -1795,7 +1796,7 @@ dasd_3990_update_1B(dasd_ccw_req_t * previous_erp, char *sense)
        dasd_ccw_req_t *cqr;
        dasd_ccw_req_t *erp;
        char *LO_data;          /* LO_eckd_data_t */
-       ccw1_t *ccw;
+       struct ccw1 *ccw;
 
        DEV_MESSAGE(KERN_DEBUG, device, "%s",
                    "Write not finished because of unexpected condition"
@@ -1821,7 +1822,7 @@ dasd_3990_update_1B(dasd_ccw_req_t * previous_erp, char *sense)
 
        /* determine the address of the CCW to be restarted */
        /* Imprecise ending is not set -> addr from IRB-SCSW */
-       cpa = previous_erp->dstat->cpa;
+       cpa = previous_erp->dstat->scsw.cpa;
 
        if (cpa == 0) {
 
@@ -1954,7 +1955,7 @@ dasd_3990_erp_compound_path(dasd_ccw_req_t * erp, char *sense)
                        /* reset the lpm and the status to be able to 
                         * try further actions. */
 
-                       erp->lpm = LPM_ANYPATH;
+                       erp->lpm = 0;
 
                        erp->status = DASD_CQR_ERROR;
 
@@ -2234,7 +2235,7 @@ dasd_3990_erp_inspect(dasd_ccw_req_t * erp)
        dasd_ccw_req_t *erp_new = NULL;
        /* sense data are located in the refers record of the */
        /* already set up new ERP !                           */
-       char *sense = erp->refers->dstat->ii.sense.data;
+       char *sense = erp->refers->dstat->ecw;
 
        /* distinguish between 24 and 32 byte sense data */
        if (sense[27] & DASD_SENSE_BIT_0) {
@@ -2291,7 +2292,6 @@ dasd_3990_erp_add_erp(dasd_ccw_req_t * cqr)
        erp->refers = cqr;
        erp->device = cqr->device;
        erp->magic = cqr->magic;
-       erp->lpm = 0xFF;
        erp->expires = 0;
        erp->retries = 256;
 
@@ -2357,18 +2357,14 @@ dasd_3990_erp_error_match(dasd_ccw_req_t * cqr1, dasd_ccw_req_t * cqr2)
 {
 
        /* check failed CCW */
-       if (cqr1->dstat->cpa != cqr2->dstat->cpa) {
+       if (cqr1->dstat->scsw.cpa != cqr2->dstat->scsw.cpa) {
                //      return 0;       /* CCW doesn't match */
        }
 
        /* check sense data; byte 0-2,25,27 */
-       if (!((strncmp(cqr1->dstat->ii.sense.data,
-                      cqr2->dstat->ii.sense.data,
-                      3) == 0) &&
-             (cqr1->dstat->ii.sense.data[27] ==
-              cqr2->dstat->ii.sense.data[27]) &&
-             (cqr1->dstat->ii.sense.data[25] ==
-              cqr2->dstat->ii.sense.data[25]))) {
+       if (!((strncmp(cqr1->dstat->ecw, cqr2->dstat->ecw, 3) == 0) &&
+             (cqr1->dstat->ecw[27] == cqr2->dstat->ecw[27]) &&
+             (cqr1->dstat->ecw[25] == cqr2->dstat->ecw[25]))) {
 
                return 0;       /* sense doesn't match */
        }
@@ -2441,7 +2437,7 @@ dasd_3990_erp_further_erp(dasd_ccw_req_t * erp)
 {
 
        dasd_device_t *device = erp->device;
-       char *sense = erp->dstat->ii.sense.data;
+       char *sense = erp->dstat->ecw;
 
        /* check for 24 byte sense ERP */
        if ((erp->function == dasd_3990_erp_bus_out) ||
@@ -2553,7 +2549,7 @@ dasd_3990_erp_handle_match_erp(dasd_ccw_req_t * erp_head, dasd_ccw_req_t * erp)
 
        if (erp->retries > 0) {
 
-               char *sense = erp->dstat->ii.sense.data;
+               char *sense = erp->dstat->ecw;
 
                /* check for special retries */
                if (erp->function == dasd_3990_erp_action_4) {
@@ -2611,7 +2607,7 @@ dasd_3990_erp_action(dasd_ccw_req_t * cqr)
 
        dasd_ccw_req_t *erp = NULL;
        dasd_device_t *device = cqr->device;
-       __u32 cpa = cqr->dstat->cpa;
+       __u32 cpa = cqr->dstat->scsw.cpa;
 
 #ifdef ERP_DEBUG
        /* print current erp_chain */
@@ -2631,8 +2627,8 @@ dasd_3990_erp_action(dasd_ccw_req_t * cqr)
 #endif                         /* ERP_DEBUG */
 
        /* double-check if current erp/cqr was successfull */
-       if ((cqr->dstat->cstat == 0x00) &&
-           (cqr->dstat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) {
+       if ((cqr->dstat->scsw.cstat == 0x00) &&
+           (cqr->dstat->scsw.dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END))) {
 
                DEV_MESSAGE(KERN_DEBUG, device,
                            "ERP called for successful request %p"
@@ -2643,7 +2639,7 @@ dasd_3990_erp_action(dasd_ccw_req_t * cqr)
                return cqr;
        }
        /* check if sense data are available */
-       if (!cqr->dstat->ii.sense.data) {
+       if (!cqr->dstat->ecw) {
                DEV_MESSAGE(KERN_DEBUG, device,
                            "ERP called witout sense data avail ..."
                            "request %p - NO ERP possible", cqr);
diff --git a/drivers/s390/block/dasd_3990_erp.h b/drivers/s390/block/dasd_3990_erp.h
deleted file mode 100644 (file)
index bc19c59..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* 
- * File...........: linux/drivers/s390/block/dasd_3990_erp.h
- * Author(s)......: Horst Hummel <Horst Hummel@de.ibm.com>
- * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
- *
- * History of changes (starts July 2000)
- */
-
-#ifndef DASD_3990_ERP_H
-#define DASD_3990_ERP_H
-
-dasd_era_t dasd_3990_erp_examine(dasd_ccw_req_t *, devstat_t *);
-
-dasd_ccw_req_t *dasd_3990_erp_action(dasd_ccw_req_t *);
-dasd_ccw_req_t *dasd_2105_erp_action(ccw_req_t *);
-
-void dasd_3990_erp_restart_queue(unsigned long);
-
-typedef struct DCTL_data_t {
-       unsigned char subcommand;       /* e.g Inhibit Write, Enable Write,... */
-       unsigned char modifier; /* Subcommand modifier                 */
-       unsigned short res;     /* reserved */
-} __attribute__ ((packed)) DCTL_data_t;
-
-#endif                         /* DASD_3990_ERP_H */
index 0b0643a23e69c5e322d8985f9f08df84173e7fd0..897fca6a626add646234e6704ee5df8d4f02c050 100644 (file)
@@ -3,6 +3,11 @@
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ *
+ * $Revision: 1.6 $
+ *
+ * History of changes 
+ *
  */
 
 #define PRINTK_HEADER "dasd_erp(9336)"
  *   dasd_era_recover  for all others.
  */
 dasd_era_t
-dasd_9336_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
+dasd_9336_erp_examine(dasd_ccw_req_t * cqr, struct irb * irb)
 {
        /* check for successful execution first */
-       if (stat->cstat == 0x00 &&
-           stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+       if (irb->scsw.cstat == 0x00 &&
+           irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
                return dasd_era_none;
 
        /* examine the 24 byte sense data */
diff --git a/drivers/s390/block/dasd_9336_erp.h b/drivers/s390/block/dasd_9336_erp.h
deleted file mode 100644 (file)
index e15e89d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* 
- * File...........: linux/drivers/s390/block/dasd_9336_erp.h
- * Author(s)......: Horst Hummel <Horst Hummel@de.ibm.com>
- * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
- *
- * History of changes (starts July 2000)
- */
-
-#ifndef DASD_9336_ERP_H
-#define DASD_9336_ERP_H
-
-dasd_era_t dasd_9336_erp_examine(dasd_ccw_req_t *, devstat_t *);
-
-#endif                         /* DASD_3990_ERP_H */
index dd59f4768c8d1427ea1b8c53cb98f3f7caa2e298..1a0c7b9080f7d74bcd9b59b7cc04b0ee005de4df 100644 (file)
@@ -1,8 +1,13 @@
 /* 
- * File...........: linux/drivers/s390/block/dasd_9345_erp.h
+ * File...........: linux/drivers/s390/block/dasd_9345_erp.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ *
+ * $Revision: 1.11 $
+ *
+ * History of changes 
+ * 
  */
 
 #define PRINTK_HEADER "dasd_erp(9343)"
 #include "dasd_int.h"
 
 dasd_era_t
-dasd_9343_erp_examine(dasd_ccw_req_t * cqr, devstat_t * stat)
+dasd_9343_erp_examine(dasd_ccw_req_t * cqr, struct irb * irb)
 {
-       if (stat->cstat == 0x00 &&
-           stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+       if (irb->scsw.cstat == 0x00 &&
+           irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
                return dasd_era_none;
+
        return dasd_era_recover;
 }
diff --git a/drivers/s390/block/dasd_9343_erp.h b/drivers/s390/block/dasd_9343_erp.h
deleted file mode 100644 (file)
index 82b76f7..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 
- * File...........: linux/drivers/s390/block/dasd_9343_erp.h
- * Author(s)......: Horst Hummel <Horst Hummel@de.ibm.com>
- * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
- *
- * History of changes (starts July 2000)
- */
-
-#ifndef DASD_9343_ERP_H
-#define DASD_9343_ERP_H
-
-dasd_era_t dasd_9343_erp_examine(dasd_ccw_req_t *, devstat_t *);
-
-dasd_ccw_req_t *dasd_9343_erp_action(dasd_ccw_req_t *);
-
-#endif                         /* DASD_9343_ERP_H */
index 27c3f2416150370d6163a79955be16775c09c0b0..6ead754e9bbe99bb6ffccc24df822870f329d40a 100644 (file)
@@ -11,6 +11,9 @@
  * functions may not be called from interrupt context. In particular
  * dasd_get_device is a no-no from interrupt context.
  *
+ * $Revision: 1.11 $
+ *
+ * History of changes 
  * 05/04/02 split from dasd.c, code restructuring.
  */
 
@@ -20,7 +23,6 @@
 #include <linux/init.h>
 
 #include <asm/debug.h>
-#include <asm/irq.h>
 #include <asm/uaccess.h>
 
 /* This is ugly... */
@@ -84,9 +86,11 @@ __setup ("dasd=", dasd_call_setup);
  * Read a device number from a string. The number is always in hex,
  * a leading 0x is accepted.
  */
-int
+static inline int
 dasd_devno(char *str, char **endp)
 {
+       int val;
        /* remove leading '0x' */
        if (*str == '0') {
                str++;
@@ -96,7 +100,10 @@ dasd_devno(char *str, char **endp)
        /* We require at least one hex digit */
        if (!isxdigit(*str))
                return -EINVAL;
-       return simple_strtoul(str, endp, 16);
+       val = simple_strtoul(str, endp, 16);
+       if ((val > 0xFFFF) || (val < 0))
+               return -EINVAL;
+       return val;
 }
 
 /*
@@ -104,7 +111,7 @@ dasd_devno(char *str, char **endp)
  * only one: "ro" for read-only devices. The default feature set
  * is empty (value 0).
  */
-int
+static inline int
 dasd_feature_list(char *str, char **endp)
 {
        int features, len, rc;
@@ -260,64 +267,12 @@ dasd_add_range(int from, int to, int features)
                        devmap->devindex = devindex;
                        devmap->devno = devno;
                        devmap->features = features;
-                       devmap->devreg = NULL;
                        devmap->device = NULL;
                        list_add(&devmap->devindex_list,
                                 &dasd_devindex_hashlists[devindex & 255]);
                        list_add(&devmap->devno_list,
                                 &dasd_devno_hashlists[devno & 255]);
                }
-               if (devmap->devreg == NULL) {
-                       /* The devreg is missing. */
-                       devmap->devreg = (devreg_t *)
-                               kmalloc(sizeof(devreg_t), GFP_KERNEL);
-                       if (devmap->devreg == NULL)
-                               return -ENOMEM;
-                       memset(devmap->devreg, sizeof(devreg_t), 0);
-                       devmap->devreg->ci.devno = devno;
-                       devmap->devreg->flag = DEVREG_TYPE_DEVNO;
-                       devmap->devreg->oper_func = dasd_oper_handler;
-                       s390_device_register(devmap->devreg);
-               }
-       }
-       spin_unlock(&dasd_devmap_lock);
-       return 0;
-}
-
-/*
- * Removes the devreg_t structures for a range of devices. This does
- * NOT remove the range itself. The mapping between devno and kdevs
- * for the devices is remembered until dasd_forget_ranges() is called.
- */
-static int
-dasd_clear_range(int from, int to)
-{
-       int devno;
-
-       if (from > to) {
-               MESSAGE(KERN_ERR,
-                       "Invalid device range %04x-%04x", from, to);
-               return -EINVAL;
-       }
-       spin_lock(&dasd_devmap_lock);
-       for (devno = from; devno <= to; devno++) {
-               struct list_head *l;
-               dasd_devmap_t *devmap = NULL;
-               /* Find previous devmap for device number i */
-               list_for_each(l, &dasd_devno_hashlists[devno & 255]) {
-                       devmap = list_entry(l, dasd_devmap_t, devno_list);
-                       if (devmap->devno == devno)
-                               break;
-               }
-               if (devmap == NULL)
-                       continue;
-               if (devmap->device != NULL)
-                       BUG();
-               if (devmap->devreg == NULL)
-                       continue;
-               s390_device_unregister(devmap->devreg);
-               kfree(devmap->devreg);
-               devmap->devreg = NULL;
        }
        spin_unlock(&dasd_devmap_lock);
        return 0;
@@ -340,11 +295,6 @@ dasd_forget_ranges(void)
                        devmap = list_entry(l, dasd_devmap_t, devno_list);
                        if (devmap->device != NULL)
                                BUG();
-                       if (devmap->devreg != NULL) {
-                               s390_device_unregister(devmap->devreg);
-                               kfree(devmap->devreg);
-                               devmap->devreg = NULL;
-                       }
                        list_del(&devmap->devindex_list);
                        list_del(&devmap->devno_list);
                        kfree(devmap);
@@ -403,52 +353,6 @@ dasd_devmap_from_devindex(int devindex)
        return devmap;
 }
 
-/*
- * Find the devmap for a device by its irq line.
- */
-dasd_devmap_t *
-dasd_devmap_from_irq(int irq)
-{
-       struct list_head *l;
-       dasd_devmap_t *devmap, *tmp;
-       int i;
-
-       devmap = NULL;
-       spin_lock(&dasd_devmap_lock);
-       for (i = 0; (i < 256) && (devmap == NULL); i++) {
-               list_for_each(l, &dasd_devno_hashlists[i & 255]) {
-                       tmp = list_entry(l, dasd_devmap_t, devno_list);
-                       if (tmp->device != NULL &&
-                           tmp->device->devinfo.irq == irq) {
-                               devmap = tmp;
-                               break;
-                       }
-               }
-       }
-       spin_unlock(&dasd_devmap_lock);
-       return devmap;
-}
-
-/*
- * Find the devmap for a device corresponding to a block_device.
- */
-dasd_devmap_t *
-dasd_devmap_from_bdev(struct block_device *bdev)
-{
-       kdev_t kdev = to_kdev_t(bdev->bd_dev);
-       int devindex;
-
-       /* Find the devindex for kdev. */
-       devindex = dasd_gendisk_major_index(major(kdev));
-       if (devindex < 0)
-               /* No such major -> no devmap */
-               return NULL;
-       devindex += minor(kdev) >> DASD_PARTN_BITS;
-
-       /* Now find the devmap by the devindex. */
-       return dasd_devmap_from_devindex(devindex);
-}
-
 /*
  * Find the device structure for device number devno. If it does not
  * exists yet, allocate it. Increase the reference counter in the device
@@ -479,6 +383,8 @@ dasd_get_device(dasd_devmap_t *devmap)
        } else
                devmap->device = device;
        atomic_inc(&device->ref_count);
+       device->ro_flag = (devmap->features & DASD_FEATURE_READONLY) ? 1 : 0;
+       device->use_diag_flag = 1;
        spin_unlock(&dasd_devmap_lock);
        return device;
 }
@@ -523,9 +429,3 @@ dasd_devmap_exit(void)
 {
        dasd_forget_ranges();
 }
-
-EXPORT_SYMBOL(dasd_devmap_from_devno);
-EXPORT_SYMBOL(dasd_devmap_from_devindex);
-EXPORT_SYMBOL(dasd_devmap_from_irq);
-EXPORT_SYMBOL(dasd_get_device);
-EXPORT_SYMBOL(dasd_put_device);
index cbf8818e316b4cc46d5a977bc0bd735ed324fe4b..12af93a2dec9e4d88072461f9c54034aebff096a 100644 (file)
@@ -5,7 +5,9 @@
  * ...............: by Hartmunt Penner <hpenner@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
-
+ *
+ * $Revision: 1.27 $
+ *
  * History of changes
  * 07/13/00 Added fixup sections for diagnoses ans saved some registers
  * 07/14/00 fixed constraints in newly generated inline asm
 #include <linux/slab.h>
 #include <linux/hdreg.h>       /* HDIO_GETGEO                      */
 #include <linux/bio.h>
+#include <linux/module.h>
+#include <linux/init.h>
 
 #include <asm/dasd.h>
 #include <asm/debug.h>
 #include <asm/ebcdic.h>
 #include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/s390dyn.h>
 #include <asm/s390_ext.h>
 #include <asm/todclk.h>
 
@@ -40,7 +42,7 @@
 #endif                         /* PRINTK_HEADER */
 #define PRINTK_HEADER "dasd(diag):"
 
-static dasd_discipline_t dasd_diag_discipline;
+MODULE_LICENSE("GPL");
 
 typedef struct dasd_diag_private_t {
        dasd_diag_characteristics_t rdc_data;
@@ -57,25 +59,30 @@ typedef struct dasd_diag_req_t {
 static __inline__ int
 dia250(void *iob, int cmd)
 {
-       __asm__ __volatile__("    lr    0,%1\n"
-                            "    diag  0,%0,0x250\n"
+       int rc;
+
+       __asm__ __volatile__("    lhi   %0,3\n"
+                            "    lr    0,%2\n"
+                            "    diag  0,%1,0x250\n"
                             "0:  ipm   %0\n"
                             "    srl   %0,28\n"
                             "    or    %0,1\n"
                             "1:\n"
-                            ".section .fixup,\"ax\"\n"
-                            "2:  lhi   %0,3\n"
-                            "    bras  1,3f\n"
-                            "    .long 1b\n"
-                            "3:  l     1,0(1)\n"
-                            "    br    1\n"
-                            ".previous\n"
+#ifndef CONFIG_ARCH_S390X
                             ".section __ex_table,\"a\"\n"
                             "    .align 4\n"
-                            "    .long 0b,2b\n" ".previous\n":"+d"(cmd)
-                            :"d"((void *) __pa(iob))
-                            :"0", "1", "cc");
-       return cmd;
+                            "    .long 0b,1b\n"
+                            ".previous\n"
+#else
+                            ".section __ex_table,\"a\"\n"
+                            "    .align 8\n"
+                            "    .quad  0b,1b\n"
+                            ".previous\n"
+#endif
+                            : "=&d" (rc)
+                            : "d" (cmd), "d" ((void *) __pa(iob))
+                            : "0", "1", "cc");
+       return rc;
 }
 
 static __inline__ int
@@ -89,7 +96,7 @@ mdsk_init_io(dasd_device_t * device, int blocksize, int offset, int size)
        iib = &private->iib;
        memset(iib, 0, sizeof (diag_init_io_t));
 
-       iib->dev_nr = device->devinfo.devno;
+       iib->dev_nr = device->devno;
        iib->block_size = blocksize;
        iib->offset = offset;
        iib->start_block = 0;
@@ -110,7 +117,7 @@ mdsk_term_io(dasd_device_t * device)
        private = (dasd_diag_private_t *) device->private;
        iib = &private->iib;
        memset(iib, 0, sizeof (diag_init_io_t));
-       iib->dev_nr = device->devinfo.devno;
+       iib->dev_nr = device->devno;
        rc = dia250(iib, TERM_BIO);
        return rc & 3;
 }
@@ -127,7 +134,7 @@ dasd_start_diag(dasd_ccw_req_t * cqr)
        private = (dasd_diag_private_t *) device->private;
        dreq = (dasd_diag_req_t *) cqr->data;
 
-       private->iob.dev_nr = device->devinfo.devno;
+       private->iob.dev_nr = device->devno;
        private->iob.key = 0;
        private->iob.flags = 2; /* do asynchronous io */
        private->iob.block_count = dreq->block_count;
@@ -191,7 +198,7 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
        }
 
        /* get irq lock to modify request queue */
-       spin_lock_irqsave(get_irq_lock(device->devinfo.irq), flags);
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
 
        cqr->stopclk = get_clock();
 
@@ -219,7 +226,7 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
                dasd_clear_timer(device);
        dasd_schedule_bh(device);
 
-       spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq), flags);
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
        irq_exit();
 }
 
@@ -245,10 +252,10 @@ dasd_diag_check_device(dasd_device_t *device)
        }
        /* Read Device Characteristics */
        rdc_data = (void *) &(private->rdc_data);
-       rdc_data->dev_nr = device->devinfo.devno;
+       rdc_data->dev_nr = device->devno;
        rdc_data->rdc_len = sizeof (dasd_diag_characteristics_t);
 
-       rc = diag210((diag210_t *) rdc_data);
+       rc = diag210((struct diag210 *) rdc_data);
        if (rc)
                return -ENOTSUPP;
 
@@ -328,7 +335,7 @@ dasd_diag_fill_geometry(dasd_device_t *device, struct hd_geometry *geo)
 }
 
 static dasd_era_t
-dasd_diag_examine_error(dasd_ccw_req_t * cqr, devstat_t * stat)
+dasd_diag_examine_error(dasd_ccw_req_t * cqr, struct irb * stat)
 {
        return dasd_era_fatal;
 }
@@ -433,7 +440,8 @@ dasd_diag_fill_info(dasd_device_t * device, dasd_information2_t * info)
 }
 
 static void
-dasd_diag_dump_sense(dasd_device_t *device, dasd_ccw_req_t * req)
+dasd_diag_dump_sense(dasd_device_t *device, dasd_ccw_req_t * req,
+                    struct irb *stat)
 {
        char *page;
 
@@ -443,8 +451,8 @@ dasd_diag_dump_sense(dasd_device_t *device, dasd_ccw_req_t * req)
                return;
        }
        sprintf(page, KERN_WARNING PRINTK_HEADER
-               "device %04X on irq %d: I/O status report:\n",
-               device->devinfo.devno, device->devinfo.irq);
+               "device %s: I/O status report:\n",
+               device->cdev->dev.bus_id);
 
        MESSAGE(KERN_ERR, "Sense data:\n%s", page);
 
@@ -463,7 +471,7 @@ dasd_diag_dump_sense(dasd_device_t *device, dasd_ccw_req_t * req)
  * start the next request if one finishes off. That makes 252.75 blocks
  * for one request. Give a little safety and the result is 240.
  */
-static dasd_discipline_t dasd_diag_discipline = {
+dasd_discipline_t dasd_diag_discipline = {
        .owner = THIS_MODULE,
        .name = "DIAG",
        .ebcname = "DIAG",
@@ -479,7 +487,7 @@ static dasd_discipline_t dasd_diag_discipline = {
        .fill_info = dasd_diag_fill_info,
 };
 
-int
+static int __init
 dasd_diag_init(void)
 {
        if (!MACHINE_IS_VM) {
@@ -489,13 +497,13 @@ dasd_diag_init(void)
                return -EINVAL;
        }
        ASCEBC(dasd_diag_discipline.ebcname, 4);
+
        ctl_set_bit(0, 9);
        register_external_interrupt(0x2603, dasd_ext_handler);
-       dasd_discipline_add(&dasd_diag_discipline);
        return 0;
 }
 
-void
+static void __exit
 dasd_diag_cleanup(void)
 {
        if (!MACHINE_IS_VM) {
@@ -504,24 +512,12 @@ dasd_diag_cleanup(void)
                        dasd_diag_discipline.name);
                return;
        }
-       dasd_discipline_del(&dasd_diag_discipline);
        unregister_external_interrupt(0x2603, dasd_ext_handler);
        ctl_clear_bit(0, 9);
 }
 
-#ifdef MODULE
-int
-init_module(void)
-{
-       return dasd_diag_init();
-}
-
-void
-cleanup_module(void)
-{
-       dasd_diag_cleanup();
-}
-#endif
+module_init(dasd_diag_init);
+module_exit(dasd_diag_cleanup);
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 71004b95b78f1c69ea6f201bb4bd4f8ad677b81e..fdd430a434a5cf591fb816ec2eb05eb6cbb4070e 100644 (file)
@@ -5,6 +5,11 @@
  * ...............: by Hartmunt Penner <hpenner@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * $Revision: 1.4 $
+ *
+ * History of changes
+ *
  */
 
 #define MDSK_WRITE_REQ 0x01
@@ -70,5 +75,3 @@ typedef struct diag_rw_io_t {
 
     diag_rw_io_t;
 
-int dasd_diag_init(void);
-void dasd_diag_cleanup(void);
index 64e59fb1bc783d263baf9c2cb0175e329bae05dc..134385afbb444fd19eb3197c76bf3de84f31b998 100644 (file)
@@ -7,6 +7,8 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
+ * $Revision: 1.35 $
+ *
  * History of changes (starts July 2000)
  * 07/11/00 Enabled rotational position sensing
  * 07/14/00 Reorganized the format process for better ERP
 #include <linux/slab.h>
 #include <linux/hdreg.h>       /* HDIO_GETGEO                      */
 #include <linux/bio.h>
+#include <linux/module.h>
+#include <linux/init.h>
 
 #include <asm/debug.h>
 #include <asm/idals.h>
 #include <asm/ebcdic.h>
 #include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/s390dyn.h>
 #include <asm/todclk.h>
 #include <asm/uaccess.h>
+#include <asm/ccwdev.h>
 
 #include "dasd_int.h"
 #include "dasd_eckd.h"
@@ -59,6 +62,8 @@
 #define ECKD_F7(i) (i->factor7)
 #define ECKD_F8(i) (i->factor8)
 
+MODULE_LICENSE("GPL");
+
 static dasd_discipline_t dasd_eckd_discipline;
 
 typedef struct dasd_eckd_private_t {
@@ -70,29 +75,44 @@ typedef struct dasd_eckd_private_t {
        attrib_data_t attrib;   /* e.g. cache operations */
 } dasd_eckd_private_t;
 
-static
-devreg_t dasd_eckd_known_devices[] = {
-       {
-               .ci = { .hc = { .ctype = 0x3880, .dtype = 3390 } },
-               .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE |
-                     DEVREG_TYPE_DEVCHARS),
-               .oper_func = dasd_oper_handler
-       },
-       {
-               .ci = { .hc = { .ctype = 0x3990 } },
-               .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS),
-               .oper_func = dasd_oper_handler
-       },
-       {
-               .ci = { .hc = { .ctype = 0x2105 } },
-               .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS),
-               .oper_func = dasd_oper_handler
-       },
-       {
-               .ci = { .hc = { .ctype = 0x9343 } },
-               .flag = (DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS),
-               .oper_func = dasd_oper_handler
-       }
+/* The ccw bus type uses this table to find devices that it sends to
+ * dasd_eckd_probe */
+static struct ccw_device_id dasd_eckd_ids[] = {
+       { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3390, 0), driver_info: 0x1},
+       { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3390, 0), driver_info: 0x2},
+       { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3390, 0), driver_info: 0x3},
+       { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), driver_info: 0x4},
+       { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), driver_info: 0x5},
+       { CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), driver_info: 0x6},
+       { /* end of list */ },
+};
+
+MODULE_DEVICE_TABLE(ccw, dasd_eckd_ids);
+
+static struct ccw_driver dasd_eckd_driver; /* see below */
+
+/* initial attempt at a probe function. this can be simplified once
+ * the other detection code is gone */
+static int
+dasd_eckd_probe (struct ccw_device *cdev)
+{
+       return dasd_generic_probe (cdev, &dasd_eckd_discipline);
+}
+
+static int
+dasd_eckd_set_online(struct ccw_device *cdev)
+{
+       return dasd_generic_set_online (cdev, &dasd_eckd_discipline);
+}
+
+static struct ccw_driver dasd_eckd_driver = {
+       .name        = "dasd-eckd",
+       .owner       = THIS_MODULE,
+       .ids         = dasd_eckd_ids,
+       .probe       = dasd_eckd_probe,
+       .remove      = dasd_generic_remove,
+       .set_offline = dasd_generic_set_offline,
+       .set_online  = dasd_eckd_set_online,
 };
 
 static const int sizes_trk0[] = { 28, 148, 84 };
@@ -183,7 +203,32 @@ recs_per_track(dasd_eckd_characteristics_t * rdc,
 }
 
 static inline void
-define_extent(ccw1_t * ccw, DE_eckd_data_t * data, int trk, int totrk,
+check_XRC (struct ccw1         *de_ccw,
+           DE_eckd_data_t *data,
+           dasd_device_t  *device)
+{
+        dasd_eckd_private_t *private;
+
+        private = (dasd_eckd_private_t *) device->private;
+
+        /* switch on System Time Stamp - needed for XRC Support */
+        if (private->rdc_data.facilities.XRC_supported) {
+                
+                data->ga_extended |= 0x08;   /* switch on 'Time Stamp Valid'   */
+                data->ga_extended |= 0x02;   /* switch on 'Extended Parameter' */
+                
+                data->ep_sys_time = get_clock ();
+                
+                de_ccw->count = sizeof (DE_eckd_data_t);
+                de_ccw->flags = CCW_FLAG_SLI;  
+        }
+
+        return;
+
+} /* end check_XRC */
+
+static inline void
+define_extent(struct ccw1 * ccw, DE_eckd_data_t * data, int trk, int totrk,
              int cmd, dasd_device_t * device)
 {
        dasd_eckd_private_t *private;
@@ -216,10 +261,12 @@ define_extent(ccw1_t * ccw, DE_eckd_data_t * data, int trk, int totrk,
        case DASD_ECKD_CCW_WRITE_KD_MT:
                data->mask.perm = 0x02;
                data->attributes.operation = private->attrib.operation;
+                check_XRC (ccw, data, device);
                break;
        case DASD_ECKD_CCW_WRITE_CKD:
        case DASD_ECKD_CCW_WRITE_CKD_MT:
                data->attributes.operation = DASD_BYPASS_CACHE;
+                check_XRC (ccw, data, device);
                break;
        case DASD_ECKD_CCW_ERASE:
        case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
@@ -227,6 +274,7 @@ define_extent(ccw1_t * ccw, DE_eckd_data_t * data, int trk, int totrk,
                data->mask.perm = 0x3;
                data->mask.auth = 0x1;
                data->attributes.operation = DASD_BYPASS_CACHE;
+                check_XRC (ccw, data, device);
                break;
        default:
                MESSAGE(KERN_ERR, "unknown opcode 0x%x", cmd);
@@ -271,7 +319,7 @@ define_extent(ccw1_t * ccw, DE_eckd_data_t * data, int trk, int totrk,
 }
 
 static inline void
-locate_record(ccw1_t *ccw, LO_eckd_data_t *data, int trk,
+locate_record(struct ccw1 *ccw, LO_eckd_data_t *data, int trk,
              int rec_on_trk, int no_rec, int cmd,
              dasd_device_t * device, int reclen)
 {
@@ -407,24 +455,7 @@ dasd_eckd_cdl_reclen(int recid)
        return LABEL_SIZE;
 }
 
-static inline int
-dasd_eckd_id_check(s390_dev_info_t * info)
-{
-       if (info->sid_data.cu_type == 0x3990 ||
-           info->sid_data.cu_type == 0x2105)
-               if (info->sid_data.dev_type == 0x3390)
-                       return 0;
-       if (info->sid_data.cu_type == 0x3990 ||
-           info->sid_data.cu_type == 0x2105)
-               if (info->sid_data.dev_type == 0x3380)
-                       return 0;
-       if (info->sid_data.cu_type == 0x9343)
-               if (info->sid_data.dev_type == 0x9345)
-                       return 0;
-       return -ENODEV;
-}
-
-static inline int
+static int
 dasd_eckd_check_characteristics(dasd_device_t *device)
 {
        dasd_eckd_private_t *private;
@@ -452,7 +483,7 @@ dasd_eckd_check_characteristics(dasd_device_t *device)
 
        /* Read Device Characteristics */
        rdc_data = (void *) &(private->rdc_data);
-       rc = read_dev_chars(device->devinfo.irq, &rdc_data, 64);
+       rc = read_dev_chars(device->cdev, &rdc_data, 64);
        if (rc) {
                MESSAGE(KERN_WARNING,
                        "Read device characteristics returned error %d", rc);
@@ -470,8 +501,7 @@ dasd_eckd_check_characteristics(dasd_device_t *device)
                    private->rdc_data.sec_per_trk);
 
        /* Read Configuration Data */
-       rc = read_conf_data(device->devinfo.irq,
-                           &conf_data, &conf_len, LPM_ANYPATH);
+       rc = read_conf_data(device->cdev, &conf_data, &conf_len);
        if (rc && rc != -EOPNOTSUPP) {  /* -EOPNOTSUPP is ok */
                MESSAGE(KERN_WARNING,
                        "Read configuration data returned error %d", rc);
@@ -497,17 +527,11 @@ dasd_eckd_check_characteristics(dasd_device_t *device)
                    private->rdc_data.cu_type,
                    private->rdc_data.cu_model.model);
        return 0;
-}
-
-static int
-dasd_eckd_check_device(struct dasd_device_t *device)
-{
-       int rc;
 
-       rc = dasd_eckd_id_check(&device->devinfo);
-       if (rc)
-               return rc;
-       return dasd_eckd_check_characteristics(device);
+        /* get characteristis via diag to determine the kind of minidisk under VM */
+        /* needed beacause XRC is not support by VM (jet)                         */
+        /* Can be removed as soon as VM supports XRC                              */
+       // TBD ??? HUM
 }
 
 static dasd_ccw_req_t *
@@ -517,7 +541,7 @@ dasd_eckd_analysis_ccw(struct dasd_device_t *device)
        eckd_count_t *count_data;
        LO_eckd_data_t *LO_data;
        dasd_ccw_req_t *cqr;
-       ccw1_t *ccw;
+       struct ccw1 *ccw;
        int cplength, datasize;
        int i;
 
@@ -563,6 +587,7 @@ dasd_eckd_analysis_ccw(struct dasd_device_t *device)
 
        cqr->device = device;
        cqr->retries = 0;
+       cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
        return cqr;
 }
@@ -716,7 +741,7 @@ dasd_eckd_format_device(dasd_device_t * device, format_data_t * fdata)
        dasd_eckd_private_t *private;
        dasd_ccw_req_t *fcp;
        eckd_count_t *ect;
-       ccw1_t *ccw;
+       struct ccw1 *ccw;
        void *data;
        int rpt, cyl, head;
        int cplength, datasize;
@@ -881,25 +906,28 @@ dasd_eckd_format_device(dasd_device_t * device, format_data_t * fdata)
        }
        fcp->device = device;
        fcp->retries = 2;       /* set retry counter to enable ERP */
+       fcp->buildclk = get_clock();
        fcp->status = DASD_CQR_FILLED;
        return fcp;
 }
 
 static dasd_era_t
-dasd_eckd_examine_error(dasd_ccw_req_t * cqr, devstat_t * stat)
+dasd_eckd_examine_error(dasd_ccw_req_t * cqr, struct irb * irb)
 {
        dasd_device_t *device = (dasd_device_t *) cqr->device;
+       struct ccw_device *cdev = device->cdev;
 
-       if (stat->cstat == 0x00 &&
-           stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+       if (irb->scsw.cstat == 0x00 &&
+           irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
                return dasd_era_none;
 
-       switch (device->devinfo.sid_data.cu_type) {
+       switch (cdev->id.cu_type) {
        case 0x3990:
        case 0x2105:
-               return dasd_3990_erp_examine(cqr, stat);
+               return dasd_3990_erp_examine(cqr, irb);
        case 0x9343:
-               return dasd_9343_erp_examine(cqr, stat);
+               return dasd_9343_erp_examine(cqr, irb);
+       case 0x3880:
        default:
                MESSAGE(KERN_WARNING, "%s",
                        "default (unknown CU type) - RECOVERABLE return");
@@ -911,13 +939,15 @@ static dasd_erp_fn_t
 dasd_eckd_erp_action(dasd_ccw_req_t * cqr)
 {
        dasd_device_t *device = (dasd_device_t *) cqr->device;
+       struct ccw_device *cdev = device->cdev;
 
-       switch (device->devinfo.sid_data.cu_type) {
+       switch (cdev->id.cu_type) {
        case 0x3990:
        case 0x2105:
                return dasd_3990_erp_action;
        case 0x9343:
                /* Return dasd_9343_erp_action; */
+       case 0x3880:
        default:
                return dasd_default_erp_action;
        }
@@ -936,13 +966,15 @@ dasd_eckd_build_cp(dasd_device_t * device, struct request *req)
        unsigned long *idaws;
        LO_eckd_data_t *LO_data;
        dasd_ccw_req_t *cqr;
-       ccw1_t *ccw;
+       struct ccw1 *ccw;
        struct bio *bio;
        struct bio_vec *bv;
        char *dst;
        unsigned int blksize, blk_per_trk, off;
        int count, cidaw, cplength, datasize;
        sector_t recid, first_rec, last_rec;
+       sector_t first_trk, last_trk;
+       unsigned int first_offs, last_offs;
        unsigned char cmd, rcmd;
        int i;
 
@@ -957,8 +989,10 @@ dasd_eckd_build_cp(dasd_device_t * device, struct request *req)
        blksize = device->bp_block;
        blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
        /* Calculate record id of first and last block. */
-       first_rec = req->sector >> device->s2b_shift;
-       last_rec = (req->sector + req->nr_sectors - 1) >> device->s2b_shift;
+       first_rec = first_trk = req->sector >> device->s2b_shift;
+       first_offs = sector_div(first_trk, blk_per_trk);
+       last_rec = last_trk = (req->sector + req->nr_sectors - 1) >> device->s2b_shift;
+       last_offs = sector_div(last_trk, blk_per_trk);
        /* Check struct bio and count the number of blocks for the request. */
        count = 0;
        cidaw = 0;
@@ -996,8 +1030,7 @@ dasd_eckd_build_cp(dasd_device_t * device, struct request *req)
                return cqr;
        ccw = cqr->cpaddr;
        /* First ccw is define extent. */
-       define_extent(ccw++, cqr->data, first_rec / blk_per_trk, 
-                     last_rec / blk_per_trk, cmd, device);
+       define_extent(ccw++, cqr->data, first_trk, last_trk, cmd, device);
        /* Build locate_record+read/write/ccws. */
        idaws = (unsigned long *) (cqr->data + sizeof(DE_eckd_data_t));
        LO_data = (LO_eckd_data_t *) (idaws + cidaw);
@@ -1005,13 +1038,14 @@ dasd_eckd_build_cp(dasd_device_t * device, struct request *req)
        if (private->uses_cdl == 0 || recid > 2*blk_per_trk) {
                /* Only standard blocks so there is just one locate record. */
                ccw[-1].flags |= CCW_FLAG_CC;
-               locate_record(ccw++, LO_data++,
-                             recid / blk_per_trk, recid % blk_per_trk + 1,
+               locate_record(ccw++, LO_data++, first_trk, first_offs + 1,
                              last_rec - recid + 1, cmd, device, blksize);
        }
        rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) {
                dst = kmap(bv->bv_page) + bv->bv_offset;
                for (off = 0; off < bv->bv_len; off += blksize) {
+                       sector_t trkid = recid;
+                       unsigned int recoffs = sector_div(trkid, blk_per_trk);
                        rcmd = cmd;
                        count = blksize;
                        /* Locate record for cdl special block ? */
@@ -1025,16 +1059,14 @@ dasd_eckd_build_cp(dasd_device_t * device, struct request *req)
                                }
                                ccw[-1].flags |= CCW_FLAG_CC;
                                locate_record(ccw++, LO_data++,
-                                             recid / blk_per_trk,
-                                             recid % blk_per_trk + 1,
+                                             trkid, recoffs + 1,
                                              1, rcmd, device, count);
                        }
                        /* Locate record for standard blocks ? */
                        if (private->uses_cdl && recid == 2*blk_per_trk) {
                                ccw[-1].flags |= CCW_FLAG_CC;
                                locate_record(ccw++, LO_data++,
-                                             recid / blk_per_trk,
-                                             recid % blk_per_trk + 1,
+                                             trkid, recoffs + 1,
                                              last_rec - recid + 1,
                                              cmd, device, count);
                        }
@@ -1094,37 +1126,34 @@ dasd_eckd_fill_info(dasd_device_t * device, dasd_information2_t * info)
 static int
 dasd_eckd_release(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
        dasd_ccw_req_t *cqr;
        int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
+
+       device = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
 
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1, 0, device);
        if (cqr == NULL) {
                MESSAGE(KERN_WARNING, "%s",
                        "No memory to allocate initialization request");
-               dasd_put_device(devmap);
                return -ENOMEM;
        }
        cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE;
        cqr->device = device;
        cqr->retries = 0;
        cqr->expires = 10 * HZ;
+       cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
 
        rc = dasd_sleep_on_immediatly(cqr);
 
        dasd_kfree_request(cqr, cqr->device);
-       dasd_put_device(devmap);
        return rc;
 }
 
@@ -1137,18 +1166,16 @@ dasd_eckd_release(struct block_device *bdev, int no, long args)
 static int
 dasd_eckd_reserve(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
        dasd_ccw_req_t *cqr;
        int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
+
+       device = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
 
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1, 0, device);
@@ -1156,13 +1183,13 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
        if (cqr == NULL) {
                MESSAGE(KERN_WARNING, "%s",
                        "No memory to allocate initialization request");
-               dasd_put_device(devmap);
                return -ENOMEM;
        }
        cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE;
        cqr->device = device;
        cqr->retries = 0;
        cqr->expires = 10 * HZ;
+       cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
 
        rc = dasd_sleep_on_immediatly(cqr);
@@ -1172,7 +1199,6 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
                dasd_eckd_release(bdev, no, args);
        }
        dasd_kfree_request(cqr, cqr->device);
-       dasd_put_device(devmap);
        return rc;
 }
 
@@ -1184,31 +1210,29 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
 static int
 dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
        dasd_ccw_req_t *cqr;
        int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
+
+       device = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
 
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1, 0, device);
        if (cqr == NULL) {
                MESSAGE(KERN_WARNING, "%s",
                        "No memory to allocate initialization request");
-               dasd_put_device(devmap);
                return -ENOMEM;
        }
        cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK;
        cqr->device = device;
        cqr->retries = 0;
        cqr->expires = 10 * HZ;
+       cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
 
        rc = dasd_sleep_on_immediatly(cqr);
@@ -1218,7 +1242,6 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
                dasd_eckd_release(bdev, no, args);
        }
        dasd_kfree_request(cqr, cqr->device);
-       dasd_put_device(devmap);
        return rc;
 }
 
@@ -1228,19 +1251,16 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
 static int
 dasd_eckd_performance(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
        dasd_psf_prssd_data_t *prssdp;
        dasd_rssd_perf_stats_t *stats;
        dasd_ccw_req_t *cqr;
-       ccw1_t *ccw;
+       struct ccw1 *ccw;
        int rc;
 
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
+       device = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
 
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1 /* PSF */  + 1 /* RSSD */ ,
@@ -1249,7 +1269,6 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args)
        if (cqr == NULL) {
                MESSAGE(KERN_WARNING, "%s",
                        "No memory to allocate initialization request");
-               dasd_put_device(devmap);
                return -ENOMEM;
        }
        cqr->device = device;
@@ -1277,6 +1296,7 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args)
        ccw->count = sizeof (dasd_rssd_perf_stats_t);
        ccw->cda = (__u32)(addr_t) stats;
 
+       cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
        rc = dasd_sleep_on(cqr);
        if (rc == 0) {
@@ -1287,7 +1307,6 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args)
                                  sizeof(dasd_rssd_perf_stats_t));
        }
        dasd_sfree_request(cqr, cqr->device);
-       dasd_put_device(devmap);
        return rc;
 }
 
@@ -1298,7 +1317,6 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args)
 static int
 dasd_eckd_set_attrib(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
        dasd_eckd_private_t *private;
        attrib_data_t attrib;
@@ -1308,14 +1326,11 @@ dasd_eckd_set_attrib(struct block_device *bdev, int no, long args)
        if (!args)
                return -EINVAL;
 
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
+       device = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
 
        if (copy_from_user(&attrib, (void *) args, sizeof (attrib_data_t))) {
-               dasd_put_device(devmap);
                return -EFAULT;
        }
 
@@ -1332,16 +1347,16 @@ dasd_eckd_set_attrib(struct block_device *bdev, int no, long args)
                      "cache operation mode set to "
                      "%x (%i cylinder prestage)",
                      private->attrib.operation, private->attrib.nr_cyl);
-       dasd_put_device(devmap);
        return 0;
 }
 
 static void
-dasd_eckd_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req)
+dasd_eckd_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req,
+                    struct irb *irb)
 {
 
-       char *page, *sense;
-       ccw1_t *act;
+       char *page;
+       struct ccw1 *act;
        int len, sl, sct;
 
        page = (char *) get_zeroed_page(GFP_ATOMIC);
@@ -1350,14 +1365,14 @@ dasd_eckd_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req)
                return;
        }
        len = sprintf(page, KERN_ERR PRINTK_HEADER
-                     "device %04X on irq %d: I/O status report:\n",
-                     device->devinfo.devno, device->devinfo.irq);
+                     "device %s: I/O status report:\n",
+                     device->cdev->dev.bus_id);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       "in req: %p CS: 0x%02X DS: 0x%02X\n", req,
-                      device->dev_status.cstat, device->dev_status.dstat);
+                      irb->scsw.cstat, irb->scsw.dstat);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       "Failing CCW: %p\n", 
-                      (void *) (addr_t) device->dev_status.cpa);
+                      (void *) (addr_t) irb->scsw.cpa);
        act = req->cpaddr;
        do {
                DBF_EVENT(DBF_INFO,
@@ -1370,8 +1385,7 @@ dasd_eckd_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req)
                          ((int *) (addr_t) act->cda)[2],
                          ((int *) (addr_t) act->cda)[3]);
        } while (act++->flags & (CCW_FLAG_CC | CCW_FLAG_DC));
-       sense = device->dev_status.ii.sense.data;
-       if (device->dev_status.flag & DEVSTAT_FLAG_SENSE_AVAIL) {
+       if (irb->esw.esw0.erw.cons) {
                for (sl = 0; sl < 4; sl++) {
                        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                                       "Sense(hex) %2d-%2d:",
@@ -1379,23 +1393,23 @@ dasd_eckd_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req)
 
                        for (sct = 0; sct < 8; sct++) {
                                len += sprintf(page + len, " %02x",
-                                              sense[8 * sl + sct]);
+                                              irb->ecw[8 * sl + sct]);
                        }
                        len += sprintf(page + len, "\n");
                }
 
-               if (sense[27] & DASD_SENSE_BIT_0) {
+               if (irb->ecw[27] & DASD_SENSE_BIT_0) {
                        /* 24 Byte Sense Data */
                        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                                       "24 Byte: %x MSG %x, %s MSGb to SYSOP\n",
-                                      sense[7] >> 4, sense[7] & 0x0f,
-                                      sense[1] & 0x10 ? "" : "no");
+                                      irb->ecw[7] >> 4, irb->ecw[7] & 0x0f,
+                                      irb->ecw[1] & 0x10 ? "" : "no");
                } else {
                        /* 32 Byte Sense Data */
                        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                                       "32 Byte: Format: %x "
                                       "Exception class %x\n",
-                                      sense[6] & 0x0f, sense[22] >> 4);
+                                      irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
                }
        }
 
@@ -1422,7 +1436,7 @@ static dasd_discipline_t dasd_eckd_discipline = {
        .name = "ECKD",
        .ebcname = "ECKD",
        .max_blocks = 240,
-       .check_device = dasd_eckd_check_device,
+       .check_device = dasd_eckd_check_characteristics,
        .do_analysis = dasd_eckd_do_analysis,
        .fill_geometry = dasd_eckd_fill_geometry,
        .start_IO = dasd_start_IO,
@@ -1436,12 +1450,9 @@ static dasd_discipline_t dasd_eckd_discipline = {
        .fill_info = dasd_eckd_fill_info,
 };
 
-int
+static int __init
 dasd_eckd_init(void)
 {
-       int i;
-       printk("sizeof(dasd_ccw_req_t) = %li\n",
-              sizeof(dasd_ccw_req_t));
        dasd_ioctl_no_register(THIS_MODULE, BIODASDSATTR,
                               dasd_eckd_set_attrib);
        dasd_ioctl_no_register(THIS_MODULE, BIODASDPSRD,
@@ -1454,22 +1465,15 @@ dasd_eckd_init(void)
                               dasd_eckd_steal_lock);
 
        ASCEBC(dasd_eckd_discipline.ebcname, 4);
-       dasd_discipline_add(&dasd_eckd_discipline);
 
-       for (i = 0; i < sizeof(dasd_eckd_known_devices)/sizeof(devreg_t); i++)
-                       s390_device_register(&dasd_eckd_known_devices[i]);
+       ccw_driver_register(&dasd_eckd_driver);
        return 0;
 }
 
-void
+static void __exit
 dasd_eckd_cleanup(void)
 {
-       int i;
-
-       for (i = 0; i < sizeof(dasd_eckd_known_devices)/sizeof(devreg_t); i++)
-               s390_device_unregister(&dasd_eckd_known_devices[i]);
-
-       dasd_discipline_del(&dasd_eckd_discipline);
+       ccw_driver_unregister(&dasd_eckd_driver);
 
        dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR,
                                 dasd_eckd_set_attrib);
@@ -1483,19 +1487,8 @@ dasd_eckd_cleanup(void)
                                 dasd_eckd_steal_lock);
 }
 
-#ifdef MODULE
-int
-init_module(void)
-{
-       return dasd_eckd_init();
-}
-
-void
-cleanup_module(void)
-{
-       dasd_eckd_cleanup();
-}
-#endif
+module_init(dasd_eckd_init);
+module_exit(dasd_eckd_cleanup);
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 1690246e9f97f1762a1bb607a533c3ba9ad92fe6..16e74cd2f9eb708166f00d58a3f3efc4d0535002 100644 (file)
@@ -1,3 +1,16 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd_eckd.h
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ *                  Horst Hummel <Horst.Hummel@de.ibm.com> 
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * $Revision: 1.5 $
+ *
+ * History of changes 
+ * 
+ */
+
 #ifndef DASD_ECKD_H
 #define DASD_ECKD_H
 
@@ -102,6 +115,10 @@ typedef struct DE_eckd_data_t {
        __u8 ga_extended;       /* Global Attributes Extended   */
        ch_t beg_ext;
        ch_t end_ext;
+       unsigned long long ep_sys_time; /* Extended Parameter - System Time Stamp */
+       __u8 ep_format;        /* Extended Parameter format byte       */
+       __u8 ep_prio;          /* Extended Parameter priority I/O byte */
+       __u8 ep_reserved[6];   /* Extended Parameter Reserved          */
 } __attribute__ ((packed)) DE_eckd_data_t;
 
 typedef struct LO_eckd_data_t {
@@ -141,7 +158,8 @@ typedef struct dasd_eckd_characteristics_t {
                unsigned char reserved2:4;
                unsigned char reserved3:8;
                unsigned char defect_wr:1;
-               unsigned char reserved4:2;
+               unsigned char XRC_supported:1; 
+               unsigned char reserved4:1;
                unsigned char striping:1;
                unsigned char reserved5:4;
                unsigned char cfw:1;
@@ -322,6 +340,4 @@ typedef struct dasd_psf_prssd_data_t {
        unsigned char varies[9];
 } __attribute__ ((packed)) dasd_psf_prssd_data_t;
 
-int dasd_eckd_init(void);
-void dasd_eckd_cleanup(void);
 #endif                         /* DASD_ECKD_H */
index 04edc4d66fd7dddef6239e865f80de0388dcc01a..03c0c016ecce268a127407109e3d1770199429e7 100644 (file)
@@ -7,6 +7,9 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
+ * $Revision: 1.6 $
+ *
+ * History of changes
  * 05/04/02 split from dasd.c, code restructuring.
  */
 
@@ -17,7 +20,6 @@
 
 #include <asm/debug.h>
 #include <asm/ebcdic.h>
-#include <asm/irq.h>
 #include <asm/uaccess.h>
 
 /* This is ugly... */
@@ -36,7 +38,7 @@ dasd_alloc_erp_request(char *magic, int cplength, int datasize,
 
        /* Sanity checks */
        if ( magic == NULL || datasize > PAGE_SIZE ||
-            (cplength*sizeof(ccw1_t)) > PAGE_SIZE)
+            (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
                BUG();
        debug_text_event ( dasd_debug_area, 1, "ALLC");
        debug_text_event ( dasd_debug_area, 1, magic);
@@ -45,7 +47,7 @@ dasd_alloc_erp_request(char *magic, int cplength, int datasize,
 
        size = (sizeof(dasd_ccw_req_t) + 7L) & -8L;
        if (cplength > 0)
-               size += cplength * sizeof(ccw1_t);
+               size += cplength * sizeof(struct ccw1);
        if (datasize > 0)
                size += datasize;
        spin_lock_irqsave(&device->mem_lock, flags);
@@ -57,9 +59,9 @@ dasd_alloc_erp_request(char *magic, int cplength, int datasize,
        data = (char *) cqr + ((sizeof(dasd_ccw_req_t) + 7L) & -8L);
        cqr->cpaddr = NULL;
        if (cplength > 0) {
-               cqr->cpaddr = (ccw1_t *) data;
-               data += cplength*sizeof(ccw1_t);
-               memset(cqr->cpaddr, 0, cplength*sizeof(ccw1_t));
+               cqr->cpaddr = (struct ccw1 *) data;
+               data += cplength*sizeof(struct ccw1);
+               memset(cqr->cpaddr, 0, cplength*sizeof(struct ccw1));
        }
        cqr->data = NULL;
        if (datasize > 0) {
@@ -201,18 +203,25 @@ hex_dump_memory(dasd_device_t *device, void *data, int len)
 }
 
 void
-dasd_log_ccw(dasd_ccw_req_t * cqr, int caller, __u32 cpa)
+dasd_log_sense(dasd_ccw_req_t *cqr, struct irb *irb)
 {
        dasd_device_t *device;
-       dasd_ccw_req_t *lcqr;
-       ccw1_t *ccw;
-       int cplength;
 
        device = cqr->device;
        /* dump sense data */
        if (device->discipline && device->discipline->dump_sense)
-               device->discipline->dump_sense(device, cqr);
+               device->discipline->dump_sense(device, cqr, irb);
+}
 
+void
+dasd_log_ccw(dasd_ccw_req_t * cqr, int caller, __u32 cpa)
+{
+       dasd_device_t *device;
+       dasd_ccw_req_t *lcqr;
+       struct ccw1 *ccw;
+       int cplength;
+
+       device = cqr->device;
        /* log the channel program */
        for (lcqr = cqr; lcqr != NULL; lcqr = lcqr->refers) {
                DEV_MESSAGE(KERN_ERR, device,
@@ -229,17 +238,17 @@ dasd_log_ccw(dasd_ccw_req_t * cqr, int caller, __u32 cpa)
                        DEV_MESSAGE(KERN_ERR, device, "%s",
                                    "Start of channel program:");
                        hex_dump_memory(device, lcqr->cpaddr,
-                                       40*sizeof(ccw1_t));
+                                       40*sizeof(struct ccw1));
 
                        DEV_MESSAGE(KERN_ERR, device, "%s",
                                    "End of channel program:");
                        hex_dump_memory(device, lcqr->cpaddr + cplength - 10,
-                                       10*sizeof(ccw1_t));
+                                       10*sizeof(struct ccw1));
                } else {        /* log the whole CP */
                        DEV_MESSAGE(KERN_ERR, device, "%s",
                                    "Channel program (complete):");
                        hex_dump_memory(device, lcqr->cpaddr,
-                                       cplength*sizeof(ccw1_t));
+                                       cplength*sizeof(struct ccw1));
                }
 
                if (lcqr != cqr)
@@ -258,7 +267,7 @@ dasd_log_ccw(dasd_ccw_req_t * cqr, int caller, __u32 cpa)
                                    "Failed CCW (%p) (area):",
                                    (void *) (long) cpa);
                        hex_dump_memory(device, cqr->cpaddr - 10,
-                                       20*sizeof(ccw1_t));
+                                       20*sizeof(struct ccw1));
                }
        }
 
@@ -268,4 +277,5 @@ EXPORT_SYMBOL(dasd_default_erp_action);
 EXPORT_SYMBOL(dasd_default_erp_postaction);
 EXPORT_SYMBOL(dasd_alloc_erp_request);
 EXPORT_SYMBOL(dasd_free_erp_request);
+EXPORT_SYMBOL(dasd_log_sense);
 EXPORT_SYMBOL(dasd_log_ccw);
index 419eff8f941b4ff34bccf81a6810ff7a9cf9727b..442f2bd28cd026738a364f46d40661acb5971b52 100644 (file)
@@ -1,9 +1,12 @@
-
 /* 
  * File...........: linux/drivers/s390/block/dasd_fba.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * $Revision: 1.25 $
+ *
+ * History of changes
  *         fixed partition handling and HDIO_GETGEO
  * 2002/01/04 Created 2.4-2.5 compatibility mode
  * 05/04/02 code restructuring.
 #include <linux/slab.h>
 #include <linux/hdreg.h>       /* HDIO_GETGEO                      */
 #include <linux/bio.h>
+#include <linux/module.h>
+#include <linux/init.h>
 
 #include <asm/idals.h>
 #include <asm/ebcdic.h>
 #include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/s390dyn.h>
 #include <asm/todclk.h>
+#include <asm/ccwdev.h>
 
 #include "dasd_int.h"
 #include "dasd_fba.h"
 #define DASD_FBA_CCW_LOCATE 0x43
 #define DASD_FBA_CCW_DEFINE_EXTENT 0x63
 
+MODULE_LICENSE("GPL");
+
 static dasd_discipline_t dasd_fba_discipline;
 
 typedef struct dasd_fba_private_t {
        dasd_fba_characteristics_t rdc_data;
 } dasd_fba_private_t;
 
-static
-devreg_t dasd_fba_known_devices[] = {
-       {
-               .ci = {.hc = {.ctype = 0x6310, .dtype = 0x9336}},
-               .flag = (DEVREG_MATCH_CU_TYPE |
-                     DEVREG_MATCH_DEV_TYPE | DEVREG_TYPE_DEVCHARS),
-               .oper_func = dasd_oper_handler
-       },
-       {
-               .ci = {.hc = {.ctype = 0x3880, .dtype = 0x3370}},
-               .flag = (DEVREG_MATCH_CU_TYPE |
-                     DEVREG_MATCH_DEV_TYPE | DEVREG_TYPE_DEVCHARS),
-               .oper_func = dasd_oper_handler
-       }
+static struct ccw_device_id dasd_fba_ids[] = {
+       { CCW_DEVICE_DEVTYPE (0x6310, 0, 0x9336, 0), driver_info: 0x1},
+       { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3370, 0), driver_info: 0x2},
+       { /* end of list */ },
+};
+
+MODULE_DEVICE_TABLE(ccw, dasd_fba_ids);
+
+static struct ccw_driver dasd_fba_driver; /* see below */
+static int
+dasd_fba_probe(struct ccw_device *cdev)
+{
+       return  dasd_generic_probe (cdev, &dasd_fba_discipline);
+}
+
+static int
+dasd_fba_set_online(struct ccw_device *cdev)
+{
+       return dasd_generic_set_online (cdev, &dasd_fba_discipline);
+}
+
+static struct ccw_driver dasd_fba_driver = {
+       .name        = "dasd-fba",
+       .owner       = THIS_MODULE,
+       .ids         = dasd_fba_ids,
+       .probe       = dasd_fba_probe,
+       .remove      = dasd_generic_remove,
+       .set_offline = dasd_generic_set_offline,
+       .set_online  = dasd_fba_set_online,
 };
 
 static inline void
-define_extent(ccw1_t * ccw, DE_fba_data_t *data, int rw,
+define_extent(struct ccw1 * ccw, DE_fba_data_t *data, int rw,
              int blksize, int beg, int nr)
 {
        ccw->cmd_code = DASD_FBA_CCW_DEFINE_EXTENT;
@@ -81,7 +102,7 @@ define_extent(ccw1_t * ccw, DE_fba_data_t *data, int rw,
 }
 
 static inline void
-locate_record(ccw1_t * ccw, LO_fba_data_t *data, int rw,
+locate_record(struct ccw1 * ccw, LO_fba_data_t *data, int rw,
              int block_nr, int block_ct)
 {
        ccw->cmd_code = DASD_FBA_CCW_LOCATE;
@@ -99,22 +120,11 @@ locate_record(ccw1_t * ccw, LO_fba_data_t *data, int rw,
        data->blk_ct = block_ct;
 }
 
-static inline int
-dasd_fba_id_check(s390_dev_info_t * info)
-{
-       if (info->sid_data.cu_type == 0x3880)
-               if (info->sid_data.dev_type == 0x3370)
-                       return 0;
-       if (info->sid_data.cu_type == 0x6310)
-               if (info->sid_data.dev_type == 0x9336)
-                       return 0;
-       return -ENODEV;
-}
-
-static inline int
+static int
 dasd_fba_check_characteristics(struct dasd_device_t *device)
 {
        dasd_fba_private_t *private;
+       struct ccw_device *cdev = device->cdev; 
        void *rdc_data;
        int rc;
 
@@ -130,7 +140,7 @@ dasd_fba_check_characteristics(struct dasd_device_t *device)
        }
        /* Read Device Characteristics */
        rdc_data = (void *) &(private->rdc_data);
-       rc = read_dev_chars(device->devinfo.irq, &rdc_data, 32);
+       rc = read_dev_chars(device->cdev, &rdc_data, 32);
        if (rc) {
                MESSAGE(KERN_WARNING,
                        "Read device characteristics returned error %d", rc);
@@ -139,27 +149,16 @@ dasd_fba_check_characteristics(struct dasd_device_t *device)
 
        DEV_MESSAGE(KERN_INFO, device,
                    "%04X/%02X(CU:%04X/%02X) %dMB at(%d B/blk)",
-                   device->devinfo.sid_data.dev_type,
-                   device->devinfo.sid_data.dev_model,
-                   device->devinfo.sid_data.cu_type,
-                   device->devinfo.sid_data.cu_model,
+                   cdev->id.dev_type,
+                   cdev->id.dev_model,
+                   cdev->id.cu_type,
+                   cdev->id.cu_model,
                    ((private->rdc_data.blk_bdsa *
                      (private->rdc_data.blk_size >> 9)) >> 11),
                    private->rdc_data.blk_size);
        return 0;
 }
 
-static int
-dasd_fba_check_device(struct dasd_device_t *device)
-{
-       int rc;
-
-       rc = dasd_fba_id_check(&device->devinfo);
-       if (rc)
-               return rc;
-       return dasd_fba_check_characteristics(device);
-}
-
 static int
 dasd_fba_do_analysis(struct dasd_device_t *device)
 {
@@ -193,20 +192,22 @@ dasd_fba_fill_geometry(struct dasd_device_t *device, struct hd_geometry *geo)
 }
 
 static dasd_era_t
-dasd_fba_examine_error(dasd_ccw_req_t * cqr, devstat_t * stat)
+dasd_fba_examine_error(dasd_ccw_req_t * cqr, struct irb * irb)
 {
        dasd_device_t *device;
+       struct ccw_device *cdev;
 
        device = (dasd_device_t *) cqr->device;
-       if (stat->cstat == 0x00 &&
-           stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+       if (irb->scsw.cstat == 0x00 &&
+           irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
                return dasd_era_none;
-
-       switch (device->devinfo.sid_data.dev_model) {
+       
+       cdev = device->cdev;
+       switch (cdev->id.dev_model) {
        case 0x3370:
-               return dasd_3370_erp_examine(cqr, stat);
+               return dasd_3370_erp_examine(cqr, irb);
        case 0x9336:
-               return dasd_9336_erp_examine(cqr, stat);
+               return dasd_9336_erp_examine(cqr, irb);
        default:
                return dasd_era_recover;
        }
@@ -236,7 +237,7 @@ dasd_fba_build_cp(dasd_device_t * device, struct request *req)
        unsigned long *idaws;
        LO_fba_data_t *LO_data;
        dasd_ccw_req_t *cqr;
-       ccw1_t *ccw;
+       struct ccw1 *ccw;
        struct bio *bio;
        struct bio_vec *bv;
        char *dst;
@@ -359,7 +360,8 @@ dasd_fba_fill_info(dasd_device_t * device, dasd_information2_t * info)
 }
 
 static void
-dasd_fba_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req)
+dasd_fba_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req,
+                   struct irb *irb)
 {
        char *page;
 
@@ -369,8 +371,8 @@ dasd_fba_dump_sense(struct dasd_device_t *device, dasd_ccw_req_t * req)
                return;
        }
        sprintf(page, KERN_WARNING PRINTK_HEADER
-               "device %04X on irq %d: I/O status report:\n",
-               device->devinfo.devno, device->devinfo.irq);
+               "device %s: I/O status report:\n",
+               device->cdev->dev.bus_id);
 
        MESSAGE(KERN_ERR, "Sense data:\n%s", page);
 
@@ -396,7 +398,7 @@ static dasd_discipline_t dasd_fba_discipline = {
        .name = "FBA ",
        .ebcname = "FBA ",
        .max_blocks = 96,
-       .check_device = dasd_fba_check_device,
+       .check_device = dasd_fba_check_characteristics,
        .do_analysis = dasd_fba_do_analysis,
        .fill_geometry = dasd_fba_fill_geometry,
        .start_IO = dasd_start_IO,
@@ -409,41 +411,22 @@ static dasd_discipline_t dasd_fba_discipline = {
        .fill_info = dasd_fba_fill_info,
 };
 
-int
+static int __init
 dasd_fba_init(void)
 {
-       int i;
-
        ASCEBC(dasd_fba_discipline.ebcname, 4);
-       dasd_discipline_add(&dasd_fba_discipline);
-       for (i = 0; i < sizeof(dasd_fba_known_devices) / sizeof(devreg_t); i++)
-               s390_device_register(&dasd_fba_known_devices[i]);
-       return 0;
-}
-
-void
-dasd_fba_cleanup(void)
-{
-       int i;
 
-       for (i = 0; i < sizeof(dasd_fba_known_devices) / sizeof(devreg_t); i++)
-               s390_device_unregister(&dasd_fba_known_devices[i]);
-       dasd_discipline_del(&dasd_fba_discipline);
+       return ccw_driver_register(&dasd_fba_driver);
 }
 
-#ifdef MODULE
-int
-init_module(void)
+static void __exit
+dasd_fba_cleanup(void)
 {
-       return dasd_fba_init();
+       ccw_driver_unregister(&dasd_fba_driver);
 }
 
-void
-cleanup_module(void)
-{
-       dasd_fba_cleanup();
-}
-#endif
+module_init(dasd_fba_init);
+module_exit(dasd_fba_cleanup);
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 1bc664d05b1f1ef7dbf28a4090de0f27afaea52d..eae043bcd98b68f81d582289d9012a6a4c78a4ff 100644 (file)
@@ -1,3 +1,14 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd_fba.h
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * $Revision: 1.4 $
+ *
+ * History of changes 
+ * 
+ */
 
 #ifndef DASD_FBA_H
 #define DASD_FBA_H
@@ -71,6 +82,4 @@ typedef
 
     dasd_fba_characteristics_t;
 
-int dasd_fba_init(void);
-void dasd_fba_cleanup(void);
 #endif                         /* DASD_FBA_H */
index 7d8b3aab313b3b4aba2c893d74bdc1638dd259a4..3a150a9ee099406194e025950f89d00ef8ee4dbc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_ioctl.c
+ * File...........: linux/drivers/s390/block/dasd_genhd.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  *                 Carsten Otte <Cotte@de.ibm.com>
@@ -9,6 +9,9 @@
  *
  * Dealing with devices registered to multiple major numbers.
  *
+ * $Revision: 1.23 $
+ *
+ * History of changes
  * 05/04/02 split from dasd.c, code restructuring.
  */
 
@@ -19,7 +22,6 @@
 #include <linux/blkpg.h>
 #include <linux/blk.h>
 
-#include <asm/irq.h>
 #include <asm/uaccess.h>
 
 /* This is ugly... */
@@ -72,7 +74,6 @@ dasd_register_major(int major)
        /* Initialize major info structure. */
        mi->major = new_major;
 
-       /* Setup block device pointers for the new major. */
        /* Insert the new major info structure into dasd_major_info list. */
        spin_lock(&dasd_major_lock);
        list_add_tail(&mi->list, &dasd_major_info);
@@ -104,35 +105,6 @@ dasd_unregister_major(struct major_info * mi)
        kfree(mi);
 }
 
-/*
- * This one is needed for naming 18000+ possible dasd devices.
- *   dasda - dasdz : 26 devices
- *   dasdaa - dasdzz : 676 devices, added up = 702
- *   dasdaaa - dasdzzz : 17576 devices, added up = 18278
- */
-int
-dasd_device_name(char *str, int index, int partition)
-{
-       int len;
-
-       if (partition > DASD_PARTN_MASK)
-               return -EINVAL;
-
-       len = sprintf(str, "dasd");
-       if (index > 25) {
-               if (index > 701)
-                       len += sprintf(str + len, "%c",
-                                      'a' + (((index - 702) / 676) % 26));
-               len += sprintf(str + len, "%c",
-                              'a' + (((index - 26) / 26) % 26));
-       }
-       len += sprintf(str + len, "%c", 'a' + (index % 26));
-
-       if (partition)
-               len += sprintf(str + len, "%d", partition);
-       return 0;
-}
-
 /*
  * Allocate gendisk structure for devindex.
  */
@@ -164,7 +136,7 @@ dasd_gendisk_alloc(int devindex)
                        return ERR_PTR(rc);
                }
        }
-
+       
        gdp = alloc_disk(1 << DASD_PARTN_BITS);
        if (!gdp)
                return ERR_PTR(-ENOMEM);
@@ -196,7 +168,7 @@ dasd_gendisk_alloc(int devindex)
 /*
  * Return devindex of first device using a specific major number.
  */
-int dasd_gendisk_major_index(int major)
+static int dasd_gendisk_major_index(int major)
 {
        struct list_head *l;
        struct major_info *mi;
index f836d3809a109f7e81b65fc895ceab65d8163d3f..32189d47046d80ad0e2df60fdf9da13d35a33ab0 100644 (file)
@@ -1,10 +1,13 @@
 /* 
- * File...........: linux/drivers/s390/block/dasd.c
+ * File...........: linux/drivers/s390/block/dasd_int.h
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ *                  Horst Hummel <Horst.Hummel@de.ibm.com> 
  *                 Martin Schwidefsky <schwidefsky@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
+ * $Revision: 1.36 $
+ *
  * History of changes (starts July 2000)
  * 02/01/01 added dynamic registration of ioctls
  * 2002/01/04 Created 2.4-2.5 compatibility mode
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/interrupt.h>
+#include <asm/ccwdev.h>
 #include <linux/workqueue.h>
 #include <asm/debug.h>
 #include <asm/dasd.h>
 #include <asm/idals.h>
-#include <asm/irq.h>
-#include <asm/s390dyn.h>
 
 /*
  * SECTION: Type definitions
@@ -140,10 +142,9 @@ do { \
 /* messages to be written via klogd and dbf */
 #define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
 do { \
-       printk(d_loglevel PRINTK_HEADER " %s,%04x@%02x: " \
+       printk(d_loglevel PRINTK_HEADER " %s,%s: " \
               d_string "\n", d_device->gdp->disk_name, \
-              d_device->devinfo.devno, d_device->devinfo.irq, \
-              d_args); \
+              d_device->cdev->dev.bus_id, d_args); \
        DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \
 } while(0)
 
@@ -159,18 +160,17 @@ typedef struct dasd_ccw_req_t {
 
        /* Where to execute what... */
        struct dasd_device_t *device;   /* device the request is for */
-       ccw1_t *cpaddr;                 /* address of channel program */
+       struct ccw1 *cpaddr;            /* address of channel program */
        char status;                    /* status of this request */
        short retries;                  /* A retry counter */
 
        /* ... and how */
-       int options;                    /* options for execution */
        int expires;                    /* expiration period in jiffies */
        char lpm;                       /* logical path mask */
        void *data;                     /* pointer to data area */
 
        /* these are important for recovering erroneous requests          */
-       devstat_t *dstat;               /* device status in case of an error */
+       struct irb *dstat;              /* device status in case of an error */
        struct dasd_ccw_req_t *refers;  /* ERP-chain queueing. */
        void *function;                 /* originating ERP action */
 
@@ -247,16 +247,24 @@ typedef struct dasd_discipline_t {
          * is called for every error condition to print the sense data
          * to the console.
          */
-       dasd_era_t(*examine_error) (dasd_ccw_req_t *, devstat_t *);
+       dasd_era_t(*examine_error) (dasd_ccw_req_t *, struct irb *);
        dasd_erp_fn_t(*erp_action) (dasd_ccw_req_t *);
        dasd_erp_fn_t(*erp_postaction) (dasd_ccw_req_t *);
-       void (*dump_sense) (struct dasd_device_t *, dasd_ccw_req_t *);
+       void (*dump_sense) (struct dasd_device_t *, dasd_ccw_req_t *,
+                           struct irb *);
 
         /* i/o control functions. */
        int (*fill_geometry) (struct dasd_device_t *, struct hd_geometry *);
        int (*fill_info) (struct dasd_device_t *, dasd_information2_t *);
 } dasd_discipline_t;
 
+extern dasd_discipline_t dasd_diag_discipline;
+#ifdef CONFIG_DASD_DIAG
+#define dasd_diag_discipline_pointer (&dasd_diag_discipline)
+#else
+#define dasd_diag_discipline_pointer (0)
+#endif
+
 typedef struct dasd_device_t {
        /* Block device stuff. */
        struct gendisk *gdp;
@@ -267,6 +275,8 @@ typedef struct dasd_device_t {
        unsigned int bp_block;          /* bytes per block */
        unsigned int s2b_shift;         /* log2 (bp_block/512) */
        int ro_flag;                    /* read-only flag */
+       int use_diag_flag;              /* diag allowed flag */
+
 
        /* Device discipline stuff. */
        dasd_discipline_t *discipline;
@@ -288,8 +298,8 @@ typedef struct dasd_device_t {
        struct list_head erp_chunks;
 
        /* Common i/o stuff. */
-       s390_dev_info_t devinfo;
-       devstat_t dev_status;
+       /* FIXME: remove the next */
+       int devno;
 
        atomic_t tasklet_scheduled;
         struct tasklet_struct tasklet;
@@ -297,6 +307,9 @@ typedef struct dasd_device_t {
        struct timer_list timer;
 
        debug_info_t *debug_area;
+
+       struct ccw_device *cdev;
+
 #ifdef CONFIG_DASD_PROFILE
        dasd_profile_info_t profile;
 #endif
@@ -318,7 +331,6 @@ typedef struct {
         unsigned int devindex;
         unsigned short devno;
         unsigned short features;
-        devreg_t *devreg;
         dasd_device_t *device;
 } dasd_devmap_t;
 
@@ -427,17 +439,14 @@ void dasd_kfree_request(dasd_ccw_req_t *, dasd_device_t *);
 void dasd_sfree_request(dasd_ccw_req_t *, dasd_device_t *);
 
 static inline int
-dasd_kmalloc_set_cda(ccw1_t *ccw, void *cda, dasd_device_t *device)
+dasd_kmalloc_set_cda(struct ccw1 *ccw, void *cda, dasd_device_t *device)
 {
        return set_normalized_cda(ccw, cda);
 }
 
 dasd_device_t *dasd_alloc_device(dasd_devmap_t *);
 void dasd_free_device(dasd_device_t *);
-void dasd_enable_devices(int, int);
-void dasd_disable_devices(int, int);
-void dasd_discipline_add(dasd_discipline_t *);
-void dasd_discipline_del(dasd_discipline_t *);
+void dasd_enable_device(dasd_device_t *);
 void dasd_set_target_state(dasd_device_t *, int);
 void dasd_kick_device(dasd_device_t *);
 
@@ -445,7 +454,6 @@ void dasd_add_request_head(dasd_ccw_req_t *);
 void dasd_add_request_tail(dasd_ccw_req_t *); /* unused */
 int  dasd_start_IO(dasd_ccw_req_t *);
 int  dasd_term_IO(dasd_ccw_req_t *);
-int  dasd_oper_handler(int, devreg_t *);
 void dasd_schedule_bh(dasd_device_t *);
 int  dasd_sleep_on(dasd_ccw_req_t *);
 int  dasd_sleep_on_immediatly(dasd_ccw_req_t *);
@@ -453,6 +461,12 @@ int  dasd_sleep_on_interruptible(dasd_ccw_req_t *);
 void dasd_set_timer(dasd_device_t *, int);
 void dasd_clear_timer(dasd_device_t *);
 int  dasd_cancel_req(dasd_ccw_req_t *); /* unused */
+int dasd_generic_probe (struct ccw_device *cdev, 
+                       dasd_discipline_t *discipline);
+int dasd_generic_remove (struct ccw_device *cdev);
+int dasd_generic_set_online(struct ccw_device *cdev, 
+                           dasd_discipline_t *discipline);
+int dasd_generic_set_offline (struct ccw_device *cdev);
 
 /* externals in dasd_devmap.c */
 extern int dasd_max_devindex;
@@ -463,20 +477,15 @@ int dasd_devmap_init(void);
 void dasd_devmap_exit(void);
 dasd_devmap_t *dasd_devmap_from_devno(int);
 dasd_devmap_t *dasd_devmap_from_devindex(int);
-dasd_devmap_t *dasd_devmap_from_irq(int);
-dasd_devmap_t *dasd_devmap_from_bdev(struct block_device *bdev);
 dasd_device_t *dasd_get_device(dasd_devmap_t *);
 void dasd_put_device(dasd_devmap_t *);
 
-int dasd_devno(char *, char **);
-int dasd_feature_list(char *, char **);
 int dasd_parse(void);
 int dasd_add_range(int, int, int);
 
 /* externals in dasd_gendisk.c */
 int  dasd_gendisk_init(void);
 void dasd_gendisk_exit(void);
-int  dasd_gendisk_major_index(int);
 int  dasd_gendisk_index_major(int);
 struct gendisk *dasd_gendisk_alloc(int);
 void dasd_setup_partitions(dasd_device_t *);
@@ -498,22 +507,21 @@ dasd_ccw_req_t *dasd_default_erp_action(dasd_ccw_req_t *);
 dasd_ccw_req_t *dasd_default_erp_postaction(dasd_ccw_req_t *);
 dasd_ccw_req_t *dasd_alloc_erp_request(char *, int, int, dasd_device_t *);
 void dasd_free_erp_request(dasd_ccw_req_t *, dasd_device_t *);
+void dasd_log_sense(dasd_ccw_req_t *, struct irb *);
 void dasd_log_ccw(dasd_ccw_req_t *, int, __u32);
 
 /* externals in dasd_3370_erp.c */
-dasd_era_t dasd_3370_erp_examine(dasd_ccw_req_t *, devstat_t *);
+dasd_era_t dasd_3370_erp_examine(dasd_ccw_req_t *, struct irb *);
 
 /* externals in dasd_3990_erp.c */
-dasd_era_t dasd_3990_erp_examine(dasd_ccw_req_t *, devstat_t *);
+dasd_era_t dasd_3990_erp_examine(dasd_ccw_req_t *, struct irb *);
 dasd_ccw_req_t *dasd_3990_erp_action(dasd_ccw_req_t *);
-dasd_ccw_req_t *dasd_2105_erp_action(dasd_ccw_req_t *);
-void dasd_3990_erp_restart_queue(unsigned long);
 
 /* externals in dasd_9336_erp.c */
-dasd_era_t dasd_9336_erp_examine(dasd_ccw_req_t *, devstat_t *);
+dasd_era_t dasd_9336_erp_examine(dasd_ccw_req_t *, struct irb *);
 
 /* externals in dasd_9336_erp.c */
-dasd_era_t dasd_9343_erp_examine(dasd_ccw_req_t *, devstat_t *);
+dasd_era_t dasd_9343_erp_examine(dasd_ccw_req_t *, struct irb *);
 dasd_ccw_req_t *dasd_9343_erp_action(dasd_ccw_req_t *);
 
 #endif                         /* __KERNEL__ */
index 4c86c36abee3801fe6703e06a619f1235a81e408..def999eb433474559f8a07734edb72ae82ed8911 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/blkpg.h>
 #include <linux/blk.h>
 
-#include <asm/irq.h>
+#include <asm/ccwdev.h>
 #include <asm/uaccess.h>
 
 /* This is ugly... */
@@ -125,7 +125,7 @@ dasd_ioctl(struct inode *inp, struct file *filp,
        DBF_DEV_EVENT(DBF_INFO, device,
                      "unknown ioctl 0x%08x=%s'0x%x'%d(%d) data %8lx", no,
                      dir, _IOC_TYPE(no), _IOC_NR(no), _IOC_SIZE(no), data);
-       return -ENOTTY;
+       return -EINVAL;
 }
 
 static int
@@ -137,24 +137,20 @@ dasd_ioctl_api_version(struct block_device *bdev, int no, long args)
 
 /*
  * Enable device.
+ * FIXME: how can we get here if the device is not already enabled?
+ *     -arnd
  */
 static int
 dasd_ioctl_enable(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
-       int devno;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
-       devno = device->devinfo.devno;
-       dasd_enable_devices(devno, devno);
-       dasd_put_device(devmap);
+       device = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
+       dasd_enable_device(device);
        return 0;
 }
 
@@ -164,16 +160,13 @@ dasd_ioctl_enable(struct block_device *bdev, int no, long args)
 static int
 dasd_ioctl_disable(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
+       device = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
        /*
         * Man this is sick. We don't do a real disable but only downgrade
         * the device to DASD_STATE_BASIC. The reason is that dasdfmt uses
@@ -183,7 +176,6 @@ dasd_ioctl_disable(struct block_device *bdev, int no, long args)
         * device is DASD_STATE_BASIC that allows to do basic i/o.
         */
        dasd_set_target_state(device, DASD_STATE_BASIC);
-       dasd_put_device(devmap);
        return 0;
 }
 
@@ -238,35 +230,28 @@ dasd_format(dasd_device_t * device, format_data_t * fdata)
 static int
 dasd_ioctl_format(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
        format_data_t fdata;
-       int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
        if (!args)
                return -EINVAL;
        /* fdata == NULL is no longer a valid arg to dasd_format ! */
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
+       device = bdev->bd_disk->private_data;
 
-       rc = 0;
-       if (devmap->features & DASD_FEATURE_READONLY)
-               rc = -EROFS;
-       else if (copy_from_user(&fdata, (void *) args, sizeof (format_data_t)))
-               rc = -EFAULT;
-       else if (bdev != bdev->bd_contains) {
+       if (device == NULL)
+               return -ENODEV;
+       if (device->ro_flag)
+               return -EROFS;
+       if (copy_from_user(&fdata, (void *) args, sizeof (format_data_t)))
+               return -EFAULT;
+       if (bdev != bdev->bd_contains) {
                DEV_MESSAGE(KERN_WARNING, device, "%s",
                            "Cannot low-level format a partition");
-               rc = -EINVAL;
-       } else
-               rc = dasd_format(device, &fdata);
-       dasd_put_device(devmap);
-       return rc;
+               return -EINVAL;
+       }
+       return dasd_format(device, &fdata);
 }
 
 #ifdef CONFIG_DASD_PROFILE
@@ -276,18 +261,16 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
 static int
 dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
+
+       device = = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
+
        memset(&device->profile, 0, sizeof (dasd_profile_info_t));
-       dasd_put_device(devmap);
        return 0;
 }
 
@@ -297,21 +280,16 @@ dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args)
 static int
 dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
-       int rc;
 
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
-       rc = 0;
+       device = = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
+
        if (copy_to_user((long *) args, (long *) &device->profile,
                         sizeof (dasd_profile_info_t)))
-               rc = -EFAULT;
-       dasd_put_device(devmap);
-       return rc;
+               return -EFAULT;
+       return 0;
 }
 #else
 static int
@@ -333,40 +311,37 @@ dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
 static int
 dasd_ioctl_information(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
        dasd_information2_t *dasd_info;
        unsigned long flags;
        int rc;
+       struct ccw_device *cdev;
+
+       device = bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
 
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
-       if (!device->discipline->fill_info) {
-               dasd_put_device(devmap);
+       if (!device->discipline->fill_info)
                return -EINVAL;
-       }
 
        dasd_info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
-       if (dasd_info == NULL) {
-               dasd_put_device(devmap);
+       if (dasd_info == NULL)
                return -ENOMEM;
-       }
+
        rc = device->discipline->fill_info(device, dasd_info);
        if (rc) {
-               dasd_put_device(devmap);
                kfree(dasd_info);
                return rc;
        }
 
-       dasd_info->devno = device->devinfo.devno;
-       dasd_info->schid = device->devinfo.irq;
-       dasd_info->cu_type = device->devinfo.sid_data.cu_type;
-       dasd_info->cu_model = device->devinfo.sid_data.cu_model;
-       dasd_info->dev_type = device->devinfo.sid_data.dev_type;
-       dasd_info->dev_model = device->devinfo.sid_data.dev_model;
+       cdev = device->cdev;
+
+       dasd_info->devno = device->devno;
+       dasd_info->schid = _ccw_device_get_subchannel_number(device->cdev);
+       dasd_info->cu_type = cdev->id.cu_type;
+       dasd_info->cu_model = cdev->id.cu_model;
+       dasd_info->dev_type = cdev->id.dev_type;
+       dasd_info->dev_model = cdev->id.dev_model;
        dasd_info->open_count = atomic_read(&device->open_count);
        dasd_info->status = device->state;
        
@@ -378,8 +353,9 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
            (dasd_check_blocksize(device->bp_block)))
                dasd_info->format = DASD_FORMAT_NONE;
        
-       dasd_info->features = devmap->features;
-       
+       dasd_info->features |= device->ro_flag ? DASD_FEATURE_READONLY
+                                              : DASD_FEATURE_DEFAULT;
+
        if (device->discipline)
                memcpy(dasd_info->type, device->discipline->name, 4);
        else
@@ -397,10 +373,10 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
                        spin_unlock_irqrestore(&device->lock, flags);
                }
 #endif                         /* DASD_EXTENDED_PROFILING */
-               spin_lock_irqsave(get_irq_lock(device->devinfo.irq), flags);
+               spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
                list_for_each(l, &device->ccw_queue)
                        dasd_info->chanq_len++;
-               spin_unlock_irqrestore(get_irq_lock(device->devinfo.irq),
+               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev),
                                       flags);
        }
        
@@ -410,7 +386,6 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
                          sizeof (dasd_information2_t) :
                          sizeof (dasd_information_t))))
                rc = -EFAULT;
-       dasd_put_device(devmap);
        kfree(dasd_info);
        return rc;
 }
@@ -421,9 +396,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
 static int
 dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
 {
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
-       int intval, i;
+       int intval;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
@@ -432,18 +406,11 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
                return -EINVAL;
        if (get_user(intval, (int *) args))
                return -EFAULT;
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
-       if (intval)
-               devmap->features |= DASD_FEATURE_READONLY;
-       else
-               devmap->features &= ~DASD_FEATURE_READONLY;
+       device =  bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
        set_disk_ro(bdev->bd_disk, intval);
        device->ro_flag = intval;
-       dasd_put_device(devmap);
        return 0;
 }
 
@@ -454,27 +421,24 @@ static int
 dasd_ioctl_getgeo(struct block_device *bdev, int no, long args)
 {
        struct hd_geometry geo = { 0, };
-       dasd_devmap_t *devmap;
        dasd_device_t *device;
-       int rc;
 
-       devmap = dasd_devmap_from_bdev(bdev);
-       device = (devmap != NULL) ?
-               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-       if (IS_ERR(device))
-               return PTR_ERR(device);
-       rc = 0;
-       if (device != NULL && device->discipline != NULL &&
-           device->discipline->fill_geometry != NULL) {
-               device->discipline->fill_geometry(device, &geo);
-               geo.start = get_start_sect(bdev);
-               if (copy_to_user((struct hd_geometry *) args, &geo,
-                                sizeof (struct hd_geometry)))
-                       rc = -EFAULT;
-       } else
-               rc = -EINVAL;
-       dasd_put_device(devmap);
-       return rc;
+       device =  bdev->bd_disk->private_data;
+       if (device == NULL)
+               return -ENODEV;
+
+       if (device == NULL || device->discipline == NULL ||
+           device->discipline->fill_geometry == NULL)
+               return -EINVAL;
+
+       geo = (struct hd_geometry) {};
+       device->discipline->fill_geometry(device, &geo);
+       geo.start = get_start_sect(bdev) >> device->s2b_shift;
+       if (copy_to_user((struct hd_geometry *) args, &geo,
+                        sizeof (struct hd_geometry)))
+               return -EFAULT;
+
+       return 0;
 }
 
 /*
index cc76c4bdbd364c93a5a4c5104af695261397f819..c9df1587373c96aba57fe133842320edbd6a15c0 100644 (file)
@@ -9,16 +9,19 @@
  *
  * /proc interface for the dasd driver.
  *
+ * $Revision: 1.17 $
+ *
+ * History of changes
  * 05/04/02 split from dasd.c, code restructuring.
  */
 
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/ctype.h>
+#include <linux/seq_file.h>
 #include <linux/vmalloc.h>
 
 #include <asm/debug.h>
-#include <asm/irq.h>
 #include <asm/uaccess.h>
 
 /* This is ugly... */
 
 #include "dasd_int.h"
 
-typedef struct {
-       char *data;
-       int len;
-} tempinfo_t;
-
 static struct proc_dir_entry *dasd_proc_root_entry = NULL;
-static struct proc_dir_entry *dasd_devices_entry;
-static struct proc_dir_entry *dasd_statistics_entry;
-
-static ssize_t
-dasd_generic_read(struct file *file, char *user_buf, size_t user_len,
-                 loff_t * offset)
-{
-       loff_t len;
-       tempinfo_t *p_info = (tempinfo_t *) file->private_data;
-
-       if (*offset >= p_info->len)
-               return 0;       /* EOF */
-       len = p_info->len - *offset;
-       if (user_len < len)
-               len = user_len;
-       if (copy_to_user(user_buf, &(p_info->data[*offset]), len))
-               return -EFAULT;
-       (*offset) += len;
-       return len;             /* number of bytes "read" */
-}
-
-static int
-dasd_generic_close (struct inode *inode, struct file *file)
-{
-       tempinfo_t *info;
-
-       info = (tempinfo_t *) file->private_data;
-       file->private_data = NULL;
-       if (info) {
-               if (info->data)
-                       vfree (info->data);
-               kfree (info);
-       }
-       return 0;
-}
+static struct proc_dir_entry *dasd_devices_entry = NULL;
+static struct proc_dir_entry *dasd_statistics_entry = NULL;
 
 static inline char *
 dasd_get_user_string(const char *user_buf, size_t user_len)
@@ -88,189 +53,121 @@ dasd_get_user_string(const char *user_buf, size_t user_len)
        return buffer;
 }
 
-static ssize_t
-dasd_devices_write(struct file *file, const char *user_buf,
-                  size_t user_len, loff_t * offset)
-{
-       char *buffer, *str;
-       int add_or_set;
-       int from, to, features;
-
-       buffer = dasd_get_user_string(user_buf, user_len);
-       MESSAGE(KERN_INFO, "/proc/dasd/devices: '%s'", buffer);
-
-       /* Scan for "add " or "set ". */
-       for (str = buffer; isspace(*str); str++);
-       if (strncmp(str, "add", 3) == 0 && isspace(str[3]))
-               add_or_set = 0;
-       else if (strncmp(str, "set", 3) == 0 && isspace(str[3]))
-               add_or_set = 1;
-       else
-               goto out_error;
-       for (str = str + 4; isspace(*str); str++);
-
-       /* Scan for "device " and "range=" and ignore it. This is sick. */
-       if (strncmp(str, "device", 6) == 0 && isspace(str[6]))
-               for (str = str + 6; isspace(*str); str++);
-       if (strncmp(str, "range=", 6) == 0) 
-               for (str = str + 6; isspace(*str); str++);
-
-       /* Scan device number range and feature string. */
-       to = from = dasd_devno(str, &str);
-       if (*str == '-') {
-               str++;
-               to = dasd_devno(str, &str);
-       }
-       features = dasd_feature_list(str, &str);
-       /* Negative numbers in from/to/features indicate errors */
-       if (from < 0 || to < 0 || from > 65546 || to > 65536 || features < 0)
-               goto out_error;
-
-       if (add_or_set == 0) {
-               dasd_add_range(from, to, features);
-               dasd_enable_devices(from, to);
-       } else {
-               for (; isspace(*str); str++);
-               if (strcmp(str, "on") == 0)
-                       dasd_enable_devices(from, to);
-               else if (strcmp(str, "off") == 0)
-                       dasd_disable_devices(from, to);
-               else
-                       goto out_error;
-       }
-       kfree(buffer);
-       return user_len;
-out_error:
-       MESSAGE(KERN_WARNING,
-               "/proc/dasd/devices: range parse error in '%s'",
-               buffer);
-       kfree(buffer);
-       return -EINVAL;
-}
-
-static inline int
-dasd_devices_print(dasd_devmap_t *devmap, char *str)
+static int
+dasd_devices_show(struct seq_file *m, void *v)
 {
+       dasd_devmap_t *devmap;
        dasd_device_t *device;
        char *substr;
-       int len;
 
-       device = dasd_get_device(devmap);
+       devmap = dasd_devmap_from_devindex((unsigned long) v - 1);
+       device = (devmap != NULL) ?
+               dasd_get_device(devmap) : ERR_PTR(-ENODEV);
        if (IS_ERR(device))
                return 0;
        /* Print device number. */
-       len = sprintf(str, "%04x", devmap->devno);
+       seq_printf(m, "%04x", devmap->devno);
        /* Print discipline string. */
        if (device != NULL && device->discipline != NULL)
-               len += sprintf(str + len, "(%s)", device->discipline->name);
+               seq_printf(m, "(%s)", device->discipline->name);
        else
-               len += sprintf(str + len, "(none)");
+               seq_printf(m, "(none)");
        /* Print kdev. */
-       len += sprintf(str + len, " at (%3d:%3d)",
-                      device->gdp->major, device->gdp->first_minor);
+       seq_printf(m, " at (%3d:%3d)",
+                  device->gdp->major, device->gdp->first_minor);
        /* Print device name. */
-       len += sprintf(str + len, " is %-7s", device->gdp->disk_name);
+       seq_printf(m, " is %-7s", device->gdp->disk_name);
        /* Print devices features. */
-       substr = (devmap->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
-       len += sprintf(str + len, "%4s: ", substr);
+       substr = device->ro_flag ? "(ro)" : " ";
+       seq_printf(m, "%4s: ", substr);
        /* Print device status information. */
-       if (device == NULL) {
-               len += sprintf(str + len, "unknown");
-               dasd_put_device(devmap);
-               return len;
-       }
-       switch (device->state) {
+       switch ((device != NULL) ? device->state : -1) {
+       case -1:
+               seq_printf(m, "unknown");
+               break;
        case DASD_STATE_NEW:
-               len += sprintf(str + len, "new");
+               seq_printf(m, "new");
                break;
        case DASD_STATE_KNOWN:
-               len += sprintf(str + len, "detected");
+               seq_printf(m, "detected");
                break;
        case DASD_STATE_BASIC:
-               len += sprintf(str + len, "basic");
+               seq_printf(m, "basic");
                break;
        case DASD_STATE_ACCEPT:
-               len += sprintf(str + len, "accepted");
+               seq_printf(m, "accepted");
                break;
        case DASD_STATE_READY:
        case DASD_STATE_ONLINE:
-               if (device->state < DASD_STATE_ONLINE)
-                       len += sprintf(str + len, "fenced ");
-               else
-                       len += sprintf(str + len, "active ");
+               seq_printf(m, "active ");
                if (dasd_check_blocksize(device->bp_block))
-                       len += sprintf(str + len, "n/f   ");
+                       seq_printf(m, "n/f       ");
                else
-                       len += sprintf(str + len,
-                                      "at blocksize: %d, %ld blocks, %ld MB",
-                                      device->bp_block, device->blocks,
-                                      ((device->bp_block >> 9) *
-                                       device->blocks) >> 11);
+                       seq_printf(m,
+                                  "at blocksize: %d, %ld blocks, %ld MB",
+                                  device->bp_block, device->blocks,
+                                  ((device->bp_block >> 9) *
+                                   device->blocks) >> 11);
                break;
        default:
-               len += sprintf(str + len, "no stat");
+               seq_printf(m, "no stat");
                break;
        }
        dasd_put_device(devmap);
-       return len;
+       if (dasd_probeonly)
+               seq_printf(m, "(probeonly)");
+       seq_printf(m, "\n");
+       return 0;
 }
 
-static int
-dasd_devices_open(struct inode *inode, struct file *file)
+static void *dasd_devices_start(struct seq_file *m, loff_t *pos)
 {
-       tempinfo_t *info;
-       int size, len;
-       int devindex;
-
-       info = (tempinfo_t *) kmalloc(sizeof (tempinfo_t), GFP_KERNEL);
-       if (info == NULL) {
-               MESSAGE(KERN_WARNING, "%s",
-                       "No memory available for data (tempinfo)");
-               return -ENOMEM;
-
-       }
+       if (*pos >= dasd_max_devindex)
+               return NULL;
+       return (void *)((unsigned long) *pos + 1);
+}
 
-       size = dasd_max_devindex * 128;
-       info->data = (char *) vmalloc (size);
-       if (size && info->data == NULL) {
-               MESSAGE(KERN_WARNING, "%s",
-                       "No memory available for data (info->data)");
-               kfree(info);
-               return -ENOMEM;
-       }
-       file->private_data = (void *) info;
+static void *dasd_devices_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       ++*pos;
+       return dasd_devices_start(m, pos);
+}
 
-       DBF_EVENT(DBF_NOTICE,
-                 "procfs-area: %p, size 0x%x allocated", info->data, size);
+static void dasd_devices_stop(struct seq_file *m, void *v)
+{
+}
 
-       len = 0;
-       for (devindex = 0; devindex < dasd_max_devindex; devindex++) {
-               dasd_devmap_t *devmap;
+static struct seq_operations dasd_devices_seq_ops = {
+       .start          = dasd_devices_start,
+       .next           = dasd_devices_next,
+       .stop           = dasd_devices_stop,
+       .show           = dasd_devices_show,
+};
 
-               devmap = dasd_devmap_from_devindex(devindex);
-               len += dasd_devices_print(devmap, info->data + len);
-               if (dasd_probeonly)
-                       len += sprintf(info->data + len, "(probeonly)");
-               len += sprintf(info->data + len, "\n");
-       }
-       info->len = len;
-       if (len > size) {
-               printk("len = %i, size = %i\n", len, size);
-               BUG();
-       }
-       return 0;
+static int dasd_devices_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &dasd_devices_seq_ops);
 }
 
 static struct file_operations dasd_devices_file_ops = {
-       .owner = THIS_MODULE,
-       .read = dasd_generic_read,              /* read */
-       .write = dasd_devices_write,    /* write */
-       .open = dasd_devices_open,              /* open */
-       .release = dasd_generic_close,  /* close */
+       .open           = dasd_devices_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
 };
 
-static struct inode_operations dasd_devices_inode_ops = {
-};
+static inline int
+dasd_calc_metrics(char *page, char **start, off_t off,
+                 int count, int *eof, int len)
+{
+       len = (len > off) ? len - off : 0;
+       if (len > count)
+               len = count;
+       if (len < count)
+               *eof = 1;
+       *start = page + off;
+       return len;
+}
 
 static inline char *
 dasd_statistics_array(char *str, int *array, int shift)
@@ -287,48 +184,28 @@ dasd_statistics_array(char *str, int *array, int shift)
 }
 
 static int
-dasd_statistics_open(struct inode *inode, struct file *file)
+dasd_statistics_read(char *page, char **start, off_t off,
+                    int count, int *eof, void *data)
 {
-       tempinfo_t *info;
+       unsigned long len;
 #ifdef CONFIG_DASD_PROFILE
        dasd_profile_info_t *prof;
        char *str;
        int shift;
-#endif
-
-       info = (tempinfo_t *) kmalloc(sizeof (tempinfo_t), GFP_KERNEL);
-       if (info == NULL) {
-               MESSAGE(KERN_WARNING, "%s",
-                       "No memory available for data (tempinfo)");
-               return -ENOMEM;
-       }
 
-       file->private_data = (void *) info;
-       /* FIXME! determine space needed in a better way */
-       info->data = (char *) vmalloc (PAGE_SIZE);
-
-       if (info->data == NULL) {
-               MESSAGE(KERN_WARNING, "%s",
-                       "No memory available for data (info->data)");
-               kfree(info);
-               file->private_data = NULL;
-               return -ENOMEM;
-       }
-#ifdef CONFIG_DASD_PROFILE
        /* check for active profiling */
        if (dasd_profile_level == DASD_PROFILE_OFF) {
-               info->len = sprintf(info->data,
-                                   "Statistics are off - they might be "
+               len = sprintf(page, "Statistics are off - they might be "
                                    "switched on using 'echo set on > "
                                    "/proc/dasd/statistics'\n");
-               return 0;
+               return dasd_calc_metrics(page, start, off, count, eof, len);
        }
 
        prof = &dasd_global_profile;
        /* prevent couter 'overflow' on output */
        for (shift = 0; (prof->dasd_io_reqs >> shift) > 9999999; shift++);
 
-       str = info->data;
+       str = page;
        str += sprintf(str, "%d dasd I/O requests\n", prof->dasd_io_reqs);
        str += sprintf(str, "with %d sectors(512B each)\n",
                       prof->dasd_io_sects);
@@ -358,22 +235,22 @@ dasd_statistics_open(struct inode *inode, struct file *file)
        str = dasd_statistics_array(str, prof->dasd_io_time3, shift);
        str += sprintf(str, "# of req in chanq at enqueuing (1..32) \n");
        str = dasd_statistics_array(str, prof->dasd_io_nr_req, shift);
-
-       info->len = str - info->data;
+       len = str - page;
 #else
-       info->len = sprintf(info->data,
-                           "Statistics are not activated in this kernel\n");
+       len = sprintf(page, "Statistics are not activated in this kernel\n");
 #endif
-       return 0;
+       return dasd_calc_metrics(page, start, off, count, eof, len);
 }
 
-static ssize_t
+static int
 dasd_statistics_write(struct file *file, const char *user_buf,
-                     size_t user_len, loff_t * offset)
+                     unsigned long user_len, void *data)
 {
 #ifdef CONFIG_DASD_PROFILE
        char *buffer, *str;
 
+       if (user_len > 65536)
+               user_len = 65536;
        buffer = dasd_get_user_string(user_buf, user_len);
        MESSAGE(KERN_INFO, "/proc/dasd/statictics: '%s'", buffer);
 
@@ -415,31 +292,22 @@ out_error:
 #endif                         /* CONFIG_DASD_PROFILE */
 }
 
-static struct file_operations dasd_statistics_file_ops = {
-       .owner  = THIS_MODULE,
-       .read   = dasd_generic_read,    /* read */
-       .write  = dasd_statistics_write,        /* write */
-       .open   = dasd_statistics_open, /* open */
-       .release = dasd_generic_close,  /* close */
-};
-
-static struct inode_operations dasd_statistics_inode_ops = {
-};
-
 int
 dasd_proc_init(void)
 {
        dasd_proc_root_entry = proc_mkdir("dasd", &proc_root);
+       dasd_proc_root_entry->owner = THIS_MODULE;
        dasd_devices_entry = create_proc_entry("devices",
                                               S_IFREG | S_IRUGO | S_IWUSR,
                                               dasd_proc_root_entry);
        dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
-       dasd_devices_entry->proc_iops = &dasd_devices_inode_ops;
+       dasd_devices_entry->owner = THIS_MODULE;
        dasd_statistics_entry = create_proc_entry("statistics",
                                                  S_IFREG | S_IRUGO | S_IWUSR,
                                                  dasd_proc_root_entry);
-       dasd_statistics_entry->proc_fops = &dasd_statistics_file_ops;
-       dasd_statistics_entry->proc_iops = &dasd_statistics_inode_ops;
+       dasd_statistics_entry->read_proc = dasd_statistics_read;
+       dasd_statistics_entry->write_proc = dasd_statistics_write;
+       dasd_statistics_entry->owner = THIS_MODULE;
        return 0;
 }
 
index d536b229bfc93253fddd2571f9538e06a3218614..b8b3d6c1d35b989ff14f8571b82465da38863457 100644 (file)
@@ -8,6 +8,8 @@
  * any future changes wrt the API will result in a change of the APIVERSION reported
  * to userspace by the DASDAPIVER-ioctl
  *
+ * $Revision: 1.3 $
+ *
  * History of changes (starts July 2000)
  * 05/04/01 created by moving the kernel interface to drivers/s390/block/dasd_int.h
  * 12/06/01 DASD_API_VERSION 2 - binary compatible to 0 (new BIODASDINFO2)
@@ -224,8 +226,6 @@ typedef struct attrib_data_t {
 #define BIODASDSLCK    _IO(DASD_IOCTL_LETTER,4) /* steal lock */
 /* reset profiling information of a device */
 #define BIODASDPRRST   _IO(DASD_IOCTL_LETTER,5)
-/* enable PAV */
-#define BIODASDENAPAV  _IO(DASD_IOCTL_LETTER,6)
 
 
 /* retrieve API version number */
index d536b229bfc93253fddd2571f9538e06a3218614..b8b3d6c1d35b989ff14f8571b82465da38863457 100644 (file)
@@ -8,6 +8,8 @@
  * any future changes wrt the API will result in a change of the APIVERSION reported
  * to userspace by the DASDAPIVER-ioctl
  *
+ * $Revision: 1.3 $
+ *
  * History of changes (starts July 2000)
  * 05/04/01 created by moving the kernel interface to drivers/s390/block/dasd_int.h
  * 12/06/01 DASD_API_VERSION 2 - binary compatible to 0 (new BIODASDINFO2)
@@ -224,8 +226,6 @@ typedef struct attrib_data_t {
 #define BIODASDSLCK    _IO(DASD_IOCTL_LETTER,4) /* steal lock */
 /* reset profiling information of a device */
 #define BIODASDPRRST   _IO(DASD_IOCTL_LETTER,5)
-/* enable PAV */
-#define BIODASDENAPAV  _IO(DASD_IOCTL_LETTER,6)
 
 
 /* retrieve API version number */