下是我参照网上修改的8019as中断式网络驱动(以ne2000的ISA驱动修改)
下面这个是Ne.c (drivers\net) 主要修改地方用红色的字表示
现在是文件系统都能进去了,用板子ping主机,显示出来的结果是时间超时,但我用抓包工具显示,主机的网卡也确实接受到数据,而且也显示是同一个MAC地址发出的。
目前自己认为是中断赋值出错,就是我用绿色字表示的。主要的就是我的中断号如何我的硬件中断联系起来,用什么函数在那定义。
而且在板子里ping自己是能ping通的(就是ping 127.0.0.1)
硬件情况:网卡中断接的针脚:PA23(既IRQ3)
网卡基地址:0x50000000(既片选NCS4)
现在不知如何是好,希望高人指点帮助
#include
#include
#include
#include
#include
#include //add by wzj
#include //add by wzj
#include 8390.h
#define DRV_NAME ne
#define RTL_8019_IRQ (22) //add by wzj
#define EBI_CSA 0x00 //add by wzj
#define EBI_CFGR 0x04 //add by wzj
#define SMC2_CSR4 0x10 //add by wzj
#define SUPPORT_NE_BAD_CLONES
#ifndef MODULE
static unsigned int netcard_portlist[] __initdata = {
0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
};
#endif
static struct isapnp_device_id isapnp_clone_list[] __initdata = {
{ ISAPNP_CARD_ID(A,X,E,0x2011),
ISAPNP_VENDOR(A,X,E), ISAPNP_FUNCTION(0x2011),
(long) NetGear EA201 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR(E,D,I), ISAPNP_FUNCTION(0x0216),
(long) NN NE2000 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR(P,N,P), ISAPNP_FUNCTION(0x80d6),
(long) Generic PNP },
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
#ifdef SUPPORT_NE_BAD_CLONES
/* A list of bad clones that we none-the-less recognize. */
static struct { const char *name8, *name16; unsigned char SAprefix[4];}
bad_clone_list[] __initdata = {
{DE100, DE200, {0x00, 0xDE, 0x01,}},
{DE120, DE220, {0x00, 0x80, 0xc8,}},
{DFI1000, DFI2000, {D, F, I,}}, /* Original, eh? */
{EtherNext UTP8, EtherNext UTP16, {0x00, 0x00, 0x79}},
{NE1000,NE2000-invalid, {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
{NN1000, NN2000, {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
{4-DIM8,4-DIM16, {0x00,0x00,0x4d,}}, /* Outlaw 4-Dimension cards. */
{Con-Intl_8, Con-Intl_16, {0x00, 0x00, 0x24}}, /* Connect Intnl */
{ET-100,ET-200, {0x00, 0x45, 0x54}}, /* YANG and YA clone */
{COMPEX,COMPEX16,{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
{E-LAN100, E-LAN200, {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
{PCM-4823, PCM-4823, {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
{REALTEK, RTL8019, {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
{LCS-8834, LCS-8836, {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
{RTL8019AS, NE2000-compatible, {0x08, 0x08, 0x08}}, //add by wzj
{NULL,}
};
#endif
/* ---- No user-serviceable parts below ---- */
#define NE_BASE RTL_8019_BASE //(dev->base_addr)
#define NE_CMD 0x00
#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */
#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */
#define NE_IO_EXTENT 0x20
#define NE1SM_START_PG 0x20 /* First page of TX buffer */
#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
#define NESM_START_PG 0x40 /* First page of TX buffer */
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
#if 0 //add by wzj
#if defined(CONFIG_PLAT_MAPPI)
# define DCR_VAL 0x4b
#elif defined(CONFIG_PLAT_OAKS32R)
# define DCR_VAL 0x48
#else
# define DCR_VAL 0x49
#endif
#endif //add by wzj
#define DCR_VAL 0x48 //add by wzj 只能是8bit 模式(由于硬件的原因目前只能8bit模式)
static int ne_probe1(struct net_device *dev, int ioaddr);
static int ne_probe_isapnp(struct net_device *dev);
static int ne_open(struct net_device *dev);
static int ne_close(struct net_device *dev);
static void ne_reset_8390(struct net_device *dev);
static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
static void ne_block_input(struct net_device *dev, int count,
struct sk_buff *skb, int ring_offset);
static void ne_block_output(struct net_device *dev, const int count,
const unsigned char *buf, const int start_page);
static int __init do_ne_probe(struct net_device *dev)
{
unsigned int base_addr =dev->base_addr;
#ifndef MODULE
int orig_irq = dev->irq;
#endif
//****************************** wzj ********************************
//在do_ne_probe函数中增加配置总线参数、基地址和中断的语句
static int once=0;
if (once) {
return -ENXIO;
}
unsigned int value;
value = __raw_readl(AT91C_VA_BASE_EBI);
value&=~AT91C_EBI_CS4A;
__raw_writel(value,AT91C_VA_BASE_EBI+EBI_CSA);
value=0;
value=((AT91C_EBI_DBPUC & 0x00) | (AT91C_EBI_EBSEN & 0x00));
__raw_writel(value,AT91C_VA_BASE_EBI+EBI_CFGR);
value=0;
value= ((AT91C_SMC2_NWS & 0x9) | AT91C_SMC2_WSEN | (AT91C_SMC2_TDF & 0x200) | AT91C_SMC2_DBW_8);
__raw_writel(value,AT91C_VA_BASE_SMC2+SMC2_CSR4);
printk(\n value=0x%x\n AT91C_EBI_CS4A=0x%X\n,value,AT91C_EBI_CS4A);
set_irq_type(RTL_8019_IRQ,IRQT_LOW ); //这个函数在2.4内核没有的,不知道用什么函数能代替他。
if(base_addr==0){
dev->base_addr = base_addr = __ioremap(0x50000000,sizeof(unsigned int),0,1); //这个函数2.6内涵是4个参数,2.4内核就只有3个参数就够了。
dev->irq = RTL_8019_IRQ;
once++;
}
//*********************************** wzj ************************************
SET_MODULE_OWNER(dev);
/* First check any supplied i/o locations. User knows best. */
if (base_addr > 0x1ff) /* Check a single specified location. */
return ne_probe1(dev, base_addr);
else if (base_addr != 0) /* Dont probe at all. */
return -ENXIO;
/* Then look for any installed ISAPnP clones */
if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
return 0;
#ifndef MODULE
/* Last resort. The semi-risky ISA auto-probe. */
for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
int ioaddr = netcard_portlist[base_addr];
dev->irq = orig_irq;
if (ne_probe1(dev, ioaddr) == 0)
return 0;
}
#endif
return -ENODEV;
}
static void cleanup_card(struct net_device *dev)
{
struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
if (idev)
pnp_device_detach(idev);
free_irq(dev->irq, dev);
release_region(dev->base_addr, NE_IO_EXTENT);
}
————————————————————————————
..................
————————————————————————————
static int __init ne_probe1(struct net_device *dev, int ioaddr)
{
int i;
unsigned char SA_prom[32];
int wordlength = 2;
const char *name = NULL;
unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x12,0x27,0}; //8019as 的MAC 地址
int start_page, stop_page;
int neX000, ctron, copam, bad_card;
int reg0, ret;
static unsigned version_printed;
if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
return -EBUSY;
reg0 = inb_p(ioaddr);
if (reg0 == 0xFF) {
ret = -ENODEV;
goto err_out;
}
————————————————————————————
.........................
————————————————————————————
{
struct {unsigned char value, offset; } program_seq[] =
{
{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
{0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
{0x00, EN0_RCNTLO}, /* Clear the count regs. */
{0x00, EN0_RCNTHI},
{0x00, EN0_IMR}, /* Mask completion irq. */
{0xFF, EN0_ISR},
{E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
{E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
{32, EN0_RCNTLO},
{0x00, EN0_RCNTHI},
{0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
{0x00, EN0_RSARHI},
{E8390_RREAD+E8390_START, E8390_CMD},
};
for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
outb_p(program_seq.value, ioaddr + program_seq.offset);
}
//****************************************wzj start*********************************
//下面是添加MAC 地址
{
unsigned char *ep;
ep = (unsigned char * ) &ne_defethaddr[0];
for(i=0;i<6;i++) {
SA_prom = ep;
}
SA_prom[14] = SA_prom[15]=0x57;
wordlength =1;
}
//****************************************wzj end*********************************
#if 0 //add by wzj
for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
SA_prom = inb(ioaddr + NE_DATAPORT);
SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
if (SA_prom != SA_prom[i+1])
wordlength = 1;
}
#endif //add by wzj
if (wordlength == 2)
{
#if 0 //add by wzj
for (i = 0; i < 16; i++)
SA_prom = SA_prom[i+i];
/* We must set the 8390 for word mode. */
outb_p(DCR_VAL, ioaddr + EN0_DCFG);
start_page = NESM_START_PG;
stop_page = NESM_STOP_PG;
#endif //add by wzj
//下面3 句是定义数据宽度16bit 模式
outb_p(0x49, ioaddr + EN0_DCFG); // add by wzj
start_page = NESM_START_PG; // add by wzj
stop_page = NESM_STOP_PG; // add by wzj
} else {
start_page = NE1SM_START_PG;
stop_page = NE1SM_STOP_PG;
}
————————————————
.......................
——————————————————
#else
printk( not found.\n);
ret = -ENXIO;
goto err_out;
#endif
}
if (dev->irq < 2)
{
unsigned long cookie = probe_irq_on();
outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
outb_p(0x00, ioaddr + EN0_RCNTLO);
outb_p(0x00, ioaddr + EN0_RCNTHI);
outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
mdelay(10); /* wait 10ms for interrupt to propagate */
outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */
dev->irq = probe_irq_off(cookie);
if (ei_debug > 2)
printk( autoirq is %d\n, dev->irq);
} else if (dev->irq == 2)
/* Fixup for users that dont know that IRQ 2 is really IRQ 9,
or dont know which one to set. */
dev->irq = 9;
if (! dev->irq) {
printk( failed to detect IRQ line.\n);
ret = -EAGAIN;
goto err_out;
}
/* Snarf the interrupt now. Theres no point in waiting since we cannot
share and the board will usually be enabled. */
ret = request_irq(dev->irq, ei_interrupt, 0, name, dev); //这里的中断号,如何和我硬件中断联系起来呢???
//ret = at91rm9200_gpio_request_irq(dev->irq,23,1,ei_interrupt,GPIO-PA23);
if (ret) {
printk ( unable to get IRQ %d (errno=%d).\n, dev->irq, ret);
goto err_out;
}
dev->base_addr = ioaddr;
#ifdef CONFIG_PLAT_MAPPI
outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
ioaddr + E8390_CMD); /* 0x61 */
for (i = 0 ; i < ETHER_ADDR_LEN ; i++) {
dev->dev_addr[i] = SA_prom[i]
= inb_p(ioaddr + EN1_PHYS_SHIFT(i));
printk( %2.2x, SA_prom[i]);
}
#else
for(i = 0; i < ETHER_ADDR_LEN; i++) {
printk( %2.2x, SA_prom[i]);
dev->dev_addr[i] = SA_prom[i];
}
#endif
printk(\n%s: %s found at %#x, using IRQ %d.\n,
dev->name, name, ioaddr, dev->irq);
ei_status.name = name;
ei_status.tx_start_page = start_page;
ei_status.stop_page = stop_page;
#ifdef CONFIG_PLAT_OAKS32R
ei_status.word16 = 0;
#else
ei_status.word16 = (wordlength == 2);
#endif
ei_status.rx_start_page = start_page + TX_PAGES;
#ifdef PACKETBUF_MEMSIZE
/* Allow the packet buffer size to be overridden by know-it-alls. */
ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
#endif