linux/drivers/isdn/hardware/eicon/divasproc.c
<<
>>
Prefs
   1/* $Id: divasproc.c,v 1.19.4.3 2005/01/31 12:22:20 armin Exp $
   2 *
   3 * Low level driver for Eicon DIVA Server ISDN cards.
   4 * /proc functions
   5 *
   6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
   7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
   8 *
   9 * This software may be used and distributed according to the terms
  10 * of the GNU General Public License, incorporated herein by reference.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/kernel.h>
  15#include <linux/poll.h>
  16#include <linux/proc_fs.h>
  17#include <linux/list.h>
  18#include <asm/uaccess.h>
  19
  20#include "platform.h"
  21#include "debuglib.h"
  22#undef ID_MASK
  23#undef N_DATA
  24#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"
  33
  34
  35extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
  36extern void divas_get_version(char *);
  37extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf);
  38
  39/*********************************************************
  40 ** Functions for /proc interface / File operations
  41 *********************************************************/
  42
  43static 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";
  48
  49/*
  50** "divas" entry
  51*/
  52
  53extern struct proc_dir_entry *proc_net_eicon;
  54static struct proc_dir_entry *divas_proc_entry = NULL;
  55
  56static ssize_t
  57divas_read(struct file *file, char __user *buf, size_t count, loff_t * off)
  58{
  59        int len = 0;
  60        int cadapter;
  61        char tmpbuf[80];
  62        char tmpser[16];
  63
  64        if (*off)
  65                return 0;
  66
  67        divas_get_version(tmpbuf);
  68        if (copy_to_user(buf + len, &tmpbuf, strlen(tmpbuf)))
  69                return -EFAULT;
  70        len += strlen(tmpbuf);
  71
  72        for (cadapter = 0; cadapter < MAX_ADAPTER; cadapter++) {
  73                if (IoAdapters[cadapter]) {
  74                        diva_get_vserial_number(IoAdapters[cadapter],
  75                                                tmpser);
  76                        sprintf(tmpbuf,
  77                                "%2d: %-30s Serial:%-10s IRQ:%2d\n",
  78                                cadapter + 1,
  79                                IoAdapters[cadapter]->Properties.Name,
  80                                tmpser,
  81                                IoAdapters[cadapter]->irq_info.irq_nr);
  82                        if ((strlen(tmpbuf) + len) > count)
  83                                break;
  84                        if (copy_to_user
  85                            (buf + len, &tmpbuf,
  86                             strlen(tmpbuf))) return -EFAULT;
  87                        len += strlen(tmpbuf);
  88                }
  89        }
  90
  91        *off += len;
  92        return (len);
  93}
  94
  95static ssize_t
  96divas_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
  97{
  98        return (-ENODEV);
  99}
 100
 101static unsigned int divas_poll(struct file *file, poll_table * wait)
 102{
 103        return (POLLERR);
 104}
 105
 106static int divas_open(struct inode *inode, struct file *file)
 107{
 108        return nonseekable_open(inode, file);
 109}
 110
 111static int divas_close(struct inode *inode, struct file *file)
 112{
 113        return (0);
 114}
 115
 116static 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_close
 124};
 125
 126int create_divas_proc(void)
 127{
 128        divas_proc_entry = proc_create(divas_proc_name, S_IFREG | S_IRUGO,
 129                                        proc_net_eicon, &divas_fops);
 130        if (!divas_proc_entry)
 131                return (0);
 132
 133        return (1);
 134}
 135
 136void remove_divas_proc(void)
 137{
 138        if (divas_proc_entry) {
 139                remove_proc_entry(divas_proc_name, proc_net_eicon);
 140                divas_proc_entry = NULL;
 141        }
 142}
 143
 144/*
 145** write group_optimization 
 146*/
 147static int
 148write_grp_opt(struct file *file, const char __user *buffer, unsigned long count,
 149              void *data)
 150{
 151        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
 152        PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 153
 154        if ((count == 1) || (count == 2)) {
 155                char c;
 156                if (get_user(c, buffer))
 157                        return -EFAULT;
 158                switch (c) {
 159                case '0':
 160                        IoAdapter->capi_cfg.cfg_1 &=
 161                            ~DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;
 162                        break;
 163                case '1':
 164                        IoAdapter->capi_cfg.cfg_1 |=
 165                            DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;
 166                        break;
 167                default:
 168                        return (-EINVAL);
 169                }
 170                return (count);
 171        }
 172        return (-EINVAL);
 173}
 174
 175/*
 176** write dynamic_l1_down
 177*/
 178static int
 179write_d_l1_down(struct file *file, const char __user *buffer, unsigned long count,
 180                void *data)
 181{
 182        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
 183        PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 184
 185        if ((count == 1) || (count == 2)) {
 186                char c;
 187                if (get_user(c, buffer))
 188                        return -EFAULT;
 189                switch (c) {
 190                case '0':
 191                        IoAdapter->capi_cfg.cfg_1 &=
 192                            ~DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;
 193                        break;
 194                case '1':
 195                        IoAdapter->capi_cfg.cfg_1 |=
 196                            DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;
 197                        break;
 198                default:
 199                        return (-EINVAL);
 200                }
 201                return (count);
 202        }
 203        return (-EINVAL);
 204}
 205
 206
 207/*
 208** read dynamic_l1_down 
 209*/
 210static int
 211read_d_l1_down(char *page, char **start, off_t off, int count, int *eof,
 212               void *data)
 213{
 214        int len = 0;
 215        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
 216        PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 217
 218        len += sprintf(page + len, "%s\n",
 219                       (IoAdapter->capi_cfg.
 220                        cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? "1" :
 221                       "0");
 222
 223        if (off + count >= len)
 224                *eof = 1;
 225        if (len < off)
 226                return 0;
 227        *start = page + off;
 228        return ((count < len - off) ? count : len - off);
 229}
 230
 231/*
 232** read group_optimization
 233*/
 234static int
 235read_grp_opt(char *page, char **start, off_t off, int count, int *eof,
 236             void *data)
 237{
 238        int len = 0;
 239        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
 240        PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 241
 242        len += sprintf(page + len, "%s\n",
 243                       (IoAdapter->capi_cfg.
 244                        cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON)
 245                       ? "1" : "0");
 246
 247        if (off + count >= len)
 248                *eof = 1;
 249        if (len < off)
 250                return 0;
 251        *start = page + off;
 252        return ((count < len - off) ? count : len - off);
 253}
 254
 255/*
 256** info write
 257*/
 258static int
 259info_write(struct file *file, const char __user *buffer, unsigned long count,
 260           void *data)
 261{
 262        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
 263        PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 264        char c[4];
 265
 266        if (count <= 4)
 267                return -EINVAL;
 268
 269        if (copy_from_user(c, buffer, 4))
 270                return -EFAULT;
 271
 272        /* this is for test purposes only */
 273        if (!memcmp(c, "trap", 4)) {
 274                (*(IoAdapter->os_trap_nfy_Fnc)) (IoAdapter, IoAdapter->ANum);
 275                return (count);
 276        }
 277        return (-EINVAL);
 278}
 279
 280/*
 281** info read
 282*/
 283static int
 284info_read(char *page, char **start, off_t off, int count, int *eof,
 285          void *data)
 286{
 287        int i = 0;
 288        int len = 0;
 289        char *p;
 290        char tmpser[16];
 291        diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
 292        PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
 293
 294        len +=
 295            sprintf(page + len, "Name        : %s\n",
 296                    IoAdapter->Properties.Name);
 297        len += sprintf(page + len, "DSP state   : %08x\n", a->dsp_mask);
 298        len += sprintf(page + len, "Channels    : %02d\n",
 299                       IoAdapter->Properties.Channels);
 300        len += sprintf(page + len, "E. max/used : %03d/%03d\n",
 301                       IoAdapter->e_max, IoAdapter->e_count);
 302        diva_get_vserial_number(IoAdapter, tmpser);
 303        len += sprintf(page + len, "Serial      : %s\n", tmpser);
 304        len +=
 305            sprintf(page + len, "IRQ         : %d\n",
 306                    IoAdapter->irq_info.irq_nr);
 307        len += sprintf(page + len, "CardIndex   : %d\n", a->CardIndex);
 308        len += sprintf(page + len, "CardOrdinal : %d\n", a->CardOrdinal);
 309        len += sprintf(page + len, "Controller  : %d\n", a->controller);
 310        len += sprintf(page + len, "Bus-Type    : %s\n",
 311                       (a->Bus ==
 312                        DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA" : "PCI");
 313        len += sprintf(page + len, "Port-Name   : %s\n", a->port_name);
 314        if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) {
 315                len +=
 316                    sprintf(page + len, "PCI-bus     : %d\n",
 317                            a->resources.pci.bus);
 318                len +=
 319                    sprintf(page + len, "PCI-func    : %d\n",
 320                            a->resources.pci.func);
 321                for (i = 0; i < 8; i++) {
 322                        if (a->resources.pci.bar[i]) {
 323                                len +=
 324                                    sprintf(page + len,
 325                                            "Mem / I/O %d : 0x%x / mapped : 0x%lx",
 326                                            i, a->resources.pci.bar[i],
 327                                            (unsigned long) a->resources.
 328                                            pci.addr[i]);
 329                                if (a->resources.pci.length[i]) {
 330                                        len +=
 331                                            sprintf(page + len,
 332                                                    " / length : %d",
 333                                                    a->resources.pci.
 334                                                    length[i]);
 335                                }
 336                                len += sprintf(page + len, "\n");
 337                        }
 338                }
 339        }
 340        if ((!a->xdi_adapter.port) &&
 341            ((!a->xdi_adapter.ram) ||
 342            (!a->xdi_adapter.reset)
 343             || (!a->xdi_adapter.cfg))) {
 344                if (!IoAdapter->irq_info.irq_nr) {
 345                        p = "slave";
 346                } else {
 347                        p = "out of service";
 348                }
 349        } else if (a->xdi_adapter.trapped) {
 350                p = "trapped";
 351        } else if (a->xdi_adapter.Initialized) {
 352                p = "active";
 353        } else {
 354                p = "ready";
 355        }
 356        len += sprintf(page + len, "State       : %s\n", p);
 357
 358        if (off + count >= len)
 359                *eof = 1;
 360        if (len < off)
 361                return 0;
 362        *start = page + off;
 363        return ((count < len - off) ? count : len - off);
 364}
 365
 366/*
 367** adapter proc init/de-init
 368*/
 369
 370/* --------------------------------------------------------------------------
 371    Create adapter directory and files in proc file system
 372   -------------------------------------------------------------------------- */
 373int create_adapter_proc(diva_os_xdi_adapter_t * a)
 374{
 375        struct proc_dir_entry *de, *pe;
 376        char tmp[16];
 377
 378        sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
 379        if (!(de = proc_mkdir(tmp, proc_net_eicon)))
 380                return (0);
 381        a->proc_adapter_dir = (void *) de;
 382
 383        if (!(pe =
 384             create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de)))
 385                return (0);
 386        a->proc_info = (void *) pe;
 387        pe->write_proc = info_write;
 388        pe->read_proc = info_read;
 389        pe->data = a;
 390
 391        if ((pe = create_proc_entry(grp_opt_proc_name,
 392                               S_IFREG | S_IRUGO | S_IWUSR, de))) {
 393                a->proc_grp_opt = (void *) pe;
 394                pe->write_proc = write_grp_opt;
 395                pe->read_proc = read_grp_opt;
 396                pe->data = a;
 397        }
 398        if ((pe = create_proc_entry(d_l1_down_proc_name,
 399                               S_IFREG | S_IRUGO | S_IWUSR, de))) {
 400                a->proc_d_l1_down = (void *) pe;
 401                pe->write_proc = write_d_l1_down;
 402                pe->read_proc = read_d_l1_down;
 403                pe->data = a;
 404        }
 405
 406        DBG_TRC(("proc entry %s created", tmp));
 407
 408        return (1);
 409}
 410
 411/* --------------------------------------------------------------------------
 412    Remove adapter directory and files in proc file system
 413   -------------------------------------------------------------------------- */
 414void remove_adapter_proc(diva_os_xdi_adapter_t * a)
 415{
 416        char tmp[16];
 417
 418        if (a->proc_adapter_dir) {
 419                if (a->proc_d_l1_down) {
 420                        remove_proc_entry(d_l1_down_proc_name,
 421                                          (struct proc_dir_entry *) a->proc_adapter_dir);
 422                }
 423                if (a->proc_grp_opt) {
 424                        remove_proc_entry(grp_opt_proc_name,
 425                                          (struct proc_dir_entry *) a->proc_adapter_dir);
 426                }
 427                if (a->proc_info) {
 428                        remove_proc_entry(info_proc_name,
 429                                          (struct proc_dir_entry *) a->proc_adapter_dir);
 430                }
 431                sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
 432                remove_proc_entry(tmp, proc_net_eicon);
 433                DBG_TRC(("proc entry %s%d removed", adapter_dir_name,
 434                         a->controller));
 435        }
 436}
 437