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