xref: /netbsd-src/sys/arch/landisk/dev/wdc_obio.c (revision a6ce3504542ed8b086b0b8c7681fff4540e0cdd8)
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