Updated to use the new bus space interface code. Use a number of bus
space handles to describe the task file registers, aux register, 16 bit data register and 32 bit data register. The wdc softc structure has been moved to a separate file. Added support for multiple attachments by separating the core of the probe and attach functions from the mainbus probe and attach routines. Added a new wdc flags 32_BIT so that the wd can determine 32 bit xfer support from the wdc device.
This commit is contained in:
parent
a9295bf811
commit
aab5efa574
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: wd.c,v 1.12 1996/11/13 06:36:57 thorpej Exp $ */
|
/* $NetBSD: wd.c,v 1.13 1997/02/04 02:04:53 mark Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
|
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* from: wd.c,v 1.149 1996/04/29 19:50:47
|
* from: wd.c,v 1.156 1997/01/17 20:45:29 perry Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
@ -53,12 +53,12 @@
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
|
|
||||||
#include <machine/cpu.h>
|
#include <machine/cpu.h>
|
||||||
#include <machine/irqhandler.h>
|
|
||||||
#include <machine/io.h>
|
|
||||||
#include <machine/katelib.h>
|
|
||||||
|
|
||||||
#include <arm32/mainbus/wdreg.h>
|
#include <machine/irqhandler.h>
|
||||||
|
#include <machine/bus.h>
|
||||||
#include <arm32/mainbus/mainbus.h>
|
#include <arm32/mainbus/mainbus.h>
|
||||||
|
#include <arm32/mainbus/wdreg.h>
|
||||||
|
#include <arm32/mainbus/wdvar.h>
|
||||||
|
|
||||||
extern int wdresethack;
|
extern int wdresethack;
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ struct wd_softc {
|
||||||
#define GEOMETRY_WAIT 3 /* done uploading geometry */
|
#define GEOMETRY_WAIT 3 /* done uploading geometry */
|
||||||
#define MULTIMODE 4 /* set multiple mode */
|
#define MULTIMODE 4 /* set multiple mode */
|
||||||
#define MULTIMODE_WAIT 5 /* done setting multiple mode */
|
#define MULTIMODE_WAIT 5 /* done setting multiple mode */
|
||||||
#define OPEN 6 /* done with open */
|
#define READY 6 /* ready for use */
|
||||||
int sc_mode; /* transfer mode */
|
int sc_mode; /* transfer mode */
|
||||||
#define WDM_PIOSINGLE 0 /* single-sector PIO */
|
#define WDM_PIOSINGLE 0 /* single-sector PIO */
|
||||||
#define WDM_PIOMULTI 1 /* multi-sector PIO */
|
#define WDM_PIOMULTI 1 /* multi-sector PIO */
|
||||||
|
@ -123,24 +123,6 @@ struct wd_softc {
|
||||||
struct buf sc_q;
|
struct buf sc_q;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wdc_softc {
|
|
||||||
struct device sc_dev;
|
|
||||||
irqhandler_t sc_ih;
|
|
||||||
|
|
||||||
int sc_iobase; /* I/O port base */
|
|
||||||
int sc_drq; /* DMA channel */
|
|
||||||
|
|
||||||
TAILQ_HEAD(drivehead, wd_softc) sc_drives;
|
|
||||||
int sc_flags;
|
|
||||||
#define WDCF_ACTIVE 0x01 /* controller is active */
|
|
||||||
#define WDCF_SINGLE 0x02 /* sector at a time mode */
|
|
||||||
#define WDCF_ERROR 0x04 /* processing a disk error */
|
|
||||||
#define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */
|
|
||||||
int sc_errors; /* errors during current transfer */
|
|
||||||
u_char sc_status; /* copy of status register */
|
|
||||||
u_char sc_error; /* copy of error register */
|
|
||||||
};
|
|
||||||
|
|
||||||
int wdcprobe __P((struct device *, void *, void *));
|
int wdcprobe __P((struct device *, void *, void *));
|
||||||
void wdcattach __P((struct device *, struct device *, void *));
|
void wdcattach __P((struct device *, struct device *, void *));
|
||||||
int wdcintr __P((void *));
|
int wdcintr __P((void *));
|
||||||
|
@ -153,9 +135,9 @@ struct cfdriver wdc_cd = {
|
||||||
NULL, "wdc", DV_DULL
|
NULL, "wdc", DV_DULL
|
||||||
};
|
};
|
||||||
|
|
||||||
int wdprobe __P((struct device *, void *, void *));
|
int wdprobe __P((struct device *, void *, void *));
|
||||||
void wdattach __P((struct device *, struct device *, void *));
|
void wdattach __P((struct device *, struct device *, void *));
|
||||||
int wdprint __P((void *, const char *));
|
int wdprint __P((void *, const char *));
|
||||||
|
|
||||||
struct cfattach wd_ca = {
|
struct cfattach wd_ca = {
|
||||||
sizeof(struct wd_softc), wdprobe, wdattach
|
sizeof(struct wd_softc), wdprobe, wdattach
|
||||||
|
@ -199,45 +181,87 @@ void wdunlock __P((struct wd_softc *));
|
||||||
#define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
|
#define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
|
||||||
#define wait_for_unbusy(d) wdcwait(d, 0)
|
#define wait_for_unbusy(d) wdcwait(d, 0)
|
||||||
|
|
||||||
|
int
|
||||||
|
wdcprobe_internal(iot, ioh, aux_ioh, data_ioh, data32_ioh, name)
|
||||||
|
bus_space_tag_t iot;
|
||||||
|
bus_space_handle_t ioh;
|
||||||
|
bus_space_handle_t aux_ioh;
|
||||||
|
bus_space_handle_t data_ioh;
|
||||||
|
bus_space_handle_t data32_ioh;
|
||||||
|
char *name;
|
||||||
|
{
|
||||||
|
struct wdc_softc wdc;
|
||||||
|
|
||||||
|
/* fake a wdc structure for the benefit of the routines called */
|
||||||
|
|
||||||
|
wdc.sc_iot = iot;
|
||||||
|
wdc.sc_ioh = ioh;
|
||||||
|
wdc.sc_auxioh = aux_ioh;
|
||||||
|
wdc.sc_dataioh = data_ioh;
|
||||||
|
wdc.sc_data32ioh = data32_ioh;
|
||||||
|
wdc.sc_inten = NULL;
|
||||||
|
wdc.sc_flags = WDCF_QUIET; /* Supress warning during probe */
|
||||||
|
strcpy(wdc.sc_dev.dv_xname, name);
|
||||||
|
|
||||||
|
/* Check if we have registers that work. */
|
||||||
|
bus_space_write_1(iot, ioh, wd_error, 0x5a); /* Error register not writable, */
|
||||||
|
bus_space_write_1(iot, ioh, wd_cyl_lo, 0xa5); /* but all of cyllo are. */
|
||||||
|
if (bus_space_read_1(iot, ioh, wd_error) == 0x5a
|
||||||
|
|| bus_space_read_1(iot, ioh, wd_cyl_lo) != 0xa5)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
if (wdcreset(&wdc) != 0) {
|
||||||
|
delay(500000);
|
||||||
|
if (wdcreset(&wdc) != 0)
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select drive 0. */
|
||||||
|
bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0);
|
||||||
|
|
||||||
|
/* Wait for controller to become ready. */
|
||||||
|
if (wait_for_unbusy(&wdc) < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
/* Start drive diagnostics. */
|
||||||
|
bus_space_write_1(iot, ioh, wd_command, WDCC_DIAGNOSE);
|
||||||
|
|
||||||
|
/* Wait for command to complete. */
|
||||||
|
if (wait_for_unbusy(&wdc) < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
wdcprobe(parent, match, aux)
|
wdcprobe(parent, match, aux)
|
||||||
struct device *parent;
|
struct device *parent;
|
||||||
void *match, *aux;
|
void *match, *aux;
|
||||||
{
|
{
|
||||||
struct wdc_softc *wdc = match;
|
|
||||||
struct mainbus_attach_args *mb = aux;
|
struct mainbus_attach_args *mb = aux;
|
||||||
int iobase;
|
bus_space_tag_t iot;
|
||||||
|
bus_space_handle_t ioh;
|
||||||
|
bus_space_handle_t aux_ioh;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
wdc->sc_iobase = iobase = mb->mb_iobase;
|
/* XXX - need xname */
|
||||||
|
|
||||||
/* Check if we have registers that work. */
|
iot = mb->mb_iot;
|
||||||
outb(iobase+wd_error, 0x5a); /* Error register not writable, */
|
|
||||||
outb(iobase+wd_cyl_lo, 0xa5); /* but all of cyllo are. */
|
if (bus_space_map(iot, mb->mb_iobase, 8, 0, &ioh))
|
||||||
if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5)
|
return(0);
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (wdcreset(wdc) != 0) {
|
if (bus_space_map(iot, mb->mb_iobase + (WD_ALTSTATUS*4), 1, 0, &aux_ioh))
|
||||||
delay(500000);
|
goto out;
|
||||||
if (wdcreset(wdc) != 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select drive 0. */
|
rv = wdcprobe_internal(iot, ioh, aux_ioh, ioh, -1, ((struct device *)(match))->dv_xname);
|
||||||
outb(iobase+wd_sdh, WDSD_IBM | 0);
|
|
||||||
|
|
||||||
/* Wait for controller to become ready. */
|
mb->mb_iosize = 8*4;
|
||||||
if (wait_for_unbusy(wdc) < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Start drive diagnostics. */
|
|
||||||
outb(iobase+wd_command, WDCC_DIAGNOSE);
|
|
||||||
|
|
||||||
/* Wait for command to complete. */
|
out:
|
||||||
if (wait_for_unbusy(wdc) < 0)
|
bus_space_unmap(iot, ioh, 8);
|
||||||
return 0;
|
bus_space_unmap(iot, aux_ioh, 1);
|
||||||
|
return(rv);
|
||||||
mb->mb_iosize = 32;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wdc_attach_args {
|
struct wdc_attach_args {
|
||||||
|
@ -256,6 +280,33 @@ wdprint(aux, wdc)
|
||||||
return QUIET;
|
return QUIET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wdcattach_internal(wdc, iot, ioh, aux_ioh, data_ioh, data32_ioh, drq)
|
||||||
|
struct wdc_softc *wdc;
|
||||||
|
bus_space_tag_t iot;
|
||||||
|
bus_space_handle_t ioh;
|
||||||
|
bus_space_handle_t aux_ioh;
|
||||||
|
bus_space_handle_t data_ioh;
|
||||||
|
bus_space_handle_t data32_ioh;
|
||||||
|
int drq;
|
||||||
|
{
|
||||||
|
struct wdc_attach_args wa;
|
||||||
|
|
||||||
|
TAILQ_INIT(&wdc->sc_drives);
|
||||||
|
wdc->sc_drq = drq;
|
||||||
|
wdc->sc_iot = iot;
|
||||||
|
wdc->sc_ioh = ioh;
|
||||||
|
wdc->sc_auxioh = aux_ioh;
|
||||||
|
wdc->sc_dataioh = data_ioh;
|
||||||
|
wdc->sc_data32ioh = data32_ioh;
|
||||||
|
wdc->sc_inten = NULL;
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
|
||||||
|
(void)config_found((struct device *)wdc, (void *)&wa, wdprint);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wdcattach(parent, self, aux)
|
wdcattach(parent, self, aux)
|
||||||
struct device *parent, *self;
|
struct device *parent, *self;
|
||||||
|
@ -263,22 +314,24 @@ wdcattach(parent, self, aux)
|
||||||
{
|
{
|
||||||
struct wdc_softc *wdc = (void *)self;
|
struct wdc_softc *wdc = (void *)self;
|
||||||
struct mainbus_attach_args *mb = aux;
|
struct mainbus_attach_args *mb = aux;
|
||||||
struct wdc_attach_args wa;
|
bus_space_tag_t iot;
|
||||||
|
bus_space_handle_t ioh;
|
||||||
|
bus_space_handle_t aux_ioh;
|
||||||
|
|
||||||
TAILQ_INIT(&wdc->sc_drives);
|
TAILQ_INIT(&wdc->sc_drives);
|
||||||
wdc->sc_drq = mb->mb_drq;
|
iot = mb->mb_iot;
|
||||||
|
|
||||||
printf("\n");
|
if (bus_space_map(iot, mb->mb_iobase, 8, 0, &ioh))
|
||||||
|
panic("%s: Cannot map IO\n", wdc->sc_dev.dv_xname);
|
||||||
|
|
||||||
wdc->sc_ih.ih_func = wdcintr;
|
if (bus_space_map(iot, mb->mb_iobase + (WD_ALTSTATUS*4), 1, 0,
|
||||||
wdc->sc_ih.ih_arg = wdc;
|
&aux_ioh))
|
||||||
wdc->sc_ih.ih_level = IPL_BIO;
|
panic("%s: Cannot map IO\n", wdc->sc_dev.dv_xname);
|
||||||
wdc->sc_ih.ih_name = "wdc";
|
|
||||||
if (irq_claim(mb->mb_irq, &wdc->sc_ih))
|
|
||||||
panic("Cannot claim IRQ %d for wdc%d\n", mb->mb_irq, parent->dv_unit);
|
|
||||||
|
|
||||||
for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
|
wdc->sc_ih = intr_claim(mb->mb_irq, IPL_BIO, "wdc",
|
||||||
(void)config_found(self, (void *)&wa, wdprint);
|
wdcintr, wdc);
|
||||||
|
|
||||||
|
wdcattach_internal(wdc, iot, ioh, aux_ioh, ioh, -1, mb->mb_drq);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -317,6 +370,7 @@ wdattach(parent, self, aux)
|
||||||
/*
|
/*
|
||||||
* Initialize and attach the disk structure.
|
* Initialize and attach the disk structure.
|
||||||
*/
|
*/
|
||||||
|
wd->sc_flags = ((wdc->sc_flags & WDCF_32BIT) ? WDF_32BIT : 0);
|
||||||
wd->sc_dk.dk_driver = &wddkdriver;
|
wd->sc_dk.dk_driver = &wddkdriver;
|
||||||
wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
|
wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
|
||||||
disk_attach(&wd->sc_dk);
|
disk_attach(&wd->sc_dk);
|
||||||
|
@ -338,15 +392,15 @@ wdattach(parent, self, aux)
|
||||||
}
|
}
|
||||||
*q++ = '\0';
|
*q++ = '\0';
|
||||||
|
|
||||||
printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec <%s>\n",
|
printf(": <%s>\n%s: %dMB, %d cyl, %d head, %d sec, %d bytes/sec\n",
|
||||||
|
buf, wd->sc_dev.dv_xname,
|
||||||
wd->sc_params.wdp_cylinders *
|
wd->sc_params.wdp_cylinders *
|
||||||
(wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) /
|
(wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) /
|
||||||
(1048576 / DEV_BSIZE),
|
(1048576 / DEV_BSIZE),
|
||||||
wd->sc_params.wdp_cylinders,
|
wd->sc_params.wdp_cylinders,
|
||||||
wd->sc_params.wdp_heads,
|
wd->sc_params.wdp_heads,
|
||||||
wd->sc_params.wdp_sectors,
|
wd->sc_params.wdp_sectors,
|
||||||
DEV_BSIZE,
|
DEV_BSIZE);
|
||||||
buf);
|
|
||||||
|
|
||||||
if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
|
if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
|
||||||
wdc->sc_drq != DRQUNK) {
|
wdc->sc_drq != DRQUNK) {
|
||||||
|
@ -554,7 +608,7 @@ loop:
|
||||||
bp = wd->sc_q.b_actf;
|
bp = wd->sc_q.b_actf;
|
||||||
|
|
||||||
if (wdc->sc_errors >= WDIORETRIES) {
|
if (wdc->sc_errors >= WDIORETRIES) {
|
||||||
wderror(wd, bp, "hard error");
|
wderror(wd, bp, "wdcstart hard error");
|
||||||
bp->b_error = EIO;
|
bp->b_error = EIO;
|
||||||
bp->b_flags |= B_ERROR;
|
bp->b_flags |= B_ERROR;
|
||||||
wdfinish(wd, bp);
|
wdfinish(wd, bp);
|
||||||
|
@ -562,7 +616,7 @@ loop:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do control operations specially. */
|
/* Do control operations specially. */
|
||||||
if (wd->sc_state < OPEN) {
|
if (wd->sc_state < READY) {
|
||||||
/*
|
/*
|
||||||
* Actually, we want to be careful not to mess with the control
|
* Actually, we want to be careful not to mess with the control
|
||||||
* state if the device is currently busy, but we can assume
|
* state if the device is currently busy, but we can assume
|
||||||
|
@ -595,7 +649,7 @@ loop:
|
||||||
daddr_t blkno;
|
daddr_t blkno;
|
||||||
|
|
||||||
#ifdef WDDEBUG
|
#ifdef WDDEBUG
|
||||||
printf("\n%s: wdcstart %s %d@%d; map ", wd->sc_dev.dv_xname,
|
printf("\n%s: wdcstart %s %ld@%d; map ", wd->sc_dev.dv_xname,
|
||||||
(bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
|
(bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
|
||||||
bp->b_blkno);
|
bp->b_blkno);
|
||||||
#endif
|
#endif
|
||||||
|
@ -606,7 +660,8 @@ loop:
|
||||||
wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
|
wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
|
||||||
} else {
|
} else {
|
||||||
#ifdef WDDEBUG
|
#ifdef WDDEBUG
|
||||||
printf(" %d)%x", wd->sc_skip, inb(wd->sc_iobase+wd_altsts));
|
printf(" %d)%x", wd->sc_skip, bus_space_read_1(wdc->sc_iot,
|
||||||
|
wdc->sc_auxioh, wd_altsts));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,8 +777,9 @@ loop:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WDDEBUG
|
#ifdef WDDEBUG
|
||||||
printf("sector %d cylin %d head %d addr %x sts %x\n", sector,
|
printf("sector %ld cylin %ld head %ld addr %p sts %x\n",
|
||||||
cylin, head, bp->b_data, 0/*inb(wd->sc_iobase+wd_altsts*/));
|
sector, cylin, head, bp->b_data,
|
||||||
|
bus_space_read_1(wdc->sc_iot, wdc->sc_auxioh, wd_altsts));
|
||||||
#endif
|
#endif
|
||||||
} else if (wd->sc_nblks > 1) {
|
} else if (wd->sc_nblks > 1) {
|
||||||
/* The number of blocks in the last stretch may be smaller. */
|
/* The number of blocks in the last stretch may be smaller. */
|
||||||
|
@ -745,17 +801,17 @@ loop:
|
||||||
|
|
||||||
/* Push out data. */
|
/* Push out data. */
|
||||||
if ((wd->sc_flags & WDF_32BIT) == 0)
|
if ((wd->sc_flags & WDF_32BIT) == 0)
|
||||||
outsw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
|
bus_space_write_multi_2(wdc->sc_iot, wdc->sc_dataioh,
|
||||||
|
wd_data, (u_int16_t *)(bp->b_data + wd->sc_skip),
|
||||||
wd->sc_nbytes >> 1);
|
wd->sc_nbytes >> 1);
|
||||||
else
|
else
|
||||||
panic("wd cannot do 32 bit transfers\n");
|
bus_space_write_multi_4(wdc->sc_iot, wdc->sc_data32ioh,
|
||||||
#if 0
|
wd_data, (u_int32_t *)(bp->b_data + wd->sc_skip),
|
||||||
outsl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
|
|
||||||
wd->sc_nbytes >> 2);
|
wd->sc_nbytes >> 2);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wdc->sc_flags |= WDCF_ACTIVE;
|
wdc->sc_flags |= WDCF_ACTIVE;
|
||||||
|
if (wdc->sc_inten) wdc->sc_inten(wdc, 1);
|
||||||
timeout(wdctimeout, wdc, WAITTIME);
|
timeout(wdctimeout, wdc, WAITTIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,18 +831,19 @@ wdcintr(arg)
|
||||||
|
|
||||||
if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
|
if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
|
||||||
/* Clear the pending interrupt and abort. */
|
/* Clear the pending interrupt and abort. */
|
||||||
(void) inb(wdc->sc_iobase+wd_status);
|
(void) bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wdc->sc_flags &= ~WDCF_ACTIVE;
|
wdc->sc_flags &= ~WDCF_ACTIVE;
|
||||||
|
if (wdc->sc_inten) wdc->sc_inten(wdc, 0);
|
||||||
untimeout(wdctimeout, wdc);
|
untimeout(wdctimeout, wdc);
|
||||||
|
|
||||||
wd = wdc->sc_drives.tqh_first;
|
wd = wdc->sc_drives.tqh_first;
|
||||||
bp = wd->sc_q.b_actf;
|
bp = wd->sc_q.b_actf;
|
||||||
|
|
||||||
#ifdef WDDEBUG
|
#ifdef WDDEBUG
|
||||||
printf("I%d ", ctrlr);
|
printf("I%d ", wdc->sc_dev.dv_unit);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (wait_for_unbusy(wdc) < 0) {
|
if (wait_for_unbusy(wdc) < 0) {
|
||||||
|
@ -795,7 +852,7 @@ wdcintr(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is it not a transfer, but a control operation? */
|
/* Is it not a transfer, but a control operation? */
|
||||||
if (wd->sc_state < OPEN) {
|
if (wd->sc_state < READY) {
|
||||||
if (wdcontrol(wd) == 0) {
|
if (wdcontrol(wd) == 0) {
|
||||||
/* The drive is busy. Wait. */
|
/* The drive is busy. Wait. */
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -806,10 +863,11 @@ wdcintr(arg)
|
||||||
|
|
||||||
/* Turn off the DMA channel and unbounce the buffer. */
|
/* Turn off the DMA channel and unbounce the buffer. */
|
||||||
if (wd->sc_mode == WDM_DMA)
|
if (wd->sc_mode == WDM_DMA)
|
||||||
panic("wd cannot do DMA\n");
|
|
||||||
#if 0
|
#if 0
|
||||||
isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
|
isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
|
||||||
bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
|
bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
|
||||||
|
#else
|
||||||
|
panic("wd cannot do DMA yet\n");
|
||||||
#endif
|
#endif
|
||||||
/* Have we an error? */
|
/* Have we an error? */
|
||||||
if (wdc->sc_status & WDCS_ERR) {
|
if (wdc->sc_status & WDCS_ERR) {
|
||||||
|
@ -825,11 +883,18 @@ wdcintr(arg)
|
||||||
if (bp->b_flags & B_FORMAT)
|
if (bp->b_flags & B_FORMAT)
|
||||||
goto bad;
|
goto bad;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (++wdc->sc_errors < WDIORETRIES)
|
|
||||||
goto restart;
|
|
||||||
wderror(wd, bp, "hard error");
|
|
||||||
|
|
||||||
|
if (++wdc->sc_errors < WDIORETRIES) {
|
||||||
|
if (wdc->sc_errors == (WDIORETRIES + 1) / 2) {
|
||||||
|
#if 0
|
||||||
|
wderror(wd, NULL, "wedgie");
|
||||||
|
#endif
|
||||||
|
wdcunwedge(wdc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
wderror(wd, bp, "wdcintr hard error");
|
||||||
#ifdef B_FORMAT
|
#ifdef B_FORMAT
|
||||||
bad:
|
bad:
|
||||||
#endif
|
#endif
|
||||||
|
@ -850,14 +915,13 @@ wdcintr(arg)
|
||||||
|
|
||||||
/* Pull in data. */
|
/* Pull in data. */
|
||||||
if ((wd->sc_flags & WDF_32BIT) == 0)
|
if ((wd->sc_flags & WDF_32BIT) == 0)
|
||||||
insw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
|
bus_space_read_multi_2(wdc->sc_iot, wdc->sc_dataioh,
|
||||||
|
wd_data, (u_int16_t *)(bp->b_data + wd->sc_skip),
|
||||||
wd->sc_nbytes >> 1);
|
wd->sc_nbytes >> 1);
|
||||||
else
|
else
|
||||||
panic("wd cannot do 32 bit transfers\n");
|
bus_space_read_multi_4(wdc->sc_iot, wdc->sc_data32ioh,
|
||||||
#if 0
|
wd_data, (u_int32_t *)(bp->b_data + wd->sc_skip),
|
||||||
insl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
|
|
||||||
wd->sc_nbytes >> 2);
|
wd->sc_nbytes >> 2);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we encountered any abnormalities, flag it as a soft error. */
|
/* If we encountered any abnormalities, flag it as a soft error. */
|
||||||
|
@ -1146,8 +1210,8 @@ wdcontrol(wd)
|
||||||
case MULTIMODE:
|
case MULTIMODE:
|
||||||
multimode:
|
multimode:
|
||||||
if (wd->sc_mode != WDM_PIOMULTI)
|
if (wd->sc_mode != WDM_PIOMULTI)
|
||||||
goto open;
|
goto ready;
|
||||||
outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple);
|
bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt, wd->sc_multiple);
|
||||||
if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
|
if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
|
||||||
wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
|
wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -1161,10 +1225,10 @@ wdcontrol(wd)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case OPEN:
|
case READY:
|
||||||
open:
|
ready:
|
||||||
wdc->sc_errors = 0;
|
wdc->sc_errors = 0;
|
||||||
wd->sc_state = OPEN;
|
wd->sc_state = READY;
|
||||||
/*
|
/*
|
||||||
* The rest of the initialization can be done by normal means.
|
* The rest of the initialization can be done by normal means.
|
||||||
*/
|
*/
|
||||||
|
@ -1176,6 +1240,7 @@ wdcontrol(wd)
|
||||||
}
|
}
|
||||||
|
|
||||||
wdc->sc_flags |= WDCF_ACTIVE;
|
wdc->sc_flags |= WDCF_ACTIVE;
|
||||||
|
if (wdc->sc_inten) wdc->sc_inten(wdc, 1);
|
||||||
timeout(wdctimeout, wdc, WAITTIME);
|
timeout(wdctimeout, wdc, WAITTIME);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1192,11 +1257,12 @@ wdcommand(wd, command, cylin, head, sector, count)
|
||||||
int cylin, head, sector, count;
|
int cylin, head, sector, count;
|
||||||
{
|
{
|
||||||
struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
|
struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
|
||||||
int iobase = wdc->sc_iobase;
|
bus_space_tag_t iot = wdc->sc_iot;
|
||||||
|
bus_space_handle_t ioh = wdc->sc_ioh;
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
/* Select drive, head, and addressing mode. */
|
/* Select drive, head, and addressing mode. */
|
||||||
outb(iobase+wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head);
|
bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head);
|
||||||
|
|
||||||
/* Wait for it to become ready to accept a command. */
|
/* Wait for it to become ready to accept a command. */
|
||||||
if (command == WDCC_IDP)
|
if (command == WDCC_IDP)
|
||||||
|
@ -1208,16 +1274,16 @@ wdcommand(wd, command, cylin, head, sector, count)
|
||||||
|
|
||||||
/* Load parameters. */
|
/* Load parameters. */
|
||||||
if (wd->sc_dk.dk_label->d_type == DTYPE_ST506)
|
if (wd->sc_dk.dk_label->d_type == DTYPE_ST506)
|
||||||
outb(iobase+wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4);
|
bus_space_write_1(iot, ioh, wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4);
|
||||||
else
|
else
|
||||||
outb(iobase+wd_features, 0);
|
bus_space_write_1(iot, ioh, wd_features, 0);
|
||||||
outb(iobase+wd_cyl_lo, cylin);
|
bus_space_write_1(iot, ioh, wd_cyl_lo, cylin);
|
||||||
outb(iobase+wd_cyl_hi, cylin >> 8);
|
bus_space_write_1(iot, ioh, wd_cyl_hi, cylin >> 8);
|
||||||
outb(iobase+wd_sector, sector);
|
bus_space_write_1(iot, ioh, wd_sector, sector);
|
||||||
outb(iobase+wd_seccnt, count);
|
bus_space_write_1(iot, ioh, wd_seccnt, count);
|
||||||
|
|
||||||
/* Send command. */
|
/* Send command. */
|
||||||
outb(iobase+wd_command, command);
|
bus_space_write_1(iot, ioh, wd_command, command);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1231,15 +1297,13 @@ wdcommandshort(wdc, drive, command)
|
||||||
int drive;
|
int drive;
|
||||||
int command;
|
int command;
|
||||||
{
|
{
|
||||||
int iobase = wdc->sc_iobase;
|
|
||||||
|
|
||||||
/* Select drive. */
|
/* Select drive. */
|
||||||
outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
|
bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | (drive << 4));
|
||||||
|
|
||||||
if (wdcwait(wdc, WDCS_DRDY) < 0)
|
if (wdcwait(wdc, WDCS_DRDY) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
outb(iobase+wd_command, command);
|
bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_command, command);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1324,7 +1388,8 @@ wd_get_parms(wd)
|
||||||
wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
|
wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
|
||||||
|
|
||||||
/* Read in parameter block. */
|
/* Read in parameter block. */
|
||||||
insw(wdc->sc_iobase+wd_data, tb, sizeof(tb) / sizeof(short));
|
bus_space_read_multi_2(wdc->sc_iot, wdc->sc_dataioh, wd_data,
|
||||||
|
(u_int16_t *)tb, sizeof(tb) / sizeof(short));
|
||||||
bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
|
bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
|
||||||
|
|
||||||
/* Shuffle string byte order. */
|
/* Shuffle string byte order. */
|
||||||
|
@ -1336,7 +1401,7 @@ wd_get_parms(wd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear any leftover interrupt. */
|
/* Clear any leftover interrupt. */
|
||||||
(void) inb(wdc->sc_iobase+wd_status);
|
(void) bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
|
||||||
|
|
||||||
/* Restart the queue. */
|
/* Restart the queue. */
|
||||||
wdcstart(wdc);
|
wdcstart(wdc);
|
||||||
|
@ -1517,7 +1582,7 @@ wddump(dev, blkno, va, size)
|
||||||
part = WDPART(dev);
|
part = WDPART(dev);
|
||||||
|
|
||||||
/* Make sure it was initialized. */
|
/* Make sure it was initialized. */
|
||||||
if (wd->sc_state < OPEN)
|
if (wd->sc_state < READY)
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
|
|
||||||
wdc = (void *)wd->sc_dev.dv_parent;
|
wdc = (void *)wd->sc_dev.dv_parent;
|
||||||
|
@ -1591,7 +1656,8 @@ wddump(dev, blkno, va, size)
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
outsw(wdc->sc_iobase+wd_data, va, lp->d_secsize >> 1);
|
bus_space_write_multi_2(wdc->sc_iot, wdc->sc_dataioh, wd_data,
|
||||||
|
(u_int16_t *)va, lp->d_secsize >> 1);
|
||||||
|
|
||||||
/* Check data request (should be done). */
|
/* Check data request (should be done). */
|
||||||
if (wait_for_ready(wdc) != 0) {
|
if (wait_for_ready(wdc) != 0) {
|
||||||
|
@ -1655,23 +1721,27 @@ int
|
||||||
wdcreset(wdc)
|
wdcreset(wdc)
|
||||||
struct wdc_softc *wdc;
|
struct wdc_softc *wdc;
|
||||||
{
|
{
|
||||||
int iobase = wdc->sc_iobase;
|
bus_space_tag_t iot = wdc->sc_iot;
|
||||||
|
bus_space_handle_t ioh = wdc->sc_ioh;
|
||||||
|
bus_space_handle_t aux_ioh = wdc->sc_auxioh;
|
||||||
|
|
||||||
/* Reset the device. */
|
/* Reset the device. */
|
||||||
if (wdresethack) {
|
if (wdresethack) {
|
||||||
outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
|
bus_space_write_1(iot, aux_ioh, wd_ctlr, WDCTL_RST | WDCTL_IDS);
|
||||||
delay(1000);
|
delay(1000);
|
||||||
outb(iobase+wd_ctlr, WDCTL_IDS);
|
bus_space_write_1(iot, aux_ioh, wd_ctlr, WDCTL_IDS);
|
||||||
delay(1000);
|
delay(1000);
|
||||||
(void) inb(iobase+wd_error);
|
(void) bus_space_read_1(iot, ioh, wd_error);
|
||||||
outb(iobase+wd_ctlr, WDCTL_4BIT);
|
bus_space_write_1(iot, aux_ioh, wd_ctlr, WDCTL_4BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait_for_unbusy(wdc) < 0) {
|
if (wait_for_unbusy(wdc) < 0) {
|
||||||
printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
|
if (!(wdc->sc_flags & WDCF_QUIET))
|
||||||
|
printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*printf("wdcreset: %d\n", __LINE__);*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1724,7 +1794,6 @@ wdcwait(wdc, mask)
|
||||||
struct wdc_softc *wdc;
|
struct wdc_softc *wdc;
|
||||||
int mask;
|
int mask;
|
||||||
{
|
{
|
||||||
int iobase = wdc->sc_iobase;
|
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
u_char status;
|
u_char status;
|
||||||
#ifdef WDCNDELAY_DEBUG
|
#ifdef WDCNDELAY_DEBUG
|
||||||
|
@ -1732,7 +1801,8 @@ wdcwait(wdc, mask)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
wdc->sc_status = status = inb(iobase+wd_status);
|
wdc->sc_status = status = bus_space_read_1(wdc->sc_iot,
|
||||||
|
wdc->sc_ioh, wd_status);
|
||||||
if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
|
if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
|
||||||
break;
|
break;
|
||||||
if (++timeout > WDCNDELAY)
|
if (++timeout > WDCNDELAY)
|
||||||
|
@ -1740,7 +1810,8 @@ wdcwait(wdc, mask)
|
||||||
delay(WDCDELAY);
|
delay(WDCDELAY);
|
||||||
}
|
}
|
||||||
if (status & WDCS_ERR) {
|
if (status & WDCS_ERR) {
|
||||||
wdc->sc_error = inb(iobase+wd_error);
|
wdc->sc_error = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh,
|
||||||
|
wd_error);
|
||||||
return WDCS_ERR;
|
return WDCS_ERR;
|
||||||
}
|
}
|
||||||
#ifdef WDCNDELAY_DEBUG
|
#ifdef WDCNDELAY_DEBUG
|
||||||
|
@ -1765,6 +1836,7 @@ wdctimeout(arg)
|
||||||
struct buf *bp = wd->sc_q.b_actf;
|
struct buf *bp = wd->sc_q.b_actf;
|
||||||
|
|
||||||
wdc->sc_flags &= ~WDCF_ACTIVE;
|
wdc->sc_flags &= ~WDCF_ACTIVE;
|
||||||
|
if (wdc->sc_inten) wdc->sc_inten(wdc, 0);
|
||||||
wderror(wdc, NULL, "lost interrupt");
|
wderror(wdc, NULL, "lost interrupt");
|
||||||
printf("%s: lost interrupt: %sing %d@%s:%d\n",
|
printf("%s: lost interrupt: %sing %d@%s:%d\n",
|
||||||
wdc->sc_dev.dv_xname,
|
wdc->sc_dev.dv_xname,
|
||||||
|
@ -1784,17 +1856,12 @@ wderror(dev, bp, msg)
|
||||||
{
|
{
|
||||||
struct wd_softc *wd = dev;
|
struct wd_softc *wd = dev;
|
||||||
struct wdc_softc *wdc = dev;
|
struct wdc_softc *wdc = dev;
|
||||||
char bits[64];
|
|
||||||
|
|
||||||
if (bp) {
|
if (bp) {
|
||||||
diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE,
|
diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE,
|
||||||
wd->sc_dk.dk_label);
|
wd->sc_dk.dk_label);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
} else {
|
} else
|
||||||
printf("%s: %s: status %s ", wdc->sc_dev.dv_xname,
|
printf("%s: %s: status %b error %b\n", wdc->sc_dev.dv_xname,
|
||||||
msg, bitmask_snprintf(wdc->sc_status, WDCS_BITS,
|
msg, wdc->sc_status, WDCS_BITS, wdc->sc_error, WDERR_BITS);
|
||||||
bits, sizeof(bits)));
|
|
||||||
printf("error %s\n", bitmask_snprintf(wdc->sc_error,
|
|
||||||
WDERR_BITS, bits, sizeof(bits)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* $NetBSD: wdcvar.h,v 1.1 1997/02/04 02:04:51 mark Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1991 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* William Jolitz.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @(#)wdreg.h 7.1 (Berkeley) 5/9/91
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct wdc_softc {
|
||||||
|
struct device sc_dev;
|
||||||
|
void *sc_ih;
|
||||||
|
|
||||||
|
bus_space_tag_t sc_iot; /* Bus space tag */
|
||||||
|
bus_space_handle_t sc_ioh; /* handle for drive registers */
|
||||||
|
bus_space_handle_t sc_auxioh; /* handle for aux register */
|
||||||
|
bus_space_handle_t sc_dataioh; /* handle for 16 bit data */
|
||||||
|
bus_space_handle_t sc_data32ioh;/* handle for 32 bit data */
|
||||||
|
|
||||||
|
void (*sc_inten)(struct wdc_softc *, int);
|
||||||
|
|
||||||
|
int sc_drq; /* DMA channel */
|
||||||
|
|
||||||
|
TAILQ_HEAD(drivehead, wd_softc) sc_drives;
|
||||||
|
int sc_flags;
|
||||||
|
#define WDCF_ACTIVE 0x01 /* controller is active */
|
||||||
|
#define WDCF_SINGLE 0x02 /* sector at a time mode */
|
||||||
|
#define WDCF_ERROR 0x04 /* processing a disk error */
|
||||||
|
#define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */
|
||||||
|
#define WDCF_QUIET 0x10 /* Be quiet about errors */
|
||||||
|
#define WDCF_32BIT 0x20 /* Use 32bit xfers */
|
||||||
|
int sc_errors; /* errors during current transfer */
|
||||||
|
u_char sc_status; /* copy of status register */
|
||||||
|
u_char sc_error; /* copy of error register */
|
||||||
|
};
|
||||||
|
|
||||||
|
int wdcprobe_internal __P((bus_space_tag_t iot, bus_space_handle_t ioh,
|
||||||
|
bus_space_handle_t aux_ioh, bus_space_handle_t data_ioh,
|
||||||
|
bus_space_handle_t data32_ioh, char *name));
|
||||||
|
void wdcattach_internal __P((struct wdc_softc *wdc, bus_space_tag_t iot, bus_space_handle_t ioh,
|
||||||
|
bus_space_handle_t aux_ioh, bus_space_handle_t data_ioh,
|
||||||
|
bus_space_handle_t data32_ioh, int drq));
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: wdreg.h,v 1.1 1996/01/31 23:25:18 mark Exp $ */
|
/* $NetBSD: wdreg.h,v 1.2 1997/02/04 02:04:55 mark Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991 The Regents of the University of California.
|
||||||
|
@ -36,29 +36,31 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)wdreg.h 7.1 (Berkeley) 5/9/91
|
* @(#)wdreg.h 7.1 (Berkeley) 5/9/91
|
||||||
|
* from: wdreg.h,v 1.13 1995/03/29 21:56:46 briggs Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disk Controller register definitions.
|
* Disk Controller register definitions.
|
||||||
*/
|
*/
|
||||||
#define wd_data 0x000 /* data register (R/W - 16 bits) */
|
#define wd_data 0x000 /* data register (R/W - 16 bits) */
|
||||||
#define wd_error 0x004 /* error register (R) */
|
#define wd_error 0x001 /* error register (R) */
|
||||||
#define wd_precomp 0x004 /* write precompensation (W) */
|
#define wd_precomp 0x001 /* write precompensation (W) */
|
||||||
#define wd_features 0x004 /* features (W) */
|
#define wd_features 0x001 /* features (W) */
|
||||||
#define wd_seccnt 0x008 /* sector count (R/W) */
|
#define wd_seccnt 0x002 /* sector count (R/W) */
|
||||||
#define wd_sector 0x00c /* first sector number (R/W) */
|
#define wd_sector 0x003 /* first sector number (R/W) */
|
||||||
#define wd_cyl_lo 0x010 /* cylinder address, low byte (R/W) */
|
#define wd_cyl_lo 0x004 /* cylinder address, low byte (R/W) */
|
||||||
#define wd_cyl_hi 0x014 /* cylinder address, high byte (R/W) */
|
#define wd_cyl_hi 0x005 /* cylinder address, high byte (R/W) */
|
||||||
#define wd_sdh 0x018 /* sector size/drive/head (R/W) */
|
#define wd_sdh 0x006 /* sector size/drive/head (R/W) */
|
||||||
#define wd_command 0x01c /* command register (W) */
|
#define wd_command 0x007 /* command register (W) */
|
||||||
#define wd_status 0x01c /* immediate status (R) */
|
#define wd_status 0x007 /* immediate status (R) */
|
||||||
|
|
||||||
#define wd_altsts 0x818 /* alternate fixed disk status (via 1015) (R) */
|
#define WD_ALTSTATUS 0x206 /* base offset for alt status */
|
||||||
#define wd_ctlr 0x818 /* fixed disk controller control (via 1015) (W) */
|
#define wd_altsts 0x000 /* alternate fixed disk status (via 1015) (R) */
|
||||||
|
#define wd_ctlr 0x000 /* fixed disk controller control (via 1015) (W) */
|
||||||
#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */
|
#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */
|
||||||
#define WDCTL_RST 0x04 /* reset the controller */
|
#define WDCTL_RST 0x04 /* reset the controller */
|
||||||
#define WDCTL_IDS 0x02 /* disable controller interrupts */
|
#define WDCTL_IDS 0x02 /* disable controller interrupts */
|
||||||
#define wd_digin 0x81c /* disk controller input (via 1015) (R) */
|
#define wd_digin 0x001 /* disk controller input (via 1015) (R) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Status bits.
|
* Status bits.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: wd.c,v 1.12 1996/11/13 06:36:57 thorpej Exp $ */
|
/* $NetBSD: wd.c,v 1.13 1997/02/04 02:04:53 mark Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
|
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* from: wd.c,v 1.149 1996/04/29 19:50:47
|
* from: wd.c,v 1.156 1997/01/17 20:45:29 perry Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
@ -53,12 +53,12 @@
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
|
|
||||||
#include <machine/cpu.h>
|
#include <machine/cpu.h>
|
||||||
#include <machine/irqhandler.h>
|
|
||||||
#include <machine/io.h>
|
|
||||||
#include <machine/katelib.h>
|
|
||||||
|
|
||||||
#include <arm32/mainbus/wdreg.h>
|
#include <machine/irqhandler.h>
|
||||||
|
#include <machine/bus.h>
|
||||||
#include <arm32/mainbus/mainbus.h>
|
#include <arm32/mainbus/mainbus.h>
|
||||||
|
#include <arm32/mainbus/wdreg.h>
|
||||||
|
#include <arm32/mainbus/wdvar.h>
|
||||||
|
|
||||||
extern int wdresethack;
|
extern int wdresethack;
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ struct wd_softc {
|
||||||
#define GEOMETRY_WAIT 3 /* done uploading geometry */
|
#define GEOMETRY_WAIT 3 /* done uploading geometry */
|
||||||
#define MULTIMODE 4 /* set multiple mode */
|
#define MULTIMODE 4 /* set multiple mode */
|
||||||
#define MULTIMODE_WAIT 5 /* done setting multiple mode */
|
#define MULTIMODE_WAIT 5 /* done setting multiple mode */
|
||||||
#define OPEN 6 /* done with open */
|
#define READY 6 /* ready for use */
|
||||||
int sc_mode; /* transfer mode */
|
int sc_mode; /* transfer mode */
|
||||||
#define WDM_PIOSINGLE 0 /* single-sector PIO */
|
#define WDM_PIOSINGLE 0 /* single-sector PIO */
|
||||||
#define WDM_PIOMULTI 1 /* multi-sector PIO */
|
#define WDM_PIOMULTI 1 /* multi-sector PIO */
|
||||||
|
@ -123,24 +123,6 @@ struct wd_softc {
|
||||||
struct buf sc_q;
|
struct buf sc_q;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wdc_softc {
|
|
||||||
struct device sc_dev;
|
|
||||||
irqhandler_t sc_ih;
|
|
||||||
|
|
||||||
int sc_iobase; /* I/O port base */
|
|
||||||
int sc_drq; /* DMA channel */
|
|
||||||
|
|
||||||
TAILQ_HEAD(drivehead, wd_softc) sc_drives;
|
|
||||||
int sc_flags;
|
|
||||||
#define WDCF_ACTIVE 0x01 /* controller is active */
|
|
||||||
#define WDCF_SINGLE 0x02 /* sector at a time mode */
|
|
||||||
#define WDCF_ERROR 0x04 /* processing a disk error */
|
|
||||||
#define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */
|
|
||||||
int sc_errors; /* errors during current transfer */
|
|
||||||
u_char sc_status; /* copy of status register */
|
|
||||||
u_char sc_error; /* copy of error register */
|
|
||||||
};
|
|
||||||
|
|
||||||
int wdcprobe __P((struct device *, void *, void *));
|
int wdcprobe __P((struct device *, void *, void *));
|
||||||
void wdcattach __P((struct device *, struct device *, void *));
|
void wdcattach __P((struct device *, struct device *, void *));
|
||||||
int wdcintr __P((void *));
|
int wdcintr __P((void *));
|
||||||
|
@ -153,9 +135,9 @@ struct cfdriver wdc_cd = {
|
||||||
NULL, "wdc", DV_DULL
|
NULL, "wdc", DV_DULL
|
||||||
};
|
};
|
||||||
|
|
||||||
int wdprobe __P((struct device *, void *, void *));
|
int wdprobe __P((struct device *, void *, void *));
|
||||||
void wdattach __P((struct device *, struct device *, void *));
|
void wdattach __P((struct device *, struct device *, void *));
|
||||||
int wdprint __P((void *, const char *));
|
int wdprint __P((void *, const char *));
|
||||||
|
|
||||||
struct cfattach wd_ca = {
|
struct cfattach wd_ca = {
|
||||||
sizeof(struct wd_softc), wdprobe, wdattach
|
sizeof(struct wd_softc), wdprobe, wdattach
|
||||||
|
@ -199,45 +181,87 @@ void wdunlock __P((struct wd_softc *));
|
||||||
#define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
|
#define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
|
||||||
#define wait_for_unbusy(d) wdcwait(d, 0)
|
#define wait_for_unbusy(d) wdcwait(d, 0)
|
||||||
|
|
||||||
|
int
|
||||||
|
wdcprobe_internal(iot, ioh, aux_ioh, data_ioh, data32_ioh, name)
|
||||||
|
bus_space_tag_t iot;
|
||||||
|
bus_space_handle_t ioh;
|
||||||
|
bus_space_handle_t aux_ioh;
|
||||||
|
bus_space_handle_t data_ioh;
|
||||||
|
bus_space_handle_t data32_ioh;
|
||||||
|
char *name;
|
||||||
|
{
|
||||||
|
struct wdc_softc wdc;
|
||||||
|
|
||||||
|
/* fake a wdc structure for the benefit of the routines called */
|
||||||
|
|
||||||
|
wdc.sc_iot = iot;
|
||||||
|
wdc.sc_ioh = ioh;
|
||||||
|
wdc.sc_auxioh = aux_ioh;
|
||||||
|
wdc.sc_dataioh = data_ioh;
|
||||||
|
wdc.sc_data32ioh = data32_ioh;
|
||||||
|
wdc.sc_inten = NULL;
|
||||||
|
wdc.sc_flags = WDCF_QUIET; /* Supress warning during probe */
|
||||||
|
strcpy(wdc.sc_dev.dv_xname, name);
|
||||||
|
|
||||||
|
/* Check if we have registers that work. */
|
||||||
|
bus_space_write_1(iot, ioh, wd_error, 0x5a); /* Error register not writable, */
|
||||||
|
bus_space_write_1(iot, ioh, wd_cyl_lo, 0xa5); /* but all of cyllo are. */
|
||||||
|
if (bus_space_read_1(iot, ioh, wd_error) == 0x5a
|
||||||
|
|| bus_space_read_1(iot, ioh, wd_cyl_lo) != 0xa5)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
if (wdcreset(&wdc) != 0) {
|
||||||
|
delay(500000);
|
||||||
|
if (wdcreset(&wdc) != 0)
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select drive 0. */
|
||||||
|
bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0);
|
||||||
|
|
||||||
|
/* Wait for controller to become ready. */
|
||||||
|
if (wait_for_unbusy(&wdc) < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
/* Start drive diagnostics. */
|
||||||
|
bus_space_write_1(iot, ioh, wd_command, WDCC_DIAGNOSE);
|
||||||
|
|
||||||
|
/* Wait for command to complete. */
|
||||||
|
if (wait_for_unbusy(&wdc) < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
wdcprobe(parent, match, aux)
|
wdcprobe(parent, match, aux)
|
||||||
struct device *parent;
|
struct device *parent;
|
||||||
void *match, *aux;
|
void *match, *aux;
|
||||||
{
|
{
|
||||||
struct wdc_softc *wdc = match;
|
|
||||||
struct mainbus_attach_args *mb = aux;
|
struct mainbus_attach_args *mb = aux;
|
||||||
int iobase;
|
bus_space_tag_t iot;
|
||||||
|
bus_space_handle_t ioh;
|
||||||
|
bus_space_handle_t aux_ioh;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
wdc->sc_iobase = iobase = mb->mb_iobase;
|
/* XXX - need xname */
|
||||||
|
|
||||||
/* Check if we have registers that work. */
|
iot = mb->mb_iot;
|
||||||
outb(iobase+wd_error, 0x5a); /* Error register not writable, */
|
|
||||||
outb(iobase+wd_cyl_lo, 0xa5); /* but all of cyllo are. */
|
if (bus_space_map(iot, mb->mb_iobase, 8, 0, &ioh))
|
||||||
if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5)
|
return(0);
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (wdcreset(wdc) != 0) {
|
if (bus_space_map(iot, mb->mb_iobase + (WD_ALTSTATUS*4), 1, 0, &aux_ioh))
|
||||||
delay(500000);
|
goto out;
|
||||||
if (wdcreset(wdc) != 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select drive 0. */
|
rv = wdcprobe_internal(iot, ioh, aux_ioh, ioh, -1, ((struct device *)(match))->dv_xname);
|
||||||
outb(iobase+wd_sdh, WDSD_IBM | 0);
|
|
||||||
|
|
||||||
/* Wait for controller to become ready. */
|
mb->mb_iosize = 8*4;
|
||||||
if (wait_for_unbusy(wdc) < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Start drive diagnostics. */
|
|
||||||
outb(iobase+wd_command, WDCC_DIAGNOSE);
|
|
||||||
|
|
||||||
/* Wait for command to complete. */
|
out:
|
||||||
if (wait_for_unbusy(wdc) < 0)
|
bus_space_unmap(iot, ioh, 8);
|
||||||
return 0;
|
bus_space_unmap(iot, aux_ioh, 1);
|
||||||
|
return(rv);
|
||||||
mb->mb_iosize = 32;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wdc_attach_args {
|
struct wdc_attach_args {
|
||||||
|
@ -256,6 +280,33 @@ wdprint(aux, wdc)
|
||||||
return QUIET;
|
return QUIET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wdcattach_internal(wdc, iot, ioh, aux_ioh, data_ioh, data32_ioh, drq)
|
||||||
|
struct wdc_softc *wdc;
|
||||||
|
bus_space_tag_t iot;
|
||||||
|
bus_space_handle_t ioh;
|
||||||
|
bus_space_handle_t aux_ioh;
|
||||||
|
bus_space_handle_t data_ioh;
|
||||||
|
bus_space_handle_t data32_ioh;
|
||||||
|
int drq;
|
||||||
|
{
|
||||||
|
struct wdc_attach_args wa;
|
||||||
|
|
||||||
|
TAILQ_INIT(&wdc->sc_drives);
|
||||||
|
wdc->sc_drq = drq;
|
||||||
|
wdc->sc_iot = iot;
|
||||||
|
wdc->sc_ioh = ioh;
|
||||||
|
wdc->sc_auxioh = aux_ioh;
|
||||||
|
wdc->sc_dataioh = data_ioh;
|
||||||
|
wdc->sc_data32ioh = data32_ioh;
|
||||||
|
wdc->sc_inten = NULL;
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
|
||||||
|
(void)config_found((struct device *)wdc, (void *)&wa, wdprint);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wdcattach(parent, self, aux)
|
wdcattach(parent, self, aux)
|
||||||
struct device *parent, *self;
|
struct device *parent, *self;
|
||||||
|
@ -263,22 +314,24 @@ wdcattach(parent, self, aux)
|
||||||
{
|
{
|
||||||
struct wdc_softc *wdc = (void *)self;
|
struct wdc_softc *wdc = (void *)self;
|
||||||
struct mainbus_attach_args *mb = aux;
|
struct mainbus_attach_args *mb = aux;
|
||||||
struct wdc_attach_args wa;
|
bus_space_tag_t iot;
|
||||||
|
bus_space_handle_t ioh;
|
||||||
|
bus_space_handle_t aux_ioh;
|
||||||
|
|
||||||
TAILQ_INIT(&wdc->sc_drives);
|
TAILQ_INIT(&wdc->sc_drives);
|
||||||
wdc->sc_drq = mb->mb_drq;
|
iot = mb->mb_iot;
|
||||||
|
|
||||||
printf("\n");
|
if (bus_space_map(iot, mb->mb_iobase, 8, 0, &ioh))
|
||||||
|
panic("%s: Cannot map IO\n", wdc->sc_dev.dv_xname);
|
||||||
|
|
||||||
wdc->sc_ih.ih_func = wdcintr;
|
if (bus_space_map(iot, mb->mb_iobase + (WD_ALTSTATUS*4), 1, 0,
|
||||||
wdc->sc_ih.ih_arg = wdc;
|
&aux_ioh))
|
||||||
wdc->sc_ih.ih_level = IPL_BIO;
|
panic("%s: Cannot map IO\n", wdc->sc_dev.dv_xname);
|
||||||
wdc->sc_ih.ih_name = "wdc";
|
|
||||||
if (irq_claim(mb->mb_irq, &wdc->sc_ih))
|
|
||||||
panic("Cannot claim IRQ %d for wdc%d\n", mb->mb_irq, parent->dv_unit);
|
|
||||||
|
|
||||||
for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
|
wdc->sc_ih = intr_claim(mb->mb_irq, IPL_BIO, "wdc",
|
||||||
(void)config_found(self, (void *)&wa, wdprint);
|
wdcintr, wdc);
|
||||||
|
|
||||||
|
wdcattach_internal(wdc, iot, ioh, aux_ioh, ioh, -1, mb->mb_drq);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -317,6 +370,7 @@ wdattach(parent, self, aux)
|
||||||
/*
|
/*
|
||||||
* Initialize and attach the disk structure.
|
* Initialize and attach the disk structure.
|
||||||
*/
|
*/
|
||||||
|
wd->sc_flags = ((wdc->sc_flags & WDCF_32BIT) ? WDF_32BIT : 0);
|
||||||
wd->sc_dk.dk_driver = &wddkdriver;
|
wd->sc_dk.dk_driver = &wddkdriver;
|
||||||
wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
|
wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
|
||||||
disk_attach(&wd->sc_dk);
|
disk_attach(&wd->sc_dk);
|
||||||
|
@ -338,15 +392,15 @@ wdattach(parent, self, aux)
|
||||||
}
|
}
|
||||||
*q++ = '\0';
|
*q++ = '\0';
|
||||||
|
|
||||||
printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec <%s>\n",
|
printf(": <%s>\n%s: %dMB, %d cyl, %d head, %d sec, %d bytes/sec\n",
|
||||||
|
buf, wd->sc_dev.dv_xname,
|
||||||
wd->sc_params.wdp_cylinders *
|
wd->sc_params.wdp_cylinders *
|
||||||
(wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) /
|
(wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) /
|
||||||
(1048576 / DEV_BSIZE),
|
(1048576 / DEV_BSIZE),
|
||||||
wd->sc_params.wdp_cylinders,
|
wd->sc_params.wdp_cylinders,
|
||||||
wd->sc_params.wdp_heads,
|
wd->sc_params.wdp_heads,
|
||||||
wd->sc_params.wdp_sectors,
|
wd->sc_params.wdp_sectors,
|
||||||
DEV_BSIZE,
|
DEV_BSIZE);
|
||||||
buf);
|
|
||||||
|
|
||||||
if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
|
if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
|
||||||
wdc->sc_drq != DRQUNK) {
|
wdc->sc_drq != DRQUNK) {
|
||||||
|
@ -554,7 +608,7 @@ loop:
|
||||||
bp = wd->sc_q.b_actf;
|
bp = wd->sc_q.b_actf;
|
||||||
|
|
||||||
if (wdc->sc_errors >= WDIORETRIES) {
|
if (wdc->sc_errors >= WDIORETRIES) {
|
||||||
wderror(wd, bp, "hard error");
|
wderror(wd, bp, "wdcstart hard error");
|
||||||
bp->b_error = EIO;
|
bp->b_error = EIO;
|
||||||
bp->b_flags |= B_ERROR;
|
bp->b_flags |= B_ERROR;
|
||||||
wdfinish(wd, bp);
|
wdfinish(wd, bp);
|
||||||
|
@ -562,7 +616,7 @@ loop:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do control operations specially. */
|
/* Do control operations specially. */
|
||||||
if (wd->sc_state < OPEN) {
|
if (wd->sc_state < READY) {
|
||||||
/*
|
/*
|
||||||
* Actually, we want to be careful not to mess with the control
|
* Actually, we want to be careful not to mess with the control
|
||||||
* state if the device is currently busy, but we can assume
|
* state if the device is currently busy, but we can assume
|
||||||
|
@ -595,7 +649,7 @@ loop:
|
||||||
daddr_t blkno;
|
daddr_t blkno;
|
||||||
|
|
||||||
#ifdef WDDEBUG
|
#ifdef WDDEBUG
|
||||||
printf("\n%s: wdcstart %s %d@%d; map ", wd->sc_dev.dv_xname,
|
printf("\n%s: wdcstart %s %ld@%d; map ", wd->sc_dev.dv_xname,
|
||||||
(bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
|
(bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
|
||||||
bp->b_blkno);
|
bp->b_blkno);
|
||||||
#endif
|
#endif
|
||||||
|
@ -606,7 +660,8 @@ loop:
|
||||||
wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
|
wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
|
||||||
} else {
|
} else {
|
||||||
#ifdef WDDEBUG
|
#ifdef WDDEBUG
|
||||||
printf(" %d)%x", wd->sc_skip, inb(wd->sc_iobase+wd_altsts));
|
printf(" %d)%x", wd->sc_skip, bus_space_read_1(wdc->sc_iot,
|
||||||
|
wdc->sc_auxioh, wd_altsts));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,8 +777,9 @@ loop:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WDDEBUG
|
#ifdef WDDEBUG
|
||||||
printf("sector %d cylin %d head %d addr %x sts %x\n", sector,
|
printf("sector %ld cylin %ld head %ld addr %p sts %x\n",
|
||||||
cylin, head, bp->b_data, 0/*inb(wd->sc_iobase+wd_altsts*/));
|
sector, cylin, head, bp->b_data,
|
||||||
|
bus_space_read_1(wdc->sc_iot, wdc->sc_auxioh, wd_altsts));
|
||||||
#endif
|
#endif
|
||||||
} else if (wd->sc_nblks > 1) {
|
} else if (wd->sc_nblks > 1) {
|
||||||
/* The number of blocks in the last stretch may be smaller. */
|
/* The number of blocks in the last stretch may be smaller. */
|
||||||
|
@ -745,17 +801,17 @@ loop:
|
||||||
|
|
||||||
/* Push out data. */
|
/* Push out data. */
|
||||||
if ((wd->sc_flags & WDF_32BIT) == 0)
|
if ((wd->sc_flags & WDF_32BIT) == 0)
|
||||||
outsw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
|
bus_space_write_multi_2(wdc->sc_iot, wdc->sc_dataioh,
|
||||||
|
wd_data, (u_int16_t *)(bp->b_data + wd->sc_skip),
|
||||||
wd->sc_nbytes >> 1);
|
wd->sc_nbytes >> 1);
|
||||||
else
|
else
|
||||||
panic("wd cannot do 32 bit transfers\n");
|
bus_space_write_multi_4(wdc->sc_iot, wdc->sc_data32ioh,
|
||||||
#if 0
|
wd_data, (u_int32_t *)(bp->b_data + wd->sc_skip),
|
||||||
outsl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
|
|
||||||
wd->sc_nbytes >> 2);
|
wd->sc_nbytes >> 2);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wdc->sc_flags |= WDCF_ACTIVE;
|
wdc->sc_flags |= WDCF_ACTIVE;
|
||||||
|
if (wdc->sc_inten) wdc->sc_inten(wdc, 1);
|
||||||
timeout(wdctimeout, wdc, WAITTIME);
|
timeout(wdctimeout, wdc, WAITTIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,18 +831,19 @@ wdcintr(arg)
|
||||||
|
|
||||||
if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
|
if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
|
||||||
/* Clear the pending interrupt and abort. */
|
/* Clear the pending interrupt and abort. */
|
||||||
(void) inb(wdc->sc_iobase+wd_status);
|
(void) bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wdc->sc_flags &= ~WDCF_ACTIVE;
|
wdc->sc_flags &= ~WDCF_ACTIVE;
|
||||||
|
if (wdc->sc_inten) wdc->sc_inten(wdc, 0);
|
||||||
untimeout(wdctimeout, wdc);
|
untimeout(wdctimeout, wdc);
|
||||||
|
|
||||||
wd = wdc->sc_drives.tqh_first;
|
wd = wdc->sc_drives.tqh_first;
|
||||||
bp = wd->sc_q.b_actf;
|
bp = wd->sc_q.b_actf;
|
||||||
|
|
||||||
#ifdef WDDEBUG
|
#ifdef WDDEBUG
|
||||||
printf("I%d ", ctrlr);
|
printf("I%d ", wdc->sc_dev.dv_unit);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (wait_for_unbusy(wdc) < 0) {
|
if (wait_for_unbusy(wdc) < 0) {
|
||||||
|
@ -795,7 +852,7 @@ wdcintr(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is it not a transfer, but a control operation? */
|
/* Is it not a transfer, but a control operation? */
|
||||||
if (wd->sc_state < OPEN) {
|
if (wd->sc_state < READY) {
|
||||||
if (wdcontrol(wd) == 0) {
|
if (wdcontrol(wd) == 0) {
|
||||||
/* The drive is busy. Wait. */
|
/* The drive is busy. Wait. */
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -806,10 +863,11 @@ wdcintr(arg)
|
||||||
|
|
||||||
/* Turn off the DMA channel and unbounce the buffer. */
|
/* Turn off the DMA channel and unbounce the buffer. */
|
||||||
if (wd->sc_mode == WDM_DMA)
|
if (wd->sc_mode == WDM_DMA)
|
||||||
panic("wd cannot do DMA\n");
|
|
||||||
#if 0
|
#if 0
|
||||||
isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
|
isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
|
||||||
bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
|
bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
|
||||||
|
#else
|
||||||
|
panic("wd cannot do DMA yet\n");
|
||||||
#endif
|
#endif
|
||||||
/* Have we an error? */
|
/* Have we an error? */
|
||||||
if (wdc->sc_status & WDCS_ERR) {
|
if (wdc->sc_status & WDCS_ERR) {
|
||||||
|
@ -825,11 +883,18 @@ wdcintr(arg)
|
||||||
if (bp->b_flags & B_FORMAT)
|
if (bp->b_flags & B_FORMAT)
|
||||||
goto bad;
|
goto bad;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (++wdc->sc_errors < WDIORETRIES)
|
|
||||||
goto restart;
|
|
||||||
wderror(wd, bp, "hard error");
|
|
||||||
|
|
||||||
|
if (++wdc->sc_errors < WDIORETRIES) {
|
||||||
|
if (wdc->sc_errors == (WDIORETRIES + 1) / 2) {
|
||||||
|
#if 0
|
||||||
|
wderror(wd, NULL, "wedgie");
|
||||||
|
#endif
|
||||||
|
wdcunwedge(wdc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
wderror(wd, bp, "wdcintr hard error");
|
||||||
#ifdef B_FORMAT
|
#ifdef B_FORMAT
|
||||||
bad:
|
bad:
|
||||||
#endif
|
#endif
|
||||||
|
@ -850,14 +915,13 @@ wdcintr(arg)
|
||||||
|
|
||||||
/* Pull in data. */
|
/* Pull in data. */
|
||||||
if ((wd->sc_flags & WDF_32BIT) == 0)
|
if ((wd->sc_flags & WDF_32BIT) == 0)
|
||||||
insw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
|
bus_space_read_multi_2(wdc->sc_iot, wdc->sc_dataioh,
|
||||||
|
wd_data, (u_int16_t *)(bp->b_data + wd->sc_skip),
|
||||||
wd->sc_nbytes >> 1);
|
wd->sc_nbytes >> 1);
|
||||||
else
|
else
|
||||||
panic("wd cannot do 32 bit transfers\n");
|
bus_space_read_multi_4(wdc->sc_iot, wdc->sc_data32ioh,
|
||||||
#if 0
|
wd_data, (u_int32_t *)(bp->b_data + wd->sc_skip),
|
||||||
insl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
|
|
||||||
wd->sc_nbytes >> 2);
|
wd->sc_nbytes >> 2);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we encountered any abnormalities, flag it as a soft error. */
|
/* If we encountered any abnormalities, flag it as a soft error. */
|
||||||
|
@ -1146,8 +1210,8 @@ wdcontrol(wd)
|
||||||
case MULTIMODE:
|
case MULTIMODE:
|
||||||
multimode:
|
multimode:
|
||||||
if (wd->sc_mode != WDM_PIOMULTI)
|
if (wd->sc_mode != WDM_PIOMULTI)
|
||||||
goto open;
|
goto ready;
|
||||||
outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple);
|
bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt, wd->sc_multiple);
|
||||||
if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
|
if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
|
||||||
wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
|
wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -1161,10 +1225,10 @@ wdcontrol(wd)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case OPEN:
|
case READY:
|
||||||
open:
|
ready:
|
||||||
wdc->sc_errors = 0;
|
wdc->sc_errors = 0;
|
||||||
wd->sc_state = OPEN;
|
wd->sc_state = READY;
|
||||||
/*
|
/*
|
||||||
* The rest of the initialization can be done by normal means.
|
* The rest of the initialization can be done by normal means.
|
||||||
*/
|
*/
|
||||||
|
@ -1176,6 +1240,7 @@ wdcontrol(wd)
|
||||||
}
|
}
|
||||||
|
|
||||||
wdc->sc_flags |= WDCF_ACTIVE;
|
wdc->sc_flags |= WDCF_ACTIVE;
|
||||||
|
if (wdc->sc_inten) wdc->sc_inten(wdc, 1);
|
||||||
timeout(wdctimeout, wdc, WAITTIME);
|
timeout(wdctimeout, wdc, WAITTIME);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1192,11 +1257,12 @@ wdcommand(wd, command, cylin, head, sector, count)
|
||||||
int cylin, head, sector, count;
|
int cylin, head, sector, count;
|
||||||
{
|
{
|
||||||
struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
|
struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
|
||||||
int iobase = wdc->sc_iobase;
|
bus_space_tag_t iot = wdc->sc_iot;
|
||||||
|
bus_space_handle_t ioh = wdc->sc_ioh;
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
/* Select drive, head, and addressing mode. */
|
/* Select drive, head, and addressing mode. */
|
||||||
outb(iobase+wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head);
|
bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head);
|
||||||
|
|
||||||
/* Wait for it to become ready to accept a command. */
|
/* Wait for it to become ready to accept a command. */
|
||||||
if (command == WDCC_IDP)
|
if (command == WDCC_IDP)
|
||||||
|
@ -1208,16 +1274,16 @@ wdcommand(wd, command, cylin, head, sector, count)
|
||||||
|
|
||||||
/* Load parameters. */
|
/* Load parameters. */
|
||||||
if (wd->sc_dk.dk_label->d_type == DTYPE_ST506)
|
if (wd->sc_dk.dk_label->d_type == DTYPE_ST506)
|
||||||
outb(iobase+wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4);
|
bus_space_write_1(iot, ioh, wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4);
|
||||||
else
|
else
|
||||||
outb(iobase+wd_features, 0);
|
bus_space_write_1(iot, ioh, wd_features, 0);
|
||||||
outb(iobase+wd_cyl_lo, cylin);
|
bus_space_write_1(iot, ioh, wd_cyl_lo, cylin);
|
||||||
outb(iobase+wd_cyl_hi, cylin >> 8);
|
bus_space_write_1(iot, ioh, wd_cyl_hi, cylin >> 8);
|
||||||
outb(iobase+wd_sector, sector);
|
bus_space_write_1(iot, ioh, wd_sector, sector);
|
||||||
outb(iobase+wd_seccnt, count);
|
bus_space_write_1(iot, ioh, wd_seccnt, count);
|
||||||
|
|
||||||
/* Send command. */
|
/* Send command. */
|
||||||
outb(iobase+wd_command, command);
|
bus_space_write_1(iot, ioh, wd_command, command);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1231,15 +1297,13 @@ wdcommandshort(wdc, drive, command)
|
||||||
int drive;
|
int drive;
|
||||||
int command;
|
int command;
|
||||||
{
|
{
|
||||||
int iobase = wdc->sc_iobase;
|
|
||||||
|
|
||||||
/* Select drive. */
|
/* Select drive. */
|
||||||
outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
|
bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | (drive << 4));
|
||||||
|
|
||||||
if (wdcwait(wdc, WDCS_DRDY) < 0)
|
if (wdcwait(wdc, WDCS_DRDY) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
outb(iobase+wd_command, command);
|
bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_command, command);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1324,7 +1388,8 @@ wd_get_parms(wd)
|
||||||
wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
|
wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
|
||||||
|
|
||||||
/* Read in parameter block. */
|
/* Read in parameter block. */
|
||||||
insw(wdc->sc_iobase+wd_data, tb, sizeof(tb) / sizeof(short));
|
bus_space_read_multi_2(wdc->sc_iot, wdc->sc_dataioh, wd_data,
|
||||||
|
(u_int16_t *)tb, sizeof(tb) / sizeof(short));
|
||||||
bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
|
bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
|
||||||
|
|
||||||
/* Shuffle string byte order. */
|
/* Shuffle string byte order. */
|
||||||
|
@ -1336,7 +1401,7 @@ wd_get_parms(wd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear any leftover interrupt. */
|
/* Clear any leftover interrupt. */
|
||||||
(void) inb(wdc->sc_iobase+wd_status);
|
(void) bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
|
||||||
|
|
||||||
/* Restart the queue. */
|
/* Restart the queue. */
|
||||||
wdcstart(wdc);
|
wdcstart(wdc);
|
||||||
|
@ -1517,7 +1582,7 @@ wddump(dev, blkno, va, size)
|
||||||
part = WDPART(dev);
|
part = WDPART(dev);
|
||||||
|
|
||||||
/* Make sure it was initialized. */
|
/* Make sure it was initialized. */
|
||||||
if (wd->sc_state < OPEN)
|
if (wd->sc_state < READY)
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
|
|
||||||
wdc = (void *)wd->sc_dev.dv_parent;
|
wdc = (void *)wd->sc_dev.dv_parent;
|
||||||
|
@ -1591,7 +1656,8 @@ wddump(dev, blkno, va, size)
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
outsw(wdc->sc_iobase+wd_data, va, lp->d_secsize >> 1);
|
bus_space_write_multi_2(wdc->sc_iot, wdc->sc_dataioh, wd_data,
|
||||||
|
(u_int16_t *)va, lp->d_secsize >> 1);
|
||||||
|
|
||||||
/* Check data request (should be done). */
|
/* Check data request (should be done). */
|
||||||
if (wait_for_ready(wdc) != 0) {
|
if (wait_for_ready(wdc) != 0) {
|
||||||
|
@ -1655,23 +1721,27 @@ int
|
||||||
wdcreset(wdc)
|
wdcreset(wdc)
|
||||||
struct wdc_softc *wdc;
|
struct wdc_softc *wdc;
|
||||||
{
|
{
|
||||||
int iobase = wdc->sc_iobase;
|
bus_space_tag_t iot = wdc->sc_iot;
|
||||||
|
bus_space_handle_t ioh = wdc->sc_ioh;
|
||||||
|
bus_space_handle_t aux_ioh = wdc->sc_auxioh;
|
||||||
|
|
||||||
/* Reset the device. */
|
/* Reset the device. */
|
||||||
if (wdresethack) {
|
if (wdresethack) {
|
||||||
outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
|
bus_space_write_1(iot, aux_ioh, wd_ctlr, WDCTL_RST | WDCTL_IDS);
|
||||||
delay(1000);
|
delay(1000);
|
||||||
outb(iobase+wd_ctlr, WDCTL_IDS);
|
bus_space_write_1(iot, aux_ioh, wd_ctlr, WDCTL_IDS);
|
||||||
delay(1000);
|
delay(1000);
|
||||||
(void) inb(iobase+wd_error);
|
(void) bus_space_read_1(iot, ioh, wd_error);
|
||||||
outb(iobase+wd_ctlr, WDCTL_4BIT);
|
bus_space_write_1(iot, aux_ioh, wd_ctlr, WDCTL_4BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait_for_unbusy(wdc) < 0) {
|
if (wait_for_unbusy(wdc) < 0) {
|
||||||
printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
|
if (!(wdc->sc_flags & WDCF_QUIET))
|
||||||
|
printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*printf("wdcreset: %d\n", __LINE__);*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1724,7 +1794,6 @@ wdcwait(wdc, mask)
|
||||||
struct wdc_softc *wdc;
|
struct wdc_softc *wdc;
|
||||||
int mask;
|
int mask;
|
||||||
{
|
{
|
||||||
int iobase = wdc->sc_iobase;
|
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
u_char status;
|
u_char status;
|
||||||
#ifdef WDCNDELAY_DEBUG
|
#ifdef WDCNDELAY_DEBUG
|
||||||
|
@ -1732,7 +1801,8 @@ wdcwait(wdc, mask)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
wdc->sc_status = status = inb(iobase+wd_status);
|
wdc->sc_status = status = bus_space_read_1(wdc->sc_iot,
|
||||||
|
wdc->sc_ioh, wd_status);
|
||||||
if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
|
if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
|
||||||
break;
|
break;
|
||||||
if (++timeout > WDCNDELAY)
|
if (++timeout > WDCNDELAY)
|
||||||
|
@ -1740,7 +1810,8 @@ wdcwait(wdc, mask)
|
||||||
delay(WDCDELAY);
|
delay(WDCDELAY);
|
||||||
}
|
}
|
||||||
if (status & WDCS_ERR) {
|
if (status & WDCS_ERR) {
|
||||||
wdc->sc_error = inb(iobase+wd_error);
|
wdc->sc_error = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh,
|
||||||
|
wd_error);
|
||||||
return WDCS_ERR;
|
return WDCS_ERR;
|
||||||
}
|
}
|
||||||
#ifdef WDCNDELAY_DEBUG
|
#ifdef WDCNDELAY_DEBUG
|
||||||
|
@ -1765,6 +1836,7 @@ wdctimeout(arg)
|
||||||
struct buf *bp = wd->sc_q.b_actf;
|
struct buf *bp = wd->sc_q.b_actf;
|
||||||
|
|
||||||
wdc->sc_flags &= ~WDCF_ACTIVE;
|
wdc->sc_flags &= ~WDCF_ACTIVE;
|
||||||
|
if (wdc->sc_inten) wdc->sc_inten(wdc, 0);
|
||||||
wderror(wdc, NULL, "lost interrupt");
|
wderror(wdc, NULL, "lost interrupt");
|
||||||
printf("%s: lost interrupt: %sing %d@%s:%d\n",
|
printf("%s: lost interrupt: %sing %d@%s:%d\n",
|
||||||
wdc->sc_dev.dv_xname,
|
wdc->sc_dev.dv_xname,
|
||||||
|
@ -1784,17 +1856,12 @@ wderror(dev, bp, msg)
|
||||||
{
|
{
|
||||||
struct wd_softc *wd = dev;
|
struct wd_softc *wd = dev;
|
||||||
struct wdc_softc *wdc = dev;
|
struct wdc_softc *wdc = dev;
|
||||||
char bits[64];
|
|
||||||
|
|
||||||
if (bp) {
|
if (bp) {
|
||||||
diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE,
|
diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE,
|
||||||
wd->sc_dk.dk_label);
|
wd->sc_dk.dk_label);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
} else {
|
} else
|
||||||
printf("%s: %s: status %s ", wdc->sc_dev.dv_xname,
|
printf("%s: %s: status %b error %b\n", wdc->sc_dev.dv_xname,
|
||||||
msg, bitmask_snprintf(wdc->sc_status, WDCS_BITS,
|
msg, wdc->sc_status, WDCS_BITS, wdc->sc_error, WDERR_BITS);
|
||||||
bits, sizeof(bits)));
|
|
||||||
printf("error %s\n", bitmask_snprintf(wdc->sc_error,
|
|
||||||
WDERR_BITS, bits, sizeof(bits)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: wdreg.h,v 1.1 1996/01/31 23:25:18 mark Exp $ */
|
/* $NetBSD: wdreg.h,v 1.2 1997/02/04 02:04:55 mark Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991 The Regents of the University of California.
|
||||||
|
@ -36,29 +36,31 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)wdreg.h 7.1 (Berkeley) 5/9/91
|
* @(#)wdreg.h 7.1 (Berkeley) 5/9/91
|
||||||
|
* from: wdreg.h,v 1.13 1995/03/29 21:56:46 briggs Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disk Controller register definitions.
|
* Disk Controller register definitions.
|
||||||
*/
|
*/
|
||||||
#define wd_data 0x000 /* data register (R/W - 16 bits) */
|
#define wd_data 0x000 /* data register (R/W - 16 bits) */
|
||||||
#define wd_error 0x004 /* error register (R) */
|
#define wd_error 0x001 /* error register (R) */
|
||||||
#define wd_precomp 0x004 /* write precompensation (W) */
|
#define wd_precomp 0x001 /* write precompensation (W) */
|
||||||
#define wd_features 0x004 /* features (W) */
|
#define wd_features 0x001 /* features (W) */
|
||||||
#define wd_seccnt 0x008 /* sector count (R/W) */
|
#define wd_seccnt 0x002 /* sector count (R/W) */
|
||||||
#define wd_sector 0x00c /* first sector number (R/W) */
|
#define wd_sector 0x003 /* first sector number (R/W) */
|
||||||
#define wd_cyl_lo 0x010 /* cylinder address, low byte (R/W) */
|
#define wd_cyl_lo 0x004 /* cylinder address, low byte (R/W) */
|
||||||
#define wd_cyl_hi 0x014 /* cylinder address, high byte (R/W) */
|
#define wd_cyl_hi 0x005 /* cylinder address, high byte (R/W) */
|
||||||
#define wd_sdh 0x018 /* sector size/drive/head (R/W) */
|
#define wd_sdh 0x006 /* sector size/drive/head (R/W) */
|
||||||
#define wd_command 0x01c /* command register (W) */
|
#define wd_command 0x007 /* command register (W) */
|
||||||
#define wd_status 0x01c /* immediate status (R) */
|
#define wd_status 0x007 /* immediate status (R) */
|
||||||
|
|
||||||
#define wd_altsts 0x818 /* alternate fixed disk status (via 1015) (R) */
|
#define WD_ALTSTATUS 0x206 /* base offset for alt status */
|
||||||
#define wd_ctlr 0x818 /* fixed disk controller control (via 1015) (W) */
|
#define wd_altsts 0x000 /* alternate fixed disk status (via 1015) (R) */
|
||||||
|
#define wd_ctlr 0x000 /* fixed disk controller control (via 1015) (W) */
|
||||||
#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */
|
#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */
|
||||||
#define WDCTL_RST 0x04 /* reset the controller */
|
#define WDCTL_RST 0x04 /* reset the controller */
|
||||||
#define WDCTL_IDS 0x02 /* disable controller interrupts */
|
#define WDCTL_IDS 0x02 /* disable controller interrupts */
|
||||||
#define wd_digin 0x81c /* disk controller input (via 1015) (R) */
|
#define wd_digin 0x001 /* disk controller input (via 1015) (R) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Status bits.
|
* Status bits.
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* $NetBSD: wdvar.h,v 1.1 1997/02/04 02:04:51 mark Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1991 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* William Jolitz.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @(#)wdreg.h 7.1 (Berkeley) 5/9/91
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct wdc_softc {
|
||||||
|
struct device sc_dev;
|
||||||
|
void *sc_ih;
|
||||||
|
|
||||||
|
bus_space_tag_t sc_iot; /* Bus space tag */
|
||||||
|
bus_space_handle_t sc_ioh; /* handle for drive registers */
|
||||||
|
bus_space_handle_t sc_auxioh; /* handle for aux register */
|
||||||
|
bus_space_handle_t sc_dataioh; /* handle for 16 bit data */
|
||||||
|
bus_space_handle_t sc_data32ioh;/* handle for 32 bit data */
|
||||||
|
|
||||||
|
void (*sc_inten)(struct wdc_softc *, int);
|
||||||
|
|
||||||
|
int sc_drq; /* DMA channel */
|
||||||
|
|
||||||
|
TAILQ_HEAD(drivehead, wd_softc) sc_drives;
|
||||||
|
int sc_flags;
|
||||||
|
#define WDCF_ACTIVE 0x01 /* controller is active */
|
||||||
|
#define WDCF_SINGLE 0x02 /* sector at a time mode */
|
||||||
|
#define WDCF_ERROR 0x04 /* processing a disk error */
|
||||||
|
#define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */
|
||||||
|
#define WDCF_QUIET 0x10 /* Be quiet about errors */
|
||||||
|
#define WDCF_32BIT 0x20 /* Use 32bit xfers */
|
||||||
|
int sc_errors; /* errors during current transfer */
|
||||||
|
u_char sc_status; /* copy of status register */
|
||||||
|
u_char sc_error; /* copy of error register */
|
||||||
|
};
|
||||||
|
|
||||||
|
int wdcprobe_internal __P((bus_space_tag_t iot, bus_space_handle_t ioh,
|
||||||
|
bus_space_handle_t aux_ioh, bus_space_handle_t data_ioh,
|
||||||
|
bus_space_handle_t data32_ioh, char *name));
|
||||||
|
void wdcattach_internal __P((struct wdc_softc *wdc, bus_space_tag_t iot, bus_space_handle_t ioh,
|
||||||
|
bus_space_handle_t aux_ioh, bus_space_handle_t data_ioh,
|
||||||
|
bus_space_handle_t data32_ioh, int drq));
|
Loading…
Reference in New Issue