1、芯片介绍
CS8900A是CIRRUS LOGIC公司生产的低功耗,性能优越的16位以太网控制器,功能强大。该芯片
的突出特点是使用灵活,其物理层接口、数据传输模式和工作模式等都能根据需要而动态调整,通过
内部寄存器的设置来适应不同的应用环境。CS8900A内部功能模块主要是802.3截止访问控制块
(MAC)。802.3截止访问控制块支持全双工操作,完全依照IEEE 802.3以太网标准,它负责处理有关
以太网数据帧的发送和接收,包括:冲突检测、帧头的产生和检测,CRC校验的生成和验证。通过对
发送控制寄存器(TxCMD)的初始化配置,MAC能自动完成帧的冲突后重传。如果帧的数据部分少于46
个字节,它能生成填充字段使数据帧达到802.3所要求的最短长度。
2、以太网帧
1>寄存器
LINECTL(0112H):
LINECTL决定CS8900的基本配置和物理接口,例如:设置初始化为00dH,选择物理接口为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、RXCTL、RCCFG、BUSCT;
发送数据时,写控制寄存器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_cs89x.base_addr = io;
-
-
dev_cs89x0.init = cs89x0_probe;
-
-
-
request_region(dev_cs89x0.base_addr,NETCARD_IO_EXTENT,"cs8900a");
-
-
if(register_netdev(&dev_cs89x0) != 0)
-
}
-
-
/*2、设备检测*/
-
-
static int __init cs89x0_probel(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 & REVISION_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_timcout = net_timcout;
-
-
dev->watchdog_timeo = 3*HZ;
-
-
dev->hard_start_xmit = net_send_packet;
-
-
dev->get_stats = net_get_stats;
-
-
dev->set_multicast_list = set_mulitcat_list;
-
-
dev->set_mac_address = set_mac_address;
-
-
/*fill in the fields of the device structure with ethernet values.*/
-
-
ether_setup(dev);
-
-
}
-
-
/*3、数据发送*/
-
-
static int net_send_packet(struct sk_buff *skb,struct net_device *dev)
-
{
-
netif_stop_queue(dev);
-
-
/*initiate a transmit sequeue*/
-
-
writeword(dev,TX_CMD_PORT,lp->send_cmd);
-
-
wreteword(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);
-
DRRINTK(1,"cs89x0: TX buffer not free!\n");
-
return 1;
-
}
-
-
/*write the contens of the packet*/
-
writeblock(dev,skb->data,skb->len);
-
-
return 0;
-
}
-
-
/*4、中断*/
-
-
static void net_interrupt(int irq,void *dev_id,struct pr_regs *regs)
-
{
-
while((status = readword(dev,ISQ_PORT)))
-
{
-
switch(status & ISQ_EVENT_MASK)
-
{
-
case ISQ_RECEIVER_EVENT:net_rx(dev);
-
break;
-
case ISQ_TRANSMITTER_EVENT:lp->status_packets++;
-
netif_wake_queue(dev);
-
break;
-
}
-
}
-
}
-
-
/*5、接收*/
-
-
static void net_rx(struct net_device *dev)
-
{
-
status = inw(loaddr + RX_FRAME_PORT);
-
if((status & RX_OK) == 0){
-
count_rx_errors(status,lp);
-
return;
-
}
-
-
length = inw(loaddr + RX_FRAME_PORT);
-
-
/* malloc up new buffer.*/
-
skb = dev_alloc_skb(length + 2);
-
-
if(skb == NULL){
-
lp->status_dropped++;
-
return;
-
}
-
-
skb_reserve(skb,2);
-
/*mac头是14个字节,一开始保留两个字节,正是为了保证lp头的开始是四字节对齐的*/
-
-
skb->len = length;
-
skb->dev = dev;
-
-
readblock(dev,skb->data,skb->len);
-
-
skb->protocol=eth_type_trans(skb,dev);
-
-
netif_rx(skb);
-
}
阅读(3402) | 评论(0) | 转发(0) |