Exemplo n.º 1
0
int encdec_init(void)
{
	u64 muid, dma_bus_addr;
	int result;

	result = lv1_allocate_memory(ENCDEC_DMA_SIZE, ENCDEC_DMA_PAGE_SIZE, 0, 0,
		&encdec_buf_lpar_addr, &muid);
	if (result != 0)
		return result;

	result = lv1_allocate_device_dma_region(ENCDEC_BUS_ID, ENCDEC_DEV_ID,
		ENCDEC_DMA_SIZE, ENCDEC_DMA_PAGE_SIZE, 0, &dma_bus_addr);
	if (result != 0)
		return result;

	result = lv1_map_device_dma_region(ENCDEC_BUS_ID, ENCDEC_DEV_ID,
		encdec_buf_lpar_addr, dma_bus_addr, ENCDEC_DMA_SIZE, 0xF800000000000000ULL);
	if (result != 0)
		return result;

	MM_LOAD_BASE(encdec_buf, ENCDEC_DMA_OFFSET);

	result = mm_map_lpar_memory_region(0, MM_EA2VA((u64) encdec_buf), encdec_buf_lpar_addr,
		ENCDEC_DMA_SIZE, ENCDEC_DMA_PAGE_SIZE, 0, 0);
	if (result != 0)
		return result;

	memset(encdec_buf, 0, ENCDEC_DMA_SIZE);

	return 0;
}
Exemplo n.º 2
0
static void map_dma_mem(int bus_id, int dev_id, void *start, size_t len,
			u64 *real_bus_addr)
{
	s64 result;
	u64 real_addr = ((u64)start) & 0x0fffffffffffffffUL;
	u64 real_end = real_addr + len;
	u64 map_start = real_addr & ~0xfff;
	u64 map_end = (real_end + 0xfff) & ~0xfff;
	u64 bus_addr = 0;

	u64 flags = 0xf800000000000000UL;

	result = lv1_allocate_device_dma_region(bus_id, dev_id,
						map_end - map_start, 12, 0,
						&bus_addr);
	if (result)
		lv1_panic(0);

	result = lv1_map_device_dma_region(bus_id, dev_id, map_start,
					   bus_addr, map_end - map_start,
					   flags);
	if (result)
		lv1_panic(0);

	*real_bus_addr = bus_addr + real_addr - map_start;
}
Exemplo n.º 3
0
static bus_dma_tag_t
ps3bus_get_dma_tag(device_t dev, device_t child)
{
	struct ps3bus_devinfo *dinfo = device_get_ivars(child);
	struct ps3bus_softc *sc = device_get_softc(dev);
	int i, err, flags, pagesize;

	if (dinfo->bustype != PS3_BUSTYPE_SYSBUS &&
	    dinfo->bustype != PS3_BUSTYPE_STORAGE)
		return (bus_get_dma_tag(dev));

	mtx_lock(&dinfo->iommu_mtx);
	if (dinfo->dma_tag != NULL) {
		mtx_unlock(&dinfo->iommu_mtx);
		return (dinfo->dma_tag);
	}

	flags = 0; /* 32-bit mode */
	if (dinfo->bustype == PS3_BUSTYPE_SYSBUS &&
	    dinfo->devtype == PS3_DEVTYPE_USB)
		flags = 2; /* 8-bit mode */

	pagesize = 24; /* log_2(16 MB) */
	if (dinfo->bustype == PS3_BUSTYPE_STORAGE)
		pagesize = 12; /* 4 KB */

	for (i = 0; i < sc->rcount; i++) {
		err = lv1_allocate_device_dma_region(dinfo->bus, dinfo->dev,
		    sc->regions[i].mr_size, pagesize, flags,
		    &dinfo->dma_base[i]);
		if (err != 0) {
			device_printf(child,
			    "could not allocate DMA region %d: %d\n", i, err);
			goto fail;
		}

		err = lv1_map_device_dma_region(dinfo->bus, dinfo->dev,
		    sc->regions[i].mr_start, dinfo->dma_base[i],
		    sc->regions[i].mr_size,
		    0xf800000000000800UL /* Cell Handbook Figure 7.3.4.1 */);
		if (err != 0) {
			device_printf(child,
			    "could not map DMA region %d: %d\n", i, err);
			goto fail;
		}
	}

	err = bus_dma_tag_create(bus_get_dma_tag(dev),
	    1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
	    NULL, NULL, BUS_SPACE_MAXSIZE, 0, BUS_SPACE_MAXSIZE,
	    0, NULL, NULL, &dinfo->dma_tag);

	/*
	 * Note: storage devices have IOMMU mappings set up by the hypervisor,
	 * but use physical, non-translated addresses. The above IOMMU
	 * initialization is necessary for the hypervisor to be able to set up
	 * the mappings, but actual DMA mappings should not use the IOMMU
	 * routines.
	 */
	if (dinfo->bustype != PS3_BUSTYPE_STORAGE)
		bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo);

fail:
	mtx_unlock(&dinfo->iommu_mtx);

	if (err)
		return (NULL);

	return (dinfo->dma_tag);
}