1 /* $NetBSD: mcbus.c,v 1.26 2023/06/19 08:40:29 msaitoh 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.26 2023/06/19 08:40:29 msaitoh Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 46 #include <machine/autoconf.h> 47 #include <machine/rpb.h> 48 #include <machine/pte.h> 49 50 #include <alpha/mcbus/mcbusreg.h> 51 #include <alpha/mcbus/mcbusvar.h> 52 53 #include <alpha/pci/mcpciareg.h> 54 55 #include "locators.h" 56 57 #define KV(_addr) ((void *)ALPHA_PHYS_TO_K0SEG((_addr))) 58 #define MCPCIA_EXISTS(mid, gid) \ 59 (!badaddr((void *)KV(MCPCIA_BRIDGE_ADDR(gid, mid)), sizeof (uint32_t))) 60 61 extern struct cfdriver mcbus_cd; 62 63 struct mcbus_cpu_busdep mcbus_primary; 64 65 static int mcbusmatch(device_t, cfdata_t, void *); 66 static void mcbusattach(device_t, device_t, void *); 67 static int mcbusprint(void *, const char *); 68 static const char *mcbus_node_type_str(uint8_t); 69 70 typedef struct { 71 uint8_t mcbus_types[MCBUS_MID_MAX]; 72 } mcbus_softc_t; 73 74 CFATTACH_DECL_NEW(mcbus, sizeof (mcbus_softc_t), 75 mcbusmatch, mcbusattach, NULL, NULL); 76 77 /* 78 * Tru64 UNIX (formerly Digital UNIX (formerly DEC OSF/1)) probes for MCPCIAs 79 * in the following order: 80 * 81 * 5, 4, 7, 6 82 * 83 * This is so that the built-in CD-ROM on the internal 53c810 is always 84 * dka500. We probe them in the same order, for consistency. 85 */ 86 const int mcbus_mcpcia_probe_order[] = { 5, 4, 7, 6 }; 87 88 extern void mcpcia_config_cleanup(void); 89 90 static int 91 mcbusprint(void *aux, const char *cp) 92 { 93 struct mcbus_dev_attach_args *tap = aux; 94 aprint_normal(" mid %d: %s", tap->ma_mid, 95 mcbus_node_type_str(tap->ma_type)); 96 return (UNCONF); 97 } 98 99 static int 100 mcbusmatch(device_t parent, cfdata_t cf, void *aux) 101 { 102 struct mainbus_attach_args *ma = aux; 103 104 /* Make sure we're looking for a MCBUS. */ 105 if (strcmp(ma->ma_name, mcbus_cd.cd_name) != 0) 106 return (0); 107 108 /* 109 * Only available on 4100 processor type platforms. 110 */ 111 if (cputype != ST_DEC_4100) 112 return (0); 113 return (1); 114 } 115 116 static void 117 mcbusattach(device_t parent, device_t self, void *aux) 118 { 119 static const char * const bcs[CPU_BCacheMask + 1] = { 120 "No", "1MB", "2MB", "4MB", 121 }; 122 struct mcbus_dev_attach_args ta; 123 mcbus_softc_t *mbp = device_private(self); 124 int i, mid; 125 int locs[MCBUSCF_NLOCS]; 126 127 printf(": %s BCache\n", mcbus_primary.mcbus_valid ? 128 bcs[mcbus_primary.mcbus_bcache] : "Unknown"); 129 130 mbp->mcbus_types[0] = MCBUS_TYPE_RES; 131 for (mid = 1; mid < MCBUS_MID_MAX; ++mid) 132 mbp->mcbus_types[mid] = MCBUS_TYPE_UNK; 133 134 /* 135 * Find and "configure" memory. 136 */ 137 138 /* 139 * XXX If we ever support more than one MCBUS, we'll 140 * XXX have to probe for them, and map them to unit 141 * XXX numbers. 142 */ 143 ta.ma_gid = MCBUS_GID_FROM_INSTANCE(0); 144 ta.ma_mid = 1; 145 ta.ma_type = MCBUS_TYPE_MEM; 146 mbp->mcbus_types[1] = MCBUS_TYPE_MEM; 147 locs[MCBUSCF_MID] = 1; 148 config_found(self, &ta, mcbusprint, 149 CFARGS(.submatch = config_stdsubmatch, 150 .locators = locs)); 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 config_found(self, &ta, mcbusprint, 168 CFARGS(.submatch = config_stdsubmatch, 169 .locators = locs)); 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 config_found(self, &ta, mcbusprint, 197 CFARGS(.submatch = config_stdsubmatch, 198 .locators = locs)); 199 } 200 #endif 201 202 /* 203 * Now clean up after configuring everything. 204 * 205 * This is an unfortunate layering violation- but 206 * we can't enable interrupts until *all* probing 207 * is done, but the code and knowledge to clean 208 * up after probing and to enable interrupts is 209 * down in the MCPCIA layer. 210 */ 211 mcpcia_config_cleanup(); 212 } 213 214 static const char * 215 mcbus_node_type_str(uint8_t type) 216 { 217 switch (type) { 218 case MCBUS_TYPE_RES: 219 panic ("RESERVED TYPE IN MCBUS_NODE_TYPE_STR"); 220 break; 221 case MCBUS_TYPE_UNK: 222 panic ("UNKNOWN TYPE IN MCBUS_NODE_TYPE_STR"); 223 break; 224 case MCBUS_TYPE_MEM: 225 return ("Memory"); 226 case MCBUS_TYPE_CPU: 227 return ("CPU"); 228 case MCBUS_TYPE_PCI: 229 return ("PCI Bridge"); 230 default: 231 panic("REALLY UNKNOWN (%x) TYPE IN MCBUS_NODE_TYPE_STR", type); 232 break; 233 } 234 } 235