linux/drivers/staging/cxt1e1/linux.c
<<
>>
Prefs
   1/* Copyright (C) 2007-2008  One Stop Systems
   2 * Copyright (C) 2003-2006  SBE, Inc.
   3 *
   4 *   This program is free software; you can redistribute it and/or modify
   5 *   it under the terms of the GNU General Public License as published by
   6 *   the Free Software Foundation; either version 2 of the License, or
   7 *   (at your option) any later version.
   8 *
   9 *   This program is distributed in the hope that it will be useful,
  10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 *   GNU General Public License for more details.
  13 */
  14
  15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  16
  17#include <linux/types.h>
  18#include <linux/netdevice.h>
  19#include <linux/module.h>
  20#include <linux/hdlc.h>
  21#include <linux/if_arp.h>
  22#include <linux/init.h>
  23#include <asm/uaccess.h>
  24#include <linux/rtnetlink.h>
  25#include <linux/skbuff.h>
  26#include "pmcc4_sysdep.h"
  27#include "sbecom_inline_linux.h"
  28#include "libsbew.h"
  29#include "pmcc4.h"
  30#include "pmcc4_ioctls.h"
  31#include "pmcc4_private.h"
  32#include "sbeproc.h"
  33
  34/*****************************************************************************************
  35 * Error out early if we have compiler trouble.
  36 *
  37 *   (This section is included from the kernel's init/main.c as a friendly
  38 *   spiderman recommendation...)
  39 *
  40 * Versions of gcc older than that listed below may actually compile and link
  41 * okay, but the end product can have subtle run time bugs.  To avoid associated
  42 * bogus bug reports, we flatly refuse to compile with a gcc that is known to be
  43 * too old from the very beginning.
  44 */
  45#if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2)
  46#error Sorry, your GCC is too old. It builds incorrect kernels.
  47#endif
  48
  49#if __GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ == 0
  50#warning gcc-4.1.0 is known to miscompile the kernel.  A different compiler version is recommended.
  51#endif
  52
  53/*****************************************************************************************/
  54
  55#define CHANNAME "hdlc"
  56
  57/*******************************************************************/
  58/* forward references */
  59status_t    c4_chan_work_init (mpi_t *, mch_t *);
  60void        musycc_wq_chan_restart (void *);
  61status_t __init c4_init (ci_t *, u_char *, u_char *);
  62status_t __init c4_init2 (ci_t *);
  63ci_t       *__init c4_new (void *);
  64int __init  c4hw_attach_all (void);
  65void __init hdw_sn_get (hdw_info_t *, int);
  66
  67#ifdef CONFIG_SBE_PMCC4_NCOMM
  68irqreturn_t c4_ebus_intr_th_handler (void *);
  69
  70#endif
  71int         c4_frame_rw (ci_t *, struct sbecom_port_param *);
  72status_t    c4_get_port (ci_t *, int);
  73int         c4_loop_port (ci_t *, int, u_int8_t);
  74int         c4_musycc_rw (ci_t *, struct c4_musycc_param *);
  75int         c4_new_chan (ci_t *, int, int, void *);
  76status_t    c4_set_port (ci_t *, int);
  77int         c4_pld_rw (ci_t *, struct sbecom_port_param *);
  78void        cleanup_devs (void);
  79void        cleanup_ioremap (void);
  80status_t    musycc_chan_down (ci_t *, int);
  81irqreturn_t musycc_intr_th_handler (void *);
  82int         musycc_start_xmit (ci_t *, int, void *);
  83
  84extern char pmcc4_OSSI_release[];
  85extern ci_t *CI;
  86extern struct s_hdw_info hdw_info[];
  87
  88#if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
  89    defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
  90#define _v7_hdlc_  1
  91#else
  92#define _v7_hdlc_  0
  93#endif
  94
  95#if _v7_hdlc_
  96#define V7(x) (x ## _v7)
  97extern int  hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *);
  98extern int  register_hdlc_device_v7 (hdlc_device *);
  99extern int  unregister_hdlc_device_v7 (hdlc_device *);
 100
 101#else
 102#define V7(x) x
 103#endif
 104
 105int         error_flag;         /* module load error reporting */
 106int         cxt1e1_log_level = LOG_ERROR;
 107int         log_level_default = LOG_ERROR;
 108module_param(cxt1e1_log_level, int, 0444);
 109
 110int         cxt1e1_max_mru = MUSYCC_MRU;
 111int         max_mru_default = MUSYCC_MRU;
 112module_param(cxt1e1_max_mru, int, 0444);
 113
 114int         cxt1e1_max_mtu = MUSYCC_MTU;
 115int         max_mtu_default = MUSYCC_MTU;
 116module_param(cxt1e1_max_mtu, int, 0444);
 117
 118int         max_txdesc_used = MUSYCC_TXDESC_MIN;
 119int         max_txdesc_default = MUSYCC_TXDESC_MIN;
 120module_param(max_txdesc_used, int, 0444);
 121
 122int         max_rxdesc_used = MUSYCC_RXDESC_MIN;
 123int         max_rxdesc_default = MUSYCC_RXDESC_MIN;
 124module_param(max_rxdesc_used, int, 0444);
 125
 126/****************************************************************************/
 127/****************************************************************************/
 128/****************************************************************************/
 129
 130void       *
 131getuserbychan (int channum)
 132{
 133    mch_t      *ch;
 134
 135    ch = c4_find_chan (channum);
 136    return ch ? ch->user : 0;
 137}
 138
 139
 140char       *
 141get_hdlc_name (hdlc_device *hdlc)
 142{
 143    struct c4_priv *priv = hdlc->priv;
 144    struct net_device *dev = getuserbychan (priv->channum);
 145
 146    return dev->name;
 147}
 148
 149
 150static      status_t
 151mkret (int bsd)
 152{
 153    if (bsd > 0)
 154        return -bsd;
 155    else
 156        return bsd;
 157}
 158
 159/***************************************************************************/
 160#include <linux/workqueue.h>
 161
 162/***
 163 * One workqueue (wq) per port (since musycc allows simultaneous group
 164 * commands), with individual data for each channel:
 165 *
 166 *   mpi_t -> struct workqueue_struct *wq_port;  (dynamically allocated using
 167 *                                               create_workqueue())
 168 *
 169 * With work structure (work) statically allocated for each channel:
 170 *
 171 *   mch_t -> struct work_struct ch_work;  (statically allocated using ???)
 172 *
 173 ***/
 174
 175
 176/*
 177 * Called by the start transmit routine when a channel TX_ENABLE is to be
 178 * issued.  This queues the transmission start request among other channels
 179 * within a port's group.
 180 */
 181void
 182c4_wk_chan_restart (mch_t *ch)
 183{
 184    mpi_t      *pi = ch->up;
 185
 186#ifdef RLD_RESTART_DEBUG
 187    pr_info(">> %s: queueing Port %d Chan %d, mch_t @ %p\n",
 188            __func__, pi->portnum, ch->channum, ch);
 189#endif
 190
 191    /* create new entry w/in workqueue for this channel and let'er rip */
 192
 193    /** queue_work (struct workqueue_struct *queue,
 194     **             struct work_struct *work);
 195     **/
 196    queue_work (pi->wq_port, &ch->ch_work);
 197}
 198
 199status_t
 200c4_wk_chan_init (mpi_t *pi, mch_t *ch)
 201{
 202    /*
 203     * this will be used to restart a stopped channel
 204     */
 205
 206    /** INIT_WORK (struct work_struct *work,
 207     **            void (*function)(void *),
 208     **            void *data);
 209     **/
 210    INIT_WORK(&ch->ch_work, (void *)musycc_wq_chan_restart);
 211    return 0;                       /* success */
 212}
 213
 214status_t
 215c4_wq_port_init (mpi_t *pi)
 216{
 217
 218    char        name[16], *np;  /* NOTE: name of the queue limited by system
 219                                 * to 10 characters */
 220
 221    if (pi->wq_port)
 222        return 0;                   /* already initialized */
 223
 224    np = name;
 225    memset (name, 0, 16);
 226    sprintf (np, "%s%d", pi->up->devname, pi->portnum); /* IE pmcc4-01) */
 227
 228#ifdef RLD_RESTART_DEBUG
 229    pr_info(">> %s: creating workqueue <%s> for Port %d.\n",
 230            __func__, name, pi->portnum); /* RLD DEBUG */
 231#endif
 232    if (!(pi->wq_port = create_singlethread_workqueue (name)))
 233        return ENOMEM;
 234    return 0;                       /* success */
 235}
 236
 237void
 238c4_wq_port_cleanup (mpi_t *pi)
 239{
 240    /*
 241     * PORT POINT: cannot call this if WQ is statically allocated w/in
 242     * structure since it calls kfree(wq);
 243     */
 244    if (pi->wq_port)
 245    {
 246        destroy_workqueue (pi->wq_port);        /* this also calls
 247                                                 * flush_workqueue() */
 248        pi->wq_port = 0;
 249    }
 250}
 251
 252/***************************************************************************/
 253
 254irqreturn_t
 255c4_linux_interrupt (int irq, void *dev_instance)
 256{
 257    struct net_device *ndev = dev_instance;
 258
 259    return musycc_intr_th_handler(netdev_priv(ndev));
 260}
 261
 262
 263#ifdef CONFIG_SBE_PMCC4_NCOMM
 264irqreturn_t
 265c4_ebus_interrupt (int irq, void *dev_instance)
 266{
 267    struct net_device *ndev = dev_instance;
 268
 269    return c4_ebus_intr_th_handler(netdev_priv(ndev));
 270}
 271#endif
 272
 273
 274static int
 275void_open (struct net_device *ndev)
 276{
 277    pr_info("%s: trying to open master device !\n", ndev->name);
 278    return -1;
 279}
 280
 281
 282static int
 283chan_open (struct net_device *ndev)
 284{
 285    hdlc_device *hdlc = dev_to_hdlc (ndev);
 286    const struct c4_priv *priv = hdlc->priv;
 287    int         ret;
 288
 289    if ((ret = hdlc_open (ndev)))
 290    {
 291        pr_info("hdlc_open failure, err %d.\n", ret);
 292        return ret;
 293    }
 294    if ((ret = c4_chan_up (priv->ci, priv->channum)))
 295        return -ret;
 296    try_module_get (THIS_MODULE);
 297    netif_start_queue (ndev);
 298    return 0;                       /* no error = success */
 299}
 300
 301
 302static int
 303chan_close (struct net_device *ndev)
 304{
 305    hdlc_device *hdlc = dev_to_hdlc (ndev);
 306    const struct c4_priv *priv = hdlc->priv;
 307
 308    netif_stop_queue (ndev);
 309    musycc_chan_down ((ci_t *) 0, priv->channum);
 310    hdlc_close (ndev);
 311    module_put (THIS_MODULE);
 312    return 0;
 313}
 314
 315
 316static int
 317chan_dev_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 318{
 319    return hdlc_ioctl (dev, ifr, cmd);
 320}
 321
 322
 323static int
 324chan_attach_noop (struct net_device *ndev, unsigned short foo_1, unsigned short foo_2)
 325{
 326    return 0;                   /* our driver has nothing to do here, show's
 327                                 * over, go home */
 328}
 329
 330
 331static struct net_device_stats *
 332chan_get_stats (struct net_device *ndev)
 333{
 334    mch_t      *ch;
 335    struct net_device_stats *nstats;
 336    struct sbecom_chan_stats *stats;
 337    int         channum;
 338
 339    {
 340        struct c4_priv *priv;
 341
 342        priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv;
 343        channum = priv->channum;
 344    }
 345
 346    ch = c4_find_chan (channum);
 347    if (ch == NULL)
 348        return NULL;
 349
 350    nstats = &ndev->stats;
 351    stats = &ch->s;
 352
 353    memset (nstats, 0, sizeof (struct net_device_stats));
 354    nstats->rx_packets = stats->rx_packets;
 355    nstats->tx_packets = stats->tx_packets;
 356    nstats->rx_bytes = stats->rx_bytes;
 357    nstats->tx_bytes = stats->tx_bytes;
 358    nstats->rx_errors = stats->rx_length_errors +
 359        stats->rx_over_errors +
 360        stats->rx_crc_errors +
 361        stats->rx_frame_errors +
 362        stats->rx_fifo_errors +
 363        stats->rx_missed_errors;
 364    nstats->tx_errors = stats->tx_dropped +
 365        stats->tx_aborted_errors +
 366        stats->tx_fifo_errors;
 367    nstats->rx_dropped = stats->rx_dropped;
 368    nstats->tx_dropped = stats->tx_dropped;
 369
 370    nstats->rx_length_errors = stats->rx_length_errors;
 371    nstats->rx_over_errors = stats->rx_over_errors;
 372    nstats->rx_crc_errors = stats->rx_crc_errors;
 373    nstats->rx_frame_errors = stats->rx_frame_errors;
 374    nstats->rx_fifo_errors = stats->rx_fifo_errors;
 375    nstats->rx_missed_errors = stats->rx_missed_errors;
 376
 377    nstats->tx_aborted_errors = stats->tx_aborted_errors;
 378    nstats->tx_fifo_errors = stats->tx_fifo_errors;
 379
 380    return nstats;
 381}
 382
 383
 384static ci_t *
 385get_ci_by_dev (struct net_device *ndev)
 386{
 387    return (ci_t *)(netdev_priv(ndev));
 388}
 389
 390
 391static int
 392c4_linux_xmit (struct sk_buff *skb, struct net_device *ndev)
 393{
 394    const struct c4_priv *priv;
 395    int         rval;
 396
 397    hdlc_device *hdlc = dev_to_hdlc (ndev);
 398
 399    priv = hdlc->priv;
 400
 401    rval = musycc_start_xmit (priv->ci, priv->channum, skb);
 402    return rval;
 403}
 404
 405static const struct net_device_ops chan_ops = {
 406       .ndo_open       = chan_open,
 407       .ndo_stop       = chan_close,
 408       .ndo_start_xmit = c4_linux_xmit,
 409       .ndo_do_ioctl   = chan_dev_ioctl,
 410       .ndo_get_stats  = chan_get_stats,
 411};
 412
 413static struct net_device *
 414create_chan (struct net_device *ndev, ci_t *ci,
 415             struct sbecom_chan_param *cp)
 416{
 417    hdlc_device *hdlc;
 418    struct net_device *dev;
 419    hdw_info_t *hi;
 420    int         ret;
 421
 422    if (c4_find_chan (cp->channum))
 423        return 0;                   /* channel already exists */
 424
 425    {
 426        struct c4_priv *priv;
 427
 428        /* allocate then fill in private data structure */
 429        priv = OS_kmalloc (sizeof (struct c4_priv));
 430        if (!priv)
 431        {
 432            pr_warning("%s: no memory for net_device !\n", ci->devname);
 433            return 0;
 434        }
 435        dev = alloc_hdlcdev (priv);
 436        if (!dev)
 437        {
 438            pr_warning("%s: no memory for hdlc_device !\n", ci->devname);
 439            OS_kfree (priv);
 440            return 0;
 441        }
 442        priv->ci = ci;
 443        priv->channum = cp->channum;
 444    }
 445
 446    hdlc = dev_to_hdlc (dev);
 447
 448    dev->base_addr = 0;             /* not I/O mapped */
 449    dev->irq = ndev->irq;
 450    dev->type = ARPHRD_RAWHDLC;
 451    *dev->name = 0;                 /* default ifconfig name = "hdlc" */
 452
 453    hi = (hdw_info_t *) ci->hdw_info;
 454    if (hi->mfg_info_sts == EEPROM_OK)
 455    {
 456        switch (hi->promfmt)
 457        {
 458        case PROM_FORMAT_TYPE1:
 459            memcpy (dev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
 460            break;
 461        case PROM_FORMAT_TYPE2:
 462            memcpy (dev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
 463            break;
 464        default:
 465            memset (dev->dev_addr, 0, 6);
 466            break;
 467        }
 468    } else
 469    {
 470        memset (dev->dev_addr, 0, 6);
 471    }
 472
 473    hdlc->xmit = c4_linux_xmit;
 474
 475    dev->netdev_ops = &chan_ops;
 476    /*
 477     * The native hdlc stack calls this 'attach' routine during
 478     * hdlc_raw_ioctl(), passing parameters for line encoding and parity.
 479     * Since hdlc_raw_ioctl() stack does not interrogate whether an 'attach'
 480     * routine is actually registered or not, we supply a dummy routine which
 481     * does nothing (since encoding and parity are setup for our driver via a
 482     * special configuration application).
 483     */
 484
 485    hdlc->attach = chan_attach_noop;
 486
 487    rtnl_unlock ();                 /* needed due to Ioctl calling sequence */
 488    ret = register_hdlc_device (dev);
 489    /* NOTE: <stats> setting must occur AFTER registration in order to "take" */
 490    dev->tx_queue_len = MAX_DEFAULT_IFQLEN;
 491
 492    rtnl_lock ();                   /* needed due to Ioctl calling sequence */
 493    if (ret)
 494    {
 495        if (cxt1e1_log_level >= LOG_WARN)
 496            pr_info("%s: create_chan[%d] registration error = %d.\n",
 497                    ci->devname, cp->channum, ret);
 498        free_netdev (dev);          /* cleanup */
 499        return 0;                   /* failed to register */
 500    }
 501    return dev;
 502}
 503
 504
 505/* the idea here is to get port information and pass it back (using pointer) */
 506static      status_t
 507do_get_port (struct net_device *ndev, void *data)
 508{
 509    int         ret;
 510    ci_t       *ci;             /* ci stands for card information */
 511    struct sbecom_port_param pp;/* copy data to kernel land */
 512
 513    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
 514        return -EFAULT;
 515    if (pp.portnum >= MUSYCC_NPORTS)
 516        return -EFAULT;
 517    ci = get_ci_by_dev (ndev);
 518    if (!ci)
 519        return -EINVAL;             /* get card info */
 520
 521    ret = mkret (c4_get_port (ci, pp.portnum));
 522    if (ret)
 523        return ret;
 524    if (copy_to_user (data, &ci->port[pp.portnum].p,
 525                      sizeof (struct sbecom_port_param)))
 526        return -EFAULT;
 527    return 0;
 528}
 529
 530/* this function copys the user data and then calls the real action function */
 531static      status_t
 532do_set_port (struct net_device *ndev, void *data)
 533{
 534    ci_t       *ci;             /* ci stands for card information */
 535    struct sbecom_port_param pp;/* copy data to kernel land */
 536
 537    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
 538        return -EFAULT;
 539    if (pp.portnum >= MUSYCC_NPORTS)
 540        return -EFAULT;
 541    ci = get_ci_by_dev (ndev);
 542    if (!ci)
 543        return -EINVAL;             /* get card info */
 544
 545    if (pp.portnum >= ci->max_port) /* sanity check */
 546        return -ENXIO;
 547
 548    memcpy (&ci->port[pp.portnum].p, &pp, sizeof (struct sbecom_port_param));
 549    return mkret (c4_set_port (ci, pp.portnum));
 550}
 551
 552/* work the port loopback mode as per directed */
 553static      status_t
 554do_port_loop (struct net_device *ndev, void *data)
 555{
 556    struct sbecom_port_param pp;
 557    ci_t       *ci;
 558
 559    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
 560        return -EFAULT;
 561    ci = get_ci_by_dev (ndev);
 562    if (!ci)
 563        return -EINVAL;
 564    return mkret (c4_loop_port (ci, pp.portnum, pp.port_mode));
 565}
 566
 567/* set the specified register with the given value / or just read it */
 568static      status_t
 569do_framer_rw (struct net_device *ndev, void *data)
 570{
 571    struct sbecom_port_param pp;
 572    ci_t       *ci;
 573    int         ret;
 574
 575    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
 576        return -EFAULT;
 577    ci = get_ci_by_dev (ndev);
 578    if (!ci)
 579        return -EINVAL;
 580    ret = mkret (c4_frame_rw (ci, &pp));
 581    if (ret)
 582        return ret;
 583    if (copy_to_user (data, &pp, sizeof (struct sbecom_port_param)))
 584        return -EFAULT;
 585    return 0;
 586}
 587
 588/* set the specified register with the given value / or just read it */
 589static      status_t
 590do_pld_rw (struct net_device *ndev, void *data)
 591{
 592    struct sbecom_port_param pp;
 593    ci_t       *ci;
 594    int         ret;
 595
 596    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
 597        return -EFAULT;
 598    ci = get_ci_by_dev (ndev);
 599    if (!ci)
 600        return -EINVAL;
 601    ret = mkret (c4_pld_rw (ci, &pp));
 602    if (ret)
 603        return ret;
 604    if (copy_to_user (data, &pp, sizeof (struct sbecom_port_param)))
 605        return -EFAULT;
 606    return 0;
 607}
 608
 609/* set the specified register with the given value / or just read it */
 610static      status_t
 611do_musycc_rw (struct net_device *ndev, void *data)
 612{
 613    struct c4_musycc_param mp;
 614    ci_t       *ci;
 615    int         ret;
 616
 617    if (copy_from_user (&mp, data, sizeof (struct c4_musycc_param)))
 618        return -EFAULT;
 619    ci = get_ci_by_dev (ndev);
 620    if (!ci)
 621        return -EINVAL;
 622    ret = mkret (c4_musycc_rw (ci, &mp));
 623    if (ret)
 624        return ret;
 625    if (copy_to_user (data, &mp, sizeof (struct c4_musycc_param)))
 626        return -EFAULT;
 627    return 0;
 628}
 629
 630static      status_t
 631do_get_chan (struct net_device *ndev, void *data)
 632{
 633    struct sbecom_chan_param cp;
 634    int         ret;
 635
 636    if (copy_from_user (&cp, data,
 637                        sizeof (struct sbecom_chan_param)))
 638        return -EFAULT;
 639
 640    if ((ret = mkret (c4_get_chan (cp.channum, &cp))))
 641        return ret;
 642
 643    if (copy_to_user (data, &cp, sizeof (struct sbecom_chan_param)))
 644        return -EFAULT;
 645    return 0;
 646}
 647
 648static      status_t
 649do_set_chan (struct net_device *ndev, void *data)
 650{
 651    struct sbecom_chan_param cp;
 652    int         ret;
 653    ci_t       *ci;
 654
 655    if (copy_from_user (&cp, data, sizeof (struct sbecom_chan_param)))
 656        return -EFAULT;
 657    ci = get_ci_by_dev (ndev);
 658    if (!ci)
 659        return -EINVAL;
 660    switch (ret = mkret (c4_set_chan (cp.channum, &cp)))
 661    {
 662    case 0:
 663        return 0;
 664    default:
 665        return ret;
 666    }
 667}
 668
 669static      status_t
 670do_create_chan (struct net_device *ndev, void *data)
 671{
 672    ci_t       *ci;
 673    struct net_device *dev;
 674    struct sbecom_chan_param cp;
 675    int         ret;
 676
 677    if (copy_from_user (&cp, data, sizeof (struct sbecom_chan_param)))
 678        return -EFAULT;
 679    ci = get_ci_by_dev (ndev);
 680    if (!ci)
 681        return -EINVAL;
 682    dev = create_chan (ndev, ci, &cp);
 683    if (!dev)
 684        return -EBUSY;
 685    ret = mkret (c4_new_chan (ci, cp.port, cp.channum, dev));
 686    if (ret)
 687    {
 688        rtnl_unlock ();             /* needed due to Ioctl calling sequence */
 689        unregister_hdlc_device (dev);
 690        rtnl_lock ();               /* needed due to Ioctl calling sequence */
 691        free_netdev (dev);
 692    }
 693    return ret;
 694}
 695
 696static      status_t
 697do_get_chan_stats (struct net_device *ndev, void *data)
 698{
 699    struct c4_chan_stats_wrap ccs;
 700    int         ret;
 701
 702    if (copy_from_user (&ccs, data,
 703                        sizeof (struct c4_chan_stats_wrap)))
 704        return -EFAULT;
 705    switch (ret = mkret (c4_get_chan_stats (ccs.channum, &ccs.stats)))
 706    {
 707    case 0:
 708        break;
 709    default:
 710        return ret;
 711    }
 712    if (copy_to_user (data, &ccs,
 713                      sizeof (struct c4_chan_stats_wrap)))
 714        return -EFAULT;
 715    return 0;
 716}
 717static      status_t
 718do_set_loglevel (struct net_device *ndev, void *data)
 719{
 720    unsigned int cxt1e1_log_level;
 721
 722    if (copy_from_user (&cxt1e1_log_level, data, sizeof (int)))
 723        return -EFAULT;
 724    sbecom_set_loglevel (cxt1e1_log_level);
 725    return 0;
 726}
 727
 728static      status_t
 729do_deluser (struct net_device *ndev, int lockit)
 730{
 731    if (ndev->flags & IFF_UP)
 732        return -EBUSY;
 733
 734    {
 735        ci_t       *ci;
 736        mch_t      *ch;
 737        const struct c4_priv *priv;
 738        int         channum;
 739
 740        priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv;
 741        ci = priv->ci;
 742        channum = priv->channum;
 743
 744        ch = c4_find_chan (channum);
 745        if (ch == NULL)
 746            return -ENOENT;
 747        ch->user = 0;               /* will be freed, below */
 748    }
 749
 750    if (lockit)
 751        rtnl_unlock ();             /* needed if Ioctl calling sequence */
 752    unregister_hdlc_device (ndev);
 753    if (lockit)
 754        rtnl_lock ();               /* needed if Ioctl calling sequence */
 755    free_netdev (ndev);
 756    return 0;
 757}
 758
 759int
 760do_del_chan (struct net_device *musycc_dev, void *data)
 761{
 762    struct sbecom_chan_param cp;
 763    char        buf[sizeof (CHANNAME) + 3];
 764    struct net_device *dev;
 765    int         ret;
 766
 767    if (copy_from_user (&cp, data,
 768                        sizeof (struct sbecom_chan_param)))
 769        return -EFAULT;
 770    if (cp.channum > 999)
 771        return -EINVAL;
 772    snprintf (buf, sizeof(buf), CHANNAME "%d", cp.channum);
 773    if (!(dev = dev_get_by_name (&init_net, buf)))
 774        return -ENOENT;
 775    dev_put (dev);
 776    ret = do_deluser (dev, 1);
 777    if (ret)
 778        return ret;
 779    return c4_del_chan (cp.channum);
 780}
 781int         c4_reset_board (void *);
 782
 783int
 784do_reset (struct net_device *musycc_dev, void *data)
 785{
 786    const struct c4_priv *priv;
 787    int         i;
 788
 789    for (i = 0; i < 128; i++)
 790    {
 791        struct net_device *ndev;
 792        char        buf[sizeof (CHANNAME) + 3];
 793
 794        sprintf (buf, CHANNAME "%d", i);
 795        if (!(ndev = dev_get_by_name(&init_net, buf)))
 796            continue;
 797        priv = dev_to_hdlc (ndev)->priv;
 798
 799        if ((unsigned long) (priv->ci) ==
 800            (unsigned long) (netdev_priv(musycc_dev)))
 801        {
 802            ndev->flags &= ~IFF_UP;
 803            dev_put (ndev);
 804            netif_stop_queue (ndev);
 805            do_deluser (ndev, 1);
 806        } else
 807            dev_put (ndev);
 808    }
 809    return 0;
 810}
 811
 812int
 813do_reset_chan_stats (struct net_device *musycc_dev, void *data)
 814{
 815    struct sbecom_chan_param cp;
 816
 817    if (copy_from_user (&cp, data,
 818                        sizeof (struct sbecom_chan_param)))
 819        return -EFAULT;
 820    return mkret (c4_del_chan_stats (cp.channum));
 821}
 822
 823static      status_t
 824c4_ioctl (struct net_device *ndev, struct ifreq *ifr, int cmd)
 825{
 826    ci_t       *ci;
 827    void       *data;
 828    int         iocmd, iolen;
 829    status_t    ret;
 830    static struct data
 831    {
 832        union
 833        {
 834            u_int8_t c;
 835            u_int32_t i;
 836            struct sbe_brd_info bip;
 837            struct sbe_drv_info dip;
 838            struct sbe_iid_info iip;
 839            struct sbe_brd_addr bap;
 840            struct sbecom_chan_stats stats;
 841            struct sbecom_chan_param param;
 842            struct temux_card_stats cards;
 843            struct sbecom_card_param cardp;
 844            struct sbecom_framer_param frp;
 845        }           u;
 846    }           arg;
 847
 848
 849    if (!capable (CAP_SYS_ADMIN))
 850        return -EPERM;
 851    if (cmd != SIOCDEVPRIVATE + 15)
 852        return -EINVAL;
 853    if (!(ci = get_ci_by_dev (ndev)))
 854        return -EINVAL;
 855    if (ci->state != C_RUNNING)
 856        return -ENODEV;
 857    if (copy_from_user (&iocmd, ifr->ifr_data, sizeof (iocmd)))
 858        return -EFAULT;
 859#if 0
 860    if (copy_from_user (&len, ifr->ifr_data + sizeof (iocmd), sizeof (len)))
 861        return -EFAULT;
 862#endif
 863
 864#if 0
 865    pr_info("c4_ioctl: iocmd %x, dir %x type %x nr %x iolen %d.\n", iocmd,
 866            _IOC_DIR (iocmd), _IOC_TYPE (iocmd), _IOC_NR (iocmd),
 867            _IOC_SIZE (iocmd));
 868#endif
 869    iolen = _IOC_SIZE (iocmd);
 870    data = ifr->ifr_data + sizeof (iocmd);
 871    if (copy_from_user (&arg, data, iolen))
 872        return -EFAULT;
 873
 874    ret = 0;
 875    switch (iocmd)
 876    {
 877    case SBE_IOC_PORT_GET:
 878        //pr_info(">> SBE_IOC_PORT_GET Ioctl...\n");
 879        ret = do_get_port (ndev, data);
 880        break;
 881    case SBE_IOC_PORT_SET:
 882        //pr_info(">> SBE_IOC_PORT_SET Ioctl...\n");
 883        ret = do_set_port (ndev, data);
 884        break;
 885    case SBE_IOC_CHAN_GET:
 886        //pr_info(">> SBE_IOC_CHAN_GET Ioctl...\n");
 887        ret = do_get_chan (ndev, data);
 888        break;
 889    case SBE_IOC_CHAN_SET:
 890        //pr_info(">> SBE_IOC_CHAN_SET Ioctl...\n");
 891        ret = do_set_chan (ndev, data);
 892        break;
 893    case C4_DEL_CHAN:
 894        //pr_info(">> C4_DEL_CHAN Ioctl...\n");
 895        ret = do_del_chan (ndev, data);
 896        break;
 897    case SBE_IOC_CHAN_NEW:
 898        ret = do_create_chan (ndev, data);
 899        break;
 900    case SBE_IOC_CHAN_GET_STAT:
 901        ret = do_get_chan_stats (ndev, data);
 902        break;
 903    case SBE_IOC_LOGLEVEL:
 904        ret = do_set_loglevel (ndev, data);
 905        break;
 906    case SBE_IOC_RESET_DEV:
 907        ret = do_reset (ndev, data);
 908        break;
 909    case SBE_IOC_CHAN_DEL_STAT:
 910        ret = do_reset_chan_stats (ndev, data);
 911        break;
 912    case C4_LOOP_PORT:
 913        ret = do_port_loop (ndev, data);
 914        break;
 915    case C4_RW_FRMR:
 916        ret = do_framer_rw (ndev, data);
 917        break;
 918    case C4_RW_MSYC:
 919        ret = do_musycc_rw (ndev, data);
 920        break;
 921    case C4_RW_PLD:
 922        ret = do_pld_rw (ndev, data);
 923        break;
 924    case SBE_IOC_IID_GET:
 925        ret = (iolen == sizeof (struct sbe_iid_info)) ? c4_get_iidinfo (ci, &arg.u.iip) : -EFAULT;
 926        if (ret == 0)               /* no error, copy data */
 927            if (copy_to_user (data, &arg, iolen))
 928                return -EFAULT;
 929        break;
 930    default:
 931        //pr_info(">> c4_ioctl: EINVAL - unknown iocmd <%x>\n", iocmd);
 932        ret = -EINVAL;
 933        break;
 934    }
 935    return mkret (ret);
 936}
 937
 938static const struct net_device_ops c4_ops = {
 939       .ndo_open       = void_open,
 940       .ndo_start_xmit = c4_linux_xmit,
 941       .ndo_do_ioctl   = c4_ioctl,
 942};
 943
 944static void c4_setup(struct net_device *dev)
 945{
 946       dev->type = ARPHRD_VOID;
 947       dev->netdev_ops = &c4_ops;
 948}
 949
 950struct net_device *__init
 951c4_add_dev (hdw_info_t *hi, int brdno, unsigned long f0, unsigned long f1,
 952            int irq0, int irq1)
 953{
 954    struct net_device *ndev;
 955    ci_t       *ci;
 956
 957    ndev = alloc_netdev(sizeof(ci_t), SBE_IFACETMPL, c4_setup);
 958    if (!ndev)
 959    {
 960        pr_warning("%s: no memory for struct net_device !\n", hi->devname);
 961        error_flag = ENOMEM;
 962        return 0;
 963    }
 964    ci = (ci_t *)(netdev_priv(ndev));
 965    ndev->irq = irq0;
 966
 967    ci->hdw_info = hi;
 968    ci->state = C_INIT;         /* mark as hardware not available */
 969    ci->next = c4_list;
 970    c4_list = ci;
 971    ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
 972
 973    if (CI == 0)
 974        CI = ci;                    /* DEBUG, only board 0 usage */
 975
 976    strcpy (ci->devname, hi->devname);
 977    ci->release = &pmcc4_OSSI_release[0];
 978
 979    /* tasklet */
 980#if defined(SBE_ISR_TASKLET)
 981    tasklet_init (&ci->ci_musycc_isr_tasklet,
 982                  (void (*) (unsigned long)) musycc_intr_bh_tasklet,
 983                  (unsigned long) ci);
 984
 985    if (atomic_read (&ci->ci_musycc_isr_tasklet.count) == 0)
 986        tasklet_disable_nosync (&ci->ci_musycc_isr_tasklet);
 987#elif defined(SBE_ISR_IMMEDIATE)
 988    ci->ci_musycc_isr_tq.routine = (void *) (unsigned long) musycc_intr_bh_tasklet;
 989    ci->ci_musycc_isr_tq.data = ci;
 990#endif
 991
 992
 993    if (register_netdev (ndev) ||
 994        (c4_init (ci, (u_char *) f0, (u_char *) f1) != SBE_DRVR_SUCCESS))
 995    {
 996        OS_kfree (netdev_priv(ndev));
 997        OS_kfree (ndev);
 998        error_flag = ENODEV;
 999        return 0;
1000    }
1001    /*************************************************************
1002     *  int request_irq(unsigned int irq,
1003     *                  void (*handler)(int, void *, struct pt_regs *),
1004     *                  unsigned long flags, const char *dev_name, void *dev_id);
1005     *  wherein:
1006     *  irq      -> The interrupt number that is being requested.
1007     *  handler  -> Pointer to handling function being installed.
1008     *  flags    -> A bit mask of options related to interrupt management.
1009     *  dev_name -> String used in /proc/interrupts to show owner of interrupt.
1010     *  dev_id   -> Pointer (for shared interrupt lines) to point to its own
1011     *              private data area (to identify which device is interrupting).
1012     *
1013     *  extern void free_irq(unsigned int irq, void *dev_id);
1014     **************************************************************/
1015
1016    if (request_irq (irq0, &c4_linux_interrupt,
1017                     IRQF_SHARED,
1018                     ndev->name, ndev))
1019    {
1020        pr_warning("%s: MUSYCC could not get irq: %d\n", ndev->name, irq0);
1021        unregister_netdev (ndev);
1022        OS_kfree (netdev_priv(ndev));
1023        OS_kfree (ndev);
1024        error_flag = EIO;
1025        return 0;
1026    }
1027#ifdef CONFIG_SBE_PMCC4_NCOMM
1028    if (request_irq (irq1, &c4_ebus_interrupt, IRQF_SHARED, ndev->name, ndev))
1029    {
1030        pr_warning("%s: EBUS could not get irq: %d\n", hi->devname, irq1);
1031        unregister_netdev (ndev);
1032        free_irq (irq0, ndev);
1033        OS_kfree (netdev_priv(ndev));
1034        OS_kfree (ndev);
1035        error_flag = EIO;
1036        return 0;
1037    }
1038#endif
1039
1040    /* setup board identification information */
1041
1042    {
1043        u_int32_t   tmp;
1044
1045        hdw_sn_get (hi, brdno);     /* also sets PROM format type (promfmt)
1046                                     * for later usage */
1047
1048        switch (hi->promfmt)
1049        {
1050        case PROM_FORMAT_TYPE1:
1051            memcpy (ndev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
1052            memcpy (&tmp, (FLD_TYPE1 *) (hi->mfg_info.pft1.Id), 4);     /* unaligned data
1053                                                                         * acquisition */
1054            ci->brd_id = cpu_to_be32 (tmp);
1055            break;
1056        case PROM_FORMAT_TYPE2:
1057            memcpy (ndev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
1058            memcpy (&tmp, (FLD_TYPE2 *) (hi->mfg_info.pft2.Id), 4);     /* unaligned data
1059                                                                         * acquisition */
1060            ci->brd_id = cpu_to_be32 (tmp);
1061            break;
1062        default:
1063            ci->brd_id = 0;
1064            memset (ndev->dev_addr, 0, 6);
1065            break;
1066        }
1067
1068#if 1
1069        sbeid_set_hdwbid (ci);      /* requires bid to be preset */
1070#else
1071        sbeid_set_bdtype (ci);      /* requires hdw_bid to be preset */
1072#endif
1073
1074    }
1075
1076#ifdef CONFIG_PROC_FS
1077    sbecom_proc_brd_init (ci);
1078#endif
1079#if defined(SBE_ISR_TASKLET)
1080    tasklet_enable (&ci->ci_musycc_isr_tasklet);
1081#endif
1082
1083
1084    if ((error_flag = c4_init2 (ci)) != SBE_DRVR_SUCCESS)
1085    {
1086#ifdef CONFIG_PROC_FS
1087        sbecom_proc_brd_cleanup (ci);
1088#endif
1089        unregister_netdev (ndev);
1090        free_irq (irq1, ndev);
1091        free_irq (irq0, ndev);
1092        OS_kfree (netdev_priv(ndev));
1093        OS_kfree (ndev);
1094        return 0;                   /* failure, error_flag is set */
1095    }
1096    return ndev;
1097}
1098
1099static int  __init
1100c4_mod_init (void)
1101{
1102    int         rtn;
1103
1104    pr_warning("%s\n", pmcc4_OSSI_release);
1105    if ((rtn = c4hw_attach_all ()))
1106        return -rtn;                /* installation failure - see system log */
1107
1108    /* housekeeping notifications */
1109    if (cxt1e1_log_level != log_level_default)
1110        pr_info("NOTE: driver parameter <cxt1e1_log_level> changed from default %d to %d.\n",
1111                log_level_default, cxt1e1_log_level);
1112       if (cxt1e1_max_mru != max_mru_default)
1113               pr_info("NOTE: driver parameter <cxt1e1_max_mru> changed from default %d to %d.\n",
1114                               max_mru_default, cxt1e1_max_mru);
1115       if (cxt1e1_max_mtu != max_mtu_default)
1116               pr_info("NOTE: driver parameter <cxt1e1_max_mtu> changed from default %d to %d.\n",
1117                               max_mtu_default, cxt1e1_max_mtu);
1118    if (max_rxdesc_used != max_rxdesc_default)
1119    {
1120        if (max_rxdesc_used > 2000)
1121            max_rxdesc_used = 2000; /* out-of-bounds reset */
1122        pr_info("NOTE: driver parameter <max_rxdesc_used> changed from default %d to %d.\n",
1123                max_rxdesc_default, max_rxdesc_used);
1124    }
1125    if (max_txdesc_used != max_txdesc_default)
1126    {
1127        if (max_txdesc_used > 1000)
1128            max_txdesc_used = 1000; /* out-of-bounds reset */
1129        pr_info("NOTE: driver parameter <max_txdesc_used> changed from default %d to %d.\n",
1130                max_txdesc_default, max_txdesc_used);
1131    }
1132    return 0;                       /* installation success */
1133}
1134
1135
1136 /*
1137  * find any still allocated hdlc registrations and unregister via call to
1138  * do_deluser()
1139  */
1140
1141static void __exit
1142cleanup_hdlc (void)
1143{
1144    hdw_info_t *hi;
1145    ci_t       *ci;
1146    struct net_device *ndev;
1147    int         i, j, k;
1148
1149    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
1150    {
1151        if (hi->ndev)               /* a board has been attached */
1152        {
1153            ci = (ci_t *)(netdev_priv(hi->ndev));
1154            for (j = 0; j < ci->max_port; j++)
1155                for (k = 0; k < MUSYCC_NCHANS; k++)
1156                    if ((ndev = ci->port[j].chan[k]->user))
1157                    {
1158                        do_deluser (ndev, 0);
1159                    }
1160        }
1161    }
1162}
1163
1164
1165static void __exit
1166c4_mod_remove (void)
1167{
1168        cleanup_hdlc();            /* delete any missed channels */
1169        cleanup_devs();
1170        c4_cleanup();
1171        cleanup_ioremap();
1172        pr_info("SBE - driver removed.\n");
1173}
1174
1175module_init (c4_mod_init);
1176module_exit (c4_mod_remove);
1177
1178MODULE_AUTHOR ("SBE Technical Services <support@sbei.com>");
1179MODULE_DESCRIPTION ("wanPCI-CxT1E1 Generic HDLC WAN Driver module");
1180#ifdef MODULE_LICENSE
1181MODULE_LICENSE ("GPL");
1182#endif
1183
1184/***  End-of-File  ***/
1185