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