1
2
3
4
5
6
7
8
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 <asm/sn/sgi.h>
18#include <linux/devfs_fs.h>
19#include <linux/devfs_fs_kernel.h>
20#include <asm/io.h>
21#include <asm/sn/iograph.h>
22#include <asm/sn/invent.h>
23#include <asm/sn/hcl.h>
24#include <asm/sn/labelcl.h>
25#include <asm/sn/simulator.h>
26
27#define HCL_NAME "SGI-HWGRAPH COMPATIBILITY DRIVER"
28#define HCL_TEMP_NAME "HCL_TEMP_NAME_USED_FOR_HWGRAPH_VERTEX_CREATE"
29#define HCL_TEMP_NAME_LEN 44
30#define HCL_VERSION "1.0"
31vertex_hdl_t hwgraph_root;
32vertex_hdl_t linux_busnum;
33
34extern void pci_bus_cvlink_init(void);
35
36
37
38
39#define OPTION_NONE 0x00
40#define HCL_DEBUG_NONE 0x00000
41#define HCL_DEBUG_ALL 0x0ffff
42#if defined(CONFIG_HCL_DEBUG)
43static unsigned int hcl_debug_init __initdata = HCL_DEBUG_NONE;
44#endif
45static unsigned int hcl_debug = HCL_DEBUG_NONE;
46#if defined(CONFIG_HCL_DEBUG) && !defined(MODULE)
47static unsigned int boot_options = OPTION_NONE;
48#endif
49
50
51
52
53static vertex_hdl_t hcl_handle;
54
55invplace_t invplace_none = {
56 GRAPH_VERTEX_NONE,
57 GRAPH_VERTEX_PLACE_NONE,
58 NULL
59};
60
61
62
63
64
65
66
67
68
69static int hcl_open(struct inode * inode, struct file * filp)
70{
71 if (hcl_debug) {
72 printk("HCL: hcl_open called.\n");
73 }
74
75 return(0);
76
77}
78
79static int hcl_close(struct inode * inode, struct file * filp)
80{
81
82 if (hcl_debug) {
83 printk("HCL: hcl_close called.\n");
84 }
85
86 return(0);
87
88}
89
90static int hcl_ioctl(struct inode * inode, struct file * file,
91 unsigned int cmd, unsigned long arg)
92{
93
94 if (hcl_debug) {
95 printk("HCL: hcl_ioctl called.\n");
96 }
97
98 switch (cmd) {
99 default:
100 if (hcl_debug) {
101 printk("HCL: hcl_ioctl cmd = 0x%x\n", cmd);
102 }
103 }
104
105 return(0);
106
107}
108
109struct file_operations hcl_fops = {
110 (struct module *)0,
111 NULL,
112 NULL,
113 NULL,
114 NULL,
115 NULL,
116 hcl_ioctl,
117 NULL,
118 hcl_open,
119 NULL,
120 hcl_close,
121 NULL,
122 NULL,
123 NULL,
124 NULL,
125 NULL,
126};
127
128
129
130
131
132
133
134
135
136
137int __init init_hcl(void)
138{
139 extern void string_table_init(struct string_table *);
140 extern struct string_table label_string_table;
141 extern int init_ifconfig_net(void);
142 extern int init_ioconfig_bus(void);
143 int status = 0;
144 int rv = 0;
145
146 if (IS_RUNNING_ON_SIMULATOR()) {
147 extern u64 klgraph_addr[];
148 klgraph_addr[0] = 0xe000003000030000;
149 }
150
151
152
153
154 rv = hwgraph_path_add(NULL, EDGE_LBL_HW, &hwgraph_root);
155 if (rv)
156 printk ("WARNING: init_hcl: Failed to create hwgraph_root. Error = %d.\n", rv);
157
158 status = devfs_set_flags (hwgraph_root, DEVFS_FL_HIDE);
159
160
161
162
163
164
165 hcl_handle = hwgraph_register(hwgraph_root, ".hcl",
166 0, DEVFS_FL_AUTO_DEVNUM,
167 0, 0,
168 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
169 &hcl_fops, NULL);
170
171 if (hcl_handle == NULL) {
172 panic("HCL: Unable to create HCL Driver in init_hcl().\n");
173 return(0);
174 }
175
176
177
178
179 string_table_init(&label_string_table);
180
181
182
183
184 rv = hwgraph_path_add(hwgraph_root, EDGE_LBL_LINUX_BUS, &linux_busnum);
185 if (linux_busnum == NULL) {
186 panic("HCL: Unable to create %s\n", EDGE_LBL_LINUX_BUS);
187 return(0);
188 }
189
190 pci_bus_cvlink_init();
191
192
193
194
195
196 init_ifconfig_net();
197 init_ioconfig_bus();
198
199 return(0);
200
201}
202
203
204
205
206
207
208
209
210
211
212
213
214static int __init hcl_setup(char *str)
215{
216 while ( (*str != '\0') && !isspace (*str) )
217 {
218#ifdef CONFIG_HCL_DEBUG
219 if (strncmp (str, "all", 3) == 0) {
220 hcl_debug_init |= HCL_DEBUG_ALL;
221 str += 3;
222 } else
223 return 0;
224#endif
225 if (*str != ',') return 0;
226 ++str;
227 }
228
229 return 1;
230
231}
232
233__setup("hcl=", hcl_setup);
234
235
236int
237hwgraph_generate_path(
238 vertex_hdl_t de,
239 char *path,
240 int buflen)
241{
242 return (devfs_generate_path(de, path, buflen));
243}
244
245
246
247
248
249void
250hwgraph_fastinfo_set(vertex_hdl_t de, arbitrary_info_t fastinfo)
251{
252 labelcl_info_replace_IDX(de, HWGRAPH_FASTINFO, fastinfo, NULL);
253}
254
255
256
257
258
259
260arbitrary_info_t
261hwgraph_fastinfo_get(vertex_hdl_t de)
262{
263 arbitrary_info_t fastinfo;
264 int rv;
265
266 if (!de) {
267 printk(KERN_WARNING "HCL: hwgraph_fastinfo_get handle given is NULL.\n");
268 return(-1);
269 }
270
271 rv = labelcl_info_get_IDX(de, HWGRAPH_FASTINFO, &fastinfo);
272 if (rv == 0)
273 return(fastinfo);
274
275 return(0);
276}
277
278
279
280
281
282
283
284int
285hwgraph_connectpt_set(vertex_hdl_t de, vertex_hdl_t connect_de)
286{
287 int rv;
288
289 if (!de)
290 return(-1);
291
292 rv = labelcl_info_connectpt_set(de, connect_de);
293
294 return(rv);
295}
296
297
298
299
300
301
302vertex_hdl_t
303hwgraph_connectpt_get(vertex_hdl_t de)
304{
305 int rv;
306 arbitrary_info_t info;
307 vertex_hdl_t connect;
308
309 rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info);
310 if (rv != 0) {
311 return(NULL);
312 }
313
314 connect = (vertex_hdl_t)info;
315 return(connect);
316
317}
318
319
320
321
322
323
324
325vertex_hdl_t
326hwgraph_mk_dir(vertex_hdl_t de, const char *name,
327 unsigned int namelen, void *info)
328{
329
330 int rv;
331 labelcl_info_t *labelcl_info = NULL;
332 vertex_hdl_t new_devfs_handle = NULL;
333 vertex_hdl_t parent = NULL;
334
335
336
337
338 labelcl_info = labelcl_info_create();
339 if (!labelcl_info)
340 return(NULL);
341
342
343
344
345 new_devfs_handle = devfs_mk_dir(de, name, (void *)labelcl_info);
346 if (!new_devfs_handle) {
347 labelcl_info_destroy(labelcl_info);
348 return(NULL);
349 }
350
351
352
353
354 parent = devfs_get_parent (new_devfs_handle);
355
356
357
358
359 rv = hwgraph_connectpt_set(new_devfs_handle, parent);
360 if (!rv) {
361
362
363
364 }
365
366
367
368
369
370
371 if (info)
372 hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info);
373
374 return(new_devfs_handle);
375
376}
377
378
379
380
381
382int
383hwgraph_path_add(vertex_hdl_t fromv,
384 char *path,
385 vertex_hdl_t *new_de)
386{
387
388 unsigned int namelen = strlen(path);
389 int rv;
390
391
392
393
394
395
396 if (fromv == NULL)
397 fromv = hwgraph_root;
398
399
400
401
402
403
404 rv = hwgraph_edge_get(fromv, path, new_de);
405 if (rv) {
406 *new_de = hwgraph_mk_dir(fromv, path, namelen, NULL);
407 if (new_de == NULL)
408 return(-1);
409 else
410 return(0);
411 }
412 else
413 return(0);
414
415}
416
417
418
419
420
421
422vertex_hdl_t
423hwgraph_register(vertex_hdl_t de, const char *name,
424 unsigned int namelen, unsigned int flags,
425 unsigned int major, unsigned int minor,
426 umode_t mode, uid_t uid, gid_t gid,
427 struct file_operations *fops,
428 void *info)
429{
430
431 vertex_hdl_t new_devfs_handle = NULL;
432
433
434
435
436 new_devfs_handle = devfs_register(de, name, flags, major,
437 minor, mode, fops, info);
438 if (!new_devfs_handle) {
439 return(NULL);
440 }
441
442 return(new_devfs_handle);
443
444}
445
446
447
448
449
450int
451hwgraph_mk_symlink(vertex_hdl_t de, const char *name, unsigned int namelen,
452 unsigned int flags, const char *link, unsigned int linklen,
453 vertex_hdl_t *handle, void *info)
454{
455
456 void *labelcl_info = NULL;
457 int status = 0;
458 vertex_hdl_t new_devfs_handle = NULL;
459
460
461
462
463 labelcl_info = labelcl_info_create();
464 if (!labelcl_info)
465 return(-1);
466
467
468
469
470 status = devfs_mk_symlink(de, name, flags, link,
471 &new_devfs_handle, labelcl_info);
472 if ( (!new_devfs_handle) || (!status) ){
473 labelcl_info_destroy((labelcl_info_t *)labelcl_info);
474 return(-1);
475 }
476
477
478
479
480
481
482 if (info)
483 hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info);
484
485 *handle = new_devfs_handle;
486 return(0);
487
488}
489
490
491
492
493int
494hwgraph_vertex_destroy(vertex_hdl_t de)
495{
496
497 void *labelcl_info = NULL;
498
499 labelcl_info = devfs_get_info(de);
500 devfs_unregister(de);
501
502 if (labelcl_info)
503 labelcl_info_destroy((labelcl_info_t *)labelcl_info);
504
505 return(0);
506}
507
508
509
510
511
512
513int
514hwgraph_edge_add(vertex_hdl_t from, vertex_hdl_t to, char *name)
515{
516
517 char *path;
518 char *s1;
519 char *index;
520 int name_start;
521 vertex_hdl_t handle = NULL;
522 int rv;
523 int i, count;
524
525 path = kmalloc(1024, GFP_KERNEL);
526 memset(path, 0x0, 1024);
527 name_start = devfs_generate_path (from, path, 1024);
528 s1 = &path[name_start];
529 count = 0;
530 while (1) {
531 index = strstr (s1, "/");
532 if (index) {
533 count++;
534 s1 = ++index;
535 } else {
536 count++;
537 break;
538 }
539 }
540
541 memset(path, 0x0, 1024);
542 name_start = devfs_generate_path (to, path, 1024);
543
544 for (i = 0; i < count; i++) {
545 strcat(path,"../");
546 }
547
548 strcat(path, &path[name_start]);
549
550
551
552
553
554 rv = devfs_mk_symlink (from, (const char *)name,
555 DEVFS_FL_DEFAULT, path,
556 &handle, NULL);
557
558 name_start = devfs_generate_path (handle, path, 1024);
559 return(rv);
560
561
562}
563
564int
565hwgraph_edge_get(vertex_hdl_t from, char *name, vertex_hdl_t *toptr)
566{
567
568 int namelen = 0;
569 vertex_hdl_t target_handle = NULL;
570
571 if (name == NULL)
572 return(-1);
573
574 if (toptr == NULL)
575 return(-1);
576
577
578
579
580 if (!strcmp(name, HWGRAPH_EDGELBL_DOT)) {
581 if (toptr) {
582 *toptr = from;
583 }
584 } else if (!strcmp(name, HWGRAPH_EDGELBL_DOTDOT)) {
585
586
587
588
589
590
591
592 target_handle = hwgraph_connectpt_get(from);
593 if (target_handle) {
594
595
596
597 *toptr = target_handle;
598 return(0);
599 }
600 target_handle = devfs_get_parent(from);
601 *toptr = target_handle;
602
603 } else {
604
605
606
607 namelen = (int) strlen(name);
608 target_handle = devfs_find_handle (from, name, 0, 0,
609 0, 1);
610 if (target_handle == NULL)
611 return(-1);
612 else
613 *toptr = target_handle;
614 }
615
616 return(0);
617}
618
619
620
621
622
623
624int
625hwgraph_info_add_LBL( vertex_hdl_t de,
626 char *name,
627 arbitrary_info_t info)
628{
629 return(labelcl_info_add_LBL(de, name, INFO_DESC_PRIVATE, info));
630}
631
632
633
634
635
636int
637hwgraph_info_remove_LBL( vertex_hdl_t de,
638 char *name,
639 arbitrary_info_t *old_info)
640{
641 return(labelcl_info_remove_LBL(de, name, NULL, old_info));
642}
643
644
645
646
647
648
649int
650hwgraph_info_replace_LBL( vertex_hdl_t de,
651 char *name,
652 arbitrary_info_t info,
653 arbitrary_info_t *old_info)
654{
655 return(labelcl_info_replace_LBL(de, name,
656 INFO_DESC_PRIVATE, info,
657 NULL, old_info));
658}
659
660
661
662
663
664int
665hwgraph_info_get_LBL( vertex_hdl_t de,
666 char *name,
667 arbitrary_info_t *infop)
668{
669 return(labelcl_info_get_LBL(de, name, NULL, infop));
670}
671
672
673
674
675
676
677
678
679int
680hwgraph_info_get_exported_LBL( vertex_hdl_t de,
681 char *name,
682 int *export_info,
683 arbitrary_info_t *infop)
684{
685 int rc;
686 arb_info_desc_t info_desc;
687
688 rc = labelcl_info_get_LBL(de, name, &info_desc, infop);
689 if (rc == 0)
690 *export_info = (int)info_desc;
691
692 return(rc);
693}
694
695
696
697
698
699
700
701
702
703int
704hwgraph_info_get_next_LBL( vertex_hdl_t de,
705 char *buf,
706 arbitrary_info_t *infop,
707 labelcl_info_place_t *place)
708{
709 return(labelcl_info_get_next_LBL(de, buf, NULL, infop, place));
710}
711
712
713
714
715
716
717int
718hwgraph_info_export_LBL(vertex_hdl_t de, char *name, int nbytes)
719{
720 arbitrary_info_t info;
721 int rc;
722
723 if (nbytes == 0)
724 nbytes = INFO_DESC_EXPORT;
725
726 if (nbytes < 0)
727 return(-1);
728
729 rc = labelcl_info_get_LBL(de, name, NULL, &info);
730 if (rc != 0)
731 return(rc);
732
733 rc = labelcl_info_replace_LBL(de, name,
734 nbytes, info, NULL, NULL);
735
736 return(rc);
737}
738
739
740
741
742
743
744int
745hwgraph_info_unexport_LBL(vertex_hdl_t de, char *name)
746{
747 arbitrary_info_t info;
748 int rc;
749
750 rc = labelcl_info_get_LBL(de, name, NULL, &info);
751 if (rc != 0)
752 return(rc);
753
754 rc = labelcl_info_replace_LBL(de, name,
755 INFO_DESC_PRIVATE, info, NULL, NULL);
756
757 return(rc);
758}
759
760
761
762
763
764int
765hwgraph_path_lookup( vertex_hdl_t start_vertex_handle,
766 char *lookup_path,
767 vertex_hdl_t *vertex_handle_ptr,
768 char **remainder)
769{
770 *vertex_handle_ptr = devfs_find_handle(start_vertex_handle,
771 lookup_path,
772 0,
773 0,
774 0,
775 1);
776 if (*vertex_handle_ptr == NULL)
777 return(-1);
778 else
779 return(0);
780}
781
782
783
784
785
786graph_error_t
787hwgraph_traverse(vertex_hdl_t de, char *path, vertex_hdl_t *found)
788{
789
790
791
792
793 *found = devfs_find_handle(de,
794 path,
795 0,
796 0,
797 0,
798 1);
799 if (*found == NULL)
800 return(GRAPH_NOT_FOUND);
801 else
802 return(GRAPH_SUCCESS);
803}
804
805
806
807
808
809vertex_hdl_t
810hwgraph_path_to_vertex(char *path)
811{
812 return(devfs_find_handle(NULL,
813 path,
814 0,
815 0,
816 0,
817 1));
818}
819
820
821
822
823
824
825
826
827int
828hwgraph_inventory_remove( vertex_hdl_t de,
829 int class,
830 int type,
831 major_t controller,
832 minor_t unit,
833 int state)
834{
835 return(0);
836}
837
838
839
840
841
842
843
844
845
846
847
848
849int
850hwgraph_vertex_name_get(vertex_hdl_t vhdl, char *buf, uint buflen)
851{
852 char *locbuf;
853 int pos;
854
855 if (buflen < 1)
856 return(-1);
857
858 locbuf = kmalloc(buflen, GFP_KERNEL);
859
860 pos = devfs_generate_path(vhdl, locbuf, buflen);
861 if (pos < 0) {
862 kfree(locbuf);
863 return pos;
864 }
865
866 strcpy(buf, &locbuf[pos]);
867 kfree(locbuf);
868 return 0;
869}
870
871
872
873
874
875
876
877
878
879
880
881
882#define DEVNAME_UNKNOWN "UnknownDevice"
883
884char *
885vertex_to_name(vertex_hdl_t vhdl, char *buf, uint buflen)
886{
887 if (hwgraph_vertex_name_get(vhdl, buf, buflen) == GRAPH_SUCCESS)
888 return(buf);
889 else
890 return(DEVNAME_UNKNOWN);
891}
892
893graph_error_t
894hwgraph_edge_remove(vertex_hdl_t from, char *name, vertex_hdl_t *toptr)
895{
896 printk("WARNING: hwgraph_edge_remove NOT supported.\n");
897 return(GRAPH_ILLEGAL_REQUEST);
898}
899
900graph_error_t
901hwgraph_vertex_unref(vertex_hdl_t vhdl)
902{
903 return(GRAPH_ILLEGAL_REQUEST);
904}
905
906
907EXPORT_SYMBOL(hwgraph_mk_dir);
908EXPORT_SYMBOL(hwgraph_path_add);
909EXPORT_SYMBOL(hwgraph_register);
910EXPORT_SYMBOL(hwgraph_vertex_destroy);
911EXPORT_SYMBOL(hwgraph_fastinfo_get);
912EXPORT_SYMBOL(hwgraph_fastinfo_set);
913EXPORT_SYMBOL(hwgraph_connectpt_set);
914EXPORT_SYMBOL(hwgraph_connectpt_get);
915EXPORT_SYMBOL(hwgraph_info_add_LBL);
916EXPORT_SYMBOL(hwgraph_info_remove_LBL);
917EXPORT_SYMBOL(hwgraph_info_replace_LBL);
918EXPORT_SYMBOL(hwgraph_info_get_LBL);
919EXPORT_SYMBOL(hwgraph_info_get_exported_LBL);
920EXPORT_SYMBOL(hwgraph_info_get_next_LBL);
921EXPORT_SYMBOL(hwgraph_info_export_LBL);
922EXPORT_SYMBOL(hwgraph_info_unexport_LBL);
923EXPORT_SYMBOL(hwgraph_path_lookup);
924EXPORT_SYMBOL(hwgraph_traverse);
925EXPORT_SYMBOL(hwgraph_vertex_name_get);
926