Linux Audio

Check our new training course

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