Commit 51b75159 authored by Petko Manolov's avatar Petko Manolov Committed by Greg Kroah-Hartman

[PATCH] ADM8513 support added;

parent 4eba467f
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
* is out of the interrupt routine. * is out of the interrupt routine.
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -46,7 +45,7 @@ ...@@ -46,7 +45,7 @@
/* /*
* Version Information * Version Information
*/ */
#define DRIVER_VERSION "v0.5.6 (2002/06/23)" #define DRIVER_VERSION "v0.5.7 (2002/11/18)"
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>" #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
...@@ -119,16 +118,9 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -119,16 +118,9 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data) void *data)
{ {
int ret; int ret;
unsigned char *buffer; unsigned char buffer[256];
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
return 0;
}
memcpy(buffer, data, size);
add_wait_queue(&pegasus->ctrl_wait, &wait); add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
while (pegasus->flags & ETH_REGS_CHANGED) while (pegasus->flags & ETH_REGS_CHANGED)
...@@ -161,7 +153,6 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -161,7 +153,6 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
out: out:
remove_wait_queue(&pegasus->ctrl_wait, &wait); remove_wait_queue(&pegasus->ctrl_wait, &wait);
memcpy(data, buffer, size); memcpy(data, buffer, size);
kfree(buffer);
return ret; return ret;
} }
...@@ -170,14 +161,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -170,14 +161,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data) void *data)
{ {
int ret; int ret;
unsigned char *buffer; unsigned char buffer[256];
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
return 0;
}
memcpy(buffer, data, size); memcpy(buffer, data, size);
add_wait_queue(&pegasus->ctrl_wait, &wait); add_wait_queue(&pegasus->ctrl_wait, &wait);
...@@ -210,7 +196,6 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -210,7 +196,6 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
schedule(); schedule();
out: out:
remove_wait_queue(&pegasus->ctrl_wait, &wait); remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(buffer);
return ret; return ret;
} }
...@@ -218,17 +203,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -218,17 +203,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
{ {
int ret; int ret;
unsigned char *buffer; __u16 tmp = data;
__u16 dat = data;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(1, GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
return 0;
}
memcpy(buffer, &data, 1);
add_wait_queue(&pegasus->ctrl_wait, &wait); add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
while (pegasus->flags & ETH_REGS_CHANGED) while (pegasus->flags & ETH_REGS_CHANGED)
...@@ -238,7 +215,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) ...@@ -238,7 +215,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
pegasus->dr.bRequest = PEGASUS_REQ_SET_REG; pegasus->dr.bRequest = PEGASUS_REQ_SET_REG;
pegasus->dr.wValue = cpu_to_le16p(&dat); pegasus->dr.wValue = cpu_to_le16p(&tmp);
pegasus->dr.wIndex = cpu_to_le16p(&indx); pegasus->dr.wIndex = cpu_to_le16p(&indx);
pegasus->dr.wLength = cpu_to_le16(1); pegasus->dr.wLength = cpu_to_le16(1);
pegasus->ctrl_urb->transfer_buffer_length = 1; pegasus->ctrl_urb->transfer_buffer_length = 1;
...@@ -246,7 +223,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) ...@@ -246,7 +223,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
usb_sndctrlpipe(pegasus->usb, 0), usb_sndctrlpipe(pegasus->usb, 0),
(char *) &pegasus->dr, (char *) &pegasus->dr,
buffer, 1, ctrl_callback, pegasus); &data, 1, ctrl_callback, pegasus);
add_wait_queue(&pegasus->ctrl_wait, &wait); add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
...@@ -259,7 +236,6 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) ...@@ -259,7 +236,6 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
schedule(); schedule();
out: out:
remove_wait_queue(&pegasus->ctrl_wait, &wait); remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(buffer);
return ret; return ret;
} }
...@@ -294,7 +270,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) ...@@ -294,7 +270,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
__u16 regdi; __u16 regdi;
set_register(pegasus, PhyCtrl, 0); set_register(pegasus, PhyCtrl, 0);
set_registers(pegasus, PhyAddr, sizeof(data), data); set_registers(pegasus, PhyAddr, sizeof (data), data);
set_register(pegasus, PhyCtrl, (indx | PHY_READ)); set_register(pegasus, PhyCtrl, (indx | PHY_READ));
for (i = 0; i < REG_TIMEOUT; i++) { for (i = 0; i < REG_TIMEOUT; i++) {
get_registers(pegasus, PhyCtrl, 1, data); get_registers(pegasus, PhyCtrl, 1, data);
...@@ -311,6 +287,15 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) ...@@ -311,6 +287,15 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
return 1; return 1;
} }
static int mdio_read(struct net_device *dev, int phy_id, int loc)
{
pegasus_t *pegasus = (pegasus_t *) dev->priv;
int res;
read_mii_word(pegasus, phy_id, loc, (u16 *) & res);
return res & 0xffff;
}
static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
{ {
int i; int i;
...@@ -332,6 +317,13 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) ...@@ -332,6 +317,13 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
return 1; return 1;
} }
static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
{
pegasus_t *pegasus = (pegasus_t *) dev->priv;
write_mii_word(pegasus, phy_id, loc, val);
}
static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
{ {
int i; int i;
...@@ -415,8 +407,8 @@ static void set_ethernet_addr(pegasus_t * pegasus) ...@@ -415,8 +407,8 @@ static void set_ethernet_addr(pegasus_t * pegasus)
__u8 node_id[6]; __u8 node_id[6];
get_node_id(pegasus, node_id); get_node_id(pegasus, node_id);
set_registers(pegasus, EthID, sizeof(node_id), node_id); set_registers(pegasus, EthID, sizeof (node_id), node_id);
memcpy(pegasus->net->dev_addr, node_id, sizeof(node_id)); memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
} }
static inline int reset_mac(pegasus_t * pegasus) static inline int reset_mac(pegasus_t * pegasus)
...@@ -473,7 +465,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) ...@@ -473,7 +465,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
data[1] = 0; data[1] = 0;
data[2] = (loopback & 1) ? 0x09 : 0x01; data[2] = (loopback & 1) ? 0x09 : 0x01;
memcpy(pegasus->eth_regs, data, sizeof(data)); memcpy(pegasus->eth_regs, data, sizeof (data));
set_registers(pegasus, EthCtrl0, 3, data); set_registers(pegasus, EthCtrl0, 3, data);
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
...@@ -486,11 +478,11 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) ...@@ -486,11 +478,11 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
return 0; return 0;
} }
static void fill_skb_pool(pegasus_t *pegasus) static void fill_skb_pool(pegasus_t * pegasus)
{ {
int i; int i;
for (i=0; i < RX_SKBS; i++) { for (i = 0; i < RX_SKBS; i++) {
if (pegasus->rx_pool[i]) if (pegasus->rx_pool[i])
continue; continue;
pegasus->rx_pool[i] = dev_alloc_skb(PEGASUS_MTU + 2); pegasus->rx_pool[i] = dev_alloc_skb(PEGASUS_MTU + 2);
...@@ -505,11 +497,11 @@ static void fill_skb_pool(pegasus_t *pegasus) ...@@ -505,11 +497,11 @@ static void fill_skb_pool(pegasus_t *pegasus)
} }
} }
static void free_skb_pool(pegasus_t *pegasus) static void free_skb_pool(pegasus_t * pegasus)
{ {
int i; int i;
for (i=0; i < RX_SKBS; i++) { for (i = 0; i < RX_SKBS; i++) {
if (pegasus->rx_pool[i]) { if (pegasus->rx_pool[i]) {
dev_kfree_skb(pegasus->rx_pool[i]); dev_kfree_skb(pegasus->rx_pool[i]);
pegasus->rx_pool[i] = NULL; pegasus->rx_pool[i] = NULL;
...@@ -517,12 +509,12 @@ static void free_skb_pool(pegasus_t *pegasus) ...@@ -517,12 +509,12 @@ static void free_skb_pool(pegasus_t *pegasus)
} }
} }
static inline struct sk_buff *pull_skb(pegasus_t *pegasus) static inline struct sk_buff *pull_skb(pegasus_t * pegasus)
{ {
int i; int i;
struct sk_buff *skb; struct sk_buff *skb;
for (i=0; i < RX_SKBS; i++) { for (i = 0; i < RX_SKBS; i++) {
if (likely(pegasus->rx_pool[i] != NULL)) { if (likely(pegasus->rx_pool[i] != NULL)) {
skb = pegasus->rx_pool[i]; skb = pegasus->rx_pool[i];
pegasus->rx_pool[i] = NULL; pegasus->rx_pool[i] = NULL;
...@@ -563,7 +555,7 @@ static void read_bulk_callback(struct urb *urb) ...@@ -563,7 +555,7 @@ static void read_bulk_callback(struct urb *urb)
if (!count) if (!count)
goto goon; goto goon;
rx_status = le32_to_cpu(*(int *)(urb->transfer_buffer + count - 4)); rx_status = le32_to_cpu(*(int *) (urb->transfer_buffer + count - 4));
if (rx_status & 0x000e0000) { if (rx_status & 0x000e0000) {
dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000); dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
pegasus->stats.rx_errors++; pegasus->stats.rx_errors++;
...@@ -575,13 +567,17 @@ static void read_bulk_callback(struct urb *urb) ...@@ -575,13 +567,17 @@ static void read_bulk_callback(struct urb *urb)
pegasus->stats.rx_frame_errors++; pegasus->stats.rx_frame_errors++;
goto goon; goto goon;
} }
if (pegasus->chip == 0x8513) {
pkt_len = le32_to_cpu(*(int *)urb->transfer_buffer);
pkt_len &= 0x0fff;
pegasus->rx_skb->data += 2;
} else {
pkt_len = (rx_status & 0xfff) - 8; pkt_len = (rx_status & 0xfff) - 8;
}
if (pegasus->rx_skb == NULL)
printk("%s: rx_skb == NULL\n", __FUNCTION__);
/* /*
** we are sure at this point pegasus->rx_skb != NULL * at this point we are sure pegasus->rx_skb != NULL
** so we go ahead and pass up the packet. * so we go ahead and pass up the packet.
*/ */
skb_put(pegasus->rx_skb, pkt_len); skb_put(pegasus->rx_skb, pkt_len);
pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net); pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net);
...@@ -609,7 +605,7 @@ static void read_bulk_callback(struct urb *urb) ...@@ -609,7 +605,7 @@ static void read_bulk_callback(struct urb *urb)
return; return;
tl_sched: tl_sched:
tasklet_schedule(&pegasus->rx_tl); tasklet_schedule(&pegasus->rx_tl);
} }
...@@ -617,7 +613,7 @@ static void rx_fixup(unsigned long data) ...@@ -617,7 +613,7 @@ static void rx_fixup(unsigned long data)
{ {
pegasus_t *pegasus; pegasus_t *pegasus;
pegasus = (pegasus_t *)data; pegasus = (pegasus_t *) data;
spin_lock_irq(&pegasus->rx_pool_lock); spin_lock_irq(&pegasus->rx_pool_lock);
fill_skb_pool(pegasus); fill_skb_pool(pegasus);
...@@ -704,10 +700,9 @@ static void intr_callback(struct urb *urb) ...@@ -704,10 +700,9 @@ static void intr_callback(struct urb *urb)
} }
} }
status = usb_submit_urb (urb, SLAB_ATOMIC); status = usb_submit_urb(urb, SLAB_ATOMIC);
if (status) if (status)
err ("%s: can't resubmit interrupt urb, %d", err("%s: can't resubmit interrupt urb, %d", net->name, status);
net->name, status);
} }
static void pegasus_tx_timeout(struct net_device *net) static void pegasus_tx_timeout(struct net_device *net)
...@@ -794,7 +789,7 @@ static void set_carrier(struct net_device *net) ...@@ -794,7 +789,7 @@ static void set_carrier(struct net_device *net)
} }
static void free_all_urbs(pegasus_t *pegasus) static void free_all_urbs(pegasus_t * pegasus)
{ {
usb_free_urb(pegasus->intr_urb); usb_free_urb(pegasus->intr_urb);
usb_free_urb(pegasus->tx_urb); usb_free_urb(pegasus->tx_urb);
...@@ -802,7 +797,7 @@ static void free_all_urbs(pegasus_t *pegasus) ...@@ -802,7 +797,7 @@ static void free_all_urbs(pegasus_t *pegasus)
usb_free_urb(pegasus->ctrl_urb); usb_free_urb(pegasus->ctrl_urb);
} }
static void unlink_all_urbs(pegasus_t *pegasus) static void unlink_all_urbs(pegasus_t * pegasus)
{ {
usb_unlink_urb(pegasus->intr_urb); usb_unlink_urb(pegasus->intr_urb);
usb_unlink_urb(pegasus->tx_urb); usb_unlink_urb(pegasus->tx_urb);
...@@ -810,7 +805,7 @@ static void unlink_all_urbs(pegasus_t *pegasus) ...@@ -810,7 +805,7 @@ static void unlink_all_urbs(pegasus_t *pegasus)
usb_unlink_urb(pegasus->ctrl_urb); usb_unlink_urb(pegasus->ctrl_urb);
} }
static int alloc_urbs(pegasus_t *pegasus) static int alloc_urbs(pegasus_t * pegasus)
{ {
pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->ctrl_urb) { if (!pegasus->ctrl_urb) {
...@@ -860,7 +855,7 @@ static int pegasus_open(struct net_device *net) ...@@ -860,7 +855,7 @@ static int pegasus_open(struct net_device *net)
warn("%s: failed rx_urb %d", __FUNCTION__, res); warn("%s: failed rx_urb %d", __FUNCTION__, res);
usb_fill_int_urb(pegasus->intr_urb, pegasus->usb, usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
usb_rcvintpipe(pegasus->usb, 3), usb_rcvintpipe(pegasus->usb, 3),
pegasus->intr_buff, sizeof(pegasus->intr_buff), pegasus->intr_buff, sizeof (pegasus->intr_buff),
intr_callback, pegasus, pegasus->intr_interval); intr_callback, pegasus, pegasus->intr_interval);
if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)))
warn("%s: failed intr_urb %d", __FUNCTION__, res); warn("%s: failed intr_urb %d", __FUNCTION__, res);
...@@ -896,7 +891,82 @@ static int pegasus_close(struct net_device *net) ...@@ -896,7 +891,82 @@ static int pegasus_close(struct net_device *net)
return 0; return 0;
} }
#ifdef CONFIG_MII
static int pegasus_ethtool_ioctl(struct net_device *dev, void *useraddr)
{
u32 ethcmd;
pegasus_t *pegasus = dev->priv;
if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
return -EFAULT;
switch (ethcmd) {
/* get driver-specific version/etc. info */
case ETHTOOL_GDRVINFO:{
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
strncpy(info.driver, driver_name,
sizeof (info.driver) - 1);
strncpy(info.version, DRIVER_VERSION,
sizeof (info.version) - 1);
if (copy_to_user(useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
}
/* get settings */
case ETHTOOL_GSET:{
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
mii_ethtool_gset(&pegasus->mii, &ecmd);
if (copy_to_user(useraddr, &ecmd, sizeof (ecmd)))
return -EFAULT;
return 0;
}
/* set settings */
case ETHTOOL_SSET:{
int r;
struct ethtool_cmd ecmd;
if (copy_from_user(&ecmd, useraddr, sizeof (ecmd)))
return -EFAULT;
r = mii_ethtool_sset(&pegasus->mii, &ecmd);
return r;
}
/* restart autonegotiation */
case ETHTOOL_NWAY_RST:{
return mii_nway_restart(&pegasus->mii);
}
/* get link status */
case ETHTOOL_GLINK:{
struct ethtool_value edata = { ETHTOOL_GLINK };
edata.data = mii_link_ok(&pegasus->mii);
if (copy_to_user(useraddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
}
/* get message-level */
case ETHTOOL_GMSGLVL:{
struct ethtool_value edata = { ETHTOOL_GMSGLVL };
/* edata.data = pegasus->msg_enable; FIXME */
if (copy_to_user(useraddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
}
/* set message-level */
case ETHTOOL_SMSGLVL:{
struct ethtool_value edata;
if (copy_from_user(&edata, useraddr, sizeof (edata)))
return -EFAULT;
/* sp->msg_enable = edata.data; FIXME */
return 0;
}
}
return -EOPNOTSUPP;
}
#else
static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr) static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
{ {
pegasus_t *pegasus; pegasus_t *pegasus;
...@@ -913,7 +983,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr) ...@@ -913,7 +983,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
ETHTOOL_BUSINFO_LEN); ETHTOOL_BUSINFO_LEN);
usb_make_path(pegasus->usb, info.bus_info, usb_make_path(pegasus->usb, info.bus_info,
sizeof info.bus_info); sizeof info.bus_info);
if (copy_to_user(uaddr, &info, sizeof(info))) if (copy_to_user(uaddr, &info, sizeof (info)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
...@@ -950,7 +1020,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr) ...@@ -950,7 +1020,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
ecmd.duplex = bmcr & BMCR_FULLDPLX ? ecmd.duplex = bmcr & BMCR_FULLDPLX ?
DUPLEX_FULL : DUPLEX_HALF; DUPLEX_FULL : DUPLEX_HALF;
} }
if (copy_to_user(uaddr, &ecmd, sizeof(ecmd))) if (copy_to_user(uaddr, &ecmd, sizeof (ecmd)))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -961,7 +1031,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr) ...@@ -961,7 +1031,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
case ETHTOOL_GLINK:{ case ETHTOOL_GLINK:{
struct ethtool_value edata = { ETHTOOL_GLINK }; struct ethtool_value edata = { ETHTOOL_GLINK };
edata.data = netif_carrier_ok(net); edata.data = netif_carrier_ok(net);
if (copy_to_user(uaddr, &edata, sizeof(edata))) if (copy_to_user(uaddr, &edata, sizeof (edata)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
...@@ -969,7 +1039,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr) ...@@ -969,7 +1039,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
} }
#endif
static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{ {
__u16 *data = (__u16 *) & rq->ifr_data; __u16 *data = (__u16 *) & rq->ifr_data;
...@@ -1045,8 +1115,26 @@ static __u8 mii_phy_probe(pegasus_t * pegasus) ...@@ -1045,8 +1115,26 @@ static __u8 mii_phy_probe(pegasus_t * pegasus)
static inline void setup_pegasus_II(pegasus_t * pegasus) static inline void setup_pegasus_II(pegasus_t * pegasus)
{ {
u16 data = 0xa5;
set_register(pegasus, Reg1d, 0); set_register(pegasus, Reg1d, 0);
set_register(pegasus, Reg7b, 1);
mdelay(100);
set_register(pegasus, Reg7b, 2); set_register(pegasus, Reg7b, 2);
set_register(pegasus, 0x83, data);
get_registers(pegasus, 0x83, 1, &data);
if (data == 0xa5) {
pegasus->chip = 0x8513;
} else {
pegasus->chip = 0;
}
set_register(pegasus, 0x80, 0xc0);
set_register(pegasus, 0x83, 0xff);
set_register(pegasus, 0x84, 0x01);
if (pegasus->features & HAS_HOME_PNA && mii_mode) if (pegasus->features & HAS_HOME_PNA && mii_mode)
set_register(pegasus, Reg81, 6); set_register(pegasus, Reg81, 6);
else else
...@@ -1065,13 +1153,13 @@ static int pegasus_probe(struct usb_interface *intf, ...@@ -1065,13 +1153,13 @@ static int pegasus_probe(struct usb_interface *intf,
err("usb_set_configuration() failed"); err("usb_set_configuration() failed");
return -ENODEV; return -ENODEV;
} }
if (!(pegasus = kmalloc(sizeof(struct pegasus), GFP_KERNEL))) { if (!(pegasus = kmalloc(sizeof (struct pegasus), GFP_KERNEL))) {
err("out of memory allocating device structure"); err("out of memory allocating device structure");
return -ENOMEM; return -ENOMEM;
} }
usb_get_dev(dev); usb_get_dev(dev);
memset(pegasus, 0, sizeof(struct pegasus)); memset(pegasus, 0, sizeof (struct pegasus));
pegasus->dev_index = dev_index; pegasus->dev_index = dev_index;
init_waitqueue_head(&pegasus->ctrl_wait); init_waitqueue_head(&pegasus->ctrl_wait);
...@@ -1088,7 +1176,7 @@ static int pegasus_probe(struct usb_interface *intf, ...@@ -1088,7 +1176,7 @@ static int pegasus_probe(struct usb_interface *intf,
} }
init_MUTEX(&pegasus->sem); init_MUTEX(&pegasus->sem);
tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long)pegasus); tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
down(&pegasus->sem); down(&pegasus->sem);
pegasus->usb = dev; pegasus->usb = dev;
...@@ -1104,6 +1192,11 @@ static int pegasus_probe(struct usb_interface *intf, ...@@ -1104,6 +1192,11 @@ static int pegasus_probe(struct usb_interface *intf,
net->set_multicast_list = pegasus_set_multicast; net->set_multicast_list = pegasus_set_multicast;
net->get_stats = pegasus_netdev_stats; net->get_stats = pegasus_netdev_stats;
net->mtu = PEGASUS_MTU; net->mtu = PEGASUS_MTU;
pegasus->mii.dev = net;
pegasus->mii.mdio_read = mdio_read;
pegasus->mii.mdio_write = mdio_write;
pegasus->mii.phy_id_mask = 0x1f;
pegasus->mii.reg_num_mask = 0x1f;
spin_lock_init(&pegasus->rx_pool_lock); spin_lock_init(&pegasus->rx_pool_lock);
pegasus->features = usb_dev_id[dev_index].private; pegasus->features = usb_dev_id[dev_index].private;
...@@ -1132,7 +1225,7 @@ static int pegasus_probe(struct usb_interface *intf, ...@@ -1132,7 +1225,7 @@ static int pegasus_probe(struct usb_interface *intf,
exit: exit:
up(&pegasus->sem); up(&pegasus->sem);
if (pegasus) { if (pegasus) {
dev_set_drvdata (&intf->dev, pegasus); dev_set_drvdata(&intf->dev, pegasus);
return 0; return 0;
} }
return -EIO; return -EIO;
...@@ -1140,9 +1233,9 @@ static int pegasus_probe(struct usb_interface *intf, ...@@ -1140,9 +1233,9 @@ static int pegasus_probe(struct usb_interface *intf,
static void pegasus_disconnect(struct usb_interface *intf) static void pegasus_disconnect(struct usb_interface *intf)
{ {
struct pegasus *pegasus = dev_get_drvdata (&intf->dev); struct pegasus *pegasus = dev_get_drvdata(&intf->dev);
dev_set_drvdata (&intf->dev, NULL); dev_set_drvdata(&intf->dev, NULL);
if (!pegasus) { if (!pegasus) {
warn("unregistering non-existant device"); warn("unregistering non-existant device");
return; return;
......
...@@ -85,6 +85,7 @@ typedef struct pegasus { ...@@ -85,6 +85,7 @@ typedef struct pegasus {
struct usb_device *usb; struct usb_device *usb;
struct net_device *net; struct net_device *net;
struct net_device_stats stats; struct net_device_stats stats;
struct mii_if_info mii;
unsigned flags; unsigned flags;
unsigned features; unsigned features;
int dev_index; int dev_index;
...@@ -97,6 +98,7 @@ typedef struct pegasus { ...@@ -97,6 +98,7 @@ typedef struct pegasus {
wait_queue_head_t ctrl_wait; wait_queue_head_t ctrl_wait;
struct semaphore sem; struct semaphore sem;
spinlock_t rx_pool_lock; spinlock_t rx_pool_lock;
int chip;
unsigned char intr_buff[8]; unsigned char intr_buff[8];
__u8 tx_buff[PEGASUS_MTU]; __u8 tx_buff[PEGASUS_MTU];
__u8 eth_regs[4]; __u8 eth_regs[4];
...@@ -131,11 +133,11 @@ struct usb_eth_dev { ...@@ -131,11 +133,11 @@ struct usb_eth_dev {
#define VENDOR_LANEED 0x056e #define VENDOR_LANEED 0x056e
#define VENDOR_LINKSYS 0x066b #define VENDOR_LINKSYS 0x066b
#define VENDOR_MELCO 0x0411 #define VENDOR_MELCO 0x0411
#define VENDOR_NETGEAR 0x0846
#define VENDOR_SMARTBRIDGES 0x08d1 #define VENDOR_SMARTBRIDGES 0x08d1
#define VENDOR_SMC 0x0707 #define VENDOR_SMC 0x0707
#define VENDOR_SOHOWARE 0x15e8 #define VENDOR_SOHOWARE 0x15e8
#define VENDOR_SIEMENS 0x067c #define VENDOR_SIEMENS 0x067c
#define VENDOR_JTEC 0x11ad
#else /* PEGASUS_DEV */ #else /* PEGASUS_DEV */
...@@ -169,7 +171,10 @@ PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046, ...@@ -169,7 +171,10 @@ PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet", PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
VENDOR_ADMTEK, 0x8511, VENDOR_ADMTEK, 0x8511,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)", PEGASUS_DEV( "ADMtek ADM8513 \"Pegasus II\" USB Ethernet",
VENDOR_ADMTEK, 0x8513,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation board)",
VENDOR_ADMTEK, 0x0986, VENDOR_ADMTEK, 0x0986,
DEFAULT_GPIO_RESET | HAS_HOME_PNA ) DEFAULT_GPIO_RESET | HAS_HOME_PNA )
PEGASUS_DEV( "AN986A USB MAC", VENDOR_ADMTEK, 1986, PEGASUS_DEV( "AN986A USB MAC", VENDOR_ADMTEK, 1986,
...@@ -192,7 +197,7 @@ PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511, ...@@ -192,7 +197,7 @@ PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004, PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004,
DEFAULT_GPIO_RESET ) DEFAULT_GPIO_RESET )
PEGASUS_DEV( "Corega FEter", VENDOR_COREGA, 0x000d, PEGASUS_DEV( "Corega FEter USB-TXS", VENDOR_COREGA, 0x000d,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001, PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001,
LINKSYS_GPIO_RESET ) LINKSYS_GPIO_RESET )
...@@ -246,6 +251,8 @@ PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005, ...@@ -246,6 +251,8 @@ PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005,
DEFAULT_GPIO_RESET ) DEFAULT_GPIO_RESET )
PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009, PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "NETGEAR FA101", VENDOR_NETGEAR, 0x1020,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003, PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200, PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
...@@ -258,8 +265,6 @@ PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110, ...@@ -258,8 +265,6 @@ PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001, PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "FA8101 USB To ETHERNET", VENDOR_JTEC, 0x8101,
DEFAULT_GPIO_RESET | PEGASUS_II )
#endif /* PEGASUS_DEV */ #endif /* PEGASUS_DEV */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment