Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2629793
  • 博文数量: 333
  • 博客积分: 4817
  • 博客等级: 上校
  • 技术积分: 4413
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-28 10:51
文章分类

全部博文(333)

文章存档

2017年(20)

2016年(57)

2015年(27)

2014年(20)

2013年(21)

2012年(164)

2011年(24)

分类: LINUX

2012-02-27 21:41:22

1. 寄存器

·LINECTL0112H


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


发送控制寄存器,如果写入数据00C0H,那么网卡芯片在全部数据写入后

开始发送数据。


·TXLENG
0006H


发送数据长度寄存器,发送数据时,首先写入发送数据长度,然后将数据通

PORT0写入芯片。

以上为几个最主要的工作寄存器(为16位)。


系统工作时,应首先对网卡芯片进行初始化,即写寄存器LINECTL

RXCTLRCCFGBUSCT


发数据时,写控制寄存器TXCMD,并将发送数据长度写入TXLENG,然

后将数据依次写入PORT0口,网卡芯片将数据组织为链路层类型并添加填

充位和CRC校验送到网络。


2. 程序框架

    1. 模块注册

static int __init init_cs8900a_s3c2410(void)

{

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, "cs8900a");


if (register_netdev(&dev_cs89x0) != 0)

}



    1. 设备检测


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);

}



    1. 数据发送


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;

}

    1. 中断



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;

}

    1. 接收


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);

}


好东东,认真理解,深刻体会!祝各位好运!

阅读(2094) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~