<html><head><style type='text/css'>p { margin: 0; }</style></head><body><div style='font-family: times new roman,new york,times,serif; font-size: 12pt; color: #000000'><font face="lucida console,sans-serif" size="2">All,<br><br>I've added code to output.c to implement a I2C console interface.<br>Everything was working great on my AMD/Persimmon until I added additional code<br>to determine what southbridge I was on. I'm evidently not correctly handling<br>the 16/32 bit code segments correctly. It's evident when I run the debugger<br>and watch the disassembly. Not only is the disassembly wrong but it isn't<br>even consistent between runs.<br><br>The new code is below, along with the modified <font face="lucida console,sans-serif" size="2">putc_debug().<br><br>Any suggestions would be appreciated.<br><br>Thanks,<br>Dave<br></font></font><font face="lucida console,sans-serif" size="2"><br><br>#if MODE16<br>#define FIXUP_CODE_SEG_LOCATION VAR16<br>#elif MODESEGMENT<br>#define FIXUP_CODE_SEG_LOCATION VAR32SEG<br>#else<br>#define FIXUP_CODE_SEG_LOCATION<br>#endif<br><br>struct amd_i2c_list{<br>    u16 sb_ven;<br>    u16 sb_dev;<br>    u8  sb_ver;<br>    u8 base_access;<br>};<br><br>/* send a debug character to the i2c port */<br>static void debug_i2c(char data)<br>{<br>    static int FIXUP_CODE_SEG_LOCATION i2c_amd_iobase = 0;<br>    static int FIXUP_CODE_SEG_LOCATION i2c_inited = 0;<br><br>    static const FIXUP_CODE_SEG_LOCATION struct amd_i2c_list amd_smbus_table[] = {<br>        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, 0x39, 2 }, /* ATI/AMD SB700 base in pci space */<br>        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, 0x42, 1 }, /* ATI/AMD SB800 base in pmreg */<br>        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SB900_SM,    0x14, 1 }, /* ATI/AMD SB900 base in pmreg */<br>    };<br><br>    volatile u16 rd_vendor, rd_device;<br>    volatile u8 rd_ver, base_access;<br>    int i;<br>    u32 x;<br><br>    if (!CONFIG_DEBUG_I2C)<br>        return;<br><br>    /* check to see if we already tried init and it failed */<br>    if (i2c_inited && !i2c_amd_iobase)<br>        return;<br><br>    /* check to see if the base address has been initialized */<br>    if (!i2c_inited) {<br>        i2c_inited=1;<br>        /* check for the AMD/ATI southbridges */<br>        rd_vendor = pci_config_readw(0xA0, 0x00);<br>        rd_device = pci_config_readw(0xA0, 0x02);<br>        rd_ver = pci_config_readb(0xA0, 0x08);<br>        base_access=0;<br>        for (i=0;i < sizeof(amd_smbus_table)/sizeof(amd_smbus_table[0]);++i) {<br>            if ((amd_smbus_table[i].sb_ven==rd_vendor)<br>                && (amd_smbus_table[i].sb_dev==rd_device)<br>                && (amd_smbus_table[i].sb_ver==rd_ver)) {<br>                base_access = amd_smbus_table[i].base_access;<br>                break;<br>            }<br>        }<br><br>        switch (base_access) {<br>        case 1:<br>            /* check the PM regs for the SM bus base address */<br>            outb (0x2D, 0xCD6);<br>            i2c_amd_iobase = inb(0xCD7)<<8;<br>            outb (0x2C, 0xCD6);<br>            i2c_amd_iobase |= inb(0xCD7);<br>            if ((i2c_amd_iobase!=0) && ((i2c_amd_iobase&0x01)==0x01)) {<br>                /* Found a SBx00 base address in PM reg space */<br>                i2c_amd_iobase &= 0xffe0;<br>            }<br>            else {<br>                /* can not find a valid base address */<br>                i2c_amd_iobase = 0;<br>            }<br>            break;<br>        case 2:<br>            /* check PCI config space for SM bus base address */<br>            x = pci_config_readl(0xA0, 0x90);<br>            if ((x!=0) && ((x&0x01)==0x01)) {<br>                /* Found a SBx00 base address in PCI cfg space */<br>                i2c_amd_iobase = (int)(x & 0xffe0);<br>            }<br>            else {<br>                /* can not find a valid base address */<br>                i2c_amd_iobase = 0;<br>            }<br>            break;<br>        default:<br>            i2c_amd_iobase = 0;<br>            break;<br>        }<br>        /* add checks for other vendors SMBUS controllers here */<br>    }<br><br>    if (i2c_amd_iobase) {<br>        /* this sequence will send out addr/data on the AMD SBx00 smbus */<br>        int timeout=DEBUG_TIMEOUT;<br>        /* check to see if the h/w is idle */<br>        do {<br>            if (!timeout--)<br>                return; // Ran out of time.<br>        }<br>        while ((inb(i2c_amd_iobase) & 0x01)!=0x00);<br>        outb (0xFF, i2c_amd_iobase + 0);     // clear error status<br>        outb (0x1F, i2c_amd_iobase + 1);     // clear error status<br>        outb (data, i2c_amd_iobase + 3);     // tx index<br>        outb (CONFIG_DEBUG_I2C_DEVICE_ADDR, i2c_amd_iobase + 4);  // slave address and write bit<br>        outb (0x44, i2c_amd_iobase + 2);     // command it to go<br>        /* check to see if the h/w is done */<br>        do {<br>            if (!timeout--)<br>                return; // Ran out of time.<br>        }<br>        while ((inb(i2c_amd_iobase) & 0x01)!=0x00);<br>    }<br>}<br><br>// Write a character to debug port(s).<br>static void<br>putc_debug(struct putcinfo *action, char c)<br>{<br>    if (! CONFIG_DEBUG_LEVEL)<br>        return;<br>    if (CONFIG_DEBUG_IO)<br>        // Send character to debug port.<br>        outb(c, GET_GLOBAL(DebugOutputPort));<br>    if (CONFIG_DEBUG_I2C)<br>        debug_i2c(c);<br>    if (c == '\n')<br>        debug_serial('\r');<br>    debug_serial(c);<br>}<br><br></font></div></body></html>