shub.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 247 行

C
247
字号
/* * 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) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All Rights Reserved. */#include <linux/types.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/seq_file.h>#include <linux/sched.h>#include <asm/smp.h>#include <asm/irq.h>#include <asm/hw_irq.h>#include <asm/system.h>#include <asm/sn/sgi.h>#include <asm/uaccess.h>#include <asm/sn/hcl.h>#include <asm/sn/labelcl.h>#include <asm/sn/io.h>#include <asm/sn/sn_private.h>#include <asm/sn/klconfig.h>#include <asm/sn/sn_cpuid.h>#include <asm/sn/pci/pciio.h>#include <asm/sn/pci/pcibr.h>#include <asm/sn/xtalk/xtalk.h>#include <asm/sn/pci/pcibr_private.h>#include <asm/sn/intr.h>#include <asm/sn/sn2/shub_mmr.h>#include <asm/sn/sn2/shub_mmr_t.h>#include <asm/sal.h>#include <asm/sn/sn_sal.h>#include <asm/sn/sndrv.h>#include <asm/sn/sn2/shubio.h>#define SHUB_NUM_ECF_REGISTERS 8static uint32_t	shub_perf_counts[SHUB_NUM_ECF_REGISTERS];static shubreg_t shub_perf_counts_regs[SHUB_NUM_ECF_REGISTERS] = {	SH_PERFORMANCE_COUNTER0,	SH_PERFORMANCE_COUNTER1,	SH_PERFORMANCE_COUNTER2,	SH_PERFORMANCE_COUNTER3,	SH_PERFORMANCE_COUNTER4,	SH_PERFORMANCE_COUNTER5,	SH_PERFORMANCE_COUNTER6,	SH_PERFORMANCE_COUNTER7};static inline voidshub_mmr_write(cnodeid_t cnode, shubreg_t reg, uint64_t val){	int		   nasid = cnodeid_to_nasid(cnode);	volatile uint64_t *addr = (uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));	*addr = val;	__ia64_mf_a();}static inline voidshub_mmr_write_iospace(cnodeid_t cnode, shubreg_t reg, uint64_t val){	int		   nasid = cnodeid_to_nasid(cnode);	REMOTE_HUB_S(nasid, reg, val);}static inline voidshub_mmr_write32(cnodeid_t cnode, shubreg_t reg, uint32_t val){	int		   nasid = cnodeid_to_nasid(cnode);	volatile uint32_t *addr = (uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));	*addr = val;	__ia64_mf_a();}static inline uint64_tshub_mmr_read(cnodeid_t cnode, shubreg_t reg){	int		  nasid = cnodeid_to_nasid(cnode);	volatile uint64_t val;	val = *(uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));	__ia64_mf_a();	return val;}static inline uint64_tshub_mmr_read_iospace(cnodeid_t cnode, shubreg_t reg){	int		  nasid = cnodeid_to_nasid(cnode);	return REMOTE_HUB_L(nasid, reg);}static inline uint32_tshub_mmr_read32(cnodeid_t cnode, shubreg_t reg){	int		  nasid = cnodeid_to_nasid(cnode);	volatile uint32_t val;	val = *(uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));	__ia64_mf_a();	return val;}static intreset_shub_stats(cnodeid_t cnode){	int i;	for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {		shub_perf_counts[i] = 0;		shub_mmr_write32(cnode, shub_perf_counts_regs[i], 0);	}	return 0;}static intconfigure_shub_stats(cnodeid_t cnode, unsigned long arg){	uint64_t	*p = (uint64_t *)arg;	uint64_t	i;	uint64_t	regcnt;	uint64_t	regval[2];	if (copy_from_user((void *)&regcnt, p, sizeof(regcnt)))	    return -EFAULT;	for (p++, i=0; i < regcnt; i++, p += 2) {		if (copy_from_user((void *)regval, (void *)p, sizeof(regval)))		    return -EFAULT;		if (regval[0] & 0x7) {		    printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]);		    return -EINVAL;		}		shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]);	}	return 0;}static intcapture_shub_stats(cnodeid_t cnode, uint32_t *counts){	int 		i;	for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {		counts[i] = shub_mmr_read32(cnode, shub_perf_counts_regs[i]);	}	return 0;}static intshubstats_ioctl(struct inode *inode, struct file *file,        unsigned int cmd, unsigned long arg){	cnodeid_t       cnode;	uint64_t        longarg;	uint64_t        intarg;	uint64_t        regval[2];	int		nasid;        cnode = (cnodeid_t)(u64)file->f_dentry->d_fsdata;        if (cnode < 0 || cnode >= numnodes)                return -ENODEV;        switch (cmd) {	case SNDRV_SHUB_CONFIGURE:		return configure_shub_stats(cnode, arg);		break;	case SNDRV_SHUB_RESETSTATS:		reset_shub_stats(cnode);		break;	case SNDRV_SHUB_INFOSIZE:		longarg = sizeof(shub_perf_counts);		if (copy_to_user((void *)arg, &longarg, sizeof(longarg))) {		    return -EFAULT;		}		break;	case SNDRV_SHUB_GETSTATS:		capture_shub_stats(cnode, shub_perf_counts);		if (copy_to_user((void *)arg, shub_perf_counts,				       	sizeof(shub_perf_counts))) {		    return -EFAULT;		}		break;	case SNDRV_SHUB_GETNASID:		nasid = cnodeid_to_nasid(cnode);		if (copy_to_user((void *)arg, &nasid,				       	sizeof(nasid))) {		    return -EFAULT;		}		break;	case SNDRV_SHUB_GETMMR32:		intarg = shub_mmr_read32(cnode, arg);		if (copy_to_user((void *)arg, &intarg,					sizeof(intarg))) {		    return -EFAULT;		}		break; 	case SNDRV_SHUB_GETMMR64:	case SNDRV_SHUB_GETMMR64_IO:		if (cmd == SNDRV_SHUB_GETMMR64)		    longarg = shub_mmr_read(cnode, arg);		else		    longarg = shub_mmr_read_iospace(cnode, arg);		if (copy_to_user((void *)arg, &longarg, sizeof(longarg)))		    return -EFAULT;		break; 	case SNDRV_SHUB_PUTMMR64:	case SNDRV_SHUB_PUTMMR64_IO:		if (copy_from_user((void *)regval, (void *)arg, sizeof(regval)))		    return -EFAULT;		if (regval[0] & 0x7) {		    printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]);		    return -EINVAL;		}		if (cmd == SNDRV_SHUB_PUTMMR64)		    shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]);		else		    shub_mmr_write_iospace(cnode, (shubreg_t)regval[0], regval[1]);		break; 	default:		return -EINVAL;	}	return 0;}struct file_operations shub_mon_fops = {	        .ioctl          = shubstats_ioctl,};

⌨️ 快捷键说明

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