📄 dm9000x.c
字号:
#endif
} // end of switch
} // end of if
}
//edit by fae
#if 1
phy_write(db, 0, 0x8000);
phy_write(db, 4, phy_reg4);
phy_write(db, 0, phy_reg0);
#else
phy_write(db, 0, phy_reg0);
phy_write(db, 4, phy_reg4);
#endif
/*
for(i = 0; i < 30000; i++)
{
udelay (1000);
if(ior(db, 0x01) & 0x40) break;
}
printk("link:%s , speed:%s , duplex:%s \n",
(ior (db, 0x01) & 0x40) ? "ok": "fail",
(ior (db, 0x01) & 0x80) ? "10Mbps": "100Mbps",
(ior (db, 0x00 ) & 0x08) ? "Full": "Half");
*/
db->Preg0 = phy_reg0;
db->Preg4 = phy_reg4;
}
/* Initilize dm9000 board */
static void dmfe_init_dm9000(struct net_device *dev)
{
board_info_t *db = (board_info_t *) dev->priv;
DMFE_DBUG(0, "dmfe_init_dm9000()", 0);
//edit by fae
#if 0
/* set the internal PHY power-on, GPIOs normal, and wait 2ms */
iow(db, 0x1F, 1); /* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY */
udelay(500);
iow(db, 0x1F, 0); /* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY */
if(ETH_DM9008AE == board_nic) //DM9008
{
udelay(200);
/* set the internal PHY power-on, GPIOs normal, and wait 2ms */
iow(db, 0x1F, 1); /* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY */
udelay(700);
iow(db, 0x1F, 0); /* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY */
}
#endif
udelay(20);
/* do a software reset and wait 20us */
iow(db, DM9000_NCR, 3);
udelay(20); /* wait 20us at least for software reset ok */
iow(db, DM9000_NCR, 3); /* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on. Added by SPenser */
udelay(20); /* wait 20us at least for software reset ok */
/* I/O mode */
db->io_mode = ior(db, 0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */
//edit by fae
#if 1
/* set the internal PHY power-on, GPIOs normal, and wait 2ms */
iow(db, 0x1F, 1); /* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY */
udelay(500);
iow(db, 0x1F, 0); /* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY */
/* set the internal PHY power-on, GPIOs normal, and wait 2ms */
iow(db, 0x1F, 1); /* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY */
/* Set PHY */
db->op_mode = media_mode;
set_PHY_mode(db);
udelay(700);
iow(db, 0x1F, 0); /* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY */
#else
/* Set PHY */
db->op_mode = media_mode;
set_PHY_mode(db);
#endif
/* Init needed register value */
db->reg0 = DM9000_NCR;
/* User passed argument */
db->reg5 = reg5;
db->reg8 = reg8;
db->reg9 = reg9;
db->rega = rega;
/* Program operating register */
iow(db, 0x00, 0);
iow(db, 0x02, 0); /* TX Polling clear */
iow(db, 0x2d, 0x80);
iow(db, 0x08, 0x3f); /* Less 3kb, 600us */
iow(db, 0x2f, 0); /* Special Mode */
iow(db, 0x01, 0x2c); /* clear TX status */
iow(db, 0xfe, 0x0f); /* Clear interrupt status */
if(ETH_DM9008AE == board_nic) //DM9008
{
iow(db, 0x8, 0x37);
iow(db, 0x9, 0x38);
iow(db, 0xa, 0x28);
}
/* Set address filter table */
dm9000_hash_table(dev);
//edit by fae
#if 1
iow(db, 0x38, 0x21);
iow(db, 0x30, 0x81);
iow(db, 0xa, 0x28);
// iow(db, 0x39, 0x01);
iow(db, 0x32, 0x02);
db->rx_int_timer = 0;
#endif
/* Activate DM9000 */
iow(db, 0x05, db->reg5 | 1); /* RX enable */
iow(db, 0xff, DM9000_REGFF); /* Enable TX/RX interrupt mask */
/* Init Driver variable */
db->link_failed = 0;
db->tx_pkt_cnt = 0;
db->queue_pkt_len = 0;
dev->trans_start = 0;
netif_carrier_on(dev);
spin_lock_init(&db->lock);
if(db->ioaddr==0x20300000)
{
*pFIO_FLAG_C = WAN_FIO_PATTERN;
*pFIO_INEN |= WAN_FIO_PATTERN;
}
if(db->ioaddr==0x20300010)
{
*pFIO_FLAG_C = LAN_FIO_PATTERN;
*pFIO_INEN |= LAN_FIO_PATTERN;
}
}
//edit by fae 05/08
#if 1
/* reset dm9000 board */
static void dmfe_reset_dm9000(struct net_device *dev)
{
board_info_t *db = (board_info_t *) dev->priv;
DMFE_DBUG(0, "dmfe_reset_dm9000()", 0);
printk("\ndmfe_reset_dm9000()\n");
udelay(20);
/* do a software reset and wait 20us */
iow(db, DM9000_NCR, 3);
udelay(20); /* wait 20us at least for software reset ok */
iow(db, DM9000_NCR, 3); /* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on. Added by SPenser */
udelay(20); /* wait 20us at least for software reset ok */
/* Init needed register value */
db->reg0 = DM9000_NCR;
/* User passed argument */
db->reg5 = reg5;
db->reg8 = reg8;
db->reg9 = reg9;
db->rega = rega;
/* Program operating register */
iow(db, 0x00, 0);
iow(db, 0x02, 0); /* TX Polling clear */
iow(db, 0x2d, 0x80);
iow(db, 0x08, 0x3f); /* Less 3kb, 600us */
iow(db, 0x2f, 0); /* Special Mode */
iow(db, 0x01, 0x2c); /* clear TX status */
iow(db, 0xfe, 0x0f); /* Clear interrupt status */
if(ETH_DM9008AE == board_nic) //DM9008
{
iow(db, 0x8, 0x37);
iow(db, 0x9, 0x38);
iow(db, 0xa, 0x28);
}
//edit by fae
#if 1
iow(db, 0x38, 0x21);
iow(db, 0x30, 0x81);
iow(db, 0xa, 0x28);
// iow(db, 0x39, 0x01);
iow(db, 0x32, 0x02);
db->rx_int_timer = 0;
#endif
/* Activate DM9000 */
iow(db, 0x05, db->reg5 | 1); /* RX enable */
iow(db, 0xff, DM9000_REGFF); /* Enable TX/RX interrupt mask */
/* Init Driver variable */
db->link_failed = 0;
db->tx_pkt_cnt = 0;
db->queue_pkt_len = 0;
dev->trans_start = 0;
netif_carrier_on(dev);
spin_lock_init(&db->lock);
if(db->ioaddr==0x20300000)
{
*pFIO_FLAG_C = WAN_FIO_PATTERN;
*pFIO_INEN |= WAN_FIO_PATTERN;
}
if(db->ioaddr==0x20300010)
{
*pFIO_FLAG_C = LAN_FIO_PATTERN;
*pFIO_INEN |= LAN_FIO_PATTERN;
}
}
#endif
/* Hardware start transmission.
* Send a packet to media from the upper layer.
*/
static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
board_info_t *db = (board_info_t *) dev->priv;
char *data_ptr;
int i, tmplen;
DMFE_DBUG(0, "dmfe_start_xmit", 0);
//edit by fae
#if 1
if(db->tx_pkt_cnt) return 1;
// if(ior(db, 0x02) & 0x01) return 1;
// ior(db, 0x30);
// if(ior(db, 0x30) & 0x60) return 1;
#else
if (db->tx_pkt_cnt >= 1) return 1;
#endif
netif_stop_queue(dev);
/* Disable all interrupt */
iow(db, 0xff, 0x80);
//edit by fae
#if 1
/* Set TX length to DM9000 */
iow(db, 0xfc, skb->len & 0xff);
iow(db, 0xfd, (skb->len >> 8) & 0xff);
#endif
/* Move data to DM9000 TX RAM */
data_ptr = (char *) skb->data;
outb(0xf8, db->ioaddr);
db->sent_pkt_len = skb->len;
if (db->io_mode == DM9000_BYTE_MODE) { /* Byte mode */
for (i = 0; i < skb->len; i++)
outb((data_ptr[i] & 0xff), db->io_data);
} else if (db->io_mode == DM9000_WORD_MODE) { /* Word mode */
tmplen = (skb->len + 1) / 2;
for (i = 0; i < tmplen; i++)
outw(((u16 *) data_ptr)[i], db->io_data);
} else { /* DWord mode */
tmplen = (skb->len + 3) / 4;
for (i = 0; i < tmplen; i++)
outl(((u32 *) data_ptr)[i], db->io_data);
}
//edit by fae
#if 1
db->tx_pkt_cnt++;
// iow(db, 0x2, 0x1); /* Cleared after TX complete */
/* saved the time stamp */
dev->trans_start = jiffies;
/* free this SKB */
dev_kfree_skb(skb);
#else
/* TX control: First packet immediately send, second packet queue */
if (db->tx_pkt_cnt == 0) { /* First Packet */
db->tx_pkt_cnt++;
/* Set TX length to DM9000 */
iow(db, 0xfc, skb->len & 0xff);
iow(db, 0xfd, (skb->len >> 8) & 0xff);
/* Issue TX polling command */
iow(db, 0x2, 0x1); /* Cleared after TX complete */
/* saved the time stamp */
dev->trans_start = jiffies;
} else { /* Second packet */
db->tx_pkt_cnt++;
db->queue_pkt_len = skb->len;
}
/* free this SKB */
dev_kfree_skb(skb);
/* Re-enable resource check */
if (db->tx_pkt_cnt == 1) netif_wake_queue(dev);
#endif
/* Re-enable interrupt */
iow(db, 0xff, 0x83);
return 0;
}
/* Stop the interface.
* The interface is stopped when it is brought.
*/
static int dmfe_stop(struct net_device *dev)
{
board_info_t *db = (board_info_t *) dev->priv;
DMFE_DBUG(0, "dmfe_stop", 0);
/* deleted timer */
del_timer(&db->timer);
netif_stop_queue(dev);
/* free interrupt */
free_irq(dev->irq, dev);
/* RESET devie */
phy_write(db, 0x00, 0x8000); /* PHY RESET */
iow(db, 0x1f, 0x01); /* Power-Down PHY */
iow(db, 0xff, 0x80); /* Disable all interrupt */
iow(db, 0x05, 0x00); /* Disable RX */
#if FALSE /* Dump Statistic counter */
printk("\nRX FIFO OVERFLOW %lx\n", db->stats.rx_fifo_errors);
printk("RX CRC %lx\n", db->stats.rx_crc_errors);
printk("RX LEN Err %lx\n", db->stats.rx_length_errors);
printk("RX LEN < 64byte %x\n", db->runt_length_counter);
printk("RX LEN > 1514byte %x\n", db->long_length_counter);
printk("RESET %x\n", db->reset_counter);
printk("RESET: TX Timeout %x\n", db->reset_tx_timeout);
printk("RESET: RX Status Wrong %x\n", db->reset_rx_status);
#endif
return 0;
}
static void dmfe_tx_done(struct net_device *dev_ptr)
{
struct net_device *dev = dev_ptr;
board_info_t *db = (board_info_t *) dev->priv;
int tx_status = ior(db, 0x01); /* Got TX status */
DMFE_DBUG(0, "dmfe_tx_done()", 0);
//edit by fae
#if 1
// if(!(ior(db, 0x02) & 0x01))
// ior(db, 0x30);
// if(!(ior(db, 0x30) & 0x60))
{
db->tx_pkt_cnt--;
dev->trans_start = 0;
db->stats.tx_packets++;
netif_wake_queue(dev);
}
#else
if (tx_status & 0xc) { /* One packet sent complete */
db->tx_pkt_cnt--;
dev->trans_start = 0;
db->stats.tx_packets++;
if (db->tx_pkt_cnt > 0) { /* Queue packet check & send */
/* Set TX length to DM9000 */
iow(db, 0xfc, db->queue_pkt_len & 0xff);
iow(db, 0xfd, (db->queue_pkt_len >> 8) & 0xff);
/* Issue TX polling command */
iow(db, 0x2, 0x1); /* Cleared after TX complete */
dev->trans_start = jiffies; /* saved the time stamp */
}
netif_wake_queue(dev);
}
#endif
}
/* DM9102 insterrupt handler.
* receive the packet to upper layer, free the transmitted packet
*/
static int dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
board_info_t *db;
int int_status;
u8 reg_save;
unsigned long flags;
#if 0 /* comment by mhfan */
DMFE_DBUG(0, "dmfe_interrupt()", 0);
#else
/*
if (!(*pFIO_FLAG_C & LAN_FIO_PATTERN)) return IRQ_NONE;
*pFIO_FLAG_C = LAN_FIO_PATTERN;
asm __volatile__ ("ssync;");
*/
#endif /* comment by mhfan */
if (!dev)
{
DMFE_DBUG(1, "dmfe_interrupt() without DEVICE arg", 0);
return IRQ_NONE;
}
tintrflag++;
/* A real interrupt coming */
db = (board_info_t *) dev->priv;
#if 1 /* comment by mhfan */
spin_lock(&db->lock);
#else
spin_lock_irqsave(&db->lock,flags);
/*local_irq_save(flags); *//* comment by guang */
#endif /* comment by mhfan */
/* Save previous register address */
reg_save = inb(db->ioaddr);
/* Disable all interrupt */
//iow(db, 0xff, 0x80);
/* Got DM9000 interrupt status */
int_status = ior(db, 0xfe); /* Got ISR */
//edit by fae
#if 1
iow(db, 0xfe, int_status & 0xfc); /* Clear ISR status */
#else
iow(db, 0xfe, int_status); /* Clear ISR status */
#endif
/* clear irq status on interrupt lines
Add by Zhoujh ,2006.10.30 */
if(DM9000_ETH0_IO == db->ioaddr)
{
*pFIO_FLAG_C = WAN_FIO_PATTERN;
}
else
{
*pFIO_FLAG_C = LAN_FIO_PATTERN;
}
if (int_status & DM9000_LNKCHG_INTR)
{
/*
printk("link change:%s , speed:%s , duplex:%s \n",
(ior (db, 0x01) & 0x40) ? "ok": "fail",
(ior (db, 0x01) & 0x80) ? "10Mbps": "100Mbps",
(ior (db, 0x00 ) & 0x08) ? "Full": "Half");
*/
}
//edit by fae
#if 0
if (int_status & DM9000_TX_INTR)
{ /* Trnasmit Interrupt check */
//printk("%s TX\n",dev->name);
dmfe_tx_done(dev);
}
#endif
if (int_status & DM9000_RX_INTR)
{ /* Received the coming packet */
/*printk("%s RX\n",dev->name);*/
//edit by fae
#if 1
db->rx_int_timer = jiffies;
/*printk("%s RX\n",dev->name);*/
rxintrflag++;
dmfe_packet_receive(dev);
iow(db, 0xfe, DM9000_RX_INTR);
#else
/*printk("%s RX\n",dev->name);*/
rxintrflag++;
dmfe_tx_done(dev); /* perhaps it is a bug for chip */
dmfe_packet_receive(dev);
#endif
}
//edit by fae
#if 1
int_status |= ior(db, 0xfe); /* Got ISR */
if (int_status & DM9000_TX_INTR)
{ /* Trnasmit Interrupt check */
//printk("%s TX\n",dev->name);
dmfe_tx_done(dev);
iow(db, 0xfe, DM9000_TX_INTR);
}
#endif
/* Re-enable interrupt mask */
// iow(db, 0xff, 0x83);
/* Restore previous register address */
outb(reg_save, db->ioaddr);
spin_unlock(&db->lock);
//spin_unlock_irqrestore(&db->lock,flags);
return IRQ_HANDLED;
}
/*
Get statistics from driver.
*/
static struct net_device_stats *dmfe_get_stats(struct net_device *dev)
{
board_info_t *db = (board_info_t *) dev->priv;
DMFE_DBUG(0, "dmfe_get_stats", 0);
return &db->stats;
}
/*
Process the upper socket ioctl command
*/
static int dmfe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
DMFE_DBUG(0, "dmfe_do_ioctl()", 0);
return 0;
}
/*
A periodic timer routine
Dynamic media sense, allocated Rx buffer...
*/
static void dmfe_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
board_info_t *db = (board_info_t *) dev->priv;
u8 reg_save, tmp_reg;
//edit by fae
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -