示例#1
0
文件: x86_64.c 项目: karibou/progit
/*
 * Translate a virtual address to a physical address by using 4 levels paging.
 */
unsigned long long
vtop4_x86_64(unsigned long vaddr)
{
	unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
	unsigned long pte_paddr, pte;

	if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
		ERRMSG("Can't get the symbol of init_level4_pgt.\n");
		return NOT_PADDR;
	}

	/*
	 * Get PGD.
	 */
	page_dir  = SYMBOL(init_level4_pgt);
	page_dir += pml4_index(vaddr) * sizeof(unsigned long);
	if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) {
		ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir);
		return NOT_PADDR;
	}
	if (info->vaddr_for_vtop == vaddr)
		MSG("  PGD : %16lx => %16lx\n", page_dir, pml4);

	if (!(pml4 & _PAGE_PRESENT)) {
		ERRMSG("Can't get a valid pml4.\n");
		return NOT_PADDR;
	}

	/*
	 * Get PUD.
	 */
	pgd_paddr  = pml4 & PHYSICAL_PAGE_MASK;
	pgd_paddr += pgd_index(vaddr) * sizeof(unsigned long);
	if (!readmem(PADDR, pgd_paddr, &pgd_pte, sizeof pgd_pte)) {
		ERRMSG("Can't get pgd_pte (pgd_paddr:%lx).\n", pgd_paddr);
		return NOT_PADDR;
	}
	if (info->vaddr_for_vtop == vaddr)
		MSG("  PUD : %16lx => %16lx\n", pgd_paddr, pgd_pte);

	if (!(pgd_pte & _PAGE_PRESENT)) {
		ERRMSG("Can't get a valid pgd_pte.\n");
		return NOT_PADDR;
	}

	/*
	 * Get PMD.
	 */
	pmd_paddr  = pgd_pte & PHYSICAL_PAGE_MASK;
	pmd_paddr += pmd_index(vaddr) * sizeof(unsigned long);
	if (!readmem(PADDR, pmd_paddr, &pmd_pte, sizeof pmd_pte)) {
		ERRMSG("Can't get pmd_pte (pmd_paddr:%lx).\n", pmd_paddr);
		return NOT_PADDR;
	}
	if (info->vaddr_for_vtop == vaddr)
		MSG("  PMD : %16lx => %16lx\n", pmd_paddr, pmd_pte);

	if (!(pmd_pte & _PAGE_PRESENT)) {
		ERRMSG("Can't get a valid pmd_pte.\n");
		return NOT_PADDR;
	}
	if (pmd_pte & _PAGE_PSE)
		return (PAGEBASE(pmd_pte) & PHYSICAL_PAGE_MASK)
			+ (vaddr & ~_2MB_PAGE_MASK);

	/*
	 * Get PTE.
	 */
	pte_paddr  = pmd_pte & PHYSICAL_PAGE_MASK;
	pte_paddr += pte_index(vaddr) * sizeof(unsigned long);
	if (!readmem(PADDR, pte_paddr, &pte, sizeof pte)) {
		ERRMSG("Can't get pte (pte_paddr:%lx).\n", pte_paddr);
		return NOT_PADDR;
	}
	if (info->vaddr_for_vtop == vaddr)
		MSG("  PTE : %16lx => %16lx\n", pte_paddr, pte);

	if (!(pte & _PAGE_PRESENT)) {
		ERRMSG("Can't get a valid pte.\n");
		return NOT_PADDR;
	}
	return (PAGEBASE(pte) & PHYSICAL_PAGE_MASK) + PAGEOFFSET(vaddr);
}
示例#2
0
文件: hnddma.c 项目: ariavie/bcm
/*
 * Just like above except go through the extra effort of splitting
 * buffers that cross 4Kbyte boundaries into multiple tx descriptors.
 */
int
dma_tx(dma_info_t *di, void *p0, uint32 coreflags)
{
	void *p, *next;
	uchar *data;
	uint plen, len;
	uchar *page, *start, *end;
	uint txout;
	uint32 ctrl;
	uint32 pa;

	DMA_TRACE(("%s: dma_tx\n", di->name));

	txout = di->txout;
	ctrl = 0;

	/*
	 * Walk the chain of packet buffers
	 * splitting those that cross 4 Kbyte boundaries
	 * allocating and initializing transmit descriptor entries.
	 */
	for (p = p0; p; p = next) {
		data = PKTDATA(di->drv, p);
		plen = PKTLEN(di->drv, p);
		next = PKTNEXT(di->drv, p);

		/* PR988 - skip zero length buffers */
		if (plen == 0)
			continue;

		for (page = (uchar*)PAGEBASE(data);
			page <= (uchar*)PAGEBASE(data + plen - 1);
			page += PAGESZ) {

			/* return nonzero if out of tx descriptors */
			if (NEXTTXD(txout) == di->txin)
				goto outoftxd;

			start = (page == (uchar*)PAGEBASE(data))?  data: page;
			end = (page == (uchar*)PAGEBASE(data + plen))?
				(data + plen): (page + PAGESZ);
			len = end - start;

			/* build the descriptor control value */
			ctrl = len & CTRL_BC_MASK;

			/* PR3697: Descriptor flags are not ignored for descriptors where SOF is clear */
			ctrl |= coreflags;

			if ((p == p0) && (start == data))
				ctrl |= CTRL_SOF;
			if ((next == NULL) && (end == (data + plen)))
				ctrl |= (CTRL_IOC | CTRL_EOF);
			if (txout == (di->ntxd - 1))
				ctrl |= CTRL_EOT;

			/* get physical address of buffer start */
			pa = (uint32) DMA_MAP(di->dev, start, len, DMA_TX, p);

			/* init the tx descriptor */
			W_SM(&di->txd[txout].ctrl, BUS_SWAP32(ctrl));
			W_SM(&di->txd[txout].addr, BUS_SWAP32(pa + di->dataoffset));

			ASSERT(di->txp[txout] == NULL);

			txout = NEXTTXD(txout);
		}
	}

	/* if last txd eof not set, fix it */
	if (!(ctrl & CTRL_EOF))
		W_SM(&di->txd[PREVTXD(txout)].ctrl, BUS_SWAP32(ctrl | CTRL_IOC | CTRL_EOF));

	/* save the packet */
	di->txp[di->txout] = p0;

	/* bump the tx descriptor index */
	di->txout = txout;

	/* kick the chip */
	W_REG(&di->regs->xmtptr, I2B(txout));

	/* tx flow control */
	di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;

	return (0);

outoftxd:
	DMA_ERROR(("%s: dma_tx: out of txds\n", di->name));
	PKTFREE(di->drv, p0, TRUE);
	di->txavail = 0;
	di->hnddma.txnobuf++;
	return (-1);
}