5f830ea2cd
-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?
117 lines
4.1 KiB
C
117 lines
4.1 KiB
C
/*-
|
|
* Copyright (c) 1990 The Regents of the University of California.
|
|
* All rights reserved.
|
|
*
|
|
* 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.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the University of
|
|
* California, Berkeley and its contributors.
|
|
* 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.
|
|
*
|
|
* 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.
|
|
*
|
|
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91
|
|
* $FreeBSD$
|
|
*
|
|
*/
|
|
|
|
enum fdc_type
|
|
{
|
|
FDC_NE765, FDC_I82077, FDC_NE72065, FDC_UNKNOWN = -1
|
|
};
|
|
|
|
|
|
/***********************************************************************\
|
|
* Per controller structure. *
|
|
\***********************************************************************/
|
|
struct fdc_data
|
|
{
|
|
int fdcu; /* our unit number */
|
|
int dmachan;
|
|
int flags;
|
|
#define FDC_ATTACHED 0x01
|
|
#define FDC_STAT_VALID 0x08
|
|
#define FDC_HAS_FIFO 0x10
|
|
#define FDC_NEEDS_RESET 0x20
|
|
#define FDC_NODMA 0x40
|
|
#define FDC_ISPNP 0x80
|
|
#define FDC_ISPCMCIA 0x100
|
|
struct fd_data *fd;
|
|
int fdu; /* the active drive */
|
|
int state;
|
|
int retry;
|
|
int fdout; /* mirror of the w/o digital output reg */
|
|
u_int status[7]; /* copy of the registers */
|
|
enum fdc_type fdct; /* chip version of FDC */
|
|
int fdc_errs; /* number of logged errors */
|
|
struct buf_queue_head head;
|
|
struct buf *bp; /* active buffer */
|
|
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
|
|
int rid_ioport, rid_ctl, rid_irq, rid_drq;
|
|
int port_off;
|
|
bus_space_tag_t portt;
|
|
bus_space_handle_t porth;
|
|
bus_space_tag_t ctlt;
|
|
bus_space_handle_t ctlh;
|
|
void *fdc_intr;
|
|
struct device *fdc_dev;
|
|
void (*fdctl_wr)(struct fdc_data *fdc, u_int8_t v);
|
|
};
|
|
|
|
/***********************************************************************\
|
|
* Throughout this file the following conventions will be used: *
|
|
* fd is a pointer to the fd_data struct for the drive in question *
|
|
* fdc is a pointer to the fdc_data struct for the controller *
|
|
* fdu is the floppy drive unit number *
|
|
* fdcu is the floppy controller unit number *
|
|
* fdsu is the floppy drive unit number on that controller. (sub-unit) *
|
|
\***********************************************************************/
|
|
typedef int fdu_t;
|
|
typedef int fdcu_t;
|
|
typedef int fdsu_t;
|
|
typedef struct fd_data *fd_p;
|
|
typedef struct fdc_data *fdc_p;
|
|
typedef enum fdc_type fdc_t;
|
|
|
|
#define FDUNIT(s) (((s) >> 6) & 3)
|
|
#define FDTYPE(s) ((s) & 0x3f)
|
|
|
|
/*
|
|
* fdc maintains a set (1!) of ivars per child of each controller.
|
|
*/
|
|
enum fdc_device_ivars {
|
|
FDC_IVAR_FDUNIT,
|
|
};
|
|
|
|
/*
|
|
* Simple access macros for the ivars.
|
|
*/
|
|
#define FDC_ACCESSOR(A, B, T) \
|
|
static __inline T fdc_get_ ## A(device_t dev) \
|
|
{ \
|
|
uintptr_t v; \
|
|
BUS_READ_IVAR(device_get_parent(dev), dev, FDC_IVAR_ ## B, &v); \
|
|
return (T) v; \
|
|
}
|
|
FDC_ACCESSOR(fdunit, FDUNIT, int)
|