linux/drivers/staging/cxt1e1/sbeproc.c
<<
>>
Prefs
   1/* Copyright (C) 2004-2005  SBE, Inc.
   2 *
   3 *   This program is free software; you can redistribute it and/or modify
   4 *   it under the terms of the GNU General Public License as published by
   5 *   the Free Software Foundation; either version 2 of the License, or
   6 *   (at your option) any later version.
   7 *
   8 *   This program is distributed in the hope that it will be useful,
   9 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 *   GNU General Public License for more details.
  12 */
  13
  14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  15
  16#include <linux/types.h>
  17#include <linux/module.h>
  18#include <linux/errno.h>
  19#include <linux/kernel.h>
  20#include <linux/init.h>
  21#include <linux/proc_fs.h>
  22#include <linux/sched.h>
  23#include <asm/uaccess.h>
  24#include "pmcc4_sysdep.h"
  25#include "sbecom_inline_linux.h"
  26#include "pmcc4_private.h"
  27#include "sbeproc.h"
  28
  29/* forwards */
  30void        sbecom_get_brdinfo (ci_t *, struct sbe_brd_info *, u_int8_t *);
  31extern struct s_hdw_info hdw_info[MAX_BOARDS];
  32
  33#ifdef CONFIG_PROC_FS
  34
  35/********************************************************************/
  36/* procfs stuff                                                     */
  37/********************************************************************/
  38
  39
  40void
  41sbecom_proc_brd_cleanup (ci_t * ci)
  42{
  43    if (ci->dir_dev)
  44    {
  45        char dir[7 + SBE_IFACETMPL_SIZE + 1];
  46        snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
  47        remove_proc_entry("info", ci->dir_dev);
  48        remove_proc_entry(dir, NULL);
  49        ci->dir_dev = NULL;
  50    }
  51}
  52
  53
  54static int
  55sbecom_proc_get_sbe_info (char *buffer, char **start, off_t offset,
  56                          int length, int *eof, void *priv)
  57{
  58    ci_t       *ci = (ci_t *) priv;
  59    int         len = 0;
  60    char       *spd;
  61    struct sbe_brd_info *bip;
  62
  63    if (!(bip = OS_kmalloc (sizeof (struct sbe_brd_info))))
  64    {
  65        return -ENOMEM;
  66    }
  67#if 0
  68    /** RLD DEBUG **/
  69    pr_info(">> sbecom_proc_get_sbe_info: entered, offset %d. length %d.\n",
  70            (int) offset, (int) length);
  71#endif
  72
  73    {
  74        hdw_info_t *hi = &hdw_info[ci->brdno];
  75
  76        u_int8_t *bsn = 0;
  77
  78        switch (hi->promfmt)
  79        {
  80        case PROM_FORMAT_TYPE1:
  81            bsn = (u_int8_t *) hi->mfg_info.pft1.Serial;
  82            break;
  83        case PROM_FORMAT_TYPE2:
  84            bsn = (u_int8_t *) hi->mfg_info.pft2.Serial;
  85            break;
  86        }
  87
  88        sbecom_get_brdinfo (ci, bip, bsn);
  89    }
  90
  91#if 0
  92    /** RLD DEBUG **/
  93    pr_info(">> sbecom_get_brdinfo: returned, first_if %p <%s> last_if %p <%s>\n",
  94            (char *) &bip->first_iname, (char *) &bip->first_iname,
  95            (char *) &bip->last_iname, (char *) &bip->last_iname);
  96#endif
  97    len += sprintf (buffer + len, "Board Type:    ");
  98    switch (bip->brd_id)
  99    {
 100    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3):
 101        len += sprintf (buffer + len, "wanPMC-C1T3");
 102        break;
 103    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1):
 104        len += sprintf (buffer + len, "wanPTMC-256T3 <E1>");
 105        break;
 106    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1):
 107        len += sprintf (buffer + len, "wanPTMC-256T3 <T1>");
 108        break;
 109    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1):
 110        len += sprintf (buffer + len, "wanPTMC-C24TE1");
 111        break;
 112
 113    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1):
 114    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L):
 115        len += sprintf (buffer + len, "wanPMC-C4T1E1");
 116        break;
 117    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1):
 118    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L):
 119        len += sprintf (buffer + len, "wanPMC-C2T1E1");
 120        break;
 121    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1):
 122    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L):
 123        len += sprintf (buffer + len, "wanPMC-C1T1E1");
 124        break;
 125
 126    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1):
 127        len += sprintf (buffer + len, "wanPCI-C4T1E1");
 128        break;
 129    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1):
 130        len += sprintf (buffer + len, "wanPCI-C2T1E1");
 131        break;
 132    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1):
 133        len += sprintf (buffer + len, "wanPCI-C1T1E1");
 134        break;
 135
 136    default:
 137        len += sprintf (buffer + len, "unknown");
 138        break;
 139    }
 140    len += sprintf (buffer + len, "  [%08X]\n", bip->brd_id);
 141
 142    len += sprintf (buffer + len, "Board Number:  %d\n", bip->brdno);
 143    len += sprintf (buffer + len, "Hardware ID:   0x%02X\n", ci->hdw_bid);
 144    len += sprintf (buffer + len, "Board SN:      %06X\n", bip->brd_sn);
 145        len += sprintf(buffer + len, "Board MAC:     %pMF\n",
 146                bip->brd_mac_addr);
 147    len += sprintf (buffer + len, "Ports:         %d\n", ci->max_port);
 148    len += sprintf (buffer + len, "Channels:      %d\n", bip->brd_chan_cnt);
 149#if 1
 150    len += sprintf (buffer + len, "Interface:     %s -> %s\n",
 151                    (char *) &bip->first_iname, (char *) &bip->last_iname);
 152#else
 153    len += sprintf (buffer + len, "Interface:     <not available> 1st %p lst %p\n",
 154                    (char *) &bip->first_iname, (char *) &bip->last_iname);
 155#endif
 156
 157    switch (bip->brd_pci_speed)
 158    {
 159    case BINFO_PCI_SPEED_33:
 160        spd = "33Mhz";
 161        break;
 162    case BINFO_PCI_SPEED_66:
 163        spd = "66Mhz";
 164        break;
 165    default:
 166        spd = "<not available>";
 167        break;
 168    }
 169    len += sprintf (buffer + len, "PCI Bus Speed: %s\n", spd);
 170    len += sprintf (buffer + len, "Release:       %s\n", ci->release);
 171
 172#ifdef SBE_PMCC4_ENABLE
 173    {
 174               extern int cxt1e1_max_mru;
 175#if 0
 176        extern int max_chans_used;
 177        extern int cxt1e1_max_mtu;
 178#endif
 179        extern int max_rxdesc_used, max_txdesc_used;
 180
 181        len += sprintf (buffer + len, "\ncxt1e1_max_mru:         %d\n", cxt1e1_max_mru);
 182#if 0
 183        len += sprintf (buffer + len, "\nmax_chans_used:  %d\n", max_chans_used);
 184        len += sprintf (buffer + len, "cxt1e1_max_mtu:         %d\n", cxt1e1_max_mtu);
 185#endif
 186        len += sprintf (buffer + len, "max_rxdesc_used: %d\n", max_rxdesc_used);
 187        len += sprintf (buffer + len, "max_txdesc_used: %d\n", max_txdesc_used);
 188    }
 189#endif
 190
 191    OS_kfree (bip);                 /* cleanup */
 192
 193    /***
 194     * How to be a proc read function
 195     * ------------------------------
 196     * Prototype:
 197     *    int f(char *buffer, char **start, off_t offset,
 198     *          int count, int *peof, void *dat)
 199     *
 200     * Assume that the buffer is "count" bytes in size.
 201     *
 202     * If you know you have supplied all the data you
 203     * have, set *peof.
 204     *
 205     * You have three ways to return data:
 206     * 0) Leave *start = NULL.  (This is the default.)
 207     *    Put the data of the requested offset at that
 208     *    offset within the buffer.  Return the number (n)
 209     *    of bytes there are from the beginning of the
 210     *    buffer up to the last byte of data.  If the
 211     *    number of supplied bytes (= n - offset) is
 212     *    greater than zero and you didn't signal eof
 213     *    and the reader is prepared to take more data
 214     *    you will be called again with the requested
 215     *    offset advanced by the number of bytes
 216     *    absorbed.  This interface is useful for files
 217     *    no larger than the buffer.
 218     * 1) Set *start = an unsigned long value less than
 219     *    the buffer address but greater than zero.
 220     *    Put the data of the requested offset at the
 221     *    beginning of the buffer.  Return the number of
 222     *    bytes of data placed there.  If this number is
 223     *    greater than zero and you didn't signal eof
 224     *    and the reader is prepared to take more data
 225     *    you will be called again with the requested
 226     *    offset advanced by *start.  This interface is
 227     *    useful when you have a large file consisting
 228     *    of a series of blocks which you want to count
 229     *    and return as wholes.
 230     *    (Hack by Paul.Russell@rustcorp.com.au)
 231     * 2) Set *start = an address within the buffer.
 232     *    Put the data of the requested offset at *start.
 233     *    Return the number of bytes of data placed there.
 234     *    If this number is greater than zero and you
 235     *    didn't signal eof and the reader is prepared to
 236     *    take more data you will be called again with the
 237     *    requested offset advanced by the number of bytes
 238     *    absorbed.
 239     */
 240
 241#if 1
 242    /* #4 - intepretation of above = set EOF, return len */
 243    *eof = 1;
 244#endif
 245
 246#if 0
 247    /*
 248     * #1 - from net/wireless/atmel.c RLD NOTE -there's something wrong with
 249     * this plagarized code which results in this routine being called TWICE.
 250     * The second call returns ZERO, resulting in hidden failure, but at
 251     * least only a single message set is being displayed.
 252     */
 253    if (len <= offset + length)
 254        *eof = 1;
 255    *start = buffer + offset;
 256    len -= offset;
 257    if (len > length)
 258        len = length;
 259    if (len < 0)
 260        len = 0;
 261#endif
 262
 263#if 0                               /* #2 from net/tokenring/olympic.c +
 264                                     * lanstreamer.c */
 265    {
 266        off_t       begin = 0;
 267        int         size = 0;
 268        off_t       pos = 0;
 269
 270        size = len;
 271        pos = begin + size;
 272        if (pos < offset)
 273        {
 274            len = 0;
 275            begin = pos;
 276        }
 277        *start = buffer + (offset - begin);     /* Start of wanted data */
 278        len -= (offset - begin);    /* Start slop */
 279        if (len > length)
 280            len = length;           /* Ending slop */
 281    }
 282#endif
 283
 284#if 0                               /* #3 from
 285                                     * char/ftape/lowlevel/ftape-proc.c */
 286    len = strlen (buffer);
 287    *start = NULL;
 288    if (offset + length >= len)
 289        *eof = 1;
 290    else
 291        *eof = 0;
 292#endif
 293
 294#if 0
 295    pr_info(">> proc_fs: returned len = %d., start %p\n", len, start);  /* RLD DEBUG */
 296#endif
 297
 298/***
 299   using NONE: returns = 314.314.314.
 300   using #1  : returns = 314, 0.
 301   using #2  : returns = 314, 0, 0.
 302   using #3  : returns = 314, 314.
 303   using #4  : returns = 314, 314.
 304***/
 305
 306    return len;
 307}
 308
 309/* initialize the /proc subsystem for the specific SBE driver */
 310
 311int         __init
 312sbecom_proc_brd_init (ci_t * ci)
 313{
 314    struct proc_dir_entry *e;
 315    char dir[7 + SBE_IFACETMPL_SIZE + 1];
 316
 317    /* create a directory in the root procfs */
 318    snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
 319    ci->dir_dev = proc_mkdir(dir, NULL);
 320    if (!ci->dir_dev)
 321    {
 322        pr_err("Unable to create directory /proc/driver/%s\n", ci->devname);
 323        goto fail;
 324    }
 325    e = create_proc_read_entry ("info", S_IFREG | S_IRUGO,
 326                                ci->dir_dev, sbecom_proc_get_sbe_info, ci);
 327    if (!e)
 328    {
 329        pr_err("Unable to create entry /proc/driver/%s/info\n", ci->devname);
 330        goto fail;
 331    }
 332    return 0;
 333
 334fail:
 335    sbecom_proc_brd_cleanup (ci);
 336    return 1;
 337}
 338
 339#else                           /*** ! CONFIG_PROC_FS ***/
 340
 341/* stubbed off dummy routines */
 342
 343void
 344sbecom_proc_brd_cleanup (ci_t * ci)
 345{
 346}
 347
 348int         __init
 349sbecom_proc_brd_init (ci_t * ci)
 350{
 351    return 0;
 352}
 353
 354#endif                          /*** CONFIG_PROC_FS ***/
 355
 356
 357/*** End-of-File ***/
 358