|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.