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:
mark 1997-02-04 02:04:51 +00:00
parent a9295bf811
commit aab5efa574
6 changed files with 580 additions and 296 deletions

View File

@ -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)));
}
} }

View File

@ -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));

View File

@ -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.

View File

@ -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)));
}
} }

View File

@ -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.

View File

@ -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));