diff options
Diffstat (limited to 'util/romcc/tests')
32 files changed, 5502 insertions, 8 deletions
diff --git a/util/romcc/tests/fail_test10.c b/util/romcc/tests/fail_test10.c new file mode 100644 index 0000000000..1993e0e59c --- /dev/null +++ b/util/romcc/tests/fail_test10.c @@ -0,0 +1,19 @@ + + +struct result { + int a, b, c, d; +}; + +struct big_arg { + int a, b; +}; +static struct result main(int a, int b, struct big_arg d) +{ + struct result result; + result.a = 1; + result.b = 1; + result.c = b + 1; + result.d = a + 1; + +} + diff --git a/util/romcc/tests/fail_test11.c b/util/romcc/tests/fail_test11.c new file mode 100644 index 0000000000..3252060cc8 --- /dev/null +++ b/util/romcc/tests/fail_test11.c @@ -0,0 +1,21 @@ + + +struct big_arg { + int x, y; +}; +struct result { + struct big_arg a; + int c, d; +}; + +static struct result main(int a, int b, int c, int d) +{ + struct result result; + result.a.x = d + 1; + result.a.y = c + 1; + result.c = b + 1; + result.d = a + 1; + + return result; +} + diff --git a/util/romcc/tests/fail_test9.c b/util/romcc/tests/fail_test9.c new file mode 100644 index 0000000000..a24ce9ea3e --- /dev/null +++ b/util/romcc/tests/fail_test9.c @@ -0,0 +1,9 @@ +typedef __builtin_msr_t msr_t; + +static msr_t rdmsr(unsigned long index) +{ + return __builtin_rdmsr(index); +} + +#warning "romcc should die gracefully here" + diff --git a/util/romcc/tests/hello_world1.c b/util/romcc/tests/hello_world1.c new file mode 100644 index 0000000000..6dd80d89b8 --- /dev/null +++ b/util/romcc/tests/hello_world1.c @@ -0,0 +1,128 @@ +void outb(unsigned char value, unsigned short port) +{ + __builtin_outb(value, port); +} + +unsigned char inb(unsigned short port) +{ + return __builtin_inb(port); +} + +/* Base Address */ +#ifndef TTYS0_BASE +#define TTYS0_BASE 0x3f8 +#endif + +#ifndef TTYS0_BAUD +#define TTYS0_BAUD 115200 +#endif + +#if ((115200%TTYS0_BAUD) != 0) +#error Bad ttys0 baud rate +#endif + +#if TTYS0_BAUD == 115200 +#define TTYS0_DIV (1) +#else +#define TTYS0_DIV (115200/TTYS0_BAUD) +#endif + +/* Line Control Settings */ +#ifndef TTYS0_LCS +/* Set 8bit, 1 stop bit, no parity */ +#define TTYS0_LCS 0x3 +#endif + +#define UART_LCS TTYS0_LCS + +/* Data */ +#define UART_RBR 0x00 +#define UART_TBR 0x00 + +/* Control */ +#define UART_IER 0x01 +#define UART_IIR 0x02 +#define UART_FCR 0x02 +#define UART_LCR 0x03 +#define UART_MCR 0x04 +#define UART_DLL 0x00 +#define UART_DLM 0x01 + +/* Status */ +#define UART_LSR 0x05 +#define UART_MSR 0x06 +#define UART_SCR 0x07 + +int uart_can_tx_byte(void) +{ + return inb(TTYS0_BASE + UART_LSR) & 0x20; +} + +void uart_wait_to_tx_byte(void) +{ + while(!uart_can_tx_byte()) + ; +} + +void uart_wait_until_sent(void) +{ + while(!(inb(TTYS0_BASE + UART_LSR) & 0x40)) + ; +} + +static void uart_tx_byte(unsigned char data) +{ + uart_wait_to_tx_byte(); + outb(data, TTYS0_BASE + UART_TBR); + /* Make certain the data clears the fifos */ + uart_wait_until_sent(); +} + + +void uart_init(void) +{ + /* disable interrupts */ + outb(0x0, TTYS0_BASE + UART_IER); + /* enable fifo's */ + outb(0x01, TTYS0_BASE + UART_FCR); + /* Set Baud Rate Divisor to 12 ==> 115200 Baud */ + outb(0x80 | UART_LCS, TTYS0_BASE + UART_LCR); + outb(TTYS0_DIV & 0xFF, TTYS0_BASE + UART_DLL); + outb((TTYS0_DIV >> 8) & 0xFF, TTYS0_BASE + UART_DLM); + outb(UART_LCS, TTYS0_BASE + UART_LCR); +} + + +void __console_tx_char(unsigned char byte) +{ + uart_tx_byte(byte); + +} + +void __console_tx_string(char *str) +{ + unsigned char ch; + while((ch = *str++) != '\0') { + __console_tx_char(ch); + } +} + + +void print_debug_char(unsigned char byte) { __console_tx_char(byte); } +void print_debug(char *str) { __console_tx_string(str); } + +void main(void) +{ + static const char msg[] = "hello world\r\n"; + uart_init(); +#if 0 + print_debug(msg); +#endif +#if 1 + print_debug("hello world\r\n"); + print_debug("how are you today\r\n"); +#endif + while(1) { + ; + } +} diff --git a/util/romcc/tests/include/linux_console.h b/util/romcc/tests/include/linux_console.h new file mode 100644 index 0000000000..861c701e5d --- /dev/null +++ b/util/romcc/tests/include/linux_console.h @@ -0,0 +1,136 @@ +#ifndef LINUX_CONSOLE_H +#define LINUX_CONSOLE_H + +#include "linux_syscall.h" + +static const char *addr_of_char(unsigned char ch) +{ + static const char byte[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + }; + return byte + ch; +} + +static void console_tx_byte(unsigned char ch) +{ + write(STDOUT_FILENO, addr_of_char(ch), 1); +} + +static inline void console_tx_nibble(unsigned nibble) +{ + unsigned char digit; + digit = nibble + '0'; + if (digit > '9') { + digit += 39; + } + console_tx_byte(digit); +} + +static void console_tx_char(unsigned char byte) +{ + console_tx_byte(byte); +} + +static void console_tx_hex8(unsigned char value) +{ + console_tx_nibble((value >> 4U) & 0x0fU); + console_tx_nibble(value & 0x0fU); +} + +static void console_tx_hex16(unsigned short value) +{ + console_tx_nibble((value >> 12U) & 0x0FU); + console_tx_nibble((value >> 8U) & 0x0FU); + console_tx_nibble((value >> 4U) & 0x0FU); + console_tx_nibble(value & 0x0FU); +} + +static void console_tx_hex32(unsigned int value) +{ + console_tx_nibble((value >> 28U) & 0x0FU); + console_tx_nibble((value >> 24U) & 0x0FU); + console_tx_nibble((value >> 20U) & 0x0FU); + console_tx_nibble((value >> 16U) & 0x0FU); + console_tx_nibble((value >> 12U) & 0x0FU); + console_tx_nibble((value >> 8U) & 0x0FU); + console_tx_nibble((value >> 4U) & 0x0FU); + console_tx_nibble(value & 0x0FU); +} + +static void console_tx_string(const char *str) +{ + unsigned char ch; + while((ch = *str++) != '\0') { + console_tx_byte(ch); + } +} + +static void print_emerg_char(unsigned char byte) { console_tx_char(byte); } +static void print_emerg_hex8(unsigned char value) { console_tx_hex8(value); } +static void print_emerg_hex16(unsigned short value){ console_tx_hex16(value); } +static void print_emerg_hex32(unsigned int value) { console_tx_hex32(value); } +static void print_emerg(const char *str) { console_tx_string(str); } + +static void print_warn_char(unsigned char byte) { console_tx_char(byte); } +static void print_warn_hex8(unsigned char value) { console_tx_hex8(value); } +static void print_warn_hex16(unsigned short value){ console_tx_hex16(value); } +static void print_warn_hex32(unsigned int value) { console_tx_hex32(value); } +static void print_warn(const char *str) { console_tx_string(str); } + +static void print_info_char(unsigned char byte) { console_tx_char(byte); } +static void print_info_hex8(unsigned char value) { console_tx_hex8(value); } +static void print_info_hex16(unsigned short value){ console_tx_hex16(value); } +static void print_info_hex32(unsigned int value) { console_tx_hex32(value); } +static void print_info(const char *str) { console_tx_string(str); } + +static void print_debug_char(unsigned char byte) { console_tx_char(byte); } +static void print_debug_hex8(unsigned char value) { console_tx_hex8(value); } +static void print_debug_hex16(unsigned short value){ console_tx_hex16(value); } +static void print_debug_hex32(unsigned int value) { console_tx_hex32(value); } +static void print_debug(const char *str) { console_tx_string(str); } + +static void print_spew_char(unsigned char byte) { console_tx_char(byte); } +static void print_spew_hex8(unsigned char value) { console_tx_hex8(value); } +static void print_spew_hex16(unsigned short value){ console_tx_hex16(value); } +static void print_spew_hex32(unsigned int value) { console_tx_hex32(value); } +static void print_spew(const char *str) { console_tx_string(str); } + +static void die(const char *str) +{ + print_emerg(str); + do { + asm volatile (" "); + } while(1); +} +#endif /* LINUX_CONSOLE_H */ diff --git a/util/romcc/tests/include/linux_syscall.h b/util/romcc/tests/include/linux_syscall.h new file mode 100644 index 0000000000..487095f712 --- /dev/null +++ b/util/romcc/tests/include/linux_syscall.h @@ -0,0 +1,7 @@ +#ifndef LINUX_SYSCALL_H +#define LINUX_SYSCALL_H + +/* When I support other platforms use #ifdefs here */ +#include "linuxi386_syscall.h" + +#endif /* LINUX_SYSCALL_H */ diff --git a/util/romcc/tests/include/linuxi386_syscall.h b/util/romcc/tests/include/linuxi386_syscall.h new file mode 100644 index 0000000000..d202661c67 --- /dev/null +++ b/util/romcc/tests/include/linuxi386_syscall.h @@ -0,0 +1,299 @@ +struct syscall_result { + long val; + int errno; +}; + +static inline struct syscall_result syscall_return(long result) +{ + struct syscall_result res; + if (((unsigned long)result) >= ((unsigned long)-125)) { + res.errno = - result; + res.val = -1; + } else { + res.errno = 0; + res.val = result; + } + return res; +} + +static struct syscall_result syscall0(unsigned long nr) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr)); + return syscall_return(res); +} + +static struct syscall_result syscall1(unsigned long nr, unsigned long arg1) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr), "b" (arg1)); + return syscall_return(res); + +} + +static struct syscall_result syscall2(unsigned long nr, unsigned long arg1, unsigned long arg2) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr), "b" (arg1), "c" (arg2)); + return syscall_return(res); + +} + + +static struct syscall_result syscall3(unsigned long nr, unsigned long arg1, unsigned long arg2, + unsigned long arg3) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3)); + return syscall_return(res); + +} + +static struct syscall_result syscall4(unsigned long nr, unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)); + return syscall_return(res); + +} + +static struct syscall_result syscall5(unsigned long nr, unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, unsigned long arg5) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3), + "S" (arg4), "D" (arg5)); + return syscall_return(res); + +} + +#define NR_exit 1 +#define NR_fork 2 +#define NR_read 3 +#define NR_write 4 +#define NR_open 5 +#define NR_close 6 +#define NR_waitpid 7 +#define NR_creat 8 +#define NR_link 9 +#define NR_unlink 10 +#define NR_execve 11 +#define NR_chdir 12 +#define NR_time 13 +#define NR_mknod 14 +#define NR_chmod 15 +#define NR_lchown 16 +#define NR_break 17 +#define NR_oldstat 18 +#define NR_lseek 19 +#define NR_getpid 20 +#define NR_mount 21 +#define NR_umount 22 +#define NR_setuid 23 +#define NR_getuid 24 +#define NR_stime 25 +#define NR_ptrace 26 +#define NR_alarm 27 +#define NR_oldfstat 28 +#define NR_pause 29 +#define NR_utime 30 +#define NR_stty 31 +#define NR_gtty 32 +#define NR_access 33 +#define NR_nice 34 +#define NR_ftime 35 +#define NR_sync 36 +#define NR_kill 37 +#define NR_rename 38 +#define NR_mkdir 39 +#define NR_rmdir 40 +#define NR_dup 41 +#define NR_pipe 42 +#define NR_times 43 +#define NR_prof 44 +#define NR_brk 45 +#define NR_setgid 46 +#define NR_getgid 47 +#define NR_signal 48 +#define NR_geteuid 49 +#define NR_getegid 50 +#define NR_acct 51 +#define NR_umount2 52 +#define NR_lock 53 +#define NR_ioctl 54 +#define NR_fcntl 55 +#define NR_mpx 56 +#define NR_setpgid 57 +#define NR_ulimit 58 +#define NR_oldolduname 59 +#define NR_umask 60 +#define NR_chroot 61 +#define NR_ustat 62 +#define NR_dup2 63 +#define NR_getppid 64 +#define NR_getpgrp 65 +#define NR_setsid 66 +#define NR_sigaction 67 +#define NR_sgetmask 68 +#define NR_ssetmask 69 +#define NR_setreuid 70 +#define NR_setregid 71 +#define NR_sigsuspend 72 +#define NR_sigpending 73 +#define NR_sethostname 74 +#define NR_setrlimit 75 +#define NR_getrlimit 76 +#define NR_getrusage 77 +#define NR_gettimeofday 78 +#define NR_settimeofday 79 +#define NR_getgroups 80 +#define NR_setgroups 81 +#define NR_select 82 +#define NR_symlink 83 +#define NR_oldlstat 84 +#define NR_readlink 85 +#define NR_uselib 86 +#define NR_swapon 87 +#define NR_reboot 88 +#define NR_readdir 89 +#define NR_mmap 90 +#define NR_munmap 91 +#define NR_truncate 92 +#define NR_ftruncate 93 +#define NR_fchmod 94 +#define NR_fchown 95 +#define NR_getpriority 96 +#define NR_setpriority 97 +#define NR_profil 98 +#define NR_statfs 99 +#define NR_fstatfs 100 +#define NR_ioperm 101 +#define NR_socketcall 102 +#define NR_syslog 103 +#define NR_setitimer 104 +#define NR_getitimer 105 +#define NR_stat 106 +#define NR_lstat 107 +#define NR_fstat 108 +#define NR_olduname 109 +#define NR_iopl 110 +#define NR_vhangup 111 +#define NR_idle 112 +#define NR_vm86old 113 +#define NR_wait4 114 +#define NR_swapoff 115 +#define NR_sysinfo 116 +#define NR_ipc 117 +#define NR_fsync 118 +#define NR_sigreturn 119 +#define NR_clone 120 +#define NR_setdomainname 121 +#define NR_uname 122 +#define NR_modify_ldt 123 +#define NR_adjtimex 124 +#define NR_mprotect 125 +#define NR_sigprocmask 126 +#define NR_create_module 127 +#define NR_init_module 128 +#define NR_delete_module 129 +#define NR_get_kernel_syms 130 +#define NR_quotactl 131 +#define NR_getpgid 132 +#define NR_fchdir 133 +#define NR_bdflush 134 +#define NR_sysfs 135 +#define NR_personality 136 +#define NR_afs_syscall 137 /* Syscall for Andrew File System */ +#define NR_setfsuid 138 +#define NR_setfsgid 139 +#define NR__llseek 140 +#define NR_getdents 141 +#define NR__newselect 142 +#define NR_flock 143 +#define NR_msync 144 +#define NR_readv 145 +#define NR_writev 146 +#define NR_getsid 147 +#define NR_fdatasync 148 +#define NR__sysctl 149 +#define NR_mlock 150 +#define NR_munlock 151 +#define NR_mlockall 152 +#define NR_munlockall 153 +#define NR_sched_setparam 154 +#define NR_sched_getparam 155 +#define NR_sched_setscheduler 156 +#define NR_sched_getscheduler 157 +#define NR_sched_yield 158 +#define NR_sched_get_priority_max 159 +#define NR_sched_get_priority_min 160 +#define NR_sched_rr_get_interval 161 +#define NR_nanosleep 162 +#define NR_mremap 163 +#define NR_setresuid 164 +#define NR_getresuid 165 +#define NR_vm86 166 +#define NR_query_module 167 +#define NR_poll 168 +#define NR_nfsservctl 169 +#define NR_setresgid 170 +#define NR_getresgid 171 +#define NR_prctl 172 +#define NR_rt_sigreturn 173 +#define NR_rt_sigaction 174 +#define NR_rt_sigprocmask 175 +#define NR_rt_sigpending 176 +#define NR_rt_sigtimedwait 177 +#define NR_rt_sigqueueinfo 178 +#define NR_rt_sigsuspend 179 +#define NR_pread 180 +#define NR_pwrite 181 +#define NR_chown 182 +#define NR_getcwd 183 +#define NR_capget 184 +#define NR_capset 185 +#define NR_sigaltstack 186 +#define NR_sendfile 187 +#define NR_getpmsg 188 /* some people actually want streams */ +#define NR_putpmsg 189 /* some people actually want streams */ +#define NR_vfork 190 + +/* Standard file descriptors */ +#define STDIN_FILENO 0 /* Standard input */ +#define STDOUT_FILENO 1 /* Standard output */ +#define STDERR_FILENO 2 /* Standard error output */ + +typedef long ssize_t; +typedef unsigned long size_t; + +static ssize_t write(int fd, const void *buf, size_t count) +{ + struct syscall_result res; + res = syscall3(NR_write, fd, (unsigned long)buf, count); + return res.val; +} + +static void _exit(int status) +{ + struct syscall_result res; + res = syscall1(NR_exit, status); +} diff --git a/util/romcc/tests/ldscript.ld b/util/romcc/tests/ldscript.ld index 97b307fc66..249ebd5c19 100644 --- a/util/romcc/tests/ldscript.ld +++ b/util/romcc/tests/ldscript.ld @@ -4,6 +4,7 @@ ENTRY(_start) SECTIONS { . = 0x1000; + __cpu_reset = 0xdeadbeef; .text . : { . = ALIGN(16); _start = . ; diff --git a/util/romcc/tests/linux_test10.c b/util/romcc/tests/linux_test10.c new file mode 100644 index 0000000000..ef8c930187 --- /dev/null +++ b/util/romcc/tests/linux_test10.c @@ -0,0 +1,57 @@ +#include "linux_syscall.h" +#include "linux_console.h" + +struct stuff { + signed int a : 5; + signed int b : 6; + signed int c : 2; + unsigned int d : 3; +}; + +static void test(void) +{ + struct stuff var; +#if 0 + int a, b, c, d; + + a = 1; + b = 2; + c = 3; + d = 7; + + var.a = a; + var.b = b; + var.c = c; + var.d = d; + + a = var.a; + b = var.b; + c = var.c; + d = var.d; + + print_debug(" a: "); + print_debug_hex32(a); + print_debug(" b: "); + print_debug_hex32(b); + print_debug(" c: "); + print_debug_hex32(c); + print_debug(" d: "); + print_debug_hex32(d); +#else + var.a = 1; + var.b = 2; + var.c = 3; + var.d = 7; + + print_debug(" a: "); + print_debug_hex32(var.a); + print_debug(" b: "); + print_debug_hex32(var.b); + print_debug(" c: "); + print_debug_hex32(var.c); + print_debug(" d: "); + print_debug_hex32(var.d); +#endif + print_debug("\n"); + _exit(0); +} diff --git a/util/romcc/tests/linux_test11.c b/util/romcc/tests/linux_test11.c new file mode 100644 index 0000000000..9c1183fd87 --- /dev/null +++ b/util/romcc/tests/linux_test11.c @@ -0,0 +1,11 @@ +#include "linux_syscall.h" +#include "linux_console.h" + +static void test(void) +{ + signed char x; + x = -1; + print_debug_hex32(x); + print_debug("\n"); + _exit(0); +} diff --git a/util/romcc/tests/linux_test12.c b/util/romcc/tests/linux_test12.c new file mode 100644 index 0000000000..5503aa05f0 --- /dev/null +++ b/util/romcc/tests/linux_test12.c @@ -0,0 +1,70 @@ +#include "linux_syscall.h" +#include "linux_console.h" + +#define MACRO(hello, hello2) 1 + +#ifndef A +#define A 135 +#endif +#define B A +#define C B +#define D C +#define E D +#define F E +#define G F +#define H G +#define I H + +#define FOO() "hah?\n" +#define BAR(X) ( X " There\n" ) +#define BAZ(X) #X +#define SUM(X, Y) ((X) + (Y)) +#define REALLY_SUM(...) SUM(__VA_ARGS__) + + +#define hash_hash # /* comment */ ## # +#define mkstr(a) # a +#define in_between(a) mkstr(a) +#define join(c, d) in_between(c hash_hash d) + +#define ECHO(X) X +#define print_debug(X) ECHO(print_debug(X)) + +static void test(void) +{ + print_debug(FOO()); + print_debug(BAR("Hi!!")); + print_debug(BAZ(This should be shown as a string... "enclosed in quotes") "\n"); + print_debug("This is a quote\" see\n"); + print_debug(BAR(BAZ(I))); + + print_debug_hex32(REALLY_SUM(1,2)); + print_debug("\n"); + + print_debug(join(x, y) "\n"); + + print_debug("romcc: "); + print_debug_hex8(__ROMCC__); + print_debug("."); + print_debug_hex8(__ROMCC_MINOR__); + print_debug("\n"); + + print_debug(__FILE__); + print_debug(":"); + print_debug(__func__); + print_debug(":"); + print_debug_hex32(__LINE__); + print_debug("\n"); + + print_debug("Compiled at: "); + print_debug(__DATE__); + print_debug(" "); + print_debug(__TIME__); + print_debug("\n"); + + print_debug("Compile time: "); + print_debug(__TIME__); + print_debug("\n"); + + _exit(0); +} diff --git a/util/romcc/tests/linux_test13.c b/util/romcc/tests/linux_test13.c new file mode 100644 index 0000000000..83ef239854 --- /dev/null +++ b/util/romcc/tests/linux_test13.c @@ -0,0 +1,47 @@ +#include "linux_syscall.h" +#include "linux_console.h" + +struct mem_controller { + unsigned short channel0[4]; +}; + +static unsigned int spd_detect_dimms(const struct mem_controller *ctrl) +{ + unsigned dimm_mask; + int i; + + print_debug("1\n"); + dimm_mask = 0; + for(i = 0; i < 4; i++) { + int byte; + unsigned device; + + print_debug("2\n"); + device = ctrl->channel0[i]; + if (device) { + print_debug("3\n"); + byte = ctrl->channel0[i] + 2; + if (byte == 7) { + dimm_mask |= (1 << i); + } + } + print_debug("4\n"); + } + print_debug("5\n"); + return dimm_mask; +} + + +static void main(void) +{ + static const struct mem_controller cpu[] = { + { + .channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 }, + }, + }; + long dimm_mask; + print_debug("A\n"); + dimm_mask = spd_detect_dimms(cpu); + print_debug("B\n"); + _exit(0); +} diff --git a/util/romcc/tests/linux_test5.c b/util/romcc/tests/linux_test5.c index 55613c21b0..13093fb0fc 100644 --- a/util/romcc/tests/linux_test5.c +++ b/util/romcc/tests/linux_test5.c @@ -1,7 +1,7 @@ #include "linux_syscall.h" #include "linux_console.h" -int log2(int value) +inline int log2(int value) { /* __builtin_bsr is a exactly equivalent to the x86 machine * instruction with the exception that it returns -1 diff --git a/util/romcc/tests/linux_test9.c b/util/romcc/tests/linux_test9.c new file mode 100644 index 0000000000..2a900a55fc --- /dev/null +++ b/util/romcc/tests/linux_test9.c @@ -0,0 +1,13 @@ +#include "linux_syscall.h" +#include "linux_console.h" + +static void test(void) +{ + unsigned char i; + for(i = 127; i != 5; i++) { + print_debug("i: "); + print_debug_hex32((unsigned )i); + print_debug("\n"); + } + _exit(0); +} diff --git a/util/romcc/tests/raminit_test1.c b/util/romcc/tests/raminit_test1.c new file mode 100644 index 0000000000..9b6cf5d31c --- /dev/null +++ b/util/romcc/tests/raminit_test1.c @@ -0,0 +1,1292 @@ +#define HAVE_STRING_SUPPORT 0 +#define HAVE_CAST_SUPPORT 1 +#define HAVE_STATIC_ARRAY_SUPPORT 1 +#define HAVE_POINTER_SUPPORT 1 +#define HAVE_MACRO_ARG_SUPPORT 0 + +void outb(unsigned char value, unsigned short port) +{ + __builtin_outb(value, port); +} + +void outw(unsigned short value, unsigned short port) +{ + __builtin_outw(value, port); +} + +void outl(unsigned int value, unsigned short port) +{ + __builtin_outl(value, port); +} + +unsigned char inb(unsigned short port) +{ + return __builtin_inb(port); +} + +unsigned char inw(unsigned short port) +{ + return __builtin_inw(port); +} + +unsigned char inl(unsigned short port) +{ + return __builtin_inl(port); +} + +static unsigned int config_cmd(unsigned char bus, unsigned devfn, unsigned where) +{ + return 0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3); +} + +static unsigned char pcibios_read_config_byte( + unsigned char bus, unsigned devfn, unsigned where) +{ + outl(config_cmd(bus, devfn, where), 0xCF8); + return inb(0xCFC + (where & 3)); +} + +static unsigned short pcibios_read_config_word( + unsigned char bus, unsigned devfn, unsigned where) +{ + outl(config_cmd(bus, devfn, where), 0xCF8); + return inw(0xCFC + (where & 2)); +} + +static unsigned int pcibios_read_config_dword( + unsigned char bus, unsigned devfn, unsigned where) +{ + outl(config_cmd(bus, devfn, where), 0xCF8); + return inl(0xCFC); +} + + +static void pcibios_write_config_byte( + unsigned char bus, unsigned devfn, unsigned where, unsigned char value) +{ + outl(config_cmd(bus, devfn, where), 0xCF8); + outb(value, 0xCFC + (where & 3)); +} + +static void pcibios_write_config_word( + unsigned char bus, unsigned devfn, unsigned where, unsigned short value) +{ + outl(config_cmd(bus, devfn, where), 0xCF8); + outw(value, 0xCFC + (where & 2)); +} + +static void pcibios_write_config_dword( + unsigned char bus, unsigned devfn, unsigned where, unsigned int value) +{ + outl(config_cmd(bus, devfn, where), 0xCF8); + outl(value, 0xCFC); +} + +/* Base Address */ +#ifndef TTYS0_BASE +#define TTYS0_BASE 0x3f8 +#endif + +#ifndef TTYS0_BAUD +#define TTYS0_BAUD 115200 +#endif + +#if ((115200%TTYS0_BAUD) != 0) +#error Bad ttys0 baud rate +#endif + +#define TTYS0_DIV (115200/TTYS0_BAUD) + +/* Line Control Settings */ +#ifndef TTYS0_LCS +/* Set 8bit, 1 stop bit, no parity */ +#define TTYS0_LCS 0x3 +#endif + +#define UART_LCS TTYS0_LCS + +/* Data */ +#define UART_RBR 0x00 +#define UART_TBR 0x00 + +/* Control */ +#define UART_IER 0x01 +#define UART_IIR 0x02 +#define UART_FCR 0x02 +#define UART_LCR 0x03 +#define UART_MCR 0x04 +#define UART_DLL 0x00 +#define UART_DLM 0x01 + +/* Status */ +#define UART_LSR 0x05 +#define UART_MSR 0x06 +#define UART_SCR 0x07 + +int uart_can_tx_byte(void) +{ + return inb(TTYS0_BASE + UART_LSR) & 0x20; +} + +void uart_wait_to_tx_byte(void) +{ + while(!uart_can_tx_byte()) + ; +} + +void uart_wait_until_sent(void) +{ + while(!(inb(TTYS0_BASE + UART_LSR) & 0x40)) + ; +} + +void uart_tx_byte(unsigned char data) +{ + uart_wait_to_tx_byte(); + outb(data, TTYS0_BASE + UART_TBR); + /* Make certain the data clears the fifos */ + uart_wait_until_sent(); +} + +void uart_init(void) +{ + /* disable interrupts */ + outb(0x0, TTYS0_BASE + UART_IER); + /* enable fifo's */ + outb(0x01, TTYS0_BASE + UART_FCR); + /* Set Baud Rate Divisor to 12 ==> 115200 Baud */ + outb(0x80 | UART_LCS, TTYS0_BASE + UART_LCR); + outb(TTYS0_DIV & 0xFF, TTYS0_BASE + UART_DLL); + outb((TTYS0_DIV >> 8) & 0xFF, TTYS0_BASE + UART_DLM); + outb(UART_LCS, TTYS0_BASE + UART_LCR); +} + +void __console_tx_char(unsigned char byte) +{ + uart_tx_byte(byte); +} +void __console_tx_nibble(unsigned nibble) +{ + unsigned char digit; + digit = nibble + '0'; + if (digit > '9') { + digit += 39; + } + __console_tx_char(digit); +} +void __console_tx_hex8(unsigned char byte) +{ + __console_tx_nibble(byte >> 4); + __console_tx_nibble(byte & 0x0f); +} + +void __console_tx_hex32(unsigned char value) +{ + __console_tx_nibble((value >> 28) & 0x0f); + __console_tx_nibble((value >> 24) & 0x0f); + __console_tx_nibble((value >> 20) & 0x0f); + __console_tx_nibble((value >> 16) & 0x0f); + __console_tx_nibble((value >> 12) & 0x0f); + __console_tx_nibble((value >> 8) & 0x0f); + __console_tx_nibble((value >> 4) & 0x0f); + __console_tx_nibble(value & 0x0f); +} + +#if HAVE_STRING_SUPPORT +void __console_tx_string(char *str) +{ + unsigned char ch; + while((ch = *str++) != '\0') { + __console_tx_char(ch); + } +} +#else +void __console_tx_string(char *str) +{ +} +#endif + + +void print_emerg_char(unsigned char byte) { __console_tx_char(byte); } +void print_emerg_hex8(unsigned char value) { __console_tx_hex8(value); } +void print_emerg_hex32(unsigned int value) { __console_tx_hex32(value); } +void print_emerg(char *str) { __console_tx_string(str); } + +void print_alert_char(unsigned char byte) { __console_tx_char(byte); } +void print_alert_hex8(unsigned char value) { __console_tx_hex8(value); } +void print_alert_hex32(unsigned int value) { __console_tx_hex32(value); } +void print_alert(char *str) { __console_tx_string(str); } + +void print_crit_char(unsigned char byte) { __console_tx_char(byte); } +void print_crit_hex8(unsigned char value) { __console_tx_hex8(value); } +void print_crit_hex32(unsigned int value) { __console_tx_hex32(value); } +void print_crit(char *str) { __console_tx_string(str); } + +void print_err_char(unsigned char byte) { __console_tx_char(byte); } +void print_err_hex8(unsigned char value) { __console_tx_hex8(value); } +void print_err_hex32(unsigned int value) { __console_tx_hex32(value); } +void print_err(char *str) { __console_tx_string(str); } + +void print_warning_char(unsigned char byte) { __console_tx_char(byte); } +void print_warning_hex8(unsigned char value) { __console_tx_hex8(value); } +void print_warning_hex32(unsigned int value) { __console_tx_hex32(value); } +void print_warning(char *str) { __console_tx_string(str); } + +void print_notice_char(unsigned char byte) { __console_tx_char(byte); } +void print_notice_hex8(unsigned char value) { __console_tx_hex8(value); } +void print_notice_hex32(unsigned int value) { __console_tx_hex32(value); } +void print_notice(char *str) { __console_tx_string(str); } + +void print_info_char(unsigned char byte) { __console_tx_char(byte); } +void print_info_hex8(unsigned char value) { __console_tx_hex8(value); } +void print_info_hex32(unsigned int value) { __console_tx_hex32(value); } +void print_info(char *str) { __console_tx_string(str); } + +void print_debug_char(unsigned char byte) { __console_tx_char(byte); } +void print_debug_hex8(unsigned char value) { __console_tx_hex8(value); } +void print_debug_hex32(unsigned int value) { __console_tx_hex32(value); } +void print_debug(char *str) { __console_tx_string(str); } + +void print_spew_char(unsigned char byte) { __console_tx_char(byte); } +void print_spew_hex8(unsigned char value) { __console_tx_hex8(value); } +void print_spew_hex32(unsigned int value) { __console_tx_hex32(value); } +void print_spew(char *str) { __console_tx_string(str); } + +#define PIIX4_DEVFN 0x90 +#define SMBUS_MEM_DEVICE_START 0x50 +#define SMBUS_MEM_DEVICE_END 0x53 +#define SMBUS_MEM_DEVICE_INC 1 + + +#define PM_BUS 0 +#define PM_DEVFN (PIIX4_DEVFN+3) + +#define SMBUS_IO_BASE 0x1000 +#define SMBHSTSTAT 0 +#define SMBHSTCTL 2 +#define SMBHSTCMD 3 +#define SMBHSTADD 4 +#define SMBHSTDAT0 5 +#define SMBHSTDAT1 6 +#define SMBBLKDAT 7 + +void smbus_enable(void) +{ + /* iobase addr */ + pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x90, SMBUS_IO_BASE | 1); + /* smbus enable */ + pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0xd2, (0x4 << 1) | 1); + /* iospace enable */ + pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1); +} + +void smbus_setup(void) +{ + outb(0, SMBUS_IO_BASE + SMBHSTSTAT); +} + +static void smbus_wait_until_ready(void) +{ + while((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) { + /* nop */ + } +} + +static void smbus_wait_until_done(void) +{ + unsigned char byte; + do { + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + }while((byte &1) == 1); + while( (byte & ~1) == 0) { + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + } +} + +int smbus_read_byte(unsigned device, unsigned address) +{ + unsigned char host_status_register; + unsigned char byte; + int result; + + smbus_wait_until_ready(); + + /* setup transaction */ + /* disable interrupts */ + outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL); + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADD); + /* set the command/address... */ + outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD); + /* set up for a byte data read */ + outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2), SMBUS_IO_BASE + SMBHSTCTL); + + /* clear any lingering errors, so the transaction will run */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + + /* clear the data byte...*/ + outb(0, SMBUS_IO_BASE + SMBHSTDAT0); + + /* start the command */ + outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL); + + /* poll for transaction completion */ + smbus_wait_until_done(); + + host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT); + + /* read results of transaction */ + byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); + + result = byte; + if (host_status_register != 0x02) { + result = -1; + } + return result; +} + +#define I440GX_BUS 0 +#define I440GX_DEVFN ((0x00 << 3) + 0) + +#define USE_ECC 0 + +#define CAS_LATENCY 3 + + /* CAS latency 2 */ +#if (CAS_LATENCY == 2) +#define CAS_NB 0x17 + /* + * 7 == 0111 + * 1 == 0001 + */ +#define CAS_MODE 0x2a + /* + * a == 1010 + * 2 == 0010 + */ +#endif + + /* CAS latency 3 */ +#if (CAS_LATENCY == 3) +#define CAS_NB 0x13 + /* + * 3 == 0011 + * 1 == 0001 + */ +#define CAS_MODE 0x3a + /* + * a == 1010 + * 3 == 0011 + */ +#endif + +#ifndef CAS_NB +#error "Nothing defined" +#endif + +/* Default values for config registers */ + +static void set_nbxcfg(void) +{ + /* NBXCFG 0x50 - 0x53 */ + /* f == 1111 + * 0 == 0000 + * 0 == 0000 + * 0 == 0000 + * 0 == 0000 + * 1 == 0001 + * 8 == 1000 + * c == 1100 + * SDRAM Row without ECC: + * row 0 == 1 No ECC + * row 1 == 1 No ECC + * row 2 == 1 No ECC + * row 3 == 1 No ECC + * row 4 == 1 No ECC + * row 5 == 1 No ECC + * row 6 == 1 No ECC + * row 7 == 1 No ECC + * Host Bus Fast Data Ready Enable == 0 Disabled + * IDSEL_REDIRECT == 0 (430TX compatibility disable?) + * WSC# Hanshake Disable == 0 enable (Use External IOAPIC) + * Host/DRAM Frequence == 00 100Mhz + * AGP to PCI Access Enable == 0 Disable + * PCI Agent to Aperture Access Disable == 0 Enable (Ignored) + * Aperture Access Global Enable == 0 Disable + * DRAM Data Integrity Mode == 11 (Error Checking/Correction) + * ECC Diagnostic Mode Enable == 0 Not Enabled + * MDA present == 0 Not Present + * USWC Write Post During During I/O Bridge Access Enable == 1 Enabled + * In Order Queue Depth (IQD) (RO) == ?? + */ + pcibios_write_config_dword(I440GX_BUS, I440GX_DEVFN, 0x50, 0xff00000c); +} + +static void set_dramc(void) +{ + /* 0 == 0000 + * 8 == 1000 + * Not registered SDRAM + * refresh disabled + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, 0x8); +} + +static void set_pam(void) +{ + /* PAM - Programmable Attribute Map Registers */ + /* Ideally we want to enable all of these as DRAM and teach + * linux it is o.k. to use them... + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x59, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5a, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5b, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5d, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5e, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5f, 0x00); +} + +static void set_drb(void) +{ + /* DRB - DRAM Row Boundary Registers */ + /* Conservative setting 8MB of ram on first DIMM... */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x60, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x61, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x62, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x63, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x64, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x65, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x66, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x67, 0x01); +} + +static void set_fdhc(void) +{ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x68, 0x00); +} +static void set_mbsc(void) +{ + /* MBSC - Memory Buffer Strength Control */ + /* 00c00003e820 + * [47:44] 0 == 0000 + * [43:40] 0 == 0000 + * [39:36] c == 1100 + * [35:32] 0 == 0000 + * [31:28] 0 == 0000 + * [27:24] 0 == 0000 + * [23:20] 0 == 0000 + * [19:16] 3 == 0011 + * [15:12] e == 1110 + * [11: 8] 8 == 1000 + * [ 7: 4] 2 == 0010 + * [ 3: 0] 0 == 0000 + * MAA[14:0]#, WEA#, SRASA#, SCASA# Buffer Strengths == 3x + * MAB[14,13,10,12:11,9:0]#, WEB#, SRASB#, SCASB# Buffer Strengths == 3x + * MD[63:0]# Buffer Strength Control 2 == 3x + * MD[63:0]# Buffer Strength Control 1 == 3x + * MECC[7:0] Buffer Strength Control 2 == 3x + * MECC[7:0] Buffer Strength Control 1 == 3x + * CSB7# Buffer Strength == 3x + * CSA7# Buffer Strength == 3x + * CSB6# Buffer Strength == 3x + * CSA6# Buffer Strength == 3x + * CSA5#/CSB5# Buffer Strength == 2x + * CSA4#/CSB4# Buffer Strength == 2x + * CSA3#/CSB3# Buffer Strength == 2x + * CSA2#/CSB2# Buffer Strength == 2x + * CSA1#/CSB1# Buffer Strength == 2x + * CSA0#/CSB0# Buffer Strength == 2x + * DQMA5 Buffer Strength == 2x + * DQMA1 Buffer Strength == 3x + * DQMB5 Buffer Strength == 2x + * DQMB1 Buffer Strength == 2x + * DQMA[7:6,4:2,0] Buffer Strength == 3x + * GCKE Buffer Strength == 1x + * FENA Buffer Strength == 3x + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x69, 0xB3); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6a, 0xee); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6b, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6c, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6d, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6e, 0x03); +} + +static void set_smram(void) +{ + /* 0x72 SMRAM */ + /* 1 == 0001 + * a == 1010 + * SMM Compatible base segment == 010 (Hardcoded value) + */ +} + +static void set_esramc(void) +{ + /* 0x73 ESMRAMC */ +} + +static void set_rps(void) +{ + /* RPS - Row Page Size Register */ + /* 0x0055 + * [15:12] 0 == 0000 + * [11: 8] 0 == 0000 + * [ 7: 4] 5 == 0101 + * [ 3: 0] 5 == 0101 + * DRB[0] == 4KB + * DRB[1] == 4KB + * DRB[2] == 4KB + * DRB[3] == 4KB + * DRB[4] == 2KB + * DRB[5] == 2KB + * DRB[6] == 2KB + * DRB[7] == 2KB + */ + pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x74, 0x5555); +} + +static void set_sdramc(void) +{ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, CAS_NB); +} + +static void set_pgpol(void) +{ + /* PGPOL - Paging Policy Register */ + /* 0xff07 + * [15:12] f == 1111 + * [11: 8] f == 1111 + * [ 7: 4] 0 == 0000 + * [ 3: 0] 7 == 0111 + * row0 == 4banks + * row1 == 4banks + * row2 == 4banks + * row3 == 4banks + * row4 == 4banks + * row5 == 4banks + * row6 == 4banks + * row7 == 4banks + * Dram Idle Timer (DIT) == 32 clocks + */ + pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x78, 0xff07); +} + +static void set_mbfs(void) +{ + /* MBFS - Memory Buffer Frequencey Select Register */ + /* 0xffff7f + * [23:20] f == 1111 + * [19:16] f == 1111 + * [15:12] f == 1111 + * [11: 8] f == 1111 + * [ 7: 4] 7 == 0111 + * [ 3: 0] f == 1111 + * MAA[14:0], WEA#, SRASA#, SCASA# == 100Mhz Buffers Enabled + * MAB[14,13,10,12:11,9:0], WEB#, SRASB#, SCASB# == 100Mhz Buffers Enabled + * MD[63:0] Control 2 == 100 Mhz Buffer Enable + * MD[63:0] Control 1 == 100 Mhz B + * MECC[7:0] Control 2 == 100 Mhz B + * + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xca, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcb, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcc, 0x7f); +} + +static void set_dwtc(void) +{ + /* DWTC - DRAM Write Thermal Throttle Control */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe0, 0xb4); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe1, 0xbe); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe2, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe3, 0xd7); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe4, 0x97); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe5, 0x3e); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe6, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe7, 0x80); +} + +static void set_drtc(void) +{ + /* DRTC - DRAM Read Thermal Throttle Control */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe8, 0x2c); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe9, 0xd3); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xea, 0xf7); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xeb, 0xcf); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xec, 0x9d); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xed, 0x3e); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xee, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xef, 0x00); +} + +static void set_pmcr(void) +{ + /* PMCR -- BIOS sets 0x90 into it. + * 0x10 is REQUIRED. + * we have never used it. So why did this ever work? + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x7a, 0x90); + +} +void sdram_set_registers(void) +{ + set_nbxcfg(); + set_dramc(); + set_pam(); + set_drb(); + set_fdhc(); + set_mbsc(); + set_smram(); + set_esramc(); + set_rps(); + set_sdramc(); + set_pgpol(); + set_mbfs(); + set_dwtc(); + set_drtc(); + set_pmcr(); +} + +int log2(int value) +{ + /* __builtin_bsr is a exactly equivalent to the x86 machine + * instruction with the exception that it returns -1 + * when the value presented to it is zero. + * Otherwise __builtin_bsr returns the zero based index of + * the highest bit set. + */ + return __builtin_bsr(value); +} + + +static void spd_set_drb(void) +{ + /* + * Effects: Uses serial presence detect to set the + * DRB registers which holds the ending memory address assigned + * to each DIMM. + */ + unsigned end_of_memory; + unsigned device; + unsigned drb_reg; + + end_of_memory = 0; /* in multiples of 8MiB */ + device = SMBUS_MEM_DEVICE_START; + drb_reg = 0x60; + while (device <= SMBUS_MEM_DEVICE_END) { + unsigned side1_bits, side2_bits; + int byte, byte2; + + side1_bits = side2_bits = -1; + + /* rows */ + byte = smbus_read_byte(device, 3); + if (byte >= 0) { + side1_bits += byte & 0xf; + + /* columns */ + byte = smbus_read_byte(device, 4); + side1_bits += byte & 0xf; + + /* banks */ + byte = smbus_read_byte(device, 17); + side1_bits += log2(byte); + + /* Get the moduel data width and convert it to a power of two */ + /* low byte */ + byte = smbus_read_byte(device, 6); + + /* high byte */ + byte2 = smbus_read_byte(device, 7); +#if HAVE_CAST_SUPPORT + side1_bits += log2((((unsigned long)byte2 << 8)| byte)); +#else + side1_bits += log2((byte2 << 8) | byte); +#endif + + /* now I have the ram size in bits as a power of two (less 1) */ + /* Make it mulitples of 8MB */ + side1_bits -= 25; + + /* side two */ + + /* number of physical banks */ + byte = smbus_read_byte(device, 5); + if (byte > 1) { + /* for now only handle the symmetrical case */ + side2_bits = side1_bits; + } + } + + /* Compute the end address for the DRB register */ + /* Only process dimms < 2GB (2^8 * 8MB) */ + if (side1_bits < 8) { + end_of_memory += (1 << side1_bits); + } +#if HAVE_STRING_SUPPORT + print_debug("end_of_memory: "); print_debug_hex32(end_of_memory); print_debug("\n"); +#endif + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, drb_reg, end_of_memory); + + if (side2_bits < 8 ) { + end_of_memory += (1 << side2_bits); + } +#if HAVE_STRING_SUPPORT + print_debug("end_of_memory: "); print_debug_hex32(end_of_memory); print_debug("\n"); +#endif + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, drb_reg +1, end_of_memory); + + drb_reg += 2; + device += SMBUS_MEM_DEVICE_INC; + } +} + +void sdram_no_memory(void) +{ +#if HAVE_STRING_SUPPORT + print_err("No memory!!\n"); +#endif + while(1) ; +} + +static void spd_set_dramc(void) +{ + /* + * Effects: Uses serial presence detect to set the + * DRAMC register, which records if ram is registerd or not, + * and controls the refresh rate. + * The refresh rate is not set here, as memory refresh + * cannot be enbaled until after memory is initialized. + * see spd_enable_refresh. + */ + /* auto detect if ram is registered or not. */ + /* The DRAMC register also contorls the refresh rate but we can't + * set that here because we must leave refresh disabled. + * see: spd_enable_refresh + */ + /* Find the first dimm and assume the rest are the same */ + /* FIXME Check for illegal/unsupported ram configurations and abort */ + unsigned device; + int byte; + unsigned dramc; + byte = -1; + device = SMBUS_MEM_DEVICE_START; + + while ((byte < 0) && (device <= SMBUS_MEM_DEVICE_END)) { + byte = smbus_read_byte(device, 21); + device += SMBUS_MEM_DEVICE_INC; + } + if (byte < 0) { + /* We couldn't find anything we must have no memory */ + sdram_no_memory(); + } + dramc = 0x8; + if ((byte & 0x12) != 0) { + /* this is a registered part. + * observation: for register parts, BIOS zeros (!) + * registers CA-CC. This has an undocumented meaning. + */ + /* But it does make sense the oppisite of registered + * sdram is buffered and 0xca - 0xcc control the buffers. + * Clearing them aparently disables them. + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xca, 0); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcb, 0); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcc, 0); + dramc = 0x10; + } + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, dramc); +} + +static void spd_enable_refresh(void) +{ + /* + * Effects: Uses serial presence detect to set the + * refresh rate in the DRAMC register. + * see spd_set_dramc for the other values. + * FIXME: Check for illegal/unsupported ram configurations and abort + */ +#if HAVE_STATIC_ARRAY_SUPPORT + static const unsigned char refresh_rates[] = { + 0x01, /* Normal 15.625 us -> 15.6 us */ + 0x05, /* Reduced(.25X) 3.9 us -> 7.8 us */ + 0x05, /* Reduced(.5X) 7.8 us -> 7.8 us */ + 0x02, /* Extended(2x) 31.3 us -> 31.2 us */ + 0x03, /* Extended(4x) 62.5 us -> 62.4 us */ + 0x04, /* Extended(8x) 125 us -> 124.8 us */ + }; +#endif + /* Find the first dimm and assume the rest are the same */ + int status; + int byte; + unsigned device; + unsigned refresh_rate; + byte = -1; + status = -1; + device = SMBUS_MEM_DEVICE_START; + while ((byte < 0) && (device <= SMBUS_MEM_DEVICE_END)) { + byte = smbus_read_byte(device, 12); + device += SMBUS_MEM_DEVICE_INC; + } + if (byte < 0) { + /* We couldn't find anything we must have no memory */ + sdram_no_memory(); + } + byte &= 0x7f; + /* Default refresh rate be conservative */ + refresh_rate = 5; + /* see if the ram refresh is a supported one */ + if (byte < 6) { +#if HAVE_STATIC_ARRAY_SUPPORT + refresh_rate = refresh_rates[byte]; +#endif + } + byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57); + byte &= 0xf8; + byte |= refresh_rate; + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, byte); +} + +static void spd_set_sdramc(void) +{ + return; +} + +static void spd_set_rps(void) +{ + /* + * Effects: Uses serial presence detect to set the row size + * on a given DIMM + * FIXME: Check for illegal/unsupported ram configurations and abort + */ + /* The RPS register holds the size of a ``page'' of DRAM on each DIMM */ + unsigned page_sizes; + unsigned index; + unsigned device; + unsigned char dramc; + /* default all page sizes to 2KB */ + page_sizes = 0; + index = 0; + device = SMBUS_MEM_DEVICE_START; + for(; device <= SMBUS_MEM_DEVICE_END; index += 4, device += SMBUS_MEM_DEVICE_INC) { + unsigned int status; + unsigned int byte; + int page_size; + + byte = smbus_read_byte(device, 3); + if (byte < 0) continue; + + /* I now have the row page size as a power of 2 */ + page_size = byte & 0xf; + /* make it in multiples of 2Kb */ + page_size -= 11; + + if (page_size <= 0) continue; + + /* FIXME: do something with page sizes greather than 8KB!! */ + page_sizes |= (page_size << index); + + /* side two */ + byte = smbus_read_byte(device, 5); + if (byte <= 1) continue; + + /* For now only handle the symmetrical case */ + page_sizes |= (page_size << (index +2)); + } + /* next block is for Ron's attempt to get registered to work. */ + /* we have just verified that we have to have this code. It appears that + * the registered SDRAMs do indeed set the RPS wrong. sheesh. + */ + /* at this point, page_sizes holds the RPS for all ram. + * we have verified that for registered DRAM the values are + * 1/2 the size they should be. So we test for registered + * and then double the sizes if needed. + */ + + dramc = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57); + if (dramc & 0x10) { + /* registered */ + + /* BIOS makes weird page size for registered! */ + /* what we have found is you need to set the EVEN banks to + * twice the size. Fortunately there is a very easy way to + * do this. First, read the WORD value of register 0x74. + */ + page_sizes += 0x1111; + } + + pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x74, page_sizes); +} + +static void spd_set_pgpol(void) +{ + /* + * Effects: Uses serial presence detect to set the number of banks + * on a given DIMM + * FIXME: Check for illegal/unsupported ram configurations and abort + */ + /* The PGPOL register stores the number of logical banks per DIMM, + * and number of clocks the DRAM controller waits in the idle + * state. + */ + unsigned device; + unsigned bank_sizes; + unsigned bank; + unsigned reg; + /* default all bank counts 2 */ + bank_sizes = 0; + bank = 0; + device = SMBUS_MEM_DEVICE_START; + for(; device <= SMBUS_MEM_DEVICE_END; + bank += 2, device += SMBUS_MEM_DEVICE_INC) { + int byte; + + /* logical banks */ + byte = smbus_read_byte(device, 17); + if (byte < 0) continue; + if (byte < 4) continue; + bank_sizes |= (1 << bank); + + /* side 2 */ + /* Number of physical banks */ + byte = smbus_read_byte(device, 5); + if (byte <= 1) continue; + /* for now only handle the symmetrical case */ + bank_sizes |= (1 << (bank +1)); + } + reg = bank_sizes << 8; + reg |= 0x7; /* 32 clocks idle time */ + pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x78, reg); +} + +static void spd_set_nbxcfg(void) +{ + /* + * Effects: Uses serial presence detect to set the + * ECC support flags in the NBXCFG register + * FIXME: Check for illegal/unsupported ram configurations and abort + */ + unsigned reg; + unsigned index; + unsigned device; + + /* Say all dimms have no ECC support */ + reg = 0xff; + index = 0; + + device = SMBUS_MEM_DEVICE_START; + for(; device <= SMBUS_MEM_DEVICE_END; index += 2, device += SMBUS_MEM_DEVICE_INC) { + int byte; + + byte = smbus_read_byte(device, 11); + if (byte < 0) continue; +#if !USE_ECC + byte = 0; /* Disable ECC */ +#endif + /* 0 == None, 1 == Parity, 2 == ECC */ + if (byte != 2) continue; + reg ^= (1 << index); + + /* side two */ + /* number of physical banks */ + byte = smbus_read_byte(device, 5); + if (byte <= 1) continue; + /* There is only the symmetrical case */ + reg ^= (1 << (index +1)); + } + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x53, reg); + /* Now see if reg is 0xff. If it is we are done. If not, + * we need to set 0x18 into regster 0x50.l + * we will do this in two steps, first or in 0x80 to 0x50.b, + * then or in 0x1 to 0x51.b + */ +#if HAVE_STRING_SUPPORT + print_debug("spd_set_nbxcfg reg="); print_debug_hex8(reg); print_debug("\n"); +#endif + if (reg != 0xff) { + unsigned char byte; + byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x50); + byte |= 0x80; + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x50, byte); + byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x51); + byte |= 1; + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x51, byte); + /* try this. + * We should be setting bit 2 in register 76 and we're not + * technically we should see if CL=2 for the ram, + * but registered is so screwed up that it's kind of a lost + * cause. + */ + byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76); + byte |= 4; + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, byte); +#if HAVE_STRING_SUPPORT + print_debug("spd_set_nbxcfg 0x76.b="); print_debug_hex8(byte); print_debug("\n"); +#endif + } +} + +void sdram_set_spd_registers(void) +{ + spd_set_drb(); + spd_set_dramc(); + spd_set_rps(); + spd_set_sdramc(); + spd_set_pgpol(); + spd_set_nbxcfg(); +} + +void sdram_first_normal_reference(void) +{ + return; +} + +void sdram_special_finishup(void) +{ + return; +} + +static void set_ram_command(unsigned command) +{ + unsigned char byte; + command &= 0x7; + byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76); + byte &= 0x1f; + byte |= (command << 5); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, byte); +#if HAVE_STRING_SUPPORT + print_debug("set_ram_command 0x76.b="); print_debug_hex8(byte); print_debug("\n"); +#endif +} + +#define RAM_COMMAND_NONE 0x0 +#define RAM_COMMAND_NOOP 0x1 +#define RAM_COMMAND_PRECHARGE 0x2 +#define RAM_COMMAND_MRS 0x3 +#define RAM_COMMAND_CBR 0x4 + +void sdram_set_command_none(void) +{ + set_ram_command(RAM_COMMAND_NONE); +} +void sdram_set_command_noop(void) +{ + set_ram_command(RAM_COMMAND_NOOP); +} +void sdram_set_command_precharge(void) +{ + set_ram_command(RAM_COMMAND_PRECHARGE); +} + +static unsigned long dimm_base(int n) +{ + unsigned char byte; + unsigned long result; + if (n == 0) { + return 0; + } + + byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x60 + (n - 1)); + result = byte; + result <<= 23; + return result; +} + +static void dimms_read(unsigned long offset) +{ + int i; + for(i = 0; i < 8; i++) { + unsigned long dummy; + unsigned long addr; + unsigned long next_base; + + next_base = dimm_base(i +1); + addr = dimm_base(i); + if (addr == next_base) { + continue; + } + addr += offset; +#if HAVE_STRING_SUPPORT + print_debug("Reading "); + print_debug_hex32(addr); + print_debug("\n"); +#endif +#if HAVE_POINTER_SUPPORT +#if HAVE_MACRO_ARG_SUPPORT + dummy = RAM(unsigned long, addr); +#else + dummy = *((volatile unsigned long *)(addr)); +#endif +#endif +#if HAVE_STRING_SUPPORT + print_debug("Reading "); + print_debug_hex32(addr ^ 0xddf8); + print_debug("\n"); +#endif +#if HAVE_POINTER_SUPPORT +#if HAVE_MACRO_ARG_SUPPORT + dummy = RAM(unsigned long, addr ^ 0xdff8); +#else + dummy = *((volatile unsigned long *)(addr ^ 0xdff8)); +#endif +#endif +#if HAVE_STRING_SUPPORT + print_debug("Read "); + print_debug_hex32(addr); + print_debug_hex32(addr ^ 0xddf8); + print_debug("\n"); +#endif + } +} + +void sdram_set_command_cbr(void) +{ + set_ram_command(RAM_COMMAND_CBR); +} + +void sdram_assert_command(void) +{ + dimms_read(0x400); +} + +void sdram_set_mode_register(void) +{ + unsigned char byte; + unsigned cas_mode; + set_ram_command(RAM_COMMAND_MRS); + byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76); + cas_mode = byte & 0x4; + cas_mode ^= 4; + cas_mode <<= 2; + cas_mode |= 0x2a; + cas_mode <<= 3; + dimms_read(cas_mode); +} + +void sdram_enable_refresh(void) +{ + spd_enable_refresh(); +} + + +unsigned long sdram_get_ecc_size_bytes(void) +{ + unsigned char byte; + unsigned long size; + /* FIXME handle the no ram case. */ + /* Read the RAM SIZE */ + byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x67); + /* Convert it to bytes */ + size = byte; + size <<= 23; +#if !USE_ECC + size = 0; +#endif + return size; +} + +/* Dummy udelay code acting as a place holder... */ +void udelay(int count) +{ + int i; + i = 5; +} + +void sdram_enable(void) +{ +#if HAVE_STRING_SUPPORT + print_debug("Ram Enable 1\n"); +#endif + + /* noop command */ + sdram_set_command_noop(); + udelay(200); + sdram_assert_command(); + + /* Precharge all */ + sdram_set_command_precharge(); + sdram_assert_command(); + + /* wait until the all banks idle state... */ +#if HAVE_STRING_SUPPORT + print_debug("Ram Enable 2\n"); +#endif + + /* Now we need 8 AUTO REFRESH / CBR cycles to be performed */ + + sdram_set_command_cbr(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + +#if HAVE_STRING_SUPPORT + print_debug("Ram Enable 3\n"); +#endif + + /* mode register set */ + sdram_set_mode_register(); + /* MAx[14:0] lines, + * MAx[2:0 ] 010 == burst mode of 4 + * MAx[3:3 ] 1 == interleave wrap type + * MAx[4:4 ] == CAS# latency bit + * MAx[6:5 ] == 01 + * MAx[12:7] == 0 + */ + +#if HAVE_STRING_SUPPORT + print_debug("Ram Enable 4\n"); +#endif + + /* normal operation */ + sdram_set_command_none(); + +#if HAVE_STRING_SUPPORT + print_debug("Ram Enable 5\n"); +#endif +} + +/* Setup SDRAM */ +void sdram_initialize(void) +{ +#if HAVE_STRING_SUPPORT + print_debug("Ram1\n"); +#endif + /* Set the registers we can set once to reasonable values */ + sdram_set_registers(); + +#if HAVE_STRING_SUPPORT + print_debug("Ram2\n"); +#endif + /* Now setup those things we can auto detect */ + sdram_set_spd_registers(); + +#if HAVE_STRING_SUPPORT + print_debug("Ram3\n"); +#endif + /* Now that everything is setup enable the SDRAM. + * Some chipsets do the work for use while on others + * we need to it by hand. + */ + sdram_enable(); + +#if HAVE_STRING_SUPPORT + print_debug("Ram4\n"); +#endif + sdram_first_normal_reference(); + +#if HAVE_STRING_SUPPORT + print_debug("Ram5\n"); +#endif + sdram_enable_refresh(); + sdram_special_finishup(); + +#if HAVE_STRING_SUPPORT + print_debug("Ram6\n"); +#endif +} diff --git a/util/romcc/tests/raminit_test7.c b/util/romcc/tests/raminit_test7.c new file mode 100644 index 0000000000..be62d30573 --- /dev/null +++ b/util/romcc/tests/raminit_test7.c @@ -0,0 +1,2805 @@ +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned char uint_least8_t; +typedef signed char int_least8_t; +typedef unsigned short uint_least16_t; +typedef signed short int_least16_t; +typedef unsigned int uint_least32_t; +typedef signed int int_least32_t; + +typedef unsigned char uint_fast8_t; +typedef signed char int_fast8_t; +typedef unsigned int uint_fast16_t; +typedef signed int int_fast16_t; +typedef unsigned int uint_fast32_t; +typedef signed int int_fast32_t; + +typedef int intptr_t; +typedef unsigned int uintptr_t; + +typedef long int intmax_t; +typedef unsigned long int uintmax_t; + +static inline unsigned long apic_read(unsigned long reg) +{ + return *((volatile unsigned long *)(0xfee00000 +reg)); +} +static inline void apic_write(unsigned long reg, unsigned long v) +{ + *((volatile unsigned long *)(0xfee00000 +reg)) = v; +} +static inline void apic_wait_icr_idle(void) +{ + do { } while ( apic_read( 0x300 ) & 0x01000 ); +} + +static void outb(unsigned char value, unsigned short port) +{ + __builtin_outb(value, port); +} +static void outw(unsigned short value, unsigned short port) +{ + __builtin_outw(value, port); +} +static void outl(unsigned int value, unsigned short port) +{ + __builtin_outl(value, port); +} +static unsigned char inb(unsigned short port) +{ + return __builtin_inb(port); +} +static unsigned char inw(unsigned short port) +{ + return __builtin_inw(port); +} +static unsigned char inl(unsigned short port) +{ + return __builtin_inl(port); +} +static inline void outsb(uint16_t port, const void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; outsb " + : "=S" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} +static inline void outsw(uint16_t port, const void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; outsw " + : "=S" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} +static inline void outsl(uint16_t port, const void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; outsl " + : "=S" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} +static inline void insb(uint16_t port, void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; insb " + : "=D" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} +static inline void insw(uint16_t port, void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; insw " + : "=D" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} +static inline void insl(uint16_t port, void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; insl " + : "=D" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} +static inline void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg) +{ + outb(reg, port); + outb(value, port +1); +} +static inline unsigned char pnp_read_config(unsigned char port, unsigned char reg) +{ + outb(reg, port); + return inb(port +1); +} +static inline void pnp_set_logical_device(unsigned char port, int device) +{ + pnp_write_config(port, device, 0x07); +} +static inline void pnp_set_enable(unsigned char port, int enable) +{ + pnp_write_config(port, enable?0x1:0x0, 0x30); +} +static inline int pnp_read_enable(unsigned char port) +{ + return !!pnp_read_config(port, 0x30); +} +static inline void pnp_set_iobase0(unsigned char port, unsigned iobase) +{ + pnp_write_config(port, (iobase >> 8) & 0xff, 0x60); + pnp_write_config(port, iobase & 0xff, 0x61); +} +static inline void pnp_set_iobase1(unsigned char port, unsigned iobase) +{ + pnp_write_config(port, (iobase >> 8) & 0xff, 0x62); + pnp_write_config(port, iobase & 0xff, 0x63); +} +static inline void pnp_set_irq0(unsigned char port, unsigned irq) +{ + pnp_write_config(port, irq, 0x70); +} +static inline void pnp_set_irq1(unsigned char port, unsigned irq) +{ + pnp_write_config(port, irq, 0x72); +} +static inline void pnp_set_drq(unsigned char port, unsigned drq) +{ + pnp_write_config(port, drq & 0xff, 0x74); +} +static void hlt(void) +{ + __builtin_hlt(); +} +typedef __builtin_div_t div_t; +typedef __builtin_ldiv_t ldiv_t; +typedef __builtin_udiv_t udiv_t; +typedef __builtin_uldiv_t uldiv_t; +static div_t div(int numer, int denom) +{ + return __builtin_div(numer, denom); +} +static ldiv_t ldiv(long numer, long denom) +{ + return __builtin_ldiv(numer, denom); +} +static udiv_t udiv(unsigned numer, unsigned denom) +{ + return __builtin_udiv(numer, denom); +} +static uldiv_t uldiv(unsigned long numer, unsigned long denom) +{ + return __builtin_uldiv(numer, denom); +} +int log2(int value) +{ + + return __builtin_bsr(value); +} +typedef unsigned device_t; +static unsigned char pci_read_config8(device_t dev, unsigned where) +{ + unsigned addr; + addr = dev | where; + outl(0x80000000 | (addr & ~3), 0xCF8); + return inb(0xCFC + (addr & 3)); +} +static unsigned short pci_read_config16(device_t dev, unsigned where) +{ + unsigned addr; + addr = dev | where; + outl(0x80000000 | (addr & ~3), 0xCF8); + return inw(0xCFC + (addr & 2)); +} +static unsigned int pci_read_config32(device_t dev, unsigned where) +{ + unsigned addr; + addr = dev | where; + outl(0x80000000 | (addr & ~3), 0xCF8); + return inl(0xCFC); +} +static void pci_write_config8(device_t dev, unsigned where, unsigned char value) +{ + unsigned addr; + addr = dev | where; + outl(0x80000000 | (addr & ~3), 0xCF8); + outb(value, 0xCFC + (addr & 3)); +} +static void pci_write_config16(device_t dev, unsigned where, unsigned short value) +{ + unsigned addr; + addr = dev | where; + outl(0x80000000 | (addr & ~3), 0xCF8); + outw(value, 0xCFC + (addr & 2)); +} +static void pci_write_config32(device_t dev, unsigned where, unsigned int value) +{ + unsigned addr; + addr = dev | where; + outl(0x80000000 | (addr & ~3), 0xCF8); + outl(value, 0xCFC); +} +static device_t pci_locate_device(unsigned pci_id, device_t dev) +{ + for(; dev <= ( ((( 255 ) & 0xFF) << 16) | ((( 31 ) & 0x1f) << 11) | ((( 7 ) & 0x7) << 8)) ; dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ) { + unsigned int id; + id = pci_read_config32(dev, 0); + if (id == pci_id) { + return dev; + } + } + return (0xffffffffU) ; +} + + + + + +static int uart_can_tx_byte(void) +{ + return inb(1016 + 0x05 ) & 0x20; +} +static void uart_wait_to_tx_byte(void) +{ + while(!uart_can_tx_byte()) + ; +} +static void uart_wait_until_sent(void) +{ + while(!(inb(1016 + 0x05 ) & 0x40)) + ; +} +static void uart_tx_byte(unsigned char data) +{ + uart_wait_to_tx_byte(); + outb(data, 1016 + 0x00 ); + + uart_wait_until_sent(); +} +static void uart_init(void) +{ + + outb(0x0, 1016 + 0x01 ); + + outb(0x01, 1016 + 0x02 ); + + outb(0x80 | 3 , 1016 + 0x03 ); + outb((115200/ 115200 ) & 0xFF, 1016 + 0x00 ); + outb(((115200/ 115200 ) >> 8) & 0xFF, 1016 + 0x01 ); + outb(3 , 1016 + 0x03 ); +} + +static void __console_tx_byte(unsigned char byte) +{ + uart_tx_byte(byte); +} +static void __console_tx_nibble(unsigned nibble) +{ + unsigned char digit; + digit = nibble + '0'; + if (digit > '9') { + digit += 39; + } + __console_tx_byte(digit); +} +static void __console_tx_char(int loglevel, unsigned char byte) +{ + if (8 > loglevel) { + uart_tx_byte(byte); + } +} +static void __console_tx_hex8(int loglevel, unsigned char value) +{ + if (8 > loglevel) { + __console_tx_nibble((value >> 4U) & 0x0fU); + __console_tx_nibble(value & 0x0fU); + } +} +static void __console_tx_hex16(int loglevel, unsigned short value) +{ + if (8 > loglevel) { + __console_tx_nibble((value >> 12U) & 0x0fU); + __console_tx_nibble((value >> 8U) & 0x0fU); + __console_tx_nibble((value >> 4U) & 0x0fU); + __console_tx_nibble(value & 0x0fU); + } +} +static void __console_tx_hex32(int loglevel, unsigned int value) +{ + if (8 > loglevel) { + __console_tx_nibble((value >> 28U) & 0x0fU); + __console_tx_nibble((value >> 24U) & 0x0fU); + __console_tx_nibble((value >> 20U) & 0x0fU); + __console_tx_nibble((value >> 16U) & 0x0fU); + __console_tx_nibble((value >> 12U) & 0x0fU); + __console_tx_nibble((value >> 8U) & 0x0fU); + __console_tx_nibble((value >> 4U) & 0x0fU); + __console_tx_nibble(value & 0x0fU); + } +} + +static void do_console_tx_string(const char *str) __attribute__((noinline)) +{ + unsigned char ch; + while((ch = *str++) != '\0') { + __console_tx_byte(ch); + } +} +static void __console_tx_string(int loglevel, const char *str) +{ + if (8 > loglevel) { + do_console_tx_string(str); + } +} +static void print_emerg_char(unsigned char byte) { __console_tx_char(0 , byte); } +static void print_emerg_hex8(unsigned char value){ __console_tx_hex8(0 , value); } +static void print_emerg_hex16(unsigned short value){ __console_tx_hex16(0 , value); } +static void print_emerg_hex32(unsigned int value) { __console_tx_hex32(0 , value); } +static void print_emerg(const char *str) { __console_tx_string(0 , str); } +static void print_alert_char(unsigned char byte) { __console_tx_char(1 , byte); } +static void print_alert_hex8(unsigned char value) { __console_tx_hex8(1 , value); } +static void print_alert_hex16(unsigned short value){ __console_tx_hex16(1 , value); } +static void print_alert_hex32(unsigned int value) { __console_tx_hex32(1 , value); } +static void print_alert(const char *str) { __console_tx_string(1 , str); } +static void print_crit_char(unsigned char byte) { __console_tx_char(2 , byte); } +static void print_crit_hex8(unsigned char value) { __console_tx_hex8(2 , value); } +static void print_crit_hex16(unsigned short value){ __console_tx_hex16(2 , value); } +static void print_crit_hex32(unsigned int value) { __console_tx_hex32(2 , value); } +static void print_crit(const char *str) { __console_tx_string(2 , str); } +static void print_err_char(unsigned char byte) { __console_tx_char(3 , byte); } +static void print_err_hex8(unsigned char value) { __console_tx_hex8(3 , value); } +static void print_err_hex16(unsigned short value){ __console_tx_hex16(3 , value); } +static void print_err_hex32(unsigned int value) { __console_tx_hex32(3 , value); } +static void print_err(const char *str) { __console_tx_string(3 , str); } +static void print_warning_char(unsigned char byte) { __console_tx_char(4 , byte); } +static void print_warning_hex8(unsigned char value) { __console_tx_hex8(4 , value); } +static void print_warning_hex16(unsigned short value){ __console_tx_hex16(4 , value); } +static void print_warning_hex32(unsigned int value) { __console_tx_hex32(4 , value); } +static void print_warning(const char *str) { __console_tx_string(4 , str); } +static void print_notice_char(unsigned char byte) { __console_tx_char(5 , byte); } +static void print_notice_hex8(unsigned char value) { __console_tx_hex8(5 , value); } +static void print_notice_hex16(unsigned short value){ __console_tx_hex16(5 , value); } +static void print_notice_hex32(unsigned int value) { __console_tx_hex32(5 , value); } +static void print_notice(const char *str) { __console_tx_string(5 , str); } +static void print_info_char(unsigned char byte) { __console_tx_char(6 , byte); } +static void print_info_hex8(unsigned char value) { __console_tx_hex8(6 , value); } +static void print_info_hex16(unsigned short value){ __console_tx_hex16(6 , value); } +static void print_info_hex32(unsigned int value) { __console_tx_hex32(6 , value); } +static void print_info(const char *str) { __console_tx_string(6 , str); } +static void print_debug_char(unsigned char byte) { __console_tx_char(7 , byte); } +static void print_debug_hex8(unsigned char value) { __console_tx_hex8(7 , value); } +static void print_debug_hex16(unsigned short value){ __console_tx_hex16(7 , value); } +static void print_debug_hex32(unsigned int value) { __console_tx_hex32(7 , value); } +static void print_debug(const char *str) { __console_tx_string(7 , str); } +static void print_spew_char(unsigned char byte) { __console_tx_char(8 , byte); } +static void print_spew_hex8(unsigned char value) { __console_tx_hex8(8 , value); } +static void print_spew_hex16(unsigned short value){ __console_tx_hex16(8 , value); } +static void print_spew_hex32(unsigned int value) { __console_tx_hex32(8 , value); } +static void print_spew(const char *str) { __console_tx_string(8 , str); } +static void console_init(void) +{ + static const char console_test[] = + "\r\n\r\nLinuxBIOS-" + "1.1.4" + ".0Fallback" + " " + "Thu Oct 9 20:29:48 MDT 2003" + " starting...\r\n"; + print_info(console_test); +} +static void die(const char *str) +{ + print_emerg(str); + do { + hlt(); + } while(1); +} +static void write_phys(unsigned long addr, unsigned long value) +{ + asm volatile( + "movnti %1, (%0)" + : + : "r" (addr), "r" (value) + : + ); +} +static unsigned long read_phys(unsigned long addr) +{ + volatile unsigned long *ptr; + ptr = (void *)addr; + return *ptr; +} +static void ram_fill(unsigned long start, unsigned long stop) +{ + unsigned long addr; + + print_debug("DRAM fill: "); + print_debug_hex32(start); + print_debug("-"); + print_debug_hex32(stop); + print_debug("\r\n"); + for(addr = start; addr < stop ; addr += 4) { + + if (!(addr & 0xffff)) { + print_debug_hex32(addr); + print_debug("\r"); + } + write_phys(addr, addr); + }; + + print_debug_hex32(addr); + print_debug("\r\nDRAM filled\r\n"); +} +static void ram_verify(unsigned long start, unsigned long stop) +{ + unsigned long addr; + + print_debug("DRAM verify: "); + print_debug_hex32(start); + print_debug_char('-'); + print_debug_hex32(stop); + print_debug("\r\n"); + for(addr = start; addr < stop ; addr += 4) { + unsigned long value; + + if (!(addr & 0xffff)) { + print_debug_hex32(addr); + print_debug("\r"); + } + value = read_phys(addr); + if (value != addr) { + + print_err_hex32(addr); + print_err_char(':'); + print_err_hex32(value); + print_err("\r\n"); + } + } + + print_debug_hex32(addr); + print_debug("\r\nDRAM verified\r\n"); +} +void ram_check(unsigned long start, unsigned long stop) +{ + int result; + + print_debug("Testing DRAM : "); + print_debug_hex32(start); + print_debug("-"); + print_debug_hex32(stop); + print_debug("\r\n"); + ram_fill(start, stop); + ram_verify(start, stop); + print_debug("Done.\r\n"); +} +static int enumerate_ht_chain(unsigned link) +{ + + unsigned next_unitid, last_unitid; + int reset_needed = 0; + next_unitid = 1; + do { + uint32_t id; + uint8_t hdr_type, pos; + last_unitid = next_unitid; + id = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x00 ); + + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + break; + } + hdr_type = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x0e ); + pos = 0; + hdr_type &= 0x7f; + if ((hdr_type == 0 ) || + (hdr_type == 1 )) { + pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x34 ); + } + while(pos != 0) { + uint8_t cap; + cap = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 0 ); + if (cap == 0x08 ) { + uint16_t flags; + flags = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 2 ); + if ((flags >> 13) == 0) { + unsigned count; + flags &= ~0x1f; + flags |= next_unitid & 0x1f; + count = (flags >> 5) & 0x1f; + pci_write_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 2 , flags); + next_unitid += count; + break; + } + } + pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 1 ); + } + } while((last_unitid != next_unitid) && (next_unitid <= 0x1f)); + return reset_needed; +} +static void enable_smbus(void) +{ + device_t dev; + dev = pci_locate_device((((( 0x746b ) & 0xFFFF) << 16) | (( 0x1022 ) & 0xFFFF)) , 0); + if (dev == (0xffffffffU) ) { + die("SMBUS controller not found\r\n"); + } + uint8_t enable; + print_debug("SMBus controller enabled\r\n"); + pci_write_config32(dev, 0x58, 0x0f00 | 1); + enable = pci_read_config8(dev, 0x41); + pci_write_config8(dev, 0x41, enable | (1 << 7)); + + outw(inw(0x0f00 + 0xe0 ), 0x0f00 + 0xe0 ); +} +static inline void smbus_delay(void) +{ + outb(0x80, 0x80); +} +static int smbus_wait_until_ready(void) +{ + unsigned long loops; + loops = (100*1000*10) ; + do { + unsigned short val; + smbus_delay(); + val = inw(0x0f00 + 0xe0 ); + if ((val & 0x800) == 0) { + break; + } + if(loops == ((100*1000*10) / 2)) { + outw(inw(0x0f00 + 0xe0 ), + 0x0f00 + 0xe0 ); + } + } while(--loops); + return loops?0:-2; +} +static int smbus_wait_until_done(void) +{ + unsigned long loops; + loops = (100*1000*10) ; + do { + unsigned short val; + smbus_delay(); + + val = inw(0x0f00 + 0xe0 ); + if (((val & 0x8) == 0) | ((val & 0x437) != 0)) { + break; + } + } while(--loops); + return loops?0:-3; +} +static int smbus_read_byte(unsigned device, unsigned address) +{ + unsigned char global_control_register; + unsigned char global_status_register; + unsigned char byte; + if (smbus_wait_until_ready() < 0) { + return -2; + } + + + + outw(inw(0x0f00 + 0xe2 ) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), 0x0f00 + 0xe2 ); + + outw(((device & 0x7f) << 1) | 1, 0x0f00 + 0xe4 ); + + outb(address & 0xFF, 0x0f00 + 0xe8 ); + + outw((inw(0x0f00 + 0xe2 ) & ~7) | (0x2), 0x0f00 + 0xe2 ); + + + outw(inw(0x0f00 + 0xe0 ), 0x0f00 + 0xe0 ); + + outw(0, 0x0f00 + 0xe6 ); + + outw((inw(0x0f00 + 0xe2 ) | (1 << 3)), 0x0f00 + 0xe2 ); + + if (smbus_wait_until_done() < 0) { + return -3; + } + global_status_register = inw(0x0f00 + 0xe0 ); + + byte = inw(0x0f00 + 0xe6 ) & 0xff; + if (global_status_register != (1 << 4)) { + return -1; + } + return byte; +} +static void smbus_write_byte(unsigned device, unsigned address, unsigned char val) +{ + return; +} +struct mem_controller { + unsigned node_id; + device_t f0, f1, f2, f3; + uint8_t channel0[4]; + uint8_t channel1[4]; +}; +typedef __builtin_msr_t msr_t; +static msr_t rdmsr(unsigned long index) +{ + return __builtin_rdmsr(index); +} +static void wrmsr(unsigned long index, msr_t msr) +{ + __builtin_wrmsr(index, msr.lo, msr.hi); +} +struct tsc_struct { + unsigned lo; + unsigned hi; +}; +typedef struct tsc_struct tsc_t; +static tsc_t rdtsc(void) +{ + tsc_t res; + asm ("rdtsc" + : "=a" (res.lo), "=d"(res.hi) + : + : + ); + return res; +} +void init_timer(void) +{ + + apic_write(0x320 , (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0)); + + apic_write(0x3E0 , 0xB ); + + apic_write(0x380 , 0xffffffff); +} +void udelay(unsigned usecs) +{ + uint32_t start, value, ticks; + + ticks = usecs * 200; + start = apic_read(0x390 ); + do { + value = apic_read(0x390 ); + } while((start - value) < ticks); + +} +void mdelay(unsigned msecs) +{ + unsigned i; + for(i = 0; i < msecs; i++) { + udelay(1000); + } +} +void delay(unsigned secs) +{ + unsigned i; + for(i = 0; i < secs; i++) { + mdelay(1000); + } +} +int boot_cpu(void) +{ + volatile unsigned long *local_apic; + unsigned long apic_id; + int bsp; + msr_t msr; + msr = rdmsr(0x1b); + bsp = !!(msr.lo & (1 << 8)); + return bsp; +} +static int cpu_init_detected(void) +{ + unsigned long htic; + htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c ); + return !!(htic & (1<<6) ); +} +static int bios_reset_detected(void) +{ + unsigned long htic; + htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c ); + return (htic & (1<<4) ) && !(htic & (1<<5) ); +} +static int cold_reset_detected(void) +{ + unsigned long htic; + htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c ); + return !(htic & (1<<4) ); +} +static void distinguish_cpu_resets(unsigned node_id) +{ + uint32_t htic; + device_t device; + device = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 + node_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ; + htic = pci_read_config32(device, 0x6c ); + htic |= (1<<4) | (1<<5) | (1<<6) ; + pci_write_config32(device, 0x6c , htic); +} +static void set_bios_reset(void) +{ + unsigned long htic; + htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c ); + htic &= ~(1<<5) ; + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c , htic); +} +static void print_debug_pci_dev(unsigned dev) +{ + print_debug("PCI: "); + print_debug_hex8((dev >> 16) & 0xff); + print_debug_char(':'); + print_debug_hex8((dev >> 11) & 0x1f); + print_debug_char('.'); + print_debug_hex8((dev >> 8) & 7); +} +static void print_pci_devices(void) +{ + device_t dev; + for(dev = ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ; + dev <= ( ((( 0 ) & 0xFF) << 16) | ((( 0x1f ) & 0x1f) << 11) | ((( 0x7 ) & 0x7) << 8)) ; + dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ) { + uint32_t id; + id = pci_read_config32(dev, 0x00 ); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + print_debug_pci_dev(dev); + print_debug("\r\n"); + } +} +static void dump_pci_device(unsigned dev) +{ + int i; + print_debug_pci_dev(dev); + print_debug("\r\n"); + + for(i = 0; i <= 255; i++) { + unsigned char val; + if ((i & 0x0f) == 0) { + print_debug_hex8(i); + print_debug_char(':'); + } + val = pci_read_config8(dev, i); + print_debug_char(' '); + print_debug_hex8(val); + if ((i & 0x0f) == 0x0f) { + print_debug("\r\n"); + } + } +} +static void dump_pci_devices(void) +{ + device_t dev; + for(dev = ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ; + dev <= ( ((( 0 ) & 0xFF) << 16) | ((( 0x1f ) & 0x1f) << 11) | ((( 0x7 ) & 0x7) << 8)) ; + dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ) { + uint32_t id; + id = pci_read_config32(dev, 0x00 ); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + dump_pci_device(dev); + } +} +static void dump_spd_registers(const struct mem_controller *ctrl) +{ + int i; + print_debug("\r\n"); + for(i = 0; i < 4; i++) { + unsigned device; + device = ctrl->channel0[i]; + if (device) { + int j; + print_debug("dimm: "); + print_debug_hex8(i); + print_debug(".0: "); + print_debug_hex8(device); + for(j = 0; j < 256; j++) { + int status; + unsigned char byte; + if ((j & 0xf) == 0) { + print_debug("\r\n"); + print_debug_hex8(j); + print_debug(": "); + } + status = smbus_read_byte(device, j); + if (status < 0) { + print_debug("bad device\r\n"); + break; + } + byte = status & 0xff; + print_debug_hex8(byte); + print_debug_char(' '); + } + print_debug("\r\n"); + } + device = ctrl->channel1[i]; + if (device) { + int j; + print_debug("dimm: "); + print_debug_hex8(i); + print_debug(".1: "); + print_debug_hex8(device); + for(j = 0; j < 256; j++) { + int status; + unsigned char byte; + if ((j & 0xf) == 0) { + print_debug("\r\n"); + print_debug_hex8(j); + print_debug(": "); + } + status = smbus_read_byte(device, j); + if (status < 0) { + print_debug("bad device\r\n"); + break; + } + byte = status & 0xff; + print_debug_hex8(byte); + print_debug_char(' '); + } + print_debug("\r\n"); + } + } +} + +static unsigned int cpuid(unsigned int op) +{ + unsigned int ret; + unsigned dummy2,dummy3,dummy4; + asm volatile ( + "cpuid" + : "=a" (ret), "=b" (dummy2), "=c" (dummy3), "=d" (dummy4) + : "a" (op) + ); + return ret; +} +static int is_cpu_rev_a0(void) +{ + return (cpuid(1) & 0xffff) == 0x0f10; +} +static int is_cpu_pre_c0(void) +{ + return (cpuid(1) & 0xffef) < 0x0f48; +} +static void memreset_setup(void) +{ + if (is_cpu_pre_c0()) { + + outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00 + 0xc0 + 28); + + outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00 + 0xc0 + 29); + } + else { + + outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00 + 0xc0 + 29); + } +} +static void memreset(int controllers, const struct mem_controller *ctrl) +{ + if (is_cpu_pre_c0()) { + udelay(800); + + outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00 + 0xc0 + 28); + udelay(90); + } +} +static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes) +{ + + uint32_t ret=0x00010101; + static const unsigned int rows_2p[2][2] = { + { 0x00050101, 0x00010404 }, + { 0x00010404, 0x00050101 } + }; + if(maxnodes>2) { + print_debug("this mainboard is only designed for 2 cpus\r\n"); + maxnodes=2; + } + if (!(node>=maxnodes || row>=maxnodes)) { + ret=rows_2p[node][row]; + } + return ret; +} +static inline int spd_read_byte(unsigned device, unsigned address) +{ + return smbus_read_byte(device, address); +} + +static void coherent_ht_mainboard(unsigned cpus) +{ +} + +void cpu_ldtstop(unsigned cpus) +{ + uint32_t tmp; + device_t dev; + unsigned cnt; + for(cnt=0; cnt<cpus; cnt++) { + + pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0x81,0x23); + + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0xd4,0x00000701); + + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0xd8,0x00000000); + + tmp=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,0x90); + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,0x90, tmp | (1<<24) ); + } +} + + + + + +static void setup_resource_map(const unsigned int *register_values, int max) +{ + int i; + print_debug("setting up resource map....\r\n"); + for(i = 0; i < max; i += 3) { + device_t dev; + unsigned where; + unsigned long reg; + dev = register_values[i] & ~0xff; + where = register_values[i] & 0xff; + reg = pci_read_config32(dev, where); + reg &= register_values[i+1]; + reg |= register_values[i+2]; + pci_write_config32(dev, where, reg); + } + print_debug("done.\r\n"); +} +static void setup_default_resource_map(void) +{ + static const unsigned int register_values[] = { + + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x84 ) & 0xFF)) , 0x00000048, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x8C ) & 0xFF)) , 0x00000048, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x94 ) & 0xFF)) , 0x00000048, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x9C ) & 0xFF)) , 0x00000048, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xA4 ) & 0xFF)) , 0x00000048, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xAC ) & 0xFF)) , 0x00000048, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xB4 ) & 0xFF)) , 0x00000048, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xBC ) & 0xFF)) , 0x00000048, 0x00ffff00, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x80 ) & 0xFF)) , 0x000000f0, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x88 ) & 0xFF)) , 0x000000f0, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x90 ) & 0xFF)) , 0x000000f0, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0x000000f0, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xA0 ) & 0xFF)) , 0x000000f0, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xA8 ) & 0xFF)) , 0x000000f0, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xB0 ) & 0xFF)) , 0x000000f0, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xB8 ) & 0xFF)) , 0x000000f0, 0x00fc0003, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xC4 ) & 0xFF)) , 0xFE000FC8, 0x01fff000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xCC ) & 0xFF)) , 0xFE000FC8, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xD4 ) & 0xFF)) , 0xFE000FC8, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xDC ) & 0xFF)) , 0xFE000FC8, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xC0 ) & 0xFF)) , 0xFE000FCC, 0x00000003, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xC8 ) & 0xFF)) , 0xFE000FCC, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xD0 ) & 0xFF)) , 0xFE000FCC, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xD8 ) & 0xFF)) , 0xFE000FCC, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xE0 ) & 0xFF)) , 0x0000FC88, 0xff000003, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xE4 ) & 0xFF)) , 0x0000FC88, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xE8 ) & 0xFF)) , 0x0000FC88, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xEC ) & 0xFF)) , 0x0000FC88, 0x00000000, + }; + int max; + max = sizeof(register_values)/sizeof(register_values[0]); + setup_resource_map(register_values, max); +} +static void sdram_set_registers(const struct mem_controller *ctrl) +{ + static const unsigned int register_values[] = { + + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x40 ) & 0xFF)) , 0x001f01fe, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x44 ) & 0xFF)) , 0x001f01fe, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x48 ) & 0xFF)) , 0x001f01fe, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x4C ) & 0xFF)) , 0x001f01fe, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x50 ) & 0xFF)) , 0x001f01fe, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x54 ) & 0xFF)) , 0x001f01fe, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0x001f01fe, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x001f01fe, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0xC01f01ff, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x64 ) & 0xFF)) , 0xC01f01ff, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x68 ) & 0xFF)) , 0xC01f01ff, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x6C ) & 0xFF)) , 0xC01f01ff, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x70 ) & 0xFF)) , 0xC01f01ff, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x74 ) & 0xFF)) , 0xC01f01ff, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x78 ) & 0xFF)) , 0xC01f01ff, 0x00000000, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x7C ) & 0xFF)) , 0xC01f01ff, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x80 ) & 0xFF)) , 0xffff8888, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x88 ) & 0xFF)) , 0xe8088008, 0x02522001 , + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x8c ) & 0xFF)) , 0xff8fe08e, (0 << 20)|(0 << 8)|(0 << 4)|(0 << 0), + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x90 ) & 0xFF)) , 0xf0000000, + (4 << 25)|(0 << 24)| + (0 << 23)|(0 << 22)|(0 << 21)|(0 << 20)| + (1 << 19)|(0 << 18)|(1 << 17)|(0 << 16)| + (2 << 14)|(0 << 13)|(0 << 12)| + (0 << 11)|(0 << 10)|(0 << 9)|(0 << 8)| + (0 << 3) |(0 << 1) |(0 << 0), + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x94 ) & 0xFF)) , 0xc180f0f0, + (0 << 29)|(0 << 28)|(0 << 27)|(0 << 26)|(0 << 25)| + (0 << 20)|(0 << 19)|(3 << 16)|(0 << 8)|(0 << 0), + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0xfc00ffff, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0xffe0e0e0, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000003e, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0xffffff00, 0x00000000, + + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x94 ) & 0xFF)) , 0xffff8000, 0x00000f70, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x90 ) & 0xFF)) , 0xffffff80, 0x00000002, + ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0x0000000f, 0x00068300, + }; + int i; + int max; + print_debug("setting up CPU"); + print_debug_hex8(ctrl->node_id); + print_debug(" northbridge registers\r\n"); + max = sizeof(register_values)/sizeof(register_values[0]); + for(i = 0; i < max; i += 3) { + device_t dev; + unsigned where; + unsigned long reg; + dev = (register_values[i] & ~0xff) - ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) + ctrl->f0; + where = register_values[i] & 0xff; + reg = pci_read_config32(dev, where); + reg &= register_values[i+1]; + reg |= register_values[i+2]; + pci_write_config32(dev, where, reg); + } + print_debug("done.\r\n"); +} +static int is_dual_channel(const struct mem_controller *ctrl) +{ + uint32_t dcl; + dcl = pci_read_config32(ctrl->f2, 0x90 ); + return dcl & (1<<16) ; +} +static int is_opteron(const struct mem_controller *ctrl) +{ + + uint32_t nbcap; + nbcap = pci_read_config32(ctrl->f3, 0xE8 ); + return !!(nbcap & 0x0001 ); +} +static int is_registered(const struct mem_controller *ctrl) +{ + + uint32_t dcl; + dcl = pci_read_config32(ctrl->f2, 0x90 ); + return !(dcl & (1<<18) ); +} +struct dimm_size { + unsigned long side1; + unsigned long side2; +}; +static struct dimm_size spd_get_dimm_size(unsigned device) +{ + + struct dimm_size sz; + int value, low; + sz.side1 = 0; + sz.side2 = 0; + + value = spd_read_byte(device, 3); + if (value < 0) goto out; + sz.side1 += value & 0xf; + value = spd_read_byte(device, 4); + if (value < 0) goto out; + sz.side1 += value & 0xf; + value = spd_read_byte(device, 17); + if (value < 0) goto out; + sz.side1 += log2(value & 0xff); + + value = spd_read_byte(device, 7); + if (value < 0) goto out; + value &= 0xff; + value <<= 8; + + low = spd_read_byte(device, 6); + if (low < 0) goto out; + value = value | (low & 0xff); + sz.side1 += log2(value); + + value = spd_read_byte(device, 5); + if (value <= 1) goto out; + + sz.side2 = sz.side1; + value = spd_read_byte(device, 3); + if (value < 0) goto out; + if ((value & 0xf0) == 0) goto out; + sz.side2 -= (value & 0x0f); + sz.side2 += ((value >> 4) & 0x0f); + value = spd_read_byte(device, 4); + if (value < 0) goto out; + sz.side2 -= (value & 0x0f); + sz.side2 += ((value >> 4) & 0x0f); + out: + return sz; +} +static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index) +{ + uint32_t base0, base1, map; + uint32_t dch; + if (sz.side1 != sz.side2) { + sz.side2 = 0; + } + map = pci_read_config32(ctrl->f2, 0x80 ); + map &= ~(0xf << (index + 4)); + + + base0 = base1 = 0; + + if (sz.side1 >= (25 +3)) { + map |= (sz.side1 - (25 + 3)) << (index *4); + base0 = (1 << ((sz.side1 - (25 + 3)) + 21)) | 1; + } + + if (sz.side2 >= (25 + 3)) { + base1 = (1 << ((sz.side2 - (25 + 3)) + 21)) | 1; + } + + if (is_dual_channel(ctrl)) { + base0 = (base0 << 1) | (base0 & 1); + base1 = (base1 << 1) | (base1 & 1); + } + + base0 &= ~0x001ffffe; + base1 &= ~0x001ffffe; + + pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+0)<<2), base0); + pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+1)<<2), base1); + pci_write_config32(ctrl->f2, 0x80 , map); + + + if (base0) { + dch = pci_read_config32(ctrl->f2, 0x94 ); + dch |= (1 << 26) << index; + pci_write_config32(ctrl->f2, 0x94 , dch); + } +} +static void spd_set_ram_size(const struct mem_controller *ctrl) +{ + int i; + + for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { + struct dimm_size sz; + sz = spd_get_dimm_size(ctrl->channel0[i]); + set_dimm_size(ctrl, sz, i); + } +} +static void route_dram_accesses(const struct mem_controller *ctrl, + unsigned long base_k, unsigned long limit_k) +{ + + unsigned node_id; + unsigned limit; + unsigned base; + unsigned index; + unsigned limit_reg, base_reg; + device_t device; + node_id = ctrl->node_id; + index = (node_id << 3); + limit = (limit_k << 2); + limit &= 0xffff0000; + limit -= 0x00010000; + limit |= ( 0 << 8) | (node_id << 0); + base = (base_k << 2); + base &= 0xffff0000; + base |= (0 << 8) | (1<<1) | (1<<0); + limit_reg = 0x44 + index; + base_reg = 0x40 + index; + 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)) ) { + pci_write_config32(device, limit_reg, limit); + pci_write_config32(device, base_reg, base); + } +} +static void set_top_mem(unsigned tom_k) +{ + + if (!tom_k) { + set_bios_reset(); + print_debug("No memory - reset"); + + pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0x04 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) , 0x41, 0xf1); + + outb(0x0e, 0x0cf9); + } + + print_debug("RAM: 0x"); + print_debug_hex32(tom_k); + print_debug(" KB\r\n"); + + msr_t msr; + msr.lo = (tom_k & 0x003fffff) << 10; + msr.hi = (tom_k & 0xffc00000) >> 22; + wrmsr(0xC001001D , msr); + + if (tom_k >= 0x003f0000) { + tom_k = 0x3f0000; + } + msr.lo = (tom_k & 0x003fffff) << 10; + msr.hi = (tom_k & 0xffc00000) >> 22; + wrmsr(0xC001001A , msr); +} +static unsigned long interleave_chip_selects(const struct mem_controller *ctrl) +{ + + static const uint32_t csbase_low[] = { + (1 << (13 - 4)), + (1 << (14 - 4)), + (1 << (14 - 4)), + (1 << (15 - 4)), + (1 << (15 - 4)), + (1 << (16 - 4)), + (1 << (16 - 4)), + }; + uint32_t csbase_inc; + int chip_selects, index; + int bits; + int dual_channel; + unsigned common_size; + uint32_t csbase, csmask; + + chip_selects = 0; + common_size = 0; + for(index = 0; index < 8; index++) { + unsigned size; + uint32_t value; + + value = pci_read_config32(ctrl->f2, 0x40 + (index << 2)); + + + if (!(value & 1)) { + continue; + } + chip_selects++; + size = value >> 21; + if (common_size == 0) { + common_size = size; + } + + if (common_size != size) { + return 0; + } + } + + bits = log2(chip_selects); + if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) { + return 0; + + } + + if ((bits == 3) && (common_size == (1 << (32 - 3)))) { + print_debug("8 4GB chip selects cannot be interleaved\r\n"); + return 0; + } + + if (is_dual_channel(ctrl)) { + csbase_inc = csbase_low[log2(common_size) - 1] << 1; + } else { + csbase_inc = csbase_low[log2(common_size)]; + } + + csbase = 0 | 1; + csmask = (((common_size << bits) - 1) << 21); + csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc); + for(index = 0; index < 8; index++) { + uint32_t value; + value = pci_read_config32(ctrl->f2, 0x40 + (index << 2)); + + if (!(value & 1)) { + continue; + } + pci_write_config32(ctrl->f2, 0x40 + (index << 2), csbase); + pci_write_config32(ctrl->f2, 0x60 + (index << 2), csmask); + csbase += csbase_inc; + } + + print_debug("Interleaved\r\n"); + + return common_size << (15 + bits); +} +static unsigned long order_chip_selects(const struct mem_controller *ctrl) +{ + unsigned long tom; + + + tom = 0; + for(;;) { + + unsigned index, canidate; + uint32_t csbase, csmask; + unsigned size; + csbase = 0; + canidate = 0; + for(index = 0; index < 8; index++) { + uint32_t value; + value = pci_read_config32(ctrl->f2, 0x40 + (index << 2)); + + if (!(value & 1)) { + continue; + } + + + if (value <= csbase) { + continue; + } + + + if (tom & (1 << (index + 24))) { + continue; + } + + csbase = value; + canidate = index; + } + + if (csbase == 0) { + break; + } + + size = csbase >> 21; + + tom |= (1 << (canidate + 24)); + + csbase = (tom << 21) | 1; + + tom += size; + + csmask = ((size -1) << 21); + csmask |= 0xfe00; + + pci_write_config32(ctrl->f2, 0x40 + (canidate << 2), csbase); + + pci_write_config32(ctrl->f2, 0x60 + (canidate << 2), csmask); + + } + + return (tom & ~0xff000000) << 15; +} +static void order_dimms(const struct mem_controller *ctrl) +{ + unsigned long tom, tom_k, base_k; + unsigned node_id; + tom_k = interleave_chip_selects(ctrl); + if (!tom_k) { + tom_k = order_chip_selects(ctrl); + } + + base_k = 0; + for(node_id = 0; node_id < ctrl->node_id; node_id++) { + uint32_t limit, base; + unsigned index; + index = node_id << 3; + base = pci_read_config32(ctrl->f1, 0x40 + index); + + if ((base & 3) == 3) { + limit = pci_read_config32(ctrl->f1, 0x44 + index); + base_k = ((limit + 0x00010000) & 0xffff0000) >> 2; + } + } + tom_k += base_k; + route_dram_accesses(ctrl, base_k, tom_k); + set_top_mem(tom_k); +} +static void disable_dimm(const struct mem_controller *ctrl, unsigned index) +{ + print_debug("disabling dimm"); + print_debug_hex8(index); + print_debug("\r\n"); + pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+0)<<2), 0); + pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+1)<<2), 0); +} +static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl) +{ + int i; + int registered; + int unbuffered; + uint32_t dcl; + unbuffered = 0; + registered = 0; + for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { + int value; + value = spd_read_byte(ctrl->channel0[i], 21); + if (value < 0) { + disable_dimm(ctrl, i); + continue; + } + + if (value & (1 << 1)) { + registered = 1; + } + + else { + unbuffered = 1; + } + } + if (unbuffered && registered) { + die("Mixed buffered and registered dimms not supported"); + } + if (unbuffered && is_opteron(ctrl)) { + die("Unbuffered Dimms not supported on Opteron"); + } + dcl = pci_read_config32(ctrl->f2, 0x90 ); + dcl &= ~(1<<18) ; + if (unbuffered) { + dcl |= (1<<18) ; + } + pci_write_config32(ctrl->f2, 0x90 , dcl); +} +static void spd_enable_2channels(const struct mem_controller *ctrl) +{ + int i; + uint32_t nbcap; + + + static const unsigned addresses[] = { + 2, + 3, + 4, + 5, + 6, + 7, + 9, + 11, + 13, + 17, + 18, + 21, + 23, + 26, + 27, + 28, + 29, + 30, + 41, + 42, + }; + nbcap = pci_read_config32(ctrl->f3, 0xE8 ); + if (!(nbcap & 0x0001 )) { + return; + } + for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { + unsigned device0, device1; + int value0, value1; + int j; + device0 = ctrl->channel0[i]; + device1 = ctrl->channel1[i]; + if (!device1) + return; + for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) { + unsigned addr; + addr = addresses[j]; + value0 = spd_read_byte(device0, addr); + if (value0 < 0) { + break; + } + value1 = spd_read_byte(device1, addr); + if (value1 < 0) { + return; + } + if (value0 != value1) { + return; + } + } + } + print_debug("Enabling dual channel memory\r\n"); + uint32_t dcl; + dcl = pci_read_config32(ctrl->f2, 0x90 ); + dcl &= ~(1<<19) ; + dcl |= (1<<16) ; + pci_write_config32(ctrl->f2, 0x90 , dcl); +} +struct mem_param { + uint8_t cycle_time; + uint8_t divisor; + uint8_t tRC; + uint8_t tRFC; + uint32_t dch_memclk; + uint16_t dch_tref4k, dch_tref8k; + uint8_t dtl_twr; + char name[9]; +}; +static const struct mem_param *get_mem_param(unsigned min_cycle_time) +{ + static const struct mem_param speed[] = { + { + .name = "100Mhz\r\n", + .cycle_time = 0xa0, + .divisor = (10 <<1), + .tRC = 0x46, + .tRFC = 0x50, + .dch_memclk = 0 << 20 , + .dch_tref4k = 0x00 , + .dch_tref8k = 0x08 , + .dtl_twr = 2, + }, + { + .name = "133Mhz\r\n", + .cycle_time = 0x75, + .divisor = (7<<1)+1, + .tRC = 0x41, + .tRFC = 0x4B, + .dch_memclk = 2 << 20 , + .dch_tref4k = 0x01 , + .dch_tref8k = 0x09 , + .dtl_twr = 2, + }, + { + .name = "166Mhz\r\n", + .cycle_time = 0x60, + .divisor = (6<<1), + .tRC = 0x3C, + .tRFC = 0x48, + .dch_memclk = 5 << 20 , + .dch_tref4k = 0x02 , + .dch_tref8k = 0x0A , + .dtl_twr = 3, + }, + { + .name = "200Mhz\r\n", + .cycle_time = 0x50, + .divisor = (5<<1), + .tRC = 0x37, + .tRFC = 0x46, + .dch_memclk = 7 << 20 , + .dch_tref4k = 0x03 , + .dch_tref8k = 0x0B , + .dtl_twr = 3, + }, + { + .cycle_time = 0x00, + }, + }; + const struct mem_param *param; + for(param = &speed[0]; param->cycle_time ; param++) { + if (min_cycle_time > (param+1)->cycle_time) { + break; + } + } + if (!param->cycle_time) { + die("min_cycle_time to low"); + } + print_debug(param->name); + return param; +} +static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl) +{ + + const struct mem_param *param; + unsigned min_cycle_time, min_latency; + int i; + uint32_t value; + static const int latency_indicies[] = { 26, 23, 9 }; + static const unsigned char min_cycle_times[] = { + [0 ] = 0x50, + [1 ] = 0x60, + [2 ] = 0x75, + [3 ] = 0xa0, + }; + value = pci_read_config32(ctrl->f3, 0xE8 ); + min_cycle_time = min_cycle_times[(value >> 5 ) & 3 ]; + min_latency = 2; + + for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { + int new_cycle_time, new_latency; + int index; + int latencies; + int latency; + + new_cycle_time = 0xa0; + new_latency = 5; + latencies = spd_read_byte(ctrl->channel0[i], 18); + if (latencies <= 0) continue; + + latency = log2(latencies) -2; + + for(index = 0; index < 3; index++, latency++) { + int value; + if ((latency < 2) || (latency > 4) || + (!(latencies & (1 << latency)))) { + continue; + } + value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]); + if (value < 0) { + continue; + } + + if ((value >= min_cycle_time) && (value < new_cycle_time)) { + new_cycle_time = value; + new_latency = latency; + } + } + if (new_latency > 4){ + continue; + } + + if (new_cycle_time > min_cycle_time) { + min_cycle_time = new_cycle_time; + } + + if (new_latency > min_latency) { + min_latency = new_latency; + } + } + + + for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { + int latencies; + int latency; + int index; + int value; + int dimm; + latencies = spd_read_byte(ctrl->channel0[i], 18); + if (latencies <= 0) { + goto dimm_err; + } + + latency = log2(latencies) -2; + + for(index = 0; index < 3; index++, latency++) { + if (!(latencies & (1 << latency))) { + continue; + } + if (latency == min_latency) + break; + } + + if ((latency != min_latency) || (index >= 3)) { + goto dimm_err; + } + + + value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]); + + + if (value <= min_cycle_time) { + continue; + } + + dimm_err: + disable_dimm(ctrl, i); + } + + param = get_mem_param(min_cycle_time); + + value = pci_read_config32(ctrl->f2, 0x94 ); + value &= ~(0x7 << 20 ); + value |= param->dch_memclk; + pci_write_config32(ctrl->f2, 0x94 , value); + static const unsigned latencies[] = { 1 , 5 , 2 }; + + value = pci_read_config32(ctrl->f2, 0x88 ); + value &= ~(0x7 << 0 ); + value |= latencies[min_latency - 2] << 0 ; + pci_write_config32(ctrl->f2, 0x88 , value); + + return param; +} +static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_param *param, int i) +{ + unsigned clocks, old_clocks; + uint32_t dtl; + int value; + value = spd_read_byte(ctrl->channel0[i], 41); + if (value < 0) return -1; + if ((value == 0) || (value == 0xff)) { + value = param->tRC; + } + clocks = ((value << 1) + param->divisor - 1)/param->divisor; + if (clocks < 7 ) { + clocks = 7 ; + } + if (clocks > 22 ) { + return -1; + } + dtl = pci_read_config32(ctrl->f2, 0x88 ); + old_clocks = ((dtl >> 4 ) & 0xf ) + 7 ; + if (old_clocks > clocks) { + clocks = old_clocks; + } + dtl &= ~(0xf << 4 ); + dtl |= ((clocks - 7 ) << 4 ); + pci_write_config32(ctrl->f2, 0x88 , dtl); + return 0; +} +static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i) +{ + unsigned clocks, old_clocks; + uint32_t dtl; + int value; + value = spd_read_byte(ctrl->channel0[i], 42); + if (value < 0) return -1; + if ((value == 0) || (value == 0xff)) { + value = param->tRFC; + } + clocks = ((value << 1) + param->divisor - 1)/param->divisor; + if (clocks < 9 ) { + clocks = 9 ; + } + if (clocks > 24 ) { + return -1; + } + dtl = pci_read_config32(ctrl->f2, 0x88 ); + old_clocks = ((dtl >> 8 ) & 0xf ) + 9 ; + if (old_clocks > clocks) { + clocks = old_clocks; + } + dtl &= ~(0xf << 8 ); + dtl |= ((clocks - 9 ) << 8 ); + pci_write_config32(ctrl->f2, 0x88 , dtl); + return 0; +} +static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_param *param, int i) +{ + unsigned clocks, old_clocks; + uint32_t dtl; + int value; + value = spd_read_byte(ctrl->channel0[i], 29); + if (value < 0) return -1; + clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1); + if (clocks < 2 ) { + clocks = 2 ; + } + if (clocks > 6 ) { + return -1; + } + dtl = pci_read_config32(ctrl->f2, 0x88 ); + old_clocks = ((dtl >> 12 ) & 0x7 ) + 0 ; + if (old_clocks > clocks) { + clocks = old_clocks; + } + dtl &= ~(0x7 << 12 ); + dtl |= ((clocks - 0 ) << 12 ); + pci_write_config32(ctrl->f2, 0x88 , dtl); + return 0; +} +static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i) +{ + unsigned clocks, old_clocks; + uint32_t dtl; + int value; + value = spd_read_byte(ctrl->channel0[i], 28); + if (value < 0) return -1; + clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1); + if (clocks < 2 ) { + clocks = 2 ; + } + if (clocks > 4 ) { + return -1; + } + dtl = pci_read_config32(ctrl->f2, 0x88 ); + old_clocks = ((dtl >> 16 ) & 0x7 ) + 0 ; + if (old_clocks > clocks) { + clocks = old_clocks; + } + dtl &= ~(0x7 << 16 ); + dtl |= ((clocks - 0 ) << 16 ); + pci_write_config32(ctrl->f2, 0x88 , dtl); + return 0; +} +static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i) +{ + unsigned clocks, old_clocks; + uint32_t dtl; + int value; + value = spd_read_byte(ctrl->channel0[i], 30); + if (value < 0) return -1; + clocks = ((value << 1) + param->divisor - 1)/param->divisor; + if (clocks < 5 ) { + clocks = 5 ; + } + if (clocks > 15 ) { + return -1; + } + dtl = pci_read_config32(ctrl->f2, 0x88 ); + old_clocks = ((dtl >> 20 ) & 0xf ) + 0 ; + if (old_clocks > clocks) { + clocks = old_clocks; + } + dtl &= ~(0xf << 20 ); + dtl |= ((clocks - 0 ) << 20 ); + pci_write_config32(ctrl->f2, 0x88 , dtl); + return 0; +} +static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i) +{ + unsigned clocks, old_clocks; + uint32_t dtl; + int value; + value = spd_read_byte(ctrl->channel0[i], 27); + if (value < 0) return -1; + clocks = (value + ((param->divisor & 0xff) << 1) - 1)/((param->divisor & 0xff) << 1); + if (clocks < 2 ) { + clocks = 2 ; + } + if (clocks > 6 ) { + return -1; + } + dtl = pci_read_config32(ctrl->f2, 0x88 ); + old_clocks = ((dtl >> 24 ) & 0x7 ) + 0 ; + if (old_clocks > clocks) { + clocks = old_clocks; + } + dtl &= ~(0x7 << 24 ); + dtl |= ((clocks - 0 ) << 24 ); + pci_write_config32(ctrl->f2, 0x88 , dtl); + return 0; +} +static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param) +{ + uint32_t dtl; + dtl = pci_read_config32(ctrl->f2, 0x88 ); + dtl &= ~(0x1 << 28 ); + dtl |= (param->dtl_twr - 2 ) << 28 ; + pci_write_config32(ctrl->f2, 0x88 , dtl); +} +static void init_Tref(const struct mem_controller *ctrl, const struct mem_param *param) +{ + uint32_t dth; + dth = pci_read_config32(ctrl->f2, 0x8c ); + dth &= ~(0x1f << 8 ); + dth |= (param->dch_tref4k << 8 ); + pci_write_config32(ctrl->f2, 0x8c , dth); +} +static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_param *param, int i) +{ + uint32_t dth; + int value; + unsigned tref, old_tref; + value = spd_read_byte(ctrl->channel0[i], 3); + if (value < 0) return -1; + value &= 0xf; + tref = param->dch_tref8k; + if (value == 12) { + tref = param->dch_tref4k; + } + dth = pci_read_config32(ctrl->f2, 0x8c ); + old_tref = (dth >> 8 ) & 0x1f ; + if ((value == 12) && (old_tref == param->dch_tref4k)) { + tref = param->dch_tref4k; + } else { + tref = param->dch_tref8k; + } + dth &= ~(0x1f << 8 ); + dth |= (tref << 8 ); + pci_write_config32(ctrl->f2, 0x8c , dth); + return 0; +} +static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_param *param, int i) +{ + uint32_t dcl; + int value; + int dimm; + value = spd_read_byte(ctrl->channel0[i], 13); + if (value < 0) { + return -1; + } + dimm = i; + dimm += 20 ; + dcl = pci_read_config32(ctrl->f2, 0x90 ); + dcl &= ~(1 << dimm); + if (value == 4) { + dcl |= (1 << dimm); + } + pci_write_config32(ctrl->f2, 0x90 , dcl); + return 0; +} +static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i) +{ + uint32_t dcl; + int value; + value = spd_read_byte(ctrl->channel0[i], 11); + if (value < 0) { + return -1; + } + if (value != 2) { + dcl = pci_read_config32(ctrl->f2, 0x90 ); + dcl &= ~(1<<17) ; + pci_write_config32(ctrl->f2, 0x90 , dcl); + } + return 0; +} +static int count_dimms(const struct mem_controller *ctrl) +{ + int dimms; + unsigned index; + dimms = 0; + for(index = 0; index < 8; index += 2) { + uint32_t csbase; + csbase = pci_read_config32(ctrl->f2, (0x40 + index << 2)); + if (csbase & 1) { + dimms += 1; + } + } + return dimms; +} +static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param) +{ + uint32_t dth; + unsigned clocks; + clocks = 1; + dth = pci_read_config32(ctrl->f2, 0x8c ); + dth &= ~(0x1 << 0 ); + dth |= ((clocks - 1 ) << 0 ); + pci_write_config32(ctrl->f2, 0x8c , dth); +} +static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param) +{ + uint32_t dth, dtl; + unsigned divisor; + unsigned latency; + unsigned clocks; + clocks = 0; + dtl = pci_read_config32(ctrl->f2, 0x88 ); + latency = (dtl >> 0 ) & 0x7 ; + divisor = param->divisor; + if (is_opteron(ctrl)) { + if (latency == 1 ) { + if (divisor == ((6 << 0) + 0)) { + + clocks = 3; + } + else if (divisor > ((6 << 0)+0)) { + + clocks = 2; + } + } + else if (latency == 5 ) { + clocks = 3; + } + else if (latency == 2 ) { + if (divisor == ((6 << 0)+0)) { + + clocks = 4; + } + else if (divisor > ((6 << 0)+0)) { + + clocks = 3; + } + } + } + else { + if (is_registered(ctrl)) { + if (latency == 1 ) { + clocks = 2; + } + else if (latency == 5 ) { + clocks = 3; + } + else if (latency == 2 ) { + clocks = 3; + } + } + else { + if (latency == 1 ) { + clocks = 3; + } + else if (latency == 5 ) { + clocks = 4; + } + else if (latency == 2 ) { + clocks = 4; + } + } + } + if ((clocks < 1 ) || (clocks > 6 )) { + die("Unknown Trwt"); + } + + dth = pci_read_config32(ctrl->f2, 0x8c ); + dth &= ~(0x7 << 4 ); + dth |= ((clocks - 1 ) << 4 ); + pci_write_config32(ctrl->f2, 0x8c , dth); + return; +} +static void set_Twcl(const struct mem_controller *ctrl, const struct mem_param *param) +{ + + uint32_t dth; + unsigned clocks; + if (is_registered(ctrl)) { + clocks = 2; + } else { + clocks = 1; + } + dth = pci_read_config32(ctrl->f2, 0x8c ); + dth &= ~(0x7 << 20 ); + dth |= ((clocks - 1 ) << 20 ); + pci_write_config32(ctrl->f2, 0x8c , dth); +} +static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param) +{ + uint32_t dch; + unsigned divisor; + unsigned rdpreamble; + divisor = param->divisor; + dch = pci_read_config32(ctrl->f2, 0x94 ); + dch &= ~(0xf << 8 ); + rdpreamble = 0; + if (is_registered(ctrl)) { + if (divisor == ((10 << 1)+0)) { + + rdpreamble = ((9 << 1)+ 0); + } + else if (divisor == ((7 << 1)+1)) { + + rdpreamble = ((8 << 1)+0); + } + else if (divisor == ((6 << 1)+0)) { + + rdpreamble = ((7 << 1)+1); + } + else if (divisor == ((5 << 1)+0)) { + + rdpreamble = ((7 << 1)+0); + } + } + else { + int slots; + int i; + slots = 0; + for(i = 0; i < 4; i++) { + if (ctrl->channel0[i]) { + slots += 1; + } + } + if (divisor == ((10 << 1)+0)) { + + if (slots <= 2) { + + rdpreamble = ((9 << 1)+0); + } else { + + rdpreamble = ((14 << 1)+0); + } + } + else if (divisor == ((7 << 1)+1)) { + + if (slots <= 2) { + + rdpreamble = ((7 << 1)+0); + } else { + + rdpreamble = ((11 << 1)+0); + } + } + else if (divisor == ((6 << 1)+0)) { + + if (slots <= 2) { + + rdpreamble = ((7 << 1)+0); + } else { + + rdpreamble = ((9 << 1)+0); + } + } + else if (divisor == ((5 << 1)+0)) { + + if (slots <= 2) { + + rdpreamble = ((5 << 1)+0); + } else { + + rdpreamble = ((7 << 1)+0); + } + } + } + if ((rdpreamble < ((2<<1)+0) ) || (rdpreamble > ((9<<1)+1) )) { + die("Unknown rdpreamble"); + } + dch |= (rdpreamble - ((2<<1)+0) ) << 8 ; + pci_write_config32(ctrl->f2, 0x94 , dch); +} +static void set_max_async_latency(const struct mem_controller *ctrl, const struct mem_param *param) +{ + uint32_t dch; + int i; + unsigned async_lat; + int dimms; + dimms = count_dimms(ctrl); + dch = pci_read_config32(ctrl->f2, 0x94 ); + dch &= ~(0xf << 0 ); + async_lat = 0; + if (is_registered(ctrl)) { + if (dimms == 4) { + + async_lat = 9; + } + else { + + async_lat = 8; + } + } + else { + if (dimms > 3) { + die("Too many unbuffered dimms"); + } + else if (dimms == 3) { + + async_lat = 7; + } + else { + + async_lat = 6; + } + } + dch |= ((async_lat - 0 ) << 0 ); + pci_write_config32(ctrl->f2, 0x94 , dch); +} +static void set_idle_cycle_limit(const struct mem_controller *ctrl, const struct mem_param *param) +{ + uint32_t dch; + + dch = pci_read_config32(ctrl->f2, 0x94 ); + dch &= ~(0x7 << 16 ); + dch |= 3 << 16 ; + dch |= (1 << 19) ; + pci_write_config32(ctrl->f2, 0x94 , dch); +} +static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param) +{ + int dimms; + int i; + int rc; + + init_Tref(ctrl, param); + for(i = 0; (i < 4) && ctrl->channel0[i]; i++) { + int rc; + + if (update_dimm_Trc (ctrl, param, i) < 0) goto dimm_err; + if (update_dimm_Trfc(ctrl, param, i) < 0) goto dimm_err; + if (update_dimm_Trcd(ctrl, param, i) < 0) goto dimm_err; + if (update_dimm_Trrd(ctrl, param, i) < 0) goto dimm_err; + if (update_dimm_Tras(ctrl, param, i) < 0) goto dimm_err; + if (update_dimm_Trp (ctrl, param, i) < 0) goto dimm_err; + + if (update_dimm_Tref(ctrl, param, i) < 0) goto dimm_err; + + if (update_dimm_x4 (ctrl, param, i) < 0) goto dimm_err; + if (update_dimm_ecc(ctrl, param, i) < 0) goto dimm_err; + continue; + dimm_err: + disable_dimm(ctrl, i); + + } + + set_Twr(ctrl, param); + + set_Twtr(ctrl, param); + set_Trwt(ctrl, param); + set_Twcl(ctrl, param); + + set_read_preamble(ctrl, param); + set_max_async_latency(ctrl, param); + set_idle_cycle_limit(ctrl, param); +} +static void sdram_set_spd_registers(const struct mem_controller *ctrl) +{ + const struct mem_param *param; + spd_enable_2channels(ctrl); + spd_set_ram_size(ctrl); + spd_handle_unbuffered_dimms(ctrl); + param = spd_set_memclk(ctrl); + spd_set_dram_timing(ctrl, param); + order_dimms(ctrl); +} +static void sdram_enable(int controllers, const struct mem_controller *ctrl) +{ + int i; + + for(i = 0; i < controllers; i++) { + uint32_t dch; + dch = pci_read_config32(ctrl[i].f2, 0x94 ); + dch |= (1 << 25) ; + pci_write_config32(ctrl[i].f2, 0x94 , dch); + } + + memreset(controllers, ctrl); + for(i = 0; i < controllers; i++) { + uint32_t dcl; + + dcl = pci_read_config32(ctrl[i].f2, 0x90 ); + if (dcl & (1<<17) ) { + uint32_t mnc; + print_debug("ECC enabled\r\n"); + mnc = pci_read_config32(ctrl[i].f3, 0x44 ); + mnc |= (1 << 22) ; + if (dcl & (1<<16) ) { + mnc |= (1 << 23) ; + } + pci_write_config32(ctrl[i].f3, 0x44 , mnc); + } + dcl |= (1<<3) ; + pci_write_config32(ctrl[i].f2, 0x90 , dcl); + dcl &= ~(1<<3) ; + dcl &= ~(1<<0) ; + dcl &= ~(1<<1) ; + dcl &= ~(1<<2) ; + dcl |= (1<<8) ; + pci_write_config32(ctrl[i].f2, 0x90 , dcl); + } + for(i = 0; i < controllers; i++) { + uint32_t dcl; + print_debug("Initializing memory: "); + int loops = 0; + do { + dcl = pci_read_config32(ctrl[i].f2, 0x90 ); + loops += 1; + if ((loops & 1023) == 0) { + print_debug("."); + } + } while(((dcl & (1<<8) ) != 0) && (loops < 300000 )); + if (loops >= 300000 ) { + print_debug(" failed\r\n"); + } else { + print_debug(" done\r\n"); + } + if (dcl & (1<<17) ) { + print_debug("Clearing memory: "); + if (!is_cpu_pre_c0()) { + + dcl &= ~((1<<11) | (1<<10) ); + pci_write_config32(ctrl[i].f2, 0x90 , dcl); + do { + dcl = pci_read_config32(ctrl[i].f2, 0x90 ); + } while(((dcl & (1<<11) ) == 0) || ((dcl & (1<<10) ) == 0) ); + } + uint32_t base, last_scrub_k, scrub_k; + uint32_t cnt,zstart,zend; + msr_t msr,msr_201; + + pci_write_config32(ctrl[i].f3, 0x58 , + (0 << 16) | (0 << 8) | (0 << 0)); + + msr_201 = rdmsr(0x201); + zstart = pci_read_config32(ctrl[0].f1, 0x40 + (i*8)); + zend = pci_read_config32(ctrl[0].f1, 0x44 + (i*8)); + zstart >>= 16; + zend >>=16; + print_debug("addr "); + print_debug_hex32(zstart); + print_debug("-"); + print_debug_hex32(zend); + print_debug("\r\n"); + + + msr = rdmsr(0x2ff ); + msr.lo &= ~(1<<10); + wrmsr(0x2ff , msr); + + msr = rdmsr(0xc0010015); + msr.lo |= (1<<17); + wrmsr(0xc0010015,msr); + for(;zstart<zend;zstart+=4) { + + if(zstart == 0x0fc) + continue; + + + __asm__ volatile( + "movl %%cr0, %0\n\t" + "orl $0x40000000, %0\n\t" + "movl %0, %%cr0\n\t" + :"=r" (cnt) + ); + + + msr.lo = 1 + ((zstart&0x0ff)<<24); + msr.hi = (zstart&0x0ff00)>>8; + wrmsr(0x200,msr); + + msr.hi = 0x000000ff; + msr.lo = 0xfc000800; + wrmsr(0x201,msr); + + __asm__ volatile( + "movl %%cr0, %0\n\t" + "andl $0x9fffffff, %0\n\t" + "movl %0, %%cr0\n\t" + :"=r" (cnt) + ); + + msr.lo = (zstart&0xff) << 24; + msr.hi = (zstart&0xff00) >> 8; + wrmsr(0xc0000100,msr); + print_debug_char((zstart > 0x0ff)?'+':'-'); + + + __asm__ volatile( + "1: \n\t" + "movl %0, %%fs:(%1)\n\t" + "addl $4,%1\n\t" + "subl $1,%2\n\t" + "jnz 1b\n\t" + : + : "a" (0), "D" (0), "c" (0x01000000) + ); + } + + + __asm__ volatile( + "movl %%cr0, %0\n\t" + "orl $0x40000000, %0\n\t" + "movl %0, %%cr0\n\t" + :"=r" (cnt) + ); + + + msr = rdmsr(0x2ff ); + msr.lo |= 0x0400; + wrmsr(0x2ff , msr); + + msr.lo = 6; + msr.hi = 0; + wrmsr(0x200,msr); + wrmsr(0x201,msr_201); + + msr.lo = 0; + msr.hi = 0; + wrmsr(0xc0000100,msr); + + __asm__ volatile( + "movl %%cr0, %0\n\t" + "andl $0x9fffffff, %0\n\t" + "movl %0, %%cr0\n\t" + :"=r" (cnt) + ); + + + msr = rdmsr(0xc0010015); + msr.lo &= ~(1<<17); + wrmsr(0xc0010015,msr); + + base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3)); + base &= 0xffff0000; + + pci_write_config32(ctrl[i].f3, 0x5C , base << 8); + pci_write_config32(ctrl[i].f3, 0x60 , base >> 24); + + pci_write_config32(ctrl[i].f3, 0x58 , + (22 << 16) | (22 << 8) | (22 << 0)); + print_debug("done\r\n"); + } + } +} + + + + + +typedef uint8_t u8; +typedef uint32_t u32; +typedef int8_t bool; +static void disable_probes(void) +{ + + + u32 val; + print_debug("Disabling read/write/fill probes for UP... "); + val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x68); + val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0); + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x68, val); + print_debug("done.\r\n"); +} + +static void wait_ap_stop(u8 node) +{ + unsigned long reg; + unsigned long i; + for(i=0;i< 1000 ;i++) { + unsigned long regx; + regx = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x6c); + if((regx & (1<<4))==1) break; + } + reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x6c); + reg &= ~(1<<4); + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c, reg); +} +static void notify_bsp_ap_is_stopped(void) +{ + unsigned long reg; + unsigned long apic_id; + apic_id = *((volatile unsigned long *)(0xfee00000 + 0x020 )); + apic_id >>= 24; + + if(apic_id != 0) { + + reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6C); + reg |= 1<<4; + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6C, reg); + } + +} + +static void enable_routing(u8 node) +{ + u32 val; + + + print_debug("Enabling routing table for node "); + print_debug_hex32(node); + val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c); + val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)); + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c, val); + + if(node!=0) { + wait_ap_stop(node); + } + + print_debug(" done.\r\n"); +} +static void rename_temp_node(u8 node) +{ + uint32_t val; + print_debug("Renaming current temp node to "); + print_debug_hex32(node); + val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60); + val &= (~7); + val |= node; + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60, val); + print_debug(" done.\r\n"); +} +static bool check_connection(u8 src, u8 dest, u8 link) +{ + + u32 val; + + + val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ src ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x98+link); + if ( (val&0x17) != 0x03) + return 0; + + val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ dest ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0); + if(val != 0x11001022) + return 0; + return 1; +} +static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2) +{ + static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 }; + static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 }; + uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask; + uint8_t width_cap1, width_cap2, width_cap, width, ln_width1, ln_width2; + uint8_t freq; + + + freq_cap1 = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 0x0a ); + freq_cap2 = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 0x0a ); + + + freq = log2(freq_cap1 & freq_cap2 & 0xff); + + pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 0x09 , freq); + pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 0x09 , freq); + + width_cap1 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 6 ); + width_cap2 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 6 ); + + ln_width1 = link_width_to_pow2[width_cap1 & 7]; + ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7]; + if (ln_width1 > ln_width2) { + ln_width1 = ln_width2; + } + width = pow2_to_link_width[ln_width1]; + + ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7]; + ln_width2 = link_width_to_pow2[width_cap2 & 7]; + if (ln_width1 > ln_width2) { + ln_width1 = ln_width2; + } + width |= pow2_to_link_width[ln_width1] << 4; + + + pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 6 + 1, width); + + width = ((width & 0x70) >> 4) | ((width & 0x7) << 4); + pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 6 + 1, width); +} +static void fill_row(u8 node, u8 row, u32 value) +{ + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x40+(row<<2), value); +} +static void setup_row(u8 source, u8 dest, u8 cpus) +{ + fill_row(source,dest,generate_row(source,dest,cpus)); +} +static void setup_temp_row(u8 source, u8 dest, u8 cpus) +{ + fill_row(source,7,((generate_row( source,dest,cpus )&(~0x0f0000))|0x010000) ); +} +static void setup_node(u8 node, u8 cpus) +{ + u8 row; + for(row=0; row<cpus; row++) + setup_row(node, row, cpus); +} +static void setup_remote_row(u8 source, u8 dest, u8 cpus) +{ + fill_row(7, dest, generate_row(source, dest, cpus)); +} +static void setup_remote_node(u8 node, u8 cpus) +{ + static const uint8_t pci_reg[] = { + 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c, + 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78, + 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc, + 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, + 0xc4, 0xcc, 0xd4, 0xdc, + 0xc0, 0xc8, 0xd0, 0xd8, + 0xe0, 0xe4, 0xe8, 0xec, + }; + uint8_t row; + int i; + print_debug("setup_remote_node\r\n"); + for(row=0; row<cpus; row++) + setup_remote_row(node, row, cpus); + + for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) { + uint32_t value; + uint8_t reg; + reg = pci_reg[i]; + value = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) , reg); + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) , reg, value); + } + print_debug("setup_remote_done\r\n"); +} +static u8 setup_uniprocessor(void) +{ + print_debug("Enabling UP settings\r\n"); + disable_probes(); + return 1; +} +static u8 setup_smp(void) +{ + u8 cpus=2; + print_debug("Enabling SMP settings\r\n"); + setup_row(0,0,cpus); + + setup_temp_row(0,1,cpus); + + if (!check_connection(0, 7, 0x20 )) { + print_debug("No connection to Node 1.\r\n"); + fill_row( 0 ,7,0x00010101 ) ; + setup_uniprocessor(); + return 1; + } + + optimize_connection(0, 0x20 , 7, 0x20 ); + setup_node(0, cpus); + setup_remote_node(1, cpus); + rename_temp_node(1); + enable_routing(1); + + fill_row( 0 ,7,0x00010101 ) ; + + print_debug_hex32(cpus); + print_debug(" nodes initialized.\r\n"); + return cpus; +} +static unsigned detect_mp_capabilities(unsigned cpus) +{ + unsigned node, row, mask; + bool mp_cap= (-1) ; + print_debug("detect_mp_capabilities: "); + print_debug_hex32(cpus); + print_debug("\r\n"); + if (cpus>2) + mask=0x06; + else + mask=0x02; + for (node=0; node<cpus; node++) { + if ((pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) , 0xe8) & mask)!=mask) + mp_cap= (0) ; + } + if (mp_cap) + return cpus; + + print_debug("One of the CPUs is not MP capable. Going back to UP\r\n"); + for (node=cpus; node>0; node--) + for (row=cpus; row>0; row--) + fill_row(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node-1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , row-1, 0x00010101 ); + + return setup_uniprocessor(); +} +static void coherent_ht_finalize(unsigned cpus) +{ + int node; + bool rev_a0; + + + print_debug("coherent_ht_finalize\r\n"); + rev_a0= is_cpu_rev_a0(); + for (node=0; node<cpus; node++) { + u32 val; + val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60); + val &= (~0x000F0070); + val |= ((cpus-1)<<16)|((cpus-1)<<4); + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x60,val); + val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x68); + val |= 0x00008000; + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x68,val); + if (rev_a0) { + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x94,0); + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0xb4,0); + pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0xd4,0); + } + } + print_debug("done\r\n"); +} +static int setup_coherent_ht_domain(void) +{ + unsigned cpus; + int reset_needed = 0; + enable_routing(0) ; + cpus=setup_smp(); + cpus=detect_mp_capabilities(cpus); + coherent_ht_finalize(cpus); + + coherent_ht_mainboard(cpus); + return reset_needed; +} +void sdram_no_memory(void) +{ + print_err("No memory!!\r\n"); + while(1) { + hlt(); + } +} + +void sdram_initialize(int controllers, const struct mem_controller *ctrl) +{ + int i; + + for(i = 0; i < controllers; i++) { + print_debug("Ram1."); + print_debug_hex8(i); + print_debug("\r\n"); + sdram_set_registers(ctrl + i); + } + + for(i = 0; i < controllers; i++) { + print_debug("Ram2."); + print_debug_hex8(i); + print_debug("\r\n"); + sdram_set_spd_registers(ctrl + i); + } + + print_debug("Ram3\r\n"); + sdram_enable(controllers, ctrl); + print_debug("Ram4\r\n"); +} +static void enable_lapic(void) +{ + msr_t msr; + msr = rdmsr(0x1b); + msr.hi &= 0xffffff00; + msr.lo &= 0x000007ff; + msr.lo |= 0xfee00000 | (1 << 11); + wrmsr(0x1b, msr); +} +static void stop_this_cpu(void) +{ + unsigned apicid; + apicid = apic_read(0x020 ) >> 24; + + apic_write(0x310 , (( apicid )<<24) ); + apic_write(0x300 , 0x08000 | 0x04000 | 0x00500 ); + + apic_wait_icr_idle(); + + apic_write(0x310 , (( apicid )<<24) ); + apic_write(0x300 , 0x08000 | 0x00500 ); + + apic_wait_icr_idle(); + + for(;;) { + hlt(); + } +} +static void pc87360_enable_serial(void) +{ + pnp_set_logical_device(0x2e , 0x03 ); + pnp_set_enable(0x2e , 1); + pnp_set_iobase0(0x2e , 0x3f8); +} +static void main(void) +{ + + static const struct mem_controller cpu[] = { + { + .node_id = 0, + .f0 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , + .f1 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) , + .f2 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) , + .f3 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) , + .channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 }, + .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 }, + }, + { + .node_id = 1, + .f0 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , + .f1 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) , + .f2 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) , + .f3 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) , + .channel0 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 }, + .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 }, + }, + }; + if (cpu_init_detected()) { + asm("jmp __cpu_reset"); + } + enable_lapic(); + init_timer(); + if (!boot_cpu()) { + stop_this_cpu(); + } + pc87360_enable_serial(); + uart_init(); + console_init(); + setup_default_resource_map(); + setup_coherent_ht_domain(); + enumerate_ht_chain(0); + distinguish_cpu_resets(0); + + enable_smbus(); + memreset_setup(); + sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu); + +} diff --git a/util/romcc/tests/simple_test1.c b/util/romcc/tests/simple_test1.c new file mode 100644 index 0000000000..feacbfdc38 --- /dev/null +++ b/util/romcc/tests/simple_test1.c @@ -0,0 +1,252 @@ +void land_test(void) +{ + int i; + i = 1 && 2; +} +void lor_test(void) +{ + int i; + i = 1 || 2; +} + +void outb(unsigned char value, unsigned short port) +{ + __builtin_outb(value, port); +} + +unsigned char inb(unsigned short port) +{ + return __builtin_inb(port); +} + +static unsigned int config_cmd2(unsigned char bus, unsigned devfn, unsigned where) +{ + return 0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3) ; +} + +/* Base Address */ +#ifndef TTYS0_BASE +#define TTYS0_BASE 0x3f8 +#endif + +#ifndef TTYS0_BAUD +#define TTYS0_BAUD 115200 +#endif + +#if ((115200%TTYS0_BAUD) != 0) +#error Bad ttys0 baud rate +#endif + +#define TTYS0_DIV (115200/TTYS0_BAUD) + +/* Line Control Settings */ +#ifndef TTYS0_LCS +/* Set 8bit, 1 stop bit, no parity */ +#define TTYS0_LCS 0x3 +#endif + +#define UART_LCS TTYS0_LCS + +/* Data */ +#define UART_RBR 0x00 +#define UART_TBR 0x00 + +/* Control */ +#define UART_IER 0x01 +#define UART_IIR 0x02 +#define UART_FCR 0x02 +#define UART_LCR 0x03 +#define UART_MCR 0x04 +#define UART_DLL 0x00 +#define UART_DLM 0x01 + +/* Status */ +#define UART_LSR 0x05 +#define UART_MSR 0x06 +#define UART_SCR 0x07 + +int uart_can_tx_byte(void) +{ + return inb(TTYS0_BASE + UART_LSR) & 0x20; +} + +void uart_wait_to_tx_byte(void) +{ + while(!uart_can_tx_byte()) + ; +} + +void uart_wait_until_sent(void) +{ + while(!(inb(TTYS0_BASE + UART_LSR) & 0x40)) + ; +} + +void uart_tx_byte(unsigned char data) +{ + uart_wait_to_tx_byte(); + outb(data, TTYS0_BASE + UART_TBR); + /* Make certain the data clears the fifos */ + uart_wait_until_sent(); +} + +void dummy(void) +{ + uart_tx_byte(5); +} + +#define PIIX4_DEVFN 0x90 +#define SMBUS_MEM_DEVICE_START 0x50 +#define SMBUS_MEM_DEVICE_END 0x53 +#define SMBUS_MEM_DEVICE_INC 1 + + +#define PM_BUS 0 +#define PM_DEVFN (PIIX4_DEVFN+3) + +#define SMBUS_IO_BASE 0x1000 +#define SMBHSTSTAT 0 +#define SMBHSTCTL 2 +#define SMBHSTCMD 3 +#define SMBHSTADD 4 +#define SMBHSTDAT0 5 +#define SMBHSTDAT1 6 +#define SMBBLKDAT 7 + +static void smbus_wait_until_done(void) +{ + unsigned char byte; + do { + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + }while((byte &1) == 1); +#if 1 + while( (byte & ~1) == 0) { + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + } +#endif +} + +#if 0 +void ifthenelse(void) +{ + int i; + if (5 > 2) { + i = 1; + } + else { + i = 2; + } + i = i + 3; +} +#endif +#if 0 +static int add(int left, int right) +{ + { + return left + right; + } +} +#else +#if 0 +static int add(int left, int right) +{ + return left + right; +} +#endif +#endif + +#if 0 +static void assign(void) +{ + int i, j; + i = j = 1; +} +#endif + +#if 0 +static void and(void) +{ + int i, j, k; + i = 1; + j = 2; + k = i && j; + +} +static void and_test(void) +{ + and(); +} +#endif +#if 0 +#define INC_TEST 2 +static void inc(void) +{ + int i; + i = 5; +#if (INC_TEST == 1) + i += 7; +#endif +#if (INC_TEST == 2) + ++i; +#endif +#if (INC_TEST == 3) + i++; +#endif +} + +#if 0 +static void inc_test(void) +{ + inc(); +} +#endif +#endif +#if 0 +static void loop(void) +{ + int i; + for(i = 0; i < 10; i++) { + ; + } while(i < 10); +} + +static void loop_test(void) +{ + loop(); +} +#endif + +#if 0 +static void simple(void) +{ + add(1,2); +} +#endif + +#if 0 +static void fun(void) +{ + int bar; + bar = add(1, 2); +} +#endif + + +#if 0 +static void func(void) +{ + int bar, baz; + int i; + + baz = add(1, 2); + baz = add(1, 2); + bar = 1; + baz = 2; + for(i = 0; i < 10; i = i + 1) { + baz = i; + } + bar = 1 + 2 * 3; + bar = add(3, 4); + bar = add(bar, baz); +} +#endif diff --git a/util/romcc/tests/simple_test60.c b/util/romcc/tests/simple_test60.c index d277c94dd3..860bf3240d 100644 --- a/util/romcc/tests/simple_test60.c +++ b/util/romcc/tests/simple_test60.c @@ -27,6 +27,6 @@ static void test(void) const struct mem_param *param; param = ¶m0; value = 0x48; -#warning "this generates word loads instead of byte loads" +#warning "this generated word loads instead of byte loads" clocks = (value + (param->divisor << 1) - 1)/(param->divisor << 1); } diff --git a/util/romcc/tests/simple_test71.c b/util/romcc/tests/simple_test71.c index 35956c5ea8..52ffc8d42c 100644 --- a/util/romcc/tests/simple_test71.c +++ b/util/romcc/tests/simple_test71.c @@ -6,16 +6,10 @@ static void main(void) { int i; -#if 1 foo(); -#endif -#if 1 foo(); -#endif for(i = 0; i < 10; i++) { -#if 1 foo(); -#endif #if 0 foo(); #endif diff --git a/util/romcc/tests/simple_test74.c b/util/romcc/tests/simple_test74.c new file mode 100644 index 0000000000..177e00f29e --- /dev/null +++ b/util/romcc/tests/simple_test74.c @@ -0,0 +1,88 @@ +struct syscall_result { + long val; + int errno; +}; + +static struct syscall_result syscall_return(long result) +{ + struct syscall_result res; + if (((unsigned long)result) >= ((unsigned long)-125)) { + res.errno = - result; + res.val = -1; + } else { + res.errno = 0; + res.val = result; + } + return res; +} + +static struct syscall_result syscall1(unsigned long nr, unsigned long arg1) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr), "b" (arg1)); + return syscall_return(res); + +} + + +static struct syscall_result syscall3(unsigned long nr, unsigned long arg1, unsigned long arg2, + unsigned long arg3) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3)); + return syscall_return(res); + +} + +#define NR_exit 1 +#define NR_write 4 + +/* Standard file descriptors */ +#define STDIN_FILENO 0 /* Standard input */ +#define STDOUT_FILENO 1 /* Standard output */ +#define STDERR_FILENO 2 /* Standard error output */ + +typedef long ssize_t; +typedef unsigned long size_t; + +static ssize_t write(int fd, const void *buf, size_t count) +{ + struct syscall_result res; + res = syscall3(NR_write, fd, (unsigned long)buf, count); + return res.val; +} + +static void _exit(int status) +{ + struct syscall_result res; + res = syscall1(NR_exit, status); +} + +static void console_tx_string(const char *str) +{ + unsigned char ch; + while(1) { + + } + for(;1;) { + } + do { + } while(1); + if (1) { + }else { + } +} + + +static void main(void) +{ + static const char msg[] = "hello world\r\n"; + write(STDOUT_FILENO, msg, sizeof(msg)); + _exit(0); +} diff --git a/util/romcc/tests/simple_test75.c b/util/romcc/tests/simple_test75.c new file mode 100644 index 0000000000..1ad87bd2a0 --- /dev/null +++ b/util/romcc/tests/simple_test75.c @@ -0,0 +1,21 @@ +static void goto_test(void) +{ + int i; + + i = 0; + goto bottom; + { + top: + i = i + 1; + } + bottom: + if (i < 10) { + goto top; + } + ; +} + +static void main(void) +{ + goto_test(); +} diff --git a/util/romcc/tests/simple_test76.c b/util/romcc/tests/simple_test76.c new file mode 100644 index 0000000000..4f682d37d4 --- /dev/null +++ b/util/romcc/tests/simple_test76.c @@ -0,0 +1,69 @@ +struct syscall_result { + long val; + int errno; +}; + +static struct syscall_result syscall_return(long result) +{ + struct syscall_result res; + if (((unsigned long)result) >= ((unsigned long)-125)) { + res.errno = - result; + res.val = -1; + } else { + res.errno = 0; + res.val = result; + } + return res; +} +static struct syscall_result syscall1(unsigned long nr, unsigned long arg1) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr), "b" (arg1)); + return syscall_return(res); + +} + +static struct syscall_result syscall3(unsigned long nr, unsigned long arg1, unsigned long arg2, + unsigned long arg3) +{ + long res; + asm volatile( + "int $0x80" + : "=a" (res) + : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3)); + return syscall_return(res); + +} + +#define NR_exit 1 +#define NR_write 4 +/* Standard file descriptors */ +#define STDIN_FILENO 0 /* Standard input */ +#define STDOUT_FILENO 1 /* Standard output */ +#define STDERR_FILENO 2 /* Standard error output */ + +typedef long ssize_t; +typedef unsigned long size_t; + +static ssize_t write(int fd, const void *buf, size_t count) +{ + struct syscall_result res; + res = syscall3(NR_write, fd, (unsigned long)buf, count); + return res.val; +} + +static void _exit(int status) +{ + struct syscall_result res; + res = syscall1(NR_exit, status); +} + +static void main(void) +{ + static const char msg[] = "hello world\r\n"; + write(STDOUT_FILENO, msg, sizeof(msg)); + _exit(0); +} diff --git a/util/romcc/tests/simple_test77.c b/util/romcc/tests/simple_test77.c new file mode 100644 index 0000000000..74be92e39b --- /dev/null +++ b/util/romcc/tests/simple_test77.c @@ -0,0 +1,5 @@ +static void main(void) +{ + do { + } while(1); +} diff --git a/util/romcc/tests/simple_test78.c b/util/romcc/tests/simple_test78.c new file mode 100644 index 0000000000..5e6b27b4bf --- /dev/null +++ b/util/romcc/tests/simple_test78.c @@ -0,0 +1,7 @@ +static void main(void) +{ + int x = 25; + do { + } while(1); + *((volatile int *)5) = x; +} diff --git a/util/romcc/tests/simple_test79.c b/util/romcc/tests/simple_test79.c new file mode 100644 index 0000000000..2f501ca840 --- /dev/null +++ b/util/romcc/tests/simple_test79.c @@ -0,0 +1,5 @@ +static void main(void) +{ + do { + } while(0); +} diff --git a/util/romcc/tests/simple_test80.c b/util/romcc/tests/simple_test80.c new file mode 100644 index 0000000000..3a31a0a1ec --- /dev/null +++ b/util/romcc/tests/simple_test80.c @@ -0,0 +1,13 @@ +typedef __builtin_msr_t msr_t; + +static msr_t rdmsr(unsigned long index) +{ + return __builtin_rdmsr(index); +} + +static void main(void) +{ + msr_t msr; + msr = rdmsr(0x12345678); +} + diff --git a/util/romcc/tests/simple_test81.c b/util/romcc/tests/simple_test81.c new file mode 100644 index 0000000000..e942679d67 --- /dev/null +++ b/util/romcc/tests/simple_test81.c @@ -0,0 +1,8 @@ +static void main(void) +{ + int i; + i = __builtin_inb(0x1234); + int j; + j = __builtin_inb(0xabcd); + +} diff --git a/util/romcc/tests/simple_test82.c b/util/romcc/tests/simple_test82.c new file mode 100644 index 0000000000..25b08babb4 --- /dev/null +++ b/util/romcc/tests/simple_test82.c @@ -0,0 +1,17 @@ + + +struct result { + int a, b, c, d; +}; + +static struct result main(int a, int b, int c, int d) +{ + struct result result; + result.a = d; + result.b = c; + result.c = b; + result.d = a; + + return result; +} + diff --git a/util/romcc/tests/simple_test83.c b/util/romcc/tests/simple_test83.c new file mode 100644 index 0000000000..cf9f817fe2 --- /dev/null +++ b/util/romcc/tests/simple_test83.c @@ -0,0 +1,16 @@ + + +struct result { + int a, b, c, d; +}; + +static struct result main(int a, int b, int c, int d) +{ + struct result result; + result.a = d + 1; + result.b = c + 1; + result.c = b + 1; + result.d = a + 1; + + return result; +} diff --git a/util/romcc/tests/simple_test84.c b/util/romcc/tests/simple_test84.c new file mode 100644 index 0000000000..bc98bf3419 --- /dev/null +++ b/util/romcc/tests/simple_test84.c @@ -0,0 +1,28 @@ +struct stuff { + signed int a : 5; + signed int b : 6; + signed int c : 2; + unsigned int d : 3; +}; + +static void main(void) +{ + struct stuff var; + volatile int a, b, c, d; + a = 1; + b = 2; + c = 3; + d = 7; + + var.a = a; + var.b = b; + var.c = c; + var.d = d; + + a = var.a; + b = var.b; + c = var.c; + d = var.d; + + asm(" " :: "r"(a), "r"(b), "r"(c), "r"(d)); +} diff --git a/util/romcc/tests/simple_test85.c b/util/romcc/tests/simple_test85.c new file mode 100644 index 0000000000..f223e2e3a5 --- /dev/null +++ b/util/romcc/tests/simple_test85.c @@ -0,0 +1,51 @@ +struct sub4 { + unsigned a; + unsigned b; + unsigned c; + unsigned d; + unsigned e; + unsigned f; + unsigned g; +}; +struct sub3 { + unsigned a; + unsigned b; + unsigned c; + unsigned d; + unsigned e; + unsigned f; + struct sub4 s4; +}; +struct sub2 { + unsigned a; + unsigned b; + unsigned c; + unsigned d; + unsigned e; + struct sub3 s3; +}; +struct sub1 { + unsigned a; + unsigned b; + struct sub2 s2; +}; + +struct stuff { + signed int a; + signed int b; + signed int c; + unsigned int d; + struct sub1 s1; +}; + + +static void main(void) +{ + struct stuff *var; + unsigned int *foo; + + var = (struct stuff *)(0x12345678); + foo = &var->d; + foo = &((*var).d); + foo = &var->s1.s2.s3.s4.g; +} diff --git a/util/romcc/tests/simple_test86.c b/util/romcc/tests/simple_test86.c new file mode 100644 index 0000000000..d9d4c6584b --- /dev/null +++ b/util/romcc/tests/simple_test86.c @@ -0,0 +1,5 @@ +static void main(void) +{ + asm("cpuid" + ::: "eax", "ebx", "ecx", "edx"); +} |