tlsb.c revision 1.8 1 /* $NetBSD: tlsb.c,v 1.8 1998/04/15 00:51:00 mjacob 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.8 1998/04/15 00:51:00 mjacob 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 static int
77 tlsbprint(aux, cp)
78 void *aux;
79 const char *cp;
80 {
81 struct tlsb_dev_attach_args *tap = aux;
82 printf(" node %d: %s", tap->ta_node,
83 tlsb_node_type_str(tap->ta_dtype));
84 return (UNCONF);
85 }
86
87 static int
88 tlsbsubmatch(parent, cf, aux)
89 struct device *parent;
90 struct cfdata *cf;
91 void *aux;
92 {
93 struct tlsb_dev_attach_args *tap = aux;
94 if (tap->ta_name != tlsb_cd.cd_name)
95 return (0);
96 if (cf->cf_loc[TLSBCF_NODE] != TLSBCF_NODE_DEFAULT &&
97 cf->cf_loc[TLSBCF_NODE] != tap->ta_node)
98 return (0);
99 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
100 }
101
102 static int
103 tlsbmatch(parent, cf, aux)
104 struct device *parent;
105 struct cfdata *cf;
106 void *aux;
107 {
108 struct confargs *ca = aux;
109
110 /* Make sure we're looking for a TurboLaser. */
111 if (strcmp(ca->ca_name, tlsb_cd.cd_name) != 0)
112 return (0);
113
114 /*
115 * Only one instance of TurboLaser allowed,
116 * and only available on 21000 processor type
117 * platforms.
118 */
119 if ((cputype != ST_DEC_21000) || (cf->cf_unit != 0))
120 return (0);
121
122 return (1);
123 }
124
125 static void
126 tlsbattach(parent, self, aux)
127 struct device *parent;
128 struct device *self;
129 void *aux;
130 {
131 extern struct cfdriver cpu_cd;
132 struct tlsb_dev_attach_args ta;
133 u_int32_t tldev;
134 u_int8_t vid;
135 int node;
136 struct cfdriver *cfd = &cpu_cd;
137
138 printf("\n");
139
140 /*
141 * Attempt to find all devices on the bus, including
142 * CPUs, memory modules, and I/O modules.
143 */
144
145 /*
146 * Sigh. I would like to just start off nicely,
147 * but I need to treat I/O modules differently-
148 * The highest priority I/O node has to be in
149 * node #8, and I want to find it *first*, since
150 * it will have the primary disks (most likely)
151 * on it.
152 */
153 for (node = 0; node <= TLSB_NODE_MAX; ++node) {
154 /*
155 * Check for invalid address. This may not really
156 * be necessary, but what the heck...
157 */
158 if (badaddr(TLSB_NODE_REG_ADDR(node, TLDEV), sizeof(u_int32_t)))
159 continue;
160 tldev = TLSB_GET_NODEREG(node, TLDEV);
161 if (tldev == 0) {
162 /* Nothing at this node. */
163 continue;
164 }
165 if (TLDEV_ISIOPORT(tldev))
166 continue; /* not interested right now */
167 ta.ta_name = tlsb_cd.cd_name;
168 ta.ta_node = node;
169 ta.ta_dtype = TLDEV_DTYPE(tldev);
170 ta.ta_swrev = TLDEV_SWREV(tldev);
171 ta.ta_hwrev = TLDEV_HWREV(tldev);
172
173 /*
174 * Deal with hooking CPU instances to TurboLaser nodes.
175 */
176 if (TLDEV_ISCPU(tldev)) {
177 printf("%s node %d: %s", self->dv_xname,
178 node, tlsb_node_type_str(tldev));
179
180 /*
181 * Hook in the first CPU unit.
182 */
183 vid = (TLSB_GET_NODEREG(node, TLVID) &
184 TLVID_VIDA_MASK) >> TLVID_VIDA_SHIFT;
185 printf(", VID %d -> %s", vid, cfd->cd_name);
186 printf("\n");
187 TLSB_PUT_NODEREG(node, TLCPUMASK, (1<<vid));
188 }
189 /*
190 * Attach any children nodes, including a CPU's GBus
191 */
192 config_found_sm(self, &ta, tlsbprint, tlsbsubmatch);
193 }
194 /*
195 * *Now* search for I/O nodes (in descending order)
196 */
197 while (--node > 0) {
198 if (badaddr(TLSB_NODE_REG_ADDR(node, TLDEV), sizeof(u_int32_t)))
199 continue;
200 tldev = TLSB_GET_NODEREG(node, TLDEV);
201 if (tldev == 0) {
202 continue;
203 }
204 if (TLDEV_ISIOPORT(tldev)) {
205 ta.ta_name = tlsb_cd.cd_name;
206 ta.ta_node = node;
207 ta.ta_dtype = TLDEV_DTYPE(tldev);
208 ta.ta_swrev = TLDEV_SWREV(tldev);
209 ta.ta_hwrev = TLDEV_HWREV(tldev);
210 config_found_sm(self, &ta, tlsbprint, tlsbsubmatch);
211 }
212 }
213 }
214
215 static char *
216 tlsb_node_type_str(dtype)
217 u_int32_t dtype;
218 {
219 static char tlsb_line[64];
220
221 switch (dtype & TLDEV_DTYPE_MASK) {
222 case TLDEV_DTYPE_KFTHA:
223 return ("KFTHA I/O interface");
224
225 case TLDEV_DTYPE_KFTIA:
226 return ("KFTIA I/O interface");
227
228 case TLDEV_DTYPE_MS7CC:
229 return ("MS7CC Memory Module");
230
231 case TLDEV_DTYPE_SCPU4:
232 return ("Single CPU, 4MB cache");
233
234 case TLDEV_DTYPE_SCPU16:
235 return ("Single CPU, 16MB cache");
236
237 case TLDEV_DTYPE_DCPU4:
238 return ("Dual CPU, 4MB cache");
239
240 case TLDEV_DTYPE_DCPU16:
241 return ("Dual CPU, 16MB cache");
242
243 default:
244 bzero(tlsb_line, sizeof(tlsb_line));
245 sprintf(tlsb_line, "unknown, dtype 0x%x", dtype);
246 return (tlsb_line);
247 }
248 /* NOTREACHED */
249 }
250