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, NULL }
 121 };
 122 
 123 struct ii_state {
 124         dev_info_t *dip;
 125         int     instance;
 126 };
 127 
 128 /* used for logging sysevent, gets set in _ii_attach */
 129 dev_info_t *ii_dip = NULL;
 130 
 131 extern _ii_info_t *_ii_info_top;
 132 extern _ii_lsthead_t *_ii_cluster_top;
 133 extern _ii_lsthead_t *_ii_group_top;
 134 extern kmutex_t _ii_cluster_mutex;
 135 extern kmutex_t _ii_group_mutex;
 136 
 137 const int dsw_major_rev = ISS_VERSION_MAJ;      /* Major release number */
 138 const int dsw_minor_rev = ISS_VERSION_MIN;      /* Minor release number */
 139 const int dsw_micro_rev = ISS_VERSION_MIC;      /* Micro release number */
 140 const int dsw_baseline_rev = ISS_VERSION_NUM;   /* Baseline revision */
 141 static void *ii_statep;
 142 
 143 extern int _ii_init_dev();
 144 extern void _ii_deinit_dev();
 145 extern int _ii_config(intptr_t arg, int ilp32, int *rvp, int iflags);
 146 extern int _ii_disable(intptr_t arg, int ilp32, int *rvp);
 147 extern int _ii_suspend(intptr_t arg, int ilp32, int *rvp);
 148 extern int _ii_bitmap(intptr_t arg, int ilp32, int *rvp);
 149 extern int _ii_segment(intptr_t arg, int ilp32, int *rvp);
 150 extern int _ii_abort(intptr_t arg, int ilp32, int *rvp);
 151 extern int _ii_acopy(intptr_t arg, int ilp32, int *rvp);
 152 extern int _ii_copy(intptr_t arg, int ilp32, int *rvp);
 153 extern int _ii_shutdown(intptr_t arg, int *rvp);
 154 extern int _ii_stat(intptr_t arg, int ilp32, int *rvp);
 155 extern int _ii_version(intptr_t arg, int ilp32, int *rvp);
 156 extern int _ii_wait(intptr_t arg, int ilp32, int *rvp);
 157 extern int _ii_reset(intptr_t arg, int ilp32, int *rvp);
 158 extern int _ii_offline(intptr_t arg, int ilp32, int *rvp);
 159 extern int _ii_list(intptr_t arg, int ilp32, int *rvp);
 160 extern int _ii_listlen(int cmd, int ilp32, int *rvp);
 161 extern int _ii_export(intptr_t arg, int ilp32, int *rvp);
 162 extern int _ii_join(intptr_t arg, int ilp32, int *rvp);
 163 extern int _ii_copyparm(intptr_t arg, int ilp32, int *rvp);
 164 extern int _ii_ocreate(intptr_t arg, int ilp32, int *rvp);
 165 extern int _ii_oattach(intptr_t arg, int ilp32, int *rvp);
 166 extern int _ii_odetach(intptr_t arg, int ilp32, int *rvp);
 167 extern int _ii_olist(intptr_t arg, int ilp32, int *rvp);
 168 extern int _ii_ostat(intptr_t arg, int ilp32, int *rvp, int is_iost_2);
 169 extern int _ii_bitsset(intptr_t arg, int ilp32, int cmd, int *rvp);
 170 extern int _ii_gc_list(intptr_t, int, int *, kmutex_t *, _ii_lsthead_t *);
 171 extern int _ii_clist(intptr_t arg, int ilp32, int *rvp);
 172 extern int _ii_move_grp(intptr_t arg, int ilp32, int *rvp);
 173 extern int _ii_change_tag(intptr_t arg, int ilp32, int *rvp);
 174 extern int ii_debug;
 175 extern int ii_throttle_unit;
 176 extern int ii_throttle_delay;
 177 extern int ii_copy_direct;
 178 extern int ii_bitmap;
 179 
 180 int
 181 _init(void)
 182 {
 183         int error;
 184 
 185         error = ddi_soft_state_init(&ii_statep, sizeof (struct ii_state), 1);
 186         if (!error) {
 187                 error = mod_install(&ii_modlinkage);
 188                 if (error)
 189                         ddi_soft_state_fini(&ii_statep);
 190         }
 191 
 192         return (error);
 193 }
 194 
 195 int
 196 _fini(void)
 197 {
 198         int error;
 199 
 200         error = mod_remove(&ii_modlinkage);
 201         if (!error)
 202                 ddi_soft_state_fini(&ii_statep);
 203 
 204         return (error);
 205 }
 206 
 207 int
 208 _info(struct modinfo *modinfop)
 209 {
 210         int rc;
 211 
 212         rc = mod_info(&ii_modlinkage, modinfop);
 213 
 214         return (rc);
 215 }
 216 
 217 /* ARGSUSED */
 218 
 219 static int
 220 iiprobe(dev_info_t *dip)
 221 {
 222         return (DDI_PROBE_SUCCESS);
 223 }
 224 
 225 /*ARGSUSED*/
 226 static int
 227 ii_stats_update(kstat_t *ksp, int rw)
 228 {
 229         if (KSTAT_WRITE == rw) {
 230                 return (EACCES);
 231         }
 232 
 233         /*
 234          * We do nothing here for now -- the kstat structure is
 235          * updated in-place
 236          */
 237 
 238         return (0);
 239 }
 240 
 241 static void
 242 ii_create_kstats()
 243 {
 244         /* create global info structure */
 245         if (!ii_gkstat) {
 246                 ii_gkstat = kstat_create("ii", 0, "global", "StorEdge",
 247                     KSTAT_TYPE_NAMED,
 248                     sizeof (iigkstat) / sizeof (kstat_named_t),
 249                     KSTAT_FLAG_VIRTUAL);
 250                 if (ii_gkstat) {
 251                         ii_gkstat->ks_data = &iigkstat;
 252                         ii_gkstat->ks_update = ii_stats_update;
 253                         ii_gkstat->ks_private = 0;
 254                         kstat_install(ii_gkstat);
 255 
 256                         /* fill in immutable values */
 257                         iigkstat.ii_debug.value.ul = ii_debug;
 258                         iigkstat.ii_bitmap.value.ul = ii_bitmap;
 259                         iigkstat.ii_throttle_unit.value.ul = ii_throttle_unit;
 260                         iigkstat.ii_throttle_delay.value.ul =
 261                             ii_throttle_delay;
 262                         iigkstat.ii_copy_direct.value.ul = ii_copy_direct;
 263                 } else {
 264                         cmn_err(CE_WARN, "!Unable to create II global stats");
 265                 }
 266         }
 267 }
 268 
 269 static int
 270 iiattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 271 {
 272         struct ii_state *xsp;
 273         int instance;
 274         int i;
 275         intptr_t flags;
 276 
 277         if (cmd != DDI_ATTACH) {
 278                 return (DDI_FAILURE);
 279         }
 280         /* save the dev_info_t to be used in logging using ddi_log_sysevent */
 281         ii_dip = dip;
 282 
 283         instance = ddi_get_instance(dip);
 284         if (ddi_soft_state_zalloc(ii_statep, instance) != 0) {
 285                 cmn_err(CE_WARN, "!ii: no memory for instance %d state.",
 286                     instance);
 287                 return (DDI_FAILURE);
 288         }
 289 
 290         flags = 0;
 291         xsp = ddi_get_soft_state(ii_statep, instance);
 292         if (xsp == NULL) {
 293                 cmn_err(CE_WARN,
 294                     "!ii: attach: could not get state for instance %d.",
 295                     instance);
 296                 goto out;
 297         }
 298 
 299         ii_debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 300             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_debug", 0);
 301         if (ii_debug != 0) {
 302 #ifdef DEBUG
 303                 cmn_err(CE_NOTE, "!ii: initializing ii version %d.%d.%d.%d",
 304                     dsw_major_rev, dsw_minor_rev,
 305                     dsw_micro_rev, dsw_baseline_rev);
 306 #else
 307                 if (dsw_micro_rev) {
 308                         cmn_err(CE_NOTE, "!ii: initializing ii vers %d.%d.%d",
 309                             dsw_major_rev, dsw_minor_rev, dsw_micro_rev);
 310                 } else {
 311                         cmn_err(CE_NOTE, "!ii: initializing ii version %d.%d",
 312                             dsw_major_rev, dsw_minor_rev);
 313                 }
 314 #endif
 315                 switch (ii_debug) {
 316                 case 1:
 317                 case 2: cmn_err(CE_NOTE,
 318                             "!ii: ii_debug=%d is enabled.", ii_debug);
 319                         break;
 320                 default:
 321                         cmn_err(CE_WARN,
 322                             "!ii: Value of ii_debug=%d is not 0,1 or 2.",
 323                             ii_debug);
 324                 }
 325         }
 326 
 327         ii_bitmap = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 328             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_bitmap", II_WTHRU);
 329         switch (ii_bitmap) {
 330                 case II_KMEM:
 331                         if (ii_debug > 0)
 332                                 cmn_err(CE_NOTE, "!ii: ii_bitmap is in memory");
 333                 break;
 334                 case II_FWC:
 335                         if (ii_debug > 0)
 336                                 cmn_err(CE_NOTE, "!ii: ii_bitmap is on disk,"
 337                                     " no FWC");
 338                 break;
 339                 case II_WTHRU:
 340                         if (ii_debug > 0)
 341                                 cmn_err(CE_NOTE, "!ii: ii_bitmap is on disk");
 342                 break;
 343                 default:
 344                         cmn_err(CE_NOTE,
 345                             "!ii: ii_bitmap=%d out of range; "
 346                             "defaulting WTHRU(%d)", ii_bitmap, II_WTHRU);
 347                         ii_bitmap = II_WTHRU;
 348         }
 349 
 350         /* pick up these values if in ii.conf, otherwise leave alone */
 351         i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 352             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_unit", 0);
 353         if (i > 0) {
 354                 ii_throttle_unit = i;
 355                 if ((ii_throttle_unit < MIN_THROTTLE_UNIT) ||
 356                     (ii_throttle_unit > MAX_THROTTLE_UNIT) ||
 357                     (ii_debug > 0))
 358                         cmn_err(CE_NOTE,
 359                             "!ii: ii_throttle_unit=%d", ii_throttle_unit);
 360         }
 361 
 362         i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 363             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_throttle_delay", 0);
 364         if (i > 0) {
 365                 ii_throttle_delay = i;
 366                 if ((ii_throttle_delay < MIN_THROTTLE_DELAY) ||
 367                     (ii_throttle_delay > MIN_THROTTLE_DELAY) ||
 368                     (ii_debug > 0))
 369                         cmn_err(CE_NOTE,
 370                             "!ii: ii_throttle_delay=%d", ii_throttle_delay);
 371         }
 372 
 373         ii_copy_direct = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 374             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "ii_copy_direct", 1);
 375         if (i > 0) {
 376                 ii_copy_direct = i;
 377                 if ((ii_copy_direct < 0) || (ii_copy_direct > 1))
 378                         cmn_err(CE_NOTE,
 379                             "!ii: ii_copy_direct=%d", ii_copy_direct);
 380         }
 381 
 382         if (_ii_init_dev()) {
 383                 cmn_err(CE_WARN, "!ii: _ii_init_dev failed");
 384                 goto out;
 385         }
 386         flags |= DIDINIT;
 387 
 388         xsp->dip = dip;
 389         xsp->instance = instance;
 390 
 391         if (ddi_create_minor_node(dip, "ii", S_IFCHR, instance, DDI_PSEUDO, 0)
 392             != DDI_SUCCESS) {
 393                 cmn_err(CE_WARN, "!ii: could not create node.");
 394                 goto out;
 395         }
 396         flags |= DIDNODES;
 397 
 398         ddi_set_driver_private(dip, (caddr_t)flags);
 399         ddi_report_dev(dip);
 400 
 401         ii_create_kstats();
 402 
 403         return (DDI_SUCCESS);
 404 
 405 out:
 406         ddi_set_driver_private(dip, (caddr_t)flags);
 407         (void) iidetach(dip, DDI_DETACH);
 408 
 409         return (DDI_FAILURE);
 410 }
 411 
 412 static int
 413 iidetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 414 {
 415         struct ii_state *xsp;
 416         int instance;
 417         intptr_t flags;
 418 
 419         if (cmd != DDI_DETACH) {
 420                 return (DDI_FAILURE);
 421         }
 422 
 423         if (_ii_info_top) {
 424                 return (DDI_FAILURE);   /* busy */
 425         }
 426 
 427         instance = ddi_get_instance(dip);
 428         xsp = ddi_get_soft_state(ii_statep, instance);
 429         if (xsp == NULL) {
 430                 cmn_err(CE_WARN,
 431                     "!ii: detach: could not get state for instance %d.",
 432                     instance);
 433                 return (DDI_FAILURE);
 434         }
 435 
 436         flags = (intptr_t)ddi_get_driver_private(dip);
 437         if (flags & DIDNODES)
 438                 ddi_remove_minor_node(dip, NULL);
 439         if (flags & DIDINIT)
 440                 _ii_deinit_dev();
 441 
 442         ddi_soft_state_free(ii_statep, instance);
 443 
 444         if (ii_gkstat) {
 445                 kstat_delete(ii_gkstat);
 446                 ii_gkstat = NULL;
 447         }
 448 
 449         return (DDI_SUCCESS);
 450 }
 451 
 452 
 453 /* ARGSUSED */
 454 
 455 static int
 456 iiopen(dev_t *devp, int flag, int otyp, cred_t *crp)
 457 {
 458         int error;
 459 
 460         error = drv_priv(crp);
 461 
 462         return (error);
 463 }
 464 
 465 
 466 /* ARGSUSED */
 467 
 468 static int
 469 iiclose(dev_t dev, int flag, int otyp, cred_t *crp)
 470 {
 471         return (0);
 472 }
 473 
 474 /* ARGSUSED */
 475 
 476 static int
 477 iiprint(dev_t dev, char *str)
 478 {
 479         int instance = 0;
 480 
 481         cmn_err(CE_WARN, "!ii%d: %s", instance, str);
 482         return (0);
 483 }
 484 
 485 /* ARGSUSED */
 486 
 487 static int
 488 iiioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, int *rvp)
 489 {
 490         int rc;
 491         int ilp32;
 492 
 493         ilp32 = (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32);
 494 
 495 
 496         switch (cmd) {
 497         case DSWIOC_WAIT:
 498                 rc = _ii_wait(arg, ilp32, rvp);
 499                 break;
 500 
 501         case DSWIOC_RESET:
 502                 rc = _ii_reset(arg, ilp32, rvp);
 503                 break;
 504 
 505         case DSWIOC_VERSION:
 506                 rc = _ii_version(arg, ilp32, rvp);
 507                 break;
 508 
 509         case DSWIOC_ENABLE:
 510                 rc = _ii_config(arg, ilp32, rvp, 0);
 511                 break;
 512 
 513         case DSWIOC_RESUME:
 514                 rc = _ii_config(arg, ilp32, rvp, II_EXISTING);
 515                 break;
 516 
 517         case DSWIOC_DISABLE:
 518                 rc = _ii_disable(arg, ilp32, rvp);
 519                 break;
 520 
 521         case DSWIOC_SUSPEND:
 522                 rc = _ii_suspend(arg, ilp32, rvp);
 523                 break;
 524 
 525         case DSWIOC_ACOPY:
 526                 rc = _ii_acopy(arg, ilp32, rvp);
 527                 break;
 528 
 529         case DSWIOC_COPY:
 530                 rc = _ii_copy(arg, ilp32, rvp);
 531                 break;
 532 
 533         case DSWIOC_SHUTDOWN:
 534                 rc = _ii_shutdown(arg, rvp);
 535                 break;
 536 
 537         case DSWIOC_STAT:
 538                 rc = _ii_stat(arg, ilp32, rvp);
 539                 break;
 540 
 541         case DSWIOC_BITMAP:
 542                 rc = _ii_bitmap(arg, ilp32, rvp);
 543                 break;
 544 
 545         case DSWIOC_SEGMENT:
 546                 rc = _ii_segment(arg, ilp32, rvp);
 547                 break;
 548 
 549         case DSWIOC_ABORT:
 550                 rc = _ii_abort(arg, ilp32, rvp);
 551                 break;
 552 
 553         case DSWIOC_OFFLINE:
 554                 rc = _ii_offline(arg, ilp32, rvp);
 555                 break;
 556 
 557         case DSWIOC_LIST:
 558                 rc = _ii_list(arg, ilp32, rvp);
 559                 break;
 560 
 561         case DSWIOC_LISTLEN:
 562         case DSWIOC_OLISTLEN:
 563                 rc = _ii_listlen(cmd, ilp32, rvp);
 564                 break;
 565 
 566         case DSWIOC_EXPORT:
 567                 rc = _ii_export(arg, ilp32, rvp);
 568                 break;
 569 
 570         case DSWIOC_IMPORT:
 571                 rc = _ii_config(arg, ilp32, rvp, II_IMPORT);
 572                 break;
 573 
 574         case DSWIOC_JOIN:
 575                 rc = _ii_join(arg, ilp32, rvp);
 576                 break;
 577 
 578         case DSWIOC_COPYP:
 579                 rc = _ii_copyparm(arg, ilp32, rvp);
 580                 break;
 581 
 582         case DSWIOC_OCREAT:
 583                 rc = _ii_ocreate(arg, ilp32, rvp);
 584                 break;
 585 
 586         case DSWIOC_OATTACH:
 587                 rc = _ii_oattach(arg, ilp32, rvp);
 588                 break;
 589 
 590         case DSWIOC_ODETACH:
 591                 rc = _ii_odetach(arg, ilp32, rvp);
 592                 break;
 593 
 594         case DSWIOC_OLIST:
 595                 rc = _ii_olist(arg, ilp32, rvp);
 596                 break;
 597 
 598         case DSWIOC_OSTAT:
 599                 rc = _ii_ostat(arg, ilp32, rvp, FALSE);
 600                 break;
 601 
 602         case DSWIOC_OSTAT2:
 603                 rc = _ii_ostat(arg, ilp32, rvp, TRUE);
 604                 break;
 605 
 606         case DSWIOC_SBITSSET:
 607         case DSWIOC_CBITSSET:
 608                 rc = _ii_bitsset(arg, ilp32, cmd, rvp);
 609                 break;
 610 
 611         case DSWIOC_CLIST:
 612                 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_cluster_mutex,
 613                     _ii_cluster_top);
 614                 break;
 615 
 616         case DSWIOC_GLIST:
 617                 rc = _ii_gc_list(arg, ilp32, rvp, &_ii_group_mutex,
 618                     _ii_group_top);
 619                 break;
 620 
 621         case DSWIOC_MOVEGRP:
 622                 rc = _ii_move_grp(arg, ilp32, rvp);
 623                 break;
 624 
 625         case DSWIOC_CHANGETAG:
 626                 rc = _ii_change_tag(arg, ilp32, rvp);
 627                 break;
 628 
 629         default:
 630                 rc = EINVAL;
 631                 break;
 632         }
 633 
 634         return (rc);
 635 }
 636 
 637 /*
 638  * dummy function
 639  */
 640 
 641 static int
 642 iistrat(struct buf *bp)
 643 {
 644         bp->b_error = EIO;
 645         biodone(bp);
 646 
 647         return (0);
 648 }
 649 
 650 static int
 651 iiread()
 652 {
 653         return (EIO);
 654 }