Пример #1
0
static int enable_flash_rdc_r8610(struct pci_dev *dev, const char *name)
{
	uint8_t tmp;

	/* enable ROMCS for writes */
	tmp = pci_read_byte(dev, 0x43);
	tmp |= 0x80;
	pci_write_byte(dev, 0x43, tmp);

	/* read the bootstrapping register */
	tmp = pci_read_byte(dev, 0x40) & 0x3;
	switch (tmp) {
	case 3:
		internal_buses_supported = BUS_FWH;
		break;
	case 2:
		internal_buses_supported = BUS_LPC;
		break;
	default:
		internal_buses_supported = BUS_PARALLEL;
		break;
	}

	return 0;
}
static uint8_t pci_find_cap_offset(struct pci_dev *pci_dev, uint8_t cap)
{
    int id;
    int max_cap = 48;
    int pos = PCI_CAPABILITY_LIST;
    int status;

    status = pci_read_byte(pci_dev, PCI_STATUS);
    if ((status & PCI_STATUS_CAP_LIST) == 0)
        return 0;

    while (max_cap--) {
        pos = pci_read_byte(pci_dev, pos);
        if (pos < 0x40)
            break;

        pos &= ~3;
        id = pci_read_byte(pci_dev, pos + PCI_CAP_LIST_ID);

        if (id == 0xff)
            break;
        if (id == cap)
            return pos;

        pos += PCI_CAP_LIST_NEXT;
    }
    return 0;
}
Пример #3
0
int try_ich(struct pci_access *pci,
            uint16_t reg_gpiobase, uint16_t reg_gc,
            const char *desc, int *fatal) {
  MSG("Checking for a %s system", desc);

  struct pci_dev *d31f0 = pci_find_dev(pci, 0, 31, 0);
  uint32_t gpiobase = pci_read_long(d31f0, reg_gpiobase);
  uint8_t gc = pci_read_byte(d31f0, reg_gc);
  MSG("GPIOBASE=%08x, GC=%02x", gpiobase, gc);

  if(gpiobase == 0xffffffff) {
    *fatal = 1;
    ERR("Cannot read GPIOBASE, are you running me as root?");
  } else if(gpiobase == 0) {
    ERR("GPIOBASE not implemented at %04x", reg_gpiobase);
  } else if(!(gpiobase & 1)) {
    *fatal = 1;
    ERR("GPIOBASE is not an I/O BAR");
  }

  if(!(gpiobase & 0xfffc)) {
    const uint32_t DEFAULT_GPIOBASE = 0x0480;

    MSG("GPIOBASE is not configured, setting to %08x and hoping this works", DEFAULT_GPIOBASE);
    pci_write_long(d31f0, reg_gpiobase, DEFAULT_GPIOBASE);
    gpiobase = pci_read_long(d31f0, reg_gpiobase);
    if((gpiobase & 0xfffc) != DEFAULT_GPIOBASE) {
      ERR("Cannot set GPIOBASE");
    }
  }

  MSG("GPIO decoding is %s", (gc & REG_ICHx_GC_EN) ? "enabled" : "disabled");
  MSG("GPIO lockdown is %s", (gc & REG_ICHx_GC_GLE) ? "enabled" : "disabled");

  if(!(gc & REG_ICHx_GC_EN)) {
    MSG("Enabling GPIO decoding");
    pci_write_byte(d31f0, reg_gc, gc | REG_ICHx_GC_EN);
    gc = pci_read_byte(d31f0, reg_gc);
    if(!(gc & REG_ICHx_GC_EN)) {
      ERR("Cannot enable GPIO decoding");
    }
  }

  gpiobase &= 0xfffc;
  if(ioperm(gpiobase, 128, 1) == -1) {
    ERR("Cannot access I/O ports %04x:%04x", gpiobase, gpiobase + 128);
  }

  for(int n = 1; n < 3; n++) {
    MSG("USE_SEL%d=%08x", n, inl(gpiobase + ichx_regs[GPIO_USE_SEL][n]));
    MSG("IO_SEL%d=%08x", n, inl(gpiobase + ichx_regs[GPIO_IO_SEL][n]));
    MSG("LVL%d=%08x", n, inl(gpiobase + ichx_regs[GPIO_LVL][n]));
  }

  return 0;
}
Пример #4
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);
}
Пример #5
0
int print_ambs(struct pci_dev *dev, struct pci_access *pacc)
{
	struct pci_dev *dev16;
	int branch, channel, amb;
	int max_branch, max_channel, max_amb;
	volatile void *ambconfig;
	uint64_t ambconfig_phys;

	printf("\n============= AMBs ============\n\n");

	switch (dev->device_id) {
	case PCI_DEVICE_ID_INTEL_I5000P:
	case PCI_DEVICE_ID_INTEL_I5000X:
	case PCI_DEVICE_ID_INTEL_I5000Z:

		max_branch = 2;

		if (!(dev16 = pci_get_dev(pacc, 0, 0, 0x10, 0))) {
			perror("Error: no device 0:16.0\n");
			return 1;
		}

		ambconfig_phys = ((uint64_t)pci_read_long(dev16, 0x4c) << 32) |
			pci_read_long(dev16, 0x48);

		max_channel = pci_read_byte(dev16, 0x56)/max_branch;
		max_amb = pci_read_byte(dev16, 0x57);
		pci_free_dev(dev16);
		break;

	default:
		fprintf(stderr, "Error: Dumping AMBs on this MCH is not (yet) supported.\n");
		return 1;
	}

	if (!(ambconfig = map_physical(ambconfig_phys, AMB_CONFIG_SPACE_SIZE))) {
		fprintf(stderr, "Error mapping AMB config space\n");
		return 1;
	}

	for(branch = 0; branch < max_branch; branch++) {
		for(channel = 0; channel < max_channel; channel++) {
			for(amb = 0; amb < max_amb; amb++) {
				dump_amb(ambconfig, branch, channel, amb);
			}
		}
	}
	unmap_physical((void *)ambconfig, AMB_CONFIG_SPACE_SIZE);
	return 0;
}
Пример #6
0
static void
exec_op(struct op *op, struct pci_dev *dev)
{
  char *mm[] = { NULL, "%02x", "%04x", NULL, "%08x" };
  char *m = mm[op->width];
  unsigned int x;
  int i, addr;

  if (verbose)
    printf("%02x:%02x.%x:%02x", dev->bus, dev->dev, dev->func, op->addr);
  addr = op->addr;
  if (op->num_values >= 0)
    for(i=0; i<op->num_values; i++)
      {
	if (verbose)
	  {
	    putchar(' ');
	    printf(m, op->values[i]);
	  }
	if (demo_mode)
	  continue;
	switch (op->width)
	  {
	  case 1:
	    pci_write_byte(dev, addr, op->values[i]);
	    break;
	  case 2:
	    pci_write_word(dev, addr, op->values[i]);
	    break;
	  default:
	    pci_write_long(dev, addr, op->values[i]);
	    break;
	  }
	addr += op->width;
      }
  else
    {
      if (verbose)
	printf(" = ");
      if (!demo_mode)
	{
	  switch (op->width)
	    {
	    case 1:
	      x = pci_read_byte(dev, addr);
	      break;
	    case 2:
	      x = pci_read_word(dev, addr);
	      break;
	    default:
	      x = pci_read_long(dev, addr);
	      break;
	    }
	  printf(m, x);
	}
      else
	putchar('?');
    }
  putchar('\n');
}
Пример #7
0
static int board_via_epia_m(const char *name)
{
	struct pci_dev *dev;
	unsigned int base;
	uint8_t val;

	dev = pci_dev_find(0x1106, 0x3177);	/* VT8235 ISA bridge */
	if (!dev) {
		fprintf(stderr, "\nERROR: VT8235 ISA Bridge not found.\n");
		return -1;
	}

	/* GPIO12-15 -> output */
	val = pci_read_byte(dev, 0xE4);
	val |= 0x10;
	pci_write_byte(dev, 0xE4, val);

	/* Get Power Management IO address. */
	base = pci_read_word(dev, 0x88) & 0xFF80;

	/* enable GPIO15 which is connected to write protect. */
	val = inb(base + 0x4D);
	val |= 0x80;
	outb(val, base + 0x4D);

	return 0;
}
Пример #8
0
static int board_asus_a7v8x_mx(const char *name)
{
	struct pci_dev *dev;
	uint8_t val;

	dev = pci_dev_find(0x1106, 0x3177);	/* VT8235 ISA bridge */
	if (!dev)
		dev = pci_dev_find(0x1106, 0x3227);	/* VT8237 ISA bridge */
	if (!dev) {
		fprintf(stderr, "\nERROR: VT823x ISA bridge not found.\n");
		return -1;
	}

	/* This bit is marked reserved actually */
	val = pci_read_byte(dev, 0x59);
	val &= 0x7F;
	pci_write_byte(dev, 0x59, val);

	/* Raise ROM MEMW# line on Winbond w83697 SuperIO */
	w836xx_ext_enter();

	if (!(wbsio_read(0x24) & 0x02))	/* flash rom enabled? */
		wbsio_mask(0x24, 0x08, 0x08);	/* enable MEMW# */

	w836xx_ext_leave();

	return 0;
}
Пример #9
0
static int enable_flash_sis85c496(struct pci_dev *dev, const char *name)
{
	uint8_t tmp;

	tmp = pci_read_byte(dev, 0xd0);
	tmp |= 0xf8;
	rpci_write_byte(dev, 0xd0, tmp);

	return 0;
}
Пример #10
0
static int enable_flash_ali_m1533(struct pci_dev *dev, const char *name)
{
	uint8_t tmp;

	/*
	 * ROM Write enable, 0xFFFC0000-0xFFFDFFFF and
	 * 0xFFFE0000-0xFFFFFFFF ROM select enable.
	 */
	tmp = pci_read_byte(dev, 0x47);
	tmp |= 0x46;
	rpci_write_byte(dev, 0x47, tmp);

	return 0;
}
Пример #11
0
bool pci_device_get_next(struct pci_address* addr, int16_t class_id, int16_t sub_class, pci_device* result)
{
	uint32_t* res_device_ptr = (uint32_t*)(result);

	for(; addr->bus < MAX_PCI_BUS_NR; addr->bus++)
	{
		for(; addr->device < MAX_PCI_BUS_DEV_NR; addr->device++)
		{
			for(; addr->func < MAX_FUNC_PER_PCI_BUS_DEV; addr->func++)
			{
                if(pci_read_word(addr, PCI_VENDOR_ID_REG_OFFSET) == PCI_VENDOR_ID_NO_DEVICE)
                    continue;

                if(class_id != -1 && pci_read_byte(addr, PCI_DEV_CLASS_REG_OFFSET) != class_id)
                    continue;

                if(sub_class != -1 && pci_read_byte(addr, PCI_DEV_SUB_CLASS_REG_OFFSET) != sub_class)
                    continue;

				// Device found, read in the entire configuration space
				for (uint8_t i = 0; i < 64; i++)
					res_device_ptr[i] = pci_read_dword(addr, (i << 2));

				return true;
			}

			// Ensure we scan all functions on the next device
			addr->func = 0;
		}

		// Ensure we scan all devices on the next bus
		addr->device = 0;
	}

	return false; // No more devices

}
Пример #12
0
static void
pci_scan_trad_caps(struct pci_dev *d)
{
  word status = pci_read_word(d, PCI_STATUS);
  byte been_there[256];
  int where;

  if (!(status & PCI_STATUS_CAP_LIST))
    return;

  memset(been_there, 0, 256);
  where = pci_read_byte(d, PCI_CAPABILITY_LIST) & ~3;
  while (where)
    {
      byte id = pci_read_byte(d, where + PCI_CAP_LIST_ID);
      byte next = pci_read_byte(d, where + PCI_CAP_LIST_NEXT) & ~3;
      if (been_there[where]++)
	break;
      if (id == 0xff)
	break;
      pci_add_cap(d, where, id, PCI_CAP_NORMAL);
      where = next;
    }
}
Пример #13
0
static void process_uhci(struct pci_address* addr, pci_device* dev)
{
    uint8_t revision = pci_read_byte(addr, 0x60);
    if(revision != UHCI_REV_1_0) {
        // This host controller indicates that it supports a version
        // of the USB specification that is *not* 1.0. Ignore it
        KWARN("Detected UHCI with unsupported revision, ignoring...");
        return;
    }

    // Bit 0 indicates whether it's memory mapped or port I/O
    bool memory_mapped = (dev->base_addr4 & 0x1) == 1;

    // Beore we initialize the card, make sure the cards I/O is disabled
    uint16_t cmd = pci_read_word(addr, PCI_COMMAND_REG_OFFSET);
    cmd = (cmd & ~0x1);
    pci_write_word(addr, PCI_COMMAND_REG_OFFSET, cmd);

    // THe USB book I'm reading is telling me to null out the
    // capabilities register as well as the two registers marked as "reserved"
    // Not sure why, TODO: Investigate! :-S
    pci_write_dword(addr, PCI_CAPS_OFF_REG_OFFSET, 0x00000000);
    pci_write_dword(addr, 0x38, 0x00000000);

    // Set the IRQ
    pci_write_byte(addr, PCI_IRQ_REG_OFFSET, UHCI_IRQ);

    // Now try to get the size of the address space
    //uint32_t size = pci_device_get_memory_size(addr, PCI_BASE_ADDR4_REG_OFFSET);
    // Enable bus mastering and I/O access 
    pci_write_word(addr, 0x04, memory_mapped ? 0x06 : 0x05);

    // Disable legacy support and clear current status
    pci_write_word(addr, PCI_LEG_SUP_REG_OFFSET,
            PCI_LEGACY_PTS | // Clear Sequence ended bit
            PCI_LEGACY_TBY64W | PCI_LEGACY_TBY64R | PCI_LEGACY_TBY60W | PCI_LEGACY_TBY60R); // Clear status

    // The device is now ready for the UHCI driver to take over
    uhci_init(dev->base_addr4, dev, addr, UHCI_IRQ);
}
Пример #14
0
uint16_t detect_ec(void)
{
    uint16_t ec_port;
    struct pci_dev *dev;

    dev = pci_dev_find(0x1002, 0x439d);

    if (!dev) {
        return 0;
    }

    /* is EC disabled ? */
    if (!(pci_read_byte(dev, 0x40) & (1 << 7)))
        return 0;

    ec_port = pci_read_word(dev, 0xa4);

    if (!(ec_port & 0x1))
        return 0;

    ec_port &= ~0x1;

    return ec_port;
}
Пример #15
0
int print_bioscntl(struct pci_dev *sb)
{
	int i, size = 0;
	unsigned char bios_cntl = 0xff;
	const io_register_t *bios_cntl_register = NULL;

	printf("\n============= SPI / BIOS CNTL =============\n\n");

	switch (sb->device_id) {
	case PCI_DEVICE_ID_INTEL_ICH6:
		bios_cntl = pci_read_byte(sb, 0xdc);
		bios_cntl_register = ich6_bios_cntl_registers;
		size = ARRAY_SIZE(ich6_bios_cntl_registers);
		break;
	case PCI_DEVICE_ID_INTEL_ICH7:
	case PCI_DEVICE_ID_INTEL_ICH7M:
	case PCI_DEVICE_ID_INTEL_ICH7DH:
	case PCI_DEVICE_ID_INTEL_ICH7MDH:
	case PCI_DEVICE_ID_INTEL_ICH8:
	case PCI_DEVICE_ID_INTEL_ICH8M:
	case PCI_DEVICE_ID_INTEL_ICH8ME:
	case PCI_DEVICE_ID_INTEL_ICH9DH:
	case PCI_DEVICE_ID_INTEL_ICH9DO:
	case PCI_DEVICE_ID_INTEL_ICH9R:
	case PCI_DEVICE_ID_INTEL_ICH9:
	case PCI_DEVICE_ID_INTEL_ICH9M:
	case PCI_DEVICE_ID_INTEL_ICH9ME:
	case PCI_DEVICE_ID_INTEL_ICH10:
	case PCI_DEVICE_ID_INTEL_ICH10R:
	case PCI_DEVICE_ID_INTEL_NM10:
		bios_cntl = pci_read_byte(sb, 0xdc);
		bios_cntl_register = ich7_bios_cntl_registers;
		size = ARRAY_SIZE(ich7_bios_cntl_registers);
		break;
	case PCI_DEVICE_ID_INTEL_3400:
	case PCI_DEVICE_ID_INTEL_3420:
	case PCI_DEVICE_ID_INTEL_3450:
	case PCI_DEVICE_ID_INTEL_3400_DESKTOP:
	case PCI_DEVICE_ID_INTEL_B55_A:
	case PCI_DEVICE_ID_INTEL_B55_B:
	case PCI_DEVICE_ID_INTEL_H55:
	case PCI_DEVICE_ID_INTEL_H57:
	case PCI_DEVICE_ID_INTEL_P55:
	case PCI_DEVICE_ID_INTEL_Q57:
	case PCI_DEVICE_ID_INTEL_3400_MOBILE:
	case PCI_DEVICE_ID_INTEL_3400_MOBILE_SFF:
	case PCI_DEVICE_ID_INTEL_HM55:
	case PCI_DEVICE_ID_INTEL_HM57:
	case PCI_DEVICE_ID_INTEL_PM55:
	case PCI_DEVICE_ID_INTEL_QM57:
	case PCI_DEVICE_ID_INTEL_QS57:
	case PCI_DEVICE_ID_INTEL_Z68:
	case PCI_DEVICE_ID_INTEL_P67:
	case PCI_DEVICE_ID_INTEL_UM67:
	case PCI_DEVICE_ID_INTEL_HM65:
	case PCI_DEVICE_ID_INTEL_H67:
	case PCI_DEVICE_ID_INTEL_HM67:
	case PCI_DEVICE_ID_INTEL_Q65:
	case PCI_DEVICE_ID_INTEL_QS67:
	case PCI_DEVICE_ID_INTEL_Q67:
	case PCI_DEVICE_ID_INTEL_QM67:
	case PCI_DEVICE_ID_INTEL_B65:
	case PCI_DEVICE_ID_INTEL_C202:
	case PCI_DEVICE_ID_INTEL_C204:
	case PCI_DEVICE_ID_INTEL_C206:
	case PCI_DEVICE_ID_INTEL_H61:
	case PCI_DEVICE_ID_INTEL_Z77:
	case PCI_DEVICE_ID_INTEL_Z75:
	case PCI_DEVICE_ID_INTEL_Q77:
	case PCI_DEVICE_ID_INTEL_Q75:
	case PCI_DEVICE_ID_INTEL_B75:
	case PCI_DEVICE_ID_INTEL_H77:
	case PCI_DEVICE_ID_INTEL_C216:
	case PCI_DEVICE_ID_INTEL_QM77:
	case PCI_DEVICE_ID_INTEL_QS77:
	case PCI_DEVICE_ID_INTEL_HM77:
	case PCI_DEVICE_ID_INTEL_UM77:
	case PCI_DEVICE_ID_INTEL_HM76:
	case PCI_DEVICE_ID_INTEL_HM75:
	case PCI_DEVICE_ID_INTEL_HM70:
	case PCI_DEVICE_ID_INTEL_NM70:
	case PCI_DEVICE_ID_INTEL_C8_MOBILE:
	case PCI_DEVICE_ID_INTEL_C8_DESKTOP:
	case PCI_DEVICE_ID_INTEL_Z87:
	case PCI_DEVICE_ID_INTEL_Z85:
	case PCI_DEVICE_ID_INTEL_HM86:
	case PCI_DEVICE_ID_INTEL_H87:
	case PCI_DEVICE_ID_INTEL_HM87:
	case PCI_DEVICE_ID_INTEL_Q85:
	case PCI_DEVICE_ID_INTEL_Q87:
	case PCI_DEVICE_ID_INTEL_QM87:
	case PCI_DEVICE_ID_INTEL_B85:
	case PCI_DEVICE_ID_INTEL_C222:
	case PCI_DEVICE_ID_INTEL_C224:
	case PCI_DEVICE_ID_INTEL_C226:
	case PCI_DEVICE_ID_INTEL_H81:
		bios_cntl = pci_read_byte(sb, 0xdc);
		bios_cntl_register = pch_bios_cntl_registers;
		size = ARRAY_SIZE(pch_bios_cntl_registers);
		break;
	default:
		printf("Error: Dumping SPI on this southbridge is not (yet) supported.\n");
		return 1;
	}

	printf("BIOS_CNTL = 0x%04x (IO)\n\n", bios_cntl);

	if (bios_cntl_register) {
		for (i = 0; i < size; i++) {
			unsigned int val = bios_cntl >> bios_cntl_register[i].addr;
			val &= ((1 << bios_cntl_register[i].size) -1);
			printf("0x%04x = %s\n", val, bios_cntl_register[i].name);
		}
	}

	return 0;
}
Пример #16
0
Файл: pci.c Проект: levex/levos5
uint8_t pci_config_read_byte(struct pci_device *pdev, uint32_t offset)
{
	return pci_read_byte(pdev->bus, pdev->slot, pdev->func, offset);
}
Пример #17
0
uintptr_t pcidev_readbar(struct pci_dev *dev, int bar)
{
	uint64_t addr;
	uint32_t upperaddr;
	uint8_t headertype;
	uint16_t supported_cycles;
	enum pci_bartype bartype = TYPE_UNKNOWN;


	headertype = pci_read_byte(dev, PCI_HEADER_TYPE) & 0x7f;
	msg_pspew("PCI header type 0x%02x\n", headertype);

	/* Don't use dev->base_addr[x] (as value for 'bar'), won't work on older libpci. */
	addr = pci_read_long(dev, bar);

	/* Sanity checks. */
	switch (headertype) {
	case PCI_HEADER_TYPE_NORMAL:
		switch (bar) {
		case PCI_BASE_ADDRESS_0:
		case PCI_BASE_ADDRESS_1:
		case PCI_BASE_ADDRESS_2:
		case PCI_BASE_ADDRESS_3:
		case PCI_BASE_ADDRESS_4:
		case PCI_BASE_ADDRESS_5:
			if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
				bartype = TYPE_IOBAR;
			else
				bartype = TYPE_MEMBAR;
			break;
		case PCI_ROM_ADDRESS:
			bartype = TYPE_ROMBAR;
			break;
		}
		break;
	case PCI_HEADER_TYPE_BRIDGE:
		switch (bar) {
		case PCI_BASE_ADDRESS_0:
		case PCI_BASE_ADDRESS_1:
			if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
				bartype = TYPE_IOBAR;
			else
				bartype = TYPE_MEMBAR;
			break;
		case PCI_ROM_ADDRESS1:
			bartype = TYPE_ROMBAR;
			break;
		}
		break;
	case PCI_HEADER_TYPE_CARDBUS:
		break;
	default:
		msg_perr("Unknown PCI header type 0x%02x, BAR type cannot be determined reliably.\n",
			 headertype);
		break;
	}

	supported_cycles = pci_read_word(dev, PCI_COMMAND);

	msg_pdbg("Requested BAR is of type ");
	switch (bartype) {
	case TYPE_MEMBAR:
		msg_pdbg("MEM");
		if (!(supported_cycles & PCI_COMMAND_MEMORY)) {
			msg_perr("MEM BAR access requested, but device has MEM space accesses disabled.\n");
			/* TODO: Abort here? */
		}
		msg_pdbg(", %sbit, %sprefetchable\n",
			 ((addr & 0x6) == 0x0) ? "32" : (((addr & 0x6) == 0x4) ? "64" : "reserved"),
			 (addr & 0x8) ? "" : "not ");
		if ((addr & 0x6) == 0x4) {
			/* The spec says that a 64-bit register consumes
			 * two subsequent dword locations.
			 */
			upperaddr = pci_read_long(dev, bar + 4);
			if (upperaddr != 0x00000000) {
				/* Fun! A real 64-bit resource. */
				if (sizeof(uintptr_t) != sizeof(uint64_t)) {
					msg_perr("BAR unreachable!");
					/* TODO: Really abort here? If multiple PCI devices match,
					 * we might never tell the user about the other devices.
					 */
					return 0;
				}
				addr |= (uint64_t)upperaddr << 32;
			}
		}
		addr &= PCI_BASE_ADDRESS_MEM_MASK;
		break;
	case TYPE_IOBAR:
		msg_pdbg("I/O\n");
#if __FLASHROM_HAVE_OUTB__
		if (!(supported_cycles & PCI_COMMAND_IO)) {
			msg_perr("I/O BAR access requested, but device has I/O space accesses disabled.\n");
			/* TODO: Abort here? */
		}
#else
		msg_perr("I/O BAR access requested, but flashrom does not support I/O BAR access on this "
			 "platform (yet).\n");
#endif
		addr &= PCI_BASE_ADDRESS_IO_MASK;
		break;
	case TYPE_ROMBAR:
		msg_pdbg("ROM\n");
		/* Not sure if this check is needed. */
		if (!(supported_cycles & PCI_COMMAND_MEMORY)) {
			msg_perr("MEM BAR access requested, but device has MEM space accesses disabled.\n");
			/* TODO: Abort here? */
		}
		addr &= PCI_ROM_ADDRESS_MASK;
		break;
	case TYPE_UNKNOWN:
		msg_perr("BAR type unknown, please report a bug at [email protected]\n");
	}

	return (uintptr_t)addr;
}
Пример #18
0
static void determine_generation(struct pci_dev *dev)
{
	amd_gen = CHIPSET_AMD_UNKNOWN;
	msg_pdbg2("Trying to determine the generation of the SPI interface... ");
	if (dev->device_id == 0x438d) {
		amd_gen = CHIPSET_SB6XX;
		msg_pdbg("SB6xx detected.\n");
	} else if (dev->device_id == 0x439d) {
		struct pci_dev *smbus_dev = pci_dev_find(0x1002, 0x4385);
		if (smbus_dev == NULL)
			return;
		uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID);
		if (rev >= 0x39 && rev <= 0x3D) {
			amd_gen = CHIPSET_SB7XX;
			msg_pdbg("SB7xx/SP5100 detected.\n");
		} else if (rev >= 0x40 && rev <= 0x42) {
			amd_gen = CHIPSET_SB89XX;
			msg_pdbg("SB8xx/SB9xx/Hudson-1 detected.\n");
		} else {
			msg_pwarn("SB device found but SMBus revision 0x%02x does not match known values.\n"
				  "Assuming SB8xx/SB9xx/Hudson-1. Please send a log to [email protected]\n",
				   rev);
			amd_gen = CHIPSET_SB89XX;
		}
	} else if (dev->device_id == 0x780e) {
		/* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash)
		 * although they use different SPI interfaces. */
#ifdef USE_YANGTZE_HEURISTICS
		/* This heuristic accesses the SPI interface MMIO BAR at locations beyond those supported by
		 * Hudson in the hope of getting 0xff readback on older chipsets and non-0xff readback on
		 * Yangtze (and newer, compatible chipsets). */
		int i;
		msg_pdbg("Checking for AMD Yangtze (Kabini/Temash) or later... ");
		for (i = 0x20; i <= 0x4f; i++) {
			if (mmio_readb(sb600_spibar + i) != 0xff) {
				amd_gen = CHIPSET_YANGTZE;
				msg_pdbg("found.\n");
				return;
			}
		}
		msg_pdbg("not found. Assuming Hudson.\n");
		amd_gen = CHIPSET_HUDSON234;
#else
		struct pci_dev *smbus_dev = pci_dev_find(0x1022, 0x780B);
		if (smbus_dev == NULL) {
			msg_pdbg("No SMBus device with ID 1022:780B found.\n");
			return;
		}
		uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID);
		if (rev >= 0x11 && rev <= 0x15) {
			amd_gen = CHIPSET_HUDSON234;
			msg_pdbg("Hudson-2/3/4 detected.\n");
		} else if (rev >= 0x39 && rev <= 0x3A) {
			amd_gen = CHIPSET_YANGTZE;
			msg_pdbg("Yangtze detected.\n");
		} else {
			msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n"
				  "Please report this to [email protected] and include this log and\n"
				  "the output of lspci -nnvx, thanks!.\n", rev);
		}
#endif
	} else
		msg_pwarn("%s: Unknown LPC device %" PRIx16 ":%" PRIx16 ".\n"
			  "Please report this to [email protected] and include this log and\n"
			  "the output of lspci -nnvx, thanks!\n",
			  __func__, dev->vendor_id, dev->device_id);
}
Пример #19
0
int
pci_generic_fill_info(struct pci_dev *d, int flags)
{
  struct pci_access *a = d->access;

  if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0)
    d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
  if (flags & PCI_FILL_IDENT)
    {
      d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
      d->device_id = pci_read_word(d, PCI_DEVICE_ID);
    }
  if (flags & PCI_FILL_CLASS)
      d->device_class = pci_read_word(d, PCI_CLASS_DEVICE);
  if (flags & PCI_FILL_IRQ)
    d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
  if (flags & PCI_FILL_BASES)
    {
      int cnt = 0, i;
      memset(d->base_addr, 0, sizeof(d->base_addr));
      switch (d->hdrtype)
	{
	case PCI_HEADER_TYPE_NORMAL:
	  cnt = 6;
	  break;
	case PCI_HEADER_TYPE_BRIDGE:
	  cnt = 2;
	  break;
	case PCI_HEADER_TYPE_CARDBUS:
	  cnt = 1;
	  break;
	}
      if (cnt)
	{
	  for (i=0; i<cnt; i++)
	    {
	      u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
	      if (!x || x == (u32) ~0)
		continue;
	      if ((x & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
		d->base_addr[i] = x;
	      else
		{
		  if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != PCI_BASE_ADDRESS_MEM_TYPE_64)
		    d->base_addr[i] = x;
		  else if (i >= cnt-1)
		    a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.", d->domain, d->bus, d->dev, d->func, i);
		  else
		    {
		      u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
#ifdef PCI_HAVE_64BIT_ADDRESS
		      d->base_addr[i-1] = x | (((pciaddr_t) y) << 32);
#else
		      if (y)
			a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func);
		      else
			d->base_addr[i-1] = x;
#endif
		    }
		}
	    }
	}
    }
  if (flags & PCI_FILL_ROM_BASE)
    {
      int reg = 0;
      d->rom_base_addr = 0;
      switch (d->hdrtype)
	{
	case PCI_HEADER_TYPE_NORMAL:
	  reg = PCI_ROM_ADDRESS;
	  break;
	case PCI_HEADER_TYPE_BRIDGE:
	  reg = PCI_ROM_ADDRESS1;
	  break;
	}
      if (reg)
	{
	  u32 u = pci_read_long(d, reg);
	  if (u != 0xffffffff)
	    d->rom_base_addr = u;
	}
    }
  if (flags & (PCI_FILL_CAPS | PCI_FILL_EXT_CAPS))
    flags |= pci_scan_caps(d, flags);
  return flags & ~PCI_FILL_SIZES;
}
Пример #20
0
static void
exec_op(struct op *op, struct pci_dev *dev)
{
  const char * const formats[] = { NULL, " %02x", " %04x", NULL, " %08x" };
  const char * const mask_formats[] = { NULL, " %02x->(%02x:%02x)->%02x", " %04x->(%04x:%04x)->%04x", NULL, " %08x->(%08x:%08x)->%08x" };
  unsigned int i, x, y;
  int addr = 0;
  int width = op->width;
  char slot[16];

  sprintf(slot, "%04x:%02x:%02x.%x", dev->domain, dev->bus, dev->dev, dev->func);
  trace("%s ", slot);
  if (op->cap_type)
    {
      struct pci_cap *cap;
      cap = pci_find_cap(dev, op->cap_id, op->cap_type);
      if (cap)
	addr = cap->addr;
      else
	die("%s: %s %04x not found", slot, ((op->cap_type == PCI_CAP_NORMAL) ? "Capability" : "Extended capability"), op->cap_id);
      trace(((op->cap_type == PCI_CAP_NORMAL) ? "(cap %02x @%02x) " : "(ecap %04x @%03x) "), op->cap_id, addr);
    }
  addr += op->addr;
  trace("@%02x", addr);

  /* We have already checked it when parsing, but addressing relative to capabilities can change the address. */
  if (addr & (width-1))
    die("%s: Unaligned access of width %d to register %04x", slot, width, addr);
  if (addr + width > 0x1000)
    die("%s: Access of width %d to register %04x out of range", slot, width, addr);

  if (op->num_values)
    {
      for (i=0; i<op->num_values; i++)
	{
	  if ((op->values[i].mask & max_values[width]) == max_values[width])
	    {
	      x = op->values[i].value;
	      trace(formats[width], op->values[i].value);
	    }
	  else
	    {
	      switch (width)
		{
		case 1:
		  y = pci_read_byte(dev, addr);
		  break;
		case 2:
		  y = pci_read_word(dev, addr);
		  break;
		default:
		  y = pci_read_long(dev, addr);
		  break;
		}
	      x = (y & ~op->values[i].mask) | op->values[i].value;
	      trace(mask_formats[width], y, op->values[i].value, op->values[i].mask, x);
	    }
	  if (!demo_mode)
	    {
	      switch (width)
		{
		case 1:
		  pci_write_byte(dev, addr, x);
		  break;
		case 2:
		  pci_write_word(dev, addr, x);
		  break;
		default:
		  pci_write_long(dev, addr, x);
		  break;
		}
	    }
	  addr += width;
	}
      trace("\n");
    }
  else
    {
      trace(" = ");
      switch (width)
	{
	case 1:
	  x = pci_read_byte(dev, addr);
	  break;
	case 2:
	  x = pci_read_word(dev, addr);
	  break;
	default:
	  x = pci_read_long(dev, addr);
	  break;
	}
      printf(formats[width]+1, x);
      putchar('\n');
    }
}
Пример #21
0
int
pci_generic_fill_info(struct pci_dev *d, int flags)
{
  struct pci_access *a = d->access;

  if (flags & PCI_FILL_IDENT)
    {
      d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
      d->device_id = pci_read_word(d, PCI_DEVICE_ID);
    }
  if (flags & PCI_FILL_IRQ)
    d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
  if (flags & PCI_FILL_BASES)
    {
      int cnt = 0, i;
      //bzero(d->base_addr, sizeof(d->base_addr));
      memset(d->base_addr,0, sizeof(d->base_addr));
      switch (d->hdrtype)
	{
	case PCI_HEADER_TYPE_NORMAL:
	  cnt = 6;
	  break;
	case PCI_HEADER_TYPE_BRIDGE:
	  cnt = 2;
	  break;
	case PCI_HEADER_TYPE_CARDBUS:
	  cnt = 1;
	  break;
	}
      if (cnt)
	{
	  u16 cmd = pci_read_word(d, PCI_COMMAND);
	  for(i=0; i<cnt; i++)
	    {
	      u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
	      if (!x || x == (u32) ~0)
		continue;
	      d->base_addr[i] = x;
	      if (x & PCI_BASE_ADDRESS_SPACE_IO)
		{
		  if (!a->buscentric && !(cmd & PCI_COMMAND_IO))
		    d->base_addr[i] = 0;
		}
	      else if (a->buscentric || (cmd & PCI_COMMAND_MEMORY))
		{
		  if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
		    {
		      if (i >= cnt-1)
			a->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d->bus, d->dev, d->func);
		      else
			{
			  u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
#ifdef HAVE_64BIT_ADDRESS
			  d->base_addr[i-1] |= ((pciaddr_t) y) << 32;
#else
			  if (y)
			    {
			      a->warning("%02x:%02x.%d 64-bit device address ignored.", d->bus, d->dev, d->func);
			      d->base_addr[i-1] = 0;
			    }
#endif
			}
		    }
		}
	      else
		d->base_addr[i] = 0;
	    }
	}
    }
  if (flags & PCI_FILL_ROM_BASE)
    {
      int reg = 0;
      d->rom_base_addr = 0;
      switch (d->hdrtype)
	{
	case PCI_HEADER_TYPE_NORMAL:
	  reg = PCI_ROM_ADDRESS;
	  break;
	case PCI_HEADER_TYPE_BRIDGE:
	  reg = PCI_ROM_ADDRESS1;
	  break;
	}
      if (reg)
	{
	  u32 a = pci_read_long(d, reg);
	  if (a & PCI_ROM_ADDRESS_ENABLE)
	    d->rom_base_addr = a;
	}
    }
  return flags & ~PCI_FILL_SIZES;
}
Пример #22
0
void pci::probe(void) {
    pci_scan_bus(_pacc);

    uint8_t buf[CONFIG_SPACE_SIZE] = {0};
    char classbuf[128] = {0}, vendorbuf[128] {0}, devbuf[128] = {0};

    for (struct pci_dev *dev = _pacc->devices; dev && _entries.size() < MAX_DEVICES; dev = dev->next) {
	_entries.push_back(pciEntry());
	pciEntry &e = _entries.back();
	memset(buf, 0, sizeof(buf));
	memset(classbuf, 0, sizeof(classbuf));
	memset(vendorbuf, 0, sizeof(vendorbuf));
	memset(devbuf, 0, sizeof(devbuf));

	pci_setup_cache(dev, buf, CONFIG_SPACE_SIZE);
	pci_read_block(dev, 0, buf, CONFIG_SPACE_SIZE);
	pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_CAPS);

	pci_lookup_name(_pacc, vendorbuf, sizeof(vendorbuf), PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id);
	pci_lookup_name(_pacc, devbuf,    sizeof(devbuf),    PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
	e.text.append(vendorbuf).append("|").append(devbuf);
	e.class_type += classbuf;
	e.vendor =     dev->vendor_id;
	e.device =     dev->device_id;
	e.pci_domain = dev->domain;
	e.bus =        dev->bus;
	e.pciusb_device = dev->dev;
	e.pci_function = dev->func;

	e.class_id = dev->device_class;
	e.subvendor = pci_read_word(dev, PCI_SUBSYSTEM_VENDOR_ID);
	e.subdevice = pci_read_word(dev, PCI_SUBSYSTEM_ID);
	e.pci_revision = pci_read_byte(dev, PCI_REVISION_ID);

	if ((e.subvendor == 0 && e.subdevice == 0) ||
		(e.subvendor == e.vendor && e.subdevice == e.device)) {
	    e.subvendor = 0xffff;
	    e.subdevice = 0xffff;
	}

	if (pci_find_cap(dev,PCI_CAP_ID_EXP, PCI_CAP_NORMAL))
	    e.is_pciexpress = true;

	/* special case for realtek 8139 that has two drivers */
	if (e.vendor == 0x10ec && e.device == 0x8139) {
	    if (e.pci_revision < 0x20)
		e.module = "8139too";
	    else
		e.module = "8139cp";
	}
    }

    // fake two PCI controllers for xen
    struct stat sb;
    if (!stat("/sys/bus/xen", &sb)) {
	// FIXME: use C++ streams..
	FILE *f;
	if ((f = fopen("/sys/hypervisor/uuid", "r"))) {
	    char buf[38];
	    fgets(buf, sizeof(buf) - 1, f);
	    fclose(f);
	    if (strncmp(buf, "00000000-0000-0000-0000-000000000000", sizeof(buf))) {
		// We're now sure to be in a Xen guest:
		{
		    _entries.push_back(pciEntry());
		    pciEntry &e = _entries.back();
		    e.text.append("XenSource, Inc.|Block Frontend");
		    e.class_id = 0x0106; // STORAGE_SATA

		    e.vendor =  0x1a71; // XenSource
		    e.device =  0xfffa; // fake
		    e.subvendor = 0;
		    e.subdevice = 0;
		    e.class_id = 0x0106;
		    e.module = "xen_blkfront";
		}
		{
		    _entries.push_back(pciEntry());
		    pciEntry &e = _entries.back();
		    e.text.append("XenSource, Inc.|Network Frontend");
		    e.class_id = 0x0200; // NETWORK_ETHERNET

		    e.vendor =  0x1a71; // XenSource
		    e.device =  0xfffb; // fake
		    e.subvendor = 0;
		    e.subdevice = 0;
		    e.class_id = 0x0200;
		    e.module = "xen_netfront";
		}
	    }
	}
    }
    findModules("pcitable", false);
}