mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 04:43:53 +00:00
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:
parent
0f81131e63
commit
1b67be7b75
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=134081
3046
sys/dev/fdc/fdc.c
3046
sys/dev/fdc/fdc.c
File diff suppressed because it is too large
Load diff
|
@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
#include <dev/acpica/acpivar.h>
|
#include <dev/acpica/acpivar.h>
|
||||||
#include <dev/fdc/fdcreg.h>
|
|
||||||
#include <dev/fdc/fdcvar.h>
|
#include <dev/fdc/fdcvar.h>
|
||||||
|
|
||||||
static int fdc_acpi_probe(device_t dev);
|
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);
|
void *fde);
|
||||||
static ACPI_STATUS fdc_acpi_probe_child(ACPI_HANDLE h, device_t *dev,
|
static ACPI_STATUS fdc_acpi_probe_child(ACPI_HANDLE h, device_t *dev,
|
||||||
int level, void *arg);
|
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.) */
|
/* Maximum number of child devices of a controller (4 floppy + 1 tape.) */
|
||||||
#define ACPI_FDC_MAXDEVS 5
|
#define ACPI_FDC_MAXDEVS 5
|
||||||
|
@ -72,12 +70,6 @@ struct fdc_walk_ctx {
|
||||||
device_t dev;
|
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
|
static int
|
||||||
fdc_acpi_probe(device_t dev)
|
fdc_acpi_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
@ -101,7 +93,7 @@ fdc_acpi_attach(device_t dev)
|
||||||
struct fdc_data *sc;
|
struct fdc_data *sc;
|
||||||
ACPI_BUFFER buf;
|
ACPI_BUFFER buf;
|
||||||
device_t bus;
|
device_t bus;
|
||||||
int error, i, ic_type;
|
int error, i;
|
||||||
ACPI_OBJECT *obj, *pkg;
|
ACPI_OBJECT *obj, *pkg;
|
||||||
ACPI_HANDLE h;
|
ACPI_HANDLE h;
|
||||||
uint32_t *fde;
|
uint32_t *fde;
|
||||||
|
@ -109,7 +101,6 @@ fdc_acpi_attach(device_t dev)
|
||||||
/* Get our softc and use the same accessor as ISA. */
|
/* Get our softc and use the same accessor as ISA. */
|
||||||
sc = device_get_softc(dev);
|
sc = device_get_softc(dev);
|
||||||
sc->fdc_dev = dev;
|
sc->fdc_dev = dev;
|
||||||
sc->fdctl_wr = fdctl_wr_acpi;
|
|
||||||
sc->flags |= FDC_ISPNP;
|
sc->flags |= FDC_ISPNP;
|
||||||
|
|
||||||
/* Initialize variables and get a temporary buffer for _FDE. */
|
/* Initialize variables and get a temporary buffer for _FDE. */
|
||||||
|
@ -130,26 +121,6 @@ fdc_acpi_attach(device_t dev)
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
goto out;
|
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
|
* Enumerate _FDE, which lists floppy drives that are present. If
|
||||||
* this fails, fall back to the ISA hints-based probe method.
|
* this fails, fall back to the ISA hints-based probe method.
|
||||||
|
|
|
@ -33,20 +33,20 @@ __FBSDID("$FreeBSD$");
|
||||||
#include <sys/bio.h>
|
#include <sys/bio.h>
|
||||||
#include <sys/bus.h>
|
#include <sys/bus.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/lock.h>
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
|
#include <sys/mutex.h>
|
||||||
#include <sys/rman.h>
|
#include <sys/rman.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
|
||||||
#include <dev/fdc/fdcvar.h>
|
#include <dev/fdc/fdcvar.h>
|
||||||
#include <dev/fdc/fdcreg.h>
|
|
||||||
|
|
||||||
#include <isa/isavar.h>
|
#include <isa/isavar.h>
|
||||||
#include <isa/isareg.h>
|
#include <isa/isareg.h>
|
||||||
|
|
||||||
static int fdc_isa_probe(device_t);
|
static int fdc_isa_probe(device_t);
|
||||||
static void fdctl_wr_isa(fdc_p, u_int8_t);
|
|
||||||
|
|
||||||
static struct isa_pnp_id fdc_ids[] = {
|
static struct isa_pnp_id fdc_ids[] = {
|
||||||
{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
|
{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
|
||||||
|
@ -54,12 +54,6 @@ static struct isa_pnp_id fdc_ids[] = {
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
fdctl_wr_isa(fdc_p fdc, u_int8_t v)
|
|
||||||
{
|
|
||||||
bus_space_write_1(fdc->ctlt, fdc->ctlh, 0, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc)
|
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->ctlt = rman_get_bustag(fdc->res_ctl);
|
||||||
fdc->ctlh = rman_get_bushandle(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,
|
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
|
||||||
RF_ACTIVE | RF_SHAREABLE);
|
RF_ACTIVE | RF_SHAREABLE);
|
||||||
|
@ -189,12 +184,11 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc)
|
||||||
static int
|
static int
|
||||||
fdc_isa_probe(device_t dev)
|
fdc_isa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
int error, ic_type;
|
int error;
|
||||||
struct fdc_data *fdc;
|
struct fdc_data *fdc;
|
||||||
|
|
||||||
fdc = device_get_softc(dev);
|
fdc = device_get_softc(dev);
|
||||||
fdc->fdc_dev = dev;
|
fdc->fdc_dev = dev;
|
||||||
fdc->fdctl_wr = fdctl_wr_isa;
|
|
||||||
|
|
||||||
/* Check pnp ids */
|
/* Check pnp ids */
|
||||||
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_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 */
|
/* Attempt to allocate our resources for the duration of the probe */
|
||||||
error = fdc_isa_alloc_resources(dev, fdc);
|
error = fdc_isa_alloc_resources(dev, fdc);
|
||||||
if (error)
|
if (error == 0)
|
||||||
goto out;
|
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);
|
fdc_release_resources(fdc);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
@ -236,40 +207,20 @@ fdc_isa_probe(device_t dev)
|
||||||
static int
|
static int
|
||||||
fdc_isa_attach(device_t dev)
|
fdc_isa_attach(device_t dev)
|
||||||
{
|
{
|
||||||
int ic_type;
|
|
||||||
struct fdc_data *fdc;
|
struct fdc_data *fdc;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
fdc = device_get_softc(dev);
|
fdc = device_get_softc(dev);
|
||||||
fdc->fdctl_wr = fdctl_wr_isa;
|
|
||||||
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
|
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
fdc->flags |= FDC_ISPNP;
|
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 == 0)
|
||||||
if (error)
|
error = fdc_isa_alloc_resources(dev, fdc);
|
||||||
goto out;
|
if (error == 0)
|
||||||
error = fdc_attach(dev);
|
error = fdc_attach(dev);
|
||||||
if (error)
|
if (error == 0)
|
||||||
goto out;
|
error = fdc_hints_probe(dev);
|
||||||
error = fdc_hints_probe(dev);
|
|
||||||
if (error)
|
|
||||||
goto out;
|
|
||||||
out:
|
|
||||||
if (error)
|
if (error)
|
||||||
fdc_release_resources(fdc);
|
fdc_release_resources(fdc);
|
||||||
return (error);
|
return (error);
|
||||||
|
|
|
@ -33,7 +33,9 @@ __FBSDID("$FreeBSD$");
|
||||||
#include <sys/bio.h>
|
#include <sys/bio.h>
|
||||||
#include <sys/bus.h>
|
#include <sys/bus.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/lock.h>
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
|
#include <sys/mutex.h>
|
||||||
#include <sys/rman.h>
|
#include <sys/rman.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
@ -41,11 +43,9 @@ __FBSDID("$FreeBSD$");
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
|
||||||
#include <dev/fdc/fdcvar.h>
|
#include <dev/fdc/fdcvar.h>
|
||||||
#include <dev/fdc/fdcreg.h>
|
|
||||||
#include <dev/pccard/pccardvar.h>
|
#include <dev/pccard/pccardvar.h>
|
||||||
#include "pccarddevs.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_probe(device_t);
|
||||||
static int fdc_pccard_attach(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),
|
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
|
static int
|
||||||
fdc_pccard_alloc_resources(device_t dev, struct fdc_data *fdc)
|
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->portt = rman_get_bustag(fdc->res_ioport);
|
||||||
fdc->porth = rman_get_bushandle(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->rid_irq = 0;
|
||||||
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
|
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;
|
return ENXIO;
|
||||||
|
|
||||||
fdc = device_get_softc(dev);
|
fdc = device_get_softc(dev);
|
||||||
fdc->fdctl_wr = fdctl_wr_pcmcia;
|
|
||||||
fdc->flags = FDC_NODMA;
|
fdc->flags = FDC_NODMA;
|
||||||
fdc->fdct = FDC_NE765;
|
fdc->fdct = FDC_NE765;
|
||||||
error = fdc_pccard_alloc_resources(dev, fdc);
|
error = fdc_pccard_alloc_resources(dev, fdc);
|
||||||
if (error)
|
if (error == 0)
|
||||||
goto out;
|
error = fdc_attach(dev);
|
||||||
error = fdc_attach(dev);
|
|
||||||
if (error)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (error)
|
if (error)
|
||||||
fdc_release_resources(fdc);
|
fdc_release_resources(fdc);
|
||||||
return (error);
|
return (error);
|
||||||
|
|
|
@ -30,71 +30,31 @@
|
||||||
|
|
||||||
/* XXX should audit this file to see if additional copyrights needed */
|
/* XXX should audit this file to see if additional copyrights needed */
|
||||||
|
|
||||||
enum fdc_type
|
enum fdc_type {
|
||||||
{
|
|
||||||
FDC_NE765, FDC_ENHANCED, FDC_UNKNOWN = -1
|
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).
|
* Per controller structure (softc).
|
||||||
*/
|
*/
|
||||||
struct fdc_data
|
struct fdc_data {
|
||||||
{
|
|
||||||
int fdcu; /* our unit number */
|
int fdcu; /* our unit number */
|
||||||
int dmacnt;
|
int dmacnt;
|
||||||
int dmachan;
|
int dmachan;
|
||||||
int flags;
|
int flags;
|
||||||
|
#define FDC_HASDMA 0x01
|
||||||
#define FDC_STAT_VALID 0x08
|
#define FDC_STAT_VALID 0x08
|
||||||
#define FDC_HAS_FIFO 0x10
|
#define FDC_HAS_FIFO 0x10
|
||||||
#define FDC_NEEDS_RESET 0x20
|
#define FDC_NEEDS_RESET 0x20
|
||||||
#define FDC_NODMA 0x40
|
#define FDC_NODMA 0x40
|
||||||
#define FDC_ISPNP 0x80
|
#define FDC_ISPNP 0x80
|
||||||
#define FDC_ISPCMCIA 0x100
|
#define FDC_ISPCMCIA 0x100
|
||||||
struct fd_data *fd;
|
struct fd_data *fd; /* The active drive */
|
||||||
int fdu; /* the active drive */
|
|
||||||
enum fdc_states state;
|
|
||||||
int retry;
|
int retry;
|
||||||
int fdout; /* mirror of the w/o digital output reg */
|
int fdout; /* mirror of the w/o digital output reg */
|
||||||
u_int status[7]; /* copy of the registers */
|
u_int status[7]; /* copy of the registers */
|
||||||
enum fdc_type fdct; /* chip version of FDC */
|
enum fdc_type fdct; /* chip version of FDC */
|
||||||
int fdc_errs; /* number of logged errors */
|
int fdc_errs; /* number of logged errors */
|
||||||
int dma_overruns; /* number of DMA overruns */
|
|
||||||
struct bio_queue_head head;
|
struct bio_queue_head head;
|
||||||
struct bio *bp; /* active buffer */
|
struct bio *bp; /* active buffer */
|
||||||
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
|
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
|
||||||
|
@ -104,23 +64,13 @@ struct fdc_data
|
||||||
bus_space_handle_t porth;
|
bus_space_handle_t porth;
|
||||||
bus_space_tag_t ctlt;
|
bus_space_tag_t ctlt;
|
||||||
bus_space_handle_t ctlh;
|
bus_space_handle_t ctlh;
|
||||||
|
int ctl_off;
|
||||||
void *fdc_intr;
|
void *fdc_intr;
|
||||||
struct device *fdc_dev;
|
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;
|
extern devclass_t fdc_devclass;
|
||||||
|
|
||||||
enum fdc_device_ivars {
|
enum fdc_device_ivars {
|
||||||
|
@ -131,15 +81,12 @@ enum fdc_device_ivars {
|
||||||
__BUS_ACCESSOR(fdc, fdunit, FDC, FDUNIT, int);
|
__BUS_ACCESSOR(fdc, fdunit, FDC, FDUNIT, int);
|
||||||
__BUS_ACCESSOR(fdc, fdtype, FDC, FDTYPE, 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 *);
|
void fdc_release_resources(struct fdc_data *);
|
||||||
int fdc_attach(device_t);
|
int fdc_attach(device_t);
|
||||||
int fdc_hints_probe(device_t);
|
int fdc_hints_probe(device_t);
|
||||||
int fdc_detach(device_t dev);
|
int fdc_detach(device_t dev);
|
||||||
device_t fdc_add_child(device_t, const char *, int);
|
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_print_child(device_t, device_t);
|
||||||
int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
|
int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
|
||||||
int fdc_write_ivar(device_t, device_t, int, uintptr_t);
|
int fdc_write_ivar(device_t, device_t, int, uintptr_t);
|
||||||
|
|
|
@ -44,44 +44,41 @@ struct fd_formb {
|
||||||
int cyl, head;
|
int cyl, head;
|
||||||
int transfer_rate; /* FDC_???KBPS */
|
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
|
* data to write into id fields;
|
||||||
* it is hardware-dependent since it exactly
|
* for obscure formats, they mustn't match
|
||||||
* matches the byte sequence to write to FDC
|
* the real values (but mostly do)
|
||||||
* during its `format track' operation
|
|
||||||
*/
|
*/
|
||||||
u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */
|
u_char cylno; /* 0 thru 79 (or 39) */
|
||||||
u_char nsecs; /* must be <= FD_MAX_NSEC */
|
u_char headno; /* 0, or 1 */
|
||||||
u_char gaplen; /* GAP 3 length; usually 84 */
|
u_char secno; /* starting at 1! */
|
||||||
u_char fillbyte; /* usually 0xf6 */
|
u_char secsize; /* usually 2 */
|
||||||
struct fd_idfield_data {
|
} idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */
|
||||||
/*
|
|
||||||
* 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 */
|
|
||||||
} format_info;
|
} format_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* make life easier */
|
/* make life easier */
|
||||||
# define fd_formb_secshift format_info.structured.secshift
|
# define fd_formb_secshift format_info.secshift
|
||||||
# define fd_formb_nsecs format_info.structured.nsecs
|
# define fd_formb_nsecs format_info.nsecs
|
||||||
# define fd_formb_gaplen format_info.structured.gaplen
|
# define fd_formb_gaplen format_info.gaplen
|
||||||
# define fd_formb_fillbyte format_info.structured.fillbyte
|
# define fd_formb_fillbyte format_info.fillbyte
|
||||||
/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */
|
/* 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_cylno(i) format_info.idfields[i].cylno
|
||||||
# define fd_formb_headno(i) format_info.structured.idfields[i].headno
|
# define fd_formb_headno(i) format_info.idfields[i].headno
|
||||||
# define fd_formb_secno(i) format_info.structured.idfields[i].secno
|
# define fd_formb_secno(i) format_info.idfields[i].secno
|
||||||
# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize
|
# define fd_formb_secsize(i) format_info.idfields[i].secsize
|
||||||
|
|
||||||
struct fd_type {
|
struct fd_type {
|
||||||
int sectrac; /* sectors per track */
|
int sectrac; /* sectors per track */
|
||||||
|
@ -99,6 +96,7 @@ struct fd_type {
|
||||||
#define FL_MFM 0x0001 /* MFM recording */
|
#define FL_MFM 0x0001 /* MFM recording */
|
||||||
#define FL_2STEP 0x0002 /* 2 steps between cylinders */
|
#define FL_2STEP 0x0002 /* 2 steps between cylinders */
|
||||||
#define FL_PERPND 0x0004 /* perpendicular recording */
|
#define FL_PERPND 0x0004 /* perpendicular recording */
|
||||||
|
#define FL_AUTO 0x0008 /* autodetect format */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fdc_status {
|
struct fdc_status {
|
||||||
|
@ -133,8 +131,6 @@ enum fd_drivetype {
|
||||||
#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */
|
#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */
|
||||||
#define FD_SOPTS _IOW('F', 65, int)
|
#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_CLRERR _IO('F', 67) /* clear error counter */
|
||||||
|
|
||||||
#define FD_READID _IOWR('F', 68, struct fdc_readid) /* read ID field */
|
#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_NOERRLOG 0x002 /* no "hard error" kernel log messages */
|
||||||
#define FDOPT_NOERROR 0x0004 /* do not indicate errors, caller will use
|
#define FDOPT_NOERROR 0x0004 /* do not indicate errors, caller will use
|
||||||
FD_GSTAT in order to obtain status */
|
FD_GSTAT in order to obtain status */
|
||||||
|
#ifdef PC98
|
||||||
#define FDOPT_AUTOSEL 0x8000 /* read/only option: device performs media
|
#define FDOPT_AUTOSEL 0x8000 /* read/only option: device performs media
|
||||||
* autoselection */
|
* autoselection */
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transfer rate definitions. Used in the structures above. They
|
* 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_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */
|
||||||
#define FDC_1MBPS 0x03 /* 1MPBS 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_ */
|
#endif /* !_MACHINE_IOCTL_FD_H_ */
|
||||||
|
|
|
@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
|
||||||
#include "fdutil.h"
|
#include "fdutil.h"
|
||||||
|
|
||||||
|
|
||||||
static int debug = -1, format, verbose, show = 1, showfmt;
|
static int format, verbose, show = 1, showfmt;
|
||||||
static char *fmtstring;
|
static char *fmtstring;
|
||||||
|
|
||||||
static void showdev(enum fd_drivetype, const char *);
|
static void showdev(enum fd_drivetype, const char *);
|
||||||
|
@ -72,20 +72,14 @@ main(int argc, char **argv)
|
||||||
enum fd_drivetype type;
|
enum fd_drivetype type;
|
||||||
struct fd_type ft, newft, *fdtp;
|
struct fd_type ft, newft, *fdtp;
|
||||||
const char *name, *descr;
|
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) {
|
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':
|
case 'F':
|
||||||
showfmt = 1;
|
showfmt = 1;
|
||||||
show = 0;
|
show = 0;
|
||||||
|
@ -141,6 +135,11 @@ mode = O_RDONLY | O_NONBLOCK;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (autofmt) {
|
||||||
|
memset(&newft, 0, sizeof newft);
|
||||||
|
ft = newft;
|
||||||
|
}
|
||||||
|
|
||||||
if (format) {
|
if (format) {
|
||||||
getname(type, &name, &descr);
|
getname(type, &name, &descr);
|
||||||
fdtp = get_fmt(format, type);
|
fdtp = get_fmt(format, type);
|
||||||
|
@ -195,6 +194,10 @@ mode = O_RDONLY | O_NONBLOCK;
|
||||||
printf("%sPERPENDICULAR", s);
|
printf("%sPERPENDICULAR", s);
|
||||||
s = ",";
|
s = ",";
|
||||||
}
|
}
|
||||||
|
if (ft.flags & FL_AUTO) {
|
||||||
|
printf("%sAUTO", s);
|
||||||
|
s = ",";
|
||||||
|
}
|
||||||
printf(">\n");
|
printf(">\n");
|
||||||
} else {
|
} else {
|
||||||
print_fmt(ft);
|
print_fmt(ft);
|
||||||
|
@ -208,11 +211,5 @@ mode = O_RDONLY | O_NONBLOCK;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug != -1) {
|
|
||||||
if (ioctl(fd, FD_DEBUG, &debug) == -1)
|
|
||||||
err(EX_OSERR, "ioctl(FD_DEBUG)");
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,13 +268,8 @@ main(int argc, char **argv)
|
||||||
parse_fmt(fmtstring, type, fdt, &newft);
|
parse_fmt(fmtstring, type, fdt, &newft);
|
||||||
fdt = newft;
|
fdt = newft;
|
||||||
}
|
}
|
||||||
if (fdopts & FDOPT_AUTOSEL) {
|
if (ioctl(fd, FD_STYPE, &fdt) < 0)
|
||||||
if (ioctl(fd, FD_STYPE, &fdt) < 0)
|
err(EX_OSERR, "ioctl(FD_STYPE)");
|
||||||
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)
|
if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
|
||||||
err(EX_OSERR, "fcntl(F_GETFL)");
|
err(EX_OSERR, "fcntl(F_GETFL)");
|
||||||
flags &= ~O_NONBLOCK;
|
flags &= ~O_NONBLOCK;
|
||||||
|
|
|
@ -59,7 +59,9 @@ printstatus(struct fdc_status *fdcsp, int terse)
|
||||||
fdcsp->status[5] & 0xff,
|
fdcsp->status[5] & 0xff,
|
||||||
fdcsp->status[6] & 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",
|
sprintf(msgbuf, "unexcpted interrupt code %#x",
|
||||||
fdcsp->status[0] & NE7_ST0_IC_RC);
|
fdcsp->status[0] & NE7_ST0_IC_RC);
|
||||||
} else {
|
} else {
|
||||||
|
@ -85,98 +87,60 @@ printstatus(struct fdc_status *fdcsp, int terse)
|
||||||
fputs(msgbuf, stderr);
|
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[] = {
|
static struct fd_type fd_types_288m[] = {
|
||||||
{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */
|
|
||||||
#if 0
|
#if 0
|
||||||
{ 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */
|
{ FDF_3_2880 },
|
||||||
{ 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 */
|
|
||||||
#endif
|
#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[] = {
|
static struct fd_type fd_types_144m[] = {
|
||||||
#if 0
|
{ FDF_3_1722 },
|
||||||
{ 21,2,0xFF,0x04,82,3444,2,2,0x0C,2,0,FL_MFM }, /* 1.72M in 3mode */
|
{ FDF_3_1476 },
|
||||||
{ 18,2,0xFF,0x1B,82,2952,2,2,0x54,1,0,FL_MFM }, /* 1.48M in 3mode */
|
{ FDF_3_1440 },
|
||||||
#endif
|
{ FDF_3_1200 },
|
||||||
{ 18,2,0xFF,0x1B,80,2880,2,2,0x54,1,0,FL_MFM }, /* 1.44M in 3mode */
|
{ FDF_3_820 },
|
||||||
{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */
|
{ FDF_3_800 },
|
||||||
#if 0
|
{ FDF_3_720 },
|
||||||
{ 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */
|
{ 0 }
|
||||||
{ 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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#else /* PC98 */
|
static struct fd_type fd_types_12m[] = {
|
||||||
|
{ FDF_5_1200 },
|
||||||
static struct fd_type fd_types_288m[] =
|
{ FDF_5_1230 },
|
||||||
{
|
{ FDF_5_1480 },
|
||||||
#if 0
|
{ FDF_5_1440 },
|
||||||
{ 36,2,0xFF,0x1B,80,5760,FDC_1MBPS, 2,0x4C,1,1,FL_MFM|FL_PERPND } /*2.88M*/
|
{ FDF_5_820 },
|
||||||
#endif
|
{ FDF_5_800 },
|
||||||
{ 21,2,0xFF,0x04,82,3444,FDC_500KBPS,2,0x0C,2,0,FL_MFM }, /* 1.72M */
|
{ FDF_5_720 },
|
||||||
{ 18,2,0xFF,0x1B,82,2952,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.48M */
|
{ FDF_5_360 | FL_2STEP },
|
||||||
{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.44M */
|
{ FDF_5_640 },
|
||||||
{ 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* 1.2M */
|
{ 0 }
|
||||||
{ 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[] =
|
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[] =
|
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'.
|
* 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:
|
default:
|
||||||
abort(); /* paranoia */
|
abort(); /* paranoia */
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
case FDT_360K:
|
case FDT_360K:
|
||||||
case FDT_720K:
|
case FDT_720K:
|
||||||
if (j == 250)
|
if (j == 250)
|
||||||
|
@ -292,23 +255,22 @@ parse_fmt(const char *s, enum fd_drivetype type,
|
||||||
else
|
else
|
||||||
errx(EX_USAGE, "bad speed %d", j);
|
errx(EX_USAGE, "bad speed %d", j);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
case FDT_12M:
|
case FDT_12M:
|
||||||
if (j == 300)
|
if (j == 300)
|
||||||
out->trans = FDC_300KBPS;
|
out->trans = FDC_300KBPS;
|
||||||
|
else if (j == 250)
|
||||||
|
out->trans = FDC_250KBPS;
|
||||||
else if (j == 500)
|
else if (j == 500)
|
||||||
out->trans = FDC_500KBPS;
|
out->trans = FDC_500KBPS;
|
||||||
else
|
else
|
||||||
errx(EX_USAGE, "bad speed %d", j);
|
errx(EX_USAGE, "bad speed %d", j);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
case FDT_288M:
|
case FDT_288M:
|
||||||
if (j == 1000)
|
if (j == 1000)
|
||||||
out->trans = FDC_1MBPS;
|
out->trans = FDC_1MBPS;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
#endif
|
|
||||||
case FDT_144M:
|
case FDT_144M:
|
||||||
if (j == 250)
|
if (j == 250)
|
||||||
out->trans = FDC_250KBPS;
|
out->trans = FDC_250KBPS;
|
||||||
|
@ -353,6 +315,10 @@ parse_fmt(const char *s, enum fd_drivetype type,
|
||||||
out->flags |= FL_MFM;
|
out->flags |= FL_MFM;
|
||||||
else if (strcmp(s1, "-mfm") == 0)
|
else if (strcmp(s1, "-mfm") == 0)
|
||||||
out->flags &= ~FL_MFM;
|
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)
|
else if (strcmp(s1, "+2step") == 0)
|
||||||
out->flags |= FL_2STEP;
|
out->flags |= FL_2STEP;
|
||||||
else if (strcmp(s1, "-2step") == 0)
|
else if (strcmp(s1, "-2step") == 0)
|
||||||
|
@ -399,6 +365,8 @@ print_fmt(struct fd_type in)
|
||||||
printf(",+2step");
|
printf(",+2step");
|
||||||
if (in.flags & FL_PERPND)
|
if (in.flags & FL_PERPND)
|
||||||
printf(",+perpnd");
|
printf(",+perpnd");
|
||||||
|
if (in.flags & FL_AUTO)
|
||||||
|
printf(",+auto");
|
||||||
putc('\n', stdout);
|
putc('\n', stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +386,6 @@ get_fmt(int size, enum fd_drivetype type)
|
||||||
default:
|
default:
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
case FDT_360K:
|
case FDT_360K:
|
||||||
fdtp = fd_types_360k;
|
fdtp = fd_types_360k;
|
||||||
n = sizeof fd_types_360k / sizeof(struct fd_type);
|
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;
|
fdtp = fd_types_720k;
|
||||||
n = sizeof fd_types_720k / sizeof(struct fd_type);
|
n = sizeof fd_types_720k / sizeof(struct fd_type);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
case FDT_12M:
|
case FDT_12M:
|
||||||
fdtp = fd_types_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);
|
n = sizeof fd_types_144m / sizeof(struct fd_type);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
case FDT_288M:
|
case FDT_288M:
|
||||||
fdtp = fd_types_288m;
|
fdtp = fd_types_288m;
|
||||||
n = sizeof fd_types_288m / sizeof(struct fd_type);
|
n = sizeof fd_types_288m / sizeof(struct fd_type);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == -1)
|
if (size == -1)
|
||||||
return fd_types_auto;
|
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)
|
if (((128 << fdtp->secsize) * fdtp->size / 1024) == size)
|
||||||
return (fdtp);
|
return (fdtp);
|
||||||
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,35 +456,29 @@ getname(enum fd_drivetype t, const char **name, const char **descr)
|
||||||
*descr = "unknown drive type";
|
*descr = "unknown drive type";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
case FDT_360K:
|
case FDT_360K:
|
||||||
*name = "360K";
|
*name = "360K";
|
||||||
*descr = "5.25\" double-density";
|
*descr = "5.25\" double-density";
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
case FDT_12M:
|
case FDT_12M:
|
||||||
*name = "1.2M";
|
*name = "1.2M";
|
||||||
*descr = "5.25\" high-density";
|
*descr = "5.25\" high-density";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
case FDT_720K:
|
case FDT_720K:
|
||||||
*name = "720K";
|
*name = "720K";
|
||||||
*descr = "3.5\" double-density";
|
*descr = "3.5\" double-density";
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
case FDT_144M:
|
case FDT_144M:
|
||||||
*name = "1.44M";
|
*name = "1.44M";
|
||||||
*descr = "3.5\" high-density";
|
*descr = "3.5\" high-density";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
case FDT_288M:
|
case FDT_288M:
|
||||||
*name = "2.88M";
|
*name = "2.88M";
|
||||||
*descr = "3.5\" extra-density";
|
*descr = "3.5\" extra-density";
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue