예제 #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;
}
예제 #2
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));
}
예제 #3
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);
}
예제 #4
0
파일: pci.c 프로젝트: m943040028/prex
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;
}
예제 #5
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);
}
예제 #6
0
int
pci_mapreg_info(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type,
    bus_addr_t *basep, bus_size_t *sizep, int *flagsp)
{

	if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO)
		return (pci_io_find(pc, tag, reg, type, basep, sizep,
		    flagsp));
	else
		return (pci_mem_find(pc, tag, reg, type, basep, sizep,
		    flagsp));
}
예제 #7
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);
}
예제 #8
0
파일: sti_pci.c 프로젝트: ajinkya93/OpenBSD
/*
 * Decode a BAR register.
 */
int
sti_readbar(struct sti_softc *sc, struct pci_attach_args *pa, u_int region,
    int bar)
{
	bus_addr_t addr;
	bus_size_t size;
	u_int32_t cf;
	int rc;

	if (bar == 0) {
		sc->bases[region] = 0;
		return (0);
	}

#ifdef DIAGNOSTIC
	if (bar < PCI_MAPREG_START || bar > PCI_MAPREG_PPB_END) {
		sti_pci_disable_rom(sc);
		printf("%s: unexpected bar %02x for region %d\n",
		    sc->sc_dev.dv_xname, bar, region);
		sti_pci_enable_rom(sc);
	}
#endif

	cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar);

	if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO)
		rc = pci_io_find(pa->pa_pc, pa->pa_tag, bar, &addr, &size);
	else
		rc = pci_mem_find(pa->pa_pc, pa->pa_tag, bar, &addr, &size,
		    NULL);

	if (rc != 0) {
		sti_pci_disable_rom(sc);
		printf("%s: invalid bar %02x for region %d\n",
		    sc->sc_dev.dv_xname, bar, region);
		sti_pci_enable_rom(sc);
		return (rc);
	}

	sc->bases[region] = addr;
	return (0);
}
예제 #9
0
파일: gcu.c 프로젝트: SylvestreG/bitrig
void
gcu_attach(struct device *parent, struct device *self, void *aux)
{
	struct gcu_softc *sc = (struct gcu_softc *)self;
	struct pci_attach_args *pa = aux;
	int val;

	val = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
	if (PCI_MAPREG_TYPE(val) != PCI_MAPREG_TYPE_MEM) {
		printf(": mmba is not mem space\n");
		return;
	}

	if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_MEM_TYPE(val), 0, &sc->tag, 
	    &sc->handle, &sc->addr, &sc->size, 0)) {
		printf(": cannot find mem space\n");
		return;
	}

	mtx_init(&sc->mdio_mtx, IPL_NET);

	printf("\n");
}
예제 #10
0
/*
 * 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;
}
예제 #11
0
int
pci_mapreg_map(struct pci_attach_args *pa, int reg, pcireg_t type, int busflags,
    bus_space_tag_t *tagp, bus_space_handle_t *handlep, bus_addr_t *basep,
    bus_size_t *sizep, bus_size_t maxsize)
{
	bus_space_tag_t tag;
	bus_space_handle_t handle;
	bus_addr_t base;
	bus_size_t size;
	pcireg_t csr;
	int flags;
	int rv;

	if ((rv = pci_mapreg_info(pa->pa_pc, pa->pa_tag, reg, type,
	    &base, &size, &flags)) != 0)
		return (rv);
	if (base == 0)
		return (EINVAL);	/* disabled because of invalid BAR */

	csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
	if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO)
		csr |= PCI_COMMAND_IO_ENABLE;
	else
		csr |= PCI_COMMAND_MEM_ENABLE;
	/* XXX Should this only be done for devices that do DMA?  */
	csr |= PCI_COMMAND_MASTER_ENABLE;
	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr);

	if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
		if ((pa->pa_flags & PCI_FLAGS_IO_ENABLED) == 0)
			return (EINVAL);
		tag = pa->pa_iot;
	} else {
		if ((pa->pa_flags & PCI_FLAGS_MEM_ENABLED) == 0)
			return (EINVAL);
		tag = pa->pa_memt;
	}

	/* The caller can request limitation of the mapping's size. */
	if (maxsize != 0 && size > maxsize) {
#ifdef DEBUG
		printf("pci_mapreg_map: limited PCI mapping from %lx to %lx\n",
		    (u_long)size, (u_long)maxsize);
#endif
		size = maxsize;
	}

	if (bus_space_map(tag, base, size, busflags | flags, &handle))
		return (1);

	if (tagp != NULL)
		*tagp = tag;
	if (handlep != NULL)
		*handlep = handle;
	if (basep != NULL)
		*basep = base;
	if (sizep != NULL)
		*sizep = size;

	return (0);
}
예제 #12
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 (cpu_comcnprobe(cn, &pa) != 0) {
		return 0;
	}
	puctag = pa.pa_iot;
	pci_decompose_tag(pa.pa_pc, pa.pa_tag, &bus, &maxdev, NULL);

	/* scan through devices */

	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 (!foundport)
		return 0;
	foundport = 0;

	desc = puc_find_description(PCI_VENDOR(pa.pa_id),
	    PCI_PRODUCT(pa.pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys));
	if (desc == NULL) {
		func++;
		goto resume_scan;
	}

	for (i = 0; PUC_PORT_VALID(desc, i); i++)
	{
		if (desc->ports[i].type != PUC_PORT_TYPE_COM)
			continue;
		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)
			continue;
		base = PCI_MAPREG_IO_ADDR(base);
		if (com_is_console(puctag, base, NULL))
			continue;
		foundport = 1;
		break;
	}

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

	cn->cn_pri = CN_REMOTE;
	return PCI_MAPREG_IO_ADDR(base);
}
예제 #13
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
}
예제 #14
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);
	}
}
예제 #15
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"));
}
예제 #16
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);
}
예제 #17
0
파일: pci.c 프로젝트: yazshel/netbsd-kernel
int
pci_probe_device(struct pci_softc *sc, pcitag_t tag,
    int (*match)(const struct pci_attach_args *),
    struct pci_attach_args *pap)
{
	pci_chipset_tag_t pc = sc->sc_pc;
	struct pci_attach_args pa;
	pcireg_t id, /* csr, */ pciclass, intr, bhlcr, bar, endbar;
#ifdef __HAVE_PCI_MSI_MSIX
	pcireg_t cap;
	int off;
#endif
	int ret, pin, bus, device, function, i, width;
	int locs[PCICF_NLOCS];

	pci_decompose_tag(pc, tag, &bus, &device, &function);

	/* a driver already attached? */
	if (sc->PCI_SC_DEVICESC(device, function).c_dev != NULL && !match)
		return 0;

	bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
	if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
		return 0;

	id = pci_conf_read(pc, tag, PCI_ID_REG);
	/* csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); */
	pciclass = pci_conf_read(pc, tag, PCI_CLASS_REG);

	/* Invalid vendor ID value? */
	if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
		return 0;
	/* XXX Not invalid, but we've done this ~forever. */
	if (PCI_VENDOR(id) == 0)
		return 0;

	/* Collect memory range info */
	memset(sc->PCI_SC_DEVICESC(device, function).c_range, 0,
	    sizeof(sc->PCI_SC_DEVICESC(device, function).c_range));
	i = 0;
	switch (PCI_HDRTYPE_TYPE(bhlcr)) {
	case PCI_HDRTYPE_PPB:
		endbar = PCI_MAPREG_PPB_END;
		break;
	case PCI_HDRTYPE_PCB:
		endbar = PCI_MAPREG_PCB_END;
		break;
	default:
		endbar = PCI_MAPREG_END;
		break;
	}
	for (bar = PCI_MAPREG_START; bar < endbar; bar += width) {
		struct pci_range *r;
		pcireg_t type;

		width = 4;
		if (pci_mapreg_probe(pc, tag, bar, &type) == 0)
			continue;

		if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) {
			if (PCI_MAPREG_MEM_TYPE(type) ==
			    PCI_MAPREG_MEM_TYPE_64BIT)
				width = 8;

			r = &sc->PCI_SC_DEVICESC(device, function).c_range[i++];
			if (pci_mapreg_info(pc, tag, bar, type,
			    &r->r_offset, &r->r_size, &r->r_flags) != 0)
				break;
			if ((PCI_VENDOR(id) == PCI_VENDOR_ATI) && (bar == 0x10)
			    && (r->r_size == 0x1000000)) {
				struct pci_range *nr;
				/*
				 * this has to be a mach64
				 * split things up so each half-aperture can
				 * be mapped PREFETCHABLE except the last page
				 * which may contain registers
				 */
				r->r_size = 0x7ff000;
				r->r_flags = BUS_SPACE_MAP_LINEAR |
					     BUS_SPACE_MAP_PREFETCHABLE;
				nr = &sc->PCI_SC_DEVICESC(device,
				    function).c_range[i++];
				nr->r_offset = r->r_offset + 0x800000;
				nr->r_size = 0x7ff000;
				nr->r_flags = BUS_SPACE_MAP_LINEAR |
					      BUS_SPACE_MAP_PREFETCHABLE;
			}
			
		}
	}

	pa.pa_iot = sc->sc_iot;
	pa.pa_memt = sc->sc_memt;
	pa.pa_dmat = sc->sc_dmat;
	pa.pa_dmat64 = sc->sc_dmat64;
	pa.pa_pc = pc;
	pa.pa_bus = bus;
	pa.pa_device = device;
	pa.pa_function = function;
	pa.pa_tag = tag;
	pa.pa_id = id;
	pa.pa_class = pciclass;

	/*
	 * Set up memory, I/O enable, and PCI command flags
	 * as appropriate.
	 */
	pa.pa_flags = sc->sc_flags;

	/*
	 * If the cache line size is not configured, then
	 * clear the MRL/MRM/MWI command-ok flags.
	 */
	if (PCI_CACHELINE(bhlcr) == 0) {
		pa.pa_flags &= ~(PCI_FLAGS_MRL_OKAY|
		    PCI_FLAGS_MRM_OKAY|PCI_FLAGS_MWI_OKAY);
	}

	if (sc->sc_bridgetag == NULL) {
		pa.pa_intrswiz = 0;
		pa.pa_intrtag = tag;
	} else {
		pa.pa_intrswiz = sc->sc_intrswiz + device;
		pa.pa_intrtag = sc->sc_intrtag;
	}

	intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);

	pin = PCI_INTERRUPT_PIN(intr);
	pa.pa_rawintrpin = pin;
	if (pin == PCI_INTERRUPT_PIN_NONE) {
		/* no interrupt */
		pa.pa_intrpin = 0;
	} else {
		/*
		 * swizzle it based on the number of busses we're
		 * behind and our device number.
		 */
		pa.pa_intrpin = 	/* XXX */
		    ((pin + pa.pa_intrswiz - 1) % 4) + 1;
	}
	pa.pa_intrline = PCI_INTERRUPT_LINE(intr);

#ifdef __HAVE_PCI_MSI_MSIX
	if (pci_get_ht_capability(pc, tag, PCI_HT_CAP_MSIMAP, &off, &cap)) {
		/*
		 * XXX Should we enable MSI mapping ourselves on
		 * systems that have it disabled?
		 */
		if (cap & PCI_HT_MSI_ENABLED) {
			uint64_t addr;
			if ((cap & PCI_HT_MSI_FIXED) == 0) {
				addr = pci_conf_read(pc, tag,
				    off + PCI_HT_MSI_ADDR_LO);
				addr |= (uint64_t)pci_conf_read(pc, tag,
				    off + PCI_HT_MSI_ADDR_HI) << 32;
			} else
				addr = PCI_HT_MSI_FIXED_ADDR;

			/*
			 * XXX This will fail to enable MSI on systems
			 * that don't use the canonical address.
			 */
			if (addr == PCI_HT_MSI_FIXED_ADDR) {
				pa.pa_flags |= PCI_FLAGS_MSI_OKAY;
				pa.pa_flags |= PCI_FLAGS_MSIX_OKAY;
			}
		}
	}
#endif

	if (match != NULL) {
		ret = (*match)(&pa);
		if (ret != 0 && pap != NULL)
			*pap = pa;
	} else {
		struct pci_child *c;
		locs[PCICF_DEV] = device;
		locs[PCICF_FUNCTION] = function;

		c = &sc->PCI_SC_DEVICESC(device, function);
		pci_conf_capture(pc, tag, &c->c_conf);
		if (pci_get_powerstate(pc, tag, &c->c_powerstate) == 0)
			c->c_psok = true;
		else
			c->c_psok = false;

		c->c_dev = config_found_sm_loc(sc->sc_dev, "pci", locs, &pa,
					     pciprint, config_stdsubmatch);

		ret = (c->c_dev != NULL);
	}

	return ret;
}
예제 #18
0
/**
 * radeon_driver_load_kms - Main load function for KMS.
 *
 * @dev: drm dev pointer
 * @flags: device flags
 *
 * This is the main load function for KMS (all asics).
 * It calls radeon_device_init() to set up the non-display
 * parts of the chip (asic init, CP, writeback, etc.), and
 * radeon_modeset_init() to set up the display parts
 * (crtcs, encoders, hotplug detect, etc.).
 * Returns 0 on success, error on failure.
 */
void
radeondrm_attach_kms(struct device *parent, struct device *self, void *aux)
{
	struct radeon_device	*rdev = (struct radeon_device *)self;
	struct drm_device	*dev;
	struct pci_attach_args	*pa = aux;
	const struct drm_pcidev *id_entry;
	int			 is_agp;
	pcireg_t		 type;
	uint8_t			 iobar;
#if !defined(__sparc64__)
	pcireg_t		 addr, mask;
	int			 s;
#endif

#if defined(__sparc64__) || defined(__macppc__)
	extern int fbnode;
#endif

	id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
	    PCI_PRODUCT(pa->pa_id), radeondrm_pciidlist);
	rdev->flags = id_entry->driver_data;
	rdev->pc = pa->pa_pc;
	rdev->pa_tag = pa->pa_tag;
	rdev->iot = pa->pa_iot;
	rdev->memt = pa->pa_memt;
	rdev->dmat = pa->pa_dmat;

#if defined(__sparc64__) || defined(__macppc__)
	if (fbnode == PCITAG_NODE(rdev->pa_tag))
		rdev->console = 1;
#else
	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA &&
	    (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG)
	    & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
	    == (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) {
		rdev->console = 1;
#if NVGA > 0
		vga_console_attached = 1;
#endif
	}
#if NEFIFB > 0
	if (efifb_is_console(pa)) {
		rdev->console = 1;
		efifb_cndetach();
	}
#endif
#endif

#define RADEON_PCI_MEM		0x10
#define RADEON_PCI_IO		0x14
#define RADEON_PCI_MMIO		0x18
#define RADEON_PCI_IO2		0x20

	type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM);
	if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
	    pci_mapreg_info(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM,
	    type, &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL)) {
		printf(": can't get frambuffer info\n");
		return;
	}

	if (PCI_MAPREG_MEM_TYPE(type) != PCI_MAPREG_MEM_TYPE_64BIT)
		iobar = RADEON_PCI_IO;
	else
		iobar = RADEON_PCI_IO2;
	
	if (pci_mapreg_map(pa, iobar, PCI_MAPREG_TYPE_IO, 0,
	    NULL, &rdev->rio_mem, NULL, &rdev->rio_mem_size, 0)) {
		printf(": can't map IO space\n");
		return;
	}

	type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MMIO);
	if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
	    pci_mapreg_map(pa, RADEON_PCI_MMIO, type, 0, NULL,
	    &rdev->rmmio, &rdev->rmmio_base, &rdev->rmmio_size, 0)) {
		printf(": can't map mmio space\n");
		return;
	}

#if !defined(__sparc64__)
	/*
	 * Make sure we have a base address for the ROM such that we
	 * can map it later.
	 */
	s = splhigh();
	addr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, ~PCI_ROM_ENABLE);
	mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, addr);
	splx(s);

	if (addr == 0 && PCI_ROM_SIZE(mask) != 0 && pa->pa_memex) {
		bus_size_t size, start, end;
		bus_addr_t base;

		size = PCI_ROM_SIZE(mask);
		start = max(PCI_MEM_START, pa->pa_memex->ex_start);
		end = min(PCI_MEM_END, pa->pa_memex->ex_end);
		if (extent_alloc_subregion(pa->pa_memex, start, end, size,
		    size, 0, 0, 0, &base) == 0)
			pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, base);
	}
#endif

#ifdef notyet
	mtx_init(&rdev->swi_lock, IPL_TTY);
#endif

	/* update BUS flag */
	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL)) {
		rdev->flags |= RADEON_IS_AGP;
	} else if (pci_get_capability(pa->pa_pc, pa->pa_tag,
	    PCI_CAP_PCIEXPRESS, NULL, NULL)) {
		rdev->flags |= RADEON_IS_PCIE;
	} else {
		rdev->flags |= RADEON_IS_PCI;
	}

	DRM_DEBUG("%s card detected\n",
		 ((rdev->flags & RADEON_IS_AGP) ? "AGP" :
		 (((rdev->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));

	is_agp = pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
	    NULL, NULL);

	printf("\n");

	kms_driver.num_ioctls = radeon_max_kms_ioctl;

	dev = (struct drm_device *)drm_attach_pci(&kms_driver, pa, is_agp,
	    rdev->console, self);
	rdev->ddev = dev;
	rdev->pdev = dev->pdev;

	rdev->family = rdev->flags & RADEON_FAMILY_MASK;
	if (!radeon_msi_ok(rdev))
		pa->pa_flags &= ~PCI_FLAGS_MSI_ENABLED;

	rdev->msi_enabled = 0;
	if (pci_intr_map_msi(pa, &rdev->intrh) == 0)
		rdev->msi_enabled = 1;
	else if (pci_intr_map(pa, &rdev->intrh) != 0) {
		printf(": couldn't map interrupt\n");
		return;
	}
	printf("%s: %s\n", rdev->dev.dv_xname,
	    pci_intr_string(pa->pa_pc, rdev->intrh));

	rdev->irqh = pci_intr_establish(pa->pa_pc, rdev->intrh, IPL_TTY,
	    radeon_driver_irq_handler_kms, rdev->ddev, rdev->dev.dv_xname);
	if (rdev->irqh == NULL) {
		printf("%s: couldn't establish interrupt\n",
		    rdev->dev.dv_xname);
		return;
	}

#ifdef __sparc64__
{
	struct rasops_info *ri;
	int node, console;

	node = PCITAG_NODE(pa->pa_tag);
	console = (fbnode == node);

	fb_setsize(&rdev->sf, 8, 1152, 900, node, 0);

	/*
	 * The firmware sets up the framebuffer such that at starts at
	 * an offset from the start of video memory.
	 */
	rdev->fb_offset =
	    bus_space_read_4(rdev->memt, rdev->rmmio, RADEON_CRTC_OFFSET);
	if (bus_space_map(rdev->memt, rdev->fb_aper_offset + rdev->fb_offset,
	    rdev->sf.sf_fbsize, BUS_SPACE_MAP_LINEAR, &rdev->memh)) {
		printf("%s: can't map video memory\n", rdev->dev.dv_xname);
		return;
	}

	ri = &rdev->sf.sf_ro;
	ri->ri_bits = bus_space_vaddr(rdev->memt, rdev->memh);
	ri->ri_hw = rdev;
	ri->ri_updatecursor = NULL;

	fbwscons_init(&rdev->sf, RI_VCONS | RI_WRONLY | RI_BSWAP, console);
	if (console)
		fbwscons_console_init(&rdev->sf, -1);
}
#endif

	rdev->shutdown = true;
	config_mountroot(self, radeondrm_attachhook);
}
예제 #19
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);
}
예제 #20
0
int
pci_mapreg_submap(struct pci_attach_args *pa, int reg, pcireg_t type,
    int busflags, bus_size_t maxsize, bus_size_t offset, bus_space_tag_t *tagp,
	bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep)
{
	bus_space_tag_t tag;
	bus_space_handle_t handle;
	bus_addr_t base;
	bus_size_t size;
	int flags;

	if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
		if ((pa->pa_flags & PCI_FLAGS_IO_ENABLED) == 0)
			return (1);
		if (pci_io_find(pa->pa_pc, pa->pa_tag, reg, type, &base,
		    &size, &flags))
			return (1);
		tag = pa->pa_iot;
	} else {
		if ((pa->pa_flags & PCI_FLAGS_MEM_ENABLED) == 0)
			return (1);
		if (pci_mem_find(pa->pa_pc, pa->pa_tag, reg, type, &base,
		    &size, &flags))
			return (1);
		tag = pa->pa_memt;
	}

	if (reg == PCI_MAPREG_ROM) {
		pcireg_t 	mask;
		int		s;
		/* we have to enable the ROM address decoder... */
		s = splhigh();
		mask = pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
		mask |= PCI_MAPREG_ROM_ENABLE;
		pci_conf_write(pa->pa_pc, pa->pa_tag, reg, mask);
		splx(s);
	}

	/* If we're called with maxsize/offset of 0, behave like 
	 * pci_mapreg_map.
	 */

	maxsize = (maxsize && offset) ? maxsize : size;
	base += offset;

	if ((maxsize < size && offset + maxsize <= size) || offset != 0)
		return (1);

	if (bus_space_map(tag, base, maxsize, busflags | flags, &handle))
		return (1);

	if (tagp != 0)
		*tagp = tag;
	if (handlep != 0)
		*handlep = handle;
	if (basep != 0)
		*basep = base;
	if (sizep != 0)
		*sizep = maxsize;

	return (0);
}
예제 #21
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;
}
예제 #22
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);
}
예제 #23
0
/*
 * int cardbus_mapreg_map(struct cardbus_softc *, int, int, pcireg_t,
 *			  int bus_space_tag_t *, bus_space_handle_t *,
 *			  bus_addr_t *, bus_size_t *)
 *    This function maps bus-space on the value of Base Address
 *   Register (BAR) indexed by the argument `reg' (the second argument).
 *   When the value of the BAR is not valid, such as 0x00000000, a new
 *   address should be allocated for the BAR and new address values is
 *   written on the BAR.
 */
int
cardbus_mapreg_map(struct cardbus_softc *sc, int func, int reg, pcireg_t type, int busflags, bus_space_tag_t *tagp, bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep)
{
	cardbus_chipset_tag_t cc = sc->sc_cc;
	cardbus_function_tag_t cf = sc->sc_cf;
	bus_space_tag_t bustag;
	rbus_tag_t rbustag;
	bus_space_handle_t handle;
	bus_addr_t base;
	bus_size_t size;
	int flags;
	int status = 0;
	pcitag_t tag;

	size = 0;	/* XXX gcc */
	flags = 0;	/* XXX gcc */

	tag = cardbus_make_tag(cc, cf, sc->sc_bus, func);

	DPRINTF(("cardbus_mapreg_map called: %s %x\n", device_xname(sc->sc_dev),
	   type));

	if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
		if (cardbus_io_find(cc, cf, tag, reg, type, &base, &size, &flags)) {
			status = 1;
		}
		bustag = sc->sc_iot;
		rbustag = sc->sc_rbus_iot;
	} else {
		if (cardbus_mem_find(cc, cf, tag, reg, type, &base, &size, &flags)){
			status = 1;
		}
		bustag = sc->sc_memt;
		rbustag = sc->sc_rbus_memt;
	}
	if (status == 0) {
		bus_addr_t mask = size - 1;
		if (base != 0) {
			mask = 0xffffffff;
		}
		if ((*cf->cardbus_space_alloc)(cc, rbustag, base, size, mask,
		    size, busflags | flags, &base, &handle)) {
			panic("io alloc");
		}
	}
	cardbus_conf_write(cc, cf, tag, reg, base);

	DPRINTF(("cardbus_mapreg_map: physaddr %lx\n", (unsigned long)base));

	if (tagp != 0) {
		*tagp = bustag;
	}
	if (handlep != 0) {
		*handlep = handle;
	}
	if (basep != 0) {
		*basep = base;
	}
	if (sizep != 0) {
		*sizep = size;
	}

	return 0;
}
예제 #24
0
파일: cac_pci.c 프로젝트: ryoon/netbsd-xhci
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);
}
예제 #25
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;
}
예제 #26
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");
}
예제 #27
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;
}
예제 #28
0
/**
 * radeon_driver_load_kms - Main load function for KMS.
 *
 * @dev: drm dev pointer
 * @flags: device flags
 *
 * This is the main load function for KMS (all asics).
 * It calls radeon_device_init() to set up the non-display
 * parts of the chip (asic init, CP, writeback, etc.), and
 * radeon_modeset_init() to set up the display parts
 * (crtcs, encoders, hotplug detect, etc.).
 * Returns 0 on success, error on failure.
 */
void
radeondrm_attach_kms(struct device *parent, struct device *self, void *aux)
{
	struct radeon_device	*rdev = (struct radeon_device *)self;
	struct drm_device	*dev;
	struct pci_attach_args	*pa = aux;
	const struct drm_pcidev *id_entry;
	int			 is_agp;
	pcireg_t		 type;
	uint8_t			 iobar;

#if defined(__sparc64__) || defined(__macppc__)
	extern int fbnode;
#endif

	id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
	    PCI_PRODUCT(pa->pa_id), radeondrm_pciidlist);
	rdev->flags = id_entry->driver_data;
	rdev->pc = pa->pa_pc;
	rdev->pa_tag = pa->pa_tag;
	rdev->iot = pa->pa_iot;
	rdev->memt = pa->pa_memt;
	rdev->dmat = pa->pa_dmat;

#if defined(__sparc64__) || defined(__macppc__)
	if (fbnode == PCITAG_NODE(rdev->pa_tag))
		rdev->console = 1;
#else
	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA &&
	    (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG)
	    & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
	    == (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) {
		rdev->console = 1;
#if NVGA > 0
		vga_console_attached = 1;
#endif
	}
#endif

#define RADEON_PCI_MEM		0x10
#define RADEON_PCI_IO		0x14
#define RADEON_PCI_MMIO		0x18
#define RADEON_PCI_IO2		0x20

	type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM);
	if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
	    pci_mapreg_info(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM,
	    type, &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL)) {
		printf(": can't get frambuffer info\n");
		return;
	}

	if (PCI_MAPREG_MEM_TYPE(type) != PCI_MAPREG_MEM_TYPE_64BIT)
		iobar = RADEON_PCI_IO;
	else
		iobar = RADEON_PCI_IO2;
	
	if (pci_mapreg_map(pa, iobar, PCI_MAPREG_TYPE_IO, 0,
	    NULL, &rdev->rio_mem, NULL, &rdev->rio_mem_size, 0)) {
		printf(": can't map IO space\n");
		return;
	}

	type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MMIO);
	if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
	    pci_mapreg_map(pa, RADEON_PCI_MMIO, type, 0, NULL,
	    &rdev->rmmio, &rdev->rmmio_base, &rdev->rmmio_size, 0)) {
		printf(": can't map mmio space\n");
		return;
	}

	if (pci_intr_map(pa, &rdev->intrh) != 0) {
		printf(": couldn't map interrupt\n");
		return;
	}
	printf(": %s\n", pci_intr_string(pa->pa_pc, rdev->intrh));
#ifdef notyet
	mtx_init(&rdev->swi_lock, IPL_TTY);
#endif

	/* update BUS flag */
	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL)) {
		rdev->flags |= RADEON_IS_AGP;
	} else if (pci_get_capability(pa->pa_pc, pa->pa_tag,
	    PCI_CAP_PCIEXPRESS, NULL, NULL)) {
		rdev->flags |= RADEON_IS_PCIE;
	} else {
		rdev->flags |= RADEON_IS_PCI;
	}

	DRM_DEBUG("%s card detected\n",
		 ((rdev->flags & RADEON_IS_AGP) ? "AGP" :
		 (((rdev->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));

	is_agp = pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
	    NULL, NULL);

	dev = (struct drm_device *)drm_attach_pci(&kms_driver, pa, is_agp, self);
	rdev->ddev = dev;

	rdev->irqh = pci_intr_establish(pa->pa_pc, rdev->intrh, IPL_TTY,
	    radeon_driver_irq_handler_kms, rdev->ddev, rdev->dev.dv_xname);
	if (rdev->irqh == NULL) {
		printf("%s: couldn't establish interrupt\n",
		    rdev->dev.dv_xname);
		return;
	}

#ifdef __sparc64__
{
	struct rasops_info *ri;
	int node, console;

	node = PCITAG_NODE(pa->pa_tag);
	console = (fbnode == node);

	fb_setsize(&rdev->sf, 8, 1152, 900, node, 0);

	/*
	 * The firmware sets up the framebuffer such that at starts at
	 * an offset from the start of video memory.
	 */
	rdev->fb_offset =
	    bus_space_read_4(rdev->memt, rdev->rmmio, RADEON_CRTC_OFFSET);
	if (bus_space_map(rdev->memt, rdev->fb_aper_offset + rdev->fb_offset,
	    rdev->sf.sf_fbsize, BUS_SPACE_MAP_LINEAR, &rdev->memh)) {
		printf("%s: can't map video memory\n", rdev->dev.dv_xname);
		return;
	}

	ri = &rdev->sf.sf_ro;
	ri->ri_bits = bus_space_vaddr(rdev->memt, rdev->memh);
	ri->ri_hw = rdev;
	ri->ri_updatecursor = NULL;

	fbwscons_init(&rdev->sf, RI_VCONS | RI_WRONLY | RI_BSWAP, console);
	if (console)
		fbwscons_console_init(&rdev->sf, -1);
}
#endif

	rdev->shutdown = true;
	if (rootvp == NULL)
		mountroothook_establish(radeondrm_attachhook, rdev);
	else
		radeondrm_attachhook(rdev);
}