Annotation of Gnu-Mach/scsi/rz_disk_bbr.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,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_disk_bbr.c
        !            28:  *     Author: Alessandro Forin, Carnegie Mellon University
        !            29:  *     Date:   4/91
        !            30:  *
        !            31:  *     Top layer of the SCSI driver: interface with the MI.
        !            32:  *     This file contains bad-block management functions
        !            33:  *     (retry, replace) for disk-like devices.
        !            34:  */
        !            35: 
        !            36: #include <mach/std_types.h>
        !            37: #include <scsi/compat_30.h>
        !            38: 
        !            39: #include <scsi/scsi.h>
        !            40: #include <scsi/scsi_defs.h>
        !            41: #include <scsi/rz.h>
        !            42: 
        !            43: #if  (NSCSI > 0)
        !            44: 
        !            45: int    scsi_bbr_retries = 10;
        !            46: 
        !            47: #define        BBR_ACTION_COMPLETE     1
        !            48: #define        BBR_ACTION_RETRY_READ   2
        !            49: #define BBR_ACTION_REASSIGN    3
        !            50: #define        BBR_ACTION_COPY         4
        !            51: #define        BBR_ACTION_VERIFY       5
        !            52: 
        !            53: static void make_msf(); /* forward */
        !            54: 
        !            55: /*
        !            56:  * Bad block replacement routine, invoked on
        !            57:  * unrecovereable disk read/write errors.
        !            58:  */
        !            59: boolean_t
        !            60: scdisk_bad_block_repl(tgt, blockno)
        !            61:        target_info_t           *tgt;
        !            62:        unsigned int            blockno;
        !            63: {
        !            64:        register io_req_t       ior = tgt->ior;
        !            65: 
        !            66:        if (scsi_no_automatic_bbr || (ior->io_op & IO_INTERNAL))
        !            67:                return FALSE;
        !            68: 
        !            69:        /* signal we took over */
        !            70:        tgt->flags |= TGT_BBR_ACTIVE;
        !            71: 
        !            72:        printf("%s", "Attempting bad block replacement..");
        !            73: 
        !            74:        tgt->dev_info.disk.b.badblockno = blockno;
        !            75:        tgt->dev_info.disk.b.retry_count = 0;
        !            76: 
        !            77:        tgt->dev_info.disk.b.save_rec   = ior->io_recnum;
        !            78:        tgt->dev_info.disk.b.save_addr  = ior->io_data;
        !            79:        tgt->dev_info.disk.b.save_count = ior->io_count;
        !            80:        tgt->dev_info.disk.b.save_resid = ior->io_residual;
        !            81: 
        !            82:        /*
        !            83:         * On a write all we need is to rewire the offending block.
        !            84:         * Note that the sense data identified precisely which 512 sector
        !            85:         * is bad.  At the end we'll retry the entire write, so if there
        !            86:         * is more than one bad sector involved they will be handled one
        !            87:         * at a time.
        !            88:         */
        !            89:        if ((ior->io_op & IO_READ) == 0) {
        !            90:                char msf[sizeof(int)];
        !            91:                ior->io_temporary = BBR_ACTION_COMPLETE;
        !            92:                printf("%s", "just reassign..");
        !            93:                make_msf(msf,blockno);
        !            94:                scsi_reassign_blocks( tgt, msf, 1, ior);
        !            95:        } else
        !            96:        /*
        !            97:         * This is more complicated.  We asked for N bytes, and somewhere
        !            98:         * in there there is a chunk of bad data.  First off, we should retry
        !            99:         * at least a couple of times to retrieve that data [yes the drive
        !           100:         * should have done its best already so what].  If that fails we
        !           101:         * should recover as much good data as possible (before the bad one).
        !           102:         */
        !           103:        {
        !           104:                ior->io_temporary = BBR_ACTION_RETRY_READ;
        !           105:                printf("%s", "retry read..");
        !           106:                ior->io_residual = 0;
        !           107:                scdisk_start_rw(tgt, ior);
        !           108:        }
        !           109: 
        !           110:        return TRUE;
        !           111: }
        !           112: 
        !           113: static
        !           114: void make_msf(buf,val)
        !           115:        unsigned char   *buf;
        !           116:        unsigned int    val;
        !           117: {
        !           118:        *buf++ = val >> 24;
        !           119:        *buf++ = val >> 16;
        !           120:        *buf++ = val >>  8;
        !           121:        *buf++ = val >>  0;
        !           122: }
        !           123: 
        !           124: /*
        !           125:  * This effectively replaces the strategy routine during bbr.
        !           126:  */
        !           127: void scdisk_bbr_start( tgt, done)
        !           128:        target_info_t           *tgt;
        !           129:        boolean_t               done;
        !           130: {
        !           131:        register io_req_t       ior = tgt->ior;
        !           132:        char                    *msg;
        !           133: 
        !           134:        switch (ior->io_temporary) {
        !           135: 
        !           136:        case BBR_ACTION_COMPLETE:
        !           137: 
        !           138:                /* all done, either way */
        !           139: fin:
        !           140:                tgt->flags &= ~TGT_BBR_ACTIVE;
        !           141:                ior->io_recnum   = tgt->dev_info.disk.b.save_rec;
        !           142:                ior->io_data     = tgt->dev_info.disk.b.save_addr;
        !           143:                ior->io_count    = tgt->dev_info.disk.b.save_count;
        !           144:                ior->io_residual = tgt->dev_info.disk.b.save_resid;
        !           145: 
        !           146:                if (tgt->done == SCSI_RET_SUCCESS) {
        !           147:                        /* restart normal life */
        !           148:                        register unsigned int   xferred;
        !           149:                        if (xferred = ior->io_residual) {
        !           150:                                ior->io_data -= xferred;
        !           151:                                ior->io_count += xferred;
        !           152:                                ior->io_recnum -= xferred / tgt->block_size;
        !           153:                                ior->io_residual = 0;
        !           154:                        }
        !           155:                        /* from the beginning */
        !           156:                        ior->io_error = 0;
        !           157:                        msg = "done, restarting.";
        !           158:                } else {
        !           159:                        /* we could not fix it.  Tell user and give up */
        !           160:                        tgt->ior = ior->io_next;
        !           161:                        iodone(ior);
        !           162:                        msg = "done, but could not recover.";
        !           163:                }
        !           164: 
        !           165:                printf("%s\n", msg);
        !           166:                scdisk_start( tgt, FALSE);
        !           167:                return;
        !           168: 
        !           169:        case BBR_ACTION_RETRY_READ:
        !           170: 
        !           171:                /* see if retry worked, if not do it again */
        !           172:                if (tgt->done == SCSI_RET_SUCCESS) {
        !           173:                        char msf[sizeof(int)];
        !           174: 
        !           175:                        /* whew, retry worked.  Now rewire that bad block
        !           176:                         * and don't forget to copy the good data over */
        !           177: 
        !           178:                        tgt->dev_info.disk.b.retry_count = 0;
        !           179:                        printf("%s", "ok now, reassign..");
        !           180:                        ior->io_temporary = BBR_ACTION_COPY;
        !           181:                        make_msf(msf, tgt->dev_info.disk.b.badblockno);
        !           182:                        scsi_reassign_blocks( tgt, msf, 1, ior);
        !           183:                        return;
        !           184:                }
        !           185:                if (tgt->dev_info.disk.b.retry_count++ < scsi_bbr_retries) {
        !           186:                        scdisk_start_rw( tgt, ior);
        !           187:                        return;
        !           188:                }
        !           189:                /* retrying was hopeless. Leave the bad block there for maintainance */
        !           190:                /* because we do not know what to write on it */
        !           191:                printf("%s%d%s", "failed after ", scsi_bbr_retries, " retries..");
        !           192:                goto fin;
        !           193: 
        !           194: 
        !           195:        case BBR_ACTION_COPY:
        !           196: 
        !           197:                /* retrying succeded and we rewired the bad block. */
        !           198:                if (tgt->done == SCSI_RET_SUCCESS) {
        !           199:                        unsigned int tmp;
        !           200:                        struct diskpart *label;
        !           201: 
        !           202:                        printf("%s", "ok, rewrite..");
        !           203: 
        !           204:                        /* writeback only the bad sector */
        !           205: 
        !           206:                        /* map blockno back to partition offset */
        !           207: /* !!! partition code changes: */
        !           208:                        tmp = rzpartition(ior->io_unit);
        !           209: /*                     label=lookup_part(array, tmp +1); */
        !           210:                        tmp = tgt->dev_info.disk.b.badblockno - 
        !           211: /*                             label->start; */
        !           212: /* #if 0 */
        !           213:                              tgt->dev_info.disk.l.d_partitions[tmp].p_offset;
        !           214: /* #endif 0 */
        !           215:                        ior->io_data += (tmp - ior->io_recnum) * tgt->block_size;
        !           216:                        ior->io_recnum = tmp;
        !           217:                        ior->io_count = tgt->block_size;
        !           218:                        ior->io_op &= ~IO_READ;
        !           219: 
        !           220:                        ior->io_temporary = BBR_ACTION_VERIFY;
        !           221:                        scdisk_start_rw( tgt, ior);
        !           222:                } else {
        !           223: 
        !           224:                        /* either unsupported command, or repl table full */
        !           225:                        printf("%s", "reassign failed (really needs reformatting), ");
        !           226:                        ior->io_error = 0;
        !           227:                        goto fin;
        !           228:                }
        !           229:                break;
        !           230: 
        !           231:        case BBR_ACTION_VERIFY:
        !           232: 
        !           233:                if (tgt->done == SCSI_RET_SUCCESS) {
        !           234:                        ior->io_op |= IO_READ;
        !           235:                        goto fin;
        !           236:                }
        !           237: 
        !           238:                if (tgt->dev_info.disk.b.retry_count++ > scsi_bbr_retries) {
        !           239:                        printf("%s%d%s", "failed after ",
        !           240:                                scsi_bbr_retries, " retries..");
        !           241:                        ior->io_op |= IO_READ;
        !           242:                        goto fin;
        !           243:                }
        !           244: 
        !           245:                /* retry, we are *this* close to success.. */
        !           246:                scdisk_start_rw( tgt, ior);
        !           247: 
        !           248:                break;
        !           249: 
        !           250:        case BBR_ACTION_REASSIGN:
        !           251: 
        !           252:                /* if we wanted to issue the reassign multiple times */
        !           253:                /* XXX unimplemented XXX */
        !           254: 
        !           255:        default:        /* snafu */
        !           256:                panic("scdisk_bbr_start");
        !           257:        }
        !           258: }
        !           259: #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.