diff --git a/sys/arch/alpha/isa/awd.c b/sys/arch/alpha/isa/awd.c index fa77271867a5..1fb2c818cb46 100644 --- a/sys/arch/alpha/isa/awd.c +++ b/sys/arch/alpha/isa/awd.c @@ -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 -#include #include -#include +#include #include +#ifndef NO_ISADMA_SUPPORT #include +#endif #include #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