linux/drivers/isdn/capi/kcapi_proc.c
<<
>>
Prefs
   1/*
   2 * Kernel CAPI 2.0 Module - /proc/capi handling
   3 *
   4 * Copyright 1999 by Carsten Paeth <calle@calle.de>
   5 * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
   6 *
   7 * This software may be used and distributed according to the terms
   8 * of the GNU General Public License, incorporated herein by reference.
   9 *
  10 */
  11
  12
  13#include "kcapi.h"
  14#include <linux/proc_fs.h>
  15#include <linux/seq_file.h>
  16#include <linux/init.h>
  17#include <linux/export.h>
  18
  19static char *state2str(unsigned short state)
  20{
  21        switch (state) {
  22        case CAPI_CTR_DETECTED: return "detected";
  23        case CAPI_CTR_LOADING:  return "loading";
  24        case CAPI_CTR_RUNNING:  return "running";
  25        default:                return "???";
  26        }
  27}
  28
  29// /proc/capi
  30// ===========================================================================
  31
  32// /proc/capi/controller:
  33//      cnr driver cardstate name driverinfo
  34// /proc/capi/contrstats:
  35//      cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
  36// ---------------------------------------------------------------------------
  37
  38static void *controller_start(struct seq_file *seq, loff_t *pos)
  39        __acquires(capi_controller_lock)
  40{
  41        mutex_lock(&capi_controller_lock);
  42
  43        if (*pos < CAPI_MAXCONTR)
  44                return &capi_controller[*pos];
  45
  46        return NULL;
  47}
  48
  49static void *controller_next(struct seq_file *seq, void *v, loff_t *pos)
  50{
  51        ++*pos;
  52        if (*pos < CAPI_MAXCONTR)
  53                return &capi_controller[*pos];
  54
  55        return NULL;
  56}
  57
  58static void controller_stop(struct seq_file *seq, void *v)
  59        __releases(capi_controller_lock)
  60{
  61        mutex_unlock(&capi_controller_lock);
  62}
  63
  64static int controller_show(struct seq_file *seq, void *v)
  65{
  66        struct capi_ctr *ctr = *(struct capi_ctr **) v;
  67
  68        if (!ctr)
  69                return 0;
  70
  71        seq_printf(seq, "%d %-10s %-8s %-16s %s\n",
  72                   ctr->cnr, ctr->driver_name,
  73                   state2str(ctr->state),
  74                   ctr->name,
  75                   ctr->procinfo ?  ctr->procinfo(ctr) : "");
  76
  77        return 0;
  78}
  79
  80static int contrstats_show(struct seq_file *seq, void *v)
  81{
  82        struct capi_ctr *ctr = *(struct capi_ctr **) v;
  83
  84        if (!ctr)
  85                return 0;
  86
  87        seq_printf(seq, "%d %lu %lu %lu %lu\n",
  88                   ctr->cnr,
  89                   ctr->nrecvctlpkt,
  90                   ctr->nrecvdatapkt,
  91                   ctr->nsentctlpkt,
  92                   ctr->nsentdatapkt);
  93
  94        return 0;
  95}
  96
  97static const struct seq_operations seq_controller_ops = {
  98        .start  = controller_start,
  99        .next   = controller_next,
 100        .stop   = controller_stop,
 101        .show   = controller_show,
 102};
 103
 104static const struct seq_operations seq_contrstats_ops = {
 105        .start  = controller_start,
 106        .next   = controller_next,
 107        .stop   = controller_stop,
 108        .show   = contrstats_show,
 109};
 110
 111// /proc/capi/applications:
 112//      applid l3cnt dblkcnt dblklen #ncci recvqueuelen
 113// /proc/capi/applstats:
 114//      applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
 115// ---------------------------------------------------------------------------
 116
 117static void *applications_start(struct seq_file *seq, loff_t *pos)
 118        __acquires(capi_controller_lock)
 119{
 120        mutex_lock(&capi_controller_lock);
 121
 122        if (*pos < CAPI_MAXAPPL)
 123                return &capi_applications[*pos];
 124
 125        return NULL;
 126}
 127
 128static void *
 129applications_next(struct seq_file *seq, void *v, loff_t *pos)
 130{
 131        ++*pos;
 132        if (*pos < CAPI_MAXAPPL)
 133                return &capi_applications[*pos];
 134
 135        return NULL;
 136}
 137
 138static void applications_stop(struct seq_file *seq, void *v)
 139        __releases(capi_controller_lock)
 140{
 141        mutex_unlock(&capi_controller_lock);
 142}
 143
 144static int
 145applications_show(struct seq_file *seq, void *v)
 146{
 147        struct capi20_appl *ap = *(struct capi20_appl **) v;
 148
 149        if (!ap)
 150                return 0;
 151
 152        seq_printf(seq, "%u %d %d %d\n",
 153                   ap->applid,
 154                   ap->rparam.level3cnt,
 155                   ap->rparam.datablkcnt,
 156                   ap->rparam.datablklen);
 157
 158        return 0;
 159}
 160
 161static int
 162applstats_show(struct seq_file *seq, void *v)
 163{
 164        struct capi20_appl *ap = *(struct capi20_appl **) v;
 165
 166        if (!ap)
 167                return 0;
 168
 169        seq_printf(seq, "%u %lu %lu %lu %lu\n",
 170                   ap->applid,
 171                   ap->nrecvctlpkt,
 172                   ap->nrecvdatapkt,
 173                   ap->nsentctlpkt,
 174                   ap->nsentdatapkt);
 175
 176        return 0;
 177}
 178
 179static const struct seq_operations seq_applications_ops = {
 180        .start  = applications_start,
 181        .next   = applications_next,
 182        .stop   = applications_stop,
 183        .show   = applications_show,
 184};
 185
 186static const struct seq_operations seq_applstats_ops = {
 187        .start  = applications_start,
 188        .next   = applications_next,
 189        .stop   = applications_stop,
 190        .show   = applstats_show,
 191};
 192
 193// ---------------------------------------------------------------------------
 194
 195/* /proc/capi/drivers is always empty */
 196static ssize_t empty_read(struct file *file, char __user *buf,
 197                          size_t size, loff_t *off)
 198{
 199        return 0;
 200}
 201
 202static const struct proc_ops empty_proc_ops = {
 203        .proc_read      = empty_read,
 204};
 205
 206// ---------------------------------------------------------------------------
 207
 208void __init
 209kcapi_proc_init(void)
 210{
 211        proc_mkdir("capi",             NULL);
 212        proc_mkdir("capi/controllers", NULL);
 213        proc_create_seq("capi/controller",   0, NULL, &seq_controller_ops);
 214        proc_create_seq("capi/contrstats",   0, NULL, &seq_contrstats_ops);
 215        proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops);
 216        proc_create_seq("capi/applstats",    0, NULL, &seq_applstats_ops);
 217        proc_create("capi/driver",           0, NULL, &empty_proc_ops);
 218}
 219
 220void
 221kcapi_proc_exit(void)
 222{
 223        remove_proc_entry("capi/driver",       NULL);
 224        remove_proc_entry("capi/controller",   NULL);
 225        remove_proc_entry("capi/contrstats",   NULL);
 226        remove_proc_entry("capi/applications", NULL);
 227        remove_proc_entry("capi/applstats",    NULL);
 228        remove_proc_entry("capi/controllers",  NULL);
 229        remove_proc_entry("capi",              NULL);
 230}
 231