232 lines · c
1/*2 * Kernel CAPI 2.0 Module - /proc/capi handling3 *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 terms8 * 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/capi30// ===========================================================================31 32// /proc/capi/controller:33// cnr driver cardstate name driverinfo34// /proc/capi/contrstats:35// cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt36// ---------------------------------------------------------------------------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 recvqueuelen113// /proc/capi/applstats:114// applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt115// ---------------------------------------------------------------------------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 int145applications_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 int162applstats_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 .proc_lseek = default_llseek,205};206 207// ---------------------------------------------------------------------------208 209void __init210kcapi_proc_init(void)211{212 proc_mkdir("capi", NULL);213 proc_mkdir("capi/controllers", NULL);214 proc_create_seq("capi/controller", 0, NULL, &seq_controller_ops);215 proc_create_seq("capi/contrstats", 0, NULL, &seq_contrstats_ops);216 proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops);217 proc_create_seq("capi/applstats", 0, NULL, &seq_applstats_ops);218 proc_create("capi/driver", 0, NULL, &empty_proc_ops);219}220 221void222kcapi_proc_exit(void)223{224 remove_proc_entry("capi/driver", NULL);225 remove_proc_entry("capi/controller", NULL);226 remove_proc_entry("capi/contrstats", NULL);227 remove_proc_entry("capi/applications", NULL);228 remove_proc_entry("capi/applstats", NULL);229 remove_proc_entry("capi/controllers", NULL);230 remove_proc_entry("capi", NULL);231}232