diff options
Diffstat (limited to 'util/romcc/tests')
-rw-r--r-- | util/romcc/tests/hello_world.c | 128 | ||||
-rw-r--r-- | util/romcc/tests/raminit_test.c | 1283 | ||||
-rw-r--r-- | util/romcc/tests/raminit_test2.c | 1283 | ||||
-rw-r--r-- | util/romcc/tests/simple_test.c | 252 | ||||
-rw-r--r-- | util/romcc/tests/simple_test10.c | 31 | ||||
-rw-r--r-- | util/romcc/tests/simple_test11.c | 13 | ||||
-rw-r--r-- | util/romcc/tests/simple_test12.c | 9 | ||||
-rw-r--r-- | util/romcc/tests/simple_test13.c | 23 | ||||
-rw-r--r-- | util/romcc/tests/simple_test14.c | 288 | ||||
-rw-r--r-- | util/romcc/tests/simple_test15.c | 47 | ||||
-rw-r--r-- | util/romcc/tests/simple_test2.c | 36 | ||||
-rw-r--r-- | util/romcc/tests/simple_test3.c | 38 | ||||
-rw-r--r-- | util/romcc/tests/simple_test4.c | 509 | ||||
-rw-r--r-- | util/romcc/tests/simple_test5.c | 310 | ||||
-rw-r--r-- | util/romcc/tests/simple_test6.c | 269 | ||||
-rw-r--r-- | util/romcc/tests/simple_test7.c | 12 | ||||
-rw-r--r-- | util/romcc/tests/simple_test8.c | 12 | ||||
-rw-r--r-- | util/romcc/tests/simple_test9.c | 12 |
18 files changed, 4555 insertions, 0 deletions
diff --git a/util/romcc/tests/hello_world.c b/util/romcc/tests/hello_world.c new file mode 100644 index 0000000000..6dd80d89b8 --- /dev/null +++ b/util/romcc/tests/hello_world.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/raminit_test.c b/util/romcc/tests/raminit_test.c new file mode 100644 index 0000000000..8dd9c977e5 --- /dev/null +++ b/util/romcc/tests/raminit_test.c @@ -0,0 +1,1283 @@ +#define HAVE_STRING_SUPPORT 0 +#define HAVE_CAST_SUPPORT 0 +#define HAVE_STATIC_ARRAY_SUPPORT 0 +#define HAVE_POINTER_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_byte(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 + dummy = RAM(unsigned long, addr); +#endif +#if HAVE_STRING_SUPPORT + print_debug("Reading "); + print_debug_hex32(addr ^ 0xddf8); + print_debug("\n"); +#endif +#if HAVE_POINTER_SUPPORT + dummy = RAM(unsigned long, addr ^ 0xdff8); +#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_test2.c b/util/romcc/tests/raminit_test2.c new file mode 100644 index 0000000000..8dd9c977e5 --- /dev/null +++ b/util/romcc/tests/raminit_test2.c @@ -0,0 +1,1283 @@ +#define HAVE_STRING_SUPPORT 0 +#define HAVE_CAST_SUPPORT 0 +#define HAVE_STATIC_ARRAY_SUPPORT 0 +#define HAVE_POINTER_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_byte(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 + dummy = RAM(unsigned long, addr); +#endif +#if HAVE_STRING_SUPPORT + print_debug("Reading "); + print_debug_hex32(addr ^ 0xddf8); + print_debug("\n"); +#endif +#if HAVE_POINTER_SUPPORT + dummy = RAM(unsigned long, addr ^ 0xdff8); +#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/simple_test.c b/util/romcc/tests/simple_test.c new file mode 100644 index 0000000000..feacbfdc38 --- /dev/null +++ b/util/romcc/tests/simple_test.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_test10.c b/util/romcc/tests/simple_test10.c new file mode 100644 index 0000000000..3e7f510d67 --- /dev/null +++ b/util/romcc/tests/simple_test10.c @@ -0,0 +1,31 @@ +#define SMBUS_MEM_DEVICE_START 0x50 +#define SMBUS_MEM_DEVICE_END 0x53 +#define SMBUS_MEM_DEVICE_INC 1 + +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 char device; + + end_of_memory = 0; /* in multiples of 8MiB */ + device = SMBUS_MEM_DEVICE_START; + while (device <= SMBUS_MEM_DEVICE_END) { + unsigned side1_bits, side2_bits; + int byte, byte2; + + side1_bits = side2_bits = -1; + + /* 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); + } + device += SMBUS_MEM_DEVICE_INC; + } +} + diff --git a/util/romcc/tests/simple_test11.c b/util/romcc/tests/simple_test11.c new file mode 100644 index 0000000000..7e6b0fbef8 --- /dev/null +++ b/util/romcc/tests/simple_test11.c @@ -0,0 +1,13 @@ +static void spd_set_drb(void) +{ + unsigned char ch; + char *str; + str = "test_string"; + ch = *str; + __builtin_outb(ch, 0xab); +} + +void sdram_set_spd_registers(void) +{ + spd_set_drb(); +} diff --git a/util/romcc/tests/simple_test12.c b/util/romcc/tests/simple_test12.c new file mode 100644 index 0000000000..52c965fc96 --- /dev/null +++ b/util/romcc/tests/simple_test12.c @@ -0,0 +1,9 @@ +static void spd_set_drb(void) +{ + unsigned char ch; + char *str; + str = "test_string"; + ch = *str; + __builtin_outb(ch, 0xab); +} + diff --git a/util/romcc/tests/simple_test13.c b/util/romcc/tests/simple_test13.c new file mode 100644 index 0000000000..563ba54bc4 --- /dev/null +++ b/util/romcc/tests/simple_test13.c @@ -0,0 +1,23 @@ +static void outb(unsigned char value, unsigned short port) +{ + __builtin_outb(value, port); +} + +static void uart_init(void) +{ + + int a; + if (1 == 1) { + a = 1; + outb(a, 0x3f8); + } else { + a = 2; + outb(a, 0x3f8); + } + outb(a, 0x3f8); +} + +static void main(void) +{ + uart_init(); +} diff --git a/util/romcc/tests/simple_test14.c b/util/romcc/tests/simple_test14.c new file mode 100644 index 0000000000..cc2f67c8a4 --- /dev/null +++ b/util/romcc/tests/simple_test14.c @@ -0,0 +1,288 @@ +static void ram_set_registers(void) +{ + static const unsigned int register_values[] = { + 0x000c, 0x00000000, + 0x0010, 0x90000008, + 0x0014, 0x00000000, + 0x002c, 0x74541022, + 0x0030, 0x00000000, + 0x0034, 0x000000a0, + 0x0038, 0x00000000, + 0x0040, 0x00000001, + 0x0044, 0x00000000, + 0x0050, 0x0016000b, + 0x0058, 0x00000000, + 0x0060, 0xd02950e1, + 0x0064, 0x00000000, + 0x00a0, 0x0030c002, + 0x00a4, 0x1f000b77, + 0x00a8, 0x00000b21, + 0x00ac, 0x00000000, + 0x00b0, 0x00000100, + 0x00b4, 0x00010900, + 0x00b8, 0x00000000, + 0x00c0, 0x00600008, + 0x00c4, 0x11110020, + 0x00c8, 0x00000020, + 0x00cc, 0x00350522, + 0x00d0, 0x00350002, + 0x00d4, 0x00000000, + 0x00e0, 0x000d0808, + 0x00e4, 0x000c0808, + 0x00e8, 0x00130f0f, + 0x00ec, 0x00000000, + 0x00f0, 0x00040008, + 0x00f4, 0x00000000, + + + + + + 0x080c, 0x00012000, + 0x0810, 0x00000000, + 0x0818, 0x20010100, + 0x081c, 0x2220c1c1, + 0x0820, 0xe1f0e000, + 0x0824, 0xdff0d800, + 0x0828, 0x00000000, + 0x083c, 0x000c00ff, + 0x0840, 0x00000000, + + + + + + 0x300c, 0x00012000, + 0x3010, 0x00000000, + 0x3018, 0x20020200, + 0x301c, 0x220000f0, + 0x3020, 0xe3f0e200, + 0x3024, 0x0000fff0, + 0x3028, 0x00000000, + 0x3034, 0x000000c0, + 0x3038, 0x00000000, + 0x303c, 0x000600ff, + 0x3040, 0x00000000, + 0x3060, 0x06040000, + 0x3064, 0x00000000, + 0x30c0, 0x0086f008, + 0x30c4, 0x00000020, + 0x30c8, 0x000000d0, + 0x30cc, 0x00010022, + 0x30d0, 0x00000002, + 0x30d4, 0x00000000, + 0x30e0, 0x000d0008, + 0x30e4, 0x000e0008, + 0x30e8, 0x0016000f, + 0x30ec, 0x00000000, + 0x30f0, 0x80000008, + 0x30f4, 0x00000000, + + + + + + 0x3a0c, 0x00002000, + 0x3a10, 0x0000d401, + 0x3a14, 0x00000000, + 0x3a2c, 0x746a1022, + 0x3a30, 0x00000000, + 0x3a3c, 0x0000040c, + 0x3a40, 0x0c050002, + 0x3a44, 0x746a1022, + 0x3a48, 0x00000006, + 0x3a4c, 0x00000000, + + + + + + 0x3b0c, 0x00002000, + 0x3b10, 0x00000000, + 0x3b2c, 0x746b1022, + 0x3b30, 0x00000000, + 0x3b40, 0x84099100, + 0x3b44, 0x00000000, + 0x3b48, 0x00500420, + 0x3b4c, 0x00000000, + 0x3b50, 0x00008101, + 0x3b54, 0xc5ba000f, + 0x3b58, 0x00005001, + 0x3b5c, 0x00000000, + 0x3b60, 0x06800000, + 0x3b64, 0x00000013, + 0x3b68, 0x00000000, + 0x3b70, 0xd54b2906, + 0x3b74, 0x0000000c, + 0x3b78, 0x00000000, + 0x3b7c, 0x746b1022, + 0x3b80, 0x00000000, + 0x3b84, 0x00000001, + 0x3b88, 0x00000000, + 0x3bf0, 0x0072ff93, + 0x3bf4, 0x00000000, + + + + + + 0x900c, 0x00800000, + 0x9010, 0x00000000, + 0x9014, 0x00000000, + 0x9018, 0x00000000, + 0x901C, 0x00000000, + 0x9020, 0x00000000, + 0x9024, 0x00000000, + 0x9028, 0x00000000, + 0x902C, 0x00000000, + 0x9030, 0x00000000, + 0x9034, 0x00000080, + 0x9038, 0x00000000, + 0x903C, 0x00000000, + 0x9040, 0x00010101, + 0x9044, 0x00000000, + 0x9048, 0x00000000, + 0x904C, 0x00000000, + 0x9050, 0x00000000, + 0x9054, 0x00000000, + 0x9058, 0x00000000, + 0x905C, 0x00000000, + 0x9060, 0x00000000, + 0x9064, 0x000000e4, + 0x9068, 0x0f008c0f, + 0x906c, 0x0000002c, + 0x9070, 0x00000000, + 0x9074, 0x00000000, + 0x9078, 0x00000000, + 0x907C, 0x00000000, + 0x9080, 0x21010008, + 0x9084, 0x11110020, + 0x9088, 0x80750522, + 0x908c, 0x00000002, + 0x9090, 0x02510456, + 0x9094, 0x00ff0000, + 0x9098, 0x00000007, + 0x909c, 0x00000000, + 0x90a0, 0x00000000, + 0x90a4, 0x00000000, + 0x90a8, 0x00000000, + 0x90aC, 0x00000000, + 0x90b0, 0x00000000, + 0x90b4, 0x00000000, + 0x90b8, 0x00000000, + 0x90bC, 0x00000000, + 0x90c0, 0x00000000, + 0x90c4, 0x00000000, + 0x90c8, 0x00000000, + 0x90cC, 0x00000000, + + + + + 0x910c, 0x00800000, + 0x9110, 0x00000000, + 0x9140, 0x00000003, + 0x9144, 0x001f0000, + 0x9148, 0x00200000, + 0x914c, 0x00000001, + 0x9150, 0x00200000, + 0x9154, 0x00000002, + 0x9158, 0x00200000, + 0x915c, 0x00000003, + 0x9160, 0x00200000, + 0x9164, 0x00000004, + 0x9168, 0x00200000, + 0x916c, 0x00000005, + 0x9170, 0x00200000, + 0x9174, 0x00000006, + 0x9178, 0x00200000, + 0x917c, 0x00000007, + 0x9180, 0x00e00003, + 0x9184, 0x00e1ff00, + 0x9188, 0x00d80003, + 0x918c, 0x00dfff00, + 0x9190, 0x00e20003, + 0x9194, 0x00e3ff00, + 0x9198, 0x00000000, + 0x91b0, 0x00000a03, + 0x91b4, 0x00000b00, + 0x91b8, 0x00200003, + 0x91bc, 0x00fe0b00, + 0x91c0, 0x0000c003, + 0x91c4, 0x0000c000, + 0x91c8, 0x00001013, + 0x91cc, 0x000ff000, + 0x91d0, 0x00000000, + 0x91e0, 0xff000003, + 0x91e4, 0x00000000, + 0x9200, 0x11021022, + 0x9204, 0x00000000, + 0x9208, 0x06000000, + 0x920c, 0x00800000, + 0x9210, 0x00000000, + 0x9240, 0x00000001, + 0x9244, 0x00800001, + 0x9248, 0x01000001, + 0x924c, 0x01800001, + 0x9250, 0x00000000, + 0x9260, 0x0060fe00, + 0x9270, 0x00000000, + 0x9280, 0x00000022, + 0x9284, 0x00000000, + 0x9288, 0x03623125, + 0x928c, 0x00000130, + 0x9290, 0x080c8000, + 0x9294, 0x0e2b0a06, + 0x9298, 0x00000000, + 0x92b0, 0xd1e8eb05, + 0x92b4, 0x000000cc, + 0x92b8, 0xdfbfe7ad, + 0x92bc, 0xdf4bdfae, + 0x92c0, 0x00000003, + 0x92c4, 0x00000000, + 0x92cc, 0x9f1f0000, + 0x92d0, 0xfbf177f5, + 0x92d4, 0x3fefda0e, + 0x92d8, 0x33bd35dc, + 0x92dc, 0x578d89c1, + 0x92e0, 0xdae70105, + 0x92e4, 0xfa835cfc, + 0x92e8, 0x404e87e6, + 0x92ec, 0xba35df44, + 0x92f0, 0x00000000, + + + + + + 0x930c, 0x00800000, + 0x9310, 0x00000000, + 0x9340, 0x00003bff, + 0x9344, 0x00000040, + 0x9348, 0x00000000, + 0x935c, 0xfe3fb540, + 0x9360, 0x00000090, + 0x9364, 0x00000000, + 0x9370, 0x51020111, + 0x9374, 0x50008011, + 0x9378, 0x08003800, + 0x937c, 0x0000221b, + 0x9380, 0x21272321, + 0x9384, 0x00232123, + 0x9388, 0x00000000, + 0x9390, 0x00000005, + 0x9394, 0x00000068, + 0x9398, 0x001fe800, + 0x939c, 0x00000000, + 0x93b8, 0xe000001d, + 0x93bc, 0x000000bb, + 0x93c0, 0x00000000, + 0x93d4, 0x000d0001, + 0x93d8, 0x00000000, + 0x93e4, 0x00001520, + 0x93e8, 0x00000108, + 0x93ec, 0x00000000, + }; + int max; + max = sizeof(register_values); +} diff --git a/util/romcc/tests/simple_test15.c b/util/romcc/tests/simple_test15.c new file mode 100644 index 0000000000..d02eaefd35 --- /dev/null +++ b/util/romcc/tests/simple_test15.c @@ -0,0 +1,47 @@ +static void outb(unsigned char value, unsigned short port) +{ + __builtin_outb(value, port); +} + +static unsigned char inb(unsigned short port) +{ + return __builtin_inb(port); +} +static int uart_can_tx_byte(void) +{ + return inb(0x3f8 + 0x05) & 0x20; +} + +static void uart_wait_to_tx_byte(void) +{ + while(!uart_can_tx_byte()) + ; +} + +static void uart_wait_until_sent(void) +{ + while(!(inb(0x3f8 + 0x05) & 0x40)) + ; +} + +static void uart_tx_byte(unsigned char data) +{ + uart_wait_to_tx_byte(); + outb(data, 0x3f8 + 0x00); + + uart_wait_until_sent(); +} + +static void print_debug(const char *str) +{ + unsigned char ch; + while((ch = *str++) != '\0') { + uart_tx_byte(ch); + } +} + +static void main(void) +{ + print_debug("one\r\n"); + print_debug("two\r\n"); +} diff --git a/util/romcc/tests/simple_test2.c b/util/romcc/tests/simple_test2.c new file mode 100644 index 0000000000..aef936a8ff --- /dev/null +++ b/util/romcc/tests/simple_test2.c @@ -0,0 +1,36 @@ +void outl(unsigned int value, unsigned short port) +{ + __builtin_outl(value, port); +} + +#define PIIX4_DEVFN 0x90 +#define SMBUS_MEM_DEVICE_START 0x50 +#define SMBUS_MEM_DEVICE_END 0x53 +#define SMBUS_MEM_DEVICE_INC 1 + + +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; + + end_of_memory = 0; /* in multiples of 8MiB */ + device = SMBUS_MEM_DEVICE_START; + while (device <= SMBUS_MEM_DEVICE_END) { + unsigned side1_bits; + + side1_bits = -1; + + /* 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); + } + outl(end_of_memory, 0x1234); + } +} diff --git a/util/romcc/tests/simple_test3.c b/util/romcc/tests/simple_test3.c new file mode 100644 index 0000000000..008d0ab528 --- /dev/null +++ b/util/romcc/tests/simple_test3.c @@ -0,0 +1,38 @@ +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; + + end_of_memory = 0; /* in multiples of 8MiB */ + device = 0x50; + while (device <= 0x53) { + unsigned side1_bits, side2_bits; + int byte, byte2; + + side1_bits = side2_bits = -1; + + /* rows */ + byte = -1; + if (1) { + /* now I have the ram size in bits as a power of two (less 1) */ + /* Make it mulitples of 8MB */ + side1_bits -= 25; + } + + /* Compute the end address for the DRB register */ + /* Only process dimms < 2GB (2^8 * 8MB) */ + if (1) { + end_of_memory += side1_bits; + } + __builtin_outl(end_of_memory, 0x1234); + + if (1) { + end_of_memory += side2_bits; + } + } +} diff --git a/util/romcc/tests/simple_test4.c b/util/romcc/tests/simple_test4.c new file mode 100644 index 0000000000..bfc05d9e0d --- /dev/null +++ b/util/romcc/tests/simple_test4.c @@ -0,0 +1,509 @@ +#define HAVE_STRING_SUPPORT 1 +#define HAVE_CAST_SUPPORT 1 +#define HAVE_STATIC_ARRAY_SUPPORT 1 +#define HAVE_POINTER_SUPPORT 1 +#define HAVE_CONSTANT_PROPOGATION 1 +#define CALCULATE_DRB_REG 1 + +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); +} + +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); +} + + +/* 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) + +#if HAVE_CONSTANT_PROPOGATION +#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_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; +} + +#else /* !HAVE_CONSTANT_PROPOGATION */ + +#define SMBUS_IO_HSTSTAT 0x1000 +#define SMBUS_IO_HSTCTL 0x1002 +#define SMBUS_IO_HSTCMD 0x1003 +#define SMBUS_IO_HSTADD 0x1004 +#define SMBUS_IO_HSTDAT0 0x1005 +#define SMBUS_IO_HSTDAT1 0x1006 +#define SMBUS_IO_HSTBLKDAT 0x1007 + + +static void smbus_wait_until_ready(void) +{ + while((inb(SMBUS_IO_HSTSTAT) & 1) == 1) { + /* nop */ + } +} + +static void smbus_wait_until_done(void) +{ + unsigned char byte; + do { + byte = inb(SMBUS_IO_HSTSTAT); + }while((byte &1) == 1); + while( (byte & ~1) == 0) { + byte = inb(SMBUS_IO_HSTSTAT); + } +} + +short smbus_read_byte(unsigned char device, unsigned char address) +{ + unsigned char host_status_register; + short result; + + smbus_wait_until_ready(); + + /* setup transaction */ + /* disable interrupts */ + outb(inb(SMBUS_IO_HSTCTL) & (~1), SMBUS_IO_HSTCTL); + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 1, SMBUS_IO_HSTADD); + /* set the command/address... */ + outb(address & 0xFF, SMBUS_IO_HSTCMD); + /* set up for a byte data read */ + outb((inb(SMBUS_IO_HSTCTL) & 0xE3) | 8, SMBUS_IO_HSTCTL); + + /* clear any lingering errors, so the transaction will run */ + outb(inb(SMBUS_IO_HSTSTAT), SMBUS_IO_HSTSTAT); + + /* clear the data byte...*/ + outb(0, SMBUS_IO_HSTDAT0); + + /* start the command */ + outb((inb(SMBUS_IO_HSTCTL) | 0x40), SMBUS_IO_HSTCTL); + + /* poll for transaction completion */ + smbus_wait_until_done(); + + host_status_register = inb(SMBUS_IO_HSTSTAT); + + /* read results of transaction */ + result = inb(SMBUS_IO_HSTDAT0); + + if (host_status_register != 0x02) { + result = -1; + } + return result; +} +#endif /* HAVE_CONSTANT_PROPOGATION */ + +#define I440GX_BUS 0 +#define I440GX_DEVFN ((0x00 << 3) + 0) + + +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 char device; + unsigned char drb_reg; + + end_of_memory = 0; /* in multiples of 8MiB */ + device = SMBUS_MEM_DEVICE_START; +#if !CALCULATE_DRB_REG + drb_reg = 0x60; +#endif + 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 module 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 CALCULATE_DRB_REG + drb_reg = ((device - SMBUS_MEM_DEVICE_START) << 1) + 0x60; +#endif + +#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); + +#if !CALCULATE_DRB_REG + drb_reg += 2; +#endif + device += SMBUS_MEM_DEVICE_INC; + } +} diff --git a/util/romcc/tests/simple_test5.c b/util/romcc/tests/simple_test5.c new file mode 100644 index 0000000000..efc1e9489a --- /dev/null +++ b/util/romcc/tests/simple_test5.c @@ -0,0 +1,310 @@ +#define HAVE_STRING_SUPPORT 0 +#define HAVE_CAST_SUPPORT 0 +#define HAVE_STATIC_ARRAY_SUPPORT 0 +#define HAVE_POINTER_SUPPORT 0 +#define HAVE_CONSTANT_PROPOGATION 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); +} + +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); +} + +#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) + +#if HAVE_CONSTANT_PROPOGATION +#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_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; +} + +#else /* !HAVE_CONSTANT_PROPOGATION */ + +#define SMBUS_IO_HSTSTAT 0x1000 +#define SMBUS_IO_HSTCTL 0x1002 +#define SMBUS_IO_HSTCMD 0x1003 +#define SMBUS_IO_HSTADD 0x1004 +#define SMBUS_IO_HSTDAT0 0x1005 +#define SMBUS_IO_HSTDAT1 0x1006 +#define SMBUS_IO_HSTBLKDAT 0x1007 + + +static void smbus_wait_until_ready(void) +{ + while((inb(SMBUS_IO_HSTSTAT) & 1) == 1) { + /* nop */ + } +} + +static void smbus_wait_until_done(void) +{ + unsigned char byte; + do { + byte = inb(SMBUS_IO_HSTSTAT); + }while((byte &1) == 1); + while( (byte & ~1) == 0) { + byte = inb(SMBUS_IO_HSTSTAT); + } +} + +int smbus_read_byte(unsigned device, unsigned address) +{ + unsigned char host_status_register; + int result; + + smbus_wait_until_ready(); + + /* setup transaction */ + /* disable interrupts */ + outb(inb(SMBUS_IO_HSTCTL) & (~1), SMBUS_IO_HSTCTL); + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 1, SMBUS_IO_HSTADD); + /* set the command/address... */ + outb(address & 0xFF, SMBUS_IO_HSTCMD); + /* set up for a byte data read */ + outb((inb(SMBUS_IO_HSTCTL) & 0xE3) | 8, SMBUS_IO_HSTCTL); + + /* clear any lingering errors, so the transaction will run */ + outb(inb(SMBUS_IO_HSTSTAT), SMBUS_IO_HSTSTAT); + + /* clear the data byte...*/ + outb(0, SMBUS_IO_HSTDAT0); + + /* start the command */ + outb((inb(SMBUS_IO_HSTCTL) | 0x40), SMBUS_IO_HSTCTL); + + /* poll for transaction completion */ + smbus_wait_until_done(); + + host_status_register = inb(SMBUS_IO_HSTSTAT); + + /* read results of transaction */ + result = inb(SMBUS_IO_HSTDAT0); + + if (host_status_register != 0x02) { + result = -1; + } + return result; +} +#endif /* HAVE_CONSTANT_PROPOGATION */ + + +#define I440GX_BUS 0 +#define I440GX_DEVFN ((0x00 << 3) + 0) + +void sdram_no_memory(void) +{ +#if HAVE_STRING_SUPPORT + print_err("No memory!!\n"); +#endif + while(1) ; +} + +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); +} + +void sdram_enable_refresh(void) +{ + spd_enable_refresh(); +} + diff --git a/util/romcc/tests/simple_test6.c b/util/romcc/tests/simple_test6.c new file mode 100644 index 0000000000..3dac72d0fb --- /dev/null +++ b/util/romcc/tests/simple_test6.c @@ -0,0 +1,269 @@ +#define HAVE_CONSTANT_PROPOGATION 1 + +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); +} + +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); +} + +#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) + +#if HAVE_CONSTANT_PROPOGATION +#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_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; +} + +#else /* !HAVE_CONSTANT_PROPOGATION */ + +#define SMBUS_IO_HSTSTAT 0x1000 +#define SMBUS_IO_HSTCTL 0x1002 +#define SMBUS_IO_HSTCMD 0x1003 +#define SMBUS_IO_HSTADD 0x1004 +#define SMBUS_IO_HSTDAT0 0x1005 +#define SMBUS_IO_HSTDAT1 0x1006 +#define SMBUS_IO_HSTBLKDAT 0x1007 + + +static void smbus_wait_until_ready(void) +{ + while((inb(SMBUS_IO_HSTSTAT) & '\1') == '\1') { + /* nop */ + } +} + +static void smbus_wait_until_done(void) +{ + unsigned char byte; + do { + byte = inb(SMBUS_IO_HSTSTAT); + }while((byte &1) == 1); + while( (byte & ~1) == 0) { + byte = inb(SMBUS_IO_HSTSTAT); + } +} + +short smbus_read_byte(unsigned char device, unsigned char address) +{ + unsigned char host_status_register; + short result; + + smbus_wait_until_ready(); /* 2 */ + + /* setup transaction */ + /* disable interrupts */ + outb(inb(SMBUS_IO_HSTCTL) & (~1), SMBUS_IO_HSTCTL); /* 3 */ + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 1, SMBUS_IO_HSTADD); /* 1 + 3 */ + /* set the command/address... */ + outb(address & 0xFF, SMBUS_IO_HSTCMD); /* 1 + 3 */ + /* set up for a byte data read */ + outb((inb(SMBUS_IO_HSTCTL) & 0xE3) | 8, SMBUS_IO_HSTCTL); /* 3 */ + + /* clear any lingering errors, so the transaction will run */ + outb(inb(SMBUS_IO_HSTSTAT), SMBUS_IO_HSTSTAT); /* 3 */ + + /* clear the data byte...*/ + outb(0, SMBUS_IO_HSTDAT0); /* 3 */ + + /* start the command */ + outb((inb(SMBUS_IO_HSTCTL) | 0x40), SMBUS_IO_HSTCTL); + + /* poll for transaction completion */ + smbus_wait_until_done(); + + host_status_register = inb(SMBUS_IO_HSTSTAT); + + /* read results of transaction */ + result = inb(SMBUS_IO_HSTDAT0); + + if (host_status_register != 0x02) { + result = -1; + } + return result; +} +#endif /* HAVE_CONSTANT_PROPOGATION */ + + +static void test(void) +{ + short byte; + unsigned device; + unsigned char i, j, k, l, m, n, o; + i = 1; + j = 2; + k = 3; + l = 4; + m = 5; + n = 6; + o = 7; + device = inb(SMBUS_MEM_DEVICE_START); + byte = smbus_read_byte(device, 3); + outb(i, 0xab); + outb(j, 0xab); + outb(k, 0xab); + outb(l, 0x1234); +#if 1 + outb(m, 0xab); +#endif +#if 0 + outb(n, 0xab); +#endif +#if 0 + outb(o, 0xab); +#endif +} diff --git a/util/romcc/tests/simple_test7.c b/util/romcc/tests/simple_test7.c new file mode 100644 index 0000000000..571f2cdb71 --- /dev/null +++ b/util/romcc/tests/simple_test7.c @@ -0,0 +1,12 @@ +void main(void) +{ + int i; + i = 0; + do { + int j; + __builtin_outb(i, 0xab); + j = i++; + __builtin_outb(j, 0xdc); + } while(i <= 9); + +} diff --git a/util/romcc/tests/simple_test8.c b/util/romcc/tests/simple_test8.c new file mode 100644 index 0000000000..0b6b853e19 --- /dev/null +++ b/util/romcc/tests/simple_test8.c @@ -0,0 +1,12 @@ + + +void main(void) +{ + static const char msg[] = "hello world\r\n"; + char *str; + char ch; + str = msg; + while(1) { + ch = *str++; + } +} diff --git a/util/romcc/tests/simple_test9.c b/util/romcc/tests/simple_test9.c new file mode 100644 index 0000000000..e8df1b9afb --- /dev/null +++ b/util/romcc/tests/simple_test9.c @@ -0,0 +1,12 @@ + + +void main(void) +{ + static const char msg[] = "hello world\r\n"; + char *str; + char ch; + str = msg; + do { + ch = *str++; + } while(ch); +} |