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 19 static 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 38 static 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 49 static 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 58 static void controller_stop(struct seq_file *seq, void *v) 59 __releases(capi_controller_lock) 60 { 61 mutex_unlock(&capi_controller_lock); 62 } 63 64 static 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 80 static 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 97 static 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 104 static 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 recvqueuelen 113 // /proc/capi/applstats: 114 // applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt 115 // --------------------------------------------------------------------------- 116 117 static 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 128 static void * 129 applications_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 138 static void applications_stop(struct seq_file *seq, void *v) 139 __releases(capi_controller_lock) 140 { 141 mutex_unlock(&capi_controller_lock); 142 } 143 144 static int 145 applications_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 161 static int 162 applstats_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 179 static 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 186 static 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 */ 196 static ssize_t empty_read(struct file *file, char __user *buf, 197 size_t size, loff_t *off) 198 { 199 return 0; 200 } 201 202 static const struct proc_ops empty_proc_ops = { 203 .proc_read = empty_read, 204 .proc_lseek = default_llseek, 205 }; 206 207 // --------------------------------------------------------------------------- 208 209 void __init 210 kcapi_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 221 void 222 kcapi_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