⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pciba.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		break;			/* "unable to set up ULI" */	    }	    atomic_inc(&pciba_prevent_unload);	    pciio_intr_connect(intr, pciba_intr, uli, (void *) 0);	    /* NOTE: don't set the teardown function	     * until the interrupt is connected.	     */	    uli->teardownarg1 = (__psint_t) intr;	    uli->teardown = pciba_clearuli;	    arg.uli.id = uli->index;	    if (!ABI_IS_64BIT(abi)) {		struct uliargs32 uliargs32;		uliargs_to_uliargs32(&arg.uli, &uliargs32);		arg.uli32 = uliargs32;	    }	    err = 0;	    break;#endif	case PCIBA_SPACE_UDMA:		/* the "dma" vertex */	    switch (cmd) {	    case PCIIOCDMAALLOC:		/* PCIIOCDMAALLOC: allocate a chunk of physical		 * memory and set it up for DMA. Return the		 * PCI address that gets to it.		 * NOTE: this allocates memory local to the		 * CPU doing the ioctl, not local to the		 * device that will be doing the DMA.		 */		if (!_CAP_ABLE(CAP_DEVICE_MGT)) {		    err = EPERM;		    break;		}		/* separate the halves of the incoming parameter */		flags = arg.ud >> 32;		bytes = arg.ud & 0xFFFFFFFF;#if DEBUG_PCIBA		printf("pciba: user wants 0x%x bytes of DMA, flags 0x%x\n",		       bytes, flags);#endif		/* round up the requested size to the next highest page */		pages = (bytes + NBPP - 1) / NBPP;		/* make sure the requested size is something reasonable */		if (pages > pci_user_dma_max_pages) {#if DEBUG_PCIBA		    printf("pciba: request for too much buffer space\n");#endif		    err = EINVAL;		    break;		/* "request for too much buffer space" */		}		/* "correct" number of bytes */		bytes = pages * NBPP;		/* allocate the space */		/* XXX- force to same node as the device? */		/* XXX- someday, we want to handle user buffers,		 *    and noncontiguous pages, but this will		 *      require either fancy mapping or handing		 *      a list of blocks back to the user. For		 *      now, just tell users to allocate a lot of		 *      individual single-pages and manage their		 *      scatter-gather manually.		 */		kaddr = kvpalloc(pages, VM_DIRECT | KM_NOSLEEP, 0);		if (kaddr == 0) {#if DEBUG_PCIBA		    printf("pciba: unable to get %d contiguous pages\n", pages);#endif		    err = EAGAIN;	/* "insufficient resources, try again later" */		    break;		}#if DEBUG_PCIBA		printf("pciba: kaddr is 0x%x\n", kaddr);#endif		paddr = kvtophys(kaddr);		daddr = pciio_dmatrans_addr		    (soft->comm->conn, 0, paddr, bytes, flags);		if (daddr == 0) {	/* "no direct path available" */#if DEBUG_PCIBA		    printf("pciba: dmatrans failed, trying dmamap\n");#endif		    dmamap = pciio_dmamap_alloc			(soft->comm->conn, 0, bytes, flags);		    if (dmamap == 0) {#if DEBUG_PCIBA			printf("pciba: unable to allocate dmamap\n");#endif			err = ENOMEM;			break;		/* "out of mapping resources" */		    }		    daddr = pciio_dmamap_addr			(dmamap, paddr, bytes);		    if (daddr == 0) {#if DEBUG_PCIBA			printf("pciba: dmamap_addr failed\n");#endif			err = EINVAL;			break;		/* "can't get there from here" */		    }		}#if DEBUG_PCIBA		printf("pciba: daddr is 0x%x\n", daddr);#endif		NEW(dmap);		if (!dmap) {		    err = ENOMEM;		    break;		/* "no memory available" */		}		dmap->bytes = bytes;		dmap->pages = pages;		dmap->paddr = paddr;		dmap->kaddr = kaddr;		dmap->map = dmamap;		dmap->daddr = daddr;		dmap->handle = 0;#if DEBUG_PCIBA		printf("pciba: dmap 0x%x contains va 0x%x bytes 0x%x pa 0x%x pages 0x%x daddr 0x%x\n",		       dmap, kaddr, bytes, paddr, pages, daddr);#endif		arg.ud = dmap->daddr;		err = 0;		break;	    case PCIIOCDMAFREE:		/* PCIIOCDMAFREE: Find the chunk of		 * User DMA memory, and release its		 * resources back to the system.		 */		if (!_CAP_ABLE(CAP_DEVICE_MGT)) {		    err = EPERM;	/* "you can't do that" */		    break;		}		if (soft->comm->dmap == NULL) {		    err = EINVAL;	/* "no User DMA to free" */		    break;		}		/* find the request. */		daddr = arg.ud;		err = EINVAL;		/* "block not found" */		pciba_soft_lock(soft);		for (dmah = &soft->comm->dmap; dmap = *dmah; dmah = &dmap->next) {		    if (dmap->daddr == daddr) {			if (dmap->handle != 0) {			    dmap = 0;	/* don't DEL this dmap! */			    err = EINVAL;	/* "please unmap first" */			    break;		/* break outa for loop. */			}			*dmah = dmap->next;			if (dmamap = dmap->map) {			    pciio_dmamap_free(dmamap);			    dmamap = 0;	/* don't free it twice! */			}			kvpfree(dmap->kaddr, dmap->bytes / NBPP);			DEL(dmap);			dmap = 0;	/* don't link this back into the list! */			err = 0;	/* "all done" */			break;		/* break outa for loop. */		    }		}		pciba_soft_unlock(soft);		break;		/* break outa case PCIIOCDMAFREE: */	    }	    break;		/* break outa case PCIBA_SPACE_UDMA: */	case PCIIO_SPACE_CFG:	    /* PCIIOCCFG{RD,WR}: read and/or write	     * PCI configuration space. If both,	     * the read happens first (this becomes	     * a swap operation, atomic with respect	     * to other updates through this path).	     *	     * Should be *last* IOCTl command checked,	     * so other patterns can nip useless codes	     * out of the space this decodes.	     */	    err = EINVAL;	    if ((psize > 0) || (psize <= 8) &&		(((cmd & 0xFF) + psize) <= 256) &&		(cmd & (IOC_IN | IOC_OUT))) {		uint64_t                rdata;		uint64_t                wdata;		int                     shft;		shft = 64 - (8 * psize);		wdata = arg.ud >> shft;		pciba_soft_lock(soft);		if (cmd & IOC_OUT)		    rdata = pciio_config_get(soft->comm->conn, cmd & 0xFFFF, psize);		if (cmd & IOC_IN)		    pciio_config_set(soft->comm->conn, cmd & 0xFFFF, psize, wdata);		pciba_soft_unlock(soft);		arg.ud = rdata << shft;		err = 0;		break;	    }	    break;	}    }    /* done: come here if all went OK.     */    if ((err == 0) &&	((cmd & IOC_OUT) && (psize > 0)) &&	copyout(arg.data, uarg, psize))	err = EFAULT;    /* This gets delayed until after the copyout so we     * do not free the dmap on a copyout error, or     * alternately end up with a dangling allocated     * buffer that the user never got back.     */    if ((err == 0) && dmap) {	pciba_soft_lock(soft);	dmap->next = soft->comm->dmap;	soft->comm->dmap = dmap;	pciba_soft_unlock(soft);    }    if (err) {	/* Things went badly. Clean up.	 */#if ULI	if (intr) {	    pciio_intr_disconnect(intr);	    pciio_intr_free(intr);	}	if (uli)	    free_uli(uli);#endif	if (dmap) {	    if (dmap->map && (dmap->map != dmamap))		pciio_dmamap_free(dmap->map);	    DEL(dmap);	}	if (dmamap)	    pciio_dmamap_free(dmamap);	if (kaddr)	    kvpfree(kaddr, pages);    }    return *rvalp = err;}/* ================================================================ *            mapping support *//*ARGSUSED */intpciba_map(dev_t dev, vhandl_t *vt,	  off_t off, size_t len, uint32_t prot){    devfs_handle_t          vhdl = dev_to_vhdl(dev);    pciba_soft_t            soft = pciba_soft_get(vhdl);    devfs_handle_t          conn = soft->comm->conn;    pciio_space_t           space = soft->space;    size_t                  pages = (len + NBPP - 1) / NBPP;    pciio_piomap_t          pciio_piomap = 0;    caddr_t                 kaddr;    pciba_map_t             map;    pciba_dma_t             dmap;#if DEBUG_PCIBA    printf("pciba_map(%V,vt=0x%x)\n", dev, vt);#endif    if (space == PCIBA_SPACE_UDMA) {	pciba_soft_lock(soft);	for (dmap = soft->comm->dmap; dmap != NULL; dmap = dmap->next) {	    if (off == dmap->daddr) {		if (pages != dmap->pages) {		    pciba_soft_unlock(soft);		    return EINVAL;	/* "size mismatch" */		}		v_mapphys(vt, dmap->kaddr, dmap->bytes);		dmap->handle = v_gethandle(vt);		pciba_soft_unlock(soft);#if DEBUG_PCIBA		printf("pciba: mapped dma at kaddr 0x%x via handle 0x%x\n",		       dmap->kaddr, dmap->handle);#endif		return 0;	    }	}	pciba_soft_unlock(soft);	return EINVAL;			/* "block not found" */    }    if (soft->iomem == PCIIO_SPACE_NONE)	return EINVAL;			/* "mmap not supported" */    kaddr = (caddr_t) pciio_pio_addr	(conn, 0, space, off, len, &pciio_piomap, soft->flags | PCIIO_FIXED );#if DEBUG_PCIBA    printf("pciba: mapped %R[0x%x..0x%x] via map 0x%x to kaddr 0x%x\n",	   space, space_desc, off, off + len - 1, pciio_piomap, kaddr);#endif    if (kaddr == NULL)	return EINVAL;			/* "you can't get there from here" */    NEW(map);    if (map == NULL) {	if (pciio_piomap)	    pciio_piomap_free(pciio_piomap);	return ENOMEM;			/* "unable to get memory resources */    }#ifdef LATER    map->uthread = curuthread;#endif    map->handle = v_gethandle(vt);    map->uvaddr = v_getaddr(vt);    map->map = pciio_piomap;    map->space = soft->iomem;    map->base = soft->base + off;    map->size = len;    pciba_map_push(soft->comm->bus, map);    /* Inform the system of the correct     * kvaddr corresponding to the thing     * that is being mapped.     */    v_mapphys(vt, kaddr, len);    return 0;}/*ARGSUSED */intpciba_unmap(dev_t dev, vhandl_t *vt){    devfs_handle_t         vhdl = dev_to_vhdl(dev);    pciba_soft_t            soft = pciba_soft_get(vhdl);    pciba_bus_t             bus = soft->comm->bus;    pciba_map_t             map;    __psunsigned_t          handle = v_gethandle(vt);#if DEBUG_PCIBA    printf("pciba_unmap(%V,vt=%x)\n", dev, vt);#endif    /* If this is a userDMA buffer,     * make a note that it has been unmapped     * so it can be released.     */    if (soft->comm->dmap) {	pciba_dma_t             dmap;	pciba_soft_lock(soft);	for (dmap = soft->comm->dmap; dmap != NULL; dmap = dmap->next)	    if (handle == dmap->handle) {		dmap->handle = 0;		pciba_soft_unlock(soft);#if DEBUG_PCIBA		printf("pciba: unmapped dma at kaddr 0x%x via handle 0x%x\n",		       dmap->kaddr, handle);#endif		return 0;		/* found userPCI */	    }	pciba_soft_unlock(soft);    }    map = pciba_map_pop_hdl(bus, handle);    if (map == NULL)	return EINVAL;			/* no match */    if (map->map)	pciio_piomap_free(map->map);    DEL(map);    return (0);				/* all done OK */}#if ULIvoidpciba_clearuli(struct uli *uli){    pciio_intr_t            intr = (pciio_intr_t) uli->teardownarg1;#if DEBUG_PCIBA    printf("pciba_clearuli(0x%x)\n", uli);#endif    pciio_intr_disconnect(intr);    pciio_intr_free(intr);    atomic_dec(&pciba_prevent_unload);}voidpciba_intr(intr_arg_t arg){    struct uli             *uli = (struct uli *) arg;    int                     ulinum = uli->index;    extern void frs_handle_uli(void);    if (ulinum >= 0 && ulinum < MAX_ULIS) {	    uli_callup(ulinum);	    if (private.p_frs_flags)		    frs_handle_uli();    }}#endif#endif /* LATER - undef as we implement each routine */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -