
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>

#include "pci.h"

static int IsPCIPresent(void)
{
  union REGS r;

  r.x.ax = 0xb101;
  int86 (0x1a, &r, &r);
  return (r.h.ah == 0);
}

static unsigned int FindPCIDevice(unsigned int deviceID)
{
  union REGS r;

  r.x.ax = 0xb102;
  r.x.cx = deviceID;
  r.x.dx = PCI_VENDER_ID;
  r.x.si = 0;
  int86 (0x1a, &r, &r);
  if (r.h.ah == 0)
    return r.x.bx;
  else
    return 0;
}

static unsigned int FindPCIClassCode(unsigned int classCode)
{
  union REGS r;

  r.x.ax = 0xb103;
  r.x.cx = classCode;
  r.x.dx = PCI_VENDER_ID;
  r.x.si = 0;
  int86 (0x1a, &r, &r);
  if (r.h.ah == 0)
    return r.x.bx;
  else
    return 0;
}

static unsigned char ReadPCIConfigByte (unsigned int pciaddr, int index)
{
  union REGS r;

  r.x.ax = 0xb108;
  r.x.bx = pciaddr;
  r.x.di = index;
  int86 (0x1a, &r, &r);
  if (r.h.ah == 0)
    return r.h.cl;
  else
    return 0;
}

static unsigned int ReadPCIConfigWord (unsigned int pciaddr, int index)
{
  union REGS r;

  r.x.ax = 0xb109;
  r.x.bx = pciaddr;
  r.x.di = index;
  int86 (0x1a, &r, &r);
  if (r.h.ah == 0)
    return r.x.cx;
  else
    return 0;
}

static unsigned long ReadPCIConfigDWord (unsigned int pciaddr, int index)
{
  union REGS r;

  r.x.ax = 0xb10a;
  r.x.bx = pciaddr;
  r.x.di = index;
  int86 (0x1a, &r, &r);
  if (r.h.ah == 0)
    return r.x.cx;
  else
    return 0;
}

int GetPCICardInfo (unsigned int deviceID, unsigned int *addr)
{
  unsigned int pciaddr, index;

  if (!addr)
    return 1;

  if (!IsPCIPresent ())
    return 2;

  pciaddr = FindPCIDevice (deviceID);

  if (pciaddr == 0)
    return 3;

  for (index = 0x18; index <= 0x24; index += 4) {
    *addr = ReadPCIConfigDWord (pciaddr, index) & 0xfffe;
    if (*addr != 0)
      break;
  }
  return 0;
}
