📄 pcilow.c
字号:
_asm mov di,reg
_asm mov ah,PCI_FUNCTION_ID
_asm mov al,WRITE_CONFIG_WORD
_asm mov cx,value
_asm int 1ah
_asm mov result,ax
_asm jc write_fail3
_asm cmp ah,SUCCESSFUL
_asm jnz write_fail3
_asm mov ah,PCI_FUNCTION_ID
_asm mov al,WRITE_CONFIG_WORD
_asm add di,2
_asm mov bx,temp
_asm mov cx,WORD PTR [value + 2]
_asm int 1ah
_asm mov result,ax
_asm jc write_fail3
_asm cmp ah,SUCCESSFUL
_asm jnz write_fail3
write_fail3:
break;
};
return (long)((result & 0xff00) >> 8);
}
long pci_bios_read_config_byte(struct pci_dev *dev, long where, u8 *value)
{
int result;
u32 data;
if (!value)
return -EINVAL;
result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 1, &data);
*value = (u8)data;
return result;
}
long pci_bios_read_config_word(struct pci_dev *dev, long where, u16 *value)
{
int result;
u32 data;
if (!value)
return -EINVAL;
result = pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 2, &data);
*value = (u16)data;
return result;
}
long pci_bios_read_config_dword(struct pci_dev *dev, long where, u32 *value)
{
if (!value)
return -EINVAL;
return pci_bios_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 4, value);
}
long pci_bios_write_config_byte(struct pci_dev *dev, long where, u8 value)
{
return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 1, value);
}
long pci_bios_write_config_word(struct pci_dev *dev, long where, u16 value)
{
return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 2, value);
}
long pci_bios_write_config_dword(struct pci_dev *dev, long where, u32 value)
{
return pci_bios_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 4, value);
}
/*
* Function table for BIOS32 access
*/
extern struct pci_ops pci_bios_access;
long pci_read_config_byte (struct pci_dev *dev, long pos, u8 * value)
{
long res;
if (PCI_byte_BAD)
return BAD_REGISTER_NUMBER;
local_irq_save(0);
res = dev->bus->ops->read_byte(dev, pos, value);
local_irq_restore(0);
return res;
}
long pci_read_config_word (struct pci_dev *dev, long pos, u16 * value)
{
long res;
if (PCI_word_BAD)
return BAD_REGISTER_NUMBER;
local_irq_save(0);
res = dev->bus->ops->read_word(dev, pos, value);
local_irq_restore(0);
return res;
}
long pci_read_config_dword (struct pci_dev *dev, long pos, u32 * value)
{
long res;
if (PCI_dword_BAD)
return BAD_REGISTER_NUMBER;
local_irq_save(0);
res = dev->bus->ops->read_dword(dev, pos, value);
local_irq_restore(0);
return res;
}
long pci_write_config_byte (struct pci_dev *dev, long pos, u8 value)
{
long res;
if (PCI_byte_BAD)
return BAD_REGISTER_NUMBER;
local_irq_save(0);
res = dev->bus->ops->write_byte(dev, pos, value);
local_irq_restore(0);
return res;
}
long pci_write_config_word (struct pci_dev *dev, long pos, u16 value)
{
long res;
if (PCI_word_BAD)
return BAD_REGISTER_NUMBER;
local_irq_save(0);
res = dev->bus->ops->write_word(dev, pos, value);
local_irq_restore(0);
return res;
}
long pci_write_config_dword (struct pci_dev *dev, long pos, u32 value)
{
long res;
if (PCI_dword_BAD)
return BAD_REGISTER_NUMBER;
local_irq_save(0);
res = dev->bus->ops->write_dword(dev, pos, value);
local_irq_restore(0);
return res;
}
long pci_sanity_check(struct pci_ops *o)
{
u16 x;
struct pci_bus bus; /* Fake bus and device */
struct pci_dev dev;
if (pci_probe & PCI_NO_CHECKS)
return 1;
bus.number = 0;
dev.bus = &bus;
for(dev.devfn=0; dev.devfn < 0x100; dev.devfn++)
if ((!o->read_word(&dev, PCI_CLASS_DEVICE, &x) &&
(x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
(!o->read_word(&dev, PCI_VENDOR_ID, &x) &&
(x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
return 1;
safe_printf("PCI: Sanity check failed\n");
return 0;
}
struct pci_ops * pci_check_direct(void)
{
unsigned long tmp;
local_irq_save(0);
/*
* Check if configuration type 1 works.
*/
if (pci_probe & PCI_PROBE_CONF1) {
outb (0x01, 0xCFB);
tmp = inl (0xCF8);
outl (0x80000000, 0xCF8);
if (inl (0xCF8) == 0x80000000 &&
pci_sanity_check(&pci_direct_conf1)) {
outl (tmp, 0xCF8);
local_irq_restore(0);
return &pci_direct_conf1;
}
outl (tmp, 0xCF8);
}
/*
* Check if configuration type 2 works.
*/
if (pci_probe & PCI_PROBE_CONF2) {
outb (0x00, 0xCFB);
outb (0x00, 0xCF8);
outb (0x00, 0xCFA);
if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00 &&
pci_sanity_check(&pci_direct_conf2)) {
local_irq_restore(0);
safe_printf("PCI: Using configuration type 2\n");
return &pci_direct_conf2;
}
}
local_irq_restore(0);
return NULL;
}
void pcibios_config_init(void)
{
if ((pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
&& (pci_root_ops = pci_check_direct())) {
if (pci_root_ops == &pci_direct_conf1) {
pci_config_read = pci_conf1_read;
pci_config_write = pci_conf1_write;
}
else {
pci_config_read = pci_conf2_read;
pci_config_write = pci_conf2_write;
}
return;
}
if ((pci_probe & PCI_PROBE_BIOS)
&& ((pci_root_ops = pci_find_bios()))) {
pci_probe |= PCI_BIOS_SORT;
pci_bios_present = 1;
pci_config_read = pci_bios_read;
pci_config_write = pci_bios_write;
}
return;
}
void pcibios_init(void)
{
if (!pci_root_ops)
pcibios_config_init();
if (!pci_root_ops) {
safe_printf("PCI: System does not support PCI\n");
return;
}
safe_printf("PCI: Probing PCI hardware\n");
pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
pcibios_irq_init();
pcibios_fixup_peer_bridges();
pcibios_fixup_irqs();
pcibios_resource_survey();
if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
pcibios_sort();
}
struct pci_ops * pci_find_bios(void)
{
_asm mov ah,PCI_FUNCTION_ID
_asm mov al,PCI_BIOS_PRESENT
_asm int 1ah
_asm jc check_fail
_asm cmp ah,SUCCESSFUL
_asm jnz check_fail
_asm cmp dx,PCIBIOS_SIGNATURE
_asm jnz check_fail
return &pci_bios_access;
check_fail:
return NULL;
}
long pci_bios_find_device (unsigned short vendor, unsigned short device_id,
unsigned short index, unsigned char far * bus,
unsigned char far * device_fn)
{
unsigned short bx1;
unsigned short res;
_asm push si
_asm mov ah,PCI_FUNCTION_ID
_asm mov al,FIND_PCI_DEVICE
_asm mov cx,device_id
_asm mov dx,vendor
_asm mov si,index
_asm int 1ah
_asm pop si
_asm mov res,ax
_asm jc find_fail
_asm cmp ah,SUCCESSFUL
_asm jnz find_fail
_asm mov bx1,bx
_asm jmp find_ok
find_fail:
if(!(res & 0xff00))
return 0xff00L;
else
return (long)(res & 0xff00) >> 8;
find_ok:
*bus = (bx1 >> 8) & 0xff;
*device_fn = bx1 & 0xff;
return (long) (res & 0xff00) >> 8;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -