#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define FASTATA4K_MAX_CHANNELS 2 /* we're accesing the bus with stride 4 so multiply any address by 4! */ #define FASTATA4K_REG_SIZE 0x400 /* 0x1000 */ #define FASTATA4K_OFF_PIO0 0x0 /* 0x0 */ #define FASTATA4K_OFF_PIO3 0x800 /* 0x2000 */ #define FASTATA4K_OFF_PIO4 0x1800 /* 0x6000 */ #define FASTATA4K_OFF_DATAL 0x0 #define FASTATA4K_OFF_ERROR 0x80 /* error/feature */ #define FASTATA4K_OFF_DATA 0xC0 #define FASTATA4K_OFF_SECCNT 0x100 #define FASTATA4K_OFF_INTSTAT 0x140 /* int status (bit 7 set if int. set on any port) */ #define FASTATA4K_OFF_SECTOR 0x180 #define FASTATA4K_OFF_CYL_LO 0x200 #define FASTATA4K_OFF_CYL_HI 0x280 #define FASTATA4K_OFF_SDH 0x300 /* device/head? 101nNNNN is this standard? */ #define FASTATA4K_OFF_COMMAND 0x380 /* status/command */ struct wdc_fastata4k_softc { struct wdc_softc sc_wdcdev; struct ata_channel *wdc_chanarray[FASTATA4K_MAX_CHANNELS]; struct ata_channel channels[FASTATA4K_MAX_CHANNELS]; struct bus_space_tag sc_iot; struct isr sc_isr; volatile char *ba; }; int wdc_fastata4k_probe(device_t, cfdata_t, void *); void wdc_fastata4k_attach(device_t, device_t, void *); /*int wdc_fastata4k_intr(void *);*/ void wdc_fastata4k_dumpregs(bus_space_tag_t iot, bus_space_handle_t ioh, struct wdc_regs *wdr); CFATTACH_DECL_NEW(wdc_fastata4k, sizeof(struct wdc_fastata4k_softc), wdc_fastata4k_probe, wdc_fastata4k_attach, NULL, NULL); int wdc_fastata4k_probe(device_t parent, cfdata_t cfp, void *aux) { struct zbus_args *zap; zap = aux; if (zap->manid != 2206) return 0; if ((zap->prodid != 25) && /* FastATA 4000 Mk-I */ (zap->prodid != 29) && /* FastATA 4000 Mk-II/Mk-III */ (zap->prodid != 62)) /* FastATA 4000 Mk-V */ return 0; return 1; } void wdc_fastata4k_dumpregs(bus_space_tag_t iot, bus_space_handle_t ioh, struct wdc_regs *wdr) { uint8_t error, seccnt, intstat, sector, cyl_lo, cyl_hi, sdh, command; uint16_t datal, data; /* data == datal in pio0? */ datal = bus_space_read_2(iot, ioh, FASTATA4K_OFF_DATAL); error = bus_space_read_1(iot, ioh, FASTATA4K_OFF_ERROR); data = bus_space_read_2(iot, ioh, FASTATA4K_OFF_DATA); seccnt = bus_space_read_1(iot, ioh, FASTATA4K_OFF_SECCNT); intstat = bus_space_read_1(iot, ioh, FASTATA4K_OFF_INTSTAT); sector = bus_space_read_1(iot, ioh, FASTATA4K_OFF_SECTOR); cyl_lo = bus_space_read_1(iot, ioh, FASTATA4K_OFF_CYL_LO); cyl_hi = bus_space_read_1(iot, ioh, FASTATA4K_OFF_CYL_HI); sdh = bus_space_read_1(iot, ioh, FASTATA4K_OFF_SDH); command = bus_space_read_1(iot, ioh, FASTATA4K_OFF_COMMAND); /* print what do we have here */ aprint_normal("FastATA regs: %x %x %x %x %x %x %x %x %x %x\n", datal, error, data, seccnt, sector, cyl_lo, cyl_hi, sdh, command, intstat); data = bus_space_read_2(wdr->cmd_iot, wdr->cmd_iohs[wd_data], 0); error = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_error], 0); seccnt = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt], 0); sector = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sector], 0); cyl_lo = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_lo], 0); cyl_hi = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_hi], 0); sdh = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0); command = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0); /* as seen by wdc layer */ aprint_normal("wdc regs : %x %x XX %x %x %x %x %x %x XX\n", data, error, seccnt, sector, cyl_lo, cyl_hi, sdh, command); } void wdc_fastata4k_attach(device_t parent, device_t self, void *aux) { struct wdc_fastata4k_softc *sc; struct zbus_args *zap; int nchannels; int ch; sc = device_private(self); sc->sc_wdcdev.sc_atac.atac_dev = self; zap = aux; sc->ba = zap->va; sc->sc_iot.base = (bus_addr_t)sc->ba; sc->sc_iot.absm = &amiga_bus_stride_4swap; nchannels = 2; if (zap->prodid == 25) aprint_normal(": FastATA 4000 Mk-I\n"); else if (zap->prodid == 29) aprint_normal(": FastATA 4000 Mk-II/Mk-III\n"); else if (zap->prodid == 62) aprint_normal(": FastATA 4000 Mk-V\n"); else aprint_normal(": FastATA 4000 unknown model"); /* XXX pio mode setting not implemented yet. */ sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16|ATAC_CAP_NOIRQ; sc->sc_wdcdev.sc_atac.atac_pio_cap = 0; sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; sc->sc_wdcdev.sc_atac.atac_nchannels = nchannels; wdc_allocate_regs(&sc->sc_wdcdev); for (ch = 0; ch < nchannels; ch++) { struct ata_channel *cp; struct wdc_regs *wdr; cp = &sc->channels[ch]; sc->wdc_chanarray[ch] = cp; cp->ch_channel = ch; cp->ch_atac = &sc->sc_wdcdev.sc_atac; cp->ch_queue = malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); if (cp->ch_queue == NULL) { aprint_error_dev(self, "can't allocate memory for command queue\n"); return; } cp->ch_ndrive = 2; wdr = CHAN_TO_WDC_REGS(cp); wdr->cmd_iot = &sc->sc_iot; /* map command registers space, for PIO0 port 0 is at 0x0, port 1 is at +0x1000, one set of registers is 0x1000 wide */ if (bus_space_map(wdr->cmd_iot, FASTATA4K_OFF_PIO0+ch*FASTATA4K_REG_SIZE, FASTATA4K_REG_SIZE, 0, &wdr->cmd_baseioh)) { aprint_error_dev(self, "couldn't map cmd registers\n"); return; } /* wdr->ctl_iot = &sc->sc_iot; */ /* FastATA does not have aux ctl regs? */ /* subregion individual command registers */ bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_DATA, 2, &wdr->cmd_iohs[wd_data]); bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_ERROR, 1, &wdr->cmd_iohs[wd_error]); bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_SECCNT, 1, &wdr->cmd_iohs[wd_seccnt]); bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_SECTOR, 1, &wdr->cmd_iohs[wd_sector]); bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_CYL_LO, 1, &wdr->cmd_iohs[wd_cyl_lo]); bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_CYL_HI, 1, &wdr->cmd_iohs[wd_cyl_hi]); bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_SDH, 1, &wdr->cmd_iohs[wd_sdh]); bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_COMMAND, 1, &wdr->cmd_iohs[wd_command]); wdc_init_shadow_regs(cp); wdcattach(cp); bus_space_write_1(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_CYL_LO, 0x02); bus_space_write_1(wdr->cmd_iot, wdr->cmd_baseioh, FASTATA4K_OFF_CYL_HI, 0x02); wdc_fastata4k_dumpregs(wdr->cmd_iot, wdr->cmd_baseioh, wdr); } /* XXX: no hardware interrupt? sc->sc_isr.isr_intr = wdc_fastata4k_intr; sc->sc_isr.isr_arg = sc; sc->sc_isr.isr_ipl = 2; add_isr (&sc->sc_isr); */ } /* no hardware interrupt? */ /* int wdc_fastata4k_intr(void *arg) { struct wdc_fastata4k_softc *sc = (struct wdc_fastata4k_softc *)arg; int nchannels, ret; volatile char *p; aprint_normal("FastATA interrupt start: "); ret = 0; nchannels = sc->sc_wdcdev.sc_atac.atac_nchannels; p = sc->ba; if (p[FASTATA4K_OFF_PIO0+FASTATA4K_OFF_INTSTAT] & 0x40) { aprint_normal("interrupt on port 0\n"); wdcintr(&sc->channels[0]); ret = 1; } if (p[FASTATA4K_OFF_PIO0+FASTATA4K_OFF_INTSTAT] & 0x20) { aprint_normal("interrupt on port 1\n"); wdcintr(&sc->channels[1]); ret = 1; } aprint_normal("FastATA interrupt end\n"); return ret; } */