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 + -
显示快捷键?