162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Kernel CAPI 2.0 Module - /proc/capi handling
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright 1999 by Carsten Paeth <calle@calle.de>
562306a36Sopenharmony_ci * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * This software may be used and distributed according to the terms
862306a36Sopenharmony_ci * of the GNU General Public License, incorporated herein by reference.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "kcapi.h"
1462306a36Sopenharmony_ci#include <linux/proc_fs.h>
1562306a36Sopenharmony_ci#include <linux/seq_file.h>
1662306a36Sopenharmony_ci#include <linux/init.h>
1762306a36Sopenharmony_ci#include <linux/export.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic char *state2str(unsigned short state)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	switch (state) {
2262306a36Sopenharmony_ci	case CAPI_CTR_DETECTED:	return "detected";
2362306a36Sopenharmony_ci	case CAPI_CTR_LOADING:	return "loading";
2462306a36Sopenharmony_ci	case CAPI_CTR_RUNNING:	return "running";
2562306a36Sopenharmony_ci	default:	        return "???";
2662306a36Sopenharmony_ci	}
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci// /proc/capi
3062306a36Sopenharmony_ci// ===========================================================================
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci// /proc/capi/controller:
3362306a36Sopenharmony_ci//      cnr driver cardstate name driverinfo
3462306a36Sopenharmony_ci// /proc/capi/contrstats:
3562306a36Sopenharmony_ci//      cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
3662306a36Sopenharmony_ci// ---------------------------------------------------------------------------
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic void *controller_start(struct seq_file *seq, loff_t *pos)
3962306a36Sopenharmony_ci	__acquires(capi_controller_lock)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	mutex_lock(&capi_controller_lock);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	if (*pos < CAPI_MAXCONTR)
4462306a36Sopenharmony_ci		return &capi_controller[*pos];
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	return NULL;
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic void *controller_next(struct seq_file *seq, void *v, loff_t *pos)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	++*pos;
5262306a36Sopenharmony_ci	if (*pos < CAPI_MAXCONTR)
5362306a36Sopenharmony_ci		return &capi_controller[*pos];
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	return NULL;
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic void controller_stop(struct seq_file *seq, void *v)
5962306a36Sopenharmony_ci	__releases(capi_controller_lock)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	mutex_unlock(&capi_controller_lock);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic int controller_show(struct seq_file *seq, void *v)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	struct capi_ctr *ctr = *(struct capi_ctr **) v;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	if (!ctr)
6962306a36Sopenharmony_ci		return 0;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	seq_printf(seq, "%d %-10s %-8s %-16s %s\n",
7262306a36Sopenharmony_ci		   ctr->cnr, ctr->driver_name,
7362306a36Sopenharmony_ci		   state2str(ctr->state),
7462306a36Sopenharmony_ci		   ctr->name,
7562306a36Sopenharmony_ci		   ctr->procinfo ?  ctr->procinfo(ctr) : "");
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	return 0;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic int contrstats_show(struct seq_file *seq, void *v)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	struct capi_ctr *ctr = *(struct capi_ctr **) v;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	if (!ctr)
8562306a36Sopenharmony_ci		return 0;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	seq_printf(seq, "%d %lu %lu %lu %lu\n",
8862306a36Sopenharmony_ci		   ctr->cnr,
8962306a36Sopenharmony_ci		   ctr->nrecvctlpkt,
9062306a36Sopenharmony_ci		   ctr->nrecvdatapkt,
9162306a36Sopenharmony_ci		   ctr->nsentctlpkt,
9262306a36Sopenharmony_ci		   ctr->nsentdatapkt);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	return 0;
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistatic const struct seq_operations seq_controller_ops = {
9862306a36Sopenharmony_ci	.start	= controller_start,
9962306a36Sopenharmony_ci	.next	= controller_next,
10062306a36Sopenharmony_ci	.stop	= controller_stop,
10162306a36Sopenharmony_ci	.show	= controller_show,
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic const struct seq_operations seq_contrstats_ops = {
10562306a36Sopenharmony_ci	.start	= controller_start,
10662306a36Sopenharmony_ci	.next	= controller_next,
10762306a36Sopenharmony_ci	.stop	= controller_stop,
10862306a36Sopenharmony_ci	.show	= contrstats_show,
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci// /proc/capi/applications:
11262306a36Sopenharmony_ci//      applid l3cnt dblkcnt dblklen #ncci recvqueuelen
11362306a36Sopenharmony_ci// /proc/capi/applstats:
11462306a36Sopenharmony_ci//      applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
11562306a36Sopenharmony_ci// ---------------------------------------------------------------------------
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic void *applications_start(struct seq_file *seq, loff_t *pos)
11862306a36Sopenharmony_ci	__acquires(capi_controller_lock)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	mutex_lock(&capi_controller_lock);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	if (*pos < CAPI_MAXAPPL)
12362306a36Sopenharmony_ci		return &capi_applications[*pos];
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	return NULL;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic void *
12962306a36Sopenharmony_ciapplications_next(struct seq_file *seq, void *v, loff_t *pos)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	++*pos;
13262306a36Sopenharmony_ci	if (*pos < CAPI_MAXAPPL)
13362306a36Sopenharmony_ci		return &capi_applications[*pos];
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	return NULL;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic void applications_stop(struct seq_file *seq, void *v)
13962306a36Sopenharmony_ci	__releases(capi_controller_lock)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	mutex_unlock(&capi_controller_lock);
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic int
14562306a36Sopenharmony_ciapplications_show(struct seq_file *seq, void *v)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	struct capi20_appl *ap = *(struct capi20_appl **) v;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	if (!ap)
15062306a36Sopenharmony_ci		return 0;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	seq_printf(seq, "%u %d %d %d\n",
15362306a36Sopenharmony_ci		   ap->applid,
15462306a36Sopenharmony_ci		   ap->rparam.level3cnt,
15562306a36Sopenharmony_ci		   ap->rparam.datablkcnt,
15662306a36Sopenharmony_ci		   ap->rparam.datablklen);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	return 0;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic int
16262306a36Sopenharmony_ciapplstats_show(struct seq_file *seq, void *v)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct capi20_appl *ap = *(struct capi20_appl **) v;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	if (!ap)
16762306a36Sopenharmony_ci		return 0;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	seq_printf(seq, "%u %lu %lu %lu %lu\n",
17062306a36Sopenharmony_ci		   ap->applid,
17162306a36Sopenharmony_ci		   ap->nrecvctlpkt,
17262306a36Sopenharmony_ci		   ap->nrecvdatapkt,
17362306a36Sopenharmony_ci		   ap->nsentctlpkt,
17462306a36Sopenharmony_ci		   ap->nsentdatapkt);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	return 0;
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_cistatic const struct seq_operations seq_applications_ops = {
18062306a36Sopenharmony_ci	.start	= applications_start,
18162306a36Sopenharmony_ci	.next	= applications_next,
18262306a36Sopenharmony_ci	.stop	= applications_stop,
18362306a36Sopenharmony_ci	.show	= applications_show,
18462306a36Sopenharmony_ci};
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic const struct seq_operations seq_applstats_ops = {
18762306a36Sopenharmony_ci	.start	= applications_start,
18862306a36Sopenharmony_ci	.next	= applications_next,
18962306a36Sopenharmony_ci	.stop	= applications_stop,
19062306a36Sopenharmony_ci	.show	= applstats_show,
19162306a36Sopenharmony_ci};
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci// ---------------------------------------------------------------------------
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci/* /proc/capi/drivers is always empty */
19662306a36Sopenharmony_cistatic ssize_t empty_read(struct file *file, char __user *buf,
19762306a36Sopenharmony_ci			  size_t size, loff_t *off)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	return 0;
20062306a36Sopenharmony_ci}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_cistatic const struct proc_ops empty_proc_ops = {
20362306a36Sopenharmony_ci	.proc_read	= empty_read,
20462306a36Sopenharmony_ci	.proc_lseek	= default_llseek,
20562306a36Sopenharmony_ci};
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci// ---------------------------------------------------------------------------
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_civoid __init
21062306a36Sopenharmony_cikcapi_proc_init(void)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	proc_mkdir("capi",             NULL);
21362306a36Sopenharmony_ci	proc_mkdir("capi/controllers", NULL);
21462306a36Sopenharmony_ci	proc_create_seq("capi/controller",   0, NULL, &seq_controller_ops);
21562306a36Sopenharmony_ci	proc_create_seq("capi/contrstats",   0, NULL, &seq_contrstats_ops);
21662306a36Sopenharmony_ci	proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops);
21762306a36Sopenharmony_ci	proc_create_seq("capi/applstats",    0, NULL, &seq_applstats_ops);
21862306a36Sopenharmony_ci	proc_create("capi/driver",           0, NULL, &empty_proc_ops);
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_civoid
22262306a36Sopenharmony_cikcapi_proc_exit(void)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	remove_proc_entry("capi/driver",       NULL);
22562306a36Sopenharmony_ci	remove_proc_entry("capi/controller",   NULL);
22662306a36Sopenharmony_ci	remove_proc_entry("capi/contrstats",   NULL);
22762306a36Sopenharmony_ci	remove_proc_entry("capi/applications", NULL);
22862306a36Sopenharmony_ci	remove_proc_entry("capi/applstats",    NULL);
22962306a36Sopenharmony_ci	remove_proc_entry("capi/controllers",  NULL);
23062306a36Sopenharmony_ci	remove_proc_entry("capi",              NULL);
23162306a36Sopenharmony_ci}
232