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