initcpu.c revision 26985
1/* 2 * Copyright (c) KATO Takenori, 1997. 3 * 4 * All rights reserved. Unpublished rights reserved under the copyright 5 * laws of Japan. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer as 13 * the first lines of this file unmodified. 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 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * $Id: initcpu.c,v 1.5 1997/05/31 08:45:24 kato Exp $ 30 */ 31 32#include "opt_cpu.h" 33 34#include <sys/param.h> 35#include <sys/kernel.h> 36#include <sys/systm.h> 37 38#include <machine/cpu.h> 39#include <machine/cputypes.h> 40#include <machine/md_var.h> 41#include <machine/specialreg.h> 42 43void initializecpu(void); 44#ifdef I486_CPU 45static void init_5x86(void); 46static void init_bluelightning(void); 47static void init_486dlc(void); 48static void init_cy486dx(void); 49#ifdef CPU_I486_ON_386 50static void init_i486_on_386(void); 51#endif 52static void init_6x86(void); 53#endif /* I486_CPU */ 54 55#ifdef I586_CPU 56static void init_6x86MX(void); 57#endif 58 59#ifdef I486_CPU 60/* 61 * IBM Blue Lightning 62 */ 63static void 64init_bluelightning(void) 65{ 66 u_long eflags; 67 68#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE) 69 need_post_dma_flush = 1; 70#endif 71 72 eflags = read_eflags(); 73 disable_intr(); 74 75 load_cr0(rcr0() | CR0_CD | CR0_NW); 76 invd(); 77 78#ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE 79 wrmsr(0x1000, 0x9c92LL); /* FP operand can be cacheable on Cyrix FPU */ 80#else 81 wrmsr(0x1000, 0x1c92LL); /* Intel FPU */ 82#endif 83 /* Enables 13MB and 0-640KB cache. */ 84 wrmsr(0x1001, (0xd0LL << 32) | 0x3ff); 85#ifdef CPU_BLUELIGHTNING_3X 86 wrmsr(0x1002, 0x04000000LL); /* Enables triple-clock mode. */ 87#else 88 wrmsr(0x1002, 0x03000000LL); /* Enables double-clock mode. */ 89#endif 90 91 /* Enable caching in CR0. */ 92 load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ 93 invd(); 94 write_eflags(eflags); 95} 96 97/* 98 * Cyrix 486SLC/DLC/SR/DR series 99 */ 100static void 101init_486dlc(void) 102{ 103 u_long eflags; 104 u_char ccr0; 105 106 eflags = read_eflags(); 107 disable_intr(); 108 invd(); 109 110 ccr0 = read_cyrix_reg(CCR0); 111#ifndef CYRIX_CACHE_WORKS 112 ccr0 |= CCR0_NC1 | CCR0_BARB; 113 write_cyrix_reg(CCR0, ccr0); 114 invd(); 115#else 116 ccr0 &= ~CCR0_NC0; 117#ifndef CYRIX_CACHE_REALLY_WORKS 118 ccr0 |= CCR0_NC1 | CCR0_BARB; 119#else 120 ccr0 |= CCR0_NC1; 121#endif 122#ifdef CPU_DIRECT_MAPPED_CACHE 123 ccr0 |= CCR0_CO; /* Direct mapped mode. */ 124#endif 125 write_cyrix_reg(CCR0, ccr0); 126 127 /* Clear non-cacheable region. */ 128 write_cyrix_reg(NCR1+2, NCR_SIZE_0K); 129 write_cyrix_reg(NCR2+2, NCR_SIZE_0K); 130 write_cyrix_reg(NCR3+2, NCR_SIZE_0K); 131 write_cyrix_reg(NCR4+2, NCR_SIZE_0K); 132 133 write_cyrix_reg(0, 0); /* dummy write */ 134 135 /* Enable caching in CR0. */ 136 load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ 137 invd(); 138#endif /* !CYRIX_CACHE_WORKS */ 139 write_eflags(eflags); 140} 141 142 143/* 144 * Cyrix 486S/DX series 145 */ 146static void 147init_cy486dx(void) 148{ 149 u_long eflags; 150 u_char ccr2; 151 152 eflags = read_eflags(); 153 disable_intr(); 154 invd(); 155 156 ccr2 = read_cyrix_reg(CCR2); 157#ifdef SUSP_HLT 158 ccr2 |= CCR2_SUSP_HTL; 159#endif 160 write_cyrix_reg(CCR2, ccr2); 161 write_eflags(eflags); 162} 163 164 165/* 166 * Cyrix 5x86 167 */ 168static void 169init_5x86(void) 170{ 171 u_long eflags; 172 u_char ccr2, ccr3, ccr4, pcr0; 173 174 eflags = read_eflags(); 175 disable_intr(); 176 177 load_cr0(rcr0() | CR0_CD | CR0_NW); 178 wbinvd(); 179 180 (void)read_cyrix_reg(CCR3); /* dummy */ 181 182 /* Initialize CCR2. */ 183 ccr2 = read_cyrix_reg(CCR2); 184 ccr2 |= CCR2_WB; 185#ifdef CPU_SUSP_HLT 186 ccr2 |= CCR2_SUSP_HLT; 187#else 188 ccr2 &= ~CCR2_SUSP_HLT; 189#endif 190 ccr2 |= CCR2_WT1; 191 write_cyrix_reg(CCR2, ccr2); 192 193 /* Initialize CCR4. */ 194 ccr3 = read_cyrix_reg(CCR3); 195 write_cyrix_reg(CCR3, CCR3_MAPEN0); 196 197 ccr4 = read_cyrix_reg(CCR4); 198 ccr4 |= CCR4_DTE; 199 ccr4 |= CCR4_MEM; 200#ifdef CPU_FASTER_5X86_FPU 201 ccr4 |= CCR4_FASTFPE; 202#else 203 ccr4 &= ~CCR4_FASTFPE; 204#endif 205 ccr4 &= ~CCR4_IOMASK; 206 /******************************************************************** 207 * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time 208 * should be 0 for errata fix. 209 ********************************************************************/ 210#ifdef CPU_IORT 211 ccr4 |= CPU_IORT & CCR4_IOMASK; 212#endif 213 write_cyrix_reg(CCR4, ccr4); 214 215 /* Initialize PCR0. */ 216 /**************************************************************** 217 * WARNING: RSTK_EN and LOOP_EN could make your system unstable. 218 * BTB_EN might make your system unstable. 219 ****************************************************************/ 220 pcr0 = read_cyrix_reg(PCR0); 221#ifdef CPU_RSTK_EN 222 pcr0 |= PCR0_RSTK; 223#else 224 pcr0 &= ~PCR0_RSTK; 225#endif 226#ifdef CPU_BTB_EN 227 pcr0 |= PCR0_BTB; 228#else 229 pcr0 &= ~PCR0_BTB; 230#endif 231#ifdef CPU_LOOP_EN 232 pcr0 |= PCR0_LOOP; 233#else 234 pcr0 &= ~PCR0_LOOP; 235#endif 236 237 /**************************************************************** 238 * WARNING: if you use a memory mapped I/O device, don't use 239 * DISABLE_5X86_LSSER option, which may reorder memory mapped 240 * I/O access. 241 * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER. 242 ****************************************************************/ 243#ifdef CPU_DISABLE_5X86_LSSER 244 pcr0 &= ~PCR0_LSSER; 245#else 246 pcr0 |= PCR0_LSSER; 247#endif 248 write_cyrix_reg(PCR0, pcr0); 249 250 /* Restore CCR3. */ 251 write_cyrix_reg(CCR3, ccr3); 252 253 (void)read_cyrix_reg(0x80); /* dummy */ 254 255 /* Unlock NW bit in CR0. */ 256 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW); 257 load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0, NW = 1 */ 258 /* Lock NW bit in CR0. */ 259 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW); 260 261 write_eflags(eflags); 262} 263 264#ifdef CPU_I486_ON_386 265/* 266 * There are i486 based upgrade products for i386 machines. 267 * In this case, BIOS doesn't enables CPU cache. 268 */ 269void 270init_i486_on_386(void) 271{ 272 u_long eflags; 273 274#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE) 275 need_post_dma_flush = 1; 276#endif 277 278 eflags = read_eflags(); 279 disable_intr(); 280 281 load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0, NW = 0 */ 282 283 write_eflags(eflags); 284} 285#endif 286 287/* 288 * Cyrix 6x86 289 * 290 * XXX - What should I do here? Please let me know. 291 */ 292static void 293init_6x86(void) 294{ 295 u_long eflags; 296 u_char ccr3, ccr4; 297 298 eflags = read_eflags(); 299 disable_intr(); 300 301 load_cr0(rcr0() | CR0_CD | CR0_NW); 302 wbinvd(); 303 304 /* Initialize CCR0. */ 305 write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1); 306 307 /* Initialize CCR2. */ 308#ifdef CPU_SUSP_HLT 309 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT); 310#else 311 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT); 312#endif 313 314 ccr3 = read_cyrix_reg(CCR3); 315 write_cyrix_reg(CCR3, CCR3_MAPEN0); 316 317 /* Initialize CCR4. */ 318 ccr4 = read_cyrix_reg(CCR4); 319 ccr4 |= CCR4_DTE; 320 ccr4 &= ~CCR4_IOMASK; 321#ifdef CPU_IORT 322 write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK)); 323#else 324 write_cyrix_reg(CCR4, ccr4 | 7); 325#endif 326 327 /* Restore CCR3. */ 328 write_cyrix_reg(CCR3, ccr3); 329 330 /* Unlock NW bit in CR0. */ 331 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW); 332 333 /* 334 * Earlier revision of the 6x86 CPU could crash the system if 335 * L1 cache is in write-back mode. 336 */ 337 if ((cyrix_did & 0xff00) > 0x1600) 338 load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ 339 else { 340 /* Revision 2.6 and lower. */ 341#ifdef CYRIX_CACHE_REALLY_WORKS 342 load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ 343#else 344 load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0 and NW = 1 */ 345#endif 346 } 347 348 /* Lock NW bit in CR0. */ 349 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW); 350 351 write_eflags(eflags); 352} 353#endif /* I486_CPU */ 354 355#ifdef I586_CPU 356/* 357 * Cyrix 6x86MX (code-named M2) 358 * 359 * XXX - What should I do here? Please let me know. 360 */ 361static void 362init_6x86MX(void) 363{ 364 u_long eflags; 365 u_char ccr3, ccr4; 366 367 eflags = read_eflags(); 368 disable_intr(); 369 370 load_cr0(rcr0() | CR0_CD | CR0_NW); 371 wbinvd(); 372 373 /* Initialize CCR0. */ 374 write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1); 375 376 /* Initialize CCR2. */ 377#ifdef CPU_SUSP_HLT 378 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT); 379#else 380 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT); 381#endif 382 383 ccr3 = read_cyrix_reg(CCR3); 384 write_cyrix_reg(CCR3, CCR3_MAPEN0); 385 386 /* Initialize CCR4. */ 387 ccr4 = read_cyrix_reg(CCR4); 388 ccr4 &= ~CCR4_IOMASK; 389#ifdef CPU_IORT 390 write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK)); 391#else 392 write_cyrix_reg(CCR4, ccr4 | 7); 393#endif 394 395 /* Restore CCR3. */ 396 write_cyrix_reg(CCR3, ccr3); 397 398 /* Unlock NW bit in CR0. */ 399 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW); 400 401 load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ 402 403 /* Lock NW bit in CR0. */ 404 write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW); 405 406 write_eflags(eflags); 407} 408#endif /* I586_CPU */ 409 410void 411initializecpu(void) 412{ 413 414 switch (cpu) { 415#ifdef I486_CPU 416 case CPU_BLUE: 417 init_bluelightning(); 418 break; 419 case CPU_486DLC: 420 init_486dlc(); 421 break; 422 case CPU_CY486DX: 423 init_cy486dx(); 424 break; 425 case CPU_M1SC: 426 init_5x86(); 427 break; 428#ifdef CPU_I486_ON_386 429 case CPU_486: 430 init_i486_on_386(); 431 break; 432#endif 433 case CPU_M1: 434 init_6x86(); 435 break; 436#endif /* I486_CPU */ 437#ifdef I586_CPU 438 case CPU_M2: 439 init_6x86MX(); 440 break; 441#endif 442 default: 443 break; 444 } 445 446#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE) 447 /* 448 * OS should flush L1 cahce by itself because no PC-98 supports 449 * non-Intel CPUs. Use wbinvd instruction before DMA transfer 450 * when need_pre_dma_flush = 1, use invd instruction after DMA 451 * transfer when need_post_dma_flush = 1. If your CPU upgrade 452 * product support hardware cache control, you can add 453 * UPGRADE_CPU_HW_CACHE option in your kernel configuration file. 454 * This option elminate unneeded cache flush instruction. 455 */ 456 if (strcmp(cpu_vendor, "CyrixInstead") == 0) { 457 switch (cpu) { 458#ifdef I486_CPU 459 case CPU_486DLC: 460 need_post_dma_flush = 1; 461 break; 462 case CPU_M1SC: 463 need_pre_dma_flush = 1; 464 break; 465#endif 466 default: 467 break; 468 } 469 } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { 470 switch (cpu_id & 0xFF0) { 471 case 0x470: /* Enhanced Am486DX2 WB */ 472 case 0x490: /* Enhanced Am486DX4 WB */ 473 case 0x4F0: /* Am5x86 WB */ 474 need_pre_dma_flush = 1; 475 break; 476 } 477 } else if (strcmp(cpu_vendor, "IBM") == 0) { 478 need_post_dma_flush = 1; 479 } else { 480#ifdef CPU_I486_ON_386 481 need_pre_dma_flush = 1; 482#endif 483 } 484#endif /* PC98 && !UPGRADE_CPU_HW_CACHE */ 485} 486 487#include "opt_ddb.h" 488#ifdef DDB 489#include <ddb/ddb.h> 490 491DB_SHOW_COMMAND(cyrixreg, cyrixreg) 492{ 493 u_long eflags; 494 u_int cr0; 495 u_char ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, pcr0; 496 497 cr0 = rcr0(); 498 if (strcmp(cpu_vendor,"CyrixInstead") == 0) { 499 eflags = read_eflags(); 500 disable_intr(); 501 502 503 if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) { 504 ccr0 = read_cyrix_reg(CCR0); 505 } 506 ccr1 = read_cyrix_reg(CCR1); 507 ccr2 = read_cyrix_reg(CCR2); 508 ccr3 = read_cyrix_reg(CCR3); 509 if ((cpu == CPU_M1SC) || (cpu == CPU_M1)) { 510 write_cyrix_reg(CCR3, CCR3_MAPEN0); 511 ccr4 = read_cyrix_reg(CCR4); 512 if (cpu == CPU_M1) 513 ccr5 = read_cyrix_reg(CCR5); 514 else 515 pcr0 = read_cyrix_reg(PCR0); 516 write_cyrix_reg(CCR3, ccr3); /* Restore CCR3. */ 517 } 518 write_eflags(eflags); 519 520 if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) 521 printf("CCR0=%x, ", (u_int)ccr0); 522 523 printf("CCR1=%x, CCR2=%x, CCR3=%x", 524 (u_int)ccr1, (u_int)ccr2, (u_int)ccr3); 525 if ((cpu == CPU_M1SC) || (cpu == CPU_M1)) { 526 printf(", CCR4=%x, ", (u_int)ccr4); 527 if (cpu == CPU_M1) 528 printf("CCR5=%x\n", ccr5); 529 else 530 printf("PCR0=%x\n", pcr0); 531 } 532 } 533 printf("CR0=%x\n", cr0); 534} 535#endif /* DDB */ 536