Use more care when implementing the PCI BIOS functions.
The READ_CONF and WRITE_CONF functions would both do the wrong thing if the passed in BDF was not found. We should return and error to the caller, but not stop running the option ROM. Signed-off-by: Mark Marshall <mark.marshall@csr.com> I slightly reworked the patch: The 'CHECK' function seemed to be both wrong code and the wrong number. In fact the CHECK function was given the function number of the "Microsoft Real-Time Compression Interface". Since this is definitely wrong I removed the code. Dropped some unneeded scopes, too, to make the code easier to read. Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4910 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
2fa7c2e210
commit
d08e69dd5e
|
@ -34,19 +34,22 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CHECK = 0xb001,
|
PCIBIOS_CHECK = 0xb101,
|
||||||
FINDDEV = 0xb102,
|
PCIBIOS_FINDDEV = 0xb102,
|
||||||
READCONFBYTE = 0xb108,
|
PCIBIOS_READCONFBYTE = 0xb108,
|
||||||
READCONFWORD = 0xb109,
|
PCIBIOS_READCONFWORD = 0xb109,
|
||||||
READCONFDWORD = 0xb10a,
|
PCIBIOS_READCONFDWORD = 0xb10a,
|
||||||
WRITECONFBYTE = 0xb10b,
|
PCIBIOS_WRITECONFBYTE = 0xb10b,
|
||||||
WRITECONFWORD = 0xb10c,
|
PCIBIOS_WRITECONFWORD = 0xb10c,
|
||||||
WRITECONFDWORD = 0xb10d
|
PCIBIOS_WRITECONFDWORD = 0xb10d
|
||||||
};
|
};
|
||||||
|
|
||||||
// errors go in AH. Just set these up so that word assigns
|
// errors go in AH. Just set these up so that word assigns
|
||||||
// will work. KISS.
|
// will work. KISS.
|
||||||
enum {
|
enum {
|
||||||
|
PCIBIOS_SUCCESSFUL = 0x0000,
|
||||||
|
PCIBIOS_UNSUPPORTED = 0x8100,
|
||||||
|
PCIBIOS_BADVENDOR = 0x8300,
|
||||||
PCIBIOS_NODEV = 0x8600,
|
PCIBIOS_NODEV = 0x8600,
|
||||||
PCIBIOS_BADREG = 0x8700
|
PCIBIOS_BADREG = 0x8700
|
||||||
};
|
};
|
||||||
|
@ -63,7 +66,7 @@ int int12_handler(struct eregs *regs)
|
||||||
|
|
||||||
int int1a_handler(struct eregs *regs)
|
int int1a_handler(struct eregs *regs)
|
||||||
{
|
{
|
||||||
unsigned short func = (unsigned short) regs->eax;
|
unsigned short func = (unsigned short)regs->eax;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
unsigned short devid, vendorid, devfn;
|
unsigned short devid, vendorid, devfn;
|
||||||
/* Use short to get rid of gabage in upper half of 32-bit register */
|
/* Use short to get rid of gabage in upper half of 32-bit register */
|
||||||
|
@ -71,14 +74,13 @@ int int1a_handler(struct eregs *regs)
|
||||||
unsigned char bus;
|
unsigned char bus;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
switch(func) {
|
switch (func) {
|
||||||
case CHECK:
|
case PCIBIOS_CHECK:
|
||||||
regs->edx = 0x4350;
|
regs->edx = 0x20494350; /* ' ICP' */
|
||||||
regs->ecx = 0x2049;
|
regs->edi = 0x00000000; /* protected mode entry */
|
||||||
retval = 0;
|
retval = 0;
|
||||||
break;
|
break;
|
||||||
case FINDDEV:
|
case PCIBIOS_FINDDEV:
|
||||||
{
|
|
||||||
devid = regs->ecx;
|
devid = regs->ecx;
|
||||||
vendorid = regs->edx;
|
vendorid = regs->edx;
|
||||||
devindex = regs->esi;
|
devindex = regs->esi;
|
||||||
|
@ -98,7 +100,7 @@ int int1a_handler(struct eregs *regs)
|
||||||
// busnum is an unsigned char;
|
// busnum is an unsigned char;
|
||||||
// devfn is an int, so we mask it off.
|
// devfn is an int, so we mask it off.
|
||||||
busdevfn = (dev->bus->secondary << 8)
|
busdevfn = (dev->bus->secondary << 8)
|
||||||
| (dev->path.pci.devfn & 0xff);
|
| (dev->path.pci.devfn & 0xff);
|
||||||
printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, busdevfn);
|
printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, busdevfn);
|
||||||
regs->ebx = busdevfn;
|
regs->ebx = busdevfn;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
@ -106,15 +108,13 @@ int int1a_handler(struct eregs *regs)
|
||||||
regs->eax = PCIBIOS_NODEV;
|
regs->eax = PCIBIOS_NODEV;
|
||||||
retval = -1;
|
retval = -1;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case PCIBIOS_READCONFDWORD:
|
||||||
case READCONFDWORD:
|
case PCIBIOS_READCONFWORD:
|
||||||
case READCONFWORD:
|
case PCIBIOS_READCONFBYTE:
|
||||||
case READCONFBYTE:
|
case PCIBIOS_WRITECONFDWORD:
|
||||||
case WRITECONFDWORD:
|
case PCIBIOS_WRITECONFWORD:
|
||||||
case WRITECONFWORD:
|
case PCIBIOS_WRITECONFBYTE:
|
||||||
case WRITECONFBYTE:
|
|
||||||
{
|
|
||||||
unsigned long dword;
|
unsigned long dword;
|
||||||
unsigned short word;
|
unsigned short word;
|
||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
|
@ -124,49 +124,48 @@ int int1a_handler(struct eregs *regs)
|
||||||
bus = regs->ebx >> 8;
|
bus = regs->ebx >> 8;
|
||||||
reg = regs->edi;
|
reg = regs->edi;
|
||||||
dev = dev_find_slot(bus, devfn);
|
dev = dev_find_slot(bus, devfn);
|
||||||
if (! dev) {
|
if (!dev) {
|
||||||
printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
|
printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
|
||||||
// idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
|
// idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
|
||||||
regs->eax = PCIBIOS_BADREG;
|
regs->eax = PCIBIOS_BADREG;
|
||||||
retval = -1;
|
retval = -1;
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
switch(func) {
|
switch (func) {
|
||||||
case READCONFBYTE:
|
case PCIBIOS_READCONFBYTE:
|
||||||
byte = pci_read_config8(dev, reg);
|
byte = pci_read_config8(dev, reg);
|
||||||
regs->ecx = byte;
|
regs->ecx = byte;
|
||||||
break;
|
break;
|
||||||
case READCONFWORD:
|
case PCIBIOS_READCONFWORD:
|
||||||
word = pci_read_config16(dev, reg);
|
word = pci_read_config16(dev, reg);
|
||||||
regs->ecx = word;
|
regs->ecx = word;
|
||||||
break;
|
break;
|
||||||
case READCONFDWORD:
|
case PCIBIOS_READCONFDWORD:
|
||||||
dword = pci_read_config32(dev, reg);
|
dword = pci_read_config32(dev, reg);
|
||||||
regs->ecx = dword;
|
regs->ecx = dword;
|
||||||
break;
|
break;
|
||||||
case WRITECONFBYTE:
|
case PCIBIOS_WRITECONFBYTE:
|
||||||
byte = regs->ecx;
|
byte = regs->ecx;
|
||||||
pci_write_config8(dev, reg, byte);
|
pci_write_config8(dev, reg, byte);
|
||||||
break;
|
break;
|
||||||
case WRITECONFWORD:
|
case PCIBIOS_WRITECONFWORD:
|
||||||
word = regs->ecx;
|
word = regs->ecx;
|
||||||
pci_write_config16(dev, reg, word);
|
pci_write_config16(dev, reg, word);
|
||||||
break;
|
break;
|
||||||
case WRITECONFDWORD:
|
case PCIBIOS_WRITECONFDWORD:
|
||||||
dword = regs->ecx;
|
dword = regs->ecx;
|
||||||
pci_write_config32(dev, reg, dword);
|
pci_write_config32(dev, reg, dword);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval)
|
|
||||||
retval = PCIBIOS_BADREG;
|
|
||||||
printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
|
printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
|
||||||
func, bus, devfn, reg, regs->ecx);
|
func, bus, devfn, reg, regs->ecx);
|
||||||
regs->eax = 0;
|
regs->eax = 0;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
|
printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
|
||||||
|
retval = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue