1 /* $Id: shub_intr.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $
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 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <asm/sn/types.h>
13 #include <asm/sn/sgi.h>
14 #include <asm/sn/driver.h>
15 #include <asm/sn/iograph.h>
16 #include <asm/param.h>
17 #include <asm/sn/pio.h>
18 #include <asm/sn/xtalk/xwidget.h>
19 #include <asm/sn/io.h>
20 #include <asm/sn/sn_private.h>
21 #include <asm/sn/addrs.h>
22 #include <asm/sn/invent.h>
23 #include <asm/sn/hcl.h>
24 #include <asm/sn/hcl_util.h>
25 #include <asm/sn/intr.h>
26 #include <asm/sn/xtalk/xtalkaddrs.h>
27 #include <asm/sn/klconfig.h>
28 #include <asm/sn/sn2/shub_mmr.h>
29 #include <asm/sn/sn_cpuid.h>
33 hub_intr_init(vertex_hdl_t hubv)
38 hub_widget_id(nasid_t nasid)
40 hubii_wcr_t ii_wcr; /* the control status register */
42 ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid,IIO_WCR);
44 return ii_wcr.wcr_fields_s.wcr_widget_id;
48 do_hub_intr_alloc(vertex_hdl_t dev,
49 device_desc_t dev_desc,
50 vertex_hdl_t owner_dev,
60 struct xtalk_intr_s *xtalk_info;
61 xwidget_info_t xwidget_info;
62 ilvl_t intr_swlevel = 0;
64 cpu = intr_heuristic(dev, dev_desc, -1, 0, owner_dev, NULL, &vector);
66 if (cpu == CPU_NONE) {
67 printk("Unable to allocate interrupt for 0x%p\n", (void *)owner_dev);
71 cpuphys = cpu_physical_id(cpu);
72 slice = cpu_physical_id_to_slice(cpuphys);
73 nasid = cpu_physical_id_to_nasid(cpuphys);
74 cnode = cpuid_to_cnodeid(cpu);
77 xtalk_addr = SH_II_INT1 | ((unsigned long)nasid << 36) | (1UL << 47);
79 xtalk_addr = SH_II_INT0 | ((unsigned long)nasid << 36) | (1UL << 47);
82 intr_hdl = snia_kmem_alloc_node(sizeof(struct hub_intr_s), KM_NOSLEEP, cnode);
83 ASSERT_ALWAYS(intr_hdl);
85 xtalk_info = &intr_hdl->i_xtalk_info;
86 xtalk_info->xi_dev = dev;
87 xtalk_info->xi_vector = vector;
88 xtalk_info->xi_addr = xtalk_addr;
90 xwidget_info = xwidget_info_get(dev);
92 xtalk_info->xi_target = xwidget_info_masterid_get(xwidget_info);
95 intr_hdl->i_swlevel = intr_swlevel;
96 intr_hdl->i_cpuid = cpu;
97 intr_hdl->i_bit = vector;
98 intr_hdl->i_flags |= HUB_INTR_IS_ALLOCED;
104 hub_intr_alloc(vertex_hdl_t dev,
105 device_desc_t dev_desc,
106 vertex_hdl_t owner_dev)
108 return(do_hub_intr_alloc(dev, dev_desc, owner_dev, 0));
112 hub_intr_alloc_nothd(vertex_hdl_t dev,
113 device_desc_t dev_desc,
114 vertex_hdl_t owner_dev)
116 return(do_hub_intr_alloc(dev, dev_desc, owner_dev, 1));
120 hub_intr_free(hub_intr_t intr_hdl)
122 cpuid_t cpu = intr_hdl->i_cpuid;
123 int vector = intr_hdl->i_bit;
124 xtalk_intr_t xtalk_info;
126 if (intr_hdl->i_flags & HUB_INTR_IS_CONNECTED) {
127 xtalk_info = &intr_hdl->i_xtalk_info;
128 xtalk_info->xi_dev = 0;
129 xtalk_info->xi_vector = 0;
130 xtalk_info->xi_addr = 0;
131 hub_intr_disconnect(intr_hdl);
134 if (intr_hdl->i_flags & HUB_INTR_IS_ALLOCED) {
137 intr_unreserve_level(cpu, vector);
141 hub_intr_connect(hub_intr_t intr_hdl,
142 intr_func_t intr_func, /* xtalk intr handler */
143 void *intr_arg, /* arg to intr handler */
144 xtalk_intr_setfunc_t setfunc,
148 cpuid_t cpu = intr_hdl->i_cpuid;
149 int vector = intr_hdl->i_bit;
151 ASSERT(intr_hdl->i_flags & HUB_INTR_IS_ALLOCED);
153 rv = intr_connect_level(cpu, vector, intr_hdl->i_swlevel, NULL);
158 intr_hdl->i_xtalk_info.xi_setfunc = setfunc;
159 intr_hdl->i_xtalk_info.xi_sfarg = setfunc_arg;
162 (*setfunc)((xtalk_intr_t)intr_hdl);
165 intr_hdl->i_flags |= HUB_INTR_IS_CONNECTED;
171 * Disassociate handler with the specified interrupt.
174 hub_intr_disconnect(hub_intr_t intr_hdl)
178 cpuid_t cpu = intr_hdl->i_cpuid;
179 int bit = intr_hdl->i_bit;
180 xtalk_intr_setfunc_t setfunc;
182 setfunc = intr_hdl->i_xtalk_info.xi_setfunc;
184 /* TBD: send disconnected interrupts somewhere harmless */
185 if (setfunc) (*setfunc)((xtalk_intr_t)intr_hdl);
187 rv = intr_disconnect_level(cpu, bit);
189 intr_hdl->i_flags &= ~HUB_INTR_IS_CONNECTED;