~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Bochs x86 Emulator
bochs/bios/rombios32.c

Version: ~ [ 2.3.5 ] ~ [ 2.3 ] ~

** Warning: Cannot open xref database.

1 ///////////////////////////////////////////////////////////////////////// 2 // $Id: rombios32.c,v 1.15 2007/09/15 07:24:04 vruppert Exp $ 3 ///////////////////////////////////////////////////////////////////////// 4 // 5 // 32 bit Bochs BIOS init code 6 // Copyright (C) 2006 Fabrice Bellard 7 // 8 // This library is free software; you can redistribute it and/or 9 // modify it under the terms of the GNU Lesser General Public 10 // License as published by the Free Software Foundation; either 11 // version 2 of the License, or (at your option) any later version. 12 // 13 // This library is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 // Lesser General Public License for more details. 17 // 18 // You should have received a copy of the GNU Lesser General Public 19 // License along with this library; if not, write to the Free Software 20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 #include <stdarg.h> 22 #include <stddef.h> 23 24 #include "rombios.h" 25 26 typedef signed char int8_t; 27 typedef short int16_t; 28 typedef int int32_t; 29 typedef long long int64_t; 30 typedef unsigned char uint8_t; 31 typedef unsigned short uint16_t; 32 typedef unsigned int uint32_t; 33 typedef unsigned long long uint64_t; 34 35 /* if true, put the MP float table and ACPI RSDT in EBDA and the MP 36 table in RAM. Unfortunately, Linux has bugs with that, so we prefer 37 to modify the BIOS in shadow RAM */ 38 //#define BX_USE_EBDA_TABLES 39 40 /* define it if the (emulated) hardware supports SMM mode */ 41 #define BX_USE_SMM 42 43 #define cpuid(index, eax, ebx, ecx, edx) \ 44 asm volatile ("cpuid" \ 45 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ 46 : "" (index)) 47 48 #define wbinvd() asm volatile("wbinvd") 49 50 #define CPUID_APIC (1 << 9) 51 52 #define APIC_BASE ((uint8_t *)0xfee00000) 53 #define APIC_ICR_LOW 0x300 54 #define APIC_SVR 0x0F0 55 #define APIC_ID 0x020 56 #define APIC_LVT3 0x370 57 58 #define APIC_ENABLED 0x0100 59 60 #define AP_BOOT_ADDR 0x10000 61 62 #define MPTABLE_MAX_SIZE 0x00002000 63 #define SMI_CMD_IO_ADDR 0xb2 64 65 #define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */ 66 67 static inline void outl(int addr, int val) 68 { 69 asm volatile ("outl %1, %w0" : : "d" (addr), "a" (val)); 70 } 71 72 static inline void outw(int addr, int val) 73 { 74 asm volatile ("outw %w1, %w0" : : "d" (addr), "a" (val)); 75 } 76 77 static inline void outb(int addr, int val) 78 { 79 asm volatile ("outb %b1, %w0" : : "d" (addr), "a" (val)); 80 } 81 82 static inline uint32_t inl(int addr) 83 { 84 uint32_t val; 85 asm volatile ("inl %w1, %0" : "=a" (val) : "d" (addr)); 86 return val; 87 } 88 89 static inline uint16_t inw(int addr) 90 { 91 uint16_t val; 92 asm volatile ("inw %w1, %w0" : "=a" (val) : "d" (addr)); 93 return val; 94 } 95 96 static inline uint8_t inb(int addr) 97 { 98 uint8_t val; 99 asm volatile ("inb %w1, %b0" : "=a" (val) : "d" (addr)); 100 return val; 101 } 102 103 static inline void writel(void *addr, uint32_t val) 104 { 105 *(volatile uint32_t *)addr = val; 106 } 107 108 static inline void writew(void *addr, uint16_t val) 109 { 110 *(volatile uint16_t *)addr = val; 111 } 112 113 static inline void writeb(void *addr, uint8_t val) 114 { 115 *(volatile uint8_t *)addr = val; 116 } 117 118 static inline uint32_t readl(const void *addr) 119 { 120 return *(volatile const uint32_t *)addr; 121 } 122 123 static inline uint16_t readw(const void *addr) 124 { 125 return *(volatile const uint16_t *)addr; 126 } 127 128 static inline uint8_t readb(const void *addr) 129 { 130 return *(volatile const uint8_t *)addr; 131 } 132 133 static inline void putc(int c) 134 { 135 outb(INFO_PORT, c); 136 } 137 138 static inline int isdigit(int c) 139 { 140 return c >= '' && c <= '9'; 141 } 142 143 void *memset(void *d1, int val, size_t len) 144 { 145 uint8_t *d = d1; 146 147 while (len--) { 148 *d++ = val; 149 } 150 return d1; 151 } 152 153 void *memcpy(void *d1, const void *s1, size_t len) 154 { 155 uint8_t *d = d1; 156 const uint8_t *s = s1; 157 158 while (len--) { 159 *d++ = *s++; 160 } 161 return d1; 162 } 163 164 void *memmove(void *d1, const void *s1, size_t len) 165 { 166 uint8_t *d = d1; 167 const uint8_t *s = s1; 168 169 if (d <= s) { 170 while (len--) { 171 *d++ = *s++; 172 } 173 } else { 174 d += len; 175 s += len; 176 while (len--) { 177 *--d = *--s; 178 } 179 } 180 return d1; 181 } 182 183 size_t strlen(const char *s) 184 { 185 const char *s1; 186 for(s1 = s; *s1 != '\0'; s1++); 187 return s1 - s; 188 } 189 190 /* from BSD ppp sources */ 191 int vsnprintf(char *buf, int buflen, const char *fmt, va_list args) 192 { 193 int c, i, n; 194 int width, prec, fillch; 195 int base, len, neg; 196 unsigned long val = 0; 197 const char *f; 198 char *str, *buf0; 199 char num[32]; 200 static const char hexchars[] = "0123456789abcdef"; 201 202 buf0 = buf; 203 --buflen; 204 while (buflen > 0) { 205 for (f = fmt; *f != '%' && *f != 0; ++f) 206 ; 207 if (f > fmt) { 208 len = f - fmt; 209 if (len > buflen) 210 len = buflen; 211 memcpy(buf, fmt, len); 212 buf += len; 213 buflen -= len; 214 fmt = f; 215 } 216 if (*fmt == 0) 217 break; 218 c = *++fmt; 219 width = prec = 0; 220 fillch = ' '; 221 if (c == '') { 222 fillch = ''; 223 c = *++fmt; 224 } 225 if (c == '*') { 226 width = va_arg(args, int); 227 c = *++fmt; 228 } else { 229 while (isdigit(c)) { 230 width = width * 10 + c - ''; 231 c = *++fmt; 232 } 233 } 234 if (c == '.') { 235 c = *++fmt; 236 if (c == '*') { 237 prec = va_arg(args, int); 238 c = *++fmt; 239 } else { 240 while (isdigit(c)) { 241 prec = prec * 10 + c - ''; 242 c = *++fmt; 243 } 244 } 245 } 246 /* modifiers */ 247 switch(c) { 248 case 'l': 249 c = *++fmt; 250 break; 251 default: 252 break; 253 } 254 str = 0; 255 base = 0; 256 neg = 0; 257 ++fmt; 258 switch (c) { 259 case 'd': 260 i = va_arg(args, int); 261 if (i < 0) { 262 neg = 1; 263 val = -i; 264 } else 265 val = i; 266 base = 10; 267 break; 268 case 'o': 269 val = va_arg(args, unsigned int); 270 base = 8; 271 break; 272 case 'x': 273 case 'X': 274 val = va_arg(args, unsigned int); 275 base = 16; 276 break; 277 case 'p': 278 val = (unsigned long) va_arg(args, void *); 279 base = 16; 280 neg = 2; 281 break; 282 case 's': 283 str = va_arg(args, char *); 284 break; 285 case 'c': 286 num[0] = va_arg(args, int); 287 num[1] = 0; 288 str = num; 289 break; 290 default: 291 *buf++ = '%'; 292 if (c != '%') 293 --fmt; /* so %z outputs %z etc. */ 294 --buflen; 295 continue; 296 } 297 if (base != 0) { 298 str = num + sizeof(num); 299 *--str = 0; 300 while (str > num + neg) { 301 *--str = hexchars[val % base]; 302 val = val / base; 303 if (--prec <= 0 && val == 0) 304 break; 305 } 306 switch (neg) { 307 case 1: 308 *--str = '-'; 309 break; 310 case 2: 311 *--str = 'x'; 312 *--str = ''; 313 break; 314 } 315 len = num + sizeof(num) - 1 - str; 316 } else { 317 len = strlen(str); 318 if (prec > 0 && len > prec) 319 len = prec; 320 } 321 if (width > 0) { 322 if (width > buflen) 323 width = buflen; 324 if ((n = width - len) > 0) { 325 buflen -= n; 326 for (; n > 0; --n) 327 *buf++ = fillch; 328 } 329 } 330 if (len > buflen) 331 len = buflen; 332 memcpy(buf, str, len); 333 buf += len; 334 buflen -= len; 335 } 336 *buf = 0; 337 return buf - buf0; 338 } 339 340 void bios_printf(int flags, const char *fmt, ...) 341 { 342 va_list ap; 343 char buf[1024]; 344 const char *s; 345 346 va_start(ap, fmt); 347 vsnprintf(buf, sizeof(buf), fmt, ap); 348 s = buf; 349 while (*s) 350 putc(*s++); 351 va_end(ap); 352 } 353 354 void delay_ms(int n) 355 { 356 int i, j; 357 for(i = 0; i < n; i++) { 358 #ifdef BX_QEMU 359 /* approximative ! */ 360 for(j = 0; j < 1000000; j++); 361 #else 362 { 363 int r1, r2; 364 j = 66; 365 r1 = inb(0x61) & 0x10; 366 do { 367 r2 = inb(0x61) & 0x10; 368 if (r1 != r2) { 369 j--; 370 r1 = r2; 371 } 372 } while (j > 0); 373 } 374 #endif 375 } 376 } 377 378 int smp_cpus; 379 uint32_t cpuid_features; 380 uint32_t cpuid_ext_features; 381 unsigned long ram_size; 382 #ifdef BX_USE_EBDA_TABLES 383 unsigned long ebda_cur_addr; 384 #endif 385 int acpi_enabled; 386 uint32_t pm_io_base, smb_io_base; 387 int pm_sci_int; 388 unsigned long bios_table_cur_addr; 389 unsigned long bios_table_end_addr; 390 391 void cpu_probe(void) 392 { 393 uint32_t eax, ebx, ecx, edx; 394 cpuid(1, eax, ebx, ecx, edx); 395 cpuid_features = edx; 396 cpuid_ext_features = ecx; 397 } 398 399 static int cmos_readb(int addr) 400 { 401 outb(0x70, addr); 402 return inb(0x71); 403 } 404 405 void ram_probe(void) 406 { 407 if (cmos_readb(0x34) | cmos_readb(0x35)) 408 ram_size = (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 + 409 16 * 1024 * 1024; 410 else 411 ram_size = (cmos_readb(0x17) | (cmos_readb(0x18) << 8)) * 1024; 412 #ifdef BX_USE_EBDA_TABLES 413 ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380; 414 #endif 415 BX_INFO("ram_size=0x%08lx\n", ram_size); 416 } 417 418 /****************************************************/ 419 /* SMP probe */ 420 421 extern uint8_t smp_ap_boot_code_start; 422 extern uint8_t smp_ap_boot_code_end; 423 424 /* find the number of CPUs by launching a SIPI to them */ 425 void smp_probe(void) 426 { 427 uint32_t val, sipi_vector; 428 429 smp_cpus = 1; 430 if (cpuid_features & CPUID_APIC) { 431 432 /* enable local APIC */ 433 val = readl(APIC_BASE + APIC_SVR); 434 val |= APIC_ENABLED; 435 writel(APIC_BASE + APIC_SVR, val); 436 437 writew((void *)CPU_COUNT_ADDR, 1); 438 /* copy AP boot code */ 439 memcpy((void *)AP_BOOT_ADDR, &smp_ap_boot_code_start, 440 &smp_ap_boot_code_end - &smp_ap_boot_code_start); 441 442 /* broadcast SIPI */ 443 writel(APIC_BASE + APIC_ICR_LOW, 0x000C4500); 444 sipi_vector = AP_BOOT_ADDR >> 12; 445 writel(APIC_BASE + APIC_ICR_LOW, 0x000C4600 | sipi_vector); 446 447 delay_ms(10); 448 449 smp_cpus = readw((void *)CPU_COUNT_ADDR); 450 } 451 BX_INFO("Found %d cpu(s)\n", smp_cpus); 452 } 453 454 /****************************************************/ 455 /* PCI init */ 456 457 #define PCI_ADDRESS_SPACE_MEM 0x00 458 #define PCI_ADDRESS_SPACE_IO 0x01 459 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 460 461 #define PCI_ROM_SLOT 6 462 #define PCI_NUM_REGIONS 7 463 464 #define PCI_DEVICES_MAX 64 465 466 #define PCI_VENDOR_ID 0x00 /* 16 bits */ 467 #define PCI_DEVICE_ID 0x02 /* 16 bits */ 468 #define PCI_COMMAND 0x04 /* 16 bits */ 469 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ 470 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ 471 #define PCI_CLASS_DEVICE 0x0a /* Device class */ 472 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ 473 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ 474 #define PCI_MIN_GNT 0x3e /* 8 bits */ 475 #define PCI_MAX_LAT 0x3f /* 8 bits */ 476 477 typedef struct PCIDevice { 478 int bus; 479 int devfn; 480 } PCIDevice; 481 482 static uint32_t pci_bios_io_addr; 483 static uint32_t pci_bios_mem_addr; 484 static uint32_t pci_bios_bigmem_addr; 485 /* host irqs corresponding to PCI irqs A-D */ 486 static uint8_t pci_irqs[4] = { 11, 9, 11, 9 }; 487 static PCIDevice i440_pcidev; 488 489 static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) 490 { 491 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); 492 outl(0xcfc, val); 493 } 494 495 static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) 496 { 497 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); 498 outw(0xcfc + (addr & 2), val); 499 } 500 501 static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) 502 { 503 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); 504 outb(0xcfc + (addr & 3), val); 505 } 506 507 static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr) 508 { 509 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); 510 return inl(0xcfc); 511 } 512 513 static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) 514 { 515 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); 516 return inw(0xcfc + (addr & 2)); 517 } 518 519 static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr) 520 { 521 outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); 522 return inb(0xcfc + (addr & 3)); 523 } 524 525 static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr) 526 { 527 uint16_t cmd; 528 uint32_t ofs, old_addr; 529 530 if ( region_num == PCI_ROM_SLOT ) { 531 ofs = 0x30; 532 }else{ 533 ofs = 0x10 + region_num * 4; 534 } 535 536 old_addr = pci_config_readl(d, ofs); 537 538 pci_config_writel(d, ofs, addr); 539 BX_INFO("region %d: 0x%08x\n", region_num, addr); 540 541 /* enable memory mappings */ 542 cmd = pci_config_readw(d, PCI_COMMAND); 543 if ( region_num == PCI_ROM_SLOT ) 544 cmd |= 2; 545 else if (old_addr & PCI_ADDRESS_SPACE_IO) 546 cmd |= 1; 547 else 548 cmd |= 2; 549 pci_config_writew(d, PCI_COMMAND, cmd); 550 } 551 552 /* return the global irq number corresponding to a given device irq 553 pin. We could also use the bus number to have a more precise 554 mapping. */ 555 static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) 556 { 557 int slot_addend; 558 slot_addend = (pci_dev->devfn >> 3) - 1; 559 return (irq_num + slot_addend) & 3; 560 } 561 562 static int find_bios_table_area(void) 563 { 564 unsigned long addr; 565 for(addr = 0xf0000; addr < 0x100000; addr += 16) { 566 if (*(uint32_t *)addr == 0xaafb4442) { 567 bios_table_cur_addr = addr + 8; 568 bios_table_end_addr = bios_table_cur_addr + *(uint32_t *)(addr + 4); 569 BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n", 570 bios_table_cur_addr, bios_table_end_addr); 571 return 0; 572 } 573 } 574 return -1; 575 } 576 577 static void bios_shadow_init(PCIDevice *d) 578 { 579 int v; 580 581 if (find_bios_table_area() < 0) 582 return; 583 584 /* remap the BIOS to shadow RAM an keep it read/write while we 585 are writing tables */ 586 memcpy((void *)BIOS_TMP_STORAGE, (void *)0x000f0000, 0x10000); 587 v = pci_config_readb(d, 0x59); 588 v = (v & 0x0f) | (0x30); 589 pci_config_writeb(d, 0x59, v); 590 memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE, 0x10000); 591 592 i440_pcidev = *d; 593 } 594 595 static void bios_lock_shadow_ram(void) 596 { 597 PCIDevice *d = &i440_pcidev; 598 int v; 599 600 wbinvd(); 601 v = pci_config_readb(d, 0x59); 602 v = (v & 0x0f) | (0x10); 603 pci_config_writeb(d, 0x59, v); 604 } 605 606 static void pci_bios_init_bridges(PCIDevice *d) 607 { 608 uint16_t vendor_id, device_id; 609 610 vendor_id = pci_config_readw(d, PCI_VENDOR_ID); 611 device_id = pci_config_readw(d, PCI_DEVICE_ID); 612 613 if (vendor_id == 0x8086 && device_id == 0x7000) { 614 int i, irq; 615 uint8_t elcr[2]; 616 617 /* PIIX3 bridge */ 618 619 elcr[0] = 0x00; 620 elcr[1] = 0x00; 621 for(i = 0; i < 4; i++) { 622 irq = pci_irqs[i]; 623 /* set to trigger level */ 624 elcr[irq >> 3] |= (1 << (irq & 7)); 625 /* activate irq remapping in PIIX */ 626 pci_config_writeb(d, 0x60 + i, irq); 627 } 628 outb(0x4d0, elcr[0]); 629 outb(0x4d1, elcr[1]); 630 BX_INFO("PIIX3 init: elcr=%02x %02x\n", 631 elcr[0], elcr[1]); 632 } else if (vendor_id == 0x8086 && device_id == 0x1237) { 633 /* i440 PCI bridge */ 634 bios_shadow_init(d); 635 } 636 } 637 638 extern uint8_t smm_relocation_start, smm_relocation_end; 639 extern uint8_t smm_code_start, smm_code_end; 640 641 #ifdef BX_USE_SMM 642 static void smm_init(PCIDevice *d) 643 { 644 /* copy the SMM relocation code */ 645 memcpy((void *)0x38000, &smm_relocation_start, 646 &smm_relocation_end - &smm_relocation_start); 647 648 /* enable SMI generation when writing to the APMC register */ 649 pci_config_writel(d, 0x58, pci_config_readl(d, 0x58) | (1 << 25)); 650 651 /* init APM status port */ 652 outb(0xb3, 0x01); 653 654 /* raise an SMI interrupt */ 655 outb(0xb2, 0x00); 656 657 /* wait until SMM code executed */ 658 while (inb(0xb3) != 0x00); 659 660 /* enable the SMM memory window */ 661 pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x48); 662 663 /* copy the SMM code */ 664 memcpy((void *)0xa8000, &smm_code_start, 665 &smm_code_end - &smm_code_start); 666 wbinvd(); 667 668 /* close the SMM memory window and enable normal SMM */ 669 pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x08); 670 } 671 #endif 672 673 static void pci_bios_init_device(PCIDevice *d) 674 { 675 int class; 676 uint32_t *paddr; 677 int i, pin, pic_irq, vendor_id, device_id; 678 679 class = pci_config_readw(d, PCI_CLASS_DEVICE); 680 vendor_id = pci_config_readw(d, PCI_VENDOR_ID); 681 device_id = pci_config_readw(d, PCI_DEVICE_ID); 682 BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n", 683 d->bus, d->devfn, vendor_id, device_id); 684 switch(class) { 685 case 0x0101: 686 if (vendor_id == 0x8086 && device_id == 0x7010) { 687 /* PIIX3 IDE */ 688 pci_config_writew(d, 0x40, 0x8000); // enable IDE0 689 pci_config_writew(d, 0x42, 0x8000); // enable IDE1 690 goto default_map; 691 } else { 692 /* IDE: we map it as in ISA mode */ 693 pci_set_io_region_addr(d, 0, 0x1f0); 694 pci_set_io_region_addr(d, 1, 0x3f4); 695 pci_set_io_region_addr(d, 2, 0x170); 696 pci_set_io_region_addr(d, 3, 0x374); 697 } 698 break; 699 case 0x0300: 700 if (vendor_id != 0x1234) 701 goto default_map; 702 /* VGA: map frame buffer to default Bochs VBE address */ 703 pci_set_io_region_addr(d, 0, 0xE0000000); 704 break; 705 case 0x0800: 706 /* PIC */ 707 if (vendor_id == 0x1014) { 708 /* IBM */ 709 if (device_id == 0x0046 || device_id == 0xFFFF) { 710 /* MPIC & MPIC2 */ 711 pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000); 712 } 713 } 714 break; 715 case 0xff00: 716 if (vendor_id == 0x0106b && 717 (device_id == 0x0017 || device_id == 0x0022)) { 718 /* macio bridge */ 719 pci_set_io_region_addr(d, 0, 0x80800000); 720 } 721 break; 722 default: 723 default_map: 724 /* default memory mappings */ 725 for(i = 0; i < PCI_NUM_REGIONS; i++) { 726 int ofs; 727 uint32_t val, size ; 728 729 if (i == PCI_ROM_SLOT) 730 ofs = 0x30; 731 else 732 ofs = 0x10 + i * 4; 733 pci_config_writel(d, ofs, 0xffffffff); 734 val = pci_config_readl(d, ofs); 735 if (val != 0) { 736 size = (~(val & ~0xf)) + 1; 737 if (val & PCI_ADDRESS_SPACE_IO) 738 paddr = &pci_bios_io_addr; 739 else if (size >= 0x04000000) 740 paddr = &pci_bios_bigmem_addr; 741 else 742 paddr = &pci_bios_mem_addr; 743 *paddr = (*paddr + size - 1) & ~(size - 1); 744 pci_set_io_region_addr(d, i, *paddr); 745 *paddr += size; 746 } 747 } 748 break; 749 } 750 751 /* map the interrupt */ 752 pin = pci_config_readb(d, PCI_INTERRUPT_PIN); 753 if (pin != 0) { 754 pin = pci_slot_get_pirq(d, pin - 1); 755 pic_irq = pci_irqs[pin]; 756 pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq); 757 } 758 759 if (vendor_id == 0x8086 && device_id == 0x7113) { 760 /* PIIX4 Power Management device (for ACPI) */ 761 pm_io_base = PM_IO_BASE; 762 pci_config_writel(d, 0x40, pm_io_base | 1); 763 pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */ 764 smb_io_base = SMB_IO_BASE; 765 pci_config_writel(d, 0x90, smb_io_base | 1); 766 pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */ 767 pm_sci_int = pci_config_readb(d, PCI_INTERRUPT_LINE); 768 #ifdef BX_USE_SMM 769 smm_init(d); 770 #endif 771 acpi_enabled = 1; 772 } 773 } 774 775 void pci_for_each_device(void (*init_func)(PCIDevice *d)) 776 { 777 PCIDevice d1, *d = &d1; 778 int bus, devfn; 779 uint16_t vendor_id, device_id; 780 781 for(bus = 0; bus < 1; bus++) { 782 for(devfn = 0; devfn < 256; devfn++) { 783 d->bus = bus; 784 d->devfn = devfn; 785 vendor_id = pci_config_readw(d, PCI_VENDOR_ID); 786 device_id = pci_config_readw(d, PCI_DEVICE_ID); 787 if (vendor_id != 0xffff || device_id != 0xffff) { 788 init_func(d); 789 } 790 } 791 } 792 } 793 794 void pci_bios_init(void) 795 { 796 pci_bios_io_addr = 0xc000; 797 pci_bios_mem_addr = 0xf0000000; 798 pci_bios_bigmem_addr = ram_size; 799 if (pci_bios_bigmem_addr < 0x90000000) 800 pci_bios_bigmem_addr = 0x90000000; 801 802 pci_for_each_device(pci_bios_init_bridges); 803 804 pci_for_each_device(pci_bios_init_device); 805 } 806 807 /****************************************************/ 808 /* Multi Processor table init */ 809 810 static void putb(uint8_t **pp, int val) 811 { 812 uint8_t *q; 813 q = *pp; 814 *q++ = val; 815 *pp = q; 816 } 817 818 static void putstr(uint8_t **pp, const char *str) 819 { 820 uint8_t *q; 821 q = *pp; 822 while (*str) 823 *q++ = *str++; 824 *pp = q; 825 } 826 827 static void putle16(uint8_t **pp, int val) 828 { 829 uint8_t *q; 830 q = *pp; 831 *q++ = val; 832 *q++ = val >> 8; 833 *pp = q; 834 } 835 836 static void putle32(uint8_t **pp, int val) 837 { 838 uint8_t *q; 839 q = *pp; 840 *q++ = val; 841 *q++ = val >> 8; 842 *q++ = val >> 16; 843 *q++ = val >> 24; 844 *pp = q; 845 } 846 847 static int mpf_checksum(const uint8_t *data, int len) 848 { 849 int sum, i; 850 sum = 0; 851 for(i = 0; i < len; i++) 852 sum += data[i]; 853 return sum & 0xff; 854 } 855 856 static unsigned long align(unsigned long addr, unsigned long v) 857 { 858 return (addr + v - 1) & ~(v - 1); 859 } 860 861 static void mptable_init(void) 862 { 863 uint8_t *mp_config_table, *q, *float_pointer_struct; 864 int ioapic_id, i, len; 865 int mp_config_table_size; 866 867 #ifdef BX_USE_EBDA_TABLES 868 mp_config_table = (uint8_t *)(ram_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE); 869 #else 870 bios_table_cur_addr = align(bios_table_cur_addr, 16); 871 mp_config_table = (uint8_t *)bios_table_cur_addr; 872 #endif 873 q = mp_config_table; 874 putstr(&q, "PCMP"); /* "PCMP signature */ 875 putle16(&q, 0); /* table length (patched later) */ 876 putb(&q, 4); /* spec rev */ 877 putb(&q, 0); /* checksum (patched later) */ 878 #ifdef BX_QEMU 879 putstr(&q, "QEMUCPU "); /* OEM id */ 880 #else 881 putstr(&q, "BOCHSCPU"); 882 #endif 883 putstr(&q, "0.1 "); /* vendor id */ 884 putle32(&q, 0); /* OEM table ptr */ 885 putle16(&q, 0); /* OEM table size */ 886 putle16(&q, smp_cpus + 18); /* entry count */ 887 putle32(&q, 0xfee00000); /* local APIC addr */ 888 putle16(&q, 0); /* ext table length */ 889 putb(&q, 0); /* ext table checksum */ 890 putb(&q, 0); /* reserved */ 891 892 for(i = 0; i < smp_cpus; i++) { 893 putb(&q, 0); /* entry type = processor */ 894 putb(&q, i); /* APIC id */ 895 putb(&q, 0x11); /* local APIC version number */ 896 if (i == 0) 897 putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */ 898 else 899 putb(&q, 1); /* cpu flags: enabled */ 900 putb(&q, 0); /* cpu signature */ 901 putb(&q, 6); 902 putb(&q, 0); 903 putb(&q, 0); 904 putle16(&q, 0x201); /* feature flags */ 905 putle16(&q, 0); 906 907 putle16(&q, 0); /* reserved */ 908 putle16(&q, 0); 909 putle16(&q, 0); 910 putle16(&q, 0); 911 } 912 913 /* isa bus */ 914 putb(&q, 1); /* entry type = bus */ 915 putb(&q, 0); /* bus ID */ 916 putstr(&q, "ISA "); 917 918 /* ioapic */ 919 ioapic_id = smp_cpus; 920 putb(&q, 2); /* entry type = I/O APIC */ 921 putb(&q, ioapic_id); /* apic ID */ 922 putb(&q, 0x11); /* I/O APIC version number */ 923 putb(&q, 1); /* enable */ 924 putle32(&q, 0xfec00000); /* I/O APIC addr */ 925 926 /* irqs */ 927 for(i = 0; i < 16; i++) { 928 putb(&q, 3); /* entry type = I/O interrupt */ 929 putb(&q, 0); /* interrupt type = vectored interrupt */ 930 putb(&q, 0); /* flags: po=0, el=0 */ 931 putb(&q, 0); 932 putb(&q, 0); /* source bus ID = ISA */ 933 putb(&q, i); /* source bus IRQ */ 934 putb(&q, ioapic_id); /* dest I/O APIC ID */ 935 putb(&q, i); /* dest I/O APIC interrupt in */ 936 } 937 /* patch length */ 938 len = q - mp_config_table; 939 mp_config_table[4] = len; 940 mp_config_table[5] = len >> 8; 941 942 mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table); 943 944 mp_config_table_size = q - mp_config_table; 945 946 #ifndef BX_USE_EBDA_TABLES 947 bios_table_cur_addr += mp_config_table_size; 948 #endif 949 950 /* floating pointer structure */ 951 #ifdef BX_USE_EBDA_TABLES 952 ebda_cur_addr = align(ebda_cur_addr, 16); 953 float_pointer_struct = (uint8_t *)ebda_cur_addr; 954 #else 955 bios_table_cur_addr = align(bios_table_cur_addr, 16); 956 float_pointer_struct = (uint8_t *)bios_table_cur_addr; 957 #endif 958 q = float_pointer_struct; 959 putstr(&q, "_MP_"); 960 /* pointer to MP config table */ 961 putle32(&q, (unsigned long)mp_config_table); 962 963 putb(&q, 1); /* length in 16 byte units */ 964 putb(&q, 4); /* MP spec revision */ 965 putb(&q, 0); /* checksum (patched later) */ 966 putb(&q, 0); /* MP feature byte 1 */ 967 968 putb(&q, 0); 969 putb(&q, 0); 970 putb(&q, 0); 971 putb(&q, 0); 972 float_pointer_struct[10] = 973 -mpf_checksum(float_pointer_struct, q - float_pointer_struct); 974 #ifdef BX_USE_EBDA_TABLES 975 ebda_cur_addr += (q - float_pointer_struct); 976 #else 977 bios_table_cur_addr += (q - float_pointer_struct); 978 #endif 979 BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n", 980 (unsigned long)float_pointer_struct, 981 (unsigned long)mp_config_table, 982 mp_config_table_size); 983 } 984 985 /****************************************************/ 986 /* ACPI tables init */ 987 988 /* Table structure from Linux kernel (the ACPI tables are under the 989 BSD license) */ 990 991 #define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ 992 uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\ 993 uint32_t length; /* Length of table, in bytes, including header */\ 994 uint8_t revision; /* ACPI Specification minor version # */\ 995 uint8_t checksum; /* To make sum of entire table == 0 */\ 996 uint8_t oem_id [6]; /* OEM identification */\ 997 uint8_t oem_table_id [8]; /* OEM table identification */\ 998 uint32_t oem_revision; /* OEM revision number */\ 999 uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\ 1000 uint32_t asl_compiler_revision; /* ASL compiler revision number */ 1001 1002 1003 struct acpi_table_header /* ACPI common table header */ 1004 { 1005 ACPI_TABLE_HEADER_DEF 1006 }; 1007 1008 struct rsdp_descriptor /* Root System Descriptor Pointer */ 1009 { 1010 uint8_t signature [8]; /* ACPI signature, contains "RSD PTR " */ 1011 uint8_t checksum; /* To make sum of struct == 0 */ 1012 uint8_t oem_id [6]; /* OEM identification */ 1013 uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */ 1014 uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */ 1015 uint32_t length; /* XSDT Length in bytes including hdr */ 1016 uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */ 1017 uint8_t extended_checksum; /* Checksum of entire table */ 1018 uint8_t reserved [3]; /* Reserved field must be 0 */ 1019 }; 1020 1021 /* 1022 * ACPI 1.0 Root System Description Table (RSDT) 1023 */ 1024 struct rsdt_descriptor_rev1 1025 { 1026 ACPI_TABLE_HEADER_DEF /* ACPI common table header */ 1027 uint32_t table_offset_entry [2]; /* Array of pointers to other */ 1028 /* ACPI tables */ 1029 }; 1030 1031 /* 1032 * ACPI 1.0 Firmware ACPI Control Structure (FACS) 1033 */ 1034 struct facs_descriptor_rev1 1035 { 1036 uint8_t signature[4]; /* ACPI Signature */ 1037 uint32_t length; /* Length of structure, in bytes */ 1038 uint32_t hardware_signature; /* Hardware configuration signature */ 1039 uint32_t firmware_waking_vector; /* ACPI OS waking vector */ 1040 uint32_t global_lock; /* Global Lock */ 1041 uint32_t S4bios_f : 1; /* Indicates if S4BIOS support is present */ 1042 uint32_t reserved1 : 31; /* Must be 0 */ 1043 uint8_t resverved3 [40]; /* Reserved - must be zero */ 1044 }; 1045 1046 1047 /* 1048 * ACPI 1.0 Fixed ACPI Description Table (FADT) 1049 */ 1050 struct fadt_descriptor_rev1 1051 { 1052 ACPI_TABLE_HEADER_DEF /* ACPI common table header */ 1053 uint32_t firmware_ctrl; /* Physical address of FACS */ 1054 uint32_t dsdt; /* Physical address of DSDT */ 1055 uint8_t model; /* System Interrupt Model */ 1056 uint8_t reserved1; /* Reserved */ 1057 uint16_t sci_int; /* System vector of SCI interrupt */ 1058 uint32_t smi_cmd; /* Port address of SMI command port */ 1059 uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */ 1060 uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */ 1061 uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ 1062 uint8_t reserved2; /* Reserved - must be zero */ 1063 uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ 1064 uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ 1065 uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ 1066 uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ 1067 uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ 1068 uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ 1069 uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ 1070 uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ 1071 uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ 1072 uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ 1073 uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ 1074 uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */ 1075 uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ 1076 uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ 1077 uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */ 1078 uint8_t reserved3; /* Reserved */ 1079 uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ 1080 uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ 1081 uint16_t flush_size; /* Size of area read to flush caches */ 1082 uint16_t flush_stride; /* Stride used in flushing caches */ 1083 uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */ 1084 uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */ 1085 uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ 1086 uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ 1087 uint8_t century; /* Index to century in RTC CMOS RAM */ 1088 uint8_t reserved4; /* Reserved */ 1089 uint8_t reserved4a; /* Reserved */ 1090 uint8_t reserved4b; /* Reserved */ 1091 #if 0 1092 uint32_t wb_invd : 1; /* The wbinvd instruction works properly */ 1093 uint32_t wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */ 1094 uint32_t proc_c1 : 1; /* All processors support C1 state */ 1095 uint32_t plvl2_up : 1; /* C2 state works on MP system */ 1096 uint32_t pwr_button : 1; /* Power button is handled as a generic feature */ 1097 uint32_t sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ 1098 uint32_t fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ 1099 uint32_t rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ 1100 uint32_t tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */ 1101 uint32_t reserved5 : 23; /* Reserved - must be zero */ 1102 #else 1103 uint32_t flags; 1104 #endif 1105 }; 1106 1107 /* 1108 * MADT values and structures 1109 */ 1110 1111 /* Values for MADT PCATCompat */ 1112 1113 #define DUAL_PIC 0 1114 #define MULTIPLE_APIC 1 1115 1116 1117 /* Master MADT */ 1118 1119 struct multiple_apic_table 1120 { 1121 ACPI_TABLE_HEADER_DEF /* ACPI common table header */ 1122 uint32_t local_apic_address; /* Physical address of local APIC */ 1123 #if 0 1124 uint32_t PCATcompat : 1; /* A one indicates system also has dual 8259s */ 1125 uint32_t reserved1 : 31; 1126 #else 1127 uint32_t flags; 1128 #endif 1129 }; 1130 1131 1132 /* Values for Type in APIC_HEADER_DEF */ 1133 1134 #define APIC_PROCESSOR 0 1135 #define APIC_IO 1 1136 #define APIC_XRUPT_OVERRIDE 2 1137 #define APIC_NMI 3 1138 #define APIC_LOCAL_NMI 4 1139 #define APIC_ADDRESS_OVERRIDE 5 1140 #define APIC_IO_SAPIC 6 1141 #define APIC_LOCAL_SAPIC 7 1142 #define APIC_XRUPT_SOURCE 8 1143 #define APIC_RESERVED 9 /* 9 and greater are reserved */ 1144 1145 /* 1146 * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) 1147 */ 1148 #define APIC_HEADER_DEF /* Common APIC sub-structure header */\ 1149 uint8_t type; \ 1150 uint8_t length; 1151 1152 /* Sub-structures for MADT */ 1153 1154 struct madt_processor_apic 1155 { 1156 APIC_HEADER_DEF 1157 uint8_t processor_id; /* ACPI processor id */ 1158 uint8_t local_apic_id; /* Processor's local APIC id */ 1159 #if 0 1160 uint32_t processor_enabled: 1; /* Processor is usable if set */ 1161 uint32_t reserved2 : 31; /* Reserved, must be zero */ 1162 #else 1163 uint32_t flags; 1164 #endif 1165 }; 1166 1167 struct madt_io_apic 1168 { 1169 APIC_HEADER_DEF 1170 uint8_t io_apic_id; /* I/O APIC ID */ 1171 uint8_t reserved; /* Reserved - must be zero */ 1172 uint32_t address; /* APIC physical address */ 1173 uint32_t interrupt; /* Global system interrupt where INTI 1174 * lines start */ 1175 }; 1176 1177 #include "acpi-dsdt.hex" 1178 1179 static inline uint16_t cpu_to_le16(uint16_t x) 1180 { 1181 return x; 1182 } 1183 1184 static inline uint32_t cpu_to_le32(uint32_t x) 1185 { 1186 return x; 1187 } 1188 1189 static int acpi_checksum(const uint8_t *data, int len) 1190 { 1191 int sum, i; 1192 sum = 0; 1193 for(i = 0; i < len; i++) 1194 sum += data[i]; 1195 return (-sum) & 0xff; 1196 } 1197 1198 static void acpi_build_table_header(struct acpi_table_header *h, 1199 char *sig, int len, uint8_t rev) 1200 { 1201 memcpy(h->signature, sig, 4); 1202 h->length = cpu_to_le32(len); 1203 h->revision = rev; 1204 #ifdef BX_QEMU 1205 memcpy(h->oem_id, "QEMU ", 6); 1206 memcpy(h->oem_table_id, "QEMU", 4); 1207 #else 1208 memcpy(h->oem_id, "BOCHS ", 6); 1209 memcpy(h->oem_table_id, "BXPC", 4); 1210 #endif 1211 memcpy(h->oem_table_id + 4, sig, 4); 1212 h->oem_revision = cpu_to_le32(1); 1213 #ifdef BX_QEMU 1214 memcpy(h->asl_compiler_id, "QEMU", 4); 1215 #else 1216 memcpy(h->asl_compiler_id, "BXPC", 4); 1217 #endif 1218 h->asl_compiler_revision = cpu_to_le32(1); 1219 h->checksum = acpi_checksum((void *)h, len); 1220 } 1221 1222 /* base_addr must be a multiple of 4KB */ 1223 void acpi_bios_init(void) 1224 { 1225 struct rsdp_descriptor *rsdp; 1226 struct rsdt_descriptor_rev1 *rsdt; 1227 struct fadt_descriptor_rev1 *fadt; 1228 struct facs_descriptor_rev1 *facs; 1229 struct multiple_apic_table *madt; 1230 uint8_t *dsdt; 1231 uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr; 1232 uint32_t acpi_tables_size, madt_addr, madt_size; 1233 int i; 1234 1235 /* reserve memory space for tables */ 1236 #ifdef BX_USE_EBDA_TABLES 1237 ebda_cur_addr = align(ebda_cur_addr, 16); 1238 rsdp = (void *)(ebda_cur_addr); 1239 ebda_cur_addr += sizeof(*rsdp); 1240 #else 1241 bios_table_cur_addr = align(bios_table_cur_addr, 16); 1242 rsdp = (void *)(bios_table_cur_addr); 1243 bios_table_cur_addr += sizeof(*rsdp); 1244 #endif 1245 1246 addr = base_addr = ram_size - ACPI_DATA_SIZE; 1247 rsdt_addr = addr; 1248 rsdt = (void *)(addr); 1249 addr += sizeof(*rsdt); 1250 1251 fadt_addr = addr; 1252 fadt = (void *)(addr); 1253 addr += sizeof(*fadt); 1254 1255 /* XXX: FACS should be in RAM */ 1256 addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */ 1257 facs_addr = addr; 1258 facs = (void *)(addr); 1259 addr += sizeof(*facs); 1260 1261 dsdt_addr = addr; 1262 dsdt = (void *)(addr); 1263 addr += sizeof(AmlCode); 1264 1265 addr = (addr + 7) & ~7; 1266 madt_addr = addr; 1267 madt_size = sizeof(*madt) + 1268 sizeof(struct madt_processor_apic) * smp_cpus + 1269 sizeof(struct madt_io_apic); 1270 madt = (void *)(addr); 1271 addr += madt_size; 1272 1273 acpi_tables_size = addr - base_addr; 1274 1275 BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n", 1276 (unsigned long)rsdp, 1277 (unsigned long)rsdt, acpi_tables_size); 1278 1279 /* RSDP */ 1280 memset(rsdp, 0, sizeof(*rsdp)); 1281 memcpy(rsdp->signature, "RSD PTR ", 8); 1282 #ifdef BX_QEMU 1283 memcpy(rsdp->oem_id, "QEMU ", 6); 1284 #else 1285 memcpy(rsdp->oem_id, "BOCHS ", 6); 1286 #endif 1287 rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr); 1288 rsdp->checksum = acpi_checksum((void *)rsdp, 20); 1289 1290 /* RSDT */ 1291 memset(rsdt, 0, sizeof(*rsdt)); 1292 rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr); 1293 rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr); 1294 acpi_build_table_header((struct acpi_table_header *)rsdt, 1295 "RSDT", sizeof(*rsdt), 1); 1296 1297 /* FADT */ 1298 memset(fadt, 0, sizeof(*fadt)); 1299 fadt->firmware_ctrl = cpu_to_le32(facs_addr); 1300 fadt->dsdt = cpu_to_le32(dsdt_addr); 1301 fadt->model = 1; 1302 fadt->reserved1 = 0; 1303 fadt->sci_int = cpu_to_le16(pm_sci_int); 1304 fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR); 1305 fadt->acpi_enable = 0xf1; 1306 fadt->acpi_disable = 0xf0; 1307 fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base); 1308 fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04); 1309 fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08); 1310 fadt->pm1_evt_len = 4; 1311 fadt->pm1_cnt_len = 2; 1312 fadt->pm_tmr_len = 4; 1313 fadt->plvl2_lat = cpu_to_le16(50); 1314 fadt->plvl3_lat = cpu_to_le16(50); 1315 fadt->plvl3_lat = cpu_to_le16(50); 1316 /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */ 1317 fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6)); 1318 acpi_build_table_header((struct acpi_table_header *)fadt, "FACP", 1319 sizeof(*fadt), 1); 1320 1321 /* FACS */ 1322 memset(facs, 0, sizeof(*facs)); 1323 memcpy(facs->signature, "FACS", 4); 1324 facs->length = cpu_to_le32(sizeof(*facs)); 1325 1326 /* DSDT */ 1327 memcpy(dsdt, AmlCode, sizeof(AmlCode)); 1328 1329 /* MADT */ 1330 { 1331 struct madt_processor_apic *apic; 1332 struct madt_io_apic *io_apic; 1333 1334 memset(madt, 0, madt_size); 1335 madt->local_apic_address = cpu_to_le32(0xfee00000); 1336 madt->flags = cpu_to_le32(1); 1337 apic = (void *)(madt + 1); 1338 for(i=0;i<smp_cpus;i++) { 1339 apic->type = APIC_PROCESSOR; 1340 apic->length = sizeof(*apic); 1341 apic->processor_id = i; 1342 apic->local_apic_id = i; 1343 apic->flags = cpu_to_le32(1); 1344 apic++; 1345 } 1346 io_apic = (void *)apic; 1347 io_apic->type = APIC_IO; 1348 io_apic->length = sizeof(*io_apic); 1349 io_apic->io_apic_id = smp_cpus; 1350 io_apic->address = cpu_to_le32(0xfec00000); 1351 io_apic->interrupt = cpu_to_le32(0); 1352 1353 acpi_build_table_header((struct acpi_table_header *)madt, 1354 "APIC", madt_size, 1); 1355 } 1356 } 1357 1358 void rombios32_init(void) 1359 { 1360 BX_INFO("Starting rombios32\n"); 1361 1362 ram_probe(); 1363 1364 cpu_probe(); 1365 1366 smp_probe(); 1367 1368 pci_bios_init(); 1369 1370 if (bios_table_cur_addr != 0) { 1371 1372 mptable_init(); 1373 1374 if (acpi_enabled) 1375 acpi_bios_init(); 1376 1377 bios_lock_shadow_ram(); 1378 } 1379 } 1380

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.