3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
7 * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
10 #ident "$Revision: 1.167 $"
12 #include <linux/types.h>
13 #include <linux/slab.h>
14 #include <linux/interrupt.h>
17 #include <asm/hw_irq.h>
18 #include <asm/sn/sgi.h>
19 #include <asm/sn/iograph.h>
20 #include <asm/sn/invent.h>
21 #include <asm/sn/hcl.h>
22 #include <asm/sn/labelcl.h>
23 #include <asm/sn/io.h>
24 #include <asm/sn/sn_private.h>
25 #include <asm/sn/klconfig.h>
26 #include <asm/sn/sn_cpuid.h>
27 #include <asm/sn/pci/pciio.h>
28 #include <asm/sn/pci/pcibr.h>
29 #include <asm/sn/xtalk/xtalk.h>
30 #include <asm/sn/pci/pcibr_private.h>
31 #include <asm/sn/intr.h>
32 #include <asm/sn/sn2/shub_mmr_t.h>
34 #include <asm/sn/sn_sal.h>
35 #include <asm/sn/sndrv.h>
38 * Shub WAR for Xbridge Little Endian problem:
39 * Xbridge has to run in BIG ENDIAN even with Shub.
44 * io_sh_swapper: Turn on Shub byte swapping.
45 * All data destined to and from Shub to XIO are byte-swapped.
48 io_sh_swapper(nasid_t nasid, int onoff)
52 ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
54 ii_iwc.ii_iwc_fld_s.i_dma_byte_swap = onoff;
55 REMOTE_HUB_S(nasid, IIO_IWC, ii_iwc.ii_iwc_regval);
56 ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
61 * io_get_sh_swapper: Return current Swap mode.
62 * 1 = Swap on, 0 = Swap off.
65 io_get_sh_swapper(nasid_t nasid)
69 ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
70 return(ii_iwc.ii_iwc_fld_s.i_dma_byte_swap);
74 #define SHUB_NUM_ECF_REGISTERS 8
76 static uint32_t shub_perf_counts[SHUB_NUM_ECF_REGISTERS];
78 static shubreg_t shub_perf_counts_regs[SHUB_NUM_ECF_REGISTERS] = {
79 SH_PERFORMANCE_COUNTER0,
80 SH_PERFORMANCE_COUNTER1,
81 SH_PERFORMANCE_COUNTER2,
82 SH_PERFORMANCE_COUNTER3,
83 SH_PERFORMANCE_COUNTER4,
84 SH_PERFORMANCE_COUNTER5,
85 SH_PERFORMANCE_COUNTER6,
86 SH_PERFORMANCE_COUNTER7
90 shub_mmr_write(cnodeid_t cnode, shubreg_t reg, uint64_t val)
92 int nasid = cnodeid_to_nasid(cnode);
93 volatile uint64_t *addr = (uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));
100 shub_mmr_write32(cnodeid_t cnode, shubreg_t reg, uint32_t val)
102 int nasid = cnodeid_to_nasid(cnode);
103 volatile uint32_t *addr = (uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));
109 static inline uint64_t
110 shub_mmr_read(cnodeid_t cnode, shubreg_t reg)
112 int nasid = cnodeid_to_nasid(cnode);
113 volatile uint64_t val;
115 val = *(uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));
121 static inline uint32_t
122 shub_mmr_read32(cnodeid_t cnode, shubreg_t reg)
124 int nasid = cnodeid_to_nasid(cnode);
125 volatile uint32_t val;
127 val = *(uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));
134 reset_shub_stats(cnodeid_t cnode)
138 for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {
139 shub_perf_counts[i] = 0;
140 shub_mmr_write32(cnode, shub_perf_counts_regs[i], 0);
146 configure_shub_stats(cnodeid_t cnode, unsigned long arg)
148 uint64_t *p = (uint64_t *)arg;
153 if (copy_from_user((void *)®cnt, p, sizeof(regcnt)))
156 for (p++, i=0; i < regcnt; i++, p += 2) {
157 if (copy_from_user((void *)regval, (void *)p, sizeof(regval)))
159 if (regval[0] & 0x7) {
160 printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]);
163 shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]);
169 capture_shub_stats(cnodeid_t cnode, uint32_t *counts)
173 for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {
174 counts[i] = shub_mmr_read32(cnode, shub_perf_counts_regs[i]);
180 shubstats_ioctl(struct inode *inode, struct file *file,
181 unsigned int cmd, unsigned long arg)
188 if ((d = devfs_get_handle_from_inode(inode)) == NULL)
190 cnode = (cnodeid_t)hwgraph_fastinfo_get(d);
193 case SNDRV_SHUB_CONFIGURE:
194 return configure_shub_stats(cnode, arg);
197 case SNDRV_SHUB_RESETSTATS:
198 reset_shub_stats(cnode);
201 case SNDRV_SHUB_INFOSIZE:
202 longarg = sizeof(shub_perf_counts);
203 if (copy_to_user((void *)arg, &longarg, sizeof(longarg))) {
208 case SNDRV_SHUB_GETSTATS:
209 capture_shub_stats(cnode, shub_perf_counts);
210 if (copy_to_user((void *)arg, shub_perf_counts,
211 sizeof(shub_perf_counts))) {
216 case SNDRV_SHUB_GETNASID:
217 nasid = cnodeid_to_nasid(cnode);
218 if (copy_to_user((void *)arg, &nasid,
231 struct file_operations shub_mon_fops = {
232 ioctl: shubstats_ioctl,