Subversion Repositories shark

Rev

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