1 /* Copyright (C) 2007-2008 One Stop Systems
2 * Copyright (C) 2003-2006 SBE, Inc.
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.
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.
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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"
30 #include "pmcc4_ioctls.h"
31 #include "pmcc4_private.h"
34 /*****************************************************************************************
35 * Error out early if we have compiler trouble.
37 * (This section is included from the kernel's init/main.c as a friendly
38 * spiderman recommendation...)
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.
45 #if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2)
46 #error Sorry, your GCC is too old. It builds incorrect kernels.
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.
53 /*****************************************************************************************/
55 #ifdef SBE_INCLUDE_SYMBOLS
61 #define CHANNAME "hdlc"
63 /*******************************************************************/
64 /* forward references */
65 status_t
c4_chan_work_init (mpi_t
*, mch_t
*);
66 void musycc_wq_chan_restart (void *);
67 status_t __init
c4_init (ci_t
*, u_char
*, u_char
*);
68 status_t __init
c4_init2 (ci_t
*);
69 ci_t
*__init
c4_new (void *);
70 int __init
c4hw_attach_all (void);
71 void __init
hdw_sn_get (hdw_info_t
*, int);
73 #ifdef CONFIG_SBE_PMCC4_NCOMM
74 irqreturn_t
c4_ebus_intr_th_handler (void *);
77 int c4_frame_rw (ci_t
*, struct sbecom_port_param
*);
78 status_t
c4_get_port (ci_t
*, int);
79 int c4_loop_port (ci_t
*, int, u_int8_t
);
80 int c4_musycc_rw (ci_t
*, struct c4_musycc_param
*);
81 int c4_new_chan (ci_t
*, int, int, void *);
82 status_t
c4_set_port (ci_t
*, int);
83 int c4_pld_rw (ci_t
*, struct sbecom_port_param
*);
84 void cleanup_devs (void);
85 void cleanup_ioremap (void);
86 status_t
musycc_chan_down (ci_t
*, int);
87 irqreturn_t
musycc_intr_th_handler (void *);
88 int musycc_start_xmit (ci_t
*, int, void *);
90 extern char pmcc4_OSSI_release
[];
92 extern struct s_hdw_info hdw_info
[];
94 #if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
95 defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
102 #define V7(x) (x ## _v7)
103 extern int hdlc_netif_rx_v7 (hdlc_device
*, struct sk_buff
*);
104 extern int register_hdlc_device_v7 (hdlc_device
*);
105 extern int unregister_hdlc_device_v7 (hdlc_device
*);
111 int error_flag
; /* module load error reporting */
112 int cxt1e1_log_level
= LOG_ERROR
;
113 int log_level_default
= LOG_ERROR
;
114 module_param(cxt1e1_log_level
, int, 0444);
116 int cxt1e1_max_mru
= MUSYCC_MRU
;
117 int max_mru_default
= MUSYCC_MRU
;
118 module_param(cxt1e1_max_mru
, int, 0444);
120 int cxt1e1_max_mtu
= MUSYCC_MTU
;
121 int max_mtu_default
= MUSYCC_MTU
;
122 module_param(cxt1e1_max_mtu
, int, 0444);
124 int max_txdesc_used
= MUSYCC_TXDESC_MIN
;
125 int max_txdesc_default
= MUSYCC_TXDESC_MIN
;
126 module_param(max_txdesc_used
, int, 0444);
128 int max_rxdesc_used
= MUSYCC_RXDESC_MIN
;
129 int max_rxdesc_default
= MUSYCC_RXDESC_MIN
;
130 module_param(max_rxdesc_used
, int, 0444);
132 /****************************************************************************/
133 /****************************************************************************/
134 /****************************************************************************/
137 getuserbychan (int channum
)
141 ch
= c4_find_chan (channum
);
142 return ch
? ch
->user
: 0;
147 get_hdlc_name (hdlc_device
* hdlc
)
149 struct c4_priv
*priv
= hdlc
->priv
;
150 struct net_device
*dev
= getuserbychan (priv
->channum
);
165 /***************************************************************************/
166 #include <linux/workqueue.h>
169 * One workqueue (wq) per port (since musycc allows simultaneous group
170 * commands), with individual data for each channel:
172 * mpi_t -> struct workqueue_struct *wq_port; (dynamically allocated using
173 * create_workqueue())
175 * With work structure (work) statically allocated for each channel:
177 * mch_t -> struct work_struct ch_work; (statically allocated using ???)
183 * Called by the start transmit routine when a channel TX_ENABLE is to be
184 * issued. This queues the transmission start request among other channels
185 * within a port's group.
188 c4_wk_chan_restart (mch_t
* ch
)
192 #ifdef RLD_RESTART_DEBUG
193 pr_info(">> %s: queueing Port %d Chan %d, mch_t @ %p\n",
194 __func__
, pi
->portnum
, ch
->channum
, ch
);
197 /* create new entry w/in workqueue for this channel and let'er rip */
199 /** queue_work (struct workqueue_struct *queue,
200 ** struct work_struct *work);
202 queue_work (pi
->wq_port
, &ch
->ch_work
);
206 c4_wk_chan_init (mpi_t
* pi
, mch_t
* ch
)
209 * this will be used to restart a stopped channel
212 /** INIT_WORK (struct work_struct *work,
213 ** void (*function)(void *),
216 INIT_WORK(&ch
->ch_work
, (void *)musycc_wq_chan_restart
);
217 return 0; /* success */
221 c4_wq_port_init (mpi_t
* pi
)
224 char name
[16], *np
; /* NOTE: name of the queue limited by system
225 * to 10 characters */
228 return 0; /* already initialized */
231 memset (name
, 0, 16);
232 sprintf (np
, "%s%d", pi
->up
->devname
, pi
->portnum
); /* IE pmcc4-01) */
234 #ifdef RLD_RESTART_DEBUG
235 pr_info(">> %s: creating workqueue <%s> for Port %d.\n",
236 __func__
, name
, pi
->portnum
); /* RLD DEBUG */
238 if (!(pi
->wq_port
= create_singlethread_workqueue (name
)))
240 return 0; /* success */
244 c4_wq_port_cleanup (mpi_t
* pi
)
247 * PORT POINT: cannot call this if WQ is statically allocated w/in
248 * structure since it calls kfree(wq);
252 destroy_workqueue (pi
->wq_port
); /* this also calls
253 * flush_workqueue() */
258 /***************************************************************************/
261 c4_linux_interrupt (int irq
, void *dev_instance
)
263 struct net_device
*ndev
= dev_instance
;
265 return musycc_intr_th_handler(netdev_priv(ndev
));
269 #ifdef CONFIG_SBE_PMCC4_NCOMM
271 c4_ebus_interrupt (int irq
, void *dev_instance
)
273 struct net_device
*ndev
= dev_instance
;
275 return c4_ebus_intr_th_handler(netdev_priv(ndev
));
281 void_open (struct net_device
* ndev
)
283 pr_info("%s: trying to open master device !\n", ndev
->name
);
289 chan_open (struct net_device
* ndev
)
291 hdlc_device
*hdlc
= dev_to_hdlc (ndev
);
292 const struct c4_priv
*priv
= hdlc
->priv
;
295 if ((ret
= hdlc_open (ndev
)))
297 pr_info("hdlc_open failure, err %d.\n", ret
);
300 if ((ret
= c4_chan_up (priv
->ci
, priv
->channum
)))
302 try_module_get (THIS_MODULE
);
303 netif_start_queue (ndev
);
304 return 0; /* no error = success */
309 chan_close (struct net_device
* ndev
)
311 hdlc_device
*hdlc
= dev_to_hdlc (ndev
);
312 const struct c4_priv
*priv
= hdlc
->priv
;
314 netif_stop_queue (ndev
);
315 musycc_chan_down ((ci_t
*) 0, priv
->channum
);
317 module_put (THIS_MODULE
);
323 chan_dev_ioctl (struct net_device
* dev
, struct ifreq
* ifr
, int cmd
)
325 return hdlc_ioctl (dev
, ifr
, cmd
);
330 chan_attach_noop (struct net_device
* ndev
, unsigned short foo_1
, unsigned short foo_2
)
332 return 0; /* our driver has nothing to do here, show's
337 STATIC
struct net_device_stats
*
338 chan_get_stats (struct net_device
* ndev
)
341 struct net_device_stats
*nstats
;
342 struct sbecom_chan_stats
*stats
;
346 struct c4_priv
*priv
;
348 priv
= (struct c4_priv
*) dev_to_hdlc (ndev
)->priv
;
349 channum
= priv
->channum
;
352 ch
= c4_find_chan (channum
);
356 nstats
= &ndev
->stats
;
359 memset (nstats
, 0, sizeof (struct net_device_stats
));
360 nstats
->rx_packets
= stats
->rx_packets
;
361 nstats
->tx_packets
= stats
->tx_packets
;
362 nstats
->rx_bytes
= stats
->rx_bytes
;
363 nstats
->tx_bytes
= stats
->tx_bytes
;
364 nstats
->rx_errors
= stats
->rx_length_errors
+
365 stats
->rx_over_errors
+
366 stats
->rx_crc_errors
+
367 stats
->rx_frame_errors
+
368 stats
->rx_fifo_errors
+
369 stats
->rx_missed_errors
;
370 nstats
->tx_errors
= stats
->tx_dropped
+
371 stats
->tx_aborted_errors
+
372 stats
->tx_fifo_errors
;
373 nstats
->rx_dropped
= stats
->rx_dropped
;
374 nstats
->tx_dropped
= stats
->tx_dropped
;
376 nstats
->rx_length_errors
= stats
->rx_length_errors
;
377 nstats
->rx_over_errors
= stats
->rx_over_errors
;
378 nstats
->rx_crc_errors
= stats
->rx_crc_errors
;
379 nstats
->rx_frame_errors
= stats
->rx_frame_errors
;
380 nstats
->rx_fifo_errors
= stats
->rx_fifo_errors
;
381 nstats
->rx_missed_errors
= stats
->rx_missed_errors
;
383 nstats
->tx_aborted_errors
= stats
->tx_aborted_errors
;
384 nstats
->tx_fifo_errors
= stats
->tx_fifo_errors
;
391 get_ci_by_dev (struct net_device
* ndev
)
393 return (ci_t
*)(netdev_priv(ndev
));
398 c4_linux_xmit (struct sk_buff
* skb
, struct net_device
* ndev
)
400 const struct c4_priv
*priv
;
403 hdlc_device
*hdlc
= dev_to_hdlc (ndev
);
407 rval
= musycc_start_xmit (priv
->ci
, priv
->channum
, skb
);
411 static const struct net_device_ops chan_ops
= {
412 .ndo_open
= chan_open
,
413 .ndo_stop
= chan_close
,
414 .ndo_start_xmit
= c4_linux_xmit
,
415 .ndo_do_ioctl
= chan_dev_ioctl
,
416 .ndo_get_stats
= chan_get_stats
,
419 STATIC
struct net_device
*
420 create_chan (struct net_device
* ndev
, ci_t
* ci
,
421 struct sbecom_chan_param
* cp
)
424 struct net_device
*dev
;
428 if (c4_find_chan (cp
->channum
))
429 return 0; /* channel already exists */
432 struct c4_priv
*priv
;
434 /* allocate then fill in private data structure */
435 priv
= OS_kmalloc (sizeof (struct c4_priv
));
438 pr_warning("%s: no memory for net_device !\n", ci
->devname
);
441 dev
= alloc_hdlcdev (priv
);
444 pr_warning("%s: no memory for hdlc_device !\n", ci
->devname
);
449 priv
->channum
= cp
->channum
;
452 hdlc
= dev_to_hdlc (dev
);
454 dev
->base_addr
= 0; /* not I/O mapped */
455 dev
->irq
= ndev
->irq
;
456 dev
->type
= ARPHRD_RAWHDLC
;
457 *dev
->name
= 0; /* default ifconfig name = "hdlc" */
459 hi
= (hdw_info_t
*) ci
->hdw_info
;
460 if (hi
->mfg_info_sts
== EEPROM_OK
)
464 case PROM_FORMAT_TYPE1
:
465 memcpy (dev
->dev_addr
, (FLD_TYPE1
*) (hi
->mfg_info
.pft1
.Serial
), 6);
467 case PROM_FORMAT_TYPE2
:
468 memcpy (dev
->dev_addr
, (FLD_TYPE2
*) (hi
->mfg_info
.pft2
.Serial
), 6);
471 memset (dev
->dev_addr
, 0, 6);
476 memset (dev
->dev_addr
, 0, 6);
479 hdlc
->xmit
= c4_linux_xmit
;
481 dev
->netdev_ops
= &chan_ops
;
483 * The native hdlc stack calls this 'attach' routine during
484 * hdlc_raw_ioctl(), passing parameters for line encoding and parity.
485 * Since hdlc_raw_ioctl() stack does not interrogate whether an 'attach'
486 * routine is actually registered or not, we supply a dummy routine which
487 * does nothing (since encoding and parity are setup for our driver via a
488 * special configuration application).
491 hdlc
->attach
= chan_attach_noop
;
493 rtnl_unlock (); /* needed due to Ioctl calling sequence */
494 ret
= register_hdlc_device (dev
);
495 /* NOTE: <stats> setting must occur AFTER registration in order to "take" */
496 dev
->tx_queue_len
= MAX_DEFAULT_IFQLEN
;
498 rtnl_lock (); /* needed due to Ioctl calling sequence */
501 if (cxt1e1_log_level
>= LOG_WARN
)
502 pr_info("%s: create_chan[%d] registration error = %d.\n",
503 ci
->devname
, cp
->channum
, ret
);
504 free_netdev (dev
); /* cleanup */
505 return 0; /* failed to register */
511 /* the idea here is to get port information and pass it back (using pointer) */
513 do_get_port (struct net_device
* ndev
, void *data
)
516 ci_t
*ci
; /* ci stands for card information */
517 struct sbecom_port_param pp
;/* copy data to kernel land */
519 if (copy_from_user (&pp
, data
, sizeof (struct sbecom_port_param
)))
521 if (pp
.portnum
>= MUSYCC_NPORTS
)
523 ci
= get_ci_by_dev (ndev
);
525 return -EINVAL
; /* get card info */
527 ret
= mkret (c4_get_port (ci
, pp
.portnum
));
530 if (copy_to_user (data
, &ci
->port
[pp
.portnum
].p
,
531 sizeof (struct sbecom_port_param
)))
536 /* this function copys the user data and then calls the real action function */
538 do_set_port (struct net_device
* ndev
, void *data
)
540 ci_t
*ci
; /* ci stands for card information */
541 struct sbecom_port_param pp
;/* copy data to kernel land */
543 if (copy_from_user (&pp
, data
, sizeof (struct sbecom_port_param
)))
545 if (pp
.portnum
>= MUSYCC_NPORTS
)
547 ci
= get_ci_by_dev (ndev
);
549 return -EINVAL
; /* get card info */
551 if (pp
.portnum
>= ci
->max_port
) /* sanity check */
554 memcpy (&ci
->port
[pp
.portnum
].p
, &pp
, sizeof (struct sbecom_port_param
));
555 return mkret (c4_set_port (ci
, pp
.portnum
));
558 /* work the port loopback mode as per directed */
560 do_port_loop (struct net_device
* ndev
, void *data
)
562 struct sbecom_port_param pp
;
565 if (copy_from_user (&pp
, data
, sizeof (struct sbecom_port_param
)))
567 ci
= get_ci_by_dev (ndev
);
570 return mkret (c4_loop_port (ci
, pp
.portnum
, pp
.port_mode
));
573 /* set the specified register with the given value / or just read it */
575 do_framer_rw (struct net_device
* ndev
, void *data
)
577 struct sbecom_port_param pp
;
581 if (copy_from_user (&pp
, data
, sizeof (struct sbecom_port_param
)))
583 ci
= get_ci_by_dev (ndev
);
586 ret
= mkret (c4_frame_rw (ci
, &pp
));
589 if (copy_to_user (data
, &pp
, sizeof (struct sbecom_port_param
)))
594 /* set the specified register with the given value / or just read it */
596 do_pld_rw (struct net_device
* ndev
, void *data
)
598 struct sbecom_port_param pp
;
602 if (copy_from_user (&pp
, data
, sizeof (struct sbecom_port_param
)))
604 ci
= get_ci_by_dev (ndev
);
607 ret
= mkret (c4_pld_rw (ci
, &pp
));
610 if (copy_to_user (data
, &pp
, sizeof (struct sbecom_port_param
)))
615 /* set the specified register with the given value / or just read it */
617 do_musycc_rw (struct net_device
* ndev
, void *data
)
619 struct c4_musycc_param mp
;
623 if (copy_from_user (&mp
, data
, sizeof (struct c4_musycc_param
)))
625 ci
= get_ci_by_dev (ndev
);
628 ret
= mkret (c4_musycc_rw (ci
, &mp
));
631 if (copy_to_user (data
, &mp
, sizeof (struct c4_musycc_param
)))
637 do_get_chan (struct net_device
* ndev
, void *data
)
639 struct sbecom_chan_param cp
;
642 if (copy_from_user (&cp
, data
,
643 sizeof (struct sbecom_chan_param
)))
646 if ((ret
= mkret (c4_get_chan (cp
.channum
, &cp
))))
649 if (copy_to_user (data
, &cp
, sizeof (struct sbecom_chan_param
)))
655 do_set_chan (struct net_device
* ndev
, void *data
)
657 struct sbecom_chan_param cp
;
661 if (copy_from_user (&cp
, data
, sizeof (struct sbecom_chan_param
)))
663 ci
= get_ci_by_dev (ndev
);
666 switch (ret
= mkret (c4_set_chan (cp
.channum
, &cp
)))
676 do_create_chan (struct net_device
* ndev
, void *data
)
679 struct net_device
*dev
;
680 struct sbecom_chan_param cp
;
683 if (copy_from_user (&cp
, data
, sizeof (struct sbecom_chan_param
)))
685 ci
= get_ci_by_dev (ndev
);
688 dev
= create_chan (ndev
, ci
, &cp
);
691 ret
= mkret (c4_new_chan (ci
, cp
.port
, cp
.channum
, dev
));
694 rtnl_unlock (); /* needed due to Ioctl calling sequence */
695 unregister_hdlc_device (dev
);
696 rtnl_lock (); /* needed due to Ioctl calling sequence */
703 do_get_chan_stats (struct net_device
* ndev
, void *data
)
705 struct c4_chan_stats_wrap ccs
;
708 if (copy_from_user (&ccs
, data
,
709 sizeof (struct c4_chan_stats_wrap
)))
711 switch (ret
= mkret (c4_get_chan_stats (ccs
.channum
, &ccs
.stats
)))
718 if (copy_to_user (data
, &ccs
,
719 sizeof (struct c4_chan_stats_wrap
)))
724 do_set_loglevel (struct net_device
* ndev
, void *data
)
726 unsigned int cxt1e1_log_level
;
728 if (copy_from_user (&cxt1e1_log_level
, data
, sizeof (int)))
730 sbecom_set_loglevel (cxt1e1_log_level
);
735 do_deluser (struct net_device
* ndev
, int lockit
)
737 if (ndev
->flags
& IFF_UP
)
743 const struct c4_priv
*priv
;
746 priv
= (struct c4_priv
*) dev_to_hdlc (ndev
)->priv
;
748 channum
= priv
->channum
;
750 ch
= c4_find_chan (channum
);
753 ch
->user
= 0; /* will be freed, below */
757 rtnl_unlock (); /* needed if Ioctl calling sequence */
758 unregister_hdlc_device (ndev
);
760 rtnl_lock (); /* needed if Ioctl calling sequence */
766 do_del_chan (struct net_device
* musycc_dev
, void *data
)
768 struct sbecom_chan_param cp
;
769 char buf
[sizeof (CHANNAME
) + 3];
770 struct net_device
*dev
;
773 if (copy_from_user (&cp
, data
,
774 sizeof (struct sbecom_chan_param
)))
776 sprintf (buf
, CHANNAME
"%d", cp
.channum
);
777 if (!(dev
= dev_get_by_name (&init_net
, buf
)))
780 ret
= do_deluser (dev
, 1);
783 return c4_del_chan (cp
.channum
);
785 int c4_reset_board (void *);
788 do_reset (struct net_device
* musycc_dev
, void *data
)
790 const struct c4_priv
*priv
;
793 for (i
= 0; i
< 128; i
++)
795 struct net_device
*ndev
;
796 char buf
[sizeof (CHANNAME
) + 3];
798 sprintf (buf
, CHANNAME
"%d", i
);
799 if (!(ndev
= dev_get_by_name(&init_net
, buf
)))
801 priv
= dev_to_hdlc (ndev
)->priv
;
803 if ((unsigned long) (priv
->ci
) ==
804 (unsigned long) (netdev_priv(musycc_dev
)))
806 ndev
->flags
&= ~IFF_UP
;
808 netif_stop_queue (ndev
);
809 do_deluser (ndev
, 1);
817 do_reset_chan_stats (struct net_device
* musycc_dev
, void *data
)
819 struct sbecom_chan_param cp
;
821 if (copy_from_user (&cp
, data
,
822 sizeof (struct sbecom_chan_param
)))
824 return mkret (c4_del_chan_stats (cp
.channum
));
828 c4_ioctl (struct net_device
* ndev
, struct ifreq
* ifr
, int cmd
)
840 struct sbe_brd_info bip
;
841 struct sbe_drv_info dip
;
842 struct sbe_iid_info iip
;
843 struct sbe_brd_addr bap
;
844 struct sbecom_chan_stats stats
;
845 struct sbecom_chan_param param
;
846 struct temux_card_stats cards
;
847 struct sbecom_card_param cardp
;
848 struct sbecom_framer_param frp
;
853 if (!capable (CAP_SYS_ADMIN
))
855 if (cmd
!= SIOCDEVPRIVATE
+ 15)
857 if (!(ci
= get_ci_by_dev (ndev
)))
859 if (ci
->state
!= C_RUNNING
)
861 if (copy_from_user (&iocmd
, ifr
->ifr_data
, sizeof (iocmd
)))
864 if (copy_from_user (&len
, ifr
->ifr_data
+ sizeof (iocmd
), sizeof (len
)))
869 pr_info("c4_ioctl: iocmd %x, dir %x type %x nr %x iolen %d.\n", iocmd
,
870 _IOC_DIR (iocmd
), _IOC_TYPE (iocmd
), _IOC_NR (iocmd
),
873 iolen
= _IOC_SIZE (iocmd
);
874 data
= ifr
->ifr_data
+ sizeof (iocmd
);
875 if (copy_from_user (&arg
, data
, iolen
))
881 case SBE_IOC_PORT_GET
:
882 //pr_info(">> SBE_IOC_PORT_GET Ioctl...\n");
883 ret
= do_get_port (ndev
, data
);
885 case SBE_IOC_PORT_SET
:
886 //pr_info(">> SBE_IOC_PORT_SET Ioctl...\n");
887 ret
= do_set_port (ndev
, data
);
889 case SBE_IOC_CHAN_GET
:
890 //pr_info(">> SBE_IOC_CHAN_GET Ioctl...\n");
891 ret
= do_get_chan (ndev
, data
);
893 case SBE_IOC_CHAN_SET
:
894 //pr_info(">> SBE_IOC_CHAN_SET Ioctl...\n");
895 ret
= do_set_chan (ndev
, data
);
898 //pr_info(">> C4_DEL_CHAN Ioctl...\n");
899 ret
= do_del_chan (ndev
, data
);
901 case SBE_IOC_CHAN_NEW
:
902 ret
= do_create_chan (ndev
, data
);
904 case SBE_IOC_CHAN_GET_STAT
:
905 ret
= do_get_chan_stats (ndev
, data
);
907 case SBE_IOC_LOGLEVEL
:
908 ret
= do_set_loglevel (ndev
, data
);
910 case SBE_IOC_RESET_DEV
:
911 ret
= do_reset (ndev
, data
);
913 case SBE_IOC_CHAN_DEL_STAT
:
914 ret
= do_reset_chan_stats (ndev
, data
);
917 ret
= do_port_loop (ndev
, data
);
920 ret
= do_framer_rw (ndev
, data
);
923 ret
= do_musycc_rw (ndev
, data
);
926 ret
= do_pld_rw (ndev
, data
);
928 case SBE_IOC_IID_GET
:
929 ret
= (iolen
== sizeof (struct sbe_iid_info
)) ? c4_get_iidinfo (ci
, &arg
.u
.iip
) : -EFAULT
;
930 if (ret
== 0) /* no error, copy data */
931 if (copy_to_user (data
, &arg
, iolen
))
935 //pr_info(">> c4_ioctl: EINVAL - unknown iocmd <%x>\n", iocmd);
942 static const struct net_device_ops c4_ops
= {
943 .ndo_open
= void_open
,
944 .ndo_start_xmit
= c4_linux_xmit
,
945 .ndo_do_ioctl
= c4_ioctl
,
948 static void c4_setup(struct net_device
*dev
)
950 dev
->type
= ARPHRD_VOID
;
951 dev
->netdev_ops
= &c4_ops
;
954 struct net_device
*__init
955 c4_add_dev (hdw_info_t
* hi
, int brdno
, unsigned long f0
, unsigned long f1
,
958 struct net_device
*ndev
;
961 ndev
= alloc_netdev(sizeof(ci_t
), SBE_IFACETMPL
, c4_setup
);
964 pr_warning("%s: no memory for struct net_device !\n", hi
->devname
);
968 ci
= (ci_t
*)(netdev_priv(ndev
));
972 ci
->state
= C_INIT
; /* mark as hardware not available */
975 ci
->brdno
= ci
->next
? ci
->next
->brdno
+ 1 : 0;
978 CI
= ci
; /* DEBUG, only board 0 usage */
980 strcpy (ci
->devname
, hi
->devname
);
981 ci
->release
= &pmcc4_OSSI_release
[0];
984 #if defined(SBE_ISR_TASKLET)
985 tasklet_init (&ci
->ci_musycc_isr_tasklet
,
986 (void (*) (unsigned long)) musycc_intr_bh_tasklet
,
989 if (atomic_read (&ci
->ci_musycc_isr_tasklet
.count
) == 0)
990 tasklet_disable_nosync (&ci
->ci_musycc_isr_tasklet
);
991 #elif defined(SBE_ISR_IMMEDIATE)
992 ci
->ci_musycc_isr_tq
.routine
= (void *) (unsigned long) musycc_intr_bh_tasklet
;
993 ci
->ci_musycc_isr_tq
.data
= ci
;
997 if (register_netdev (ndev
) ||
998 (c4_init (ci
, (u_char
*) f0
, (u_char
*) f1
) != SBE_DRVR_SUCCESS
))
1000 OS_kfree (netdev_priv(ndev
));
1002 error_flag
= ENODEV
;
1005 /*************************************************************
1006 * int request_irq(unsigned int irq,
1007 * void (*handler)(int, void *, struct pt_regs *),
1008 * unsigned long flags, const char *dev_name, void *dev_id);
1010 * irq -> The interrupt number that is being requested.
1011 * handler -> Pointer to handling function being installed.
1012 * flags -> A bit mask of options related to interrupt management.
1013 * dev_name -> String used in /proc/interrupts to show owner of interrupt.
1014 * dev_id -> Pointer (for shared interrupt lines) to point to its own
1015 * private data area (to identify which device is interrupting).
1017 * extern void free_irq(unsigned int irq, void *dev_id);
1018 **************************************************************/
1020 if (request_irq (irq0
, &c4_linux_interrupt
,
1024 pr_warning("%s: MUSYCC could not get irq: %d\n", ndev
->name
, irq0
);
1025 unregister_netdev (ndev
);
1026 OS_kfree (netdev_priv(ndev
));
1031 #ifdef CONFIG_SBE_PMCC4_NCOMM
1032 if (request_irq (irq1
, &c4_ebus_interrupt
, IRQF_SHARED
, ndev
->name
, ndev
))
1034 pr_warning("%s: EBUS could not get irq: %d\n", hi
->devname
, irq1
);
1035 unregister_netdev (ndev
);
1036 free_irq (irq0
, ndev
);
1037 OS_kfree (netdev_priv(ndev
));
1044 /* setup board identification information */
1049 hdw_sn_get (hi
, brdno
); /* also sets PROM format type (promfmt)
1050 * for later usage */
1052 switch (hi
->promfmt
)
1054 case PROM_FORMAT_TYPE1
:
1055 memcpy (ndev
->dev_addr
, (FLD_TYPE1
*) (hi
->mfg_info
.pft1
.Serial
), 6);
1056 memcpy (&tmp
, (FLD_TYPE1
*) (hi
->mfg_info
.pft1
.Id
), 4); /* unaligned data
1058 ci
->brd_id
= cpu_to_be32 (tmp
);
1060 case PROM_FORMAT_TYPE2
:
1061 memcpy (ndev
->dev_addr
, (FLD_TYPE2
*) (hi
->mfg_info
.pft2
.Serial
), 6);
1062 memcpy (&tmp
, (FLD_TYPE2
*) (hi
->mfg_info
.pft2
.Id
), 4); /* unaligned data
1064 ci
->brd_id
= cpu_to_be32 (tmp
);
1068 memset (ndev
->dev_addr
, 0, 6);
1073 sbeid_set_hdwbid (ci
); /* requires bid to be preset */
1075 sbeid_set_bdtype (ci
); /* requires hdw_bid to be preset */
1080 #ifdef CONFIG_PROC_FS
1081 sbecom_proc_brd_init (ci
);
1083 #if defined(SBE_ISR_TASKLET)
1084 tasklet_enable (&ci
->ci_musycc_isr_tasklet
);
1088 if ((error_flag
= c4_init2 (ci
)) != SBE_DRVR_SUCCESS
)
1090 #ifdef CONFIG_PROC_FS
1091 sbecom_proc_brd_cleanup (ci
);
1093 unregister_netdev (ndev
);
1094 free_irq (irq1
, ndev
);
1095 free_irq (irq0
, ndev
);
1096 OS_kfree (netdev_priv(ndev
));
1098 return 0; /* failure, error_flag is set */
1108 pr_warning("%s\n", pmcc4_OSSI_release
);
1109 if ((rtn
= c4hw_attach_all ()))
1110 return -rtn
; /* installation failure - see system log */
1112 /* housekeeping notifications */
1113 if (cxt1e1_log_level
!= log_level_default
)
1114 pr_info("NOTE: driver parameter <cxt1e1_log_level> changed from default %d to %d.\n",
1115 log_level_default
, cxt1e1_log_level
);
1116 if (cxt1e1_max_mru
!= max_mru_default
)
1117 pr_info("NOTE: driver parameter <cxt1e1_max_mru> changed from default %d to %d.\n",
1118 max_mru_default
, cxt1e1_max_mru
);
1119 if (cxt1e1_max_mtu
!= max_mtu_default
)
1120 pr_info("NOTE: driver parameter <cxt1e1_max_mtu> changed from default %d to %d.\n",
1121 max_mtu_default
, cxt1e1_max_mtu
);
1122 if (max_rxdesc_used
!= max_rxdesc_default
)
1124 if (max_rxdesc_used
> 2000)
1125 max_rxdesc_used
= 2000; /* out-of-bounds reset */
1126 pr_info("NOTE: driver parameter <max_rxdesc_used> changed from default %d to %d.\n",
1127 max_rxdesc_default
, max_rxdesc_used
);
1129 if (max_txdesc_used
!= max_txdesc_default
)
1131 if (max_txdesc_used
> 1000)
1132 max_txdesc_used
= 1000; /* out-of-bounds reset */
1133 pr_info("NOTE: driver parameter <max_txdesc_used> changed from default %d to %d.\n",
1134 max_txdesc_default
, max_txdesc_used
);
1136 return 0; /* installation success */
1141 * find any still allocated hdlc registrations and unregister via call to
1150 struct net_device
*ndev
;
1153 for (i
= 0, hi
= hdw_info
; i
< MAX_BOARDS
; i
++, hi
++)
1155 if (hi
->ndev
) /* a board has been attached */
1157 ci
= (ci_t
*)(netdev_priv(hi
->ndev
));
1158 for (j
= 0; j
< ci
->max_port
; j
++)
1159 for (k
= 0; k
< MUSYCC_NCHANS
; k
++)
1160 if ((ndev
= ci
->port
[j
].chan
[k
]->user
))
1162 do_deluser (ndev
, 0);
1170 c4_mod_remove (void)
1172 cleanup_hdlc (); /* delete any missed channels */
1176 pr_info("SBE - driver removed.\n");
1179 module_init (c4_mod_init
);
1180 module_exit (c4_mod_remove
);
1182 MODULE_AUTHOR ("SBE Technical Services <support@sbei.com>");
1183 MODULE_DESCRIPTION ("wanPCI-CxT1E1 Generic HDLC WAN Driver module");
1184 #ifdef MODULE_LICENSE
1185 MODULE_LICENSE ("GPL");
1188 /*** End-of-File ***/