1/* $Id: invent.c,v 1.1.1.1 2008/10/15 03:26:03 james26_jang 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-2001 Silicon Graphics, Inc. All rights reserved.
8 */
9
10/*
11 * Hardware Inventory
12 *
13 * See sys/sn/invent.h for an explanation of the hardware inventory contents.
14 *
15 */
16#include <linux/types.h>
17#include <asm/sn/sgi.h>
18#include <asm/sn/invent.h>
19#include <asm/sn/hcl.h>
20#include <asm/sn/labelcl.h>
21
22void
23inventinit(void)
24{
25}
26
27/*
28 * For initializing/updating an inventory entry.
29 */
30void
31replace_in_inventory(
32	inventory_t *pinv, int class, int type,
33	int controller, int unit, int state)
34{
35	pinv->inv_class = class;
36	pinv->inv_type = type;
37	pinv->inv_controller = controller;
38	pinv->inv_unit = unit;
39	pinv->inv_state = state;
40}
41
42void
43add_to_inventory(int class, int type, int controller, int unit, int state)
44{
45	(void)device_inventory_add((devfs_handle_t)GRAPH_VERTEX_NONE, class, type,
46					controller, unit, state);
47}
48
49
50/*
51 * Inventory retrieval
52 *
53 * These two routines are intended to prevent the caller from having to know
54 * the internal structure of the inventory table.
55 *
56 * The caller of get_next_inventory is supposed to call start_scan_invent
57 * before the irst call to get_next_inventory, and the caller is required
58 * to call end_scan_invent after the last call to get_next_inventory.
59 */
60inventory_t *
61get_next_inventory(invplace_t *place)
62{
63	inventory_t *pinv;
64	devfs_handle_t device = place->invplace_vhdl;
65	int rv;
66
67	while ((pinv = device_inventory_get_next(device, place)) == NULL) {
68		/*
69		 * We've exhausted inventory items on the last device.
70		 * Advance to next device.
71		 */
72		place->invplace_inv = NULL; /* Start from beginning invent on this device */
73		rv = hwgraph_vertex_get_next(&device, &place->invplace_vplace);
74		if (rv == LABELCL_SUCCESS) {
75			place->invplace_vhdl = device;
76		}
77		else {
78			place->invplace_vhdl = GRAPH_VERTEX_NONE;
79			return(NULL);
80		}
81	}
82
83	return(pinv);
84}
85
86/* ARGSUSED */
87int
88get_sizeof_inventory(int abi)
89{
90	return sizeof(inventory_t);
91}
92
93/* Must be called prior to first call to get_next_inventory */
94void
95start_scan_inventory(invplace_t *iplace)
96{
97	*iplace = INVPLACE_NONE;
98}
99
100/* Must be called after last call to get_next_inventory */
101void
102end_scan_inventory(invplace_t *iplace)
103{
104	devfs_handle_t vhdl = iplace->invplace_vhdl;
105	if (vhdl != GRAPH_VERTEX_NONE)
106		hwgraph_vertex_unref(vhdl);
107	*iplace = INVPLACE_NONE; /* paranoia */
108}
109
110/*
111 * Hardware inventory scanner.
112 *
113 * Calls fun() for every entry in inventory list unless fun() returns something
114 * other than 0.
115 */
116int
117scaninvent(int (*fun)(inventory_t *, void *), void *arg)
118{
119	inventory_t *ie;
120	invplace_t iplace = { NULL,NULL, NULL };
121	int rc;
122
123	ie = 0;
124	rc = 0;
125	start_scan_inventory(&iplace);
126	while ((ie = (inventory_t *)get_next_inventory(&iplace))) {
127		rc = (*fun)(ie, arg);
128		if (rc)
129			break;
130	}
131	end_scan_inventory(&iplace);
132	return rc;
133}
134
135/*
136 * Find a particular inventory object
137 *
138 * pinv can be a pointer to an inventory entry and the search will begin from
139 * there, or it can be 0 in which case the search starts at the beginning.
140 * A -1 for any of the other arguments is a wildcard (i.e. it always matches).
141 */
142inventory_t *
143find_inventory(inventory_t *pinv, int class, int type, int controller,
144	       int unit, int state)
145{
146	invplace_t iplace =  { NULL,NULL, NULL };
147
148	start_scan_inventory(&iplace);
149	while ((pinv = (inventory_t *)get_next_inventory(&iplace)) != NULL) {
150		if (class != -1 && pinv->inv_class != class)
151			continue;
152		if (type != -1 && pinv->inv_type != type)
153			continue;
154
155		/* XXXX - perhaps the "state" entry should be ignored so an
156		 * an existing entry can be updated.  See vino_init() and
157		 * ml/IP22.c:add_ioboard() for an example.
158		 */
159		if (state != -1 && pinv->inv_state != state)
160			continue;
161		if (controller != -1
162		    && pinv->inv_controller != controller)
163			continue;
164		if (unit != -1 && pinv->inv_unit != unit)
165			continue;
166		break;
167	}
168	end_scan_inventory(&iplace);
169
170	return(pinv);
171}
172
173
174/*
175** Retrieve inventory data associated with a device.
176*/
177inventory_t *
178device_inventory_get_next(	devfs_handle_t device,
179				invplace_t *invplace)
180{
181	inventory_t *pinv;
182	int rv;
183
184	rv = hwgraph_inventory_get_next(device, invplace, &pinv);
185	if (rv == LABELCL_SUCCESS)
186		return(pinv);
187	else
188		return(NULL);
189}
190
191
192/*
193** Associate canonical inventory information with a device (and
194** add it to the general inventory).
195*/
196void
197device_inventory_add(	devfs_handle_t device,
198			int class,
199			int type,
200			major_t controller,
201			minor_t unit,
202			int state)
203{
204	hwgraph_inventory_add(device, class, type, controller, unit, state);
205}
206
207int
208device_controller_num_get(devfs_handle_t device)
209{
210	return (hwgraph_controller_num_get(device));
211}
212
213void
214device_controller_num_set(devfs_handle_t device, int contr_num)
215{
216	hwgraph_controller_num_set(device, contr_num);
217}
218