Esempio n. 1
0
void
tsp_bus_mem_init2(bus_space_tag_t t, void *v)
{
    struct tsp_config *pcp = v;
    struct ts_pchip *pccsr = pcp->pc_csr;
    int i, error;

    /*
     * Allocate the DMA windows out of the extent map.
     */
    for (i = 0; i < 4; i++) {
        alpha_mb();
        if ((pccsr->tsp_wsba[i].tsg_r & WSBA_ENA) == 0) {
            /* Window not in use. */
            continue;
        }

        error = extent_alloc_region(CHIP_MEM_EXTENT(v),
                                    WSBA_ADDR(pccsr->tsp_wsba[i].tsg_r),
                                    WSM_LEN(pccsr->tsp_wsm[i].tsg_r),
                                    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
        if (error) {
            printf("WARNING: unable to reserve DMA window "
                   "0x%lx - 0x%lx\n",
                   WSBA_ADDR(pccsr->tsp_wsba[i].tsg_r),
                   WSBA_ADDR(pccsr->tsp_wsba[i].tsg_r) +
                   (WSM_LEN(pccsr->tsp_wsm[i].tsg_r) - 1));
        }
    }
}
void
tsp_dma_init(struct tsp_config *pcp)
{
	int i;
	bus_dma_tag_t t;
	struct ts_pchip *pccsr = pcp->pc_csr;
	bus_addr_t dwbase, dwlen, sgwbase, sgwlen, tbase;
	static struct map_expected {
		uint32_t base, mask, enables;
	} premap[4] = {
		{ 0x00800000, 0x00700000, WSBA_ENA | WSBA_SG },
		{ 0x80000000, 0x3ff00000, WSBA_ENA           },
		{ 0, 0, 0 },
		{ 0, 0, 0 }
	};

	alpha_mb();
	for(i = 0; i < 4; ++i) {
		if (EDIFF(pccsr->tsp_wsba[i].tsg_r, premap[i].base) ||
		    EDIFF(pccsr->tsp_wsm[i].tsg_r, premap[i].mask))
			printf("tsp%d: window %d: %lx/base %lx/mask %lx"
			    " reinitialized\n",
			    pcp->pc_pslot, i,
			    pccsr->tsp_wsba[i].tsg_r,
			    pccsr->tsp_wsm[i].tsg_r,
			    pccsr->tsp_tba[i].tsg_r);
		pccsr->tsp_wsba[i].tsg_r = premap[i].base | premap[i].enables;
		pccsr->tsp_wsm[i].tsg_r = premap[i].mask;
	}
	alpha_mb();

	/*
	 * Initialize the DMA tag used for direct-mapped DMA.
	 */
	t = &pcp->pc_dmat_direct;
	t->_cookie = pcp;
	t->_wbase = dwbase = WSBA_ADDR(pccsr->tsp_wsba[1].tsg_r);
	t->_wsize = dwlen = WSM_LEN(pccsr->tsp_wsm[1].tsg_r);
	t->_next_window = &pcp->pc_dmat_sgmap;
	t->_boundary = 0;
	t->_sgmap = NULL;
	t->_get_tag = tsp_dma_get_tag;
	t->_dmamap_create = _bus_dmamap_create;
	t->_dmamap_destroy = _bus_dmamap_destroy;
	t->_dmamap_load = _bus_dmamap_load_direct;
	t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct;
	t->_dmamap_load_uio = _bus_dmamap_load_uio_direct;
	t->_dmamap_load_raw = _bus_dmamap_load_raw_direct;
	t->_dmamap_unload = _bus_dmamap_unload;
	t->_dmamap_sync = _bus_dmamap_sync;

	t->_dmamem_alloc = _bus_dmamem_alloc;
	t->_dmamem_free = _bus_dmamem_free;
	t->_dmamem_map = _bus_dmamem_map;
	t->_dmamem_unmap = _bus_dmamem_unmap;
	t->_dmamem_mmap = _bus_dmamem_mmap;

	/*
	 * Initialize the DMA tag used for sgmap-mapped DMA.
	 */
	t = &pcp->pc_dmat_sgmap;
	t->_cookie = pcp;
	t->_wbase = sgwbase = WSBA_ADDR(pccsr->tsp_wsba[0].tsg_r);
	t->_wsize = sgwlen = WSM_LEN(pccsr->tsp_wsm[0].tsg_r);
	t->_next_window = NULL;
	t->_boundary = 0;
	t->_sgmap = &pcp->pc_sgmap;
	t->_pfthresh = TSP_SGMAP_PFTHRESH;
	t->_get_tag = tsp_dma_get_tag;
	t->_dmamap_create = alpha_sgmap_dmamap_create;
	t->_dmamap_destroy = alpha_sgmap_dmamap_destroy;
	t->_dmamap_load = tsp_bus_dmamap_load_sgmap;
	t->_dmamap_load_mbuf = tsp_bus_dmamap_load_mbuf_sgmap;
	t->_dmamap_load_uio = tsp_bus_dmamap_load_uio_sgmap;
	t->_dmamap_load_raw = tsp_bus_dmamap_load_raw_sgmap;
	t->_dmamap_unload = tsp_bus_dmamap_unload_sgmap;
	t->_dmamap_sync = _bus_dmamap_sync;

	t->_dmamem_alloc = _bus_dmamem_alloc;
	t->_dmamem_free = _bus_dmamem_free;
	t->_dmamem_map = _bus_dmamem_map;
	t->_dmamem_unmap = _bus_dmamem_unmap;
	t->_dmamem_mmap = _bus_dmamem_mmap;

	/*
	 * Initialize the SGMAP.  Align page table to 32k in case
	 * window is somewhat larger than expected.
	 */
	alpha_sgmap_init(t, &pcp->pc_sgmap, "tsp_sgmap",
	    sgwbase, 0, sgwlen, sizeof(uint64_t), NULL, (32*1024));

	/*
	 * Enable window 0 and enable SG PTE mapping.
	 */
	alpha_mb();
	pccsr->tsp_wsba[0].tsg_r |= WSBA_SG | WSBA_ENA;
	alpha_mb();

	/*
	 * Enable window 1 in direct mode.
	 */
	alpha_mb();
	pccsr->tsp_wsba[1].tsg_r =
	    (pccsr->tsp_wsba[1].tsg_r & ~WSBA_SG) | WSBA_ENA;
	alpha_mb();

	/*
	 * Check windows for sanity, especially if we later decide to
	 * use the firmware's initialization in some cases.
	 */
	if ((sgwbase <= dwbase && dwbase < sgwbase + sgwlen) ||
	    (dwbase <= sgwbase && sgwbase < dwbase + dwlen))
		panic("tsp_dma_init: overlap");

	tbase = pcp->pc_sgmap.aps_ptpa;
	if (tbase & ~0x7fffffc00UL)
		panic("tsp_dma_init: bad page table address");
	alpha_mb();
	pccsr->tsp_tba[0].tsg_r = tbase;
	alpha_mb();

	tsp_tlb_invalidate(pcp);
	alpha_mb();

	/* XXX XXX BEGIN XXX XXX */
	{							/* XXX */
		extern paddr_t alpha_XXX_dmamap_or;		/* XXX */
		alpha_XXX_dmamap_or = dwbase;			/* XXX */
	}							/* XXX */
	/* XXX XXX END XXX XXX */
}