This is reasb.c in view mode; [Download] [Up]
/* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved. * * reasb - reassign logical SCSI block. */ #include <sys/types.h> #include <sys/param.h> #include <sys/ioctl.h> #include <nextdev/scsireg.h> #include <errno.h> #include <fcntl.h> /* * reassign block command data format */ struct rb_defect_list { /* for one defect only */ u_short rdl_spare; u_short rdl_length; /* will always be 4 */ u_int rdl_bad_block; /* logical block to be reassigned */ }; #define RDL_LENGTH 4 /* for rdl_length */ #define RDL_DMA_LENGTH 8 /* DMA length */ #define RECOVER_ATTEMPTS 20 /* # of times to read bad sector */ /* * values for 'silent' argument for do_ioc() */ #define SILENT_FALSE 0 #define SILENT_TRUE 1 int saved_sect_valid=0; u_char saved_sect[DEV_BSIZE]; int fd; int recover_flag=0; u_int bad_block; /* to be reassigned */ main(int argc, char **argv) { int arg; struct scsi_req sr; struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6; if(argc<3) usage(argv); bad_block = atoi(argv[2]); if(bad_block < 0) usage(argv); for(arg=3; arg<argc; arg++) { if(argv[arg][1] == 'r') recover_flag++; } if ((fd = open (argv[1], O_RDWR)) <= 0) { printf("\nCould not open %s\n",argv[1]); perror("open()"); exit(-1); } /* * request sense - just to be clean */ if(do_request_sense(fd)) exit(1); if(recover_flag) { /* * try to read the sector we want. */ int attempt; u_char inch; printf("...Trying to recover block %d(d)\n",bad_block); for(attempt=0; attempt<RECOVER_ATTEMPTS; attempt++) { if(do_read(fd, bad_block, 1, saved_sect, SILENT_TRUE) == 0) { /* ah hah! */ printf("...block %d(d) recovered after %d attempts\n", bad_block, attempt+1); saved_sect_valid++; break; } } if(!saved_sect_valid) { printf("...Could not recover block %d(d) after %d " "attempts.\n", bad_block,attempt); printf("Reassign anyway (y/anything)? "); inch = getchar(); if(inch != 'y') exit(1); } } /* recovering bad block */ printf("...Reassigning block %d(d)\n",bad_block); if(do_reassign(fd,bad_block)) /* do it */ exit(1); printf("...Block %d(d) reassigned\n",bad_block); if(saved_sect_valid) { /* * OK, restore the block's data to the new location */ if(do_write(fd, bad_block, 1, saved_sect, SILENT_FALSE)) { printf("***COULD NOT RESTORE DATA TO BLOCK %d(d)\n", bad_block); exit(1); } printf("...Block %d(d) data restored\n",bad_block); } exit(0); } /* main() */ usage(char **argv) { printf("\nusage: %s raw_device SCSI_block_number [-r]\n", argv[0]); exit(1); } /* * standard I/O routines */ do_request_sense(int fd) { struct scsi_req sr; struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6; int rtn; u_char sbuf[0x40]; cdb_clr(cdbp); cdbp->c6_opcode = C6OP_REQSENSE; cdbp->c6_len = 0x40; sr.sr_dma_dir = SR_DMA_RD; sr.sr_addr = (caddr_t)sbuf; sr.sr_dma_max = 0x40; sr.sr_ioto = 10; rtn = do_ioc(fd, &sr, SILENT_FALSE); if(rtn) printf("\n***REQUEST SENSE COMMAND FAILED\n"); return(rtn); } /* do_request_sense() */ do_read(int fd, int lba, int block_count, u_char *bp, int silent) { /* read block_count blocks starting at lba. Data goes to *bp. */ struct scsi_req sr; struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6; int rtn; cdb_clr(cdbp); cdbp->c6_opcode = C6OP_READ; cdbp->c6_lun = 0; cdbp->c6_lba = lba; cdbp->c6_len = block_count; sr.sr_dma_dir = SR_DMA_RD; sr.sr_addr = (char *)bp; sr.sr_dma_max = block_count * DEV_BSIZE; sr.sr_ioto = 10; rtn = do_ioc(fd, &sr, silent); if(rtn && !silent) printf("\n***READ COMMAND FAILED\n"); return(rtn); } /* gs_read() */ do_write(int fd, int lba, int block_count, u_char *bp) { /* write block_count blocks starting at lba. Data comes from *bp. */ struct scsi_req sr; struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6; int rtn; cdb_clr(cdbp); cdbp->c6_opcode = C6OP_WRITE; cdbp->c6_lun = 0; cdbp->c6_lba = lba; cdbp->c6_len = block_count; sr.sr_dma_dir = SR_DMA_WR; sr.sr_addr = (char *)bp; sr.sr_dma_max = block_count * DEV_BSIZE; sr.sr_ioto = 10; rtn = do_ioc(fd, &sr, SILENT_FALSE); if(rtn) printf("\n***WRITE COMMAND FAILED\n"); return(rtn); } /* gs_write() */ do_reassign(int fd, u_int bad_block) { struct scsi_req sr; struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6; struct rb_defect_list rdl, *rdlp; int rtn; rdlp = &rdl; cdb_clr(cdbp); cdbp->c6_opcode = C6OP_REASSIGNBLK; sr.sr_dma_dir = SR_DMA_WR; sr.sr_addr = (caddr_t)rdlp; sr.sr_dma_max = RDL_DMA_LENGTH; sr.sr_ioto = 100; /* * set up the defect list */ rdlp->rdl_spare = 0; rdlp->rdl_length = RDL_LENGTH; rdlp->rdl_bad_block = bad_block; rtn = do_ioc(fd, &sr, SILENT_FALSE); if(rtn) printf("\n***REASSIGN BLOCK COMMAND FAILED\n"); return(rtn); } /* do_reassign() */ cdb_clr(cdbp) union cdb *cdbp; { int i; char *p; p = (char *)cdbp; for(i=0; i<sizeof(union cdb); i++) *p++ = 0; } do_ioc(int fd, struct scsi_req *sr, int silent) { if (ioctl(fd,SDIOCSRQ,sr) < 0) { if(!silent) perror("ioctl(SDIOCREQ)"); return(1); } if(sr->sr_io_status) { if(!silent) { printf("sr_io_status = 0x%X\n",sr->sr_io_status); if(sr->sr_io_status == SR_IOST_CHKSV) { printf(" sense key = %02XH sense code = %02XH\n", sr->sr_esense.er_sensekey, sr->sr_esense.er_addsensecode); } printf("SCSI status = %02XH\n",sr->sr_scsi_status); } return(1); } return(0); } /* do_ioc() */ /* end of reasb.c */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.