1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * %sccs.include.redist.c% 15 * 16 * @(#)cpu.c 8.3 (Berkeley) 09/30/93 17 * 18 * from: $Header: cpu.c,v 1.16.1.1 93/09/30 22:38:50 torek Exp $ (LBL) 19 */ 20 21 #include <sys/param.h> 22 #include <sys/device.h> 23 24 #include <machine/autoconf.h> 25 #include <machine/cpu.h> 26 #include <machine/reg.h> 27 #include <machine/trap.h> 28 29 #include <sparc/sparc/cache.h> 30 31 /* This is declared here so that you must include a CPU for the cache code. */ 32 struct cacheinfo cacheinfo; 33 34 /* The following are used externally (sysctl_hw). */ 35 char machine[] = "sparc"; 36 char cpu_model[100]; 37 38 /* The CPU configuration driver. */ 39 static void cpu_attach __P((struct device *, struct device *, void *)); 40 41 struct cfdriver cpucd = 42 { NULL, "cpu", matchbyname, cpu_attach, DV_CPU, sizeof(struct device) }; 43 44 static char *psrtoname __P((int, int, int, char *)); 45 static char *fsrtoname __P((int, int, int, char *)); 46 47 #define IU_IMPL(psr) ((u_int)(psr) >> 28) 48 #define IU_VERS(psr) (((psr) >> 24) & 0xf) 49 50 #ifdef notdef 51 /* 52 * IU implementations are parceled out to vendors (with some slight 53 * glitches). Printing these is cute but takes too much space. 54 */ 55 static char *iu_vendor[16] = { 56 "Fujitsu", /* and also LSI Logic */ 57 "ROSS", /* ROSS (ex-Cypress) */ 58 "BIT", 59 "LSIL", /* LSI Logic finally got their own */ 60 "TI", /* Texas Instruments */ 61 "Matsushita", 62 "Philips", 63 "Harvest", /* Harvest VLSI Design Center */ 64 "SPEC", /* Systems and Processes Engineering Corporation */ 65 "Weitek", 66 "vendor#10", 67 "vendor#11", 68 "vendor#12", 69 "vendor#13", 70 "vendor#14", 71 "vendor#15" 72 }; 73 #endif 74 75 /* 76 * Attach the CPU. 77 * Discover interesting goop about the virtual address cache 78 * (slightly funny place to do it, but this is where it is to be found). 79 */ 80 static void 81 cpu_attach(parent, dev, aux) 82 struct device *parent; 83 struct device *dev; 84 void *aux; 85 { 86 register int node, clk, i, l; 87 register int impl, vers, fver; 88 register char *fpuname; 89 struct fpstate fpstate; 90 char iubuf[40], fpbuf[40]; 91 92 /* 93 * Get the FSR and clear any exceptions. If we do not unload 94 * the queue here and it is left over from a previous crash, we 95 * will panic in the first loadfpstate(), due to a sequence error, 96 * so we need to dump the whole state anyway. 97 * 98 * If there is no FPU, trap.c will advance over all the stores, 99 * so we initialize fs_fsr here. 100 */ 101 fpstate.fs_fsr = 7 << FSR_VER_SHIFT; /* 7 is reserved for "none" */ 102 savefpstate(&fpstate); 103 fver = (fpstate.fs_fsr >> FSR_VER_SHIFT) & (FSR_VER >> FSR_VER_SHIFT); 104 i = getpsr(); 105 impl = IU_IMPL(i); 106 vers = IU_VERS(i); 107 if (fver != 7) { 108 foundfpu = 1; 109 fpuname = fsrtoname(impl, vers, fver, fpbuf); 110 } else 111 fpuname = "no"; 112 113 /* tell them what we have */ 114 node = ((struct romaux *)aux)->ra_node; 115 clk = getpropint(node, "clock-frequency", 0); 116 sprintf(cpu_model, "%s (%s @ %s MHz, %s FPU)", 117 getpropstring(node, "name"), 118 psrtoname(impl, vers, fver, iubuf), clockfreq(clk), fpuname); 119 printf(": %s\n", cpu_model); 120 121 /* 122 * Fill in the cache info. Note, vac-hwflush is spelled 123 * with an underscore on 4/75s. 124 */ 125 cacheinfo.c_totalsize = getpropint(node, "vac-size", 65536); 126 cacheinfo.c_hwflush = getpropint(node, "vac_hwflush", 0) | 127 getpropint(node, "vac-hwflush", 0); 128 cacheinfo.c_linesize = l = getpropint(node, "vac-linesize", 16); 129 for (i = 0; (1 << i) < l; i++) 130 /* void */; 131 if ((1 << i) != l) 132 panic("bad cache line size %d", l); 133 cacheinfo.c_l2linesize = i; 134 vactype = VAC_WRITETHROUGH; 135 136 /* 137 * Machines with "buserr-type" 1 have a bug in the cache 138 * chip that affects traps. (I wish I knew more about this 139 * mysterious buserr-type variable....) 140 */ 141 if (getpropint(node, "buserr-type", 0) == 1) { 142 kvm_uncache((caddr_t)trapbase, 1); 143 printf("%s: cache chip bug; trap page uncached\n", 144 dev->dv_xname); 145 } 146 147 printf("%s: %d byte write-through, %d bytes/line, %cw flush ", 148 dev->dv_xname, cacheinfo.c_totalsize, l, 149 cacheinfo.c_hwflush ? 'h' : 's'); 150 cache_enable(); 151 } 152 153 /* 154 * The following tables convert <IU impl, IU version, FPU version> triples 155 * into names for the CPU and FPU chip. In most cases we do not need to 156 * inspect the FPU version to name the IU chip, but there is one exception 157 * (for Tsunami), and this makes the tables the same. 158 * 159 * The table contents (and much of the structure here) are from Guy Harris. 160 * 161 * NOTE: we have Sun-4m cpu types here, even though this only runs on the 162 * Sun-4c (yet)... 163 */ 164 struct info { 165 u_char valid; 166 u_char iu_impl; 167 u_char iu_vers; 168 u_char fpu_vers; 169 char *name; 170 }; 171 172 #define ANY 0xff /* match any FPU version (or, later, IU version) */ 173 174 static struct info iu_types[] = { 175 { 1, 0x0, 0x0, ANY, "MB86900/1A or L64801" }, 176 { 1, 0x1, 0x0, ANY, "RT601 or L64811 v1" }, 177 { 1, 0x1, 0x1, ANY, "RT601 or L64811 v2" }, 178 { 1, 0x1, 0x3, ANY, "RT611" }, 179 { 1, 0x1, 0xf, ANY, "RT620" }, 180 { 1, 0x2, 0x0, ANY, "B5010" }, 181 { 1, 0x4, 0x0, 0, "TMS390Z50 v0" }, 182 { 1, 0x4, 0x1, 0, "TMS390Z50 v1" }, 183 { 1, 0x4, 0x1, 4, "TMS390S10" }, 184 { 1, 0x5, 0x0, ANY, "MN10501" }, 185 { 1, 0x9, 0x0, ANY, "W8601/8701 or MB86903" }, 186 { 0 } 187 }; 188 189 static char * 190 psrtoname(impl, vers, fver, buf) 191 register int impl, vers, fver; 192 char *buf; 193 { 194 register struct info *p; 195 196 for (p = iu_types; p->valid; p++) 197 if (p->iu_impl == impl && p->iu_vers == vers && 198 (p->fpu_vers == fver || p->fpu_vers == ANY)) 199 return (p->name); 200 201 /* Not found. */ 202 sprintf(buf, "IU impl 0x%x vers 0x%x", impl, vers); 203 return (buf); 204 } 205 206 /* NB: table order matters here; specific numbers must appear before ANY. */ 207 static struct info fpu_types[] = { 208 /* 209 * Vendor 0, IU Fujitsu0. 210 */ 211 { 1, 0x0, ANY, 0, "MB86910 or WTL1164/5" }, 212 { 1, 0x0, ANY, 1, "MB86911 or WTL1164/5" }, 213 { 1, 0x0, ANY, 2, "L64802 or ACT8847" }, 214 { 1, 0x0, ANY, 3, "WTL3170/2" }, 215 { 1, 0x0, ANY, 4, "L64804" }, 216 217 /* 218 * Vendor 1, IU ROSS0/1. 219 */ 220 { 1, 0x1, ANY, 0, "L64812 or ACT8847" }, 221 { 1, 0x1, ANY, 1, "L64814" }, 222 { 1, 0x1, ANY, 2, "TMS390C602A" }, 223 { 1, 0x1, ANY, 3, "RT602 or WTL3171" }, 224 225 /* 226 * Vendor 2, IU BIT0. 227 */ 228 { 1, 0x2, ANY, 0, "B5010 or B5110/20 or B5210" }, 229 230 /* 231 * Vendor 4, Texas Instruments. 232 */ 233 { 1, 0x4, ANY, 0, "on-chip" }, /* Viking */ 234 { 1, 0x4, ANY, 4, "on-chip" }, /* Tsunami */ 235 236 /* 237 * Vendor 5, IU Matsushita0. 238 */ 239 { 1, 0x5, ANY, 0, "on-chip" }, 240 241 /* 242 * Vendor 9, Weitek. 243 */ 244 { 1, 0x9, ANY, 3, "on-chip" }, 245 246 { 0 } 247 }; 248 249 static char * 250 fsrtoname(impl, vers, fver, buf) 251 register int impl, vers, fver; 252 char *buf; 253 { 254 register struct info *p; 255 256 for (p = fpu_types; p->valid; p++) 257 if (p->iu_impl == impl && 258 (p->iu_vers == vers || p->iu_vers == ANY) & 259 p->fpu_vers == fver) 260 return (p->name); 261 sprintf(buf, "version %x", fver); 262 return (buf); 263 } 264