Rev 16 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
#include <ll/i386/hw-instr.h>
#include <ll/i386/hw-data.h>
#include <ll/i386/hw-arch.h>
#include <ll/i386/hw-io.h>
#include <ll/i386/cons.h>
#include <ll/stdlib.h>
#include <drivers/llpci.h>
#include <drivers/pci.h>
#include <drivers/linuxpci.h>
#include <kernel/log.h>
static int ndev = 0;
static struct pci_des pci_devs[N_MAX_DEVS];
/* scan the bus to find all the connected devices */
int scan_bus(struct pci_des *p_des)
{
int ndev;
DWORD tmp;
BYTE hdr;
int j, ok;
BYTE bus, b;
WORD dev;
int present;
if (pcibios_present() == 0) return -1;
ndev = 0;
for (bus = 0; bus <= 1; bus++) {
for (dev = 0; dev <= 0xFF; dev++) {
present = 0;
if ((dev & 0x07) == 0) {
present = pcibios_read_config_byte(bus, dev, 0x0e, &hdr);
}
if (hdr & 0x80) {
present = 1;
}
if (present) {
ok = pcibios_read_config_dword(bus, dev, 0, &tmp);
if ( ok && (((tmp & 0xFFFF) != 0xFFFF) && ((tmp >> 16) != 0xFFFF))) {
p_des[ndev].bus = bus;
p_des[ndev].dev = dev;
for (j = 0; j <= 255; j++) {
pcibios_read_config_byte(bus, dev, j, &b);
p_des[ndev].mem[j] = b;
}
ndev++;
}
}
}
}
return ndev;
}
struct pci_regs *pci_device(WORD vendor, WORD device, WORD index, BYTE *bus, BYTE *dev)
{
int i, curr;
struct pci_regs *regs;
curr = 0;
for (i = 0; i < ndev; i++) {
regs = (struct pci_regs *)pci_devs[i].mem;
if ((regs->VendorId == vendor) && (regs->DeviceId == device)) {
if (curr == index) {
*dev = pci_devs[i].dev;
*bus = pci_devs[i].bus;
return regs;
}
++curr;
}
}
return NULL;
}
struct pci_regs *pci_class(DWORD class_code, WORD index, BYTE *bus, BYTE *dev)
{
int i, curr;
struct pci_regs *regs;
curr = 0;
for (i = 0; i < ndev; i++) {
regs = (struct pci_regs *)pci_devs[i].mem;
if ((regs->ClassCode << 8) == class_code) {
if (curr == index) {
*dev = pci_devs[i].dev;
*bus = pci_devs[i].bus;
return regs;
}
++curr;
}
}
return NULL;
}
int pcibios_find_device(WORD vendor, WORD device, WORD index, BYTE *bus, BYTE *dev)
{
if (pci_device(vendor, device, index, bus, dev) != NULL) {
return PCIBIOS_SUCCESSFUL;
} else {
return PCIBIOS_DEVICE_NOT_FOUND;
}
}
int pcibios_find_class(DWORD class_code, WORD index, BYTE *bus, BYTE *dev)
{
if (pci_class(class_code, index, bus, dev) != NULL) {
#ifdef DEBUG_PCI
printk(KERN_DEBUG "PCIBIOS_FIND_CLASS:"
"found at bus %d, dev %d\n", *bus, *dev);
#endif
return PCIBIOS_SUCCESSFUL;
} else {
return PCIBIOS_DEVICE_NOT_FOUND;
}
}
/* shows the detected devices */
void pci_show(void)
{
int i;
struct pci_regs *r;
printk(KERN_INFO "DevLib PCI support\n\n");
printk(KERN_INFO "PCI config type %d\n", pcibios_present());
printk(KERN_INFO "%d PCI devices found:\n\n", ndev);
for(i = 0; i < ndev; i++) {
r = (struct pci_regs *) pci_devs[i].mem;
printk(KERN_INFO "%d: bus %d dev %d\n",
i, pci_devs[i].bus, pci_devs[i].dev);
printk(KERN_INFO "Vendor: %s", pci_strvendor(r->VendorId));
printk(KERN_INFO "Class: %s\n", pci_strclass(r->ClassCode << 8));
}
}
/*Linux-->unsigned long pci_init(unsigned long mem_start, unsigned long mem_end) */
/* H-PCI --> void pci_init(void) */
/* (mem_start/mem_end have no sense) */
int pci_init(void)
{
if (pcibios_init() == -1) {
return -1;
}
ndev = scan_bus(pci_devs);
return 1;
}