patch-2.3.99-pre1 linux/drivers/usb/pegasus.c
Next file: linux/drivers/usb/serial/Makefile
Previous file: linux/drivers/usb/ov511.h
Back to the patch index
Back to the overall index
- Lines: 882
- Date:
Mon Mar 13 16:33:10 2000
- Orig file:
v2.3.51/linux/drivers/usb/pegasus.c
- Orig date:
Fri Mar 10 16:40:45 2000
diff -u --recursive --new-file v2.3.51/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c
@@ -1,578 +1,474 @@
/*
-**
** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller
**
-** Copyleft (L) 1999 Petko Manolov - Petkan (petkan@spct.net)
-**
+** Copyright (R) 1999,2000 Petko Manolov - Petkan (petkan@spct.net)
+**
** Distribute under GPL version 2 or later.
*/
-
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/usb.h>
-
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/usb.h>
-#if LINUX_VERSION_CODE<0x2032d || !defined(__KERNEL__) || !defined(__OPTIMIZE__)
-#error You can not compile this driver on this kernel with this C options!
-#endif
-
-
-#define ADMTEK_VENDOR_ID 0x07a6
-#define ADMTEK_HPNA_PEGASUS 0x0986
-
-#define HPNA_MTU 1500
-#define MAX_MTU 1536
-#define TX_TIMEOUT (HZ*5)
-#define SOMETHING (jiffies + TX_TIMEOUT)
+static const char *version = __FILE__ ": v0.3.3 2000/03/13 Written by Petko Manolov (petkan@spct.net)\n";
-static const char version[] = "pegasus.c: v0.2.27 2000/02/29 Written by Petko Manolov (petkan@spct.net)\n";
+#define ADMTEK_VENDOR_ID 0x07a6
+#define ADMTEK_DEVICE_ID_PEGASUS 0x0986
+#define PEGASUS_MTU 1500
+#define PEGASUS_MAX_MTU 1536
+#define PEGASUS_TX_TIMEOUT (HZ*5)
+#define ALIGN(x) x __attribute__((aligned(16)))
-typedef struct usb_hpna
-{
- struct usb_device *usb_dev;
- struct net_device *net_dev;
- int present;
- int active;
- void *irq_handler;
- struct list_head list;
+struct pegasus {
+ struct usb_device *usb;
+ struct net_device *net;
struct net_device_stats stats;
- spinlock_t hpna_lock;
- struct timer_list timer;
-
- unsigned int rx_pipe;
- unsigned char * rx_buff;
- urb_t rx_urb;
-
- unsigned int tx_pipe;
- unsigned char * tx_buff;
- urb_t tx_urb;
- struct sk_buff * tx_skbuff;
-
- __u8 intr_ival;
- unsigned int intr_pipe;
- unsigned char intr_buff[8];
- urb_t intr_urb;
-} usb_hpna_t;
-
-
-usb_hpna_t usb_dev_hpna;
-static int loopback = 0;
-int multicast_filter_limit = 32;
-static LIST_HEAD(hpna_list);
+ spinlock_t pegasus_lock;
+ struct urb rx_urb, tx_urb, intr_urb;
+ unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]);
+ unsigned char ALIGN(tx_buff[PEGASUS_MAX_MTU]);
+ unsigned char ALIGN(intr_buff[8]);
+};
+static int loopback = 0;
+static int multicast_filter_limit = 32;
MODULE_AUTHOR("Petko Manolov <petkan@spct.net>");
-MODULE_DESCRIPTION("ADMtek \"Pegasus\" USB Ethernet driver");
+MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver");
MODULE_PARM(loopback, "i");
-
-/*** vendor specific commands ***/
-static __inline__ int hpna_get_registers( struct usb_device *dev, __u16 indx, __u16 size, void *data )
-{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev,0), 0xf0, 0xc0, 0,
- indx, data, size, HZ);
-}
-
-
-static __inline__ int hpna_set_register( struct usb_device *dev, __u16 indx, __u8 value )
-{
- __u8 data = value;
- return usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0xf1, 0x40,
- data, indx, &data, 1, HZ);
-}
-
-
-static __inline__ int hpna_set_registers( struct usb_device *dev, __u16 indx, __u16 size, void *data )
-{
- return usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0xf1, 0x40, 0,
- indx, data, size, HZ);
-}
-
-
-static int read_phy_word( struct usb_device *dev, __u8 index, __u16 *regdata )
-{
- int i;
- __u8 data[4];
-
- data[0] = 1;
- data[1] = 0;
- data[2] = 0;
- data[3] = 0x40 + index;
- hpna_set_registers( dev, 0x25, 4, data );
- for ( i=0; i<100; i++ ) {
- hpna_get_registers( dev, 0x25, 4, data );
- if ( data[3] & 0x80 ) {
- *regdata = *(__u16 *)(data+1);
- return 0;
+#define pegasus_get_registers(dev, indx, size, data)\
+ usb_control_msg(dev, usb_rcvctrlpipe(dev,0), 0xf0, 0xc0, 0, indx, data, size, HZ);
+#define pegasus_set_registers(dev, indx, size, data)\
+ usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0xf1, 0x40, 0, indx, data, size, HZ);
+#define pegasus_set_register(dev, indx, value) \
+ { __u8 data = value; \
+ usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0xf1, 0x40, data, indx, &data, 1, HZ);}
+
+
+static int pegasus_read_phy_word(struct usb_device *dev, __u8 index, __u16 *regdata)
+{
+ int i;
+ __u8 data[4] = { 1, 0, 0, 0x40 + index };
+
+ pegasus_set_registers(dev, 0x25, 4, data);
+ for (i = 0; i < 100; i++) {
+ pegasus_get_registers(dev, 0x26, 3, data);
+ if (data[2] & 0x80) {
+ *regdata = *(__u16 *)(data);
+ return 0;
}
udelay(100);
}
+
warn("read_phy_word() failed");
- return 1;
+ return 1;
}
-
-static int write_phy_word( struct usb_device *dev, __u8 index, __u16 regdata )
+static int pegasus_write_phy_word(struct usb_device *dev, __u8 index, __u16 regdata)
{
- int i;
- __u8 data[4];
+ int i;
+ __u8 data[4] = { 1, regdata, regdata >> 8, 0x20 + index };
- data[0] = 1;
- data[1] = regdata;
- data[2] = regdata >> 8;
- data[3] = 0x20 + index;
- hpna_set_registers( dev, 0x25, 4, data );
- for ( i=0; i<100; i++ ) {
- hpna_get_registers( dev, 0x28, 1, data );
- if ( data[0] & 0x80 ) {
- return 0;
- }
+ pegasus_set_registers(dev, 0x25, 4, data);
+ for (i = 0; i < 100; i++) {
+ pegasus_get_registers(dev, 0x28, 1, data);
+ if (data[0] & 0x80)
+ return 0;
udelay(100);
}
+
warn("write_phy_word() failed");
- return 1;
+ return 1;
}
-
-int read_srom_word( struct usb_device *dev, __u8 index, __u16 *retdata)
+static int pegasus_read_srom_word(struct usb_device *dev, __u8 index, __u16 *retdata)
{
- int i;
- __u8 data[4];
+ int i;
+ __u8 data[4] = { index, 0, 0, 0x02 };
- data[0] = index;
- data[1] = data[2] = 0;
- data[3] = 0x02;
- hpna_set_registers(dev, 0x20, 4, data);
- for ( i=0; i<100; i++ ) {
- hpna_get_registers(dev, 0x23, 1, data);
- if ( data[0] & 4 ) {
- hpna_get_registers(dev, 0x21, 2, data);
+ pegasus_set_registers(dev, 0x20, 4, data);
+ for (i = 0; i < 100; i++) {
+ pegasus_get_registers(dev, 0x23, 1, data);
+ if (data[0] & 4) {
+ pegasus_get_registers(dev, 0x21, 2, data);
*retdata = *(__u16 *)data;
- return 0;
+ return 0;
}
}
+
warn("read_srom_word() failed");
- return 1;
+ return 1;
}
-/*** end ***/
-
-
-
-int get_node_id( struct usb_device *dev, __u8 *id )
+static int pegasus_get_node_id(struct usb_device *dev, __u8 *id)
{
- int i;
-
- for ( i=0; i<3; i++ ) {
- if ( read_srom_word(dev, i, (__u16 *)&id[i*2] ) )
- return 1;
- }
- return 0;
+ int i;
+ for (i = 0; i < 3; i++)
+ if (pegasus_read_srom_word(dev, i, (__u16 *)&id[i * 2]))
+ return 1;
+ return 0;
}
-
-static int reset_mac( struct usb_device *dev )
+static int pegasus_reset_mac(struct usb_device *dev)
{
- __u8 data = 0x8;
- int i;
-
- hpna_set_register( dev, 1, 0x08 );
- for ( i=0; i<100; i++ ) {
- hpna_get_registers( dev, 1, 1, &data);
- if ( !(data & 0x08) ) {
- if ( loopback & 1 )
- return 0;
- else if ( loopback & 2 ) {
- write_phy_word( dev, 0, 0x4000 );
- /*return 0;*/
- }
- hpna_set_register( dev, 0x7e, 0x24 );
- hpna_set_register( dev, 0x7e, 0x27 );
- return 0;
+ __u8 data = 0x8;
+ int i;
+
+ pegasus_set_register(dev, 1, data);
+ for (i = 0; i < 100; i++) {
+ pegasus_get_registers(dev, 1, 1, &data);
+ if (~data & 0x08) {
+ if (loopback & 1)
+ return 0;
+ if (loopback & 2)
+ pegasus_write_phy_word(dev, 0, 0x4000);
+ pegasus_set_register(dev, 0x7e, 0x24);
+ pegasus_set_register(dev, 0x7e, 0x27);
+ return 0;
}
}
+
return 1;
}
-
-int start_net( struct net_device *dev, struct usb_device *usb_dev )
+static int pegasus_start_net(struct net_device *dev, struct usb_device *usb)
{
- __u16 partmedia, temp;
- __u8 node_id[6];
- __u8 data[4];
-
- if ( get_node_id(usb_dev, node_id) )
- return 1;
- hpna_set_registers(usb_dev, 0x10, 6, node_id);
+ __u16 partmedia, temp;
+ __u8 node_id[6];
+ __u8 data[4];
+
+ if (pegasus_get_node_id(usb, node_id))
+ return 1;
+
+ pegasus_set_registers(usb, 0x10, 6, node_id);
memcpy(dev->dev_addr, node_id, 6);
- if ( read_phy_word(usb_dev, 1, &temp) )
- return 2;
- if ( !(temp & 4) ) {
- if ( loopback )
- goto ok;
+ if (pegasus_read_phy_word(usb, 1, &temp))
+ return 2;
+
+ if ((~temp & 4) && !loopback) {
err("link NOT established - %x", temp);
- return 3;
+ return 3;
}
-ok:
- if ( read_phy_word(usb_dev, 5, &partmedia) )
- return 4;
- temp = partmedia;
- partmedia &= 0x1f;
- if ( partmedia != 1 ) {
- err("party FAIL %x", temp);
- return 5;
- }
- partmedia = temp;
- if ( partmedia & 0x100 )
- data[1] = 0x30;
- else {
- if ( partmedia & 0x80 )
- data[1] = 0x10;
- else
- data[1] = 0;
+
+ if (pegasus_read_phy_word(usb, 5, &partmedia))
+ return 4;
+
+ if ((partmedia & 0x1f) != 1) {
+ err("party FAIL %x", partmedia);
+ return 5;
}
-
+
data[0] = 0xc9;
- data[2] = (loopback & 1) ? 0x08 : 0x00;
-
- hpna_set_registers(usb_dev, 0, 3, data);
-
- return 0;
-}
+ data[1] = (partmedia & 0x100) ? 0x30 : ((partmedia & 0x80) ? 0x10 : 0);
+ data[2] = (loopback & 1) ? 0x08 : 0x00;
+ pegasus_set_registers(usb, 0, 3, data);
-static void hpna_read_irq( purb_t urb )
-{
- struct net_device *net_dev = urb->context;
- usb_hpna_t *hpna = net_dev->priv;
- int count = urb->actual_length, res;
- int rx_status = *(int *)(hpna->rx_buff + count - 4);
+ return 0;
+}
+static void pegasus_read_bulk(struct urb *urb)
+{
+ struct pegasus *pegasus = urb->context;
+ struct net_device *net = pegasus->net;
+ int count = urb->actual_length, res;
+ int rx_status = *(int *)(pegasus->rx_buff + count - 4);
+ struct sk_buff *skb;
+ __u16 pkt_len;
- if ( urb->status ) {
- info( "%s: RX status %d\n", net_dev->name, urb->status );
+ if (urb->status) {
+ info("%s: RX status %d", net->name, urb->status);
goto goon;
}
- if ( !count )
+ if (!count)
goto goon;
-/* if ( rx_status & 0x00010000 )
+#if 0
+ if (rx_status & 0x00010000)
goto goon;
-*/
- if ( rx_status & 0x000e0000 ) {
- dbg("%s: error receiving packet %x",
- net_dev->name, rx_status & 0xe0000);
- hpna->stats.rx_errors++;
- if(rx_status & 0x060000) hpna->stats.rx_length_errors++;
- if(rx_status & 0x080000) hpna->stats.rx_crc_errors++;
- if(rx_status & 0x100000) hpna->stats.rx_frame_errors++;
- } else {
- struct sk_buff *skb;
- __u16 pkt_len = (rx_status & 0xfff) - 8;
+#endif
+ if (rx_status & 0x000e0000) {
+ dbg("%s: error receiving packet %x", net->name, rx_status & 0xe0000);
+ pegasus->stats.rx_errors++;
+ if(rx_status & 0x060000) pegasus->stats.rx_length_errors++;
+ if(rx_status & 0x080000) pegasus->stats.rx_crc_errors++;
+ if(rx_status & 0x100000) pegasus->stats.rx_frame_errors++;
- if((skb = dev_alloc_skb(pkt_len+2)) != NULL ) {
- skb->dev = net_dev;
- skb_reserve(skb, 2);
- eth_copy_and_sum(skb, hpna->rx_buff, pkt_len, 0);
- skb_put(skb, pkt_len);
- } else
- goto goon;
- skb->protocol = eth_type_trans(skb, net_dev);
- netif_rx(skb);
- hpna->stats.rx_packets++;
- hpna->stats.rx_bytes += pkt_len;
+ goto goon;
}
+
+ pkt_len = (rx_status & 0xfff) - 8;
+
+ if(!(skb = dev_alloc_skb(pkt_len+2)))
+ goto goon;
+
+ skb->dev = net;
+ skb_reserve(skb, 2);
+ eth_copy_and_sum(skb, pegasus->rx_buff, pkt_len, 0);
+ skb_put(skb, pkt_len);
+
+ skb->protocol = eth_type_trans(skb, net);
+ netif_rx(skb);
+ pegasus->stats.rx_packets++;
+ pegasus->stats.rx_bytes += pkt_len;
+
goon:
- if ( (res = usb_submit_urb( &hpna->rx_urb )) )
- warn("failed rx_urb %d", res);
+ if ((res = usb_submit_urb(&pegasus->rx_urb)))
+ warn("(prb)failed rx_urb %d", res);
}
-
-static void hpna_irq( urb_t *urb)
+static void pegasus_irq(urb_t *urb)
{
- if( urb->status ) {
+ if(urb->status) {
__u8 *d = urb->transfer_buffer;
printk("txst0 %x, txst1 %x, rxst %x, rxlst0 %x, rxlst1 %x, wakest %x",
- d[0], d[1], d[2], d[3], d[4], d[5] );
+ d[0], d[1], d[2], d[3], d[4], d[5]);
}
}
-
-static void hpna_write_irq( purb_t urb )
+static void pegasus_write_bulk(struct urb *urb)
{
- struct net_device *net_dev = urb->context;
- usb_hpna_t *hpna = net_dev->priv;
+ struct pegasus *pegasus = urb->context;
+ spin_lock(&pegasus->pegasus_lock);
- spin_lock( &hpna->hpna_lock );
-
- if ( urb->status )
- info("%s: TX status %d\n", net_dev->name, urb->status);
- netif_wake_queue( net_dev );
+ if (urb->status)
+ info("%s: TX status %d", pegasus->net->name, urb->status);
+ netif_wake_queue(pegasus->net);
- spin_unlock( &hpna->hpna_lock );
+ spin_unlock(&pegasus->pegasus_lock);
}
-
-static void tx_timeout( struct net_device *dev )
+static void pegasus_tx_timeout(struct net_device *net)
{
- usb_hpna_t *hpna = dev->priv;
+ struct pegasus *pegasus = net->priv;
- warn( "%s: Tx timed out. Reseting...", dev->name );
- hpna->stats.tx_errors++;
- dev->trans_start = jiffies;
- netif_wake_queue( dev );
-}
+ warn("%s: Tx timed out. Reseting...", net->name);
+ pegasus->stats.tx_errors++;
+ net->trans_start = jiffies;
+ netif_wake_queue(net);
+}
-static int hpna_start_xmit( struct sk_buff *skb, struct net_device *net_dev )
+static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
{
- usb_hpna_t *hpna = (usb_hpna_t *)net_dev->priv;
- int count = skb->len+2 % 64 ? skb->len+2 : skb->len+3;
- int res;
+ struct pegasus *pegasus = net->priv;
+ int count = ((skb->len+2) & 0x3f) ? skb->len+2 : skb->len+3;
+ int res;
- spin_lock( &hpna->hpna_lock );
+ spin_lock(&pegasus->pegasus_lock);
- netif_stop_queue( net_dev );
- ((__u16 *)hpna->tx_buff)[0] = skb->len;
- memcpy(hpna->tx_buff+2, skb->data, skb->len);
- (&hpna->tx_urb)->transfer_buffer_length = count;
- if ( (res = usb_submit_urb( &hpna->tx_urb )) ) {
+ netif_stop_queue(net);
+
+ ((__u16 *)pegasus->tx_buff)[0] = skb->len;
+ memcpy(pegasus->tx_buff+2, skb->data, skb->len);
+ (&pegasus->tx_urb)->transfer_buffer_length = count;
+
+ if ((res = usb_submit_urb(&pegasus->tx_urb))) {
warn("failed tx_urb %d", res);
- hpna->stats.tx_errors++;
- netif_start_queue( net_dev );
+ pegasus->stats.tx_errors++;
+ netif_start_queue(net);
} else {
- hpna->stats.tx_packets++;
- hpna->stats.tx_bytes += skb->len;
- net_dev->trans_start = jiffies;
+ pegasus->stats.tx_packets++;
+ pegasus->stats.tx_bytes += skb->len;
+ net->trans_start = jiffies;
}
- dev_kfree_skb( skb );
- spin_unlock( &hpna->hpna_lock );
- return 0;
-}
+ dev_kfree_skb(skb);
-static struct net_device_stats *hpna_netdev_stats( struct net_device *dev )
-{
- return &((usb_hpna_t *)dev->priv)->stats;
+ spin_unlock(&pegasus->pegasus_lock);
+
+ return 0;
}
-static int hpna_open( struct net_device *net_dev )
+static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
{
- usb_hpna_t *hpna = (usb_hpna_t *)net_dev->priv;
- int res;
+ return &((struct pegasus *)dev->priv)->stats;
+}
- if ( hpna->active )
- return -EBUSY;
- else
- hpna->active = 1;
+static int pegasus_open(struct net_device *net)
+{
+ struct pegasus *pegasus = (struct pegasus *)net->priv;
+ int res;
- if ( start_net(net_dev, hpna->usb_dev) ) {
- err("can't start_net()");
- return -EIO;
+ if ((res = pegasus_start_net(net, pegasus->usb))) {
+ err("can't start_net() - %d", res);
+ return -EIO;
}
- if ( (res = usb_submit_urb( &hpna->rx_urb )) )
- warn("failed rx_urb %d", res);
+ if ((res = usb_submit_urb(&pegasus->rx_urb)))
+ warn("(open)failed rx_urb %d", res);
-/* usb_submit_urb( &hpna->intr_urb );*/
- netif_start_queue( net_dev );
+/* usb_submit_urb(&pegasus->intr_urb);*/
+ netif_start_queue(net);
MOD_INC_USE_COUNT;
return 0;
}
-
-static int hpna_close( struct net_device *net_dev )
+static int pegasus_close(struct net_device *net)
{
- usb_hpna_t *hpna = net_dev->priv;
-
+ struct pegasus *pegasus = net->priv;
- netif_stop_queue( net_dev );
+ netif_stop_queue(net);
- usb_unlink_urb( &hpna->rx_urb );
- usb_unlink_urb( &hpna->tx_urb );
-/* usb_unlink_urb( hpna->intr_urb );*/
-
- hpna->active = 0;
+ usb_unlink_urb(&pegasus->rx_urb);
+ usb_unlink_urb(&pegasus->tx_urb);
+/* usb_unlink_urb(&pegasus->intr_urb); */
MOD_DEC_USE_COUNT;
return 0;
}
-
-static int hpna_ioctl( struct net_device *dev, struct ifreq *rq, int cmd )
+static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{
- __u16 *data = (__u16 *)&rq->ifr_data;
- usb_hpna_t *hpna = dev->priv;
+ __u16 *data = (__u16 *)&rq->ifr_data;
+ struct pegasus *pegasus = net->priv;
- switch( cmd ) {
- case SIOCDEVPRIVATE:
+ switch(cmd) {
+ case SIOCDEVPRIVATE:
data[0] = 1;
case SIOCDEVPRIVATE+1:
- read_phy_word(hpna->usb_dev, data[1] & 0x1f, &data[3]);
- return 0;
+ pegasus_read_phy_word(pegasus->usb, data[1] & 0x1f, &data[3]);
+ return 0;
case SIOCDEVPRIVATE+2:
- if ( !capable(CAP_NET_ADMIN) )
- return -EPERM;
- write_phy_word(hpna->usb_dev, data[1] & 0x1f, data[2]);
- return 0;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ pegasus_write_phy_word(pegasus->usb, data[1] & 0x1f, data[2]);
+ return 0;
default:
- return -EOPNOTSUPP;
+ return -EOPNOTSUPP;
}
}
-
-static void set_rx_mode( struct net_device *net_dev )
+static void pegasus_set_rx_mode(struct net_device *net)
{
- usb_hpna_t *hpna=net_dev->priv;
+ struct pegasus *pegasus = net->priv;
- netif_stop_queue( net_dev );
-
- if ( net_dev->flags & IFF_PROMISC ) {
- info("%s: Promiscuous mode enabled", net_dev->name);
- hpna_set_register( hpna->usb_dev, 2, 0x04 );
- } else if ((net_dev->mc_count > multicast_filter_limit) ||
- (net_dev->flags & IFF_ALLMULTI)) {
- hpna_set_register(hpna->usb_dev, 0, 0xfa);
- hpna_set_register(hpna->usb_dev, 2, 0);
+ netif_stop_queue(net);
+
+ if (net->flags & IFF_PROMISC) {
+ info("%s: Promiscuous mode enabled", net->name);
+ pegasus_set_register(pegasus->usb, 2, 0x04);
+ } else if ((net->mc_count > multicast_filter_limit) ||
+ (net->flags & IFF_ALLMULTI)) {
+ pegasus_set_register(pegasus->usb, 0, 0xfa);
+ pegasus_set_register(pegasus->usb, 2, 0);
} else {
- dbg("%s: set Rx mode", net_dev->name);
+ dbg("%s: set Rx mode", net->name);
}
- netif_wake_queue( net_dev );
+ netif_wake_queue(net);
}
-
-static void * usb_hpna_probe( struct usb_device *dev, unsigned int ifnum )
+static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum)
{
- struct net_device *net_dev;
- usb_hpna_t *hpna = &usb_dev_hpna;
-
+ struct net_device *net;
+ struct pegasus *pegasus;
-
- if ( dev->descriptor.idVendor != ADMTEK_VENDOR_ID ||
- dev->descriptor.idProduct != ADMTEK_HPNA_PEGASUS ) {
- return NULL;
+ if (dev->descriptor.idVendor != ADMTEK_VENDOR_ID ||
+ dev->descriptor.idProduct != ADMTEK_DEVICE_ID_PEGASUS) {
+ return NULL;
}
- printk("USB HPNA Pegasus found\n");
-
- if ( usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
+ if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
err("usb_set_configuration() failed");
return NULL;
}
- hpna->usb_dev = dev;
-
- hpna->rx_pipe = usb_rcvbulkpipe(hpna->usb_dev, 1);
- hpna->tx_pipe = usb_sndbulkpipe(hpna->usb_dev, 2);
- hpna->intr_pipe = usb_rcvintpipe(hpna->usb_dev, 0);
+ if(!(pegasus = kmalloc(sizeof(struct pegasus), GFP_KERNEL))) {
+ err("out of memory allocating device structure");
+ return NULL;
+ }
+ memset(pegasus, 0, sizeof(struct pegasus));
- if ( reset_mac(dev) ) {
+ if (pegasus_reset_mac(dev)) {
err("can't reset MAC");
+ kfree(pegasus);
+ return NULL;
}
-
- hpna->present = 1;
-
- if(!(hpna->rx_buff=kmalloc(MAX_MTU, GFP_KERNEL))) {
- err("not enough mem for out buff");
- return NULL;
- }
- if(!(hpna->tx_buff=kmalloc(MAX_MTU, GFP_KERNEL))) {
- kfree_s(hpna->rx_buff, MAX_MTU);
- err("not enough mem for out buff");
- return NULL;
- }
-
- net_dev = init_etherdev( 0, 0 );
- hpna->net_dev = net_dev;
- net_dev->priv = hpna;
- net_dev->open = hpna_open;
- net_dev->stop = hpna_close;
- net_dev->watchdog_timeo = TX_TIMEOUT;
- net_dev->tx_timeout = tx_timeout;
- net_dev->do_ioctl = hpna_ioctl;
- net_dev->hard_start_xmit = hpna_start_xmit;
- net_dev->set_multicast_list = set_rx_mode;
- net_dev->get_stats = hpna_netdev_stats;
- net_dev->mtu = HPNA_MTU;
- hpna->hpna_lock = SPIN_LOCK_UNLOCKED;
-
- FILL_BULK_URB( &hpna->rx_urb, hpna->usb_dev, hpna->rx_pipe,
- hpna->rx_buff, MAX_MTU, hpna_read_irq, net_dev );
- FILL_BULK_URB( &hpna->tx_urb, hpna->usb_dev, hpna->tx_pipe,
- hpna->tx_buff, MAX_MTU, hpna_write_irq, net_dev );
- FILL_INT_URB( &hpna->intr_urb, hpna->usb_dev, hpna->intr_pipe,
- hpna->intr_buff, 8, hpna_irq, net_dev, 250 );
-
-/* list_add( &hpna->list, &hpna_list );*/
- return net_dev;
+ net = init_etherdev(0, 0);
+ net->priv = pegasus;
+ net->open = pegasus_open;
+ net->stop = pegasus_close;
+ net->watchdog_timeo = PEGASUS_TX_TIMEOUT;
+ net->tx_timeout = pegasus_tx_timeout;
+ net->do_ioctl = pegasus_ioctl;
+ net->hard_start_xmit = pegasus_start_xmit;
+ net->set_multicast_list = pegasus_set_rx_mode;
+ net->get_stats = pegasus_netdev_stats;
+ net->mtu = PEGASUS_MTU;
+
+ pegasus->usb = dev;
+ pegasus->net = net;
+ pegasus->pegasus_lock = SPIN_LOCK_UNLOCKED;
+
+ FILL_BULK_URB(&pegasus->rx_urb, dev, usb_rcvbulkpipe(dev, 1),
+ pegasus->rx_buff, PEGASUS_MAX_MTU, pegasus_read_bulk,
+ pegasus);
+ FILL_BULK_URB(&pegasus->tx_urb, dev, usb_sndbulkpipe(dev, 2),
+ pegasus->tx_buff, PEGASUS_MAX_MTU, pegasus_write_bulk,
+ pegasus);
+ FILL_INT_URB(&pegasus->intr_urb, dev, usb_rcvintpipe(dev, 0),
+ pegasus->intr_buff, 8, pegasus_irq, pegasus, 250);
+
+
+ printk(KERN_INFO "%s: ADMtek AN986 Pegasus usb device\n", net->name);
+
+ return pegasus;
}
-
-static void usb_hpna_disconnect( struct usb_device *dev, void *ptr )
+static void pegasus_disconnect(struct usb_device *dev, void *ptr)
{
- struct net_device *net_dev = ptr;
- struct usb_hpna *hpna = net_dev->priv;
+ struct pegasus *pegasus = ptr;
+ if (!pegasus) {
+ warn("unregistering non-existant device");
+ return;
+ }
- if ( net_dev->flags & IFF_UP )
- dev_close(net_dev);
-
- unregister_netdev( net_dev );
+ if (pegasus->net->flags & IFF_UP)
+ dev_close(pegasus->net);
- if ( !hpna ) /* should never happen */
- return;
-
- usb_unlink_urb( &hpna->rx_urb );
- usb_unlink_urb( &hpna->tx_urb );
-/* usb_unlink_urb( &hpna->intr_urb );*/
- kfree_s(hpna->rx_buff, MAX_MTU);
- kfree_s(hpna->tx_buff, MAX_MTU);
+ unregister_netdev(pegasus->net);
- hpna->usb_dev = NULL;
- hpna->present = 0;
+ usb_unlink_urb(&pegasus->rx_urb);
+ usb_unlink_urb(&pegasus->tx_urb);
+/* usb_unlink_urb(&pegasus->intr_urb);*/
- printk("USB HPNA disconnected\n");
+ kfree(pegasus);
}
-
-static struct usb_driver usb_hpna_driver = {
- "ADMtek \"Pegasus\" USB Ethernet",
- usb_hpna_probe,
- usb_hpna_disconnect,
- {NULL, NULL}
+static struct usb_driver pegasus_driver = {
+ name: "pegasus",
+ probe: pegasus_probe,
+ disconnect: pegasus_disconnect,
};
-
-
-static int __init start_hpna( void )
+int __init pegasus_init(void)
{
printk( version );
- return usb_register( &usb_hpna_driver );
+ return usb_register(&pegasus_driver);
}
-
-static void __exit stop_hpna( void )
+void __exit pegasus_exit(void)
{
- usb_deregister( &usb_hpna_driver );
+ usb_deregister(&pegasus_driver);
}
-
-module_init( start_hpna );
-module_exit( stop_hpna );
+module_init(pegasus_init);
+module_exit(pegasus_exit);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)