fdread.c revision 77729
176589Sjoerg/* 276589Sjoerg * Copyright (c) 2001 Joerg Wunsch 376589Sjoerg * 476589Sjoerg * All rights reserved. 576589Sjoerg * 676589Sjoerg * Redistribution and use in source and binary forms, with or without 776589Sjoerg * modification, are permitted provided that the following conditions 876589Sjoerg * are met: 976589Sjoerg * 1. Redistributions of source code must retain the above copyright 1076589Sjoerg * notice, this list of conditions and the following disclaimer. 1176589Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 1276589Sjoerg * notice, this list of conditions and the following disclaimer in the 1376589Sjoerg * documentation and/or other materials provided with the distribution. 1476589Sjoerg * 1576589Sjoerg * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR 1676589Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1776589Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1876589Sjoerg * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, 1976589Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2076589Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2176589Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2276589Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2376589Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2476589Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2576589Sjoerg * 2676589Sjoerg * $FreeBSD: head/usr.sbin/fdread/fdread.c 77729 2001-06-04 21:16:28Z joerg $ 2776589Sjoerg */ 2876589Sjoerg 2976589Sjoerg#include <sys/types.h> 3076589Sjoerg#include <sys/stat.h> 3176589Sjoerg 3276589Sjoerg#include <machine/ioctl_fd.h> 3376589Sjoerg 3476589Sjoerg#include <err.h> 3576589Sjoerg#include <errno.h> 3676589Sjoerg#include <fcntl.h> 3776589Sjoerg#include <paths.h> 3876589Sjoerg#include <stdio.h> 3976589Sjoerg#include <stdlib.h> 4076589Sjoerg#include <string.h> 4176589Sjoerg#include <sysexits.h> 4276589Sjoerg#include <unistd.h> 4376589Sjoerg 4477729Sjoerg#include <dev/ic/nec765.h> 4576589Sjoerg 4676589Sjoergint quiet, recover; 4776589Sjoergunsigned char fillbyte = 0xf0; /* "foo" */ 4876589Sjoerg 4976589Sjoergint doread(int fd, FILE *of, const char *devname); 5076589Sjoergvoid printstatus(struct fdc_status *fdcsp); 5176589Sjoergvoid usage(void); 5276589Sjoerg 5376589Sjoergvoid 5476589Sjoergusage(void) 5576589Sjoerg{ 5676589Sjoerg 5776589Sjoerg errx(EX_USAGE, 5876589Sjoerg "usage: fdread [-qr] [-d device] [-f fillbyte] [-o file]"); 5976589Sjoerg} 6076589Sjoerg 6176589Sjoerg 6276589Sjoergint 6376589Sjoergmain(int argc, char **argv) 6476589Sjoerg{ 6576589Sjoerg int c, errs = 0; 6676589Sjoerg const char *fname = 0, *devname = "/dev/fd0"; 6776589Sjoerg char *cp; 6876589Sjoerg FILE *of = stdout; 6976589Sjoerg int fd; 7076589Sjoerg unsigned long ul; 7176589Sjoerg 7276589Sjoerg while ((c = getopt(argc, argv, "d:f:o:qr")) != -1) 7376589Sjoerg switch (c) { 7476589Sjoerg case 'd': 7576589Sjoerg devname = optarg; 7676589Sjoerg break; 7776589Sjoerg 7876589Sjoerg case 'f': 7976589Sjoerg ul = strtoul(optarg, &cp, 0); 8076589Sjoerg if (*cp != '\0') { 8176589Sjoerg fprintf(stderr, 8276589Sjoerg "Bad argument %s to -f option; must be numeric\n", 8376589Sjoerg optarg); 8476589Sjoerg usage(); 8576589Sjoerg } 8676589Sjoerg if (ul > 0xff) 8776589Sjoerg warnx( 8876589Sjoerg "Warning: fillbyte %#lx too large, truncating\n", 8976589Sjoerg ul); 9076589Sjoerg fillbyte = ul & 0xff; 9176589Sjoerg break; 9276589Sjoerg 9376589Sjoerg case 'o': 9476589Sjoerg fname = optarg; 9576589Sjoerg break; 9676589Sjoerg 9776589Sjoerg case 'q': 9876589Sjoerg quiet++; 9976589Sjoerg break; 10076589Sjoerg 10176589Sjoerg case 'r': 10276589Sjoerg recover++; 10376589Sjoerg break; 10476589Sjoerg 10576589Sjoerg default: 10676589Sjoerg errs++; 10776589Sjoerg } 10876589Sjoerg argc -= optind; 10976589Sjoerg argv += optind; 11076589Sjoerg 11176589Sjoerg if (argc != 0 || errs) 11276589Sjoerg usage(); 11376589Sjoerg 11476589Sjoerg if (fname) { 11576589Sjoerg if ((of = fopen(fname, "w")) == NULL) 11676589Sjoerg err(EX_OSERR, "cannot create output file %s", fname); 11776589Sjoerg } 11876589Sjoerg 11976589Sjoerg if ((fd = open(devname, O_RDONLY)) == -1) 12076589Sjoerg err(EX_OSERR, "cannot open device %s", devname); 12176589Sjoerg 12276589Sjoerg return (doread(fd, of, devname)); 12376589Sjoerg} 12476589Sjoerg 12576589Sjoergint 12676589Sjoergdoread(int fd, FILE *of, const char *devname) 12776589Sjoerg{ 12876589Sjoerg char *trackbuf; 12976589Sjoerg int rv, fdopts, recoverable, nerrs = 0; 13076589Sjoerg unsigned int nbytes, tracksize, mediasize, secsize, n; 13176589Sjoerg struct fdc_status fdcs; 13276589Sjoerg struct fd_type fdt; 13376589Sjoerg 13476589Sjoerg if (ioctl(fd, FD_GTYPE, &fdt) == -1) 13576589Sjoerg err(EX_OSERR, "ioctl(FD_GTYPE) failed -- not a floppy?"); 13676589Sjoerg fdopts = FDOPT_NOERRLOG; 13776589Sjoerg if (ioctl(fd, FD_SOPTS, &fdopts) == -1) 13876589Sjoerg err(EX_OSERR, "ioctl(FD_SOPTS, FDOPT_NOERRLOG)"); 13976589Sjoerg 14076589Sjoerg secsize = 128 << fdt.secsize; 14176589Sjoerg tracksize = fdt.sectrac * secsize; 14276589Sjoerg mediasize = tracksize * fdt.tracks * fdt.heads; 14376589Sjoerg if ((trackbuf = malloc(tracksize)) == 0) 14476589Sjoerg errx(EX_TEMPFAIL, "out of memory"); 14576589Sjoerg 14676589Sjoerg if (!quiet) 14776589Sjoerg fprintf(stderr, "Reading %d * %d * %d * %d medium at %s\n", 14876589Sjoerg fdt.tracks, fdt.heads, fdt.sectrac, secsize, devname); 14976589Sjoerg 15076589Sjoerg for (nbytes = 0; nbytes < mediasize;) { 15176589Sjoerg if (lseek(fd, nbytes, SEEK_SET) != nbytes) 15276589Sjoerg err(EX_OSERR, "cannot lseek()"); 15376589Sjoerg rv = read(fd, trackbuf, tracksize); 15476589Sjoerg if (rv == 0) { 15576589Sjoerg /* EOF? */ 15676589Sjoerg warnx("premature EOF after %u bytes", nbytes); 15776589Sjoerg return (EX_OK); 15876589Sjoerg } 15976589Sjoerg if (rv == tracksize) { 16076589Sjoerg nbytes += rv; 16176589Sjoerg if (!quiet) 16276589Sjoerg fprintf(stderr, "%5d KB\r", nbytes / 1024); 16376589Sjoerg fwrite(trackbuf, sizeof(unsigned char), rv, of); 16476589Sjoerg fflush(of); 16576589Sjoerg continue; 16676589Sjoerg } 16776589Sjoerg if (rv < tracksize) { 16876589Sjoerg /* should not happen */ 16976589Sjoerg nbytes += rv; 17076589Sjoerg if (!quiet) 17176589Sjoerg fprintf(stderr, "\nshort after %5d KB\r", 17276589Sjoerg nbytes / 1024); 17376589Sjoerg fwrite(trackbuf, sizeof(unsigned char), rv, of); 17476589Sjoerg fflush(of); 17576589Sjoerg continue; 17676589Sjoerg } 17776589Sjoerg if (rv == -1) { 17876589Sjoerg /* fall back reading one sector at a time */ 17976589Sjoerg for (n = 0; n < tracksize; n += secsize) { 18076589Sjoerg if (lseek(fd, nbytes, SEEK_SET) != nbytes) 18176589Sjoerg err(EX_OSERR, "cannot lseek()"); 18276589Sjoerg rv = read(fd, trackbuf, secsize); 18376589Sjoerg if (rv == secsize) { 18476589Sjoerg nbytes += rv; 18576589Sjoerg if (!quiet) 18676589Sjoerg fprintf(stderr, "%5d KB\r", 18776589Sjoerg nbytes / 1024); 18876589Sjoerg fwrite(trackbuf, sizeof(unsigned char), 18976589Sjoerg rv, of); 19076589Sjoerg fflush(of); 19176589Sjoerg continue; 19276589Sjoerg } 19376589Sjoerg if (rv == -1) { 19476589Sjoerg if (errno != EIO) { 19576589Sjoerg if (!quiet) 19676589Sjoerg putc('\n', stderr); 19776589Sjoerg perror("non-IO error"); 19876589Sjoerg return (EX_OSERR); 19976589Sjoerg } 20076589Sjoerg if (ioctl(fd, FD_GSTAT, &fdcs) == -1) 20176589Sjoerg errx(EX_IOERR, 20276589Sjoerg "floppy IO error, but no FDC status"); 20376589Sjoerg nerrs++; 20476589Sjoerg recoverable = fdcs.status[2] & 20576589Sjoerg NE7_ST2_DD; 20676589Sjoerg if (!quiet) { 20776589Sjoerg printstatus(&fdcs); 20876589Sjoerg fputs(" (", stderr); 20976589Sjoerg if (!recoverable) 21076589Sjoerg fputs("not ", stderr); 21176589Sjoerg fputs("recoverable)", stderr); 21276589Sjoerg } 21376589Sjoerg if (!recover) { 21476589Sjoerg if (!quiet) 21576589Sjoerg putc('\n', stderr); 21676589Sjoerg return (EX_IOERR); 21776589Sjoerg } 21876589Sjoerg memset(trackbuf, fillbyte, secsize); 21976589Sjoerg if (recoverable) { 22076589Sjoerg fdopts |= FDOPT_NOERROR; 22176589Sjoerg if (ioctl(fd, FD_SOPTS, 22276589Sjoerg &fdopts) == -1) 22376589Sjoerg err(EX_OSERR, 22476589Sjoerg "ioctl(fd, FD_SOPTS, FDOPT_NOERROR)"); 22576589Sjoerg rv = read(fd, trackbuf, 22676589Sjoerg secsize); 22776589Sjoerg if (rv != secsize) 22876589Sjoerg err(EX_IOERR, 22976589Sjoerg "read() with FDOPT_NOERROR still fails"); 23076589Sjoerg fdopts &= ~FDOPT_NOERROR; 23176589Sjoerg (void)ioctl(fd, FD_SOPTS, 23276589Sjoerg &fdopts); 23376589Sjoerg } 23476589Sjoerg if (!quiet) { 23576589Sjoerg if (recoverable) 23676589Sjoerg fprintf(stderr, 23776589Sjoerg ": recovered"); 23876589Sjoerg else 23976589Sjoerg fprintf(stderr, 24076589Sjoerg ": dummy"); 24176589Sjoerg fprintf(stderr, 24276589Sjoerg " data @ %#x ... %#x\n", 24376589Sjoerg nbytes, 24476589Sjoerg nbytes + secsize - 1); 24576589Sjoerg } 24676589Sjoerg nbytes += secsize; 24776589Sjoerg fwrite(trackbuf, sizeof(unsigned char), 24876589Sjoerg secsize, of); 24976589Sjoerg fflush(of); 25076589Sjoerg continue; 25176589Sjoerg } 25276589Sjoerg errx(EX_OSERR, "unexpected read() result: %d", 25376589Sjoerg rv); 25476589Sjoerg } 25576589Sjoerg } 25676589Sjoerg } 25776589Sjoerg if (!quiet) { 25876589Sjoerg putc('\n', stderr); 25976589Sjoerg if (nerrs) 26076589Sjoerg fprintf(stderr, "%d error%s\n", 26176589Sjoerg nerrs, nerrs > 1? "s": ""); 26276589Sjoerg } 26376589Sjoerg 26476589Sjoerg return (nerrs? EX_IOERR: EX_OK); 26576589Sjoerg} 26676589Sjoerg 26776589Sjoergvoid 26876589Sjoergprintstatus(struct fdc_status *fdcsp) 26976589Sjoerg{ 27076589Sjoerg char msgbuf[100]; 27176589Sjoerg 27276589Sjoerg fprintf(stderr, 27376589Sjoerg "\nFDC status ST0=%#x ST1=%#x ST2=%#x C=%u H=%u R=%u N=%u:\n", 27476589Sjoerg fdcsp->status[0] & 0xff, 27576589Sjoerg fdcsp->status[1] & 0xff, 27676589Sjoerg fdcsp->status[2] & 0xff, 27776589Sjoerg fdcsp->status[3] & 0xff, 27876589Sjoerg fdcsp->status[4] & 0xff, 27976589Sjoerg fdcsp->status[5] & 0xff, 28076589Sjoerg fdcsp->status[6] & 0xff); 28176589Sjoerg 28276589Sjoerg if ((fdcsp->status[0] & NE7_ST0_IC_RC) != NE7_ST0_IC_AT) { 28376589Sjoerg sprintf(msgbuf, "unexcpted interrupt code %#x", 28476589Sjoerg fdcsp->status[0] & NE7_ST0_IC_RC); 28576589Sjoerg } else { 28676589Sjoerg strcpy(msgbuf, "unexpected error code in ST1/ST2"); 28776589Sjoerg 28876589Sjoerg if (fdcsp->status[1] & NE7_ST1_EN) 28976589Sjoerg strcpy(msgbuf, "end of cylinder (wrong format)"); 29076589Sjoerg else if (fdcsp->status[1] & NE7_ST1_DE) { 29176589Sjoerg if (fdcsp->status[2] & NE7_ST2_DD) 29276589Sjoerg strcpy(msgbuf, "CRC error in data field"); 29376589Sjoerg else 29476589Sjoerg strcpy(msgbuf, "CRC error in ID field"); 29576589Sjoerg } else if (fdcsp->status[1] & NE7_ST1_MA) { 29676589Sjoerg if (fdcsp->status[2] & NE7_ST2_MD) 29776589Sjoerg strcpy(msgbuf, "no address mark in data field"); 29876589Sjoerg else 29976589Sjoerg strcpy(msgbuf, "no address mark in ID field"); 30076589Sjoerg } else if (fdcsp->status[2] & NE7_ST2_WC) 30176589Sjoerg strcpy(msgbuf, "wrong cylinder (format mismatch)"); 30276589Sjoerg else if (fdcsp->status[1] & NE7_ST1_ND) 30376589Sjoerg strcpy(msgbuf, "no data (sector not found)"); 30476589Sjoerg } 30576589Sjoerg fputs(msgbuf, stderr); 30676589Sjoerg} 307