ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / sn / io / hwgfs / hcl_util.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/kernel.h>
11 #include <asm/sn/sgi.h>
12 #include <asm/io.h>
13 #include <asm/sn/io.h>
14 #include <asm/sn/iograph.h>
15 #include <asm/sn/hwgfs.h>
16 #include <asm/sn/hcl.h>
17 #include <asm/sn/labelcl.h>
18 #include <asm/sn/hcl_util.h>
19 #include <asm/sn/nodepda.h>
20
21 static vertex_hdl_t hwgraph_all_cnodes = GRAPH_VERTEX_NONE;
22 extern vertex_hdl_t hwgraph_root;
23 static vertex_hdl_t hwgraph_all_cpuids = GRAPH_VERTEX_NONE;
24 extern int maxcpus;
25
26 void
27 mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid)
28 {
29         char cpuid_buffer[10];
30
31         if (cpuid == CPU_NONE)
32                 return;
33
34         if (hwgraph_all_cpuids == GRAPH_VERTEX_NONE) {
35                 (void)hwgraph_path_add( hwgraph_root,
36                                         EDGE_LBL_CPUNUM,
37                                         &hwgraph_all_cpuids);
38         }
39
40         sprintf(cpuid_buffer, "%ld", cpuid);
41         (void)hwgraph_edge_add( hwgraph_all_cpuids, vhdl, cpuid_buffer);
42 }
43
44 /*
45 ** Return the "master" for a given vertex.  A master vertex is a
46 ** controller or adapter or other piece of hardware that the given
47 ** vertex passes through on the way to the rest of the system.
48 */
49 vertex_hdl_t
50 device_master_get(vertex_hdl_t vhdl)
51 {
52         graph_error_t rc;
53         vertex_hdl_t master;
54
55         rc = hwgraph_edge_get(vhdl, EDGE_LBL_MASTER, &master);
56         if (rc == GRAPH_SUCCESS)
57                 return(master);
58         else
59                 return(GRAPH_VERTEX_NONE);
60 }
61
62 /*
63 ** Set the master for a given vertex.
64 ** Returns 0 on success, non-0 indicates failure
65 */
66 int
67 device_master_set(vertex_hdl_t vhdl, vertex_hdl_t master)
68 {
69         graph_error_t rc;
70
71         rc = hwgraph_edge_add(vhdl, master, EDGE_LBL_MASTER);
72         return(rc != GRAPH_SUCCESS);
73 }
74
75
76 /*
77 ** Return the compact node id of the node that ultimately "owns" the specified
78 ** vertex.  In order to do this, we walk back through masters and connect points
79 ** until we reach a vertex that represents a node.
80 */
81 cnodeid_t
82 master_node_get(vertex_hdl_t vhdl)
83 {
84         cnodeid_t cnodeid;
85         vertex_hdl_t master;
86
87         for (;;) {
88                 cnodeid = nodevertex_to_cnodeid(vhdl);
89                 if (cnodeid != CNODEID_NONE)
90                         return(cnodeid);
91
92                 master = device_master_get(vhdl);
93
94                 /* Check for exceptional cases */
95                 if (master == vhdl) {
96                         /* Since we got a reference to the "master" thru
97                          * device_master_get() we should decrement
98                          * its reference count by 1
99                          */
100                         return(CNODEID_NONE);
101                 }
102
103                 if (master == GRAPH_VERTEX_NONE) {
104                         master = hwgraph_connectpt_get(vhdl);
105                         if ((master == GRAPH_VERTEX_NONE) ||
106                             (master == vhdl)) {
107                                 return(CNODEID_NONE);
108                         }
109                 }
110
111                 vhdl = master;
112         }
113 }
114
115
116 /*
117 ** If the specified device represents a node, return its
118 ** compact node ID; otherwise, return CNODEID_NONE.
119 */
120 cnodeid_t
121 nodevertex_to_cnodeid(vertex_hdl_t vhdl)
122 {
123         int rv = 0;
124         arbitrary_info_t cnodeid = CNODEID_NONE;
125
126         rv = labelcl_info_get_LBL(vhdl, INFO_LBL_CNODEID, NULL, &cnodeid);
127
128         return((cnodeid_t)cnodeid);
129 }
130
131 void
132 mark_nodevertex_as_node(vertex_hdl_t vhdl, cnodeid_t cnodeid)
133 {
134         if (cnodeid == CNODEID_NONE)
135                 return;
136
137         cnodeid_to_vertex(cnodeid) = vhdl;
138         labelcl_info_add_LBL(vhdl, INFO_LBL_CNODEID, INFO_DESC_EXPORT, 
139                 (arbitrary_info_t)cnodeid);
140
141         {
142                 char cnodeid_buffer[10];
143
144                 if (hwgraph_all_cnodes == GRAPH_VERTEX_NONE) {
145                         (void)hwgraph_path_add( hwgraph_root,
146                                                 EDGE_LBL_NODENUM,
147                                                 &hwgraph_all_cnodes);
148                 }
149
150                 sprintf(cnodeid_buffer, "%d", cnodeid);
151                 (void)hwgraph_edge_add( hwgraph_all_cnodes,
152                                         vhdl,
153                                         cnodeid_buffer);
154                 HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, hwgraph_all_cnodes, NULL, "Creating path vhdl1\n");
155         }
156 }
157
158 /*
159 ** dev_to_name converts a vertex_hdl_t into a canonical name.  If the vertex_hdl_t
160 ** represents a vertex in the hardware graph, it is converted in the
161 ** normal way for vertices.  If the vertex_hdl_t is an old vertex_hdl_t (one which
162 ** does not represent a hwgraph vertex), we synthesize a name based
163 ** on major/minor number.
164 **
165 ** Usually returns a pointer to the original buffer, filled in as
166 ** appropriate.  If the buffer is too small to hold the entire name,
167 ** or if anything goes wrong while determining the name, dev_to_name
168 ** returns "UnknownDevice".
169 */
170 char *
171 dev_to_name(vertex_hdl_t dev, char *buf, uint buflen)
172 {
173         return(vertex_to_name(dev, buf, buflen));
174 }
175