Rewrite of the floppy driver to make it MPsafe & GEOM friendly:

Centralize the fdctl_wr() function by adding the offset in
	the resource to the softc structure.

	Bugfix: Read the drive-change signal from the correct place:
	same place as the ctl register.

	Remove the cdevsw{} related code and implement a GEOM class.

	Ditch the state-engine and park a thread on each controller
	to service the queue.

	Make the interrupt FAST & MPSAFE since it is just a simple
	wakeup(9) call.

	Rely on a per controller mutex to protect the bioqueues.
	Grab GEOMs topology lock when we have to and Giant when
	ISADMA needs it.  Since all access to the hardware is
	isolated in the per controller thread, the rest of the
	driver is lock & Giant free.

	Create a per-drive queue where requests are parked while
	the motor spins up.  When the motor is running the requests
	are purged to the per controller queue.  This allows
	requests to other drives to be serviced during spin-up.

	Only setup the motor-off timeout when we finish the last
	request on the queue and cancel it when a new request
	arrives.  This fixes the bug in the old code where the motor
	turned off while we were still retrying a request.

	Make the "drive-change" work reliably.  Probe the drive on
	first opens.  Probe with a recal and a seek to cyl=1 to
	reset the drive change line and check again to see if we
	have a media.

	When we see the media disappear we destroy the geom provider,
	create a new one, and flag that autodetection should happen
	next time we see a media (unless a specific format is configured).

	Add sysctl tunables for a lot of drive related parameters.
	If you spend a lot of time waiting for floppies you can
	grab the i82078 pdf from Intels web-page and try tuning
	these.

	Add sysctl debug.fdc.debugflags which will enable various
	kinds of debugging printfs.

	Add central definitions of our well known floppy formats.

	Simplify datastructures for autoselection of format and
	call the code at the right times.

	Bugfix: Remove at least one piece of code which would have
	made 2.88M floppies not work.

	Use implied seeks on enhanced controllers.

	Use multisector transfers on all controllers.  Increase
	ISADMA bounce buffers accordingly.

	Fall back to single sector when retrying.  Reset retry count
	on every successful transaction.

	Sort functions in a more sensible order and generally tidy
	up a fair bit here and there.

	Assorted related fixes and adjustments in userland utilities.

WORKAROUNDS:
	Do allow r/w opens of r/o media but refuse actual write
	operations.  This is necessary until the p4::phk_bufwork
	branch gets integrated (This problem relates to remounting
	not reopening devices, see sys/*/*/${fs}_vfsops.c for details).

	Keep PC98's private copy of the old floppy driver compiling
	and presumably working (see below).

TODO (planned)

	Move probing of drives until after interrupts/timeouts work
	(like for ATA/SCSI drives).

TODO (unplanned)

	This driver should be made to work on PC98 as well.

	Test on YE-DATA PCMCIA floppy drive.

	Fix 2.88M media.

This is a MT5 candidate (depends on the bioq_takefirst() addition).
This commit is contained in:
Poul-Henning Kamp 2004-08-20 15:14:25 +00:00
parent 0f81131e63
commit 1b67be7b75
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=134081
9 changed files with 1485 additions and 2032 deletions

File diff suppressed because it is too large Load diff

View file

@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$");
#include "acpi.h"
#include <dev/acpica/acpivar.h>
#include <dev/fdc/fdcreg.h>
#include <dev/fdc/fdcvar.h>
static int fdc_acpi_probe(device_t dev);
@ -46,7 +45,6 @@ static int fdc_acpi_probe_children(device_t bus, device_t dev,
void *fde);
static ACPI_STATUS fdc_acpi_probe_child(ACPI_HANDLE h, device_t *dev,
int level, void *arg);
static void fdctl_wr_acpi(fdc_p fdc, u_int8_t v);
/* Maximum number of child devices of a controller (4 floppy + 1 tape.) */
#define ACPI_FDC_MAXDEVS 5
@ -72,12 +70,6 @@ struct fdc_walk_ctx {
device_t dev;
};
static void
fdctl_wr_acpi(fdc_p fdc, u_int8_t v)
{
bus_space_write_1(fdc->ctlt, fdc->ctlh, 0, v);
}
static int
fdc_acpi_probe(device_t dev)
{
@ -101,7 +93,7 @@ fdc_acpi_attach(device_t dev)
struct fdc_data *sc;
ACPI_BUFFER buf;
device_t bus;
int error, i, ic_type;
int error, i;
ACPI_OBJECT *obj, *pkg;
ACPI_HANDLE h;
uint32_t *fde;
@ -109,7 +101,6 @@ fdc_acpi_attach(device_t dev)
/* Get our softc and use the same accessor as ISA. */
sc = device_get_softc(dev);
sc->fdc_dev = dev;
sc->fdctl_wr = fdctl_wr_acpi;
sc->flags |= FDC_ISPNP;
/* Initialize variables and get a temporary buffer for _FDE. */
@ -130,26 +121,6 @@ fdc_acpi_attach(device_t dev)
if (error != 0)
goto out;
/* Check that the controller is working and get its type. */
error = fdc_initial_reset(sc);
if (error)
goto out;
if (fd_cmd(sc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) {
ic_type = (u_char)ic_type;
switch (ic_type) {
case 0x80:
sc->fdct = FDC_NE765;
break;
case 0x81: /* not mentioned in any hardware doc */
case 0x90:
sc->fdct = FDC_ENHANCED;
break;
default:
sc->fdct = FDC_UNKNOWN;
break;
}
}
/*
* Enumerate _FDE, which lists floppy drives that are present. If
* this fails, fall back to the ISA hints-based probe method.

View file

@ -33,20 +33,20 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/rman.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <dev/fdc/fdcvar.h>
#include <dev/fdc/fdcreg.h>
#include <isa/isavar.h>
#include <isa/isareg.h>
static int fdc_isa_probe(device_t);
static void fdctl_wr_isa(fdc_p, u_int8_t);
static struct isa_pnp_id fdc_ids[] = {
{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
@ -54,12 +54,6 @@ static struct isa_pnp_id fdc_ids[] = {
{0}
};
static void
fdctl_wr_isa(fdc_p fdc, u_int8_t v)
{
bus_space_write_1(fdc->ctlt, fdc->ctlh, 0, v);
}
int
fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc)
{
@ -165,6 +159,7 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc)
}
fdc->ctlt = rman_get_bustag(fdc->res_ctl);
fdc->ctlh = rman_get_bushandle(fdc->res_ctl);
fdc->ctl_off = 0;
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
RF_ACTIVE | RF_SHAREABLE);
@ -189,12 +184,11 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc)
static int
fdc_isa_probe(device_t dev)
{
int error, ic_type;
int error;
struct fdc_data *fdc;
fdc = device_get_softc(dev);
fdc->fdc_dev = dev;
fdc->fdctl_wr = fdctl_wr_isa;
/* Check pnp ids */
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
@ -203,32 +197,9 @@ fdc_isa_probe(device_t dev)
/* Attempt to allocate our resources for the duration of the probe */
error = fdc_isa_alloc_resources(dev, fdc);
if (error)
goto out;
if (error == 0)
error = fdc_initial_reset(dev, fdc);
/* Check that the controller is working. */
error = fdc_initial_reset(fdc);
if (error)
goto out;
/* Try to determine a more specific device type. */
if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) {
switch (ic_type & 0xff) {
case 0x80:
device_set_desc(dev, "NEC 765 or clone");
break;
case 0x81: /* not mentioned in any hardware doc */
case 0x90:
device_set_desc(dev,
"Enhanced floppy controller (i82077, NE72065 or clone)");
break;
default:
device_set_desc(dev, "Generic floppy controller");
break;
}
}
out:
fdc_release_resources(fdc);
return (error);
}
@ -236,40 +207,20 @@ fdc_isa_probe(device_t dev)
static int
fdc_isa_attach(device_t dev)
{
int ic_type;
struct fdc_data *fdc;
int error;
fdc = device_get_softc(dev);
fdc->fdctl_wr = fdctl_wr_isa;
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
if (error == 0)
fdc->flags |= FDC_ISPNP;
if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) {
switch (ic_type & 0xff) {
case 0x80:
fdc->fdct = FDC_NE765;
break;
case 0x81: /* not mentioned in any hardware doc */
case 0x90:
fdc->fdct = FDC_ENHANCED;
break;
default:
fdc->fdct = FDC_UNKNOWN;
break;
}
}
error = fdc_isa_alloc_resources(dev, fdc);
if (error)
goto out;
error = fdc_attach(dev);
if (error)
goto out;
error = fdc_hints_probe(dev);
if (error)
goto out;
out:
if (error == 0)
error = fdc_isa_alloc_resources(dev, fdc);
if (error == 0)
error = fdc_attach(dev);
if (error == 0)
error = fdc_hints_probe(dev);
if (error)
fdc_release_resources(fdc);
return (error);

View file

@ -33,7 +33,9 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/rman.h>
#include <sys/systm.h>
#include <machine/bus.h>
@ -41,11 +43,9 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <dev/fdc/fdcvar.h>
#include <dev/fdc/fdcreg.h>
#include <dev/pccard/pccardvar.h>
#include "pccarddevs.h"
static void fdctl_wr_pcmcia(fdc_p, u_int8_t);
static int fdc_pccard_probe(device_t);
static int fdc_pccard_attach(device_t);
@ -53,12 +53,6 @@ static const struct pccard_product fdc_pccard_products[] = {
PCMCIA_CARD(YEDATA, EXTERNAL_FDD, 0),
};
static void
fdctl_wr_pcmcia(fdc_p fdc, u_int8_t v)
{
bus_space_write_1(fdc->portt, fdc->porth, FDCTL+fdc->port_off, v);
}
static int
fdc_pccard_alloc_resources(device_t dev, struct fdc_data *fdc)
{
@ -71,6 +65,9 @@ fdc_pccard_alloc_resources(device_t dev, struct fdc_data *fdc)
}
fdc->portt = rman_get_bustag(fdc->res_ioport);
fdc->porth = rman_get_bushandle(fdc->res_ioport);
fdc->ctlt = fdc->portt;
fdc->ctlh = fdc->porth;
fdc->ctl_off = 7;
fdc->rid_irq = 0;
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
@ -105,17 +102,11 @@ fdc_pccard_attach(device_t dev)
return ENXIO;
fdc = device_get_softc(dev);
fdc->fdctl_wr = fdctl_wr_pcmcia;
fdc->flags = FDC_NODMA;
fdc->fdct = FDC_NE765;
error = fdc_pccard_alloc_resources(dev, fdc);
if (error)
goto out;
error = fdc_attach(dev);
if (error)
goto out;
out:
if (error == 0)
error = fdc_attach(dev);
if (error)
fdc_release_resources(fdc);
return (error);

View file

@ -30,71 +30,31 @@
/* XXX should audit this file to see if additional copyrights needed */
enum fdc_type
{
enum fdc_type {
FDC_NE765, FDC_ENHANCED, FDC_UNKNOWN = -1
};
enum fdc_states {
DEVIDLE,
FINDWORK,
DOSEEK,
SEEKCOMPLETE ,
IOCOMPLETE,
RECALCOMPLETE,
STARTRECAL,
RESETCTLR,
SEEKWAIT,
RECALWAIT,
MOTORWAIT,
IOTIMEDOUT,
RESETCOMPLETE,
PIOREAD
};
#ifdef FDC_DEBUG
static char const * const fdstates[] = {
"DEVIDLE",
"FINDWORK",
"DOSEEK",
"SEEKCOMPLETE",
"IOCOMPLETE",
"RECALCOMPLETE",
"STARTRECAL",
"RESETCTLR",
"SEEKWAIT",
"RECALWAIT",
"MOTORWAIT",
"IOTIMEDOUT",
"RESETCOMPLETE",
"PIOREAD"
};
#endif
/*
* Per controller structure (softc).
*/
struct fdc_data
{
struct fdc_data {
int fdcu; /* our unit number */
int dmacnt;
int dmachan;
int flags;
#define FDC_HASDMA 0x01
#define FDC_STAT_VALID 0x08
#define FDC_HAS_FIFO 0x10
#define FDC_NEEDS_RESET 0x20
#define FDC_NODMA 0x40
#define FDC_ISPNP 0x80
#define FDC_ISPCMCIA 0x100
struct fd_data *fd;
int fdu; /* the active drive */
enum fdc_states state;
struct fd_data *fd; /* The active drive */
int retry;
int fdout; /* mirror of the w/o digital output reg */
u_int status[7]; /* copy of the registers */
enum fdc_type fdct; /* chip version of FDC */
int fdc_errs; /* number of logged errors */
int dma_overruns; /* number of DMA overruns */
struct bio_queue_head head;
struct bio *bp; /* active buffer */
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
@ -104,23 +64,13 @@ struct fdc_data
bus_space_handle_t porth;
bus_space_tag_t ctlt;
bus_space_handle_t ctlh;
int ctl_off;
void *fdc_intr;
struct device *fdc_dev;
void (*fdctl_wr)(struct fdc_data *fdc, u_int8_t v);
struct mtx fdc_mtx;
struct proc *fdc_thread;
};
typedef int fdu_t;
typedef int fdcu_t;
typedef int fdsu_t;
typedef struct fd_data *fd_p;
typedef struct fdc_data *fdc_p;
typedef enum fdc_type fdc_t;
/* error returns for fd_cmd() */
#define FD_FAILED -1
#define FD_NOT_VALID -2
#define FDC_ERRMAX 100 /* do not log more */
extern devclass_t fdc_devclass;
enum fdc_device_ivars {
@ -131,15 +81,12 @@ enum fdc_device_ivars {
__BUS_ACCESSOR(fdc, fdunit, FDC, FDUNIT, int);
__BUS_ACCESSOR(fdc, fdtype, FDC, FDTYPE, int);
int fdc_alloc_resources(struct fdc_data *);
void fdout_wr(fdc_p, u_int8_t);
int fd_cmd(struct fdc_data *, int, ...);
void fdc_release_resources(struct fdc_data *);
int fdc_attach(device_t);
int fdc_hints_probe(device_t);
int fdc_detach(device_t dev);
device_t fdc_add_child(device_t, const char *, int);
int fdc_initial_reset(struct fdc_data *);
int fdc_initial_reset(device_t, struct fdc_data *);
int fdc_print_child(device_t, device_t);
int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
int fdc_write_ivar(device_t, device_t, int, uintptr_t);

View file

@ -44,44 +44,41 @@ struct fd_formb {
int cyl, head;
int transfer_rate; /* FDC_???KBPS */
union {
struct fd_form_data {
struct fd_form_data {
/*
* DO NOT CHANGE THE LAYOUT OF THIS STRUCTS
* it is hardware-dependent since it exactly
* matches the byte sequence to write to FDC
* during its `format track' operation
*/
u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */
u_char nsecs; /* must be <= FD_MAX_NSEC */
u_char gaplen; /* GAP 3 length; usually 84 */
u_char fillbyte; /* usually 0xf6 */
struct fd_idfield_data {
/*
* DO NOT CHANGE THE LAYOUT OF THIS STRUCTS
* it is hardware-dependent since it exactly
* matches the byte sequence to write to FDC
* during its `format track' operation
* data to write into id fields;
* for obscure formats, they mustn't match
* the real values (but mostly do)
*/
u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */
u_char nsecs; /* must be <= FD_MAX_NSEC */
u_char gaplen; /* GAP 3 length; usually 84 */
u_char fillbyte; /* usually 0xf6 */
struct fd_idfield_data {
/*
* data to write into id fields;
* for obscure formats, they mustn't match
* the real values (but mostly do)
*/
u_char cylno; /* 0 thru 79 (or 39) */
u_char headno; /* 0, or 1 */
u_char secno; /* starting at 1! */
u_char secsize; /* usually 2 */
} idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */
} structured;
u_char raw[1]; /* to have continuous indexed access */
u_char cylno; /* 0 thru 79 (or 39) */
u_char headno; /* 0, or 1 */
u_char secno; /* starting at 1! */
u_char secsize; /* usually 2 */
} idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */
} format_info;
};
/* make life easier */
# define fd_formb_secshift format_info.structured.secshift
# define fd_formb_nsecs format_info.structured.nsecs
# define fd_formb_gaplen format_info.structured.gaplen
# define fd_formb_fillbyte format_info.structured.fillbyte
# define fd_formb_secshift format_info.secshift
# define fd_formb_nsecs format_info.nsecs
# define fd_formb_gaplen format_info.gaplen
# define fd_formb_fillbyte format_info.fillbyte
/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */
# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno
# define fd_formb_headno(i) format_info.structured.idfields[i].headno
# define fd_formb_secno(i) format_info.structured.idfields[i].secno
# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize
# define fd_formb_cylno(i) format_info.idfields[i].cylno
# define fd_formb_headno(i) format_info.idfields[i].headno
# define fd_formb_secno(i) format_info.idfields[i].secno
# define fd_formb_secsize(i) format_info.idfields[i].secsize
struct fd_type {
int sectrac; /* sectors per track */
@ -99,6 +96,7 @@ struct fd_type {
#define FL_MFM 0x0001 /* MFM recording */
#define FL_2STEP 0x0002 /* 2 steps between cylinders */
#define FL_PERPND 0x0004 /* perpendicular recording */
#define FL_AUTO 0x0008 /* autodetect format */
};
struct fdc_status {
@ -133,8 +131,6 @@ enum fd_drivetype {
#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */
#define FD_SOPTS _IOW('F', 65, int)
#define FD_DEBUG _IOW('F', 66, int)
#define FD_CLRERR _IO('F', 67) /* clear error counter */
#define FD_READID _IOWR('F', 68, struct fdc_readid) /* read ID field */
@ -152,8 +148,10 @@ enum fd_drivetype {
#define FDOPT_NOERRLOG 0x002 /* no "hard error" kernel log messages */
#define FDOPT_NOERROR 0x0004 /* do not indicate errors, caller will use
FD_GSTAT in order to obtain status */
#ifdef PC98
#define FDOPT_AUTOSEL 0x8000 /* read/only option: device performs media
* autoselection */
#endif
/*
* Transfer rate definitions. Used in the structures above. They
@ -167,4 +165,34 @@ enum fd_drivetype {
#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */
#define FDC_1MBPS 0x03 /* 1MPBS MFM drive transfer rate */
/*
* Parameters for common formats
*
* See struct fd_type for layout.
* XXX: Field 'size' must be calculated.
* XXX: Fields 'f_inter' and 'offset_side2' are unused by kernel.
*
* XXX: These should really go in a /etc/floppycap colon separated file
* XXX: but the kernel needs some of them for proper defaults and it would
* XXX: should have been done 20 years ago to make sense.
*/
#define FDF_3_2880 36,2,0xFF,0x1B,80,0,FDC_1MBPS,002,0x4C,1,1,FL_MFM|FL_PERPND
#define FDF_3_1722 21,2,0xFF,0x04,82,0,FDC_500KBPS,2,0x0C,2,0,FL_MFM
#define FDF_3_1476 18,2,0xFF,0x1B,82,0,FDC_500KBPS,2,0x6C,1,0,FL_MFM
#define FDF_3_1440 18,2,0xFF,0x1B,80,0,FDC_500KBPS,2,0x6C,1,0,FL_MFM
#define FDF_3_1200 15,2,0xFF,0x1B,80,0,FDC_500KBPS,2,0x54,1,0,FL_MFM
#define FDF_3_820 10,2,0xFF,0x10,82,0,FDC_250KBPS,2,0x2e,1,0,FL_MFM
#define FDF_3_800 10,2,0xFF,0x10,80,0,FDC_250KBPS,2,0x2e,1,0,FL_MFM
#define FDF_3_720 9,2,0xFF,0x20,80,0,FDC_250KBPS,2,0x50,1,0,FL_MFM
#define FDF_5_1480 18,2,0xFF,0x02,82,0,FDC_500KBPS,2,0x02,2,0,FL_MFM
#define FDF_5_1440 18,2,0xFF,0x02,80,0,FDC_500KBPS,2,0x02,2,0,FL_MFM
#define FDF_5_1230 8,3,0xFF,0x35,77,0,FDC_500KBPS,2,0x74,1,0,FL_MFM
#define FDF_5_1200 15,2,0xFF,0x1B,80,0,FDC_500KBPS,2,0x54,1,0,FL_MFM
#define FDF_5_820 10,2,0xFF,0x10,82,0,FDC_300KBPS,2,0x2e,1,0,FL_MFM
#define FDF_5_800 10,2,0xFF,0x10,80,0,FDC_300KBPS,2,0x2e,1,0,FL_MFM
#define FDF_5_720 9,2,0xFF,0x20,80,0,FDC_300KBPS,2,0x50,1,0,FL_MFM
#define FDF_5_640 8,2,0xFF,0x2A,80,0,FDC_300KBPS,2,0x50,1,0,FL_MFM
#define FDF_5_360 9,2,0xFF,0x23,40,0,FDC_300KBPS,2,0x50,1,0,FL_MFM
/* XXX: 0x2a ? */
#endif /* !_MACHINE_IOCTL_FD_H_ */

View file

@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
#include "fdutil.h"
static int debug = -1, format, verbose, show = 1, showfmt;
static int format, verbose, show = 1, showfmt;
static char *fmtstring;
static void showdev(enum fd_drivetype, const char *);
@ -72,20 +72,14 @@ main(int argc, char **argv)
enum fd_drivetype type;
struct fd_type ft, newft, *fdtp;
const char *name, *descr;
int fd, i, mode;
int fd, i, mode, autofmt;
while((i = getopt(argc, argv, "d:Ff:s:v")) != -1)
autofmt = 0;
while((i = getopt(argc, argv, "aFf: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 'a':
autofmt = 1;
case 'F':
showfmt = 1;
show = 0;
@ -141,6 +135,11 @@ mode = O_RDONLY | O_NONBLOCK;
return (0);
}
if (autofmt) {
memset(&newft, 0, sizeof newft);
ft = newft;
}
if (format) {
getname(type, &name, &descr);
fdtp = get_fmt(format, type);
@ -195,6 +194,10 @@ mode = O_RDONLY | O_NONBLOCK;
printf("%sPERPENDICULAR", s);
s = ",";
}
if (ft.flags & FL_AUTO) {
printf("%sAUTO", s);
s = ",";
}
printf(">\n");
} else {
print_fmt(ft);
@ -208,11 +211,5 @@ mode = O_RDONLY | O_NONBLOCK;
return (0);
}
if (debug != -1) {
if (ioctl(fd, FD_DEBUG, &debug) == -1)
err(EX_OSERR, "ioctl(FD_DEBUG)");
return (0);
}
return 0;
}

View file

@ -268,13 +268,8 @@ main(int argc, char **argv)
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 (ioctl(fd, FD_STYPE, &fdt) < 0)
err(EX_OSERR, "ioctl(FD_STYPE)");
if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
err(EX_OSERR, "fcntl(F_GETFL)");
flags &= ~O_NONBLOCK;

View file

@ -59,7 +59,9 @@ printstatus(struct fdc_status *fdcsp, int terse)
fdcsp->status[5] & 0xff,
fdcsp->status[6] & 0xff);
if ((fdcsp->status[0] & NE7_ST0_IC_RC) != NE7_ST0_IC_AT) {
if ((fdcsp->status[0] & NE7_ST0_IC_RC) == 0) {
sprintf(msgbuf, "timeout");
} else if ((fdcsp->status[0] & NE7_ST0_IC_RC) != NE7_ST0_IC_AT) {
sprintf(msgbuf, "unexcpted interrupt code %#x",
fdcsp->status[0] & NE7_ST0_IC_RC);
} else {
@ -85,98 +87,60 @@ printstatus(struct fdc_status *fdcsp, int terse)
fputs(msgbuf, stderr);
}
static struct fd_type fd_types_auto[1];
static struct fd_type fd_types_auto[1] =
{ { 0,0,0,0,0,0,0,0,0,0,0,FL_AUTO } };
#ifdef PC98
static struct fd_type fd_types_12m[] = {
{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */
static struct fd_type fd_types_288m[] = {
#if 0
{ 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */
{ 10,2,0xFF,0x10,80,1600,1,2,0x30,1,0,FL_MFM }, /* 800K */
#endif
{ 9,2,0xFF,0x20,80,1440,1,2,0x50,1,0,FL_MFM }, /* 720K */
{ 9,2,0xFF,0x20,40, 720,1,2,0x50,1,0,FL_MFM|FL_2STEP },/* 360K */
{ 8,2,0xFF,0x2A,80,1280,1,2,0x50,1,0,FL_MFM }, /* 640K */
{ 8,3,0xFF,0x35,77,1232,0,2,0x74,1,0,FL_MFM }, /* 1.23M 1024/sec */
#if 0
{ 8,3,0xFF,0x35,80,1280,0,2,0x74,1,0,FL_MFM }, /* 1.28M 1024/sec */
{ FDF_3_2880 },
#endif
{ FDF_3_1722 },
{ FDF_3_1476 },
{ FDF_3_1440 },
{ FDF_3_1200 },
{ FDF_3_820 },
{ FDF_3_800 },
{ FDF_3_720 },
{ 0 }
};
static struct fd_type fd_types_144m[] = {
#if 0
{ 21,2,0xFF,0x04,82,3444,2,2,0x0C,2,0,FL_MFM }, /* 1.72M in 3mode */
{ 18,2,0xFF,0x1B,82,2952,2,2,0x54,1,0,FL_MFM }, /* 1.48M in 3mode */
#endif
{ 18,2,0xFF,0x1B,80,2880,2,2,0x54,1,0,FL_MFM }, /* 1.44M in 3mode */
{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */
#if 0
{ 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */
{ 10,2,0xFF,0x10,80,1600,1,2,0x30,1,0,FL_MFM }, /* 800K */
#endif
{ 9,2,0xFF,0x20,80,1440,1,2,0x50,1,0,FL_MFM }, /* 720K */
{ 9,2,0xFF,0x20,40, 720,1,2,0x50,1,0,FL_MFM|FL_2STEP },/* 360K */
{ 8,2,0xFF,0x2A,80,1280,1,2,0x50,1,0,FL_MFM }, /* 640K */
{ 8,3,0xFF,0x35,77,1232,0,2,0x74,1,0,FL_MFM }, /* 1.23M 1024/sec */
#if 0
{ 8,3,0xFF,0x35,80,1280,0,2,0x74,1,0,FL_MFM }, /* 1.28M 1024/sec */
{ 9,3,0xFF,0x35,82,1476,0,2,0x47,1,0,FL_MFM }, /* 1.48M 1024/sec 9sec */
{ 10,3,0xFF,0x1B,82,1640,2,2,0x54,1,0,FL_MFM }, /* 1.64M in 3mode - Reserve */
#endif
{ FDF_3_1722 },
{ FDF_3_1476 },
{ FDF_3_1440 },
{ FDF_3_1200 },
{ FDF_3_820 },
{ FDF_3_800 },
{ FDF_3_720 },
{ 0 }
};
#else /* PC98 */
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_12m[] = {
{ FDF_5_1200 },
{ FDF_5_1230 },
{ FDF_5_1480 },
{ FDF_5_1440 },
{ FDF_5_820 },
{ FDF_5_800 },
{ FDF_5_720 },
{ FDF_5_360 | FL_2STEP },
{ FDF_5_640 },
{ 0 }
};
static struct fd_type fd_types_720k[] =
{
{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */
{ FDF_3_720 },
{ 0 }
};
static struct fd_type fd_types_360k[] =
{
{ 9,2,0xFF,0x2A,40, 720,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 360K */
{ FDF_5_360 },
{ 0 }
};
#endif /* PC98 */
/*
* Parse a format string, and fill in the parameter pointed to by `out'.
@ -284,7 +248,6 @@ parse_fmt(const char *s, enum fd_drivetype type,
default:
abort(); /* paranoia */
#ifndef PC98
case FDT_360K:
case FDT_720K:
if (j == 250)
@ -292,23 +255,22 @@ parse_fmt(const char *s, enum fd_drivetype type,
else
errx(EX_USAGE, "bad speed %d", j);
break;
#endif
case FDT_12M:
if (j == 300)
out->trans = FDC_300KBPS;
else if (j == 250)
out->trans = FDC_250KBPS;
else if (j == 500)
out->trans = FDC_500KBPS;
else
errx(EX_USAGE, "bad speed %d", j);
break;
#ifndef PC98
case FDT_288M:
if (j == 1000)
out->trans = FDC_1MBPS;
/* FALLTHROUGH */
#endif
case FDT_144M:
if (j == 250)
out->trans = FDC_250KBPS;
@ -353,6 +315,10 @@ parse_fmt(const char *s, enum fd_drivetype type,
out->flags |= FL_MFM;
else if (strcmp(s1, "-mfm") == 0)
out->flags &= ~FL_MFM;
else if (strcmp(s1, "+auto") == 0)
out->flags |= FL_AUTO;
else if (strcmp(s1, "-auto") == 0)
out->flags &= ~FL_AUTO;
else if (strcmp(s1, "+2step") == 0)
out->flags |= FL_2STEP;
else if (strcmp(s1, "-2step") == 0)
@ -399,6 +365,8 @@ print_fmt(struct fd_type in)
printf(",+2step");
if (in.flags & FL_PERPND)
printf(",+perpnd");
if (in.flags & FL_AUTO)
printf(",+auto");
putc('\n', stdout);
}
@ -418,7 +386,6 @@ get_fmt(int size, enum fd_drivetype type)
default:
return (0);
#ifndef PC98
case FDT_360K:
fdtp = fd_types_360k;
n = sizeof fd_types_360k / sizeof(struct fd_type);
@ -428,7 +395,6 @@ get_fmt(int size, enum fd_drivetype type)
fdtp = fd_types_720k;
n = sizeof fd_types_720k / sizeof(struct fd_type);
break;
#endif
case FDT_12M:
fdtp = fd_types_12m;
@ -440,21 +406,20 @@ get_fmt(int size, enum fd_drivetype type)
n = sizeof fd_types_144m / sizeof(struct fd_type);
break;
#ifndef PC98
case FDT_288M:
fdtp = fd_types_288m;
n = sizeof fd_types_288m / sizeof(struct fd_type);
break;
#endif
}
if (size == -1)
return fd_types_auto;
for (i = 0; i < n; i++, fdtp++)
for (i = 0; i < n; i++, fdtp++) {
fdtp->size = fdtp->sectrac * fdtp->heads * fdtp->tracks;
if (((128 << fdtp->secsize) * fdtp->size / 1024) == size)
return (fdtp);
}
return (0);
}
@ -491,35 +456,29 @@ getname(enum fd_drivetype t, const char **name, const char **descr)
*descr = "unknown drive type";
break;
#ifndef PC98
case FDT_360K:
*name = "360K";
*descr = "5.25\" double-density";
break;
#endif
case FDT_12M:
*name = "1.2M";
*descr = "5.25\" high-density";
break;
#ifndef PC98
case FDT_720K:
*name = "720K";
*descr = "3.5\" double-density";
break;
#endif
case FDT_144M:
*name = "1.44M";
*descr = "3.5\" high-density";
break;
#ifndef PC98
case FDT_288M:
*name = "2.88M";
*descr = "3.5\" extra-density";
break;
#endif
}
}