|
|
1.1 ! root 1: /*********************************************************************** ! 2: * Module: haisd.c ! 3: * ! 4: * Unix device driver functions for accessing SCSI hard drives as ! 5: * block devices. Conforms to Mark Williams Coherent definition of ! 6: * the Unix Device Driver interface. ! 7: * ! 8: * Copyright (c) 1993, Christopher Sean Hilton. All rights reserved. ! 9: * ! 10: * Last Modified: Mon Jul 26 17:16:43 1993 by [chris] ! 11: * ! 12: * This code assumes BSIZE == (1 << 9). ! 13: * ! 14: * $Id: haisd.c,v 2.3 93/08/09 13:45:26 bin Exp Locker: bin $ ! 15: * ! 16: * $Log: haisd.c,v $ ! 17: * Revision 2.3 93/08/09 13:45:26 bin ! 18: * Kernel 82 changes ! 19: * ! 20: */ ! 21: ! 22: #include <stddef.h> ! 23: #include <sys/fdisk.h> ! 24: #include <sys/coherent.h> ! 25: #include <sys/buf.h> ! 26: #include <sys/inode.h> ! 27: #include <sys/stat.h> ! 28: #include <sys/sched.h> ! 29: #include <sys/sdioctl.h> /* This is not the Coherent sdioctl.h */ ! 30: #include <sys/hdioctl.h> /* All this is to make fdisk work... */ ! 31: #include <errno.h> ! 32: ! 33: #include <sys/haiscsi.h> ! 34: ! 35: #define REMOVABLE_MEDIA 0 /* Support Removable media? */ ! 36: ! 37: #define INQBUFSZ 64 ! 38: ! 39: #define SDIDLE 0 ! 40: #define SDINIT 1 ! 41: #define SDIO 2 ! 42: #define SDSENSE 3 ! 43: #define SDIOCTL 4 ! 44: ! 45: #define INQUIRY 0x12 ! 46: #define GETCAPACITY 0x25 ! 47: #define REQSENSE 0x03 ! 48: #define G1READ 0x28 ! 49: #define G1WRITE 0x2a ! 50: ! 51: typedef struct partlim_s *partlim_p; ! 52: ! 53: typedef struct partlim_s { ! 54: unsigned long base; /* base of the partition (blocks) */ ! 55: unsigned long size; /* size of the partition (blocks) */ ! 56: } partlim_t; ! 57: ! 58: typedef struct sdctrl_s *sdctrl_p; ! 59: ! 60: typedef struct sdctrl_s { ! 61: unsigned short state; ! 62: unsigned short lastclose; ! 63: BUF *actf, ! 64: *actl; ! 65: srb_t srb; ! 66: partlim_t plim[1 + 4]; /* special device (1) + all partitions (4) */ ! 67: BUF buf; ! 68: } sdctrl_t; ! 69: ! 70: static int sdload(); /* Initialize a SCSI device at (id) */ ! 71: static void sdopen(); /* Open SCSI DASD at (dev) */ ! 72: static void sdclose(); /* Close SCSI DASD at (dev) */ ! 73: static void sdblock(); /* Block Entry Point */ ! 74: static void sdread(); /* Read SCSI DASD at (dev) */ ! 75: static void sdwrite(); /* Write SCSI DASD at (dev) */ ! 76: static void sdioctl(); /* I/O Control for DASD. */ ! 77: ! 78: extern int nulldev(); ! 79: extern int nonedev(); ! 80: ! 81: static void sdstart(); ! 82: static void sdfinish(); ! 83: ! 84: #define partindex(d) ((((d) & (SPECIAL | PARTMASK)) == 0x80) ? 0 : ((d) & PARTMASK) + 1) ! 85: ! 86: dca_t sddca = { ! 87: sdopen, /* Open */ ! 88: sdclose, /* Close */ ! 89: sdblock, /* Block */ ! 90: sdread, /* Read */ ! 91: sdwrite, /* Write */ ! 92: sdioctl, /* Ioctl */ ! 93: sdload, /* Load */ ! 94: nulldev, /* Unload */ ! 95: nulldev /* Poll */ ! 96: }; ! 97: ! 98: #if REMOVABLE_MEDIA ! 99: static int rmsdload(); /* Removable Media Disks */ ! 100: ! 101: dca_t rmsddca = { ! 102: sdopen, /* Open */ ! 103: sdclose, /* Close */ ! 104: sdblock, /* Block */ ! 105: sdread, /* Read */ ! 106: sdwrite, /* Write */ ! 107: sdioctl, /* Ioctl */ ! 108: rmsdload, /* Load */ ! 109: nulldev, /* Unload */ ! 110: nulldev /* Poll */ ! 111: }; ! 112: #endif ! 113: ! 114: static sdctrl_p sddevs[MAXDEVS]; ! 115: ! 116: /*********************************************************************** ! 117: * sdload() ! 118: * ! 119: * Start up a DASD device at (id). ! 120: * ! 121: * 1) Make sure that it's a disk drive and that we can support it. ! 122: * 2) Get its size and blocksize to make sure that we can use it. ! 123: * 3) Set up a control structure for it. ! 124: */ ! 125: ! 126: static int sdload(id) ! 127: register int id; ! 128: { ! 129: register sdctrl_p c; ! 130: register srb_p r; ! 131: int timeout; ! 132: char inqbuf[INQBUFSZ]; ! 133: long diskcap[2]; ! 134: ! 135: _CHIRP('Q', 143); ! 136: c = kalloc(sizeof(sdctrl_t)); ! 137: if (!c) { ! 138: printf("\tout of memory in sdload(): "); ! 139: return 0; ! 140: } ! 141: ! 142: memset(c, 0, sizeof(sdctrl_t)); ! 143: c->state = SDINIT; ! 144: r = &(c->srb); ! 145: r->dev = makedev(SCSIMAJOR, SPECIAL | (id << 4)); ! 146: r->target = id; ! 147: r->lun = 0; ! 148: r->timeout = 0; ! 149: r->cleanup = NULL; ! 150: r->xferdir = DMAREAD; ! 151: ! 152: /* Request Sense to clear reset condition. */ ! 153: r->buf. space = KRNL_ADDR; ! 154: r->buf. addr. caddr = (caddr_t) r->sensebuf; ! 155: r->buf. size = sizeof(r->sensebuf); ! 156: memset(&(r->cdb), 0, sizeof(cdb_t)); ! 157: r->cdb. g0. opcode = REQSENSE; ! 158: r->cdb. g0. xfr_len = sizeof(r->sensebuf); ! 159: startscsi(r); ! 160: timeout = 1000000L; ! 161: while (r->status == ST_PENDING && --timeout > 0L) ! 162: ; ! 163: ! 164: if (r->status != ST_GOOD) { ! 165: printf("\tRequest sense failed: status (0x%x)\n", r->status); ! 166: kfree(c); ! 167: return 0; ! 168: } ! 169: ! 170: /* Inquiry to make sure that this is a disk drive */ ! 171: r->buf. space = KRNL_ADDR; ! 172: r->buf. addr. caddr = (caddr_t) inqbuf; ! 173: r->buf. size = sizeof(inqbuf); ! 174: memset(&(r->cdb), 0, sizeof(cdb_t)); ! 175: r->cdb. g0. opcode = INQUIRY; ! 176: r->cdb. g0. xfr_len = sizeof(inqbuf); ! 177: startscsi(r); ! 178: timeout = 1000000L; ! 179: while (r->status == ST_PENDING && --timeout > 0L) ! 180: ; ! 181: ! 182: if (r->status != ST_GOOD) { ! 183: printf("\tInquiry failed status: (0x%x)\n", r->status); ! 184: kfree(c); ! 185: return 0; ! 186: } ! 187: if (inqbuf[0] != 0) { ! 188: printf("\tDevice type byte: (0x%x) - not a DASD\n", inqbuf[0]); ! 189: kfree(c); ! 190: return 0; ! 191: } ! 192: else if (inqbuf[1] & 0x80) { ! 193: printf("\tRemovable Media Not supported yet.\n"); ! 194: kfree(c); ! 195: return 0; ! 196: } ! 197: ! 198: /* Get Capacity to set up the drive for use */ ! 199: r->buf. space = KRNL_ADDR; ! 200: r->buf. addr. caddr = (caddr_t) diskcap; ! 201: r->buf. size = sizeof(diskcap); ! 202: diskcap[0] = diskcap[1] = 0; ! 203: memset(&r->cdb, 0, sizeof(cdb_t)); ! 204: r->cdb. g1. opcode = GETCAPACITY; ! 205: startscsi(r); ! 206: timeout = 1000000L; ! 207: while (r->status == ST_PENDING && --timeout > 0L) ! 208: ; ! 209: ! 210: if (r->status != ST_GOOD) { ! 211: printf("\tGet Capacity Failed: 0x%x\n", r->status); ! 212: kfree(c); ! 213: return 0; ! 214: } ! 215: flip(diskcap[0]); ! 216: flip(diskcap[1]); ! 217: if (diskcap[1] != BSIZE) { ! 218: printf("\tInvalid Block Size %d Reformat with %d Bytes/Block\n", diskcap[1], BSIZE); ! 219: kfree(c); ! 220: return 0; ! 221: } ! 222: ! 223: inqbuf[36] = '\0'; ! 224: printf("\t%s %d MB\n", (inqbuf + 8), (diskcap[0] + bit(10)) >> 11); ! 225: sddevs[id] = c; ! 226: sddevs[id]->state = SDIDLE; ! 227: sddevs[id]->plim[0]. base = 0; ! 228: sddevs[id]->plim[0]. size = diskcap[0]; ! 229: sddevs[id]->actf = sddevs[id]->actl = NULL; ! 230: return 1; ! 231: } /* sdload() */ ! 232: ! 233: #if REMOVABLE_MEDIA ! 234: static int rmsdload(id) ! 235: register int id; ! 236: { ! 237: register sdctrl_p c; ! 238: register srb_p r; ! 239: int timeout; ! 240: long diskcap[2]; ! 241: ! 242: c = kalloc(sizeof(sdctrl_t)); ! 243: if (!c) { ! 244: printf("\tout of memory in rmsdload(): "); ! 245: return 0; ! 246: } ! 247: ! 248: memset(c, 0, sizeof(sdctrl_t)); ! 249: c->state = SDINIT; ! 250: r = &(c->srb); ! 251: r->dev = makedev(SCSIMAJOR, SPECIAL | (id << 4)); ! 252: r->target = id; ! 253: r->lun = 0; ! 254: r->timeout = 0; ! 255: r->cleanup = NULL; ! 256: r->xferdir = DMAREAD; ! 257: ! 258: /* Request Sense to clear reset condition. */ ! 259: r->buf. space = KRNL_ADDR; ! 260: r->buf. addr. caddr = (caddr_t) r->sensebuf; ! 261: r->buf. size = sizeof(r->sensebuf); ! 262: memset(&(r->cdb), 0, sizeof(cdb_t)); ! 263: r->cdb. g0. opcode = REQSENSE; ! 264: r->cdb. g0. xfr_len = sizeof(r->sensebuf); ! 265: startscsi(r); ! 266: timeout = 1000000L; ! 267: while (r->status == ST_PENDING && --timeout > 0L) ! 268: ; ! 269: ! 270: if (r->status != ST_GOOD) { ! 271: printf("\tRequest sense failed: status (0x%x)\n", r->status); ! 272: kfree(c); ! 273: return 0; ! 274: } ! 275: ! 276: /* Inquiry to make sure that this is a disk drive */ ! 277: r->buf. space = KRNL_ADDR; ! 278: r->buf. addr. caddr = (caddr_t) c->inqbuf; ! 279: r->buf. size = sizeof(c->inqbuf); ! 280: memset(&(r->cdb), 0, sizeof(cdb_t)); ! 281: r->cdb. g0. opcode = INQUIRY; ! 282: r->cdb. g0. xfr_len = sizeof(c->inqbuf); ! 283: startscsi(r); ! 284: timeout = 1000000L; ! 285: while (r->status == ST_PENDING && --timeout > 0L) ! 286: ; ! 287: ! 288: if (r->status != ST_GOOD) { ! 289: printf("\tInquiry failed status: (0x%x)\n", r->status); ! 290: kfree(c); ! 291: return 0; ! 292: } ! 293: if (c->inqbuf[0] != 0) { ! 294: printf("\tDevice type byte: (0x%x) - not a DASD\n", c->inqbuf[0]); ! 295: kfree(c); ! 296: return 0; ! 297: } ! 298: else if ((c->inqbuf[1] & 0x80) == 0) ! 299: printf("\tConfiguration error ID %d is fixed media.\n", id); ! 300: ! 301: /* Get Capacity to set up the drive for use */ ! 302: r->buf. space = KRNL_ADDR; ! 303: r->buf. addr. caddr = (caddr_t) diskcap; ! 304: r->buf. size = sizeof(diskcap); ! 305: diskcap[0] = diskcap[1] = 0; ! 306: memset(&r->cdb, 0, sizeof(cdb_t)); ! 307: r->cdb. g1. opcode = GETCAPACITY; ! 308: startscsi(r); ! 309: timeout = 1000000L; ! 310: while (r->status == ST_PENDING && --timeout > 0L) ! 311: ; ! 312: ! 313: if (r->status != ST_GOOD) { ! 314: printf("\tGet Capacity Failed: 0x%x\n", r->status); ! 315: kfree(c); ! 316: return 0; ! 317: } ! 318: flip(diskcap[0]); ! 319: flip(diskcap[1]); ! 320: printf("Get Capacity results count: %d, size %d\n", diskcap[0], diskcap[1]); ! 321: /* if (diskcap[1] != BSIZE) { ! 322: printf("\tInvalid Block Size %d Reformat with %d Bytes/Block\n", diskcap[1], BSIZE); ! 323: kfree(c); ! 324: return 0; ! 325: } ! 326: */ ! 327: c->inqbuf[36] = '\0'; ! 328: printf("\t%s %d MB\n", (c->inqbuf + 8), (diskcap[0] + bit(10)) >> 11); ! 329: sddevs[id] = c; ! 330: sddevs[id]->state = SDIDLE; ! 331: sddevs[id]->plim[0]. base = 0; ! 332: sddevs[id]->plim[0]. size = diskcap[0]; ! 333: sddevs[id]->actf = sddevs[id]->actl = NULL; ! 334: return 1; ! 335: } /* rmsdload() */ ! 336: #endif ! 337: ! 338: #if 0 ! 339: /*********************************************************************** ! 340: * sdunload() ! 341: * ! 342: * Unload routine. Right now unused so ifdefed out. ! 343: */ ! 344: ! 345: static void sdunload(id) ! 346: register int id; ! 347: { ! 348: if (sddevs[id]) { ! 349: kfree(sddevs[id]); ! 350: sddevs[id] = NULL; ! 351: } ! 352: } /* sdunload() */ ! 353: #endif ! 354: ! 355: /*********************************************************************** ! 356: * loadptable() ! 357: * ! 358: * Read the master boot record from the Fixed disk and set the block ! 359: * limits on the individual partition devices. Wouldn't it be nice if ! 360: * there were more than four partition slots available?! ! 361: */ ! 362: ! 363: static int loadptable(dev) ! 364: register dev_t dev; ! 365: { ! 366: struct fdisk_s fp[4]; ! 367: register sdctrl_p c; ! 368: register int i; ! 369: ! 370: if (!partindex(dev)) ! 371: return 0; ! 372: ! 373: if (fdisk(makedev(major(dev), (minor(dev) & ~PARTMASK) | SPECIAL), fp)) { ! 374: for (c = sddevs[tid(dev)], i = 1; i < 5; ++i) { ! 375: c->plim[i]. base = fp[i-1]. p_base; ! 376: c->plim[i]. size = fp[i-1]. p_size; ! 377: } ! 378: return 1; ! 379: } ! 380: else { ! 381: printf("fdisk failed\n"); ! 382: return -1; ! 383: } ! 384: } /* loadptable() */ ! 385: ! 386: /*********************************************************************** ! 387: * sdopen() ! 388: * ! 389: * Open Entry point for SCSI DASD devices. ! 390: */ ! 391: ! 392: static void sdopen(dev /*, mode */) ! 393: dev_t dev; ! 394: /* int mode; */ ! 395: { ! 396: register sdctrl_p c; ! 397: ! 398: c = sddevs[tid(dev)]; ! 399: if (!c || loadptable(dev) == -1) { ! 400: u. u_error = ENXIO; ! 401: return; ! 402: } ! 403: ++c->lastclose; ! 404: return; ! 405: } /* sdopen() */ ! 406: ! 407: /*********************************************************************** ! 408: * sdclose() ! 409: * ! 410: * Close the SCSI DASD device at dev. ! 411: */ ! 412: ! 413: static void sdclose(dev) ! 414: dev_t dev; ! 415: { ! 416: register sdctrl_p c; ! 417: ! 418: c = sddevs[tid(dev)]; ! 419: if (!c) ! 420: u. u_error = ENXIO; ! 421: else if (c->lastclose) ! 422: --c->lastclose; ! 423: } /* sdclose() */ ! 424: ! 425: /*********************************************************************** ! 426: * sdfinish() ! 427: * ! 428: * Finish up a fixed disk srb. ! 429: */ ! 430: ! 431: static void sdfinish(r) ! 432: register srb_p r; ! 433: { ! 434: register sdctrl_p c; ! 435: register BUF *bp; ! 436: extsense_p e; ! 437: ! 438: c = sddevs[r->target]; ! 439: bp = c->actf; ! 440: switch (c->state) { ! 441: case SDIO: ! 442: switch (r->status) { ! 443: case ST_GOOD: ! 444: bp->b_resid = bp->b_count - r->buf. size; ! 445: break; ! 446: case ST_CHKCOND: ! 447: r->timeout = 4; ! 448: r->buf. space = KRNL_ADDR; ! 449: r->buf. addr. caddr = (caddr_t) r->sensebuf; ! 450: r->buf. size = sizeof(r->sensebuf); ! 451: r->xferdir = DMAREAD; ! 452: memset(&(r->cdb), 0, sizeof(cdb_t)); ! 453: r->cdb. g0. opcode = REQSENSE; ! 454: r->cdb. g0. lun_lba = (r->lun << 5); ! 455: r->cdb. g0. xfr_len = r->buf. size; ! 456: if (startscsi(r)) ! 457: c->state = SDSENSE; ! 458: return; ! 459: default: ! 460: devmsg(r->dev, ! 461: "%s failed at block %d: status (0x%x)", ! 462: (bp->b_req == BREAD) ? "Read" : "Write", ! 463: bp->b_bno, ! 464: r->status); ! 465: bp->b_resid = bp->b_count; ! 466: bp->b_flag |= BFERR; ! 467: break; ! 468: } ! 469: break; ! 470: case SDSENSE: ! 471: if (r->status != ST_GOOD) ! 472: devmsg(r->dev, "%s sense failed at block %d", ! 473: (bp->b_req == BREAD) ? "Read" : "Write", ! 474: bp->b_bno); ! 475: else { ! 476: e = r->sensebuf; ! 477: printsense(r->dev, ! 478: (bp->b_req == BREAD) ? "Read failed" : "Write failed", ! 479: e); ! 480: if ((e->errorcode & 0x70) == 0x70 && (e->sensekey & 0x0f) == 0x01) ! 481: bp->b_resid = bp->b_count - r->buf. size; ! 482: else { ! 483: bp->b_resid = bp->b_count; ! 484: bp->b_flag |= BFERR; ! 485: } ! 486: } ! 487: break; ! 488: default: ! 489: bp->b_resid = bp->b_count; ! 490: bp->b_flag |= BFERR; ! 491: break; ! 492: } ! 493: c->actf = c->actf->b_actf; ! 494: bdone(bp); ! 495: c->state = SDIDLE; ! 496: sdstart(c); ! 497: return; ! 498: } /* sdfinish() */ ! 499: ! 500: /*********************************************************************** ! 501: * sdstart() ! 502: * ! 503: * Start/restart the Fixed disk request queue. ! 504: */ ! 505: ! 506: static void sdstart(c) ! 507: sdctrl_p c; ! 508: { ! 509: register BUF *bp; ! 510: register g1cmd_p g1; ! 511: register srb_p r = &(c->srb); ! 512: unsigned long blkcnt; ! 513: int i; ! 514: ! 515: if (!(bp = c->actf) || c->state != SDIDLE) ! 516: return; ! 517: ! 518: i = partindex(bp->b_dev); ! 519: blkcnt = bp->b_count >> 9; ! 520: if (bp->b_bno + blkcnt > c->plim[i]. size) ! 521: blkcnt = c->plim[i]. size - bp->b_bno; ! 522: ! 523: r->dev = bp->b_dev; ! 524: r->target = tid(bp->b_dev); ! 525: r->lun = lun(bp->b_dev); ! 526: r->timeout = 4; ! 527: r->buf. space = SYSGLBL_ADDR; ! 528: r->buf. addr. paddr = bp->b_paddr; ! 529: r->buf. size = (blkcnt << 9); ! 530: r->xferdir = (bp->b_req == BREAD) ? DMAREAD : DMAWRITE; ! 531: r->cleanup = &sdfinish; ! 532: g1 = &(r->cdb. g1); ! 533: memset(g1, 0, sizeof(cdb_t)); ! 534: g1->opcode = (bp->b_req == BREAD) ? G1READ : G1WRITE; ! 535: g1->lun = (r->lun << 5); ! 536: g1->lba = c->plim[i]. base + bp->b_bno; ! 537: flip(g1->lba); ! 538: g1->xfr_len = blkcnt; ! 539: flip(g1->xfr_len); ! 540: if (startscsi(r)) ! 541: c->state = SDIO; ! 542: } /* sdstart() */ ! 543: ! 544: /*********************************************************************** ! 545: * sdblock() ! 546: * ! 547: * Block/strategy entry point for SCSI fixed disks. ! 548: */ ! 549: ! 550: static void sdblock(bp) ! 551: register BUF *bp; ! 552: { ! 553: int i, s; ! 554: register sdctrl_p c; ! 555: ! 556: c = sddevs[tid(bp->b_dev)]; ! 557: i = partindex(bp->b_dev); ! 558: ! 559: bp->b_resid = bp->b_count; ! 560: if (bp->b_bno > c->plim[i]. size || (bp->b_count & (BSIZE-1)) != 0) { ! 561: bp->b_flag |= BFERR; ! 562: bdone(bp); ! 563: return; ! 564: } ! 565: ! 566: if (bp->b_bno == c->plim[i]. size) { ! 567: if (bp->b_req != BREAD) ! 568: bp->b_flag |= BFERR; ! 569: bdone(bp); ! 570: return; ! 571: } ! 572: ! 573: s = sphi(); ! 574: bp->b_actf = NULL; ! 575: if (!c->actf) ! 576: c->actf = bp; ! 577: else ! 578: c->actl->b_actf = bp; ! 579: c->actl = bp; ! 580: while (c->state == SDIDLE && c->actf) ! 581: sdstart(c); ! 582: spl(s); ! 583: } /* sdblock() */ ! 584: ! 585: /*********************************************************************** ! 586: * sdread() ! 587: * ! 588: * Read entry point for SCSI DASD devices. ! 589: */ ! 590: ! 591: static void sdread(dev, iop) ! 592: dev_t dev; ! 593: register IO *iop; ! 594: { ! 595: register sdctrl_p c; ! 596: ! 597: c = sddevs[tid(dev)]; ! 598: ioreq(&(c->buf), iop, dev, BREAD, BFIOC | BFRAW); ! 599: } /* sdread() */ ! 600: ! 601: /*********************************************************************** ! 602: * sdwrite() ! 603: * ! 604: * Write entry point for SCSI DASD devices. ! 605: */ ! 606: ! 607: static void sdwrite(dev, iop) ! 608: dev_t dev; ! 609: register IO *iop; ! 610: { ! 611: register sdctrl_p c; ! 612: ! 613: c = sddevs[tid(dev)]; ! 614: ioreq(&(c->buf), iop, dev, BWRITE, BFIOC | BFRAW); ! 615: } /* sdwrite() */ ! 616: ! 617: /*********************************************************************** ! 618: * sdioctl() ! 619: * ! 620: * I/O Control for DASD's right now. The options here are for the ! 621: * self configuring SCSI kernel. ! 622: */ ! 623: ! 624: static void sdioctl(dev, cmd, vec) ! 625: register dev_t dev; ! 626: register int cmd; ! 627: char *vec; ! 628: { ! 629: register sdctrl_p c = sddevs[tid(dev)]; ! 630: int s; ! 631: hdparm_t hdp; ! 632: ! 633: switch (cmd) { ! 634: case HDGETA: ! 635: haihdgeta(&hdp, c->plim[0]. size); ! 636: kucopy(&hdp, vec, sizeof(hdparm_t)); ! 637: break; ! 638: case HDSETA: ! 639: if (ukcopy(vec, &hdp, sizeof(hdparm_t))) ! 640: haihdseta(&hdp); ! 641: break; ! 642: default: ! 643: if (c->lastclose > 1) { ! 644: u. u_error = EACCES; /* Only one open on this device */ ! 645: return; ! 646: } ! 647: ! 648: s = sphi(); ! 649: while (c->state != SDIDLE) ! 650: /* Where is the wakeup for this sleep? */ ! 651: if (x_sleep(&(c->state), pridisk, slpriSigCatch, "sdioctl")) { ! 652: u. u_error = EINTR; ! 653: return; ! 654: } ! 655: c->state = SDIOCTL; ! 656: haiioctl(&(c->srb), cmd, vec); ! 657: c->state = SDIDLE; ! 658: spl(s); ! 659: break; ! 660: } ! 661: } /* sdioctl() */ ! 662: ! 663: /* End of file */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.