prominfo_proc.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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_fit_open(struct inode *inode, struct file *file)
  124. {
  125. return single_open(file, proc_fit_show, PDE_DATA(inode));
  126. }
  127. static const struct file_operations proc_fit_fops = {
  128. .open = proc_fit_open,
  129. .read = seq_read,
  130. .llseek = seq_lseek,
  131. .release = single_release,
  132. };
  133. static int proc_version_show(struct seq_file *m, void *v)
  134. {
  135. unsigned long nasid = (unsigned long)m->private;
  136. unsigned long fentry[2];
  137. char banner[128];
  138. int index;
  139. for (index = 0; ; index++) {
  140. if (get_fit_entry(nasid, index, fentry, banner,
  141. sizeof(banner)))
  142. return 0;
  143. if (FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A)
  144. break;
  145. }
  146. seq_printf(m, "%x.%02x\n", FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]));
  147. if (banner[0])
  148. seq_printf(m, "%s\n", banner);
  149. return 0;
  150. }
  151. static int proc_version_open(struct inode *inode, struct file *file)
  152. {
  153. return single_open(file, proc_version_show, PDE_DATA(inode));
  154. }
  155. static const struct file_operations proc_version_fops = {
  156. .open = proc_version_open,
  157. .read = seq_read,
  158. .llseek = seq_lseek,
  159. .release = single_release,
  160. };
  161. /* module entry points */
  162. int __init prominfo_init(void);
  163. void __exit prominfo_exit(void);
  164. module_init(prominfo_init);
  165. module_exit(prominfo_exit);
  166. #define NODE_NAME_LEN 11
  167. int __init prominfo_init(void)
  168. {
  169. struct proc_dir_entry *sgi_prominfo_entry;
  170. cnodeid_t cnodeid;
  171. if (!ia64_platform_is("sn2"))
  172. return 0;
  173. sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL);
  174. if (!sgi_prominfo_entry)
  175. return -ENOMEM;
  176. for_each_online_node(cnodeid) {
  177. struct proc_dir_entry *dir;
  178. unsigned long nasid;
  179. char name[NODE_NAME_LEN];
  180. sprintf(name, "node%d", cnodeid);
  181. dir = proc_mkdir(name, sgi_prominfo_entry);
  182. if (!dir)
  183. continue;
  184. nasid = cnodeid_to_nasid(cnodeid);
  185. proc_create_data("fit", 0, dir,
  186. &proc_fit_fops, (void *)nasid);
  187. proc_create_data("version", 0, dir,
  188. &proc_version_fops, (void *)nasid);
  189. }
  190. return 0;
  191. }
  192. void __exit prominfo_exit(void)
  193. {
  194. remove_proc_subtree("sgi_prominfo", NULL);
  195. }