|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1993-1990 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * File: rz.c ! 28: * Author: Alessandro Forin, Carnegie Mellon University ! 29: * Date: 10/90 ! 30: * ! 31: * Top layer of the SCSI driver: interface with the MI side. ! 32: */ ! 33: ! 34: /* ! 35: * This file contains the code that is common to all scsi devices, ! 36: * operations and/or behaviours specific to certain devices live ! 37: * in the corresponding rz_mumble files. ! 38: */ ! 39: ! 40: #include <scsi.h> ! 41: ! 42: #if (NSCSI>0) ! 43: ! 44: #include <mach/std_types.h> ! 45: #include <machine/machspl.h> /* spl definitions */ ! 46: #include <scsi/compat_30.h> ! 47: ! 48: #ifdef MACH_KERNEL ! 49: #include <kern/time_out.h> ! 50: #else /*MACH_KERNEL*/ ! 51: #include <sys/kernel.h> /* for hz */ ! 52: ! 53: static io_req_t getbp(); ! 54: #endif /*MACH_KERNEL*/ ! 55: ! 56: #include <scsi/scsi_defs.h> ! 57: #include <scsi/rz.h> ! 58: ! 59: ! 60: boolean_t ! 61: rz_check(dev, p_sc, p_tgt) ! 62: int dev; ! 63: scsi_softc_t **p_sc; ! 64: target_info_t **p_tgt; ! 65: { ! 66: if (rzcontroller(dev) >= NSCSI || ! 67: (*p_sc = scsi_softc[rzcontroller(dev)]) == 0) ! 68: return FALSE; ! 69: ! 70: *p_tgt = (*p_sc)->target[rzslave(dev)]; ! 71: ! 72: if (!*p_tgt || ! 73: !((*p_tgt)->flags&TGT_ALIVE)) ! 74: return FALSE; ! 75: return TRUE; ! 76: } ! 77: ! 78: /* ! 79: * Open routine ! 80: * ! 81: * On tapes and other devices might have to wait a bit for ! 82: * the unit to come alive. The following patchable variable ! 83: * takes this into account ! 84: */ ! 85: int rz_open_timeout = 60;/* seconds */ ! 86: ! 87: int rz_open(dev, mode, ior) ! 88: int dev; ! 89: dev_mode_t mode; ! 90: io_req_t ior; ! 91: { ! 92: scsi_softc_t *sc = 0; ! 93: target_info_t *tgt; ! 94: scsi_ret_t ret; ! 95: register int i; ! 96: ! 97: if (!rz_check(dev, &sc, &tgt)) { ! 98: /* ! 99: * Probe it again: might have installed a new device ! 100: */ ! 101: if (!sc || !scsi_probe(sc, &tgt, rzslave(dev), ior)) ! 102: return D_NO_SUCH_DEVICE; ! 103: } ! 104: ! 105: /* tapes do not wait for rewind to complete on close */ ! 106: if (tgt->ior && !(tgt->flags & TGT_ONLINE)) ! 107: return D_WOULD_BLOCK; ! 108: ! 109: if (scsi_debug) ! 110: printf("opening %s%d..", (*tgt->dev_ops->driver_name)(TRUE), dev&0xff); ! 111: ! 112: if (sc->watchdog) { ! 113: (*sc->watchdog)(tgt->hw_state); ! 114: sc->watchdog = 0; ! 115: } ! 116: ! 117: /* ! 118: * Bring the unit online, retrying if necessary. ! 119: * If the target is spinning up we wait for it. ! 120: */ ! 121: if ( ! (tgt->flags & TGT_ONLINE)) { ! 122: io_req_t tmp_ior; ! 123: ! 124: io_req_alloc(tmp_ior,0); ! 125: tmp_ior->io_next = 0; ! 126: tmp_ior->io_count = 0; ! 127: ! 128: for (i = 0; i < rz_open_timeout; i++) { ! 129: ! 130: tmp_ior->io_op = IO_INTERNAL; ! 131: tmp_ior->io_error = 0; ! 132: ret = scsi_test_unit_ready(tgt, tmp_ior); ! 133: ! 134: if (ret == SCSI_RET_SUCCESS) ! 135: break; ! 136: ! 137: if (ret == SCSI_RET_DEVICE_DOWN) { ! 138: i = rz_open_timeout; ! 139: break; ! 140: } ! 141: ! 142: if (ret == SCSI_RET_NEED_SENSE) { ! 143: ! 144: tmp_ior->io_op = IO_INTERNAL; ! 145: tmp_ior->io_count = 0; ! 146: tmp_ior->io_residual = 0; ! 147: tgt->ior = tmp_ior; ! 148: scsi_request_sense(tgt, tmp_ior, 0); ! 149: iowait(tmp_ior); ! 150: ! 151: } ! 152: ! 153: if (i == 5) printf("%s%d: %s\n", ! 154: (*tgt->dev_ops->driver_name)(TRUE), ! 155: tgt->target_id, ! 156: "Waiting to come online.."); ! 157: timeout(wakeup, tgt, hz); ! 158: await(tgt); ! 159: } ! 160: ! 161: /* lock on removable media */ ! 162: if ((i != rz_open_timeout) && (tgt->flags & TGT_REMOVABLE_MEDIA)) { ! 163: tmp_ior->io_op = IO_INTERNAL; ! 164: /* too many dont support it. Sigh */ ! 165: tgt->flags |= TGT_OPTIONAL_CMD; ! 166: (void) scsi_medium_removal( tgt, FALSE, tmp_ior); ! 167: tgt->flags &= ~TGT_OPTIONAL_CMD; ! 168: } ! 169: ! 170: io_req_free(tmp_ior); ! 171: if (i == rz_open_timeout) ! 172: return D_DEVICE_DOWN; ! 173: } ! 174: /* ! 175: * Perform anything open-time special on the device ! 176: */ ! 177: if (tgt->dev_ops->open != SCSI_OPEN_NULL) { ! 178: ret = (*tgt->dev_ops->open)(tgt, ior); ! 179: if (ret != SCSI_RET_SUCCESS) { ! 180: if (scsi_debug) printf("%s%d: open failed x%x\n", ! 181: (*tgt->dev_ops->driver_name)(TRUE), dev&0xff, ret); ! 182: return ret; ! 183: } ! 184: } ! 185: tgt->flags |= TGT_ONLINE; ! 186: ior->io_device->bsize = tgt->block_size; ! 187: return D_SUCCESS; ! 188: } ! 189: ! 190: int rz_close(dev) ! 191: int dev; ! 192: { ! 193: scsi_softc_t *sc; ! 194: target_info_t *tgt; ! 195: scsi_ret_t ret; ! 196: ! 197: if (!rz_check(dev, &sc, &tgt)) ! 198: return D_NO_SUCH_DEVICE; ! 199: ! 200: if (scsi_debug) ! 201: printf("closing %s%d..", (*tgt->dev_ops->driver_name)(TRUE), dev&0xff); ! 202: ! 203: if (tgt->flags & TGT_REMOVABLE_MEDIA) { ! 204: io_req_t ior; ! 205: ! 206: io_req_alloc(ior,0); ! 207: ior->io_next = 0; ! 208: ior->io_count = 0; ! 209: ior->io_op = IO_INTERNAL; ! 210: ior->io_error = 0; ! 211: /* too many dont support it. Sigh */ ! 212: tgt->flags |= TGT_OPTIONAL_CMD; ! 213: (void) scsi_medium_removal( tgt, TRUE, ior); ! 214: tgt->flags &= ~TGT_OPTIONAL_CMD; ! 215: io_req_free(ior); ! 216: } ! 217: ! 218: /* ! 219: * Perform anything close-time special on the device ! 220: */ ! 221: if (tgt->dev_ops->close != SCSI_CLOSE_NULL) { ! 222: ret = (*tgt->dev_ops->close)(tgt); ! 223: if (ret != SCSI_RET_SUCCESS) { ! 224: printf("%s%d: close failed x%x\n", ! 225: (*tgt->dev_ops->driver_name)(TRUE), dev&0xff, ret); ! 226: } ! 227: } ! 228: if (tgt->flags & TGT_REMOVABLE_MEDIA) ! 229: tgt->flags &= ~TGT_ONLINE; ! 230: ! 231: return D_SUCCESS; ! 232: } ! 233: ! 234: /* our own minphys */ ! 235: void rz_minphys(ior) ! 236: io_req_t ior; ! 237: { ! 238: #ifdef MACH_KERNEL ! 239: #else /*MACH_KERNEL*/ ! 240: if (ior->io_count > scsi_per_target_virtual) ! 241: ior->io_count = scsi_per_target_virtual; ! 242: #endif /*MACH_KERNEL*/ ! 243: } ! 244: ! 245: int rz_read(dev, ior) ! 246: int dev; ! 247: io_req_t ior; ! 248: { ! 249: target_info_t *tgt; ! 250: ! 251: tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; ! 252: ! 253: #ifdef MACH_KERNEL ! 254: return block_io(tgt->dev_ops->strategy, rz_minphys, ior); ! 255: #else /*MACH_KERNEL*/ ! 256: return physio(tgt->dev_ops->strategy, getbp(dev), dev, IO_READ, rz_minphys, ior); ! 257: #endif /*MACH_KERNEL*/ ! 258: } ! 259: ! 260: int rz_write(dev, ior) ! 261: int dev; ! 262: io_req_t ior; ! 263: { ! 264: target_info_t *tgt; ! 265: ! 266: tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; ! 267: ! 268: if (tgt->flags & TGT_READONLY) ! 269: return D_INVALID_OPERATION; ! 270: ! 271: #ifdef MACH_KERNEL ! 272: return block_io(tgt->dev_ops->strategy, rz_minphys, ior); ! 273: #else /*MACH_KERNEL*/ ! 274: return physio(tgt->dev_ops->strategy, getbp(dev), dev, IO_WRITE, rz_minphys, ior); ! 275: #endif /*MACH_KERNEL*/ ! 276: } ! 277: ! 278: int rz_get_status(dev, flavor, status, status_count) ! 279: int dev; ! 280: dev_flavor_t flavor; ! 281: dev_status_t status; ! 282: natural_t *status_count; ! 283: { ! 284: target_info_t *tgt; ! 285: ! 286: tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; ! 287: ! 288: if (scsi_debug) ! 289: printf("rz_get_status: x%x x%x x%x x%x\n", ! 290: dev, flavor, status, *status_count); ! 291: return (*tgt->dev_ops->get_status)(dev, tgt, flavor, status, status_count); ! 292: } ! 293: ! 294: int rz_set_status(dev, flavor, status, status_count) ! 295: int dev; ! 296: dev_flavor_t flavor; ! 297: dev_status_t status; ! 298: natural_t status_count; ! 299: { ! 300: target_info_t *tgt; ! 301: ! 302: tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; ! 303: ! 304: if (scsi_debug) ! 305: printf("rz_set_status: x%x x%x x%x x%x\n", ! 306: dev, flavor, status, status_count); ! 307: return (*tgt->dev_ops->set_status)(dev, tgt, flavor, status, status_count); ! 308: } ! 309: ! 310: /* ! 311: * Routine to return information to kernel. ! 312: */ ! 313: int ! 314: rz_devinfo(dev, flavor, info) ! 315: int dev; ! 316: int flavor; ! 317: char *info; ! 318: { ! 319: register int result; ! 320: ! 321: result = D_SUCCESS; ! 322: ! 323: switch (flavor) { ! 324: /* Caller stupidity, should use device->bsize instead */ ! 325: case D_INFO_BLOCK_SIZE: ! 326: *((int *) info) = scsi_softc[rzcontroller(dev)]-> ! 327: target[rzslave(dev)]->block_size; ! 328: break; ! 329: default: ! 330: result = D_INVALID_OPERATION; ! 331: } ! 332: ! 333: return(result); ! 334: } ! 335: ! 336: void ! 337: rz_simpleq_strategy(ior, start) ! 338: io_req_t ior; ! 339: void (*start)(); ! 340: { ! 341: target_info_t *tgt; ! 342: register scsi_softc_t *sc; ! 343: scsi_ret_t ret; ! 344: register int i = ior->io_unit; ! 345: io_req_t head, tail; ! 346: spl_t s; ! 347: ! 348: sc = scsi_softc[rzcontroller(i)]; ! 349: tgt = sc->target[rzslave(i)]; ! 350: ! 351: ior->io_next = 0; ! 352: ior->io_prev = 0; ! 353: ! 354: s = splbio(); ! 355: simple_lock(&tgt->target_lock); ! 356: if (head = tgt->ior) { ! 357: /* Queue it up at the end of the list */ ! 358: if (tail = head->io_prev) ! 359: tail->io_next = ior; ! 360: else ! 361: head->io_next = ior; ! 362: head->io_prev = ior; /* tail pointer */ ! 363: simple_unlock(&tgt->target_lock); ! 364: } else { ! 365: /* Was empty, start operation */ ! 366: tgt->ior = ior; ! 367: simple_unlock(&tgt->target_lock); ! 368: (*start)( tgt, FALSE); ! 369: } ! 370: splx(s); ! 371: } ! 372: #ifdef MACH_KERNEL ! 373: #else /*MACH_KERNEL*/ ! 374: ! 375: rz_strategy(ior) ! 376: io_req_t ior; ! 377: { ! 378: target_info_t *tgt; ! 379: register int dev = ior->io_unit; ! 380: ! 381: tgt = scsi_softc[rzcontroller(dev)]->target[rzslave(dev)]; ! 382: ! 383: return (*tgt->dev_ops->strategy)(ior); ! 384: } ! 385: ! 386: ! 387: #define IOCPARM_SIZE(c) (((c)>>16)&IOCPARM_MASK) ! 388: #define IOC_WDSIZE(s) ((IOCPARM_SIZE(s))>>2) ! 389: ! 390: rz_ioctl(dev, cmd, data, flag) ! 391: { ! 392: io_return_t error; ! 393: unsigned int count; ! 394: ! 395: count = IOC_WDSIZE(cmd); ! 396: if (cmd & (IOC_VOID|IOC_IN)) { ! 397: error = rz_set_status(dev, cmd, (dev_status_t)data, count); ! 398: if (error) ! 399: return (error); ! 400: } ! 401: if (cmd & IOC_OUT) { ! 402: error = rz_get_status(dev, cmd, (dev_status_t *)data, &count); ! 403: if (error) ! 404: return (error); ! 405: } ! 406: return (0); ! 407: } ! 408: ! 409: /* This is a very simple-minded config, ! 410: * assumes we have << 8 disks per bus */ ! 411: #define NBUF (NSCSI*8) ! 412: struct io_req rz_buffers[NBUF]; ! 413: ! 414: static io_req_t ! 415: getbp(dev) ! 416: { ! 417: io_req_t ior; ! 418: int hash = minor(dev) >> 3; ! 419: ! 420: ior = &rz_buffers[hash]; ! 421: if (ior->io_op & IO_BUSY) { ! 422: register io_req_t ior; ! 423: for (ior = rz_buffers; ior < &rz_buffers[NBUF]; ior++) ! 424: if ((ior->io_op & IO_BUSY) == 0) ! 425: return ior; ! 426: ! 427: } ! 428: return ior; ! 429: } ! 430: ! 431: /* ! 432: * This ugliness is only needed because of the ! 433: * way the minor is encoded for tapes. ! 434: */ ! 435: tz_open(dev, mode, ior) ! 436: int dev; ! 437: dev_mode_t mode; ! 438: io_req_t ior; ! 439: { ! 440: io_return_t error; ! 441: ! 442: error = rz_open(TAPE_UNIT(dev), mode, ior); ! 443: if(error) ! 444: return error; ! 445: if (TAPE_REWINDS(dev)) { ! 446: scsi_softc_t *sc; ! 447: target_info_t *tgt; ! 448: ! 449: rz_check(TAPE_UNIT(dev), &sc, &tgt); ! 450: tgt->flags |= TGT_REWIND_ON_CLOSE; ! 451: } ! 452: return 0; ! 453: } ! 454: ! 455: tz_close(dev) { return rz_close(TAPE_UNIT(dev));} ! 456: tz_read(dev, ior) { return rz_read(TAPE_UNIT(dev), ior);} ! 457: tz_write(dev, ior) { return rz_write(TAPE_UNIT(dev), ior);} ! 458: tz_ioctl(dev, cmd, data, flag) { return rz_ioctl(TAPE_UNIT(dev), cmd, data, flag);} ! 459: ! 460: #endif /*MACH_KERNEL*/ ! 461: ! 462: #endif (NSCSI>0)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.