1 /* $NetBSD: mcbus.c,v 1.19 2007/03/04 05:59:11 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1998 by Matthew Jacob 5 * NASA AMES Research Center. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice immediately at the beginning of the file, without modification, 13 * this list of conditions, and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Autoconfiguration routines for the MCBUS system 35 * bus found on AlphaServer 4100 systems. 36 */ 37 38 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 39 40 __KERNEL_RCSID(0, "$NetBSD: mcbus.c,v 1.19 2007/03/04 05:59:11 christos Exp $"); 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/mcbus/mcbusreg.h> 52 #include <alpha/mcbus/mcbusvar.h> 53 54 #include <alpha/pci/mcpciareg.h> 55 56 #include "locators.h" 57 58 #define KV(_addr) ((void *)ALPHA_PHYS_TO_K0SEG((_addr))) 59 #define MCPCIA_EXISTS(mid, gid) \ 60 (!badaddr((void *)KV(MCPCIA_BRIDGE_ADDR(gid, mid)), sizeof (u_int32_t))) 61 62 extern struct cfdriver mcbus_cd; 63 64 struct mcbus_cpu_busdep mcbus_primary; 65 66 static int mcbusmatch __P((struct device *, struct cfdata *, void *)); 67 static void mcbusattach __P((struct device *, struct device *, void *)); 68 static int mcbusprint __P((void *, const char *)); 69 static const char *mcbus_node_type_str __P((u_int8_t)); 70 71 typedef struct { 72 struct device mcbus_dev; 73 u_int8_t mcbus_types[MCBUS_MID_MAX]; 74 } mcbus_softc_t; 75 76 CFATTACH_DECL(mcbus, sizeof (mcbus_softc_t), 77 mcbusmatch, mcbusattach, NULL, NULL); 78 79 /* 80 * Tru64 UNIX (formerly Digital UNIX (formerly DEC OSF/1)) probes for MCPCIAs 81 * in the following order: 82 * 83 * 5, 4, 7, 6 84 * 85 * This is so that the built-in CD-ROM on the internal 53c810 is always 86 * dka500. We probe them in the same order, for consistency. 87 */ 88 const int mcbus_mcpcia_probe_order[] = { 5, 4, 7, 6 }; 89 90 extern void mcpcia_config_cleanup __P((void)); 91 92 static int 93 mcbusprint(aux, cp) 94 void *aux; 95 const char *cp; 96 { 97 struct mcbus_dev_attach_args *tap = aux; 98 aprint_normal(" mid %d: %s", tap->ma_mid, 99 mcbus_node_type_str(tap->ma_type)); 100 return (UNCONF); 101 } 102 103 static int 104 mcbusmatch(parent, cf, aux) 105 struct device *parent; 106 struct cfdata *cf; 107 void *aux; 108 { 109 struct mainbus_attach_args *ma = aux; 110 111 /* Make sure we're looking for a MCBUS. */ 112 if (strcmp(ma->ma_name, mcbus_cd.cd_name) != 0) 113 return (0); 114 115 /* 116 * Only available on 4100 processor type platforms. 117 */ 118 if (cputype != ST_DEC_4100) 119 return (0); 120 return (1); 121 } 122 123 static void 124 mcbusattach(parent, self, aux) 125 struct device *parent; 126 struct device *self; 127 void *aux; 128 { 129 static const char * const bcs[CPU_BCacheMask + 1] = { 130 "No", "1MB", "2MB", "4MB", 131 }; 132 struct mcbus_dev_attach_args ta; 133 mcbus_softc_t *mbp = (mcbus_softc_t *)self; 134 int i, mid; 135 int locs[MCBUSCF_NLOCS]; 136 137 printf(": %s BCache\n", mcbus_primary.mcbus_valid ? 138 bcs[mcbus_primary.mcbus_bcache] : "Unknown"); 139 140 mbp->mcbus_types[0] = MCBUS_TYPE_RES; 141 for (mid = 1; mid <= MCBUS_MID_MAX; ++mid) 142 mbp->mcbus_types[mid] = MCBUS_TYPE_UNK; 143 144 /* 145 * Find and "configure" memory. 146 */ 147 148 /* 149 * XXX If we ever support more than one MCBUS, we'll 150 * XXX have to probe for them, and map them to unit 151 * XXX numbers. 152 */ 153 ta.ma_gid = MCBUS_GID_FROM_INSTANCE(0); 154 ta.ma_mid = 1; 155 ta.ma_type = MCBUS_TYPE_MEM; 156 mbp->mcbus_types[1] = MCBUS_TYPE_MEM; 157 locs[MCBUSCF_MID] = 1; 158 (void) config_found_sm_loc(self, "mcbus", locs, &ta, 159 mcbusprint, config_stdsubmatch); 160 161 /* 162 * Now find PCI busses. 163 */ 164 for (i = 0; i < MCPCIA_PER_MCBUS; i++) { 165 mid = mcbus_mcpcia_probe_order[i]; 166 /* 167 * XXX If we ever support more than one MCBUS, we'll 168 * XXX have to probe for them, and map them to unit 169 * XXX numbers. 170 */ 171 ta.ma_gid = MCBUS_GID_FROM_INSTANCE(0); 172 ta.ma_mid = mid; 173 ta.ma_type = MCBUS_TYPE_PCI; 174 locs[MCBUSCF_MID] = mid; 175 if (MCPCIA_EXISTS(ta.ma_mid, ta.ma_gid)) 176 (void) config_found_sm_loc(self, "mcbus", locs, &ta, 177 mcbusprint, 178 config_stdsubmatch); 179 } 180 181 #if 0 182 /* 183 * Deal with hooking CPU instances to MCBUS module ids. 184 * 185 * Note that we do this here because it's the read of 186 * stupid MCPCIA WHOAMI register that can get us the 187 * module ID and type of the configuring CPU. 188 */ 189 190 if (mcbus_primary.mcbus_valid) { 191 mid = mcbus_primary.mcbus_cpu_mid; 192 printf("%s mid %d: %s %s\n", self->dv_xname, 193 mid, mcbus_node_type_str(MCBUS_TYPE_CPU), 194 bcs[mcbus_primary.mcbus_bcache & 0x7]); 195 /* 196 * XXX If we ever support more than one MCBUS, we'll 197 * XXX have to probe for them, and map them to unit 198 * XXX numbers. 199 */ 200 ta.ma_gid = MCBUS_GID_FROM_INSTANCE(0); 201 ta.ma_mid = mid; 202 ta.ma_type = MCBUS_TYPE_CPU; 203 mbp->mcbus_types[mid] = MCBUS_TYPE_CPU; 204 locs[MCBUSCF_MID] = mid; 205 (void) config_found_sm_loc(self, "mcbus", locs, &ta, 206 mcbusprint, config_stdsubmatch); 207 } 208 #endif 209 210 /* 211 * Now clean up after configuring everything. 212 * 213 * This is an unfortunate layering violation- but 214 * we can't enable interrupts until *all* probing 215 * is done, but the code and knowledge to clean 216 * up after probing and to enable interrupts is 217 * down in the MCPCIA layer. 218 */ 219 mcpcia_config_cleanup(); 220 } 221 222 static const char * 223 mcbus_node_type_str(type) 224 u_int8_t type; 225 { 226 switch (type) { 227 case MCBUS_TYPE_RES: 228 panic ("RESERVED TYPE IN MCBUS_NODE_TYPE_STR"); 229 break; 230 case MCBUS_TYPE_UNK: 231 panic ("UNKNOWN TYPE IN MCBUS_NODE_TYPE_STR"); 232 break; 233 case MCBUS_TYPE_MEM: 234 return ("Memory"); 235 case MCBUS_TYPE_CPU: 236 return ("CPU"); 237 case MCBUS_TYPE_PCI: 238 return ("PCI Bridge"); 239 default: 240 panic("REALLY UNKNWON (%x) TYPE IN MCBUS_NODE_TYPE_STR", type); 241 break; 242 } 243 } 244