Ejemplo n.º 1
0
/*
 * PCI resource handling
 */
struct extent *
octeon_pcibus_get_resource_extent(pci_chipset_tag_t pc, int io)
{
	struct octeon_pcibus_softc *sc = pc->pc_conf_v;
	struct extent *ex;
	char *exname;
	int exnamesz;
	int errors;

	exnamesz = 1 + 16 + 4;
	exname = (char *)malloc(exnamesz, M_DEVBUF, M_NOWAIT);
	if (exname == NULL)
		return NULL;
	snprintf(exname, exnamesz, "%s%s", sc->sc_dev.dv_xname,
	    io ? "_io" : "_mem");

	ex = extent_create(exname, 0, 0xffffffffffffffff, M_DEVBUF, NULL, 0,
	    EX_NOWAIT | EX_FILLED);
	if (ex == NULL)
		goto out;

	exname = NULL;
	errors = 0;
	if (io) {
		if (extent_free(ex, _OCTEON_PCIBUS_PCIIO_BASE, _OCTEON_PCIBUS_PCIIO_SIZE,
		    EX_NOWAIT) != 0)
			errors++;
	} else {
		if (extent_free(ex, _OCTEON_PCIBUS_PCIMEM_BASE, _OCTEON_PCIBUS_PCIMEM_SIZE,
		    EX_NOWAIT) != 0)
			errors++;
	}

	if (errors != 0) {
		extent_destroy(ex);
		ex = NULL;
	}

#ifdef OCTEON_PCIBUS_DEBUG
	extent_print(ex);
#endif

out:
	if (exname != NULL)
		free(exname, M_DEVBUF);

	return ex;
}
Ejemplo n.º 2
0
void 
_bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
{
	bus_dma_segment_t *segs;
	vaddr_t dva;
	vsize_t sgsize;
	int error, s;

#ifdef DIAGNOSTIC
	if (map->dm_nsegs != 1)
		panic("%s: invalid nsegs = %d", __func__, map->dm_nsegs);
#endif

	segs = map->dm_segs;
	dva = segs[0]._ds_va & ~PGOFSET;
	sgsize = segs[0]._ds_sgsize;

	/* Unmap the DVMA addresses. */
	pmap_remove(pmap_kernel(), dva, dva + sgsize);
	pmap_update(pmap_kernel());

	/* Free the DVMA addresses. */
	s = splvm();
	error = extent_free(dvma_extent, dva, sgsize, EX_NOWAIT);
	splx(s);
#ifdef DIAGNOSTIC
	if (error)
		panic("%s: unable to free DVMA region", __func__);
#endif

	/* Mark the mappings as invalid. */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;
}
Ejemplo n.º 3
0
void
__C(CHIP,_mem_unmap)(
    void *v,
    bus_space_handle_t memh,
    bus_size_t memsize,
    int acct)
{
    bus_addr_t memaddr;
    int error;

    if (acct == 0)
        return;

#ifdef EXTENT_DEBUG
    printf("mem: freeing handle 0x%lx for 0x%lx\n", memh, memsize);
#endif

    memaddr = memh - ALPHA_PHYS_TO_K0SEG(CHIP_MEM_SYS_START(v));

#ifdef EXTENT_DEBUG
    printf("mem: freeing 0x%lx to 0x%lx\n", memaddr, memaddr + memsize - 1);
#endif

    error = extent_free(CHIP_MEM_EXTENT(v), memaddr, memsize,
                        EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
    if (error) {
        printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
               __S(__C(CHIP,_mem_unmap)), memaddr, memaddr + memsize - 1,
               error);
#ifdef EXTENT_DEBUG
        extent_print(CHIP_MEM_EXTENT(v));
#endif
    }
}
Ejemplo n.º 4
0
int
mbus_alloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
    bus_size_t align, bus_size_t boundary, int flags,
    bus_addr_t *addrp, bus_space_handle_t *bshp)
{
	bus_addr_t bpa;
	int error;

	rstart &= HPPA_PHYSMAP;
	rend &= HPPA_PHYSMAP;
	if (rstart < hppa_ex->ex_start || rend > hppa_ex->ex_end)
		panic("bus_space_alloc: bad region start/end");

	if ((error = extent_alloc_subregion(hppa_ex, rstart, rend, size,
	    align, 0, boundary, EX_NOWAIT, &bpa)))
		return (error);

	if ((error = mbus_add_mapping(bpa, size, flags, bshp))) {
		if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) {
			printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n",
				bpa, size);
			printf("bus_space_alloc: can't free region\n");
		}
	}

	*addrp = bpa | ~HPPA_PHYSMAP;
	return (error);
}
Ejemplo n.º 5
0
void
jensenio_intio_unmap(void *v, bus_space_handle_t ioh, bus_size_t iosize,
    int acct)
{
	struct jensenio_config *jcp = v;
	bus_addr_t ioaddr;
	int error;

	if (acct == 0)
		return;

#ifdef EXTENT_DEBUG
	printf("intio: freeing handle 0x%lx for 0x%lx\n", ioh, iosize);
#endif

	ioh = ALPHA_K0SEG_TO_PHYS(ioh);

	ioaddr = (ioh - JENSEN_VL82C106) >> 9;

#ifdef EXTENT_DEBUG
	printf("intio: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
#endif
	error = extent_free(jcp->jc_io_ex, ioaddr, iosize,
	    EX_NOWAIT | (jcp->jc_mallocsafe ? EX_MALLOCOK : 0));
	if (error) {
		printf("WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
		    ioaddr, ioaddr + iosize - 1, error);
#ifdef EXTENT_DEBUG
		extent_print(jcp->jc_io_ex);
#endif
	}
}
Ejemplo n.º 6
0
int
bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
    bus_space_handle_t *bshp)
{
	int error;
	struct extent *ex;

	/*
	 * Pick the appropriate extent map.
	 */
	if (t == X86_BUS_SPACE_IO) {
		ex = ioport_ex;
		if (flags & BUS_SPACE_MAP_LINEAR)
			return (EINVAL);
	} else if (t == X86_BUS_SPACE_MEM)
		ex = iomem_ex;
	else
		panic("bus_space_map: bad bus space tag");

	/*
	 * Before we go any further, let's make sure that this
	 * region is available.
	 */
	error = extent_alloc_region(ex, bpa, size,
	    EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
	if (error)
		return (error);

	/*
	 * For I/O space, that's all she wrote.
	 */
	if (t == X86_BUS_SPACE_IO) {
		*bshp = bpa;
		return (0);
	}

	if (bpa >= IOM_BEGIN && (bpa + size) <= IOM_END) {
		*bshp = (bus_space_handle_t)ISA_HOLE_VADDR(bpa);
		return(0);
	}

	/*
	 * For memory space, map the bus physical address to
	 * a kernel virtual address.
	 */
	error = x86_mem_add_mapping(bpa, size, flags, bshp);
	if (error) {
		if (extent_free(ex, bpa, size, EX_NOWAIT |
		    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
			printf("bus_space_map: pa 0x%lx, size 0x%lx\n",
			    bpa, size);
			printf("bus_space_map: can't free region\n");
		}
	}

	return (error);
}
Ejemplo n.º 7
0
int
vme_map(struct vme_softc *sc, struct extent *ext, u_int awidth,
    bus_addr_t addr, bus_size_t size, int flags, vaddr_t *rva)
{
	const struct vme_range *r;
	int rc;
	paddr_t pa;
	psize_t offs, len;

	/*
	 * Since we need to map VME address ranges on demand, we will allocate
	 * with a page granularity.
	 */
	pa = trunc_page(addr);
	offs = addr - pa;
	len = round_page(addr + size) - pa;

	/*
	 * Check that the mapping fits within the available address ranges.
	 */
	for (r = sc->sc_ranges; r->vr_width != 0; r++) {
		if (r->vr_width == awidth &&
		    r->vr_start <= addr && r->vr_end >= addr + size - 1)
			break;
	}
	if (r->vr_width == 0)
		return EINVAL;

	/*
	 * Register this range in the per-width extent.
	 */
	if (ext != NULL) {
		rc = extent_alloc_region(ext, atop(pa), atop(len),
		    EX_NOWAIT | EX_MALLOCOK);
		if (rc != 0)
			return rc;
	}

	/*
	 * Allocate virtual memory for the range and map it.
	 */
	rc = vme_map_r(r, pa, len, flags, UVM_PROT_RW, rva);
	if (rc != 0) {
		if (ext != NULL)
			(void)extent_free(ext, atop(pa), atop(len),
			    EX_NOWAIT | EX_MALLOCOK);
		return rc;
	}

	*rva += offs;
	return 0;
}
Ejemplo n.º 8
0
void
pci_init_extents(void)
{
	bios_memmap_t *bmp;
	u_int64_t size;

	if (pciio_ex == NULL) {
		/*
		 * We only have 64K of addressable I/O space.
		 * However, since BARs may contain garbage, we cover
		 * the full 32-bit address space defined by PCI of
		 * which we only make the first 64K available.
		 */
		pciio_ex = extent_create("pciio", 0, 0xffffffff, M_DEVBUF,
		    NULL, 0, EX_NOWAIT | EX_FILLED);
		if (pciio_ex == NULL)
			return;
		extent_free(pciio_ex, 0, 0x10000, M_NOWAIT);
	}

	if (pcimem_ex == NULL) {
		pcimem_ex = extent_create("pcimem", 0, 0xffffffff, M_DEVBUF,
		    NULL, 0, EX_NOWAIT);
		if (pcimem_ex == NULL)
			return;

		for (bmp = bios_memmap; bmp->type != BIOS_MAP_END; bmp++) {
			/*
			 * Ignore address space beyond 4G.
			 */
			if (bmp->addr >= 0x100000000ULL)
				continue;
			size = bmp->size;
			if (bmp->addr + size >= 0x100000000ULL)
				size = 0x100000000ULL - bmp->addr;

			/* Ignore zero-sized regions. */
			if (size == 0)
				continue;

			if (extent_alloc_region(pcimem_ex, bmp->addr, size,
			    EX_NOWAIT))
				printf("memory map conflict 0x%llx/0x%llx\n",
				    bmp->addr, bmp->size);
		}

		/* Take out the video buffer area and BIOS areas. */
		extent_alloc_region(pcimem_ex, IOM_BEGIN, IOM_SIZE,
		    EX_CONFLICTOK | EX_NOWAIT);
	}
}
Ejemplo n.º 9
0
void
bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
{
	struct extent *ex;
	u_long va, endva;
	bus_addr_t bpa;

	/*
	 * Find the correct extent and bus physical address.
	 */
	if (t == X86_BUS_SPACE_IO) {
		ex = ioport_ex;
		bpa = bsh;
	} else if (t == X86_BUS_SPACE_MEM) {
		ex = iomem_ex;
		bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
		if (IOM_BEGIN <= bpa && bpa <= IOM_END)
			goto ok;

		va = trunc_page(bsh);
		endva = round_page(bsh + size);

#ifdef DIAGNOSTIC
		if (endva <= va)
			panic("bus_space_unmap: overflow");
#endif

		(void)pmap_extract(pmap_kernel(), va, &bpa);
		bpa += (bsh & PGOFSET);

		pmap_kremove(va, endva - va);
		pmap_update(pmap_kernel());

		/*
		 * Free the kernel virtual mapping.
		 */
		uvm_km_free(kernel_map, va, endva - va);
	} else
		panic("bus_space_unmap: bad bus space tag");

ok:
	if (extent_free(ex, bpa, size,
	    EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
		printf("bus_space_unmap: %s 0x%lx, size 0x%lx\n",
		    (t == X86_BUS_SPACE_IO) ? "port" : "pa", bpa, size);
		printf("bus_space_unmap: can't free region\n");
	}
}
Ejemplo n.º 10
0
void
b3_617_unmap_vme(void *vsc, vme_mapresc_t resc)
{
	unsigned long i;
	struct b3_617_vmeresc *r = resc;

	/* unmap PCI window */
	bus_space_unmap(sc->sc_vmet, r->handle, r->len);

	for (i = r->firstpage; i < r->firstpage + r->maplen; i += 4)
		write_mapmem(sc, i, MR_RAM_INVALID);

	extent_free(sc->vmeext, r->firstpage, r->maplen, 0);

	free(r, M_DEVBUF);
}
Ejemplo n.º 11
0
void
vme_unmap(struct vme_softc *sc, struct extent *ext, u_int awidth,
    vaddr_t vaddr, paddr_t paddr, bus_size_t size)
{
	const struct vme_range *r;
	vaddr_t va;
	paddr_t pa, addr;
	psize_t len;

	va = trunc_page(vaddr);
	pa = trunc_page(paddr);
	len = round_page(paddr + size) - pa;

	/*
	 * Retrieve the address range this mapping comes from.
	 */
	for (r = sc->sc_ranges; r->vr_width != 0; r++) {
		if (r->vr_width != awidth)
			continue;
		addr = paddr - r->vr_base;
		if (r->vr_width == awidth &&
		    r->vr_start <= addr && r->vr_end >= addr + size - 1)
			break;
	}
	if (r->vr_width == 0) {
#ifdef DIAGNOSTIC
		printf("%s: nonsensical A%d mapping at va 0x%08lx pa 0x%08lx\n",
		    __func__, AWIDTH(awidth), vaddr, paddr);
#endif
		return;
	}

	/*
	 * Undo the mapping.
	 */
	pmap_kremove(va, len);
	pmap_update(pmap_kernel());
	uvm_km_free(kernel_map, va, len);

	/*
	 * Unregister mapping.
	 */
	if (ext != NULL) {
		pa -= r->vr_base;
		extent_free(ext, atop(pa), atop(len), EX_NOWAIT | EX_MALLOCOK);
	}
}
Ejemplo n.º 12
0
static void
_default_unmap(void *t, bus_space_handle_t bsh, bus_size_t size)
{
	struct playstation2_bus_space *pbs = t;
	struct extent *ex = pbs->pbs_extent;
	int error;

	if (ex == 0)
		return;

	error = extent_free(ex, bsh, size, EX_NOWAIT);

	if (error) {
		DPRINTF("%#lx-%#lx of %s space lost\n", bsh, bsh + size,
		    ex->ex_name);
	}
}
Ejemplo n.º 13
0
/*
 * Unmap a previously mapped device.
 */
void
iounmap(void *kva, int size)
{

#ifdef DEBUG
	if (((vaddr_t)kva & PGOFSET) || (size & PGOFSET))
		panic("iounmap: unaligned");
	if ((uint8_t *)kva < extiobase ||
	    (uint8_t *)kva >= extiobase + ptoa(EIOMAPSIZE))
		panic("iounmap: bad address");
#endif
	physunaccess(kva, size);
	if (extent_free(extio_ex, (vaddr_t)kva, size,
	    EX_NOWAIT | (extio_ex_malloc_safe ? EX_MALLOCOK : 0)))
		printf("iounmap: kva %p size 0x%x: can't free region\n",
		    kva, size);
}
Ejemplo n.º 14
0
int
au_himem_alloc(void *cookie, bus_addr_t start, bus_addr_t end,
    bus_size_t size, bus_size_t align, bus_size_t boundary, int flags,
    bus_addr_t *addrp, bus_space_handle_t *bshp)
{
	au_himem_cookie_t	*c = (au_himem_cookie_t *)cookie;
	int			err;

	err = extent_alloc_subregion(c->c_extent, start, end, size,
	    align, boundary, EX_FAST | EX_NOWAIT, addrp);
	if (err) {
		return err;
	}
	err = au_himem_map(cookie, *addrp, size, flags, bshp, 0);
	if (err)
		extent_free(c->c_extent, *addrp, size, EX_NOWAIT);
	return err;
}
Ejemplo n.º 15
0
/*
 * Free some DVMA space allocated by the above.
 * This IS safe to call at interrupt time.
 * (Typically called at SPLBIO)
 */
void 
dvma_mapout(void *dma, int len)
{
	vaddr_t seg_dma;
	vsize_t seg_len, seg_off;
	vaddr_t v, x;
	int sme;
	int s;

	/* Get seg-aligned address and length. */
	seg_dma = (vaddr_t)dma;
	seg_len = (vsize_t)len;
	seg_off = seg_dma & SEGOFSET;
	seg_dma -= seg_off;
	seg_len = m68k_round_seg(seg_len + seg_off);

	s = splvm();

	/* Flush cache and remove DVMA mappings. */
	v = seg_dma;
	x = v + seg_len;
	while (v < x) {
		sme = get_segmap(v);
#ifdef	DIAGNOSTIC
		if (sme == SEGINV)
			panic("dvma_mapout: seg not mapped");
#endif
#ifdef	HAVECACHE
		/* flush write-back on the DVMA mappings */
		if (cache_size)
			cache_flush_segment(v);
#endif
		set_segmap_allctx(v, SEGINV);
		v += NBSG;
	}

	if (extent_free(dvma_extent, seg_dma, seg_len,
	    EX_NOWAIT | EX_MALLOCOK))
		panic("dvma_mapout: unable to free 0x%lx,0x%lx",
		    seg_dma, seg_len);
	splx(s);
}
Ejemplo n.º 16
0
int
mbus_map(void *v, bus_addr_t bpa, bus_size_t size,
    int flags, bus_space_handle_t *bshp)
{
	int error;

	bpa &= HPPA_PHYSMAP;
	if ((error = extent_alloc_region(hppa_ex, bpa, size, EX_NOWAIT)))
		return (error);

	if ((error = mbus_add_mapping(bpa, size, flags, bshp))) {
		if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) {
			printf("bus_space_map: pa 0x%lx, size 0x%lx\n",
				bpa, size);
			printf("bus_space_map: can't free region\n");
		}
	}

	return error;
}
Ejemplo n.º 17
0
void
bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
{
	vaddr_t kva;
	vsize_t offset;

	if (t->bustype == HP300_BUS_SPACE_INTIO) {
		/*
		 * Intio space is direct-mapped in pmap_bootstrap(); nothing
		 * to do
		 */
		return;
	}

	if (t->bustype != HP300_BUS_SPACE_DIO &&
	    t->bustype != HP300_BUS_SPACE_SGC)
		panic("%s: bad space tag", __func__);

	kva = m68k_trunc_page(bsh);
	offset = m68k_page_offset(bsh);
	size = m68k_round_page(offset + size);

#ifdef DIAGNOSTIC
	if (bsh < (vaddr_t)extiobase ||
	    bsh >= ((vaddr_t)extiobase + ptoa(EIOMAPSIZE)))
		panic("%s: bad bus space handle", __func__);
#endif

	/*
	 * Unmap the range.
	 */
	physunaccess((void *)kva, size);

	/*
	 * Free it from the extio extent map.
	 */
	if (extent_free(extio_ex, kva, size,
	    EX_NOWAIT | (extio_ex_malloc_safe ? EX_MALLOCOK : 0)))
		printf("%s: kva 0x%lx size 0x%lx: "
		    "can't free region\n", __func__, (u_long)bsh, size);
}
Ejemplo n.º 18
0
void
mbus_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
{
	u_long sva, eva;

	sva = trunc_page(bsh);
	eva = round_page(bsh + size);

#ifdef DIAGNOSTIC
	if (eva <= sva)
		panic("bus_space_unmap: overflow");
#endif

	pmap_kremove(sva, eva - sva);

	if (extent_free(hppa_ex, bsh, size, EX_NOWAIT)) {
		printf("bus_space_unmap: ps 0x%lx, size 0x%lx\n",
		    bsh, size);
		printf("bus_space_unmap: can't free region\n");
	}
}
Ejemplo n.º 19
0
void
arc_bus_space_unmap(bus_space_tag_t bst, bus_space_handle_t bsh,
    bus_size_t size)
{

	if (bst->bs_extent != NULL) {
		paddr_t pa;
		bus_addr_t addr;
		int err;

		/* bus_space_paddr() becomes unavailable after unmapping */
		err = bus_space_paddr(bst, bsh, &pa);
		if (err)
			panic("arc_bus_space_unmap: %s va 0x%qx: error %d",
			    bst->bs_name, (unsigned long long) bsh, err);
		addr = (bus_size_t)(pa - bst->bs_pbase) + bst->bs_start;
		extent_free(bst->bs_extent, addr, size,
		    EX_NOWAIT | malloc_safe);
	}
	bus_space_dispose_handle(bst, bsh, size);
}
Ejemplo n.º 20
0
/*
 * Unload a dvmamap.
 */
void
viommu_dvmamap_unload(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dmamap_t map)
{
	struct iommu_state *is;
	struct iommu_map_state *ims = map->_dm_cookie;
	bus_addr_t dvmaddr = map->_dm_dvmastart;
	bus_size_t sgsize = map->_dm_dvmasize;
	int error;

#ifdef DEBUG
	if (ims == NULL)
		panic("viommu_dvmamap_unload: null map state");
	if (ims->ims_iommu == NULL)
		panic("viommu_dvmamap_unload: null iommu");
#endif /* DEBUG */

	is = ims->ims_iommu;

	/* Remove the IOMMU entries */
	viommu_iomap_unload_map(is, ims);

	/* Clear the iomap */
	iommu_iomap_clear_pages(ims);

	bus_dmamap_unload(t->_parent, map);

	/* Mark the mappings as invalid. */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;

	mtx_enter(&is->is_mtx);
	error = extent_free(is->is_dvmamap, dvmaddr, 
		sgsize, EX_NOWAIT);
	map->_dm_dvmastart = 0;
	map->_dm_dvmasize = 0;
	mtx_leave(&is->is_mtx);
	if (error != 0)
		printf("warning: %qd of DVMA space lost\n", sgsize);
}
Ejemplo n.º 21
0
void
au_himem_unmap(void *cookie, bus_space_handle_t bsh, bus_size_t size, int acct)
{
	au_himem_cookie_t	*c = (au_himem_cookie_t *)cookie;
	vaddr_t			va;
	vsize_t			realsz;
	paddr_t			pa;
	int			s;

	va = (vaddr_t)TRUNC_PAGE(bsh);
	realsz = (vsize_t)ROUND_PAGE((bsh % PAGE_SIZE) + size);

	s = splhigh();

	/* make sure that any pending writes are flushed */
	wbflush();

	/*
	 * we have to get the bus address, so that we can free it in the
	 * extent manager.  this is the unfortunate thing about using
	 * virtual memory instead of just a 1:1 mapping scheme.
	 */
	if (pmap_extract(pmap_kernel(), va, &pa) == false)
		panic("au_himem_unmap: virtual address invalid!");

	/* now remove it from the pmap */
	pmap_kremove(va, realsz);
	pmap_update(pmap_kernel());
	splx(s);

	/* finally we can release both virtual and bus address ranges */
	uvm_km_free(kernel_map, va, realsz, UVM_KMF_VAONLY);

	if (acct) {
		bus_addr_t		addr;
		addr = ((pa - c->c_physoff) + (bsh % PAGE_SIZE));
		extent_free(c->c_extent, addr, size, EX_NOWAIT);
	}
}
Ejemplo n.º 22
0
/*
 * we take the trinary returned from intel_setup_mchbar and clean up after
 * it.
 */
void
intel_teardown_mchbar(struct inteldrm_softc *dev_priv,
    struct pci_attach_args *bpa, int disable)
{
	struct drm_device	*dev = (struct drm_device *)dev_priv->drmdev;
	u_int64_t		 mchbar_addr;
	pcireg_t		 tmp, low, high = 0;
	int			 reg;

	reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;

	switch(disable) {
	case 2:
		if (INTEL_INFO(dev)->gen >= 4)
			high = pci_conf_read(bpa->pa_pc, bpa->pa_tag, reg + 4);
		low = pci_conf_read(bpa->pa_pc, bpa->pa_tag, reg);
		mchbar_addr = ((u_int64_t)high << 32) | low;
		if (bpa->pa_memex)
			extent_free(bpa->pa_memex, mchbar_addr, MCHBAR_SIZE, 0);
		/* FALLTHROUGH */
	case 1:
		if (IS_I915G(dev) || IS_I915GM(dev)) {
			tmp = pci_conf_read(bpa->pa_pc, bpa->pa_tag, DEVEN_REG);
			tmp &= ~DEVEN_MCHBAR_EN;
			pci_conf_write(bpa->pa_pc, bpa->pa_tag, DEVEN_REG, tmp);
		} else {
			tmp = pci_conf_read(bpa->pa_pc, bpa->pa_tag, reg);
			tmp &= ~1;
			pci_conf_write(bpa->pa_pc, bpa->pa_tag, reg, tmp);
		}
		break;
	case 0:
	default:
		break;
	};
}
Ejemplo n.º 23
0
void
ppbattach(struct device *parent, struct device *self, void *aux)
{
	struct ppb_softc *sc = (struct ppb_softc *)self;
	struct pci_attach_args *pa = aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	struct pcibus_attach_args pba;
	pci_intr_handle_t ih;
	pcireg_t busdata, reg, blr;
	char *name;
	int pin;

	sc->sc_pc = pc;
	sc->sc_tag = pa->pa_tag;

	busdata = pci_conf_read(pc, pa->pa_tag, PPB_REG_BUSINFO);

	if (PPB_BUSINFO_SECONDARY(busdata) == 0) {
		printf(": not configured by system firmware\n");
		return;
	}

#if 0
	/*
	 * XXX can't do this, because we're not given our bus number
	 * (we shouldn't need it), and because we've no way to
	 * decompose our tag.
	 */
	/* sanity check. */
	if (pa->pa_bus != PPB_BUSINFO_PRIMARY(busdata))
		panic("ppbattach: bus in tag (%d) != bus in reg (%d)",
		    pa->pa_bus, PPB_BUSINFO_PRIMARY(busdata));
#endif

	/* Check for PCI Express capabilities and setup hotplug support. */
	if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PCIEXPRESS,
	    &sc->sc_cap_off, &reg) && (reg & PCI_PCIE_XCAP_SI)) {
#ifdef __i386__
		if (pci_intr_map(pa, &ih) == 0)
			sc->sc_intrhand = pci_intr_establish(pc, ih, IPL_BIO,
			    ppb_intr, sc, self->dv_xname);
#else
		if (pci_intr_map_msi(pa, &ih) == 0 ||
		    pci_intr_map(pa, &ih) == 0)
			sc->sc_intrhand = pci_intr_establish(pc, ih, IPL_BIO,
			    ppb_intr, sc, self->dv_xname);
#endif

		if (sc->sc_intrhand) {
			printf(": %s", pci_intr_string(pc, ih));

			/* Enable hotplug interrupt. */
			reg = pci_conf_read(pc, pa->pa_tag,
			    sc->sc_cap_off + PCI_PCIE_SLCSR);
			reg |= (PCI_PCIE_SLCSR_HPE | PCI_PCIE_SLCSR_PDE);
			pci_conf_write(pc, pa->pa_tag,
			    sc->sc_cap_off + PCI_PCIE_SLCSR, reg);

			timeout_set(&sc->sc_to, ppb_hotplug_insert_finish, sc);
		}
	}

	printf("\n");

	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL ||
	    (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_82801BA_HPB &&
	    PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_82801BAM_HPB))
		ppb_alloc_resources(sc, pa);

	for (pin = PCI_INTERRUPT_PIN_A; pin <= PCI_INTERRUPT_PIN_D; pin++) {
		pa->pa_intrpin = pa->pa_rawintrpin = pin;
		pa->pa_intrline = 0;
		pci_intr_map(pa, &sc->sc_ih[pin - PCI_INTERRUPT_PIN_A]);
	}

	/*
	 * The UltraSPARC-IIi APB doesn't implement the standard
	 * address range registers.
	 */
	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN &&
	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_SIMBA)
		goto attach;

	/* Figure out the I/O address range of the bridge. */
	blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_IOSTATUS);
	sc->sc_iobase = (blr & 0x000000f0) << 8;
	sc->sc_iolimit = (blr & 0x000f000) | 0x00000fff;
	blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_IO_HI);
	sc->sc_iobase |= (blr & 0x0000ffff) << 16;
	sc->sc_iolimit |= (blr & 0xffff0000);
	if (sc->sc_iolimit > sc->sc_iobase) {
		name = malloc(32, M_DEVBUF, M_NOWAIT);
		if (name) {
			snprintf(name, 32, "%s pciio", sc->sc_dev.dv_xname);
			sc->sc_ioex = extent_create(name, 0, 0xffffffff,
			    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
			extent_free(sc->sc_ioex, sc->sc_iobase,
			    sc->sc_iolimit - sc->sc_iobase + 1, EX_NOWAIT);
		}
	}

	/* Figure out the memory mapped I/O address range of the bridge. */
	blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_MEM);
	sc->sc_membase = (blr & 0x0000fff0) << 16;
	sc->sc_memlimit = (blr & 0xfff00000) | 0x000fffff;
	if (sc->sc_memlimit > sc->sc_membase) {
		name = malloc(32, M_DEVBUF, M_NOWAIT);
		if (name) {
			snprintf(name, 32, "%s pcimem", sc->sc_dev.dv_xname);
			sc->sc_memex = extent_create(name, 0, 0xffffffff,
			    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
			extent_free(sc->sc_memex, sc->sc_membase,
			    sc->sc_memlimit - sc->sc_membase + 1,
			    EX_NOWAIT);
		}
	}

	/* Figure out the prefetchable MMI/O address range of the bridge. */
	blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFMEM);
	sc->sc_pmembase = (blr & 0x0000fff0) << 16;
	sc->sc_pmemlimit = (blr & 0xfff00000) | 0x000fffff;
#ifdef __LP64__	/* XXX because extents use long... */
	blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFBASE_HI32);
	sc->sc_pmembase |= ((uint64_t)blr) << 32;
	blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFLIM_HI32);
	sc->sc_pmemlimit |= ((uint64_t)blr) << 32;
#endif
	if (sc->sc_pmemlimit > sc->sc_pmembase) {
		name = malloc(32, M_DEVBUF, M_NOWAIT);
		if (name) {
			snprintf(name, 32, "%s pcipmem", sc->sc_dev.dv_xname);
			sc->sc_pmemex = extent_create(name, 0, (u_long)-1L,
			    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
			extent_free(sc->sc_pmemex, sc->sc_pmembase,
			    sc->sc_pmemlimit - sc->sc_pmembase + 1,
			    EX_NOWAIT);
		}
	}

	/*
	 * The Intel 82801BAM Hub-to-PCI can decode subtractively.
	 * XXX We probably should handle subtractive decode bridges
	 * in general.
	 */
	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
	    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BA_HPB ||
	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BAM_HPB)) {
		if (sc->sc_ioex == NULL)
			sc->sc_ioex = pa->pa_ioex;
		if (sc->sc_memex == NULL)
			sc->sc_memex = pa->pa_memex;
	}

 attach:
	/*
	 * Attach the PCI bus that hangs off of it.
	 *
	 * XXX Don't pass-through Memory Read Multiple.  Should we?
	 * XXX Consult the spec...
	 */
	bzero(&pba, sizeof(pba));
	pba.pba_busname = "pci";
	pba.pba_iot = pa->pa_iot;
	pba.pba_memt = pa->pa_memt;
	pba.pba_dmat = pa->pa_dmat;
	pba.pba_pc = pc;
	pba.pba_flags = pa->pa_flags & ~PCI_FLAGS_MRM_OKAY;
	pba.pba_ioex = sc->sc_ioex;
	pba.pba_memex = sc->sc_memex;
	pba.pba_pmemex = sc->sc_pmemex;
	pba.pba_domain = pa->pa_domain;
	pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata);
	pba.pba_bridgeih = sc->sc_ih;
	pba.pba_bridgetag = &sc->sc_tag;
	pba.pba_intrswiz = pa->pa_intrswiz;
	pba.pba_intrtag = pa->pa_intrtag;

	sc->sc_psc = config_found(self, &pba, ppbprint);
}
Ejemplo n.º 24
0
void
socpcic_attach(struct socpcic_softc *sc)
{
	struct pcibus_attach_args pba;
	struct extent *io_ex;
	struct extent *mem_ex;
	bus_addr_t io_base, mem_base;
	bus_size_t io_size, mem_size;
	uint32_t *ranges;
	int len;

	if (OF_getprop(sc->sc_node, "interrupt-map-mask", sc->sc_map_mask,
	    sizeof(sc->sc_map_mask)) != sizeof(sc->sc_map_mask)) {
		printf(": missing interrupt-map-mask\n");
		return;
	}

	sc->sc_map_len = OF_getproplen(sc->sc_node, "interrupt-map");
	if (sc->sc_map_len > 0) {
		sc->sc_map = malloc(sc->sc_map_len, M_DEVBUF, M_NOWAIT);
		if (sc->sc_map == NULL)
			panic("out of memory");

		len = OF_getprop(sc->sc_node, "interrupt-map",
		    sc->sc_map, sc->sc_map_len);
		KASSERT(len == sc->sc_map_len);
	}

	sc->sc_ranges_len = OF_getproplen(sc->sc_node, "ranges");
	if (sc->sc_ranges_len <= 0) {
		printf(": missing ranges\n");
		return;
	}

	sc->sc_ranges = malloc(sc->sc_ranges_len, M_DEVBUF, M_NOWAIT);
	if (ranges == NULL)
		panic("out of memory");

	len = OF_getprop(sc->sc_node, "ranges", sc->sc_ranges,
	    sc->sc_ranges_len);
	KASSERT(len == sc->sc_ranges_len);

	ranges = sc->sc_ranges;
	while (len >= 6 * sizeof(uint32_t)) {
		switch (ranges[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
		case OFW_PCI_PHYS_HI_SPACE_IO:
			KASSERT(ranges[1] == 0);
			KASSERT(ranges[4] == 0);
			sc->sc_io_bus_space.bus_base = ranges[3];
			sc->sc_io_bus_space.bus_size = ranges[5];
			sc->sc_io_bus_space.bus_io = 1;
			io_base = ranges[2];
			io_size = ranges[5];
			break;
		case  OFW_PCI_PHYS_HI_SPACE_MEM32:
			KASSERT(ranges[1] == 0);
			KASSERT(ranges[4] == 0);
			sc->sc_mem_bus_space.bus_base = ranges[3];
			sc->sc_mem_bus_space.bus_size = ranges[5];
			sc->sc_mem_bus_space.bus_io = 0;
			mem_base = ranges[2];
			mem_size = ranges[5];
			break;
		}
		len -= 6 * sizeof(uint32_t);
		ranges += 6;
	}

	sc->sc_pc.pc_conf_v = sc;
	sc->sc_pc.pc_attach_hook = socpcic_attach_hook;
	sc->sc_pc.pc_bus_maxdevs = socpcic_bus_maxdevs;
	sc->sc_pc.pc_make_tag = socpcic_make_tag;
	sc->sc_pc.pc_decompose_tag = socpcic_decompose_tag;
	sc->sc_pc.pc_conf_size = socpcic_conf_size;
	sc->sc_pc.pc_conf_read = socpcic_conf_read;
	sc->sc_pc.pc_conf_write = socpcic_conf_write;

	sc->sc_pc.pc_intr_v = sc;
	sc->sc_pc.pc_intr_map = socpcic_intr_map;
	sc->sc_pc.pc_intr_string = socpcic_intr_string;
	sc->sc_pc.pc_intr_line = socpcic_intr_line;
	sc->sc_pc.pc_intr_establish = socpcic_intr_establish;
	sc->sc_pc.pc_intr_disestablish = socpcic_intr_disestablish;
	sc->sc_pc.pc_ether_hw_addr = socpcic_ether_hw_addr;

	io_ex = extent_create("pciio", 0, 0xffffffff, M_DEVBUF, NULL, 0,
	    EX_NOWAIT | EX_FILLED);
	if (io_ex != NULL && io_size)
		extent_free(io_ex, io_base, io_size, EX_NOWAIT);
	mem_ex = extent_create("pcimem", 0, 0xffffffff, M_DEVBUF, NULL, 0,
	    EX_NOWAIT | EX_FILLED);
	if (mem_ex != NULL)
		extent_free(mem_ex, mem_base, mem_size, EX_NOWAIT);

	bzero(&pba, sizeof(pba));
	pba.pba_busname = "pci";
	pba.pba_iot = &sc->sc_io_bus_space;
	pba.pba_memt = &sc->sc_mem_bus_space;
	pba.pba_dmat = sc->sc_dmat;
	pba.pba_ioex = io_ex;
	pba.pba_memex = mem_ex;
	pba.pba_pc = &sc->sc_pc;
	pba.pba_domain = pci_ndomains++;
	pba.pba_bus = 0;

	printf("\n");

	config_found((struct device *)sc, &pba, socpcic_print);
}
Ejemplo n.º 25
0
int
b3_617_map_vme(void *vsc, vme_addr_t vmeaddr, vme_size_t len, vme_am_t am, vme_datasize_t datasizes, vme_swap_t swap, bus_space_tag_t *tag, bus_space_handle_t *handle, vme_mapresc_t *resc)
{
	vme_addr_t vmebase, vmeend, va;
	unsigned long maplen, first, i;
	u_int32_t mapreg;
	bus_addr_t pcibase;
	int res;
	struct b3_617_vmeresc *r;

	/* first mapped address */
	vmebase = vmeaddr & ~(VME_PAGESIZE - 1);
	/* base of last mapped page */
	vmeend = (vmeaddr + len - 1) & ~(VME_PAGESIZE - 1);
	/* bytes in scatter table required */
	maplen = ((vmeend - vmebase) / VME_PAGESIZE + 1) * 4;

	if (extent_alloc(sc->vmeext, maplen, 4, 0, EX_FAST, &first))
		return (ENOMEM);

	/*
	 * set up adapter mapping registers
	 */
	mapreg = (am << MR_AMOD_SHIFT) | MR_FC_RRAM | swap;

	for (i = first, va = vmebase;
	     i < first + maplen;
	     i += 4, va += VME_PAGESIZE) {
		write_mapmem(sc, i, mapreg | va);
#ifdef BIT3DEBUG
		printf("mapreg@%lx=%x\n", i, read_mapmem(sc, i));
#endif
	}

#ifdef DIAGNOSTIC
	if (va != vmeend + VME_PAGESIZE)
		panic("b3_617_map_pci_vme: botch");
#endif
	/*
	 * map needed range in PCI space
	 */
	pcibase = sc->vmepbase + (first - MR_PCI_VME) / 4 * VME_PAGESIZE
	    + (vmeaddr & (VME_PAGESIZE - 1));

	if ((res = bus_space_map(sc->sc_vmet, pcibase, len, 0, handle))) {
		for (i = first; i < first + maplen; i += 4)
			write_mapmem(sc, i, MR_RAM_INVALID);
		extent_free(sc->vmeext, first, maplen, 0);
		return (res);
	}

	*tag = sc->sc_vmet;

	/*
	 * save all data needed for later unmapping
	 */
	r = malloc(sizeof(*r), M_DEVBUF, M_NOWAIT); /* XXX check! */
	r->handle = *handle;
	r->len = len;
	r->firstpage = first;
	r->maplen = maplen;
	*resc = r;
	return (0);
}
void
__BS(init)(bus_space_tag_t t, void *v)
{
#ifdef CHIP_EXTENT
	struct extent *ex;
#endif

	/*
	 * Initialize the bus space tag.
	 */

	/* cookie */
	t->bs_cookie =		v;

	/* mapping/unmapping */
	t->bs_map =		__BS(map);
	t->bs_unmap =		__BS(unmap);
	t->bs_subregion =	__BS(subregion);

	t->bs_translate =	__BS(translate);
	t->bs_get_window =	__BS(get_window);

	/* allocation/deallocation */
	t->bs_alloc =		__BS(alloc);
	t->bs_free =		__BS(free);

	/* get kernel virtual address */
	t->bs_vaddr =		__BS(vaddr);

	/* mmap for user */
	t->bs_mmap =		__BS(mmap);

	/* barrier */
	t->bs_barrier =		__BS(barrier);
	
	/* read (single) */
	t->bs_r_1 =		__BS(read_1);
	t->bs_r_2 =		__BS(read_2);
	t->bs_r_4 =		__BS(read_4);
	t->bs_r_8 =		__BS(read_8);
	
	/* read multiple */
	t->bs_rm_1 =		__BS(read_multi_1);
	t->bs_rm_2 =		__BS(read_multi_2);
	t->bs_rm_4 =		__BS(read_multi_4);
	t->bs_rm_8 =		__BS(read_multi_8);
	
	/* read region */
	t->bs_rr_1 =		__BS(read_region_1);
	t->bs_rr_2 =		__BS(read_region_2);
	t->bs_rr_4 =		__BS(read_region_4);
	t->bs_rr_8 =		__BS(read_region_8);
	
	/* write (single) */
	t->bs_w_1 =		__BS(write_1);
	t->bs_w_2 =		__BS(write_2);
	t->bs_w_4 =		__BS(write_4);
	t->bs_w_8 =		__BS(write_8);
	
	/* write multiple */
	t->bs_wm_1 =		__BS(write_multi_1);
	t->bs_wm_2 =		__BS(write_multi_2);
	t->bs_wm_4 =		__BS(write_multi_4);
	t->bs_wm_8 =		__BS(write_multi_8);
	
	/* write region */
	t->bs_wr_1 =		__BS(write_region_1);
	t->bs_wr_2 =		__BS(write_region_2);
	t->bs_wr_4 =		__BS(write_region_4);
	t->bs_wr_8 =		__BS(write_region_8);

	/* set multiple */
	t->bs_sm_1 =		__BS(set_multi_1);
	t->bs_sm_2 =		__BS(set_multi_2);
	t->bs_sm_4 =		__BS(set_multi_4);
	t->bs_sm_8 =		__BS(set_multi_8);
	
	/* set region */
	t->bs_sr_1 =		__BS(set_region_1);
	t->bs_sr_2 =		__BS(set_region_2);
	t->bs_sr_4 =		__BS(set_region_4);
	t->bs_sr_8 =		__BS(set_region_8);

	/* copy */
	t->bs_c_1 =		__BS(copy_region_1);
	t->bs_c_2 =		__BS(copy_region_2);
	t->bs_c_4 =		__BS(copy_region_4);
	t->bs_c_8 =		__BS(copy_region_8);

#ifdef CHIP_NEED_STREAM
	/* read (single), stream */
	t->bs_rs_1 =		__BS(read_stream_1);
	t->bs_rs_2 =		__BS(read_stream_2);
	t->bs_rs_4 =		__BS(read_stream_4);
	t->bs_rs_8 =		__BS(read_stream_8);
	
	/* read multiple, stream */
	t->bs_rms_1 =		__BS(read_multi_stream_1);
	t->bs_rms_2 =		__BS(read_multi_stream_2);
	t->bs_rms_4 =		__BS(read_multi_stream_4);
	t->bs_rms_8 =		__BS(read_multi_stream_8);
	
	/* read region, stream */
	t->bs_rrs_1 =		__BS(read_region_stream_1);
	t->bs_rrs_2 =		__BS(read_region_stream_2);
	t->bs_rrs_4 =		__BS(read_region_stream_4);
	t->bs_rrs_8 =		__BS(read_region_stream_8);
	
	/* write (single), stream */
	t->bs_ws_1 =		__BS(write_stream_1);
	t->bs_ws_2 =		__BS(write_stream_2);
	t->bs_ws_4 =		__BS(write_stream_4);
	t->bs_ws_8 =		__BS(write_stream_8);
	
	/* write multiple, stream */
	t->bs_wms_1 =		__BS(write_multi_stream_1);
	t->bs_wms_2 =		__BS(write_multi_stream_2);
	t->bs_wms_4 =		__BS(write_multi_stream_4);
	t->bs_wms_8 =		__BS(write_multi_stream_8);
	
	/* write region, stream */
	t->bs_wrs_1 =		__BS(write_region_stream_1);
	t->bs_wrs_2 =		__BS(write_region_stream_2);
	t->bs_wrs_4 =		__BS(write_region_stream_4);
	t->bs_wrs_8 =		__BS(write_region_stream_8);

#else	/* CHIP_NEED_STREAM */

	/* read (single), stream */
	t->bs_rs_1 =		__BS(read_1);
	t->bs_rs_2 =		__BS(read_2);
	t->bs_rs_4 =		__BS(read_4);
	t->bs_rs_8 =		__BS(read_8);
	
	/* read multiple, stream */
	t->bs_rms_1 =		__BS(read_multi_1);
	t->bs_rms_2 =		__BS(read_multi_2);
	t->bs_rms_4 =		__BS(read_multi_4);
	t->bs_rms_8 =		__BS(read_multi_8);
	
	/* read region, stream */
	t->bs_rrs_1 =		__BS(read_region_1);
	t->bs_rrs_2 =		__BS(read_region_2);
	t->bs_rrs_4 =		__BS(read_region_4);
	t->bs_rrs_8 =		__BS(read_region_8);
	
	/* write (single), stream */
	t->bs_ws_1 =		__BS(write_1);
	t->bs_ws_2 =		__BS(write_2);
	t->bs_ws_4 =		__BS(write_4);
	t->bs_ws_8 =		__BS(write_8);
	
	/* write multiple, stream */
	t->bs_wms_1 =		__BS(write_multi_1);
	t->bs_wms_2 =		__BS(write_multi_2);
	t->bs_wms_4 =		__BS(write_multi_4);
	t->bs_wms_8 =		__BS(write_multi_8);
	
	/* write region, stream */
	t->bs_wrs_1 =		__BS(write_region_1);
	t->bs_wrs_2 =		__BS(write_region_2);
	t->bs_wrs_4 =		__BS(write_region_4);
	t->bs_wrs_8 =		__BS(write_region_8);
#endif	/* CHIP_NEED_STREAM */

#ifdef CHIP_EXTENT
	/* XXX WE WANT EXTENT_NOCOALESCE, BUT WE CAN'T USE IT. XXX */
	ex = extent_create(__S(__BS(bus)), 0x0UL, 0xffffffffUL, M_DEVBUF,
	    (void *)CHIP_EX_STORE(v), CHIP_EX_STORE_SIZE(v), EX_NOWAIT);
	extent_alloc_region(ex, 0, 0xffffffffUL, EX_NOWAIT);

#ifdef CHIP_W1_BUS_START
	/*
	 * The window may be disabled.  We notice this by seeing
	 * -1 as the bus base address.
	 */
	if (CHIP_W1_BUS_START(v) == (bus_addr_t) -1) {
#ifdef EXTENT_DEBUG
		printf("xxx: this space is disabled\n");
#endif
		return;
	}

#ifdef EXTENT_DEBUG
	printf("xxx: freeing from 0x%x to 0x%x\n", CHIP_W1_BUS_START(v),
	    CHIP_W1_BUS_END(v));
#endif
	extent_free(ex, CHIP_W1_BUS_START(v),
	    CHIP_W1_BUS_END(v) - CHIP_W1_BUS_START(v) + 1, EX_NOWAIT);
#endif
#ifdef CHIP_W2_BUS_START
	if (CHIP_W2_BUS_START(v) != CHIP_W1_BUS_START(v)) {
#ifdef EXTENT_DEBUG
		printf("xxx: freeing from 0x%lx to 0x%lx\n",
		    (u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
#endif
		extent_free(ex, CHIP_W2_BUS_START(v),
		    CHIP_W2_BUS_END(v) - CHIP_W2_BUS_START(v) + 1, EX_NOWAIT);
	} else {
#ifdef EXTENT_DEBUG
		printf("xxx: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
		    (u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
#endif
	}
#endif
#ifdef CHIP_W3_BUS_START
	if (CHIP_W3_BUS_START(v) != CHIP_W1_BUS_START(v) &&
	    CHIP_W3_BUS_START(v) != CHIP_W2_BUS_START(v)) {
#ifdef EXTENT_DEBUG
		printf("xxx: freeing from 0x%lx to 0x%lx\n",
		    (u_long)CHIP_W3_BUS_START(v), (u_long)CHIP_W3_BUS_END(v));
#endif
		extent_free(ex, CHIP_W3_BUS_START(v),
		    CHIP_W3_BUS_END(v) - CHIP_W3_BUS_START(v) + 1, EX_NOWAIT);
	} else {
#ifdef EXTENT_DEBUG
		printf("xxx: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
		    (u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
#endif
	}
#endif

#ifdef EXTENT_DEBUG
	extent_print(ex);
#endif
	CHIP_EXTENT(v) = ex;
#endif /* CHIP_EXTENT */
}
Ejemplo n.º 27
0
int
bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
    bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
    bus_addr_t *bpap, bus_space_handle_t *bshp)
{
	struct extent *ex;
	u_long bpa;
	int error;

	/*
	 * Pick the appropriate extent map.
	 */
	if (t == X86_BUS_SPACE_IO) {
		ex = ioport_ex;
	} else if (t == X86_BUS_SPACE_MEM)
		ex = iomem_ex;
	else
		panic("bus_space_alloc: bad bus space tag");

	/*
	 * Sanity check the allocation against the extent's boundaries.
	 */
	if (rstart < ex->ex_start || rend > ex->ex_end)
		panic("bus_space_alloc: bad region start/end");

	/*
	 * Do the requested allocation.
	 */
	error = extent_alloc_subregion(ex, rstart, rend, size, alignment,
	    0, boundary,
	    EX_FAST | EX_NOWAIT | (ioport_malloc_safe ?  EX_MALLOCOK : 0),
	    &bpa);

	if (error)
		return (error);

	/*
	 * For I/O space, that's all she wrote.
	 */
	if (t == X86_BUS_SPACE_IO) {
		*bshp = *bpap = bpa;
		return (0);
	}

	/*
	 * For memory space, map the bus physical address to
	 * a kernel virtual address.
	 */
	error = x86_mem_add_mapping(bpa, size, flags, bshp);
	if (error) {
		if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
		    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
			printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n",
			    bpa, size);
			printf("bus_space_alloc: can't free region\n");
		}
	}

	*bpap = bpa;

	return (error);
}
void
__C(CHIP,_bus_mem_init)(bus_space_tag_t t, void *v)
{
#ifdef CHIP_D_MEM_W1_SYS_START
	struct extent *dex;
#endif
	struct extent *sex;

	/*
	 * Initialize the bus space tag.
	 */

	/* cookie */
	t->abs_cookie =		v;

	/* mapping/unmapping */
	t->abs_map =		__C(CHIP,_mem_map);
	t->abs_unmap =		__C(CHIP,_mem_unmap);
	t->abs_subregion =	__C(CHIP,_mem_subregion);

	t->abs_translate =	__C(CHIP,_mem_translate);
	t->abs_get_window =	__C(CHIP,_mem_get_window);

	/* allocation/deallocation */
	t->abs_alloc =		__C(CHIP,_mem_alloc);
	t->abs_free = 		__C(CHIP,_mem_free);

	/* get kernel virtual address */
	t->abs_vaddr =		__C(CHIP,_mem_vaddr);

	/* mmap for user */
	t->abs_mmap =		__C(CHIP,_mem_mmap);

	/* barrier */
	t->abs_barrier =	__C(CHIP,_mem_barrier);
	
	/* read (single) */
	t->abs_r_1 =		__C(CHIP,_mem_read_1);
	t->abs_r_2 =		__C(CHIP,_mem_read_2);
	t->abs_r_4 =		__C(CHIP,_mem_read_4);
	t->abs_r_8 =		__C(CHIP,_mem_read_8);
	
	/* read multiple */
	t->abs_rm_1 =		__C(CHIP,_mem_read_multi_1);
	t->abs_rm_2 =		__C(CHIP,_mem_read_multi_2);
	t->abs_rm_4 =		__C(CHIP,_mem_read_multi_4);
	t->abs_rm_8 =		__C(CHIP,_mem_read_multi_8);
	
	/* read region */
	t->abs_rr_1 =		__C(CHIP,_mem_read_region_1);
	t->abs_rr_2 =		__C(CHIP,_mem_read_region_2);
	t->abs_rr_4 =		__C(CHIP,_mem_read_region_4);
	t->abs_rr_8 =		__C(CHIP,_mem_read_region_8);
	
	/* write (single) */
	t->abs_w_1 =		__C(CHIP,_mem_write_1);
	t->abs_w_2 =		__C(CHIP,_mem_write_2);
	t->abs_w_4 =		__C(CHIP,_mem_write_4);
	t->abs_w_8 =		__C(CHIP,_mem_write_8);
	
	/* write multiple */
	t->abs_wm_1 =		__C(CHIP,_mem_write_multi_1);
	t->abs_wm_2 =		__C(CHIP,_mem_write_multi_2);
	t->abs_wm_4 =		__C(CHIP,_mem_write_multi_4);
	t->abs_wm_8 =		__C(CHIP,_mem_write_multi_8);
	
	/* write region */
	t->abs_wr_1 =		__C(CHIP,_mem_write_region_1);
	t->abs_wr_2 =		__C(CHIP,_mem_write_region_2);
	t->abs_wr_4 =		__C(CHIP,_mem_write_region_4);
	t->abs_wr_8 =		__C(CHIP,_mem_write_region_8);

	/* set multiple */
	t->abs_sm_1 =		__C(CHIP,_mem_set_multi_1);
	t->abs_sm_2 =		__C(CHIP,_mem_set_multi_2);
	t->abs_sm_4 =		__C(CHIP,_mem_set_multi_4);
	t->abs_sm_8 =		__C(CHIP,_mem_set_multi_8);
	
	/* set region */
	t->abs_sr_1 =		__C(CHIP,_mem_set_region_1);
	t->abs_sr_2 =		__C(CHIP,_mem_set_region_2);
	t->abs_sr_4 =		__C(CHIP,_mem_set_region_4);
	t->abs_sr_8 =		__C(CHIP,_mem_set_region_8);

	/* copy */
	t->abs_c_1 =		__C(CHIP,_mem_copy_region_1);
	t->abs_c_2 =		__C(CHIP,_mem_copy_region_2);
	t->abs_c_4 =		__C(CHIP,_mem_copy_region_4);
	t->abs_c_8 =		__C(CHIP,_mem_copy_region_8);

#ifdef CHIP_D_MEM_W1_SYS_START
	/* XXX WE WANT EXTENT_NOCOALESCE, BUT WE CAN'T USE IT. XXX */
	dex = extent_create(__S(__C(CHIP,_bus_dmem)), 0x0UL,
	    0xffffffffffffffffUL,
	    (void *)CHIP_D_MEM_EX_STORE(v), CHIP_D_MEM_EX_STORE_SIZE(v),
	    EX_NOWAIT);
	extent_alloc_region(dex, 0, 0xffffffffffffffffUL, EX_NOWAIT);

#ifdef CHIP_D_MEM_W1_BUS_START
#ifdef EXTENT_DEBUG
	printf("dmem: freeing from 0x%lx to 0x%lx\n",
	    CHIP_D_MEM_W1_BUS_START(v), CHIP_D_MEM_W1_BUS_END(v));
#endif
	extent_free(dex, CHIP_D_MEM_W1_BUS_START(v),
	    CHIP_D_MEM_W1_BUS_END(v) - CHIP_D_MEM_W1_BUS_START(v) + 1,
	    EX_NOWAIT);
#endif

#ifdef EXTENT_DEBUG
	extent_print(dex);
#endif
	CHIP_D_MEM_EXTENT(v) = dex;
#endif /* CHIP_D_MEM_W1_SYS_START */

	/* XXX WE WANT EXTENT_NOCOALESCE, BUT WE CAN'T USE IT. XXX */
	sex = extent_create(__S(__C(CHIP,_bus_smem)), 0x0UL,
	    0xffffffffffffffffUL,
	    (void *)CHIP_S_MEM_EX_STORE(v), CHIP_S_MEM_EX_STORE_SIZE(v),
	    EX_NOWAIT);
	extent_alloc_region(sex, 0, 0xffffffffffffffffUL, EX_NOWAIT);

#ifdef CHIP_S_MEM_W1_BUS_START
#ifdef EXTENT_DEBUG
	printf("smem: freeing from 0x%lx to 0x%lx\n",
	    CHIP_S_MEM_W1_BUS_START(v), CHIP_S_MEM_W1_BUS_END(v));
#endif
	extent_free(sex, CHIP_S_MEM_W1_BUS_START(v),
	    CHIP_S_MEM_W1_BUS_END(v) - CHIP_S_MEM_W1_BUS_START(v) + 1,
	    EX_NOWAIT);
#endif
#ifdef CHIP_S_MEM_W2_BUS_START
	if (CHIP_S_MEM_W2_BUS_START(v) != CHIP_S_MEM_W1_BUS_START(v)) {
#ifdef EXTENT_DEBUG
		printf("smem: freeing from 0x%lx to 0x%lx\n",
		    CHIP_S_MEM_W2_BUS_START(v), CHIP_S_MEM_W2_BUS_END(v));
#endif
		extent_free(sex, CHIP_S_MEM_W2_BUS_START(v),
		    CHIP_S_MEM_W2_BUS_END(v) - CHIP_S_MEM_W2_BUS_START(v) + 1,
		    EX_NOWAIT);
	} else {
#ifdef EXTENT_DEBUG
		printf("smem: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
		    CHIP_S_MEM_W2_BUS_START(v), CHIP_S_MEM_W2_BUS_END(v));
#endif
	}
#endif
#ifdef CHIP_S_MEM_W3_BUS_START
	if (CHIP_S_MEM_W3_BUS_START(v) != CHIP_S_MEM_W1_BUS_START(v) &&
	    CHIP_S_MEM_W3_BUS_START(v) != CHIP_S_MEM_W2_BUS_START(v)) {
#ifdef EXTENT_DEBUG
		printf("smem: freeing from 0x%lx to 0x%lx\n",
		    CHIP_S_MEM_W3_BUS_START(v), CHIP_S_MEM_W3_BUS_END(v));
#endif
		extent_free(sex, CHIP_S_MEM_W3_BUS_START(v),
		    CHIP_S_MEM_W3_BUS_END(v) - CHIP_S_MEM_W3_BUS_START(v) + 1,
		    EX_NOWAIT);
	} else {
#ifdef EXTENT_DEBUG
		printf("smem: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
		    CHIP_S_MEM_W2_BUS_START(v), CHIP_S_MEM_W2_BUS_END(v));
#endif
	}
#endif

#ifdef EXTENT_DEBUG
	extent_print(sex);
#endif
	CHIP_S_MEM_EXTENT(v) = sex;
}
void
__BS(unmap)(void *v, bus_space_handle_t h, bus_size_t size, int acct)
{
#ifdef CHIP_EXTENT
	bus_addr_t addr;
	int error;

	if (acct == 0)
		return;

#ifdef EXTENT_DEBUG
	printf("xxx: freeing handle 0x%lx for 0x%lx\n", h, size);
#endif

	if (h >= MIPS_KSEG0_START && h < MIPS_KSEG1_START)
		h = MIPS_KSEG0_TO_PHYS(h);
	else
		h = MIPS_KSEG1_TO_PHYS(h);

#ifdef CHIP_W1_BUS_START
	if (h >= CHIP_W1_SYS_START(v) && h <= CHIP_W1_SYS_END(v)) {
		addr = CHIP_W1_BUS_START(v) + (h - CHIP_W1_SYS_START(v));
	} else
#endif
#ifdef CHIP_W2_BUS_START
	if (h >= CHIP_W2_SYS_START(v) && h <= CHIP_W2_SYS_END(v)) {
		addr = CHIP_W2_BUS_START(v) + (h - CHIP_W2_SYS_START(v));
	} else
#endif
#ifdef CHIP_W3_BUS_START
	if (h >= CHIP_W3_SYS_START(v) && h <= CHIP_W3_SYS_END(v)) {
		addr = CHIP_W3_BUS_START(v) + (h - CHIP_W3_SYS_START(v));
	} else
#endif
	{
		printf("\n");
#ifdef CHIP_W1_BUS_START
		printf("%s: sys window[1]=0x%lx-0x%lx\n",
		    __S(__BS(map)), (u_long)CHIP_W1_SYS_START(v),
		    (u_long)CHIP_W1_SYS_END(v));
#endif
#ifdef CHIP_W2_BUS_START
		printf("%s: sys window[2]=0x%lx-0x%lx\n",
		    __S(__BS(map)), (u_long)CHIP_W2_SYS_START(v),
		    (u_long)CHIP_W2_SYS_END(v));
#endif
#ifdef CHIP_W3_BUS_START
		printf("%s: sys window[3]=0x%lx-0x%lx\n",
		    __S(__BS(map)), (u_long)CHIP_W3_SYS_START(v),
		    (u_long)CHIP_W3_SYS_END(v));
#endif
		panic("%s: don't know how to unmap %lx", __S(__BS(unmap)), h);
	}

#ifdef EXTENT_DEBUG
	printf("xxx: freeing 0x%lx to 0x%lx\n", addr, addr + size - 1);
#endif
        error = extent_free(CHIP_EXTENT(v), addr, size,
            EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
	if (error) {
		printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
		    __S(__BS(unmap)), addr, addr + size - 1,
		    error);
#ifdef EXTENT_DEBUG
		extent_print(CHIP_EXTENT(v));
#endif
	}	
#endif /* CHIP_EXTENT */
}
int
__BS(alloc)(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
    bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
    bus_space_handle_t *bshp)
{
#ifdef CHIP_EXTENT
	struct mips_bus_space_translation mbst;
	bus_addr_t addr;
	int error;
#if CHIP_ALIGN_STRIDE != 0
	int linear = flags & BUS_SPACE_MAP_LINEAR;

	/*
	 * Can't map xxx space linearly.
	 */
	if (linear)
		return (EOPNOTSUPP);
#endif

	/*
	 * Do the requested allocation.
	 */
#ifdef EXTENT_DEBUG
	printf("xxx: allocating from 0x%lx to 0x%lx\n", rstart, rend);
#endif
	error = extent_alloc_subregion(CHIP_EXTENT(v), rstart, rend, size,
	    align, boundary,
	    EX_FAST | EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0),
	    &addr);
	if (error) {
#ifdef EXTENT_DEBUG
		printf("xxx: allocation failed (%d)\n", error);
		extent_print(CHIP_EXTENT(v));
#endif
		return (error);
	}

#ifdef EXTENT_DEBUG
	printf("xxx: allocated 0x%lx to 0x%lx\n", addr, addr + size - 1);
#endif

	error = __BS(translate)(v, addr, size, flags, &mbst);
	if (error) {
		(void) extent_free(CHIP_EXTENT(v), addr, size,
		    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
		return (error);
	}

	*addrp = addr;
	if (flags & BUS_SPACE_MAP_CACHEABLE)
		*bshp = MIPS_PHYS_TO_KSEG0(mbst.mbst_sys_start +
		    (addr - mbst.mbst_bus_start));
	else
		*bshp = MIPS_PHYS_TO_KSEG1(mbst.mbst_sys_start +
		    (addr - mbst.mbst_bus_start));

	return (0);
#else /* ! CHIP_EXTENT */
	return (EOPNOTSUPP);
#endif /* CHIP_EXTENT */
}