coreboot-v2/util/romcc/tests/raminit_test7.c
<<
>>
Prefs
   1typedef unsigned char      uint8_t;
   2typedef signed char        int8_t; 
   3typedef unsigned short     uint16_t;
   4typedef signed short       int16_t;
   5typedef unsigned int       uint32_t;
   6typedef signed int         int32_t;
   7 
   8typedef unsigned char      uint_least8_t;
   9typedef signed char        int_least8_t; 
  10typedef unsigned short     uint_least16_t;
  11typedef signed short       int_least16_t;
  12typedef unsigned int       uint_least32_t;
  13typedef signed int         int_least32_t;
  14 
  15typedef unsigned char      uint_fast8_t;
  16typedef signed char        int_fast8_t; 
  17typedef unsigned int       uint_fast16_t;
  18typedef signed int         int_fast16_t;
  19typedef unsigned int       uint_fast32_t;
  20typedef signed int         int_fast32_t;
  21 
  22typedef int                intptr_t;
  23typedef unsigned int       uintptr_t;
  24 
  25typedef long int           intmax_t;
  26typedef unsigned long int  uintmax_t;
  27 
  28static inline unsigned long apic_read(unsigned long reg)
  29{
  30        return *((volatile unsigned long *)(0xfee00000 +reg));
  31}
  32static inline void apic_write(unsigned long reg, unsigned long v)
  33{
  34        *((volatile unsigned long *)(0xfee00000 +reg)) = v;
  35}
  36static inline void apic_wait_icr_idle(void)
  37{
  38        do { } while ( apic_read( 0x300  ) & 0x01000  );
  39}
  40 
  41static void outb(unsigned char value, unsigned short port)
  42{
  43        __builtin_outb(value, port);
  44}
  45static void outw(unsigned short value, unsigned short port)
  46{
  47        __builtin_outw(value, port);
  48}
  49static void outl(unsigned int value, unsigned short port)
  50{
  51        __builtin_outl(value, port);
  52}
  53static unsigned char inb(unsigned short port)
  54{
  55        return __builtin_inb(port);
  56}
  57static unsigned char inw(unsigned short port)
  58{
  59        return __builtin_inw(port);
  60}
  61static unsigned char inl(unsigned short port)
  62{
  63        return __builtin_inl(port);
  64}
  65static inline void outsb(uint16_t port, const void *addr, unsigned long count)
  66{
  67        __asm__ __volatile__ (
  68                "cld ; rep ; outsb " 
  69                : "=S" (addr), "=c" (count)
  70                : "d"(port), "0"(addr), "1" (count)
  71                );
  72}
  73static inline void outsw(uint16_t port, const void *addr, unsigned long count)
  74{
  75        __asm__ __volatile__ (
  76                "cld ; rep ; outsw " 
  77                : "=S" (addr), "=c" (count)
  78                : "d"(port), "0"(addr), "1" (count)
  79                );
  80}
  81static inline void outsl(uint16_t port, const void *addr, unsigned long count)
  82{
  83        __asm__ __volatile__ (
  84                "cld ; rep ; outsl " 
  85                : "=S" (addr), "=c" (count)
  86                : "d"(port), "0"(addr), "1" (count)
  87                );
  88}
  89static inline void insb(uint16_t port, void *addr, unsigned long count)
  90{
  91        __asm__ __volatile__ (
  92                "cld ; rep ; insb " 
  93                : "=D" (addr), "=c" (count)
  94                : "d"(port), "0"(addr), "1" (count)
  95                );
  96}
  97static inline void insw(uint16_t port, void *addr, unsigned long count)
  98{
  99        __asm__ __volatile__ (
 100                "cld ; rep ; insw " 
 101                : "=D" (addr), "=c" (count)
 102                : "d"(port), "0"(addr), "1" (count)
 103                );
 104}
 105static inline void insl(uint16_t port, void *addr, unsigned long count)
 106{
 107        __asm__ __volatile__ (
 108                "cld ; rep ; insl " 
 109                : "=D" (addr), "=c" (count)
 110                : "d"(port), "0"(addr), "1" (count)
 111                );
 112}
 113static inline void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg)
 114{
 115        outb(reg, port);
 116        outb(value, port +1);
 117}
 118static inline unsigned char pnp_read_config(unsigned char port, unsigned char reg)
 119{
 120        outb(reg, port);
 121        return inb(port +1);
 122}
 123static inline void pnp_set_logical_device(unsigned char port, int device)
 124{
 125        pnp_write_config(port, device, 0x07);
 126}
 127static inline void pnp_set_enable(unsigned char port, int enable)
 128{
 129        pnp_write_config(port, enable?0x1:0x0, 0x30);
 130}
 131static inline int pnp_read_enable(unsigned char port)
 132{
 133        return !!pnp_read_config(port, 0x30);
 134}
 135static inline void pnp_set_iobase0(unsigned char port, unsigned iobase)
 136{
 137        pnp_write_config(port, (iobase >> 8) & 0xff, 0x60);
 138        pnp_write_config(port, iobase & 0xff, 0x61);
 139}
 140static inline void pnp_set_iobase1(unsigned char port, unsigned iobase)
 141{
 142        pnp_write_config(port, (iobase >> 8) & 0xff, 0x62);
 143        pnp_write_config(port, iobase & 0xff, 0x63);
 144}
 145static inline void pnp_set_irq0(unsigned char port, unsigned irq)
 146{
 147        pnp_write_config(port, irq, 0x70);
 148}
 149static inline void pnp_set_irq1(unsigned char port, unsigned irq)
 150{
 151        pnp_write_config(port, irq, 0x72);
 152}
 153static inline void pnp_set_drq(unsigned char port, unsigned drq)
 154{
 155        pnp_write_config(port, drq & 0xff, 0x74);
 156}
 157static void hlt(void)
 158{
 159        __builtin_hlt();
 160}
 161typedef __builtin_div_t div_t;
 162typedef __builtin_ldiv_t ldiv_t;
 163typedef __builtin_udiv_t udiv_t;
 164typedef __builtin_uldiv_t uldiv_t;
 165static div_t div(int numer, int denom)
 166{
 167        return __builtin_div(numer, denom);
 168}
 169static ldiv_t ldiv(long numer, long denom)
 170{
 171        return __builtin_ldiv(numer, denom);
 172}
 173static udiv_t udiv(unsigned numer, unsigned denom)
 174{
 175        return __builtin_udiv(numer, denom);
 176}
 177static uldiv_t uldiv(unsigned long numer, unsigned long denom)
 178{
 179        return __builtin_uldiv(numer, denom);
 180}
 181int log2(int value)
 182{
 183         
 184        return __builtin_bsr(value);
 185}
 186typedef unsigned device_t;
 187static unsigned char pci_read_config8(device_t dev, unsigned where)
 188{
 189        unsigned addr;
 190        addr = dev | where;
 191        outl(0x80000000 | (addr & ~3), 0xCF8);
 192        return inb(0xCFC + (addr & 3));
 193}
 194static unsigned short pci_read_config16(device_t dev, unsigned where)
 195{
 196        unsigned addr;
 197        addr = dev | where;
 198        outl(0x80000000 | (addr & ~3), 0xCF8);
 199        return inw(0xCFC + (addr & 2));
 200}
 201static unsigned int pci_read_config32(device_t dev, unsigned where)
 202{
 203        unsigned addr;
 204        addr = dev | where;
 205        outl(0x80000000 | (addr & ~3), 0xCF8);
 206        return inl(0xCFC);
 207}
 208static void pci_write_config8(device_t dev, unsigned where, unsigned char value)
 209{
 210        unsigned addr;
 211        addr = dev | where;
 212        outl(0x80000000 | (addr & ~3), 0xCF8);
 213        outb(value, 0xCFC + (addr & 3));
 214}
 215static void pci_write_config16(device_t dev, unsigned where, unsigned short value)
 216{
 217        unsigned addr;
 218        addr = dev | where;
 219        outl(0x80000000 | (addr & ~3), 0xCF8);
 220        outw(value, 0xCFC + (addr & 2));
 221}
 222static void pci_write_config32(device_t dev, unsigned where, unsigned int value)
 223{
 224        unsigned addr;
 225        addr = dev | where;
 226        outl(0x80000000 | (addr & ~3), 0xCF8);
 227        outl(value, 0xCFC);
 228}
 229static device_t pci_locate_device(unsigned pci_id, device_t dev)
 230{
 231        for(; dev <= ( ((( 255 ) & 0xFF) << 16) | (((  31 ) & 0x1f) << 11) | (((  7 )  & 0x7) << 8)) ; dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8)) ) {
 232                unsigned int id;
 233                id = pci_read_config32(dev, 0);
 234                if (id == pci_id) {
 235                        return dev;
 236                }
 237        }
 238        return (0xffffffffU) ;
 239}
 240 
 241 
 242 
 243 
 244 
 245static int uart_can_tx_byte(void)
 246{
 247        return inb(1016  + 0x05 ) & 0x20;
 248}
 249static void uart_wait_to_tx_byte(void)
 250{
 251        while(!uart_can_tx_byte())
 252                ;
 253}
 254static void uart_wait_until_sent(void)
 255{
 256        while(!(inb(1016  + 0x05 ) & 0x40)) 
 257                ;
 258}
 259static void uart_tx_byte(unsigned char data)
 260{
 261        uart_wait_to_tx_byte();
 262        outb(data, 1016  + 0x00 );
 263         
 264        uart_wait_until_sent();
 265}
 266static void uart_init(void)
 267{
 268         
 269        outb(0x0, 1016  + 0x01 );
 270         
 271        outb(0x01, 1016  + 0x02 );
 272         
 273        outb(0x80 | 3  , 1016  + 0x03 );
 274        outb((115200/ 115200 )  & 0xFF,   1016  + 0x00 );
 275        outb(((115200/ 115200 )  >> 8) & 0xFF,    1016  + 0x01 );
 276        outb(3  , 1016  + 0x03 );
 277}
 278 
 279static void __console_tx_byte(unsigned char byte)
 280{
 281        uart_tx_byte(byte);
 282}
 283static void __console_tx_nibble(unsigned nibble)
 284{
 285        unsigned char digit;
 286        digit = nibble + '0';
 287        if (digit > '9') {
 288                digit += 39;
 289        }
 290        __console_tx_byte(digit);
 291}
 292static void __console_tx_char(int loglevel, unsigned char byte)
 293{
 294        if (8   > loglevel) {
 295                uart_tx_byte(byte);
 296        }
 297}
 298static void __console_tx_hex8(int loglevel, unsigned char value)
 299{
 300        if (8   > loglevel) {
 301                __console_tx_nibble((value >>  4U) & 0x0fU);
 302                __console_tx_nibble(value & 0x0fU);
 303        }
 304}
 305static void __console_tx_hex16(int loglevel, unsigned short value)
 306{
 307        if (8   > loglevel) {
 308                __console_tx_nibble((value >> 12U) & 0x0fU);
 309                __console_tx_nibble((value >>  8U) & 0x0fU);
 310                __console_tx_nibble((value >>  4U) & 0x0fU);
 311                __console_tx_nibble(value & 0x0fU);
 312        }
 313}
 314static void __console_tx_hex32(int loglevel, unsigned int value)
 315{
 316        if (8   > loglevel) {
 317                __console_tx_nibble((value >> 28U) & 0x0fU);
 318                __console_tx_nibble((value >> 24U) & 0x0fU);
 319                __console_tx_nibble((value >> 20U) & 0x0fU);
 320                __console_tx_nibble((value >> 16U) & 0x0fU);
 321                __console_tx_nibble((value >> 12U) & 0x0fU);
 322                __console_tx_nibble((value >>  8U) & 0x0fU);
 323                __console_tx_nibble((value >>  4U) & 0x0fU);
 324                __console_tx_nibble(value & 0x0fU);
 325        }
 326}
 327
 328static void do_console_tx_string(const char *str) __attribute__((noinline))
 329{
 330        unsigned char ch;
 331        while((ch = *str++) != '\0') {
 332                __console_tx_byte(ch);
 333        }
 334}
 335static void __console_tx_string(int loglevel, const char *str)
 336{
 337        if (8   > loglevel) {
 338                do_console_tx_string(str);
 339        }
 340}
 341static void print_emerg_char(unsigned char byte) { __console_tx_char(0 , byte); }
 342static void print_emerg_hex8(unsigned char value){ __console_tx_hex8(0 , value); }
 343static void print_emerg_hex16(unsigned short value){ __console_tx_hex16(0 , value); }
 344static void print_emerg_hex32(unsigned int value) { __console_tx_hex32(0 , value); }
 345static void print_emerg(const char *str) { __console_tx_string(0 , str); }
 346static void print_alert_char(unsigned char byte) { __console_tx_char(1 , byte); }
 347static void print_alert_hex8(unsigned char value) { __console_tx_hex8(1 , value); }
 348static void print_alert_hex16(unsigned short value){ __console_tx_hex16(1 , value); }
 349static void print_alert_hex32(unsigned int value) { __console_tx_hex32(1 , value); }
 350static void print_alert(const char *str) { __console_tx_string(1 , str); }
 351static void print_crit_char(unsigned char byte) { __console_tx_char(2 , byte); }
 352static void print_crit_hex8(unsigned char value) { __console_tx_hex8(2 , value); }
 353static void print_crit_hex16(unsigned short value){ __console_tx_hex16(2 , value); }
 354static void print_crit_hex32(unsigned int value) { __console_tx_hex32(2 , value); }
 355static void print_crit(const char *str) { __console_tx_string(2 , str); }
 356static void print_err_char(unsigned char byte) { __console_tx_char(3 , byte); }
 357static void print_err_hex8(unsigned char value) { __console_tx_hex8(3 , value); }
 358static void print_err_hex16(unsigned short value){ __console_tx_hex16(3 , value); }
 359static void print_err_hex32(unsigned int value) { __console_tx_hex32(3 , value); }
 360static void print_err(const char *str) { __console_tx_string(3 , str); }
 361static void print_warning_char(unsigned char byte) { __console_tx_char(4 , byte); }
 362static void print_warning_hex8(unsigned char value) { __console_tx_hex8(4 , value); }
 363static void print_warning_hex16(unsigned short value){ __console_tx_hex16(4 , value); }
 364static void print_warning_hex32(unsigned int value) { __console_tx_hex32(4 , value); }
 365static void print_warning(const char *str) { __console_tx_string(4 , str); }
 366static void print_notice_char(unsigned char byte) { __console_tx_char(5 , byte); }
 367static void print_notice_hex8(unsigned char value) { __console_tx_hex8(5 , value); }
 368static void print_notice_hex16(unsigned short value){ __console_tx_hex16(5 , value); }
 369static void print_notice_hex32(unsigned int value) { __console_tx_hex32(5 , value); }
 370static void print_notice(const char *str) { __console_tx_string(5 , str); }
 371static void print_info_char(unsigned char byte) { __console_tx_char(6 , byte); }
 372static void print_info_hex8(unsigned char value) { __console_tx_hex8(6 , value); }
 373static void print_info_hex16(unsigned short value){ __console_tx_hex16(6 , value); }
 374static void print_info_hex32(unsigned int value) { __console_tx_hex32(6 , value); }
 375static void print_info(const char *str) { __console_tx_string(6 , str); }
 376static void print_debug_char(unsigned char byte) { __console_tx_char(7 , byte); }
 377static void print_debug_hex8(unsigned char value) { __console_tx_hex8(7 , value); }
 378static void print_debug_hex16(unsigned short value){ __console_tx_hex16(7 , value); }
 379static void print_debug_hex32(unsigned int value) { __console_tx_hex32(7 , value); }
 380static void print_debug(const char *str) { __console_tx_string(7 , str); }
 381static void print_spew_char(unsigned char byte) { __console_tx_char(8 , byte); }
 382static void print_spew_hex8(unsigned char value) { __console_tx_hex8(8 , value); }
 383static void print_spew_hex16(unsigned short value){ __console_tx_hex16(8 , value); }
 384static void print_spew_hex32(unsigned int value) { __console_tx_hex32(8 , value); }
 385static void print_spew(const char *str) { __console_tx_string(8 , str); }
 386static void console_init(void)
 387{
 388        static const char console_test[] = 
 389                "\r\n\r\nLinuxBIOS-"
 390                "1.1.4"  
 391                ".0Fallback"  
 392                " "
 393                "Thu Oct 9 20:29:48 MDT 2003"  
 394                " starting...\r\n";
 395        print_info(console_test);
 396}
 397static void die(const char *str)
 398{
 399        print_emerg(str);
 400        do {
 401                hlt();
 402        } while(1);
 403}
 404static void write_phys(unsigned long addr, unsigned long value)
 405{
 406        asm volatile(
 407                "movnti %1, (%0)"
 408                :  
 409                : "r" (addr), "r" (value)  
 410                :  
 411                );
 412}
 413static unsigned long read_phys(unsigned long addr)
 414{
 415        volatile unsigned long *ptr;
 416        ptr = (void *)addr;
 417        return *ptr;
 418}
 419static void ram_fill(unsigned long start, unsigned long stop)
 420{
 421        unsigned long addr;
 422         
 423        print_debug("DRAM fill: ");
 424        print_debug_hex32(start);
 425        print_debug("-");
 426        print_debug_hex32(stop);
 427        print_debug("\r\n");
 428        for(addr = start; addr < stop ; addr += 4) {
 429                 
 430                if (!(addr & 0xffff)) {
 431                        print_debug_hex32(addr);
 432                        print_debug("\r");
 433                }
 434                write_phys(addr, addr);
 435        };
 436         
 437        print_debug_hex32(addr);
 438        print_debug("\r\nDRAM filled\r\n");
 439}
 440static void ram_verify(unsigned long start, unsigned long stop)
 441{
 442        unsigned long addr;
 443         
 444        print_debug("DRAM verify: ");
 445        print_debug_hex32(start);
 446        print_debug_char('-');
 447        print_debug_hex32(stop);
 448        print_debug("\r\n");
 449        for(addr = start; addr < stop ; addr += 4) {
 450                unsigned long value;
 451                 
 452                if (!(addr & 0xffff)) {
 453                        print_debug_hex32(addr);
 454                        print_debug("\r");
 455                }
 456                value = read_phys(addr);
 457                if (value != addr) {
 458                         
 459                        print_err_hex32(addr);
 460                        print_err_char(':');
 461                        print_err_hex32(value);
 462                        print_err("\r\n");
 463                }
 464        }
 465         
 466        print_debug_hex32(addr);
 467        print_debug("\r\nDRAM verified\r\n");
 468}
 469void ram_check(unsigned long start, unsigned long stop)
 470{
 471        int result;
 472         
 473        print_debug("Testing DRAM : ");
 474        print_debug_hex32(start);
 475        print_debug("-");       
 476        print_debug_hex32(stop);
 477        print_debug("\r\n");
 478        ram_fill(start, stop);
 479        ram_verify(start, stop);
 480        print_debug("Done.\r\n");
 481}
 482static int enumerate_ht_chain(unsigned link)
 483{
 484         
 485        unsigned next_unitid, last_unitid;
 486        int reset_needed = 0;
 487        next_unitid = 1;
 488        do {
 489                uint32_t id;
 490                uint8_t hdr_type, pos;
 491                last_unitid = next_unitid;
 492                id = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , 0x00 );
 493                 
 494                if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
 495                        (((id >> 16) & 0xffff) == 0xffff) ||
 496                        (((id >> 16) & 0xffff) == 0x0000)) {
 497                        break;
 498                }
 499                hdr_type = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , 0x0e );
 500                pos = 0;
 501                hdr_type &= 0x7f;
 502                if ((hdr_type == 0 ) ||
 503                        (hdr_type == 1 )) {
 504                        pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , 0x34 );
 505                }
 506                while(pos != 0) {
 507                        uint8_t cap;
 508                        cap = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , pos + 0 );
 509                        if (cap == 0x08 ) {
 510                                uint16_t flags;
 511                                flags = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , pos + 2 );
 512                                if ((flags >> 13) == 0) {
 513                                        unsigned count;
 514                                        flags &= ~0x1f;
 515                                        flags |= next_unitid & 0x1f;
 516                                        count = (flags >> 5) & 0x1f;
 517                                        pci_write_config16(( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , pos + 2 , flags);
 518                                        next_unitid += count;
 519                                        break;
 520                                }
 521                        }
 522                        pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , pos + 1 );
 523                }
 524        } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
 525        return reset_needed;
 526}
 527static void enable_smbus(void)
 528{
 529        device_t dev;
 530        dev = pci_locate_device(((((  0x746b ) & 0xFFFF) << 16) | (( 0x1022 ) & 0xFFFF)) , 0);
 531        if (dev == (0xffffffffU) ) {
 532                die("SMBUS controller not found\r\n");
 533        }
 534        uint8_t enable;
 535        print_debug("SMBus controller enabled\r\n");
 536        pci_write_config32(dev, 0x58, 0x0f00  | 1);
 537        enable = pci_read_config8(dev, 0x41);
 538        pci_write_config8(dev, 0x41, enable | (1 << 7));
 539         
 540        outw(inw(0x0f00  + 0xe0 ), 0x0f00  + 0xe0 );
 541}
 542static inline void smbus_delay(void)
 543{
 544        outb(0x80, 0x80);
 545}
 546static int smbus_wait_until_ready(void)
 547{
 548        unsigned long loops;
 549        loops = (100*1000*10) ;
 550        do {
 551                unsigned short val;
 552                smbus_delay();
 553                val = inw(0x0f00  + 0xe0 );
 554                if ((val & 0x800) == 0) {
 555                        break;
 556                }
 557                if(loops == ((100*1000*10)  / 2)) {
 558                        outw(inw(0x0f00  + 0xe0 ), 
 559                                0x0f00  + 0xe0 );
 560                }
 561        } while(--loops);
 562        return loops?0:-2;
 563}
 564static int smbus_wait_until_done(void)
 565{
 566        unsigned long loops;
 567        loops = (100*1000*10) ;
 568        do {
 569                unsigned short val;
 570                smbus_delay();
 571                
 572                val = inw(0x0f00  + 0xe0 );
 573                if (((val & 0x8) == 0) | ((val & 0x437) != 0)) {
 574                        break;
 575                }
 576        } while(--loops);
 577        return loops?0:-3;
 578}
 579static int smbus_read_byte(unsigned device, unsigned address)
 580{
 581        unsigned char global_control_register;
 582        unsigned char global_status_register;
 583        unsigned char byte;
 584        if (smbus_wait_until_ready() < 0) {
 585                return -2;
 586        }
 587        
 588         
 589         
 590        outw(inw(0x0f00  + 0xe2 ) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), 0x0f00  + 0xe2 );
 591         
 592        outw(((device & 0x7f) << 1) | 1, 0x0f00  + 0xe4 );
 593         
 594        outb(address & 0xFF, 0x0f00  + 0xe8 );
 595         
 596        outw((inw(0x0f00  + 0xe2 ) & ~7) | (0x2), 0x0f00  + 0xe2 );
 597         
 598         
 599        outw(inw(0x0f00  + 0xe0 ), 0x0f00  + 0xe0 );
 600         
 601        outw(0, 0x0f00  + 0xe6 );
 602         
 603        outw((inw(0x0f00  + 0xe2 ) | (1 << 3)), 0x0f00  + 0xe2 );
 604         
 605        if (smbus_wait_until_done() < 0) {
 606                return -3;
 607        }
 608        global_status_register = inw(0x0f00  + 0xe0 );
 609         
 610        byte = inw(0x0f00  + 0xe6 ) & 0xff;
 611        if (global_status_register != (1 << 4)) {
 612                return -1;
 613        }
 614        return byte;
 615}
 616static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
 617{
 618        return;
 619}
 620struct mem_controller {
 621        unsigned node_id;
 622        device_t f0, f1, f2, f3;
 623        uint8_t channel0[4];
 624        uint8_t channel1[4];
 625};
 626typedef __builtin_msr_t msr_t;
 627static msr_t rdmsr(unsigned long index)
 628{
 629        return __builtin_rdmsr(index);
 630}
 631static void wrmsr(unsigned long index, msr_t msr)
 632{
 633        __builtin_wrmsr(index, msr.lo, msr.hi);
 634}
 635struct tsc_struct {
 636        unsigned lo;
 637        unsigned hi;
 638};
 639typedef struct tsc_struct tsc_t;
 640static tsc_t rdtsc(void)
 641{
 642        tsc_t res;
 643        asm ("rdtsc"
 644                : "=a" (res.lo), "=d"(res.hi)  
 645                :  
 646                :  
 647                );
 648        return res;
 649}
 650void init_timer(void)
 651{
 652         
 653        apic_write(0x320 , (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0));
 654         
 655        apic_write(0x3E0 , 0xB );
 656         
 657        apic_write(0x380 , 0xffffffff);
 658}
 659void udelay(unsigned usecs)
 660{
 661        uint32_t start, value, ticks;
 662         
 663        ticks = usecs * 200;
 664        start = apic_read(0x390 );
 665        do {
 666                value = apic_read(0x390 );
 667        } while((start - value) < ticks);
 668        
 669}
 670void mdelay(unsigned msecs)
 671{
 672        unsigned i;
 673        for(i = 0; i < msecs; i++) {
 674                udelay(1000);
 675        }
 676}
 677void delay(unsigned secs)
 678{
 679        unsigned i;
 680        for(i = 0; i < secs; i++) {
 681                mdelay(1000);
 682        }
 683}
 684int boot_cpu(void)
 685{
 686        volatile unsigned long *local_apic;
 687        unsigned long apic_id;
 688        int bsp;
 689        msr_t msr;
 690        msr = rdmsr(0x1b);
 691        bsp = !!(msr.lo & (1 << 8));
 692        return bsp;
 693}
 694static int cpu_init_detected(void)
 695{
 696        unsigned long htic;
 697        htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
 698        return !!(htic & (1<<6) );
 699}
 700static int bios_reset_detected(void)
 701{
 702        unsigned long htic;
 703        htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
 704        return (htic & (1<<4) ) && !(htic & (1<<5) );
 705}
 706static int cold_reset_detected(void)
 707{
 708        unsigned long htic;
 709        htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
 710        return !(htic & (1<<4) );
 711}
 712static void distinguish_cpu_resets(unsigned node_id)
 713{
 714        uint32_t htic;
 715        device_t device;
 716        device = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 + node_id ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ;
 717        htic = pci_read_config32(device, 0x6c );
 718        htic |= (1<<4)  | (1<<5)  | (1<<6) ;
 719        pci_write_config32(device, 0x6c , htic);
 720}
 721static void set_bios_reset(void)
 722{
 723        unsigned long htic;
 724        htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
 725        htic &= ~(1<<5) ;
 726        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c , htic);
 727}
 728static void print_debug_pci_dev(unsigned dev)
 729{
 730        print_debug("PCI: ");
 731        print_debug_hex8((dev >> 16) & 0xff);
 732        print_debug_char(':');
 733        print_debug_hex8((dev >> 11) & 0x1f);
 734        print_debug_char('.');
 735        print_debug_hex8((dev >> 8) & 7);
 736}
 737static void print_pci_devices(void)
 738{
 739        device_t dev;
 740        for(dev = ( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ; 
 741                dev <= ( ((( 0 ) & 0xFF) << 16) | (((  0x1f ) & 0x1f) << 11) | (((  0x7 )  & 0x7) << 8)) ; 
 742                dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8)) ) {
 743                uint32_t id;
 744                id = pci_read_config32(dev, 0x00 );
 745                if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
 746                        (((id >> 16) & 0xffff) == 0xffff) ||
 747                        (((id >> 16) & 0xffff) == 0x0000)) {
 748                        continue;
 749                }
 750                print_debug_pci_dev(dev);
 751                print_debug("\r\n");
 752        }
 753}
 754static void dump_pci_device(unsigned dev)
 755{
 756        int i;
 757        print_debug_pci_dev(dev);
 758        print_debug("\r\n");
 759        
 760        for(i = 0; i <= 255; i++) {
 761                unsigned char val;
 762                if ((i & 0x0f) == 0) {
 763                        print_debug_hex8(i);
 764                        print_debug_char(':');
 765                }
 766                val = pci_read_config8(dev, i);
 767                print_debug_char(' ');
 768                print_debug_hex8(val);
 769                if ((i & 0x0f) == 0x0f) {
 770                        print_debug("\r\n");
 771                }
 772        }
 773}
 774static void dump_pci_devices(void)
 775{
 776        device_t dev;
 777        for(dev = ( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ; 
 778                dev <= ( ((( 0 ) & 0xFF) << 16) | (((  0x1f ) & 0x1f) << 11) | (((  0x7 )  & 0x7) << 8)) ; 
 779                dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8)) ) {
 780                uint32_t id;
 781                id = pci_read_config32(dev, 0x00 );
 782                if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
 783                        (((id >> 16) & 0xffff) == 0xffff) ||
 784                        (((id >> 16) & 0xffff) == 0x0000)) {
 785                        continue;
 786                }
 787                dump_pci_device(dev);
 788        }
 789}
 790static void dump_spd_registers(const struct mem_controller *ctrl)
 791{
 792        int i;
 793        print_debug("\r\n");
 794        for(i = 0; i < 4; i++) {
 795                unsigned device;
 796                device = ctrl->channel0[i];
 797                if (device) {
 798                        int j;
 799                        print_debug("dimm: "); 
 800                        print_debug_hex8(i); 
 801                        print_debug(".0: ");
 802                        print_debug_hex8(device);
 803                        for(j = 0; j < 256; j++) {
 804                                int status;
 805                                unsigned char byte;
 806                                if ((j & 0xf) == 0) {
 807                                        print_debug("\r\n");
 808                                        print_debug_hex8(j);
 809                                        print_debug(": ");
 810                                }
 811                                status = smbus_read_byte(device, j);
 812                                if (status < 0) {
 813                                        print_debug("bad device\r\n");
 814                                        break;
 815                                }
 816                                byte = status & 0xff;
 817                                print_debug_hex8(byte);
 818                                print_debug_char(' ');
 819                        }
 820                        print_debug("\r\n");
 821                }
 822                device = ctrl->channel1[i];
 823                if (device) {
 824                        int j;
 825                        print_debug("dimm: "); 
 826                        print_debug_hex8(i); 
 827                        print_debug(".1: ");
 828                        print_debug_hex8(device);
 829                        for(j = 0; j < 256; j++) {
 830                                int status;
 831                                unsigned char byte;
 832                                if ((j & 0xf) == 0) {
 833                                        print_debug("\r\n");
 834                                        print_debug_hex8(j);
 835                                        print_debug(": ");
 836                                }
 837                                status = smbus_read_byte(device, j);
 838                                if (status < 0) {
 839                                        print_debug("bad device\r\n");
 840                                        break;
 841                                }
 842                                byte = status & 0xff;
 843                                print_debug_hex8(byte);
 844                                print_debug_char(' ');
 845                        }
 846                        print_debug("\r\n");
 847                }
 848        }
 849}
 850 
 851static unsigned int cpuid(unsigned int op)
 852{
 853        unsigned int ret;
 854        unsigned dummy2,dummy3,dummy4;
 855        asm volatile ( 
 856                "cpuid" 
 857                : "=a" (ret), "=b" (dummy2), "=c" (dummy3), "=d" (dummy4)
 858                : "a" (op)
 859                );
 860        return ret;
 861}
 862static int is_cpu_rev_a0(void)
 863{
 864        return (cpuid(1) & 0xffff) == 0x0f10;
 865}
 866static int is_cpu_pre_c0(void)
 867{
 868        return (cpuid(1) & 0xffef) < 0x0f48;
 869}
 870static void memreset_setup(void)
 871{
 872        if (is_cpu_pre_c0()) {
 873                 
 874                outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00  + 0xc0 + 28);
 875                 
 876                outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00  + 0xc0 + 29);
 877        }
 878        else {
 879                 
 880                outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00  + 0xc0 + 29);
 881        }
 882}
 883static void memreset(int controllers, const struct mem_controller *ctrl)
 884{
 885        if (is_cpu_pre_c0()) {
 886                udelay(800);
 887                 
 888                outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00  + 0xc0 + 28);
 889                udelay(90);
 890        }
 891}
 892static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
 893{
 894         
 895        uint32_t ret=0x00010101;  
 896        static const unsigned int rows_2p[2][2] = {
 897                { 0x00050101, 0x00010404 },
 898                { 0x00010404, 0x00050101 }
 899        };
 900        if(maxnodes>2) {
 901                print_debug("this mainboard is only designed for 2 cpus\r\n");
 902                maxnodes=2;
 903        }
 904        if (!(node>=maxnodes || row>=maxnodes)) {
 905                ret=rows_2p[node][row];
 906        }
 907        return ret;
 908}
 909static inline int spd_read_byte(unsigned device, unsigned address)
 910{
 911        return smbus_read_byte(device, address);
 912}
 913 
 914static void coherent_ht_mainboard(unsigned cpus)
 915{
 916}
 917 
 918void cpu_ldtstop(unsigned cpus)
 919{
 920        uint32_t tmp;
 921        device_t dev;
 922        unsigned cnt;
 923        for(cnt=0; cnt<cpus; cnt++) {
 924                 
 925                pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8)) ,0x81,0x23);
 926                 
 927                pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8)) ,0xd4,0x00000701);
 928                 
 929                pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8)) ,0xd8,0x00000000);
 930                 
 931                tmp=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 )  & 0x7) << 8)) ,0x90);
 932                pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 )  & 0x7) << 8)) ,0x90, tmp | (1<<24) );
 933        }
 934}
 935 
 936 
 937 
 938 
 939 
 940static void setup_resource_map(const unsigned int *register_values, int max)
 941{
 942        int i;
 943        print_debug("setting up resource map....\r\n");
 944        for(i = 0; i < max; i += 3) {
 945                device_t dev;
 946                unsigned where;
 947                unsigned long reg;
 948                dev = register_values[i] & ~0xff;
 949                where = register_values[i] & 0xff;
 950                reg = pci_read_config32(dev, where);
 951                reg &= register_values[i+1];
 952                reg |= register_values[i+2];
 953                pci_write_config32(dev, where, reg);
 954        }
 955        print_debug("done.\r\n");
 956}
 957static void setup_default_resource_map(void)
 958{
 959        static const unsigned int register_values[] = {
 960         
 961         
 962        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
 963        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
 964        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
 965        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
 966        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
 967        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
 968        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
 969        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
 970         
 971        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
 972        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
 973        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
 974        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
 975        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
 976        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
 977        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
 978        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
 979         
 980        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x84 ) & 0xFF)) , 0x00000048, 0x00000000,
 981        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x8C ) & 0xFF)) , 0x00000048, 0x00000000,
 982        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x94 ) & 0xFF)) , 0x00000048, 0x00000000,
 983        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x9C ) & 0xFF)) , 0x00000048, 0x00000000,
 984        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xA4 ) & 0xFF)) , 0x00000048, 0x00000000,
 985        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xAC ) & 0xFF)) , 0x00000048, 0x00000000,
 986        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xB4 ) & 0xFF)) , 0x00000048, 0x00000000,
 987        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xBC ) & 0xFF)) , 0x00000048, 0x00ffff00,
 988         
 989        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x80 ) & 0xFF)) , 0x000000f0, 0x00000000,
 990        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x88 ) & 0xFF)) , 0x000000f0, 0x00000000,
 991        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x90 ) & 0xFF)) , 0x000000f0, 0x00000000,
 992        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x98 ) & 0xFF)) , 0x000000f0, 0x00000000,
 993        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xA0 ) & 0xFF)) , 0x000000f0, 0x00000000,
 994        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xA8 ) & 0xFF)) , 0x000000f0, 0x00000000,
 995        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xB0 ) & 0xFF)) , 0x000000f0, 0x00000000,
 996        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xB8 ) & 0xFF)) , 0x000000f0, 0x00fc0003,
 997         
 998        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xC4 ) & 0xFF)) , 0xFE000FC8, 0x01fff000,
 999        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xCC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
1000        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xD4 ) & 0xFF)) , 0xFE000FC8, 0x00000000,
1001        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xDC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
1002         
1003        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xC0 ) & 0xFF)) , 0xFE000FCC, 0x00000003,
1004        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xC8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
1005        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xD0 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
1006        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xD8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
1007         
1008        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xE0 ) & 0xFF)) , 0x0000FC88, 0xff000003,
1009        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xE4 ) & 0xFF)) , 0x0000FC88, 0x00000000,
1010        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xE8 ) & 0xFF)) , 0x0000FC88, 0x00000000,
1011        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xEC ) & 0xFF)) , 0x0000FC88, 0x00000000,
1012        };
1013        int max;
1014        max = sizeof(register_values)/sizeof(register_values[0]);
1015        setup_resource_map(register_values, max);
1016}
1017static void sdram_set_registers(const struct mem_controller *ctrl)
1018{
1019        static const unsigned int register_values[] = {
1020         
1021         
1022        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
1023        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
1024        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
1025        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
1026        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
1027        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
1028        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
1029        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
1030         
1031        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1032        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1033        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1034        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1035        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1036        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1037        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1038        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1039         
1040        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x40 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1041        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x44 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1042        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x48 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1043        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x4C ) & 0xFF)) , 0x001f01fe, 0x00000000,
1044        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x50 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1045        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x54 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1046        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1047        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x001f01fe, 0x00000000,
1048         
1049        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1050        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x64 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1051        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x68 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1052        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x6C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1053        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x70 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1054        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x74 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1055        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x78 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1056        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x7C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1057         
1058        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x80 ) & 0xFF)) , 0xffff8888, 0x00000000,
1059         
1060        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x88 ) & 0xFF)) , 0xe8088008, 0x02522001   ,
1061         
1062        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x8c ) & 0xFF)) , 0xff8fe08e, (0 << 20)|(0 << 8)|(0 << 4)|(0 << 0),
1063         
1064        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x90 ) & 0xFF)) , 0xf0000000, 
1065        (4 << 25)|(0 << 24)| 
1066        (0 << 23)|(0 << 22)|(0 << 21)|(0 << 20)| 
1067        (1 << 19)|(0 << 18)|(1 << 17)|(0 << 16)| 
1068        (2 << 14)|(0 << 13)|(0 << 12)| 
1069        (0 << 11)|(0 << 10)|(0 << 9)|(0 << 8)| 
1070        (0 << 3) |(0 << 1) |(0 << 0),
1071         
1072        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x94 ) & 0xFF)) , 0xc180f0f0,
1073        (0 << 29)|(0 << 28)|(0 << 27)|(0 << 26)|(0 << 25)|
1074        (0 << 20)|(0 << 19)|(3  << 16)|(0 << 8)|(0 << 0),
1075         
1076        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x98 ) & 0xFF)) , 0xfc00ffff, 0x00000000,
1077         
1078        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0xffe0e0e0, 0x00000000,
1079         
1080        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x0000003e, 0x00000000,
1081         
1082        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0xffffff00, 0x00000000,
1083         
1084        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x94 ) & 0xFF)) , 0xffff8000, 0x00000f70,
1085        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x90 ) & 0xFF)) , 0xffffff80, 0x00000002,
1086        ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x98 ) & 0xFF)) , 0x0000000f, 0x00068300,
1087        };
1088        int i;
1089        int max;
1090        print_debug("setting up CPU");
1091        print_debug_hex8(ctrl->node_id);
1092        print_debug(" northbridge registers\r\n");
1093        max = sizeof(register_values)/sizeof(register_values[0]);
1094        for(i = 0; i < max; i += 3) {
1095                device_t dev;
1096                unsigned where;
1097                unsigned long reg;
1098                dev = (register_values[i] & ~0xff) - ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8))  + ctrl->f0;
1099                where = register_values[i] & 0xff;
1100                reg = pci_read_config32(dev, where);
1101                reg &= register_values[i+1];
1102                reg |= register_values[i+2];
1103                pci_write_config32(dev, where, reg);
1104        }
1105        print_debug("done.\r\n");
1106}
1107static int is_dual_channel(const struct mem_controller *ctrl)
1108{
1109        uint32_t dcl;
1110        dcl = pci_read_config32(ctrl->f2, 0x90 );
1111        return dcl & (1<<16) ;
1112}
1113static int is_opteron(const struct mem_controller *ctrl)
1114{
1115         
1116        uint32_t nbcap;
1117        nbcap = pci_read_config32(ctrl->f3, 0xE8 );
1118        return !!(nbcap & 0x0001 );
1119}
1120static int is_registered(const struct mem_controller *ctrl)
1121{
1122         
1123        uint32_t dcl;
1124        dcl = pci_read_config32(ctrl->f2, 0x90 );
1125        return !(dcl & (1<<18) );
1126}
1127struct dimm_size {
1128        unsigned long side1;
1129        unsigned long side2;
1130};
1131static struct dimm_size spd_get_dimm_size(unsigned device)
1132{
1133         
1134        struct dimm_size sz;
1135        int value, low;
1136        sz.side1 = 0;
1137        sz.side2 = 0;
1138         
1139        value = spd_read_byte(device, 3);        
1140        if (value < 0) goto out;
1141        sz.side1 += value & 0xf;
1142        value = spd_read_byte(device, 4);        
1143        if (value < 0) goto out;
1144        sz.side1 += value & 0xf;
1145        value = spd_read_byte(device, 17);       
1146        if (value < 0) goto out;
1147        sz.side1 += log2(value & 0xff);
1148         
1149        value = spd_read_byte(device, 7);        
1150        if (value < 0) goto out;
1151        value &= 0xff;
1152        value <<= 8;
1153        
1154        low = spd_read_byte(device, 6);  
1155        if (low < 0) goto out;
1156        value = value | (low & 0xff);
1157        sz.side1 += log2(value);
1158         
1159        value = spd_read_byte(device, 5);        
1160        if (value <= 1) goto out;
1161         
1162        sz.side2 = sz.side1;
1163        value = spd_read_byte(device, 3);        
1164        if (value < 0) goto out;
1165        if ((value & 0xf0) == 0) goto out;       
1166        sz.side2 -= (value & 0x0f);              
1167        sz.side2 += ((value >> 4) & 0x0f);       
1168        value = spd_read_byte(device, 4);        
1169        if (value < 0) goto out;
1170        sz.side2 -= (value & 0x0f);              
1171        sz.side2 += ((value >> 4) & 0x0f);       
1172 out:
1173        return sz;
1174}
1175static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index)
1176{
1177        uint32_t base0, base1, map;
1178        uint32_t dch;
1179        if (sz.side1 != sz.side2) {
1180                sz.side2 = 0;
1181        }
1182        map = pci_read_config32(ctrl->f2, 0x80 );
1183        map &= ~(0xf << (index + 4));
1184         
1185        
1186        base0 = base1 = 0;
1187         
1188        if (sz.side1 >= (25 +3)) {
1189                map |= (sz.side1 - (25 + 3)) << (index *4);
1190                base0 = (1 << ((sz.side1 - (25 + 3)) + 21)) | 1;
1191        }
1192         
1193        if (sz.side2 >= (25 + 3)) {
1194                base1 = (1 << ((sz.side2 - (25 + 3)) + 21)) | 1;
1195        }
1196         
1197        if (is_dual_channel(ctrl)) {
1198                base0 = (base0 << 1) | (base0 & 1);
1199                base1 = (base1 << 1) | (base1 & 1);
1200        }
1201         
1202        base0 &= ~0x001ffffe;
1203        base1 &= ~0x001ffffe;
1204         
1205        pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+0)<<2), base0);
1206        pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+1)<<2), base1);
1207        pci_write_config32(ctrl->f2, 0x80 , map);
1208        
1209         
1210        if (base0) {
1211                dch = pci_read_config32(ctrl->f2, 0x94 );
1212                dch |= (1 << 26)  << index;
1213                pci_write_config32(ctrl->f2, 0x94 , dch);
1214        }
1215}
1216static void spd_set_ram_size(const struct mem_controller *ctrl)
1217{
1218        int i;
1219        
1220        for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1221                struct dimm_size sz;
1222                sz = spd_get_dimm_size(ctrl->channel0[i]);
1223                set_dimm_size(ctrl, sz, i);
1224        }
1225}
1226static void route_dram_accesses(const struct mem_controller *ctrl,
1227        unsigned long base_k, unsigned long limit_k)
1228{
1229         
1230        unsigned node_id;
1231        unsigned limit;
1232        unsigned base;
1233        unsigned index;
1234        unsigned limit_reg, base_reg;
1235        device_t device;
1236        node_id = ctrl->node_id;
1237        index = (node_id << 3);
1238        limit = (limit_k << 2);
1239        limit &= 0xffff0000;
1240        limit -= 0x00010000;
1241        limit |= ( 0 << 8) | (node_id << 0);
1242        base = (base_k << 2);
1243        base &= 0xffff0000;
1244        base |= (0 << 8) | (1<<1) | (1<<0);
1245        limit_reg = 0x44 + index;
1246        base_reg = 0x40 + index;
1247        for(device = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ; device <= ( ((( 0 ) & 0xFF) << 16) | (((  0x1f ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ; device += ( ((( 0 ) & 0xFF) << 16) | (((  1 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ) {
1248                pci_write_config32(device, limit_reg, limit);
1249                pci_write_config32(device, base_reg, base);
1250        }
1251}
1252static void set_top_mem(unsigned tom_k)
1253{
1254         
1255        if (!tom_k) {
1256                set_bios_reset();
1257                print_debug("No memory - reset");
1258                 
1259                pci_write_config8(( ((( 0 ) & 0xFF) << 16) | (((  0x04 ) & 0x1f) << 11) | (((  3 )  & 0x7) << 8)) , 0x41, 0xf1);
1260                 
1261                outb(0x0e, 0x0cf9);
1262        }
1263         
1264        print_debug("RAM: 0x");
1265        print_debug_hex32(tom_k);
1266        print_debug(" KB\r\n");
1267         
1268        msr_t msr;
1269        msr.lo = (tom_k & 0x003fffff) << 10;
1270        msr.hi = (tom_k & 0xffc00000) >> 22;
1271        wrmsr(0xC001001D , msr);
1272         
1273        if (tom_k >= 0x003f0000) {
1274                tom_k = 0x3f0000;
1275        }
1276        msr.lo = (tom_k & 0x003fffff) << 10;
1277        msr.hi = (tom_k & 0xffc00000) >> 22;
1278        wrmsr(0xC001001A , msr);
1279}
1280static unsigned long interleave_chip_selects(const struct mem_controller *ctrl)
1281{
1282         
1283        static const uint32_t csbase_low[] = { 
1284                (1 << (13 - 4)),
1285                (1 << (14 - 4)),
1286                (1 << (14 - 4)), 
1287                (1 << (15 - 4)),
1288                (1 << (15 - 4)),
1289                (1 << (16 - 4)),
1290                (1 << (16 - 4)), 
1291        };
1292        uint32_t csbase_inc;
1293        int chip_selects, index;
1294        int bits;
1295        int dual_channel;
1296        unsigned common_size;
1297        uint32_t csbase, csmask;
1298         
1299        chip_selects = 0;
1300        common_size = 0;
1301        for(index = 0; index < 8; index++) {
1302                unsigned size;
1303                uint32_t value;
1304                
1305                value = pci_read_config32(ctrl->f2, 0x40  + (index << 2));
1306                
1307                 
1308                if (!(value & 1)) {
1309                        continue;
1310                }
1311                chip_selects++;
1312                size = value >> 21;
1313                if (common_size == 0) {
1314                        common_size = size;
1315                }
1316                 
1317                if (common_size != size) {
1318                        return 0;
1319                }
1320        }
1321         
1322        bits = log2(chip_selects);
1323        if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) {
1324                return 0;
1325                
1326        }
1327         
1328        if ((bits == 3) && (common_size == (1 << (32 - 3)))) {
1329                print_debug("8 4GB chip selects cannot be interleaved\r\n");
1330                return 0;
1331        }
1332         
1333        if (is_dual_channel(ctrl)) {
1334                csbase_inc = csbase_low[log2(common_size) - 1] << 1;
1335        } else {
1336                csbase_inc = csbase_low[log2(common_size)];
1337        }
1338         
1339        csbase = 0 | 1;
1340        csmask = (((common_size  << bits) - 1) << 21);
1341        csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc);
1342        for(index = 0; index < 8; index++) {
1343                uint32_t value;
1344                value = pci_read_config32(ctrl->f2, 0x40  + (index << 2));
1345                 
1346                if (!(value & 1)) {
1347                        continue;
1348                }
1349                pci_write_config32(ctrl->f2, 0x40  + (index << 2), csbase);
1350                pci_write_config32(ctrl->f2, 0x60  + (index << 2), csmask);
1351                csbase += csbase_inc;
1352        }
1353        
1354        print_debug("Interleaved\r\n");
1355         
1356        return common_size << (15 + bits);
1357}
1358static unsigned long order_chip_selects(const struct mem_controller *ctrl)
1359{
1360        unsigned long tom;
1361        
1362         
1363        tom = 0;
1364        for(;;) {
1365                 
1366                unsigned index, canidate;
1367                uint32_t csbase, csmask;
1368                unsigned size;
1369                csbase = 0;
1370                canidate = 0;
1371                for(index = 0; index < 8; index++) {
1372                        uint32_t value;
1373                        value = pci_read_config32(ctrl->f2, 0x40  + (index << 2));
1374                         
1375                        if (!(value & 1)) {
1376                                continue;
1377                        }
1378                        
1379                         
1380                        if (value <= csbase) {
1381                                continue;
1382                        }
1383                        
1384                         
1385                        if (tom & (1 << (index + 24))) {
1386                                continue;
1387                        }
1388                         
1389                        csbase = value;
1390                        canidate = index;
1391                }
1392                 
1393                if (csbase == 0) {
1394                        break;
1395                }
1396                 
1397                size = csbase >> 21;
1398                 
1399                tom |= (1 << (canidate + 24));
1400                 
1401                csbase = (tom << 21) | 1;
1402                 
1403                tom += size;
1404                 
1405                csmask = ((size -1) << 21);
1406                csmask |= 0xfe00;                
1407                 
1408                pci_write_config32(ctrl->f2, 0x40  + (canidate << 2), csbase);
1409                 
1410                pci_write_config32(ctrl->f2, 0x60  + (canidate << 2), csmask);
1411                
1412        }
1413         
1414        return (tom & ~0xff000000) << 15;
1415}
1416static void order_dimms(const struct mem_controller *ctrl)
1417{
1418        unsigned long tom, tom_k, base_k;
1419        unsigned node_id;
1420        tom_k = interleave_chip_selects(ctrl);
1421        if (!tom_k) {
1422                tom_k = order_chip_selects(ctrl);
1423        }
1424         
1425        base_k = 0;
1426        for(node_id = 0; node_id < ctrl->node_id; node_id++) {
1427                uint32_t limit, base;
1428                unsigned index;
1429                index = node_id << 3;
1430                base = pci_read_config32(ctrl->f1, 0x40 + index);
1431                 
1432                if ((base & 3) == 3) {
1433                        limit = pci_read_config32(ctrl->f1, 0x44 + index);
1434                        base_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
1435                }
1436        }
1437        tom_k += base_k;
1438        route_dram_accesses(ctrl, base_k, tom_k);
1439        set_top_mem(tom_k);
1440}
1441static void disable_dimm(const struct mem_controller *ctrl, unsigned index)
1442{
1443        print_debug("disabling dimm"); 
1444        print_debug_hex8(index); 
1445        print_debug("\r\n");
1446        pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+0)<<2), 0);
1447        pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+1)<<2), 0);
1448}
1449static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
1450{
1451        int i;
1452        int registered;
1453        int unbuffered;
1454        uint32_t dcl;
1455        unbuffered = 0;
1456        registered = 0;
1457        for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1458                int value;
1459                value = spd_read_byte(ctrl->channel0[i], 21);
1460                if (value < 0) {
1461                        disable_dimm(ctrl, i);
1462                        continue;
1463                }
1464                 
1465                if (value & (1 << 1)) {
1466                        registered = 1;
1467                } 
1468                 
1469                else {
1470                        unbuffered = 1;
1471                }
1472        }
1473        if (unbuffered && registered) {
1474                die("Mixed buffered and registered dimms not supported");
1475        }
1476        if (unbuffered && is_opteron(ctrl)) {
1477                die("Unbuffered Dimms not supported on Opteron");
1478        }
1479        dcl = pci_read_config32(ctrl->f2, 0x90 );
1480        dcl &= ~(1<<18) ;
1481        if (unbuffered) {
1482                dcl |= (1<<18) ;
1483        }
1484        pci_write_config32(ctrl->f2, 0x90 , dcl);
1485}
1486static void spd_enable_2channels(const struct mem_controller *ctrl)
1487{
1488        int i;
1489        uint32_t nbcap;
1490         
1491         
1492        static const unsigned addresses[] = {
1493                2,       
1494                3,       
1495                4,       
1496                5,       
1497                6,       
1498                7,       
1499                9,       
1500                11,      
1501                13,      
1502                17,      
1503                18,      
1504                21,      
1505                23,      
1506                26,      
1507                27,      
1508                28,      
1509                29,      
1510                30,      
1511                41,      
1512                42,      
1513        };
1514        nbcap = pci_read_config32(ctrl->f3, 0xE8 );
1515        if (!(nbcap & 0x0001 )) {
1516                return;
1517        }
1518        for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1519                unsigned device0, device1;
1520                int value0, value1;
1521                int j;
1522                device0 = ctrl->channel0[i];
1523                device1 = ctrl->channel1[i];
1524                if (!device1)
1525                        return;
1526                for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) {
1527                        unsigned addr;
1528                        addr = addresses[j];
1529                        value0 = spd_read_byte(device0, addr);
1530                        if (value0 < 0) {
1531                                break;
1532                        }
1533                        value1 = spd_read_byte(device1, addr);
1534                        if (value1 < 0) {
1535                                return;
1536                        }
1537                        if (value0 != value1) {
1538                                return;
1539                        }
1540                }
1541        }
1542        print_debug("Enabling dual channel memory\r\n");
1543        uint32_t dcl;
1544        dcl = pci_read_config32(ctrl->f2, 0x90 );
1545        dcl &= ~(1<<19) ;
1546        dcl |= (1<<16) ;
1547        pci_write_config32(ctrl->f2, 0x90 , dcl);
1548}
1549struct mem_param {
1550        uint8_t cycle_time;
1551        uint8_t divisor;  
1552        uint8_t tRC;
1553        uint8_t tRFC;
1554        uint32_t dch_memclk;
1555        uint16_t dch_tref4k, dch_tref8k;
1556        uint8_t  dtl_twr;
1557        char name[9];
1558};
1559static const struct mem_param *get_mem_param(unsigned min_cycle_time)
1560{
1561        static const struct mem_param speed[] = {
1562                {
1563                        .name       = "100Mhz\r\n",
1564                        .cycle_time = 0xa0,
1565                        .divisor    = (10 <<1),
1566                        .tRC        = 0x46,
1567                        .tRFC       = 0x50,
1568                        .dch_memclk = 0  << 20 ,
1569                        .dch_tref4k = 0x00 ,
1570                        .dch_tref8k = 0x08 ,
1571                        .dtl_twr    = 2,
1572                },
1573                {
1574                        .name       = "133Mhz\r\n",
1575                        .cycle_time = 0x75,
1576                        .divisor    = (7<<1)+1,
1577                        .tRC        = 0x41,
1578                        .tRFC       = 0x4B,
1579                        .dch_memclk = 2  << 20 ,
1580                        .dch_tref4k = 0x01 ,
1581                        .dch_tref8k = 0x09 ,
1582                        .dtl_twr    = 2,
1583                },
1584                {
1585                        .name       = "166Mhz\r\n",
1586                        .cycle_time = 0x60,
1587                        .divisor    = (6<<1),
1588                        .tRC        = 0x3C,
1589                        .tRFC       = 0x48,
1590                        .dch_memclk = 5  << 20 ,
1591                        .dch_tref4k = 0x02 ,
1592                        .dch_tref8k = 0x0A ,
1593                        .dtl_twr    = 3,
1594                },
1595                {
1596                        .name       = "200Mhz\r\n",
1597                        .cycle_time = 0x50,
1598                        .divisor    = (5<<1),
1599                        .tRC        = 0x37,
1600                        .tRFC       = 0x46,
1601                        .dch_memclk = 7  << 20 ,
1602                        .dch_tref4k = 0x03 ,
1603                        .dch_tref8k = 0x0B ,
1604                        .dtl_twr    = 3,
1605                },
1606                {
1607                        .cycle_time = 0x00,
1608                },
1609        };
1610        const struct mem_param *param;
1611        for(param = &speed[0]; param->cycle_time ; param++) {
1612                if (min_cycle_time > (param+1)->cycle_time) {
1613                        break;
1614                }
1615        }
1616        if (!param->cycle_time) {
1617                die("min_cycle_time to low");
1618        }
1619        print_debug(param->name);
1620        return param;
1621}
1622static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
1623{
1624         
1625        const struct mem_param *param;
1626        unsigned min_cycle_time, min_latency;
1627        int i;
1628        uint32_t value;
1629        static const int latency_indicies[] = { 26, 23, 9 };
1630        static const unsigned char min_cycle_times[] = {
1631                [0 ] = 0x50,  
1632                [1 ] = 0x60,  
1633                [2 ] = 0x75,  
1634                [3 ] = 0xa0,  
1635        };
1636        value = pci_read_config32(ctrl->f3, 0xE8 );
1637        min_cycle_time = min_cycle_times[(value >> 5 ) & 3 ];
1638        min_latency = 2;
1639         
1640        for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1641                int new_cycle_time, new_latency;
1642                int index;
1643                int latencies;
1644                int latency;
1645                 
1646                new_cycle_time = 0xa0;
1647                new_latency = 5;
1648                latencies = spd_read_byte(ctrl->channel0[i], 18);
1649                if (latencies <= 0) continue;
1650                 
1651                latency = log2(latencies) -2;
1652                 
1653                for(index = 0; index < 3; index++, latency++) {
1654                        int value;
1655                        if ((latency < 2) || (latency > 4) ||
1656                                (!(latencies & (1 << latency)))) {
1657                                continue;
1658                        }
1659                        value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
1660                        if (value < 0) {
1661                                continue;
1662                        }
1663                         
1664                        if ((value >= min_cycle_time) && (value < new_cycle_time)) {
1665                                new_cycle_time = value;
1666                                new_latency = latency;
1667                        }
1668                }
1669                if (new_latency > 4){
1670                        continue;
1671                }
1672                 
1673                if (new_cycle_time > min_cycle_time) {
1674                        min_cycle_time = new_cycle_time;
1675                }
1676                 
1677                if (new_latency > min_latency) {
1678                        min_latency = new_latency;
1679                }
1680        }
1681         
1682        
1683        for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1684                int latencies;
1685                int latency;
1686                int index;
1687                int value;
1688                int dimm;
1689                latencies = spd_read_byte(ctrl->channel0[i], 18);
1690                if (latencies <= 0) {
1691                        goto dimm_err;
1692                }
1693                 
1694                latency = log2(latencies) -2;
1695                 
1696                for(index = 0; index < 3; index++, latency++) {
1697                        if (!(latencies & (1 << latency))) {
1698                                continue;
1699                        }
1700                        if (latency == min_latency)
1701                                break;
1702                }
1703                 
1704                if ((latency != min_latency) || (index >= 3)) {
1705                        goto dimm_err;
1706                }
1707                
1708                 
1709                value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
1710                
1711                 
1712                if (value <= min_cycle_time) {
1713                        continue;
1714                }
1715                 
1716        dimm_err:
1717                disable_dimm(ctrl, i);
1718        }
1719         
1720        param = get_mem_param(min_cycle_time);
1721         
1722        value = pci_read_config32(ctrl->f2, 0x94 );
1723        value &= ~(0x7  << 20 );
1724        value |= param->dch_memclk;
1725        pci_write_config32(ctrl->f2, 0x94 , value);
1726        static const unsigned latencies[] = { 1 , 5 , 2  };
1727         
1728        value = pci_read_config32(ctrl->f2, 0x88 );
1729        value &= ~(0x7  << 0 );
1730        value |= latencies[min_latency - 2] << 0 ;
1731        pci_write_config32(ctrl->f2, 0x88 , value);
1732        
1733        return param;
1734}
1735static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1736{
1737        unsigned clocks, old_clocks;
1738        uint32_t dtl;
1739        int value;
1740        value = spd_read_byte(ctrl->channel0[i], 41);
1741        if (value < 0) return -1;
1742        if ((value == 0) || (value == 0xff)) {
1743                value = param->tRC;
1744        }
1745        clocks = ((value << 1) + param->divisor - 1)/param->divisor;
1746        if (clocks < 7 ) {
1747                clocks = 7 ;
1748        }
1749        if (clocks > 22 ) {
1750                return -1;
1751        }
1752        dtl = pci_read_config32(ctrl->f2, 0x88 );
1753        old_clocks = ((dtl >> 4 ) & 0xf ) + 7 ;
1754        if (old_clocks > clocks) {
1755                clocks = old_clocks;
1756        }
1757        dtl &= ~(0xf  << 4 );
1758        dtl |=  ((clocks - 7 ) << 4 );
1759        pci_write_config32(ctrl->f2, 0x88 , dtl);
1760        return 0;
1761}
1762static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1763{
1764        unsigned clocks, old_clocks;
1765        uint32_t dtl;
1766        int value;
1767        value = spd_read_byte(ctrl->channel0[i], 42);
1768        if (value < 0) return -1;
1769        if ((value == 0) || (value == 0xff)) {
1770                value = param->tRFC;
1771        }
1772        clocks = ((value << 1) + param->divisor - 1)/param->divisor;
1773        if (clocks < 9 ) {
1774                clocks = 9 ;
1775        }
1776        if (clocks > 24 ) {
1777                return -1;
1778        }
1779        dtl = pci_read_config32(ctrl->f2, 0x88 );
1780        old_clocks = ((dtl >> 8 ) & 0xf ) + 9 ;
1781        if (old_clocks > clocks) {
1782                clocks = old_clocks;
1783        }
1784        dtl &= ~(0xf  << 8 );
1785        dtl |= ((clocks - 9 ) << 8 );
1786        pci_write_config32(ctrl->f2, 0x88 , dtl);
1787        return 0;
1788}
1789static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1790{
1791        unsigned clocks, old_clocks;
1792        uint32_t dtl;
1793        int value;
1794        value = spd_read_byte(ctrl->channel0[i], 29);
1795        if (value < 0) return -1;
1796        clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
1797        if (clocks < 2 ) {
1798                clocks = 2 ;
1799        }
1800        if (clocks > 6 ) {
1801                return -1;
1802        }
1803        dtl = pci_read_config32(ctrl->f2, 0x88 );
1804        old_clocks = ((dtl >> 12 ) & 0x7 ) + 0 ;
1805        if (old_clocks > clocks) {
1806                clocks = old_clocks;
1807        }
1808        dtl &= ~(0x7  << 12 );
1809        dtl |= ((clocks - 0 ) << 12 );
1810        pci_write_config32(ctrl->f2, 0x88 , dtl);
1811        return 0;
1812}
1813static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1814{
1815        unsigned clocks, old_clocks;
1816        uint32_t dtl;
1817        int value;
1818        value = spd_read_byte(ctrl->channel0[i], 28);
1819        if (value < 0) return -1;
1820        clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
1821        if (clocks < 2 ) {
1822                clocks = 2 ;
1823        }
1824        if (clocks > 4 ) {
1825                return -1;
1826        }
1827        dtl = pci_read_config32(ctrl->f2, 0x88 );
1828        old_clocks = ((dtl >> 16 ) & 0x7 ) + 0 ;
1829        if (old_clocks > clocks) {
1830                clocks = old_clocks;
1831        }
1832        dtl &= ~(0x7  << 16 );
1833        dtl |= ((clocks - 0 ) << 16 );
1834        pci_write_config32(ctrl->f2, 0x88 , dtl);
1835        return 0;
1836}
1837static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1838{
1839        unsigned clocks, old_clocks;
1840        uint32_t dtl;
1841        int value;
1842        value = spd_read_byte(ctrl->channel0[i], 30);
1843        if (value < 0) return -1;
1844        clocks = ((value << 1) + param->divisor - 1)/param->divisor;
1845        if (clocks < 5 ) {
1846                clocks = 5 ;
1847        }
1848        if (clocks > 15 ) {
1849                return -1;
1850        }
1851        dtl = pci_read_config32(ctrl->f2, 0x88 );
1852        old_clocks = ((dtl >> 20 ) & 0xf ) + 0 ;
1853        if (old_clocks > clocks) {
1854                clocks = old_clocks;
1855        }
1856        dtl &= ~(0xf  << 20 );
1857        dtl |= ((clocks - 0 ) << 20 );
1858        pci_write_config32(ctrl->f2, 0x88 , dtl);
1859        return 0;
1860}
1861static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1862{
1863        unsigned clocks, old_clocks;
1864        uint32_t dtl;
1865        int value;
1866        value = spd_read_byte(ctrl->channel0[i], 27);
1867        if (value < 0) return -1;
1868        clocks = (value + ((param->divisor & 0xff) << 1) - 1)/((param->divisor & 0xff) << 1);
1869        if (clocks < 2 ) {
1870                clocks = 2 ;
1871        }
1872        if (clocks > 6 ) {
1873                return -1;
1874        }
1875        dtl = pci_read_config32(ctrl->f2, 0x88 );
1876        old_clocks = ((dtl >> 24 ) & 0x7 ) + 0 ;
1877        if (old_clocks > clocks) {
1878                clocks = old_clocks;
1879        }
1880        dtl &= ~(0x7  << 24 );
1881        dtl |= ((clocks - 0 ) << 24 );
1882        pci_write_config32(ctrl->f2, 0x88 , dtl);
1883        return 0;
1884}
1885static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param)
1886{
1887        uint32_t dtl;
1888        dtl = pci_read_config32(ctrl->f2, 0x88 );
1889        dtl &= ~(0x1  << 28 );
1890        dtl |= (param->dtl_twr - 2 ) << 28 ;
1891        pci_write_config32(ctrl->f2, 0x88 , dtl);
1892}
1893static void init_Tref(const struct mem_controller *ctrl, const struct mem_param *param)
1894{
1895        uint32_t dth;
1896        dth = pci_read_config32(ctrl->f2, 0x8c );
1897        dth &= ~(0x1f  << 8 );
1898        dth |= (param->dch_tref4k << 8 );
1899        pci_write_config32(ctrl->f2, 0x8c , dth);
1900}
1901static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1902{
1903        uint32_t dth;
1904        int value;
1905        unsigned tref, old_tref;
1906        value = spd_read_byte(ctrl->channel0[i], 3);
1907        if (value < 0) return -1;
1908        value &= 0xf;
1909        tref = param->dch_tref8k;
1910        if (value == 12) {
1911                tref = param->dch_tref4k;
1912        }
1913        dth = pci_read_config32(ctrl->f2, 0x8c );
1914        old_tref = (dth >> 8 ) & 0x1f ;
1915        if ((value == 12) && (old_tref == param->dch_tref4k)) {
1916                tref = param->dch_tref4k;
1917        } else {
1918                tref = param->dch_tref8k;
1919        }
1920        dth &= ~(0x1f  << 8 );
1921        dth |= (tref << 8 );
1922        pci_write_config32(ctrl->f2, 0x8c , dth);
1923        return 0;
1924}
1925static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1926{
1927        uint32_t dcl;
1928        int value;
1929        int dimm;
1930        value = spd_read_byte(ctrl->channel0[i], 13);
1931        if (value < 0) {
1932                return -1;
1933        }
1934        dimm = i;
1935        dimm += 20 ;
1936        dcl = pci_read_config32(ctrl->f2, 0x90 );
1937        dcl &= ~(1 << dimm);
1938        if (value == 4) {
1939                dcl |= (1 << dimm);
1940        }
1941        pci_write_config32(ctrl->f2, 0x90 , dcl);
1942        return 0;
1943}
1944static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1945{
1946        uint32_t dcl;
1947        int value;
1948        value = spd_read_byte(ctrl->channel0[i], 11);
1949        if (value < 0) {
1950                return -1;
1951        }
1952        if (value != 2) {
1953                dcl = pci_read_config32(ctrl->f2, 0x90 );
1954                dcl &= ~(1<<17) ;
1955                pci_write_config32(ctrl->f2, 0x90 , dcl);
1956        }
1957        return 0;
1958}
1959static int count_dimms(const struct mem_controller *ctrl)
1960{
1961        int dimms;
1962        unsigned index;
1963        dimms = 0;
1964        for(index = 0; index < 8; index += 2) {
1965                uint32_t csbase;
1966                csbase = pci_read_config32(ctrl->f2, (0x40  + index << 2));
1967                if (csbase & 1) {
1968                        dimms += 1;
1969                }
1970        }
1971        return dimms;
1972}
1973static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param)
1974{
1975        uint32_t dth;
1976        unsigned clocks;
1977        clocks = 1;  
1978        dth = pci_read_config32(ctrl->f2, 0x8c );
1979        dth &= ~(0x1  << 0 );
1980        dth |= ((clocks - 1 ) << 0 );
1981        pci_write_config32(ctrl->f2, 0x8c , dth);
1982}
1983static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param)
1984{
1985        uint32_t dth, dtl;
1986        unsigned divisor;
1987        unsigned latency;
1988        unsigned clocks;
1989        clocks = 0;
1990        dtl = pci_read_config32(ctrl->f2, 0x88 );
1991        latency = (dtl >> 0 ) & 0x7 ;
1992        divisor = param->divisor;
1993        if (is_opteron(ctrl)) {
1994                if (latency == 1 ) {
1995                        if (divisor == ((6 << 0) + 0)) {
1996                                 
1997                                clocks = 3;
1998                        }
1999                        else if (divisor > ((6 << 0)+0)) {
2000                                 
2001                                clocks = 2;
2002                        }
2003                }
2004                else if (latency == 5 ) {
2005                        clocks = 3;
2006                }
2007                else if (latency == 2 ) {
2008                        if (divisor == ((6 << 0)+0)) {
2009                                 
2010                                clocks = 4;
2011                        }
2012                        else if (divisor > ((6 << 0)+0)) {
2013                                 
2014                                clocks = 3;
2015                        }
2016                }
2017        }
2018        else   {
2019                if (is_registered(ctrl)) {
2020                        if (latency == 1 ) {
2021                                clocks = 2;
2022                        }
2023                        else if (latency == 5 ) {
2024                                clocks = 3;
2025                        }
2026                        else if (latency == 2 ) {
2027                                clocks = 3;
2028                        }
2029                }
2030                else  {
2031                        if (latency == 1 ) {
2032                                clocks = 3;
2033                        }
2034                        else if (latency == 5 ) {
2035                                clocks = 4;
2036                        }
2037                        else if (latency == 2 ) {
2038                                clocks = 4;
2039                        }
2040                }
2041        }
2042        if ((clocks < 1 ) || (clocks > 6 )) {
2043                die("Unknown Trwt");
2044        }
2045        
2046        dth = pci_read_config32(ctrl->f2, 0x8c );
2047        dth &= ~(0x7  << 4 );
2048        dth |= ((clocks - 1 ) << 4 );
2049        pci_write_config32(ctrl->f2, 0x8c , dth);
2050        return;
2051}
2052static void set_Twcl(const struct mem_controller *ctrl, const struct mem_param *param)
2053{
2054         
2055        uint32_t dth;
2056        unsigned clocks;
2057        if (is_registered(ctrl)) {
2058                clocks = 2;
2059        } else {
2060                clocks = 1;
2061        }
2062        dth = pci_read_config32(ctrl->f2, 0x8c );
2063        dth &= ~(0x7  << 20 );
2064        dth |= ((clocks - 1 ) << 20 );
2065        pci_write_config32(ctrl->f2, 0x8c , dth);
2066}
2067static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param)
2068{
2069        uint32_t dch;
2070        unsigned divisor;
2071        unsigned rdpreamble;
2072        divisor = param->divisor;
2073        dch = pci_read_config32(ctrl->f2, 0x94 );
2074        dch &= ~(0xf  << 8 );
2075        rdpreamble = 0;
2076        if (is_registered(ctrl)) {
2077                if (divisor == ((10 << 1)+0)) {
2078                         
2079                        rdpreamble = ((9 << 1)+ 0);
2080                }
2081                else if (divisor == ((7 << 1)+1)) {
2082                         
2083                        rdpreamble = ((8 << 1)+0);
2084                }
2085                else if (divisor == ((6 << 1)+0)) {
2086                         
2087                        rdpreamble = ((7 << 1)+1);
2088                }
2089                else if (divisor == ((5 << 1)+0)) {
2090                         
2091                        rdpreamble = ((7 << 1)+0);
2092                }
2093        }
2094        else {
2095                int slots;
2096                int i;
2097                slots = 0;
2098                for(i = 0; i < 4; i++) {
2099                        if (ctrl->channel0[i]) {
2100                                slots += 1;
2101                        }
2102                }
2103                if (divisor == ((10 << 1)+0)) {
2104                         
2105                        if (slots <= 2) {
2106                                 
2107                                rdpreamble = ((9 << 1)+0);
2108                        } else {
2109                                 
2110                                rdpreamble = ((14 << 1)+0);
2111                        }
2112                }
2113                else if (divisor == ((7 << 1)+1)) {
2114                         
2115                        if (slots <= 2) {
2116                                 
2117                                rdpreamble = ((7 << 1)+0);
2118                        } else {
2119                                 
2120                                rdpreamble = ((11 << 1)+0);
2121                        }
2122                }
2123                else if (divisor == ((6 << 1)+0)) {
2124                         
2125                        if (slots <= 2) {
2126                                 
2127                                rdpreamble = ((7 << 1)+0);
2128                        } else {
2129                                 
2130                                rdpreamble = ((9 << 1)+0);
2131                        }
2132                }
2133                else if (divisor == ((5 << 1)+0)) {
2134                         
2135                        if (slots <= 2) {
2136                                 
2137                                rdpreamble = ((5 << 1)+0);
2138                        } else {
2139                                 
2140                                rdpreamble = ((7 << 1)+0);
2141                        }
2142                }
2143        }
2144        if ((rdpreamble < ((2<<1)+0) ) || (rdpreamble > ((9<<1)+1) )) {
2145                die("Unknown rdpreamble");
2146        }
2147        dch |= (rdpreamble - ((2<<1)+0) ) << 8 ;
2148        pci_write_config32(ctrl->f2, 0x94 , dch);
2149}
2150static void set_max_async_latency(const struct mem_controller *ctrl, const struct mem_param *param)
2151{
2152        uint32_t dch;
2153        int i;
2154        unsigned async_lat;
2155        int dimms;
2156        dimms = count_dimms(ctrl);
2157        dch = pci_read_config32(ctrl->f2, 0x94 );
2158        dch &= ~(0xf  << 0 );
2159        async_lat = 0;
2160        if (is_registered(ctrl)) {
2161                if (dimms == 4) {
2162                         
2163                        async_lat = 9;
2164                } 
2165                else {
2166                         
2167                        async_lat = 8;
2168                }
2169        }
2170        else {
2171                if (dimms > 3) {
2172                        die("Too many unbuffered dimms");
2173                }
2174                else if (dimms == 3) {
2175                         
2176                        async_lat = 7;
2177                }
2178                else {
2179                         
2180                        async_lat = 6;
2181                }
2182        }
2183        dch |= ((async_lat - 0 ) << 0 );
2184        pci_write_config32(ctrl->f2, 0x94 , dch);
2185}
2186static void set_idle_cycle_limit(const struct mem_controller *ctrl, const struct mem_param *param)
2187{
2188        uint32_t dch;
2189         
2190        dch = pci_read_config32(ctrl->f2, 0x94 );
2191        dch &= ~(0x7  << 16 );
2192        dch |= 3  << 16 ;
2193        dch |= (1 << 19) ;
2194        pci_write_config32(ctrl->f2, 0x94 , dch);
2195}
2196static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param)
2197{
2198        int dimms;
2199        int i;
2200        int rc;
2201        
2202        init_Tref(ctrl, param);
2203        for(i = 0; (i < 4) && ctrl->channel0[i]; i++) {
2204                int rc;
2205                 
2206                if (update_dimm_Trc (ctrl, param, i) < 0) goto dimm_err;
2207                if (update_dimm_Trfc(ctrl, param, i) < 0) goto dimm_err;
2208                if (update_dimm_Trcd(ctrl, param, i) < 0) goto dimm_err;
2209                if (update_dimm_Trrd(ctrl, param, i) < 0) goto dimm_err;
2210                if (update_dimm_Tras(ctrl, param, i) < 0) goto dimm_err;
2211                if (update_dimm_Trp (ctrl, param, i) < 0) goto dimm_err;
2212                 
2213                if (update_dimm_Tref(ctrl, param, i) < 0) goto dimm_err;
2214                 
2215                if (update_dimm_x4 (ctrl, param, i) < 0) goto dimm_err;
2216                if (update_dimm_ecc(ctrl, param, i) < 0) goto dimm_err;
2217                continue;
2218        dimm_err:
2219                disable_dimm(ctrl, i);
2220                
2221        }
2222         
2223        set_Twr(ctrl, param);
2224         
2225        set_Twtr(ctrl, param);
2226        set_Trwt(ctrl, param);
2227        set_Twcl(ctrl, param);
2228         
2229        set_read_preamble(ctrl, param);
2230        set_max_async_latency(ctrl, param);
2231        set_idle_cycle_limit(ctrl, param);
2232}
2233static void sdram_set_spd_registers(const struct mem_controller *ctrl) 
2234{
2235        const struct mem_param *param;
2236        spd_enable_2channels(ctrl);
2237        spd_set_ram_size(ctrl);
2238        spd_handle_unbuffered_dimms(ctrl);
2239        param = spd_set_memclk(ctrl);
2240        spd_set_dram_timing(ctrl, param);
2241        order_dimms(ctrl);
2242}
2243static void sdram_enable(int controllers, const struct mem_controller *ctrl)
2244{
2245        int i;
2246         
2247        for(i = 0; i < controllers; i++) {
2248                uint32_t dch;
2249                dch = pci_read_config32(ctrl[i].f2, 0x94 );
2250                dch |= (1 << 25) ;
2251                pci_write_config32(ctrl[i].f2, 0x94 , dch);
2252        }
2253         
2254        memreset(controllers, ctrl);
2255        for(i = 0; i < controllers; i++) {
2256                uint32_t dcl;
2257                 
2258                dcl = pci_read_config32(ctrl[i].f2, 0x90 );
2259                if (dcl & (1<<17) ) {
2260                        uint32_t mnc;
2261                        print_debug("ECC enabled\r\n");
2262                        mnc = pci_read_config32(ctrl[i].f3, 0x44 );
2263                        mnc |= (1 << 22) ;
2264                        if (dcl & (1<<16) ) {
2265                                mnc |= (1 << 23) ;
2266                        }
2267                        pci_write_config32(ctrl[i].f3, 0x44 , mnc);
2268                }
2269                dcl |= (1<<3) ;
2270                pci_write_config32(ctrl[i].f2, 0x90 , dcl);
2271                dcl &= ~(1<<3) ;
2272                dcl &= ~(1<<0) ;
2273                dcl &= ~(1<<1) ;
2274                dcl &= ~(1<<2) ;
2275                dcl |= (1<<8) ;
2276                pci_write_config32(ctrl[i].f2, 0x90 , dcl);
2277        }
2278        for(i = 0; i < controllers; i++) {
2279                uint32_t dcl;
2280                print_debug("Initializing memory: ");
2281                int loops = 0;
2282                do {
2283                        dcl = pci_read_config32(ctrl[i].f2, 0x90 );
2284                        loops += 1;
2285                        if ((loops & 1023) == 0) {
2286                                print_debug(".");
2287                        }
2288                } while(((dcl & (1<<8) ) != 0) && (loops < 300000 ));
2289                if (loops >= 300000 ) {
2290                        print_debug(" failed\r\n");
2291                } else {
2292                        print_debug(" done\r\n");
2293                }
2294                if (dcl & (1<<17) ) {
2295                        print_debug("Clearing memory: ");
2296                        if (!is_cpu_pre_c0()) {
2297                                 
2298                                dcl &= ~((1<<11)  | (1<<10) );
2299                                pci_write_config32(ctrl[i].f2, 0x90 , dcl);
2300                                do {
2301                                        dcl = pci_read_config32(ctrl[i].f2, 0x90 );
2302                                } while(((dcl & (1<<11) ) == 0) || ((dcl & (1<<10) ) == 0) );
2303                        }
2304                        uint32_t base, last_scrub_k, scrub_k;
2305                        uint32_t cnt,zstart,zend;
2306                        msr_t msr,msr_201;
2307                         
2308                        pci_write_config32(ctrl[i].f3, 0x58 ,
2309                                (0  << 16) | (0  << 8) | (0  << 0));
2310                         
2311                        msr_201 = rdmsr(0x201);
2312                        zstart = pci_read_config32(ctrl[0].f1, 0x40 + (i*8));
2313                        zend = pci_read_config32(ctrl[0].f1, 0x44 + (i*8));
2314                        zstart >>= 16;
2315                        zend >>=16;
2316                        print_debug("addr ");
2317                        print_debug_hex32(zstart);
2318                        print_debug("-");
2319                        print_debug_hex32(zend);
2320                        print_debug("\r\n");
2321                        
2322                         
2323                        msr = rdmsr(0x2ff );
2324                        msr.lo &= ~(1<<10);
2325                        wrmsr(0x2ff , msr);
2326                         
2327                        msr = rdmsr(0xc0010015);
2328                        msr.lo |= (1<<17);
2329                        wrmsr(0xc0010015,msr);
2330                        for(;zstart<zend;zstart+=4) {
2331                                 
2332                                if(zstart == 0x0fc)
2333                                        continue;
2334                                
2335                                 
2336                                __asm__ volatile(
2337                                        "movl  %%cr0, %0\n\t"
2338                                        "orl  $0x40000000, %0\n\t"
2339                                        "movl  %0, %%cr0\n\t"
2340                                        :"=r" (cnt)
2341                                        );
2342                                
2343                                 
2344                                msr.lo = 1 + ((zstart&0x0ff)<<24);
2345                                msr.hi = (zstart&0x0ff00)>>8;
2346                                wrmsr(0x200,msr);
2347                                 
2348                                msr.hi = 0x000000ff;
2349                                msr.lo = 0xfc000800;
2350                                wrmsr(0x201,msr);
2351                                 
2352                                __asm__ volatile(
2353                                        "movl  %%cr0, %0\n\t"
2354                                        "andl  $0x9fffffff, %0\n\t"
2355                                        "movl  %0, %%cr0\n\t"   
2356                                        :"=r" (cnt)     
2357                                        );
2358                                 
2359                                msr.lo = (zstart&0xff) << 24;
2360                                msr.hi = (zstart&0xff00) >> 8;
2361                                wrmsr(0xc0000100,msr);
2362                                print_debug_char((zstart > 0x0ff)?'+':'-');     
2363                                        
2364                                 
2365                                __asm__ volatile(
2366                                        "1: \n\t"
2367                                        "movl %0, %%fs:(%1)\n\t"
2368                                        "addl $4,%1\n\t"
2369                                        "subl $1,%2\n\t"
2370                                        "jnz 1b\n\t"
2371                                        :
2372                                        : "a" (0), "D" (0), "c" (0x01000000)
2373                                        );                      
2374                        }
2375                        
2376                         
2377                        __asm__ volatile(
2378                                "movl  %%cr0, %0\n\t"
2379                                "orl  $0x40000000, %0\n\t"
2380                                "movl  %0, %%cr0\n\t"
2381                                :"=r" (cnt)     
2382                                );
2383                
2384                                
2385                        msr = rdmsr(0x2ff );
2386                        msr.lo |= 0x0400;
2387                        wrmsr(0x2ff , msr);
2388                         
2389                        msr.lo = 6;
2390                        msr.hi = 0;
2391                        wrmsr(0x200,msr);
2392                        wrmsr(0x201,msr_201);
2393                         
2394                        msr.lo = 0;
2395                        msr.hi = 0;
2396                        wrmsr(0xc0000100,msr);
2397                         
2398                        __asm__ volatile(
2399                                "movl  %%cr0, %0\n\t"
2400                                "andl  $0x9fffffff, %0\n\t"
2401                                "movl  %0, %%cr0\n\t"   
2402                                :"=r" (cnt)     
2403                                );
2404                        
2405                         
2406                        msr = rdmsr(0xc0010015);
2407                        msr.lo &= ~(1<<17);
2408                        wrmsr(0xc0010015,msr);
2409                         
2410                        base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3));
2411                        base &= 0xffff0000;
2412                         
2413                        pci_write_config32(ctrl[i].f3, 0x5C , base << 8);
2414                        pci_write_config32(ctrl[i].f3, 0x60 , base >> 24);
2415                         
2416                        pci_write_config32(ctrl[i].f3, 0x58 , 
2417                                (22  << 16) | (22  << 8) | (22  << 0));
2418                        print_debug("done\r\n");
2419                }
2420        }
2421}
2422 
2423 
2424 
2425 
2426 
2427typedef uint8_t u8;
2428typedef uint32_t u32;
2429typedef int8_t bool;
2430static void disable_probes(void)
2431{
2432         
2433         
2434        u32 val;
2435        print_debug("Disabling read/write/fill probes for UP... ");
2436        val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x68);
2437        val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
2438        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x68, val);
2439        print_debug("done.\r\n");
2440}
2441 
2442static void wait_ap_stop(u8 node) 
2443{
2444        unsigned long reg;
2445        unsigned long i;
2446        for(i=0;i< 1000 ;i++) {
2447                unsigned long regx;
2448                regx = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x6c);
2449                if((regx & (1<<4))==1) break;
2450        }
2451        reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x6c);
2452        reg &= ~(1<<4);   
2453        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6c, reg);
2454}
2455static void notify_bsp_ap_is_stopped(void)
2456{
2457        unsigned long reg;
2458        unsigned long apic_id;
2459        apic_id = *((volatile unsigned long *)(0xfee00000 + 0x020 ));
2460        apic_id >>= 24;
2461         
2462        if(apic_id != 0) {
2463                 
2464                reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6C);
2465                reg |= 1<<4;
2466                pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6C, reg);
2467        }
2468 
2469}
2470 
2471static void enable_routing(u8 node)
2472{
2473        u32 val;
2474         
2475         
2476        print_debug("Enabling routing table for node ");
2477        print_debug_hex32(node);
2478        val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6c);
2479        val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
2480        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6c, val);
2481 
2482        if(node!=0) {
2483                wait_ap_stop(node);
2484        }
2485 
2486        print_debug(" done.\r\n");
2487}
2488static void rename_temp_node(u8 node)
2489{
2490        uint32_t val;
2491        print_debug("Renaming current temp node to ");
2492        print_debug_hex32(node);
2493        val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x60);
2494        val &= (~7);   
2495        val |= node;    
2496        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x60, val);
2497        print_debug(" done.\r\n");
2498}
2499static bool check_connection(u8 src, u8 dest, u8 link)
2500{
2501         
2502        u32 val;
2503        
2504         
2505        val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ src  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x98+link);
2506        if ( (val&0x17) != 0x03)
2507                return 0;
2508         
2509        val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ dest  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0);
2510        if(val != 0x11001022)
2511                return 0;
2512        return 1;
2513}
2514static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2)
2515{
2516        static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
2517        static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
2518        uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
2519        uint8_t width_cap1, width_cap2, width_cap, width, ln_width1, ln_width2;
2520        uint8_t freq;
2521         
2522         
2523        freq_cap1  = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link1 + 0x0a );
2524        freq_cap2  = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link2 + 0x0a );
2525         
2526         
2527        freq = log2(freq_cap1 & freq_cap2 & 0xff);
2528         
2529        pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link1 + 0x09 , freq);
2530        pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link2 + 0x09 , freq);
2531         
2532        width_cap1 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,  0x80 + link1 + 6 );
2533        width_cap2 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,  0x80 + link2 + 6 );
2534         
2535        ln_width1 = link_width_to_pow2[width_cap1 & 7];
2536        ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
2537        if (ln_width1 > ln_width2) {
2538                ln_width1 = ln_width2;
2539        }
2540        width = pow2_to_link_width[ln_width1];
2541         
2542        ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
2543        ln_width2 = link_width_to_pow2[width_cap2 & 7];
2544        if (ln_width1 > ln_width2) {
2545                ln_width1 = ln_width2;
2546        }
2547        width |= pow2_to_link_width[ln_width1] << 4;
2548        
2549         
2550        pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link1 + 6  + 1, width);
2551         
2552        width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
2553        pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link2 + 6  + 1, width);
2554}
2555static void fill_row(u8 node, u8 row, u32 value)
2556{
2557        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x40+(row<<2), value);
2558}
2559static void setup_row(u8 source, u8 dest, u8 cpus)
2560{
2561        fill_row(source,dest,generate_row(source,dest,cpus));
2562}
2563static void setup_temp_row(u8 source, u8 dest, u8 cpus)
2564{
2565        fill_row(source,7,((generate_row( source,dest,cpus )&(~0x0f0000))|0x010000) );
2566}
2567static void setup_node(u8 node, u8 cpus)
2568{
2569        u8 row;
2570        for(row=0; row<cpus; row++)
2571                setup_row(node, row, cpus);
2572}
2573static void setup_remote_row(u8 source, u8 dest, u8 cpus)
2574{
2575        fill_row(7, dest, generate_row(source, dest, cpus));
2576}
2577static void setup_remote_node(u8 node, u8 cpus)
2578{
2579        static const uint8_t pci_reg[] = { 
2580                0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c, 
2581                0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
2582                0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
2583                0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
2584                0xc4, 0xcc, 0xd4, 0xdc,
2585                0xc0, 0xc8, 0xd0, 0xd8,
2586                0xe0, 0xe4, 0xe8, 0xec,
2587        };
2588        uint8_t row;
2589        int i;
2590        print_debug("setup_remote_node\r\n");
2591        for(row=0; row<cpus; row++)
2592                setup_remote_row(node, row, cpus);
2593         
2594        for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
2595                uint32_t value;
2596                uint8_t reg;
2597                reg = pci_reg[i];
2598                value = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0  ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8))  , reg);
2599                pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7  ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8))  , reg, value);
2600        }
2601        print_debug("setup_remote_done\r\n");
2602}
2603static u8 setup_uniprocessor(void)
2604{
2605        print_debug("Enabling UP settings\r\n");
2606        disable_probes();
2607        return 1;
2608}
2609static u8 setup_smp(void)
2610{
2611        u8 cpus=2;
2612        print_debug("Enabling SMP settings\r\n");
2613        setup_row(0,0,cpus);
2614         
2615        setup_temp_row(0,1,cpus);
2616        
2617        if (!check_connection(0, 7, 0x20  )) {
2618                print_debug("No connection to Node 1.\r\n");
2619                fill_row( 0 ,7,0x00010101 ) ;    
2620                setup_uniprocessor();    
2621                return 1;
2622        }
2623         
2624        optimize_connection(0, 0x20 , 7, 0x20 );
2625        setup_node(0, cpus);     
2626        setup_remote_node(1, cpus);   
2627        rename_temp_node(1);     
2628        enable_routing(1);       
2629        
2630        fill_row( 0 ,7,0x00010101 ) ;    
2631        
2632        print_debug_hex32(cpus);
2633        print_debug(" nodes initialized.\r\n");
2634        return cpus;
2635}
2636static unsigned detect_mp_capabilities(unsigned cpus)
2637{
2638        unsigned node, row, mask;
2639        bool mp_cap= (-1) ;
2640        print_debug("detect_mp_capabilities: ");
2641        print_debug_hex32(cpus);
2642        print_debug("\r\n");
2643        if (cpus>2)
2644                mask=0x06;       
2645        else
2646                mask=0x02;       
2647        for (node=0; node<cpus; node++) {
2648                if ((pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8))  , 0xe8) & mask)!=mask)
2649                        mp_cap= (0) ;
2650        }
2651        if (mp_cap)
2652                return cpus;
2653         
2654        print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
2655        for (node=cpus; node>0; node--)
2656            for (row=cpus; row>0; row--)
2657                fill_row(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node-1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , row-1, 0x00010101 );
2658        
2659        return setup_uniprocessor();
2660}
2661static void coherent_ht_finalize(unsigned cpus)
2662{
2663        int node;
2664        bool rev_a0;
2665        
2666         
2667        print_debug("coherent_ht_finalize\r\n");
2668        rev_a0= is_cpu_rev_a0();
2669        for (node=0; node<cpus; node++) {
2670                u32 val;
2671                val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x60);
2672                val &= (~0x000F0070);
2673                val |= ((cpus-1)<<16)|((cpus-1)<<4);
2674                pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x60,val);
2675                val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x68);
2676                val |= 0x00008000;
2677                pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x68,val);
2678                if (rev_a0) {
2679                        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x94,0);
2680                        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0xb4,0);
2681                        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0xd4,0);
2682                }
2683        }
2684        print_debug("done\r\n");
2685}
2686static int setup_coherent_ht_domain(void)
2687{
2688        unsigned cpus;
2689        int reset_needed = 0;
2690        enable_routing(0) ;
2691        cpus=setup_smp();
2692        cpus=detect_mp_capabilities(cpus);
2693        coherent_ht_finalize(cpus);
2694         
2695        coherent_ht_mainboard(cpus);
2696        return reset_needed;
2697}
2698void sdram_no_memory(void)
2699{
2700        print_err("No memory!!\r\n");
2701        while(1) { 
2702                hlt(); 
2703        }
2704}
2705 
2706void sdram_initialize(int controllers, const struct mem_controller *ctrl)
2707{
2708        int i;
2709         
2710        for(i = 0; i < controllers; i++) {
2711                print_debug("Ram1.");
2712                print_debug_hex8(i);
2713                print_debug("\r\n");
2714                sdram_set_registers(ctrl + i);
2715        }
2716         
2717        for(i = 0; i < controllers; i++) {
2718                print_debug("Ram2.");
2719                print_debug_hex8(i);
2720                print_debug("\r\n");
2721                sdram_set_spd_registers(ctrl + i);
2722        }
2723         
2724        print_debug("Ram3\r\n");
2725        sdram_enable(controllers, ctrl);
2726        print_debug("Ram4\r\n");
2727}
2728static void enable_lapic(void)
2729{
2730        msr_t msr;
2731        msr = rdmsr(0x1b);
2732        msr.hi &= 0xffffff00;
2733        msr.lo &= 0x000007ff;
2734        msr.lo |= 0xfee00000  | (1 << 11);
2735        wrmsr(0x1b, msr);
2736}
2737static void stop_this_cpu(void)
2738{
2739        unsigned apicid;
2740        apicid = apic_read(0x020 ) >> 24;
2741         
2742        apic_write(0x310 , (( apicid )<<24) );
2743        apic_write(0x300 , 0x08000  | 0x04000  | 0x00500 );
2744         
2745        apic_wait_icr_idle();
2746         
2747        apic_write(0x310 , (( apicid )<<24) );
2748        apic_write(0x300 ,  0x08000  | 0x00500 );
2749         
2750        apic_wait_icr_idle();
2751         
2752        for(;;) {
2753                hlt();
2754        }
2755}
2756static void pc87360_enable_serial(void)
2757{
2758        pnp_set_logical_device(0x2e , 0x03 );
2759        pnp_set_enable(0x2e , 1);
2760        pnp_set_iobase0(0x2e , 0x3f8);
2761}
2762static void main(void)
2763{
2764         
2765        static const struct mem_controller cpu[] = {
2766                {
2767                        .node_id = 0,
2768                        .f0 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ,
2769                        .f1 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ,
2770                        .f2 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 )  & 0x7) << 8)) ,
2771                        .f3 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 )  & 0x7) << 8)) ,
2772                        .channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 },
2773                        .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 },
2774                },
2775                {
2776                        .node_id = 1,
2777                        .f0 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ,
2778                        .f1 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ,
2779                        .f2 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  2 )  & 0x7) << 8)) ,
2780                        .f3 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  3 )  & 0x7) << 8)) ,
2781                        .channel0 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 },
2782                        .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 },
2783                },
2784        };
2785        if (cpu_init_detected()) {
2786                asm("jmp __cpu_reset");
2787        }
2788        enable_lapic();
2789        init_timer();
2790        if (!boot_cpu()) {
2791                stop_this_cpu();
2792        }
2793        pc87360_enable_serial();
2794        uart_init();
2795        console_init();
2796        setup_default_resource_map();
2797        setup_coherent_ht_domain();
2798        enumerate_ht_chain(0);
2799        distinguish_cpu_resets(0);
2800        
2801        enable_smbus();
2802        memreset_setup();
2803        sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
2804         
2805}
2806
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.