1 /* labelcl - SGI's Hwgraph Compatibility Layer.
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
7 * Copyright (c) 2001-2003 Silicon Graphics, Inc. All rights reserved.
10 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <linux/kernel.h>
14 #include <linux/string.h>
15 #include <linux/sched.h> /* needed for smp_lock.h :( */
16 #include <linux/smp_lock.h>
17 #include <asm/sn/sgi.h>
18 #include <asm/sn/hwgfs.h>
19 #include <asm/sn/hcl.h>
20 #include <asm/sn/labelcl.h>
23 ** Very simple and dumb string table that supports only find/insert.
24 ** In practice, if this table gets too large, we may need a more
25 ** efficient data structure. Also note that currently there is no
26 ** way to delete an item once it's added. Therefore, name collision
27 ** will return an error.
30 struct string_table label_string_table;
35 * string_table_init - Initialize the given string table.
38 string_table_init(struct string_table *string_table)
40 string_table->string_table_head = NULL;
41 string_table->string_table_generation = 0;
44 * We nedd to initialize locks here!
52 * string_table_destroy - Destroy the given string table.
55 string_table_destroy(struct string_table *string_table)
57 struct string_table_item *item, *next_item;
59 item = string_table->string_table_head;
61 next_item = item->next;
68 * We need to destroy whatever lock we have here
77 * string_table_insert - Insert an entry in the string table .. duplicate
78 * names are not allowed.
81 string_table_insert(struct string_table *string_table, char *name)
83 struct string_table_item *item, *new_item = NULL, *last_item = NULL;
87 * Need to lock the table ..
89 item = string_table->string_table_head;
93 if (!strcmp(item->string, name)) {
95 * If we allocated space for the string and the found that
96 * someone else already entered it into the string table,
97 * free the space we just allocated.
100 STRTBL_FREE(new_item);
104 * Search optimization: move the found item to the head
107 if (last_item != NULL) {
108 last_item->next = item->next;
109 item->next = string_table->string_table_head;
110 string_table->string_table_head = item;
119 * name was not found, so add it to the string table.
121 if (new_item == NULL) {
122 long old_generation = string_table->string_table_generation;
124 new_item = STRTBL_ALLOC(strlen(name));
126 strcpy(new_item->string, name);
129 * While we allocated memory for the new string, someone else
130 * changed the string table.
132 if (old_generation != string_table->string_table_generation) {
136 /* At this we only have the string table lock in access mode.
137 * Promote the access lock to an update lock for the string
138 * table insertion below.
140 long old_generation =
141 string_table->string_table_generation;
144 * After we did the unlock and wer waiting for update
145 * lock someone could have potentially updated
146 * the string table. Check the generation number
147 * for this case. If it is the case we have to
148 * try all over again.
150 if (old_generation !=
151 string_table->string_table_generation) {
157 * At this point, we're committed to adding new_item to the string table.
159 new_item->next = string_table->string_table_head;
160 item = string_table->string_table_head = new_item;
161 string_table->string_table_generation++;
165 * Need to unlock here.
167 return(item->string);
171 * labelcl_info_create - Creates the data structure that will hold the
172 * device private information asscoiated with a entry.
173 * The pointer to this structure is what gets stored in the
177 labelcl_info_create()
180 labelcl_info_t *new = NULL;
182 /* Initial allocation does not include any area for labels */
183 if ( ( new = (labelcl_info_t *)kmalloc (sizeof(labelcl_info_t), GFP_KERNEL) ) == NULL )
186 memset (new, 0, sizeof(labelcl_info_t));
187 new->hwcl_magic = LABELCL_MAGIC;
193 * labelcl_info_destroy - Frees the data structure that holds the
194 * device private information asscoiated with a entry. This
195 * data structure was created by device_info_create().
197 * The caller is responsible for nulling the (void *info) in the
198 * corresponding entry.
201 labelcl_info_destroy(labelcl_info_t *labelcl_info)
204 if (labelcl_info == NULL)
207 /* Free the label list */
208 if (labelcl_info->label_list)
209 kfree(labelcl_info->label_list);
211 /* Now free the label info area */
212 labelcl_info->hwcl_magic = 0;
219 * labelcl_info_add_LBL - Adds a new label entry in the labelcl info
222 * Error is returned if we find another label with the same name.
225 labelcl_info_add_LBL(vertex_hdl_t de,
227 arb_info_desc_t info_desc,
228 arbitrary_info_t info)
230 labelcl_info_t *labelcl_info = NULL;
232 int new_label_list_size;
233 label_info_t *old_label_list, *new_label_list = NULL;
240 labelcl_info = hwgfs_get_info(de);
241 if (labelcl_info == NULL)
244 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
247 if (info_name == NULL)
250 if (strlen(info_name) >= LABEL_LENGTH_MAX)
253 name = string_table_insert(&label_string_table, info_name);
255 num_labels = labelcl_info->num_labels;
256 new_label_list_size = sizeof(label_info_t) * (num_labels+1);
259 * Create a new label info area.
261 if (new_label_list_size != 0) {
262 new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL);
264 if (new_label_list == NULL)
269 * At this point, we are committed to adding the labelled info,
270 * if there isn't already information there with the same name.
272 old_label_list = labelcl_info->label_list;
275 * Look for matching info name.
277 for (i=0; i<num_labels; i++) {
278 if (!strcmp(info_name, old_label_list[i].name)) {
279 /* Not allowed to add duplicate labelled info names. */
280 kfree(new_label_list);
283 new_label_list[i] = old_label_list[i]; /* structure copy */
286 new_label_list[num_labels].name = name;
287 new_label_list[num_labels].desc = info_desc;
288 new_label_list[num_labels].info = info;
290 labelcl_info->num_labels = num_labels+1;
291 labelcl_info->label_list = new_label_list;
293 if (old_label_list != NULL)
294 kfree(old_label_list);
300 * labelcl_info_remove_LBL - Remove a label entry.
303 labelcl_info_remove_LBL(vertex_hdl_t de,
305 arb_info_desc_t *info_desc,
306 arbitrary_info_t *info)
308 labelcl_info_t *labelcl_info = NULL;
310 int new_label_list_size;
311 label_info_t *old_label_list, *new_label_list = NULL;
312 arb_info_desc_t label_desc_found;
313 arbitrary_info_t label_info_found;
319 labelcl_info = hwgfs_get_info(de);
320 if (labelcl_info == NULL)
323 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
326 num_labels = labelcl_info->num_labels;
327 if (num_labels == 0) {
332 * Create a new info area.
334 new_label_list_size = sizeof(label_info_t) * (num_labels-1);
335 if (new_label_list_size) {
336 new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL);
337 if (new_label_list == NULL)
342 * At this point, we are committed to removing the labelled info,
343 * if it still exists.
345 old_label_list = labelcl_info->label_list;
348 * Find matching info name.
350 for (i=0; i<num_labels; i++) {
351 if (!strcmp(info_name, old_label_list[i].name)) {
352 label_desc_found = old_label_list[i].desc;
353 label_info_found = old_label_list[i].info;
356 if (i < num_labels-1) /* avoid walking off the end of the new vertex */
357 new_label_list[i] = old_label_list[i]; /* structure copy */
360 /* The named info doesn't exist. */
362 kfree(new_label_list);
367 /* Finish up rest of labelled info */
368 for (i=i+1; i<num_labels; i++)
369 new_label_list[i-1] = old_label_list[i]; /* structure copy */
371 labelcl_info->num_labels = num_labels+1;
372 labelcl_info->label_list = new_label_list;
374 kfree(old_label_list);
377 *info = label_info_found;
379 if (info_desc != NULL)
380 *info_desc = label_desc_found;
387 * labelcl_info_replace_LBL - Replace an existing label entry with the
388 * given new information.
390 * Label entry must exist.
393 labelcl_info_replace_LBL(vertex_hdl_t de,
395 arb_info_desc_t info_desc,
396 arbitrary_info_t info,
397 arb_info_desc_t *old_info_desc,
398 arbitrary_info_t *old_info)
400 labelcl_info_t *labelcl_info = NULL;
402 label_info_t *label_list;
408 labelcl_info = hwgfs_get_info(de);
409 if (labelcl_info == NULL)
412 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
415 num_labels = labelcl_info->num_labels;
416 if (num_labels == 0) {
420 if (info_name == NULL)
423 label_list = labelcl_info->label_list;
426 * Verify that information under info_name already exists.
428 for (i=0; i<num_labels; i++)
429 if (!strcmp(info_name, label_list[i].name)) {
430 if (old_info != NULL)
431 *old_info = label_list[i].info;
433 if (old_info_desc != NULL)
434 *old_info_desc = label_list[i].desc;
436 label_list[i].info = info;
437 label_list[i].desc = info_desc;
447 * labelcl_info_get_LBL - Retrieve and return the information for the
451 labelcl_info_get_LBL(vertex_hdl_t de,
453 arb_info_desc_t *info_desc,
454 arbitrary_info_t *info)
456 labelcl_info_t *labelcl_info = NULL;
458 label_info_t *label_list;
464 labelcl_info = hwgfs_get_info(de);
465 if (labelcl_info == NULL)
468 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
471 num_labels = labelcl_info->num_labels;
472 if (num_labels == 0) {
476 label_list = labelcl_info->label_list;
479 * Find information under info_name.
481 for (i=0; i<num_labels; i++)
482 if (!strcmp(info_name, label_list[i].name)) {
484 *info = label_list[i].info;
485 if (info_desc != NULL)
486 *info_desc = label_list[i].desc;
495 * labelcl_info_get_next_LBL - returns the next label entry on the list.
498 labelcl_info_get_next_LBL(vertex_hdl_t de,
500 arb_info_desc_t *info_descp,
501 arbitrary_info_t *infop,
502 labelcl_info_place_t *placeptr)
504 labelcl_info_t *labelcl_info = NULL;
506 label_info_t *label_list;
508 if ((buffer == NULL) && (infop == NULL))
511 if (placeptr == NULL)
517 labelcl_info = hwgfs_get_info(de);
518 if (labelcl_info == NULL)
521 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
524 which_info = *placeptr;
526 if (which_info >= labelcl_info->num_labels) {
530 label_list = (label_info_t *) labelcl_info->label_list;
533 strcpy(buffer, label_list[which_info].name);
536 *infop = label_list[which_info].info;
539 *info_descp = label_list[which_info].desc;
541 *placeptr = which_info + 1;
548 labelcl_info_replace_IDX(vertex_hdl_t de,
550 arbitrary_info_t info,
551 arbitrary_info_t *old_info)
553 arbitrary_info_t *info_list_IDX;
554 labelcl_info_t *labelcl_info = NULL;
557 printk(KERN_ALERT "labelcl: NULL handle given.\n");
561 labelcl_info = hwgfs_get_info(de);
562 if (labelcl_info == NULL) {
563 printk(KERN_ALERT "labelcl: Entry %p does not have info pointer.\n", (void *)de);
567 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
570 if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) )
574 * Replace information at the appropriate index in this vertex with
577 info_list_IDX = labelcl_info->IDX_list;
578 if (old_info != NULL)
579 *old_info = info_list_IDX[index];
580 info_list_IDX[index] = info;
587 * labelcl_info_connectpt_set - Sets the connectpt.
590 labelcl_info_connectpt_set(hwgfs_handle_t de,
591 hwgfs_handle_t connect_de)
593 arbitrary_info_t old_info;
596 rv = labelcl_info_replace_IDX(de, HWGRAPH_CONNECTPT,
597 (arbitrary_info_t) connect_de, &old_info);
608 * labelcl_info_get_IDX - Returns the information pointed at by index.
612 labelcl_info_get_IDX(vertex_hdl_t de,
614 arbitrary_info_t *info)
616 arbitrary_info_t *info_list_IDX;
617 labelcl_info_t *labelcl_info = NULL;
622 labelcl_info = hwgfs_get_info(de);
623 if (labelcl_info == NULL)
626 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
629 if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) )
633 * Return information at the appropriate index in this vertex.
635 info_list_IDX = labelcl_info->IDX_list;
637 *info = info_list_IDX[index];
643 * labelcl_info_connectpt_get - Retrieve the connect point for a device entry.
646 labelcl_info_connectpt_get(hwgfs_handle_t de)
649 arbitrary_info_t info;
651 rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info);
655 return((hwgfs_handle_t) info);