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