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