18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Kernel CAPI 2.0 Module - /proc/capi handling 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 1999 by Carsten Paeth <calle@calle.de> 58c2ecf20Sopenharmony_ci * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This software may be used and distributed according to the terms 88c2ecf20Sopenharmony_ci * of the GNU General Public License, incorporated herein by reference. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "kcapi.h" 148c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 158c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 168c2ecf20Sopenharmony_ci#include <linux/init.h> 178c2ecf20Sopenharmony_ci#include <linux/export.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic char *state2str(unsigned short state) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci switch (state) { 228c2ecf20Sopenharmony_ci case CAPI_CTR_DETECTED: return "detected"; 238c2ecf20Sopenharmony_ci case CAPI_CTR_LOADING: return "loading"; 248c2ecf20Sopenharmony_ci case CAPI_CTR_RUNNING: return "running"; 258c2ecf20Sopenharmony_ci default: return "???"; 268c2ecf20Sopenharmony_ci } 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci// /proc/capi 308c2ecf20Sopenharmony_ci// =========================================================================== 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci// /proc/capi/controller: 338c2ecf20Sopenharmony_ci// cnr driver cardstate name driverinfo 348c2ecf20Sopenharmony_ci// /proc/capi/contrstats: 358c2ecf20Sopenharmony_ci// cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt 368c2ecf20Sopenharmony_ci// --------------------------------------------------------------------------- 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic void *controller_start(struct seq_file *seq, loff_t *pos) 398c2ecf20Sopenharmony_ci __acquires(capi_controller_lock) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci mutex_lock(&capi_controller_lock); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci if (*pos < CAPI_MAXCONTR) 448c2ecf20Sopenharmony_ci return &capi_controller[*pos]; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci return NULL; 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic void *controller_next(struct seq_file *seq, void *v, loff_t *pos) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci ++*pos; 528c2ecf20Sopenharmony_ci if (*pos < CAPI_MAXCONTR) 538c2ecf20Sopenharmony_ci return &capi_controller[*pos]; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return NULL; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic void controller_stop(struct seq_file *seq, void *v) 598c2ecf20Sopenharmony_ci __releases(capi_controller_lock) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci mutex_unlock(&capi_controller_lock); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic int controller_show(struct seq_file *seq, void *v) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci struct capi_ctr *ctr = *(struct capi_ctr **) v; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (!ctr) 698c2ecf20Sopenharmony_ci return 0; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci seq_printf(seq, "%d %-10s %-8s %-16s %s\n", 728c2ecf20Sopenharmony_ci ctr->cnr, ctr->driver_name, 738c2ecf20Sopenharmony_ci state2str(ctr->state), 748c2ecf20Sopenharmony_ci ctr->name, 758c2ecf20Sopenharmony_ci ctr->procinfo ? ctr->procinfo(ctr) : ""); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci return 0; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic int contrstats_show(struct seq_file *seq, void *v) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci struct capi_ctr *ctr = *(struct capi_ctr **) v; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (!ctr) 858c2ecf20Sopenharmony_ci return 0; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci seq_printf(seq, "%d %lu %lu %lu %lu\n", 888c2ecf20Sopenharmony_ci ctr->cnr, 898c2ecf20Sopenharmony_ci ctr->nrecvctlpkt, 908c2ecf20Sopenharmony_ci ctr->nrecvdatapkt, 918c2ecf20Sopenharmony_ci ctr->nsentctlpkt, 928c2ecf20Sopenharmony_ci ctr->nsentdatapkt); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci return 0; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic const struct seq_operations seq_controller_ops = { 988c2ecf20Sopenharmony_ci .start = controller_start, 998c2ecf20Sopenharmony_ci .next = controller_next, 1008c2ecf20Sopenharmony_ci .stop = controller_stop, 1018c2ecf20Sopenharmony_ci .show = controller_show, 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic const struct seq_operations seq_contrstats_ops = { 1058c2ecf20Sopenharmony_ci .start = controller_start, 1068c2ecf20Sopenharmony_ci .next = controller_next, 1078c2ecf20Sopenharmony_ci .stop = controller_stop, 1088c2ecf20Sopenharmony_ci .show = contrstats_show, 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci// /proc/capi/applications: 1128c2ecf20Sopenharmony_ci// applid l3cnt dblkcnt dblklen #ncci recvqueuelen 1138c2ecf20Sopenharmony_ci// /proc/capi/applstats: 1148c2ecf20Sopenharmony_ci// applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt 1158c2ecf20Sopenharmony_ci// --------------------------------------------------------------------------- 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic void *applications_start(struct seq_file *seq, loff_t *pos) 1188c2ecf20Sopenharmony_ci __acquires(capi_controller_lock) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci mutex_lock(&capi_controller_lock); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci if (*pos < CAPI_MAXAPPL) 1238c2ecf20Sopenharmony_ci return &capi_applications[*pos]; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci return NULL; 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic void * 1298c2ecf20Sopenharmony_ciapplications_next(struct seq_file *seq, void *v, loff_t *pos) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci ++*pos; 1328c2ecf20Sopenharmony_ci if (*pos < CAPI_MAXAPPL) 1338c2ecf20Sopenharmony_ci return &capi_applications[*pos]; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci return NULL; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic void applications_stop(struct seq_file *seq, void *v) 1398c2ecf20Sopenharmony_ci __releases(capi_controller_lock) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci mutex_unlock(&capi_controller_lock); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic int 1458c2ecf20Sopenharmony_ciapplications_show(struct seq_file *seq, void *v) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci struct capi20_appl *ap = *(struct capi20_appl **) v; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (!ap) 1508c2ecf20Sopenharmony_ci return 0; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci seq_printf(seq, "%u %d %d %d\n", 1538c2ecf20Sopenharmony_ci ap->applid, 1548c2ecf20Sopenharmony_ci ap->rparam.level3cnt, 1558c2ecf20Sopenharmony_ci ap->rparam.datablkcnt, 1568c2ecf20Sopenharmony_ci ap->rparam.datablklen); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic int 1628c2ecf20Sopenharmony_ciapplstats_show(struct seq_file *seq, void *v) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci struct capi20_appl *ap = *(struct capi20_appl **) v; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci if (!ap) 1678c2ecf20Sopenharmony_ci return 0; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci seq_printf(seq, "%u %lu %lu %lu %lu\n", 1708c2ecf20Sopenharmony_ci ap->applid, 1718c2ecf20Sopenharmony_ci ap->nrecvctlpkt, 1728c2ecf20Sopenharmony_ci ap->nrecvdatapkt, 1738c2ecf20Sopenharmony_ci ap->nsentctlpkt, 1748c2ecf20Sopenharmony_ci ap->nsentdatapkt); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci return 0; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic const struct seq_operations seq_applications_ops = { 1808c2ecf20Sopenharmony_ci .start = applications_start, 1818c2ecf20Sopenharmony_ci .next = applications_next, 1828c2ecf20Sopenharmony_ci .stop = applications_stop, 1838c2ecf20Sopenharmony_ci .show = applications_show, 1848c2ecf20Sopenharmony_ci}; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic const struct seq_operations seq_applstats_ops = { 1878c2ecf20Sopenharmony_ci .start = applications_start, 1888c2ecf20Sopenharmony_ci .next = applications_next, 1898c2ecf20Sopenharmony_ci .stop = applications_stop, 1908c2ecf20Sopenharmony_ci .show = applstats_show, 1918c2ecf20Sopenharmony_ci}; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci// --------------------------------------------------------------------------- 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/* /proc/capi/drivers is always empty */ 1968c2ecf20Sopenharmony_cistatic ssize_t empty_read(struct file *file, char __user *buf, 1978c2ecf20Sopenharmony_ci size_t size, loff_t *off) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci return 0; 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic const struct proc_ops empty_proc_ops = { 2038c2ecf20Sopenharmony_ci .proc_read = empty_read, 2048c2ecf20Sopenharmony_ci}; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci// --------------------------------------------------------------------------- 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_civoid __init 2098c2ecf20Sopenharmony_cikcapi_proc_init(void) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci proc_mkdir("capi", NULL); 2128c2ecf20Sopenharmony_ci proc_mkdir("capi/controllers", NULL); 2138c2ecf20Sopenharmony_ci proc_create_seq("capi/controller", 0, NULL, &seq_controller_ops); 2148c2ecf20Sopenharmony_ci proc_create_seq("capi/contrstats", 0, NULL, &seq_contrstats_ops); 2158c2ecf20Sopenharmony_ci proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops); 2168c2ecf20Sopenharmony_ci proc_create_seq("capi/applstats", 0, NULL, &seq_applstats_ops); 2178c2ecf20Sopenharmony_ci proc_create("capi/driver", 0, NULL, &empty_proc_ops); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_civoid 2218c2ecf20Sopenharmony_cikcapi_proc_exit(void) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci remove_proc_entry("capi/driver", NULL); 2248c2ecf20Sopenharmony_ci remove_proc_entry("capi/controller", NULL); 2258c2ecf20Sopenharmony_ci remove_proc_entry("capi/contrstats", NULL); 2268c2ecf20Sopenharmony_ci remove_proc_entry("capi/applications", NULL); 2278c2ecf20Sopenharmony_ci remove_proc_entry("capi/applstats", NULL); 2288c2ecf20Sopenharmony_ci remove_proc_entry("capi/controllers", NULL); 2298c2ecf20Sopenharmony_ci remove_proc_entry("capi", NULL); 2308c2ecf20Sopenharmony_ci} 231