Exemplo n.º 1
0
static void
proc_scan(struct pci_access *a)
{
  FILE *f;
  char buf[512];

  if (snprintf(buf, sizeof(buf), "%s/devices", pci_get_param(a, "proc.path")) == sizeof(buf))
    a->error("File name too long");
  f = fopen(buf, "r");
  if (!f)
    a->error("Cannot open %s", buf);
  while (fgets(buf, sizeof(buf)-1, f))
    {
      struct pci_dev *d = pci_alloc_dev(a);
      unsigned int dfn, vend, cnt, known;

#define F " " PCIADDR_T_FMT
      cnt = sscanf(buf, "%x %x %x" F F F F F F F F F F F F F F,
	     &dfn,
	     &vend,
	     &d->irq,
	     &d->base_addr[0],
	     &d->base_addr[1],
	     &d->base_addr[2],
	     &d->base_addr[3],
	     &d->base_addr[4],
	     &d->base_addr[5],
	     &d->rom_base_addr,
	     &d->size[0],
	     &d->size[1],
	     &d->size[2],
	     &d->size[3],
	     &d->size[4],
	     &d->size[5],
	     &d->rom_size);
#undef F
      if (cnt != 9 && cnt != 10 && cnt != 17)
	a->error("proc: parse error (read only %d items)", cnt);
      d->bus = dfn >> 8U;
      d->dev = PCI_SLOT(dfn & 0xff);
      d->func = PCI_FUNC(dfn & 0xff);
      d->vendor_id = vend >> 16U;
      d->device_id = vend & 0xffff;
      known = PCI_FILL_IDENT;
      if (!a->buscentric)
	{
	  known |= PCI_FILL_IRQ | PCI_FILL_BASES;
	  if (cnt >= 10)
	    known |= PCI_FILL_ROM_BASE;
	  if (cnt >= 17)
	    known |= PCI_FILL_SIZES;
	}
      d->known_fields = known;
      pci_link_dev(a, d);
    }
  fclose(f);
}
Exemplo n.º 2
0
void
pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
{
  int dev, multi, ht;
  struct pci_dev *t;

  a->debug("Scanning bus %02x for devices...\n", bus);
  if (busmap[bus])
    {
      a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus);
      return;
    }
  busmap[bus] = 1;
  t = pci_alloc_dev(a);
  t->bus = bus;
  for (dev=0; dev<32; dev++)
    {
      t->dev = dev;
      multi = 0;
      for (t->func=0; !t->func || multi && t->func<8; t->func++)
	{
	  u32 vd = pci_read_long(t, PCI_VENDOR_ID);
	  struct pci_dev *d;

	  if (!vd || vd == 0xffffffff)
	    continue;
	  ht = pci_read_byte(t, PCI_HEADER_TYPE);
	  if (!t->func)
	    multi = ht & 0x80;
	  ht &= 0x7f;
	  d = pci_alloc_dev(a);
	  d->bus = t->bus;
	  d->dev = t->dev;
	  d->func = t->func;
	  d->vendor_id = vd & 0xffff;
	  d->device_id = vd >> 16U;
	  d->known_fields = PCI_FILL_IDENT;
	  d->hdrtype = ht;
	  pci_link_dev(a, d);
	  switch (ht)
	    {
	    case PCI_HEADER_TYPE_NORMAL:
	      break;
	    case PCI_HEADER_TYPE_BRIDGE:
	    case PCI_HEADER_TYPE_CARDBUS:
	      pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
	      break;
	    default:
	      a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht);
	    }
	}
    }
  pci_free_dev(t);
}
Exemplo n.º 3
0
static void sysfs_scan(struct pci_access *a)
{
  char dirname[1024];
  DIR *dir;
  struct dirent *entry;
  int n;

  n = snprintf(dirname, sizeof(dirname), "%s/devices", sysfs_name(a));
  if (n < 0 || n >= (int) sizeof(dirname))
    a->error("Directory name too long");
  dir = opendir(dirname);
  if (!dir)
    a->error("Cannot open %s", dirname);
  while ((entry = readdir(dir)))
    {
      struct pci_dev *d;
      unsigned int dom, bus, dev, func;

      /* ".", ".." or a special non-device perhaps */
      if (entry->d_name[0] == '.')
	continue;

      d = pci_alloc_dev(a);
      if (sscanf(entry->d_name, "%x:%x:%x.%d", &dom, &bus, &dev, &func) < 4)
	a->error("sysfs_scan: Couldn't parse entry name %s", entry->d_name);
      d->domain = dom;
      d->bus = bus;
      d->dev = dev;
      d->func = func;
      if (!a->buscentric)
	{
	  sysfs_get_resources(d);
	  d->irq = sysfs_get_value(d, "irq");
	  d->known_fields = PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES;
#if 0
	  /*
	   *  We prefer reading these from the config registers, it's faster.
	   *  However, it would be possible and maybe even useful to hack the kernel
	   *  to believe that some device has a different ID. If you do it, just
	   *  enable this piece of code.  --mj
	   */
	  d->vendor_id = sysfs_get_value(d, "vendor");
	  d->device_id = sysfs_get_value(d, "device");
	  d->known_fields |= PCI_FILL_IDENT;
#endif
	}
      pci_link_dev(a, d);
    }
  closedir(dir);
}
Exemplo n.º 4
0
Arquivo: dump.c Projeto: OPSF/uClinux
static void
dump_init(struct pci_access *a)
{
  char *name = a->method_params[PCI_ACCESS_DUMP];
  FILE *f;
  char buf[256];
  struct pci_dev *dev = NULL;
  int len, bn, dn, fn, i, j;

  if (!a)
    a->error("dump: File name not given.");
  if (!(f = fopen(name, "r")))
    a->error("dump: Cannot open %s: %s", name, strerror(errno));
  while (fgets(buf, sizeof(buf)-1, f))
    {
      char *z = strchr(buf, '\n');
      if (!z)
	a->error("dump: line too long or unterminated");
      *z-- = 0;
      if (z >= buf && *z == '\r')
	*z-- = 0;
      len = z - buf + 1;
      if (len >= 8 && buf[2] == ':' && buf[5] == '.' && buf[7] == ' ' &&
	  sscanf(buf, "%x:%x.%d ", &bn, &dn, &fn) == 3)
	{
	  dev = pci_get_dev(a, bn, dn, fn);
	  dev->aux = pci_malloc(a, 256);
	  memset(dev->aux, 0xff, 256);
	  pci_link_dev(a, dev);
	}
      else if (!len)
	dev = NULL;
      else if (dev && len >= 51 && buf[2] == ':' && buf[3] == ' ' &&
	       sscanf(buf, "%x: ", &i) == 1)
	{
	  z = buf+3;
	  while (isspace(z[0]) && isxdigit(z[1]) && isxdigit(z[2]))
	    {
	      z++;
	      if (sscanf(z, "%x", &j) != 1 || i >= 256)
		a->error("dump: Malformed line");
	      ((byte *) dev->aux)[i++] = j;
	      z += 2;
	    }
	}
    }
}
Exemplo n.º 5
0
static void sysfs_scan(struct pci_access *a)
{
  char dirname[1024];
  DIR *dir;
  struct dirent *entry;
  int n;

  n = snprintf(dirname, sizeof(dirname), "%s/devices", sysfs_name(a));
  if (n < 0 || n >= (int) sizeof(dirname))
    a->error("Directory name too long");
  dir = opendir(dirname);
  if (!dir)
    a->error("Cannot open %s", dirname);
  while ((entry = readdir(dir)))
    {
      struct pci_dev *d;
      unsigned int dom, bus, dev, func;

      /* ".", ".." or a special non-device perhaps */
      if (entry->d_name[0] == '.')
	continue;

      d = pci_alloc_dev(a);
      if (sscanf(entry->d_name, "%x:%x:%x.%d", &dom, &bus, &dev, &func) < 4)
	a->error("sysfs_scan: Couldn't parse entry name %s", entry->d_name);
      d->domain = dom;
      d->bus = bus;
      d->dev = dev;
      d->func = func;
      if (!a->buscentric)
	{
	  sysfs_get_resources(d);
	  d->irq = sysfs_get_value(d, "irq");
	  /*
	   *  We could read these faster from the config registers, but we want to give
	   *  the kernel a chance to fix up ID's and especially classes of broken devices.
	   */
	  d->vendor_id = sysfs_get_value(d, "vendor");
	  d->device_id = sysfs_get_value(d, "device");
	  d->device_class = sysfs_get_value(d, "class") >> 8;
	  d->known_fields = PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES;
	}
      pci_link_dev(a, d);
    }
Exemplo n.º 6
0
static void
dump_init(struct pci_access *a)
{
  char *name = a->method_params[PCI_ACCESS_DUMP];
  FILE *f;
  char buf[256];
  struct pci_dev *dev = NULL;
  int len, mn, bn, dn, fn, i, j;

  if (!a)
    a->error("dump: File name not given.");
  if (!(f = fopen(name, "r")))
    a->error("dump: Cannot open %s: %s", name, strerror(errno));
  while (fgets(buf, sizeof(buf)-1, f))
    {
      char *z = strchr(buf, '\n');
      if (!z)
	a->error("dump: line too long or unterminated");
      *z-- = 0;
      if (z >= buf && *z == '\r')
	*z-- = 0;
      len = z - buf + 1;
      mn = 0;
      if ((len >= 8 && buf[2] == ':' && buf[5] == '.' && buf[7] == ' ' &&
	   sscanf(buf, "%x:%x.%d ", &bn, &dn, &fn) == 3) ||
	  (len >= 13 && buf[4] == ':' && buf[7] == ':' && buf[10] == '.' && buf[12] == ' ' &&
	   sscanf(buf, "%x:%x:%x.%d", &mn, &bn, &dn, &fn) == 4))
	{
	  dev = pci_get_dev(a, mn, bn, dn, fn);
	  dump_alloc_data(dev, 256);
	  pci_link_dev(a, dev);
	}
      else if (!len)
	dev = NULL;
      else if (dev &&
	       (len >= 51 && buf[2] == ':' && buf[3] == ' ' || len >= 52 && buf[3] == ':' && buf[4] == ' ') &&
	       sscanf(buf, "%x: ", &i) == 1)
	{
	  struct dump_data *dd = dev->aux;
	  z = strchr(buf, ' ');
	  while (isspace(z[0]) && isxdigit(z[1]) && isxdigit(z[2]))
	    {
	      z++;
	      if (sscanf(z, "%x", &j) != 1 || i >= 256)
		a->error("dump: Malformed line");
	      if (i >= 4096)
		break;
	      if (i > dd->allocated)	/* Need to re-allocate the buffer */
		{
		  dump_alloc_data(dev, 4096);
		  memcpy(((struct dump_data *) dev->aux)->data, dd->data, 256);
		  pci_mfree(dd);
		  dd = dev->aux;
		}
	      dd->data[i++] = j;
	      if (i > dd->len)
		dd->len = i;
	      z += 2;
	    }
	}
    }
}
Exemplo n.º 7
0
static void
dump_init(struct pci_access *a)
{
  char *name = pci_get_param(a, "dump.name");
  FILE *f;
  char buf[256];
  struct pci_dev *dev = NULL;
  int len, mn, bn, dn, fn, i, j;

  if (!name)
    a->error("dump: File name not given.");
  if (!(f = fopen(name, "r")))
    a->error("dump: Cannot open %s: %s", name, strerror(errno));
  while (fgets(buf, sizeof(buf)-1, f))
    {
      char *z = strchr(buf, '\n');
      if (!z)
	{
	  fclose(f);
	  a->error("dump: line too long or unterminated");
	}
      *z-- = 0;
      if (z >= buf && *z == '\r')
	*z-- = 0;
      len = z - buf + 1;
      mn = 0;
      if ((dump_validate(buf, "##:##.# ") && sscanf(buf, "%x:%x.%d", &bn, &dn, &fn) == 3) ||
	  (dump_validate(buf, "####:##:##.# ") && sscanf(buf, "%x:%x:%x.%d", &mn, &bn, &dn, &fn) == 4))
	{
	  dev = pci_get_dev(a, mn, bn, dn, fn);
	  dump_alloc_data(dev, 256);
	  pci_link_dev(a, dev);
	}
      else if (!len)
	dev = NULL;
      else if (dev &&
	       (dump_validate(buf, "##: ") || dump_validate(buf, "###: ")) &&
	       sscanf(buf, "%x: ", &i) == 1)
	{
	  struct dump_data *dd = dev->aux;
	  z = strchr(buf, ' ') + 1;
	  while (isxdigit(z[0]) && isxdigit(z[1]) && (!z[2] || z[2] == ' ') &&
		 sscanf(z, "%x", &j) == 1 && j < 256)
	    {
	      if (i >= 4096)
		{
		  fclose(f);
		  a->error("dump: At most 4096 bytes of config space are supported");
		}
	      if (i >= dd->allocated)	/* Need to re-allocate the buffer */
		{
		  dump_alloc_data(dev, 4096);
		  memcpy(((struct dump_data *) dev->aux)->data, dd->data, 256);
		  pci_mfree(dd);
		  dd = dev->aux;
		}
	      dd->data[i++] = j;
	      if (i > dd->len)
		dd->len = i;
	      z += 2;
	      if (*z)
		z++;
	    }
	  if (*z)
	    {
	      fclose(f);
	      a->error("dump: Malformed line");
	    }
	}
    }
  fclose(f);
}