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 * hcl - SGI's Hardware Graph compatibility layer.
7 *
8 * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
9 */
10
11 #include <linux/types.h>
12 #include <linux/config.h>
13 #include <linux/slab.h>
14 #include <linux/ctype.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/fs.h>
19 #include <linux/string.h>
20 #include <linux/sched.h> /* needed for smp_lock.h :( */
21 #include <linux/smp_lock.h>
22 #include <asm/sn/sgi.h>
23 #include <asm/io.h>
24 #include <asm/sn/iograph.h>
25 #include <asm/sn/hwgfs.h>
26 #include <asm/sn/invent.h>
27 #include <asm/sn/hcl.h>
28 #include <asm/sn/labelcl.h>
29 #include <asm/sn/simulator.h>
30
31 #define vertex_hdl_t hwgfs_handle_t
32
33 vertex_hdl_t hwgraph_root;
34 vertex_hdl_t linux_busnum;
35 extern void pci_bus_cvlink_init(void);
36 unsigned long hwgraph_debug_mask = 0;
37
38 /*
39 * Debug flag definition.
40 */
41 #define OPTION_NONE 0x00
42 #define HCL_DEBUG_NONE 0x00000
43 #define HCL_DEBUG_ALL 0x0ffff
44 #if defined(CONFIG_HCL_DEBUG)
45 static unsigned int hcl_debug_init __initdata = HCL_DEBUG_NONE;
46 #endif
47 static unsigned int hcl_debug = HCL_DEBUG_NONE;
48 #if defined(CONFIG_HCL_DEBUG) && !defined(MODULE)
49 static unsigned int boot_options = OPTION_NONE;
50 #endif
51
52 /*
53 * Some Global definitions.
54 */
55 vertex_hdl_t hcl_handle;
56
57 invplace_t invplace_none = {
58 GRAPH_VERTEX_NONE,
59 GRAPH_VERTEX_PLACE_NONE,
60 NULL
61 };
62
63 /*
64 * HCL device driver.
65 * The purpose of this device driver is to provide a facility
66 * for User Level Apps e.g. hinv, ioconfig etc. an ioctl path
67 * to manipulate label entries without having to implement
68 * system call interfaces. This methodology will enable us to
69 * make this feature module loadable.
70 */
hcl_open(struct inode * inode,struct file * filp)71 static int hcl_open(struct inode * inode, struct file * filp)
72 {
73 if (hcl_debug) {
74 printk("HCL: hcl_open called.\n");
75 }
76
77 return(0);
78
79 }
80
hcl_close(struct inode * inode,struct file * filp)81 static int hcl_close(struct inode * inode, struct file * filp)
82 {
83
84 if (hcl_debug) {
85 printk("HCL: hcl_close called.\n");
86 }
87
88 return(0);
89
90 }
91
hcl_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)92 static int hcl_ioctl(struct inode * inode, struct file * file,
93 unsigned int cmd, unsigned long arg)
94 {
95
96 if (hcl_debug) {
97 printk("HCL: hcl_ioctl called.\n");
98 }
99
100 switch (cmd) {
101 default:
102 if (hcl_debug) {
103 printk("HCL: hcl_ioctl cmd = 0x%x\n", cmd);
104 }
105 }
106
107 return(0);
108
109 }
110
111 struct file_operations hcl_fops = {
112 (struct module *)0,
113 NULL, /* lseek - default */
114 NULL, /* read - general block-dev read */
115 NULL, /* write - general block-dev write */
116 NULL, /* readdir - bad */
117 NULL, /* poll */
118 hcl_ioctl, /* ioctl */
119 NULL, /* mmap */
120 hcl_open, /* open */
121 NULL, /* flush */
122 hcl_close, /* release */
123 NULL, /* fsync */
124 NULL, /* fasync */
125 NULL, /* lock */
126 NULL, /* readv */
127 NULL, /* writev */
128 };
129
130
131 /*
132 * init_hcl() - Boot time initialization.
133 *
134 */
init_hcl(void)135 int __init init_hcl(void)
136 {
137 extern void string_table_init(struct string_table *);
138 extern struct string_table label_string_table;
139 extern int init_ifconfig_net(void);
140 extern int init_ioconfig_bus(void);
141 extern int init_hwgfs_fs(void);
142 int rv = 0;
143
144 if (IS_RUNNING_ON_SIMULATOR()) {
145 extern u64 klgraph_addr[];
146 klgraph_addr[0] = 0xe000003000030000;
147 }
148
149 init_hwgfs_fs();
150
151 /*
152 * Create the hwgraph_root.
153 */
154 rv = hwgraph_path_add(NULL, EDGE_LBL_HW, &hwgraph_root);
155 if (rv)
156 panic("init_hcl: Failed to create hwgraph_root.\n");
157
158 /*
159 * Create the hcl driver to support inventory entry manipulations.
160 *
161 */
162 hcl_handle = hwgraph_register(hwgraph_root, ".hcl",
163 0, DEVFS_FL_AUTO_DEVNUM,
164 0, 0,
165 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
166 &hcl_fops, NULL);
167
168 if (hcl_handle == NULL) {
169 panic("HCL: Unable to create HCL Driver in init_hcl().\n");
170 return(0);
171 }
172
173 /*
174 * Initialize the HCL string table.
175 */
176
177 string_table_init(&label_string_table);
178
179 /*
180 * Create the directory that links Linux bus numbers to our Xwidget.
181 */
182 rv = hwgraph_path_add(hwgraph_root, EDGE_LBL_LINUX_BUS, &linux_busnum);
183 if (linux_busnum == NULL) {
184 panic("HCL: Unable to create %s\n", EDGE_LBL_LINUX_BUS);
185 return(0);
186 }
187
188 pci_bus_cvlink_init();
189
190 /*
191 * Initialize the ifconfgi_net driver that does network devices
192 * Persistent Naming.
193 */
194 init_ifconfig_net();
195 init_ioconfig_bus();
196
197 return(0);
198
199 }
200
201
202 /*
203 * hcl_setup() - Process boot time parameters if given.
204 * "hcl="
205 * This routine gets called only if "hcl=" is given in the
206 * boot line and before init_hcl().
207 *
208 * We currently do not have any boot options .. when we do,
209 * functionalities can be added here.
210 *
211 */
hcl_setup(char * str)212 static int __init hcl_setup(char *str)
213 {
214 while ( (*str != '\0') && !isspace (*str) )
215 {
216 #ifdef CONFIG_HCL_DEBUG
217 if (strncmp (str, "all", 3) == 0) {
218 hcl_debug_init |= HCL_DEBUG_ALL;
219 str += 3;
220 } else
221 return 0;
222 #endif
223 if (*str != ',') return 0;
224 ++str;
225 }
226
227 return 1;
228
229 }
230
231 __setup("hcl=", hcl_setup);
232
233
234 int
hwgraph_generate_path(vertex_hdl_t de,char * path,int buflen)235 hwgraph_generate_path(
236 vertex_hdl_t de,
237 char *path,
238 int buflen)
239 {
240 return (hwgfs_generate_path(de, path, buflen));
241 }
242
243 /*
244 * Set device specific "fast information".
245 *
246 */
247 void
hwgraph_fastinfo_set(vertex_hdl_t de,arbitrary_info_t fastinfo)248 hwgraph_fastinfo_set(vertex_hdl_t de, arbitrary_info_t fastinfo)
249 {
250 labelcl_info_replace_IDX(de, HWGRAPH_FASTINFO, fastinfo, NULL);
251 }
252
253
254 /*
255 * Get device specific "fast information".
256 *
257 */
258 arbitrary_info_t
hwgraph_fastinfo_get(vertex_hdl_t de)259 hwgraph_fastinfo_get(vertex_hdl_t de)
260 {
261 arbitrary_info_t fastinfo;
262 int rv;
263
264 if (!de) {
265 printk(KERN_WARNING "HCL: hwgraph_fastinfo_get handle given is NULL.\n");
266 return(-1);
267 }
268
269 rv = labelcl_info_get_IDX(de, HWGRAPH_FASTINFO, &fastinfo);
270 if (rv == 0)
271 return(fastinfo);
272
273 return(0);
274 }
275
276
277 /*
278 * hwgraph_connectpt_set - Sets the connect point handle in de to the
279 * given connect_de handle. By default, the connect point of the
280 * node is the parent. This effectively changes this assumption.
281 */
282 int
hwgraph_connectpt_set(vertex_hdl_t de,vertex_hdl_t connect_de)283 hwgraph_connectpt_set(vertex_hdl_t de, vertex_hdl_t connect_de)
284 {
285 int rv;
286
287 if (!de)
288 return(-1);
289
290 rv = labelcl_info_connectpt_set(de, connect_de);
291
292 return(rv);
293 }
294
295
296 /*
297 * hwgraph_connectpt_get: Returns the entry's connect point.
298 *
299 */
300 vertex_hdl_t
hwgraph_connectpt_get(vertex_hdl_t de)301 hwgraph_connectpt_get(vertex_hdl_t de)
302 {
303 int rv;
304 arbitrary_info_t info;
305 vertex_hdl_t connect;
306
307 rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info);
308 if (rv != 0) {
309 return(NULL);
310 }
311
312 connect = (vertex_hdl_t)info;
313 return(connect);
314
315 }
316
317
318 /*
319 * hwgraph_mk_dir - Creates a directory entry.
320 */
321 vertex_hdl_t
hwgraph_mk_dir(vertex_hdl_t de,const char * name,unsigned int namelen,void * info)322 hwgraph_mk_dir(vertex_hdl_t de, const char *name,
323 unsigned int namelen, void *info)
324 {
325
326 int rv;
327 labelcl_info_t *labelcl_info = NULL;
328 vertex_hdl_t new_handle = NULL;
329 vertex_hdl_t parent = NULL;
330
331 /*
332 * Create the device info structure for hwgraph compatiblity support.
333 */
334 labelcl_info = labelcl_info_create();
335 if (!labelcl_info)
336 return(NULL);
337
338 /*
339 * Create an entry.
340 */
341 new_handle = hwgfs_mk_dir(de, name, (void *)labelcl_info);
342 if (!new_handle) {
343 labelcl_info_destroy(labelcl_info);
344 return(NULL);
345 }
346
347 /*
348 * Get the parent handle.
349 */
350 parent = hwgfs_get_parent (new_handle);
351
352 /*
353 * To provide the same semantics as the hwgraph, set the connect point.
354 */
355 rv = hwgraph_connectpt_set(new_handle, parent);
356 if (!rv) {
357 /*
358 * We need to clean up!
359 */
360 }
361
362 /*
363 * If the caller provides a private data pointer, save it in the
364 * labelcl info structure(fastinfo). This can be retrieved via
365 * hwgraph_fastinfo_get()
366 */
367 if (info)
368 hwgraph_fastinfo_set(new_handle, (arbitrary_info_t)info);
369
370 return(new_handle);
371
372 }
373
374 /*
375 * hwgraph_path_add - Create a directory node with the given path starting
376 * from the given fromv.
377 */
378 int
hwgraph_path_add(vertex_hdl_t fromv,char * path,vertex_hdl_t * new_de)379 hwgraph_path_add(vertex_hdl_t fromv,
380 char *path,
381 vertex_hdl_t *new_de)
382 {
383
384 unsigned int namelen = strlen(path);
385 int rv;
386
387 /*
388 * We need to handle the case when fromv is NULL ..
389 * in this case we need to create the path from the
390 * hwgraph root!
391 */
392 if (fromv == NULL)
393 fromv = hwgraph_root;
394
395 /*
396 * check the entry doesn't already exist, if it does
397 * then we simply want new_de to point to it (otherwise
398 * we'll overwrite the existing labelcl_info struct)
399 */
400 rv = hwgraph_edge_get(fromv, path, new_de);
401 if (rv) { /* couldn't find entry so we create it */
402 *new_de = hwgraph_mk_dir(fromv, path, namelen, NULL);
403 if (new_de == NULL)
404 return(-1);
405 else
406 return(0);
407 }
408 else
409 return(0);
410
411 }
412
413 /*
414 * hwgraph_register - Creates a special device file.
415 *
416 */
417 vertex_hdl_t
hwgraph_register(vertex_hdl_t de,const char * name,unsigned int namelen,unsigned int flags,unsigned int major,unsigned int minor,umode_t mode,uid_t uid,gid_t gid,struct file_operations * fops,void * info)418 hwgraph_register(vertex_hdl_t de, const char *name,
419 unsigned int namelen, unsigned int flags,
420 unsigned int major, unsigned int minor,
421 umode_t mode, uid_t uid, gid_t gid,
422 struct file_operations *fops,
423 void *info)
424 {
425
426 vertex_hdl_t new_handle = NULL;
427
428 /*
429 * Create an entry.
430 */
431 new_handle = hwgfs_register(de, name, flags, major,
432 minor, mode, fops, info);
433
434 return(new_handle);
435
436 }
437
438
439 /*
440 * hwgraph_mk_symlink - Create a symbolic link.
441 */
442 int
hwgraph_mk_symlink(vertex_hdl_t de,const char * name,unsigned int namelen,unsigned int flags,const char * link,unsigned int linklen,vertex_hdl_t * handle,void * info)443 hwgraph_mk_symlink(vertex_hdl_t de, const char *name, unsigned int namelen,
444 unsigned int flags, const char *link, unsigned int linklen,
445 vertex_hdl_t *handle, void *info)
446 {
447
448 void *labelcl_info = NULL;
449 int status = 0;
450 vertex_hdl_t new_handle = NULL;
451
452 /*
453 * Create the labelcl info structure for hwgraph compatiblity support.
454 */
455 labelcl_info = labelcl_info_create();
456 if (!labelcl_info)
457 return(-1);
458
459 /*
460 * Create a symbolic link.
461 */
462 status = hwgfs_mk_symlink(de, name, flags, link,
463 &new_handle, labelcl_info);
464 if ( (!new_handle) || (!status) ){
465 labelcl_info_destroy((labelcl_info_t *)labelcl_info);
466 return(-1);
467 }
468
469 /*
470 * If the caller provides a private data pointer, save it in the
471 * labelcl info structure(fastinfo). This can be retrieved via
472 * hwgraph_fastinfo_get()
473 */
474 if (info)
475 hwgraph_fastinfo_set(new_handle, (arbitrary_info_t)info);
476
477 *handle = new_handle;
478 return(0);
479
480 }
481
482 /*
483 * hwgraph_vertex_destroy - Destroy the entry
484 */
485 int
hwgraph_vertex_destroy(vertex_hdl_t de)486 hwgraph_vertex_destroy(vertex_hdl_t de)
487 {
488
489 void *labelcl_info = NULL;
490
491 labelcl_info = hwgfs_get_info(de);
492 hwgfs_unregister(de);
493
494 if (labelcl_info)
495 labelcl_info_destroy((labelcl_info_t *)labelcl_info);
496
497 return(0);
498 }
499
500 int
hwgraph_edge_add(vertex_hdl_t from,vertex_hdl_t to,char * name)501 hwgraph_edge_add(vertex_hdl_t from, vertex_hdl_t to, char *name)
502 {
503
504 char *path, *link;
505 char *s1;
506 char *index;
507 vertex_hdl_t handle = NULL;
508 int rv;
509 int i, count;
510
511 path = kmalloc(1024, GFP_KERNEL);
512 memset((char *)path, 0x0, 1024);
513 link = kmalloc(1024, GFP_KERNEL);
514 memset((char *)link, 0x0, 1024);
515
516 i = hwgfs_generate_path (from, path, 1024);
517 s1 = (char *)path;
518 count = 0;
519 while (1) {
520 index = strstr (s1, "/");
521 if (index) {
522 count++;
523 s1 = ++index;
524 } else {
525 count++;
526 break;
527 }
528 }
529
530 for (i = 0; i < count; i++) {
531 strcat((char *)link,"../");
532 }
533
534 memset(path, 0x0, 1024);
535 i = hwgfs_generate_path (to, path, 1024);
536 strcat((char *)link, (char *)path);
537
538 /*
539 * Otherwise, just create a symlink to the vertex.
540 * In this case the vertex was previous created with a REAL pathname.
541 */
542 rv = hwgfs_mk_symlink (from, (const char *)name,
543 DEVFS_FL_DEFAULT, link,
544 &handle, NULL);
545 kfree(path);
546 kfree(link);
547
548 return(rv);
549
550
551 }
552
553 /* ARGSUSED */
554 int
hwgraph_edge_get(vertex_hdl_t from,char * name,vertex_hdl_t * toptr)555 hwgraph_edge_get(vertex_hdl_t from, char *name, vertex_hdl_t *toptr)
556 {
557
558 vertex_hdl_t target_handle = NULL;
559
560 if (name == NULL)
561 return(-1);
562
563 if (toptr == NULL)
564 return(-1);
565
566 /*
567 * If the name is "." just return the current entry handle.
568 */
569 if (!strcmp(name, HWGRAPH_EDGELBL_DOT)) {
570 if (toptr) {
571 *toptr = from;
572 }
573 } else if (!strcmp(name, HWGRAPH_EDGELBL_DOTDOT)) {
574 /*
575 * Hmmm .. should we return the connect point or parent ..
576 * see in hwgraph, the concept of parent is the connectpt!
577 *
578 * Maybe we should see whether the connectpt is set .. if
579 * not just return the parent!
580 */
581 target_handle = hwgraph_connectpt_get(from);
582 if (target_handle) {
583 /*
584 * Just return the connect point.
585 */
586 *toptr = target_handle;
587 return(0);
588 }
589 target_handle = hwgfs_get_parent(from);
590 *toptr = target_handle;
591
592 } else {
593 target_handle = hwgfs_find_handle (from, name, 0, 0,
594 0, 1); /* Yes traverse symbolic links */
595 }
596
597 if (target_handle == NULL)
598 return(-1);
599 else
600 *toptr = target_handle;
601
602 return(0);
603 }
604
605 /*
606 * hwgraph_info_add_LBL - Adds a new label for the device. Mark the info_desc
607 * of the label as INFO_DESC_PRIVATE and store the info in the label.
608 */
609 /* ARGSUSED */
610 int
hwgraph_info_add_LBL(vertex_hdl_t de,char * name,arbitrary_info_t info)611 hwgraph_info_add_LBL( vertex_hdl_t de,
612 char *name,
613 arbitrary_info_t info)
614 {
615 return(labelcl_info_add_LBL(de, name, INFO_DESC_PRIVATE, info));
616 }
617
618 /*
619 * hwgraph_info_remove_LBL - Remove the label entry for the device.
620 */
621 /* ARGSUSED */
622 int
hwgraph_info_remove_LBL(vertex_hdl_t de,char * name,arbitrary_info_t * old_info)623 hwgraph_info_remove_LBL( vertex_hdl_t de,
624 char *name,
625 arbitrary_info_t *old_info)
626 {
627 return(labelcl_info_remove_LBL(de, name, NULL, old_info));
628 }
629
630 /*
631 * hwgraph_info_replace_LBL - replaces an existing label with
632 * a new label info value.
633 */
634 /* ARGSUSED */
635 int
hwgraph_info_replace_LBL(vertex_hdl_t de,char * name,arbitrary_info_t info,arbitrary_info_t * old_info)636 hwgraph_info_replace_LBL( vertex_hdl_t de,
637 char *name,
638 arbitrary_info_t info,
639 arbitrary_info_t *old_info)
640 {
641 return(labelcl_info_replace_LBL(de, name,
642 INFO_DESC_PRIVATE, info,
643 NULL, old_info));
644 }
645 /*
646 * hwgraph_info_get_LBL - Get and return the info value in the label of the
647 * device.
648 */
649 /* ARGSUSED */
650 int
hwgraph_info_get_LBL(vertex_hdl_t de,char * name,arbitrary_info_t * infop)651 hwgraph_info_get_LBL(vertex_hdl_t de,
652 char *name,
653 arbitrary_info_t *infop)
654 {
655 return(labelcl_info_get_LBL(de, name, NULL, infop));
656 }
657
658 /*
659 * hwgraph_info_get_exported_LBL - Retrieve the info_desc and info pointer
660 * of the given label for the device. The weird thing is that the label
661 * that matches the name is return irrespective of the info_desc value!
662 * Do not understand why the word "exported" is used!
663 */
664 /* ARGSUSED */
665 int
hwgraph_info_get_exported_LBL(vertex_hdl_t de,char * name,int * export_info,arbitrary_info_t * infop)666 hwgraph_info_get_exported_LBL(vertex_hdl_t de,
667 char *name,
668 int *export_info,
669 arbitrary_info_t *infop)
670 {
671 int rc;
672 arb_info_desc_t info_desc;
673
674 rc = labelcl_info_get_LBL(de, name, &info_desc, infop);
675 if (rc == 0)
676 *export_info = (int)info_desc;
677
678 return(rc);
679 }
680
681 /*
682 * hwgraph_info_get_next_LBL - Returns the next label info given the
683 * current label entry in place.
684 *
685 * Once again this has no locking or reference count for protection.
686 *
687 */
688 /* ARGSUSED */
689 int
hwgraph_info_get_next_LBL(vertex_hdl_t de,char * buf,arbitrary_info_t * infop,labelcl_info_place_t * place)690 hwgraph_info_get_next_LBL(vertex_hdl_t de,
691 char *buf,
692 arbitrary_info_t *infop,
693 labelcl_info_place_t *place)
694 {
695 return(labelcl_info_get_next_LBL(de, buf, NULL, infop, place));
696 }
697
698 /*
699 * hwgraph_info_export_LBL - Retrieve the specified label entry and modify
700 * the info_desc field with the given value in nbytes.
701 */
702 /* ARGSUSED */
703 int
hwgraph_info_export_LBL(vertex_hdl_t de,char * name,int nbytes)704 hwgraph_info_export_LBL(vertex_hdl_t de, char *name, int nbytes)
705 {
706 arbitrary_info_t info;
707 int rc;
708
709 if (nbytes == 0)
710 nbytes = INFO_DESC_EXPORT;
711
712 if (nbytes < 0)
713 return(-1);
714
715 rc = labelcl_info_get_LBL(de, name, NULL, &info);
716 if (rc != 0)
717 return(rc);
718
719 rc = labelcl_info_replace_LBL(de, name,
720 nbytes, info, NULL, NULL);
721
722 return(rc);
723 }
724
725 /*
726 * hwgraph_info_unexport_LBL - Retrieve the given label entry and change the
727 * label info_descr filed to INFO_DESC_PRIVATE.
728 */
729 /* ARGSUSED */
730 int
hwgraph_info_unexport_LBL(vertex_hdl_t de,char * name)731 hwgraph_info_unexport_LBL(vertex_hdl_t de, char *name)
732 {
733 arbitrary_info_t info;
734 int rc;
735
736 rc = labelcl_info_get_LBL(de, name, NULL, &info);
737 if (rc != 0)
738 return(rc);
739
740 rc = labelcl_info_replace_LBL(de, name,
741 INFO_DESC_PRIVATE, info, NULL, NULL);
742
743 return(rc);
744 }
745
746 /*
747 * hwgraph_path_lookup - return the handle for the given path.
748 *
749 */
750 int
hwgraph_path_lookup(vertex_hdl_t start_vertex_handle,char * lookup_path,vertex_hdl_t * vertex_handle_ptr,char ** remainder)751 hwgraph_path_lookup(vertex_hdl_t start_vertex_handle,
752 char *lookup_path,
753 vertex_hdl_t *vertex_handle_ptr,
754 char **remainder)
755 {
756 *vertex_handle_ptr = hwgfs_find_handle(start_vertex_handle, /* start dir */
757 lookup_path, /* path */
758 0, /* major */
759 0, /* minor */
760 0, /* char | block */
761 1); /* traverse symlinks */
762 if (*vertex_handle_ptr == NULL)
763 return(-1);
764 else
765 return(0);
766 }
767
768 /*
769 * hwgraph_traverse - Find and return the handle starting from de.
770 *
771 */
772 graph_error_t
hwgraph_traverse(vertex_hdl_t de,char * path,vertex_hdl_t * found)773 hwgraph_traverse(vertex_hdl_t de, char *path, vertex_hdl_t *found)
774 {
775 /*
776 * get the directory entry (path should end in a directory)
777 */
778
779 *found = hwgfs_find_handle(de, /* start dir */
780 path, /* path */
781 0, /* major */
782 0, /* minor */
783 0, /* char | block */
784 1); /* traverse symlinks */
785 if (*found == NULL)
786 return(GRAPH_NOT_FOUND);
787 else
788 return(GRAPH_SUCCESS);
789 }
790
791 /*
792 * hwgraph_path_to_vertex - Return the entry handle for the given
793 * pathname .. assume traverse symlinks too!.
794 */
795 vertex_hdl_t
hwgraph_path_to_vertex(char * path)796 hwgraph_path_to_vertex(char *path)
797 {
798 return(hwgfs_find_handle(NULL, /* start dir */
799 path, /* path */
800 0, /* major */
801 0, /* minor */
802 0, /* char | block */
803 1)); /* traverse symlinks */
804 }
805
806 /*
807 * hwgraph_inventory_remove - Removes an inventory entry.
808 *
809 * Remove an inventory item associated with a vertex. It is the caller's
810 * responsibility to make sure that there are no races between removing
811 * inventory from a vertex and simultaneously removing that vertex.
812 */
813 int
hwgraph_inventory_remove(vertex_hdl_t de,int class,int type,major_t controller,minor_t unit,int state)814 hwgraph_inventory_remove( vertex_hdl_t de,
815 int class,
816 int type,
817 major_t controller,
818 minor_t unit,
819 int state)
820 {
821 return(0); /* Just a Stub for IRIX code. */
822 }
823
824 /*
825 * Find the canonical name for a given vertex by walking back through
826 * connectpt's until we hit the hwgraph root vertex (or until we run
827 * out of buffer space or until something goes wrong).
828 *
829 * COMPATIBILITY FUNCTIONALITY
830 * Walks back through 'parents', not necessarily the same as connectpts.
831 *
832 * Need to resolve the fact that does not return the path from
833 * "/" but rather it just stops right before /dev ..
834 */
835 int
hwgraph_vertex_name_get(vertex_hdl_t vhdl,char * buf,uint buflen)836 hwgraph_vertex_name_get(vertex_hdl_t vhdl, char *buf, uint buflen)
837 {
838 char *locbuf;
839 int pos;
840
841 if (buflen < 1)
842 return(-1); /* XXX should be GRAPH_BAD_PARAM ? */
843
844 locbuf = kmalloc(buflen, GFP_KERNEL);
845
846 pos = hwgfs_generate_path(vhdl, locbuf, buflen);
847 if (pos < 0) {
848 kfree(locbuf);
849 return pos;
850 }
851
852 strcpy(buf, &locbuf[pos]);
853 kfree(locbuf);
854 return 0;
855 }
856
857 /*
858 ** vertex_to_name converts a vertex into a canonical name by walking
859 ** back through connect points until we hit the hwgraph root (or until
860 ** we run out of buffer space).
861 **
862 ** Usually returns a pointer to the original buffer, filled in as
863 ** appropriate. If the buffer is too small to hold the entire name,
864 ** or if anything goes wrong while determining the name, vertex_to_name
865 ** returns "UnknownDevice".
866 */
867
868 #define DEVNAME_UNKNOWN "UnknownDevice"
869
870 char *
vertex_to_name(vertex_hdl_t vhdl,char * buf,uint buflen)871 vertex_to_name(vertex_hdl_t vhdl, char *buf, uint buflen)
872 {
873 if (hwgraph_vertex_name_get(vhdl, buf, buflen) == GRAPH_SUCCESS)
874 return(buf);
875 else
876 return(DEVNAME_UNKNOWN);
877 }
878
879 graph_error_t
hwgraph_edge_remove(vertex_hdl_t from,char * name,vertex_hdl_t * toptr)880 hwgraph_edge_remove(vertex_hdl_t from, char *name, vertex_hdl_t *toptr)
881 {
882 return(GRAPH_ILLEGAL_REQUEST);
883 }
884
885 graph_error_t
hwgraph_vertex_unref(vertex_hdl_t vhdl)886 hwgraph_vertex_unref(vertex_hdl_t vhdl)
887 {
888 return(GRAPH_ILLEGAL_REQUEST);
889 }
890
891 void
hwgraph_debug(char * file,char * function,int line,vertex_hdl_t vhdl1,vertex_hdl_t vhdl2,char * format,...)892 hwgraph_debug(char *file, char * function, int line, vertex_hdl_t vhdl1, vertex_hdl_t vhdl2, char *format, ...)
893 {
894
895 int pos;
896 char *hwpath;
897 va_list ap;
898
899 if ( !hwgraph_debug_mask )
900 return;
901
902 hwpath = kmalloc(MAXDEVNAME, GFP_KERNEL);
903 if (!hwpath)
904 BUG();
905
906 printk("HWGRAPH_DEBUG %s %s %d : ", file, function, line);
907
908 if (vhdl1){
909 memset(hwpath, 0, MAXDEVNAME);
910 pos = hwgfs_generate_path(vhdl1, hwpath, MAXDEVNAME);
911 printk("vhdl1 = %s : ", &hwpath[pos]);
912 }
913
914 if (vhdl2){
915 memset(hwpath, 0, MAXDEVNAME);
916 pos = hwgfs_generate_path(vhdl2, hwpath, MAXDEVNAME);
917 printk("vhdl2 = %s :", &hwpath[pos]);
918 }
919
920 memset(hwpath, 0, MAXDEVNAME);
921 va_start(ap, format);
922 vsnprintf(hwpath, 500, format, ap);
923 va_end(ap);
924 hwpath[MAXDEVNAME -1] = (char)0; /* Just in case. */
925 printk(" %s", hwpath);
926 kfree(hwpath);
927 }
928
929 EXPORT_SYMBOL(hwgraph_mk_dir);
930 EXPORT_SYMBOL(hwgraph_path_add);
931 EXPORT_SYMBOL(hwgraph_register);
932 EXPORT_SYMBOL(hwgraph_vertex_destroy);
933 EXPORT_SYMBOL(hwgraph_fastinfo_get);
934 EXPORT_SYMBOL(hwgraph_fastinfo_set);
935 EXPORT_SYMBOL(hwgraph_connectpt_set);
936 EXPORT_SYMBOL(hwgraph_connectpt_get);
937 EXPORT_SYMBOL(hwgraph_info_add_LBL);
938 EXPORT_SYMBOL(hwgraph_info_remove_LBL);
939 EXPORT_SYMBOL(hwgraph_info_replace_LBL);
940 EXPORT_SYMBOL(hwgraph_info_get_LBL);
941 EXPORT_SYMBOL(hwgraph_info_get_exported_LBL);
942 EXPORT_SYMBOL(hwgraph_info_get_next_LBL);
943 EXPORT_SYMBOL(hwgraph_info_export_LBL);
944 EXPORT_SYMBOL(hwgraph_info_unexport_LBL);
945 EXPORT_SYMBOL(hwgraph_path_lookup);
946 EXPORT_SYMBOL(hwgraph_traverse);
947 EXPORT_SYMBOL(hwgraph_vertex_name_get);
948