2004-07-12 20:49:26 +00:00
|
|
|
/*-
|
2004-08-20 15:14:25 +00:00
|
|
|
* Copyright (c) 2004 Poul-Henning Kamp
|
1993-06-12 14:58:17 +00:00
|
|
|
* Copyright (c) 1990 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* Don Ahn.
|
|
|
|
*
|
1998-12-12 08:16:01 +00:00
|
|
|
* Libretto PCMCIA floppy support by David Horwitt (dhorwitt@ucsd.edu)
|
|
|
|
* aided by the Linux floppy driver modifications from David Bateman
|
|
|
|
* (dbateman@eng.uts.edu.au).
|
|
|
|
*
|
1995-01-11 16:13:01 +00:00
|
|
|
* Copyright (c) 1993, 1994 by
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
* jc@irbs.UUCP (John Capo)
|
|
|
|
* vak@zebub.msk.su (Serge Vakulenko)
|
|
|
|
* ache@astral.msk.su (Andrew A. Chernov)
|
1995-01-11 16:13:01 +00:00
|
|
|
*
|
|
|
|
* Copyright (c) 1993, 1994, 1995 by
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
* joerg_wunsch@uriah.sax.de (Joerg Wunsch)
|
1995-01-06 15:20:00 +00:00
|
|
|
* dufault@hda.com (Peter Dufault)
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
*
|
2001-05-14 20:20:11 +00:00
|
|
|
* Copyright (c) 2001 Joerg Wunsch,
|
2001-06-03 20:41:21 +00:00
|
|
|
* joerg_wunsch@uriah.heep.sax.de (Joerg Wunsch)
|
2001-05-14 20:20:11 +00:00
|
|
|
*
|
1993-06-12 14:58:17 +00:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2001-06-28 12:35:28 +00:00
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
1993-06-12 14:58:17 +00:00
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
1993-09-15 23:27:45 +00:00
|
|
|
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91
|
2004-08-20 15:14:25 +00:00
|
|
|
*
|
1993-06-12 14:58:17 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-11 00:34:37 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
1997-09-16 07:45:45 +00:00
|
|
|
#include "opt_fdc.h"
|
1994-02-07 04:27:13 +00:00
|
|
|
|
|
|
|
#include <sys/param.h>
|
2000-05-05 09:59:14 +00:00
|
|
|
#include <sys/bio.h>
|
1999-04-16 21:22:55 +00:00
|
|
|
#include <sys/bus.h>
|
1998-09-15 08:15:30 +00:00
|
|
|
#include <sys/devicestat.h>
|
2002-09-20 12:52:03 +00:00
|
|
|
#include <sys/disk.h>
|
1999-04-16 21:22:55 +00:00
|
|
|
#include <sys/fcntl.h>
|
2001-06-06 06:15:03 +00:00
|
|
|
#include <sys/fdcio.h>
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
#include <sys/filio.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/kernel.h>
|
2004-08-20 15:14:25 +00:00
|
|
|
#include <sys/kthread.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/lock.h>
|
1994-02-07 04:27:13 +00:00
|
|
|
#include <sys/malloc.h>
|
1999-04-16 21:22:55 +00:00
|
|
|
#include <sys/module.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/mutex.h>
|
2006-11-06 13:42:10 +00:00
|
|
|
#include <sys/priv.h>
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
#include <sys/proc.h>
|
1999-04-16 21:22:55 +00:00
|
|
|
#include <sys/rman.h>
|
2004-08-20 15:14:25 +00:00
|
|
|
#include <sys/sysctl.h>
|
2004-07-07 22:35:27 +00:00
|
|
|
#include <sys/systm.h>
|
1999-04-16 21:22:55 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
#include <geom/geom.h>
|
|
|
|
|
2004-07-13 02:42:23 +00:00
|
|
|
#include <machine/bus.h>
|
1999-04-16 21:22:55 +00:00
|
|
|
#include <machine/clock.h>
|
1995-01-06 15:20:00 +00:00
|
|
|
#include <machine/stdarg.h>
|
1999-04-16 21:22:55 +00:00
|
|
|
|
|
|
|
#include <isa/isavar.h>
|
1999-05-31 18:39:17 +00:00
|
|
|
#include <isa/isareg.h>
|
2004-07-07 22:35:27 +00:00
|
|
|
#include <dev/fdc/fdcvar.h>
|
1999-05-31 18:39:17 +00:00
|
|
|
#include <isa/rtc.h>
|
1999-04-16 21:22:55 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
#include <dev/ic/nec765.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Runtime configuration hints/flags
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* configuration flags for fd */
|
|
|
|
#define FD_TYPEMASK 0x0f /* drive type, matches enum
|
|
|
|
* fd_drivetype; on i386 machines, if
|
|
|
|
* given as 0, use RTC type for fd0
|
|
|
|
* and fd1 */
|
2008-11-15 01:43:34 +00:00
|
|
|
#define FD_NO_CHLINE 0x10 /* drive does not support changeline
|
|
|
|
* aka. unit attention */
|
2004-08-20 15:14:25 +00:00
|
|
|
#define FD_NO_PROBE 0x20 /* don't probe drive (seek test), just
|
|
|
|
* assume it is there */
|
2002-03-26 19:16:37 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/*
|
|
|
|
* Things that could conceiveably considered parameters or tweakables
|
|
|
|
*/
|
1997-10-19 13:12:02 +00:00
|
|
|
|
2001-07-09 20:46:45 +00:00
|
|
|
/*
|
2004-08-20 15:14:25 +00:00
|
|
|
* Maximal number of bytes in a cylinder.
|
|
|
|
* This is used for ISADMA bouncebuffer allocation and sets the max
|
|
|
|
* xfersize we support.
|
|
|
|
*
|
2004-09-24 13:04:49 +00:00
|
|
|
* 2.88M format has 2 x 36 x 512, allow for hacked up density.
|
2001-07-09 20:46:45 +00:00
|
|
|
*/
|
2004-08-20 15:14:25 +00:00
|
|
|
#define MAX_BYTES_PER_CYL (2 * 40 * 512)
|
1995-01-06 15:20:00 +00:00
|
|
|
|
2002-05-12 15:24:21 +00:00
|
|
|
/*
|
|
|
|
* Timeout value for the PIO loops to wait until the FDC main status
|
|
|
|
* register matches our expectations (request for master, direction
|
|
|
|
* bit). This is supposed to be a number of microseconds, although
|
|
|
|
* timing might actually not be very accurate.
|
|
|
|
*
|
|
|
|
* Timeouts of 100 msec are believed to be required for some broken
|
|
|
|
* (old) hardware.
|
|
|
|
*/
|
|
|
|
#define FDSTS_TIMEOUT 100000
|
|
|
|
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
/*
|
2004-08-20 15:14:25 +00:00
|
|
|
* After this many errors, stop whining. Close will reset this count.
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
*/
|
2004-09-24 13:04:49 +00:00
|
|
|
#define FDC_ERRMAX 100
|
1993-12-16 04:28:42 +00:00
|
|
|
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
/*
|
2004-08-20 15:14:25 +00:00
|
|
|
* AutoDensity search lists for each drive type.
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
*/
|
2004-08-20 15:14:25 +00:00
|
|
|
|
|
|
|
static struct fd_type fd_searchlist_360k[] = {
|
|
|
|
{ FDF_5_360 },
|
|
|
|
{ 0 }
|
1993-06-12 14:58:17 +00:00
|
|
|
};
|
|
|
|
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
static struct fd_type fd_searchlist_12m[] = {
|
2004-08-20 15:14:25 +00:00
|
|
|
{ FDF_5_1200 | FL_AUTO },
|
|
|
|
{ FDF_5_360 | FL_2STEP | FL_AUTO},
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct fd_type fd_searchlist_720k[] = {
|
|
|
|
{ FDF_3_720 },
|
|
|
|
{ 0 }
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct fd_type fd_searchlist_144m[] = {
|
2004-08-20 15:14:25 +00:00
|
|
|
{ FDF_3_1440 | FL_AUTO},
|
|
|
|
{ FDF_3_720 | FL_AUTO},
|
|
|
|
{ 0 }
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct fd_type fd_searchlist_288m[] = {
|
2004-08-20 15:14:25 +00:00
|
|
|
{ FDF_3_1440 | FL_AUTO },
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
#if 0
|
2004-08-20 15:14:25 +00:00
|
|
|
{ FDF_3_2880 | FL_AUTO }, /* XXX: probably doesn't work */
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
#endif
|
2004-08-20 15:14:25 +00:00
|
|
|
{ FDF_3_720 | FL_AUTO},
|
|
|
|
{ 0 }
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
};
|
1995-01-11 16:13:01 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/*
|
|
|
|
* Order must match enum fd_drivetype in <sys/fdcio.h>.
|
|
|
|
*/
|
|
|
|
static struct fd_type *fd_native_types[] = {
|
|
|
|
NULL, /* FDT_NONE */
|
|
|
|
fd_searchlist_360k, /* FDT_360K */
|
|
|
|
fd_searchlist_12m, /* FDT_12M */
|
|
|
|
fd_searchlist_720k, /* FDT_720K */
|
|
|
|
fd_searchlist_144m, /* FDT_144M */
|
2004-10-10 23:39:59 +00:00
|
|
|
fd_searchlist_288m, /* FDT_288M_1 (mapped to FDT_288M) */
|
2004-08-20 15:14:25 +00:00
|
|
|
fd_searchlist_288m, /* FDT_288M */
|
|
|
|
};
|
2001-06-11 10:48:10 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/*
|
|
|
|
* Internals start here
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* registers */
|
|
|
|
#define FDOUT 2 /* Digital Output Register (W) */
|
|
|
|
#define FDO_FDSEL 0x03 /* floppy device select */
|
|
|
|
#define FDO_FRST 0x04 /* floppy controller reset */
|
|
|
|
#define FDO_FDMAEN 0x08 /* enable floppy DMA and Interrupt */
|
|
|
|
#define FDO_MOEN0 0x10 /* motor enable drive 0 */
|
|
|
|
#define FDO_MOEN1 0x20 /* motor enable drive 1 */
|
|
|
|
#define FDO_MOEN2 0x40 /* motor enable drive 2 */
|
|
|
|
#define FDO_MOEN3 0x80 /* motor enable drive 3 */
|
|
|
|
|
|
|
|
#define FDSTS 4 /* NEC 765 Main Status Register (R) */
|
2006-07-06 21:12:18 +00:00
|
|
|
#define FDDSR 4 /* Data Rate Select Register (W) */
|
2004-08-20 15:14:25 +00:00
|
|
|
#define FDDATA 5 /* NEC 765 Data Register (R/W) */
|
|
|
|
#define FDCTL 7 /* Control Register (W) */
|
|
|
|
|
|
|
|
/*
|
2005-01-19 07:46:38 +00:00
|
|
|
* The YE-DATA PC Card floppies use PIO to read in the data rather
|
|
|
|
* than DMA due to the wild variability of DMA for the PC Card
|
|
|
|
* devices. DMA was deleted from the PC Card specification in version
|
|
|
|
* 7.2 of the standard, but that post-dates the YE-DATA devices by many
|
|
|
|
* years.
|
|
|
|
*
|
|
|
|
* In addition, if we cannot setup the DMA resources for the ISA
|
|
|
|
* attachment, we'll use this same offset for data transfer. However,
|
|
|
|
* that almost certainly won't work.
|
2004-09-14 07:06:49 +00:00
|
|
|
*
|
|
|
|
* For this mode, offset 0 and 1 must be used to setup the transfer
|
2005-01-19 07:46:38 +00:00
|
|
|
* for this floppy. This is OK for PC Card YE Data devices, but for
|
|
|
|
* ISA this is likely wrong. These registers are only available on
|
|
|
|
* those systems that map them to the floppy drive. Newer systems do
|
|
|
|
* not do this, and we should likely prohibit access to them (or
|
|
|
|
* disallow NODMA to be set).
|
2004-08-20 15:14:25 +00:00
|
|
|
*/
|
2004-09-14 07:06:49 +00:00
|
|
|
#define FDBCDR 0 /* And 1 */
|
|
|
|
#define FD_YE_DATAPORT 6 /* Drive Data port */
|
2004-08-20 15:14:25 +00:00
|
|
|
|
|
|
|
#define FDI_DCHG 0x80 /* diskette has been changed */
|
|
|
|
/* requires drive and motor being selected */
|
|
|
|
/* is cleared by any step pulse to drive */
|
|
|
|
|
|
|
|
/*
|
2004-09-24 13:04:49 +00:00
|
|
|
* We have three private BIO commands.
|
2004-08-20 15:14:25 +00:00
|
|
|
*/
|
|
|
|
#define BIO_PROBE BIO_CMD0
|
|
|
|
#define BIO_RDID BIO_CMD1
|
|
|
|
#define BIO_FMT BIO_CMD2
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2001-07-14 20:25:01 +00:00
|
|
|
/*
|
|
|
|
* Per drive structure (softc).
|
|
|
|
*/
|
1999-04-16 21:22:55 +00:00
|
|
|
struct fd_data {
|
2004-08-20 15:14:25 +00:00
|
|
|
u_char *fd_ioptr; /* IO pointer */
|
|
|
|
u_int fd_iosize; /* Size of IO chunks */
|
|
|
|
u_int fd_iocount; /* Outstanding requests */
|
1994-02-07 04:27:13 +00:00
|
|
|
struct fdc_data *fdc; /* pointer to controller structure */
|
1993-06-12 14:58:17 +00:00
|
|
|
int fdsu; /* this units number on this controller */
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
enum fd_drivetype type; /* drive type */
|
|
|
|
struct fd_type *ft; /* pointer to current type descriptor */
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fd_type fts; /* type descriptors */
|
|
|
|
int sectorsize;
|
1993-06-12 14:58:17 +00:00
|
|
|
int flags;
|
2004-08-20 15:14:25 +00:00
|
|
|
#define FD_WP (1<<0) /* Write protected */
|
|
|
|
#define FD_MOTOR (1<<1) /* motor should be on */
|
|
|
|
#define FD_MOTORWAIT (1<<2) /* motor should be on */
|
|
|
|
#define FD_EMPTY (1<<3) /* no media */
|
|
|
|
#define FD_NEWDISK (1<<4) /* media changed */
|
|
|
|
#define FD_ISADMA (1<<5) /* isa dma started */
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
int track; /* where we think the head is */
|
2004-08-20 15:14:25 +00:00
|
|
|
#define FD_NO_TRACK -2
|
|
|
|
int options; /* FDOPT_* */
|
|
|
|
struct callout toffhandle;
|
|
|
|
struct g_geom *fd_geom;
|
|
|
|
struct g_provider *fd_provider;
|
1999-04-16 21:22:55 +00:00
|
|
|
device_t dev;
|
2004-08-20 15:14:25 +00:00
|
|
|
struct bio_queue_head fd_bq;
|
1999-04-16 21:22:55 +00:00
|
|
|
};
|
2000-01-05 16:31:27 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
#define FD_NOT_VALID -2
|
2004-07-12 20:49:26 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static driver_intr_t fdc_intr;
|
2007-02-23 12:19:07 +00:00
|
|
|
static driver_filter_t fdc_intr_fast;
|
2004-08-20 15:14:25 +00:00
|
|
|
static void fdc_reset(struct fdc_data *);
|
2008-11-15 01:43:34 +00:00
|
|
|
static int fd_probe_disk(struct fd_data *, int *);
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
SYSCTL_NODE(_debug, OID_AUTO, fdc, CTLFLAG_RW, 0, "fdc driver");
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static int fifo_threshold = 8;
|
2004-09-24 20:33:52 +00:00
|
|
|
SYSCTL_INT(_debug_fdc, OID_AUTO, fifo, CTLFLAG_RW, &fifo_threshold, 0,
|
2004-08-20 15:14:25 +00:00
|
|
|
"FIFO threshold setting");
|
1994-02-07 04:27:13 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static int debugflags = 0;
|
|
|
|
SYSCTL_INT(_debug_fdc, OID_AUTO, debugflags, CTLFLAG_RW, &debugflags, 0,
|
|
|
|
"Debug flags");
|
|
|
|
|
|
|
|
static int retries = 10;
|
|
|
|
SYSCTL_INT(_debug_fdc, OID_AUTO, retries, CTLFLAG_RW, &retries, 0,
|
|
|
|
"Number of retries to attempt");
|
|
|
|
|
|
|
|
static int spec1 = 0xaf;
|
|
|
|
SYSCTL_INT(_debug_fdc, OID_AUTO, spec1, CTLFLAG_RW, &spec1, 0,
|
|
|
|
"Specification byte one (step-rate + head unload)");
|
|
|
|
|
|
|
|
static int spec2 = 0x10;
|
|
|
|
SYSCTL_INT(_debug_fdc, OID_AUTO, spec2, CTLFLAG_RW, &spec2, 0,
|
|
|
|
"Specification byte two (head load time + no-dma)");
|
|
|
|
|
|
|
|
static int settle;
|
|
|
|
SYSCTL_INT(_debug_fdc, OID_AUTO, settle, CTLFLAG_RW, &settle, 0,
|
|
|
|
"Head settling time in sec/hz");
|
|
|
|
|
|
|
|
static void
|
|
|
|
fdprinttype(struct fd_type *ft)
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,0x%x)",
|
|
|
|
ft->sectrac, ft->secsize, ft->datalen, ft->gap, ft->tracks,
|
|
|
|
ft->size, ft->trans, ft->heads, ft->f_gap, ft->f_inter,
|
|
|
|
ft->offset_side2, ft->flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fdsettype(struct fd_data *fd, struct fd_type *ft)
|
|
|
|
{
|
|
|
|
fd->ft = ft;
|
|
|
|
ft->size = ft->sectrac * ft->heads * ft->tracks;
|
|
|
|
fd->sectorsize = 128 << fd->ft->secsize;
|
|
|
|
}
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2001-07-14 20:25:01 +00:00
|
|
|
/*
|
|
|
|
* Bus space handling (access to low-level IO).
|
|
|
|
*/
|
2005-01-19 07:46:38 +00:00
|
|
|
__inline static void
|
|
|
|
fdregwr(struct fdc_data *fdc, int reg, uint8_t v)
|
|
|
|
{
|
|
|
|
|
|
|
|
bus_space_write_1(fdc->iot, fdc->ioh[reg], fdc->ioff[reg], v);
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline static uint8_t
|
|
|
|
fdregrd(struct fdc_data *fdc, int reg)
|
|
|
|
{
|
|
|
|
|
|
|
|
return bus_space_read_1(fdc->iot, fdc->ioh[reg], fdc->ioff[reg]);
|
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static void
|
|
|
|
fdctl_wr(struct fdc_data *fdc, u_int8_t v)
|
|
|
|
{
|
|
|
|
|
2005-01-19 07:46:38 +00:00
|
|
|
fdregwr(fdc, FDCTL, v);
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fdout_wr(struct fdc_data *fdc, u_int8_t v)
|
1999-11-11 08:48:40 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
|
2005-01-19 07:46:38 +00:00
|
|
|
fdregwr(fdc, FDOUT, v);
|
1999-11-11 08:48:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static u_int8_t
|
2004-08-20 15:14:25 +00:00
|
|
|
fdsts_rd(struct fdc_data *fdc)
|
1999-11-11 08:48:40 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
|
2005-01-19 07:46:38 +00:00
|
|
|
return fdregrd(fdc, FDSTS);
|
1999-11-11 08:48:40 +00:00
|
|
|
}
|
|
|
|
|
2006-07-06 21:12:18 +00:00
|
|
|
static void
|
|
|
|
fddsr_wr(struct fdc_data *fdc, u_int8_t v)
|
|
|
|
{
|
|
|
|
|
|
|
|
fdregwr(fdc, FDDSR, v);
|
|
|
|
}
|
|
|
|
|
1999-11-11 08:48:40 +00:00
|
|
|
static void
|
2004-08-20 15:14:25 +00:00
|
|
|
fddata_wr(struct fdc_data *fdc, u_int8_t v)
|
1999-11-11 08:48:40 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
|
2005-01-19 07:46:38 +00:00
|
|
|
fdregwr(fdc, FDDATA, v);
|
1999-11-11 08:48:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static u_int8_t
|
2004-08-20 15:14:25 +00:00
|
|
|
fddata_rd(struct fdc_data *fdc)
|
1999-11-11 08:48:40 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
|
2005-01-19 07:46:38 +00:00
|
|
|
return fdregrd(fdc, FDDATA);
|
1999-11-11 08:48:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static u_int8_t
|
2004-08-20 15:14:25 +00:00
|
|
|
fdin_rd(struct fdc_data *fdc)
|
1999-11-11 08:48:40 +00:00
|
|
|
{
|
|
|
|
|
2005-01-19 07:46:38 +00:00
|
|
|
return fdregrd(fdc, FDCTL);
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
1999-05-30 16:53:49 +00:00
|
|
|
|
2004-09-14 07:06:49 +00:00
|
|
|
/*
|
|
|
|
* Magic pseudo-DMA initialization for YE FDC. Sets count and
|
|
|
|
* direction.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
fdbcdr_wr(struct fdc_data *fdc, int iswrite, uint16_t count)
|
|
|
|
{
|
2005-01-19 07:46:38 +00:00
|
|
|
fdregwr(fdc, FDBCDR, (count - 1) & 0xff);
|
|
|
|
fdregwr(fdc, FDBCDR + 1,
|
|
|
|
(iswrite ? 0x80 : 0) | (((count - 1) >> 8) & 0x7f));
|
2004-09-14 07:06:49 +00:00
|
|
|
}
|
|
|
|
|
1995-01-06 15:20:00 +00:00
|
|
|
static int
|
1999-04-16 21:22:55 +00:00
|
|
|
fdc_err(struct fdc_data *fdc, const char *s)
|
1995-01-06 15:20:00 +00:00
|
|
|
{
|
1999-04-16 21:22:55 +00:00
|
|
|
fdc->fdc_errs++;
|
|
|
|
if (s) {
|
2000-01-08 09:33:09 +00:00
|
|
|
if (fdc->fdc_errs < FDC_ERRMAX)
|
|
|
|
device_printf(fdc->fdc_dev, "%s", s);
|
|
|
|
else if (fdc->fdc_errs == FDC_ERRMAX)
|
|
|
|
device_printf(fdc->fdc_dev, "too many errors, not "
|
|
|
|
"logging any more\n");
|
1995-10-04 07:01:23 +00:00
|
|
|
}
|
1995-05-30 08:16:23 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FDC IO functions, take care of the main status register, timeout
|
|
|
|
* in case the desired status bits are never set.
|
|
|
|
*
|
|
|
|
* These PIO loops initially start out with short delays between
|
|
|
|
* each iteration in the expectation that the required condition
|
|
|
|
* is usually met quickly, so it can be handled immediately.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
fdc_in(struct fdc_data *fdc, int *ptr)
|
|
|
|
{
|
|
|
|
int i, j, step;
|
|
|
|
|
|
|
|
step = 1;
|
|
|
|
for (j = 0; j < FDSTS_TIMEOUT; j += step) {
|
|
|
|
i = fdsts_rd(fdc) & (NE7_DIO | NE7_RQM);
|
|
|
|
if (i == (NE7_DIO|NE7_RQM)) {
|
|
|
|
i = fddata_rd(fdc);
|
|
|
|
if (ptr)
|
|
|
|
*ptr = i;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (i == NE7_RQM)
|
|
|
|
return (fdc_err(fdc, "ready for output in input\n"));
|
|
|
|
step += step;
|
|
|
|
DELAY(step);
|
|
|
|
}
|
|
|
|
return (fdc_err(fdc, bootverbose? "input ready timeout\n": 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fdc_out(struct fdc_data *fdc, int x)
|
|
|
|
{
|
|
|
|
int i, j, step;
|
|
|
|
|
|
|
|
step = 1;
|
|
|
|
for (j = 0; j < FDSTS_TIMEOUT; j += step) {
|
|
|
|
i = fdsts_rd(fdc) & (NE7_DIO | NE7_RQM);
|
|
|
|
if (i == NE7_RQM) {
|
|
|
|
fddata_wr(fdc, x);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (i == (NE7_DIO|NE7_RQM))
|
|
|
|
return (fdc_err(fdc, "ready for input in output\n"));
|
|
|
|
step += step;
|
|
|
|
DELAY(step);
|
|
|
|
}
|
|
|
|
return (fdc_err(fdc, bootverbose? "output ready timeout\n": 0));
|
1995-01-06 15:20:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-08-20 15:14:25 +00:00
|
|
|
* fdc_cmd: Send a command to the chip.
|
|
|
|
* Takes a varargs with this structure:
|
|
|
|
* # of output bytes
|
|
|
|
* output bytes as int [...]
|
|
|
|
* # of input bytes
|
|
|
|
* input bytes as int* [...]
|
1995-01-06 15:20:00 +00:00
|
|
|
*/
|
2004-08-20 15:14:25 +00:00
|
|
|
static int
|
|
|
|
fdc_cmd(struct fdc_data *fdc, int n_out, ...)
|
1995-01-06 15:20:00 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
u_char cmd = 0;
|
1995-01-06 15:20:00 +00:00
|
|
|
int n_in;
|
2004-08-20 15:14:25 +00:00
|
|
|
int n, i;
|
1995-01-06 15:20:00 +00:00
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, n_out);
|
2004-08-20 15:14:25 +00:00
|
|
|
for (n = 0; n < n_out; n++) {
|
|
|
|
i = va_arg(ap, int);
|
|
|
|
if (n == 0)
|
|
|
|
cmd = i;
|
|
|
|
if (fdc_out(fdc, i) < 0) {
|
1995-01-06 15:20:00 +00:00
|
|
|
char msg[50];
|
1998-12-04 22:54:57 +00:00
|
|
|
snprintf(msg, sizeof(msg),
|
1995-01-06 15:20:00 +00:00
|
|
|
"cmd %x failed at out byte %d of %d\n",
|
|
|
|
cmd, n + 1, n_out);
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc->flags |= FDC_NEEDS_RESET;
|
2005-02-28 05:14:45 +00:00
|
|
|
va_end(ap);
|
1999-04-16 21:22:55 +00:00
|
|
|
return fdc_err(fdc, msg);
|
1995-01-06 15:20:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
n_in = va_arg(ap, int);
|
2004-08-20 15:14:25 +00:00
|
|
|
for (n = 0; n < n_in; n++) {
|
1995-01-06 15:20:00 +00:00
|
|
|
int *ptr = va_arg(ap, int *);
|
2004-08-20 15:14:25 +00:00
|
|
|
if (fdc_in(fdc, ptr) < 0) {
|
1995-01-06 15:20:00 +00:00
|
|
|
char msg[50];
|
1998-12-04 22:54:57 +00:00
|
|
|
snprintf(msg, sizeof(msg),
|
1995-01-06 15:20:00 +00:00
|
|
|
"cmd %02x failed at in byte %d of %d\n",
|
|
|
|
cmd, n + 1, n_in);
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc->flags |= FDC_NEEDS_RESET;
|
2005-02-28 05:14:45 +00:00
|
|
|
va_end(ap);
|
1999-04-16 21:22:55 +00:00
|
|
|
return fdc_err(fdc, msg);
|
1995-01-06 15:20:00 +00:00
|
|
|
}
|
|
|
|
}
|
2005-02-28 05:14:45 +00:00
|
|
|
va_end(ap);
|
2004-08-20 15:14:25 +00:00
|
|
|
return (0);
|
1995-01-06 15:20:00 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static void
|
|
|
|
fdc_reset(struct fdc_data *fdc)
|
1997-09-17 20:16:17 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
int i, r[10];
|
1997-09-17 20:16:17 +00:00
|
|
|
|
2006-07-06 21:12:18 +00:00
|
|
|
if (fdc->fdct == FDC_ENHANCED) {
|
|
|
|
/* Try a software reset, default precomp, and 500 kb/s */
|
|
|
|
fddsr_wr(fdc, I8207X_DSR_SR);
|
|
|
|
} else {
|
|
|
|
/* Try a hardware reset, keep motor on */
|
|
|
|
fdout_wr(fdc, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN));
|
|
|
|
DELAY(100);
|
|
|
|
/* enable FDC, but defer interrupts a moment */
|
|
|
|
fdout_wr(fdc, fdc->fdout & ~FDO_FDMAEN);
|
|
|
|
}
|
2006-08-29 18:19:39 +00:00
|
|
|
DELAY(100);
|
|
|
|
fdout_wr(fdc, fdc->fdout);
|
2004-08-20 15:14:25 +00:00
|
|
|
|
|
|
|
/* XXX after a reset, silently believe the FDC will accept commands */
|
|
|
|
if (fdc_cmd(fdc, 3, NE7CMD_SPECIFY, spec1, spec2, 0))
|
|
|
|
device_printf(fdc->fdc_dev, " SPECIFY failed in reset\n");
|
|
|
|
|
|
|
|
if (fdc->fdct == FDC_ENHANCED) {
|
|
|
|
if (fdc_cmd(fdc, 4,
|
2006-09-08 21:46:01 +00:00
|
|
|
I8207X_CONFIG,
|
2004-08-20 15:14:25 +00:00
|
|
|
0,
|
|
|
|
0x40 | /* Enable Implied Seek */
|
|
|
|
0x10 | /* Polling disabled */
|
|
|
|
(fifo_threshold - 1), /* Fifo threshold */
|
|
|
|
0x00, /* Precomp track */
|
|
|
|
0))
|
|
|
|
device_printf(fdc->fdc_dev,
|
|
|
|
" CONFIGURE failed in reset\n");
|
|
|
|
if (debugflags & 1) {
|
|
|
|
if (fdc_cmd(fdc, 1,
|
2006-09-08 21:46:01 +00:00
|
|
|
I8207X_DUMPREG,
|
2004-08-20 15:14:25 +00:00
|
|
|
10, &r[0], &r[1], &r[2], &r[3], &r[4],
|
|
|
|
&r[5], &r[6], &r[7], &r[8], &r[9]))
|
|
|
|
device_printf(fdc->fdc_dev,
|
|
|
|
" DUMPREG failed in reset\n");
|
|
|
|
for (i = 0; i < 10; i++)
|
|
|
|
printf(" %02x", r[i]);
|
|
|
|
printf("\n");
|
1997-09-17 20:16:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1995-12-10 13:40:44 +00:00
|
|
|
static int
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc_sense_drive(struct fdc_data *fdc, int *st3p)
|
1995-01-06 15:20:00 +00:00
|
|
|
{
|
|
|
|
int st3;
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
if (fdc_cmd(fdc, 2, NE7CMD_SENSED, fdc->fd->fdsu, 1, &st3))
|
|
|
|
return (fdc_err(fdc, "Sense Drive Status failed\n"));
|
1995-01-06 15:20:00 +00:00
|
|
|
if (st3p)
|
|
|
|
*st3p = st3;
|
2004-08-20 15:14:25 +00:00
|
|
|
return (0);
|
1995-01-06 15:20:00 +00:00
|
|
|
}
|
|
|
|
|
1995-12-10 13:40:44 +00:00
|
|
|
static int
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc_sense_int(struct fdc_data *fdc, int *st0p, int *cylp)
|
1995-01-06 15:20:00 +00:00
|
|
|
{
|
1999-04-16 21:22:55 +00:00
|
|
|
int cyl, st0, ret;
|
1995-01-06 15:20:00 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
ret = fdc_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0);
|
1999-04-16 21:22:55 +00:00
|
|
|
if (ret) {
|
2004-08-20 15:14:25 +00:00
|
|
|
(void)fdc_err(fdc, "sense intr err reading stat reg 0\n");
|
|
|
|
return (ret);
|
1995-01-06 15:20:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (st0p)
|
|
|
|
*st0p = st0;
|
|
|
|
|
1999-04-16 21:22:55 +00:00
|
|
|
if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) {
|
1995-01-06 15:20:00 +00:00
|
|
|
/*
|
|
|
|
* There doesn't seem to have been an interrupt.
|
|
|
|
*/
|
2004-08-20 15:14:25 +00:00
|
|
|
return (FD_NOT_VALID);
|
1995-01-06 15:20:00 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
if (fdc_in(fdc, &cyl) < 0)
|
1999-04-16 21:22:55 +00:00
|
|
|
return fdc_err(fdc, "can't get cyl num\n");
|
1995-01-06 15:20:00 +00:00
|
|
|
|
|
|
|
if (cylp)
|
|
|
|
*cylp = cyl;
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
return (0);
|
1995-01-06 15:20:00 +00:00
|
|
|
}
|
|
|
|
|
1995-12-10 13:40:44 +00:00
|
|
|
static int
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc_read_status(struct fdc_data *fdc)
|
1995-01-06 15:20:00 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
int i, ret, status;
|
1995-03-16 18:17:34 +00:00
|
|
|
|
2001-07-14 20:25:01 +00:00
|
|
|
for (i = ret = 0; i < 7; i++) {
|
2004-08-20 15:14:25 +00:00
|
|
|
ret = fdc_in(fdc, &status);
|
1995-03-16 18:17:34 +00:00
|
|
|
fdc->status[i] = status;
|
|
|
|
if (ret != 0)
|
1995-01-06 15:20:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
fdc->flags |= FDC_STAT_VALID;
|
|
|
|
else
|
|
|
|
fdc->flags &= ~FDC_STAT_VALID;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/*
|
|
|
|
* Select this drive
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
fd_select(struct fd_data *fd)
|
2000-01-05 16:31:27 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fdc_data *fdc;
|
2000-01-05 16:31:27 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* XXX: lock controller */
|
|
|
|
fdc = fd->fdc;
|
|
|
|
fdc->fdout &= ~FDO_FDSEL;
|
|
|
|
fdc->fdout |= FDO_FDMAEN | FDO_FRST | fd->fdsu;
|
|
|
|
fdout_wr(fdc, fdc->fdout);
|
2000-01-05 16:31:27 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static void
|
|
|
|
fd_turnon(void *arg)
|
2000-01-05 16:31:27 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fd_data *fd;
|
|
|
|
struct bio *bp;
|
|
|
|
int once;
|
|
|
|
|
|
|
|
fd = arg;
|
2006-02-23 19:11:16 +00:00
|
|
|
mtx_assert(&fd->fdc->fdc_mtx, MA_OWNED);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->flags &= ~FD_MOTORWAIT;
|
|
|
|
fd->flags |= FD_MOTOR;
|
|
|
|
once = 0;
|
|
|
|
for (;;) {
|
|
|
|
bp = bioq_takefirst(&fd->fd_bq);
|
|
|
|
if (bp == NULL)
|
|
|
|
break;
|
|
|
|
bioq_disksort(&fd->fdc->head, bp);
|
|
|
|
once = 1;
|
2000-01-05 16:31:27 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
if (once)
|
|
|
|
wakeup(&fd->fdc->head);
|
2004-07-12 20:49:26 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static void
|
|
|
|
fd_motor(struct fd_data *fd, int turnon)
|
2004-07-12 20:49:26 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fdc_data *fdc;
|
2004-07-12 20:49:26 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc = fd->fdc;
|
|
|
|
/*
|
|
|
|
mtx_assert(&fdc->fdc_mtx, MA_OWNED);
|
|
|
|
*/
|
|
|
|
if (turnon) {
|
|
|
|
fd->flags |= FD_MOTORWAIT;
|
|
|
|
fdc->fdout |= (FDO_MOEN0 << fd->fdsu);
|
|
|
|
callout_reset(&fd->toffhandle, hz, fd_turnon, fd);
|
|
|
|
} else {
|
2006-02-23 19:11:16 +00:00
|
|
|
callout_stop(&fd->toffhandle);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->flags &= ~(FD_MOTOR|FD_MOTORWAIT);
|
|
|
|
fdc->fdout &= ~(FDO_MOEN0 << fd->fdsu);
|
2004-07-12 20:49:26 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
fdout_wr(fdc, fdc->fdout);
|
2004-07-12 20:49:26 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static void
|
|
|
|
fd_turnoff(void *xfd)
|
2004-07-12 20:49:26 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fd_data *fd = xfd;
|
2004-07-12 20:49:26 +00:00
|
|
|
|
2006-02-23 19:11:16 +00:00
|
|
|
mtx_assert(&fd->fdc->fdc_mtx, MA_OWNED);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd_motor(fd, 0);
|
Make the Y-E Data PCMCIA floppy of the Toshiba Libretto work under
-current. It doesn't work yet as stable as the 3.x/PAO version of the
driver does, however, i get occasional `FDC direction bit not set' and
other weird messages, but it basically works at least.
The old (defunct) #ifdef FDC_YE stuff has been eliminated completely
now, PCMCIA-FDC specific functions have been implemented differently
where needed.
Unfortunately, due to the fact that the traditional PeeCee FDC with
its funny non-contiguous register space (one register for WD1003
harddisk controllers is interleaved into the FDC register set), and
Peter's subsequent changes involving two different bus space handles
for normal FDCs, the changes required for the Y-E stuff are more
complex than i'd love them to be. I've done my best to keep the logic
for normal FDCs intact.
Since the Y-E FDC seems to lose interrupts after a FDC reset
sometimes, i've also replaced the timeout logic in fd_turnoff() to
generate an artificial pseudo interrupt in case of a timeout while the
drive has still outstanding transfers waiting. This avoids the total
starvation of the driver that could be observed with highly damaged
media under 3.x/PAO. This part of the patch has been revied by bde
previously.
I've fixed a number of occasions where previous commits have been
missing the encapuslation of ISA DMA related functions inside
FDC_NODMA checks.
I've added one call to SET_BCDR() during preparation of the format
floppy operation. Floppy formatting has been totally broken before in
3.x/PAO (garbage ID fields have been written to the medium, causing
`wrong cylinder' errors upon media reading). This is just black
magic, i don't have the slightes idea _why_ this needs to be but just
copied over the hack that has been used by the PAO folks in the normal
read/write case anyway.
The entired device_busy() stuff seems to be pointless to me. In any
case, i had to add device_unbusy() calls symmetrical to the
device_busy() calls, otherwise the PCMCIA floppy driver could never be
deactivated. (As it used to be, it caused a `mark the device busier
and busier' situation.) IMHO, all block device drivers should be
marked busy based on active buffers still waiting for the driver, so
the device_unbusy() calls should probably go to biodone(). Only one
other driver (whose name escapes me at the moment) uses device_busy()
calls at all, so i question the value of all this...
I think this entire `device busy' logic simply doesn't fit for PCMCIA
&al. It cannot be the decision of some piece of kernel software to
declare a device `busy by now, you can't remove it', when the actual
physical power of removing it is the user pulling the card. The
kernel simply has to cope with the removal, however busy the device
might have been by the time of the removal, period. Perhaps a force
flag needs to be added?
Upon inserting the card a second time, i get:
WARNING: "fd" is usurping "fd"'s cdevsw[]
WARNING: "fd" is usurping "fd"'s bmaj
I suspect this is related to the XXX comment at the call to
cdevsw_add(). Does anybody know what the correct way is to cleanup
this?
2000-03-18 18:27:01 +00:00
|
|
|
}
|
|
|
|
|
1993-06-12 14:58:17 +00:00
|
|
|
/*
|
2004-09-24 13:04:49 +00:00
|
|
|
* fdc_intr - wake up the worker thread.
|
1993-06-12 14:58:17 +00:00
|
|
|
*/
|
2004-09-24 13:04:49 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static void
|
|
|
|
fdc_intr(void *arg)
|
1999-04-16 21:22:55 +00:00
|
|
|
{
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
wakeup(arg);
|
1999-04-16 21:22:55 +00:00
|
|
|
}
|
|
|
|
|
2007-02-23 12:19:07 +00:00
|
|
|
static int
|
|
|
|
fdc_intr_fast(void *arg)
|
|
|
|
{
|
|
|
|
|
|
|
|
wakeup(arg);
|
|
|
|
return(FILTER_HANDLED);
|
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/*
|
|
|
|
* fdc_pio(): perform programmed IO read/write for YE PCMCIA floppy.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
fdc_pio(struct fdc_data *fdc)
|
|
|
|
{
|
|
|
|
u_char *cptr;
|
|
|
|
struct bio *bp;
|
|
|
|
u_int count;
|
1999-04-16 21:22:55 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
bp = fdc->bp;
|
|
|
|
cptr = fdc->fd->fd_ioptr;
|
|
|
|
count = fdc->fd->fd_iosize;
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
if (bp->bio_cmd == BIO_READ) {
|
2004-09-14 07:06:49 +00:00
|
|
|
fdbcdr_wr(fdc, 0, count);
|
2005-01-19 07:46:38 +00:00
|
|
|
bus_space_read_multi_1(fdc->iot, fdc->ioh[FD_YE_DATAPORT],
|
|
|
|
fdc->ioff[FD_YE_DATAPORT], cptr, count);
|
2004-08-20 15:14:25 +00:00
|
|
|
} else {
|
2005-01-19 07:46:38 +00:00
|
|
|
bus_space_write_multi_1(fdc->iot, fdc->ioh[FD_YE_DATAPORT],
|
|
|
|
fdc->ioff[FD_YE_DATAPORT], cptr, count);
|
2004-09-14 07:06:49 +00:00
|
|
|
fdbcdr_wr(fdc, 0, count); /* needed? */
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
2004-07-15 16:39:40 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static int
|
|
|
|
fdc_biodone(struct fdc_data *fdc, int error)
|
2004-07-15 16:39:40 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fd_data *fd;
|
|
|
|
struct bio *bp;
|
2004-07-15 16:39:40 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
fd = fdc->fd;
|
|
|
|
bp = fdc->bp;
|
2000-01-05 16:31:27 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
|
|
|
if (--fd->fd_iocount == 0)
|
|
|
|
callout_reset(&fd->toffhandle, 4 * hz, fd_turnoff, fd);
|
|
|
|
fdc->bp = NULL;
|
|
|
|
fdc->fd = NULL;
|
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
|
|
|
if (bp->bio_to != NULL) {
|
|
|
|
if ((debugflags & 2) && fd->fdc->retry > 0)
|
|
|
|
printf("retries: %d\n", fd->fdc->retry);
|
|
|
|
g_io_deliver(bp, error);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
bp->bio_error = error;
|
|
|
|
bp->bio_flags |= BIO_DONE;
|
|
|
|
wakeup(bp);
|
2001-07-04 22:10:33 +00:00
|
|
|
return (0);
|
1999-04-16 21:22:55 +00:00
|
|
|
}
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static int retry_line;
|
1995-01-06 15:20:00 +00:00
|
|
|
|
1999-04-16 21:22:55 +00:00
|
|
|
static int
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc_worker(struct fdc_data *fdc)
|
1999-04-16 21:22:55 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fd_data *fd;
|
|
|
|
struct bio *bp;
|
|
|
|
int i, nsect;
|
|
|
|
int st0, st3, cyl, mfm, steptrac, cylinder, descyl, sec;
|
|
|
|
int head;
|
|
|
|
static int need_recal;
|
|
|
|
struct fdc_readid *idp;
|
|
|
|
struct fd_formb *finfo;
|
1999-04-16 21:22:55 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* Have we exhausted our retries ? */
|
|
|
|
bp = fdc->bp;
|
|
|
|
fd = fdc->fd;
|
|
|
|
if (bp != NULL &&
|
2005-08-30 23:12:18 +00:00
|
|
|
(fdc->retry >= retries || (fd->options & FDOPT_NORETRY))) {
|
2004-08-20 15:14:25 +00:00
|
|
|
if ((debugflags & 4))
|
|
|
|
printf("Too many retries (EIO)\n");
|
2008-11-15 01:43:34 +00:00
|
|
|
if (fdc->flags & FDC_NEEDS_RESET) {
|
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
|
|
|
fd->flags |= FD_EMPTY;
|
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
return (fdc_biodone(fdc, EIO));
|
|
|
|
}
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* Disable ISADMA if we bailed while it was active */
|
|
|
|
if (fd != NULL && (fd->flags & FD_ISADMA)) {
|
|
|
|
isa_dmadone(
|
|
|
|
bp->bio_cmd & BIO_READ ? ISADMA_READ : ISADMA_WRITE,
|
|
|
|
fd->fd_ioptr, fd->fd_iosize, fdc->dmachan);
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->flags &= ~FD_ISADMA;
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
2004-09-24 20:33:52 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* Unwedge the controller ? */
|
|
|
|
if (fdc->flags & FDC_NEEDS_RESET) {
|
|
|
|
fdc->flags &= ~FDC_NEEDS_RESET;
|
|
|
|
fdc_reset(fdc);
|
2007-02-23 23:06:10 +00:00
|
|
|
tsleep(fdc, PRIBIO, "fdcrst", hz);
|
2004-08-20 15:14:25 +00:00
|
|
|
/* Discard results */
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
fdc_sense_int(fdc, &st0, &cyl);
|
|
|
|
/* All drives must recal */
|
|
|
|
need_recal = 0xf;
|
2004-07-12 20:49:26 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* Pick up a request, if need be wait for it */
|
|
|
|
if (fdc->bp == NULL) {
|
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
|
|
|
do {
|
|
|
|
fdc->bp = bioq_takefirst(&fdc->head);
|
|
|
|
if (fdc->bp == NULL)
|
|
|
|
msleep(&fdc->head, &fdc->fdc_mtx,
|
|
|
|
PRIBIO, "-", hz);
|
2004-09-23 21:12:21 +00:00
|
|
|
} while (fdc->bp == NULL &&
|
|
|
|
(fdc->flags & FDC_KTHREAD_EXIT) == 0);
|
2004-08-20 15:14:25 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
2004-09-23 21:12:21 +00:00
|
|
|
|
|
|
|
if (fdc->bp == NULL)
|
|
|
|
/*
|
|
|
|
* Nothing to do, worker thread has been
|
|
|
|
* requested to stop.
|
|
|
|
*/
|
|
|
|
return (0);
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
bp = fdc->bp;
|
|
|
|
fd = fdc->fd = bp->bio_driver1;
|
|
|
|
fdc->retry = 0;
|
|
|
|
fd->fd_ioptr = bp->bio_data;
|
|
|
|
if (bp->bio_cmd & BIO_FMT) {
|
|
|
|
i = offsetof(struct fd_formb, fd_formb_cylno(0));
|
|
|
|
fd->fd_ioptr += i;
|
|
|
|
fd->fd_iosize = bp->bio_length - i;
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
}
|
1999-04-16 21:22:55 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* Select drive, setup params */
|
|
|
|
fd_select(fd);
|
2006-07-06 21:12:18 +00:00
|
|
|
if (fdc->fdct == FDC_ENHANCED)
|
|
|
|
fddsr_wr(fdc, fd->ft->trans);
|
|
|
|
else
|
|
|
|
fdctl_wr(fdc, fd->ft->trans);
|
1999-04-16 21:22:55 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
if (bp->bio_cmd & BIO_PROBE) {
|
2008-11-15 01:43:34 +00:00
|
|
|
if ((!(device_get_flags(fd->dev) & FD_NO_CHLINE) &&
|
|
|
|
!(fdin_rd(fdc) & FDI_DCHG) &&
|
|
|
|
!(fd->flags & FD_EMPTY)) ||
|
|
|
|
fd_probe_disk(fd, &need_recal) == 0)
|
2004-08-20 15:14:25 +00:00
|
|
|
return (fdc_biodone(fdc, 0));
|
2008-11-15 01:43:34 +00:00
|
|
|
return (1);
|
1999-04-16 21:22:55 +00:00
|
|
|
}
|
1995-05-30 08:16:23 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/*
|
|
|
|
* If we are dead just flush the requests
|
|
|
|
*/
|
|
|
|
if (fd->flags & FD_EMPTY)
|
|
|
|
return (fdc_biodone(fdc, ENXIO));
|
|
|
|
|
|
|
|
/* Check if we lost our media */
|
|
|
|
if (fdin_rd(fdc) & FDI_DCHG) {
|
|
|
|
if (debugflags & 0x40)
|
|
|
|
printf("Lost disk\n");
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->flags |= FD_EMPTY;
|
|
|
|
fd->flags |= FD_NEWDISK;
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
g_topology_lock();
|
2009-10-10 21:49:04 +00:00
|
|
|
g_orphan_provider(fd->fd_provider, ENXIO);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->fd_provider->flags |= G_PF_WITHER;
|
|
|
|
fd->fd_provider =
|
|
|
|
g_new_providerf(fd->fd_geom, fd->fd_geom->name);
|
|
|
|
g_error_provider(fd->fd_provider, 0);
|
|
|
|
g_topology_unlock();
|
|
|
|
return (fdc_biodone(fdc, ENXIO));
|
|
|
|
}
|
1995-05-30 08:16:23 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* Check if the floppy is write-protected */
|
|
|
|
if(bp->bio_cmd & (BIO_FMT | BIO_WRITE)) {
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if(fdc_sense_drive(fdc, &st3) != 0)
|
|
|
|
return (1);
|
|
|
|
if(st3 & NE7_ST3_WP)
|
|
|
|
return (fdc_biodone(fdc, EROFS));
|
|
|
|
}
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
mfm = (fd->ft->flags & FL_MFM)? NE7CMD_MFM: 0;
|
|
|
|
steptrac = (fd->ft->flags & FL_2STEP)? 2: 1;
|
|
|
|
i = fd->ft->sectrac * fd->ft->heads;
|
|
|
|
cylinder = bp->bio_pblkno / i;
|
|
|
|
descyl = cylinder * steptrac;
|
|
|
|
sec = bp->bio_pblkno % i;
|
|
|
|
nsect = i - sec;
|
|
|
|
head = sec / fd->ft->sectrac;
|
|
|
|
sec = sec % fd->ft->sectrac + 1;
|
|
|
|
|
|
|
|
/* If everything is going swimmingly, use multisector xfer */
|
|
|
|
if (fdc->retry == 0 && bp->bio_cmd & (BIO_READ|BIO_WRITE)) {
|
|
|
|
fd->fd_iosize = imin(nsect * fd->sectorsize, bp->bio_resid);
|
|
|
|
nsect = fd->fd_iosize / fd->sectorsize;
|
|
|
|
} else if (bp->bio_cmd & (BIO_READ|BIO_WRITE)) {
|
|
|
|
fd->fd_iosize = fd->sectorsize;
|
|
|
|
nsect = 1;
|
2004-07-12 20:49:26 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* Do RECAL if we need to or are going to track zero anyway */
|
|
|
|
if ((need_recal & (1 << fd->fdsu)) ||
|
|
|
|
(cylinder == 0 && fd->track != 0) ||
|
|
|
|
fdc->retry > 2) {
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if (fdc_cmd(fdc, 2, NE7CMD_RECAL, fd->fdsu, 0))
|
|
|
|
return (1);
|
2007-02-23 23:06:10 +00:00
|
|
|
tsleep(fdc, PRIBIO, "fdrecal", hz);
|
2004-08-20 15:14:25 +00:00
|
|
|
retry_line = __LINE__;
|
|
|
|
if (fdc_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID)
|
|
|
|
return (1); /* XXX */
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if ((st0 & 0xc0) || cyl != 0)
|
|
|
|
return (1);
|
|
|
|
need_recal &= ~(1 << fd->fdsu);
|
|
|
|
fd->track = 0;
|
|
|
|
/* let the heads settle */
|
|
|
|
if (settle)
|
2007-02-23 23:06:10 +00:00
|
|
|
tsleep(fdc->fd, PRIBIO, "fdhdstl", settle);
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
|
|
|
|
2004-09-24 20:33:52 +00:00
|
|
|
/*
|
2004-08-20 15:14:25 +00:00
|
|
|
* SEEK to where we want to be
|
|
|
|
*
|
|
|
|
* Enhanced controllers do implied seeks for read&write as long as
|
|
|
|
* we do not need multiple steps per track.
|
|
|
|
*/
|
|
|
|
if (cylinder != fd->track && (
|
|
|
|
fdc->fdct != FDC_ENHANCED ||
|
|
|
|
descyl != cylinder ||
|
|
|
|
(bp->bio_cmd & (BIO_RDID|BIO_FMT)))) {
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if (fdc_cmd(fdc, 3, NE7CMD_SEEK, fd->fdsu, descyl, 0))
|
|
|
|
return (1);
|
2007-02-23 23:06:10 +00:00
|
|
|
tsleep(fdc, PRIBIO, "fdseek", hz);
|
2004-08-20 15:14:25 +00:00
|
|
|
retry_line = __LINE__;
|
|
|
|
if (fdc_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID)
|
|
|
|
return (1); /* XXX */
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if ((st0 & 0xc0) || cyl != descyl) {
|
|
|
|
need_recal |= (1 << fd->fdsu);
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
/* let the heads settle */
|
|
|
|
if (settle)
|
2007-02-23 23:06:10 +00:00
|
|
|
tsleep(fdc->fd, PRIBIO, "fdhdstl", settle);
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
|
|
|
fd->track = cylinder;
|
|
|
|
|
2004-09-24 20:33:52 +00:00
|
|
|
if (debugflags & 8)
|
2004-08-20 15:14:25 +00:00
|
|
|
printf("op %x bn %ju siz %u ptr %p retry %d\n",
|
|
|
|
bp->bio_cmd, bp->bio_pblkno, fd->fd_iosize,
|
|
|
|
fd->fd_ioptr, fdc->retry);
|
|
|
|
|
|
|
|
/* Setup ISADMA if we need it and have it */
|
|
|
|
if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_FMT))
|
|
|
|
&& !(fdc->flags & FDC_NODMA)) {
|
|
|
|
isa_dmastart(
|
|
|
|
bp->bio_cmd & BIO_READ ? ISADMA_READ : ISADMA_WRITE,
|
|
|
|
fd->fd_ioptr, fd->fd_iosize, fdc->dmachan);
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->flags |= FD_ISADMA;
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Do PIO if we have to */
|
|
|
|
if (fdc->flags & FDC_NODMA) {
|
|
|
|
if (bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_FMT))
|
2004-09-14 07:06:49 +00:00
|
|
|
fdbcdr_wr(fdc, 1, fd->fd_iosize);
|
2004-08-20 15:14:25 +00:00
|
|
|
if (bp->bio_cmd & (BIO_WRITE|BIO_FMT))
|
|
|
|
fdc_pio(fdc);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(bp->bio_cmd) {
|
|
|
|
case BIO_FMT:
|
|
|
|
/* formatting */
|
|
|
|
finfo = (struct fd_formb *)bp->bio_data;
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if (fdc_cmd(fdc, 6,
|
|
|
|
NE7CMD_FORMAT | mfm,
|
|
|
|
head << 2 | fd->fdsu,
|
|
|
|
finfo->fd_formb_secshift,
|
|
|
|
finfo->fd_formb_nsecs,
|
|
|
|
finfo->fd_formb_gaplen,
|
|
|
|
finfo->fd_formb_fillbyte, 0))
|
|
|
|
return (1);
|
1999-04-16 21:22:55 +00:00
|
|
|
break;
|
2004-08-20 15:14:25 +00:00
|
|
|
case BIO_RDID:
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if (fdc_cmd(fdc, 2,
|
|
|
|
NE7CMD_READID | mfm,
|
|
|
|
head << 2 | fd->fdsu, 0))
|
|
|
|
return (1);
|
1999-04-16 21:22:55 +00:00
|
|
|
break;
|
2004-08-20 15:14:25 +00:00
|
|
|
case BIO_READ:
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if (fdc_cmd(fdc, 9,
|
|
|
|
NE7CMD_READ | NE7CMD_SK | mfm | NE7CMD_MT,
|
|
|
|
head << 2 | fd->fdsu, /* head & unit */
|
|
|
|
fd->track, /* track */
|
|
|
|
head, /* head */
|
|
|
|
sec, /* sector + 1 */
|
|
|
|
fd->ft->secsize, /* sector size */
|
|
|
|
fd->ft->sectrac, /* sectors/track */
|
|
|
|
fd->ft->gap, /* gap size */
|
|
|
|
fd->ft->datalen, /* data length */
|
|
|
|
0))
|
|
|
|
return (1);
|
1999-04-16 21:22:55 +00:00
|
|
|
break;
|
2004-08-20 15:14:25 +00:00
|
|
|
case BIO_WRITE:
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if (fdc_cmd(fdc, 9,
|
|
|
|
NE7CMD_WRITE | mfm | NE7CMD_MT,
|
|
|
|
head << 2 | fd->fdsu, /* head & unit */
|
|
|
|
fd->track, /* track */
|
|
|
|
head, /* head */
|
|
|
|
sec, /* sector + 1 */
|
|
|
|
fd->ft->secsize, /* sector size */
|
|
|
|
fd->ft->sectrac, /* sectors/track */
|
|
|
|
fd->ft->gap, /* gap size */
|
|
|
|
fd->ft->datalen, /* data length */
|
|
|
|
0))
|
|
|
|
return (1);
|
1999-04-16 21:22:55 +00:00
|
|
|
break;
|
|
|
|
default:
|
2004-08-20 15:14:25 +00:00
|
|
|
KASSERT(0 == 1, ("Wrong bio_cmd %x\n", bp->bio_cmd));
|
1999-04-16 21:22:55 +00:00
|
|
|
}
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* Wait for interrupt */
|
2007-02-23 23:06:10 +00:00
|
|
|
i = tsleep(fdc, PRIBIO, "fddata", hz);
|
2004-08-20 15:14:25 +00:00
|
|
|
|
|
|
|
/* PIO if the read looks good */
|
|
|
|
if (i == 0 && (fdc->flags & FDC_NODMA) && (bp->bio_cmd & BIO_READ))
|
|
|
|
fdc_pio(fdc);
|
|
|
|
|
|
|
|
/* Finish DMA */
|
|
|
|
if (fd->flags & FD_ISADMA) {
|
|
|
|
isa_dmadone(
|
|
|
|
bp->bio_cmd & BIO_READ ? ISADMA_READ : ISADMA_WRITE,
|
|
|
|
fd->fd_ioptr, fd->fd_iosize, fdc->dmachan);
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->flags &= ~FD_ISADMA;
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
1999-04-16 21:22:55 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
if (i != 0) {
|
2004-02-25 13:44:58 +00:00
|
|
|
/*
|
2004-08-20 15:14:25 +00:00
|
|
|
* Timeout.
|
2004-02-25 13:44:58 +00:00
|
|
|
*
|
2004-08-20 15:14:25 +00:00
|
|
|
* Due to IBM's brain-dead design, the FDC has a faked ready
|
|
|
|
* signal, hardwired to ready == true. Thus, any command
|
|
|
|
* issued if there's no diskette in the drive will _never_
|
|
|
|
* complete, and must be aborted by resetting the FDC.
|
|
|
|
* Many thanks, Big Blue!
|
2004-02-25 13:44:58 +00:00
|
|
|
*/
|
2004-08-20 15:14:25 +00:00
|
|
|
retry_line = __LINE__;
|
|
|
|
fdc->flags |= FDC_NEEDS_RESET;
|
|
|
|
return (1);
|
2004-07-05 20:56:06 +00:00
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
retry_line = __LINE__;
|
|
|
|
if (fdc_read_status(fdc))
|
|
|
|
return (1);
|
2004-07-05 20:56:06 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
if (debugflags & 0x10)
|
|
|
|
printf(" -> %x %x %x %x\n",
|
|
|
|
fdc->status[0], fdc->status[1],
|
|
|
|
fdc->status[2], fdc->status[3]);
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
st0 = fdc->status[0] & NE7_ST0_IC;
|
|
|
|
if (st0 != 0) {
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if (st0 == NE7_ST0_IC_AT && fdc->status[1] & NE7_ST1_OR) {
|
|
|
|
/*
|
|
|
|
* DMA overrun. Someone hogged the bus and
|
|
|
|
* didn't release it in time for the next
|
|
|
|
* FDC transfer.
|
|
|
|
*/
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
retry_line = __LINE__;
|
|
|
|
if(st0 == NE7_ST0_IC_IV) {
|
|
|
|
fdc->flags |= FDC_NEEDS_RESET;
|
|
|
|
return (1);
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
retry_line = __LINE__;
|
|
|
|
if(st0 == NE7_ST0_IC_AT && fdc->status[2] & NE7_ST2_WC) {
|
|
|
|
need_recal |= (1 << fd->fdsu);
|
|
|
|
return (1);
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
if (debugflags & 0x20) {
|
|
|
|
printf("status %02x %02x %02x %02x %02x %02x\n",
|
|
|
|
fdc->status[0], fdc->status[1], fdc->status[2],
|
|
|
|
fdc->status[3], fdc->status[4], fdc->status[5]);
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
retry_line = __LINE__;
|
|
|
|
return (1);
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
/* All OK */
|
|
|
|
switch(bp->bio_cmd) {
|
|
|
|
case BIO_RDID:
|
|
|
|
/* copy out ID field contents */
|
|
|
|
idp = (struct fdc_readid *)bp->bio_data;
|
|
|
|
idp->cyl = fdc->status[3];
|
|
|
|
idp->head = fdc->status[4];
|
|
|
|
idp->sec = fdc->status[5];
|
|
|
|
idp->secshift = fdc->status[6];
|
|
|
|
if (debugflags & 0x40)
|
|
|
|
printf("c %d h %d s %d z %d\n",
|
|
|
|
idp->cyl, idp->head, idp->sec, idp->secshift);
|
|
|
|
break;
|
|
|
|
case BIO_READ:
|
|
|
|
case BIO_WRITE:
|
|
|
|
bp->bio_pblkno += nsect;
|
|
|
|
bp->bio_resid -= fd->fd_iosize;
|
|
|
|
bp->bio_completed += fd->fd_iosize;
|
|
|
|
fd->fd_ioptr += fd->fd_iosize;
|
|
|
|
/* Since we managed to get something done, reset the retry */
|
|
|
|
fdc->retry = 0;
|
|
|
|
if (bp->bio_resid > 0)
|
|
|
|
return (0);
|
|
|
|
break;
|
|
|
|
case BIO_FMT:
|
|
|
|
break;
|
1996-11-02 23:31:11 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
return (fdc_biodone(fdc, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fdc_thread(void *arg)
|
|
|
|
{
|
|
|
|
struct fdc_data *fdc;
|
|
|
|
|
|
|
|
fdc = arg;
|
|
|
|
int i;
|
|
|
|
|
2004-09-24 20:28:00 +00:00
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
2004-09-23 21:12:21 +00:00
|
|
|
fdc->flags |= FDC_KTHREAD_ALIVE;
|
|
|
|
while ((fdc->flags & FDC_KTHREAD_EXIT) == 0) {
|
2004-09-24 20:28:00 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
i = fdc_worker(fdc);
|
|
|
|
if (i && debugflags & 0x20) {
|
|
|
|
if (fdc->bp != NULL) {
|
|
|
|
g_print_bio(fdc->bp);
|
|
|
|
printf("\n");
|
2001-07-08 20:50:20 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
printf("Retry line %d\n", retry_line);
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc->retry += i;
|
2004-09-24 20:28:00 +00:00
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
}
|
2004-09-23 21:12:21 +00:00
|
|
|
fdc->flags &= ~(FDC_KTHREAD_EXIT | FDC_KTHREAD_ALIVE);
|
2004-09-24 20:28:00 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
|
|
|
|
2007-10-20 23:23:23 +00:00
|
|
|
kproc_exit(0);
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
}
|
|
|
|
|
2001-07-14 20:25:01 +00:00
|
|
|
/*
|
2004-09-24 20:33:52 +00:00
|
|
|
* Enqueue a request.
|
2001-07-14 20:25:01 +00:00
|
|
|
*/
|
1993-11-25 01:38:01 +00:00
|
|
|
static void
|
2004-08-20 15:14:25 +00:00
|
|
|
fd_enqueue(struct fd_data *fd, struct bio *bp)
|
1993-06-12 14:58:17 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fdc_data *fdc;
|
|
|
|
int call;
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
call = 0;
|
|
|
|
fdc = fd->fdc;
|
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
|
|
|
/* If we go from idle, cancel motor turnoff */
|
|
|
|
if (fd->fd_iocount++ == 0)
|
2006-02-23 19:11:16 +00:00
|
|
|
callout_stop(&fd->toffhandle);
|
2004-08-20 15:14:25 +00:00
|
|
|
if (fd->flags & FD_MOTOR) {
|
|
|
|
/* The motor is on, send it directly to the controller */
|
|
|
|
bioq_disksort(&fdc->head, bp);
|
|
|
|
wakeup(&fdc->head);
|
|
|
|
} else {
|
|
|
|
/* Queue it on the drive until the motor has started */
|
|
|
|
bioq_insert_tail(&fd->fd_bq, bp);
|
|
|
|
if (!(fd->flags & FD_MOTORWAIT))
|
|
|
|
fd_motor(fd, 1);
|
1993-06-12 14:58:17 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
1993-06-12 14:58:17 +00:00
|
|
|
}
|
|
|
|
|
2008-11-15 01:43:34 +00:00
|
|
|
/*
|
|
|
|
* Try to find out if we have a disk in the drive.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
fd_probe_disk(struct fd_data *fd, int *recal)
|
|
|
|
{
|
|
|
|
struct fdc_data *fdc;
|
|
|
|
int st0, st3, cyl;
|
|
|
|
int oopts, ret;
|
|
|
|
|
|
|
|
fdc = fd->fdc;
|
|
|
|
oopts = fd->options;
|
|
|
|
fd->options |= FDOPT_NOERRLOG | FDOPT_NORETRY;
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* First recal, then seek to cyl#1, this clears the old condition on
|
|
|
|
* the disk change line so we can examine it for current status.
|
|
|
|
*/
|
|
|
|
if (debugflags & 0x40)
|
|
|
|
printf("New disk in probe\n");
|
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
|
|
|
fd->flags |= FD_NEWDISK;
|
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
|
|
|
if (fdc_cmd(fdc, 2, NE7CMD_RECAL, fd->fdsu, 0))
|
|
|
|
goto done;
|
|
|
|
tsleep(fdc, PRIBIO, "fdrecal", hz);
|
|
|
|
if (fdc_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID)
|
|
|
|
goto done; /* XXX */
|
|
|
|
if ((st0 & 0xc0) || cyl != 0)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
/* Seek to track 1 */
|
|
|
|
if (fdc_cmd(fdc, 3, NE7CMD_SEEK, fd->fdsu, 1, 0))
|
|
|
|
goto done;
|
|
|
|
tsleep(fdc, PRIBIO, "fdseek", hz);
|
|
|
|
if (fdc_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID)
|
|
|
|
goto done; /* XXX */
|
|
|
|
*recal |= (1 << fd->fdsu);
|
|
|
|
if (fdin_rd(fdc) & FDI_DCHG) {
|
|
|
|
if (debugflags & 0x40)
|
|
|
|
printf("Empty in probe\n");
|
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
|
|
|
fd->flags |= FD_EMPTY;
|
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
|
|
|
} else {
|
|
|
|
if (fdc_sense_drive(fdc, &st3) != 0)
|
|
|
|
goto done;
|
|
|
|
if (debugflags & 0x40)
|
|
|
|
printf("Got disk in probe\n");
|
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
|
|
|
fd->flags &= ~FD_EMPTY;
|
|
|
|
if (st3 & NE7_ST3_WP)
|
|
|
|
fd->flags |= FD_WP;
|
|
|
|
else
|
|
|
|
fd->flags &= ~FD_WP;
|
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
done:
|
|
|
|
fd->options = oopts;
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static int
|
|
|
|
fdmisccmd(struct fd_data *fd, u_int cmd, void *data)
|
1993-06-12 14:58:17 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct bio *bp;
|
|
|
|
struct fd_formb *finfo;
|
|
|
|
struct fdc_readid *idfield;
|
|
|
|
int error;
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
bp = malloc(sizeof(struct bio), M_TEMP, M_WAITOK | M_ZERO);
|
1993-06-12 14:58:17 +00:00
|
|
|
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
/*
|
2004-08-20 15:14:25 +00:00
|
|
|
* Set up a bio request for fdstrategy(). bio_offset is faked
|
|
|
|
* so that fdstrategy() will seek to the the requested
|
|
|
|
* cylinder, and use the desired head.
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
*/
|
2004-08-20 15:14:25 +00:00
|
|
|
bp->bio_cmd = cmd;
|
|
|
|
if (cmd == BIO_FMT) {
|
|
|
|
finfo = (struct fd_formb *)data;
|
|
|
|
bp->bio_pblkno =
|
|
|
|
(finfo->cyl * fd->ft->heads + finfo->head) *
|
|
|
|
fd->ft->sectrac;
|
|
|
|
bp->bio_length = sizeof *finfo;
|
|
|
|
} else if (cmd == BIO_RDID) {
|
|
|
|
idfield = (struct fdc_readid *)data;
|
|
|
|
bp->bio_pblkno =
|
|
|
|
(idfield->cyl * fd->ft->heads + idfield->head) *
|
|
|
|
fd->ft->sectrac;
|
|
|
|
bp->bio_length = sizeof(struct fdc_readid);
|
|
|
|
} else if (cmd == BIO_PROBE) {
|
|
|
|
/* nothing */
|
|
|
|
} else
|
|
|
|
panic("wrong cmd in fdmisccmd()");
|
|
|
|
bp->bio_offset = bp->bio_pblkno * fd->sectorsize;
|
|
|
|
bp->bio_data = data;
|
|
|
|
bp->bio_driver1 = fd;
|
|
|
|
bp->bio_flags = 0;
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
fd_enqueue(fd, bp);
|
1998-12-12 08:16:01 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
do {
|
2007-02-23 23:06:10 +00:00
|
|
|
tsleep(bp, PRIBIO, "fdwait", hz);
|
2004-08-20 15:14:25 +00:00
|
|
|
} while (!(bp->bio_flags & BIO_DONE));
|
|
|
|
error = bp->bio_error;
|
1998-12-12 08:16:01 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
free(bp, M_TEMP);
|
|
|
|
return (error);
|
1998-12-12 08:16:01 +00:00
|
|
|
}
|
|
|
|
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
/*
|
|
|
|
* Try figuring out the density of the media present in our device.
|
|
|
|
*/
|
|
|
|
static int
|
2004-08-20 15:14:25 +00:00
|
|
|
fdautoselect(struct fd_data *fd)
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
{
|
|
|
|
struct fd_type *fdtp;
|
|
|
|
struct fdc_readid id;
|
2004-08-20 15:14:25 +00:00
|
|
|
int oopts, rv;
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
if (!(fd->ft->flags & FL_AUTO))
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
return (0);
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
fdtp = fd_native_types[fd->type];
|
|
|
|
fdsettype(fd, fdtp);
|
|
|
|
if (!(fd->ft->flags & FL_AUTO))
|
|
|
|
return (0);
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Try reading sector ID fields, first at cylinder 0, head 0,
|
|
|
|
* then at cylinder 2, head N. We don't probe cylinder 1,
|
|
|
|
* since for 5.25in DD media in a HD drive, there are no data
|
|
|
|
* to read (2 step pulses per media cylinder required). For
|
|
|
|
* two-sided media, the second probe always goes to head 1, so
|
|
|
|
* we can tell them apart from single-sided media. As a
|
|
|
|
* side-effect this means that single-sided media should be
|
|
|
|
* mentioned in the search list after two-sided media of an
|
|
|
|
* otherwise identical density. Media with a different number
|
|
|
|
* of sectors per track but otherwise identical parameters
|
|
|
|
* cannot be distinguished at all.
|
|
|
|
*
|
|
|
|
* If we successfully read an ID field on both cylinders where
|
|
|
|
* the recorded values match our expectation, we are done.
|
|
|
|
* Otherwise, we try the next density entry from the table.
|
|
|
|
*
|
|
|
|
* Stepping to cylinder 2 has the side-effect of clearing the
|
|
|
|
* unit attention bit.
|
|
|
|
*/
|
|
|
|
oopts = fd->options;
|
|
|
|
fd->options |= FDOPT_NOERRLOG | FDOPT_NORETRY;
|
2004-08-20 15:14:25 +00:00
|
|
|
for (; fdtp->heads; fdtp++) {
|
|
|
|
fdsettype(fd, fdtp);
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
|
|
|
|
id.cyl = id.head = 0;
|
2004-08-20 15:14:25 +00:00
|
|
|
rv = fdmisccmd(fd, BIO_RDID, &id);
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
if (rv != 0)
|
|
|
|
continue;
|
2004-08-20 15:14:25 +00:00
|
|
|
if (id.cyl != 0 || id.head != 0 || id.secshift != fdtp->secsize)
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
continue;
|
|
|
|
id.cyl = 2;
|
|
|
|
id.head = fd->ft->heads - 1;
|
2004-08-20 15:14:25 +00:00
|
|
|
rv = fdmisccmd(fd, BIO_RDID, &id);
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
if (id.cyl != 2 || id.head != fdtp->heads - 1 ||
|
|
|
|
id.secshift != fdtp->secsize)
|
|
|
|
continue;
|
|
|
|
if (rv == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fd->options = oopts;
|
2004-08-20 15:14:25 +00:00
|
|
|
if (fdtp->heads == 0) {
|
|
|
|
if (debugflags & 0x40)
|
2002-05-12 17:17:46 +00:00
|
|
|
device_printf(fd->dev, "autoselection failed\n");
|
2004-08-20 15:14:25 +00:00
|
|
|
fdsettype(fd, fd_native_types[fd->type]);
|
2008-11-15 01:43:34 +00:00
|
|
|
return (-1);
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
} else {
|
2004-08-20 15:14:25 +00:00
|
|
|
if (debugflags & 0x40) {
|
|
|
|
device_printf(fd->dev,
|
|
|
|
"autoselected %d KB medium\n", fd->ft->size / 2);
|
|
|
|
fdprinttype(fd->ft);
|
|
|
|
}
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-07-14 20:25:01 +00:00
|
|
|
/*
|
2004-08-20 15:14:25 +00:00
|
|
|
* GEOM class implementation
|
2001-07-14 20:25:01 +00:00
|
|
|
*/
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static g_access_t fd_access;
|
|
|
|
static g_start_t fd_start;
|
|
|
|
static g_ioctl_t fd_ioctl;
|
1993-06-12 14:58:17 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
struct g_class g_fd_class = {
|
|
|
|
.name = "FD",
|
|
|
|
.version = G_VERSION,
|
|
|
|
.start = fd_start,
|
|
|
|
.access = fd_access,
|
|
|
|
.ioctl = fd_ioctl,
|
|
|
|
};
|
Make the Y-E Data PCMCIA floppy of the Toshiba Libretto work under
-current. It doesn't work yet as stable as the 3.x/PAO version of the
driver does, however, i get occasional `FDC direction bit not set' and
other weird messages, but it basically works at least.
The old (defunct) #ifdef FDC_YE stuff has been eliminated completely
now, PCMCIA-FDC specific functions have been implemented differently
where needed.
Unfortunately, due to the fact that the traditional PeeCee FDC with
its funny non-contiguous register space (one register for WD1003
harddisk controllers is interleaved into the FDC register set), and
Peter's subsequent changes involving two different bus space handles
for normal FDCs, the changes required for the Y-E stuff are more
complex than i'd love them to be. I've done my best to keep the logic
for normal FDCs intact.
Since the Y-E FDC seems to lose interrupts after a FDC reset
sometimes, i've also replaced the timeout logic in fd_turnoff() to
generate an artificial pseudo interrupt in case of a timeout while the
drive has still outstanding transfers waiting. This avoids the total
starvation of the driver that could be observed with highly damaged
media under 3.x/PAO. This part of the patch has been revied by bde
previously.
I've fixed a number of occasions where previous commits have been
missing the encapuslation of ISA DMA related functions inside
FDC_NODMA checks.
I've added one call to SET_BCDR() during preparation of the format
floppy operation. Floppy formatting has been totally broken before in
3.x/PAO (garbage ID fields have been written to the medium, causing
`wrong cylinder' errors upon media reading). This is just black
magic, i don't have the slightes idea _why_ this needs to be but just
copied over the hack that has been used by the PAO folks in the normal
read/write case anyway.
The entired device_busy() stuff seems to be pointless to me. In any
case, i had to add device_unbusy() calls symmetrical to the
device_busy() calls, otherwise the PCMCIA floppy driver could never be
deactivated. (As it used to be, it caused a `mark the device busier
and busier' situation.) IMHO, all block device drivers should be
marked busy based on active buffers still waiting for the driver, so
the device_unbusy() calls should probably go to biodone(). Only one
other driver (whose name escapes me at the moment) uses device_busy()
calls at all, so i question the value of all this...
I think this entire `device busy' logic simply doesn't fit for PCMCIA
&al. It cannot be the decision of some piece of kernel software to
declare a device `busy by now, you can't remove it', when the actual
physical power of removing it is the user pulling the card. The
kernel simply has to cope with the removal, however busy the device
might have been by the time of the removal, period. Perhaps a force
flag needs to be added?
Upon inserting the card a second time, i get:
WARNING: "fd" is usurping "fd"'s cdevsw[]
WARNING: "fd" is usurping "fd"'s bmaj
I suspect this is related to the XXX comment at the call to
cdevsw_add(). Does anybody know what the correct way is to cleanup
this?
2000-03-18 18:27:01 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static int
|
|
|
|
fd_access(struct g_provider *pp, int r, int w, int e)
|
|
|
|
{
|
|
|
|
struct fd_data *fd;
|
|
|
|
struct fdc_data *fdc;
|
|
|
|
int ar, aw, ae;
|
2008-01-11 11:53:04 +00:00
|
|
|
int busy;
|
1998-12-12 08:16:01 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
fd = pp->geom->softc;
|
|
|
|
fdc = fd->fdc;
|
1998-12-12 08:16:01 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/*
|
|
|
|
* If our provider is withering, we can only get negative requests
|
|
|
|
* and we don't want to even see them
|
|
|
|
*/
|
|
|
|
if (pp->flags & G_PF_WITHER)
|
|
|
|
return (0);
|
2001-07-08 20:50:20 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
ar = r + pp->acr;
|
|
|
|
aw = w + pp->acw;
|
|
|
|
ae = e + pp->ace;
|
2001-07-08 20:50:20 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
if (ar == 0 && aw == 0 && ae == 0) {
|
|
|
|
device_unbusy(fd->dev);
|
|
|
|
return (0);
|
|
|
|
}
|
2001-07-08 20:50:20 +00:00
|
|
|
|
2008-01-11 11:53:04 +00:00
|
|
|
busy = 0;
|
2004-08-20 15:14:25 +00:00
|
|
|
if (pp->acr == 0 && pp->acw == 0 && pp->ace == 0) {
|
|
|
|
if (fdmisccmd(fd, BIO_PROBE, NULL))
|
|
|
|
return (ENXIO);
|
|
|
|
if (fd->flags & FD_EMPTY)
|
|
|
|
return (ENXIO);
|
|
|
|
if (fd->flags & FD_NEWDISK) {
|
2008-11-15 01:43:34 +00:00
|
|
|
if (fdautoselect(fd) != 0 &&
|
|
|
|
(device_get_flags(fd->dev) & FD_NO_CHLINE)) {
|
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
|
|
|
fd->flags |= FD_EMPTY;
|
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->flags &= ~FD_NEWDISK;
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
1993-06-12 14:58:17 +00:00
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
device_busy(fd->dev);
|
2008-01-11 11:53:04 +00:00
|
|
|
busy = 1;
|
1993-06-12 14:58:17 +00:00
|
|
|
}
|
|
|
|
|
2008-01-11 11:53:04 +00:00
|
|
|
if (w > 0 && (fd->flags & FD_WP)) {
|
|
|
|
if (busy)
|
|
|
|
device_unbusy(fd->dev);
|
2004-08-20 15:14:25 +00:00
|
|
|
return (EROFS);
|
2008-01-11 11:53:04 +00:00
|
|
|
}
|
1999-04-16 21:22:55 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
pp->sectorsize = fd->sectorsize;
|
|
|
|
pp->stripesize = fd->ft->heads * fd->ft->sectrac * fd->sectorsize;
|
|
|
|
pp->mediasize = pp->stripesize * fd->ft->tracks;
|
|
|
|
return (0);
|
1993-06-12 14:58:17 +00:00
|
|
|
}
|
|
|
|
|
2000-05-06 07:01:47 +00:00
|
|
|
static void
|
2004-08-20 15:14:25 +00:00
|
|
|
fd_start(struct bio *bp)
|
1993-12-19 00:40:49 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fdc_data * fdc;
|
|
|
|
struct fd_data * fd;
|
2001-06-26 22:16:30 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
fd = bp->bio_to->geom->softc;
|
|
|
|
fdc = fd->fdc;
|
|
|
|
bp->bio_driver1 = fd;
|
|
|
|
if (bp->bio_cmd & BIO_GETATTR) {
|
|
|
|
if (g_handleattr_int(bp, "GEOM::fwsectors", fd->ft->sectrac))
|
|
|
|
return;
|
|
|
|
if (g_handleattr_int(bp, "GEOM::fwheads", fd->ft->heads))
|
|
|
|
return;
|
|
|
|
g_io_deliver(bp, ENOIOCTL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!(bp->bio_cmd & (BIO_READ|BIO_WRITE))) {
|
|
|
|
g_io_deliver(bp, EOPNOTSUPP);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bp->bio_pblkno = bp->bio_offset / fd->sectorsize;
|
|
|
|
bp->bio_resid = bp->bio_length;
|
|
|
|
fd_enqueue(fd, bp);
|
|
|
|
return;
|
2001-06-26 22:16:30 +00:00
|
|
|
}
|
|
|
|
|
1998-04-19 23:32:49 +00:00
|
|
|
static int
|
2004-12-12 10:09:05 +00:00
|
|
|
fd_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td)
|
1993-09-14 19:34:32 +00:00
|
|
|
{
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fd_data *fd;
|
2001-05-14 20:20:11 +00:00
|
|
|
struct fdc_status *fsp;
|
2001-06-26 22:16:30 +00:00
|
|
|
struct fdc_readid *rid;
|
2004-02-25 13:44:58 +00:00
|
|
|
int error;
|
2001-07-08 20:50:20 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
fd = pp->geom->softc;
|
2001-07-08 20:50:20 +00:00
|
|
|
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case FD_GTYPE: /* get drive type */
|
2004-08-20 15:14:25 +00:00
|
|
|
*(struct fd_type *)data = *fd->ft;
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
return (0);
|
|
|
|
|
|
|
|
case FD_STYPE: /* set drive type */
|
2004-04-25 04:33:56 +00:00
|
|
|
/*
|
|
|
|
* Allow setting drive type temporarily iff
|
|
|
|
* currently unset. Used for fdformat so any
|
|
|
|
* user can set it, and then start formatting.
|
|
|
|
*/
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->fts = *(struct fd_type *)data;
|
|
|
|
if (fd->fts.sectrac) {
|
|
|
|
/* XXX: check for rubbish */
|
|
|
|
fdsettype(fd, &fd->fts);
|
|
|
|
} else {
|
|
|
|
fdsettype(fd, fd_native_types[fd->type]);
|
|
|
|
}
|
|
|
|
if (debugflags & 0x40)
|
|
|
|
fdprinttype(fd->ft);
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
return (0);
|
|
|
|
|
|
|
|
case FD_GOPTS: /* get drive options */
|
2004-08-20 15:14:25 +00:00
|
|
|
*(int *)data = fd->options;
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
return (0);
|
|
|
|
|
|
|
|
case FD_SOPTS: /* set drive options */
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->options = *(int *)data;
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
return (0);
|
1993-09-14 19:34:32 +00:00
|
|
|
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
case FD_CLRERR:
|
2006-11-06 13:42:10 +00:00
|
|
|
error = priv_check(td, PRIV_DRIVER);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
fd->fdc->fdc_errs = 0;
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
case FD_GSTAT:
|
2004-08-20 15:14:25 +00:00
|
|
|
fsp = (struct fdc_status *)data;
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
if ((fd->fdc->flags & FDC_STAT_VALID) == 0)
|
|
|
|
return (EINVAL);
|
|
|
|
memcpy(fsp->status, fd->fdc->status, 7 * sizeof(u_int));
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
case FD_GDTYPE:
|
2004-08-20 15:14:25 +00:00
|
|
|
*(enum fd_drivetype *)data = fd->type;
|
Long promised major enhancement set for the floppy disk driver:
. The main device node now supports automatic density selection for
commonly used media densities. So you can stuff your 1.44 MB and
720 KB media into your drive and just access /dev/fd0, no questions
asked. It's all that easy, isn't it? :)
. Device density handling has been completely overhauled. The old way
of hardwired kernel density knowledge is no longer there. Instead,
the kernel now implements 16 subdevices per drive. The first
subdevice uses automatic density selection, while the remaining 15
devices are freely programmable. They can be assigned an arbitrary
name of the form /dev/fd[:digit]+.[:digit:]{1,4}, where the second
number is meant to either implement device names that are mnemonic
for their raw capacity (as it used to be), or they can alternatively
be created as "anonymous" devices like fd0.1 through fd0.15,
depending on the taste of the administrator. After creating a
subdevice, it is initialized to the maximal native density of the
respective drive type, so it needs to be customized for other
densities by using fdcontrol(8). Pseudo-partition devices (fd0a
through fd0h) are still supported as symlinks.
. The old hack to use flags 0x1 to always assume drive 0 were there is
no longer supported; this is now supposed to be done by wiring the
devices down from the loader via device flags. On IA32
architectures, the first two drives are looked up in the CMOS
configuration records though. On PCMCIA (i. e., the Y-E Data
controller of the Toshiba Libretto), a single drive is always
assumed.
. Other specialities like disabling the FIFO and not probing the drive
at boot-time are selected by per-controller or per-drive flags, too.
. Unit attentions (media has been changed) are supposed to be detected
now; density autoselection only occurs after a unit attention. (Can
be turned off by a per-drive flag, this will cause each Fdopen() to
perform the autoselection.)
. FM floppies can be handled now (on controllers that actually support
it -- not all do these days).
. Fdopen() can be told to avoid density selection by setting
O_NONBLOCK; this leaves the descriptor in a half-opened state where
only a few ioctls are accepted. This is necessary to run fdformat
on a device that uses automatic density selection (since you cannot
autoselect on an unformatted medium, obviously).
. Just differentiate between a plain old NE765 and the enhanced chips,
but don't try more; the existing code was wrong and only misdetected
the chips anyway.
BUGS and TODOs:
. All documentation update still needs to be done.
. Formatting not-so-standard format yields unpredictable results; i
have yet to figure out why this happens. "Standard" formats like
720 and 1440 KB do work, however.
. rc scripts are needed to setup device nodes with nonstandard
densities (like the old /dev/fdN.MMM we used to have).
. Obtaining device flags from the kernel environment doesn't work yet,
thus currently only drives that are present in (IA32) CMOS are
really detected. Someone who knows the odds and ends about device
flags is needed here, i can't figure out what i'm doing wrong.
. 2.88 MB still needs to be done.
2001-12-15 19:09:04 +00:00
|
|
|
return (0);
|
2001-06-29 15:30:48 +00:00
|
|
|
|
1993-12-19 00:40:49 +00:00
|
|
|
case FD_FORM:
|
2005-02-28 13:49:06 +00:00
|
|
|
if (!(fflag & FWRITE))
|
2004-12-12 10:09:05 +00:00
|
|
|
return (EPERM);
|
2004-08-20 15:14:25 +00:00
|
|
|
if (((struct fd_formb *)data)->format_version !=
|
2001-07-08 20:50:20 +00:00
|
|
|
FD_FORMAT_VERSION)
|
|
|
|
return (EINVAL); /* wrong version of formatting prog */
|
2004-08-20 15:14:25 +00:00
|
|
|
error = fdmisccmd(fd, BIO_FMT, data);
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_lock(&fd->fdc->fdc_mtx);
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->flags |= FD_NEWDISK;
|
2004-09-24 13:04:49 +00:00
|
|
|
mtx_unlock(&fd->fdc->fdc_mtx);
|
1993-12-19 00:40:49 +00:00
|
|
|
break;
|
1993-09-14 19:34:32 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
case FD_READID:
|
|
|
|
rid = (struct fdc_readid *)data;
|
|
|
|
if (rid->cyl > 85 || rid->head > 1)
|
|
|
|
return (EINVAL);
|
|
|
|
error = fdmisccmd(fd, BIO_RDID, data);
|
1993-12-19 00:40:49 +00:00
|
|
|
break;
|
1993-09-14 19:34:32 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
case FIONBIO:
|
|
|
|
case FIOASYNC:
|
|
|
|
/* For backwards compat with old fd*(8) tools */
|
|
|
|
error = 0;
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
break;
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
default:
|
|
|
|
if (debugflags & 0x80)
|
|
|
|
printf("Unknown ioctl %lx\n", cmd);
|
|
|
|
error = ENOIOCTL;
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
break;
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
};
|
1995-05-30 08:16:23 +00:00
|
|
|
|
Updated driver to the 1.1.5 version:
date: 1994/05/22 12:35:38; author: joerg; state: Exp; lines: +6 -6
First round of floppy changes. Try making `fd' more robust.
New features:
. ioctl command for setting the drive type (density etc.); restricted
to the super-user
. ioctl for getting/seting `drive options'; currently only option
is FDOPT_NORETRY: inhibit the usual retries; used when verifying
a newly formatted track
Fixes:
. function prototypes
. made all internal functions `static'
. cleaned up & corrected .h files
. restructured, to make the chaotic function sequence more rational
. compiled with -Wall, and cleared all warnings
. introduced a mirror for the (write-only) `digital output register',
to avoid the current kludge
. device probing completed by seeking/recalibrating, and looking
for track 0 being found
. holding the controller down in reset state while it is idle (and
thus saving allot of headaches)
. make requests fail that are not a multiple of the (physical)
sector size
. removed the fixed physical sector size (512 bytes), allowing for any
size the controller could handle (128/256/512/1024 bytes)
. replaced some silly messages
. fixed the TRACE* macro usage, debugging reports should be complete
now again (debugging output is HUGE! though)
. removed fd_timeout for SEEK command; seeks are always reported by
the controller to succeed, since the `success' only refers to the
controller's idea of success - there is no hardware line to tell about
the seek end (other than the `track 0' line)
. catch SENSEI's that report about a `terminated due to READY changed'
status - could happen after a controller reset
. converted ``hz / <something>'' divide operations to divisors that are
powers of two, so gcc can optimize them into shifts
. write/format operations are checked against a write-protected medium
now *prior* starting the operation
. error reports of `invalid command' and `wrong cylinder' will cause
shortcuts in the retrier() now
. fixed a bug in the retrier() causing bogus block numbers to be reported
. fdformat() does care for errors now
Known Bugs:
. no attempts have been made (yet) to improve the performance
. sometimes, bogus ``seek/recalib failed'' messages are logged; this
is still a bug in the driver, but it's not harmful since it's
usually caught by the retrier()
Reviewed by:
Submitted by:
Obtained from:
1994-09-17 16:56:10 +00:00
|
|
|
|
2001-06-29 15:30:48 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/*
|
|
|
|
* Configuration/initialization stuff, per controller.
|
|
|
|
*/
|
2001-05-14 20:20:11 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
devclass_t fdc_devclass;
|
|
|
|
static devclass_t fd_devclass;
|
2001-05-14 20:20:11 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
struct fdc_ivars {
|
|
|
|
int fdunit;
|
|
|
|
int fdtype;
|
|
|
|
};
|
2001-06-26 22:16:30 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
void
|
|
|
|
fdc_release_resources(struct fdc_data *fdc)
|
|
|
|
{
|
|
|
|
device_t dev;
|
2005-01-19 07:46:38 +00:00
|
|
|
struct resource *last;
|
|
|
|
int i;
|
2004-08-20 15:14:25 +00:00
|
|
|
|
|
|
|
dev = fdc->fdc_dev;
|
2004-09-14 07:06:49 +00:00
|
|
|
if (fdc->fdc_intr)
|
2004-09-16 06:34:00 +00:00
|
|
|
bus_teardown_intr(dev, fdc->res_irq, fdc->fdc_intr);
|
2004-09-14 07:06:49 +00:00
|
|
|
fdc->fdc_intr = NULL;
|
|
|
|
if (fdc->res_irq != NULL)
|
2004-08-20 15:14:25 +00:00
|
|
|
bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
|
2004-09-14 07:06:49 +00:00
|
|
|
fdc->res_irq);
|
|
|
|
fdc->res_irq = NULL;
|
2005-01-19 07:46:38 +00:00
|
|
|
last = NULL;
|
|
|
|
for (i = 0; i < FDC_MAXREG; i++) {
|
|
|
|
if (fdc->resio[i] != NULL && fdc->resio[i] != last) {
|
|
|
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
|
|
|
fdc->ridio[i], fdc->resio[i]);
|
|
|
|
last = fdc->resio[i];
|
|
|
|
fdc->resio[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
2004-09-14 07:06:49 +00:00
|
|
|
if (fdc->res_drq != NULL)
|
2004-08-20 15:14:25 +00:00
|
|
|
bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
|
2004-09-14 07:06:49 +00:00
|
|
|
fdc->res_drq);
|
|
|
|
fdc->res_drq = NULL;
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
|
|
|
{
|
|
|
|
struct fdc_ivars *ivars = device_get_ivars(child);
|
|
|
|
|
|
|
|
switch (which) {
|
|
|
|
case FDC_IVAR_FDUNIT:
|
|
|
|
*result = ivars->fdunit;
|
|
|
|
break;
|
|
|
|
case FDC_IVAR_FDTYPE:
|
|
|
|
*result = ivars->fdtype;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (ENOENT);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fdc_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
|
|
|
|
{
|
|
|
|
struct fdc_ivars *ivars = device_get_ivars(child);
|
|
|
|
|
|
|
|
switch (which) {
|
|
|
|
case FDC_IVAR_FDUNIT:
|
|
|
|
ivars->fdunit = value;
|
|
|
|
break;
|
|
|
|
case FDC_IVAR_FDTYPE:
|
|
|
|
ivars->fdtype = value;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (ENOENT);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fdc_initial_reset(device_t dev, struct fdc_data *fdc)
|
|
|
|
{
|
|
|
|
int ic_type, part_id;
|
|
|
|
|
2004-08-21 08:40:00 +00:00
|
|
|
/*
|
|
|
|
* A status value of 0xff is very unlikely, but not theoretically
|
|
|
|
* impossible, but it is far more likely to indicate an empty bus.
|
|
|
|
*/
|
|
|
|
if (fdsts_rd(fdc) == 0xff)
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Assert a reset to the floppy controller and check that the status
|
|
|
|
* register goes to zero.
|
|
|
|
*/
|
2004-08-20 15:14:25 +00:00
|
|
|
fdout_wr(fdc, 0);
|
2004-08-21 08:40:00 +00:00
|
|
|
fdout_wr(fdc, 0);
|
|
|
|
if (fdsts_rd(fdc) != 0)
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear the reset and see it come ready.
|
|
|
|
*/
|
2004-08-20 15:14:25 +00:00
|
|
|
fdout_wr(fdc, FDO_FRST);
|
2004-08-21 08:40:00 +00:00
|
|
|
DELAY(100);
|
|
|
|
if (fdsts_rd(fdc) != 0x80)
|
|
|
|
return (ENXIO);
|
2004-08-20 15:14:25 +00:00
|
|
|
|
|
|
|
/* Then, see if it can handle a command. */
|
|
|
|
if (fdc_cmd(fdc, 3, NE7CMD_SPECIFY, 0xaf, 0x1e, 0))
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to identify the chip.
|
|
|
|
*
|
|
|
|
* The i8272 datasheet documents that unknown commands
|
|
|
|
* will return ST0 as 0x80. The i8272 is supposedly identical
|
|
|
|
* to the NEC765.
|
|
|
|
* The i82077SL datasheet says 0x90 for the VERSION command,
|
|
|
|
* and several "superio" chips emulate this.
|
|
|
|
*/
|
|
|
|
if (fdc_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type))
|
|
|
|
return (ENXIO);
|
|
|
|
if (fdc_cmd(fdc, 1, 0x18, 1, &part_id))
|
|
|
|
return (ENXIO);
|
2004-08-27 17:08:24 +00:00
|
|
|
if (bootverbose)
|
|
|
|
device_printf(dev,
|
|
|
|
"ic_type %02x part_id %02x\n", ic_type, part_id);
|
2004-08-20 15:14:25 +00:00
|
|
|
switch (ic_type & 0xff) {
|
|
|
|
case 0x80:
|
|
|
|
device_set_desc(dev, "NEC 765 or clone");
|
|
|
|
fdc->fdct = FDC_NE765;
|
|
|
|
break;
|
|
|
|
case 0x81:
|
|
|
|
case 0x90:
|
|
|
|
device_set_desc(dev,
|
|
|
|
"Enhanced floppy controller");
|
|
|
|
fdc->fdct = FDC_ENHANCED;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
device_set_desc(dev, "Generic floppy controller");
|
|
|
|
fdc->fdct = FDC_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fdc_detach(device_t dev)
|
|
|
|
{
|
|
|
|
struct fdc_data *fdc;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
fdc = device_get_softc(dev);
|
|
|
|
|
|
|
|
/* have our children detached first */
|
|
|
|
if ((error = bus_generic_detach(dev)))
|
|
|
|
return (error);
|
|
|
|
|
2009-11-03 19:05:05 +00:00
|
|
|
if (fdc->fdc_intr)
|
|
|
|
bus_teardown_intr(dev, fdc->res_irq, fdc->fdc_intr);
|
|
|
|
fdc->fdc_intr = NULL;
|
|
|
|
|
2004-09-23 21:12:21 +00:00
|
|
|
/* kill worker thread */
|
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
2007-02-27 17:16:52 +00:00
|
|
|
fdc->flags |= FDC_KTHREAD_EXIT;
|
2004-11-08 18:53:52 +00:00
|
|
|
wakeup(&fdc->head);
|
2004-09-23 21:12:21 +00:00
|
|
|
while ((fdc->flags & FDC_KTHREAD_ALIVE) != 0)
|
2008-01-11 16:50:52 +00:00
|
|
|
msleep(fdc->fdc_thread, &fdc->fdc_mtx, PRIBIO, "fdcdet", 0);
|
2004-09-23 21:12:21 +00:00
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
/* reset controller, turn motor off */
|
|
|
|
fdout_wr(fdc, 0);
|
|
|
|
|
2004-09-16 06:34:00 +00:00
|
|
|
if (!(fdc->flags & FDC_NODMA))
|
|
|
|
isa_dma_release(fdc->dmachan);
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc_release_resources(fdc);
|
|
|
|
mtx_destroy(&fdc->fdc_mtx);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add a child device to the fdc controller. It will then be probed etc.
|
|
|
|
*/
|
|
|
|
device_t
|
|
|
|
fdc_add_child(device_t dev, const char *name, int unit)
|
|
|
|
{
|
|
|
|
struct fdc_ivars *ivar;
|
|
|
|
device_t child;
|
|
|
|
|
|
|
|
ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT | M_ZERO);
|
|
|
|
if (ivar == NULL)
|
|
|
|
return (NULL);
|
|
|
|
child = device_add_child(dev, name, unit);
|
|
|
|
if (child == NULL) {
|
|
|
|
free(ivar, M_DEVBUF);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
device_set_ivars(child, ivar);
|
|
|
|
ivar->fdunit = unit;
|
|
|
|
ivar->fdtype = FDT_NONE;
|
|
|
|
if (resource_disabled(name, unit))
|
|
|
|
device_disable(child);
|
|
|
|
return (child);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fdc_attach(device_t dev)
|
|
|
|
{
|
|
|
|
struct fdc_data *fdc;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
fdc = device_get_softc(dev);
|
|
|
|
fdc->fdc_dev = dev;
|
|
|
|
error = fdc_initial_reset(dev, fdc);
|
|
|
|
if (error) {
|
|
|
|
device_printf(dev, "does not respond\n");
|
|
|
|
return (error);
|
|
|
|
}
|
2004-09-14 17:28:51 +00:00
|
|
|
error = bus_setup_intr(dev, fdc->res_irq,
|
2007-02-23 12:19:07 +00:00
|
|
|
INTR_TYPE_BIO | INTR_ENTROPY |
|
|
|
|
((fdc->flags & FDC_NOFAST) ? INTR_MPSAFE : 0),
|
|
|
|
((fdc->flags & FDC_NOFAST) ? NULL : fdc_intr_fast),
|
|
|
|
((fdc->flags & FDC_NOFAST) ? fdc_intr : NULL),
|
|
|
|
fdc, &fdc->fdc_intr);
|
2004-08-20 15:14:25 +00:00
|
|
|
if (error) {
|
|
|
|
device_printf(dev, "cannot setup interrupt\n");
|
|
|
|
return (error);
|
|
|
|
}
|
2004-09-16 06:34:00 +00:00
|
|
|
if (!(fdc->flags & FDC_NODMA)) {
|
|
|
|
error = isa_dma_acquire(fdc->dmachan);
|
2004-10-22 19:01:10 +00:00
|
|
|
if (!error) {
|
|
|
|
error = isa_dma_init(fdc->dmachan,
|
|
|
|
MAX_BYTES_PER_CYL, M_WAITOK);
|
|
|
|
if (error)
|
|
|
|
isa_dma_release(fdc->dmachan);
|
|
|
|
}
|
2004-09-16 06:34:00 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
}
|
2004-08-20 15:14:25 +00:00
|
|
|
fdc->fdcu = device_get_unit(dev);
|
|
|
|
fdc->flags |= FDC_NEEDS_RESET;
|
|
|
|
|
|
|
|
mtx_init(&fdc->fdc_mtx, "fdc lock", NULL, MTX_DEF);
|
|
|
|
|
|
|
|
/* reset controller, turn motor off, clear fdout mirror reg */
|
|
|
|
fdout_wr(fdc, fdc->fdout = 0);
|
|
|
|
bioq_init(&fdc->head);
|
|
|
|
|
2007-10-20 23:23:23 +00:00
|
|
|
kproc_create(fdc_thread, fdc, &fdc->fdc_thread, 0, 0,
|
2004-08-20 15:14:25 +00:00
|
|
|
"fdc%d", device_get_unit(dev));
|
|
|
|
|
|
|
|
settle = hz / 8;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fdc_hints_probe(device_t dev)
|
|
|
|
{
|
|
|
|
const char *name, *dname;
|
|
|
|
int i, error, dunit;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Probe and attach any children. We should probably detect
|
|
|
|
* devices from the BIOS unless overridden.
|
|
|
|
*/
|
|
|
|
name = device_get_nameunit(dev);
|
|
|
|
i = 0;
|
|
|
|
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0) {
|
|
|
|
resource_int_value(dname, dunit, "drive", &dunit);
|
|
|
|
fdc_add_child(dev, dname, dunit);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((error = bus_generic_attach(dev)) != 0)
|
|
|
|
return (error);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fdc_print_child(device_t me, device_t child)
|
|
|
|
{
|
|
|
|
int retval = 0, flags;
|
|
|
|
|
|
|
|
retval += bus_print_child_header(me, child);
|
|
|
|
retval += printf(" on %s drive %d", device_get_nameunit(me),
|
|
|
|
fdc_get_fdunit(child));
|
|
|
|
if ((flags = device_get_flags(me)) != 0)
|
|
|
|
retval += printf(" flags %#x", flags);
|
|
|
|
retval += printf("\n");
|
|
|
|
|
|
|
|
return (retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Configuration/initialization, per drive.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
fd_probe(device_t dev)
|
|
|
|
{
|
|
|
|
int i, unit;
|
|
|
|
u_int st0, st3;
|
|
|
|
struct fd_data *fd;
|
|
|
|
struct fdc_data *fdc;
|
|
|
|
int fdsu;
|
|
|
|
int flags, type;
|
|
|
|
|
|
|
|
fdsu = fdc_get_fdunit(dev);
|
|
|
|
fd = device_get_softc(dev);
|
|
|
|
fdc = device_get_softc(device_get_parent(dev));
|
|
|
|
flags = device_get_flags(dev);
|
|
|
|
|
|
|
|
fd->dev = dev;
|
|
|
|
fd->fdc = fdc;
|
|
|
|
fd->fdsu = fdsu;
|
|
|
|
unit = device_get_unit(dev);
|
|
|
|
|
|
|
|
/* Auto-probe if fdinfo is present, but always allow override. */
|
|
|
|
type = flags & FD_TYPEMASK;
|
|
|
|
if (type == FDT_NONE && (type = fdc_get_fdtype(dev)) != FDT_NONE) {
|
|
|
|
fd->type = type;
|
|
|
|
goto done;
|
|
|
|
} else {
|
|
|
|
/* make sure fdautoselect() will be called */
|
|
|
|
fd->flags = FD_EMPTY;
|
|
|
|
fd->type = type;
|
|
|
|
}
|
|
|
|
|
2004-09-17 18:50:38 +00:00
|
|
|
#if (defined(__i386__) && !defined(PC98)) || defined(__amd64__)
|
2004-08-20 15:14:25 +00:00
|
|
|
if (fd->type == FDT_NONE && (unit == 0 || unit == 1)) {
|
|
|
|
/* Look up what the BIOS thinks we have. */
|
2004-09-17 18:50:38 +00:00
|
|
|
if (unit == 0)
|
|
|
|
fd->type = (rtcin(RTC_FDISKETTE) & 0xf0) >> 4;
|
|
|
|
else
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->type = rtcin(RTC_FDISKETTE) & 0x0f;
|
|
|
|
if (fd->type == FDT_288M_1)
|
|
|
|
fd->type = FDT_288M;
|
|
|
|
}
|
|
|
|
#endif /* __i386__ || __amd64__ */
|
|
|
|
/* is there a unit? */
|
|
|
|
if (fd->type == FDT_NONE)
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
/*
|
|
|
|
mtx_lock(&fdc->fdc_mtx);
|
|
|
|
*/
|
|
|
|
/* select it */
|
|
|
|
fd_select(fd);
|
|
|
|
fd_motor(fd, 1);
|
|
|
|
fdc->fd = fd;
|
|
|
|
fdc_reset(fdc); /* XXX reset, then unreset, etc. */
|
|
|
|
DELAY(1000000); /* 1 sec */
|
|
|
|
|
|
|
|
if ((flags & FD_NO_PROBE) == 0) {
|
|
|
|
/* If we're at track 0 first seek inwards. */
|
|
|
|
if ((fdc_sense_drive(fdc, &st3) == 0) &&
|
|
|
|
(st3 & NE7_ST3_T0)) {
|
|
|
|
/* Seek some steps... */
|
|
|
|
if (fdc_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) {
|
|
|
|
/* ...wait a moment... */
|
|
|
|
DELAY(300000);
|
|
|
|
/* make ctrlr happy: */
|
2005-02-28 05:14:45 +00:00
|
|
|
fdc_sense_int(fdc, NULL, NULL);
|
2004-08-20 15:14:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
/*
|
|
|
|
* we must recalibrate twice, just in case the
|
|
|
|
* heads have been beyond cylinder 76, since
|
|
|
|
* most FDCs still barf when attempting to
|
|
|
|
* recalibrate more than 77 steps
|
|
|
|
*/
|
|
|
|
/* go back to 0: */
|
|
|
|
if (fdc_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) {
|
|
|
|
/* a second being enough for full stroke seek*/
|
|
|
|
DELAY(i == 0 ? 1000000 : 300000);
|
|
|
|
|
|
|
|
/* anything responding? */
|
2005-02-28 05:14:45 +00:00
|
|
|
if (fdc_sense_int(fdc, &st0, NULL) == 0 &&
|
2004-08-20 15:14:25 +00:00
|
|
|
(st0 & NE7_ST0_EC) == 0)
|
|
|
|
break; /* already probed succesfully */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fd_motor(fd, 0);
|
|
|
|
fdc->fd = NULL;
|
|
|
|
/*
|
|
|
|
mtx_unlock(&fdc->fdc_mtx);
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((flags & FD_NO_PROBE) == 0 &&
|
|
|
|
(st0 & NE7_ST0_EC) != 0) /* no track 0 -> no drive present */
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
switch (fd->type) {
|
|
|
|
case FDT_12M:
|
|
|
|
device_set_desc(dev, "1200-KB 5.25\" drive");
|
|
|
|
break;
|
|
|
|
case FDT_144M:
|
|
|
|
device_set_desc(dev, "1440-KB 3.5\" drive");
|
|
|
|
break;
|
|
|
|
case FDT_288M:
|
|
|
|
device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)");
|
|
|
|
break;
|
|
|
|
case FDT_360K:
|
|
|
|
device_set_desc(dev, "360-KB 5.25\" drive");
|
|
|
|
break;
|
|
|
|
case FDT_720K:
|
|
|
|
device_set_desc(dev, "720-KB 3.5\" drive");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
|
|
|
fd->track = FD_NO_TRACK;
|
|
|
|
fd->fdc = fdc;
|
|
|
|
fd->fdsu = fdsu;
|
|
|
|
fd->options = 0;
|
2006-02-23 19:11:16 +00:00
|
|
|
callout_init_mtx(&fd->toffhandle, &fd->fdc->fdc_mtx, 0);
|
2004-08-20 15:14:25 +00:00
|
|
|
|
|
|
|
/* initialize densities for subdevices */
|
|
|
|
fdsettype(fd, fd_native_types[fd->type]);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have to do this in a geom event because GEOM is not running
|
|
|
|
* when fd_attach() is.
|
|
|
|
* XXX: move fd_attach after geom like ata/scsi disks
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
fd_attach2(void *arg, int flag)
|
|
|
|
{
|
|
|
|
struct fd_data *fd;
|
|
|
|
|
|
|
|
fd = arg;
|
2004-09-24 20:33:52 +00:00
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->fd_geom = g_new_geomf(&g_fd_class,
|
2004-09-25 08:56:57 +00:00
|
|
|
"fd%d", device_get_unit(fd->dev));
|
2004-08-20 15:14:25 +00:00
|
|
|
fd->fd_provider = g_new_providerf(fd->fd_geom, fd->fd_geom->name);
|
|
|
|
fd->fd_geom->softc = fd;
|
|
|
|
g_error_provider(fd->fd_provider, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fd_attach(device_t dev)
|
|
|
|
{
|
|
|
|
struct fd_data *fd;
|
|
|
|
|
|
|
|
fd = device_get_softc(dev);
|
|
|
|
g_post_event(fd_attach2, fd, M_WAITOK, NULL);
|
|
|
|
fd->flags |= FD_EMPTY;
|
|
|
|
bioq_init(&fd->fd_bq);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2009-11-03 19:05:05 +00:00
|
|
|
static void
|
|
|
|
fd_detach_geom(void *arg, int flag)
|
|
|
|
{
|
|
|
|
struct fd_data *fd = arg;
|
|
|
|
|
|
|
|
g_topology_assert();
|
|
|
|
g_wither_geom(fd->fd_geom, ENXIO);
|
|
|
|
}
|
|
|
|
|
2004-08-20 15:14:25 +00:00
|
|
|
static int
|
|
|
|
fd_detach(device_t dev)
|
|
|
|
{
|
|
|
|
struct fd_data *fd;
|
|
|
|
|
|
|
|
fd = device_get_softc(dev);
|
2009-11-03 19:05:05 +00:00
|
|
|
g_waitfor_event(fd_detach_geom, fd, M_WAITOK, NULL);
|
2004-11-21 16:25:21 +00:00
|
|
|
while (device_get_state(dev) == DS_BUSY)
|
|
|
|
tsleep(fd, PZERO, "fdd", hz/10);
|
2004-08-20 15:14:25 +00:00
|
|
|
callout_drain(&fd->toffhandle);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static device_method_t fd_methods[] = {
|
|
|
|
/* Device interface */
|
|
|
|
DEVMETHOD(device_probe, fd_probe),
|
|
|
|
DEVMETHOD(device_attach, fd_attach),
|
|
|
|
DEVMETHOD(device_detach, fd_detach),
|
|
|
|
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
|
|
|
DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX */
|
|
|
|
DEVMETHOD(device_resume, bus_generic_resume), /* XXX */
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static driver_t fd_driver = {
|
|
|
|
"fd",
|
|
|
|
fd_methods,
|
|
|
|
sizeof(struct fd_data)
|
|
|
|
};
|
|
|
|
|
2004-11-08 18:53:52 +00:00
|
|
|
static int
|
|
|
|
fdc_modevent(module_t mod, int type, void *data)
|
|
|
|
{
|
|
|
|
|
2009-10-27 17:14:22 +00:00
|
|
|
return (g_modevent(NULL, type, &g_fd_class));
|
2004-11-08 18:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DRIVER_MODULE(fd, fdc, fd_driver, fd_devclass, fdc_modevent, 0);
|