Example #1
0
int
smfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pcitag_t tag,
    pcireg_t id)
{
	long defattr;
	struct rasops_info *ri;
	bus_space_handle_t fbh, mmioh;
	pcireg_t bar;
	int rc, is5xx;

	/* filter out unrecognized devices */
	switch (id) {
	default:
		return ENODEV;
	case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM712):
		is5xx = 0;
		break;
	case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM501):
		is5xx = 1;
		break;
	}

	smfbcn.is5xx = is5xx;

	bar = pci_conf_read_early(tag, PCI_MAPREG_START);
	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
		return EINVAL;
	rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
	    BUS_SPACE_MAP_LINEAR, &fbh);
	if (rc != 0)
		return rc;

	if (smfbcn.is5xx) {
		bar = pci_conf_read_early(tag, PCI_MAPREG_START + 0x04);
		if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
			return EINVAL;
		rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
		    BUS_SPACE_MAP_LINEAR, &mmioh);
		if (rc != 0)
			return rc;
	} else {
		mmioh = fbh;
	}

	rc = smfb_setup(&smfbcn, memt, fbh, memt, mmioh);
	if (rc != 0)
		return rc;

	ri = &smfbcn.ri;
	ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
	wsdisplay_cnattach(&smfbcn.wsd, ri, 0, 0, defattr);

	return 0;
}
Example #2
0
void
ixp12x0_pci_dma_init(struct ixp12x0_softc *sc)
{
	extern paddr_t physical_start, physical_end;

	bus_dma_tag_t dmat = &sc->ia_pci_dmat;
	struct arm32_dma_range *dr = &sc->ia_pci_dma_range;

	dmat->_ranges = dr;
	dmat->_nranges = 1;

	dr->dr_sysbase = physical_start;
	dr->dr_busbase = PCI_MAPREG_MEM_ADDR(IXP1200_PCI_MEM_BAR +
			 physical_start);
	dr->dr_len = physical_end - physical_start;

	dmat->_dmamap_create = _bus_dmamap_create;
	dmat->_dmamap_destroy = _bus_dmamap_destroy;
	dmat->_dmamap_load = _bus_dmamap_load;
	dmat->_dmamap_load_mbuf = _bus_dmamap_load_mbuf;
	dmat->_dmamap_load_uio = _bus_dmamap_load_uio;
	dmat->_dmamap_load_raw = _bus_dmamap_load_raw;
	dmat->_dmamap_unload = _bus_dmamap_unload;
	dmat->_dmamap_sync_pre = _bus_dmamap_sync;
	dmat->_dmamap_sync_post = NULL;

	dmat->_dmamem_alloc = _bus_dmamem_alloc;
	dmat->_dmamem_free = _bus_dmamem_free;
	dmat->_dmamem_map = _bus_dmamem_map;
	dmat->_dmamem_unmap = _bus_dmamem_unmap;
	dmat->_dmamem_mmap = _bus_dmamem_mmap;
}
Example #3
0
/*
 * i80321_pci_dma_init:
 *
 *	Initialize the PCI DMA tag.
 */
static void
i80321_pci_dma_init(struct i80321_softc *sc)
{
	bus_dma_tag_t dmat = &sc->sc_pci_dmat;
	struct arm32_dma_range *dr = &sc->sc_pci_dma_range;

	dr->dr_sysbase = sc->sc_iwin[2].iwin_xlate;
	dr->dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
	dr->dr_len = sc->sc_iwin[2].iwin_size;

	dmat->_ranges = dr;
	dmat->_nranges = 1;

	dmat->_dmamap_create = _bus_dmamap_create;
	dmat->_dmamap_destroy = _bus_dmamap_destroy;
	dmat->_dmamap_load = _bus_dmamap_load;
	dmat->_dmamap_load_mbuf = _bus_dmamap_load_mbuf;
	dmat->_dmamap_load_uio = _bus_dmamap_load_uio;
	dmat->_dmamap_load_raw = _bus_dmamap_load_raw;
	dmat->_dmamap_unload = _bus_dmamap_unload;
	dmat->_dmamap_sync = _bus_dmamap_sync;

	dmat->_dmamem_alloc = _bus_dmamem_alloc;
	dmat->_dmamem_free = _bus_dmamem_free;
	dmat->_dmamem_map = _bus_dmamem_map;
	dmat->_dmamem_unmap = _bus_dmamem_unmap;
	dmat->_dmamem_mmap = _bus_dmamem_mmap;
}
Example #4
0
bus_addr_t
pciaddr_ioaddr(uint32_t val)
{
	return (PCI_MAPREG_TYPE(val) == PCI_MAPREG_TYPE_MEM)
		? PCI_MAPREG_MEM_ADDR(val)
		: PCI_MAPREG_IO_ADDR(val);
}
Example #5
0
bus_addr_t
pciaddr_ioaddr(u_int32_t val)
{
	return ((PCI_MAPREG_TYPE(val) == PCI_MAPREG_TYPE_MEM)
		? PCI_MAPREG_MEM_ADDR(val)
		: (PCI_MAPREG_IO_ADDR(val) & PCIADDR_PORT_END));
}
Example #6
0
int
pci_func_configure(struct pci_func *f)
{
	uint32_t bar_width;
	uint32_t bar;
	for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END;
	     bar += bar_width)
	{
		uint32_t oldv = pci_conf_read(f, bar);

		bar_width = 4;
		pci_conf_write(f, bar, 0xffffffff);
		uint32_t rv = pci_conf_read(f, bar);

		if (rv == 0)
			continue;

		int regnum = PCI_MAPREG_NUM(bar);
		uint32_t base, size;
		if (PCI_MAPREG_TYPE(rv) == PCI_MAPREG_TYPE_MEM) {
			if (PCI_MAPREG_MEM_TYPE(rv) == PCI_MAPREG_MEM_TYPE_64BIT)
				bar_width = 8;

			size = PCI_MAPREG_MEM_SIZE(rv);
			base = PCI_MAPREG_MEM_ADDR(oldv);
			if (!base) {
				/* device is not properly configured,
				   allocate mmio address for it */
				base = pci_allocate_memory(size);
				if (!base)
					return ENOMEM;
				oldv = base;
			}
#ifdef SHOW_PCI_VERBOSE_INFO
			printf("pci: allocated mem region %d: %d bytes at 0x%x\n",
				regnum, size, base);
#endif
		} else {
#ifdef CONFIG_ARCH_HAS_IO_SPACE
			/* TODO handle IO region */
#endif
		}

		pci_conf_write(f, bar, oldv);
		f->reg_base[regnum] = base;
		f->reg_size[regnum] = size;
	}
	f->irq_line = pci_allocate_irqline();
	/* FIXME */
	f->irq_pin = PCI_INTERRUPT_PIN_C;
	pci_conf_write(f, PCI_INTERRUPT_REG,
		       PCI_INTERRUPT_LINE(f->irq_line) |
		       PCI_INTERRUPT_PIN(f->irq_pin));

	printf("pci: function %02x:%02x.%d (%04x:%04x) configured\n",
		f->bus->busno, f->dev, f->func,
		PCI_VENDOR(f->dev_id), PCI_PRODUCT(f->dev_id));
	return 0;
}
Example #7
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;
}
Example #8
0
void
device_register(struct device *dev, void *aux)
{
#if NPCI > 0
	extern struct cfdriver pci_cd;
#endif
#if NCD > 0 || NSD > 0 || NST > 0
	extern struct cfdriver scsibus_cd;
#endif
	struct confargs *ca = aux;
	static struct device *elder = NULL;

	if (bootdv != NULL)
		return;	/* We already have a winner */

#if NPCI > 0
	if (dev->dv_parent &&
	    dev->dv_parent->dv_cfdata->cf_driver == &pci_cd) {
		struct pci_attach_args *pa = aux;
		pcireg_t addr;
		int reg;

		for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) {
			addr = pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
			if (PCI_MAPREG_TYPE(addr) == PCI_MAPREG_TYPE_IO)
				addr = PCI_MAPREG_IO_ADDR(addr);
			else
				addr = PCI_MAPREG_MEM_ADDR(addr);

			if (addr == (pcireg_t)(u_long)PAGE0->mem_boot.pz_hpa) {
				elder = dev;
				break;
			}
		}
	} else
#endif
	if (ca->ca_hpa == (hppa_hpa_t)PAGE0->mem_boot.pz_hpa) {
		/*
		 * If hpa matches, the only thing we know is that the
		 * booted device is either this one or one of its children.
		 * And the children will not necessarily have the correct
		 * hpa value.
		 * Save this elder for now.
		 */
		elder = dev;
	} else if (elder == NULL) {
		return;	/* not the device we booted from */
	}

	/*
	 * Unfortunately, we can not match on pz_class vs dv_class on
	 * older snakes netbooting using the rbootd protocol.
	 * In this case, we'll end up with pz_class == PCL_RANDOM...
	 * Instead, trust the device class from what the kernel attached
	 * now...
	 */
	switch (dev->dv_class) {
	case DV_IFNET:
		/*
		 * Netboot is the top elder
		 */
		if (elder == dev) {
			bootdv = dev;
		}
		return;
	case DV_DISK:
	case DV_DULL:
		if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_RANDOM)
			return;
		break;
	case DV_TAPE:
		if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_SEQU)
			return;
		break;
	default:
		/* No idea what we were booted from, but better ask the user */
		return;
	}

	/*
	 * If control goes here, we are booted from a block device and we
	 * matched a block device.
	 *
	 * We only grok SCSI boot currently.  Match on proper device
	 * hierarchy and unit/lun values.
	 */

#if NCD > 0 || NSD > 0 || NST > 0
	if (dev->dv_parent &&
	    dev->dv_parent->dv_cfdata->cf_driver == &scsibus_cd) {
		struct scsi_attach_args *sa = aux;
		struct scsi_link *sl = sa->sa_sc_link;

		/*
		 * sd/st/cd is attached to scsibus which is attached to
		 * the controller. Hence the grandparent here should be
		 * the elder.
		 */
		if (dev->dv_parent->dv_parent != elder) {
			return;
		}

		/*
		 * And now check for proper target and lun values
		 */
		if (sl->target == PAGE0->mem_boot.pz_layers[0] &&
		    sl->lun == PAGE0->mem_boot.pz_layers[1]) {
			bootdv = dev;
		}
	}
#endif
}
/*
 * static int cardbus_mem_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_mem_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;

	if (reg != CARDBUS_ROM_REG &&
	    (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))) {
		panic("cardbus_mem_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 (reg != CARDBUS_ROM_REG) {
		/* memory space BAR */

		if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
			printf("cardbus_mem_find: expected type mem, found i/o\n");
			return 1;
		}
		if (PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) {
			printf("cardbus_mem_find: expected mem type %08x, found %08x\n",
			    PCI_MAPREG_MEM_TYPE(type),
			    PCI_MAPREG_MEM_TYPE(address));
			return 1;
		}
	}

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

	switch (PCI_MAPREG_MEM_TYPE(address)) {
	case PCI_MAPREG_MEM_TYPE_32BIT:
	case PCI_MAPREG_MEM_TYPE_32BIT_1M:
		break;
	case PCI_MAPREG_MEM_TYPE_64BIT:
		printf("cardbus_mem_find: 64-bit memory mapping register\n");
		return 1;
	default:
		printf("cardbus_mem_find: reserved mapping register type\n");
		return 1;
	}

	if (basep != 0) {
		*basep = PCI_MAPREG_MEM_ADDR(address);
	}
	if (sizep != 0) {
		*sizep = PCI_MAPREG_MEM_SIZE(mask);
	}
	if (flagsp != 0) {
		*flagsp = PCI_MAPREG_MEM_PREFETCHABLE(address) ?
		    BUS_SPACE_MAP_PREFETCHABLE : 0;
	}

	return 0;
}
Example #10
0
int
iq80321_attach(device_t dev)
{
	struct i80321_softc *sc = device_get_softc(dev);
	int b0u, b0l, b1u, b1l;
	vm_paddr_t memstart = 0;
	vm_size_t memsize = 0;
	int busno;

	/*
	 * Fill in the space tag for the i80321's own devices,
	 * and hand-craft the space handle for it (the device
	 * was mapped during early bootstrap).
	 */
	i80321_bs_init(&i80321_bs_tag, sc);
	sc->sc_st = &i80321_bs_tag;
	sc->sc_sh = IQ80321_80321_VBASE;
	sc->dev = dev;
	sc->sc_is_host = 1;

	/*
	 * Slice off a subregion for the Memory Controller -- we need it
	 * here in order read the memory size.
	 */
	if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
	    VERDE_MCU_SIZE, &sc->sc_mcu_sh))
		panic("%s: unable to subregion MCU registers",
		    device_get_name(dev));

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
	    VERDE_ATU_SIZE, &sc->sc_atu_sh))
		panic("%s: unable to subregion ATU registers",
		    device_get_name(dev));

	/*
	 * We have mapped the PCI I/O windows in the early
	 * bootstrap phase.
	 */
	sc->sc_iow_vaddr = IQ80321_IOW_VBASE;

	/*
	 * Check the configuration of the ATU to see if another BIOS
	 * has configured us.  If a PC BIOS didn't configure us, then:
	 * 	IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
	 * 	IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
	 * If a BIOS has configured us, at least one of those should be
	 * different.  This is pretty fragile, but it's not clear what
	 * would work better.
	 */
	b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0);
	b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4);
	b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8);
	b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc);

#ifdef VERBOSE_INIT_ARM	
	printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
		   b0l,b0u, b1l, b1u );
#endif

#define PCI_MAPREG_MEM_ADDR_MASK	0xfffffff0
	b0l &= PCI_MAPREG_MEM_ADDR_MASK;
	b0u &= PCI_MAPREG_MEM_ADDR_MASK;
	b1l &= PCI_MAPREG_MEM_ADDR_MASK;
	b1u &= PCI_MAPREG_MEM_ADDR_MASK;

#ifdef VERBOSE_INIT_ARM	
	printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
		   b0l,b0u, b1l, b1u );
#endif

	if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0))
		sc->sc_is_host = 0;
	else
		sc->sc_is_host = 1;

	/* FIXME: i force it's */	

#ifdef CPU_XSCALE_80219
	sc->sc_is_host = 1;
#endif
	
	i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);
	/*
	 * We set up the Inbound Windows as follows:
	 *
	 *	0	Access to i80321 PMMRs
	 *
	 *	1	Reserve space for private devices
	 *
	 *	2	RAM access
	 *
	 *	3	Unused.
	 *
	 * This chunk needs to be customized for each IOP321 application.
	 */
#if 0
	sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE;
	sc->sc_iwin[0].iwin_base_hi = 0;
	sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE;
	sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE;
#endif
	if (sc->sc_is_host) {
		
		/* Map PCI:Local 1:1. */
		sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
		sc->sc_iwin[1].iwin_base_hi = 0;
	} else {
		
		sc->sc_iwin[1].iwin_base_lo = 0;
		sc->sc_iwin[1].iwin_base_hi = 0;
	}
	sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
	sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;
	
	if (sc->sc_is_host) {
		sc->sc_iwin[2].iwin_base_lo = memstart |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
		sc->sc_iwin[2].iwin_base_hi = 0;
	} else {
		sc->sc_iwin[2].iwin_base_lo = 0;
		sc->sc_iwin[2].iwin_base_hi = 0;
	}
	sc->sc_iwin[2].iwin_xlate = memstart;
	sc->sc_iwin[2].iwin_size = memsize;

	if (sc->sc_is_host) {
		sc->sc_iwin[3].iwin_base_lo = 0 |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
	} else {
		sc->sc_iwin[3].iwin_base_lo = 0;
	}
	sc->sc_iwin[3].iwin_base_hi = 0;
	sc->sc_iwin[3].iwin_xlate = 0;
	sc->sc_iwin[3].iwin_size = 0;
	
#ifdef 	VERBOSE_INIT_ARM
	printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
		   sc->sc_iwin[1].iwin_base_hi,
		   sc->sc_iwin[1].iwin_base_lo,
		   sc->sc_iwin[1].iwin_xlate,
		   sc->sc_iwin[1].iwin_size
		);
	printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
		   sc->sc_iwin[2].iwin_base_hi,
		   sc->sc_iwin[2].iwin_base_lo,
		   sc->sc_iwin[2].iwin_xlate,
		   sc->sc_iwin[2].iwin_size
		);
#endif

	/*
	 * We set up the Outbound Windows as follows:
	 *
	 *	0	Access to private PCI space.
	 *
	 *	1	Unused.
	 */
#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
	sc->sc_owin[0].owin_xlate_lo =
    	    PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
	sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
	/*
	 * Set the Secondary Outbound I/O window to map
	 * to PCI address 0 for all 64K of the I/O space.
	 */
	sc->sc_ioout_xlate = 0;
	i80321_attach(sc);
	i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate;
	i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
	i80321_dr.dr_len = sc->sc_iwin[2].iwin_size;
	dma_range_init = 1;
	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;
	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
	sc->sc_irq_rman.rm_descr = "i80321 IRQs";
	if (rman_init(&sc->sc_irq_rman) != 0 ||
	    rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0)
		panic("i80321_attach: failed to set up IRQ rman");

	device_add_child(dev, "obio", 0);
	device_add_child(dev, "itimer", 0);
	device_add_child(dev, "iopwdog", 0);
#ifndef 	CPU_XSCALE_80219
	device_add_child(dev, "iqseg", 0);
#endif	
	device_add_child(dev, "pcib", busno);
	device_add_child(dev, "i80321_dma", 0);
	device_add_child(dev, "i80321_dma", 1);
#ifndef CPU_XSCALE_80219	
	device_add_child(dev, "i80321_aau", 0);
#endif
	bus_generic_probe(dev);
	bus_generic_attach(dev);

	return (0);
}
Example #11
0
void
hdlg_mainbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct i80321_softc *sc = (void *) self;
	pcireg_t b0u, b0l, b1u, b1l;
	paddr_t memstart;
	psize_t memsize;

	hdlg_mainbus_found = 1;

	/*
	 * Fill in the space tag for the i80321's own devices,
	 * and hand-craft the space handle for it (the device
	 * was mapped during early bootstrap).
	 */
	i80321_bs_init(&i80321_bs_tag, sc);
	sc->sc_st = &i80321_bs_tag;
	sc->sc_sh = HDLG_80321_VBASE;

	/*
	 * Slice off a subregion for the Memory Controller -- we need it
	 * here in order read the memory size.
	 */
	if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
	    VERDE_MCU_SIZE, &sc->sc_mcu_sh))
		panic("%s: unable to subregion MCU registers",
		    device_xname(&sc->sc_dev));

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
	    VERDE_ATU_SIZE, &sc->sc_atu_sh))
		panic("%s: unable to subregion ATU registers",
		    device_xname(&sc->sc_dev));

	/*
	 * We have mapped the PCI I/O windows in the early bootstrap phase.
	 */
	sc->sc_iow_vaddr = HDLG_IOW_VBASE;

	/*
	 * Check the configuration of the ATU to see if another BIOS
	 * has configured us.  If a PC BIOS didn't configure us, then:
	 * 	IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
	 * 	IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
	 * If a BIOS has configured us, at least one of those should be
	 * different.  This is pretty fragile, but it's not clear what
	 * would work better.
	 */
	b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START+0x0);
	b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START+0x4);
	b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START+0x8);
	b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START+0xc);
	b0l &= PCI_MAPREG_MEM_ADDR_MASK;
	b0u &= PCI_MAPREG_MEM_ADDR_MASK;
	b1l &= PCI_MAPREG_MEM_ADDR_MASK;
	b1u &= PCI_MAPREG_MEM_ADDR_MASK;

	if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0))
		sc->sc_is_host = 0;
	else
		sc->sc_is_host = 1;

	aprint_naive(": i80219 I/O Processor\n");
	aprint_normal(": i80219 I/O Processor, acting as PCI %s\n",
	    sc->sc_is_host ? "host" : "slave");

	i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);

	/*
	 * We set up the Inbound Windows as follows:
	 *
	 *	0	Access to i80219 PMMRs
	 *
	 *	1	Reserve space for private devices
	 *
	 *	2	RAM access
	 *
	 *	3	Unused.
	 *
	 * This chunk needs to be customized for each IOP321 application.
	 */
#if 0
	sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE;
	sc->sc_iwin[0].iwin_base_hi = 0;
	sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE;
	sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE;
#endif

	if (sc->sc_is_host) {
		/* Map PCI:Local 1:1. */
		sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
		sc->sc_iwin[1].iwin_base_hi = 0;
	} else {
		sc->sc_iwin[1].iwin_base_lo = 0;
		sc->sc_iwin[1].iwin_base_hi = 0;
	}
	sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
	sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;

	if (sc->sc_is_host) {
		sc->sc_iwin[2].iwin_base_lo = memstart |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
		sc->sc_iwin[2].iwin_base_hi = 0;
	} else {
		sc->sc_iwin[2].iwin_base_lo = 0;
		sc->sc_iwin[2].iwin_base_hi = 0;
	}
	sc->sc_iwin[2].iwin_xlate = memstart;
	sc->sc_iwin[2].iwin_size = memsize;

	if (sc->sc_is_host) {
		sc->sc_iwin[3].iwin_base_lo = 0 |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
	} else {
		sc->sc_iwin[3].iwin_base_lo = 0;
	}
	sc->sc_iwin[3].iwin_base_hi = 0;
	sc->sc_iwin[3].iwin_xlate = 0;
	sc->sc_iwin[3].iwin_size = 0;

	/*
	 * We set up the Outbound Windows as follows:
	 *
	 *	0	Access to private PCI space.
	 *
	 *	1	Unused.
	 */
	sc->sc_owin[0].owin_xlate_lo =
	    PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
	sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;

	/*
	 * Set the Secondary Outbound I/O window to map
	 * to PCI address 0 for all 64K of the I/O space.
	 */
	sc->sc_ioout_xlate = 0;
	sc->sc_ioout_xlate_offset = 0x1000;

	/*
	 * Initialize the interrupt part of our PCI chipset tag.
	 */
	hdlg_pci_init(&sc->sc_pci_chipset, sc);

	i80321_attach(sc);
}
Example #12
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"));
}
Example #13
0
static void
iop_pci_attach(device_t parent, device_t self, void *aux)
{
	struct pci_attach_args *pa;
	struct iop_softc *sc;
	pci_chipset_tag_t pc;
	pci_intr_handle_t ih;
	const char *intrstr;
	pcireg_t reg;
	int i;
	char intrbuf[PCI_INTRSTR_LEN];

	sc = device_private(self);
	sc->sc_dev = self;
	pa = aux;
	pc = pa->pa_pc;
	printf(": ");

	/*
	 * The kernel always uses the first memory mapping to communicate
	 * with the IOP.
	 */
	for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) {
		reg = pci_conf_read(pc, pa->pa_tag, i);
		if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_MEM) {
			sc->sc_memaddr = PCI_MAPREG_MEM_ADDR(reg);
			break;
		}
	}
	if (i == PCI_MAPREG_END) {
		printf("can't find mapping\n");
		return;
	}

	/* Map the register window. */
	if (pci_mapreg_map(pa, i, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_iot,
	    &sc->sc_ioh, NULL, NULL)) {
		aprint_error_dev(self, "can't map register window\n");
		return;
	}

	/* Map the 2nd register window. */
	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_DPT &&
	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DPT_RAID_2005S) {
		i += 4;	/* next BAR */
		if (i == PCI_MAPREG_END) {
			printf("can't find mapping\n");
			return;
		}

#if 0
		/* Should we check it? (see FreeBSD's asr driver) */
		reg = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
		printf("subid %x, %x\n", PCI_VENDOR(reg), PCI_PRODUCT(reg));
#endif
		if (pci_mapreg_map(pa, i, PCI_MAPREG_TYPE_MEM, 0,
		    &sc->sc_msg_iot, &sc->sc_msg_ioh, NULL, NULL)) {
			aprint_error_dev(self, "can't map 2nd register window\n");
			return;
		}
	} else {
		/* iop devices other than 2005S */
		sc->sc_msg_iot = sc->sc_iot;
		sc->sc_msg_ioh = sc->sc_ioh;
	}

	sc->sc_pcibus = pa->pa_bus;
	sc->sc_pcidev = pa->pa_device;
	sc->sc_dmat = pa->pa_dmat;
	sc->sc_bus_memt = pa->pa_memt;
	sc->sc_bus_iot = pa->pa_iot;

	/* 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)) {
		printf("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, iop_intr, sc);
	if (sc->sc_ih == NULL) {
		printf("can't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		return;
	}

	/* Attach to the bus-independent code. */
	iop_init(sc, intrstr);
}
Example #14
0
int
obsd_pci_mem_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, address1 = 0, mask1 = 0xffffffff, csr;
	u_int64_t waddress, wmask;
	int s, is64bit;

	is64bit = (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT);

	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_mem_find: bad request");

	if (is64bit && (reg + 4) >= PCI_MAPREG_END)
		panic("pci_mem_find: bad 64-bit 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 while
	 * the device is disabled and see what we get back.
	 */
	s = splhigh();
	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
	if (csr & PCI_COMMAND_MEM_ENABLE)
		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
		    csr & ~PCI_COMMAND_MEM_ENABLE);
	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 (is64bit) {
		address1 = pci_conf_read(pc, tag, reg + 4);
		pci_conf_write(pc, tag, reg + 4, 0xffffffff);
		mask1 = pci_conf_read(pc, tag, reg + 4);
		pci_conf_write(pc, tag, reg + 4, address1);
	}
	if (csr & PCI_COMMAND_MEM_ENABLE)
		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
	splx(s);

	if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
#ifdef DEBUG
		printf("pci_mem_find: expected type mem, found i/o\n");
#endif
		return (EINVAL);
	}
	if (type != -1 && 
	    PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) {
#ifdef DEBUG
		printf("pci_mem_find: expected mem type %08x, found %08x\n",
		    PCI_MAPREG_MEM_TYPE(type),
		    PCI_MAPREG_MEM_TYPE(address));
#endif
		return (EINVAL);
	}

	waddress = (u_int64_t)address1 << 32UL | address;
	wmask = (u_int64_t)mask1 << 32UL | mask;

	if ((is64bit && PCI_MAPREG_MEM64_SIZE(wmask) == 0) ||
	    (!is64bit && PCI_MAPREG_MEM_SIZE(mask) == 0)) {
#ifdef DEBUG
		printf("pci_mem_find: void region\n");
#endif
		return (ENOENT);
	}

	switch (PCI_MAPREG_MEM_TYPE(address)) {
	case PCI_MAPREG_MEM_TYPE_32BIT:
	case PCI_MAPREG_MEM_TYPE_32BIT_1M:
		break;
	case PCI_MAPREG_MEM_TYPE_64BIT:
		/*
		 * Handle the case of a 64-bit memory register on a
		 * platform with 32-bit addressing.  Make sure that
		 * the address assigned and the device's memory size
		 * fit in 32 bits.  We implicitly assume that if
		 * bus_addr_t is 64-bit, then so is bus_size_t.
		 */
		if (sizeof(u_int64_t) > sizeof(bus_addr_t) &&
		    (address1 != 0 || mask1 != 0xffffffff)) {
#ifdef DEBUG
			printf("pci_mem_find: 64-bit memory map which is "
			    "inaccessible on a 32-bit platform\n");
#endif
			return (EINVAL);
		}
		break;
	default:
#ifdef DEBUG
		printf("pci_mem_find: reserved mapping register type\n");
#endif
		return (EINVAL);
	}

	if (sizeof(u_int64_t) > sizeof(bus_addr_t)) {
		if (basep != 0)
			*basep = PCI_MAPREG_MEM_ADDR(address);
		if (sizep != 0)
			*sizep = PCI_MAPREG_MEM_SIZE(mask);
	} else {
		if (basep != 0)
			*basep = PCI_MAPREG_MEM64_ADDR(waddress);
		if (sizep != 0)
			*sizep = PCI_MAPREG_MEM64_SIZE(wmask);
	}
	if (flagsp != 0)
		*flagsp =
#ifdef BUS_SPACE_MAP_PREFETCHABLE
		    PCI_MAPREG_MEM_PREFETCHABLE(address) ?
		      BUS_SPACE_MAP_PREFETCHABLE :
#endif
		  0;

	return (0);
}
static int
pci_mem_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, address1 = 0, mask1 = 0xffffffff;
	u_int64_t waddress, wmask;
	int s, is64bit, isrom;

	is64bit = (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT);
	isrom = (reg == PCI_MAPREG_ROM);

	if ((!isrom) && (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_mem_find: bad request");

	if (is64bit && (reg + 4) >= PCI_MAPREG_END)
		panic("pci_mem_find: bad 64-bit 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);
	if (is64bit) {
		address1 = pci_conf_read(pc, tag, reg + 4);
		pci_conf_write(pc, tag, reg + 4, 0xffffffff);
		mask1 = pci_conf_read(pc, tag, reg + 4);
		pci_conf_write(pc, tag, reg + 4, address1);
	}
	splx(s);

	if (!isrom) {
		/*
		 * roms should have an enable bit instead of a memory
		 * type decoder bit.  For normal BARs, make sure that
		 * the address decoder type matches what we asked for.
		 */
		if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
			printf("pci_mem_find: expected type mem, found i/o\n");
			return (1);
		}
		/* XXX Allow 64bit bars for 32bit requests.*/
		if (PCI_MAPREG_MEM_TYPE(address) !=
		    PCI_MAPREG_MEM_TYPE(type) &&
		    PCI_MAPREG_MEM_TYPE(address) !=
		    PCI_MAPREG_MEM_TYPE_64BIT) {
			printf("pci_mem_find: "
			    "expected mem type %08x, found %08x\n",
			    PCI_MAPREG_MEM_TYPE(type),
			    PCI_MAPREG_MEM_TYPE(address));
			return (1);
		}
	}

	waddress = (u_int64_t)address1 << 32UL | address;
	wmask = (u_int64_t)mask1 << 32UL | mask;

	if ((is64bit && PCI_MAPREG_MEM64_SIZE(wmask) == 0) ||
	    (!is64bit && PCI_MAPREG_MEM_SIZE(mask) == 0)) {
		aprint_debug("pci_mem_find: void region\n");
		return (1);
	}

	switch (PCI_MAPREG_MEM_TYPE(address)) {
	case PCI_MAPREG_MEM_TYPE_32BIT:
	case PCI_MAPREG_MEM_TYPE_32BIT_1M:
		break;
	case PCI_MAPREG_MEM_TYPE_64BIT:
		/*
		 * Handle the case of a 64-bit memory register on a
		 * platform with 32-bit addressing.  Make sure that
		 * the address assigned and the device's memory size
		 * fit in 32 bits.  We implicitly assume that if
		 * bus_addr_t is 64-bit, then so is bus_size_t.
		 */
		if (sizeof(u_int64_t) > sizeof(bus_addr_t) &&
		    (address1 != 0 || mask1 != 0xffffffff)) {
			printf("pci_mem_find: 64-bit memory map which is "
			    "inaccessible on a 32-bit platform\n");
			return (1);
		}
		break;
	default:
		printf("pci_mem_find: reserved mapping register type\n");
		return (1);
	}

	if (sizeof(u_int64_t) > sizeof(bus_addr_t)) {
		if (basep != 0)
			*basep = PCI_MAPREG_MEM_ADDR(address);
		if (sizep != 0)
			*sizep = PCI_MAPREG_MEM_SIZE(mask);
	} else {
		if (basep != 0)
			*basep = PCI_MAPREG_MEM64_ADDR(waddress);
		if (sizep != 0)
			*sizep = PCI_MAPREG_MEM64_SIZE(wmask);
	}
	if (flagsp != 0)
		*flagsp = (isrom || PCI_MAPREG_MEM_PREFETCHABLE(address)) ?
		    BUS_SPACE_MAP_PREFETCHABLE : 0;

	return (0);
}
Example #16
0
static void
puc_attach(device_t parent, device_t self, void *aux)
{
	struct puc_softc *sc = device_private(self);
	struct pci_attach_args *pa = aux;
	struct puc_attach_args paa;
	pci_intr_handle_t intrhandle;
	pcireg_t subsys;
	int i, barindex;
	bus_addr_t base;
	bus_space_tag_t tag;
#ifdef PUCCN
	bus_space_handle_t ioh;
#endif
	int locs[PUCCF_NLOCS];

	subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
	sc->sc_desc = puc_find_description(PCI_VENDOR(pa->pa_id),
	    PCI_PRODUCT(pa->pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys));
	if (sc->sc_desc == NULL) {
		/*
		 * This was a class/subclass match, so tell people to compile
		 * kernel with options that cause this driver to spew.
		 */
#ifdef PUC_PRINT_REGS
		printf(":\n");
		pci_conf_print(pa->pa_pc, pa->pa_tag, NULL);
#else
		printf(": unknown PCI communications device\n");
		printf("%s: compile kernel with PUC_PRINT_REGS and larger\n",
		    device_xname(self));
		printf("%s: mesage buffer (via 'options MSGBUFSIZE=...'),\n",
		    device_xname(self));
		printf("%s: and report the result with send-pr\n",
		    device_xname(self));
#endif
		return;
	}

	printf(": %s (", sc->sc_desc->name);
	for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++)
		printf("%s%s", i ? ", " : "",
		    puc_port_type_name(sc->sc_desc->ports[i].type));
	printf(")\n");

	for (i = 0; i < 6; i++) {
		pcireg_t bar, type;

		sc->sc_bar_mappings[i].mapped = 0;

		bar = pci_conf_read(pa->pa_pc, pa->pa_tag,
		    PCI_MAPREG_START + 4 * i);	/* XXX const */
		if (bar == 0)			/* BAR not implemented(?) */
			continue;

		type = (PCI_MAPREG_TYPE(bar) == PCI_MAPREG_TYPE_IO ?
		    PCI_MAPREG_TYPE_IO : PCI_MAPREG_MEM_TYPE(bar));

		if (type == PCI_MAPREG_TYPE_IO) {
			tag = pa->pa_iot;
			base =  PCI_MAPREG_IO_ADDR(bar);
		} else {
			tag = pa->pa_memt;
			base =  PCI_MAPREG_MEM_ADDR(bar);
		}
#ifdef PUCCN
		if (com_is_console(tag, base, &ioh)) {
			sc->sc_bar_mappings[i].mapped = 1;
			sc->sc_bar_mappings[i].a = base;
			sc->sc_bar_mappings[i].s = COM_NPORTS;
			sc->sc_bar_mappings[i].t = tag;
			sc->sc_bar_mappings[i].h = ioh;
			continue;
		}
#endif
		sc->sc_bar_mappings[i].mapped = (pci_mapreg_map(pa,
		    PCI_MAPREG_START + 4 * i, type, 0,
		    &sc->sc_bar_mappings[i].t, &sc->sc_bar_mappings[i].h,
		    &sc->sc_bar_mappings[i].a, &sc->sc_bar_mappings[i].s)
		      == 0);
		if (sc->sc_bar_mappings[i].mapped)
			continue;

		aprint_error_dev(self, "couldn't map BAR at offset 0x%lx\n",
		    (long)(PCI_MAPREG_START + 4 * i));
	}

	/* Map interrupt. */
	if (pci_intr_map(pa, &intrhandle)) {
		aprint_error_dev(self, "couldn't map interrupt\n");
		return;
	}
	/*
	 * XXX the sub-devices establish the interrupts, for the
	 * XXX following reasons:
	 * XXX
	 * XXX    * we can't really know what IPLs they'd want
	 * XXX
	 * XXX    * the MD dispatching code can ("should") dispatch
	 * XXX      chained interrupts better than we can.
	 * XXX
	 * XXX It would be nice if we could indicate to the MD interrupt
	 * XXX handling code that the interrupt line used by the device
	 * XXX was a PCI (level triggered) interrupt.
	 * XXX
	 * XXX It's not pretty, but hey, what is?
	 */

	/* Configure each port. */
	for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
		bus_space_handle_t subregion_handle;

		/* make sure the base address register is mapped */
		barindex = PUC_PORT_BAR_INDEX(sc->sc_desc->ports[i].bar);
		if (!sc->sc_bar_mappings[barindex].mapped) {
			printf("%s: %s port uses unmapped BAR (0x%x)\n",
			    device_xname(self),
			    puc_port_type_name(sc->sc_desc->ports[i].type),
			    sc->sc_desc->ports[i].bar);
			continue;
		}

		/* set up to configure the child device */
		paa.port = i;
		paa.type = sc->sc_desc->ports[i].type;
		paa.flags = sc->sc_desc->ports[i].flags;
		paa.pc = pa->pa_pc;
		paa.tag = pa->pa_tag;
		paa.intrhandle = intrhandle;
		paa.a = sc->sc_bar_mappings[barindex].a;
		paa.t = sc->sc_bar_mappings[barindex].t;
		paa.dmat = pa->pa_dmat;
		paa.dmat64 = pa->pa_dmat64;

		if (
#ifdef PUCCN
		    !com_is_console(sc->sc_bar_mappings[barindex].t,
		    sc->sc_bar_mappings[barindex].a, &subregion_handle)
		   &&
#endif
		    bus_space_subregion(sc->sc_bar_mappings[barindex].t,
		    sc->sc_bar_mappings[barindex].h,
		    sc->sc_desc->ports[i].offset,
		    sc->sc_bar_mappings[barindex].s -
		      sc->sc_desc->ports[i].offset,
		    &subregion_handle) != 0) {
			aprint_error_dev(self, "couldn't get subregion for port %d\n", i);
			continue;
		}
		paa.h = subregion_handle;

#if 0
		printf("%s: port %d: %s @ (index %d) 0x%x (0x%lx, 0x%lx)\n",
		    device_xname(self), paa.port,
		    puc_port_type_name(paa.type), barindex, (int)paa.a,
		    (long)paa.t, (long)paa.h);
#endif

		locs[PUCCF_PORT] = i;

		/* and configure it */
		sc->sc_ports[i].dev = config_found_sm_loc(self, "puc", locs,
			&paa, puc_print, config_stdsubmatch);
	}
}
Example #17
0
static bus_addr_t
pucprobe_doit(struct consdev *cn)
{
	struct pci_attach_args pa;
	int bus;
	static int dev = 0, func = 0;
	int maxdev, nfunctions = 0, i; /* XXX */
	pcireg_t reg, bhlcr, subsys = 0; /* XXX */
	int foundport = 0;
	const struct puc_device_description *desc;
	pcireg_t base;

	/* Fetch our tags */
#if defined(amd64) || defined(i386)
	if (cpu_puc_cnprobe(cn, &pa) != 0)
#endif
		return 0;

	pci_decompose_tag(pa.pa_pc, pa.pa_tag, &bus, &maxdev, NULL);

	/* Scan through devices and find a communication class device. */
	for (; dev <= maxdev ; dev++) {
		pa.pa_tag = pci_make_tag(pa.pa_pc, bus, dev, 0);
		reg = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_ID_REG);
		if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID
		    || PCI_VENDOR(reg) == 0)
			continue;
		bhlcr = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_BHLC_REG);
		if (PCI_HDRTYPE_MULTIFN(bhlcr)) {
			nfunctions = 8;
		} else {
			nfunctions = 1;
		}
resume_scan:
		for (; func < nfunctions; func++)  {
			pa.pa_tag = pci_make_tag(pa.pa_pc, bus, dev, func);
			reg = pci_conf_read(pa.pa_pc, pa.pa_tag,
			    PCI_CLASS_REG);
			if (PCI_CLASS(reg)  == PCI_CLASS_COMMUNICATIONS
			    && PCI_SUBCLASS(reg)
			       == PCI_SUBCLASS_COMMUNICATIONS_SERIAL) {
				pa.pa_id = pci_conf_read(pa.pa_pc, pa.pa_tag,
				    PCI_ID_REG);
				subsys = pci_conf_read(pa.pa_pc, pa.pa_tag,
				    PCI_SUBSYS_ID_REG);
				foundport = 1;
				break;
			}
		}
		if (foundport)
			break;

		func = 0;
	}

	/*
	 * If all devices was scanned and couldn't find any communication
	 * device, return with 0.
	 */
	if (!foundport)
		return 0;

	/* Clear foundport flag */
	foundport = 0;

	/* Check whether the device is in the puc device table or not */
	desc = puc_find_description(PCI_VENDOR(pa.pa_id),
	    PCI_PRODUCT(pa.pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys));

	/* If not, check the next communication device */
	if (desc == NULL) {
		/* Resume from the next function */
		func++;
		goto resume_scan;
	}

	/*
	 * We found a device and it's on the puc table. Set the tag and
	 * the base address.
	 */
	for (i = 0; PUC_PORT_VALID(desc, i); i++) {
		if (desc->ports[i].type != PUC_PORT_TYPE_COM)
			continue;
		puccnflags = desc->ports[i].flags;
		base = pci_conf_read(pa.pa_pc, pa.pa_tag, desc->ports[i].bar);
		base += desc->ports[i].offset;

		if (PCI_MAPREG_TYPE(base) == PCI_MAPREG_TYPE_IO) {
			puctag = pa.pa_iot;
			base = PCI_MAPREG_IO_ADDR(base);
		}
#if 0 /* For MMIO device */
		else {
			puctag = pa.pa_memt;
			base = PCI_MAPREG_MEM_ADDR(base);
		}
#endif

		if (com_is_console(puctag, base, NULL))
			continue;
		foundport = 1;
		break;
	}

	if (foundport == 0) {
		func++;
		goto resume_scan;
	}

#if 0
	cn->cn_pri = CN_REMOTE;
#else
	if (cn)
		cn->cn_pri = CN_REMOTE;
#endif
	return base;
}