diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/fdcontrol/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/fdcontrol/fdcontrol.c | 206 | ||||
-rw-r--r-- | usr.sbin/fdformat/fdformat.c | 297 | ||||
-rw-r--r-- | usr.sbin/fdread/fdutil.c | 392 | ||||
-rw-r--r-- | usr.sbin/fdread/fdutil.h | 8 |
5 files changed, 663 insertions, 244 deletions
diff --git a/usr.sbin/fdcontrol/Makefile b/usr.sbin/fdcontrol/Makefile index ec411d7a48a0..38f9a1ed3bb0 100644 --- a/usr.sbin/fdcontrol/Makefile +++ b/usr.sbin/fdcontrol/Makefile @@ -1,8 +1,12 @@ # $FreeBSD$ +.PATH: ${.CURDIR}/../fdread + PROG= fdcontrol +SRCS= fdcontrol.c fdutil.c MAN= fdcontrol.8 WARNS?= 2 +CFLAGS+= -I${.CURDIR}/../fdread .include <bsd.prog.mk> diff --git a/usr.sbin/fdcontrol/fdcontrol.c b/usr.sbin/fdcontrol/fdcontrol.c index e1200592a2b5..9d447a5447a6 100644 --- a/usr.sbin/fdcontrol/fdcontrol.c +++ b/usr.sbin/fdcontrol/fdcontrol.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1994 by Joerg Wunsch, Dresden + * Copyright (C) 1994, 2001 by Joerg Wunsch, Dresden * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,110 +36,144 @@ static const char rcsid[] = #include <err.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <sysexits.h> #include <unistd.h> -static int getnumber(void); -static void usage(void); +#include "fdutil.h" -static int -getnumber(void) -{ - int i; - char b[80]; - fgets(b, 80, stdin); - if(b[0] == '\n') return -1; +static int debug = -1, format, verbose, show = 1, showfmt; +static char *fmtstring; - sscanf(b, " %i", &i); - return i; -} +static void showdev(enum fd_drivetype, const char *); +static void usage(void); static void usage(void) { - fprintf(stderr, "usage: fdcontrol [-d 0|1] | [-s] device-node\n"); - exit(2); + errx(EX_USAGE, + "usage: fdcontrol [-F] [-d dbg] [-f fmt] [-s fmtstr] [-v] device"); } +void +showdev(enum fd_drivetype type, const char *fname) +{ + const char *name, *descr; -#define ask(name, fmt) \ -printf(#name "? [" fmt "]: ", ft.name); fflush(stdout); \ -if((i = getnumber()) != -1) ft.name = i + getname(type, &name, &descr); + if (verbose) + printf("%s: %s drive (%s)\n", fname, name, descr); + else + printf("%s\n", name); +} int main(int argc, char **argv) { - struct fd_type ft; - int fd, i; - int debug = -1, settype = 1; - - while((i = getopt(argc, argv, "d:s")) != -1) - switch(i) - { - case 'd': - debug = atoi(optarg); - settype = 0; - break; - - case 's': - debug = -1; - settype = 1; - break; - - case '?': - default: - usage(); - } - - argc -= optind; - argv += optind; - - if(argc != 1) - usage(); - - if((fd = open(argv[0], 0)) < 0) - { - warn("open(floppy)"); - return 1; - } - - if(debug != -1) - { - if(ioctl(fd, FD_DEBUG, &debug) < 0) - { - warn("ioctl(FD_DEBUG)"); - return 1; + enum fd_drivetype type; + struct fd_type ft, newft, *fdtp; + const char *name, *descr; + int fd, i, mode; + + while((i = getopt(argc, argv, "d:Ff:s:v")) != -1) + switch(i) { + case 'd': + if (strcmp(optarg, "0") == 0) + debug = 0; + else if (strcmp(optarg, "1") == 0) + debug = 1; + else + usage(); + show = 0; + break; + + case 'F': + showfmt = 1; + show = 0; + break; + + case 'f': + if (getnum(optarg, &format)) { + fprintf(stderr, + "Bad argument %s to -f option; must be numeric\n", + optarg); + usage(); + } + show = 0; + break; + + case 's': + fmtstring = optarg; + show = 0; + break; + + case 'v': + verbose++; + break; + + default: + usage(); + } + + argc -= optind; + argv += optind; + + if(argc != 1) + usage(); + + if (show || showfmt) + mode = O_RDONLY | O_NONBLOCK; + else + mode = O_RDWR; + + if((fd = open(argv[0], mode)) < 0) + err(EX_UNAVAILABLE, "open(%s)", argv[0]); + + if (ioctl(fd, FD_GDTYPE, &type) == -1) + err(EX_OSERR, "ioctl(FD_GDTYPE)"); + if (ioctl(fd, FD_GTYPE, &ft) == -1) + err(EX_OSERR, "ioctl(FD_GTYPE)"); + + if (show) { + showdev(type, argv[0]); + return (0); } - return 0; - } - - if(settype) - { - if(ioctl(fd, FD_GTYPE, &ft) < 0) - { - warn("ioctl(FD_GTYPE)"); - return 1; + + if (format) { + getname(type, &name, &descr); + fdtp = get_fmt(format, type); + if (fdtp == 0) + errx(EX_USAGE, + "unknown format %d KB for drive type %s", + format, name); + ft = *fdtp; + } + + if (fmtstring) { + parse_fmt(fmtstring, type, ft, &newft); + ft = newft; + } + + if (showfmt) { + if (verbose) + printf("%s: %d KB media type, fmt = ", + argv[0], ft.size / 2); + print_fmt(ft); + return (0); + } + + if (format || fmtstring) { + if (ioctl(fd, FD_STYPE, &ft) == -1) + err(EX_OSERR, "ioctl(FD_STYPE)"); + return (0); } - ask(sectrac, "%d"); - ask(secsize, "%d"); - ask(datalen, "0x%x"); - ask(gap, "0x%x"); - ask(tracks, "%d"); - ask(size, "%d"); - ask(steptrac, "%d"); - ask(trans, "%d"); - ask(heads, "%d"); - ask(f_gap, "0x%x"); - ask(f_inter, "%d"); - - if(ioctl(fd, FD_STYPE, &ft) < 0) - { - warn("ioctl(FD_STYPE)"); - return 1; + if (debug != -1) { + if (ioctl(fd, FD_DEBUG, &debug) == -1) + err(EX_OSERR, "ioctl(FD_DEBUG)"); + return (0); } - return 0; - } - return 0; + return 0; } diff --git a/usr.sbin/fdformat/fdformat.c b/usr.sbin/fdformat/fdformat.c index 0c194b3e0817..0e037b4fec0c 100644 --- a/usr.sbin/fdformat/fdformat.c +++ b/usr.sbin/fdformat/fdformat.c @@ -26,19 +26,9 @@ * $FreeBSD$ */ -/* - * FreeBSD: - * format a floppy disk - * - * Added FD_GTYPE ioctl, verifying, proportional indicators. - * Serge Vakulenko, vak@zebub.msk.su - * Sat Dec 18 17:45:47 MSK 1993 - * - * Final adaptation, change format/verify logic, add separate - * format gap/interleave values - * Andrew A. Chernov, ache@astral.msk.su - * Thu Jan 27 00:47:24 MSK 1994 - */ +#include <sys/types.h> +#include <sys/fdcio.h> +#include <sys/stat.h> #include <ctype.h> #include <err.h> @@ -48,24 +38,24 @@ #include <stdio.h> #include <stdlib.h> #include <strings.h> +#include <sysexits.h> #include <unistd.h> -#include <sys/fdcio.h> - #include "fdutil.h" static void format_track(int fd, int cyl, int secs, int head, int rate, - int gaplen, int secsize, int fill,int interleave) + int gaplen, int secsize, int fill, int interleave, + int offset) { struct fd_formb f; - register int i,j; - int il[FD_MAX_NSEC + 1]; + int i, j, il[FD_MAX_NSEC + 1]; - memset(il,0,sizeof il); - for(j = 0, i = 1; i <= secs; i++) { - while(il[(j%secs)+1]) j++; - il[(j%secs)+1] = i; + memset(il, 0, sizeof il); + for(j = 0, i = 1 + offset; i <= secs + offset; i++) { + while(il[(j % secs) + 1]) + j++; + il[(j % secs) + 1] = i; j += interleave; } @@ -85,14 +75,14 @@ format_track(int fd, int cyl, int secs, int head, int rate, f.fd_formb_secsize(i) = secsize; } if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) - err(1, "ioctl(FD_FORM)"); + err(EX_OSERR, "ioctl(FD_FORM)"); } static int verify_track(int fd, int track, int tracksize) { - static char *buf = 0; - static int bufsz = 0; + static char *buf; + static int bufsz; int fdopts = -1, ofdopts, rv = 0; if (ioctl(fd, FD_GOPTS, &fdopts) < 0) @@ -103,61 +93,37 @@ verify_track(int fd, int track, int tracksize) (void)ioctl(fd, FD_SOPTS, &fdopts); } - if (bufsz < tracksize) { - if (buf) - free (buf); - bufsz = tracksize; - buf = 0; - } - if (! buf) - buf = malloc (bufsz); - if (! buf) - errx(2, "out of memory"); - if (lseek (fd, (long) track*tracksize, 0) < 0) + if (bufsz < tracksize) + buf = realloc(buf, bufsz = tracksize); + if (buf == 0) + errx(EX_UNAVAILABLE, "out of memory"); + if (lseek (fd, (long) track * tracksize, 0) < 0) rv = -1; /* try twice reading it, without using the normal retrier */ else if (read (fd, buf, tracksize) != tracksize && read (fd, buf, tracksize) != tracksize) rv = -1; - if(fdopts != -1) + if (fdopts != -1) (void)ioctl(fd, FD_SOPTS, &ofdopts); return (rv); } -static const char * -makename(const char *arg, const char *suffix) -{ - static char namebuff[20]; /* big enough for "/dev/fd0a"... */ - - memset(namebuff, 0, 20); - if(*arg == '\0') /* ??? */ - return arg; - if(*arg == '/') /* do not convert absolute pathnames */ - return arg; - strcpy(namebuff, _PATH_DEV); - strncat(namebuff, arg, 3); - strcat(namebuff, suffix); - return namebuff; -} - static void usage (void) { - fprintf(stderr, "%s\n%s\n", - "usage: fdformat [-y] [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]", - " [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] device_name"); - exit(2); + errx(EX_USAGE, + "usage: fdformat [-F fill] [-f fmt] [-s fmtstr] [-nqvy] device"); } static int yes (void) { - char reply [256], *p; + char reply[256], *p; - reply[sizeof(reply)-1] = 0; + reply[sizeof(reply) - 1] = 0; for (;;) { fflush(stdout); - if (! fgets (reply, sizeof(reply)-1, stdin)) + if (!fgets (reply, sizeof(reply) - 1, stdin)) return (0); for (p=reply; *p==' ' || *p=='\t'; ++p) continue; @@ -172,129 +138,149 @@ yes (void) int main(int argc, char **argv) { - int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1; - int rate = -1, gaplen = -1, secsize = -1, steps = -1; - int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0, confirm = 0; - int fd, c, i, track, error, tracks_per_dot, bytes_per_track, errs; - int fdopts; - const char *device, *suffix; - struct fd_type fdt; + enum fd_drivetype type; + struct fd_type fdt, newft, *fdtp; + struct stat sb; #define MAXPRINTERRS 10 struct fdc_status fdcs[MAXPRINTERRS]; + int format, fill, quiet, verify, verify_only, confirm; + int fd, c, i, track, error, tracks_per_dot, bytes_per_track, errs; + int fdopts, flags; + char *fmtstring, *device; + const char *name, *descr; - while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qyvn")) != -1) - switch(c) { - case 'f': /* format in kilobytes */ - format = atoi(optarg); - break; - - case 'c': /* # of cyls */ - cyls = atoi(optarg); - break; - - case 's': /* # of secs per track */ - secs = atoi(optarg); - break; - - case 'h': /* # of heads */ - heads = atoi(optarg); - break; - - case 'r': /* transfer rate, kilobyte/sec */ - rate = atoi(optarg); - break; - - case 'g': /* length of GAP3 to format with */ - gaplen = atoi(optarg); - break; - - case 'S': /* sector size shift factor (1 << S)*128 */ - secsize = atoi(optarg); - break; + format = quiet = verify_only = confirm = 0; + verify = 1; + fill = 0xf6; + fmtstring = 0; - case 'F': /* fill byte, C-like notation allowed */ - fill = (int)strtol(optarg, (char **)0, 0); + while((c = getopt(argc, argv, "F:f:nqs:vy")) != -1) + switch(c) { + case 'F': /* fill byte */ + if (getnum(optarg, &fill)) { + fprintf(stderr, + "Bad argument %s to -F option; must be numeric\n", + optarg); + usage(); + } break; - case 't': /* steps per track */ - steps = atoi(optarg); + case 'f': /* format in kilobytes */ + if (getnum(optarg, &format)) { + fprintf(stderr, + "Bad argument %s to -f option; must be numeric\n", + optarg); + usage(); + } break; - case 'i': /* interleave factor */ - intleave = atoi(optarg); + case 'n': /* don't verify */ + verify = 0; break; - case 'q': + case 'q': /* quiet */ quiet = 1; break; - case 'y': - confirm = 1; + case 's': /* format string with detailed options */ + fmtstring = optarg; break; - case 'n': - verify = 0; - break; - - case 'v': + case 'v': /* verify only */ verify = 1; verify_only = 1; break; - case '?': default: + case 'y': /* confirm */ + confirm = 1; + break; + + default: usage(); } if(optind != argc - 1) usage(); - switch(format) { - default: - errx(2, "bad floppy size: %dK", format); - case -1: suffix = ""; break; - case 360: suffix = ".360"; break; - case 640: suffix = ".640"; break; - case 720: suffix = ".720"; break; - case 800: suffix = ".800"; break; - case 820: suffix = ".820"; break; - case 1200: suffix = ".1200"; break; - case 1232: suffix = ".1232"; break; - case 1440: suffix = ".1440"; break; - case 1480: suffix = ".1480"; break; - case 1720: suffix = ".1720"; break; + if (stat(argv[optind], &sb) == -1 && errno == ENOENT) { + /* try prepending _PATH_DEV */ + device = malloc(strlen(argv[optind] + sizeof _PATH_DEV + 1)); + if (device == 0) + errx(EX_UNAVAILABLE, "out of memory"); + strcpy(device, _PATH_DEV); + strcat(device, argv[optind]); + if (stat(device, &sb) == -1) { + free(device); + device = argv[optind]; /* let it fail below */ + } + } else { + device = argv[optind]; } - device = makename(argv[optind], suffix); - - if((fd = open(device, O_RDWR)) < 0) - err(1, "%s", device); + if ((fd = open(device, O_RDWR | O_NONBLOCK)) < 0) + err(EX_OSERR, "open(%s)", device); + /* + * Device initialization. + * + * First, get the device type descriptor. This tells us about + * the media geometry data we need to format a medium. It also + * lets us know quickly whether the device name actually points + * to a floppy disk drive. + * + * Then, obtain any drive options. We're mainly interested to + * see whether we're currently working on a device with media + * density autoselection (FDOPT_AUTOSEL). Then, we add the + * device option to tell the kernel not to log media errors, + * since we can handle them ourselves. If the device does + * media density autoselection, we then need to set the device + * type appropriately, since by opening with O_NONBLOCK we + * told the driver to bypass media autoselection (otherwise we + * wouldn't stand a chance to format an unformatted or damaged + * medium). We do not attempt to set the media type on any + * other devices since this is a privileged operation. For the + * same reason, specifying -f and -s options is only possible + * for autoselecting devices. + * + * Finally, we are ready to turn off O_NONBLOCK, and start to + * actually format something. + */ if(ioctl(fd, FD_GTYPE, &fdt) < 0) - errx(1, "not a floppy disk: %s", device); - fdopts = FDOPT_NOERRLOG; + errx(EX_OSERR, "not a floppy disk: %s", device); + if (ioctl(fd, FD_GDTYPE, &type) == -1) + err(EX_OSERR, "ioctl(FD_GDTYPE)"); + if (ioctl(fd, FD_GOPTS, &fdopts) == -1) + err(EX_OSERR, "ioctl(FD_GOPTS)"); + fdopts |= FDOPT_NOERRLOG; if (ioctl(fd, FD_SOPTS, &fdopts) == -1) - err(1, "ioctl(FD_SOPTS, FDOPT_NOERRLOG)"); - - switch(rate) { - case -1: break; - case 250: fdt.trans = FDC_250KBPS; break; - case 300: fdt.trans = FDC_300KBPS; break; - case 500: fdt.trans = FDC_500KBPS; break; - default: - errx(2, "invalid transfer rate: %d", rate); + err(EX_OSERR, "ioctl(FD_SOPTS, FDOPT_NOERRLOG)"); + if (format) { + getname(type, &name, &descr); + fdtp = get_fmt(format, type); + if (fdtp == 0) + errx(EX_USAGE, + "unknown format %d KB for drive type %s", + format, name); + fdt = *fdtp; } + if (fmtstring) { + parse_fmt(fmtstring, type, fdt, &newft); + fdt = newft; + } + if (fdopts & FDOPT_AUTOSEL) { + if (ioctl(fd, FD_STYPE, &fdt) < 0) + err(EX_OSERR, "ioctl(FD_STYPE)"); + } else if (fmtstring || format) { + errx(EX_USAGE, + "-f fmt or -s fmtstr is only allowed for autoselecting devices"); + } + if ((flags = fcntl(fd, F_GETFL, 0)) == -1) + err(EX_OSERR, "fcntl(F_GETFL)"); + flags &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) == -1) + err(EX_OSERR, "fcntl(F_SETFL)"); - if (cyls >= 0) fdt.tracks = cyls; - if (secs >= 0) fdt.sectrac = secs; - if (fdt.sectrac > FD_MAX_NSEC) - errx(2, "too many sectors per track, max value is %d", FD_MAX_NSEC); - if (heads >= 0) fdt.heads = heads; - if (gaplen >= 0) fdt.f_gap = gaplen; - if (secsize >= 0) fdt.secsize = secsize; - if (steps >= 0) fdt.steptrac = steps; - if (intleave >= 0) fdt.f_inter = intleave; - - bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; + bytes_per_track = fdt.sectrac * (128 << fdt.secsize); /* XXX 20/40 = 0.5 */ tracks_per_dot = (fdt.tracks * fdt.heads + 20) / 40; @@ -309,9 +295,9 @@ main(int argc, char **argv) printf("Format %dK floppy `%s'? (y/n): ", fdt.tracks * fdt.heads * bytes_per_track / 1024, device); - if(! yes ()) { + if(!yes()) { printf("Not confirmed.\n"); - return 3; + return (EX_UNAVAILABLE); } } @@ -332,7 +318,8 @@ main(int argc, char **argv) if (!verify_only) { format_track(fd, track / fdt.heads, fdt.sectrac, track % fdt.heads, fdt.trans, fdt.f_gap, - fdt.secsize, fill, fdt.f_inter); + fdt.secsize, fill, fdt.f_inter, + track % fdt.heads? fdt.offset_side2: 0); if(!quiet && !((track + 1) % tracks_per_dot)) { putchar('F'); fflush(stdout); @@ -344,7 +331,7 @@ main(int argc, char **argv) if (errs < MAXPRINTERRS && errno == EIO) { if (ioctl(fd, FD_GSTAT, fdcs + errs) == -1) - errx(1, + errx(EX_IOERR, "floppy IO error, but no FDC status"); errs++; } diff --git a/usr.sbin/fdread/fdutil.c b/usr.sbin/fdread/fdutil.c index fb61b30a0bf9..9990790bcc82 100644 --- a/usr.sbin/fdread/fdutil.c +++ b/usr.sbin/fdread/fdutil.c @@ -26,16 +26,23 @@ * $FreeBSD$ */ -#include <sys/types.h> +#include <dev/ic/nec765.h> + #include <sys/fdcio.h> +#include <err.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> - -#include <dev/ic/nec765.h> +#include <sysexits.h> #include "fdutil.h" +/* + * Decode the FDC status pointed to by `fdcsp', and print a textual + * translation to stderr. If `terse' is false, the numerical FDC + * register status is printed, too. + */ void printstatus(struct fdc_status *fdcsp, int terse) { @@ -78,3 +85,382 @@ printstatus(struct fdc_status *fdcsp, int terse) fputs(msgbuf, stderr); } +static struct fd_type fd_types_288m[] = +{ +#if 0 +{ 36,2,0xFF,0x1B,80,5760,FDC_1MBPS, 2,0x4C,1,1,FL_MFM|FL_PERPND } /*2.88M*/ +#endif +{ 21,2,0xFF,0x04,82,3444,FDC_500KBPS,2,0x0C,2,0,FL_MFM }, /* 1.72M */ +{ 18,2,0xFF,0x1B,82,2952,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.48M */ +{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.44M */ +{ 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* 1.2M */ +{ 10,2,0xFF,0x10,82,1640,FDC_250KBPS,2,0x2E,1,0,FL_MFM }, /* 820K */ +{ 10,2,0xFF,0x10,80,1600,FDC_250KBPS,2,0x2E,1,0,FL_MFM }, /* 800K */ +{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */ +}; + +static struct fd_type fd_types_144m[] = +{ +{ 21,2,0xFF,0x04,82,3444,FDC_500KBPS,2,0x0C,2,0,FL_MFM }, /* 1.72M */ +{ 18,2,0xFF,0x1B,82,2952,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.48M */ +{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.44M */ +{ 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* 1.2M */ +{ 10,2,0xFF,0x10,82,1640,FDC_250KBPS,2,0x2E,1,0,FL_MFM }, /* 820K */ +{ 10,2,0xFF,0x10,80,1600,FDC_250KBPS,2,0x2E,1,0,FL_MFM }, /* 800K */ +{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */ +}; + +static struct fd_type fd_types_12m[] = +{ +{ 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* 1.2M */ +{ 8,3,0xFF,0x35,77,1232,FDC_500KBPS,2,0x74,1,0,FL_MFM }, /* 1.23M */ +{ 18,2,0xFF,0x02,82,2952,FDC_500KBPS,2,0x02,2,0,FL_MFM }, /* 1.48M */ +{ 18,2,0xFF,0x02,80,2880,FDC_500KBPS,2,0x02,2,0,FL_MFM }, /* 1.44M */ +{ 10,2,0xFF,0x10,82,1640,FDC_300KBPS,2,0x2E,1,0,FL_MFM }, /* 820K */ +{ 10,2,0xFF,0x10,80,1600,FDC_300KBPS,2,0x2E,1,0,FL_MFM }, /* 800K */ +{ 9,2,0xFF,0x20,80,1440,FDC_300KBPS,2,0x50,1,0,FL_MFM }, /* 720K */ +{ 9,2,0xFF,0x23,40, 720,FDC_300KBPS,2,0x50,1,0,FL_MFM|FL_2STEP }, /* 360K */ +{ 8,2,0xFF,0x2A,80,1280,FDC_300KBPS,2,0x50,1,0,FL_MFM }, /* 640K */ +}; + +static struct fd_type fd_types_720k[] = +{ +{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */ +}; + +static struct fd_type fd_types_360k[] = +{ +{ 9,2,0xFF,0x2A,40, 720,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 360K */ +}; + +/* + * Parse a format string, and fill in the parameter pointed to by `out'. + * + * sectrac,secsize,datalen,gap,ncyls,speed,heads,f_gap,f_inter,offs2,flags[...] + * + * sectrac = sectors per track + * secsize = sector size in bytes + * datalen = length of sector if secsize == 128 + * gap = gap length when reading + * ncyls = number of cylinders + * speed = transfer speed 250/300/500/1000 KB/s + * heads = number of heads + * f_gap = gap length when formatting + * f_inter = sector interleave when formatting + * offs2 = offset of sectors on side 2 + * flags = +/-mfm | +/-2step | +/-perpend + * mfm - use MFM recording + * 2step - use 2 steps between cylinders + * perpend - user perpendicular (vertical) recording + * + * Any omitted value will be passed on from parameter `in'. + */ +void +parse_fmt(const char *s, enum fd_drivetype type, + struct fd_type in, struct fd_type *out) +{ + int i, j; + const char *cp; + char *s1; + + *out = in; + + for (i = 0;; i++) { + if (s == 0) + break; + + if ((cp = strchr(s, ',')) == 0) { + s1 = strdup(s); + if (s1 == NULL) + abort(); + s = 0; + } else { + s1 = malloc(cp - s + 1); + if (s1 == NULL) + abort(); + memcpy(s1, s, cp - s); + s1[cp - s] = 0; + + s = cp + 1; + } + if (strlen(s1) == 0) { + free(s1); + continue; + } + + switch (i) { + case 0: /* sectrac */ + if (getnum(s1, &out->sectrac)) + errx(EX_USAGE, + "bad numeric value for sectrac: %s", s1); + break; + + case 1: /* secsize */ + if (getnum(s1, &j)) + errx(EX_USAGE, + "bad numeric value for secsize: %s", s1); + if (j == 128) out->secsize = 0; + else if (j == 256) out->secsize = 1; + else if (j == 512) out->secsize = 2; + else if (j == 1024) out->secsize = 3; + else + errx(EX_USAGE, "bad sector size %d", j); + break; + + case 2: /* datalen */ + if (getnum(s1, &j)) + errx(EX_USAGE, + "bad numeric value for datalen: %s", s1); + if (j >= 256) + errx(EX_USAGE, "bad datalen %d", j); + out->datalen = j; + break; + + case 3: /* gap */ + if (getnum(s1, &out->gap)) + errx(EX_USAGE, + "bad numeric value for gap: %s", s1); + break; + + case 4: /* ncyls */ + if (getnum(s1, &j)) + errx(EX_USAGE, + "bad numeric value for ncyls: %s", s1); + if (j > 85) + errx(EX_USAGE, "bad # of cylinders %d", j); + out->tracks = j; + break; + + case 5: /* speed */ + if (getnum(s1, &j)) + errx(EX_USAGE, + "bad numeric value for speed: %s", s1); + switch (type) { + default: + abort(); /* paranoia */ + + case FDT_360K: + case FDT_720K: + if (j == 250) + out->trans = FDC_250KBPS; + else { + badspeed: + errx(EX_USAGE, "bad speed %d", j); + } + break; + + case FDT_12M: + if (j == 300) + out->trans = FDC_300KBPS; + else if (j == 500) + out->trans = FDC_500KBPS; + else + goto badspeed; + break; + + case FDT_288M: + if (j == 1000) + out->trans = FDC_1MBPS; + /* FALLTHROUGH */ + case FDT_144M: + if (j == 250) + out->trans = FDC_250KBPS; + else if (j == 500) + out->trans = FDC_500KBPS; + else + goto badspeed; + break; + } + break; + + case 6: /* heads */ + if (getnum(s1, &j)) + errx(EX_USAGE, + "bad numeric value for heads: %s", s1); + if (j == 1 || j == 2) + out->heads = j; + else + errx(EX_USAGE, "bad # of heads %d", j); + break; + + case 7: /* f_gap */ + if (getnum(s1, &out->f_gap)) + errx(EX_USAGE, + "bad numeric value for f_gap: %s", s1); + break; + + case 8: /* f_inter */ + if (getnum(s1, &out->f_inter)) + errx(EX_USAGE, + "bad numeric value for f_inter: %s", s1); + break; + + case 9: /* offs2 */ + if (getnum(s1, &out->offset_side2)) + errx(EX_USAGE, + "bad numeric value for offs2: %s", s1); + break; + + default: + if (strcmp(s1, "+mfm") == 0) + out->flags |= FL_MFM; + else if (strcmp(s1, "-mfm") == 0) + out->flags &= ~FL_MFM; + else if (strcmp(s1, "+2step") == 0) + out->flags |= FL_2STEP; + else if (strcmp(s1, "-2step") == 0) + out->flags &= ~FL_2STEP; + else if (strcmp(s1, "+perpnd") == 0) + out->flags |= FL_PERPND; + else if (strcmp(s1, "-perpnd") == 0) + out->flags &= ~FL_PERPND; + else + errx(EX_USAGE, "bad flag: %s", s1); + break; + } + free(s1); + } + + out->size = out->tracks * out->heads * out->sectrac * + (128 << out->secsize) / 512; +} + +/* + * Print a textual translation of the drive (density) type described + * by `in' to stdout. The string uses the same form that is parseable + * by parse_fmt(). + */ +void +print_fmt(struct fd_type in) +{ + int secsize, speed; + + secsize = 128 << in.secsize; + switch (in.trans) { + case FDC_250KBPS: speed = 250; break; + case FDC_300KBPS: speed = 300; break; + case FDC_500KBPS: speed = 500; break; + case FDC_1MBPS: speed = 1000; break; + default: speed = 1; break; + } + + printf("%d,%d,%#x,%#x,%d,%d,%d,%#x,%d,%d", + in.sectrac, secsize, in.datalen, in.gap, in.tracks, + speed, in.heads, in.f_gap, in.f_inter, in.offset_side2); + if (in.flags & FL_MFM) + printf(",+mfm"); + if (in.flags & FL_2STEP) + printf(",+2step"); + if (in.flags & FL_PERPND) + printf(",+perpnd"); + putc('\n', stdout); +} + +/* + * Based on `size' (in kilobytes), walk through the table of known + * densities for drive type `type' and see if we can find one. If + * found, return it (as a pointer to static storage), otherwise return + * NULL. + */ +struct fd_type * +get_fmt(int size, enum fd_drivetype type) +{ + int i, n; + struct fd_type *fdtp; + + switch (type) { + default: + return (0); + + case FDT_360K: + fdtp = fd_types_360k; + n = sizeof fd_types_360k / sizeof(struct fd_type); + break; + + case FDT_720K: + fdtp = fd_types_720k; + n = sizeof fd_types_720k / sizeof(struct fd_type); + break; + + case FDT_12M: + fdtp = fd_types_12m; + n = sizeof fd_types_12m / sizeof(struct fd_type); + break; + + case FDT_144M: + fdtp = fd_types_144m; + n = sizeof fd_types_144m / sizeof(struct fd_type); + break; + + case FDT_288M: + fdtp = fd_types_288m; + n = sizeof fd_types_288m / sizeof(struct fd_type); + break; + } + + for (i = 0; i < n; i++, fdtp++) + if (fdtp->size / 2 == size) + return (fdtp); + + return (0); +} + +/* + * Parse a number from `s'. If the string cannot be converted into a + * number completely, return -1, otherwise 0. The result is returned + * in `*res'. + */ +int +getnum(const char *s, int *res) +{ + unsigned long ul; + char *cp; + + ul = strtoul(s, &cp, 0); + if (*cp != '\0') + return (-1); + + *res = (int)ul; + return (0); +} + +/* + * Return a short name and a verbose description for the drive + * described by `t'. + */ +void +getname(enum fd_drivetype t, const char **name, const char **descr) +{ + + switch (t) { + default: + *name = "unknown"; + *descr = "unknown drive type"; + break; + + case FDT_360K: + *name = "360K"; + *descr = "5.25\" double-density"; + break; + + case FDT_12M: + *name = "1.2M"; + *descr = "5.25\" high-density"; + break; + + case FDT_720K: + *name = "720K"; + *descr = "3.5\" double-density"; + break; + + case FDT_144M: + *name = "1.44M"; + *descr = "3.5\" high-density"; + break; + + case FDT_288M: + *name = "2.88M"; + *descr = "3.5\" extra-density"; + break; + } +} diff --git a/usr.sbin/fdread/fdutil.h b/usr.sbin/fdread/fdutil.h index f4993908f047..a09322850897 100644 --- a/usr.sbin/fdread/fdutil.h +++ b/usr.sbin/fdread/fdutil.h @@ -26,4 +26,12 @@ * $FreeBSD$ */ + void printstatus(struct fdc_status *fdcsp, int terse); +void parse_fmt(const char *, enum fd_drivetype, + struct fd_type, struct fd_type *); +struct fd_type *get_fmt(int, enum fd_drivetype); +void print_fmt(struct fd_type); +int getnum(const char *, int *); +void getname(enum fd_drivetype, const char **, const char **); + |