Convert to use bus_space_* macros. The resulting code isn't quite correct,

but works on the alpha (since there's currently no floppy drive support).
This commit is contained in:
cgd 1997-04-21 13:38:38 +00:00
parent ba574b6f20
commit dbb6d5170a
1 changed files with 190 additions and 64 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: awd.c,v 1.1 1997/04/21 13:36:49 cgd Exp $ */
/* $NetBSD: awd.c,v 1.2 1997/04/21 13:38:38 cgd Exp $ */
/*
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
@ -50,12 +50,13 @@
#include <vm/vm.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <machine/pio.h>
#include <machine/bus.h>
#include <dev/isa/isavar.h>
#ifndef NO_ISADMA_SUPPORT
#include <dev/isa/isadmavar.h>
#endif
#include <dev/isa/wdreg.h>
#define WAITTIME (4 * hz) /* time to wait for a completion */
@ -123,7 +124,9 @@ struct wdc_softc {
struct device sc_dev;
void *sc_ih;
int sc_iobase; /* I/O port base */
bus_space_tag_t sc_iot; /* I/O space tag */
bus_space_handle_t sc_ioh; /* I/O space handle */
int sc_drq; /* DMA channel */
TAILQ_HEAD(drivehead, wd_softc) sc_drives;
@ -137,7 +140,11 @@ struct wdc_softc {
u_char sc_error; /* copy of error register */
};
#ifdef __BROKEN_INDIRECT_CONFIG
int wdcprobe __P((struct device *, void *, void *));
#else
int wdcprobe __P((struct device *, struct cfdata *, void *));
#endif
void wdcattach __P((struct device *, struct device *, void *));
int wdcintr __P((void *));
@ -149,7 +156,11 @@ struct cfdriver wdc_cd = {
NULL, "wdc", DV_DULL
};
#ifdef __BROKEN_INDIRECT_CONFIG
int wdprobe __P((struct device *, void *, void *));
#else
int wdprobe __P((struct device *, struct cfdata *, void *));
#endif
void wdattach __P((struct device *, struct device *, void *));
int wdprint __P((void *, const char *));
@ -181,10 +192,12 @@ int wdcontrol __P((struct wd_softc *));
int wdsetctlr __P((struct wd_softc *));
static void bad144intern __P((struct wd_softc *));
int wdcreset __P((struct wdc_softc *));
int wdcprobereset __P((bus_space_tag_t, bus_space_handle_t));
void wdcrestart __P((void *arg));
void wdcunwedge __P((struct wdc_softc *));
void wdctimeout __P((void *arg));
void wderror __P((void *, struct buf *, char *));
int wdcprobewait __P((bus_space_tag_t, bus_space_handle_t, int));
int wdcwait __P((struct wdc_softc *, int));
int wdlock __P((struct wd_softc *));
void wdunlock __P((struct wd_softc *));
@ -194,47 +207,75 @@ void wdunlock __P((struct wd_softc *));
#define wait_for_drq(d) wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
#define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
#define wait_for_unbusy(d) wdcwait(d, 0)
#define probewait_for_drq(t,h) \
wdcprobewait(t, h, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
#define probewait_for_ready(t,h) \
wdcprobewait(t, h, WDCS_DRDY | WDCS_DSC)
#define probewait_for_unbusy(t,h) \
wdcprobewait(t, h, 0)
int
wdcprobe(parent, match, aux)
struct device *parent;
void *match, *aux;
#ifdef __BROKEN_INDIRECT_CONFIG
void *match;
#else
struct cfdata *match;
#endif
void *aux;
{
struct wdc_softc *wdc = match;
struct isa_attach_args *ia = aux;
int iobase;
bus_space_tag_t iot;
bus_space_handle_t ioh;
int rv;
wdc->sc_iobase = iobase = ia->ia_iobase;
iot = ia->ia_iot;
if (bus_space_map(iot, ia->ia_iobase, 8, 0, &ioh))
return (0);
/* Check if we have registers that work. */
outb(iobase+wd_error, 0x5a); /* Error register not writable, */
outb(iobase+wd_cyl_lo, 0xa5); /* but all of cyllo are. */
if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5)
return 0;
/*
* Check if we have registers that work.
*
* Error register should not be writable, but all of cyl_lo
* register should be.
*/
bus_space_write_1(iot, ioh, wd_error, 0x5a);
bus_space_write_1(iot, ioh, wd_cyl_lo, 0xa5);
if (bus_space_read_1(iot, ioh, wd_error) == 0x5a ||
bus_space_read_1(iot, ioh, wd_cyl_lo) != 0xa5)
goto bad;
if (wdcreset(wdc) != 0) {
if (wdcprobereset(iot, ioh) != 0) {
delay(500000);
if (wdcreset(wdc) != 0)
return 0;
if (wdcprobereset(iot, ioh) != 0)
goto bad;
}
/* Select drive 0. */
outb(iobase+wd_sdh, WDSD_IBM | 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;
if (probewait_for_unbusy(iot, ioh) < 0)
goto bad;
/* Start drive diagnostics. */
outb(iobase+wd_command, WDCC_DIAGNOSE);
bus_space_write_1(iot, ioh, wd_command, WDCC_DIAGNOSE);
/* Wait for command to complete. */
if (wait_for_unbusy(wdc) < 0)
return 0;
if (probewait_for_unbusy(iot, ioh) < 0)
goto bad;
ia->ia_iosize = 8;
ia->ia_msize = 0;
return 1;
rv = 1;
out:
bus_space_unmap(iot, ioh, 8);
return rv;
bad:
rv = 0;
goto out;
}
struct wdc_attach_args {
@ -267,6 +308,12 @@ wdcattach(parent, self, aux)
printf("\n");
/* XXX RESET, DIAGNOSE AGAIN? */
wdc->sc_iot = ia->ia_iot;
if (bus_space_map(wdc->sc_iot, ia->ia_iobase, 8, 0, &wdc->sc_ioh))
panic("wdcattach: couldn't map I/O space");
wdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
IPL_BIO, wdcintr, wdc);
@ -275,16 +322,27 @@ wdcattach(parent, self, aux)
}
int
#ifdef __BROKEN_INDIRECT_CONFIG
wdprobe(parent, matchv, aux)
#else
wdprobe(parent, match, aux)
#endif
struct device *parent;
void *match, *aux;
#ifdef __BROKEN_INDIRECT_CONFIG
void *matchv;
#else
struct cfdata *match;
#endif
void *aux;
{
struct wdc_softc *wdc = (void *)parent;
struct cfdata *cf = match;
#ifdef __BROKEN_INDIRECT_CONFIG
struct cfdata *match = matchv;
#endif
struct wdc_attach_args *wa = aux;
int drive = wa->wa_drive;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
if (match->cf_loc[0] != -1 && match->cf_loc[0] != drive)
return 0;
if (wdcommandshort(wdc, drive, WDCC_RECAL) != 0 ||
@ -300,7 +358,9 @@ wdattach(parent, self, aux)
void *aux;
{
struct wd_softc *wd = (void *)self;
#ifndef NO_ISADMA_SUPPORT
struct wdc_softc *wdc = (void *)parent;
#endif
struct wdc_attach_args *wa = aux;
int i, blank;
char buf[41], c, *p, *q;
@ -341,10 +401,13 @@ wdattach(parent, self, aux)
wd->sc_params.wdp_sectors,
DEV_BSIZE);
#ifndef NO_ISADMA_SUPPORT
if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
wdc->sc_drq != DRQUNK) {
wd->sc_mode = WDM_DMA;
} else if (wd->sc_params.wdp_maxmulti > 1) {
} else
#endif
if (wd->sc_params.wdp_maxmulti > 1) {
wd->sc_mode = WDM_PIOMULTI;
wd->sc_multiple = min(wd->sc_params.wdp_maxmulti, 16);
} else {
@ -599,7 +662,8 @@ loop:
wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
} else {
#ifdef WDDEBUG
printf(" %d)%x", wd->sc_skip, inb(wdc->sc_iobase+wd_altsts));
printf(" %d)%x", wd->sc_skip,
bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_altsts));
#endif
}
@ -678,6 +742,7 @@ loop:
} else
#endif
switch (wd->sc_mode) {
#ifndef NO_ISADMA_SUPPORT
case WDM_DMA:
command = (bp->b_flags & B_READ) ?
WDCC_READDMA : WDCC_WRITEDMA;
@ -688,6 +753,7 @@ loop:
bp->b_data + wd->sc_skip,
wd->sc_nbytes, wdc->sc_drq);
break;
#endif /* NO_ISADMA_SUPPORT */
case WDM_PIOMULTI:
command = (bp->b_flags & B_READ) ?
WDCC_READMULTI : WDCC_WRITEMULTI;
@ -714,7 +780,7 @@ loop:
#ifdef WDDEBUG
printf("sector %ld cylin %ld head %ld addr %p sts %x\n",
sector, cylin, head, bp->b_data,
inb(wdc->sc_iobase+wd_altsts));
bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_altsts));
#endif
} else if (wd->sc_nblks > 1) {
/* The number of blocks in the last stretch may be smaller. */
@ -736,10 +802,12 @@ loop:
/* Push out data. */
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_ioh,
wd_data, (u_int16_t *)(bp->b_data + wd->sc_skip),
wd->sc_nbytes >> 1);
else
outsl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
bus_space_write_multi_4(wdc->sc_iot, wdc->sc_ioh,
wd_data, (u_int32_t *)(bp->b_data + wd->sc_skip),
wd->sc_nbytes >> 2);
}
@ -763,7 +831,7 @@ wdcintr(arg)
if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
/* 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;
}
@ -793,9 +861,11 @@ wdcintr(arg)
}
/* Turn off the DMA channel and unbounce the buffer. */
#ifndef NO_ISADMA_SUPPORT
if (wd->sc_mode == WDM_DMA)
isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
#endif
/* Have we an error? */
if (wdc->sc_status & WDCS_ERR) {
@ -843,10 +913,12 @@ wdcintr(arg)
/* Pull in data. */
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_ioh,
wd_data, (u_int16_t *)(bp->b_data + wd->sc_skip),
wd->sc_nbytes >> 1);
else
insl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
bus_space_read_multi_4(wdc->sc_iot, wdc->sc_ioh,
wd_data, (u_int32_t *)(bp->b_data + wd->sc_skip),
wd->sc_nbytes >> 2);
}
@ -1137,7 +1209,8 @@ wdcontrol(wd)
multimode:
if (wd->sc_mode != WDM_PIOMULTI)
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) {
wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
goto bad;
@ -1182,11 +1255,13 @@ wdcommand(wd, command, cylin, head, sector, count)
int cylin, head, sector, count;
{
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;
/* 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. */
if (command == WDCC_IDP)
@ -1198,16 +1273,17 @@ wdcommand(wd, command, cylin, head, sector, count)
/* Load parameters. */
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
outb(iobase+wd_features, 0);
outb(iobase+wd_cyl_lo, cylin);
outb(iobase+wd_cyl_hi, cylin >> 8);
outb(iobase+wd_sector, sector);
outb(iobase+wd_seccnt, count);
bus_space_write_1(iot, ioh, wd_features, 0);
bus_space_write_1(iot, ioh, wd_cyl_lo, cylin);
bus_space_write_1(iot, ioh, wd_cyl_hi, cylin >> 8);
bus_space_write_1(iot, ioh, wd_sector, sector);
bus_space_write_1(iot, ioh, wd_seccnt, count);
/* Send command. */
outb(iobase+wd_command, command);
bus_space_write_1(iot, ioh, wd_command, command);
return 0;
}
@ -1221,15 +1297,16 @@ wdcommandshort(wdc, drive, command)
int drive;
int command;
{
int iobase = wdc->sc_iobase;
bus_space_tag_t iot = wdc->sc_iot;
bus_space_handle_t ioh = wdc->sc_ioh;
/* Select drive. */
outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | (drive << 4));
if (wdcwait(wdc, WDCS_DRDY) < 0)
return -1;
outb(iobase+wd_command, command);
bus_space_write_1(iot, ioh, wd_command, command);
return 0;
}
@ -1314,7 +1391,8 @@ wd_get_parms(wd)
wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
/* 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_ioh, wd_data,
(u_int16_t *)tb, sizeof(tb) / sizeof(short));
bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
/* Shuffle string byte order. */
@ -1326,7 +1404,7 @@ wd_get_parms(wd)
}
/* 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. */
wdcstart(wdc);
@ -1580,8 +1658,9 @@ wddump(dev, blkno, va, size)
wderror(wd, NULL, "wddump: write failed");
return EIO;
}
outsw(wdc->sc_iobase+wd_data, va, lp->d_secsize >> 1);
bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
(u_int16_t *)va, lp->d_secsize >> 1);
/* Check data request (should be done). */
if (wait_for_ready(wdc) != 0) {
@ -1641,19 +1720,40 @@ bad144intern(wd)
wd->sc_badsect[i] = -1;
}
int
wdcprobereset(iot, ioh)
bus_space_tag_t iot;
bus_space_handle_t ioh;
{
/* Reset the device. */
bus_space_write_1(iot, ioh, wd_ctlr, WDCTL_RST | WDCTL_IDS);
delay(1000);
bus_space_write_1(iot, ioh, wd_ctlr, WDCTL_IDS);
delay(1000);
(void) bus_space_read_1(iot, ioh, wd_error);
bus_space_write_1(iot, ioh, wd_ctlr, WDCTL_4BIT);
if (probewait_for_unbusy(iot, ioh) < 0)
return 1;
return 0;
}
int
wdcreset(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;
/* Reset the device. */
outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
bus_space_write_1(iot, ioh, wd_ctlr, WDCTL_RST | WDCTL_IDS);
delay(1000);
outb(iobase+wd_ctlr, WDCTL_IDS);
bus_space_write_1(iot, ioh, wd_ctlr, WDCTL_IDS);
delay(1000);
(void) inb(iobase+wd_error);
outb(iobase+wd_ctlr, WDCTL_4BIT);
(void) bus_space_read_1(iot, ioh, wd_error);
bus_space_write_1(iot, ioh, wd_ctlr, WDCTL_4BIT);
if (wait_for_unbusy(wdc) < 0) {
printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
@ -1708,19 +1808,16 @@ wdcunwedge(wdc)
}
int
wdcwait(wdc, mask)
struct wdc_softc *wdc;
wdcprobewait(iot, ioh, mask)
bus_space_tag_t iot;
bus_space_handle_t ioh;
int mask;
{
int iobase = wdc->sc_iobase;
int timeout = 0;
u_char status;
#ifdef WDCNDELAY_DEBUG
extern int cold;
#endif
for (;;) {
wdc->sc_status = status = inb(iobase+wd_status);
status = bus_space_read_1(iot, ioh, wd_status);
if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
break;
if (++timeout > WDCNDELAY)
@ -1728,7 +1825,36 @@ wdcwait(wdc, mask)
delay(WDCDELAY);
}
if (status & WDCS_ERR) {
wdc->sc_error = inb(iobase+wd_error);
(void)bus_space_read_1(iot, ioh, wd_error);
return WDCS_ERR;
}
return 0;
}
int
wdcwait(wdc, mask)
struct wdc_softc *wdc;
int mask;
{
bus_space_tag_t iot = wdc->sc_iot;
bus_space_handle_t ioh = wdc->sc_ioh;
int timeout = 0;
u_char status;
#ifdef WDCNDELAY_DEBUG
extern int cold;
#endif
for (;;) {
wdc->sc_status = status = bus_space_read_1(iot, ioh,
wd_status);
if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
break;
if (++timeout > WDCNDELAY)
return -1;
delay(WDCDELAY);
}
if (status & WDCS_ERR) {
wdc->sc_error = bus_space_read_1(iot, ioh, wd_error);
return WDCS_ERR;
}
#ifdef WDCNDELAY_DEBUG