xref: /netbsd-src/sys/arch/alpha/sableio/sableio.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1 /* $NetBSD: sableio.c,v 1.16 2021/08/07 16:18:41 thorpej Exp $ */
2 
3 /*-
4  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Driver glue for the Sable STDIO module.
34  *
35  * This is kind of a hack.  The STDIO is really a junk I/O module with
36  * your regular ISA junk peripherals and their regular ISA I/O addresses.
37  * However, the main issue we have here is *interrupts*.  Not only are
38  * devices IRQs strange (i.e. not what you would expect to find if they
39  * were attached to a real ISA) IRQs, the keyboard controller isn't even
40  * connected to the (E)ISA IRQ space at all!
41  *
42  * In short, we're gluing together the following things:
43  *
44  *	- Standard ISA junk I/O chip
45  *	- ISA DMA
46  *	- Pre-mapped "PCI" interrupts that are *edge triggered*
47  */
48 
49 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
50 
51 __KERNEL_RCSID(0, "$NetBSD: sableio.c,v 1.16 2021/08/07 16:18:41 thorpej Exp $");
52 
53 #include "isadma.h"
54 
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/device.h>
58 
59 #include <dev/isa/isareg.h>
60 #include <dev/isa/isavar.h>
61 #include <dev/isa/isadmavar.h>
62 
63 #include <dev/pci/pcivar.h>
64 
65 #include <alpha/sableio/sableiovar.h>
66 
67 #include "locators.h"
68 
69 /*
70  * The devices built-in to the Sable STDIO module.
71  */
72 static const struct sableio_dev {
73 	const char *sd_name;		/* device name */
74 	bus_addr_t sd_ioaddr;		/* I/O space address */
75 	int sd_sableirq[2];		/* Sable IRQs */
76 	int sd_drq;			/* ISA DRQ */
77 } sableio_devs[] = {
78 	/*
79 	 * See alpha/pci/pci_2100_a500.c for interrupt information.
80 	 */
81 	{ "pckbc",	IO_KBD,		{ 6, 3 },	-1 },
82 	{ "fdc",	IO_FD1,		{ 7, -1 },	2 },
83 	{ "com",	IO_COM1,	{ 15, -1 },	-1 },
84 	{ "com",	IO_COM2,	{ 8, -1 },	-1 },
85 	{ "lpt",	IO_LPT3,	{ 9, -1 },	-1 },
86 	{ NULL,		0,		{ -1, -1 },	-1 },
87 };
88 
89 struct sableio_softc {
90 	device_t	sc_dev;		/* base device */
91 
92 	/*
93 	 * We have to deal with ISA DMA, so that means we have to
94 	 * hold the ISA chipset, since we attach STDIO devices
95 	 * before we attach the PCI (and thus EISA) bus.
96 	 */
97 	struct alpha_isa_chipset sc_isa_chipset;
98 };
99 
100 static int	sableio_match(device_t, cfdata_t, void *);
101 static void	sableio_attach(device_t, device_t, void *);
102 
103 CFATTACH_DECL_NEW(sableio, sizeof(struct sableio_softc),
104     sableio_match, sableio_attach, NULL, NULL);
105 
106 static int	sableio_print(void *, const char *);
107 
108 static struct sableio_softc *sableio_attached;
109 
110 static int
sableio_match(device_t parent,cfdata_t cf,void * aux)111 sableio_match(device_t parent, cfdata_t cf, void *aux)
112 {
113 	struct pcibus_attach_args *pba = aux;
114 
115 	/*
116 	 * These are really ISA devices, and thus must be on
117 	 * PCI bus 0.
118 	 */
119 	if (cf->cf_loc[SABLEIOBUSCF_BUS] != SABLEIOBUSCF_BUS_DEFAULT &&
120 	    cf->cf_loc[SABLEIOBUSCF_BUS] != pba->pba_bus)
121 		return (0);
122 
123 	/* sanity */
124 	if (pba->pba_bus != 0)
125 		return (0);
126 
127 	/* There can be only one. */
128 	if (sableio_attached != NULL)
129 		return (0);
130 
131 	return (1);
132 }
133 
134 static void
sableio_attach(device_t parent,device_t self,void * aux)135 sableio_attach(device_t parent, device_t self, void *aux)
136 {
137 	struct sableio_softc *sc = device_private(self);
138 	struct pcibus_attach_args *pba = aux;
139 	struct sableio_attach_args sa;
140 	bus_dma_tag_t dmat;
141 	int i;
142 	int locs[SABLEIOCF_NLOCS];
143 
144 	aprint_normal(": Sable STDIO module\n");
145 
146 	sableio_attached = sc;
147 	sc->sc_dev = self;
148 
149 	dmat = alphabus_dma_get_tag(pba->pba_dmat, ALPHA_BUS_ISA);
150 
151 #if NISADMA > 0
152 	/*
153 	 * Initialize our DMA state.
154 	 */
155 	isa_dmainit(&sc->sc_isa_chipset, pba->pba_iot, dmat, self);
156 #endif
157 
158 	for (i = 0; sableio_devs[i].sd_name != NULL; i++) {
159 		sa.sa_name = sableio_devs[i].sd_name;
160 		sa.sa_ioaddr = sableio_devs[i].sd_ioaddr;
161 		sa.sa_sableirq[0] = sableio_devs[i].sd_sableirq[0];
162 		sa.sa_sableirq[1] = sableio_devs[i].sd_sableirq[1];
163 		sa.sa_drq = sableio_devs[i].sd_drq;
164 
165 		sa.sa_iot = pba->pba_iot;
166 		sa.sa_dmat = dmat;
167 		sa.sa_ic = &sc->sc_isa_chipset;
168 		sa.sa_pc = pba->pba_pc;
169 
170 		locs[SABLEIOCF_PORT] = sableio_devs[i].sd_ioaddr;
171 
172 		config_found(self, &sa, sableio_print,
173 		    CFARGS(.submatch = config_stdsubmatch,
174 			   .locators = locs));
175 	}
176 }
177 
178 static int
sableio_print(void * aux,const char * pnp)179 sableio_print(void *aux, const char *pnp)
180 {
181 	struct sableio_attach_args *sa = aux;
182 
183 	if (pnp != NULL)
184 		aprint_normal("%s at %s", sa->sa_name, pnp);
185 
186 	aprint_normal(" port 0x%lx", sa->sa_ioaddr);
187 	return (UNCONF);
188 }
189 
190 isa_chipset_tag_t
sableio_pickisa(void)191 sableio_pickisa(void)
192 {
193 
194 	if (sableio_attached == NULL)
195 		panic("sableio_pickisa");
196 
197 	return (&sableio_attached->sc_isa_chipset);
198 }
199