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 111static int seq_controller_open(struct inode *inode, struct file *file) 112{ 113 return seq_open(file, &seq_controller_ops); 114} 115 116static int seq_contrstats_open(struct inode *inode, struct file *file) 117{ 118 return seq_open(file, &seq_contrstats_ops); 119} 120 121static const struct file_operations proc_controller_ops = { 122 .owner = THIS_MODULE, 123 .open = seq_controller_open, 124 .read = seq_read, 125 .llseek = seq_lseek, 126 .release = seq_release, 127}; 128 129static const struct file_operations proc_contrstats_ops = { 130 .owner = THIS_MODULE, 131 .open = seq_contrstats_open, 132 .read = seq_read, 133 .llseek = seq_lseek, 134 .release = seq_release, 135}; 136 137// /proc/capi/applications: 138// applid l3cnt dblkcnt dblklen #ncci recvqueuelen 139// /proc/capi/applstats: 140// applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt 141// --------------------------------------------------------------------------- 142 143static void *applications_start(struct seq_file *seq, loff_t *pos) 144 __acquires(capi_controller_lock) 145{ 146 mutex_lock(&capi_controller_lock); 147 148 if (*pos < CAPI_MAXAPPL) 149 return &capi_applications[*pos]; 150 151 return NULL; 152} 153 154static void * 155applications_next(struct seq_file *seq, void *v, loff_t *pos) 156{ 157 ++*pos; 158 if (*pos < CAPI_MAXAPPL) 159 return &capi_applications[*pos]; 160 161 return NULL; 162} 163 164static void applications_stop(struct seq_file *seq, void *v) 165 __releases(capi_controller_lock) 166{ 167 mutex_unlock(&capi_controller_lock); 168} 169 170static int 171applications_show(struct seq_file *seq, void *v) 172{ 173 struct capi20_appl *ap = *(struct capi20_appl **) v; 174 175 if (!ap) 176 return 0; 177 178 seq_printf(seq, "%u %d %d %d\n", 179 ap->applid, 180 ap->rparam.level3cnt, 181 ap->rparam.datablkcnt, 182 ap->rparam.datablklen); 183 184 return 0; 185} 186 187static int 188applstats_show(struct seq_file *seq, void *v) 189{ 190 struct capi20_appl *ap = *(struct capi20_appl **) v; 191 192 if (!ap) 193 return 0; 194 195 seq_printf(seq, "%u %lu %lu %lu %lu\n", 196 ap->applid, 197 ap->nrecvctlpkt, 198 ap->nrecvdatapkt, 199 ap->nsentctlpkt, 200 ap->nsentdatapkt); 201 202 return 0; 203} 204 205static const struct seq_operations seq_applications_ops = { 206 .start = applications_start, 207 .next = applications_next, 208 .stop = applications_stop, 209 .show = applications_show, 210}; 211 212static const struct seq_operations seq_applstats_ops = { 213 .start = applications_start, 214 .next = applications_next, 215 .stop = applications_stop, 216 .show = applstats_show, 217}; 218 219static int 220seq_applications_open(struct inode *inode, struct file *file) 221{ 222 return seq_open(file, &seq_applications_ops); 223} 224 225static int 226seq_applstats_open(struct inode *inode, struct file *file) 227{ 228 return seq_open(file, &seq_applstats_ops); 229} 230 231static const struct file_operations proc_applications_ops = { 232 .owner = THIS_MODULE, 233 .open = seq_applications_open, 234 .read = seq_read, 235 .llseek = seq_lseek, 236 .release = seq_release, 237}; 238 239static const struct file_operations proc_applstats_ops = { 240 .owner = THIS_MODULE, 241 .open = seq_applstats_open, 242 .read = seq_read, 243 .llseek = seq_lseek, 244 .release = seq_release, 245}; 246 247// --------------------------------------------------------------------------- 248 249static void *capi_driver_start(struct seq_file *seq, loff_t *pos) 250 __acquires(&capi_drivers_lock) 251{ 252 mutex_lock(&capi_drivers_lock); 253 return seq_list_start(&capi_drivers, *pos); 254} 255 256static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) 257{ 258 return seq_list_next(v, &capi_drivers, pos); 259} 260 261static void capi_driver_stop(struct seq_file *seq, void *v) 262 __releases(&capi_drivers_lock) 263{ 264 mutex_unlock(&capi_drivers_lock); 265} 266 267static int capi_driver_show(struct seq_file *seq, void *v) 268{ 269 struct capi_driver *drv = list_entry(v, struct capi_driver, list); 270 271 seq_printf(seq, "%-32s %s\n", drv->name, drv->revision); 272 return 0; 273} 274 275static const struct seq_operations seq_capi_driver_ops = { 276 .start = capi_driver_start, 277 .next = capi_driver_next, 278 .stop = capi_driver_stop, 279 .show = capi_driver_show, 280}; 281 282static int 283seq_capi_driver_open(struct inode *inode, struct file *file) 284{ 285 int err; 286 err = seq_open(file, &seq_capi_driver_ops); 287 return err; 288} 289 290static const struct file_operations proc_driver_ops = { 291 .owner = THIS_MODULE, 292 .open = seq_capi_driver_open, 293 .read = seq_read, 294 .llseek = seq_lseek, 295 .release = seq_release, 296}; 297 298// --------------------------------------------------------------------------- 299 300void __init 301kcapi_proc_init(void) 302{ 303 proc_mkdir("capi", NULL); 304 proc_mkdir("capi/controllers", NULL); 305 proc_create("capi/controller", 0, NULL, &proc_controller_ops); 306 proc_create("capi/contrstats", 0, NULL, &proc_contrstats_ops); 307 proc_create("capi/applications", 0, NULL, &proc_applications_ops); 308 proc_create("capi/applstats", 0, NULL, &proc_applstats_ops); 309 proc_create("capi/driver", 0, NULL, &proc_driver_ops); 310} 311 312void __exit 313kcapi_proc_exit(void) 314{ 315 remove_proc_entry("capi/driver", NULL); 316 remove_proc_entry("capi/controller", NULL); 317 remove_proc_entry("capi/contrstats", NULL); 318 remove_proc_entry("capi/applications", NULL); 319 remove_proc_entry("capi/applstats", NULL); 320 remove_proc_entry("capi/controllers", NULL); 321 remove_proc_entry("capi", NULL); 322} 323