patch-2.4.21 linux-2.4.21/drivers/net/wan/farsync.c

Next file: linux-2.4.21/drivers/net/wan/farsync.h
Previous file: linux-2.4.21/drivers/net/wan/dscc4.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/drivers/net/wan/farsync.c linux-2.4.21/drivers/net/wan/farsync.c
@@ -1,5 +1,5 @@
 /*
- *      FarSync X21 driver for Linux (2.4.x kernel version)
+ *      FarSync X21 driver for Linux (generic HDLC version)
  *
  *      Actually sync driver for X.21, V.35 and V.24 on FarSync T-series cards
  *
@@ -18,11 +18,10 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
-#include <linux/netdevice.h>
 #include <linux/init.h>
-#include <linux/if_arp.h>
 #include <asm/uaccess.h>
-#include <net/syncppp.h>
+#include <linux/if.h>
+#include <linux/hdlc.h>
 
 #include "farsync.h"
 
@@ -32,6 +31,7 @@
  */
 MODULE_AUTHOR("R.J.Dunlop <bob.dunlop@farsite.co.uk>");
 MODULE_DESCRIPTION("FarSync T-Series X21 driver. FarSite Communications Ltd.");
+MODULE_LICENSE("GPL");
 
 EXPORT_NO_SYMBOLS;
 
@@ -331,26 +331,15 @@
 /*      Per port (line or channel) information
  */
 struct fst_port_info {
-        void                   *if_ptr; /* Some drivers describe this as a
-                                         * general purpose pointer. However if
-                                         * using syncPPP it has a very specific
-                                         * purpose: it must be the first item in
-                                         * the structure pointed to by dev->priv
-                                         * and must in turn point to the
-                                         * associated ppp_device structure.
-                                         */
+        hdlc_device             hdlc;   /* HDLC device struct - must be first */
         struct fst_card_info   *card;   /* Card we're associated with */
         int                     index;  /* Port index on the card */
-        int                     proto;  /* Protocol we are running */
         int                     hwif;   /* Line hardware (lineInterface copy) */
         int                     run;    /* Port is running */
         int                     rxpos;  /* Next Rx buffer to use */
         int                     txpos;  /* Next Tx buffer to use */
         int                     txipos; /* Next Tx buffer to check for free */
         int                     txcnt;  /* Count of Tx buffers in use */
-        struct net_device      *dev;    /* Kernel network device entry */
-        struct net_device_stats stats;  /* Standard statistics */
-        struct ppp_device       pppdev; /* Link to syncPPP */
 };
 
 /*      Per card information
@@ -370,6 +359,11 @@
         struct fst_port_info ports[ FST_MAX_PORTS ];
 };
 
+/* Convert an HDLC device pointer into a port info pointer and similar */
+#define hdlc_to_port(H) ((struct fst_port_info *)(H))
+#define dev_to_port(D)  hdlc_to_port(dev_to_hdlc(D))
+#define port_to_dev(P)  hdlc_to_dev(&(P)->hdlc)
+
 
 /*
  *      Shared memory window access macros
@@ -632,25 +626,18 @@
 
         if ( signals & (( port->hwif == X21 ) ? IPSTS_INDICATE : IPSTS_DCD ))
         {
-                if ( ! netif_carrier_ok ( port->dev ))
+                if ( ! netif_carrier_ok ( port_to_dev ( port )))
                 {
                         dbg ( DBG_INTR,"DCD active\n");
-
-                        /* Poke sPPP to renegotiate */
-                        if ( port->proto == FST_HDLC || port->proto == FST_PPP )
-                        {
-                                sppp_reopen ( port->dev );
-                        }
-
-                        netif_carrier_on ( port->dev );
+                        netif_carrier_on ( port_to_dev ( port ));
                 }
         }
         else
         {
-                if ( netif_carrier_ok ( port->dev ))
+                if ( netif_carrier_ok ( port_to_dev ( port )))
                 {
                         dbg ( DBG_INTR,"DCD lost\n");
-                        netif_carrier_off ( port->dev );
+                        netif_carrier_off ( port_to_dev ( port ));
                 }
         }
 }
@@ -693,24 +680,24 @@
                                         len );
         if ( dmabits != ( RX_STP | RX_ENP ) || len > LEN_RX_BUFFER - 2 )
         {
-                port->stats.rx_errors++;
+                port->hdlc.stats.rx_errors++;
 
                 /* Update error stats and discard buffer */
                 if ( dmabits & RX_OFLO )
                 {
-                        port->stats.rx_fifo_errors++;
+                        port->hdlc.stats.rx_fifo_errors++;
                 }
                 if ( dmabits & RX_CRC )
                 {
-                        port->stats.rx_crc_errors++;
+                        port->hdlc.stats.rx_crc_errors++;
                 }
                 if ( dmabits & RX_FRAM )
                 {
-                        port->stats.rx_frame_errors++;
+                        port->hdlc.stats.rx_frame_errors++;
                 }
                 if ( dmabits == ( RX_STP | RX_ENP ))
                 {
-                        port->stats.rx_length_errors++;
+                        port->hdlc.stats.rx_length_errors++;
                 }
 
                 /* Discard buffer descriptors until we see the end of packet
@@ -747,7 +734,7 @@
         {
                 dbg ( DBG_RX,"intr_rx: can't allocate buffer\n");
 
-                port->stats.rx_dropped++;
+                port->hdlc.stats.rx_dropped++;
 
                 /* Return descriptor to card */
                 FST_WRB ( card, rxDescrRing[pi][rxp].bits, DMA_OWN );
@@ -771,29 +758,16 @@
                 port->rxpos = rxp;
 
         /* Update stats */
-        port->stats.rx_packets++;
-        port->stats.rx_bytes += len;
+        port->hdlc.stats.rx_packets++;
+        port->hdlc.stats.rx_bytes += len;
 
         /* Push upstream */
-        if ( port->proto == FST_HDLC || port->proto == FST_PPP )
-        {
-                /* Mark for further processing by sPPP module */
-                skb->protocol = htons ( ETH_P_WAN_PPP );
-        }
-        else
-        {
-                /* DEC customer specific protocol (since nothing defined for
-                 * marking raw data), at least one other driver uses this value
-                 * for this purpose.
-                 */
-                skb->protocol = htons ( ETH_P_CUST );
-                skb->pkt_type = PACKET_HOST;
-        }
         skb->mac.raw = skb->data;
-        skb->dev = port->dev;
+        skb->dev = hdlc_to_dev ( &port->hdlc );
+        skb->protocol = htons ( ETH_P_HDLC );
         netif_rx ( skb );
 
-        port->dev->last_rx = jiffies;
+        port_to_dev ( port )->last_rx = jiffies;
 }
 
 
@@ -844,7 +818,7 @@
                 case CTLB_CHG:
                 case CTLC_CHG:
                 case CTLD_CHG:
-                        if ( port->run && port->dev != NULL )
+                        if ( port->run )
                                 fst_intr_ctlchg ( card, port );
                         break;
 
@@ -863,9 +837,8 @@
                          * always load up the entire packet for DMA.
                          */
                         dbg ( DBG_TX,"Tx underflow port %d\n", event & 0x03 );
-
-                        port->stats.tx_errors++;
-                        port->stats.tx_fifo_errors++;
+                        port->hdlc.stats.tx_errors++;
+                        port->hdlc.stats.tx_fifo_errors++;
                         break;
 
                 case INIT_CPLT:
@@ -890,7 +863,7 @@
 
         for ( pi = 0, port = card->ports ; pi < card->nports ; pi++, port++ )
         {
-                if ( port->dev == NULL || ! port->run )
+                if ( ! port->run )
                         continue;
 
                 /* Check for rx completions */
@@ -907,7 +880,7 @@
                         --port->txcnt;
                         if ( ++port->txipos >= NUM_TX_BUFFER )
                                 port->txipos = 0;
-                        netif_wake_queue ( port->dev );
+                        netif_wake_queue ( port_to_dev ( port ));
                 }
         }
 
@@ -969,145 +942,28 @@
 
 
 static int
-fst_change_mtu ( struct net_device *dev, int new_mtu )
-{
-        if ( new_mtu < 128 || new_mtu > FST_MAX_MTU )
-                return -EINVAL;
-        dev->mtu = new_mtu;
-        return 0;
-}
-
-
-/* Sooner or later you can't avoid a forward declaration */
-static int fst_ioctl ( struct net_device *dev, struct ifreq *ifr, int cmd );
-
-static int
-switch_proto ( struct fst_port_info *port, int new_proto )
-{
-        int err;
-        int orig_mtu;
-        struct net_device *dev;
-
-        dev = port->dev;
-
-        /* Turn off sPPP module ? */
-        if (( new_proto != FST_HDLC && new_proto != FST_PPP )
-                && ( port->proto == FST_HDLC || port->proto == FST_PPP ))
-        {
-                sppp_close ( port->pppdev.dev );
-                sppp_detach ( port->pppdev.dev );
-
-                /* Reset some fields overwritten by sPPP */
-                dev->hard_header     = NULL;
-                dev->rebuild_header  = NULL;
-                dev->tx_queue_len    = FST_TX_QUEUE_LEN;
-                dev->type            = ARPHRD_MYTYPE;
-                dev->addr_len        = 0;
-                dev->hard_header_len = 0;
-                dev->do_ioctl        = fst_ioctl;
-                dev->change_mtu      = fst_change_mtu;
-                dev->flags           = IFF_POINTOPOINT|IFF_NOARP;
-
-                return 0;
-        }
-
-        /* Turn on sPPP ? */
-        if (( new_proto == FST_HDLC || new_proto == FST_PPP )
-                && ( port->proto != FST_HDLC && port->proto != FST_PPP ))
-        {
-                orig_mtu = dev->mtu;
-
-                /* Attach to sync PPP module */
-                port->pppdev.dev = dev;
-                sppp_attach ( &port->pppdev );
-
-                if ( orig_mtu < dev->mtu )
-                        dev->change_mtu ( dev, orig_mtu );
-
-                /* Claw back the ioctl routine. We promise to be good and call
-                 * the sync PPP routines once we've eliminated our functions.
-                 */
-                dev->do_ioctl = fst_ioctl;
-
-                /* Set the mode */
-                if ( new_proto == FST_HDLC )
-                {
-                        err = sppp_do_ioctl ( port->pppdev.dev, NULL,
-                                                                SPPPIOCCISCO );
-                }
-                else
-                {
-                        err = sppp_do_ioctl ( port->pppdev.dev, NULL,
-                                                                SPPPIOCPPP );
-                }
-
-                /* Open the device */
-                if ( err == 0 )
-                {
-                        (void) sppp_open ( port->dev );
-                }
-
-                return err;
-        }
-
-        /* Switch sPPP mode to that desired */
-        err = 0;
-        if ( new_proto == FST_HDLC && port->pppdev.dev != NULL )
-        {
-                err = sppp_do_ioctl ( port->pppdev.dev, NULL, SPPPIOCCISCO );
-        }
-        else if ( new_proto == FST_PPP && port->pppdev.dev != NULL )
-        {
-                err = sppp_do_ioctl ( port->pppdev.dev, NULL, SPPPIOCPPP );
-        }
-
-        /* Anything else is switching from one raw mode to another which is
-         * basically a NOP
-         */
-
-        return err;
-}
-
-
-static int
 set_conf_from_info ( struct fst_card_info *card, struct fst_port_info *port,
                 struct fstioc_info *info )
 {
         int err;
 
-        /* Set things according to the user set valid flags */
+        /* Set things according to the user set valid flags.
+         * Several of the old options have been invalidated/replaced by the
+         * generic HDLC package.
+         */
         err = 0;
         if ( info->valid & FSTVAL_PROTO )
-        {
-                if ( port->proto != info->proto )
-                {
-                        err = switch_proto ( port, info->proto );
-                        if ( err == 0 )
-                                port->proto = info->proto;
-                }
-        }
+                err = -EINVAL;
         if ( info->valid & FSTVAL_CABLE )
-        {
-                FST_WRB ( card, portConfig[port->index].lineInterface,
-                                        info->lineInterface );
-                port->hwif = info->lineInterface;
-        }
+                err = -EINVAL;
         if ( info->valid & FSTVAL_SPEED )
-        {
-                FST_WRL ( card, portConfig[port->index].lineSpeed,
-                                        info->lineSpeed );
-                FST_WRB ( card, portConfig[port->index].internalClock,
-                                        info->internalClock );
-        }
+                err = -EINVAL;
+
         if ( info->valid & FSTVAL_MODE )
-        {
                 FST_WRW ( card, cardMode, info->cardMode );
-        }
 #if FST_DEBUG
         if ( info->valid & FSTVAL_DEBUG )
-        {
                 fst_debug_mask = info->debug;
-        }
 #endif
 
         return err;
@@ -1125,7 +981,7 @@
         info->nports = card->nports;
         info->type   = card->type;
         info->state  = card->state;
-        info->proto  = port->proto;
+        info->proto  = FST_GEN_HDLC;
         info->index  = i;
 #if FST_DEBUG
         info->debug  = fst_debug_mask;
@@ -1154,6 +1010,107 @@
 
 
 static int
+fst_set_iface ( struct fst_card_info *card, struct fst_port_info *port,
+                struct ifreq *ifr )
+{
+        sync_serial_settings sync;
+        int i;
+
+        if (copy_from_user (&sync, ifr->ifr_settings.ifs_ifsu.sync,
+			    sizeof (sync)))
+                return -EFAULT;
+
+        if ( sync.loopback )
+                return -EINVAL;
+
+        i = port->index;
+
+        switch (ifr->ifr_settings.type)
+        {
+        case IF_IFACE_V35:
+                FST_WRW ( card, portConfig[i].lineInterface, V35 );
+                port->hwif = V35;
+                break;
+
+        case IF_IFACE_V24:
+                FST_WRW ( card, portConfig[i].lineInterface, V24 );
+                port->hwif = V24;
+                break;
+
+        case IF_IFACE_X21:
+                FST_WRW ( card, portConfig[i].lineInterface, X21 );
+                port->hwif = X21;
+                break;
+
+        case IF_IFACE_SYNC_SERIAL:
+                break;
+
+        default:
+                return -EINVAL;
+        }
+
+        switch ( sync.clock_type )
+        {
+        case CLOCK_EXT:
+                FST_WRB ( card, portConfig[i].internalClock, EXTCLK );
+                break;
+
+        case CLOCK_INT:
+                FST_WRB ( card, portConfig[i].internalClock, INTCLK );
+                break;
+
+        default:
+                return -EINVAL;
+        }
+        FST_WRL ( card, portConfig[i].lineSpeed, sync.clock_rate );
+        return 0;
+}
+
+static int
+fst_get_iface ( struct fst_card_info *card, struct fst_port_info *port,
+                struct ifreq *ifr )
+{
+        sync_serial_settings sync;
+        int i;
+
+        /* First check what line type is set, we'll default to reporting X.21
+         * if nothing is set as IF_IFACE_SYNC_SERIAL implies it can't be
+         * changed
+         */
+        switch ( port->hwif )
+        {
+        case V35:
+                ifr->ifr_settings.type = IF_IFACE_V35;
+                break;
+        case V24:
+                ifr->ifr_settings.type = IF_IFACE_V24;
+                break;
+        case X21:
+        default:
+                ifr->ifr_settings.type = IF_IFACE_X21;
+                break;
+        }
+
+	if (ifr->ifr_settings.size < sizeof(sync)) {
+		ifr->ifr_settings.size = sizeof(sync); /* data size wanted */
+		return -ENOBUFS;
+	}
+
+        i = port->index;
+        sync.clock_rate = FST_RDL ( card, portConfig[i].lineSpeed );
+        /* Lucky card and linux use same encoding here */
+        sync.clock_type = FST_RDB ( card, portConfig[i].internalClock );
+        sync.loopback = 0;
+
+        if (copy_to_user (ifr->ifr_settings.ifs_ifsu.sync, &sync,
+			  sizeof(sync)))
+                return -EFAULT;
+
+        return 0;
+}
+
+
+static int
 fst_ioctl ( struct net_device *dev, struct ifreq *ifr, int cmd )
 {
         struct fst_card_info *card;
@@ -1164,7 +1121,7 @@
 
         dbg ( DBG_IOCTL,"ioctl: %x, %p\n", cmd, ifr->ifr_data );
 
-        port = dev->priv;
+        port = dev_to_port ( dev );
         card = port->card;
 
         if ( !capable ( CAP_NET_ADMIN ))
@@ -1201,7 +1158,7 @@
                  * when going over the top
                  */
                 if ( wrthdr.size > FST_MEMSIZE || wrthdr.offset > FST_MEMSIZE
-                                || wrthdr.size + wrthdr.offset > FST_MEMSIZE )
+				|| wrthdr.size + wrthdr.offset > FST_MEMSIZE )
                 {
                         return -ENXIO;
                 }
@@ -1261,6 +1218,9 @@
 
         case FSTSETCONF:
 
+                /* Most of the setting have been moved to the generic ioctls
+                 * this just covers debug and board ident mode now
+                 */
                 if ( copy_from_user ( &info,  ifr->ifr_data, sizeof ( info )))
                 {
                         return -EFAULT;
@@ -1268,12 +1228,25 @@
 
                 return set_conf_from_info ( card, port, &info );
 
+        case SIOCWANDEV:
+                switch (ifr->ifr_settings.type)
+                {
+                case IF_GET_IFACE:
+                        return fst_get_iface ( card, port, ifr );
+
+                case IF_IFACE_SYNC_SERIAL:
+                case IF_IFACE_V35:
+                case IF_IFACE_V24:
+                case IF_IFACE_X21:
+                        return fst_set_iface ( card, port, ifr );
+
+                default:
+                        return hdlc_ioctl ( dev, ifr, cmd );
+                }
+
         default:
-                /* Not one of ours. Pass it through to sPPP package */
-                if ( port->proto == FST_HDLC || port->proto == FST_PPP )
-                        return sppp_do_ioctl ( dev, ifr, cmd );
-                else
-                        return -EINVAL;
+                /* Not one of ours. Pass through to HDLC package */
+                return hdlc_ioctl ( dev, ifr, cmd );
         }
 }
 
@@ -1306,9 +1279,9 @@
                 signals = FST_RDL ( port->card, v24DebouncedSts[port->index]);
                 if ( signals & (( port->hwif == X21 ) ? IPSTS_INDICATE
                                                       : IPSTS_DCD ))
-                        netif_carrier_on ( port->dev );
+                        netif_carrier_on ( port_to_dev ( port ));
                 else
-                        netif_carrier_off ( port->dev );
+                        netif_carrier_off ( port_to_dev ( port ));
         }
 }
 
@@ -1335,64 +1308,15 @@
 static int
 fst_open ( struct net_device *dev )
 {
-        struct fst_card_info *card;
-        struct fst_port_info *port;
-        int orig_mtu;
         int err;
 
-        MOD_INC_USE_COUNT;
-
-        port = dev->priv;
-        card = port->card;
-
-        switch ( port->proto )
-        {
-        case FST_HDLC:
-        case FST_PPP:
-
-                orig_mtu = dev->mtu;
-
-                /* Attach to sync PPP module */
-                port->pppdev.dev = dev;
-                sppp_attach ( &port->pppdev );
-
-                if ( orig_mtu < dev->mtu )
-                        dev->change_mtu ( dev, orig_mtu );
-
-                /* Claw back the ioctl routine. We promise to be good and call
-                 * the sync PPP routines once we've eliminated our functions.
-                 */
-                dev->do_ioctl = fst_ioctl;
-
-                err = sppp_do_ioctl ( dev, NULL, port->proto == FST_HDLC
-                                                ? SPPPIOCCISCO : SPPPIOCPPP );
-                if ( err )
-		{
-			sppp_detach ( dev );
-			MOD_DEC_USE_COUNT;
-			return err;
-		}
-
-                err = sppp_open ( dev );
-                if ( err )
-		{
-			sppp_detach ( dev );
-			MOD_DEC_USE_COUNT;
-			return err;
-		}
-                break;
-
-        case FST_MONITOR:
-        case FST_RAW:
-                break;
-
-        default:
-                dbg ( DBG_OPEN,"open: Unknown proto %d\n", port->proto );
-                break;
-        }
+        err = hdlc_open ( dev_to_hdlc ( dev ));
+        if ( err )
+                return err;
 
-        fst_openport ( port );
+        MOD_INC_USE_COUNT;
 
+        fst_openport ( dev_to_port ( dev ));
         netif_wake_queue ( dev );
         return 0;
 }
@@ -1400,34 +1324,22 @@
 static int
 fst_close ( struct net_device *dev )
 {
-        struct fst_port_info *port;
-
-        port = dev->priv;
-
         netif_stop_queue ( dev );
-        switch ( port->proto )
-        {
-        case FST_HDLC:
-        case FST_PPP:
-                sppp_close ( dev );
-                sppp_detach ( dev );
-                break;
-
-        case FST_MONITOR:
-        case FST_RAW:
-                break;
-
-        default:
-                dbg ( DBG_OPEN,"close: Unknown proto %d\n", port->proto );
-                break;
-        }
-
-        fst_closeport ( port );
-
+        fst_closeport ( dev_to_port ( dev ));
+        hdlc_close ( dev_to_hdlc  ( dev ));
         MOD_DEC_USE_COUNT;
         return 0;
 }
 
+static int
+fst_attach ( hdlc_device *hdlc, unsigned short encoding, unsigned short parity )
+{
+        /* Setting currently fixed in FarSync card so we check and forget */
+        if ( encoding != ENCODING_NRZ || parity != PARITY_CRC16_PR1_CCITT )
+                return -EINVAL;
+        return 0;
+}
+
 
 static void
 fst_tx_timeout ( struct net_device *dev )
@@ -1436,10 +1348,10 @@
 
         dbg ( DBG_INTR | DBG_TX,"tx_timeout\n");
 
-        port = dev->priv;
+        port = dev_to_port ( dev );
 
-        port->stats.tx_errors++;
-        port->stats.tx_aborted_errors++;
+        port->hdlc.stats.tx_errors++;
+        port->hdlc.stats.tx_aborted_errors++;
 
         if ( port->txcnt > 0 )
                 fst_issue_cmd ( port, ABORTTX );
@@ -1459,22 +1371,15 @@
         int pi;
         int txp;
 
-        port = dev->priv;
+        port = dev_to_port ( dev );
         card = port->card;
 
-        /* Drop packet if in monitor (rx only) mode */
-        if ( port->proto == FST_MONITOR )
-        {
-                dev_kfree_skb ( skb );
-                return 0;
-        }
-
         /* Drop packet with error if we don't have carrier */
         if ( ! netif_carrier_ok ( dev ))
         {
                 dev_kfree_skb ( skb );
-                port->stats.tx_errors++;
-                port->stats.tx_carrier_errors++;
+                port->hdlc.stats.tx_errors++;
+                port->hdlc.stats.tx_carrier_errors++;
                 return 0;
         }
 
@@ -1484,7 +1389,7 @@
                 dbg ( DBG_TX,"Packet too large %d vs %d\n", skb->len,
                                                 LEN_TX_BUFFER );
                 dev_kfree_skb ( skb );
-                port->stats.tx_errors++;
+                port->hdlc.stats.tx_errors++;
                 return 0;
         }
 
@@ -1498,7 +1403,7 @@
                 spin_unlock_irqrestore ( &card->card_lock, flags );
                 dbg ( DBG_TX,"Out of Tx buffers\n");
                 dev_kfree_skb ( skb );
-                port->stats.tx_errors++;
+                port->hdlc.stats.tx_errors++;
                 return 0;
         }
         if ( ++port->txpos >= NUM_TX_BUFFER )
@@ -1518,8 +1423,8 @@
         FST_WRW ( card, txDescrRing[pi][txp].bcnt, cnv_bcnt ( skb->len ));
         FST_WRB ( card, txDescrRing[pi][txp].bits, DMA_OWN | TX_STP | TX_ENP );
 
-        port->stats.tx_packets++;
-        port->stats.tx_bytes += skb->len;
+        port->hdlc.stats.tx_packets++;
+        port->hdlc.stats.tx_bytes += skb->len;
 
         dev_kfree_skb ( skb );
 
@@ -1528,18 +1433,6 @@
 }
 
 
-static struct net_device_stats *
-fst_get_stats ( struct net_device *dev )
-{
-        struct fst_port_info *port;
-
-        if (( port = dev->priv ) != NULL )
-                return &port->stats;
-        else
-                return NULL;
-}
-
-
 /*
  *      Card setup having checked hardware resources.
  *      Should be pretty bizarre if we get an error here (kernel memory
@@ -1566,34 +1459,13 @@
          */
         for ( i = 0 ; i < card->nports ; i++ )
         {
-                card->ports[i].if_ptr = &card->ports[i].pppdev;
                 card->ports[i].card   = card;
                 card->ports[i].index  = i;
-                card->ports[i].proto  = FST_HDLC;
                 card->ports[i].run    = 0;
 
-                dev = kmalloc ( sizeof ( struct net_device ), GFP_KERNEL );
-                if ( dev == NULL )
-                {
-                        printk_err ("Cannot allocate net_device for port %d\n",
-                                        i );
-                        /* No point going any further */
-                        card->nports = i;
-                        break;
-                }
-                memset ( dev, 0, sizeof ( struct net_device ));
-                card->ports[i].dev = dev;
-
-                if ( dev_alloc_name ( dev, FST_NDEV_NAME "%d") < 0 )
-                {
-                        printk_err ("Cannot allocate i/f name for port %d\n",
-                                        i );
-                        kfree ( dev );
-                        card->nports = i;
-                        break;
-                }
+                dev = hdlc_to_dev ( &card->ports[i].hdlc );
 
-                /* Fill in remainder of the net device info */
+                /* Fill in the net device info */
                                 /* Since this is a PCI setup this is purely
                                  * informational. Give them the buffer addresses
                                  * and basic card I/O.
@@ -1609,26 +1481,19 @@
                 dev->base_addr   = card->pci_conf;
                 dev->irq         = card->irq;
 
-                dev->get_stats          = fst_get_stats;
-                dev->mtu                = FST_DEF_MTU;
-                dev->change_mtu         = fst_change_mtu;
-                dev->priv               = &card->ports[i];
-                dev->tx_queue_len       = FST_TX_QUEUE_LEN;
-                dev->type               = ARPHRD_MYTYPE;
-                dev->addr_len           = 0;
-                dev->open               = fst_open;
-                dev->stop               = fst_close;
-                dev->hard_start_xmit    = fst_start_xmit;
-                dev->do_ioctl           = fst_ioctl;
-                dev->watchdog_timeo     = FST_TX_TIMEOUT;
-                dev->tx_timeout         = fst_tx_timeout;
-                dev->flags              = IFF_POINTOPOINT|IFF_NOARP;
-
-                if (( err = register_netdev ( dev )) < 0 )
-                {
-                        printk_err ("Cannot register %s (errno %d)\n",
-                                        dev->name, -err );
-                        kfree ( dev );
+                dev->tx_queue_len          = FST_TX_QUEUE_LEN;
+                dev->open                  = fst_open;
+                dev->stop                  = fst_close;
+                dev->do_ioctl              = fst_ioctl;
+                dev->watchdog_timeo        = FST_TX_TIMEOUT;
+                dev->tx_timeout            = fst_tx_timeout;
+                card->ports[i].hdlc.attach = fst_attach;
+                card->ports[i].hdlc.xmit   = fst_start_xmit;
+
+                if (( err = register_hdlc_device ( &card->ports[i].hdlc )) < 0 )
+                {
+                        printk_err ("Cannot register HDLC device for port %d"
+                                    " (errno %d)\n", i, -err );
                         card->nports = i;
                         break;
                 }
@@ -1637,8 +1502,8 @@
         spin_lock_init ( &card->card_lock );
 
         printk ( KERN_INFO "%s-%s: %s IRQ%d, %d ports\n",
-                        card->ports[0].dev->name,
-                        card->ports[card->nports-1].dev->name,
+                        hdlc_to_dev(&card->ports[0].hdlc)->name,
+                        hdlc_to_dev(&card->ports[card->nports-1].hdlc)->name,
                         type_strings[card->type], card->irq, card->nports );
 }
 
@@ -1789,8 +1654,7 @@
 
         for ( i = 0 ; i < card->nports ; i++ )
         {
-                unregister_netdev ( card->ports[i].dev );
-                kfree ( card->ports[i].dev );
+                unregister_hdlc_device ( &card->ports[i].hdlc );
         }
 
         fst_disable_intr ( card );
@@ -1830,4 +1694,3 @@
 module_init ( fst_init );
 module_exit ( fst_cleanup_module );
 
-MODULE_LICENSE("GPL");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)