全部博文(72)
2010年(72)
分类: LINUX
2010-09-24 08:42:50
CS
1. 寄存器
·LINECTL(0112H)
LINECTL决定CS8900的基本配置和物理接口。例如:设置初始值为00d3H,选择物理接口为10BASE-T,并使能设备的发送和接收控制位。
·RXCTL(0104H)
RXCTL控制CS8900接收特定数据报。设置RXTCL的初始值为0d05H,表示接收网络上的广播或者目标地址同本地物理地址相同的正确数据包。
·RXCFG(0102H)
RXCFG控制CS8900接收到特定数据报后会引发接收中断。RXCFG可设置为0103H,这样当收到一个正确的数据报后,CS8900会产生一个接收中断。
·BUSCT(0116H)
BUSCT可控制芯片的I/O接口的一些操作。设置初始值为8017H,打开CS8900的中断总控制位。
·ISQ(0120H)
ISQ是网卡芯片的中断状态寄存器,内部映射接收中断状态寄存器和发送中断状态寄存器的内容。
·PORT0(0000H)
发送和接收数据时,CPU通过PORT0传递数据。
·TXCMD(0004H)
发送控制寄存器,如果写入数据
·TXLENG(0006H)
发送数据长度寄存器,发送数据时,首先写入发送数据长度,然后将数据通过PORT0写入芯片。
以上为几个最主要的工作寄存器(为16位)。
系统工作时,应首先对网卡芯片进行初始化,即写寄存器LINECTL、RXCTL、 RCCFG、BUSCT。
发数据时,写控制寄存器TXCMD,并将发送数据长度写入TXLENG,然后将数据依次写入PORT0口,网卡芯片将数据组织为链路层类型并添加填充位和CRC校验送到网络。
2. 程序框架
2.1 模块注册
static int __init init_cs
{
struct net_local *lp;
int ret = 0;
dev_cs89x0.irq = irq;
dev_cs89x0.base_addr = io;
dev_cs89x0.init = cs89x0_probe;
request_region(dev_cs89x0.base_addr, NETCARD_IO_EXTENT, "cs
if (register_netdev(&dev_cs89x0) != 0)
}
2.2 设备检测
static int __init cs89x0_probe1(struct net_device *dev, int ioaddr)
{
/* get the chip type */
rev_type = readreg(dev, PRODUCT_ID_ADD);
lp->chip_type = rev_type &~ REVISON_BITS;
lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
if (lp->chip_type != CS8900)
{
printk(__FILE__ ": wrong device driver!\n");
ret = -ENODEV;
goto after_kmalloc;
}
dev->dev_addr[0] = 0x00;
dev->dev_addr[1] = 0x00;
dev->dev_addr[2] = 0xc0;
dev->dev_addr[3] = 0xff;
dev->dev_addr[4] = 0xee;
dev->dev_addr[5] = 0x08;
set_mac_address(dev, dev->dev_addr);
dev->irq = IRQ_LAN;
printk(", IRQ %d", dev->irq);
dev->open = net_open;
dev->stop = net_close;
dev->tx_timeout = net_timeout;
dev->watchdog_timeo = 3 * HZ;
dev->hard_start_xmit = net_send_packet;
dev->get_stats = net_get_stats;
dev->set_multicast_list = set_multicast_list;
dev->set_mac_address = set_mac_address;
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(dev);
}
2.3 数据发送
static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
netif_stop_queue(dev);
/* initiate a transmit sequence */
writeword(dev, TX_CMD_PORT, lp->send_cmd);
writeword(dev, TX_LEN_PORT, skb->len);
/* Test to see if the chip has allocated memory for the packet */
if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0)
{
spin_unlock_irq(&lp->lock);
DPRINTK(1, "cs89x0: Tx buffer not free!\n");
return 1;
}
/* Write the contents of the packet */
writeblock(dev, skb->data, skb->len);
return 0;
}
2.4 中断
static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
while ((status = readword(dev, ISQ_PORT)))
{
switch(status & ISQ_EVENT_MASK) {
case ISQ_RECEIVER_EVENT:
/* Got a packet(s). */
net_rx(dev);
break;
case ISQ_TRANSMITTER_EVENT:
lp->stats.tx_packets++;
netif_wake_queue(dev); /* Inform upper layers. */
break;
}
2.5 接收
static void net_rx(struct net_device *dev) {
status = inw(ioaddr + RX_FRAME_PORT);
if ((status & RX_OK) == 0) {
count_rx_errors(status, lp);
return;
}
length = inw(ioaddr + RX_FRAME_PORT);
/* Malloc up new buffer. */
skb = dev_alloc_skb(length + 2);
if (skb == NULL) {
lp->stats.rx_dropped++;
return;
}
skb_reserve(skb, 2);
/* mac头是14个字节,一开始保留两个字节,正是为了保证ip头的开始是四字节对齐的。*/
skb->len = length;
skb->dev = dev;
readblock(dev, skb->data, skb->len);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}