1 /* $Id$
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 <asm/sn/sgi.h>
13 #include <asm/io.h>
14 #include <asm/sn/io.h>
15 #include <asm/sn/iograph.h>
16 #include <asm/sn/hwgfs.h>
17 #include <asm/sn/invent.h>
18 #include <asm/sn/hcl.h>
19 #include <asm/sn/labelcl.h>
20 #include <asm/sn/invent.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 static vertex_hdl_t hwgraph_all_cpuids = GRAPH_VERTEX_NONE;
26 extern vertex_hdl_t hwgraph_root;
27 extern int maxcpus;
28
29
30
31 /*
32 ** Return the "master" for a given vertex. A master vertex is a
33 ** controller or adapter or other piece of hardware that the given
34 ** vertex passes through on the way to the rest of the system.
35 */
36 vertex_hdl_t
device_master_get(vertex_hdl_t vhdl)37 device_master_get(vertex_hdl_t vhdl)
38 {
39 graph_error_t rc;
40 vertex_hdl_t master;
41
42 rc = hwgraph_edge_get(vhdl, EDGE_LBL_MASTER, &master);
43 if (rc == GRAPH_SUCCESS)
44 return(master);
45 else
46 return(GRAPH_VERTEX_NONE);
47 }
48
49 /*
50 ** Set the master for a given vertex.
51 ** Returns 0 on success, non-0 indicates failure
52 */
53 int
device_master_set(vertex_hdl_t vhdl,vertex_hdl_t master)54 device_master_set(vertex_hdl_t vhdl, vertex_hdl_t master)
55 {
56 graph_error_t rc;
57
58 rc = hwgraph_edge_add(vhdl, master, EDGE_LBL_MASTER);
59 return(rc != GRAPH_SUCCESS);
60 }
61
62
63 /*
64 ** Return the compact node id of the node that ultimately "owns" the specified
65 ** vertex. In order to do this, we walk back through masters and connect points
66 ** until we reach a vertex that represents a node.
67 */
68 cnodeid_t
master_node_get(vertex_hdl_t vhdl)69 master_node_get(vertex_hdl_t vhdl)
70 {
71 cnodeid_t cnodeid;
72 vertex_hdl_t master;
73
74 for (;;) {
75 cnodeid = nodevertex_to_cnodeid(vhdl);
76 if (cnodeid != CNODEID_NONE)
77 return(cnodeid);
78
79 master = device_master_get(vhdl);
80
81 /* Check for exceptional cases */
82 if (master == vhdl) {
83 /* Since we got a reference to the "master" thru
84 * device_master_get() we should decrement
85 * its reference count by 1
86 */
87 return(CNODEID_NONE);
88 }
89
90 if (master == GRAPH_VERTEX_NONE) {
91 master = hwgraph_connectpt_get(vhdl);
92 if ((master == GRAPH_VERTEX_NONE) ||
93 (master == vhdl)) {
94 return(CNODEID_NONE);
95 }
96 }
97
98 vhdl = master;
99 }
100 }
101
102 void
mark_cpuvertex_as_cpu(vertex_hdl_t vhdl,cpuid_t cpuid)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
nodevertex_to_cnodeid(vertex_hdl_t vhdl)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
mark_nodevertex_as_node(vertex_hdl_t vhdl,cnodeid_t cnodeid)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 HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hwgraph_all_cnodes, NULL, "Creating path vhdl1\n"));
165 }
166 }
167
168 /*
169 ** If the specified device represents a CPU, return its cpuid;
170 ** otherwise, return CPU_NONE.
171 */
172 cpuid_t
cpuvertex_to_cpuid(vertex_hdl_t vhdl)173 cpuvertex_to_cpuid(vertex_hdl_t vhdl)
174 {
175 arbitrary_info_t cpuid = CPU_NONE;
176
177 (void)labelcl_info_get_LBL(vhdl, INFO_LBL_CPUID, NULL, &cpuid);
178
179 return((cpuid_t)cpuid);
180 }
181
182
183 /*
184 ** dev_to_name converts a vertex_hdl_t into a canonical name. If the vertex_hdl_t
185 ** represents a vertex in the hardware graph, it is converted in the
186 ** normal way for vertices. If the vertex_hdl_t is an old vertex_hdl_t (one which
187 ** does not represent a hwgraph vertex), we synthesize a name based
188 ** on major/minor number.
189 **
190 ** Usually returns a pointer to the original buffer, filled in as
191 ** appropriate. If the buffer is too small to hold the entire name,
192 ** or if anything goes wrong while determining the name, dev_to_name
193 ** returns "UnknownDevice".
194 */
195 char *
dev_to_name(vertex_hdl_t dev,char * buf,uint buflen)196 dev_to_name(vertex_hdl_t dev, char *buf, uint buflen)
197 {
198 return(vertex_to_name(dev, buf, buflen));
199 }
200
201
202