Date: Sun, 12 Nov 2006 06:48:42 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 109776 for review Message-ID: <200611120648.kAC6mgUp004045@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=109776 Change 109776 by sam@sam_ebb on 2006/11/12 06:48:01 Mostly working; channel attachs, interrupts work, and we fetch params but no drive yet: o add a private reset method that's a copy of ata_generic_reset but interprets reset complete w/o an error as being ok o remap registers per the linux driver o add missing bus space methods for the stream versions of read-multiple and write-multiple o mark channels 16-bit only and no slave (probably doesn't matter w/ private reset method but there'll never be slaves) o remove debug printfs we don't need any more Affected files ... .. //depot/projects/arm/src/sys/arm/xscale/ixp425/avila_ata.c#7 edit Differences ... ==== //depot/projects/arm/src/sys/arm/xscale/ixp425/avila_ata.c#7 (text+ko) ==== @@ -122,7 +122,9 @@ sc->sc_expbus_tag.bs_r_2 = ata_bs_r_2, /* read multiple */ sc->sc_expbus_tag.bs_rm_1 = ata_bs_rm_1, + sc->sc_expbus_tag.bs_rm_1_s = ata_bs_rm_1, sc->sc_expbus_tag.bs_rm_2 = ata_bs_rm_2, + sc->sc_expbus_tag.bs_rm_2_s = ata_bs_rm_2, /* write (single) */ sc->sc_expbus_tag.bs_w_1_s = ata_bs_w_1, sc->sc_expbus_tag.bs_w_2_s = ata_bs_w_2, @@ -130,7 +132,9 @@ sc->sc_expbus_tag.bs_w_2 = ata_bs_w_2, /* write multiple */ sc->sc_expbus_tag.bs_wm_1 = ata_bs_wm_1, + sc->sc_expbus_tag.bs_wm_1_s = ata_bs_wm_1, sc->sc_expbus_tag.bs_wm_2 = ata_bs_wm_2, + sc->sc_expbus_tag.bs_wm_2_s = ata_bs_wm_2, rman_set_bustag(&sc->sc_ata, &sc->sc_expbus_tag); rman_set_bushandle(&sc->sc_ata, sc->sc_ioh); @@ -274,13 +278,7 @@ { struct ata_avila_softc *sc = t; -#if 0 return bus_space_read_1(sc->sc_iot, h, o); -#else -uint8_t v = bus_space_read_1(sc->sc_iot, h, o); -printf("%s(%lx, %ld) => 0x%x\n", __func__, h, o, v); -return v; -#endif } void @@ -288,7 +286,6 @@ { struct ata_avila_softc *sc = t; -printf("%s(%lx, %ld, 0x%x)\n", __func__, h, o, v); bus_space_write_1(sc->sc_iot, h, o, v); } @@ -298,7 +295,6 @@ struct ata_avila_softc *sc = t; uint16_t v; -printf("%s(%lx, %lu)\n", __func__, h, o); enable_16(sc); v = bus_space_read_2(sc->sc_iot, h, o); disable_16(sc); @@ -310,7 +306,6 @@ { struct ata_avila_softc *sc = t; -printf("%s(%lx, %lu, 0x%x)\n", __func__, h, o, v); enable_16(sc); bus_space_write_2(sc->sc_iot, h, o, v); disable_16(sc); @@ -322,7 +317,6 @@ { struct ata_avila_softc *sc = t; -printf("%s(%lx, %lu, %p, %lu)\n", __func__, h, o, d, c); bus_space_read_multi_1(sc->sc_iot, h, o, d, c); } @@ -332,7 +326,6 @@ { struct ata_avila_softc *sc = t; -printf("%s(%lx, %lu, %p, %lu)\n", __func__, h, o, d, c); bus_space_write_multi_1(sc->sc_iot, h, o, d, c); } @@ -342,7 +335,6 @@ { struct ata_avila_softc *sc = t; -printf("%s(%lx, %lu, %p, %lu)\n", __func__, h, o, d, c); enable_16(sc); bus_space_read_multi_2(sc->sc_iot, h, o, d, c); disable_16(sc); @@ -354,7 +346,6 @@ { struct ata_avila_softc *sc = t; -printf("%s(%lx, %lu, %p, %lu)\n", __func__, h, o, d, c); enable_16(sc); bus_space_write_multi_2(sc->sc_iot, h, o, d, c); disable_16(sc); @@ -398,6 +389,7 @@ struct ata_channel *ch = device_get_softc(dev); ch->unit = 0; + ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE; device_set_desc_copy(dev, "ATA channel 0"); return ata_probe(dev); @@ -410,27 +402,116 @@ struct ata_channel *ch = device_get_softc(dev); int i; - /* registers up to ATA_STATUS map directly */ - for (i = ATA_DATA; i <= ATA_STATUS; i++) { + for (i = 0; i < ATA_MAX_RES; i++) ch->r_io[i].res = &sc->sc_ata; - ch->r_io[i].offset = i; - } - /* the control register is special */ - ch->r_io[ATA_CONTROL].res = &sc->sc_ata; + + ch->r_io[ATA_DATA].offset = ATA_DATA; + ch->r_io[ATA_FEATURE].offset = ATA_FEATURE; + ch->r_io[ATA_COUNT].offset = ATA_COUNT; + ch->r_io[ATA_SECTOR].offset = ATA_SECTOR; + ch->r_io[ATA_CYL_LSB].offset = ATA_CYL_LSB; + ch->r_io[ATA_CYL_MSB].offset = ATA_CYL_MSB; + ch->r_io[ATA_DRIVE].offset = ATA_DRIVE; + ch->r_io[ATA_COMMAND].offset = ATA_COMMAND; + ch->r_io[ATA_ERROR].offset = ATA_FEATURE; + /* NB: should be used only for ATAPI devices */ + ch->r_io[ATA_IREASON].offset = ATA_COUNT; + ch->r_io[ATA_STATUS].offset = ATA_COMMAND; + /* alias this; required by ata_generic_status */ + ch->r_io[ATA_ALTSTAT].offset = ch->r_io[ATA_STATUS].offset; + + /* NB: the control register is special */ ch->r_io[ATA_CONTROL].offset = AVILA_IDE_CTRL; + /* NB: by convention this points at the base of registers */ - ch->r_io[ATA_IDX_ADDR].res = &sc->sc_ata; ch->r_io[ATA_IDX_ADDR].offset = 0; - /* NB: should be used only for ATAPI devices */ - ch->r_io[ATA_IREASON] = ch->r_io[ATA_COUNT]; - /* alias this; required by ata_generic_status */ - ch->r_io[ATA_ALTSTAT] = ch->r_io[ATA_CONTROL]; - ata_generic_hw(dev); return ata_attach(dev); } +/* XXX override ata_generic_reset to handle non-standard status */ +static void +avila_channel_reset(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + u_int8_t ostat0 = 0, stat0 = 0; + u_int8_t err = 0, lsb = 0, msb = 0; + int mask = 0, timeout; + + /* do we have any signs of ATA/ATAPI HW being present ? */ + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER); + DELAY(10); + ostat0 = ATA_IDX_INB(ch, ATA_STATUS); + if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) { + stat0 = ATA_S_BUSY; + mask |= 0x01; + } + + if (bootverbose) + device_printf(dev, "%s: reset tp1 mask=%02x ostat0=%02x\n", + __func__, mask, ostat0); + + /* if nothing showed up there is no need to get any further */ + /* XXX SOS is that too strong?, we just might loose devices here */ + ch->devices = 0; + if (!mask) + return; + + /* reset (both) devices on this channel */ + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER); + DELAY(10); + ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS | ATA_A_RESET); + ata_udelay(10000); + ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS); + ata_udelay(100000); + ATA_IDX_INB(ch, ATA_ERROR); + + /* wait for BUSY to go inactive */ + for (timeout = 0; timeout < 310; timeout++) { + if ((mask & 0x01) && (stat0 & ATA_S_BUSY)) { + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); + DELAY(10); + err = ATA_IDX_INB(ch, ATA_ERROR); + lsb = ATA_IDX_INB(ch, ATA_CYL_LSB); + msb = ATA_IDX_INB(ch, ATA_CYL_MSB); + stat0 = ATA_IDX_INB(ch, ATA_STATUS); + if (bootverbose) + device_printf(dev, + "%s: stat0=0x%02x err=0x%02x lsb=0x%02x " + "msb=0x%02x\n", __func__, + stat0, err, lsb, msb); + if (stat0 == err && lsb == err && msb == err && + timeout > (stat0 & ATA_S_BUSY ? 100 : 10)) + mask &= ~0x01; + if (!(stat0 & ATA_S_BUSY)) { + if ((err & 0x7f) == ATA_E_ILI || err == 0) { + if (lsb == ATAPI_MAGIC_LSB && + msb == ATAPI_MAGIC_MSB) { + ch->devices |= ATA_ATAPI_MASTER; + } else if (stat0 & ATA_S_READY) { + ch->devices |= ATA_ATA_MASTER; + } + } else if ((stat0 & 0x0f) && + err == lsb && err == msb) { + stat0 |= ATA_S_BUSY; + } + } + } + if (mask == 0x00) /* nothing to wait for */ + break; + /* wait for master */ + if (!(stat0 & ATA_S_BUSY) || (stat0 == 0xff && timeout > 10)) + break; + ata_udelay(100000); + } + + if (bootverbose) + device_printf(dev, "%s: reset tp2 stat0=%02x devices=0x%b\n", + __func__, stat0, ch->devices, + "\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER"); +} + static device_method_t avila_channel_methods[] = { /* device interface */ DEVMETHOD(device_probe, avila_channel_probe), @@ -440,6 +521,8 @@ DEVMETHOD(device_suspend, ata_suspend), DEVMETHOD(device_resume, ata_resume), + DEVMETHOD(ata_reset, avila_channel_reset), + { 0, 0 } };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611120648.kAC6mgUp004045>