- Merged from sys/dev/fdc/fdc.c revision 1.275.
- Break out the cbus front end from fd.c. - Remove the pccard support because it was broken.
This commit is contained in:
parent
25ae01d997
commit
d5103548b4
@ -327,6 +327,7 @@ pc98/pc98/canbus.c optional canbus
|
|||||||
pc98/pc98/canbus_if.m optional canbus
|
pc98/pc98/canbus_if.m optional canbus
|
||||||
pc98/pc98/clock.c standard
|
pc98/pc98/clock.c standard
|
||||||
pc98/pc98/fd.c optional fdc
|
pc98/pc98/fd.c optional fdc
|
||||||
|
pc98/pc98/fdc_cbus.c optional fdc isa
|
||||||
pc98/pc98/isa_dma.c optional isa
|
pc98/pc98/isa_dma.c optional isa
|
||||||
pc98/pc98/mse.c optional mse
|
pc98/pc98/mse.c optional mse
|
||||||
pc98/pc98/nmi.c standard
|
pc98/pc98/nmi.c standard
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
.endif
|
.endif
|
||||||
KMOD= fdc
|
KMOD= fdc
|
||||||
.if ${MACHINE} == "pc98"
|
.if ${MACHINE} == "pc98"
|
||||||
SRCS= fd.c
|
SRCS= fd.c fdc_cbus.c
|
||||||
.else
|
.else
|
||||||
SRCS= fdc.c fdc_isa.c fdc_pccard.c
|
SRCS= fdc.c fdc_isa.c fdc_pccard.c
|
||||||
.endif
|
.endif
|
||||||
|
@ -54,13 +54,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "opt_fdc.h"
|
#include "opt_fdc.h"
|
||||||
#include "card.h"
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
|
||||||
#include <sys/bio.h>
|
#include <sys/bio.h>
|
||||||
#include <sys/bus.h>
|
#include <sys/bus.h>
|
||||||
#include <sys/conf.h>
|
|
||||||
#include <sys/devicestat.h>
|
#include <sys/devicestat.h>
|
||||||
#include <sys/disk.h>
|
#include <sys/disk.h>
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
@ -72,132 +69,29 @@
|
|||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/syslog.h>
|
|
||||||
|
|
||||||
#include <machine/bus.h>
|
|
||||||
#include <sys/rman.h>
|
#include <sys/rman.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
|
||||||
#include <machine/clock.h>
|
#include <machine/clock.h>
|
||||||
#include <machine/resource.h>
|
|
||||||
#include <machine/stdarg.h>
|
#include <machine/stdarg.h>
|
||||||
|
|
||||||
#include <isa/isavar.h>
|
|
||||||
#ifdef PC98
|
#ifdef PC98
|
||||||
|
#include <isa/isavar.h>
|
||||||
#include <pc98/pc98/pc98.h>
|
#include <pc98/pc98/pc98.h>
|
||||||
#include <pc98/pc98/pc98_machdep.h>
|
#include <pc98/pc98/pc98_machdep.h>
|
||||||
#include <pc98/pc98/epsonio.h>
|
#include <pc98/pc98/epsonio.h>
|
||||||
#include <pc98/pc98/fdreg.h>
|
#include <pc98/pc98/fdreg.h>
|
||||||
|
#include <pc98/pc98/fdcvar.h>
|
||||||
#else
|
#else
|
||||||
|
#include <isa/isavar.h>
|
||||||
#include <isa/isareg.h>
|
#include <isa/isareg.h>
|
||||||
#include <isa/fdreg.h>
|
#include <dev/fdc/fdcreg.h>
|
||||||
|
#include <dev/fdc/fdcvar.h>
|
||||||
#include <isa/rtc.h>
|
#include <isa/rtc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum fdc_type
|
|
||||||
{
|
|
||||||
FDC_NE765, FDC_ENHANCED, FDC_UNKNOWN = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum fdc_states {
|
|
||||||
DEVIDLE,
|
|
||||||
FINDWORK,
|
|
||||||
DOSEEK,
|
|
||||||
SEEKCOMPLETE ,
|
|
||||||
IOCOMPLETE,
|
|
||||||
RECALCOMPLETE,
|
|
||||||
STARTRECAL,
|
|
||||||
RESETCTLR,
|
|
||||||
SEEKWAIT,
|
|
||||||
RECALWAIT,
|
|
||||||
MOTORWAIT,
|
|
||||||
IOTIMEDOUT,
|
|
||||||
RESETCOMPLETE,
|
|
||||||
PIOREAD
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef FDC_DEBUG
|
|
||||||
static char const * const fdstates[] = {
|
|
||||||
"DEVIDLE",
|
|
||||||
"FINDWORK",
|
|
||||||
"DOSEEK",
|
|
||||||
"SEEKCOMPLETE",
|
|
||||||
"IOCOMPLETE",
|
|
||||||
"RECALCOMPLETE",
|
|
||||||
"STARTRECAL",
|
|
||||||
"RESETCTLR",
|
|
||||||
"SEEKWAIT",
|
|
||||||
"RECALWAIT",
|
|
||||||
"MOTORWAIT",
|
|
||||||
"IOTIMEDOUT",
|
|
||||||
"RESETCOMPLETE",
|
|
||||||
"PIOREAD"
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Per controller structure (softc).
|
|
||||||
*/
|
|
||||||
struct fdc_data
|
|
||||||
{
|
|
||||||
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 */
|
|
||||||
enum fdc_states state;
|
|
||||||
int retry;
|
|
||||||
#ifndef PC98
|
|
||||||
int fdout; /* mirror of the w/o digital output reg */
|
|
||||||
#endif
|
|
||||||
u_int status[7]; /* copy of the registers */
|
|
||||||
enum fdc_type fdct; /* chip version of FDC */
|
|
||||||
int fdc_errs; /* number of logged errors */
|
|
||||||
int dma_overruns; /* number of DMA overruns */
|
|
||||||
struct bio_queue_head head;
|
|
||||||
struct bio *bp; /* active buffer */
|
|
||||||
#ifdef PC98
|
|
||||||
struct resource *res_ioport, *res_fdsio, *res_fdemsio;
|
|
||||||
struct resource *res_irq, *res_drq;
|
|
||||||
int rid_ioport, rid_irq, rid_drq;
|
|
||||||
#else
|
|
||||||
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
|
|
||||||
int rid_ioport, rid_ctl, rid_irq, rid_drq;
|
|
||||||
#endif
|
|
||||||
int port_off;
|
|
||||||
bus_space_tag_t portt;
|
|
||||||
bus_space_handle_t porth;
|
|
||||||
#ifdef PC98
|
|
||||||
bus_space_tag_t sc_fdsiot;
|
|
||||||
bus_space_handle_t sc_fdsioh;
|
|
||||||
bus_space_tag_t sc_fdemsiot;
|
|
||||||
bus_space_handle_t sc_fdemsioh;
|
|
||||||
#else
|
|
||||||
bus_space_tag_t ctlt;
|
|
||||||
bus_space_handle_t ctlh;
|
|
||||||
#endif
|
|
||||||
void *fdc_intr;
|
|
||||||
struct device *fdc_dev;
|
|
||||||
#ifndef PC98
|
|
||||||
void (*fdctl_wr)(struct fdc_data *fdc, u_int8_t v);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#define FDBIO_FORMAT BIO_CMD2
|
#define FDBIO_FORMAT BIO_CMD2
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fdc maintains a set (1!) of ivars per child of each controller.
|
* fdc maintains a set (1!) of ivars per child of each controller.
|
||||||
*/
|
*/
|
||||||
@ -220,10 +114,6 @@ FDC_ACCESSOR(fdunit, FDUNIT, int)
|
|||||||
/* configuration flags for fdc */
|
/* configuration flags for fdc */
|
||||||
#define FDC_NO_FIFO (1 << 2) /* do not enable FIFO */
|
#define FDC_NO_FIFO (1 << 2) /* do not enable FIFO */
|
||||||
|
|
||||||
/* error returns for fd_cmd() */
|
|
||||||
#define FD_FAILED -1
|
|
||||||
#define FD_NOT_VALID -2
|
|
||||||
#define FDC_ERRMAX 100 /* do not log more */
|
|
||||||
/*
|
/*
|
||||||
* Stop retrying after this many DMA overruns. Since each retry takes
|
* Stop retrying after this many DMA overruns. Since each retry takes
|
||||||
* one revolution, with 300 rpm., 25 retries take approximately 5
|
* one revolution, with 300 rpm., 25 retries take approximately 5
|
||||||
@ -353,7 +243,7 @@ static struct fd_type fd_searchlist_288m[] = {
|
|||||||
* up to cyl 82 */
|
* up to cyl 82 */
|
||||||
#define MAX_HEAD 1
|
#define MAX_HEAD 1
|
||||||
|
|
||||||
static devclass_t fdc_devclass;
|
devclass_t fdc_devclass;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Per drive structure (softc).
|
* Per drive structure (softc).
|
||||||
@ -476,38 +366,15 @@ nrd_info(addr)
|
|||||||
* as below -- makes locating a particular function in the body much
|
* as below -- makes locating a particular function in the body much
|
||||||
* easier.
|
* easier.
|
||||||
*/
|
*/
|
||||||
#ifndef PC98
|
|
||||||
static void fdout_wr(fdc_p, u_int8_t);
|
|
||||||
#endif
|
|
||||||
static u_int8_t fdsts_rd(fdc_p);
|
static u_int8_t fdsts_rd(fdc_p);
|
||||||
static void fddata_wr(fdc_p, u_int8_t);
|
static void fddata_wr(fdc_p, u_int8_t);
|
||||||
static u_int8_t fddata_rd(fdc_p);
|
static u_int8_t fddata_rd(fdc_p);
|
||||||
#ifndef PC98
|
|
||||||
static void fdctl_wr_isa(fdc_p, u_int8_t);
|
|
||||||
#if NCARD > 0
|
|
||||||
static void fdctl_wr_pcmcia(fdc_p, u_int8_t);
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
static u_int8_t fdin_rd(fdc_p);
|
|
||||||
#endif
|
|
||||||
#endif /* PC98 */
|
|
||||||
static int fdc_err(struct fdc_data *, const char *);
|
static int fdc_err(struct fdc_data *, const char *);
|
||||||
static int fd_cmd(struct fdc_data *, int, ...);
|
|
||||||
static int enable_fifo(fdc_p fdc);
|
static int enable_fifo(fdc_p fdc);
|
||||||
static int fd_sense_drive_status(fdc_p, int *);
|
static int fd_sense_drive_status(fdc_p, int *);
|
||||||
static int fd_sense_int(fdc_p, int *, int *);
|
static int fd_sense_int(fdc_p, int *, int *);
|
||||||
static int fd_read_status(fdc_p);
|
static int fd_read_status(fdc_p);
|
||||||
static int fdc_alloc_resources(struct fdc_data *);
|
|
||||||
static void fdc_release_resources(struct fdc_data *);
|
|
||||||
static int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
|
|
||||||
static int fdc_probe(device_t);
|
|
||||||
#if NCARD > 0
|
|
||||||
static int fdc_pccard_probe(device_t);
|
|
||||||
#endif
|
|
||||||
static int fdc_detach(device_t dev);
|
|
||||||
static void fdc_add_child(device_t, const char *, int);
|
static void fdc_add_child(device_t, const char *, int);
|
||||||
static int fdc_attach(device_t);
|
|
||||||
static int fdc_print_child(device_t, device_t);
|
|
||||||
static int fd_probe(device_t);
|
static int fd_probe(device_t);
|
||||||
static int fd_attach(device_t);
|
static int fd_attach(device_t);
|
||||||
static int fd_detach(device_t);
|
static int fd_detach(device_t);
|
||||||
@ -555,7 +422,7 @@ static int volatile fd_debug = 0;
|
|||||||
* Bus space handling (access to low-level IO).
|
* Bus space handling (access to low-level IO).
|
||||||
*/
|
*/
|
||||||
#ifndef PC98
|
#ifndef PC98
|
||||||
static void
|
void
|
||||||
fdout_wr(fdc_p fdc, u_int8_t v)
|
fdout_wr(fdc_p fdc, u_int8_t v)
|
||||||
{
|
{
|
||||||
bus_space_write_1(fdc->portt, fdc->porth, FDOUT+fdc->port_off, v);
|
bus_space_write_1(fdc->portt, fdc->porth, FDOUT+fdc->port_off, v);
|
||||||
@ -589,20 +456,6 @@ fdctl_wr(fdc_p fdc, u_int8_t v)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PC98
|
#ifndef PC98
|
||||||
static void
|
|
||||||
fdctl_wr_isa(fdc_p fdc, u_int8_t v)
|
|
||||||
{
|
|
||||||
bus_space_write_1(fdc->ctlt, fdc->ctlh, 0, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if NCARD > 0
|
|
||||||
static void
|
|
||||||
fdctl_wr_pcmcia(fdc_p fdc, u_int8_t v)
|
|
||||||
{
|
|
||||||
bus_space_write_1(fdc->portt, fdc->porth, FDCTL+fdc->port_off, v);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static u_int8_t
|
static u_int8_t
|
||||||
fdin_rd(fdc_p fdc)
|
fdin_rd(fdc_p fdc)
|
||||||
{
|
{
|
||||||
@ -647,7 +500,7 @@ fdc_err(struct fdc_data *fdc, const char *s)
|
|||||||
* # of output bytes, output bytes as ints ...,
|
* # of output bytes, output bytes as ints ...,
|
||||||
* # of input bytes, input bytes as ints ...
|
* # of input bytes, input bytes as ints ...
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
fd_cmd(struct fdc_data *fdc, int n_out, ...)
|
fd_cmd(struct fdc_data *fdc, int n_out, ...)
|
||||||
{
|
{
|
||||||
u_char cmd;
|
u_char cmd;
|
||||||
@ -876,7 +729,7 @@ static int pc98_fd_check_ready(fdu_t fdu)
|
|||||||
}
|
}
|
||||||
#endif /* PC98 */
|
#endif /* PC98 */
|
||||||
|
|
||||||
static int
|
int
|
||||||
fdc_alloc_resources(struct fdc_data *fdc)
|
fdc_alloc_resources(struct fdc_data *fdc)
|
||||||
{
|
{
|
||||||
device_t dev;
|
device_t dev;
|
||||||
@ -893,6 +746,9 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
#endif
|
#endif
|
||||||
fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0;
|
fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0;
|
||||||
fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0;
|
fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0;
|
||||||
|
#ifndef PC98
|
||||||
|
fdc->rid_ctl = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PC98
|
#ifdef PC98
|
||||||
fdc->res_ioport = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
|
fdc->res_ioport = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
|
||||||
@ -916,6 +772,40 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
* one with offset 7 as control register.
|
* one with offset 7 as control register.
|
||||||
*/
|
*/
|
||||||
nports = ispcmcia ? 8 : (ispnp ? 1 : 6);
|
nports = ispcmcia ? 8 : (ispnp ? 1 : 6);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some ACPI BIOSen have _CRS objects for the floppy device that
|
||||||
|
* split the I/O port resource into several resources. We detect
|
||||||
|
* this case by checking if there are more than 2 IOPORT resources.
|
||||||
|
* If so, we use the resource with the smallest start address as
|
||||||
|
* the port RID and the largest start address as the control RID.
|
||||||
|
*/
|
||||||
|
if (bus_get_resource_count(dev, SYS_RES_IOPORT, 2) != 0) {
|
||||||
|
u_long min_start, max_start, tmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Find the min/max start addresses and their RIDs. */
|
||||||
|
max_start = 0ul;
|
||||||
|
min_start = ~0ul;
|
||||||
|
for (i = 0; bus_get_resource_count(dev, SYS_RES_IOPORT, i) > 0;
|
||||||
|
i++) {
|
||||||
|
tmp = bus_get_resource_start(dev, SYS_RES_IOPORT, i);
|
||||||
|
KASSERT(tmp != 0, ("bogus resource"));
|
||||||
|
if (tmp < min_start) {
|
||||||
|
min_start = tmp;
|
||||||
|
fdc->rid_ioport = i;
|
||||||
|
}
|
||||||
|
if (tmp > max_start) {
|
||||||
|
max_start = tmp;
|
||||||
|
fdc->rid_ctl = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (min_start + 7 != max_start) {
|
||||||
|
device_printf(dev, "I/O to control range incorrect\n");
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
|
fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
|
||||||
&fdc->rid_ioport, 0ul, ~0ul,
|
&fdc->rid_ioport, 0ul, ~0ul,
|
||||||
nports, RF_ACTIVE);
|
nports, RF_ACTIVE);
|
||||||
@ -985,7 +875,6 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
/*
|
/*
|
||||||
* Now (finally!) allocate the control port.
|
* Now (finally!) allocate the control port.
|
||||||
*/
|
*/
|
||||||
fdc->rid_ctl = 1;
|
|
||||||
fdc->res_ctl = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
|
fdc->res_ctl = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
|
||||||
&fdc->rid_ctl, RF_ACTIVE);
|
&fdc->rid_ctl, RF_ACTIVE);
|
||||||
if (fdc->res_ctl == 0) {
|
if (fdc->res_ctl == 0) {
|
||||||
@ -998,14 +887,20 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
|
#ifdef PC98
|
||||||
&fdc->rid_irq, RF_ACTIVE);
|
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
|
||||||
|
RF_ACTIVE);
|
||||||
|
#else
|
||||||
|
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
|
||||||
|
RF_ACTIVE | RF_SHAREABLE);
|
||||||
|
#endif
|
||||||
if (fdc->res_irq == 0) {
|
if (fdc->res_irq == 0) {
|
||||||
device_printf(dev, "cannot reserve interrupt line\n");
|
device_printf(dev, "cannot reserve interrupt line\n");
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fdc->flags & FDC_NODMA) == 0) {
|
if ((fdc->flags & FDC_NODMA) == 0) {
|
||||||
|
#ifdef PC98
|
||||||
fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
|
fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
|
||||||
&fdc->rid_drq, RF_ACTIVE);
|
&fdc->rid_drq, RF_ACTIVE);
|
||||||
if (fdc->res_drq == 0) {
|
if (fdc->res_drq == 0) {
|
||||||
@ -1013,12 +908,21 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
return ENXIO;
|
return ENXIO;
|
||||||
}
|
}
|
||||||
fdc->dmachan = rman_get_start(fdc->res_drq);
|
fdc->dmachan = rman_get_start(fdc->res_drq);
|
||||||
|
#else
|
||||||
|
fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
|
||||||
|
&fdc->rid_drq, RF_ACTIVE | RF_SHAREABLE);
|
||||||
|
if (fdc->res_drq == 0) {
|
||||||
|
device_printf(dev, "cannot reserve DMA request line\n");
|
||||||
|
fdc->flags |= FDC_NODMA;
|
||||||
|
} else
|
||||||
|
fdc->dmachan = rman_get_start(fdc->res_drq);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
fdc_release_resources(struct fdc_data *fdc)
|
fdc_release_resources(struct fdc_data *fdc)
|
||||||
{
|
{
|
||||||
device_t dev;
|
device_t dev;
|
||||||
@ -1068,13 +972,7 @@ fdc_release_resources(struct fdc_data *fdc)
|
|||||||
* Configuration/initialization stuff, per controller.
|
* Configuration/initialization stuff, per controller.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct isa_pnp_id fdc_ids[] = {
|
int
|
||||||
{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
|
|
||||||
{0x0107d041, "Standard floppy controller supporting MS Device Bay Spec"}, /* PNP0701 */
|
|
||||||
{0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
||||||
{
|
{
|
||||||
struct fdc_ivars *ivars = device_get_ivars(child);
|
struct fdc_ivars *ivars = device_get_ivars(child);
|
||||||
@ -1089,139 +987,7 @@ fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
fdc_probe(device_t dev)
|
|
||||||
{
|
|
||||||
#ifdef PC98
|
|
||||||
int error;
|
|
||||||
#else
|
|
||||||
int error, ic_type;
|
|
||||||
#endif
|
|
||||||
struct fdc_data *fdc;
|
|
||||||
|
|
||||||
fdc = device_get_softc(dev);
|
|
||||||
bzero(fdc, sizeof *fdc);
|
|
||||||
fdc->fdc_dev = dev;
|
|
||||||
#ifndef PC98
|
|
||||||
fdc->fdctl_wr = fdctl_wr_isa;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check pnp ids */
|
|
||||||
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
|
|
||||||
if (error == ENXIO)
|
|
||||||
return ENXIO;
|
|
||||||
if (error == 0)
|
|
||||||
fdc->flags |= FDC_ISPNP;
|
|
||||||
|
|
||||||
/* Attempt to allocate our resources for the duration of the probe */
|
|
||||||
error = fdc_alloc_resources(fdc);
|
|
||||||
if (error)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
/* First - lets reset the floppy controller */
|
|
||||||
fdout_wr(fdc, 0);
|
|
||||||
DELAY(100);
|
|
||||||
fdout_wr(fdc, FDO_FRST);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* see if it can handle a command */
|
|
||||||
#ifdef PC98
|
|
||||||
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240),
|
|
||||||
NE7_SPEC_2(2, 0), 0)) {
|
|
||||||
error = ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240),
|
|
||||||
NE7_SPEC_2(2, 0), 0)) {
|
|
||||||
error = ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) {
|
|
||||||
ic_type = (u_char)ic_type;
|
|
||||||
switch (ic_type) {
|
|
||||||
case 0x80:
|
|
||||||
device_set_desc(dev, "NEC 765 or clone");
|
|
||||||
fdc->fdct = FDC_NE765;
|
|
||||||
break;
|
|
||||||
case 0x81: /* not mentioned in any hardware doc */
|
|
||||||
case 0x90:
|
|
||||||
device_set_desc(dev,
|
|
||||||
"Enhanced floppy controller (i82077, NE72065 or clone)");
|
|
||||||
fdc->fdct = FDC_ENHANCED;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
device_set_desc(dev, "Generic floppy controller");
|
|
||||||
fdc->fdct = FDC_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
out:
|
|
||||||
fdc_release_resources(fdc);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if NCARD > 0
|
|
||||||
|
|
||||||
static int
|
|
||||||
fdc_pccard_probe(device_t dev)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
struct fdc_data *fdc;
|
|
||||||
|
|
||||||
fdc = device_get_softc(dev);
|
|
||||||
bzero(fdc, sizeof *fdc);
|
|
||||||
fdc->fdc_dev = dev;
|
|
||||||
#ifndef PC98
|
|
||||||
fdc->fdctl_wr = fdctl_wr_pcmcia;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fdc->flags |= FDC_ISPCMCIA | FDC_NODMA;
|
|
||||||
|
|
||||||
/* Attempt to allocate our resources for the duration of the probe */
|
|
||||||
error = fdc_alloc_resources(fdc);
|
|
||||||
if (error)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
/* First - lets reset the floppy controller */
|
|
||||||
fdout_wr(fdc, 0);
|
|
||||||
DELAY(100);
|
|
||||||
fdout_wr(fdc, FDO_FRST);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* see if it can handle a command */
|
|
||||||
#ifdef PC98
|
|
||||||
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240),
|
|
||||||
NE7_SPEC_2(2, 0), 0)) {
|
|
||||||
error = ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240),
|
|
||||||
NE7_SPEC_2(2, 0), 0)) {
|
|
||||||
error = ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
device_set_desc(dev, "Y-E Data PCMCIA floppy");
|
|
||||||
fdc->fdct = FDC_NE765;
|
|
||||||
|
|
||||||
out:
|
|
||||||
fdc_release_resources(fdc);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* NCARD > 0 */
|
|
||||||
|
|
||||||
static int
|
|
||||||
fdc_detach(device_t dev)
|
fdc_detach(device_t dev)
|
||||||
{
|
{
|
||||||
struct fdc_data *fdc;
|
struct fdc_data *fdc;
|
||||||
@ -1241,9 +1007,6 @@ fdc_detach(device_t dev)
|
|||||||
fdout_wr(fdc, 0);
|
fdout_wr(fdc, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((fdc->flags & FDC_NODMA) == 0)
|
|
||||||
isa_dma_release(fdc->dmachan);
|
|
||||||
|
|
||||||
if ((fdc->flags & FDC_ATTACHED) == 0) {
|
if ((fdc->flags & FDC_ATTACHED) == 0) {
|
||||||
device_printf(dev, "already unloaded\n");
|
device_printf(dev, "already unloaded\n");
|
||||||
return (0);
|
return (0);
|
||||||
@ -1253,7 +1016,6 @@ fdc_detach(device_t dev)
|
|||||||
BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
||||||
fdc->fdc_intr);
|
fdc->fdc_intr);
|
||||||
fdc_release_resources(fdc);
|
fdc_release_resources(fdc);
|
||||||
device_printf(dev, "unload\n");
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1284,7 +1046,7 @@ fdc_add_child(device_t dev, const char *name, int unit)
|
|||||||
device_disable(child);
|
device_disable(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
fdc_attach(device_t dev)
|
fdc_attach(device_t dev)
|
||||||
{
|
{
|
||||||
struct fdc_data *fdc;
|
struct fdc_data *fdc;
|
||||||
@ -1307,15 +1069,6 @@ fdc_attach(device_t dev)
|
|||||||
fdc->fdcu = device_get_unit(dev);
|
fdc->fdcu = device_get_unit(dev);
|
||||||
fdc->flags |= FDC_ATTACHED | FDC_NEEDS_RESET;
|
fdc->flags |= FDC_ATTACHED | FDC_NEEDS_RESET;
|
||||||
|
|
||||||
if ((fdc->flags & FDC_NODMA) == 0) {
|
|
||||||
/*
|
|
||||||
* Acquire the DMA channel forever, the driver will do
|
|
||||||
* the rest
|
|
||||||
* XXX should integrate with rman
|
|
||||||
*/
|
|
||||||
isa_dma_acquire(fdc->dmachan);
|
|
||||||
isa_dmainit(fdc->dmachan, MAX_SEC_SIZE);
|
|
||||||
}
|
|
||||||
fdc->state = DEVIDLE;
|
fdc->state = DEVIDLE;
|
||||||
|
|
||||||
#ifdef PC98
|
#ifdef PC98
|
||||||
@ -1342,7 +1095,7 @@ fdc_attach(device_t dev)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
fdc_print_child(device_t me, device_t child)
|
fdc_print_child(device_t me, device_t child)
|
||||||
{
|
{
|
||||||
int retval = 0, flags;
|
int retval = 0, flags;
|
||||||
@ -1357,64 +1110,6 @@ fdc_print_child(device_t me, device_t child)
|
|||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static device_method_t fdc_methods[] = {
|
|
||||||
/* Device interface */
|
|
||||||
DEVMETHOD(device_probe, fdc_probe),
|
|
||||||
DEVMETHOD(device_attach, fdc_attach),
|
|
||||||
DEVMETHOD(device_detach, fdc_detach),
|
|
||||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
|
||||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
|
||||||
DEVMETHOD(device_resume, bus_generic_resume),
|
|
||||||
|
|
||||||
/* Bus interface */
|
|
||||||
DEVMETHOD(bus_print_child, fdc_print_child),
|
|
||||||
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
|
|
||||||
/* Our children never use any other bus interface methods. */
|
|
||||||
|
|
||||||
{ 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static driver_t fdc_driver = {
|
|
||||||
"fdc",
|
|
||||||
fdc_methods,
|
|
||||||
sizeof(struct fdc_data)
|
|
||||||
};
|
|
||||||
|
|
||||||
DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0);
|
|
||||||
#ifndef PC98
|
|
||||||
DRIVER_MODULE(fdc, acpi, fdc_driver, fdc_devclass, 0, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if NCARD > 0
|
|
||||||
|
|
||||||
static device_method_t fdc_pccard_methods[] = {
|
|
||||||
/* Device interface */
|
|
||||||
DEVMETHOD(device_probe, fdc_pccard_probe),
|
|
||||||
DEVMETHOD(device_attach, fdc_attach),
|
|
||||||
DEVMETHOD(device_detach, fdc_detach),
|
|
||||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
|
||||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
|
||||||
DEVMETHOD(device_resume, bus_generic_resume),
|
|
||||||
|
|
||||||
/* Bus interface */
|
|
||||||
DEVMETHOD(bus_print_child, fdc_print_child),
|
|
||||||
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
|
|
||||||
/* Our children never use any other bus interface methods. */
|
|
||||||
|
|
||||||
{ 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static driver_t fdc_pccard_driver = {
|
|
||||||
"fdc",
|
|
||||||
fdc_pccard_methods,
|
|
||||||
sizeof(struct fdc_data)
|
|
||||||
};
|
|
||||||
|
|
||||||
DRIVER_MODULE(fdc, pccard, fdc_pccard_driver, fdc_devclass, 0, 0);
|
|
||||||
|
|
||||||
#endif /* NCARD > 0 */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configuration/initialization, per drive.
|
* Configuration/initialization, per drive.
|
||||||
*/
|
*/
|
||||||
@ -1885,7 +1580,9 @@ fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
|
|||||||
{
|
{
|
||||||
fd_p fd;
|
fd_p fd;
|
||||||
fdc_p fdc;
|
fdc_p fdc;
|
||||||
|
#ifdef PC98
|
||||||
fdu_t fdu;
|
fdu_t fdu;
|
||||||
|
#endif
|
||||||
int rv, unitattn, dflags;
|
int rv, unitattn, dflags;
|
||||||
|
|
||||||
fd = dev->si_drv1;
|
fd = dev->si_drv1;
|
||||||
@ -1894,7 +1591,9 @@ fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
|
|||||||
fdc = fd->fdc;
|
fdc = fd->fdc;
|
||||||
if ((fdc == NULL) || (fd->type == FDT_NONE))
|
if ((fdc == NULL) || (fd->type == FDT_NONE))
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
#ifdef PC98
|
||||||
fdu = fd->fdu;
|
fdu = fd->fdu;
|
||||||
|
#endif
|
||||||
dflags = device_get_flags(fd->dev);
|
dflags = device_get_flags(fd->dev);
|
||||||
/*
|
/*
|
||||||
* This is a bit bogus. It's still possible that e. g. a
|
* This is a bit bogus. It's still possible that e. g. a
|
||||||
@ -1968,6 +1667,14 @@ fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
|
|||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
fd->flags |= FD_OPEN;
|
fd->flags |= FD_OPEN;
|
||||||
|
|
||||||
|
if ((fdc->flags & FDC_NODMA) == 0) {
|
||||||
|
if (fdc->dmacnt++ == 0) {
|
||||||
|
isa_dma_acquire(fdc->dmachan);
|
||||||
|
isa_dmainit(fdc->dmachan, MAX_SEC_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clearing the DMA overrun counter at open time is a bit messy.
|
* Clearing the DMA overrun counter at open time is a bit messy.
|
||||||
* Since we're only managing one counter per controller, opening
|
* Since we're only managing one counter per controller, opening
|
||||||
@ -1988,11 +1695,17 @@ static int
|
|||||||
fdclose(struct cdev *dev, int flags, int mode, struct thread *td)
|
fdclose(struct cdev *dev, int flags, int mode, struct thread *td)
|
||||||
{
|
{
|
||||||
struct fd_data *fd;
|
struct fd_data *fd;
|
||||||
|
fdc_p fdc;
|
||||||
|
|
||||||
fd = dev->si_drv1;
|
fd = dev->si_drv1;
|
||||||
|
fdc = fd->fdc;
|
||||||
fd->flags &= ~(FD_OPEN | FD_NONBLOCK);
|
fd->flags &= ~(FD_OPEN | FD_NONBLOCK);
|
||||||
fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR);
|
fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR);
|
||||||
|
|
||||||
|
if ((fdc->flags & FDC_NODMA) == 0)
|
||||||
|
if (--fdc->dmacnt == 0)
|
||||||
|
isa_dma_release(fdc->dmachan);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2043,6 +1756,13 @@ fdstrategy(struct bio *bp)
|
|||||||
/*
|
/*
|
||||||
* Set up block calculations.
|
* Set up block calculations.
|
||||||
*/
|
*/
|
||||||
|
#ifndef PC98
|
||||||
|
if (bp->bio_offset >= ((off_t)128 << fd->ft->secsize) * fd->ft->size) {
|
||||||
|
bp->bio_error = EINVAL;
|
||||||
|
bp->bio_flags |= BIO_ERROR;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
blknum = bp->bio_offset / fdblk;
|
blknum = bp->bio_offset / fdblk;
|
||||||
nblocks = fd->ft->size;
|
nblocks = fd->ft->size;
|
||||||
if (blknum + bp->bio_bcount / fdblk > nblocks) {
|
if (blknum + bp->bio_bcount / fdblk > nblocks) {
|
||||||
|
99
sys/pc98/cbus/fdc_cbus.c
Normal file
99
sys/pc98/cbus/fdc_cbus.c
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004 Yoshihiro TAKAHASHI
|
||||||
|
* 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,
|
||||||
|
* without modification, immediately at the beginning of the file.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/bio.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
|
||||||
|
#include <pc98/pc98/fdcvar.h>
|
||||||
|
#include <pc98/pc98/fdreg.h>
|
||||||
|
|
||||||
|
#include <isa/isavar.h>
|
||||||
|
#include <pc98/pc98/pc98.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
fdc_cbus_probe(device_t dev)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
struct fdc_data *fdc;
|
||||||
|
|
||||||
|
fdc = device_get_softc(dev);
|
||||||
|
bzero(fdc, sizeof *fdc);
|
||||||
|
fdc->fdc_dev = dev;
|
||||||
|
|
||||||
|
/* Check pnp ids */
|
||||||
|
if (isa_get_vendorid(dev))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
/* Attempt to allocate our resources for the duration of the probe */
|
||||||
|
error = fdc_alloc_resources(fdc);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* see if it can handle a command */
|
||||||
|
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240),
|
||||||
|
NE7_SPEC_2(2, 0), 0)) {
|
||||||
|
error = ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
fdc_release_resources(fdc);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static device_method_t fdc_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, fdc_cbus_probe),
|
||||||
|
DEVMETHOD(device_attach, fdc_attach),
|
||||||
|
DEVMETHOD(device_detach, fdc_detach),
|
||||||
|
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||||
|
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||||
|
DEVMETHOD(device_resume, bus_generic_resume),
|
||||||
|
|
||||||
|
/* Bus interface */
|
||||||
|
DEVMETHOD(bus_print_child, fdc_print_child),
|
||||||
|
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
|
||||||
|
/* Our children never use any other bus interface methods. */
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t fdc_driver = {
|
||||||
|
"fdc",
|
||||||
|
fdc_methods,
|
||||||
|
sizeof(struct fdc_data)
|
||||||
|
};
|
||||||
|
|
||||||
|
DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0);
|
153
sys/pc98/cbus/fdcvar.h
Normal file
153
sys/pc98/cbus/fdcvar.h
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004 M. Warner Losh.
|
||||||
|
* 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,
|
||||||
|
* without modification, immediately at the beginning of the file.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* XXX should audit this file to see if additional copyrights needed */
|
||||||
|
|
||||||
|
enum fdc_type
|
||||||
|
{
|
||||||
|
FDC_NE765, FDC_ENHANCED, FDC_UNKNOWN = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fdc_states {
|
||||||
|
DEVIDLE,
|
||||||
|
FINDWORK,
|
||||||
|
DOSEEK,
|
||||||
|
SEEKCOMPLETE ,
|
||||||
|
IOCOMPLETE,
|
||||||
|
RECALCOMPLETE,
|
||||||
|
STARTRECAL,
|
||||||
|
RESETCTLR,
|
||||||
|
SEEKWAIT,
|
||||||
|
RECALWAIT,
|
||||||
|
MOTORWAIT,
|
||||||
|
IOTIMEDOUT,
|
||||||
|
RESETCOMPLETE,
|
||||||
|
PIOREAD
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef FDC_DEBUG
|
||||||
|
static char const * const fdstates[] = {
|
||||||
|
"DEVIDLE",
|
||||||
|
"FINDWORK",
|
||||||
|
"DOSEEK",
|
||||||
|
"SEEKCOMPLETE",
|
||||||
|
"IOCOMPLETE",
|
||||||
|
"RECALCOMPLETE",
|
||||||
|
"STARTRECAL",
|
||||||
|
"RESETCTLR",
|
||||||
|
"SEEKWAIT",
|
||||||
|
"RECALWAIT",
|
||||||
|
"MOTORWAIT",
|
||||||
|
"IOTIMEDOUT",
|
||||||
|
"RESETCOMPLETE",
|
||||||
|
"PIOREAD"
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Per controller structure (softc).
|
||||||
|
*/
|
||||||
|
struct fdc_data
|
||||||
|
{
|
||||||
|
int fdcu; /* our unit number */
|
||||||
|
int dmacnt;
|
||||||
|
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 */
|
||||||
|
enum fdc_states state;
|
||||||
|
int retry;
|
||||||
|
#ifndef PC98
|
||||||
|
int fdout; /* mirror of the w/o digital output reg */
|
||||||
|
#endif
|
||||||
|
u_int status[7]; /* copy of the registers */
|
||||||
|
enum fdc_type fdct; /* chip version of FDC */
|
||||||
|
int fdc_errs; /* number of logged errors */
|
||||||
|
int dma_overruns; /* number of DMA overruns */
|
||||||
|
struct bio_queue_head head;
|
||||||
|
struct bio *bp; /* active buffer */
|
||||||
|
#ifdef PC98
|
||||||
|
struct resource *res_ioport, *res_fdsio, *res_fdemsio;
|
||||||
|
struct resource *res_irq, *res_drq;
|
||||||
|
int rid_ioport, rid_irq, rid_drq;
|
||||||
|
#else
|
||||||
|
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
|
||||||
|
int rid_ioport, rid_ctl, rid_irq, rid_drq;
|
||||||
|
#endif
|
||||||
|
int port_off;
|
||||||
|
bus_space_tag_t portt;
|
||||||
|
bus_space_handle_t porth;
|
||||||
|
#ifdef PC98
|
||||||
|
bus_space_tag_t sc_fdsiot;
|
||||||
|
bus_space_handle_t sc_fdsioh;
|
||||||
|
bus_space_tag_t sc_fdemsiot;
|
||||||
|
bus_space_handle_t sc_fdemsioh;
|
||||||
|
#else
|
||||||
|
bus_space_tag_t ctlt;
|
||||||
|
bus_space_handle_t ctlh;
|
||||||
|
#endif
|
||||||
|
void *fdc_intr;
|
||||||
|
struct device *fdc_dev;
|
||||||
|
#ifndef PC98
|
||||||
|
void (*fdctl_wr)(struct fdc_data *fdc, u_int8_t v);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int fdu_t;
|
||||||
|
typedef int fdcu_t;
|
||||||
|
typedef int fdsu_t;
|
||||||
|
typedef struct fd_data *fd_p;
|
||||||
|
typedef struct fdc_data *fdc_p;
|
||||||
|
typedef enum fdc_type fdc_t;
|
||||||
|
|
||||||
|
/* error returns for fd_cmd() */
|
||||||
|
#define FD_FAILED -1
|
||||||
|
#define FD_NOT_VALID -2
|
||||||
|
#define FDC_ERRMAX 100 /* do not log more */
|
||||||
|
|
||||||
|
extern devclass_t fdc_devclass;
|
||||||
|
|
||||||
|
int fdc_alloc_resources(struct fdc_data *);
|
||||||
|
#ifndef PC98
|
||||||
|
void fdout_wr(fdc_p, u_int8_t);
|
||||||
|
#endif
|
||||||
|
int fd_cmd(struct fdc_data *, int, ...);
|
||||||
|
void fdc_release_resources(struct fdc_data *);
|
||||||
|
int fdc_attach(device_t);
|
||||||
|
int fdc_detach(device_t dev);
|
||||||
|
int fdc_print_child(device_t, device_t);
|
||||||
|
int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
|
@ -54,13 +54,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "opt_fdc.h"
|
#include "opt_fdc.h"
|
||||||
#include "card.h"
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
|
||||||
#include <sys/bio.h>
|
#include <sys/bio.h>
|
||||||
#include <sys/bus.h>
|
#include <sys/bus.h>
|
||||||
#include <sys/conf.h>
|
|
||||||
#include <sys/devicestat.h>
|
#include <sys/devicestat.h>
|
||||||
#include <sys/disk.h>
|
#include <sys/disk.h>
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
@ -72,132 +69,29 @@
|
|||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/syslog.h>
|
|
||||||
|
|
||||||
#include <machine/bus.h>
|
|
||||||
#include <sys/rman.h>
|
#include <sys/rman.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
|
||||||
#include <machine/clock.h>
|
#include <machine/clock.h>
|
||||||
#include <machine/resource.h>
|
|
||||||
#include <machine/stdarg.h>
|
#include <machine/stdarg.h>
|
||||||
|
|
||||||
#include <isa/isavar.h>
|
|
||||||
#ifdef PC98
|
#ifdef PC98
|
||||||
|
#include <isa/isavar.h>
|
||||||
#include <pc98/pc98/pc98.h>
|
#include <pc98/pc98/pc98.h>
|
||||||
#include <pc98/pc98/pc98_machdep.h>
|
#include <pc98/pc98/pc98_machdep.h>
|
||||||
#include <pc98/pc98/epsonio.h>
|
#include <pc98/pc98/epsonio.h>
|
||||||
#include <pc98/pc98/fdreg.h>
|
#include <pc98/pc98/fdreg.h>
|
||||||
|
#include <pc98/pc98/fdcvar.h>
|
||||||
#else
|
#else
|
||||||
|
#include <isa/isavar.h>
|
||||||
#include <isa/isareg.h>
|
#include <isa/isareg.h>
|
||||||
#include <isa/fdreg.h>
|
#include <dev/fdc/fdcreg.h>
|
||||||
|
#include <dev/fdc/fdcvar.h>
|
||||||
#include <isa/rtc.h>
|
#include <isa/rtc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum fdc_type
|
|
||||||
{
|
|
||||||
FDC_NE765, FDC_ENHANCED, FDC_UNKNOWN = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum fdc_states {
|
|
||||||
DEVIDLE,
|
|
||||||
FINDWORK,
|
|
||||||
DOSEEK,
|
|
||||||
SEEKCOMPLETE ,
|
|
||||||
IOCOMPLETE,
|
|
||||||
RECALCOMPLETE,
|
|
||||||
STARTRECAL,
|
|
||||||
RESETCTLR,
|
|
||||||
SEEKWAIT,
|
|
||||||
RECALWAIT,
|
|
||||||
MOTORWAIT,
|
|
||||||
IOTIMEDOUT,
|
|
||||||
RESETCOMPLETE,
|
|
||||||
PIOREAD
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef FDC_DEBUG
|
|
||||||
static char const * const fdstates[] = {
|
|
||||||
"DEVIDLE",
|
|
||||||
"FINDWORK",
|
|
||||||
"DOSEEK",
|
|
||||||
"SEEKCOMPLETE",
|
|
||||||
"IOCOMPLETE",
|
|
||||||
"RECALCOMPLETE",
|
|
||||||
"STARTRECAL",
|
|
||||||
"RESETCTLR",
|
|
||||||
"SEEKWAIT",
|
|
||||||
"RECALWAIT",
|
|
||||||
"MOTORWAIT",
|
|
||||||
"IOTIMEDOUT",
|
|
||||||
"RESETCOMPLETE",
|
|
||||||
"PIOREAD"
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Per controller structure (softc).
|
|
||||||
*/
|
|
||||||
struct fdc_data
|
|
||||||
{
|
|
||||||
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 */
|
|
||||||
enum fdc_states state;
|
|
||||||
int retry;
|
|
||||||
#ifndef PC98
|
|
||||||
int fdout; /* mirror of the w/o digital output reg */
|
|
||||||
#endif
|
|
||||||
u_int status[7]; /* copy of the registers */
|
|
||||||
enum fdc_type fdct; /* chip version of FDC */
|
|
||||||
int fdc_errs; /* number of logged errors */
|
|
||||||
int dma_overruns; /* number of DMA overruns */
|
|
||||||
struct bio_queue_head head;
|
|
||||||
struct bio *bp; /* active buffer */
|
|
||||||
#ifdef PC98
|
|
||||||
struct resource *res_ioport, *res_fdsio, *res_fdemsio;
|
|
||||||
struct resource *res_irq, *res_drq;
|
|
||||||
int rid_ioport, rid_irq, rid_drq;
|
|
||||||
#else
|
|
||||||
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
|
|
||||||
int rid_ioport, rid_ctl, rid_irq, rid_drq;
|
|
||||||
#endif
|
|
||||||
int port_off;
|
|
||||||
bus_space_tag_t portt;
|
|
||||||
bus_space_handle_t porth;
|
|
||||||
#ifdef PC98
|
|
||||||
bus_space_tag_t sc_fdsiot;
|
|
||||||
bus_space_handle_t sc_fdsioh;
|
|
||||||
bus_space_tag_t sc_fdemsiot;
|
|
||||||
bus_space_handle_t sc_fdemsioh;
|
|
||||||
#else
|
|
||||||
bus_space_tag_t ctlt;
|
|
||||||
bus_space_handle_t ctlh;
|
|
||||||
#endif
|
|
||||||
void *fdc_intr;
|
|
||||||
struct device *fdc_dev;
|
|
||||||
#ifndef PC98
|
|
||||||
void (*fdctl_wr)(struct fdc_data *fdc, u_int8_t v);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#define FDBIO_FORMAT BIO_CMD2
|
#define FDBIO_FORMAT BIO_CMD2
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fdc maintains a set (1!) of ivars per child of each controller.
|
* fdc maintains a set (1!) of ivars per child of each controller.
|
||||||
*/
|
*/
|
||||||
@ -220,10 +114,6 @@ FDC_ACCESSOR(fdunit, FDUNIT, int)
|
|||||||
/* configuration flags for fdc */
|
/* configuration flags for fdc */
|
||||||
#define FDC_NO_FIFO (1 << 2) /* do not enable FIFO */
|
#define FDC_NO_FIFO (1 << 2) /* do not enable FIFO */
|
||||||
|
|
||||||
/* error returns for fd_cmd() */
|
|
||||||
#define FD_FAILED -1
|
|
||||||
#define FD_NOT_VALID -2
|
|
||||||
#define FDC_ERRMAX 100 /* do not log more */
|
|
||||||
/*
|
/*
|
||||||
* Stop retrying after this many DMA overruns. Since each retry takes
|
* Stop retrying after this many DMA overruns. Since each retry takes
|
||||||
* one revolution, with 300 rpm., 25 retries take approximately 5
|
* one revolution, with 300 rpm., 25 retries take approximately 5
|
||||||
@ -353,7 +243,7 @@ static struct fd_type fd_searchlist_288m[] = {
|
|||||||
* up to cyl 82 */
|
* up to cyl 82 */
|
||||||
#define MAX_HEAD 1
|
#define MAX_HEAD 1
|
||||||
|
|
||||||
static devclass_t fdc_devclass;
|
devclass_t fdc_devclass;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Per drive structure (softc).
|
* Per drive structure (softc).
|
||||||
@ -476,38 +366,15 @@ nrd_info(addr)
|
|||||||
* as below -- makes locating a particular function in the body much
|
* as below -- makes locating a particular function in the body much
|
||||||
* easier.
|
* easier.
|
||||||
*/
|
*/
|
||||||
#ifndef PC98
|
|
||||||
static void fdout_wr(fdc_p, u_int8_t);
|
|
||||||
#endif
|
|
||||||
static u_int8_t fdsts_rd(fdc_p);
|
static u_int8_t fdsts_rd(fdc_p);
|
||||||
static void fddata_wr(fdc_p, u_int8_t);
|
static void fddata_wr(fdc_p, u_int8_t);
|
||||||
static u_int8_t fddata_rd(fdc_p);
|
static u_int8_t fddata_rd(fdc_p);
|
||||||
#ifndef PC98
|
|
||||||
static void fdctl_wr_isa(fdc_p, u_int8_t);
|
|
||||||
#if NCARD > 0
|
|
||||||
static void fdctl_wr_pcmcia(fdc_p, u_int8_t);
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
static u_int8_t fdin_rd(fdc_p);
|
|
||||||
#endif
|
|
||||||
#endif /* PC98 */
|
|
||||||
static int fdc_err(struct fdc_data *, const char *);
|
static int fdc_err(struct fdc_data *, const char *);
|
||||||
static int fd_cmd(struct fdc_data *, int, ...);
|
|
||||||
static int enable_fifo(fdc_p fdc);
|
static int enable_fifo(fdc_p fdc);
|
||||||
static int fd_sense_drive_status(fdc_p, int *);
|
static int fd_sense_drive_status(fdc_p, int *);
|
||||||
static int fd_sense_int(fdc_p, int *, int *);
|
static int fd_sense_int(fdc_p, int *, int *);
|
||||||
static int fd_read_status(fdc_p);
|
static int fd_read_status(fdc_p);
|
||||||
static int fdc_alloc_resources(struct fdc_data *);
|
|
||||||
static void fdc_release_resources(struct fdc_data *);
|
|
||||||
static int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
|
|
||||||
static int fdc_probe(device_t);
|
|
||||||
#if NCARD > 0
|
|
||||||
static int fdc_pccard_probe(device_t);
|
|
||||||
#endif
|
|
||||||
static int fdc_detach(device_t dev);
|
|
||||||
static void fdc_add_child(device_t, const char *, int);
|
static void fdc_add_child(device_t, const char *, int);
|
||||||
static int fdc_attach(device_t);
|
|
||||||
static int fdc_print_child(device_t, device_t);
|
|
||||||
static int fd_probe(device_t);
|
static int fd_probe(device_t);
|
||||||
static int fd_attach(device_t);
|
static int fd_attach(device_t);
|
||||||
static int fd_detach(device_t);
|
static int fd_detach(device_t);
|
||||||
@ -555,7 +422,7 @@ static int volatile fd_debug = 0;
|
|||||||
* Bus space handling (access to low-level IO).
|
* Bus space handling (access to low-level IO).
|
||||||
*/
|
*/
|
||||||
#ifndef PC98
|
#ifndef PC98
|
||||||
static void
|
void
|
||||||
fdout_wr(fdc_p fdc, u_int8_t v)
|
fdout_wr(fdc_p fdc, u_int8_t v)
|
||||||
{
|
{
|
||||||
bus_space_write_1(fdc->portt, fdc->porth, FDOUT+fdc->port_off, v);
|
bus_space_write_1(fdc->portt, fdc->porth, FDOUT+fdc->port_off, v);
|
||||||
@ -589,20 +456,6 @@ fdctl_wr(fdc_p fdc, u_int8_t v)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PC98
|
#ifndef PC98
|
||||||
static void
|
|
||||||
fdctl_wr_isa(fdc_p fdc, u_int8_t v)
|
|
||||||
{
|
|
||||||
bus_space_write_1(fdc->ctlt, fdc->ctlh, 0, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if NCARD > 0
|
|
||||||
static void
|
|
||||||
fdctl_wr_pcmcia(fdc_p fdc, u_int8_t v)
|
|
||||||
{
|
|
||||||
bus_space_write_1(fdc->portt, fdc->porth, FDCTL+fdc->port_off, v);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static u_int8_t
|
static u_int8_t
|
||||||
fdin_rd(fdc_p fdc)
|
fdin_rd(fdc_p fdc)
|
||||||
{
|
{
|
||||||
@ -647,7 +500,7 @@ fdc_err(struct fdc_data *fdc, const char *s)
|
|||||||
* # of output bytes, output bytes as ints ...,
|
* # of output bytes, output bytes as ints ...,
|
||||||
* # of input bytes, input bytes as ints ...
|
* # of input bytes, input bytes as ints ...
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
fd_cmd(struct fdc_data *fdc, int n_out, ...)
|
fd_cmd(struct fdc_data *fdc, int n_out, ...)
|
||||||
{
|
{
|
||||||
u_char cmd;
|
u_char cmd;
|
||||||
@ -876,7 +729,7 @@ static int pc98_fd_check_ready(fdu_t fdu)
|
|||||||
}
|
}
|
||||||
#endif /* PC98 */
|
#endif /* PC98 */
|
||||||
|
|
||||||
static int
|
int
|
||||||
fdc_alloc_resources(struct fdc_data *fdc)
|
fdc_alloc_resources(struct fdc_data *fdc)
|
||||||
{
|
{
|
||||||
device_t dev;
|
device_t dev;
|
||||||
@ -893,6 +746,9 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
#endif
|
#endif
|
||||||
fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0;
|
fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0;
|
||||||
fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0;
|
fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0;
|
||||||
|
#ifndef PC98
|
||||||
|
fdc->rid_ctl = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PC98
|
#ifdef PC98
|
||||||
fdc->res_ioport = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
|
fdc->res_ioport = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
|
||||||
@ -916,6 +772,40 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
* one with offset 7 as control register.
|
* one with offset 7 as control register.
|
||||||
*/
|
*/
|
||||||
nports = ispcmcia ? 8 : (ispnp ? 1 : 6);
|
nports = ispcmcia ? 8 : (ispnp ? 1 : 6);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some ACPI BIOSen have _CRS objects for the floppy device that
|
||||||
|
* split the I/O port resource into several resources. We detect
|
||||||
|
* this case by checking if there are more than 2 IOPORT resources.
|
||||||
|
* If so, we use the resource with the smallest start address as
|
||||||
|
* the port RID and the largest start address as the control RID.
|
||||||
|
*/
|
||||||
|
if (bus_get_resource_count(dev, SYS_RES_IOPORT, 2) != 0) {
|
||||||
|
u_long min_start, max_start, tmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Find the min/max start addresses and their RIDs. */
|
||||||
|
max_start = 0ul;
|
||||||
|
min_start = ~0ul;
|
||||||
|
for (i = 0; bus_get_resource_count(dev, SYS_RES_IOPORT, i) > 0;
|
||||||
|
i++) {
|
||||||
|
tmp = bus_get_resource_start(dev, SYS_RES_IOPORT, i);
|
||||||
|
KASSERT(tmp != 0, ("bogus resource"));
|
||||||
|
if (tmp < min_start) {
|
||||||
|
min_start = tmp;
|
||||||
|
fdc->rid_ioport = i;
|
||||||
|
}
|
||||||
|
if (tmp > max_start) {
|
||||||
|
max_start = tmp;
|
||||||
|
fdc->rid_ctl = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (min_start + 7 != max_start) {
|
||||||
|
device_printf(dev, "I/O to control range incorrect\n");
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
|
fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
|
||||||
&fdc->rid_ioport, 0ul, ~0ul,
|
&fdc->rid_ioport, 0ul, ~0ul,
|
||||||
nports, RF_ACTIVE);
|
nports, RF_ACTIVE);
|
||||||
@ -985,7 +875,6 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
/*
|
/*
|
||||||
* Now (finally!) allocate the control port.
|
* Now (finally!) allocate the control port.
|
||||||
*/
|
*/
|
||||||
fdc->rid_ctl = 1;
|
|
||||||
fdc->res_ctl = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
|
fdc->res_ctl = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
|
||||||
&fdc->rid_ctl, RF_ACTIVE);
|
&fdc->rid_ctl, RF_ACTIVE);
|
||||||
if (fdc->res_ctl == 0) {
|
if (fdc->res_ctl == 0) {
|
||||||
@ -998,14 +887,20 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
|
#ifdef PC98
|
||||||
&fdc->rid_irq, RF_ACTIVE);
|
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
|
||||||
|
RF_ACTIVE);
|
||||||
|
#else
|
||||||
|
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
|
||||||
|
RF_ACTIVE | RF_SHAREABLE);
|
||||||
|
#endif
|
||||||
if (fdc->res_irq == 0) {
|
if (fdc->res_irq == 0) {
|
||||||
device_printf(dev, "cannot reserve interrupt line\n");
|
device_printf(dev, "cannot reserve interrupt line\n");
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fdc->flags & FDC_NODMA) == 0) {
|
if ((fdc->flags & FDC_NODMA) == 0) {
|
||||||
|
#ifdef PC98
|
||||||
fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
|
fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
|
||||||
&fdc->rid_drq, RF_ACTIVE);
|
&fdc->rid_drq, RF_ACTIVE);
|
||||||
if (fdc->res_drq == 0) {
|
if (fdc->res_drq == 0) {
|
||||||
@ -1013,12 +908,21 @@ fdc_alloc_resources(struct fdc_data *fdc)
|
|||||||
return ENXIO;
|
return ENXIO;
|
||||||
}
|
}
|
||||||
fdc->dmachan = rman_get_start(fdc->res_drq);
|
fdc->dmachan = rman_get_start(fdc->res_drq);
|
||||||
|
#else
|
||||||
|
fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
|
||||||
|
&fdc->rid_drq, RF_ACTIVE | RF_SHAREABLE);
|
||||||
|
if (fdc->res_drq == 0) {
|
||||||
|
device_printf(dev, "cannot reserve DMA request line\n");
|
||||||
|
fdc->flags |= FDC_NODMA;
|
||||||
|
} else
|
||||||
|
fdc->dmachan = rman_get_start(fdc->res_drq);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
fdc_release_resources(struct fdc_data *fdc)
|
fdc_release_resources(struct fdc_data *fdc)
|
||||||
{
|
{
|
||||||
device_t dev;
|
device_t dev;
|
||||||
@ -1068,13 +972,7 @@ fdc_release_resources(struct fdc_data *fdc)
|
|||||||
* Configuration/initialization stuff, per controller.
|
* Configuration/initialization stuff, per controller.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct isa_pnp_id fdc_ids[] = {
|
int
|
||||||
{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
|
|
||||||
{0x0107d041, "Standard floppy controller supporting MS Device Bay Spec"}, /* PNP0701 */
|
|
||||||
{0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
||||||
{
|
{
|
||||||
struct fdc_ivars *ivars = device_get_ivars(child);
|
struct fdc_ivars *ivars = device_get_ivars(child);
|
||||||
@ -1089,139 +987,7 @@ fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
fdc_probe(device_t dev)
|
|
||||||
{
|
|
||||||
#ifdef PC98
|
|
||||||
int error;
|
|
||||||
#else
|
|
||||||
int error, ic_type;
|
|
||||||
#endif
|
|
||||||
struct fdc_data *fdc;
|
|
||||||
|
|
||||||
fdc = device_get_softc(dev);
|
|
||||||
bzero(fdc, sizeof *fdc);
|
|
||||||
fdc->fdc_dev = dev;
|
|
||||||
#ifndef PC98
|
|
||||||
fdc->fdctl_wr = fdctl_wr_isa;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check pnp ids */
|
|
||||||
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
|
|
||||||
if (error == ENXIO)
|
|
||||||
return ENXIO;
|
|
||||||
if (error == 0)
|
|
||||||
fdc->flags |= FDC_ISPNP;
|
|
||||||
|
|
||||||
/* Attempt to allocate our resources for the duration of the probe */
|
|
||||||
error = fdc_alloc_resources(fdc);
|
|
||||||
if (error)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
/* First - lets reset the floppy controller */
|
|
||||||
fdout_wr(fdc, 0);
|
|
||||||
DELAY(100);
|
|
||||||
fdout_wr(fdc, FDO_FRST);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* see if it can handle a command */
|
|
||||||
#ifdef PC98
|
|
||||||
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240),
|
|
||||||
NE7_SPEC_2(2, 0), 0)) {
|
|
||||||
error = ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240),
|
|
||||||
NE7_SPEC_2(2, 0), 0)) {
|
|
||||||
error = ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) {
|
|
||||||
ic_type = (u_char)ic_type;
|
|
||||||
switch (ic_type) {
|
|
||||||
case 0x80:
|
|
||||||
device_set_desc(dev, "NEC 765 or clone");
|
|
||||||
fdc->fdct = FDC_NE765;
|
|
||||||
break;
|
|
||||||
case 0x81: /* not mentioned in any hardware doc */
|
|
||||||
case 0x90:
|
|
||||||
device_set_desc(dev,
|
|
||||||
"Enhanced floppy controller (i82077, NE72065 or clone)");
|
|
||||||
fdc->fdct = FDC_ENHANCED;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
device_set_desc(dev, "Generic floppy controller");
|
|
||||||
fdc->fdct = FDC_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
out:
|
|
||||||
fdc_release_resources(fdc);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if NCARD > 0
|
|
||||||
|
|
||||||
static int
|
|
||||||
fdc_pccard_probe(device_t dev)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
struct fdc_data *fdc;
|
|
||||||
|
|
||||||
fdc = device_get_softc(dev);
|
|
||||||
bzero(fdc, sizeof *fdc);
|
|
||||||
fdc->fdc_dev = dev;
|
|
||||||
#ifndef PC98
|
|
||||||
fdc->fdctl_wr = fdctl_wr_pcmcia;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fdc->flags |= FDC_ISPCMCIA | FDC_NODMA;
|
|
||||||
|
|
||||||
/* Attempt to allocate our resources for the duration of the probe */
|
|
||||||
error = fdc_alloc_resources(fdc);
|
|
||||||
if (error)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
#ifndef PC98
|
|
||||||
/* First - lets reset the floppy controller */
|
|
||||||
fdout_wr(fdc, 0);
|
|
||||||
DELAY(100);
|
|
||||||
fdout_wr(fdc, FDO_FRST);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* see if it can handle a command */
|
|
||||||
#ifdef PC98
|
|
||||||
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240),
|
|
||||||
NE7_SPEC_2(2, 0), 0)) {
|
|
||||||
error = ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240),
|
|
||||||
NE7_SPEC_2(2, 0), 0)) {
|
|
||||||
error = ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
device_set_desc(dev, "Y-E Data PCMCIA floppy");
|
|
||||||
fdc->fdct = FDC_NE765;
|
|
||||||
|
|
||||||
out:
|
|
||||||
fdc_release_resources(fdc);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* NCARD > 0 */
|
|
||||||
|
|
||||||
static int
|
|
||||||
fdc_detach(device_t dev)
|
fdc_detach(device_t dev)
|
||||||
{
|
{
|
||||||
struct fdc_data *fdc;
|
struct fdc_data *fdc;
|
||||||
@ -1241,9 +1007,6 @@ fdc_detach(device_t dev)
|
|||||||
fdout_wr(fdc, 0);
|
fdout_wr(fdc, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((fdc->flags & FDC_NODMA) == 0)
|
|
||||||
isa_dma_release(fdc->dmachan);
|
|
||||||
|
|
||||||
if ((fdc->flags & FDC_ATTACHED) == 0) {
|
if ((fdc->flags & FDC_ATTACHED) == 0) {
|
||||||
device_printf(dev, "already unloaded\n");
|
device_printf(dev, "already unloaded\n");
|
||||||
return (0);
|
return (0);
|
||||||
@ -1253,7 +1016,6 @@ fdc_detach(device_t dev)
|
|||||||
BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
||||||
fdc->fdc_intr);
|
fdc->fdc_intr);
|
||||||
fdc_release_resources(fdc);
|
fdc_release_resources(fdc);
|
||||||
device_printf(dev, "unload\n");
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1284,7 +1046,7 @@ fdc_add_child(device_t dev, const char *name, int unit)
|
|||||||
device_disable(child);
|
device_disable(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
fdc_attach(device_t dev)
|
fdc_attach(device_t dev)
|
||||||
{
|
{
|
||||||
struct fdc_data *fdc;
|
struct fdc_data *fdc;
|
||||||
@ -1307,15 +1069,6 @@ fdc_attach(device_t dev)
|
|||||||
fdc->fdcu = device_get_unit(dev);
|
fdc->fdcu = device_get_unit(dev);
|
||||||
fdc->flags |= FDC_ATTACHED | FDC_NEEDS_RESET;
|
fdc->flags |= FDC_ATTACHED | FDC_NEEDS_RESET;
|
||||||
|
|
||||||
if ((fdc->flags & FDC_NODMA) == 0) {
|
|
||||||
/*
|
|
||||||
* Acquire the DMA channel forever, the driver will do
|
|
||||||
* the rest
|
|
||||||
* XXX should integrate with rman
|
|
||||||
*/
|
|
||||||
isa_dma_acquire(fdc->dmachan);
|
|
||||||
isa_dmainit(fdc->dmachan, MAX_SEC_SIZE);
|
|
||||||
}
|
|
||||||
fdc->state = DEVIDLE;
|
fdc->state = DEVIDLE;
|
||||||
|
|
||||||
#ifdef PC98
|
#ifdef PC98
|
||||||
@ -1342,7 +1095,7 @@ fdc_attach(device_t dev)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
fdc_print_child(device_t me, device_t child)
|
fdc_print_child(device_t me, device_t child)
|
||||||
{
|
{
|
||||||
int retval = 0, flags;
|
int retval = 0, flags;
|
||||||
@ -1357,64 +1110,6 @@ fdc_print_child(device_t me, device_t child)
|
|||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static device_method_t fdc_methods[] = {
|
|
||||||
/* Device interface */
|
|
||||||
DEVMETHOD(device_probe, fdc_probe),
|
|
||||||
DEVMETHOD(device_attach, fdc_attach),
|
|
||||||
DEVMETHOD(device_detach, fdc_detach),
|
|
||||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
|
||||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
|
||||||
DEVMETHOD(device_resume, bus_generic_resume),
|
|
||||||
|
|
||||||
/* Bus interface */
|
|
||||||
DEVMETHOD(bus_print_child, fdc_print_child),
|
|
||||||
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
|
|
||||||
/* Our children never use any other bus interface methods. */
|
|
||||||
|
|
||||||
{ 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static driver_t fdc_driver = {
|
|
||||||
"fdc",
|
|
||||||
fdc_methods,
|
|
||||||
sizeof(struct fdc_data)
|
|
||||||
};
|
|
||||||
|
|
||||||
DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0);
|
|
||||||
#ifndef PC98
|
|
||||||
DRIVER_MODULE(fdc, acpi, fdc_driver, fdc_devclass, 0, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if NCARD > 0
|
|
||||||
|
|
||||||
static device_method_t fdc_pccard_methods[] = {
|
|
||||||
/* Device interface */
|
|
||||||
DEVMETHOD(device_probe, fdc_pccard_probe),
|
|
||||||
DEVMETHOD(device_attach, fdc_attach),
|
|
||||||
DEVMETHOD(device_detach, fdc_detach),
|
|
||||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
|
||||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
|
||||||
DEVMETHOD(device_resume, bus_generic_resume),
|
|
||||||
|
|
||||||
/* Bus interface */
|
|
||||||
DEVMETHOD(bus_print_child, fdc_print_child),
|
|
||||||
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
|
|
||||||
/* Our children never use any other bus interface methods. */
|
|
||||||
|
|
||||||
{ 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static driver_t fdc_pccard_driver = {
|
|
||||||
"fdc",
|
|
||||||
fdc_pccard_methods,
|
|
||||||
sizeof(struct fdc_data)
|
|
||||||
};
|
|
||||||
|
|
||||||
DRIVER_MODULE(fdc, pccard, fdc_pccard_driver, fdc_devclass, 0, 0);
|
|
||||||
|
|
||||||
#endif /* NCARD > 0 */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configuration/initialization, per drive.
|
* Configuration/initialization, per drive.
|
||||||
*/
|
*/
|
||||||
@ -1885,7 +1580,9 @@ fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
|
|||||||
{
|
{
|
||||||
fd_p fd;
|
fd_p fd;
|
||||||
fdc_p fdc;
|
fdc_p fdc;
|
||||||
|
#ifdef PC98
|
||||||
fdu_t fdu;
|
fdu_t fdu;
|
||||||
|
#endif
|
||||||
int rv, unitattn, dflags;
|
int rv, unitattn, dflags;
|
||||||
|
|
||||||
fd = dev->si_drv1;
|
fd = dev->si_drv1;
|
||||||
@ -1894,7 +1591,9 @@ fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
|
|||||||
fdc = fd->fdc;
|
fdc = fd->fdc;
|
||||||
if ((fdc == NULL) || (fd->type == FDT_NONE))
|
if ((fdc == NULL) || (fd->type == FDT_NONE))
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
#ifdef PC98
|
||||||
fdu = fd->fdu;
|
fdu = fd->fdu;
|
||||||
|
#endif
|
||||||
dflags = device_get_flags(fd->dev);
|
dflags = device_get_flags(fd->dev);
|
||||||
/*
|
/*
|
||||||
* This is a bit bogus. It's still possible that e. g. a
|
* This is a bit bogus. It's still possible that e. g. a
|
||||||
@ -1968,6 +1667,14 @@ fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
|
|||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
fd->flags |= FD_OPEN;
|
fd->flags |= FD_OPEN;
|
||||||
|
|
||||||
|
if ((fdc->flags & FDC_NODMA) == 0) {
|
||||||
|
if (fdc->dmacnt++ == 0) {
|
||||||
|
isa_dma_acquire(fdc->dmachan);
|
||||||
|
isa_dmainit(fdc->dmachan, MAX_SEC_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clearing the DMA overrun counter at open time is a bit messy.
|
* Clearing the DMA overrun counter at open time is a bit messy.
|
||||||
* Since we're only managing one counter per controller, opening
|
* Since we're only managing one counter per controller, opening
|
||||||
@ -1988,11 +1695,17 @@ static int
|
|||||||
fdclose(struct cdev *dev, int flags, int mode, struct thread *td)
|
fdclose(struct cdev *dev, int flags, int mode, struct thread *td)
|
||||||
{
|
{
|
||||||
struct fd_data *fd;
|
struct fd_data *fd;
|
||||||
|
fdc_p fdc;
|
||||||
|
|
||||||
fd = dev->si_drv1;
|
fd = dev->si_drv1;
|
||||||
|
fdc = fd->fdc;
|
||||||
fd->flags &= ~(FD_OPEN | FD_NONBLOCK);
|
fd->flags &= ~(FD_OPEN | FD_NONBLOCK);
|
||||||
fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR);
|
fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR);
|
||||||
|
|
||||||
|
if ((fdc->flags & FDC_NODMA) == 0)
|
||||||
|
if (--fdc->dmacnt == 0)
|
||||||
|
isa_dma_release(fdc->dmachan);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2043,6 +1756,13 @@ fdstrategy(struct bio *bp)
|
|||||||
/*
|
/*
|
||||||
* Set up block calculations.
|
* Set up block calculations.
|
||||||
*/
|
*/
|
||||||
|
#ifndef PC98
|
||||||
|
if (bp->bio_offset >= ((off_t)128 << fd->ft->secsize) * fd->ft->size) {
|
||||||
|
bp->bio_error = EINVAL;
|
||||||
|
bp->bio_flags |= BIO_ERROR;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
blknum = bp->bio_offset / fdblk;
|
blknum = bp->bio_offset / fdblk;
|
||||||
nblocks = fd->ft->size;
|
nblocks = fd->ft->size;
|
||||||
if (blknum + bp->bio_bcount / fdblk > nblocks) {
|
if (blknum + bp->bio_bcount / fdblk > nblocks) {
|
||||||
|
99
sys/pc98/pc98/fdc_cbus.c
Normal file
99
sys/pc98/pc98/fdc_cbus.c
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004 Yoshihiro TAKAHASHI
|
||||||
|
* 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,
|
||||||
|
* without modification, immediately at the beginning of the file.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/bio.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
|
||||||
|
#include <pc98/pc98/fdcvar.h>
|
||||||
|
#include <pc98/pc98/fdreg.h>
|
||||||
|
|
||||||
|
#include <isa/isavar.h>
|
||||||
|
#include <pc98/pc98/pc98.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
fdc_cbus_probe(device_t dev)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
struct fdc_data *fdc;
|
||||||
|
|
||||||
|
fdc = device_get_softc(dev);
|
||||||
|
bzero(fdc, sizeof *fdc);
|
||||||
|
fdc->fdc_dev = dev;
|
||||||
|
|
||||||
|
/* Check pnp ids */
|
||||||
|
if (isa_get_vendorid(dev))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
/* Attempt to allocate our resources for the duration of the probe */
|
||||||
|
error = fdc_alloc_resources(fdc);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* see if it can handle a command */
|
||||||
|
if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240),
|
||||||
|
NE7_SPEC_2(2, 0), 0)) {
|
||||||
|
error = ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
fdc_release_resources(fdc);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static device_method_t fdc_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, fdc_cbus_probe),
|
||||||
|
DEVMETHOD(device_attach, fdc_attach),
|
||||||
|
DEVMETHOD(device_detach, fdc_detach),
|
||||||
|
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||||
|
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||||
|
DEVMETHOD(device_resume, bus_generic_resume),
|
||||||
|
|
||||||
|
/* Bus interface */
|
||||||
|
DEVMETHOD(bus_print_child, fdc_print_child),
|
||||||
|
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
|
||||||
|
/* Our children never use any other bus interface methods. */
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t fdc_driver = {
|
||||||
|
"fdc",
|
||||||
|
fdc_methods,
|
||||||
|
sizeof(struct fdc_data)
|
||||||
|
};
|
||||||
|
|
||||||
|
DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0);
|
153
sys/pc98/pc98/fdcvar.h
Normal file
153
sys/pc98/pc98/fdcvar.h
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004 M. Warner Losh.
|
||||||
|
* 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,
|
||||||
|
* without modification, immediately at the beginning of the file.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* XXX should audit this file to see if additional copyrights needed */
|
||||||
|
|
||||||
|
enum fdc_type
|
||||||
|
{
|
||||||
|
FDC_NE765, FDC_ENHANCED, FDC_UNKNOWN = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fdc_states {
|
||||||
|
DEVIDLE,
|
||||||
|
FINDWORK,
|
||||||
|
DOSEEK,
|
||||||
|
SEEKCOMPLETE ,
|
||||||
|
IOCOMPLETE,
|
||||||
|
RECALCOMPLETE,
|
||||||
|
STARTRECAL,
|
||||||
|
RESETCTLR,
|
||||||
|
SEEKWAIT,
|
||||||
|
RECALWAIT,
|
||||||
|
MOTORWAIT,
|
||||||
|
IOTIMEDOUT,
|
||||||
|
RESETCOMPLETE,
|
||||||
|
PIOREAD
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef FDC_DEBUG
|
||||||
|
static char const * const fdstates[] = {
|
||||||
|
"DEVIDLE",
|
||||||
|
"FINDWORK",
|
||||||
|
"DOSEEK",
|
||||||
|
"SEEKCOMPLETE",
|
||||||
|
"IOCOMPLETE",
|
||||||
|
"RECALCOMPLETE",
|
||||||
|
"STARTRECAL",
|
||||||
|
"RESETCTLR",
|
||||||
|
"SEEKWAIT",
|
||||||
|
"RECALWAIT",
|
||||||
|
"MOTORWAIT",
|
||||||
|
"IOTIMEDOUT",
|
||||||
|
"RESETCOMPLETE",
|
||||||
|
"PIOREAD"
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Per controller structure (softc).
|
||||||
|
*/
|
||||||
|
struct fdc_data
|
||||||
|
{
|
||||||
|
int fdcu; /* our unit number */
|
||||||
|
int dmacnt;
|
||||||
|
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 */
|
||||||
|
enum fdc_states state;
|
||||||
|
int retry;
|
||||||
|
#ifndef PC98
|
||||||
|
int fdout; /* mirror of the w/o digital output reg */
|
||||||
|
#endif
|
||||||
|
u_int status[7]; /* copy of the registers */
|
||||||
|
enum fdc_type fdct; /* chip version of FDC */
|
||||||
|
int fdc_errs; /* number of logged errors */
|
||||||
|
int dma_overruns; /* number of DMA overruns */
|
||||||
|
struct bio_queue_head head;
|
||||||
|
struct bio *bp; /* active buffer */
|
||||||
|
#ifdef PC98
|
||||||
|
struct resource *res_ioport, *res_fdsio, *res_fdemsio;
|
||||||
|
struct resource *res_irq, *res_drq;
|
||||||
|
int rid_ioport, rid_irq, rid_drq;
|
||||||
|
#else
|
||||||
|
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
|
||||||
|
int rid_ioport, rid_ctl, rid_irq, rid_drq;
|
||||||
|
#endif
|
||||||
|
int port_off;
|
||||||
|
bus_space_tag_t portt;
|
||||||
|
bus_space_handle_t porth;
|
||||||
|
#ifdef PC98
|
||||||
|
bus_space_tag_t sc_fdsiot;
|
||||||
|
bus_space_handle_t sc_fdsioh;
|
||||||
|
bus_space_tag_t sc_fdemsiot;
|
||||||
|
bus_space_handle_t sc_fdemsioh;
|
||||||
|
#else
|
||||||
|
bus_space_tag_t ctlt;
|
||||||
|
bus_space_handle_t ctlh;
|
||||||
|
#endif
|
||||||
|
void *fdc_intr;
|
||||||
|
struct device *fdc_dev;
|
||||||
|
#ifndef PC98
|
||||||
|
void (*fdctl_wr)(struct fdc_data *fdc, u_int8_t v);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int fdu_t;
|
||||||
|
typedef int fdcu_t;
|
||||||
|
typedef int fdsu_t;
|
||||||
|
typedef struct fd_data *fd_p;
|
||||||
|
typedef struct fdc_data *fdc_p;
|
||||||
|
typedef enum fdc_type fdc_t;
|
||||||
|
|
||||||
|
/* error returns for fd_cmd() */
|
||||||
|
#define FD_FAILED -1
|
||||||
|
#define FD_NOT_VALID -2
|
||||||
|
#define FDC_ERRMAX 100 /* do not log more */
|
||||||
|
|
||||||
|
extern devclass_t fdc_devclass;
|
||||||
|
|
||||||
|
int fdc_alloc_resources(struct fdc_data *);
|
||||||
|
#ifndef PC98
|
||||||
|
void fdout_wr(fdc_p, u_int8_t);
|
||||||
|
#endif
|
||||||
|
int fd_cmd(struct fdc_data *, int, ...);
|
||||||
|
void fdc_release_resources(struct fdc_data *);
|
||||||
|
int fdc_attach(device_t);
|
||||||
|
int fdc_detach(device_t dev);
|
||||||
|
int fdc_print_child(device_t, device_t);
|
||||||
|
int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
|
Loading…
Reference in New Issue
Block a user