Annotation of Gnu-Mach/scsi/rz_disk_bbr.c, revision 1.1.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.