ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / sn / io / xswitch.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
7  */
8
9 #include <linux/types.h>
10 #include <linux/slab.h>
11 #include <asm/errno.h>
12 #include <asm/sn/sgi.h>
13 #include <asm/sn/driver.h>
14 #include <asm/sn/hcl.h>
15 #include <asm/sn/labelcl.h>
16 #include <asm/sn/xtalk/xtalk.h>
17 #include <asm/sn/xtalk/xswitch.h>
18 #include <asm/sn/xtalk/xwidget.h>
19 #include <asm/sn/xtalk/xtalk_private.h>
20
21
22 /*
23  * This file provides generic support for Crosstalk
24  * Switches, in a way that insulates crosstalk providers
25  * from specifics about the switch chips being used.
26  */
27
28 #include <asm/sn/xtalk/xbow.h>
29
30 #define XSWITCH_CENSUS_BIT(port)                (1<<(port))
31 #define XSWITCH_CENSUS_PORT_MAX                 (0xF)
32 #define XSWITCH_CENSUS_PORTS                    (0x10)
33 #define XSWITCH_WIDGET_PRESENT(infop,port)      ((infop)->census & XSWITCH_CENSUS_BIT(port))
34
35 static char             xswitch_info_fingerprint[] = "xswitch_info";
36
37 struct xswitch_info_s {
38     char                   *fingerprint;
39     unsigned                census;
40     vertex_hdl_t            vhdl[XSWITCH_CENSUS_PORTS];
41     vertex_hdl_t            master_vhdl[XSWITCH_CENSUS_PORTS];
42     xswitch_provider_t     *xswitch_fns;
43 };
44
45 xswitch_info_t
46 xswitch_info_get(vertex_hdl_t xwidget)
47 {
48     xswitch_info_t          xswitch_info;
49
50     xswitch_info = (xswitch_info_t)
51         hwgraph_fastinfo_get(xwidget);
52
53     return (xswitch_info);
54 }
55
56 void
57 xswitch_info_vhdl_set(xswitch_info_t xswitch_info,
58                       xwidgetnum_t port,
59                       vertex_hdl_t xwidget)
60 {
61     if (port > XSWITCH_CENSUS_PORT_MAX)
62         return;
63
64     xswitch_info->vhdl[(int)port] = xwidget;
65 }
66
67 vertex_hdl_t
68 xswitch_info_vhdl_get(xswitch_info_t xswitch_info,
69                       xwidgetnum_t port)
70 {
71     if (port > XSWITCH_CENSUS_PORT_MAX)
72         return GRAPH_VERTEX_NONE;
73
74     return xswitch_info->vhdl[(int)port];
75 }
76
77 /*
78  * Some systems may allow for multiple switch masters.  On such systems,
79  * we assign a master for each port on the switch.  These interfaces
80  * establish and retrieve that assignment.
81  */
82 void
83 xswitch_info_master_assignment_set(xswitch_info_t xswitch_info,
84                                    xwidgetnum_t port,
85                                    vertex_hdl_t master_vhdl)
86 {
87     if (port > XSWITCH_CENSUS_PORT_MAX)
88         return;
89
90     xswitch_info->master_vhdl[(int)port] = master_vhdl;
91 }
92
93 vertex_hdl_t
94 xswitch_info_master_assignment_get(xswitch_info_t xswitch_info,
95                                    xwidgetnum_t port)
96 {
97     if (port > XSWITCH_CENSUS_PORT_MAX)
98         return GRAPH_VERTEX_NONE;
99
100     return xswitch_info->master_vhdl[(int)port];
101 }
102
103 void
104 xswitch_info_set(vertex_hdl_t xwidget, xswitch_info_t xswitch_info)
105 {
106     xswitch_info->fingerprint = xswitch_info_fingerprint;
107     hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) xswitch_info);
108 }
109
110 xswitch_info_t
111 xswitch_info_new(vertex_hdl_t xwidget)
112 {
113     xswitch_info_t          xswitch_info;
114
115     xswitch_info = xswitch_info_get(xwidget);
116     if (xswitch_info == NULL) {
117         int                     port;
118
119         xswitch_info = kmalloc(sizeof(*xswitch_info), GFP_KERNEL);
120         if (!xswitch_info) {
121                 printk(KERN_WARNING "xswitch_info_new(): Unable to "
122                         "allocate memory\n");
123                 return NULL;
124         }
125         xswitch_info->census = 0;
126         for (port = 0; port <= XSWITCH_CENSUS_PORT_MAX; port++) {
127             xswitch_info_vhdl_set(xswitch_info, port,
128                                   GRAPH_VERTEX_NONE);
129
130             xswitch_info_master_assignment_set(xswitch_info,
131                                                port,
132                                                GRAPH_VERTEX_NONE);
133         }
134         xswitch_info_set(xwidget, xswitch_info);
135     }
136     return xswitch_info;
137 }
138
139 void
140 xswitch_provider_register(vertex_hdl_t busv,
141                           xswitch_provider_t * xswitch_fns)
142 {
143     xswitch_info_t          xswitch_info = xswitch_info_get(busv);
144
145     ASSERT(xswitch_info);
146     xswitch_info->xswitch_fns = xswitch_fns;
147 }
148
149 void
150 xswitch_info_link_is_ok(xswitch_info_t xswitch_info, xwidgetnum_t port)
151 {
152     xswitch_info->census |= XSWITCH_CENSUS_BIT(port);
153 }
154
155 int
156 xswitch_info_link_ok(xswitch_info_t xswitch_info, xwidgetnum_t port)
157 {
158     if (port > XSWITCH_CENSUS_PORT_MAX)
159         return 0;
160
161     return (xswitch_info->census & XSWITCH_CENSUS_BIT(port));
162 }
163
164 int
165 xswitch_reset_link(vertex_hdl_t xconn_vhdl)
166 {
167     return xbow_reset_link(xconn_vhdl);
168 }