Use <machine/bus.h> ... on the right track to making this an MI driver.

This commit is contained in:
thorpej 1996-05-12 01:37:02 +00:00
parent 7f0f603f3a
commit ea8aad3319
1 changed files with 93 additions and 59 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: fd.c,v 1.88 1996/05/03 19:14:53 christos Exp $ */
/* $NetBSD: fd.c,v 1.89 1996/05/12 01:37:02 thorpej Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995 Charles Hannum.
@ -54,7 +54,7 @@
#include <sys/queue.h>
#include <machine/cpu.h>
#include <machine/pio.h>
#include <machine/bus.h>
#include <machine/conf.h>
#include <dev/isa/isavar.h>
@ -94,7 +94,9 @@ struct fdc_softc {
struct isadev sc_id;
void *sc_ih;
int sc_iobase;
bus_chipset_tag_t sc_bc; /* ISA chipset identifier */
bus_io_handle_t sc_ioh; /* ISA io handle */
int sc_drq;
struct fd_softc *sc_fd[4]; /* pointers to children */
@ -203,7 +205,7 @@ void fd_set_motor __P((struct fdc_softc *fdc, int reset));
void fd_motor_off __P((void *arg));
void fd_motor_on __P((void *arg));
int fdcresult __P((struct fdc_softc *fdc));
int out_fdc __P((int iobase, u_char x));
int out_fdc __P((bus_chipset_tag_t bc, bus_io_handle_t ioh, u_char x));
void fdcstart __P((struct fdc_softc *fdc));
void fdcstatus __P((struct device *dv, int n, char *s));
void fdctimeout __P((void *arg));
@ -219,41 +221,58 @@ fdcprobe(parent, match, aux)
void *match, *aux;
{
register struct isa_attach_args *ia = aux;
int iobase = ia->ia_iobase;
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
int rv;
bc = ia->ia_bc;
rv = 0;
/* Map the i/o space. */
if (bus_io_map(bc, ia->ia_iobase, FDC_NPORT, &ioh))
return 0;
/* reset */
outb(iobase + fdout, 0);
bus_io_write_1(bc, ioh, fdout, 0);
delay(100);
outb(iobase + fdout, FDO_FRST);
bus_io_write_1(bc, ioh, fdout, FDO_FRST);
/* see if it can handle a command */
if (out_fdc(iobase, NE7CMD_SPECIFY) < 0)
return 0;
out_fdc(iobase, 0xdf);
out_fdc(iobase, 2);
if (out_fdc(bc, ioh, NE7CMD_SPECIFY) < 0)
goto out;
out_fdc(bc, ioh, 0xdf);
out_fdc(bc, ioh, 2);
#ifdef NEWCONFIG
if (iobase == IOBASEUNK || ia->ia_drq == DRQUNK)
if (ia->ia_iobase == IOBASEUNK || ia->ia_drq == DRQUNK)
return 0;
if (ia->ia_irq == IRQUNK) {
ia->ia_irq = isa_discoverintr(fdcforceintr, aux);
if (ia->ia_irq == IRQNONE)
return 0;
goto out;
/* reset it again */
outb(iobase + fdout, 0);
bus_io_write_1(bc, ioh, fdout, 0);
delay(100);
outb(iobase + fdout, FDO_FRST);
bus_io_write_1(bc, ioh, fdout, FDO_FRST);
}
#endif
rv = 1;
ia->ia_iosize = FDC_NPORT;
ia->ia_msize = 0;
return 1;
out:
bus_io_unmap(bc, ioh, FDC_NPORT);
return rv;
}
#ifdef NEWCONFIG
/*
* XXX This is broken, and needs fixing. In general, the interface needs
* XXX to change.
*/
void
fdcforceintr(aux)
void *aux;
@ -263,9 +282,9 @@ fdcforceintr(aux)
/* the motor is off; this should generate an error with or
without a disk drive present */
out_fdc(iobase, NE7CMD_SEEK);
out_fdc(iobase, 0);
out_fdc(iobase, 0);
out_fdc(bc, ioh, NE7CMD_SEEK);
out_fdc(bc, ioh, 0);
out_fdc(bc, ioh, 0);
}
#endif
@ -302,11 +321,21 @@ fdcattach(parent, self, aux)
void *aux;
{
struct fdc_softc *fdc = (void *)self;
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
struct isa_attach_args *ia = aux;
struct fdc_attach_args fa;
int type;
fdc->sc_iobase = ia->ia_iobase;
bc = ia->ia_bc;
/* Re-map the I/O space. */
if (bus_io_map(bc, ia->ia_iobase, FDC_NPORT, &ioh))
panic("fdcattach: couldn't map I/O ports");
fdc->sc_bc = bc;
fdc->sc_ioh = ioh;
fdc->sc_drq = ia->ia_drq;
fdc->sc_state = DEVIDLE;
TAILQ_INIT(&fdc->sc_drives);
@ -349,7 +378,8 @@ fdprobe(parent, match, aux)
struct cfdata *cf = match;
struct fdc_attach_args *fa = aux;
int drive = fa->fa_drive;
int iobase = fdc->sc_iobase;
bus_chipset_tag_t bc = fdc->sc_bc;
bus_io_handle_t ioh = fdc->sc_ioh;
int n;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
@ -363,14 +393,14 @@ fdprobe(parent, match, aux)
return 0;
/* select drive and turn on motor */
outb(iobase + fdout, drive | FDO_FRST | FDO_MOEN(drive));
bus_io_write_1(bc, ioh, fdout, drive | FDO_FRST | FDO_MOEN(drive));
/* wait for motor to spin up */
delay(250000);
out_fdc(iobase, NE7CMD_RECAL);
out_fdc(iobase, drive);
out_fdc(bc, ioh, NE7CMD_RECAL);
out_fdc(bc, ioh, drive);
/* wait for recalibrate */
delay(2000000);
out_fdc(iobase, NE7CMD_SENSEI);
out_fdc(bc, ioh, NE7CMD_SENSEI);
n = fdcresult(fdc);
#ifdef FD_DEBUG
{
@ -384,7 +414,7 @@ fdprobe(parent, match, aux)
if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20)
return 0;
/* turn off motor */
outb(iobase + fdout, FDO_FRST);
bus_io_write_1(bc, ioh, fdout, FDO_FRST);
return 1;
}
@ -633,7 +663,7 @@ fd_set_motor(fdc, reset)
for (n = 0; n < 4; n++)
if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
status |= FDO_MOEN(n);
outb(fdc->sc_iobase + fdout, status);
bus_io_write_1(fdc->sc_bc, fdc->sc_ioh, fdout, status);
}
void
@ -668,13 +698,15 @@ int
fdcresult(fdc)
struct fdc_softc *fdc;
{
int iobase = fdc->sc_iobase;
bus_chipset_tag_t bc = fdc->sc_bc;
bus_io_handle_t ioh = fdc->sc_ioh;
u_char i;
int j = 100000,
n = 0;
for (; j; j--) {
i = inb(iobase + fdsts) & (NE7_DIO | NE7_RQM | NE7_CB);
i = bus_io_read_1(bc, ioh, fdsts) &
(NE7_DIO | NE7_RQM | NE7_CB);
if (i == NE7_RQM)
return n;
if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
@ -682,7 +714,7 @@ fdcresult(fdc)
log(LOG_ERR, "fdcresult: overrun\n");
return -1;
}
fdc->sc_status[n++] = inb(iobase + fddata);
fdc->sc_status[n++] = bus_io_read_1(bc, ioh, fddata);
}
}
log(LOG_ERR, "fdcresult: timeout\n");
@ -690,19 +722,20 @@ fdcresult(fdc)
}
int
out_fdc(iobase, x)
int iobase;
out_fdc(bc, ioh, x)
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
u_char x;
{
int i = 100000;
while ((inb(iobase + fdsts) & NE7_DIO) && i-- > 0);
while ((bus_io_read_1(bc, ioh, fdsts) & NE7_DIO) && i-- > 0);
if (i <= 0)
return -1;
while ((inb(iobase + fdsts) & NE7_RQM) == 0 && i-- > 0);
while ((bus_io_read_1(bc, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
if (i <= 0)
return -1;
outb(iobase + fddata, x);
bus_io_write_1(bc, ioh, fddata, x);
return 0;
}
@ -776,7 +809,7 @@ fdcstatus(dv, n, s)
struct fdc_softc *fdc = (void *)dv->dv_parent;
if (n == 0) {
out_fdc(fdc->sc_iobase, NE7CMD_SENSEI);
out_fdc(fdc->sc_bc, fdc->sc_ioh, NE7CMD_SENSEI);
(void) fdcresult(fdc);
n = 2;
}
@ -848,7 +881,8 @@ fdcintr(arg)
#define cyl fdc->sc_status[1]
struct fd_softc *fd;
struct buf *bp;
int iobase = fdc->sc_iobase;
bus_chipset_tag_t bc = fdc->sc_bc;
bus_io_handle_t ioh = fdc->sc_ioh;
int read, head, sec, i, nblks;
struct fd_type *type;
@ -903,13 +937,13 @@ loop:
if (fd->sc_cylin == bp->b_cylin)
goto doio;
out_fdc(iobase, NE7CMD_SPECIFY);/* specify command */
out_fdc(iobase, fd->sc_type->steprate);
out_fdc(iobase, 6); /* XXX head load time == 6ms */
out_fdc(bc, ioh, NE7CMD_SPECIFY);/* specify command */
out_fdc(bc, ioh, fd->sc_type->steprate);
out_fdc(bc, ioh, 6); /* XXX head load time == 6ms */
out_fdc(iobase, NE7CMD_SEEK); /* seek function */
out_fdc(iobase, fd->sc_drive); /* drive number */
out_fdc(iobase, bp->b_cylin * fd->sc_type->step);
out_fdc(bc, ioh, NE7CMD_SEEK); /* seek function */
out_fdc(bc, ioh, fd->sc_drive); /* drive number */
out_fdc(bc, ioh, bp->b_cylin * fd->sc_type->step);
fd->sc_cylin = -1;
fdc->sc_state = SEEKWAIT;
@ -949,24 +983,24 @@ loop:
isa_dmastart(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
fdc->sc_drq);
#endif
outb(iobase + fdctl, type->rate);
bus_io_write_1(bc, ioh, fdctl, type->rate);
#ifdef FD_DEBUG
printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
read ? "read" : "write", fd->sc_drive, fd->sc_cylin, head,
sec, nblks);
#endif
if (read)
out_fdc(iobase, NE7CMD_READ); /* READ */
out_fdc(bc, ioh, NE7CMD_READ); /* READ */
else
out_fdc(iobase, NE7CMD_WRITE); /* WRITE */
out_fdc(iobase, (head << 2) | fd->sc_drive);
out_fdc(iobase, fd->sc_cylin); /* track */
out_fdc(iobase, head);
out_fdc(iobase, sec + 1); /* sector +1 */
out_fdc(iobase, type->secsize); /* sector size */
out_fdc(iobase, type->sectrac); /* sectors/track */
out_fdc(iobase, type->gap1); /* gap1 size */
out_fdc(iobase, type->datalen); /* data length */
out_fdc(bc, ioh, NE7CMD_WRITE); /* WRITE */
out_fdc(bc, ioh, (head << 2) | fd->sc_drive);
out_fdc(bc, ioh, fd->sc_cylin); /* track */
out_fdc(bc, ioh, head);
out_fdc(bc, ioh, sec + 1); /* sector +1 */
out_fdc(bc, ioh, type->secsize); /* sector size */
out_fdc(bc, ioh, type->sectrac); /* sectors/track */
out_fdc(bc, ioh, type->gap1); /* gap1 size */
out_fdc(bc, ioh, type->datalen); /* data length */
fdc->sc_state = IOCOMPLETE;
disk_busy(&fd->sc_dk);
@ -986,7 +1020,7 @@ loop:
disk_unbusy(&fd->sc_dk, 0); /* no data on seek */
/* Make sure seek really happened. */
out_fdc(iobase, NE7CMD_SENSEI);
out_fdc(bc, ioh, NE7CMD_SENSEI);
if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
cyl != bp->b_cylin * fd->sc_type->step) {
#ifdef FD_DEBUG
@ -1066,14 +1100,14 @@ loop:
untimeout(fdctimeout, fdc);
/* clear the controller output buffer */
for (i = 0; i < 4; i++) {
out_fdc(iobase, NE7CMD_SENSEI);
out_fdc(bc, ioh, NE7CMD_SENSEI);
(void) fdcresult(fdc);
}
/* fall through */
case DORECAL:
out_fdc(iobase, NE7CMD_RECAL); /* recalibrate function */
out_fdc(iobase, fd->sc_drive);
out_fdc(bc, ioh, NE7CMD_RECAL); /* recalibrate function */
out_fdc(bc, ioh, fd->sc_drive);
fdc->sc_state = RECALWAIT;
timeout(fdctimeout, fdc, 5 * hz);
return 1; /* will return later */
@ -1086,7 +1120,7 @@ loop:
return 1; /* will return later */
case RECALCOMPLETE:
out_fdc(iobase, NE7CMD_SENSEI);
out_fdc(bc, ioh, NE7CMD_SENSEI);
if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
#ifdef FD_DEBUG
fdcstatus(&fd->sc_dev, 2, "recalibrate failed");