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