1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #define _DSW_
  27 
  28 #include <sys/types.h>
  29 #include <sys/ksynch.h>
  30 #include <sys/kmem.h>
  31 #include <sys/errno.h>
  32 #include <sys/conf.h>
  33 #include <sys/cmn_err.h>
  34 #include <sys/modctl.h>
  35 #include <sys/cred.h>
  36 #include <sys/file.h>
  37 #include <sys/ddi.h>
  38 #include <sys/unistat/spcs_s.h>
  39 #include <sys/dkio.h>
  40 
  41 #ifdef DS_DDICT
  42 #include "../contract.h"
  43 #endif
  44 
  45 #include <sys/nsctl/nsctl.h>
  46 #include <sys/nsctl/nsvers.h>
  47 
  48 #include <sys/sdt.h>              /* dtrace is S10 or later */
  49 
  50 #include "dsw.h"
  51 #include "dsw_dev.h"
  52 
  53 #define DIDINIT         0x01
  54 #define DIDNODES        0x02
  55 
  56 
  57 static int iiopen(dev_t *devp, int flag, int otyp, cred_t *crp);
  58 static int iiclose(dev_t dev, int flag, int otyp, cred_t *crp);
  59 static int iiprint(dev_t dev, char *str);
  60 static int iiioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp,
  61     int *rvp);
  62 static int iiprobe(dev_info_t *dip);
  63 static int iiattach(dev_info_t *dip, ddi_attach_cmd_t cmd);
  64 static int iidetach(dev_info_t *dip, ddi_detach_cmd_t cmd);
  65 static int iistrat(struct buf *);
  66 static int iiread();
  67 
  68 
  69 static kstat_t *ii_gkstat = NULL;
  70 iigkstat_t iigkstat = {
  71         { "ii_debug", KSTAT_DATA_ULONG },
  72         { "ii_bitmap", KSTAT_DATA_ULONG },
  73         { "ii_throttle_unit", KSTAT_DATA_ULONG },
  74         { "ii_throttle_delay", KSTAT_DATA_ULONG },
  75         { "ii_copy_direct", KSTAT_DATA_ULONG },
  76         { "num-sets", KSTAT_DATA_ULONG },
  77         { "assoc-over", KSTAT_DATA_ULONG },
  78         { "spilled-over", KSTAT_DATA_ULONG },
  79 };
  80 
  81 static struct cb_ops ii_cb_ops = {
  82         iiopen,
  83         iiclose,
  84         iistrat,                /* dummy strategy */
  85         iiprint,
  86         nodev,                  /* no dump */
  87         iiread,                 /* dummy read */
  88         nodev,                  /* no write */
  89         iiioctl,
  90         nodev,                  /* no devmap */
  91         nodev,                  /* no mmap */
  92         nodev,                  /* no segmap */
  93         nochpoll,
  94         ddi_prop_op,
  95         NULL,                   /* not STREAMS */
  96         D_NEW | D_MP
  97 };
  98 
  99 static struct dev_ops ii_ops = {
 100         DEVO_REV,
 101         0,
 102         nodev,                  /* no getinfo */
 103         nulldev,
 104         iiprobe,
 105         iiattach,
 106         iidetach,
 107         nodev,                  /* no reset */
 108         &ii_cb_ops,
 109         (struct bus_ops *)NULL
 110 };
 111 
 112 static struct modldrv ii_ldrv = {
 113         &mod_driverops,
 114         "nws:Point-in-Time:" ISS_VERSION_STR,
 115         &ii_ops
 116 };
 117 
 118 static struct modlinkage ii_modlinkage = {
 119         MODREV_1,
 120         &ii_ldrv,
 121         NULL
 122 };
 123 
 124 struct ii_state {
 125         dev_info_t *dip;
 126         int     instance;
 127 };
 128 
 129 /* used for logging sysevent, gets set in _ii_attach */
 130 dev_info_t *ii_dip = NULL;
 131 
 132 extern _ii_info_t *_ii_info_top;
 133 extern _ii_lsthead_t *_ii_cluster_top;
 134 extern _ii_lsthead_t *_ii_group_top;
 135 extern kmutex_t _ii_cluster_mutex;
 136 extern kmutex_t _ii_group_mutex;
 137 
 138 const int dsw_major_rev = ISS_VERSION_MAJ;      /* Major release number */
 139 const int dsw_minor_rev = ISS_VERSION_MIN;      /* Minor release number */
 140 const int dsw_micro_rev = ISS_VERSION_MIC;      /* Micro release number */
 141 const int dsw_baseline_rev = ISS_VERSION_NUM;   /* Baseline revision */
 142 static void *ii_statep;
 143 
 144 extern int _ii_init_dev();
 145 extern void _ii_deinit_dev();
 146 extern int _ii_config(intptr_t arg, int ilp32, int *rvp, int iflags);
 147 extern int _ii_disable(intptr_t arg, int ilp32, int *rvp);
 148 extern int _ii_suspend(intptr_t arg, int ilp32, int *rvp);
 149 extern int _ii_bitmap(intptr_t arg, int ilp32, int *rvp);
 150 extern int _ii_segment(intptr_t arg, int ilp32, int *rvp);
 151 extern int _ii_abort(intptr_t arg, int ilp32, int *rvp);
 152 extern int _ii_acopy(intptr_t arg, int ilp32, int *rvp);
 153 extern int _ii_copy(intptr_t arg, int ilp32, int *rvp);
 154 extern int _ii_shutdown(intptr_t arg, int *rvp);
 155 extern int _ii_stat(intptr_t arg, int ilp32, int *rvp);
 156 extern int _ii_version(intptr_t arg, int ilp32, int *rvp);
 157 extern int _ii_wait(intptr_t arg, int ilp32, int *rvp);
 158 extern int _ii_reset(intptr_t arg, int ilp32, int *rvp);
 159 extern int _ii_offline(intptr_t arg, int ilp32, int *rvp);
 160 extern int _ii_list(intptr_t arg, int ilp32, int *rvp);
 161 extern int _ii_listlen(int cmd, int ilp32, int *rvp);
 162 extern int _ii_export(intptr_t arg, int ilp32, int *rvp);
 163 extern int _ii_join(intptr_t arg, int ilp32, int *rvp);
 164 extern int _ii_copyparm(intptr_t arg, int ilp32, int *rvp);
 165 extern int _ii_ocreate(intptr_t arg, int ilp32, int *rvp);
 166 extern int _ii_oattach(intptr_t arg, int ilp32, int *rvp);
 167 extern int _ii_odetach(intptr_t arg, int ilp32, int *rvp);
 168 extern int _ii_olist(intptr_t arg, int ilp32, int *rvp);
 169 extern int _ii_ostat(intptr_t arg, int ilp32, int *rvp, int is_iost_2);
 170 extern int _ii_bitsset(intptr_t arg, int ilp32, int cmd, int *rvp);
 171 extern int _ii_gc_list(intptr_t, int, int *, kmutex_t *, _ii_lsthead_t *);
 172 extern int _ii_clist(intptr_t arg, int ilp32, int *rvp);
 173 extern int _ii_move_grp(intptr_t arg, int ilp32, int *rvp);
 174 extern int _ii_change_tag(intptr_t arg, int ilp32, int *rvp);
 175 extern int ii_debug;
 176 extern int ii_throttle_unit;
 177 extern int ii_throttle_delay;
 178 extern int ii_copy_direct;
 179 extern int ii_bitmap;
 180 
 181 int
 182 _init(void)
 183 {
 184         int error;
 185 
 186         error = ddi_soft_state_init(&ii_statep, sizeof (struct ii_state), 1);
 187         if (!error) {
 188                 error = mod_install(&ii_modlinkage);
 189                 if (error)
 190                         ddi_soft_state_fini(&ii_statep);
 191         }
 192 
 193         return (error);
 194 }
 195 
 196 int
 197 _fini(void)
 198 {
 199         int error;
 200 
 201         error = mod_remove(&ii_modlinkage);
 202         if (!error)
 203                 ddi_soft_state_fini(&ii_statep);
 204 
 205         return (error);
 206 }
 207 
 208 int
 209 _info(struct modinfo *modinfop)
 210 {
 211         int rc;
 212 
 213         rc = mod_info(&ii_modlinkage, modinfop);
 214 
 215         return (rc);
 216 }
 217 
 218 /* ARGSUSED */
 219 
 220 static int
 221 iiprobe(dev_info_t *dip)
 222 {
 223         return (DDI_PROBE_SUCCESS);
 224 }
 225 
 226 /*ARGSUSED*/
 227 static int
 228 ii_stats_update(kstat_t *ksp, int rw)
 229 {
 230         if (KSTAT_WRITE == rw) {
 231                 return (EACCES);
 232         }
 233 
 234         /*
 235          * We do nothing here for now -- the kstat structure is
 236          * updated in-place
 237          */
 238 
 239         return (0);
 240 }
 241 
 242 static void
 243 ii_create_kstats()
 244 {
 245         /* create global info structure */
 246         if (!ii_gkstat) {
 247                 ii_gkstat = kstat_create("ii", 0, "global", "StorEdge",
 248                     KSTAT_TYPE_NAMED,
 249                     sizeof (iigkstat) / sizeof (kstat_named_t),
 250                     KSTAT_FLAG_VIRTUAL);
 251                 if (ii_gkstat) {
 252                         ii_gkstat->ks_data = &iigkstat;
 253                         ii_gkstat->ks_update = ii_stats_update;
 254                         ii_gkstat->ks_private = 0;
 255                         kstat_install(ii_gkstat);
 256 
 257                         /* fill in immutable values */
 258                         iigkstat.ii_debug.value.ul = ii_debug;
 259                         iigkstat.ii_bitmap.value.ul = ii_bitmap;
 260                         iigkstat.ii_throttle_unit.value.ul = ii_throttle_unit;
 261                         iigkstat.ii_throttle_delay.value.ul =
 262                             ii_throttle_delay;
 263                         iigkstat.ii_copy_direct.value.ul = ii_copy_direct;
 264                 } else {
 265                         cmn_err(CE_WARN, "!Unable to create II global stats");
 266                 }
 267         }
 268 }
 269 
 270 static int
 271 iiattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 272 {
 273         struct ii_state *xsp;
 274         int instance;
 275         int i;
 276         intptr_t flags;
 277 
 278         if (cmd != DDI_ATTACH) {
 279                 return (DDI_FAILURE);
 280         }
 281         /* save the dev_info_t to be used in logging using ddi_log_sysevent */
 282         ii_dip = dip;
 283 
 284         instance = ddi_get_instance(dip);
 285         if (ddi_soft_state_zalloc(ii_statep, instance) != 0) {
 286                 cmn_err(CE_WARN, "!ii: no memory for instance %d state.",
 287                     instance);
 288                 return (DDI_FAILURE);
 289         }
 290 
 291         flags = 0;
 292         xsp = ddi_get_soft_state(ii_statep, instance);
 293         if (xsp == NULL) {
 294                 cmn_err(CE_WARN,
 295                     "!ii: attach: could not get state for instance %d.",
 296                     instance);
 297                 goto out;
 298         }
 299 
 300         ii_debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 301             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_debug", 0);
 302         if (ii_debug != 0) {
 303 #ifdef DEBUG
 304                 cmn_err(CE_NOTE, "!ii: initializing ii version %d.%d.%d.%d",
 305                     dsw_major_rev, dsw_minor_rev,
 306                     dsw_micro_rev, dsw_baseline_rev);
 307 #else
 308                 if (dsw_micro_rev) {
 309                         cmn_err(CE_NOTE, "!ii: initializing ii vers %d.%d.%d",
 310                             dsw_major_rev, dsw_minor_rev, dsw_micro_rev);
 311                 } else {
 312                         cmn_err(CE_NOTE, "!ii: initializing ii version %d.%d",
 313                             dsw_major_rev, dsw_minor_rev);
 314                 }
 315 #endif
 316                 switch (ii_debug) {
 317                 case 1:
 318                 case 2: cmn_err(CE_NOTE,
 319                             "!ii: ii_debug=%d is enabled.", ii_debug);
 320                         break;
 321                 default:
 322                         cmn_err(CE_WARN,
 323                             "!ii: Value of ii_debug=%d is not 0,1 or 2.",
 324                             ii_debug);
 325                 }
 326         }
 327 
 328         ii_bitmap = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 329             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_bitmap", II_WTHRU);
 330         switch (ii_bitmap) {
 331                 case II_KMEM:
 332                         if (ii_debug > 0)
 333                                 cmn_err(CE_NOTE, "!ii: ii_bitmap is in memory");
 334                 break;
 335                 case II_FWC:
 336                         if (ii_debug > 0)
 337                                 cmn_err(CE_NOTE, "!ii: ii_bitmap is on disk,"
 338                                     " no FWC");
 339                 break;
 340                 case II_WTHRU:
 341                         if (ii_debug > 0)
 342                                 cmn_err(CE_NOTE, "!ii: ii_bitmap is on disk");
 343                 break;
 344                 default:
 345                         cmn_err(CE_NOTE,
 346                             "!ii: ii_bitmap=%d out of range; "
 347                             "defaulting WTHRU(%d)", ii_bitmap, II_WTHRU);
 348                         ii_bitmap = II_WTHRU;
 349         }
 350 
 351         /* pick up these values if in ii.conf, otherwise leave alone */
 352         i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 353             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_unit", 0);
 354         if (i > 0) {
 355                 ii_throttle_unit = i;
 356                 if ((ii_throttle_unit < MIN_THROTTLE_UNIT) ||
 357                     (ii_throttle_unit > MAX_THROTTLE_UNIT) ||
 358                     (ii_debug > 0))
 359                         cmn_err(CE_NOTE,
 360                             "!ii: ii_throttle_unit=%d", ii_throttle_unit);
 361         }
 362 
 363         i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 364             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_delay", 0);
 365         if (i > 0) {
 366                 ii_throttle_delay = i;
 367                 if ((ii_throttle_delay < MIN_THROTTLE_DELAY) ||
 368                     (ii_throttle_delay > MIN_THROTTLE_DELAY) ||
 369                     (ii_debug > 0))
 370                         cmn_err(CE_NOTE,
 371                             "!ii: ii_throttle_delay=%d", ii_throttle_delay);
 372         }
 373 
 374         ii_copy_direct = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 375             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_copy_direct", 1);
 376         if (i > 0) {
 377                 ii_copy_direct = i;
 378                 if ((ii_copy_direct < 0) || (ii_copy_direct > 1))
 379                         cmn_err(CE_NOTE,
 380                             "!ii: ii_copy_direct=%d", ii_copy_direct);
 381         }
 382 
 383         if (_ii_init_dev()) {
 384                 cmn_err(CE_WARN, "!ii: _ii_init_dev failed");
 385                 goto out;
 386         }
 387         flags |= DIDINIT;
 388 
 389         xsp->dip = dip;
 390         xsp->instance = instance;
 391 
 392         if (ddi_create_minor_node(dip, "ii", S_IFCHR, instance, DDI_PSEUDO, 0)
 393             != DDI_SUCCESS) {
 394                 cmn_err(CE_WARN, "!ii: could not create node.");
 395                 goto out;
 396         }
 397         flags |= DIDNODES;
 398 
 399         ddi_set_driver_private(dip, (caddr_t)flags);
 400         ddi_report_dev(dip);
 401 
 402         ii_create_kstats();
 403 
 404         return (DDI_SUCCESS);
 405 
 406 out:
 407         ddi_set_driver_private(dip, (caddr_t)flags);
 408         (void) iidetach(dip, DDI_DETACH);
 409 
 410         return (DDI_FAILURE);
 411 }
 412 
 413 static int
 414 iidetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 415 {
 416         struct ii_state *xsp;
 417         int instance;
 418         intptr_t flags;
 419 
 420         if (cmd != DDI_DETACH) {
 421                 return (DDI_FAILURE);
 422         }
 423 
 424         if (_ii_info_top) {
 425                 return (DDI_FAILURE);   /* busy */
 426         }
 427 
 428         instance = ddi_get_instance(dip);
 429         xsp = ddi_get_soft_state(ii_statep, instance);
 430         if (xsp == NULL) {
 431                 cmn_err(CE_WARN,
 432                     "!ii: detach: could not get state for instance %d.",
 433                     instance);
 434                 return (DDI_FAILURE);
 435         }
 436 
 437         flags = (intptr_t)ddi_get_driver_private(dip);
 438         if (flags & DIDNODES)
 439                 ddi_remove_minor_node(dip, NULL);
 440         if (flags & DIDINIT)
 441                 _ii_deinit_dev();
 442 
 443         ddi_soft_state_free(ii_statep, instance);
 444 
 445         if (ii_gkstat) {
 446                 kstat_delete(ii_gkstat);
 447                 ii_gkstat = NULL;
 448         }
 449 
 450         return (DDI_SUCCESS);
 451 }
 452 
 453 
 454 /* ARGSUSED */
 455 
 456 static int
 457 iiopen(dev_t *devp, int flag, int otyp, cred_t *crp)
 458 {
 459         int error;
 460 
 461         error = drv_priv(crp);
 462 
 463         return (error);
 464 }
 465 
 466 
 467 /* ARGSUSED */
 468 
 469 static int
 470 iiclose(dev_t dev, int flag, int otyp, cred_t *crp)
 471 {
 472         return (0);
 473 }
 474 
 475 /* ARGSUSED */
 476 
 477 static int
 478 iiprint(dev_t dev, char *str)
 479 {
 480         int instance = 0;
 481 
 482         cmn_err(CE_WARN, "!ii%d: %s", instance, str);
 483         return (0);
 484 }
 485 
 486 /* ARGSUSED */
 487 
 488 static int
 489 iiioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, int *rvp)
 490 {
 491         int rc;
 492         int ilp32;
 493 
 494         ilp32 = (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32);
 495 
 496 
 497         switch (cmd) {
 498         case DSWIOC_WAIT:
 499                 rc = _ii_wait(arg, ilp32, rvp);
 500                 break;
 501 
 502         case DSWIOC_RESET:
 503                 rc = _ii_reset(arg, ilp32, rvp);
 504                 break;
 505 
 506         case DSWIOC_VERSION:
 507                 rc = _ii_version(arg, ilp32, rvp);
 508                 break;
 509 
 510         case DSWIOC_ENABLE:
 511                 rc = _ii_config(arg, ilp32, rvp, 0);
 512                 break;
 513 
 514         case DSWIOC_RESUME:
 515                 rc = _ii_config(arg, ilp32, rvp, II_EXISTING);
 516                 break;
 517 
 518         case DSWIOC_DISABLE:
 519                 rc = _ii_disable(arg, ilp32, rvp);
 520                 break;
 521 
 522         case DSWIOC_SUSPEND:
 523                 rc = _ii_suspend(arg, ilp32, rvp);
 524                 break;
 525 
 526         case DSWIOC_ACOPY:
 527                 rc = _ii_acopy(arg, ilp32, rvp);
 528                 break;
 529 
 530         case DSWIOC_COPY:
 531                 rc = _ii_copy(arg, ilp32, rvp);
 532                 break;
 533 
 534         case DSWIOC_SHUTDOWN:
 535                 rc = _ii_shutdown(arg, rvp);
 536                 break;
 537 
 538         case DSWIOC_STAT:
 539                 rc = _ii_stat(arg, ilp32, rvp);
 540                 break;
 541 
 542         case DSWIOC_BITMAP:
 543                 rc = _ii_bitmap(arg, ilp32, rvp);
 544                 break;
 545 
 546         case DSWIOC_SEGMENT:
 547                 rc = _ii_segment(arg, ilp32, rvp);
 548                 break;
 549 
 550         case DSWIOC_ABORT:
 551                 rc = _ii_abort(arg, ilp32, rvp);
 552                 break;
 553 
 554         case DSWIOC_OFFLINE:
 555                 rc = _ii_offline(arg, ilp32, rvp);
 556                 break;
 557 
 558         case DSWIOC_LIST:
 559                 rc = _ii_list(arg, ilp32, rvp);
 560                 break;
 561 
 562         case DSWIOC_LISTLEN:
 563         case DSWIOC_OLISTLEN:
 564                 rc = _ii_listlen(cmd, ilp32, rvp);
 565                 break;
 566 
 567         case DSWIOC_EXPORT:
 568                 rc = _ii_export(arg, ilp32, rvp);
 569                 break;
 570 
 571         case DSWIOC_IMPORT:
 572                 rc = _ii_config(arg, ilp32, rvp, II_IMPORT);
 573                 break;
 574 
 575         case DSWIOC_JOIN:
 576                 rc = _ii_join(arg, ilp32, rvp);
 577                 break;
 578 
 579         case DSWIOC_COPYP:
 580                 rc = _ii_copyparm(arg, ilp32, rvp);
 581                 break;
 582 
 583         case DSWIOC_OCREAT:
 584                 rc = _ii_ocreate(arg, ilp32, rvp);
 585                 break;
 586 
 587         case DSWIOC_OATTACH:
 588                 rc = _ii_oattach(arg, ilp32, rvp);
 589                 break;
 590 
 591         case DSWIOC_ODETACH:
 592                 rc = _ii_odetach(arg, ilp32, rvp);
 593                 break;
 594 
 595         case DSWIOC_OLIST:
 596                 rc = _ii_olist(arg, ilp32, rvp);
 597                 break;
 598 
 599         case DSWIOC_OSTAT:
 600                 rc = _ii_ostat(arg, ilp32, rvp, FALSE);
 601                 break;
 602 
 603         case DSWIOC_OSTAT2:
 604                 rc = _ii_ostat(arg, ilp32, rvp, TRUE);
 605                 break;
 606 
 607         case DSWIOC_SBITSSET:
 608         case DSWIOC_CBITSSET:
 609                 rc = _ii_bitsset(arg, ilp32, cmd, rvp);
 610                 break;
 611 
 612         case DSWIOC_CLIST:
 613                 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_cluster_mutex,
 614                     _ii_cluster_top);
 615                 break;
 616 
 617         case DSWIOC_GLIST:
 618                 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_group_mutex,
 619                     _ii_group_top);
 620                 break;
 621 
 622         case DSWIOC_MOVEGRP:
 623                 rc = _ii_move_grp(arg, ilp32, rvp);
 624                 break;
 625 
 626         case DSWIOC_CHANGETAG:
 627                 rc = _ii_change_tag(arg, ilp32, rvp);
 628                 break;
 629 
 630         default:
 631                 rc = EINVAL;
 632                 break;
 633         }
 634 
 635         return (rc);
 636 }
 637 
 638 /*
 639  * dummy function
 640  */
 641 
 642 static int
 643 iistrat(struct buf *bp)
 644 {
 645         bp->b_error = EIO;
 646         biodone(bp);
 647 
 648         return (0);
 649 }
 650 
 651 static int
 652 iiread()
 653 {
 654         return (EIO);
 655 }