Пример #1
0
static int
pci_io_find(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type,
    bus_addr_t *basep, bus_size_t *sizep, int *flagsp)
{
	pcireg_t address, mask;
	int s;

	if (reg < PCI_MAPREG_START ||
#if 0
	    /*
	     * Can't do this check; some devices have mapping registers
	     * way out in left field.
	     */
	    reg >= PCI_MAPREG_END ||
#endif
	    (reg & 3))
		panic("pci_io_find: bad request");

	/*
	 * Section 6.2.5.1, `Address Maps', tells us that:
	 *
	 * 1) The builtin software should have already mapped the device in a
	 * reasonable way.
	 *
	 * 2) A device which wants 2^n bytes of memory will hardwire the bottom
	 * n bits of the address to 0.  As recommended, we write all 1s and see
	 * what we get back.
	 */
	s = splhigh();
	address = pci_conf_read(pc, tag, reg);
	pci_conf_write(pc, tag, reg, 0xffffffff);
	mask = pci_conf_read(pc, tag, reg);
	pci_conf_write(pc, tag, reg, address);
	splx(s);

	if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) {
		aprint_debug("pci_io_find: expected type i/o, found mem\n");
		return (1);
	}

	if (PCI_MAPREG_IO_SIZE(mask) == 0) {
		aprint_debug("pci_io_find: void region\n");
		return (1);
	}

	if (basep != 0)
		*basep = PCI_MAPREG_IO_ADDR(address);
	if (sizep != 0)
		*sizep = PCI_MAPREG_IO_SIZE(mask);
	if (flagsp != 0)
		*flagsp = 0;

	return (0);
}
Пример #2
0
/* check if this BAR assigns/requests IO space */
static int
bar_is_io(pci_chipset_tag_t pc, pcitag_t tag, int reg)
{
	pcireg_t address, mask;
	int s;

	/*
	 * The splhigh() is not realy necessary at autoconfig time,
	 * but maybe useful if used in lkm context later.
	 */
	s = splhigh();
	address = pci_conf_read(pc, tag, reg);
	pci_conf_write(pc, tag, reg, 0xffffffff);
	mask = pci_conf_read(pc, tag, reg);
	pci_conf_write(pc, tag, reg, address);
	splx(s);

	return (PCI_MAPREG_TYPE(address) == PCI_MAPREG_TYPE_IO && PCI_MAPREG_IO_SIZE(mask) > 0);
}
Пример #3
0
static int
pci_device_openbsd_probe(struct pci_device *device)
{
	struct pci_device_private *priv = (struct pci_device_private *)device;
	struct pci_mem_region *region;
	uint64_t reg64, size64;
	uint32_t bar, reg, size;
	int domain, bus, dev, func, err;

	domain = device->domain;
	bus = device->bus;
	dev = device->dev;
	func = device->func;

	err = pci_read(domain, bus, dev, func, PCI_BHLC_REG, &reg);
	if (err)
		return err;

	priv->header_type = PCI_HDRTYPE_TYPE(reg);
	if (priv->header_type != 0)
		return 0;

	region = device->regions;
	for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END;
	     bar += sizeof(uint32_t), region++) {
		err = pci_read(domain, bus, dev, func, bar, &reg);
		if (err)
			return err;

		/* Probe the size of the region. */
		err = pci_readmask(domain, bus, dev, func, bar, &size);
		if (err)
			return err;

		if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) {
			region->is_IO = 1;
			region->base_addr = PCI_MAPREG_IO_ADDR(reg);
			region->size = PCI_MAPREG_IO_SIZE(size);
		} else {
			if (PCI_MAPREG_MEM_PREFETCHABLE(reg))
				region->is_prefetchable = 1;
			switch(PCI_MAPREG_MEM_TYPE(reg)) {
			case PCI_MAPREG_MEM_TYPE_32BIT:
			case PCI_MAPREG_MEM_TYPE_32BIT_1M:
				region->base_addr = PCI_MAPREG_MEM_ADDR(reg);
				region->size = PCI_MAPREG_MEM_SIZE(size);
				break;
			case PCI_MAPREG_MEM_TYPE_64BIT:
				region->is_64 = 1;

				reg64 = reg;
				size64 = size;

				bar += sizeof(uint32_t);

				err = pci_read(domain, bus, dev, func, bar, &reg);
				if (err)
					return err;
				reg64 |= (uint64_t)reg << 32;

				err = pci_readmask(domain, bus, dev, func, bar, &size);
				if (err)
					return err;
				size64 |= (uint64_t)size << 32;

				region->base_addr = PCI_MAPREG_MEM64_ADDR(reg64);
				region->size = PCI_MAPREG_MEM64_SIZE(size64);
				region++;
				break;
			}
		}
	}

	/* Probe expansion ROM if present */
	err = pci_read(domain, bus, dev, func, PCI_ROM_REG, &reg);
	if (err)
		return err;
	if (reg != 0) {
		err = pci_write(domain, bus, dev, func, PCI_ROM_REG, ~PCI_ROM_ENABLE);
		if (err)
			return err;
		pci_read(domain, bus, dev, func, PCI_ROM_REG, &size);
		pci_write(domain, bus, dev, func, PCI_ROM_REG, reg);

		if (PCI_ROM_ADDR(reg) != 0) {
			priv->rom_base = PCI_ROM_ADDR(reg);
			device->rom_size = PCI_ROM_SIZE(size);
		}
	}
	return 0;
}
Пример #4
0
/*
 * static int cardbus_io_find(cardbus_chipset_tag_t cc,
 *			      cardbus_function_tag_t cf, pcitag_t tag,
 *			      int reg, pcireg_t type, bus_addr_t *basep,
 *			      bus_size_t *sizep, int *flagsp)
 * This code is stolen from sys/dev/pci_map.c.
 */
static int
cardbus_io_find(
    cardbus_chipset_tag_t cc,
    cardbus_function_tag_t cf,
    pcitag_t tag,
    int reg,
    pcireg_t type,
    bus_addr_t *basep,
    bus_size_t *sizep,
    int *flagsp)
{
	pcireg_t address, mask;
	int s;

	/* EXT ROM is able to map on memory space ONLY. */
	if (reg == CARDBUS_ROM_REG) {
		return 1;
	}

	if(reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) {
		panic("cardbus_io_find: bad request");
	}

	/*
	 * Section 6.2.5.1, `Address Maps', tells us that:
	 *
	 * 1) The builtin software should have already mapped the device in a
	 * reasonable way.
	 *
	 * 2) A device which wants 2^n bytes of memory will hardwire the bottom
	 * n bits of the address to 0.  As recommended, we write all 1s and see
	 * what we get back.
	 */
	s = splhigh();
	address = cardbus_conf_read(cc, cf, tag, reg);
	cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
	mask = cardbus_conf_read(cc, cf, tag, reg);
	cardbus_conf_write(cc, cf, tag, reg, address);
	splx(s);

	if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) {
		printf("cardbus_io_find: expected type i/o, found mem\n");
		return 1;
	}

	if (PCI_MAPREG_IO_SIZE(mask) == 0) {
		printf("cardbus_io_find: void region\n");
		return 1;
	}

	if (basep != 0) {
		*basep = PCI_MAPREG_IO_ADDR(address);
	}
	if (sizep != 0) {
		*sizep = PCI_MAPREG_IO_SIZE(mask);
	}
	if (flagsp != 0) {
		*flagsp = 0;
	}

	return 0;
}
Пример #5
0
void
pciaddr_resource_manage(struct pcibios_softc *sc, pci_chipset_tag_t pc,
    pcitag_t tag, pciaddr_resource_manage_func_t func)
{
	struct extent *ex;
	pcireg_t val, mask;
	bus_addr_t addr;
	bus_size_t size;
	int error, mapreg, type, reg_start, reg_end, width;

	val = pci_conf_read(pc, tag, PCI_BHLC_REG);
	switch (PCI_HDRTYPE_TYPE(val)) {
	default:
		printf("WARNING: unknown PCI device header 0x%x.\n",
		    PCI_HDRTYPE_TYPE(val));
		sc->nbogus++;
		return;
	case 0: 
		reg_start = PCI_MAPREG_START;
		reg_end   = PCI_MAPREG_END;
		break;
	case 1: /* PCI-PCI bridge */
		reg_start = PCI_MAPREG_START;
		reg_end   = PCI_MAPREG_PPB_END;
		break;
	case 2: /* PCI-CardBus bridge */
		reg_start = PCI_MAPREG_START;
		reg_end   = PCI_MAPREG_PCB_END;
		break;
	}
	error = 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;
			}
			addr = PCI_MAPREG_MEM_ADDR(val);
			size = PCI_MAPREG_MEM_SIZE(mask);
			ex = sc->extent_mem;
		} else {
			/* XXX some devices give 32bit value */
			addr = PCI_MAPREG_IO_ADDR(val) & PCIADDR_PORT_END;
			size = PCI_MAPREG_IO_SIZE(mask);
			ex = sc->extent_port;
		}
	
		if (!size) /* unused register */
			continue;

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

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

	if (error)
		sc->nbogus++;

	PCIBIOS_PRINTV(("\t\t[%s]\n", error ? "NG" : "OK"));
}
Пример #6
0
static void
cac_pci_attach(device_t parent, device_t self, void *aux)
{
    struct pci_attach_args *pa;
    const struct cac_pci_type *ct;
    struct cac_softc *sc;
    pci_chipset_tag_t pc;
    pci_intr_handle_t ih;
    const char *intrstr;
    pcireg_t reg;
    int memr, ior, i;
    char intrbuf[PCI_INTRSTR_LEN];

    aprint_naive(": RAID controller\n");

    sc = device_private(self);
    sc->sc_dev = self;
    pa = (struct pci_attach_args *)aux;
    pc = pa->pa_pc;
    ct = cac_pci_findtype(pa);

    /*
     * Map the PCI register window.
     */
    memr = -1;
    ior = -1;

    for (i = 0x10; i <= 0x14; i += 4) {
        reg = pci_conf_read(pa->pa_pc, pa->pa_tag, i);

        if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) {
            if (ior == -1 && PCI_MAPREG_IO_SIZE(reg) != 0)
                ior = i;
        } else {
            if (memr == -1 && PCI_MAPREG_MEM_SIZE(reg) != 0)
                memr = i;
        }
    }

    if (memr != -1) {
        if (pci_mapreg_map(pa, memr, PCI_MAPREG_TYPE_MEM, 0,
                           &sc->sc_iot, &sc->sc_ioh, NULL, NULL))
            memr = -1;
        else
            ior = -1;
    }
    if (ior != -1)
        if (pci_mapreg_map(pa, ior, PCI_MAPREG_TYPE_IO, 0,
                           &sc->sc_iot, &sc->sc_ioh, NULL, NULL))
            ior = -1;
    if (memr == -1 && ior == -1) {
        aprint_error_dev(self, "can't map i/o or memory space\n");
        return;
    }

    sc->sc_dmat = pa->pa_dmat;

    /* Enable the device. */
    reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
    pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
                   reg | PCI_COMMAND_MASTER_ENABLE);

    /* Map and establish the interrupt. */
    if (pci_intr_map(pa, &ih)) {
        aprint_error("can't map interrupt\n");
        return;
    }
    intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf));
    sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, cac_intr, sc);
    if (sc->sc_ih == NULL) {
        aprint_error("can't establish interrupt");
        if (intrstr != NULL)
            aprint_error(" at %s", intrstr);
        aprint_error("\n");
        return;
    }

    aprint_normal(": Compaq %s\n", ct->ct_typestr);

    /* Now attach to the bus-independent code. */
    memcpy(&sc->sc_cl, ct->ct_linkage, sizeof(sc->sc_cl));
    cac_init(sc, intrstr, (ct->ct_flags & CT_STARTFW) != 0);
}
Пример #7
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");
}
/*
 * Enable memory and I/O on pci devices. Care about already enabled devices
 * (probabaly by the console driver).
 *
 * The idea behind the following code is:
 * We build a by sizes sorted list of the requirements of the different
 * pci devices. After that we choose the start addresses of that areas
 * in such a way that they are placed as closed as possible together.
 */
static void
enable_pci_devices(void)
{
    PCI_MEMREG memlist;
    PCI_MEMREG iolist;
    struct pci_memreg *p, *q;
    int dev, reg, id, class;
    pcitag_t tag;
    pcireg_t csr, address, mask;
    pci_chipset_tag_t pc;
    int sizecnt, membase_1m;

    pc = 0;
    csr = 0;
    tag = 0;

    LIST_INIT(&memlist);
    LIST_INIT(&iolist);

    /*
     * first step: go through all devices and gather memory and I/O
     * sizes
     */
    for (dev = 0; dev < pci_bus_maxdevs(pc,0); dev++) {

	tag = pci_make_tag(pc, 0, dev, 0);
	id  = pci_conf_read(pc, tag, PCI_ID_REG);
	if (id == 0 || id == 0xffffffff)
	    continue;

	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);

	/*
	 * special case: if a display card is found and memory is enabled
	 * preserve 128k at 0xa0000 as vga memory.
	 * XXX: if a display card is found without being enabled, leave
	 *      it alone! You will usually only create conflicts by enabeling
	 *      it.
	 */
	class = pci_conf_read(pc, tag, PCI_CLASS_REG);
	switch (PCI_CLASS(class)) {
	    case PCI_CLASS_PREHISTORIC:
	    case PCI_CLASS_DISPLAY:
	      if (csr & (PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)) {
		    p = (struct pci_memreg *)malloc(sizeof(struct pci_memreg),
				M_TEMP, M_WAITOK);
		    memset(p, '\0', sizeof(struct pci_memreg));
		    p->dev = dev;
		    p->csr = csr;
		    p->tag = tag;
		    p->reg = 0;     /* there is no register about this */
		    p->size = 0x20000;  /* 128kByte */
		    p->mask = 0xfffe0000;
		    p->address = 0xa0000;

		    insert_into_list(&memlist, p);
	      }
	      else continue;
	}

	for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) {

	    address = pci_conf_read(pc, tag, reg);
	    pci_conf_write(pc, tag, reg, 0xffffffff);
	    mask    = pci_conf_read(pc, tag, reg);
	    pci_conf_write(pc, tag, reg, address);
	    if (mask == 0)
		continue; /* Register unused */

	    p = (struct pci_memreg *)malloc(sizeof(struct pci_memreg),
			M_TEMP, M_WAITOK);
	    memset(p, '\0', sizeof(struct pci_memreg));
	    p->dev = dev;
	    p->csr = csr;
	    p->tag = tag;
	    p->reg = reg;
	    p->mask = mask;
	    p->address = 0;

	    if (mask & PCI_MAPREG_TYPE_IO) {
		p->size = PCI_MAPREG_IO_SIZE(mask);

		/*
		 * Align IO if necessary
		 */
		if (p->size < PCI_MAPREG_IO_SIZE(PCI_MACHDEP_IO_ALIGN_MASK)) {
		    p->mask = PCI_MACHDEP_IO_ALIGN_MASK;
		    p->size = PCI_MAPREG_IO_SIZE(p->mask);
		}

		/*
		 * if I/O is already enabled (probably by the console driver)
		 * save the address in order to take care about it later.
		 */
		if (csr & PCI_COMMAND_IO_ENABLE)
		    p->address = address;

		insert_into_list(&iolist, p);
	    } else {
		p->size = PCI_MAPREG_MEM_SIZE(mask);

		/*
		 * Align memory if necessary
		 */
		if (p->size < PCI_MAPREG_IO_SIZE(PCI_MACHDEP_MEM_ALIGN_MASK)) {
		    p->mask = PCI_MACHDEP_MEM_ALIGN_MASK;
		    p->size = PCI_MAPREG_MEM_SIZE(p->mask);
		}

		/*
		 * if memory is already enabled (probably by the console driver)
		 * save the address in order to take care about it later.
		 */
		if (csr & PCI_COMMAND_MEM_ENABLE)
		    p->address = address;

		insert_into_list(&memlist, p);

		if (PCI_MAPREG_MEM_TYPE(mask) == PCI_MAPREG_MEM_TYPE_64BIT)
		    reg++;
	    }
	}


#if defined(_ATARIHW_)
	/*
	 * Both interrupt pin & line are set to the device (== slot)
	 * number. This makes sense on the atari Hades because the
	 * individual slots are hard-wired to a specific MFP-pin.
	 */
	csr  = (DEV2SLOT(dev) << PCI_INTERRUPT_PIN_SHIFT);
	csr |= (DEV2SLOT(dev) << PCI_INTERRUPT_LINE_SHIFT);
	pci_conf_write(pc, tag, PCI_INTERRUPT_REG, csr);
#else
	/*
	 * On the Milan, we accept the BIOS's choice.
	 */
#endif
    }

    /*
     * second step: calculate the memory and I/O addresses beginning from
     * PCI_MEM_START and PCI_IO_START. Care about already mapped areas.
     *
     * begin with memory list
     */

    address = PCI_MEM_START;
    sizecnt = 0;
    membase_1m = 0;
    p = LIST_FIRST(&memlist);
    while (p != NULL) {
	if (!(p->csr & PCI_COMMAND_MEM_ENABLE)) {
	    if (PCI_MAPREG_MEM_TYPE(p->mask) == PCI_MAPREG_MEM_TYPE_32BIT_1M) {
		if (p->size > membase_1m)
		    membase_1m = p->size;
		do {
		    p->address = membase_1m;
		    membase_1m += p->size;
		} while (overlap_pci_areas(LIST_FIRST(&memlist), p, p->address,
					   p->size, PCI_COMMAND_MEM_ENABLE));
		if (membase_1m > 0x00100000) {
		    /*
		     * Should we panic here?
		     */
		    printf("\npcibus0: dev %d reg %d: memory not configured",
			    p->dev, p->reg);
		    p->reg = 0;
		}
	    } else {

		if (sizecnt && (p->size > sizecnt))
		    sizecnt = ((p->size + sizecnt) & p->mask) &
			      PCI_MAPREG_MEM_ADDR_MASK;
		if (sizecnt > address) {
		    address = sizecnt;
		    sizecnt = 0;
		}

		do {
		    p->address = address + sizecnt;
		    sizecnt += p->size;
		} while (overlap_pci_areas(LIST_FIRST(&memlist), p, p->address,
					   p->size, PCI_COMMAND_MEM_ENABLE));

		if ((address + sizecnt) > PCI_MEM_END) {
		    /*
		     * Should we panic here?
		     */
		    printf("\npcibus0: dev %d reg %d: memory not configured",
			    p->dev, p->reg);
		    p->reg = 0;
		}
	    }
	    if (p->reg > 0) {
		pci_conf_write(pc, p->tag, p->reg, p->address);
		csr = pci_conf_read(pc, p->tag, PCI_COMMAND_STATUS_REG);
		csr |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
		pci_conf_write(pc, p->tag, PCI_COMMAND_STATUS_REG, csr);
		p->csr = csr;
	    }
	}
	p = LIST_NEXT(p, link);
    }

    /*
     * now the I/O list
     */

    address = PCI_IO_START;
    sizecnt = 0;
    p = LIST_FIRST(&iolist);
    while (p != NULL) {
	if (!(p->csr & PCI_COMMAND_IO_ENABLE)) {

	    if (sizecnt && (p->size > sizecnt))
		sizecnt = ((p->size + sizecnt) & p->mask) &
			  PCI_MAPREG_IO_ADDR_MASK;
	    if (sizecnt > address) {
		address = sizecnt;
		sizecnt = 0;
	    }

	    do {
		p->address = address + sizecnt;
		sizecnt += p->size;
	    } while (overlap_pci_areas(LIST_FIRST(&iolist), p, p->address,
				       p->size, PCI_COMMAND_IO_ENABLE));

	    if ((address + sizecnt) > PCI_IO_END) {
		/*
		 * Should we panic here?
		 */
		printf("\npcibus0: dev %d reg %d: io not configured",
			p->dev, p->reg);
	    } else {
		pci_conf_write(pc, p->tag, p->reg, p->address);
		csr = pci_conf_read(pc, p->tag, PCI_COMMAND_STATUS_REG);
		csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE;
		pci_conf_write(pc, p->tag, PCI_COMMAND_STATUS_REG, csr);
		p->csr = csr;
	    }
	}
	p = LIST_NEXT(p, link);
    }

#ifdef DEBUG_PCI_MACHDEP
    printf("\nI/O List:\n");
    p = LIST_FIRST(&iolist);

    while (p != NULL) {
	printf("\ndev: %d, reg: 0x%02x, size: 0x%08x, addr: 0x%08x", p->dev,
			p->reg, p->size, p->address);
	p = LIST_NEXT(p, link);
    }
    printf("\nMemlist:");
    p = LIST_FIRST(&memlist);

    while (p != NULL) {
	printf("\ndev: %d, reg: 0x%02x, size: 0x%08x, addr: 0x%08x", p->dev,
			p->reg, p->size, p->address);
	p = LIST_NEXT(p, link);
    }
#endif

    /*
     * Free the lists
     */
    p = LIST_FIRST(&iolist);
    while (p != NULL) {
	q = p;
	LIST_REMOVE(q, link);
	free(p, M_WAITOK);
	p = LIST_FIRST(&iolist);
    }
    p = LIST_FIRST(&memlist);
    while (p != NULL) {
	q = p;
	LIST_REMOVE(q, link);
	free(p, M_WAITOK);
	p = LIST_FIRST(&memlist);
    }
}