tlsb.c revision 1.1 1 /* $NetBSD: tlsb.c,v 1.1 1997/03/12 19:20:15 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1997
5 * Matthew Jacob
6 * NASA AMES Research Center.
7 * All rights reserved.
8 *
9 * Based in part upon a prototype version by Jason Thorpe
10 * Copyright (c) 1996 by Jason Thorpe.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice immediately at the beginning of the file, without modification,
17 * this list of conditions, and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 /*
38 * Autoconfiguration and support routines for the TurboLaser System Bus
39 * found on AlphaServer 8200 and 8400 systems.
40 */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/device.h>
45 #include <sys/malloc.h>
46
47 #include <machine/autoconf.h>
48 #include <machine/rpb.h>
49 #include <machine/pte.h>
50
51 #include <alpha/tlsb/tlsbreg.h>
52 #include <alpha/tlsb/tlsbvar.h>
53
54 extern int cputype;
55 int cpu_node_id;
56 extern struct cfdriver cpu_cd;
57
58 #define KV(_addr) ((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr)))
59
60 static int tlsbmatch __P((struct device *, struct cfdata *, void *));
61 static void tlsbattach __P((struct device *, struct device *, void *));
62 struct cfattach tlsb_ca = {
63 sizeof (struct device), tlsbmatch, tlsbattach
64 };
65
66 struct cfdriver tlsb_cd = {
67 NULL, "tlsb", DV_DULL,
68 };
69
70 static int tlsbprint __P((void *, const char *));
71 static int tlsbsubmatch __P((struct device *, struct cfdata *, void *));
72 static char *tlsb_node_type_str __P((u_int32_t));
73
74 static int
75 tlsbprint(aux, cp)
76 void *aux;
77 const char *cp;
78 {
79 struct tlsb_dev_attach_args *tap = aux;
80 printf(" node %d: %s", tap->ta_node,
81 tlsb_node_type_str(tap->ta_dtype));
82 return (UNCONF);
83 }
84
85 static int
86 tlsbsubmatch(parent, cf, aux)
87 struct device *parent;
88 struct cfdata *cf;
89 void *aux;
90 {
91 struct tlsb_dev_attach_args *tap = aux;
92 if (tap->ta_name != tlsb_cd.cd_name)
93 return (0);
94 if ((cf->cf_loc[0] != -1) && (cf->cf_loc[0] != tap->ta_node))
95 return (0);
96 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
97 }
98
99 static int
100 tlsbmatch(parent, cf, aux)
101 struct device *parent;
102 struct cfdata *cf;
103 void *aux;
104 {
105 struct confargs *ca = aux;
106
107 /* Make sure we're looking for a TurboLaser. */
108 if (strcmp(ca->ca_name, tlsb_cd.cd_name) != 0)
109 return (0);
110
111 /*
112 * Only one instance of TurboLaser allowed,
113 * and only available on 21000 processor type
114 * platforms.
115 */
116 if ((cputype != ST_DEC_21000) || (cf->cf_unit != 0))
117 return (0);
118
119 return (1);
120 }
121
122 static void
123 tlsbattach(parent, self, aux)
124 struct device *parent;
125 struct device *self;
126 void *aux;
127 {
128 struct tlsb_dev_attach_args ta;
129 u_int32_t tldev;
130 u_int8_t vid;
131 int node;
132 struct tlsb_cpu_busdep *tcpu;
133 struct cfdriver *cfd = &cpu_cd;
134
135 printf("\n");
136
137 /*
138 * Attempt to find all devices on the bus, including
139 * CPUs, memory modules, and I/O modules.
140 */
141
142 /*
143 * Sigh. I would like to just start off nicely,
144 * but I need to treat I/O modules differently-
145 * The highest priority I/O node has to be in
146 * node #8, and I want to find it *first*, since
147 * it will have the primary disks (most likely)
148 * on it.
149 */
150 for (node = 0; node <= TLSB_NODE_MAX; ++node) {
151 /*
152 * Check for invalid address. This may not really
153 * be necessary, but what the heck...
154 */
155 if (badaddr(TLSB_NODE_REG_ADDR(node, TLDEV), sizeof(u_int32_t)))
156 continue;
157 tldev = TLSB_GET_NODEREG(node, TLDEV);
158 if (tldev == 0) {
159 /* Nothing at this node. */
160 continue;
161 }
162 if (TLDEV_ISIOPORT(tldev))
163 continue; /* not interested right now */
164 ta.ta_name = tlsb_cd.cd_name;
165 ta.ta_node = node;
166 ta.ta_dtype = TLDEV_DTYPE(tldev);
167 ta.ta_swrev = TLDEV_SWREV(tldev);
168 ta.ta_hwrev = TLDEV_HWREV(tldev);
169
170 /*
171 * Deal with hooking CPU instances to TurboLaser nodes.
172 */
173 if (TLDEV_ISCPU(tldev)) {
174 printf("%s node %d: %s", self->dv_xname,
175 node, tlsb_node_type_str(tldev));
176
177 /*
178 * Hook in the first CPU unit.
179 */
180 vid = (TLSB_GET_NODEREG(node, TLVID) &
181 TLVID_VIDA_MASK) >> TLVID_VIDA_SHIFT;
182
183 if ((tcpu = malloc(sizeof(struct tlsb_cpu_busdep),
184 M_DEVBUF, M_NOWAIT)) == NULL)
185 panic("\nno memory for cpu busdep info");
186
187 tcpu->tcpu_vid = vid;
188 tcpu->tcpu_node = node;
189 cpu_node_id = node;
190 printf(", VID %d -> %s", tcpu->tcpu_vid, cfd->cd_name);
191
192 /*
193 * Do 2nd CPU (if available) here.
194 */
195 printf("\n");
196 TLSB_PUT_NODEREG(node, TLCPUMASK, (1<<vid));
197
198 /*
199 * XXX: Check to make sure that INTRMASK has ints
200 * XXX: enabled for this CPU.
201 */
202 }
203 /*
204 * Attach any children nodes, including a CPU's GBus
205 */
206 config_found_sm(self, &ta, tlsbprint, tlsbsubmatch);
207 }
208 /*
209 * *Now* search for I/O nodes (in descending order)
210 */
211 while (--node > 0) {
212 if (badaddr(TLSB_NODE_REG_ADDR(node, TLDEV), sizeof(u_int32_t)))
213 continue;
214 tldev = TLSB_GET_NODEREG(node, TLDEV);
215 if (tldev == 0) {
216 continue;
217 }
218 if (TLDEV_ISIOPORT(tldev)) {
219 ta.ta_name = tlsb_cd.cd_name;
220 ta.ta_node = node;
221 ta.ta_dtype = TLDEV_DTYPE(tldev);
222 ta.ta_swrev = TLDEV_SWREV(tldev);
223 ta.ta_hwrev = TLDEV_HWREV(tldev);
224 config_found_sm(self, &ta, tlsbprint, tlsbsubmatch);
225 }
226 }
227 }
228
229 static char *
230 tlsb_node_type_str(dtype)
231 u_int32_t dtype;
232 {
233 static char tlsb_line[64];
234
235 switch (dtype & TLDEV_DTYPE_MASK) {
236 case TLDEV_DTYPE_KFTHA:
237 return ("KFTHA I/O interface");
238
239 case TLDEV_DTYPE_KFTIA:
240 return ("KFTIA I/O interface");
241
242 case TLDEV_DTYPE_MS7CC:
243 return ("MS7CC Memory Module");
244
245 case TLDEV_DTYPE_SCPU4:
246 return ("Single CPU, 4MB cache");
247
248 case TLDEV_DTYPE_SCPU16:
249 return ("Single CPU, 16MB cache");
250
251 case TLDEV_DTYPE_DCPU4:
252 return ("Dual CPU, 4MB cache");
253
254 case TLDEV_DTYPE_DCPU16:
255 return ("Dual CPU, 16MB cache");
256
257 default:
258 bzero(tlsb_line, sizeof(tlsb_line));
259 sprintf(tlsb_line, "unknown, dtype 0x%x", dtype);
260 return (tlsb_line);
261 }
262 /* NOTREACHED */
263 }
264