1 /* $NetBSD: mcbus.c,v 1.20 2008/07/09 21:25:59 joerg 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.20 2008/07/09 21:25:59 joerg 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(device_t, cfdata_t, void *); 67 static void mcbusattach(device_t, device_t, void *); 68 static int mcbusprint(void *, const char *); 69 static const char *mcbus_node_type_str(u_int8_t); 70 71 typedef struct { 72 u_int8_t mcbus_types[MCBUS_MID_MAX]; 73 } mcbus_softc_t; 74 75 CFATTACH_DECL_NEW(mcbus, sizeof (mcbus_softc_t), 76 mcbusmatch, mcbusattach, NULL, NULL); 77 78 /* 79 * Tru64 UNIX (formerly Digital UNIX (formerly DEC OSF/1)) probes for MCPCIAs 80 * in the following order: 81 * 82 * 5, 4, 7, 6 83 * 84 * This is so that the built-in CD-ROM on the internal 53c810 is always 85 * dka500. We probe them in the same order, for consistency. 86 */ 87 const int mcbus_mcpcia_probe_order[] = { 5, 4, 7, 6 }; 88 89 extern void mcpcia_config_cleanup(void); 90 91 static int 92 mcbusprint(void *aux, const char *cp) 93 { 94 struct mcbus_dev_attach_args *tap = aux; 95 aprint_normal(" mid %d: %s", tap->ma_mid, 96 mcbus_node_type_str(tap->ma_type)); 97 return (UNCONF); 98 } 99 100 static int 101 mcbusmatch(device_t parent, cfdata_t cf, void *aux) 102 { 103 struct mainbus_attach_args *ma = aux; 104 105 /* Make sure we're looking for a MCBUS. */ 106 if (strcmp(ma->ma_name, mcbus_cd.cd_name) != 0) 107 return (0); 108 109 /* 110 * Only available on 4100 processor type platforms. 111 */ 112 if (cputype != ST_DEC_4100) 113 return (0); 114 return (1); 115 } 116 117 static void 118 mcbusattach(device_t parent, device_t self, void *aux) 119 { 120 static const char * const bcs[CPU_BCacheMask + 1] = { 121 "No", "1MB", "2MB", "4MB", 122 }; 123 struct mcbus_dev_attach_args ta; 124 mcbus_softc_t *mbp = device_private(self); 125 int i, mid; 126 int locs[MCBUSCF_NLOCS]; 127 128 printf(": %s BCache\n", mcbus_primary.mcbus_valid ? 129 bcs[mcbus_primary.mcbus_bcache] : "Unknown"); 130 131 mbp->mcbus_types[0] = MCBUS_TYPE_RES; 132 for (mid = 1; mid <= MCBUS_MID_MAX; ++mid) 133 mbp->mcbus_types[mid] = MCBUS_TYPE_UNK; 134 135 /* 136 * Find and "configure" memory. 137 */ 138 139 /* 140 * XXX If we ever support more than one MCBUS, we'll 141 * XXX have to probe for them, and map them to unit 142 * XXX numbers. 143 */ 144 ta.ma_gid = MCBUS_GID_FROM_INSTANCE(0); 145 ta.ma_mid = 1; 146 ta.ma_type = MCBUS_TYPE_MEM; 147 mbp->mcbus_types[1] = MCBUS_TYPE_MEM; 148 locs[MCBUSCF_MID] = 1; 149 (void) config_found_sm_loc(self, "mcbus", locs, &ta, 150 mcbusprint, config_stdsubmatch); 151 152 /* 153 * Now find PCI busses. 154 */ 155 for (i = 0; i < MCPCIA_PER_MCBUS; i++) { 156 mid = mcbus_mcpcia_probe_order[i]; 157 /* 158 * XXX If we ever support more than one MCBUS, we'll 159 * XXX have to probe for them, and map them to unit 160 * XXX numbers. 161 */ 162 ta.ma_gid = MCBUS_GID_FROM_INSTANCE(0); 163 ta.ma_mid = mid; 164 ta.ma_type = MCBUS_TYPE_PCI; 165 locs[MCBUSCF_MID] = mid; 166 if (MCPCIA_EXISTS(ta.ma_mid, ta.ma_gid)) 167 (void) config_found_sm_loc(self, "mcbus", locs, &ta, 168 mcbusprint, 169 config_stdsubmatch); 170 } 171 172 #if 0 173 /* 174 * Deal with hooking CPU instances to MCBUS module ids. 175 * 176 * Note that we do this here because it's the read of 177 * stupid MCPCIA WHOAMI register that can get us the 178 * module ID and type of the configuring CPU. 179 */ 180 181 if (mcbus_primary.mcbus_valid) { 182 mid = mcbus_primary.mcbus_cpu_mid; 183 printf("%s mid %d: %s %s\n", device_xname(self), 184 mid, mcbus_node_type_str(MCBUS_TYPE_CPU), 185 bcs[mcbus_primary.mcbus_bcache & 0x7]); 186 /* 187 * XXX If we ever support more than one MCBUS, we'll 188 * XXX have to probe for them, and map them to unit 189 * XXX numbers. 190 */ 191 ta.ma_gid = MCBUS_GID_FROM_INSTANCE(0); 192 ta.ma_mid = mid; 193 ta.ma_type = MCBUS_TYPE_CPU; 194 mbp->mcbus_types[mid] = MCBUS_TYPE_CPU; 195 locs[MCBUSCF_MID] = mid; 196 (void) config_found_sm_loc(self, "mcbus", locs, &ta, 197 mcbusprint, config_stdsubmatch); 198 } 199 #endif 200 201 /* 202 * Now clean up after configuring everything. 203 * 204 * This is an unfortunate layering violation- but 205 * we can't enable interrupts until *all* probing 206 * is done, but the code and knowledge to clean 207 * up after probing and to enable interrupts is 208 * down in the MCPCIA layer. 209 */ 210 mcpcia_config_cleanup(); 211 } 212 213 static const char * 214 mcbus_node_type_str(u_int8_t type) 215 { 216 switch (type) { 217 case MCBUS_TYPE_RES: 218 panic ("RESERVED TYPE IN MCBUS_NODE_TYPE_STR"); 219 break; 220 case MCBUS_TYPE_UNK: 221 panic ("UNKNOWN TYPE IN MCBUS_NODE_TYPE_STR"); 222 break; 223 case MCBUS_TYPE_MEM: 224 return ("Memory"); 225 case MCBUS_TYPE_CPU: 226 return ("CPU"); 227 case MCBUS_TYPE_PCI: 228 return ("PCI Bridge"); 229 default: 230 panic("REALLY UNKNWON (%x) TYPE IN MCBUS_NODE_TYPE_STR", type); 231 break; 232 } 233 } 234