linux/arch/ia64/sn/kernel/sn2/prominfo_proc.c
<<
>>
Prefs
   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
  21MODULE_DESCRIPTION("PROM version reporting for /proc");
  22MODULE_AUTHOR("Chad Talbott");
  23MODULE_LICENSE("GPL");
  24
  25/* Standard Intel FIT entry types */
  26#define FIT_ENTRY_FIT_HEADER    0x00    /* FIT header entry */
  27#define FIT_ENTRY_PAL_B         0x01    /* PAL_B entry */
  28/* Entries 0x02 through 0x0D reserved by Intel */
  29#define FIT_ENTRY_PAL_A_PROC    0x0E    /* Processor-specific PAL_A entry */
  30#define FIT_ENTRY_PAL_A         0x0F    /* PAL_A entry, same as... */
  31#define FIT_ENTRY_PAL_A_GEN     0x0F    /* ...Generic PAL_A entry */
  32#define FIT_ENTRY_UNUSED        0x7F    /* Unused (reserved by Intel?) */
  33/* OEM-defined entries range from 0x10 to 0x7E. */
  34#define FIT_ENTRY_SAL_A         0x10    /* SAL_A entry */
  35#define FIT_ENTRY_SAL_B         0x11    /* SAL_B entry */
  36#define FIT_ENTRY_SALRUNTIME    0x12    /* SAL runtime entry */
  37#define FIT_ENTRY_EFI           0x1F    /* EFI entry */
  38#define FIT_ENTRY_FPSWA         0x20    /* embedded fpswa entry */
  39#define FIT_ENTRY_VMLINUX       0x21    /* embedded vmlinux entry */
  40
  41#define FIT_MAJOR_SHIFT (32 + 8)
  42#define FIT_MAJOR_MASK  ((1 << 8) - 1)
  43#define FIT_MINOR_SHIFT 32
  44#define FIT_MINOR_MASK  ((1 << 8) - 1)
  45
  46#define FIT_MAJOR(q)    \
  47        ((unsigned) ((q) >> FIT_MAJOR_SHIFT) & FIT_MAJOR_MASK)
  48#define FIT_MINOR(q)    \
  49        ((unsigned) ((q) >> FIT_MINOR_SHIFT) & FIT_MINOR_MASK)
  50
  51#define FIT_TYPE_SHIFT  (32 + 16)
  52#define FIT_TYPE_MASK   ((1 << 7) - 1)
  53
  54#define FIT_TYPE(q)     \
  55        ((unsigned) ((q) >> FIT_TYPE_SHIFT) & FIT_TYPE_MASK)
  56
  57struct fit_type_map_t {
  58        unsigned char type;
  59        const char *name;
  60};
  61
  62static const struct fit_type_map_t fit_entry_types[] = {
  63        {FIT_ENTRY_FIT_HEADER, "FIT Header"},
  64        {FIT_ENTRY_PAL_A_GEN, "Generic PAL_A"},
  65        {FIT_ENTRY_PAL_A_PROC, "Processor-specific PAL_A"},
  66        {FIT_ENTRY_PAL_A, "PAL_A"},
  67        {FIT_ENTRY_PAL_B, "PAL_B"},
  68        {FIT_ENTRY_SAL_A, "SAL_A"},
  69        {FIT_ENTRY_SAL_B, "SAL_B"},
  70        {FIT_ENTRY_SALRUNTIME, "SAL runtime"},
  71        {FIT_ENTRY_EFI, "EFI"},
  72        {FIT_ENTRY_VMLINUX, "Embedded Linux"},
  73        {FIT_ENTRY_FPSWA, "Embedded FPSWA"},
  74        {FIT_ENTRY_UNUSED, "Unused"},
  75        {0xff, "Error"},
  76};
  77
  78static const char *fit_type_name(unsigned char type)
  79{
  80        struct fit_type_map_t const *mapp;
  81
  82        for (mapp = fit_entry_types; mapp->type != 0xff; mapp++)
  83                if (type == mapp->type)
  84                        return mapp->name;
  85
  86        if ((type > FIT_ENTRY_PAL_A) && (type < FIT_ENTRY_UNUSED))
  87                return "OEM type";
  88        if ((type > FIT_ENTRY_PAL_B) && (type < FIT_ENTRY_PAL_A))
  89                return "Reserved";
  90
  91        return "Unknown type";
  92}
  93
  94static int
  95get_fit_entry(unsigned long nasid, int index, unsigned long *fentry,
  96              char *banner, int banlen)
  97{
  98        return ia64_sn_get_fit_compt(nasid, index, fentry, banner, banlen);
  99}
 100
 101
 102/*
 103 * These two routines display the FIT table for each node.
 104 */
 105static void dump_fit_entry(struct seq_file *m, unsigned long *fentry)
 106{
 107        unsigned type;
 108
 109        type = FIT_TYPE(fentry[1]);
 110        seq_printf(m, "%02x %-25s %x.%02x %016lx %u\n",
 111                   type,
 112                   fit_type_name(type),
 113                   FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]),
 114                   fentry[0],
 115                   /* mult by sixteen to get size in bytes */
 116                   (unsigned)(fentry[1] & 0xffffff) * 16);
 117}
 118
 119
 120/*
 121 * We assume that the fit table will be small enough that we can print
 122 * the whole thing into one page.  (This is true for our default 16kB
 123 * pages -- each entry is about 60 chars wide when printed.)  I read
 124 * somewhere that the maximum size of the FIT is 128 entries, so we're
 125 * OK except for 4kB pages (and no one is going to do that on SN
 126 * anyway).
 127 */
 128static int proc_fit_show(struct seq_file *m, void *v)
 129{
 130        unsigned long nasid = (unsigned long)m->private;
 131        unsigned long fentry[2];
 132        int index;
 133
 134        for (index=0;;index++) {
 135                BUG_ON(index * 60 > PAGE_SIZE);
 136                if (get_fit_entry(nasid, index, fentry, NULL, 0))
 137                        break;
 138                dump_fit_entry(m, fentry);
 139        }
 140        return 0;
 141}
 142
 143static int proc_fit_open(struct inode *inode, struct file *file)
 144{
 145        return single_open(file, proc_fit_show, PDE_DATA(inode));
 146}
 147
 148static const struct file_operations proc_fit_fops = {
 149        .open           = proc_fit_open,
 150        .read           = seq_read,
 151        .llseek         = seq_lseek,
 152        .release        = single_release,
 153};
 154
 155static int proc_version_show(struct seq_file *m, void *v)
 156{
 157        unsigned long nasid = (unsigned long)m->private;
 158        unsigned long fentry[2];
 159        char banner[128];
 160        int index;
 161
 162        for (index = 0; ; index++) {
 163                if (get_fit_entry(nasid, index, fentry, banner,
 164                                  sizeof(banner)))
 165                        return 0;
 166                if (FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A)
 167                        break;
 168        }
 169
 170        seq_printf(m, "%x.%02x\n", FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]));
 171
 172        if (banner[0])
 173                seq_printf(m, "%s\n", banner);
 174        return 0;
 175}
 176
 177static int proc_version_open(struct inode *inode, struct file *file)
 178{
 179        return single_open(file, proc_version_show, PDE_DATA(inode));
 180}
 181
 182static const struct file_operations proc_version_fops = {
 183        .open           = proc_version_open,
 184        .read           = seq_read,
 185        .llseek         = seq_lseek,
 186        .release        = single_release,
 187};
 188
 189/* module entry points */
 190int __init prominfo_init(void);
 191void __exit prominfo_exit(void);
 192
 193module_init(prominfo_init);
 194module_exit(prominfo_exit);
 195
 196#define NODE_NAME_LEN 11
 197
 198int __init prominfo_init(void)
 199{
 200        struct proc_dir_entry *sgi_prominfo_entry;
 201        cnodeid_t cnodeid;
 202
 203        if (!ia64_platform_is("sn2"))
 204                return 0;
 205
 206        sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL);
 207        if (!sgi_prominfo_entry)
 208                return -ENOMEM;
 209
 210        for_each_online_node(cnodeid) {
 211                struct proc_dir_entry *dir;
 212                unsigned long nasid;
 213                char name[NODE_NAME_LEN];
 214
 215                sprintf(name, "node%d", cnodeid);
 216                dir = proc_mkdir(name, sgi_prominfo_entry);
 217                if (!dir)
 218                        continue;
 219                nasid = cnodeid_to_nasid(cnodeid);
 220                proc_create_data("fit", 0, dir,
 221                                 &proc_fit_fops, (void *)nasid);
 222                proc_create_data("version", 0, dir,
 223                                 &proc_version_fops, (void *)nasid);
 224        }
 225        return 0;
 226}
 227
 228void __exit prominfo_exit(void)
 229{
 230        remove_proc_subtree("sgi_prominfo", NULL);
 231}
 232