coreboot/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                }