1*a6ce3504Sthorpej /* $NetBSD: wdc_obio.c,v 1.11 2023/12/20 15:00:08 thorpej Exp $ */
21fd097bfSuwe
31fd097bfSuwe /*-
41fd097bfSuwe * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
51fd097bfSuwe * All rights reserved.
61fd097bfSuwe *
71fd097bfSuwe * This code is derived from software contributed to The NetBSD Foundation
81fd097bfSuwe * by Charles M. Hannum and by Onno van der Linden.
91fd097bfSuwe *
101fd097bfSuwe * Redistribution and use in source and binary forms, with or without
111fd097bfSuwe * modification, are permitted provided that the following conditions
121fd097bfSuwe * are met:
131fd097bfSuwe * 1. Redistributions of source code must retain the above copyright
141fd097bfSuwe * notice, this list of conditions and the following disclaimer.
151fd097bfSuwe * 2. Redistributions in binary form must reproduce the above copyright
161fd097bfSuwe * notice, this list of conditions and the following disclaimer in the
171fd097bfSuwe * documentation and/or other materials provided with the distribution.
181fd097bfSuwe *
191fd097bfSuwe * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201fd097bfSuwe * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211fd097bfSuwe * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221fd097bfSuwe * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231fd097bfSuwe * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241fd097bfSuwe * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251fd097bfSuwe * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261fd097bfSuwe * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271fd097bfSuwe * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281fd097bfSuwe * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291fd097bfSuwe * POSSIBILITY OF SUCH DAMAGE.
301fd097bfSuwe */
311fd097bfSuwe
321fd097bfSuwe #include <sys/cdefs.h>
33*a6ce3504Sthorpej __KERNEL_RCSID(0, "$NetBSD: wdc_obio.c,v 1.11 2023/12/20 15:00:08 thorpej Exp $");
341fd097bfSuwe
351fd097bfSuwe #include <sys/types.h>
361fd097bfSuwe #include <sys/param.h>
371fd097bfSuwe #include <sys/systm.h>
381fd097bfSuwe #include <sys/device.h>
391fd097bfSuwe
40cf10107dSdyoung #include <sys/bus.h>
411fd097bfSuwe #include <machine/intr.h>
421fd097bfSuwe
431fd097bfSuwe #include <dev/ata/atavar.h>
441fd097bfSuwe #include <dev/ic/wdcvar.h>
451fd097bfSuwe
461fd097bfSuwe #include <landisk/dev/obiovar.h>
471fd097bfSuwe
481fd097bfSuwe struct wdc_obio_softc {
491fd097bfSuwe struct wdc_softc sc_wdcdev;
501fd097bfSuwe struct ata_channel *sc_chanlist[1];
511fd097bfSuwe struct ata_channel sc_channel;
521fd097bfSuwe struct wdc_regs sc_wdc_regs;
531fd097bfSuwe void *sc_ih;
541fd097bfSuwe };
551fd097bfSuwe
567aa6248cScube static int wdc_obio_probe(device_t, cfdata_t, void *);
577aa6248cScube static void wdc_obio_attach(device_t, device_t, void *);
581fd097bfSuwe
597aa6248cScube CFATTACH_DECL_NEW(wdc_obio, sizeof(struct wdc_obio_softc),
601fd097bfSuwe wdc_obio_probe, wdc_obio_attach, NULL, NULL);
611fd097bfSuwe
621fd097bfSuwe #define WDC_OBIO_REG_NPORTS WDC_NREG
631fd097bfSuwe #define WDC_OBIO_REG_SIZE (WDC_OBIO_REG_NPORTS * 2)
641fd097bfSuwe #define WDC_OBIO_AUXREG_NPORTS 1
651fd097bfSuwe #define WDC_OBIO_AUXREG_SIZE (WDC_OBIO_AUXREG_NPORTS * 2)
661fd097bfSuwe #define WDC_OBIO_AUXREG_OFFSET 0x2c
671fd097bfSuwe
681fd097bfSuwe static int
wdc_obio_probe(device_t parent,cfdata_t cfp,void * aux)697aa6248cScube wdc_obio_probe(device_t parent, cfdata_t cfp, void *aux)
701fd097bfSuwe {
711fd097bfSuwe struct obio_attach_args *oa = aux;
721fd097bfSuwe struct wdc_regs wdr;
731fd097bfSuwe int result = 0;
741fd097bfSuwe int i;
751fd097bfSuwe
761fd097bfSuwe if (oa->oa_nio < 1)
771fd097bfSuwe return (0);
781fd097bfSuwe if (oa->oa_nirq < 1)
791fd097bfSuwe return (0);
801fd097bfSuwe
811fd097bfSuwe if (oa->oa_io[0].or_addr == IOBASEUNK)
821fd097bfSuwe return (0);
831fd097bfSuwe if (oa->oa_irq[0].or_irq == IRQUNK)
841fd097bfSuwe return (0);
851fd097bfSuwe
861fd097bfSuwe wdr.cmd_iot = oa->oa_iot;
871fd097bfSuwe if (bus_space_map(wdr.cmd_iot, oa->oa_io[0].or_addr,
881fd097bfSuwe WDC_OBIO_REG_SIZE, 0, &wdr.cmd_baseioh)) {
891fd097bfSuwe goto out;
901fd097bfSuwe }
911fd097bfSuwe for (i = 0; i < WDC_OBIO_REG_NPORTS; i++) {
921fd097bfSuwe if (bus_space_subregion(wdr.cmd_iot, wdr.cmd_baseioh,
931fd097bfSuwe i * 2, (i == 0) ? 2 : 1, &wdr.cmd_iohs[i])) {
941fd097bfSuwe goto outunmap;
951fd097bfSuwe }
961fd097bfSuwe }
9726cf6855Sjdolecek wdc_init_shadow_regs(&wdr);
981fd097bfSuwe
991fd097bfSuwe wdr.ctl_iot = oa->oa_iot;
1001fd097bfSuwe if (bus_space_map(wdr.ctl_iot,
1011fd097bfSuwe oa->oa_io[0].or_addr + WDC_OBIO_AUXREG_OFFSET,
1021fd097bfSuwe WDC_OBIO_AUXREG_SIZE, 0, &wdr.ctl_ioh)) {
1031fd097bfSuwe goto outunmap;
1041fd097bfSuwe }
1051fd097bfSuwe
10626cf6855Sjdolecek result = wdcprobe(&wdr);
1071fd097bfSuwe if (result) {
1081fd097bfSuwe oa->oa_nio = 1;
1091fd097bfSuwe oa->oa_io[0].or_size = WDC_OBIO_REG_SIZE;
1101fd097bfSuwe oa->oa_nirq = 1;
1111fd097bfSuwe oa->oa_niomem = 0;
1121fd097bfSuwe }
1131fd097bfSuwe
1141fd097bfSuwe bus_space_unmap(wdr.ctl_iot, wdr.ctl_ioh, WDC_OBIO_AUXREG_SIZE);
1151fd097bfSuwe outunmap:
1161fd097bfSuwe bus_space_unmap(wdr.cmd_iot, wdr.cmd_baseioh, WDC_OBIO_REG_SIZE);
1171fd097bfSuwe out:
1181fd097bfSuwe return (result);
1191fd097bfSuwe }
1201fd097bfSuwe
1211fd097bfSuwe static void
wdc_obio_attach(device_t parent,device_t self,void * aux)1227aa6248cScube wdc_obio_attach(device_t parent, device_t self, void *aux)
1231fd097bfSuwe {
1247aa6248cScube struct wdc_obio_softc *sc = device_private(self);
1251fd097bfSuwe struct obio_attach_args *oa = aux;
1261fd097bfSuwe struct wdc_regs *wdr;
1271fd097bfSuwe int i;
1281fd097bfSuwe
129d767a021Suwe aprint_naive("\n");
1307aa6248cScube aprint_normal("\n");
1311fd097bfSuwe
1327aa6248cScube sc->sc_wdcdev.sc_atac.atac_dev = self;
1331fd097bfSuwe sc->sc_wdcdev.regs = wdr = &sc->sc_wdc_regs;
1341fd097bfSuwe
1351fd097bfSuwe wdr->cmd_iot = oa->oa_iot;
1361fd097bfSuwe wdr->ctl_iot = oa->oa_iot;
1371fd097bfSuwe if (bus_space_map(wdr->cmd_iot, oa->oa_io[0].or_addr,
1381fd097bfSuwe WDC_OBIO_REG_SIZE, 0, &wdr->cmd_baseioh)
1391fd097bfSuwe || bus_space_map(wdr->ctl_iot,
1401fd097bfSuwe oa->oa_io[0].or_addr + WDC_OBIO_AUXREG_OFFSET,
1411fd097bfSuwe WDC_OBIO_AUXREG_SIZE, 0, &wdr->ctl_ioh)) {
1427aa6248cScube aprint_error_dev(self, "couldn't map registers\n");
1431fd097bfSuwe return;
1441fd097bfSuwe }
1451fd097bfSuwe
1461fd097bfSuwe for (i = 0; i < WDC_OBIO_REG_NPORTS; i++) {
1471fd097bfSuwe if (bus_space_subregion(wdr->cmd_iot,
1481fd097bfSuwe wdr->cmd_baseioh, i * 2, (i == 0) ? 2 : 1,
1491fd097bfSuwe &wdr->cmd_iohs[i]) != 0) {
1507aa6248cScube aprint_error_dev(self,
1517aa6248cScube "couldn't subregion registers\n");
1521fd097bfSuwe return;
1531fd097bfSuwe }
1541fd097bfSuwe }
1551fd097bfSuwe
1561fd097bfSuwe sc->sc_ih = obio_intr_establish(oa->oa_irq[0].or_irq, IPL_BIO, wdcintr,
1571fd097bfSuwe &sc->sc_channel);
1581fd097bfSuwe
1591fd097bfSuwe sc->sc_wdcdev.cap |= WDC_CAPABILITY_PREATA;
1601fd097bfSuwe sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16;
1611fd097bfSuwe sc->sc_wdcdev.sc_atac.atac_pio_cap = 0;
1621fd097bfSuwe sc->sc_chanlist[0] = &sc->sc_channel;
1631fd097bfSuwe sc->sc_wdcdev.sc_atac.atac_channels = sc->sc_chanlist;
1641fd097bfSuwe sc->sc_wdcdev.sc_atac.atac_nchannels = 1;
1659edd4d81Sbouyer sc->sc_wdcdev.wdc_maxdrives = 2;
1661fd097bfSuwe sc->sc_channel.ch_channel = 0;
1671fd097bfSuwe sc->sc_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
1681fd097bfSuwe
16926cf6855Sjdolecek wdc_init_shadow_regs(wdr);
1701fd097bfSuwe
1711fd097bfSuwe wdcattach(&sc->sc_channel);
1721fd097bfSuwe }
173