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.