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 18 static char * 19 cardstate2str(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 38 static 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 46 static 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 55 static void controller_stop(struct seq_file *seq, void *v) 56 { 57 } 58 59 static 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 75 static 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 92 static struct seq_operations seq_controller_ops = { 93 .start = controller_start, 94 .next = controller_next, 95 .stop = controller_stop, 96 .show = controller_show, 97 }; 98 99 static struct seq_operations seq_contrstats_ops = { 100 .start = controller_start, 101 .next = controller_next, 102 .stop = controller_stop, 103 .show = contrstats_show, 104 }; 105 106 static int seq_controller_open(struct inode *inode, struct file *file) 107 { 108 return seq_open(file, &seq_controller_ops); 109 } 110 111 static int seq_contrstats_open(struct inode *inode, struct file *file) 112 { 113 return seq_open(file, &seq_contrstats_ops); 114 } 115 116 static 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 123 static 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 136 static void * 137 applications_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 145 static void * 146 applications_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 155 static void 156 applications_stop(struct seq_file *seq, void *v) 157 { 158 } 159 160 static int 161 applications_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 177 static int 178 applstats_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 195 static struct seq_operations seq_applications_ops = { 196 .start = applications_start, 197 .next = applications_next, 198 .stop = applications_stop, 199 .show = applications_show, 200 }; 201 202 static struct seq_operations seq_applstats_ops = { 203 .start = applications_start, 204 .next = applications_next, 205 .stop = applications_stop, 206 .show = applstats_show, 207 }; 208 209 static int 210 seq_applications_open(struct inode *inode, struct file *file) 211 { 212 return seq_open(file, &seq_applications_ops); 213 } 214 215 static int 216 seq_applstats_open(struct inode *inode, struct file *file) 217 { 218 return seq_open(file, &seq_applstats_ops); 219 } 220 221 static 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 228 static 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 235 static void 236 create_seq_entry(char *name, mode_t mode, 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 247 static __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 262 static 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 270 static 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 278 static void capi_driver_stop(struct seq_file *seq, void *v) 279 { 280 read_unlock(&capi_drivers_list_lock); 281 } 282 283 static 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 290 static 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 297 static int 298 seq_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 305 static 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 314 void __init 315 kcapi_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 326 void __exit 327 kcapi_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