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