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 18static char * 19cardstate2str(unsigned short cardstate) 20{ 21 switch (cardstate) { 22 case CARD_DETECTED: return "detected"; 23 case CARD_LOADING: return "loading"; 24 case CARD_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{ 40 if (*pos < CAPI_MAXCONTR) 41 return &capi_cards[*pos]; 42 43 return NULL; 44} 45 46static void *controller_next(struct seq_file *seq, void *v, loff_t *pos) 47{ 48 ++*pos; 49 if (*pos < CAPI_MAXCONTR) 50 return &capi_cards[*pos]; 51 52 return NULL; 53} 54 55static void controller_stop(struct seq_file *seq, void *v) 56{ 57} 58 59static int controller_show(struct seq_file *seq, void *v) 60{ 61 struct capi_ctr *ctr = *(struct capi_ctr **) v; 62 63 if (!ctr) 64 return 0; 65 66 seq_printf(seq, "%d %-10s %-8s %-16s %s\n", 67 ctr->cnr, ctr->driver_name, 68 cardstate2str(ctr->cardstate), 69 ctr->name, 70 ctr->procinfo ? ctr->procinfo(ctr) : ""); 71 72 return 0; 73} 74 75static int contrstats_show(struct seq_file *seq, void *v) 76{ 77 struct capi_ctr *ctr = *(struct capi_ctr **) v; 78 79 if (!ctr) 80 return 0; 81 82 seq_printf(seq, "%d %lu %lu %lu %lu\n", 83 ctr->cnr, 84 ctr->nrecvctlpkt, 85 ctr->nrecvdatapkt, 86 ctr->nsentctlpkt, 87 ctr->nsentdatapkt); 88 89 return 0; 90} 91 92static struct seq_operations seq_controller_ops = { 93 .start = controller_start, 94 .next = controller_next, 95 .stop = controller_stop, 96 .show = controller_show, 97}; 98 99static struct seq_operations seq_contrstats_ops = { 100 .start = controller_start, 101 .next = controller_next, 102 .stop = controller_stop, 103 .show = contrstats_show, 104}; 105 106static int seq_controller_open(struct inode *inode, struct file *file) 107{ 108 return seq_open(file, &seq_controller_ops); 109} 110 111static int seq_contrstats_open(struct inode *inode, struct file *file) 112{ 113 return seq_open(file, &seq_contrstats_ops); 114} 115 116static const struct file_operations proc_controller_ops = { 117 .open = seq_controller_open, 118 .read = seq_read, 119 .llseek = seq_lseek, 120 .release = seq_release, 121}; 122 123static const struct file_operations proc_contrstats_ops = { 124 .open = seq_contrstats_open, 125 .read = seq_read, 126 .llseek = seq_lseek, 127 .release = seq_release, 128}; 129 130// /proc/capi/applications: 131// applid l3cnt dblkcnt dblklen #ncci recvqueuelen 132// /proc/capi/applstats: 133// applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt 134// --------------------------------------------------------------------------- 135 136static void * 137applications_start(struct seq_file *seq, loff_t *pos) 138{ 139 if (*pos < CAPI_MAXAPPL) 140 return &capi_applications[*pos]; 141 142 return NULL; 143} 144 145static void * 146applications_next(struct seq_file *seq, void *v, loff_t *pos) 147{ 148 ++*pos; 149 if (*pos < CAPI_MAXAPPL) 150 return &capi_applications[*pos]; 151 152 return NULL; 153} 154 155static void 156applications_stop(struct seq_file *seq, void *v) 157{ 158} 159 160static int 161applications_show(struct seq_file *seq, void *v) 162{ 163 struct capi20_appl *ap = *(struct capi20_appl **) v; 164 165 if (!ap) 166 return 0; 167 168 seq_printf(seq, "%u %d %d %d\n", 169 ap->applid, 170 ap->rparam.level3cnt, 171 ap->rparam.datablkcnt, 172 ap->rparam.datablklen); 173 174 return 0; 175} 176 177static int 178applstats_show(struct seq_file *seq, void *v) 179{ 180 struct capi20_appl *ap = *(struct capi20_appl **) v; 181 182 if (!ap) 183 return 0; 184 185 seq_printf(seq, "%u %lu %lu %lu %lu\n", 186 ap->applid, 187 ap->nrecvctlpkt, 188 ap->nrecvdatapkt, 189 ap->nsentctlpkt, 190 ap->nsentdatapkt); 191 192 return 0; 193} 194 195static struct seq_operations seq_applications_ops = { 196 .start = applications_start, 197 .next = applications_next, 198 .stop = applications_stop, 199 .show = applications_show, 200}; 201 202static struct seq_operations seq_applstats_ops = { 203 .start = applications_start, 204 .next = applications_next, 205 .stop = applications_stop, 206 .show = applstats_show, 207}; 208 209static int 210seq_applications_open(struct inode *inode, struct file *file) 211{ 212 return seq_open(file, &seq_applications_ops); 213} 214 215static int 216seq_applstats_open(struct inode *inode, struct file *file) 217{ 218 return seq_open(file, &seq_applstats_ops); 219} 220 221static const struct file_operations proc_applications_ops = { 222 .open = seq_applications_open, 223 .read = seq_read, 224 .llseek = seq_lseek, 225 .release = seq_release, 226}; 227 228static const struct file_operations proc_applstats_ops = { 229 .open = seq_applstats_open, 230 .read = seq_read, 231 .llseek = seq_lseek, 232 .release = seq_release, 233}; 234 235static void 236create_seq_entry(char *name, mode_t mode, const struct file_operations *f) 237{ 238 struct proc_dir_entry *entry; 239 entry = create_proc_entry(name, mode, NULL); 240 if (entry) 241 entry->proc_fops = f; 242} 243 244// --------------------------------------------------------------------------- 245 246 247static __inline__ struct capi_driver *capi_driver_get_idx(loff_t pos) 248{ 249 struct capi_driver *drv = NULL; 250 struct list_head *l; 251 loff_t i; 252 253 i = 0; 254 list_for_each(l, &capi_drivers) { 255 drv = list_entry(l, struct capi_driver, list); 256 if (i++ == pos) 257 return drv; 258 } 259 return NULL; 260} 261 262static void *capi_driver_start(struct seq_file *seq, loff_t *pos) 263{ 264 struct capi_driver *drv; 265 read_lock(&capi_drivers_list_lock); 266 drv = capi_driver_get_idx(*pos); 267 return drv; 268} 269 270static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) 271{ 272 struct capi_driver *drv = (struct capi_driver *)v; 273 ++*pos; 274 if (drv->list.next == &capi_drivers) return NULL; 275 return list_entry(drv->list.next, struct capi_driver, list); 276} 277 278static void capi_driver_stop(struct seq_file *seq, void *v) 279{ 280 read_unlock(&capi_drivers_list_lock); 281} 282 283static int capi_driver_show(struct seq_file *seq, void *v) 284{ 285 struct capi_driver *drv = (struct capi_driver *)v; 286 seq_printf(seq, "%-32s %s\n", drv->name, drv->revision); 287 return 0; 288} 289 290static struct seq_operations seq_capi_driver_ops = { 291 .start = capi_driver_start, 292 .next = capi_driver_next, 293 .stop = capi_driver_stop, 294 .show = capi_driver_show, 295}; 296 297static int 298seq_capi_driver_open(struct inode *inode, struct file *file) 299{ 300 int err; 301 err = seq_open(file, &seq_capi_driver_ops); 302 return err; 303} 304 305static const struct file_operations proc_driver_ops = { 306 .open = seq_capi_driver_open, 307 .read = seq_read, 308 .llseek = seq_lseek, 309 .release = seq_release, 310}; 311 312// --------------------------------------------------------------------------- 313 314void __init 315kcapi_proc_init(void) 316{ 317 proc_mkdir("capi", NULL); 318 proc_mkdir("capi/controllers", NULL); 319 create_seq_entry("capi/controller", 0, &proc_controller_ops); 320 create_seq_entry("capi/contrstats", 0, &proc_contrstats_ops); 321 create_seq_entry("capi/applications", 0, &proc_applications_ops); 322 create_seq_entry("capi/applstats", 0, &proc_applstats_ops); 323 create_seq_entry("capi/driver", 0, &proc_driver_ops); 324} 325 326void __exit 327kcapi_proc_exit(void) 328{ 329 remove_proc_entry("capi/driver", NULL); 330 remove_proc_entry("capi/controller", NULL); 331 remove_proc_entry("capi/contrstats", NULL); 332 remove_proc_entry("capi/applications", NULL); 333 remove_proc_entry("capi/applstats", NULL); 334 remove_proc_entry("capi/controllers", NULL); 335 remove_proc_entry("capi", NULL); 336} 337