home *** CD-ROM | disk | FTP | other *** search
- From: <decvax!philabs!nyit!rick>
- Newsgroups: mod.sources
- Subject: badm - BSD4.2 MASSBUS disk formatter
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 84
- Submitted by: Rick Ace <decvax!philabs!nyit!rick>
-
-
- This is a copy of the 4.2bsd timesharing disk formater I posted to
- net.sources a few months ago.
-
- Rick Ace
- New York Institute of Technology
- Computer Graphics Laboratory
- Wheatley Road
- Old Westbury, NY 11568
-
- USENET: {decvax,seismo}!philabs!nyit!rick
-
- --Cut here-- --Cut here-- --Cut here--
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # README badm.c badm.8 hp.diffs dkio.add
- echo shar: extracting README
- cat - << \SHAR_EOF > README
- badm Rev 2.0 31-Oct-85
-
- The "badm" utility is a formater for certain MASSBUS disks, operating
- under full multi-user timesharing 4.2bsd Vax system. This software
- has been placed in the public domain, for the benefit of all Vax
- 4.2bsd sites. The following files are included in this distribution:
-
- badm.c C source code for badm utility
- badm.8 Manual entry for badm - READ THIS FIRST!
- hp.diffs Additions/differences to vaxmba/hp.c
- dkio.add Additions to vax/dkio.h
-
- Installation consists of some minor additions and modifications to the
- 4.2bsd MASSBUS disk driver (vaxmba/hp.c) and some additions to the
- disk ioctl header file (vax/dkio.h). badm will *not* work without
- these changes to the 4.2bsd kernel.
-
- To install:
- 1. Read hp.diffs and dkio.add, and make coding changes
- specified therein.
- 2. Recompile kernel and boot it.
- 3. Compile badm.c.
- 4. READ MANUAL ENTRY BEFORE USING badm.
-
- This is the 2.0 revision of badm, supporting the following disks:
- RM05 RM03 Eagle RP06 RP05 RP04
-
- Additional disks can be supported by adding entries to the disktypes[]
- table in badm.c (this may also require a new whdr_XXX() subroutine,
- depending upon the header design of the target disk).
-
- Please address comments, questions, flames to the author:
-
- Rick Ace
- New York Institute of Technology
- Computer Graphics Laboratory
- Wheatley Road
- Old Westbury, NY 11568
-
- USENET: {decvax,seismo}!philabs!nyit!rick
- SHAR_EOF
- echo shar: extracting badm.c
- cat - << \SHAR_EOF > badm.c
- #ifndef lint
- static char rcsid[] = "$Header: badm.c,v 2.0 85/10/31 12:57:16 rick Exp $";
- #endif
-
- /*
- * Utility to do media checking/formating during timesharing
- *
- * $Log: badm.c,v $
- * Revision 2.0 85/10/31 12:57:16 rick
- * * First publicly-released version *
- *
- * Rick Ace
- * New York Institute of Technology
- * Computer Graphics Laboratory
- * Old Westbury, New York 11568
- *
- * {seismo,decvax}!philabs!nyit!rick
- */
-
- #include <sys/types.h>
- #include <sys/ioctl.h>
- #include <sys/dkbad.h>
- #include <vax/dkio.h>
- #include <disktab.h>
- #include <signal.h>
- #include <stdio.h>
- #include <sysexits.h>
-
- /*
- * There are a few hp.c driver bugs that can be circumvented by
- * workaround code in badm. These workarounds appear under the
- * HPBUG conditional. The `normal' (i.e., driver functions
- * properly) case appears after the `#else'.
- *
- * Of course, the right thing is to fix the driver instead,
- * but who knows... the same bugs might be in 4.Xbsd forever.
- */
- #define HPBUG 1 /* hp driver bugs are present */
-
- #define MAXNUMBAD 126 /* max # of bad sectors on one disk */
-
- /*
- * Function codes for drive-specific header-write routines
- */
- #define WHDR_VALID 0 /* mark the header as valid */
- #define WHDR_BAD 1 /* mark the header as a bad sector */
-
- /*
- * Special values returned by Btsector()
- */
- #define BTEMPTY ((daddr_t) -1) /* entry is empty */
- #define BTINVALID ((daddr_t) -2) /* entry contains an illegal c/t/s */
-
- int bflag,iflag;
- char *cmd; /* command and options, from argv */
- char diskdevice[100] = "/dev/r"; /* disk device name, built from argv */
- int dfd; /* file descriptor of disk device */
- char *patternbuf; /* output buffer, contains patterns, 0 if none */
- char *readbackbuf; /* input buffer, for readback from disk */
- unsigned short short_ones = ~0; /* all 1 bits set */
- int wantout; /* set by SIGINT to request graceful exit */
- int bsi; /* T/F: bst has been initialized */
- struct dkbad bst; /* bad sector table */
- int whdr_unknown();
-
- /*
- * Drive description table
- */
- struct st {
- char vname[12]; /* vendor's name for disk */
- int sectsize; /* # bytes per sector */
- daddr_t nsect; /* # sectors/track */
- daddr_t ntrack; /* # tracks/surfaces/heads */
- daddr_t nspc; /* # sectors/cylinder */
- daddr_t ncyl; /* # cylinders */
- int (*wheader)(); /* routine to write sector header */
- daddr_t bad0sn; /* sector # of first bad sector table */
- } st =
- { "default", 0, 0, 0, 0, 0, whdr_unknown };
-
- int whdr_rm(),whdr_rp();
-
- struct st disktypes[] = {
- { "eagle", 512, 48, 20, 48*20, 842, whdr_rm },
- { "rm05", 512, 32, 19, 32*19, 823, whdr_rm },
- { "rm03", 512, 32, 5, 32* 5, 823, whdr_rm },
- { "rp06", 512, 22, 19, 22*19, 815, whdr_rp },
- { "rp05", 512, 22, 19, 22*19, 411, whdr_rp },
- { "rp04", 512, 22, 19, 22*19, 411, whdr_rp },
- { "\0" } /* LAST ENTRY SENTINEL */
- };
-
- /*
- * Bit patterns for media surface testing
- */
- unsigned short testpattern[] = {
- 0x3333, 0x71C7, 0xB6DB, 0xDB6D, 0xE38E, 0xC71C, 0x83E8, 0x0FF0,
- 0xEC6D, 0x1C71, 0x38E3, 0xAAAA, 0x5555, 0xF00F, 0xA5A5, 0x6DEC
- };
-
- #define NPATTERN (sizeof testpattern / sizeof testpattern[0])
-
- /*
- * Torture-seek routine tables
- *
- * Routines take ordinal iteration number, returning
- * a sector number to seek to
- */
- daddr_t tort0(),tort1(),tort2(),tort3();
- daddr_t (*tortvec[])() = {
- tort0, tort1, tort2, tort3
- };
-
- /*
- * Command/options table
- *
- * WHEN CHANGING THIS TABLE BE SURE TO CHANGE THE USAGE MESSAGE TOO!
- *
- * Any option characters appearing in co_opt must also appear as
- * cases of the `switch' statement in Main().
- */
- int cmda(),cmdrw(),cmdt();
-
- struct cotab {
- char co_cmd; /* command name, 1 letter */
- char co_opt[7]; /* legal options for the command */
- int (*co_rtn)(); /* driver */
- } cotab[] = {
- 'w', "bi", cmdrw,
- 'r', "", cmdrw,
- 'a', "", cmda,
- 't', "", cmdt,
- 0 /* TERMINATOR */
- };
-
- long atol(),lseek();
- char *ctime(),*index(),*malloc();
- int catchint();
- daddr_t btsector();
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- register struct cotab *co;
- register char *p;
-
- if (signal(SIGINT,SIG_IGN) != SIG_IGN)
- (void) signal(SIGINT,catchint);
- if (argc < 2)
- usage();
- /*
- * Identify the command
- */
- cmd = argv[1];
- co = &cotab[0];
- co--;
- do if ((++co)->co_cmd == 0) usage();
- while (cmd[0] != co->co_cmd);
- /*
- * Inspect and validate the options to the main command
- */
- for (p = cmd; *++p; ) {
- if (index(co->co_opt,*p) == 0)
- usage();
- /*
- * All flag characters specified in the co_opt strings
- * must have `case' entries in this switch statement.
- * Arriving at the `should not happen' default case indicates
- * that at least one such `case' is missing (programmer error).
- */
- switch (*p) {
- case 'b': bflag++; break;
- case 'i': iflag++; break;
- default: quit(EX_SOFTWARE,"UNEXPECTED FLAG: %c\n",*p);
- }
- }
- /*
- * Command/options scan is complete, invoke the driver for this command
- */
- (*co->co_rtn)(argc-2,argv+2);
- }
-
- /*
- * Add a sector to the bad sector table and rewrite the header for the sector
- *
- * Returns T/F: sector was added to the bad sector table
- */
- addbad(sn)
- daddr_t sn; /* sector number */
- {
- register struct bt_bad *e,*e1;
- register char **bsp;
- daddr_t esn;
- char *bsbuf[MAXNUMBAD];
-
- /*
- * Abort now if I don't know how to write headers on this drive
- */
- if (st.wheader == whdr_unknown) {
- whdr_unknown((daddr_t)0,0,WHDR_BAD); /* only print error msg */
- exit(EX_UNAVAILABLE); /* should never get here, but... */
- }
- if (!bsi) /* double-check for programming errors */
- quit(EX_SOFTWARE,"bst NOT SET UP!\n");
- printf("sn%d: ",sn);
- if (btsector(&bst.bt_bad[MAXNUMBAD - 1]) != BTEMPTY) {
- printf("BAD SECTOR TABLE IS FULL, CANNOT ADD\n");
- return 0;
- }
- /*
- * Locate the position in the table where the new entry will go.
- */
- e = &bst.bt_bad[-1];
- do {
- esn = btsector(++e);
- if (esn == BTINVALID) {
- /*
- * This should never happen because the sector
- * entries in bt_bad have already been validated
- */
- printf("BAD SECTOR TABLE ENTRY %d CONTAINS AN ILLEGAL ADDRESS cyl=%x trksec=%x\n\
- NO ACTION TAKEN\n", e - &bst.bt_bad[0], e->bt_cyl, e->bt_trksec);
- return 0;
- }
- if (sn == esn) {
- printf("ALREADY IN BAD SECTOR TABLE (ALTERNATE IS BAD!)\n");
- return 0;
- }
- } while (esn != BTEMPTY && sn > esn);
- /*
- * Found the proper position for the new entry. If there are any
- * active entries with higher disk addresses, they must be shuffled
- * down one slot to make room for the new entry, because DEC std 144
- * dictates that the table must be in ascending order.
- *
- * Shuffling the entries also entails shuffling the contents of the
- * alternate sectors, so the first task is to grab those contents.
- */
- bsp = &bsbuf[0];
- e1 = e;
- do {
- esn = btsector(e1);
- if (esn == BTEMPTY)
- break;
- if ((*bsp = malloc((unsigned)st.sectsize)) == 0) {
- printf("Cannot Malloc memory, no action taken\n");
- goto fre0;
- }
- if (bread(esn, *bsp++, st.sectsize) < 0) {
- printf("Error reading sector %d, no action taken\n",esn);
- *bsp = 0;
- goto fre0;
- }
- } while (++e1 < &bst.bt_bad[MAXNUMBAD]);
- *bsp = 0; /* tie off buffer list */
- /*
- * Shuffle the table entries to make room, then install the new entry
- */
- for (e1 = &bst.bt_bad[MAXNUMBAD - 2]; e1 >= e; e1--)
- e1[1] = e1[0];
- e->bt_cyl = sn / st.nspc;
- e->bt_trksec = sn % st.nspc / st.nsect << 8 | sn % st.nsect;
- writebst(); /* write bad sector table, 5 copies */
- /*
- * Rewrite the header of the new bad sector to mark it bad
- */
- (*st.wheader)(sn,1,WHDR_BAD);
- printf("added to bad sector table\n");
- /*
- * Write the contents of the shuffled sectors back to their
- * new alternates on disk
- */
- e1 = e;
- for (bsp = &bsbuf[0]; *bsp; ) {
- /*
- * For each core buffer there should be a sector number.
- * Abort if I can't determine the sector number (this
- * would imply a logic error in this subroutine).
- */
- if (++e1 >= &bst.bt_bad[MAXNUMBAD] ||
- (esn = btsector(e1)) == BTEMPTY ||
- esn == BTINVALID)
- quit(EX_SOFTWARE,"LOST SECTOR NUMBERS FOR RE-WRITE\n");
- if (bwrite(esn, *bsp, st.sectsize) < 0)
- printf("FAILED to re-write sector %d\n",esn);
- free(*bsp++); /* discard buffer */
- }
- return 1; /* added successfully */
-
- /*
- * Free Malloc buffers and error exit
- */
- fre0: for (bsp = &bsbuf[0]; *bsp; )
- free(*bsp++);
- return 0;
- }
-
- /*
- * Read from disk
- *
- * Returns 0 OK, -1 error
- */
- bread(sn,buf,size)
- daddr_t sn; /* sector number */
- char *buf; /* buffer */
- int size; /* size (bytes) */
- {
- (void) lseek(dfd, (long)sn * (long)st.sectsize, 0);
- if (read(dfd,buf,size) == size)
- return 0;
- return -1;
- }
-
- /*
- * Given a bad sector table (bt_bad) entry, convert it to a sector number
- *
- * Returns sector number, or
- * BTEMPTY if the entry is all 1s (i.e., unoccupied), or
- * BTINVALID if entry's cylinder, track, or sector number is out of range
- */
- daddr_t
- btsector(e)
- register struct bt_bad *e; /* entry to be converted */
- {
- register unsigned int etrack,esector;
-
- if (e->bt_cyl == short_ones && e->bt_trksec == short_ones)
- return BTEMPTY;
- etrack = e->bt_trksec >> 8;
- esector = e->bt_trksec & 0xFF;
- if (e->bt_cyl >= st.ncyl ||
- etrack >= st.ntrack ||
- esector >= st.nsect)
- return BTINVALID;
- return e->bt_cyl * st.nspc + etrack * st.nsect + esector;
- }
-
- /*
- * Write to disk
- *
- * Returns 0 OK, -1 error
- */
- bwrite(sn,buf,size)
- daddr_t sn; /* sector number */
- char *buf; /* buffer */
- int size; /* size (bytes) */
- {
- (void) lseek(dfd, (long)sn * (long)st.sectsize, 0);
- if (write(dfd,buf,size) == size)
- return 0;
- return -1;
- }
-
- /*
- * SIGINT (Control-C) handler
- */
- catchint()
- {
- wantout++;
- }
-
- /*
- * Driver for `a' command
- */
- cmda(ac,av)
- int ac;
- char **av; /* main() argv sans first two entries */
- {
- register int snx;
- char *sbuf;
- daddr_t sn;
- int brv;
-
- if (ac < 2)
- usage();
- diskopen(av[0],2);
- get_devdata(); /* get disk geometry, etc. */
- readbst(); /* read bad sector table off pack */
- snx = 1;
- sbuf = malloc((unsigned)st.sectsize);
- do {
- sn = atol(av[snx]);
- if (sn < 0 || sn >= st.bad0sn - MAXNUMBAD) {
- /*
- * Illegal to specify sectors that are
- * 1. beyond the end of the disk
- * 2. in the last track (where the bad sector file is)
- * 3. in the alternate-sector region (the 126 sectors
- * preceding the last track on the disk)
- */
- printf("sn%d: out of range for `%s' disk\n",sn,st.vname);
- continue;
- }
- /*
- * Read sector contents, mark sector bad, and then
- * write the old contents out to the alternate.
- * If the data is so far gone that it cannot be
- * read, then put something clean (i.e., zeros)
- * in the alternate in lieu of the data.
- */
- if ((brv = bread(sn,sbuf,st.sectsize)) < 0) {
- printf("sn%d: CANNOT READ DATA - substituting zeros\n",sn);
- bzero(sbuf,st.sectsize); /* substitute zeros */
- }
- if (addbad(sn)) {
- /* rewrite contents to alternate */
- printf("sn%d: copy ",sn);
- if (bwrite(sn,sbuf,st.sectsize) < 0 || brv < 0)
- printf("failed\n");
- else
- printf("successful\n");
- }
- } while (++snx < ac);
- free(sbuf);
- }
-
- /*
- * Driver for `r' and `w' commands
- */
- cmdrw(ac,av)
- int ac;
- char **av; /* main() argv sans first two entries */
- {
- register daddr_t sector;
- int pass,tracksize;
- time_t now;
-
- if (ac != (iflag ? 2 : 1))
- usage();
- (void) time(&now);
- printf(ctime(&now));
- diskopen(av[0], cmd[0]=='w'?2:0);
- get_devdata(); /* get disk geometry, etc. */
- printf("%s: %s #cylinders=%d, #tracks=%d, #sectors=%d, bytes/sector=%d\n",
- diskdevice, st.vname, st.ncyl, st.ntrack, st.nsect, st.sectsize);
- if (iflag) {
- int serialno;
-
- printf("\nWriting valid headers on all sectors\n");
- initheaders(); /* writes in last track too */
- serialno = atoi(av[1]);
- printf("\nInitializing empty bad sector table, pack serial # %d\n",serialno);
- initbst(serialno);
- writebst();
- }
- else {
- if (bflag) /* possibly updating the bad table? */
- readbst(); /* yes, must read it in then */
- }
- printf("\nBeginning surface test\n");
- tracksize = st.sectsize * st.nsect; /* 1 track's worth of bytes */
- if (*cmd == 'w')
- patternbuf = malloc((unsigned)tracksize);
- readbackbuf = malloc((unsigned)tracksize);
- /*
- * Loop forever:
- * FOR (all patterns, repeat ad infinitum)
- * FOR (all tracks on disk)
- * write/read all sectors in track
- * END
- * END
- */
- for (pass = 0; ; pass = (pass + 1) % NPATTERN) {
- if (patternbuf)
- initpattern(patternbuf,tracksize,pass);
- for (sector = 0; sector < st.bad0sn; sector += st.nsect) {
- if (wantout) {
- (void) time(&now);
- printf("\n*** badm interrupted at %s",ctime(&now));
- exit(EX_OK);
- }
- if (sector && (sector % (st.nspc * 100)) == 0)
- printf("cylinder %d\n", sector / st.nspc);
- format_track(sector,tracksize);
- }
- }
- }
-
- /*
- * Driver for `t' command (torture disk)
- */
- cmdt(ac,av)
- int ac;
- char **av; /* main() argv sans first two entries */
- {
- #define TORTURE_MAX 5000
- int pass,sbint,torture;
- time_t now;
- char *sbuf;
-
- if (ac != 1)
- usage();
- (void) time(&now);
- printf("Torture test, %s\n",ctime(&now));
- diskopen(av[0],0);
- get_devdata(); /* get disk geometry, etc. */
- /*
- * Slightly more optimal page-aligned buffer,
- * so kernel spends less time in vslock/vsunlock
- */
- sbint = (int) malloc((unsigned)st.sectsize + 512);
- sbint += 511; /* round up to next page */
- sbint &= ~511;
- sbuf = (char *)sbint;
- for (pass = 1; ; pass++) {
- printf("Pass %d\n",pass);
- torture = sizeof tortvec / sizeof tortvec[0] - 1;
- do {
- register daddr_t n,(*trou)();
-
- n = 0;
- trou = tortvec[torture];
- do {
- #ifdef TTEST
- printf("%d\t%6d\n",torture,(*trou)(n));
- #else
- (void) bread((*trou)(n),sbuf,st.sectsize);
- #endif
- if (wantout) {
- printf("\n*** torture interrupted\n");
- exit(EX_OK);
- }
- } while (++n < TORTURE_MAX);
- } while (--torture >= 0);
- }
- }
-
- /*
- * Construct pathname of raw disk device and open it
- *
- * Outputs:
- * dfd file descriptor on disk device
- * diskdevice ASCII name of disk device (/dev/...)
- */
- diskopen(devun,omode)
- char *devun; /* device/unit specifier, e.g., "hp1" */
- int omode; /* mode for Open() syscall */
- {
- strcat(diskdevice,devun);
- strcat(diskdevice,"c");
- if ((dfd = open(diskdevice,omode)) < 0) {
- perror(diskdevice);
- exit(EX_NOINPUT);
- }
- #ifdef HPBUG
- /*
- * hp.c driver bug. After spinning up a new disk, the Volume
- * Valid bit in the RM/RP drive is reset. hp.c notices this
- * on the first I/O request following spinup, and sneaks in
- * a read of the bad sector table prior to doing the requested
- * disk transfer. The bug comes when the first transfer
- * done by badm includes the header; hp.c mistakenly
- * 1) applies the DKIOCHDR request to the bad sector table
- * read operation,
- * 2) then resets sc_hdr, failing to honor badm's request for
- * header I/O.
- * Bummer # 1 causes hp.c to get a mangled copy of the bad
- * sector table, and bummer # 2 causes errors when badm tries
- * to write sector headers during a `badm wbi' operation.
- *
- * Workaround: perform a gratuitous non-header read operation
- * upon opening the disk to get the driver's bad sector table
- * read operation over and done with. My read here will probably
- * fail with an HCE, but even so, it will have served its purpose.
- */
- {
- char gbuf[512];
-
- (void) read(dfd,gbuf,sizeof gbuf);
- }
- #endif HPBUG
- }
-
- /*
- * Per-track logic for surface testing and bad sector flagging
- */
- format_track(startsn,tracksize)
- daddr_t startsn; /* starting sector number */
- int tracksize; /* number of bytes in the track */
- {
- register int errorval,i,readpass;
- char badmap[256];
-
- /*
- * If doing the `w' command, write test patterns
- */
- if (patternbuf && bwrite(startsn,patternbuf,tracksize) < 0) {
- /*
- * Problems... slow down to 1 sector at a time
- * ignoring errors (I'll catch them on readback)
- */
- i = 0;
- do (void) bwrite(startsn+i,patternbuf,st.sectsize);
- while (++i < st.nsect);
- }
- /*
- * Read test patterns (or whatever) back
- */
- (void) numecc(); /* clear ECC count */
- if (bread(startsn,readbackbuf,tracksize) < 0 || numecc()) {
- /*
- * Hard error or ECC, slow down to inspect sectors individually.
- * The code here makes several passes over the entire track,
- * because if the error is marginal, it might not show up on
- * the first try.
- *
- * `badmap' limits the number of complaints to one per sector
- * when I can't mark the sector as bad (i.e., Addbad()==0).
- */
- readpass = 8; /* init pass counter */
- bzero(badmap,sizeof badmap); /* no complaints issued yet */
- do {
- i = 0; /* init sector # within track */
- do {
- if (badmap[i]) /* if previous pass found it */
- continue; /* ... that was enough */
- errorval = 0;
- if (bread(startsn+i,readbackbuf,st.sectsize) < 0
- || (errorval = numecc())) {
- /*
- * Report bad sector, then if `b' flag
- * is set, bad it and retry the read
- */
- printf("sn%d: ",startsn+i);
- printf(errorval?"soft (%d)":"hard",errorval);
- printf(" read error\n");
- if (bflag && addbad(startsn+i))
- i--; /* retry */
- else
- badmap[i] = 1;
- }
- } while (++i < st.nsect);
- } while (--readpass > 0);
- }
- }
-
- /*
- * Obtain device-specific data and set up `st' structure
- */
- get_devdata()
- {
- register struct st *s;
- register struct disktab *d;
- struct iogstat gs;
-
- if (ioctl(dfd,DKIOGSTAT,(char *)&gs) < 0)
- quit(EX_UNAVAILABLE,"cannot get drive status of %s\n",diskdevice);
- if (!gs.iogs_online)
- quit(EX_IOERR,"%s: not online\n",diskdevice);
- s = &disktypes[0];
- do {
- if (strcmp(gs.iogs_vname,s->vname) == 0) {
- bcopy((char *)s,(char *)&st,sizeof st);
- goto calc0;
- }
- } while ((++s)->vname[0]);
- /*
- * Cannot find a description of the disk in my tables,
- * so try Getdiskbyname() to see if it knows anything
- */
- s = &st; /* use defaults */
- bcopy(gs.iogs_vname,s->vname,sizeof s->vname - 1);
- if ((d = getdiskbyname(gs.iogs_vname)) == 0)
- quit(EX_OSFILE,"cannot get `disktab' information for `%s' disk\n",gs.iogs_vname);
- s->sectsize = d->d_secsize;
- s->nsect = d->d_nsectors;
- s->ntrack = d->d_ntracks;
- s->ncyl = d->d_ncylinders;
- s->nspc = s->nsect * s->ntrack; /* sectors per cylinder */
- calc0: /*
- * Sector number of first copy of bad sector table, per DEC Std 144.
- * This is the first sector of the last track
- */
- s = &st;
- s->bad0sn = s->ncyl * s->nspc - s->nsect;
- }
-
- /*
- * Initialize the in-core copy of the bad sector table:
- * 1. install pack serial number
- * 2. mark all bad sector slots as unused (all 1's)
- */
- initbst(packsn)
- int packsn; /* serial number for pack */
- {
- register struct bt_bad *be;
-
- bst.bt_csn = packsn;
- bst.bt_mbz = 0;
- bst.bt_flag = 0;
- be = &bst.bt_bad[0];
- do {
- be->bt_cyl = short_ones;
- be->bt_trksec = short_ones;
- } while (++be < &bst.bt_bad[MAXNUMBAD]);
- bsi++;
- }
-
- /*
- * Write good headers to every sector on the disk, a whole track at a time
- * including the last track where the bad sector file lives.
- */
- initheaders()
- {
- register daddr_t sn,cyli;
-
- cyli = st.ntrack * 100; /* keep user entertained while I work */
- sn = 0;
- do {
- if (wantout) {
- printf("\nLast sector written: %d\n",sn - 1);
- exit(EX_OK);
- }
- (*st.wheader)(sn,(int)st.nsect,WHDR_VALID);
- if (--cyli <= 0) {
- printf("cylinder %d\n", sn / st.nspc + 1);
- cyli = st.ntrack * 100;
- }
- } while ((sn += st.nsect) < st.nspc * st.ncyl);
- }
-
- /*
- * Initialize a buffer with the requested pattern
- */
- initpattern(bp,size,patno)
- char *bp; /* buffer to initialize */
- int size; /* size (bytes) */
- int patno; /* pattern number */
- {
- register unsigned short *pp;
- unsigned short patn;
-
- pp = (unsigned short *)bp;
- patn = testpattern[patno];
- printf("Write pattern %d = 0x%04x\n",patno,patn);
- size /= sizeof patn;
- do {
- *pp++ = patn;
- } while (--size > 0);
- }
-
- /*
- * Return the number of ECC errors corrected since the last call here
- */
- numecc()
- {
- register long lecc;
- static long necc;
- static int eccnotavail;
-
- if (eccnotavail)
- return 0;
- lecc = necc; /* previous count */
- if (ioctl(dfd,DKIOGETECC,(char *)&necc) < 0) {
- printf("WARNING: ECC COUNTS NOT AVAILABLE, LIMPING ALONG\n");
- eccnotavail++;
- return 0;
- }
- return necc - lecc;
- }
-
- /*
- * Printf a diagnostic message and exit
- */
- /*VARARGS2*/
- quit(exitcode,fmt,args)
- int exitcode;
- char *fmt;
- {
- _doprnt(fmt,&args,stdout); /* tacky, tacky */
- if (exitcode == EX_SOFTWARE)
- abort(); /* make core image for debugging */
- exit(exitcode);
- /* should *NEVER EVER* get here :-) */
- }
-
- /*
- * Read the bad sector table off the pack into core, and validate it
- */
- readbst()
- {
- register int n;
- register struct bt_bad *e;
- int active;
- daddr_t btabsn, cursn, lastsn;
-
- btabsn = st.bad0sn; /* where the first copy of the table is */
- n = 5; /* 5 copies, per DEC std 144 */
- while (bread(btabsn,(char *)&bst,sizeof bst) < 0) {
- printf("WARNING: CANNOT READ BAD SECTOR TABLE (sn%d)\n",btabsn);
- btabsn += 2; /* try another copy */
- if (--n <= 0) {
- /*
- * If I can't read the current bad sector table,
- * I can't augment it now, can I?
- */
- printf("\n\
- You might have to re-format the *WHOLE* disk with `badm wbi'\n");
- exit(EX_IOERR);
- }
- }
- printf("Bad sector table read from sn%d\n",btabsn);
- /*
- * Validate the contents per these rules:
- * o Active slots, if any, must be clustered at the
- * beginning of the table, and inactive slots at the end
- * o Cylinder, track, and sector numbers must be within
- * the legal ranges for the type of disk I'm working on
- * o Bad sector entries must be in order of ascending
- * disk addresses
- */
- e = &bst.bt_bad[0];
- active = 1; /* in active region of table */
- #ifdef lint
- lastsn = 0; /* avoid lint complaint */
- #endif
- do {
- cursn = btsector(e); /* convert entry to sector number */
- if (cursn == BTINVALID)
- quit(EX_DATAERR,"Entry %d: illegal disk address, cyl=%x trksec=%x\n",
- e - &bst.bt_bad[0], e->bt_cyl, e->bt_trksec);
- if (cursn == BTEMPTY)
- active = 0;
- else {
- if (!active ||
- e > &bst.bt_bad[0] && cursn <= lastsn)
- quit(EX_DATAERR,"Entry %d: out of order\n",
- e - &bst.bt_bad[0]);
- lastsn = cursn;
- }
- } while (++e < &bst.bt_bad[MAXNUMBAD]);
- bsi++; /* note that bst is set up */
- }
-
- /*
- * Random places on disk
- */
- /*ARGSUSED*/
- daddr_t
- tort0(n)
- daddr_t n;
- {
- long random();
-
- return random() % (st.nspc * st.ncyl);
- }
-
- /*
- * Start at opposite ends of disk, then oscillate, closing in on center
- */
- daddr_t
- tort1(n)
- daddr_t n;
- {
- register daddr_t cyl,dist;
-
- dist = n % st.ncyl >> 1;
- cyl = n & 1 ? st.ncyl - dist - 1 : dist;
- return cyl * st.nspc;
- }
-
- /*
- * Slam heads from end to end
- */
- daddr_t
- tort2(n)
- daddr_t n;
- {
- /*
- * 0x301 is about 1/4 as abusive as 0x001
- */
- if (n & 0x301)
- return (st.ncyl - 1) * st.nspc;
- return 0;
- }
-
- /*
- * 4 close, large seek, 4 close, large seek ...
- */
- daddr_t
- tort3(n)
- register daddr_t n;
- {
- register daddr_t cyl;
- static daddr_t tab4[4] = { 0, 2, 1, 3 };
-
- cyl = tab4[n & 3] + (n >> 3) % (st.ncyl - 8 >> 1);
- if (n & 4)
- cyl += st.ncyl >> 1;
- return cyl * st.nspc;
- }
-
- usage()
- {
- fprintf(stderr,"Usage:\n\
- badm r DISKDEVICE\n\
- \tread entire disk sequentially, scanning for errors and ECCs\n\
- \t(does not alter disk)\n");
- fprintf(stderr,"\n\
- badm t DISKDEVICE\n\
- \tread-only torture test for disk arm\n");
- fprintf(stderr,"\n\
- badm w[bi] DISKDEVICE [ PACKSN ]\n\
- \tw write and readback test patterns (bashes filesystems!)\n\
- \twb same as `w', and augments bad sector table\n\
- \twbi same as `wb', and clears all headers and bad sector tables first\n\
- \t (decimal pack serial number PACKSN required with `wbi')\n\
- ");
- fprintf(stderr,"\n\
- badm a DISKDEVICE SECTORNO [ SECTORNO ... ]\n\
- \tadd specified sectors to the bad sector table\n\
- ");
- fprintf(stderr,"\n\
- DISKDEVICE is the device name and unit number, like `hp1'\n\
- SECTORNO is a decimal sector number\n\
- *** READ THE CAUTIONS IN THE MANUAL ENTRY FIRST!!! ***\n\
- ");
- exit(EX_USAGE);
- }
-
- char nohmemmsg[] = "cannot get memory for header I/O\n";
-
- /*
- * Sector header I/O for RM-class MASSBUS disks (incl. Eagle)
- */
- whdr_rm(sn,nb,type)
- daddr_t sn; /* disk sector number */
- int nb; /* number of sectors */
- int type; /* WHDR_xxx */
- {
- static struct rmhdrbuf {
- unsigned short hdr1;
- char h2sector;
- char h2track;
- char pad[512];
- } *ebuf;
- register struct rmhdrbuf *e;
- register int i;
-
- if ((e = ebuf) == 0) {
- e = (struct rmhdrbuf *)malloc(sizeof (struct rmhdrbuf) * (unsigned)st.nsect);
- if (e == 0)
- quit(EX_OSERR,nohmemmsg);
- ebuf = e;
- }
- i = 0;
- do {
- e->hdr1 = 1 << 12; /* 16-bit format */
- if (type == WHDR_VALID)
- e->hdr1 |= 0xC000; /* good (valid) sector */
- e->hdr1 |= (sn + i) / st.nspc;
- e->h2track = (sn + i) % st.nspc / st.nsect;
- e->h2sector = (sn + i) % st.nsect;
- e++;
- } while (++i < nb);
- if (ioctl(dfd,DKIOCHDR,(char *)0) < 0) {
- perror("DKIOCHDR");
- exit(EX_UNAVAILABLE);
- }
- #ifdef HPBUG
- /*
- * Circumvent hp.c driver bug. When testing to see if I/O will
- * tread beyond the end of the disk, hpstrategy() does not take
- * into account the fact that the sector size during header I/O
- * is 516 (not 512) bytes. Thus, the driver rejects some
- * legitimate requests because it erroneously concludes that
- * they would result in a transfer beyond the end of the disk.
- *
- * The workaround here deducts the number of bytes consumed by
- * the headers (nb * 4) from the `right' (nb * 516) byte count;
- * this appeases hp.c, but it also results in a partial write to
- * the last sector of the bunch. The partial write is harmless
- * here, since we care only about the headers and not about
- * anything else in the sectors. The only possible problem can
- * occur if more than 512 bytes are deducted (i.e., nb > 128),
- * because that would eat into the header of the last sector.
- */
- if (nb > 128) /* should never happen :-) */
- quit(EX_SOFTWARE,"\nSOFTWARE BUG: nb (%d) > 128\n",nb);
- if (bwrite(sn, (char *)ebuf, st.sectsize * nb) < 0)
- #else HPBUG
- if (bwrite(sn, (char *)ebuf, (char *)e - (char *)ebuf) < 0)
- #endif HPBUG
- printf("sn%d: HEADER WRITE FAILED, CONTINUING\n",sn);
- }
-
- /*
- * Sector header I/O for RP04/5/6 MASSBUS disks
- */
- whdr_rp(sn,nb,type)
- daddr_t sn; /* disk sector number */
- int nb; /* number of sectors */
- int type; /* WHDR_xxx */
- {
- static struct rphdrbuf {
- unsigned short hdr1;
- char h2sector;
- char h2track;
- unsigned short keyfield1,keyfield2;
- char pad[512];
- } *ebuf;
- register struct rphdrbuf *e;
- register int i;
-
- if ((e = ebuf) == 0) {
- e = (struct rphdrbuf *)malloc(sizeof (struct rphdrbuf) * (unsigned)st.nsect);
- if (e == 0)
- quit(EX_OSERR,nohmemmsg);
- ebuf = e;
- }
- i = 0;
- do {
- /*
- * Bad sector handling on RP04/5/6s is a kludge, since there
- * is no true hardware support (a la RM series drives).
- * The convention employed in badm and the kernel (hp.c) to
- * denote a bad sector is to clear 16-bit format (bit 12)
- * in the header. When reading accessing the sector, the
- * drive will report "format error", which hp.c assumes to
- * mean "RP0x bad sector".
- */
- e->hdr1 = 0; /* invalid */
- if (type == WHDR_VALID)
- e->hdr1 = 0x1000; /* good (valid) sector */
- e->hdr1 |= (sn + i) / st.nspc;
- e->h2track = (sn + i) % st.nspc / st.nsect;
- e->h2sector = (sn + i) % st.nsect;
- e->keyfield1 = 0; /* what are these for? */
- e->keyfield2 = 0;
- e++;
- } while (++i < nb);
- if (ioctl(dfd,DKIOCHDR,(char *)0) < 0) {
- perror("DKIOCHDR");
- exit(EX_UNAVAILABLE);
- }
- #ifdef HPBUG
- /*
- * Circumvent hp.c driver bug.
- * See comments in whdr_rm() for explanation of this bug.
- * Sector size during header I/O for RP06 is 520 bytes
- * (512 sector data + 8 header).
- */
- if (nb > 512 / 8) /* should never happen :-) */
- quit(EX_SOFTWARE,"\nSOFTWARE BUG: nb (%d) > 512 / 8\n",nb);
- if (bwrite(sn, (char *)ebuf, st.sectsize * nb) < 0)
- #else HPBUG
- if (bwrite(sn, (char *)ebuf, (char *)e - (char *)ebuf) < 0)
- #endif HPBUG
- printf("sn%d: HEADER WRITE FAILED, CONTINUING\n",sn);
- }
-
- /*ARGSUSED*/
- whdr_unknown(sn,nb,type)
- daddr_t sn; /* disk sector number */
- int nb; /* number of sectors */
- int type; /* WHDR_xxx */
- {
- quit(EX_UNAVAILABLE,"don't know how to read/write headers on `%s' disks\n",st.vname);
- }
-
- /*
- * Write the bad sector table out to the disk
- *
- * Writes 5 copies, in the first 5 even-numbered sectors of the
- * last track of the last cylinder of the disk (per DEC Std 144)
- *
- * Also informs the driver there's a new bad sector table, because some
- * drivers (e.g., hp.c) keep in-core copies, which are read only at bootup
- * or when the drive is spun up (i.e., when Volume-Valid is reset)
- */
- writebst()
- {
- register int i;
- static int noioctl;
-
- /*
- * Write 5 copies, per DEC std 144
- */
- i = 0;
- do {
- if (bwrite(st.bad0sn + i * 2, (char *)&bst, sizeof bst) < 0)
- printf("ERROR WRITING BAD TABLE %d, CONTINUING\n",i);
- } while (++i < 5);
- /*
- * Now tell the driver that the bad block table has been updated.
- * This is necessary because hp.c maintains an in-core copy of
- * this table (in "hpbad"), and, in order to do the job right,
- * the in-core copy must be accurate.
- */
- if (!noioctl && ioctl(dfd,DKIONEWBAD,(char *)0) < 0) {
- noioctl++;
- printf("WARNING: Cannot inform driver of new bad sector table\n");
- }
- #ifdef HPBUG
- /*
- * Perform a gratuitous read operation to force driver to read
- * the bad sector table into the in-core "hpbad" table.
- * See explanation in Diskopen() for more details.
- */
- {
- char gbuf[512];
-
- (void) bread((daddr_t)0,gbuf,sizeof gbuf);
- }
- #endif HPBUG
- }
- SHAR_EOF
- echo shar: extracting badm.8
- cat - << \SHAR_EOF > badm.8
- .TH BADM 8 10/31/85
- .SH NAME
- badm \- disk formating and bad sector maintenance
- .SH SYNOPSIS
- .B badm w
- diskdevice
- .PP
- .B badm wb
- diskdevice
- .PP
- .B badm wbi
- diskdevice packsn
- .PP
- .B badm r
- diskdevice
- .PP
- .B badm t
- diskdevice
- .PP
- .B badm a
- diskdevice sectorno [ sectorno ... ]
- .SH DESCRIPTION
- .I Badm
- gives the system administrator control over the bad sector information
- on a disk pack. Some of the salient features are:
- .TP 3
- \(bu
- Comprehensive, thorough formating capability available under
- timesharing, eliminating the need to devote an entire Vax
- system for a disk format operation
- .TP
- \(bu
- Read-only mode available to assist in locating deficient sectors
- on the disk without disturbing filesystems
- .TP
- \(bu
- Capability to add `johnny-come-lately' failing sectors to the bad
- sector table without disturbing other data on the disk
- .PP
- In the following command descriptions, the
- .I diskdevice
- argument refers to a disk drive by type and unit number (e.g., `hp1'), and
- .I sectorno
- is a sector number on the disk, expressed as an unsigned integer.
- .TP 3
- .B w
- Write and readback test patterns. With no options, the
- .B w
- command writes a test pattern to every track of the disk and reads
- each track after writing it. Any hard errors or soft ECC errors
- reported by the drive are also reported by
- .IR badm .
- If the
- .B b
- option is given,
- .I badm
- will also add all sectors with hard or soft errors to the bad
- sector table on the disk and mark the headers of the failing
- sectors as being bad. If the
- .B i
- option is given,
- .I badm
- makes an initial pass over the disk, writing good headers on all
- sectors of the disk and marking all entries in the bad sector table
- as unused. When invoking
- .I badm
- with the
- .B i
- option, the decimal serial number
- .RI ( packsn )
- of the disk must be included on the command line. The function of
- .B badm wbi
- may be used in lieu of the traditional
- .I format
- procedure that the DEC VMS formater performs on new disks.
- When invoked with the
- .B w
- command,
- .I badm
- will cycle forever through all its test patterns, writing the patterns
- to the disk and reading them back. Typing CTRL/C will exit the program.
- .TP
- .B r
- This function simply reads the entire disk from beginning to end
- ad infinitum, reporting soft ECC and hard errors to the user.
- It does not modify anything on the disk, and is thus safe to run
- at any time. Type CTRL/C to exit.
- .TP
- .B t
- Torture the disk drive by moving the arm through a series of positions,
- ad infinitum. This function does not alter any data on the disk.
- Type CTRL/C to exit.
- .TP
- .B a
- Each
- .I sectorno
- argument specifies (as a decimal number) a sector to be labeled as `bad'.
- .I Badm
- rewrites the sector header to indicate that the sector is `bad', adds the
- the sector to the disk's bad sector table, and copies the contents of the
- specified sector to its replacement sector. If the contents of the sector
- cannot be read,
- .I badm
- complains and fills the replacement sector with zeros. This function is
- useful for adding known failing sectors to the bad sector list without
- incurring the risk and expense of reformating the entire disk.
- .RB ( CAUTION:
- See operational restrictions below about other disk activity while using
- .IR badm .)
- .PP
- To format a brand new disk, use
- .B badm
- .BR wbi .
- The longer
- .I badm
- runs, the higher the probability that all of the marginal sectors on
- the disk have been classified as being `bad'. The formating process
- begun by
- .B badm wbi
- can be continued after interruption (CTRL/C, system crash, etc.) by
- .B badm
- .BR wb .
- .PP
- When invoked with the
- .B w
- command,
- .I badm
- prints a message whenever it begins writing a different test pattern
- on the disk:
- .PP
- .ti +4
- Write pattern N = 0xV
- .PP
- where
- .I N
- is the pattern number and
- .I V
- is the test data composing the pattern. The pattern number,
- .IR N ,
- will count upward from 0; when it returns to 0, all patterns have been
- written to the disk once.
- .PP
- When formating a disk, it is recommended to let
- .I badm
- write each of its test patterns on the disk at least once. This may
- take many hours, depending upon the size of the disk, but any time
- invested in the formating process will pay off well in the long run.
- If it is necessary to have a formated disk quickly, use
- .B badm wbi
- and type CTRL/C after
- .I badm
- has begun to write the first test pattern.
- .SH OPERATIONAL RESTRICTIONS
- It is
- .I absolutely imperative
- that no other I/O activity be permitted
- on a disk that is being modified by the
- .BR wb ,
- .BR wbi ,
- or
- .B a
- command to
- .IR badm .
- This means if the disk is a user disk, none of its areas may be mounted.
- Also,
- .I badm cannot be used at all
- to modify a disk that is serving as a system disk; attempts to do so can
- result in corruption of the filesystem and/or format information on the disk.
- The proper technique for using
- .I badm
- on a pack that normally serves as a system disk is to boot UNIX from
- another system disk and to operate on the target pack as a non-system disk.
- .PP
- .I Badm
- should be used with the same care that one exercises when using
- .IR mkfs (8).
- .SH DIAGNOSTICS
- .TP 5
- BAD SECTOR TABLE IS FULL, CANNOT ADD
- An attempt to place more than 126 bad sectors in the bad sector file failed.
- DEC Standard 144 limits the number of `bad' blocks on a disk to 126.
- Try reformating the disk completely
- .RB ( badm
- .BR wbi );
- if this message appears again, the disk has too many bad spots and
- should be returned to the vendor for replacement.
- .TP
- ALREADY IN BAD SECTOR TABLE (ALTERNATE IS BAD!)
- .I Badm
- detected a failure in a sector that is already marked as being bad.
- This usually means that the alternate sector is failing as well; DEC
- standard 144 does not deal well with this situation.
- .TP
- Write pattern N = 0xV
- .I Badm
- is beginning pass
- .I N
- over the disk, writing pattern
- .I V
- in all sectors of the disk. (This message is informational only,
- and indicates no problem.)
- .TP
- snS: {soft (E), hard} read error
- .I Badm
- detected a soft ECC (with
- .I E
- corrections) or a hard read error while reading sector
- .IR S .
- When operating in
- .B w
- mode,
- .I badm
- attempts to classify any sector exhibiting a read error as a `bad' sector.
- This message is a normal consequence of the formating process.
- .TP
- WARNING: ECC COUNTS NOT AVAILABLE, LIMPING ALONG
- The UNIX driver for the disk does not support the
- .I ioctl
- call to return the number of soft ECC correction counts.
- The consequence of this is that
- .I badm
- cannot detect or act upon soft ECC errors on the disk.
- Consult a system programmer.
- .TP
- WARNING: CANNOT READ BAD SECTOR TABLE (snS)
- .I Badm
- cannot read the bad sector file from sector number
- .IR S .
- There are five identical copies of the bad sector file; if the first
- copy is unreadable,
- .I badm
- tries to read the other copies until it finds one that it can read.
- If none of the copies can be read, the disk should be completely
- reformated
- .RB ( badm
- .BR wbi ).
- .TP
- WARNING: Cannot inform driver of new bad sector table
- The UNIX driver for the disk does not support the
- .I ioctl
- call to update the in-core copy of the bad block table.
- Consult a system programmer.
- .TP
- Entry N: illegal disk address, cyl=X trksec=X
- The bad sector table on the disk contains a disk address that is
- not legal. The entry number (from 0 to 125) is displayed, along
- with the contents of the cylinder and track/sector fields.
- This can be corrected by completely reformating the disk
- .RB ( badm
- .BR wbi ).
- .TP
- Entry N: out of order
- Entries in the bad sector table on the disk must be appear in order
- of ascending disk addresses. Entry N in the bad sector table is
- out of order. This can be corrected by completely reformating the disk
- .RB ( badm
- .BR wbi ).
- .PP
- There are other, more self-explanatory diagnostics.
- .PP
- While
- .I badm
- is running, reports of hard and soft disk ECC errors may appear
- at the Vax console. These messages are normal; they indicate
- that bad sectors are being identified and dealt with by
- .IR badm .
- .SH BUGS
- .I Badm
- updates the bad sector table of the disk; this is technically a violation
- of DEC standard 144, which specifies that this information is recorded at
- the time of manufacture. In practice, however, there seem to be no
- operational problems incurred by updating the bad sector table in the field.
- .PP
- The implementation of the
- .B wb
- and
- .B wbi
- functions of
- .I badm
- requires support from the UNIX kernel in the form of additional
- .IR ioctl (2)
- services. These are currently available only for RM05, RP06, RP05,
- RP04, and Eagle disks.
- .SH SEE ALSO
- bad144(8), badsect(8), format(8V)
- .PP
- DEC Standard 144
- .PP
- DEC EK-ORM05-UG-002 RM05 Disk Subsystem User Guide
- .PP
- Emulex SC7851001 SC780 Disk Controller Technical Manual
- .SH AUTHOR
- .nf
- Rick Ace
- New York Institute of Technology
- Computer Graphics Laboratory
- Old Westbury, NY 11568
- .fi
- SHAR_EOF
- echo shar: extracting hp.diffs
- cat - << \SHAR_EOF > hp.diffs
- Modifications to 4.2bsd vaxmba/hp.c to support badm Rev 2.0.
-
- These changes apply to vaxmba/hp.c bearing the identification
- /* hp.c 6.2 83/09/25 */
-
- Comments in brackets have been added to line-number markers to
- help you locate the proper places to modify if your hp.c differs.
- --------------------------------------------------------------------------
- 36a37 [add file.h for symbol "FWRITE"]
- > #include "../h/file.h" /* BADM */
- 207a209 [add new element at end of "struct hpst"]
- > char vname[12]; /* BADM vendor's name for device */
- 209,222c211,224 [add vendor name string to hpst initializers]
- < { 32, 5, 32*5, 823, rm03_sizes, 3, 4 }, /* RM03 */
- < { 32, 19, 32*19, 823, rm05_sizes, 3, 4 }, /* RM05 */
- < { 22, 19, 22*19, 815, rp06_sizes, 3, 4 }, /* RP06 */
- < { 31, 14, 31*14, 559, rm80_sizes, 3, 4 }, /* RM80 */
- < { 22, 19, 22*19, 411, rp05_sizes, 3, 4 }, /* RP04 */
- < { 22, 19, 22*19, 411, rp05_sizes, 3, 4 }, /* RP05 */
- < { 50, 32, 50*32, 630, rp07_sizes, 7, 8 }, /* RP07 */
- < { 1, 1, 1, 1, 0, 0, 0 }, /* ML11A */
- < { 1, 1, 1, 1, 0, 0, 0 }, /* ML11B */
- < { 32, 40, 32*40, 843, cdc9775_sizes, 3, 4 }, /* 9775 */
- < { 32, 10, 32*10, 823, cdc9730_sizes, 3, 4 }, /* 9730 */
- < { 32, 16, 32*16, 1024, capricorn_sizes,7, 8 }, /* Capricorn */
- < { 48, 20, 48*20, 842, eagle_sizes, 7, 8 }, /* EAGLE */
- < { 32, 19, 32*19, 815, ampex_sizes, 3, 4 }, /* 9300 */
- ---
- > { 32, 5, 32*5, 823, rm03_sizes, 3, 4, "rm03" },
- > { 32, 19, 32*19, 823, rm05_sizes, 3, 4, "rm05" },
- > { 22, 19, 22*19, 815, rp06_sizes, 3, 4, "rp06" },
- > { 31, 14, 31*14, 559, rm80_sizes, 3, 4, "rm80" },
- > { 22, 19, 22*19, 411, rp05_sizes, 3, 4, "rp04" },
- > { 22, 19, 22*19, 411, rp05_sizes, 3, 4, "rp05" },
- > { 50, 32, 50*32, 630, rp07_sizes, 7, 8, "rp07" },
- > { 1, 1, 1, 1, 0, 0, 0, "ml11a" },
- > { 1, 1, 1, 1, 0, 0, 0, "ml11b" },
- > { 32, 40, 32*40, 843, cdc9775_sizes, 3, 4, "9775" },
- > { 32, 10, 32*10, 823, cdc9730_sizes, 3, 4, "9730" },
- > { 32, 16, 32*16, 1024, capricorn_sizes,7, 8, "capricorn" },
- > { 48, 20, 48*20, 842, eagle_sizes, 7, 8, "eagle" },
- > { 32, 19, 32*19, 815, ampex_sizes, 3, 4, "9300" },
- 241a244 [add new element at end of "struct hpsoftc"]
- > long sc_ecccnt; /* BADM ECC correction count */
- 730a734,737 [add automatic variables in hpioctl()]
- > register int unit = minor(dev) >> 3; /* BADM */
- > register struct iogstat *d; /* BADM */
- > struct mba_device *mi; /* BADM */
- > int ds; /* BADM */
- 737a745,767 [add new cases to switch in hpioctl()]
- > case DKIOGETECC: /* BADM */
- > *(long *)data = hpsoftc[unit].sc_ecccnt; /* BADM */
- > return 0; /* BADM */
- >
- > case DKIOGSTAT: /* BADM */
- > mi = hpinfo[unit]; /* BADM */
- > bzero(data, sizeof (struct iogstat)); /* BADM */
- > d = (struct iogstat *)data; /* BADM */
- > d->iogs_areasize = hpst[mi->mi_type].sizes[minor(dev)&7].nblocks; /* BADM */
- > bcopy(hpst[mi->mi_type].vname,d->iogs_vname,sizeof d->iogs_vname); /* BADM */
- > ds = ((struct hpdevice *)mi->mi_drv)->hpds; /* BADM */
- > if (ds & HPDS_MOL) /* BADM */
- > d->iogs_online++; /* BADM */
- > if (ds & HPDS_WRL) /* BADM */
- > d->iogs_writelock++; /* BADM */
- > return 0; /* BADM */
- >
- > case DKIONEWBAD: /* BADM */
- > if ((flag & FWRITE) == 0) /* BADM */
- > return EBADF; /* BADM */
- > hpsoftc[unit].sc_hpinit = 0; /* BADM */
- > return 0; /* BADM */
- >
- 791a822 [add to hpecc() after statement "bit -= 8;"]
- > hpsoftc[mi->mi_unit].sc_ecccnt++; /* BADM */
- 848c879 [repair bug in hpecc()]
- < mi->mi_tab.b_errcnt = 0; /* error has been corrected */
- ---
- > mi->mi_tab.b_errcnt--; /* error has been corrected */
- SHAR_EOF
- echo shar: extracting dkio.add
- cat - << \SHAR_EOF > dkio.add
- /*
- * Additions to vax/dkio.h to support "badm" disk formater
- */
-
- #define DKIOGSTAT _IOR(d, 2, struct iogstat) /* get device status */
- #define DKIOGETECC _IOR(d, 3, long) /* disk ECC count */
- #define DKIONEWBAD _IO(d, 4) /* new bad sec table */
-
- struct iogstat {
- long iogs_areasize; /* size of disk area (512-byte units) */
- char iogs_online; /* 0 = offline, non-zero = online */
- char iogs_writelock; /* non-zero = write locked */
- char iogs_vname[12]; /* null-terminated vendor device name */
- };
- SHAR_EOF
-
-
-