Subversion Repositories shark

Rev

Rev 2 | 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 <drivers/llpci.h>

int (*pcibios_read_config_byte)(BYTE bus, BYTE dev, BYTE where, BYTE *val);
int (*pcibios_read_config_word)(BYTE bus, BYTE dev, BYTE where, WORD *val);
int (*pcibios_read_config_dword)(BYTE bus, BYTE dev, BYTE where, DWORD *val);
int (*pcibios_write_config_byte)(BYTE bus, BYTE dev, BYTE where, BYTE val);
int (*pcibios_write_config_word)(BYTE bus, BYTE dev, BYTE where, WORD val);
int (*pcibios_write_config_dword)(BYTE bus, BYTE dev, BYTE where, DWORD val);

static int PCItype = 0;

/* LowLevel Functions                                                   */
int pci_conf1_read_config_dword(BYTE bus, BYTE dev, BYTE where, DWORD *val)
{
   if (where & 3)
        return -1;
   outpd(0x0CF8, 0x80000000 | (bus <<16) | (dev << 8) | (where & ~3));
   *val = inpd(0x0CFC);
   return 1;
}

int pci_conf2_read_config_dword(BYTE bus, BYTE dev, BYTE where, DWORD *val)
{
    if (dev & 0x80)
        return -1;
    outpw(0xCF8, (((dev &  7) << 1) | 0xf0));
    outpw(0xCFA, bus);
    *val = inpd((0xC000 | ((dev & 0x78) << 5)) + where);
    outpw(0xCF8,0);
    return 1;
}

int pci_conf1_read_config_byte(BYTE bus, BYTE dev, BYTE where, BYTE *val)
{
   outpd(0x0CF8, 0x80000000 | (bus <<16) | (dev << 8) | (where & ~3));
   *val = inp(0x0CFC + (where & 3));
   return 1;
}

int pci_conf2_read_config_byte(BYTE bus, BYTE dev, BYTE where, BYTE *val)
{
    if (dev & 0x80)
        return -1;
    outpw(0xCF8, (((dev &  7) << 1) | 0xf0));
    outpw(0xCFA, bus);
    *val = inp((0xC000 | ((dev & 0x78) << 5)) + where);
    outpw(0xCF8,0);
    return 1;
}
int pci_conf1_read_config_word(BYTE bus, BYTE dev, BYTE where, WORD *val)
{
    if (where & 1)
        return -1;
    outpd(0x0CF8, 0x80000000 | (bus <<16) | (dev << 8) | (where & ~3));
    *val = inpw(0x0CFC + (where & 2));
    return 1;
}

int pci_conf2_read_config_word(BYTE bus, BYTE dev, BYTE where, WORD *val)
{
    if (dev & 0x80)
        return -1;
    outpw(0xCF8, (((dev &  7) << 1) | 0xf0));
    outpw(0xCFA, bus);
    *val = inpw((0xC000 | ((dev & 0x78) << 5)) + where);
/*    *val = inpw(0xC000 | ((dev & 0x78) << 5) + where); */
    outpw(0xCF8,0);
    return 1;
}


int pci_conf1_write_config_dword(BYTE bus, BYTE dev, BYTE where, DWORD val)
{
    if (where & 3)
        return -1;
   outpd(0x0CF8, 0x80000000 | (bus <<16) | (dev << 8) | (where & ~3));
   outpd(0x0CFC, val);
   return 1;
}

int pci_conf2_write_config_dword(BYTE bus, BYTE dev, BYTE where, DWORD val)
{
    if (dev & 0x80)
        return -1;
    outpw(0xCF8, (((dev &  7) << 1) | 0xf0));
    outpw(0xCFA, bus);
    outpd((0xC000 | ((dev & 0x78) << 5)) + where, val);
    outpw(0xCF8,0);
    return 1;
}

int pci_conf1_write_config_byte(BYTE bus, BYTE dev, BYTE where, BYTE val)
{
   outpd(0x0CF8, 0x80000000 | (bus <<16) | (dev << 8) | (where & ~3));
   outp(0x0CFC + (where & 3), val);
   return 1;
}

int pci_conf2_write_config_byte(BYTE bus, BYTE dev, BYTE where, BYTE val)
{
    if (dev & 0x80)
        return -1;
    outpw(0xCF8, (((dev &  7) << 1) | 0xf0));
    outpw(0xCFA, bus);
    outp((0xC000 | ((dev & 0x78) << 5)) + where, val);
    outpw(0xCF8,0);
    return 1;
}
int pci_conf1_write_config_word(BYTE bus, BYTE dev, BYTE where, WORD val)
{
    if (where & 1)
        return -1;
    outpd(0x0CF8, 0x80000000 | (bus <<16) | (dev << 8) | (where & ~3));
    outpw(0x0CFC + (where & 2), val);
    return 1;
}

int pci_conf2_write_config_word(BYTE bus, BYTE dev, BYTE where, WORD val)
{
    if (dev & 0x80)
        return -1;
    outpw(0xCF8, (((dev &  7) << 1) | 0xf0));
    outpw(0xCFA, bus);
    outpw((0xC000 | ((dev & 0x78) << 5)) + where, val);
    outpw(0xCF8,0);
    return 1;
}



int pci_check_direct()
{
    int PCItype;
    DWORD tmp;

    PCItype = 0;
    outp(0xCFB, 0x01);
    tmp = inpd(0xCF8);
    outpd(0xCF8, 0x80000000);
    if (inpd(0xCF8) == 0x80000000) {
        outpd(0xCF8, tmp);
        pcibios_read_config_dword = pci_conf1_read_config_dword;
        pcibios_read_config_word = pci_conf1_read_config_word;
        pcibios_read_config_byte = pci_conf1_read_config_byte;

        pcibios_write_config_dword = pci_conf1_write_config_dword;
        pcibios_write_config_word = pci_conf1_write_config_word;
        pcibios_write_config_byte = pci_conf1_write_config_byte;
        PCItype = 1;
    }
    outpw(0x0CF8,tmp);

    outp(0xCFB, 0);
    outp(0xCF8, 0);
    outp(0x0CFA,0);
    if ((inp(0x0CF8) == 0) && (inp(0x0CFA) == 0)) {
            pcibios_read_config_dword = pci_conf2_read_config_dword;
            pcibios_read_config_word = pci_conf2_read_config_word;
            pcibios_read_config_byte = pci_conf2_read_config_byte;

            pcibios_write_config_dword = pci_conf2_write_config_dword;
            pcibios_write_config_word = pci_conf2_write_config_word;
            pcibios_write_config_byte = pci_conf2_write_config_byte;
            PCItype = 2;
    }
    return PCItype;
}

/*__________________________________________________________________________*/
/*__________________________________________________________________________*/
int pcibios_present(void)
{
        return (PCItype != 0);
}

int pcibios_init(void)
{
    if (ll_arch.x86.cpu < 3) {
        return -1;              /* CPU < 386 --> No PCI */
    }
    PCItype = pci_check_direct();
    if (PCItype == 0) {
        return -1;
    }
    return 1;
}