<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>