Beispiel #1
0
static int
pciaddr_do_resource_allocate(pci_chipset_tag_t pc, pcitag_t tag,
    int mapreg, void *ctx, int type, bus_addr_t *addr, bus_size_t size)
{
 	struct pciaddr *pciaddrmap = (struct pciaddr *)ctx;
	bus_addr_t start;
	int error;
 	struct extent *ex;

	if (*addr != 0) /* no need to allocate */
		return 0;

 	ex = (type == PCI_MAPREG_TYPE_MEM ?
 	      pciaddrmap->extent_mem : pciaddrmap->extent_port);

	/* XXX Don't allocate if device is AGP device to avoid conflict. */
	if (device_is_agp(pc, tag))
		return 0;

	start = (type == PCI_MAPREG_TYPE_MEM ?
		 pciaddrmap->mem_alloc_start : pciaddrmap->port_alloc_start);

	if (start < ex->ex_start || start + size - 1 >= ex->ex_end) {
		aprint_debug("No available resources. fixup failed\n");
		return 1;
	}
	error = extent_alloc_subregion(ex, start, ex->ex_end, size,
				       size, 0,
				       EX_FAST|EX_NOWAIT|EX_MALLOCOK,
				       (u_long *)addr);
	if (error) {
		aprint_debug("No available resources. fixup failed\n");
		return 1;
	}

	/* write new address to PCI device configuration header */
	pci_conf_write(pc, tag, mapreg, *addr);
	/* check */
	aprint_debug("pci_addr_fixup: ");
	pciaddr_print_devid(pc, tag);
	if (pciaddr_ioaddr(pci_conf_read(pc, tag, mapreg)) != *addr) {
		pci_conf_write(pc, tag, mapreg, 0); /* clear */
		aprint_error("fixup failed. (new address=%#x)\n", (unsigned)*addr);
		return 1;
	}
	aprint_debug("new address 0x%08x\n", (unsigned)*addr);

	return 0;
}
Beispiel #2
0
int
pciaddr_do_resource_allocate(struct shpcic_softc *sc, pci_chipset_tag_t pc,
    pcitag_t tag, int mapreg, struct extent *ex, int  type, bus_addr_t *addr,
    bus_size_t size)
{
	bus_addr_t start;
	int error;
	
	if (type == PCI_MAPREG_TYPE_IO) {
		if ((*addr & PCIADDR_PORT_END) != 0)
			return (0);
	} else if (*addr) /* no need to allocate */
		return (0);

	/* XXX Don't allocate if device is AGP device to avoid conflict. */
	if (pciaddr_device_is_agp(pc, tag)) 
		return (0);
	
	start = (type == PCI_MAPREG_TYPE_MEM ? sc->sc_membus_space.bus_base
	    : sc->sc_iobus_space.bus_base);
	if (start < ex->ex_start || start + size - 1 >= ex->ex_end) {
		PCIBIOS_PRINTV(("No available resources. fixup failed\n"));
		return (1);
	}
	error = extent_alloc_subregion(ex, start, ex->ex_end, size, size, 0, 0,
	    EX_FAST|EX_NOWAIT|EX_MALLOCOK, addr);
	if (error) {
		PCIBIOS_PRINTV(("No available resources. fixup failed\n"));
		return (1);
	}

	/* write new address to PCI device configuration header */
	pci_conf_write(pc, tag, mapreg, *addr);
	/* check */
	if (pcibr_flags & PCIBR_VERBOSE) {
		printf("pci_addr_fixup: ");
		pciaddr_print_devid(pc, tag);
	}

	if (pciaddr_ioaddr(pci_conf_read(pc, tag, mapreg)) != *addr) {
		pci_conf_write(pc, tag, mapreg, 0); /* clear */
		printf("fixup failed. (new address=%#lx)\n", *addr);
		return (1);
	}
	if (pcibr_flags & PCIBR_VERBOSE)
		printf("new address 0x%08lx\n", *addr);

	return (0);
}
Beispiel #3
0
void
pciaddr_resource_manage(pci_chipset_tag_t pc, pcitag_t tag,
    pciaddr_resource_manage_func_t func, void *ctx)
{
	pcireg_t val, mask;
	bus_addr_t addr;
	bus_size_t size;
	int error, useport, usemem, mapreg, type, reg_start, reg_end, width;

	val = pci_conf_read(pc, tag, PCI_BHLC_REG);
	switch (PCI_HDRTYPE_TYPE(val)) {
	default:
		aprint_error("WARNING: unknown PCI device header.");
		pciaddr.nbogus++;
		return;
	case PCI_HDRTYPE_DEVICE:
		reg_start = PCI_MAPREG_START;
		reg_end   = PCI_MAPREG_END;
		break;
	case PCI_HDRTYPE_PPB: /* PCI-PCI bridge */
		reg_start = PCI_MAPREG_START;
		reg_end   = PCI_MAPREG_PPB_END;
		break;
	case PCI_HDRTYPE_PCB: /* PCI-CardBus bridge */
		reg_start = PCI_MAPREG_START;
		reg_end   = PCI_MAPREG_PCB_END;
		break;
	}
	error = useport = usemem = 0;

	for (mapreg = reg_start; mapreg < reg_end; mapreg += width) {
		/* inquire PCI device bus space requirement */
		val = pci_conf_read(pc, tag, mapreg);
		pci_conf_write(pc, tag, mapreg, ~0);

		mask = pci_conf_read(pc, tag, mapreg);
		pci_conf_write(pc, tag, mapreg, val);

		type = PCI_MAPREG_TYPE(val);
		width = 4;
		if (type == PCI_MAPREG_TYPE_MEM) {
			if (PCI_MAPREG_MEM_TYPE(val) ==
			    PCI_MAPREG_MEM_TYPE_64BIT) {
				/* XXX We could examine the upper 32 bits
				 * XXX of the BAR here, but we are totally
				 * XXX unprepared to handle a non-zero value,
				 * XXX either here or anywhere else in
				 * XXX i386-land.
				 * XXX So just arrange to not look at the
				 * XXX upper 32 bits, lest we misinterpret
				 * XXX it as a 32-bit BAR set to zero.
				 */
			    width = 8;
			}
			size = PCI_MAPREG_MEM_SIZE(mask);
		} else {
			size = PCI_MAPREG_IO_SIZE(mask);
		}
		addr = pciaddr_ioaddr(val);

		if (size == 0) /* unused register */
			continue;

		if (type == PCI_MAPREG_TYPE_MEM)
			++usemem;
		else
			++useport;

		/* reservation/allocation phase */
		error += (*func) (pc, tag, mapreg, ctx, type, &addr, size);

		aprint_debug("\n\t%02xh %s 0x%08x 0x%08x",
				mapreg, type ? "port" : "mem ",
				(unsigned int)addr, (unsigned int)size);
	}

	/* enable/disable PCI device */
	val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
	if (error == 0)
		val |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
			PCI_COMMAND_MASTER_ENABLE);
	else
		val &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
			 PCI_COMMAND_MASTER_ENABLE);
	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, val);

	if (error != 0)
		pciaddr.nbogus++;

	aprint_debug("\n\t\t[%s]\n", error ? "NG" : "OK");
}