1 /* $NetBSD: intio.c,v 1.33 2024/04/30 05:06:08 tsutsui Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1998, 2001 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 * Autoconfiguration support for hp300 internal i/o space.
34 */
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: intio.c,v 1.33 2024/04/30 05:06:08 tsutsui Exp $");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42
43 #include <machine/hp300spu.h>
44
45 #include <hp300/dev/intioreg.h>
46 #include <hp300/dev/intiovar.h>
47
48 struct intio_softc {
49 device_t sc_dev;
50 struct bus_space_tag sc_tag;
51 };
52
53 static int intiomatch(device_t, cfdata_t, void *);
54 static void intioattach(device_t, device_t, void *);
55 static int intioprint(void *, const char *);
56
57 CFATTACH_DECL_NEW(intio, sizeof(struct intio_softc),
58 intiomatch, intioattach, NULL, NULL);
59
60 #if defined(HP320) || defined(HP330) || defined(HP340) || defined(HP345) || \
61 defined(HP350) || defined(HP360) || defined(HP370) || defined(HP375) || \
62 defined(HP380) || defined(HP385)
63 #define HAVE_INTIO_FB
64 #endif
65
66 #if defined(HP382) || defined(HP400) || defined(HP425) || defined(HP433)
67 #define HAVE_INTIO_FRODO
68 #endif
69
70 #define INTIO_3xx_BUILTINS \
71 (__BIT(HP_320) | __BIT(HP_330) | __BIT(HP_340) | \
72 __BIT(HP_345) | __BIT(HP_345) | __BIT(HP_350) | \
73 __BIT(HP_360) | __BIT(HP_370) | __BIT(HP_375) | \
74 __BIT(HP_380) | __BIT(HP_385))
75
76 #define INTIO_362_BUILTINS __BIT(HP_362)
77 #define INTIO_382_BUILTINS __BIT(HP_382)
78
79 #define INTIO_4xx_BUILTINS \
80 (__BIT(HP_400) | __BIT(HP_425) | __BIT(HP_433))
81
82 #define INTIO_ALL_BUILTINS \
83 (INTIO_3xx_BUILTINS | INTIO_362_BUILTINS | \
84 INTIO_382_BUILTINS | INTIO_4xx_BUILTINS)
85
86 static const struct intio_builtins intio_builtins[] = {
87 { "rtc", RTC_BASE, -1,
88 INTIO_ALL_BUILTINS },
89
90 #ifdef HAVE_INTIO_FRODO
91 { "frodo", FRODO_BASE, 5,
92 INTIO_382_BUILTINS | INTIO_4xx_BUILTINS },
93 #endif
94
95 { "hil", HIL_BASE, 1,
96 INTIO_ALL_BUILTINS },
97
98 { "hpib", HPIB_BASE, 3,
99 INTIO_ALL_BUILTINS },
100
101 { "dma", DMA_BASE, 1,
102 INTIO_ALL_BUILTINS },
103
104 #ifdef HAVE_INTIO_FB
105 { "fb", FB_BASE, -1,
106 INTIO_3xx_BUILTINS },
107 #endif
108 };
109 #define nintio_builtins __arraycount(intio_builtins)
110
111 static int intio_matched = 0;
112 extern void *internalhpib;
113
114 static int
intiomatch(device_t parent,cfdata_t cf,void * aux)115 intiomatch(device_t parent, cfdata_t cf, void *aux)
116 {
117
118 /* Allow only one instance. */
119 if (intio_matched)
120 return 0;
121
122 intio_matched = 1;
123 return 1;
124 }
125
126 static void
intioattach(device_t parent,device_t self,void * aux)127 intioattach(device_t parent, device_t self, void *aux)
128 {
129 struct intio_softc *sc = device_private(self);
130 struct intio_attach_args ia;
131 bus_space_tag_t bst = &sc->sc_tag;
132 const uint32_t spumask = 1U << machineid;
133 int i;
134
135 sc->sc_dev = self;
136 aprint_normal("\n");
137
138 KASSERT(spumask != 0);
139
140 memset(bst, 0, sizeof(struct bus_space_tag));
141 bst->bustype = HP300_BUS_SPACE_INTIO;
142
143 memset(&ia, 0, sizeof(ia));
144
145 for (i = 0; i < nintio_builtins; i++) {
146
147 /*
148 * If the device doesn't exist on this specific model,
149 * skip it.
150 */
151 if ((intio_builtins[i].ib_spumask & spumask) == 0)
152 continue;
153
154 /*
155 * Internal HP-IB doesn't always return a device ID,
156 * so we rely on the sysflags.
157 */
158 if (intio_builtins[i].ib_offset == HPIB_BASE && !internalhpib)
159 continue;
160
161 strlcpy(ia.ia_modname, intio_builtins[i].ib_modname,
162 sizeof(ia.ia_modname));
163 ia.ia_bst = bst;
164 ia.ia_iobase = intio_builtins[i].ib_offset;
165 ia.ia_addr =
166 (bus_addr_t)(intiobase + intio_builtins[i].ib_offset);
167 ia.ia_ipl = intio_builtins[i].ib_ipl;
168 config_found(self, &ia, intioprint, CFARGS_NONE);
169 }
170 }
171
172 static int
intioprint(void * aux,const char * pnp)173 intioprint(void *aux, const char *pnp)
174 {
175 struct intio_attach_args *ia = aux;
176
177 if (pnp != NULL)
178 aprint_normal("%s at %s", ia->ia_modname, pnp);
179 if (ia->ia_iobase != 0 && pnp == NULL) {
180 aprint_normal(" addr 0x%lx", INTIOBASE + ia->ia_iobase);
181 if (ia->ia_ipl != -1)
182 aprint_normal(" ipl %d", ia->ia_ipl);
183 }
184 return UNCONF;
185 }
186