Path: blob/master/drivers/isdn/hardware/eicon/divasproc.c
15115 views
/* $Id: divasproc.c,v 1.19.4.3 2005/01/31 12:22:20 armin Exp $1*2* Low level driver for Eicon DIVA Server ISDN cards.3* /proc functions4*5* Copyright 2000-2003 by Armin Schindler ([email protected])6* Copyright 2000-2003 Cytronics & Melware ([email protected])7*8* This software may be used and distributed according to the terms9* of the GNU General Public License, incorporated herein by reference.10*/1112#include <linux/module.h>13#include <linux/kernel.h>14#include <linux/poll.h>15#include <linux/proc_fs.h>16#include <linux/seq_file.h>17#include <linux/list.h>18#include <asm/uaccess.h>1920#include "platform.h"21#include "debuglib.h"22#undef ID_MASK23#undef N_DATA24#include "pc.h"25#include "di_defs.h"26#include "divasync.h"27#include "di.h"28#include "io.h"29#include "xdi_msg.h"30#include "xdi_adapter.h"31#include "diva.h"32#include "diva_pci.h"333435extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];36extern void divas_get_version(char *);37extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf);3839/*********************************************************40** Functions for /proc interface / File operations41*********************************************************/4243static char *divas_proc_name = "divas";44static char *adapter_dir_name = "adapter";45static char *info_proc_name = "info";46static char *grp_opt_proc_name = "group_optimization";47static char *d_l1_down_proc_name = "dynamic_l1_down";4849/*50** "divas" entry51*/5253extern struct proc_dir_entry *proc_net_eicon;54static struct proc_dir_entry *divas_proc_entry = NULL;5556static ssize_t57divas_read(struct file *file, char __user *buf, size_t count, loff_t * off)58{59int len = 0;60int cadapter;61char tmpbuf[80];62char tmpser[16];6364if (*off)65return 0;6667divas_get_version(tmpbuf);68if (copy_to_user(buf + len, &tmpbuf, strlen(tmpbuf)))69return -EFAULT;70len += strlen(tmpbuf);7172for (cadapter = 0; cadapter < MAX_ADAPTER; cadapter++) {73if (IoAdapters[cadapter]) {74diva_get_vserial_number(IoAdapters[cadapter],75tmpser);76sprintf(tmpbuf,77"%2d: %-30s Serial:%-10s IRQ:%2d\n",78cadapter + 1,79IoAdapters[cadapter]->Properties.Name,80tmpser,81IoAdapters[cadapter]->irq_info.irq_nr);82if ((strlen(tmpbuf) + len) > count)83break;84if (copy_to_user85(buf + len, &tmpbuf,86strlen(tmpbuf))) return -EFAULT;87len += strlen(tmpbuf);88}89}9091*off += len;92return (len);93}9495static ssize_t96divas_write(struct file *file, const char __user *buf, size_t count, loff_t * off)97{98return (-ENODEV);99}100101static unsigned int divas_poll(struct file *file, poll_table * wait)102{103return (POLLERR);104}105106static int divas_open(struct inode *inode, struct file *file)107{108return nonseekable_open(inode, file);109}110111static int divas_close(struct inode *inode, struct file *file)112{113return (0);114}115116static const struct file_operations divas_fops = {117.owner = THIS_MODULE,118.llseek = no_llseek,119.read = divas_read,120.write = divas_write,121.poll = divas_poll,122.open = divas_open,123.release = divas_close124};125126int create_divas_proc(void)127{128divas_proc_entry = proc_create(divas_proc_name, S_IFREG | S_IRUGO,129proc_net_eicon, &divas_fops);130if (!divas_proc_entry)131return (0);132133return (1);134}135136void remove_divas_proc(void)137{138if (divas_proc_entry) {139remove_proc_entry(divas_proc_name, proc_net_eicon);140divas_proc_entry = NULL;141}142}143144static ssize_t grp_opt_proc_write(struct file *file, const char __user *buffer,145size_t count, loff_t *pos)146{147diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data;148PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];149150if ((count == 1) || (count == 2)) {151char c;152if (get_user(c, buffer))153return -EFAULT;154switch (c) {155case '0':156IoAdapter->capi_cfg.cfg_1 &=157~DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;158break;159case '1':160IoAdapter->capi_cfg.cfg_1 |=161DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;162break;163default:164return (-EINVAL);165}166return (count);167}168return (-EINVAL);169}170171static ssize_t d_l1_down_proc_write(struct file *file, const char __user *buffer,172size_t count, loff_t *pos)173{174diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data;175PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];176177if ((count == 1) || (count == 2)) {178char c;179if (get_user(c, buffer))180return -EFAULT;181switch (c) {182case '0':183IoAdapter->capi_cfg.cfg_1 &=184~DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;185break;186case '1':187IoAdapter->capi_cfg.cfg_1 |=188DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;189break;190default:191return (-EINVAL);192}193return (count);194}195return (-EINVAL);196}197198static int d_l1_down_proc_show(struct seq_file *m, void *v)199{200diva_os_xdi_adapter_t *a = m->private;201PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];202203seq_printf(m, "%s\n",204(IoAdapter->capi_cfg.205cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? "1" :206"0");207return 0;208}209210static int d_l1_down_proc_open(struct inode *inode, struct file *file)211{212return single_open(file, d_l1_down_proc_show, PDE(inode)->data);213}214215static const struct file_operations d_l1_down_proc_fops = {216.owner = THIS_MODULE,217.open = d_l1_down_proc_open,218.read = seq_read,219.llseek = seq_lseek,220.release = single_release,221.write = d_l1_down_proc_write,222};223224static int grp_opt_proc_show(struct seq_file *m, void *v)225{226diva_os_xdi_adapter_t *a = m->private;227PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];228229seq_printf(m, "%s\n",230(IoAdapter->capi_cfg.231cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON)232? "1" : "0");233return 0;234}235236static int grp_opt_proc_open(struct inode *inode, struct file *file)237{238return single_open(file, grp_opt_proc_show, PDE(inode)->data);239}240241static const struct file_operations grp_opt_proc_fops = {242.owner = THIS_MODULE,243.open = grp_opt_proc_open,244.read = seq_read,245.llseek = seq_lseek,246.release = single_release,247.write = grp_opt_proc_write,248};249250static ssize_t info_proc_write(struct file *file, const char __user *buffer,251size_t count, loff_t *pos)252{253diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data;254PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];255char c[4];256257if (count <= 4)258return -EINVAL;259260if (copy_from_user(c, buffer, 4))261return -EFAULT;262263/* this is for test purposes only */264if (!memcmp(c, "trap", 4)) {265(*(IoAdapter->os_trap_nfy_Fnc)) (IoAdapter, IoAdapter->ANum);266return (count);267}268return (-EINVAL);269}270271static int info_proc_show(struct seq_file *m, void *v)272{273int i = 0;274char *p;275char tmpser[16];276diva_os_xdi_adapter_t *a = m->private;277PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];278279seq_printf(m, "Name : %s\n", IoAdapter->Properties.Name);280seq_printf(m, "DSP state : %08x\n", a->dsp_mask);281seq_printf(m, "Channels : %02d\n", IoAdapter->Properties.Channels);282seq_printf(m, "E. max/used : %03d/%03d\n",283IoAdapter->e_max, IoAdapter->e_count);284diva_get_vserial_number(IoAdapter, tmpser);285seq_printf(m, "Serial : %s\n", tmpser);286seq_printf(m, "IRQ : %d\n", IoAdapter->irq_info.irq_nr);287seq_printf(m, "CardIndex : %d\n", a->CardIndex);288seq_printf(m, "CardOrdinal : %d\n", a->CardOrdinal);289seq_printf(m, "Controller : %d\n", a->controller);290seq_printf(m, "Bus-Type : %s\n",291(a->Bus ==292DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA" : "PCI");293seq_printf(m, "Port-Name : %s\n", a->port_name);294if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) {295seq_printf(m, "PCI-bus : %d\n", a->resources.pci.bus);296seq_printf(m, "PCI-func : %d\n", a->resources.pci.func);297for (i = 0; i < 8; i++) {298if (a->resources.pci.bar[i]) {299seq_printf(m,300"Mem / I/O %d : 0x%x / mapped : 0x%lx",301i, a->resources.pci.bar[i],302(unsigned long) a->resources.303pci.addr[i]);304if (a->resources.pci.length[i]) {305seq_printf(m,306" / length : %d",307a->resources.pci.308length[i]);309}310seq_putc(m, '\n');311}312}313}314if ((!a->xdi_adapter.port) &&315((!a->xdi_adapter.ram) ||316(!a->xdi_adapter.reset)317|| (!a->xdi_adapter.cfg))) {318if (!IoAdapter->irq_info.irq_nr) {319p = "slave";320} else {321p = "out of service";322}323} else if (a->xdi_adapter.trapped) {324p = "trapped";325} else if (a->xdi_adapter.Initialized) {326p = "active";327} else {328p = "ready";329}330seq_printf(m, "State : %s\n", p);331332return 0;333}334335static int info_proc_open(struct inode *inode, struct file *file)336{337return single_open(file, info_proc_show, PDE(inode)->data);338}339340static const struct file_operations info_proc_fops = {341.owner = THIS_MODULE,342.open = info_proc_open,343.read = seq_read,344.llseek = seq_lseek,345.release = single_release,346.write = info_proc_write,347};348349/*350** adapter proc init/de-init351*/352353/* --------------------------------------------------------------------------354Create adapter directory and files in proc file system355-------------------------------------------------------------------------- */356int create_adapter_proc(diva_os_xdi_adapter_t * a)357{358struct proc_dir_entry *de, *pe;359char tmp[16];360361sprintf(tmp, "%s%d", adapter_dir_name, a->controller);362if (!(de = proc_mkdir(tmp, proc_net_eicon)))363return (0);364a->proc_adapter_dir = (void *) de;365366pe = proc_create_data(info_proc_name, S_IRUGO | S_IWUSR, de,367&info_proc_fops, a);368if (!pe)369return (0);370a->proc_info = (void *) pe;371372pe = proc_create_data(grp_opt_proc_name, S_IRUGO | S_IWUSR, de,373&grp_opt_proc_fops, a);374if (pe)375a->proc_grp_opt = (void *) pe;376pe = proc_create_data(d_l1_down_proc_name, S_IRUGO | S_IWUSR, de,377&d_l1_down_proc_fops, a);378if (pe)379a->proc_d_l1_down = (void *) pe;380381DBG_TRC(("proc entry %s created", tmp));382383return (1);384}385386/* --------------------------------------------------------------------------387Remove adapter directory and files in proc file system388-------------------------------------------------------------------------- */389void remove_adapter_proc(diva_os_xdi_adapter_t * a)390{391char tmp[16];392393if (a->proc_adapter_dir) {394if (a->proc_d_l1_down) {395remove_proc_entry(d_l1_down_proc_name,396(struct proc_dir_entry *) a->proc_adapter_dir);397}398if (a->proc_grp_opt) {399remove_proc_entry(grp_opt_proc_name,400(struct proc_dir_entry *) a->proc_adapter_dir);401}402if (a->proc_info) {403remove_proc_entry(info_proc_name,404(struct proc_dir_entry *) a->proc_adapter_dir);405}406sprintf(tmp, "%s%d", adapter_dir_name, a->controller);407remove_proc_entry(tmp, proc_net_eicon);408DBG_TRC(("proc entry %s%d removed", adapter_dir_name,409a->controller));410}411}412413414