📄 dm9000x.c
字号:
//iow(db, 0x09, 0x38); /* Less 3Kb, 200us */
//iow(db, 0x0a, 0x21); /* Less 3Kb, 200us */
//Marked by Spenser 10/02/2003
// iow(db, 0x1e, 0x03); /* Let GPIO0/GPIO1 output */
// iow(db, 0x1f, 0x01); /* Enable PHY */
}
/*
Init HomeRun DM9801
*/
static void program_dm9801(board_info_t *db, u16 HPNA_rev)
{
__u16 reg16, reg17, reg24, reg25;
if ( !nfloor )
nfloor = DM9801_NOISE_FLOOR;
reg16 = phy_read(db, 16);
reg17 = phy_read(db, 17);
reg24 = phy_read(db, 24);
reg25 = phy_read(db, 25);
switch(HPNA_rev) {
case 0xb900: /* DM9801 E3 */
reg16 |= 0x1000;
reg25 = ( (reg24 + nfloor) & 0x00ff) | 0xf000;
break;
case 0xb901: /* DM9801 E4 */
reg25 = ( (reg24 + nfloor) & 0x00ff) | 0xc200;
reg17 = (reg17 & 0xfff0) + nfloor + 3;
break;
case 0xb902: /* DM9801 E5 */
case 0xb903: /* DM9801 E6 */
default:
reg16 |= 0x1000;
reg25 = ( (reg24 + nfloor - 3) & 0x00ff) | 0xc200;
reg17 = (reg17 & 0xfff0) + nfloor;
}
phy_write(db, 16, reg16);
phy_write(db, 17, reg17);
phy_write(db, 25, reg25);
}
/*
Init LongRun DM9802
*/
static void program_dm9802(board_info_t *db)
{
__u16 reg25;
if ( !nfloor )
nfloor = DM9802_NOISE_FLOOR;
reg25 = phy_read(db, 25);
reg25 = (reg25 & 0xff00) + nfloor;
phy_write(db, 25, reg25);
}
/*
Identify NIC type
*/
static void identify_nic(board_info_t *db)
{
u16 phy_reg3;
iow(db, 0, DM9000_EXT_MII);
phy_reg3 = phy_read(db, 3);
switch(phy_reg3 & 0xfff0) {
case 0xb900:
if (phy_read(db, 31) == 0x4404) {
db->nic_type = HOMERUN_NIC;
program_dm9801(db, phy_reg3);
} else {
db->nic_type = LONGRUN_NIC;
program_dm9802(db);
}
break;
default: db->nic_type = FASTETHER_NIC;
break;
}
iow(db, 0, DM9000_INT_MII);
}
/*
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);
/* set the internal PHY power-on, GPIOs normal, and wait 2ms */
iow(db, 0x1F, 0); /* GPR (reg_1Fh)bit GPIO0=0 pre-activate PHY */
udelay(20); /* wait 2ms for PHY power-on ready */
/* do a software reset and wait 20us */
// iow(db, 0, 1); /* NCR (reg_00h) bit[0] RST=1, reset on */
// iow(db, 0, 3); /* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on. Added by SPenser */
iow(db, DM9000_NCR, 3);
udelay(20); /* wait 20us at least for software reset ok */
iow(db, 0, 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 */
// Marked by Spenser
/* set GPIO0=1 then GPIO0=0 to turn off and on the internal PHY */
iow(db, 0x1F, 1); /* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY */
iow(db, 0x1F, 0); /* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY */
udelay(4000); /* wait 4ms linking PHY (AUTO sense) if RX/TX */
/* I/O mode */
db->io_mode = ior(db, 0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */
/* NIC Type: FASTETHER, HOMERUN, LONGRUN */
identify_nic(db);
/* Set PHY */
db->op_mode = media_mode;
set_PHY_mode(db);
/* Init needed register value */
db->reg0 = DM9000_NCR;
if ( (db->nic_type != FASTETHER_NIC) && (db->op_mode & DM9000_1M_HPNA) )
db->reg0 |= DM9000_EXT_MII;
/* User passed argument */
db->reg5 = reg5;
db->reg8 = reg8;
db->reg9 = reg9;
db->rega = rega;
/* Program operating register */
//iow(db, 0x00, db->reg0);
iow(db, 0x00, 0x08);
iow(db, 0x02, 0); /* TX Polling clear */
iow(db, 0x2f, 0); /* Special Mode */
iow(db, 0x01, 0x2c); /* clear TX status */
iow(db, 0xfe, 0x0f); /* Clear interrupt status */
iow(db, 0x08, 0x37);
iow(db, 0x09, 0x38); /* Flow control: High/Low water */
iow(db, 0x0a, 0x29); /* flow control */
/* Set address filter table */
dm9000_hash_table(dev);
/* 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 = 1;
db->tx_pkt_cnt = 0;
db->queue_pkt_len = 0;
dev->trans_start = 0;
netif_carrier_on(dev);
spin_lock_init(&db->lock);
}
/*
Reset dm9000 board due to 32bits mode while excess collision or late collision.
*/
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);
iow(db, 0, 1); /* NCR (reg_00h) bit[0] RST=1, reset on. Added by SPenser */
udelay(1); /* wait 20us at least for software reset ok */
iow(db, 0, 0);
/* software reset 2 times */
iow(db, DM9000_NCR, 3);
udelay(20);
iow(db, DM9000_NCR, 3);
udelay(20);
/* Program operating register */
iow(db, 0x00, db->reg0);
iow(db, 0x02, 0); /* TX Polling clear */
iow(db, 0x08, 0x3f); /* Less 3Kb, 200us */
iow(db, 0x09, 0x38); /* Flow Control : High/Low Water */
iow(db, 0x0a, 0x29); /* TX Pause packet */
iow(db, 0x2f, 0); /* Special Mode */
iow(db, 0x01, 0x2c); /* clear TX status */
iow(db, 0xfe, 0x0f); /* Clear interrupt status */
/* 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 = 1;
db->tx_pkt_cnt = 0;
db->queue_pkt_len = 0;
dev->trans_start = 0;
netif_carrier_on(dev);
}
/*
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);
if (db->tx_pkt_cnt > 1)
return 1;
netif_stop_queue(dev);
/* Disable all interrupt */
iow(db, 0xff, 0x80);
/* 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);
}
/* 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);
// /* First Packet */
// db->tx_pkt_cnt++;
/* 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);
/* 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);
del_timer(&db->mdix_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 */
MOD_DEC_USE_COUNT;
/* Dump Statistic counter */
#if FALSE
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(unsigned long unused)
{
struct net_device *dev = dmfe_dev;
board_info_t *db = (board_info_t *)dev->priv;
//int TxStatus; //For Collision detect
int tx_status = ior(db, 0x01); /* Got TX status */
DMFE_DBUG(0, "dmfe_tx_done()", 0);
if (tx_status & 0xc)
{
/* One packet sent complete */
db->tx_pkt_cnt--;
dev->trans_start = 0;
db->stats.tx_packets++;
/* Queue packet check & send */
if (db->tx_pkt_cnt > 0)
{
/* 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);
}
netif_wake_queue(dev);
}
}
/*
DM9102 insterrupt handler
receive the packet to upper layer, free the transmitted packet
*/
static void 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;
DMFE_DBUG(0, "dmfe_interrupt()", 0);
if (!dev) {
DMFE_DBUG(1, "dmfe_interrupt() without DEVICE arg", 0);
return;
}
/* A real interrupt coming */
db = (board_info_t *)dev->priv;
spin_lock(&db->lock);
/* Save previous register address */
reg_save = inb(db->ioaddr);
/* Disable all interrupt */
iow(db, 0xff, 0x80);
//iow(db, 0xff, 0x81);
/* Got DM9000 interrupt status */
int_status = ior(db, 0xfe); /* Got ISR */
iow(db, 0xfe, int_status); /* Clear ISR status */
/* Received the coming packet */
if (int_status & DM9000_RX_INTR)
tasklet_schedule(&dmfe_rx_tasklet);
/* Trnasmit Interrupt check */
if (int_status & DM9000_TX_INTR)
tasklet_schedule(&dmfe_tx_tasklet);
/* Re-enable interrupt mask */
iow(db, 0xff, 0x83);
/* Restore previous register address */
outb(reg_save, db->ioaddr);
spin_unlock(&db->lock);
}
/*
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;
//u8 tmpreg;
DMFE_DBUG(0, "dmfe_timer()", 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -