mbcs.c

来自「linux 内核源代码」· C语言 代码 · 共 846 行 · 第 1/2 页

C
846
字号
/* * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (c) 2005 Silicon Graphics, Inc.  All rights reserved. *//* *	MOATB Core Services driver. */#include <linux/interrupt.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/types.h>#include <linux/ioport.h>#include <linux/notifier.h>#include <linux/reboot.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/device.h>#include <linux/mm.h>#include <linux/uio.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/pgtable.h>#include <asm/sn/addrs.h>#include <asm/sn/intr.h>#include <asm/sn/tiocx.h>#include "mbcs.h"#define MBCS_DEBUG 0#if MBCS_DEBUG#define DBG(fmt...)    printk(KERN_ALERT fmt)#else#define DBG(fmt...)#endifstatic int mbcs_major;static LIST_HEAD(soft_list);/* * file operations */static const struct file_operations mbcs_ops = {	.open = mbcs_open,	.llseek = mbcs_sram_llseek,	.read = mbcs_sram_read,	.write = mbcs_sram_write,	.mmap = mbcs_gscr_mmap,};struct mbcs_callback_arg {	int minor;	struct cx_dev *cx_dev;};static inline void mbcs_getdma_init(struct getdma *gdma){	memset(gdma, 0, sizeof(struct getdma));	gdma->DoneIntEnable = 1;}static inline void mbcs_putdma_init(struct putdma *pdma){	memset(pdma, 0, sizeof(struct putdma));	pdma->DoneIntEnable = 1;}static inline void mbcs_algo_init(struct algoblock *algo_soft){	memset(algo_soft, 0, sizeof(struct algoblock));}static inline void mbcs_getdma_set(void *mmr,		       uint64_t hostAddr,		       uint64_t localAddr,		       uint64_t localRamSel,		       uint64_t numPkts,		       uint64_t amoEnable,		       uint64_t intrEnable,		       uint64_t peerIO,		       uint64_t amoHostDest,		       uint64_t amoModType, uint64_t intrHostDest,		       uint64_t intrVector){	union dma_control rdma_control;	union dma_amo_dest amo_dest;	union intr_dest intr_dest;	union dma_localaddr local_addr;	union dma_hostaddr host_addr;	rdma_control.dma_control_reg = 0;	amo_dest.dma_amo_dest_reg = 0;	intr_dest.intr_dest_reg = 0;	local_addr.dma_localaddr_reg = 0;	host_addr.dma_hostaddr_reg = 0;	host_addr.dma_sys_addr = hostAddr;	MBCS_MMR_SET(mmr, MBCS_RD_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg);	local_addr.dma_ram_addr = localAddr;	local_addr.dma_ram_sel = localRamSel;	MBCS_MMR_SET(mmr, MBCS_RD_DMA_LOC_ADDR, local_addr.dma_localaddr_reg);	rdma_control.dma_op_length = numPkts;	rdma_control.done_amo_en = amoEnable;	rdma_control.done_int_en = intrEnable;	rdma_control.pio_mem_n = peerIO;	MBCS_MMR_SET(mmr, MBCS_RD_DMA_CTRL, rdma_control.dma_control_reg);	amo_dest.dma_amo_sys_addr = amoHostDest;	amo_dest.dma_amo_mod_type = amoModType;	MBCS_MMR_SET(mmr, MBCS_RD_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg);	intr_dest.address = intrHostDest;	intr_dest.int_vector = intrVector;	MBCS_MMR_SET(mmr, MBCS_RD_DMA_INT_DEST, intr_dest.intr_dest_reg);}static inline void mbcs_putdma_set(void *mmr,		       uint64_t hostAddr,		       uint64_t localAddr,		       uint64_t localRamSel,		       uint64_t numPkts,		       uint64_t amoEnable,		       uint64_t intrEnable,		       uint64_t peerIO,		       uint64_t amoHostDest,		       uint64_t amoModType,		       uint64_t intrHostDest, uint64_t intrVector){	union dma_control wdma_control;	union dma_amo_dest amo_dest;	union intr_dest intr_dest;	union dma_localaddr local_addr;	union dma_hostaddr host_addr;	wdma_control.dma_control_reg = 0;	amo_dest.dma_amo_dest_reg = 0;	intr_dest.intr_dest_reg = 0;	local_addr.dma_localaddr_reg = 0;	host_addr.dma_hostaddr_reg = 0;	host_addr.dma_sys_addr = hostAddr;	MBCS_MMR_SET(mmr, MBCS_WR_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg);	local_addr.dma_ram_addr = localAddr;	local_addr.dma_ram_sel = localRamSel;	MBCS_MMR_SET(mmr, MBCS_WR_DMA_LOC_ADDR, local_addr.dma_localaddr_reg);	wdma_control.dma_op_length = numPkts;	wdma_control.done_amo_en = amoEnable;	wdma_control.done_int_en = intrEnable;	wdma_control.pio_mem_n = peerIO;	MBCS_MMR_SET(mmr, MBCS_WR_DMA_CTRL, wdma_control.dma_control_reg);	amo_dest.dma_amo_sys_addr = amoHostDest;	amo_dest.dma_amo_mod_type = amoModType;	MBCS_MMR_SET(mmr, MBCS_WR_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg);	intr_dest.address = intrHostDest;	intr_dest.int_vector = intrVector;	MBCS_MMR_SET(mmr, MBCS_WR_DMA_INT_DEST, intr_dest.intr_dest_reg);}static inline void mbcs_algo_set(void *mmr,		     uint64_t amoHostDest,		     uint64_t amoModType,		     uint64_t intrHostDest,		     uint64_t intrVector, uint64_t algoStepCount){	union dma_amo_dest amo_dest;	union intr_dest intr_dest;	union algo_step step;	step.algo_step_reg = 0;	intr_dest.intr_dest_reg = 0;	amo_dest.dma_amo_dest_reg = 0;	amo_dest.dma_amo_sys_addr = amoHostDest;	amo_dest.dma_amo_mod_type = amoModType;	MBCS_MMR_SET(mmr, MBCS_ALG_AMO_DEST, amo_dest.dma_amo_dest_reg);	intr_dest.address = intrHostDest;	intr_dest.int_vector = intrVector;	MBCS_MMR_SET(mmr, MBCS_ALG_INT_DEST, intr_dest.intr_dest_reg);	step.alg_step_cnt = algoStepCount;	MBCS_MMR_SET(mmr, MBCS_ALG_STEP, step.algo_step_reg);}static inline int mbcs_getdma_start(struct mbcs_soft *soft){	void *mmr_base;	struct getdma *gdma;	uint64_t numPkts;	union cm_control cm_control;	mmr_base = soft->mmr_base;	gdma = &soft->getdma;	/* check that host address got setup */	if (!gdma->hostAddr)		return -1;	numPkts =	    (gdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE;	/* program engine */	mbcs_getdma_set(mmr_base, tiocx_dma_addr(gdma->hostAddr),		   gdma->localAddr,		   (gdma->localAddr < MB2) ? 0 :		   (gdma->localAddr < MB4) ? 1 :		   (gdma->localAddr < MB6) ? 2 : 3,		   numPkts,		   gdma->DoneAmoEnable,		   gdma->DoneIntEnable,		   gdma->peerIO,		   gdma->amoHostDest,		   gdma->amoModType,		   gdma->intrHostDest, gdma->intrVector);	/* start engine */	cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);	cm_control.rd_dma_go = 1;	MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);	return 0;}static inline int mbcs_putdma_start(struct mbcs_soft *soft){	void *mmr_base;	struct putdma *pdma;	uint64_t numPkts;	union cm_control cm_control;	mmr_base = soft->mmr_base;	pdma = &soft->putdma;	/* check that host address got setup */	if (!pdma->hostAddr)		return -1;	numPkts =	    (pdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE;	/* program engine */	mbcs_putdma_set(mmr_base, tiocx_dma_addr(pdma->hostAddr),		   pdma->localAddr,		   (pdma->localAddr < MB2) ? 0 :		   (pdma->localAddr < MB4) ? 1 :		   (pdma->localAddr < MB6) ? 2 : 3,		   numPkts,		   pdma->DoneAmoEnable,		   pdma->DoneIntEnable,		   pdma->peerIO,		   pdma->amoHostDest,		   pdma->amoModType,		   pdma->intrHostDest, pdma->intrVector);	/* start engine */	cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);	cm_control.wr_dma_go = 1;	MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);	return 0;}static inline int mbcs_algo_start(struct mbcs_soft *soft){	struct algoblock *algo_soft = &soft->algo;	void *mmr_base = soft->mmr_base;	union cm_control cm_control;	if (down_interruptible(&soft->algolock))		return -ERESTARTSYS;	atomic_set(&soft->algo_done, 0);	mbcs_algo_set(mmr_base,		 algo_soft->amoHostDest,		 algo_soft->amoModType,		 algo_soft->intrHostDest,		 algo_soft->intrVector, algo_soft->algoStepCount);	/* start algorithm */	cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);	cm_control.alg_done_int_en = 1;	cm_control.alg_go = 1;	MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);	up(&soft->algolock);	return 0;}static inline ssize_tdo_mbcs_sram_dmawrite(struct mbcs_soft *soft, uint64_t hostAddr,		      size_t len, loff_t * off){	int rv = 0;	if (down_interruptible(&soft->dmawritelock))		return -ERESTARTSYS;	atomic_set(&soft->dmawrite_done, 0);	soft->putdma.hostAddr = hostAddr;	soft->putdma.localAddr = *off;	soft->putdma.bytes = len;	if (mbcs_putdma_start(soft) < 0) {		DBG(KERN_ALERT "do_mbcs_sram_dmawrite: "					"mbcs_putdma_start failed\n");		rv = -EAGAIN;		goto dmawrite_exit;	}	if (wait_event_interruptible(soft->dmawrite_queue,					atomic_read(&soft->dmawrite_done))) {		rv = -ERESTARTSYS;		goto dmawrite_exit;	}	rv = len;	*off += len;dmawrite_exit:	up(&soft->dmawritelock);	return rv;}static inline ssize_tdo_mbcs_sram_dmaread(struct mbcs_soft *soft, uint64_t hostAddr,		     size_t len, loff_t * off){	int rv = 0;	if (down_interruptible(&soft->dmareadlock))		return -ERESTARTSYS;	atomic_set(&soft->dmawrite_done, 0);	soft->getdma.hostAddr = hostAddr;	soft->getdma.localAddr = *off;	soft->getdma.bytes = len;	if (mbcs_getdma_start(soft) < 0) {		DBG(KERN_ALERT "mbcs_strategy: mbcs_getdma_start failed\n");		rv = -EAGAIN;		goto dmaread_exit;	}	if (wait_event_interruptible(soft->dmaread_queue,					atomic_read(&soft->dmaread_done))) {		rv = -ERESTARTSYS;		goto dmaread_exit;	}	rv = len;	*off += len;dmaread_exit:	up(&soft->dmareadlock);	return rv;}static int mbcs_open(struct inode *ip, struct file *fp){	struct mbcs_soft *soft;	int minor;	minor = iminor(ip);	list_for_each_entry(soft, &soft_list, list) {		if (soft->nasid == minor) {			fp->private_data = soft->cxdev;			return 0;		}	}	return -ENODEV;}static ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t * off){	struct cx_dev *cx_dev = fp->private_data;	struct mbcs_soft *soft = cx_dev->soft;	uint64_t hostAddr;	int rv = 0;	hostAddr = __get_dma_pages(GFP_KERNEL, get_order(len));	if (hostAddr == 0)		return -ENOMEM;	rv = do_mbcs_sram_dmawrite(soft, hostAddr, len, off);	if (rv < 0)		goto exit;	if (copy_to_user(buf, (void *)hostAddr, len))		rv = -EFAULT;      exit:	free_pages(hostAddr, get_order(len));	return rv;}static ssize_tmbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * off){	struct cx_dev *cx_dev = fp->private_data;

⌨️ 快捷键说明

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