📄 bios32.c
字号:
if (dev->vendor == vendor && dev->device == device_id) { if (curr == index) { *devfn = dev->devfn; *bus = dev->bus->number; return PCIBIOS_SUCCESSFUL; } ++curr; } } return PCIBIOS_DEVICE_NOT_FOUND;}/* * Given the class, find the n'th instance of that device * in the system. */static int pci_direct_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *devfn){ unsigned int curr = 0; struct pci_dev *dev; for (dev = pci_devices; dev; dev = dev->next) { if (dev->class == class_code) { if (curr == index) { *devfn = dev->devfn; *bus = dev->bus->number; return PCIBIOS_SUCCESSFUL; } ++curr; } } return PCIBIOS_DEVICE_NOT_FOUND;}/* * Functions for accessing PCI configuration space with type 1 accesses */#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char *value){ unsigned long flags; save_flags(flags); cli(); outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); *value = inb(0xCFC + (where&3)); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}static int pci_conf1_read_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short *value){ unsigned long flags; if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER; save_flags(flags); cli(); outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); *value = inw(0xCFC + (where&2)); restore_flags(flags); return PCIBIOS_SUCCESSFUL; }static int pci_conf1_read_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int *value){ unsigned long flags; if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER; save_flags(flags); cli(); outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); *value = inl(0xCFC); restore_flags(flags); return PCIBIOS_SUCCESSFUL; }static int pci_conf1_write_config_byte (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char value){ unsigned long flags; save_flags(flags); cli(); outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); outb(value, 0xCFC + (where&3)); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}static int pci_conf1_write_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short value){ unsigned long flags; if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER; save_flags(flags); cli(); outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); outw(value, 0xCFC + (where&2)); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}static int pci_conf1_write_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int value){ unsigned long flags; if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER; save_flags(flags); cli(); outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); outl(value, 0xCFC); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}#undef CONFIG_CMD/* * functiontable for type 1 */static struct pci_access pci_direct_conf1 = { pci_direct_find_device, pci_direct_find_class, pci_conf1_read_config_byte, pci_conf1_read_config_word, pci_conf1_read_config_dword, pci_conf1_write_config_byte, pci_conf1_write_config_word, pci_conf1_write_config_dword};/* * Functions for accessing PCI configuration space with type 2 accesses */#define IOADDR(devfn, where) ((0xC000 | ((devfn & 0x78) << 5)) + where)#define FUNC(devfn) (((devfn & 7) << 1) | 0xf0)static int pci_conf2_read_config_byte(unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char *value){ unsigned long flags; if (device_fn & 0x80) return PCIBIOS_DEVICE_NOT_FOUND; save_flags(flags); cli(); outb (FUNC(device_fn), 0xCF8); outb (bus, 0xCFA); *value = inb(IOADDR(device_fn,where)); outb (0, 0xCF8); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}static int pci_conf2_read_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short *value){ unsigned long flags; if (device_fn & 0x80) return PCIBIOS_DEVICE_NOT_FOUND; save_flags(flags); cli(); outb (FUNC(device_fn), 0xCF8); outb (bus, 0xCFA); *value = inw(IOADDR(device_fn,where)); outb (0, 0xCF8); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}static int pci_conf2_read_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int *value){ unsigned long flags; if (device_fn & 0x80) return PCIBIOS_DEVICE_NOT_FOUND; save_flags(flags); cli(); outb (FUNC(device_fn), 0xCF8); outb (bus, 0xCFA); *value = inl (IOADDR(device_fn,where)); outb (0, 0xCF8); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}static int pci_conf2_write_config_byte (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char value){ unsigned long flags; save_flags(flags); cli(); outb (FUNC(device_fn), 0xCF8); outb (bus, 0xCFA); outb (value, IOADDR(device_fn,where)); outb (0, 0xCF8); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}static int pci_conf2_write_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short value){ unsigned long flags; save_flags(flags); cli(); outb (FUNC(device_fn), 0xCF8); outb (bus, 0xCFA); outw (value, IOADDR(device_fn,where)); outb (0, 0xCF8); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}static int pci_conf2_write_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int value){ unsigned long flags; save_flags(flags); cli(); outb (FUNC(device_fn), 0xCF8); outb (bus, 0xCFA); outl (value, IOADDR(device_fn,where)); outb (0, 0xCF8); restore_flags(flags); return PCIBIOS_SUCCESSFUL;}#undef IOADDR#undef FUNC/* * functiontable for type 2 */static struct pci_access pci_direct_conf2 = { pci_direct_find_device, pci_direct_find_class, pci_conf2_read_config_byte, pci_conf2_read_config_word, pci_conf2_read_config_dword, pci_conf2_write_config_byte, pci_conf2_write_config_word, pci_conf2_write_config_dword};static struct pci_access *check_direct_pci(void){ unsigned int tmp; unsigned long flags; save_flags(flags); cli(); /* * check if configuration type 1 works */ outb (0x01, 0xCFB); tmp = inl (0xCF8); outl (0x80000000, 0xCF8); if (inl (0xCF8) == 0x80000000) { outl (tmp, 0xCF8); restore_flags(flags); printk("pcibios_init: Using configuration type 1\n"); return &pci_direct_conf1; } outl (tmp, 0xCF8); /* * check if configuration type 2 works */ outb (0x00, 0xCFB); outb (0x00, 0xCF8); outb (0x00, 0xCFA); if (inb (0xCF8) == 0x00 && inb (0xCFB) == 0x00) { restore_flags(flags); printk("pcibios_init: Using configuration type 2\n"); return &pci_direct_conf2; } restore_flags(flags); printk("pcibios_init: Not supported chipset for direct PCI access !\n"); return NULL;}/* * access defined pcibios functions via * the function table */int pcibios_present(void){ return access_pci ? 1 : 0;}int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *device_fn){ if (access_pci && access_pci->find_class) return access_pci->find_class(class_code, index, bus, device_fn); return PCIBIOS_FUNC_NOT_SUPPORTED;}int pcibios_find_device (unsigned short vendor, unsigned short device_id, unsigned short index, unsigned char *bus, unsigned char *device_fn){ if (access_pci && access_pci->find_device) return access_pci->find_device(vendor, device_id, index, bus, device_fn); return PCIBIOS_FUNC_NOT_SUPPORTED;}int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char *value){ if (access_pci && access_pci->read_config_byte) return access_pci->read_config_byte(bus, device_fn, where, value); return PCIBIOS_FUNC_NOT_SUPPORTED;}int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short *value){ if (access_pci && access_pci->read_config_word) return access_pci->read_config_word(bus, device_fn, where, value); return PCIBIOS_FUNC_NOT_SUPPORTED;}int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int *value){ if (access_pci && access_pci->read_config_dword) return access_pci->read_config_dword(bus, device_fn, where, value); return PCIBIOS_FUNC_NOT_SUPPORTED;}int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char value){ if (access_pci && access_pci->write_config_byte) return access_pci->write_config_byte(bus, device_fn, where, value); return PCIBIOS_FUNC_NOT_SUPPORTED;}int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short value){ if (access_pci && access_pci->write_config_word) return access_pci->write_config_word(bus, device_fn, where, value); return PCIBIOS_FUNC_NOT_SUPPORTED; }int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int value){ if (access_pci && access_pci->write_config_dword) return access_pci->write_config_dword(bus, device_fn, where, value); return PCIBIOS_FUNC_NOT_SUPPORTED;}const char *pcibios_strerror (int error){ static char buf[80]; switch (error) { case PCIBIOS_SUCCESSFUL: return "SUCCESSFUL"; case PCIBIOS_FUNC_NOT_SUPPORTED: return "FUNC_NOT_SUPPORTED"; case PCIBIOS_BAD_VENDOR_ID: return "SUCCESSFUL"; case PCIBIOS_DEVICE_NOT_FOUND: return "DEVICE_NOT_FOUND"; case PCIBIOS_BAD_REGISTER_NUMBER: return "BAD_REGISTER_NUMBER"; case PCIBIOS_SET_FAILED: return "SET_FAILED"; case PCIBIOS_BUFFER_TOO_SMALL: return "BUFFER_TOO_SMALL"; default: sprintf (buf, "UNKNOWN RETURN 0x%x", error); return buf; }}unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end){ return mem_start;}#endifunsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end){#ifdef CONFIG_PCI union bios32 *check; unsigned char sum; int i, length; /* * Follow the standard procedure for locating the BIOS32 Service * directory by scanning the permissible address range from * 0xe0000 through 0xfffff for a valid BIOS32 structure. * */ for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) { if (check->fields.signature != BIOS32_SIGNATURE) continue; length = check->fields.length * 16; if (!length) continue; sum = 0; for (i = 0; i < length ; ++i) sum += check->chars[i]; if (sum != 0) continue; if (check->fields.revision != 0) { printk("pcibios_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n", check->fields.revision, check); continue; } printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check); if (!bios32_entry) { if (check->fields.entry >= 0x100000) { printk("pcibios_init: entry in high memory, trying direct PCI access\n"); access_pci = check_direct_pci(); } else { bios32_entry = check->fields.entry; printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); bios32_indirect.address = bios32_entry; } } } if (bios32_entry && check_pcibios()) access_pci = &pci_bios_access;#endif return memory_start;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -