#include <i86.h>
#include "pci.h"

//+-------------------------------------------------------------------+
//| pci_bios_available                                                |
//| (check if BIOS is available)                                      |
//+-------------------------------------------------------------------+
int pci_bios_available(void)
{
 int ret;
 union REGS pregs;

 pregs.h.ah=PCI_FUNCTION_ID;  // BIOS: function ID for PCI calls
 pregs.h.al=PCI_BIOS_PRESENT; // function: PCI BIOS present?
 ret=make_pci_interrupt(&pregs);
 if((ret!=0) || (((pregs.x.edx)&0x0000ffffl) != 0x4350)) return(-1);
 return(0);
}

//+-------------------------------------------------------------------+
//| pci_dev_find                                                      |
//| (check if PCI device is available)                                |
//+-------------------------------------------------------------------+
int pci_dev_find(int dev_index, unsigned int *stat, unsigned long vendor_id, unsigned long device_id)
{
 int   ret;
 union REGS pregs;

 pregs.x.edx = vendor_id;                // Vendor ID
 pregs.x.ecx = device_id;                // Device ID
 pregs.x.esi = dev_index;                 // Index
 pregs.h.ah = PCI_FUNCTION_ID;
 pregs.h.al = PCI_FIND_DEVICE;
 ret=make_pci_interrupt(&pregs);
 if(ret!=0) return(-1);
 *stat=pregs.x.ebx;
 return (0);
}

//+-------------------------------------------------------------------+
//| pci_class_code_find                                               |
//| (FIND PCI CLASS CODE)                                             |
//+-------------------------------------------------------------------+
int pci_class_code_find(int dev_index, unsigned int *stat, unsigned long class_code)
{
 int   ret;
 union REGS pregs;

 pregs.x.ecx = class_code;                // Class code
 pregs.x.esi = dev_index;                 // Index
 pregs.h.ah = PCI_FUNCTION_ID;
 pregs.h.al = PCI_FIND_CLASS_CODE;
 ret=make_pci_interrupt(&pregs);
 if(ret!=0) return(-1);
 *stat=pregs.x.ebx;
 return (0);
}
//+-------------------------------------------------------------------+
//| PCIReadConfRegByte                                                |
//| (Read the word from the configuration register                    |
//+-------------------------------------------------------------------+
int PCIReadConfRegByte(int pci_dev_and_funct,int pci_bus, unsigned int config_reg, unsigned char *phy_address_ptr)
{
 int ret;
 union REGS pregs;

 pregs.h.bl = pci_dev_and_funct;
 pregs.h.bh = pci_bus;
 pregs.h.ah = PCI_FUNCTION_ID;
 pregs.h.al = PCI_READ_CONFIG_BYTE;
 pregs.x.edi = config_reg;
 ret=make_pci_interrupt(&pregs);
 *phy_address_ptr=pregs.x.ecx;
 return(ret);
}

//+-------------------------------------------------------------------+
//| PCIReadConfRegWord                                                |
//| (Read the word from the configuration register                    |
//+-------------------------------------------------------------------+
int PCIReadConfRegWord(int pci_dev_and_funct,int pci_bus, unsigned int config_reg, unsigned short *phy_address_ptr)
{
 int ret;
 union REGS pregs;

 pregs.h.bl = pci_dev_and_funct;
 pregs.h.bh = pci_bus;
 pregs.h.ah = PCI_FUNCTION_ID;
 pregs.h.al = PCI_READ_CONFIG_WORD;
 pregs.x.edi = config_reg;
 ret=make_pci_interrupt(&pregs);
 *phy_address_ptr=pregs.x.ecx;
 return(ret);
}

//+-------------------------------------------------------------------+
//| PCIReadConfRegDword                                               |
//| (Read the word from the configuration register                    |
//+-------------------------------------------------------------------+
int PCIReadConfRegDword(int pci_dev_and_funct,int pci_bus, unsigned int config_reg, unsigned long *phy_address_ptr)
{
 int ret;
 union REGS pregs;

 pregs.h.bl = pci_dev_and_funct;
 pregs.h.bh = pci_bus;
 pregs.h.ah = PCI_FUNCTION_ID;
 pregs.h.al = PCI_READ_CONFIG_DWORD;
 pregs.x.edi = config_reg;
 ret=make_pci_interrupt(&pregs);
 *phy_address_ptr=pregs.x.ecx;
 return(ret);
}

int PCIWriteConfRegByte(int pci_dev_and_funct,int pci_bus, unsigned int config_reg, unsigned char param)
{
 int ret;
 union REGS pregs;

 pregs.h.bl = pci_dev_and_funct;
 pregs.h.bh = pci_bus;
 pregs.h.ah = PCI_FUNCTION_ID;
 pregs.h.al = PCI_WRITE_CONFIG_BYTE;
 pregs.x.edi = config_reg;
 pregs.x.ecx = param;
 ret=make_pci_interrupt(&pregs);
 return(ret);
}

//+-------------------------------------------------------------------+
//| PCIWriteConfRegWord                                              |
//| (Read the word from the configuration register                    |
//+-------------------------------------------------------------------+
int PCIWriteConfRegWord(int pci_dev_and_funct,int pci_bus, unsigned int config_reg, unsigned short param)
{
 int ret;
 union REGS pregs;

 pregs.h.bl = pci_dev_and_funct;
 pregs.h.bh = pci_bus;
 pregs.h.ah = PCI_FUNCTION_ID;
 pregs.h.al = PCI_WRITE_CONFIG_WORD;
 pregs.x.edi = config_reg;
 pregs.x.ecx = param;
 ret=make_pci_interrupt(&pregs);
 return(ret);
}

//+-------------------------------------------------------------------+
//| PCIWriteConfRegDword                                              |
//| (Read the word from the configuration register                    |
//+-------------------------------------------------------------------+
int PCIWriteConfRegDword(int pci_dev_and_funct,int pci_bus, unsigned int config_reg, unsigned long param)
{
 int ret;
 union REGS pregs;

 pregs.h.bl = pci_dev_and_funct;
 pregs.h.bh = pci_bus;
 pregs.h.ah = PCI_FUNCTION_ID;
 pregs.h.al = PCI_WRITE_CONFIG_DWORD;
 pregs.x.edi = config_reg;
 pregs.x.ecx = param;
 ret=make_pci_interrupt(&pregs);
 return(ret);
}

//+-------------------------------------------------------------------+
//| make_pci_interrupt                                                |
//| (call pci interrupt)                                              |
//+-------------------------------------------------------------------+
int make_pci_interrupt(union REGS *pregs)
{
 int386(PCI_INT, pregs, pregs);
 if((pregs->x.cflag) || (pregs->h.ah)) return(-1);
 return(0);
}