prominfo_proc.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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. * Copyright (C) 1999,2001-2004, 2006 Silicon Graphics, Inc. All Rights Reserved.
  7. *
  8. * Module to export the system's Firmware Interface Tables, including
  9. * PROM revision numbers and banners, in /proc
  10. */
  11. #include <linux/module.h>
  12. #include <linux/slab.h>
  13. #include <linux/proc_fs.h>
  14. #include <linux/seq_file.h>
  15. #include <linux/nodemask.h>
  16. #include <asm/io.h>
  17. #include <asm/sn/sn_sal.h>
  18. #include <asm/sn/sn_cpuid.h>
  19. #include <asm/sn/addrs.h>
  20. MODULE_DESCRIPTION("PROM version reporting for /proc");
  21. MODULE_AUTHOR("Chad Talbott");
  22. MODULE_LICENSE("GPL");
  23. /* Standard Intel FIT entry types */
  24. #define FIT_ENTRY_FIT_HEADER 0x00 /* FIT header entry */
  25. #define FIT_ENTRY_PAL_B 0x01 /* PAL_B entry */
  26. /* Entries 0x02 through 0x0D reserved by Intel */
  27. #define FIT_ENTRY_PAL_A_PROC 0x0E /* Processor-specific PAL_A entry */
  28. #define FIT_ENTRY_PAL_A 0x0F /* PAL_A entry, same as... */
  29. #define FIT_ENTRY_PAL_A_GEN 0x0F /* ...Generic PAL_A entry */
  30. #define FIT_ENTRY_UNUSED 0x7F /* Unused (reserved by Intel?) */
  31. /* OEM-defined entries range from 0x10 to 0x7E. */
  32. #define FIT_ENTRY_SAL_A 0x10 /* SAL_A entry */
  33. #define FIT_ENTRY_SAL_B 0x11 /* SAL_B entry */
  34. #define FIT_ENTRY_SALRUNTIME 0x12 /* SAL runtime entry */
  35. #define FIT_ENTRY_EFI 0x1F /* EFI entry */
  36. #define FIT_ENTRY_FPSWA 0x20 /* embedded fpswa entry */
  37. #define FIT_ENTRY_VMLINUX 0x21 /* embedded vmlinux entry */
  38. #define FIT_MAJOR_SHIFT (32 + 8)
  39. #define FIT_MAJOR_MASK ((1 << 8) - 1)
  40. #define FIT_MINOR_SHIFT 32
  41. #define FIT_MINOR_MASK ((1 << 8) - 1)
  42. #define FIT_MAJOR(q) \
  43. ((unsigned) ((q) >> FIT_MAJOR_SHIFT) & FIT_MAJOR_MASK)
  44. #define FIT_MINOR(q) \
  45. ((unsigned) ((q) >> FIT_MINOR_SHIFT) & FIT_MINOR_MASK)
  46. #define FIT_TYPE_SHIFT (32 + 16)
  47. #define FIT_TYPE_MASK ((1 << 7) - 1)
  48. #define FIT_TYPE(q) \
  49. ((unsigned) ((q) >> FIT_TYPE_SHIFT) & FIT_TYPE_MASK)
  50. struct fit_type_map_t {
  51. unsigned char type;
  52. const char *name;
  53. };
  54. static const struct fit_type_map_t fit_entry_types[] = {
  55. {FIT_ENTRY_FIT_HEADER, "FIT Header"},
  56. {FIT_ENTRY_PAL_A_GEN, "Generic PAL_A"},
  57. {FIT_ENTRY_PAL_A_PROC, "Processor-specific PAL_A"},
  58. {FIT_ENTRY_PAL_A, "PAL_A"},
  59. {FIT_ENTRY_PAL_B, "PAL_B"},
  60. {FIT_ENTRY_SAL_A, "SAL_A"},
  61. {FIT_ENTRY_SAL_B, "SAL_B"},
  62. {FIT_ENTRY_SALRUNTIME, "SAL runtime"},
  63. {FIT_ENTRY_EFI, "EFI"},
  64. {FIT_ENTRY_VMLINUX, "Embedded Linux"},
  65. {FIT_ENTRY_FPSWA, "Embedded FPSWA"},
  66. {FIT_ENTRY_UNUSED, "Unused"},
  67. {0xff, "Error"},
  68. };
  69. static const char *fit_type_name(unsigned char type)
  70. {
  71. struct fit_type_map_t const *mapp;
  72. for (mapp = fit_entry_types; mapp->type != 0xff; mapp++)
  73. if (type == mapp->type)
  74. return mapp->name;
  75. if ((type > FIT_ENTRY_PAL_A) && (type < FIT_ENTRY_UNUSED))
  76. return "OEM type";
  77. if ((type > FIT_ENTRY_PAL_B) && (type < FIT_ENTRY_PAL_A))
  78. return "Reserved";
  79. return "Unknown type";
  80. }
  81. static int
  82. get_fit_entry(unsigned long nasid, int index, unsigned long *fentry,
  83. char *banner, int banlen)
  84. {
  85. return ia64_sn_get_fit_compt(nasid, index, fentry, banner, banlen);
  86. }
  87. /*
  88. * These two routines display the FIT table for each node.
  89. */
  90. static void dump_fit_entry(struct seq_file *m, unsigned long *fentry)
  91. {
  92. unsigned type;
  93. type = FIT_TYPE(fentry[1]);
  94. seq_printf(m, "%02x %-25s %x.%02x %016lx %u\n",
  95. type,
  96. fit_type_name(type),
  97. FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]),
  98. fentry[0],
  99. /* mult by sixteen to get size in bytes */
  100. (unsigned)(fentry[1] & 0xffffff) * 16);
  101. }
  102. /*
  103. * We assume that the fit table will be small enough that we can print
  104. * the whole thing into one page. (This is true for our default 16kB
  105. * pages -- each entry is about 60 chars wide when printed.) I read
  106. * somewhere that the maximum size of the FIT is 128 entries, so we're
  107. * OK except for 4kB pages (and no one is going to do that on SN
  108. * anyway).
  109. */
  110. static int proc_fit_show(struct seq_file *m, void *v)
  111. {
  112. unsigned long nasid = (unsigned long)m->private;
  113. unsigned long fentry[2];
  114. int index;
  115. for (index=0;;index++) {
  116. BUG_ON(index * 60 > PAGE_SIZE);
  117. if (get_fit_entry(nasid, index, fentry, NULL, 0))
  118. break;
  119. dump_fit_entry(m, fentry);
  120. }
  121. return 0;
  122. }
  123. static int proc_version_show(struct seq_file *m, void *v)
  124. {
  125. unsigned long nasid = (unsigned long)m->private;
  126. unsigned long fentry[2];
  127. char banner[128];
  128. int index;
  129. for (index = 0; ; index++) {
  130. if (get_fit_entry(nasid, index, fentry, banner,
  131. sizeof(banner)))
  132. return 0;
  133. if (FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A)
  134. break;
  135. }
  136. seq_printf(m, "%x.%02x\n", FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]));
  137. if (banner[0])
  138. seq_printf(m, "%s\n", banner);
  139. return 0;
  140. }
  141. /* module entry points */
  142. int __init prominfo_init(void);
  143. void __exit prominfo_exit(void);
  144. module_init(prominfo_init);
  145. module_exit(prominfo_exit);
  146. #define NODE_NAME_LEN 11
  147. int __init prominfo_init(void)
  148. {
  149. struct proc_dir_entry *sgi_prominfo_entry;
  150. cnodeid_t cnodeid;
  151. if (!ia64_platform_is("sn2"))
  152. return 0;
  153. sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL);
  154. if (!sgi_prominfo_entry)
  155. return -ENOMEM;
  156. for_each_online_node(cnodeid) {
  157. struct proc_dir_entry *dir;
  158. unsigned long nasid;
  159. char name[NODE_NAME_LEN];
  160. sprintf(name, "node%d", cnodeid);
  161. dir = proc_mkdir(name, sgi_prominfo_entry);
  162. if (!dir)
  163. continue;
  164. nasid = cnodeid_to_nasid(cnodeid);
  165. proc_create_single_data("fit", 0, dir, proc_fit_show,
  166. (void *)nasid);
  167. proc_create_single_data("version", 0, dir, proc_version_show,
  168. (void *)nasid);
  169. }
  170. return 0;
  171. }
  172. void __exit prominfo_exit(void)
  173. {
  174. remove_proc_subtree("sgi_prominfo", NULL);
  175. }