Annotation of Gnu-Mach/scsi/rz.c, revision 1.1.1.1

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)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.