linux/drivers/s390/block/dasd_eckd.c
<<
>>
Prefs
   1/*
   2 * File...........: linux/drivers/s390/block/dasd_eckd.c
   3 * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
   4 *                  Horst Hummel <Horst.Hummel@de.ibm.com>
   5 *                  Carsten Otte <Cotte@de.ibm.com>
   6 *                  Martin Schwidefsky <schwidefsky@de.ibm.com>
   7 * Bugreports.to..: <Linux390@de.ibm.com>
   8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
   9 *
  10 */
  11
  12#include <linux/stddef.h>
  13#include <linux/kernel.h>
  14#include <linux/slab.h>
  15#include <linux/hdreg.h>        /* HDIO_GETGEO                      */
  16#include <linux/bio.h>
  17#include <linux/module.h>
  18#include <linux/init.h>
  19
  20#include <asm/debug.h>
  21#include <asm/idals.h>
  22#include <asm/ebcdic.h>
  23#include <asm/io.h>
  24#include <asm/todclk.h>
  25#include <asm/uaccess.h>
  26#include <asm/cio.h>
  27#include <asm/ccwdev.h>
  28
  29#include "dasd_int.h"
  30#include "dasd_eckd.h"
  31
  32#ifdef PRINTK_HEADER
  33#undef PRINTK_HEADER
  34#endif                          /* PRINTK_HEADER */
  35#define PRINTK_HEADER "dasd(eckd):"
  36
  37#define ECKD_C0(i) (i->home_bytes)
  38#define ECKD_F(i) (i->formula)
  39#define ECKD_F1(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f1):\
  40                    (i->factors.f_0x02.f1))
  41#define ECKD_F2(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f2):\
  42                    (i->factors.f_0x02.f2))
  43#define ECKD_F3(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f3):\
  44                    (i->factors.f_0x02.f3))
  45#define ECKD_F4(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f4):0)
  46#define ECKD_F5(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f5):0)
  47#define ECKD_F6(i) (i->factor6)
  48#define ECKD_F7(i) (i->factor7)
  49#define ECKD_F8(i) (i->factor8)
  50
  51MODULE_LICENSE("GPL");
  52
  53static struct dasd_discipline dasd_eckd_discipline;
  54
  55struct dasd_eckd_private {
  56        struct dasd_eckd_characteristics rdc_data;
  57        struct dasd_eckd_confdata conf_data;
  58        struct dasd_eckd_path path_data;
  59        struct eckd_count count_area[5];
  60        int init_cqr_status;
  61        int uses_cdl;
  62        struct attrib_data_t attrib;    /* e.g. cache operations */
  63};
  64
  65/* The ccw bus type uses this table to find devices that it sends to
  66 * dasd_eckd_probe */
  67static struct ccw_device_id dasd_eckd_ids[] = {
  68        { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3390, 0), .driver_info = 0x1},
  69        { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3390, 0), .driver_info = 0x2},
  70        { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3390, 0), .driver_info = 0x3},
  71        { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), .driver_info = 0x4},
  72        { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), .driver_info = 0x5},
  73        { CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), .driver_info = 0x6},
  74        { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3390, 0), .driver_info = 0x7},
  75        { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3380, 0), .driver_info = 0x8},
  76        { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3390, 0), .driver_info = 0x9},
  77        { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3380, 0), .driver_info = 0xa},
  78        { /* end of list */ },
  79};
  80
  81MODULE_DEVICE_TABLE(ccw, dasd_eckd_ids);
  82
  83static struct ccw_driver dasd_eckd_driver; /* see below */
  84
  85/* initial attempt at a probe function. this can be simplified once
  86 * the other detection code is gone */
  87static int
  88dasd_eckd_probe (struct ccw_device *cdev)
  89{
  90        int ret;
  91
  92        /* set ECKD specific ccw-device options */
  93        ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE);
  94        if (ret) {
  95                printk(KERN_WARNING
  96                       "dasd_eckd_probe: could not set ccw-device options "
  97                       "for %s\n", cdev->dev.bus_id);
  98                return ret;
  99        }
 100        ret = dasd_generic_probe(cdev, &dasd_eckd_discipline);
 101        return ret;
 102}
 103
 104static int
 105dasd_eckd_set_online(struct ccw_device *cdev)
 106{
 107        return dasd_generic_set_online(cdev, &dasd_eckd_discipline);
 108}
 109
 110static struct ccw_driver dasd_eckd_driver = {
 111        .name        = "dasd-eckd",
 112        .owner       = THIS_MODULE,
 113        .ids         = dasd_eckd_ids,
 114        .probe       = dasd_eckd_probe,
 115        .remove      = dasd_generic_remove,
 116        .set_offline = dasd_generic_set_offline,
 117        .set_online  = dasd_eckd_set_online,
 118        .notify      = dasd_generic_notify,
 119};
 120
 121static const int sizes_trk0[] = { 28, 148, 84 };
 122#define LABEL_SIZE 140
 123
 124static inline unsigned int
 125round_up_multiple(unsigned int no, unsigned int mult)
 126{
 127        int rem = no % mult;
 128        return (rem ? no - rem + mult : no);
 129}
 130
 131static inline unsigned int
 132ceil_quot(unsigned int d1, unsigned int d2)
 133{
 134        return (d1 + (d2 - 1)) / d2;
 135}
 136
 137static unsigned int
 138recs_per_track(struct dasd_eckd_characteristics * rdc,
 139               unsigned int kl, unsigned int dl)
 140{
 141        int dn, kn;
 142
 143        switch (rdc->dev_type) {
 144        case 0x3380:
 145                if (kl)
 146                        return 1499 / (15 + 7 + ceil_quot(kl + 12, 32) +
 147                                       ceil_quot(dl + 12, 32));
 148                else
 149                        return 1499 / (15 + ceil_quot(dl + 12, 32));
 150        case 0x3390:
 151                dn = ceil_quot(dl + 6, 232) + 1;
 152                if (kl) {
 153                        kn = ceil_quot(kl + 6, 232) + 1;
 154                        return 1729 / (10 + 9 + ceil_quot(kl + 6 * kn, 34) +
 155                                       9 + ceil_quot(dl + 6 * dn, 34));
 156                } else
 157                        return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34));
 158        case 0x9345:
 159                dn = ceil_quot(dl + 6, 232) + 1;
 160                if (kl) {
 161                        kn = ceil_quot(kl + 6, 232) + 1;
 162                        return 1420 / (18 + 7 + ceil_quot(kl + 6 * kn, 34) +
 163                                       ceil_quot(dl + 6 * dn, 34));
 164                } else
 165                        return 1420 / (18 + 7 + ceil_quot(dl + 6 * dn, 34));
 166        }
 167        return 0;
 168}
 169
 170static int
 171check_XRC (struct ccw1         *de_ccw,
 172           struct DE_eckd_data *data,
 173           struct dasd_device  *device)
 174{
 175        struct dasd_eckd_private *private;
 176        int rc;
 177
 178        private = (struct dasd_eckd_private *) device->private;
 179        if (!private->rdc_data.facilities.XRC_supported)
 180                return 0;
 181
 182        /* switch on System Time Stamp - needed for XRC Support */
 183        data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid'   */
 184        data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */
 185
 186        rc = get_sync_clock(&data->ep_sys_time);
 187        /* Ignore return code if sync clock is switched off. */
 188        if (rc == -ENOSYS || rc == -EACCES)
 189                rc = 0;
 190
 191        de_ccw->count = sizeof (struct DE_eckd_data);
 192        de_ccw->flags |= CCW_FLAG_SLI;
 193        return rc;
 194}
 195
 196static int
 197define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
 198              int totrk, int cmd, struct dasd_device * device)
 199{
 200        struct dasd_eckd_private *private;
 201        struct ch_t geo, beg, end;
 202        int rc = 0;
 203
 204        private = (struct dasd_eckd_private *) device->private;
 205
 206        ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
 207        ccw->flags = 0;
 208        ccw->count = 16;
 209        ccw->cda = (__u32) __pa(data);
 210
 211        memset(data, 0, sizeof (struct DE_eckd_data));
 212        switch (cmd) {
 213        case DASD_ECKD_CCW_READ_HOME_ADDRESS:
 214        case DASD_ECKD_CCW_READ_RECORD_ZERO:
 215        case DASD_ECKD_CCW_READ:
 216        case DASD_ECKD_CCW_READ_MT:
 217        case DASD_ECKD_CCW_READ_CKD:
 218        case DASD_ECKD_CCW_READ_CKD_MT:
 219        case DASD_ECKD_CCW_READ_KD:
 220        case DASD_ECKD_CCW_READ_KD_MT:
 221        case DASD_ECKD_CCW_READ_COUNT:
 222                data->mask.perm = 0x1;
 223                data->attributes.operation = private->attrib.operation;
 224                break;
 225        case DASD_ECKD_CCW_WRITE:
 226        case DASD_ECKD_CCW_WRITE_MT:
 227        case DASD_ECKD_CCW_WRITE_KD:
 228        case DASD_ECKD_CCW_WRITE_KD_MT:
 229                data->mask.perm = 0x02;
 230                data->attributes.operation = private->attrib.operation;
 231                rc = check_XRC (ccw, data, device);
 232                break;
 233        case DASD_ECKD_CCW_WRITE_CKD:
 234        case DASD_ECKD_CCW_WRITE_CKD_MT:
 235                data->attributes.operation = DASD_BYPASS_CACHE;
 236                rc = check_XRC (ccw, data, device);
 237                break;
 238        case DASD_ECKD_CCW_ERASE:
 239        case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
 240        case DASD_ECKD_CCW_WRITE_RECORD_ZERO:
 241                data->mask.perm = 0x3;
 242                data->mask.auth = 0x1;
 243                data->attributes.operation = DASD_BYPASS_CACHE;
 244                rc = check_XRC (ccw, data, device);
 245                break;
 246        default:
 247                DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd);
 248                break;
 249        }
 250
 251        data->attributes.mode = 0x3;    /* ECKD */
 252
 253        if ((private->rdc_data.cu_type == 0x2105 ||
 254             private->rdc_data.cu_type == 0x2107 ||
 255             private->rdc_data.cu_type == 0x1750)
 256            && !(private->uses_cdl && trk < 2))
 257                data->ga_extended |= 0x40; /* Regular Data Format Mode */
 258
 259        geo.cyl = private->rdc_data.no_cyl;
 260        geo.head = private->rdc_data.trk_per_cyl;
 261        beg.cyl = trk / geo.head;
 262        beg.head = trk % geo.head;
 263        end.cyl = totrk / geo.head;
 264        end.head = totrk % geo.head;
 265
 266        /* check for sequential prestage - enhance cylinder range */
 267        if (data->attributes.operation == DASD_SEQ_PRESTAGE ||
 268            data->attributes.operation == DASD_SEQ_ACCESS) {
 269
 270                if (end.cyl + private->attrib.nr_cyl < geo.cyl)
 271                        end.cyl += private->attrib.nr_cyl;
 272                else
 273                        end.cyl = (geo.cyl - 1);
 274        }
 275
 276        data->beg_ext.cyl = beg.cyl;
 277        data->beg_ext.head = beg.head;
 278        data->end_ext.cyl = end.cyl;
 279        data->end_ext.head = end.head;
 280        return rc;
 281}
 282
 283static void
 284locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
 285              int rec_on_trk, int no_rec, int cmd,
 286              struct dasd_device * device, int reclen)
 287{
 288        struct dasd_eckd_private *private;
 289        int sector;
 290        int dn, d;
 291
 292        private = (struct dasd_eckd_private *) device->private;
 293
 294        DBF_DEV_EVENT(DBF_INFO, device,
 295                  "Locate: trk %d, rec %d, no_rec %d, cmd %d, reclen %d",
 296                  trk, rec_on_trk, no_rec, cmd, reclen);
 297
 298        ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
 299        ccw->flags = 0;
 300        ccw->count = 16;
 301        ccw->cda = (__u32) __pa(data);
 302
 303        memset(data, 0, sizeof (struct LO_eckd_data));
 304        sector = 0;
 305        if (rec_on_trk) {
 306                switch (private->rdc_data.dev_type) {
 307                case 0x3390:
 308                        dn = ceil_quot(reclen + 6, 232);
 309                        d = 9 + ceil_quot(reclen + 6 * (dn + 1), 34);
 310                        sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8;
 311                        break;
 312                case 0x3380:
 313                        d = 7 + ceil_quot(reclen + 12, 32);
 314                        sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7;
 315                        break;
 316                }
 317        }
 318        data->sector = sector;
 319        data->count = no_rec;
 320        switch (cmd) {
 321        case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
 322                data->operation.orientation = 0x3;
 323                data->operation.operation = 0x03;
 324                break;
 325        case DASD_ECKD_CCW_READ_HOME_ADDRESS:
 326                data->operation.orientation = 0x3;
 327                data->operation.operation = 0x16;
 328                break;
 329        case DASD_ECKD_CCW_WRITE_RECORD_ZERO:
 330                data->operation.orientation = 0x1;
 331                data->operation.operation = 0x03;
 332                data->count++;
 333                break;
 334        case DASD_ECKD_CCW_READ_RECORD_ZERO:
 335                data->operation.orientation = 0x3;
 336                data->operation.operation = 0x16;
 337                data->count++;
 338                break;
 339        case DASD_ECKD_CCW_WRITE:
 340        case DASD_ECKD_CCW_WRITE_MT:
 341        case DASD_ECKD_CCW_WRITE_KD:
 342        case DASD_ECKD_CCW_WRITE_KD_MT:
 343                data->auxiliary.last_bytes_used = 0x1;
 344                data->length = reclen;
 345                data->operation.operation = 0x01;
 346                break;
 347        case DASD_ECKD_CCW_WRITE_CKD:
 348        case DASD_ECKD_CCW_WRITE_CKD_MT:
 349                data->auxiliary.last_bytes_used = 0x1;
 350                data->length = reclen;
 351                data->operation.operation = 0x03;
 352                break;
 353        case DASD_ECKD_CCW_READ:
 354        case DASD_ECKD_CCW_READ_MT:
 355        case DASD_ECKD_CCW_READ_KD:
 356        case DASD_ECKD_CCW_READ_KD_MT:
 357                data->auxiliary.last_bytes_used = 0x1;
 358                data->length = reclen;
 359                data->operation.operation = 0x06;
 360                break;
 361        case DASD_ECKD_CCW_READ_CKD:
 362        case DASD_ECKD_CCW_READ_CKD_MT:
 363                data->auxiliary.last_bytes_used = 0x1;
 364                data->length = reclen;
 365                data->operation.operation = 0x16;
 366                break;
 367        case DASD_ECKD_CCW_READ_COUNT:
 368                data->operation.operation = 0x06;
 369                break;
 370        case DASD_ECKD_CCW_ERASE:
 371                data->length = reclen;
 372                data->auxiliary.last_bytes_used = 0x1;
 373                data->operation.operation = 0x0b;
 374                break;
 375        default:
 376                DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd);
 377        }
 378        data->seek_addr.cyl = data->search_arg.cyl =
 379                trk / private->rdc_data.trk_per_cyl;
 380        data->seek_addr.head = data->search_arg.head =
 381                trk % private->rdc_data.trk_per_cyl;
 382        data->search_arg.record = rec_on_trk;
 383}
 384
 385/*
 386 * Returns 1 if the block is one of the special blocks that needs
 387 * to get read/written with the KD variant of the command.
 388 * That is DASD_ECKD_READ_KD_MT instead of DASD_ECKD_READ_MT and
 389 * DASD_ECKD_WRITE_KD_MT instead of DASD_ECKD_WRITE_MT.
 390 * Luckily the KD variants differ only by one bit (0x08) from the
 391 * normal variant. So don't wonder about code like:
 392 * if (dasd_eckd_cdl_special(blk_per_trk, recid))
 393 *         ccw->cmd_code |= 0x8;
 394 */
 395static inline int
 396dasd_eckd_cdl_special(int blk_per_trk, int recid)
 397{
 398        if (recid < 3)
 399                return 1;
 400        if (recid < blk_per_trk)
 401                return 0;
 402        if (recid < 2 * blk_per_trk)
 403                return 1;
 404        return 0;
 405}
 406
 407/*
 408 * Returns the record size for the special blocks of the cdl format.
 409 * Only returns something useful if dasd_eckd_cdl_special is true
 410 * for the recid.
 411 */
 412static inline int
 413dasd_eckd_cdl_reclen(int recid)
 414{
 415        if (recid < 3)
 416                return sizes_trk0[recid];
 417        return LABEL_SIZE;
 418}
 419
 420/*
 421 * Generate device unique id that specifies the physical device.
 422 */
 423static int
 424dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid)
 425{
 426        struct dasd_eckd_private *private;
 427        struct dasd_eckd_confdata *confdata;
 428
 429        private = (struct dasd_eckd_private *) device->private;
 430        if (!private)
 431                return -ENODEV;
 432        confdata = &private->conf_data;
 433        if (!confdata)
 434                return -ENODEV;
 435
 436        memset(uid, 0, sizeof(struct dasd_uid));
 437        memcpy(uid->vendor, confdata->ned1.HDA_manufacturer,
 438               sizeof(uid->vendor) - 1);
 439        EBCASC(uid->vendor, sizeof(uid->vendor) - 1);
 440        memcpy(uid->serial, confdata->ned1.HDA_location,
 441               sizeof(uid->serial) - 1);
 442        EBCASC(uid->serial, sizeof(uid->serial) - 1);
 443        uid->ssid = confdata->neq.subsystemID;
 444        if (confdata->ned2.sneq.flags == 0x40) {
 445                uid->alias = 1;
 446                uid->unit_addr = confdata->ned2.sneq.base_unit_addr;
 447        } else
 448                uid->unit_addr = confdata->ned1.unit_addr;
 449
 450        return 0;
 451}
 452
 453static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device,
 454                                                    void *rcd_buffer,
 455                                                    struct ciw *ciw, __u8 lpm)
 456{
 457        struct dasd_ccw_req *cqr;
 458        struct ccw1 *ccw;
 459
 460        cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device);
 461
 462        if (IS_ERR(cqr)) {
 463                DEV_MESSAGE(KERN_WARNING, device, "%s",
 464                            "Could not allocate RCD request");
 465                return cqr;
 466        }
 467
 468        ccw = cqr->cpaddr;
 469        ccw->cmd_code = ciw->cmd;
 470        ccw->cda = (__u32)(addr_t)rcd_buffer;
 471        ccw->count = ciw->count;
 472
 473        cqr->device = device;
 474        cqr->expires = 10*HZ;
 475        cqr->lpm = lpm;
 476        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
 477        cqr->retries = 2;
 478        cqr->buildclk = get_clock();
 479        cqr->status = DASD_CQR_FILLED;
 480        return cqr;
 481}
 482
 483static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
 484                                   void **rcd_buffer,
 485                                   int *rcd_buffer_size, __u8 lpm)
 486{
 487        struct ciw *ciw;
 488        char *rcd_buf = NULL;
 489        int ret;
 490        struct dasd_ccw_req *cqr;
 491
 492        /*
 493         * scan for RCD command in extended SenseID data
 494         */
 495        ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD);
 496        if (!ciw || ciw->cmd == 0) {
 497                ret = -EOPNOTSUPP;
 498                goto out_error;
 499        }
 500        rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
 501        if (!rcd_buf) {
 502                ret = -ENOMEM;
 503                goto out_error;
 504        }
 505        cqr = dasd_eckd_build_rcd_lpm(device, rcd_buf, ciw, lpm);
 506        if (IS_ERR(cqr)) {
 507                ret =  PTR_ERR(cqr);
 508                goto out_error;
 509        }
 510        ret = dasd_sleep_on(cqr);
 511        /*
 512         * on success we update the user input parms
 513         */
 514        dasd_sfree_request(cqr, cqr->device);
 515        if (ret)
 516                goto out_error;
 517
 518        *rcd_buffer_size = ciw->count;
 519        *rcd_buffer = rcd_buf;
 520        return 0;
 521out_error:
 522        kfree(rcd_buf);
 523        *rcd_buffer = NULL;
 524        *rcd_buffer_size = 0;
 525        return ret;
 526}
 527
 528static int
 529dasd_eckd_read_conf(struct dasd_device *device)
 530{
 531        void *conf_data;
 532        int conf_len, conf_data_saved;
 533        int rc;
 534        __u8 lpm;
 535        struct dasd_eckd_private *private;
 536        struct dasd_eckd_path *path_data;
 537
 538        private = (struct dasd_eckd_private *) device->private;
 539        path_data = (struct dasd_eckd_path *) &private->path_data;
 540        path_data->opm = ccw_device_get_path_mask(device->cdev);
 541        lpm = 0x80;
 542        conf_data_saved = 0;
 543
 544        /* get configuration data per operational path */
 545        for (lpm = 0x80; lpm; lpm>>= 1) {
 546                if (lpm & path_data->opm){
 547                        rc = dasd_eckd_read_conf_lpm(device, &conf_data,
 548                                                     &conf_len, lpm);
 549                        if (rc && rc != -EOPNOTSUPP) {  /* -EOPNOTSUPP is ok */
 550                                MESSAGE(KERN_WARNING,
 551                                        "Read configuration data returned "
 552                                        "error %d", rc);
 553                                return rc;
 554                        }
 555                        if (conf_data == NULL) {
 556                                MESSAGE(KERN_WARNING, "%s", "No configuration "
 557                                        "data retrieved");
 558                                continue;       /* no error */
 559                        }
 560                        if (conf_len != sizeof (struct dasd_eckd_confdata)) {
 561                                MESSAGE(KERN_WARNING,
 562                                        "sizes of configuration data mismatch"
 563                                        "%d (read) vs %ld (expected)",
 564                                        conf_len,
 565                                        sizeof (struct dasd_eckd_confdata));
 566                                kfree(conf_data);
 567                                continue;       /* no error */
 568                        }
 569                        /* save first valid configuration data */
 570                        if (!conf_data_saved){
 571                                memcpy(&private->conf_data, conf_data,
 572                                       sizeof (struct dasd_eckd_confdata));
 573                                conf_data_saved++;
 574                        }
 575                        switch (((char *)conf_data)[242] & 0x07){
 576                        case 0x02:
 577                                path_data->npm |= lpm;
 578                                break;
 579                        case 0x03:
 580                                path_data->ppm |= lpm;
 581                                break;
 582                        }
 583                        kfree(conf_data);
 584                }
 585        }
 586        return 0;
 587}
 588
 589/*
 590 * Build CP for Perform Subsystem Function - SSC.
 591 */
 592static struct dasd_ccw_req *
 593dasd_eckd_build_psf_ssc(struct dasd_device *device)
 594{
 595       struct dasd_ccw_req *cqr;
 596       struct dasd_psf_ssc_data *psf_ssc_data;
 597       struct ccw1 *ccw;
 598
 599       cqr = dasd_smalloc_request("ECKD", 1 /* PSF */ ,
 600                                  sizeof(struct dasd_psf_ssc_data),
 601                                  device);
 602
 603       if (IS_ERR(cqr)) {
 604               DEV_MESSAGE(KERN_WARNING, device, "%s",
 605                           "Could not allocate PSF-SSC request");
 606               return cqr;
 607       }
 608       psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data;
 609       psf_ssc_data->order = PSF_ORDER_SSC;
 610       psf_ssc_data->suborder = 0x08;
 611
 612       ccw = cqr->cpaddr;
 613       ccw->cmd_code = DASD_ECKD_CCW_PSF;
 614       ccw->cda = (__u32)(addr_t)psf_ssc_data;
 615       ccw->count = 66;
 616
 617       cqr->device = device;
 618       cqr->expires = 10*HZ;
 619       cqr->buildclk = get_clock();
 620       cqr->status = DASD_CQR_FILLED;
 621       return cqr;
 622}
 623
 624/*
 625 * Perform Subsystem Function.
 626 * It is necessary to trigger CIO for channel revalidation since this
 627 * call might change behaviour of DASD devices.
 628 */
 629static int
 630dasd_eckd_psf_ssc(struct dasd_device *device)
 631{
 632       struct dasd_ccw_req *cqr;
 633       int rc;
 634
 635       cqr = dasd_eckd_build_psf_ssc(device);
 636       if (IS_ERR(cqr))
 637               return PTR_ERR(cqr);
 638
 639       rc = dasd_sleep_on(cqr);
 640       if (!rc)
 641               /* trigger CIO to reprobe devices */
 642               css_schedule_reprobe();
 643       dasd_sfree_request(cqr, cqr->device);
 644       return rc;
 645}
 646
 647/*
 648 * Valide storage server of current device.
 649 */
 650static int
 651dasd_eckd_validate_server(struct dasd_device *device, struct dasd_uid *uid)
 652{
 653        int rc;
 654
 655        /* Currently PAV is the only reason to 'validate' server on LPAR */
 656        if (dasd_nopav || MACHINE_IS_VM)
 657                return 0;
 658
 659        rc = dasd_eckd_psf_ssc(device);
 660        /* may be requested feature is not available on server,
 661         * therefore just report error and go ahead */
 662        DEV_MESSAGE(KERN_INFO, device,
 663                    "PSF-SSC on storage subsystem %s.%s.%04x returned rc=%d",
 664                    uid->vendor, uid->serial, uid->ssid, rc);
 665        /* RE-Read Configuration Data */
 666        return dasd_eckd_read_conf(device);
 667}
 668
 669/*
 670 * Check device characteristics.
 671 * If the device is accessible using ECKD discipline, the device is enabled.
 672 */
 673static int
 674dasd_eckd_check_characteristics(struct dasd_device *device)
 675{
 676        struct dasd_eckd_private *private;
 677        struct dasd_uid uid;
 678        void *rdc_data;
 679        int rc;
 680
 681        private = (struct dasd_eckd_private *) device->private;
 682        if (private == NULL) {
 683                private = kzalloc(sizeof(struct dasd_eckd_private),
 684                                  GFP_KERNEL | GFP_DMA);
 685                if (private == NULL) {
 686                        DEV_MESSAGE(KERN_WARNING, device, "%s",
 687                                    "memory allocation failed for private "
 688                                    "data");
 689                        return -ENOMEM;
 690                }
 691                device->private = (void *) private;
 692        }
 693        /* Invalidate status of initial analysis. */
 694        private->init_cqr_status = -1;
 695        /* Set default cache operations. */
 696        private->attrib.operation = DASD_NORMAL_CACHE;
 697        private->attrib.nr_cyl = 0;
 698
 699        /* Read Configuration Data */
 700        rc = dasd_eckd_read_conf(device);
 701        if (rc)
 702                return rc;
 703
 704        /* Generate device unique id and register in devmap */
 705        rc = dasd_eckd_generate_uid(device, &uid);
 706        if (rc)
 707                return rc;
 708        rc = dasd_set_uid(device->cdev, &uid);
 709        if (rc == 1)    /* new server found */
 710                rc = dasd_eckd_validate_server(device, &uid);
 711        if (rc)
 712                return rc;
 713
 714        /* Read Device Characteristics */
 715        rdc_data = (void *) &(private->rdc_data);
 716        memset(rdc_data, 0, sizeof(rdc_data));
 717        rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64);
 718        if (rc)
 719                DEV_MESSAGE(KERN_WARNING, device,
 720                            "Read device characteristics returned "
 721                            "rc=%d", rc);
 722
 723        DEV_MESSAGE(KERN_INFO, device,
 724                    "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d",
 725                    private->rdc_data.dev_type,
 726                    private->rdc_data.dev_model,
 727                    private->rdc_data.cu_type,
 728                    private->rdc_data.cu_model.model,
 729                    private->rdc_data.no_cyl,
 730                    private->rdc_data.trk_per_cyl,
 731                    private->rdc_data.sec_per_trk);
 732        return rc;
 733}
 734
 735static struct dasd_ccw_req *
 736dasd_eckd_analysis_ccw(struct dasd_device *device)
 737{
 738        struct dasd_eckd_private *private;
 739        struct eckd_count *count_data;
 740        struct LO_eckd_data *LO_data;
 741        struct dasd_ccw_req *cqr;
 742        struct ccw1 *ccw;
 743        int cplength, datasize;
 744        int i;
 745
 746        private = (struct dasd_eckd_private *) device->private;
 747
 748        cplength = 8;
 749        datasize = sizeof(struct DE_eckd_data) + 2*sizeof(struct LO_eckd_data);
 750        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
 751                                   cplength, datasize, device);
 752        if (IS_ERR(cqr))
 753                return cqr;
 754        ccw = cqr->cpaddr;
 755        /* Define extent for the first 3 tracks. */
 756        define_extent(ccw++, cqr->data, 0, 2,
 757                      DASD_ECKD_CCW_READ_COUNT, device);
 758        LO_data = cqr->data + sizeof (struct DE_eckd_data);
 759        /* Locate record for the first 4 records on track 0. */
 760        ccw[-1].flags |= CCW_FLAG_CC;
 761        locate_record(ccw++, LO_data++, 0, 0, 4,
 762                      DASD_ECKD_CCW_READ_COUNT, device, 0);
 763
 764        count_data = private->count_area;
 765        for (i = 0; i < 4; i++) {
 766                ccw[-1].flags |= CCW_FLAG_CC;
 767                ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
 768                ccw->flags = 0;
 769                ccw->count = 8;
 770                ccw->cda = (__u32)(addr_t) count_data;
 771                ccw++;
 772                count_data++;
 773        }
 774
 775        /* Locate record for the first record on track 2. */
 776        ccw[-1].flags |= CCW_FLAG_CC;
 777        locate_record(ccw++, LO_data++, 2, 0, 1,
 778                      DASD_ECKD_CCW_READ_COUNT, device, 0);
 779        /* Read count ccw. */
 780        ccw[-1].flags |= CCW_FLAG_CC;
 781        ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
 782        ccw->flags = 0;
 783        ccw->count = 8;
 784        ccw->cda = (__u32)(addr_t) count_data;
 785
 786        cqr->device = device;
 787        cqr->retries = 0;
 788        cqr->buildclk = get_clock();
 789        cqr->status = DASD_CQR_FILLED;
 790        return cqr;
 791}
 792
 793/*
 794 * This is the callback function for the init_analysis cqr. It saves
 795 * the status of the initial analysis ccw before it frees it and kicks
 796 * the device to continue the startup sequence. This will call
 797 * dasd_eckd_do_analysis again (if the devices has not been marked
 798 * for deletion in the meantime).
 799 */
 800static void
 801dasd_eckd_analysis_callback(struct dasd_ccw_req *init_cqr, void *data)
 802{
 803        struct dasd_eckd_private *private;
 804        struct dasd_device *device;
 805
 806        device = init_cqr->device;
 807        private = (struct dasd_eckd_private *) device->private;
 808        private->init_cqr_status = init_cqr->status;
 809        dasd_sfree_request(init_cqr, device);
 810        dasd_kick_device(device);
 811}
 812
 813static int
 814dasd_eckd_start_analysis(struct dasd_device *device)
 815{
 816        struct dasd_eckd_private *private;
 817        struct dasd_ccw_req *init_cqr;
 818
 819        private = (struct dasd_eckd_private *) device->private;
 820        init_cqr = dasd_eckd_analysis_ccw(device);
 821        if (IS_ERR(init_cqr))
 822                return PTR_ERR(init_cqr);
 823        init_cqr->callback = dasd_eckd_analysis_callback;
 824        init_cqr->callback_data = NULL;
 825        init_cqr->expires = 5*HZ;
 826        dasd_add_request_head(init_cqr);
 827        return -EAGAIN;
 828}
 829
 830static int
 831dasd_eckd_end_analysis(struct dasd_device *device)
 832{
 833        struct dasd_eckd_private *private;
 834        struct eckd_count *count_area;
 835        unsigned int sb, blk_per_trk;
 836        int status, i;
 837
 838        private = (struct dasd_eckd_private *) device->private;
 839        status = private->init_cqr_status;
 840        private->init_cqr_status = -1;
 841        if (status != DASD_CQR_DONE) {
 842                DEV_MESSAGE(KERN_WARNING, device, "%s",
 843                            "volume analysis returned unformatted disk");
 844                return -EMEDIUMTYPE;
 845        }
 846
 847        private->uses_cdl = 1;
 848        /* Calculate number of blocks/records per track. */
 849        blk_per_trk = recs_per_track(&private->rdc_data, 0, device->bp_block);
 850        /* Check Track 0 for Compatible Disk Layout */
 851        count_area = NULL;
 852        for (i = 0; i < 3; i++) {
 853                if (private->count_area[i].kl != 4 ||
 854                    private->count_area[i].dl != dasd_eckd_cdl_reclen(i) - 4) {
 855                        private->uses_cdl = 0;
 856                        break;
 857                }
 858        }
 859        if (i == 3)
 860                count_area = &private->count_area[4];
 861
 862        if (private->uses_cdl == 0) {
 863                for (i = 0; i < 5; i++) {
 864                        if ((private->count_area[i].kl != 0) ||
 865                            (private->count_area[i].dl !=
 866                             private->count_area[0].dl))
 867                                break;
 868                }
 869                if (i == 5)
 870                        count_area = &private->count_area[0];
 871        } else {
 872                if (private->count_area[3].record == 1)
 873                        DEV_MESSAGE(KERN_WARNING, device, "%s",
 874                                    "Trk 0: no records after VTOC!");
 875        }
 876        if (count_area != NULL && count_area->kl == 0) {
 877                /* we found notthing violating our disk layout */
 878                if (dasd_check_blocksize(count_area->dl) == 0)
 879                        device->bp_block = count_area->dl;
 880        }
 881        if (device->bp_block == 0) {
 882                DEV_MESSAGE(KERN_WARNING, device, "%s",
 883                            "Volume has incompatible disk layout");
 884                return -EMEDIUMTYPE;
 885        }
 886        device->s2b_shift = 0;  /* bits to shift 512 to get a block */
 887        for (sb = 512; sb < device->bp_block; sb = sb << 1)
 888                device->s2b_shift++;
 889
 890        blk_per_trk = recs_per_track(&private->rdc_data, 0, device->bp_block);
 891        device->blocks = (private->rdc_data.no_cyl *
 892                          private->rdc_data.trk_per_cyl *
 893                          blk_per_trk);
 894
 895        DEV_MESSAGE(KERN_INFO, device,
 896                    "(%dkB blks): %dkB at %dkB/trk %s",
 897                    (device->bp_block >> 10),
 898                    ((private->rdc_data.no_cyl *
 899                      private->rdc_data.trk_per_cyl *
 900                      blk_per_trk * (device->bp_block >> 9)) >> 1),
 901                    ((blk_per_trk * device->bp_block) >> 10),
 902                    private->uses_cdl ?
 903                    "compatible disk layout" : "linux disk layout");
 904
 905        return 0;
 906}
 907
 908static int
 909dasd_eckd_do_analysis(struct dasd_device *device)
 910{
 911        struct dasd_eckd_private *private;
 912
 913        private = (struct dasd_eckd_private *) device->private;
 914        if (private->init_cqr_status < 0)
 915                return dasd_eckd_start_analysis(device);
 916        else
 917                return dasd_eckd_end_analysis(device);
 918}
 919
 920static int
 921dasd_eckd_fill_geometry(struct dasd_device *device, struct hd_geometry *geo)
 922{
 923        struct dasd_eckd_private *private;
 924
 925        private = (struct dasd_eckd_private *) device->private;
 926        if (dasd_check_blocksize(device->bp_block) == 0) {
 927                geo->sectors = recs_per_track(&private->rdc_data,
 928                                              0, device->bp_block);
 929        }
 930        geo->cylinders = private->rdc_data.no_cyl;
 931        geo->heads = private->rdc_data.trk_per_cyl;
 932        return 0;
 933}
 934
 935static struct dasd_ccw_req *
 936dasd_eckd_format_device(struct dasd_device * device,
 937                        struct format_data_t * fdata)
 938{
 939        struct dasd_eckd_private *private;
 940        struct dasd_ccw_req *fcp;
 941        struct eckd_count *ect;
 942        struct ccw1 *ccw;
 943        void *data;
 944        int rpt, cyl, head;
 945        int cplength, datasize;
 946        int i;
 947
 948        private = (struct dasd_eckd_private *) device->private;
 949        rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize);
 950        cyl = fdata->start_unit / private->rdc_data.trk_per_cyl;
 951        head = fdata->start_unit % private->rdc_data.trk_per_cyl;
 952
 953        /* Sanity checks. */
 954        if (fdata->start_unit >=
 955            (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)) {
 956                DEV_MESSAGE(KERN_INFO, device, "Track no %d too big!",
 957                            fdata->start_unit);
 958                return ERR_PTR(-EINVAL);
 959        }
 960        if (fdata->start_unit > fdata->stop_unit) {
 961                DEV_MESSAGE(KERN_INFO, device, "Track %d reached! ending.",
 962                            fdata->start_unit);
 963                return ERR_PTR(-EINVAL);
 964        }
 965        if (dasd_check_blocksize(fdata->blksize) != 0) {
 966                DEV_MESSAGE(KERN_WARNING, device,
 967                            "Invalid blocksize %d...terminating!",
 968                            fdata->blksize);
 969                return ERR_PTR(-EINVAL);
 970        }
 971
 972        /*
 973         * fdata->intensity is a bit string that tells us what to do:
 974         *   Bit 0: write record zero
 975         *   Bit 1: write home address, currently not supported
 976         *   Bit 2: invalidate tracks
 977         *   Bit 3: use OS/390 compatible disk layout (cdl)
 978         * Only some bit combinations do make sense.
 979         */
 980        switch (fdata->intensity) {
 981        case 0x00:      /* Normal format */
 982        case 0x08:      /* Normal format, use cdl. */
 983                cplength = 2 + rpt;
 984                datasize = sizeof(struct DE_eckd_data) +
 985                        sizeof(struct LO_eckd_data) +
 986                        rpt * sizeof(struct eckd_count);
 987                break;
 988        case 0x01:      /* Write record zero and format track. */
 989        case 0x09:      /* Write record zero and format track, use cdl. */
 990                cplength = 3 + rpt;
 991                datasize = sizeof(struct DE_eckd_data) +
 992                        sizeof(struct LO_eckd_data) +
 993                        sizeof(struct eckd_count) +
 994                        rpt * sizeof(struct eckd_count);
 995                break;
 996        case 0x04:      /* Invalidate track. */
 997        case 0x0c:      /* Invalidate track, use cdl. */
 998                cplength = 3;
 999                datasize = sizeof(struct DE_eckd_data) +
1000                        sizeof(struct LO_eckd_data) +
1001                        sizeof(struct eckd_count);
1002                break;
1003        default:
1004                DEV_MESSAGE(KERN_WARNING, device, "Invalid flags 0x%x.",
1005                            fdata->intensity);
1006                return ERR_PTR(-EINVAL);
1007        }
1008        /* Allocate the format ccw request. */
1009        fcp = dasd_smalloc_request(dasd_eckd_discipline.name,
1010                                   cplength, datasize, device);
1011        if (IS_ERR(fcp))
1012                return fcp;
1013
1014        data = fcp->data;
1015        ccw = fcp->cpaddr;
1016
1017        switch (fdata->intensity & ~0x08) {
1018        case 0x00: /* Normal format. */
1019                define_extent(ccw++, (struct DE_eckd_data *) data,
1020                              fdata->start_unit, fdata->start_unit,
1021                              DASD_ECKD_CCW_WRITE_CKD, device);
1022                data += sizeof(struct DE_eckd_data);
1023                ccw[-1].flags |= CCW_FLAG_CC;
1024                locate_record(ccw++, (struct LO_eckd_data *) data,
1025                              fdata->start_unit, 0, rpt,
1026                              DASD_ECKD_CCW_WRITE_CKD, device,
1027                              fdata->blksize);
1028                data += sizeof(struct LO_eckd_data);
1029                break;
1030        case 0x01: /* Write record zero + format track. */
1031                define_extent(ccw++, (struct DE_eckd_data *) data,
1032                              fdata->start_unit, fdata->start_unit,
1033                              DASD_ECKD_CCW_WRITE_RECORD_ZERO,
1034                              device);
1035                data += sizeof(struct DE_eckd_data);
1036                ccw[-1].flags |= CCW_FLAG_CC;
1037                locate_record(ccw++, (struct LO_eckd_data *) data,
1038                              fdata->start_unit, 0, rpt + 1,
1039                              DASD_ECKD_CCW_WRITE_RECORD_ZERO, device,
1040                              device->bp_block);
1041                data += sizeof(struct LO_eckd_data);
1042                break;
1043        case 0x04: /* Invalidate track. */
1044                define_extent(ccw++, (struct DE_eckd_data *) data,
1045                              fdata->start_unit, fdata->start_unit,
1046                              DASD_ECKD_CCW_WRITE_CKD, device);
1047                data += sizeof(struct DE_eckd_data);
1048                ccw[-1].flags |= CCW_FLAG_CC;
1049                locate_record(ccw++, (struct LO_eckd_data *) data,
1050                              fdata->start_unit, 0, 1,
1051                              DASD_ECKD_CCW_WRITE_CKD, device, 8);
1052                data += sizeof(struct LO_eckd_data);
1053                break;
1054        }
1055        if (fdata->intensity & 0x01) {  /* write record zero */
1056                ect = (struct eckd_count *) data;
1057                data += sizeof(struct eckd_count);
1058                ect->cyl = cyl;
1059                ect->head = head;
1060                ect->record = 0;
1061                ect->kl = 0;
1062                ect->dl = 8;
1063                ccw[-1].flags |= CCW_FLAG_CC;
1064                ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO;
1065                ccw->flags = CCW_FLAG_SLI;
1066                ccw->count = 8;
1067                ccw->cda = (__u32)(addr_t) ect;
1068                ccw++;
1069        }
1070        if ((fdata->intensity & ~0x08) & 0x04) {        /* erase track */
1071                ect = (struct eckd_count *) data;
1072                data += sizeof(struct eckd_count);
1073                ect->cyl = cyl;
1074                ect->head = head;
1075                ect->record = 1;
1076                ect->kl = 0;
1077                ect->dl = 0;
1078                ccw[-1].flags |= CCW_FLAG_CC;
1079                ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
1080                ccw->flags = CCW_FLAG_SLI;
1081                ccw->count = 8;
1082                ccw->cda = (__u32)(addr_t) ect;
1083        } else {                /* write remaining records */
1084                for (i = 0; i < rpt; i++) {
1085                        ect = (struct eckd_count *) data;
1086                        data += sizeof(struct eckd_count);
1087                        ect->cyl = cyl;
1088                        ect->head = head;
1089                        ect->record = i + 1;
1090                        ect->kl = 0;
1091                        ect->dl = fdata->blksize;
1092                        /* Check for special tracks 0-1 when formatting CDL */
1093                        if ((fdata->intensity & 0x08) &&
1094                            fdata->start_unit == 0) {
1095                                if (i < 3) {
1096                                        ect->kl = 4;
1097                                        ect->dl = sizes_trk0[i] - 4;
1098                                }
1099                        }
1100                        if ((fdata->intensity & 0x08) &&
1101                            fdata->start_unit == 1) {
1102                                ect->kl = 44;
1103                                ect->dl = LABEL_SIZE - 44;
1104                        }
1105                        ccw[-1].flags |= CCW_FLAG_CC;
1106                        ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
1107                        ccw->flags = CCW_FLAG_SLI;
1108                        ccw->count = 8;
1109                        ccw->cda = (__u32)(addr_t) ect;
1110                        ccw++;
1111                }
1112        }
1113        fcp->device = device;
1114        fcp->retries = 2;       /* set retry counter to enable ERP */
1115        fcp->buildclk = get_clock();
1116        fcp->status = DASD_CQR_FILLED;
1117        return fcp;
1118}
1119
1120static dasd_era_t
1121dasd_eckd_examine_error(struct dasd_ccw_req * cqr, struct irb * irb)
1122{
1123        struct dasd_device *device = (struct dasd_device *) cqr->device;
1124        struct ccw_device *cdev = device->cdev;
1125
1126        if (irb->scsw.cstat == 0x00 &&
1127            irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
1128                return dasd_era_none;
1129
1130        switch (cdev->id.cu_type) {
1131        case 0x3990:
1132        case 0x2105:
1133        case 0x2107:
1134        case 0x1750:
1135                return dasd_3990_erp_examine(cqr, irb);
1136        case 0x9343:
1137                return dasd_9343_erp_examine(cqr, irb);
1138        case 0x3880:
1139        default:
1140                DEV_MESSAGE(KERN_WARNING, device, "%s",
1141                            "default (unknown CU type) - RECOVERABLE return");
1142                return dasd_era_recover;
1143        }
1144}
1145
1146static dasd_erp_fn_t
1147dasd_eckd_erp_action(struct dasd_ccw_req * cqr)
1148{
1149        struct dasd_device *device = (struct dasd_device *) cqr->device;
1150        struct ccw_device *cdev = device->cdev;
1151
1152        switch (cdev->id.cu_type) {
1153        case 0x3990:
1154        case 0x2105:
1155        case 0x2107:
1156        case 0x1750:
1157                return dasd_3990_erp_action;
1158        case 0x9343:
1159        case 0x3880:
1160        default:
1161                return dasd_default_erp_action;
1162        }
1163}
1164
1165static dasd_erp_fn_t
1166dasd_eckd_erp_postaction(struct dasd_ccw_req * cqr)
1167{
1168        return dasd_default_erp_postaction;
1169}
1170
1171static struct dasd_ccw_req *
1172dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
1173{
1174        struct dasd_eckd_private *private;
1175        unsigned long *idaws;
1176        struct LO_eckd_data *LO_data;
1177        struct dasd_ccw_req *cqr;
1178        struct ccw1 *ccw;
1179        struct req_iterator iter;
1180        struct bio_vec *bv;
1181        char *dst;
1182        unsigned int blksize, blk_per_trk, off;
1183        int count, cidaw, cplength, datasize;
1184        sector_t recid, first_rec, last_rec;
1185        sector_t first_trk, last_trk;
1186        unsigned int first_offs, last_offs;
1187        unsigned char cmd, rcmd;
1188
1189        private = (struct dasd_eckd_private *) device->private;
1190        if (rq_data_dir(req) == READ)
1191                cmd = DASD_ECKD_CCW_READ_MT;
1192        else if (rq_data_dir(req) == WRITE)
1193                cmd = DASD_ECKD_CCW_WRITE_MT;
1194        else
1195                return ERR_PTR(-EINVAL);
1196        /* Calculate number of blocks/records per track. */
1197        blksize = device->bp_block;
1198        blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
1199        /* Calculate record id of first and last block. */
1200        first_rec = first_trk = req->sector >> device->s2b_shift;
1201        first_offs = sector_div(first_trk, blk_per_trk);
1202        last_rec = last_trk =
1203                (req->sector + req->nr_sectors - 1) >> device->s2b_shift;
1204        last_offs = sector_div(last_trk, blk_per_trk);
1205        /* Check struct bio and count the number of blocks for the request. */
1206        count = 0;
1207        cidaw = 0;
1208        rq_for_each_segment(bv, req, iter) {
1209                if (bv->bv_len & (blksize - 1))
1210                        /* Eckd can only do full blocks. */
1211                        return ERR_PTR(-EINVAL);
1212                count += bv->bv_len >> (device->s2b_shift + 9);
1213#if defined(CONFIG_64BIT)
1214                if (idal_is_needed (page_address(bv->bv_page), bv->bv_len))
1215                        cidaw += bv->bv_len >> (device->s2b_shift + 9);
1216#endif
1217        }
1218        /* Paranoia. */
1219        if (count != last_rec - first_rec + 1)
1220                return ERR_PTR(-EINVAL);
1221        /* 1x define extent + 1x locate record + number of blocks */
1222        cplength = 2 + count;
1223        /* 1x define extent + 1x locate record + cidaws*sizeof(long) */
1224        datasize = sizeof(struct DE_eckd_data) + sizeof(struct LO_eckd_data) +
1225                cidaw * sizeof(unsigned long);
1226        /* Find out the number of additional locate record ccws for cdl. */
1227        if (private->uses_cdl && first_rec < 2*blk_per_trk) {
1228                if (last_rec >= 2*blk_per_trk)
1229                        count = 2*blk_per_trk - first_rec;
1230                cplength += count;
1231                datasize += count*sizeof(struct LO_eckd_data);
1232        }
1233        /* Allocate the ccw request. */
1234        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1235                                   cplength, datasize, device);
1236        if (IS_ERR(cqr))
1237                return cqr;
1238        ccw = cqr->cpaddr;
1239        /* First ccw is define extent. */
1240        if (define_extent(ccw++, cqr->data, first_trk,
1241                          last_trk, cmd, device) == -EAGAIN) {
1242                /* Clock not in sync and XRC is enabled. Try again later. */
1243                dasd_sfree_request(cqr, device);
1244                return ERR_PTR(-EAGAIN);
1245        }
1246        /* Build locate_record+read/write/ccws. */
1247        idaws = (unsigned long *) (cqr->data + sizeof(struct DE_eckd_data));
1248        LO_data = (struct LO_eckd_data *) (idaws + cidaw);
1249        recid = first_rec;
1250        if (private->uses_cdl == 0 || recid > 2*blk_per_trk) {
1251                /* Only standard blocks so there is just one locate record. */
1252                ccw[-1].flags |= CCW_FLAG_CC;
1253                locate_record(ccw++, LO_data++, first_trk, first_offs + 1,
1254                              last_rec - recid + 1, cmd, device, blksize);
1255        }
1256        rq_for_each_segment(bv, req, iter) {
1257                dst = page_address(bv->bv_page) + bv->bv_offset;
1258                if (dasd_page_cache) {
1259                        char *copy = kmem_cache_alloc(dasd_page_cache,
1260                                                      GFP_DMA | __GFP_NOWARN);
1261                        if (copy && rq_data_dir(req) == WRITE)
1262                                memcpy(copy + bv->bv_offset, dst, bv->bv_len);
1263                        if (copy)
1264                                dst = copy + bv->bv_offset;
1265                }
1266                for (off = 0; off < bv->bv_len; off += blksize) {
1267                        sector_t trkid = recid;
1268                        unsigned int recoffs = sector_div(trkid, blk_per_trk);
1269                        rcmd = cmd;
1270                        count = blksize;
1271                        /* Locate record for cdl special block ? */
1272                        if (private->uses_cdl && recid < 2*blk_per_trk) {
1273                                if (dasd_eckd_cdl_special(blk_per_trk, recid)){
1274                                        rcmd |= 0x8;
1275                                        count = dasd_eckd_cdl_reclen(recid);
1276                                        if (count < blksize &&
1277                                            rq_data_dir(req) == READ)
1278                                                memset(dst + count, 0xe5,
1279                                                       blksize - count);
1280                                }
1281                                ccw[-1].flags |= CCW_FLAG_CC;
1282                                locate_record(ccw++, LO_data++,
1283                                              trkid, recoffs + 1,
1284                                              1, rcmd, device, count);
1285                        }
1286                        /* Locate record for standard blocks ? */
1287                        if (private->uses_cdl && recid == 2*blk_per_trk) {
1288                                ccw[-1].flags |= CCW_FLAG_CC;
1289                                locate_record(ccw++, LO_data++,
1290                                              trkid, recoffs + 1,
1291                                              last_rec - recid + 1,
1292                                              cmd, device, count);
1293                        }
1294                        /* Read/write ccw. */
1295                        ccw[-1].flags |= CCW_FLAG_CC;
1296                        ccw->cmd_code = rcmd;
1297                        ccw->count = count;
1298                        if (idal_is_needed(dst, blksize)) {
1299                                ccw->cda = (__u32)(addr_t) idaws;
1300                                ccw->flags = CCW_FLAG_IDA;
1301                                idaws = idal_create_words(idaws, dst, blksize);
1302                        } else {
1303                                ccw->cda = (__u32)(addr_t) dst;
1304                                ccw->flags = 0;
1305                        }
1306                        ccw++;
1307                        dst += blksize;
1308                        recid++;
1309                }
1310        }
1311        if (req->cmd_flags & REQ_FAILFAST)
1312                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
1313        cqr->device = device;
1314        cqr->expires = 5 * 60 * HZ;     /* 5 minutes */
1315        cqr->lpm = private->path_data.ppm;
1316        cqr->retries = 256;
1317        cqr->buildclk = get_clock();
1318        cqr->status = DASD_CQR_FILLED;
1319        return cqr;
1320}
1321
1322static int
1323dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req)
1324{
1325        struct dasd_eckd_private *private;
1326        struct ccw1 *ccw;
1327        struct req_iterator iter;
1328        struct bio_vec *bv;
1329        char *dst, *cda;
1330        unsigned int blksize, blk_per_trk, off;
1331        sector_t recid;
1332        int status;
1333
1334        if (!dasd_page_cache)
1335                goto out;
1336        private = (struct dasd_eckd_private *) cqr->device->private;
1337        blksize = cqr->device->bp_block;
1338        blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
1339        recid = req->sector >> cqr->device->s2b_shift;
1340        ccw = cqr->cpaddr;
1341        /* Skip over define extent & locate record. */
1342        ccw++;
1343        if (private->uses_cdl == 0 || recid > 2*blk_per_trk)
1344                ccw++;
1345        rq_for_each_segment(bv, req, iter) {
1346                dst = page_address(bv->bv_page) + bv->bv_offset;
1347                for (off = 0; off < bv->bv_len; off += blksize) {
1348                        /* Skip locate record. */
1349                        if (private->uses_cdl && recid <= 2*blk_per_trk)
1350                                ccw++;
1351                        if (dst) {
1352                                if (ccw->flags & CCW_FLAG_IDA)
1353                                        cda = *((char **)((addr_t) ccw->cda));
1354                                else
1355                                        cda = (char *)((addr_t) ccw->cda);
1356                                if (dst != cda) {
1357                                        if (rq_data_dir(req) == READ)
1358                                                memcpy(dst, cda, bv->bv_len);
1359                                        kmem_cache_free(dasd_page_cache,
1360                                            (void *)((addr_t)cda & PAGE_MASK));
1361                                }
1362                                dst = NULL;
1363                        }
1364                        ccw++;
1365                        recid++;
1366                }
1367        }
1368out:
1369        status = cqr->status == DASD_CQR_DONE;
1370        dasd_sfree_request(cqr, cqr->device);
1371        return status;
1372}
1373
1374static int
1375dasd_eckd_fill_info(struct dasd_device * device,
1376                    struct dasd_information2_t * info)
1377{
1378        struct dasd_eckd_private *private;
1379
1380        private = (struct dasd_eckd_private *) device->private;
1381        info->label_block = 2;
1382        info->FBA_layout = private->uses_cdl ? 0 : 1;
1383        info->format = private->uses_cdl ? DASD_FORMAT_CDL : DASD_FORMAT_LDL;
1384        info->characteristics_size = sizeof(struct dasd_eckd_characteristics);
1385        memcpy(info->characteristics, &private->rdc_data,
1386               sizeof(struct dasd_eckd_characteristics));
1387        info->confdata_size = sizeof (struct dasd_eckd_confdata);
1388        memcpy(info->configuration_data, &private->conf_data,
1389               sizeof (struct dasd_eckd_confdata));
1390        return 0;
1391}
1392
1393/*
1394 * SECTION: ioctl functions for eckd devices.
1395 */
1396
1397/*
1398 * Release device ioctl.
1399 * Buils a channel programm to releases a prior reserved
1400 * (see dasd_eckd_reserve) device.
1401 */
1402static int
1403dasd_eckd_release(struct dasd_device *device)
1404{
1405        struct dasd_ccw_req *cqr;
1406        int rc;
1407
1408        if (!capable(CAP_SYS_ADMIN))
1409                return -EACCES;
1410
1411        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1412                                   1, 32, device);
1413        if (IS_ERR(cqr)) {
1414                DEV_MESSAGE(KERN_WARNING, device, "%s",
1415                            "Could not allocate initialization request");
1416                return PTR_ERR(cqr);
1417        }
1418        cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE;
1419        cqr->cpaddr->flags |= CCW_FLAG_SLI;
1420        cqr->cpaddr->count = 32;
1421        cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
1422        cqr->device = device;
1423        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
1424        set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
1425        cqr->retries = 2;       /* set retry counter to enable basic ERP */
1426        cqr->expires = 2 * HZ;
1427        cqr->buildclk = get_clock();
1428        cqr->status = DASD_CQR_FILLED;
1429
1430        rc = dasd_sleep_on_immediatly(cqr);
1431
1432        dasd_sfree_request(cqr, cqr->device);
1433        return rc;
1434}
1435
1436/*
1437 * Reserve device ioctl.
1438 * Options are set to 'synchronous wait for interrupt' and
1439 * 'timeout the request'. This leads to a terminate IO if
1440 * the interrupt is outstanding for a certain time.
1441 */
1442static int
1443dasd_eckd_reserve(struct dasd_device *device)
1444{
1445        struct dasd_ccw_req *cqr;
1446        int rc;
1447
1448        if (!capable(CAP_SYS_ADMIN))
1449                return -EACCES;
1450
1451        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1452                                   1, 32, device);
1453        if (IS_ERR(cqr)) {
1454                DEV_MESSAGE(KERN_WARNING, device, "%s",
1455                            "Could not allocate initialization request");
1456                return PTR_ERR(cqr);
1457        }
1458        cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE;
1459        cqr->cpaddr->flags |= CCW_FLAG_SLI;
1460        cqr->cpaddr->count = 32;
1461        cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
1462        cqr->device = device;
1463        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
1464        set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
1465        cqr->retries = 2;       /* set retry counter to enable basic ERP */
1466        cqr->expires = 2 * HZ;
1467        cqr->buildclk = get_clock();
1468        cqr->status = DASD_CQR_FILLED;
1469
1470        rc = dasd_sleep_on_immediatly(cqr);
1471
1472        dasd_sfree_request(cqr, cqr->device);
1473        return rc;
1474}
1475
1476/*
1477 * Steal lock ioctl - unconditional reserve device.
1478 * Buils a channel programm to break a device's reservation.
1479 * (unconditional reserve)
1480 */
1481static int
1482dasd_eckd_steal_lock(struct dasd_device *device)
1483{
1484        struct dasd_ccw_req *cqr;
1485        int rc;
1486
1487        if (!capable(CAP_SYS_ADMIN))
1488                return -EACCES;
1489
1490        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1491                                   1, 32, device);
1492        if (IS_ERR(cqr)) {
1493                DEV_MESSAGE(KERN_WARNING, device, "%s",
1494                            "Could not allocate initialization request");
1495                return PTR_ERR(cqr);
1496        }
1497        cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK;
1498        cqr->cpaddr->flags |= CCW_FLAG_SLI;
1499        cqr->cpaddr->count = 32;
1500        cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
1501        cqr->device = device;
1502        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
1503        set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
1504        cqr->retries = 2;       /* set retry counter to enable basic ERP */
1505        cqr->expires = 2 * HZ;
1506        cqr->buildclk = get_clock();
1507        cqr->status = DASD_CQR_FILLED;
1508
1509        rc = dasd_sleep_on_immediatly(cqr);
1510
1511        dasd_sfree_request(cqr, cqr->device);
1512        return rc;
1513}
1514
1515/*
1516 * Read performance statistics
1517 */
1518static int
1519dasd_eckd_performance(struct dasd_device *device, void __user *argp)
1520{
1521        struct dasd_psf_prssd_data *prssdp;
1522        struct dasd_rssd_perf_stats_t *stats;
1523        struct dasd_ccw_req *cqr;
1524        struct ccw1 *ccw;
1525        int rc;
1526
1527        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1528                                   1 /* PSF */  + 1 /* RSSD */ ,
1529                                   (sizeof (struct dasd_psf_prssd_data) +
1530                                    sizeof (struct dasd_rssd_perf_stats_t)),
1531                                   device);
1532        if (IS_ERR(cqr)) {
1533                DEV_MESSAGE(KERN_WARNING, device, "%s",
1534                            "Could not allocate initialization request");
1535                return PTR_ERR(cqr);
1536        }
1537        cqr->device = device;
1538        cqr->retries = 0;
1539        cqr->expires = 10 * HZ;
1540
1541        /* Prepare for Read Subsystem Data */
1542        prssdp = (struct dasd_psf_prssd_data *) cqr->data;
1543        memset(prssdp, 0, sizeof (struct dasd_psf_prssd_data));
1544        prssdp->order = PSF_ORDER_PRSSD;
1545        prssdp->suborder = 0x01;        /* Perfomance Statistics */
1546        prssdp->varies[1] = 0x01;       /* Perf Statistics for the Subsystem */
1547
1548        ccw = cqr->cpaddr;
1549        ccw->cmd_code = DASD_ECKD_CCW_PSF;
1550        ccw->count = sizeof (struct dasd_psf_prssd_data);
1551        ccw->flags |= CCW_FLAG_CC;
1552        ccw->cda = (__u32)(addr_t) prssdp;
1553
1554        /* Read Subsystem Data - Performance Statistics */
1555        stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1);
1556        memset(stats, 0, sizeof (struct dasd_rssd_perf_stats_t));
1557
1558        ccw++;
1559        ccw->cmd_code = DASD_ECKD_CCW_RSSD;
1560        ccw->count = sizeof (struct dasd_rssd_perf_stats_t);
1561        ccw->cda = (__u32)(addr_t) stats;
1562
1563        cqr->buildclk = get_clock();
1564        cqr->status = DASD_CQR_FILLED;
1565        rc = dasd_sleep_on(cqr);
1566        if (rc == 0) {
1567                /* Prepare for Read Subsystem Data */
1568                prssdp = (struct dasd_psf_prssd_data *) cqr->data;
1569                stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1);
1570                if (copy_to_user(argp, stats,
1571                                 sizeof(struct dasd_rssd_perf_stats_t)))
1572                        rc = -EFAULT;
1573        }
1574        dasd_sfree_request(cqr, cqr->device);
1575        return rc;
1576}
1577
1578/*
1579 * Get attributes (cache operations)
1580 * Returnes the cache attributes used in Define Extend (DE).
1581 */
1582static int
1583dasd_eckd_get_attrib(struct dasd_device *device, void __user *argp)
1584{
1585        struct dasd_eckd_private *private =
1586                (struct dasd_eckd_private *)device->private;
1587        struct attrib_data_t attrib = private->attrib;
1588        int rc;
1589
1590        if (!capable(CAP_SYS_ADMIN))
1591                return -EACCES;
1592        if (!argp)
1593                return -EINVAL;
1594
1595        rc = 0;
1596        if (copy_to_user(argp, (long *) &attrib,
1597                         sizeof (struct attrib_data_t)))
1598                rc = -EFAULT;
1599
1600        return rc;
1601}
1602
1603/*
1604 * Set attributes (cache operations)
1605 * Stores the attributes for cache operation to be used in Define Extend (DE).
1606 */
1607static int
1608dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp)
1609{
1610        struct dasd_eckd_private *private =
1611                (struct dasd_eckd_private *)device->private;
1612        struct attrib_data_t attrib;
1613
1614        if (!capable(CAP_SYS_ADMIN))
1615                return -EACCES;
1616        if (!argp)
1617                return -EINVAL;
1618
1619        if (copy_from_user(&attrib, argp, sizeof(struct attrib_data_t)))
1620                return -EFAULT;
1621        private->attrib = attrib;
1622
1623        DEV_MESSAGE(KERN_INFO, device,
1624                    "cache operation mode set to %x (%i cylinder prestage)",
1625                    private->attrib.operation, private->attrib.nr_cyl);
1626        return 0;
1627}
1628
1629static int
1630dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp)
1631{
1632        switch (cmd) {
1633        case BIODASDGATTR:
1634                return dasd_eckd_get_attrib(device, argp);
1635        case BIODASDSATTR:
1636                return dasd_eckd_set_attrib(device, argp);
1637        case BIODASDPSRD:
1638                return dasd_eckd_performance(device, argp);
1639        case BIODASDRLSE:
1640                return dasd_eckd_release(device);
1641        case BIODASDRSRV:
1642                return dasd_eckd_reserve(device);
1643        case BIODASDSLCK:
1644                return dasd_eckd_steal_lock(device);
1645        default:
1646                return -ENOIOCTLCMD;
1647        }
1648}
1649
1650/*
1651 * Dump the range of CCWs into 'page' buffer
1652 * and return number of printed chars.
1653 */
1654static int
1655dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page)
1656{
1657        int len, count;
1658        char *datap;
1659
1660        len = 0;
1661        while (from <= to) {
1662                len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1663                               " CCW %p: %08X %08X DAT:",
1664                               from, ((int *) from)[0], ((int *) from)[1]);
1665
1666                /* get pointer to data (consider IDALs) */
1667                if (from->flags & CCW_FLAG_IDA)
1668                        datap = (char *) *((addr_t *) (addr_t) from->cda);
1669                else
1670                        datap = (char *) ((addr_t) from->cda);
1671
1672                /* dump data (max 32 bytes) */
1673                for (count = 0; count < from->count && count < 32; count++) {
1674                        if (count % 8 == 0) len += sprintf(page + len, " ");
1675                        if (count % 4 == 0) len += sprintf(page + len, " ");
1676                        len += sprintf(page + len, "%02x", datap[count]);
1677                }
1678                len += sprintf(page + len, "\n");
1679                from++;
1680        }
1681        return len;
1682}
1683
1684/*
1685 * Print sense data and related channel program.
1686 * Parts are printed because printk buffer is only 1024 bytes.
1687 */
1688static void
1689dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
1690                     struct irb *irb)
1691{
1692        char *page;
1693        struct ccw1 *first, *last, *fail, *from, *to;
1694        int len, sl, sct;
1695
1696        page = (char *) get_zeroed_page(GFP_ATOMIC);
1697        if (page == NULL) {
1698                DEV_MESSAGE(KERN_ERR, device, " %s",
1699                            "No memory to dump sense data");
1700                return;
1701        }
1702        /* dump the sense data */
1703        len = sprintf(page,  KERN_ERR PRINTK_HEADER
1704                      " I/O status report for device %s:\n",
1705                      device->cdev->dev.bus_id);
1706        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1707                       " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
1708                       irb->scsw.cstat, irb->scsw.dstat);
1709        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1710                       " device %s: Failing CCW: %p\n",
1711                       device->cdev->dev.bus_id,
1712                       (void *) (addr_t) irb->scsw.cpa);
1713        if (irb->esw.esw0.erw.cons) {
1714                for (sl = 0; sl < 4; sl++) {
1715                        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
1716                                       " Sense(hex) %2d-%2d:",
1717                                       (8 * sl), ((8 * sl) + 7));
1718
1719                        for (sct = 0; sct < 8; sct++) {
1720                                len += sprintf(page + len, " %02x",
1721                                               irb->ecw[8 * sl + sct]);
1722                        }
1723                        len += sprintf(page + len, "\n");
1724                }
1725
1726                if (irb->ecw[27] & DASD_SENSE_BIT_0) {
1727                        /* 24 Byte Sense Data */
1728                        sprintf(page + len, KERN_ERR PRINTK_HEADER
1729                                " 24 Byte: %x MSG %x, "
1730                                "%s MSGb to SYSOP\n",
1731                                irb->ecw[7] >> 4, irb->ecw[7] & 0x0f,
1732                                irb->ecw[1] & 0x10 ? "" : "no");
1733                } else {
1734                        /* 32 Byte Sense Data */
1735                        sprintf(page + len, KERN_ERR PRINTK_HEADER
1736                                " 32 Byte: Format: %x "
1737                                "Exception class %x\n",
1738                                irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
1739                }
1740        } else {
1741                sprintf(page + len, KERN_ERR PRINTK_HEADER
1742                        " SORRY - NO VALID SENSE AVAILABLE\n");
1743        }
1744        printk("%s", page);
1745
1746        /* dump the Channel Program (max 140 Bytes per line) */
1747        /* Count CCW and print first CCWs (maximum 1024 % 140 = 7) */
1748        first = req->cpaddr;
1749        for (last = first; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);
1750        to = min(first + 6, last);
1751        len = sprintf(page,  KERN_ERR PRINTK_HEADER
1752                      " Related CP in req: %p\n", req);
1753        dasd_eckd_dump_ccw_range(first, to, page + len);
1754        printk("%s", page);
1755
1756        /* print failing CCW area (maximum 4) */
1757        /* scsw->cda is either valid or zero  */
1758        len = 0;
1759        from = ++to;
1760        fail = (struct ccw1 *)(addr_t) irb->scsw.cpa; /* failing CCW */
1761        if (from <  fail - 2) {
1762                from = fail - 2;     /* there is a gap - print header */
1763                len += sprintf(page, KERN_ERR PRINTK_HEADER "......\n");
1764        }
1765        to = min(fail + 1, last);
1766        len += dasd_eckd_dump_ccw_range(from, to, page + len);
1767
1768        /* print last CCWs (maximum 2) */
1769        from = max(from, ++to);
1770        if (from < last - 1) {
1771                from = last - 1;     /* there is a gap - print header */
1772                len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
1773        }
1774        len += dasd_eckd_dump_ccw_range(from, last, page + len);
1775        if (len > 0)
1776                printk("%s", page);
1777        free_page((unsigned long) page);
1778}
1779
1780/*
1781 * max_blocks is dependent on the amount of storage that is available
1782 * in the static io buffer for each device. Currently each device has
1783 * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has
1784 * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use
1785 * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In
1786 * addition we have one define extent ccw + 16 bytes of data and one
1787 * locate record ccw + 16 bytes of data. That makes:
1788 * (8192 - 24 - 136 - 8 - 16 - 8 - 16) / 16 = 499 blocks at maximum.
1789 * We want to fit two into the available memory so that we can immediately
1790 * start the next request if one finishes off. That makes 249.5 blocks
1791 * for one request. Give a little safety and the result is 240.
1792 */
1793static struct dasd_discipline dasd_eckd_discipline = {
1794        .owner = THIS_MODULE,
1795        .name = "ECKD",
1796        .ebcname = "ECKD",
1797        .max_blocks = 240,
1798        .check_device = dasd_eckd_check_characteristics,
1799        .do_analysis = dasd_eckd_do_analysis,
1800        .fill_geometry = dasd_eckd_fill_geometry,
1801        .start_IO = dasd_start_IO,
1802        .term_IO = dasd_term_IO,
1803        .format_device = dasd_eckd_format_device,
1804        .examine_error = dasd_eckd_examine_error,
1805        .erp_action = dasd_eckd_erp_action,
1806        .erp_postaction = dasd_eckd_erp_postaction,
1807        .build_cp = dasd_eckd_build_cp,
1808        .free_cp = dasd_eckd_free_cp,
1809        .dump_sense = dasd_eckd_dump_sense,
1810        .fill_info = dasd_eckd_fill_info,
1811        .ioctl = dasd_eckd_ioctl,
1812};
1813
1814static int __init
1815dasd_eckd_init(void)
1816{
1817        ASCEBC(dasd_eckd_discipline.ebcname, 4);
1818        return ccw_driver_register(&dasd_eckd_driver);
1819}
1820
1821static void __exit
1822dasd_eckd_cleanup(void)
1823{
1824        ccw_driver_unregister(&dasd_eckd_driver);
1825}
1826
1827module_init(dasd_eckd_init);
1828module_exit(dasd_eckd_cleanup);
1829
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.