All,

I took a little time and rewrote the rtl8150 driver using the usbnet framework 
and would like some folks to try to test it.  Please note that I DO NOT have 
this device, thus it is only compile tested.  The module loads cleanly, and 
that is the extent to how well I know that it works.  If anyone has the device 
and the free time to try it, I would like to hear any feedback.  This driver is 
missing a few features and may only partially work, though most of the basics 
should be there.  At this point, it weighs in at 292 lines compared to 1002 for 
the current driver.

-- 
David Hollis <[EMAIL PROTECTED]>
#define      DEBUG		// error path messages, extra info
#define      VERBOSE		// more; success messages

#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/usb.h>

#include "usbnet.h"

#define DRIVER_VERSION "21-Aug-2006"
static const char driver_name[] = "rtl8150";

#define RTL8150_REQT_READ       0xc0
#define RTL8150_REQT_WRITE      0x40
#define RTL8150_REQ_GET_REGS    0x05
#define RTL8150_REQ_SET_REGS    0x05

/* RTL8150 Registers */
#define CR	0x012e
#define TCR	0x012f
#define RCR	0x0130
#define IDR	0x0120
#define MSR	0x0137
#define PHYADD	0x0138
#define PHYDAT	0x0139
#define PHYCNT	0x013b
#define CSCR	0x014C
#define CSCR_LINK_STATUS	(1 << 3)

#define PHY_READ	0x00
#define PHY_WRITE	0x20
#define PHY_GO		0x40

/* FIXME: Lets get rid of this if we can */
#define MII_TIMEOUT	10

static int rtl8150_read_cmd(struct usbnet *dev, u16 index, u16 size, void *data)
{
	devdbg(dev, "rtl8150_read_cmd() index=0x%04x size=%d", index, size);
	return usb_control_msg(dev->udev,
			       usb_rcvctrlpipe(dev->udev, 0),
			       RTL8150_REQ_GET_REGS,
			       RTL8150_REQT_READ,
			       index, 0, data, size, USB_CTRL_GET_TIMEOUT);
}

static int rtl8150_write_cmd(struct usbnet *dev, u16 index, u16 size,
			     void *data)
{
	devdbg(dev, "rtl8150_write_cmd() index=0x%04x size=%d", index, size);
	return usb_control_msg(dev->udev,
			       usb_sndctrlpipe(dev->udev, 0),
			       RTL8150_REQ_SET_REGS,
			       RTL8150_REQT_WRITE,
			       index, 0, data, size, USB_CTRL_SET_TIMEOUT);
}

static int rtl8150_mdio_read(struct net_device *netdev, int phy_id, int loc)
{
	struct usbnet *dev = netdev_priv(netdev);
	int i;
	u8 data[3], tmp;
	int ret = 0;

	data[0] = phy_id;
	data[1] = data[2] = 0;
	tmp = loc | PHY_READ | PHY_GO;
	i = 0;

	rtl8150_write_cmd(dev, PHYADD, sizeof(data), data);
	rtl8150_write_cmd(dev, PHYCNT, 1, &tmp);
	do {
		rtl8150_read_cmd(dev, PHYCNT, 1, data);
	} while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT));

	if (i < MII_TIMEOUT) {
		rtl8150_read_cmd(dev, PHYDAT, 2, data);
		ret = data[0] | (data[1] << 8);
	}
	return ret;
}

static void
rtl8150_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
{
}

static void rtl8150_set_multicast(struct net_device *net)
{
	struct usbnet *dev = netdev_priv(net);

	devdbg(dev, "rtl8150_set_multicast() not implemented");

#if 0
	netif_stop_queue(net);
	if (net->flags & IFF_PROMISC) {
		dev->rx_creg |= cpu_to_le16(0x0001);
		info("%s: promiscuous mode", net->name);
	} else if (net->mc_count || (net->flags & IFF_ALLMULTI)) {
		dev->rx_creg &= cpu_to_le16(0xfffe);
		dev->rx_creg |= cpu_to_le16(0x0002);
		info("%s: allmulti set", net->name);
	} else {
		/* ~RX_MULTICAST, ~RX_PROMISCUOUS */
		dev->rx_creg &= cpu_to_le16(0x00fc);
	}
	async_set_registers(dev, RCR, 2);
	netif_wake_queue(netdev);
#endif
}

static int rtl8150_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{
	struct usbnet *dev = netdev_priv(net);

	return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
}

static void rtl8150_set_ethernet_addr(struct usbnet *dev)
{
	u8 node_id[6];

	rtl8150_read_cmd(dev, IDR, sizeof(node_id), node_id);
	memcpy(dev->net->dev_addr, node_id, sizeof(node_id));
}

static int rtl8150_set_mac_address(struct net_device *net, void *p)
{
	struct usbnet *dev = netdev_priv(net);
	struct sockaddr *addr = p;

	if (netif_running(net))
		return -EBUSY;

	memcpy(net->dev_addr, addr->sa_data, net->addr_len);
	/* Set the IDR registers. */
	rtl8150_write_cmd(dev, IDR, sizeof(net->dev_addr), net->dev_addr);

	return 0;
}

static int rtl8150_reset(struct usbnet *dev)
{
	u8 data = 0x10;
	int i = HZ;
	u8 rcr, tcr, cr, msr;

	devdbg(dev, "rtl8150_reset()");

	rtl8150_write_cmd(dev, CR, 1, &data);
	do {
		rtl8150_read_cmd(dev, CR, 1, &data);
	} while ((data & 0x10) && --i);

	rtl8150_write_cmd(dev, IDR, 6, dev->net->dev_addr);

	/* RCR bit7=1 attach Rx info at the end;  =0 HW CRC (which is broken) */
	rcr = 0x9e;
	tcr = 0xd8;
	cr = 0x0c;
/*
	if (!(rcr & 0x80))
		set_bit(RTL8150_HW_CRC, &dev->flags);
*/
	rtl8150_write_cmd(dev, RCR, 1, &rcr);
	rtl8150_write_cmd(dev, TCR, 1, &tcr);
	rtl8150_write_cmd(dev, CR, 1, &cr);
	rtl8150_read_cmd(dev, MSR, 1, &msr);

	return 0;
}

static void rtl8150_status(struct usbnet *dev, struct urb *urb)
{
	devdbg(dev, "rtl8150_status()");
}

static int rtl8150_check_connect(struct usbnet *dev)
{
	int tmp;

	rtl8150_read_cmd(dev, CSCR, 2, &tmp);

	return (tmp & CSCR_LINK_STATUS);
}

static int rtl8150_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
	struct usbnet *dev = netdev_priv(net);

	return mii_ethtool_gset(&dev->mii, cmd);
}

static void rtl8150_get_drvinfo(struct net_device *net,
				struct ethtool_drvinfo *info)
{
	/* Inherit standard device info */
	usbnet_get_drvinfo(net, info);
	strncpy(info->driver, driver_name, sizeof info->driver);
	strncpy(info->version, DRIVER_VERSION, sizeof info->version);
}

static struct ethtool_ops rtl8150_ethtool_ops = {
	.get_drvinfo = rtl8150_get_drvinfo,
	.get_settings = rtl8150_get_settings,
	.get_msglevel = usbnet_get_msglevel,
	.set_msglevel = usbnet_set_msglevel,
};

static int rtl8150_bind(struct usbnet *dev, struct usb_interface *intf)
{
	dbg("rtl8150_bind()");

	dev->mii.dev = dev->net;
	dev->mii.mdio_read = rtl8150_mdio_read;
	dev->mii.mdio_write = rtl8150_mdio_write;
/*
        dev->mii.phy_id_mask = 0x3f;
        dev->mii.reg_num_mask = 0x1f;
        dev->mii.phy_id = asix_get_phy_addr(dev);
*/

	dev->net->do_ioctl = rtl8150_ioctl;
	dev->net->set_multicast_list = rtl8150_set_multicast;
	dev->net->set_mac_address = rtl8150_set_mac_address;
	dev->net->ethtool_ops = &rtl8150_ethtool_ops;

	rtl8150_set_ethernet_addr(dev);

	return 0;
}

static const struct driver_info rtl8150_info = {
	.description = "RTL8150 USB Ethernet",
	.bind = rtl8150_bind,
	.reset = rtl8150_reset,
	.status = rtl8150_status,
	.check_connect = rtl8150_check_connect,
	.flags = FLAG_ETHER,
};

static const struct usb_device_id products[] = {
{
	USB_DEVICE(0x0bda, 0x8150),
	.driver_info = (unsigned long)&rtl8150_info,
}, {
	USB_DEVICE(0x0411, 0x0012),
	.driver_info = (unsigned long)&rtl8150_info,
}, {
	USB_DEVICE(0x3980, 0x0003),
	.driver_info = (unsigned long)&rtl8150_info,
}, {
	USB_DEVICE(0x07b8, 0x401a),
	.driver_info = (unsigned long)&rtl8150_info,
}, {
	USB_DEVICE(0x0586, 0x401a),
	.driver_info = (unsigned long)&rtl8150_info,
},
	{},
};
MODULE_DEVICE_TABLE(usb, products);

static struct usb_driver rtl8150_driver = {
	.name = "rtl8150",
	.id_table = products,
	.probe = usbnet_probe,
	.suspend = usbnet_suspend,
	.resume = usbnet_resume,
	.disconnect = usbnet_disconnect,
};

static int __init rtl8150_init(void)
{
	return usb_register(&rtl8150_driver);
}

module_init(rtl8150_init);

static void __exit rtl8150_exit(void)
{
	usb_deregister(&rtl8150_driver);
}

module_exit(rtl8150_exit);

MODULE_AUTHOR("David Hollis");
MODULE_DESCRIPTION("RTL8150 USB Ethernet Driver");
MODULE_LICENSE("GPL");
obj-m += rtl8150.o

KVERSION := `uname -r`
KDIR := /lib/modules/$(KVERSION)/build

all:
	make -C $(KDIR) SUBDIRS=`pwd` modules

clean:
	make -C $(KDIR) SUBDIRS=`pwd` clean

install:
	make -C $(KDIR) SUBDIRS=`pwd` install

Attachment: signature.asc
Description: This is a digitally signed message part

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to