📄 dmfe.c
字号:
{
db->HPNA_timer--;
if (!db->HPNA_timer)
dmfe_HPNA_remote_cmd_chk(db);
}
/* Timer active again */
db->timer.expires = DMFE_TIMER_WUT;
add_timer(&db->timer);
}
/*
Dynamic reset the DM910X board
Stop DM910X board
Free Tx/Rx allocated memory
Reset DM910X board
Re-initilize DM910X board
*/
static void dmfe_dynamic_reset(struct DEVICE *dev)
{
struct dmfe_board_info *db=dev->priv;
DMFE_DBUG(0, "dmfe_dynamic_reset()", 0);
/* Disable upper layer interface */
#if LINUX_VERSION_CODE < 0x20400
dev->tbusy=1; /* transmit packet disable */
dev->start=0; /* interface not ready */
#else
netif_stop_queue(dev);
#endif
/* Stop MAC controller */
db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */
update_cr6(db->cr6_data, dev->base_addr);
outl(0, dev->base_addr + DCR7);
outl(inl(dev->base_addr + DCR5), dev->base_addr + DCR5);
/* Free Rx Allocate buffer */
dmfe_free_rxbuffer(db);
/* system variable init */
db->tx_packet_cnt=0;
db->tx_queue_cnt=0;
db->rx_avail_cnt=0;
db->link_failed=1;
db->wait_reset=0;
/* Re-initilize DM910X board */
dmfe_init_dm910x(dev);
/* Restart upper layer interface */
#if LINUX_VERSION_CODE < 0x20400
dev->tbusy=0; /* Can transmit packet */
dev->start=1; /* interface ready */
#else
netif_wake_queue(dev);
#endif
}
/*
free all allocated rx buffer
*/
static void dmfe_free_rxbuffer(struct dmfe_board_info * db)
{
DMFE_DBUG(0, "dmfe_free_rxbuffer()", 0);
/* free allocated rx buffer */
while (db->rx_avail_cnt)
{
#if LINUX_VERSION_CODE > 0x20155
dev_kfree_skb((void *)(db->rx_ready_ptr->rx_skb_ptr));
#else
dev_kfree_skb((void *)(db->rx_ready_ptr->rx_skb_ptr), FREE_READ);
#endif
db->rx_ready_ptr=(struct rx_desc *)db->rx_ready_ptr->next_rx_desc;
db->rx_avail_cnt--;
}
}
/*
Reused the SK buffer
*/
static void dmfe_reused_skb(struct dmfe_board_info *db, struct sk_buff * skb)
{
struct rx_desc *rxptr=db->rx_insert_ptr;
if (!(rxptr->rdes0 & 0x80000000))
{
rxptr->rx_skb_ptr=(u32)skb;
rxptr->rdes2=virt_to_bus(skb->tail);
rxptr->rdes0=0x80000000;
db->rx_avail_cnt++;
db->rx_insert_ptr=(struct rx_desc *)rxptr->next_rx_desc;
}
else
DMFE_DBUG(0, "SK Buffer reused method error", db->rx_avail_cnt);
}
/*
Initialize transmit/Receive descriptor
Using Chain structure, and allocated Tx/Rx buffer
*/
static void dmfe_descriptor_init(struct dmfe_board_info *db, u32 ioaddr)
{
struct tx_desc *tmp_tx;
struct rx_desc *tmp_rx;
unsigned char *tmp_buf;
int i;
DMFE_DBUG(0, "dmfe_descriptor_init()", 0);
/* tx descriptor start pointer */
db->tx_insert_ptr=db->first_tx_desc;
db->tx_remove_ptr=db->first_tx_desc;
outl(virt_to_bus(db->first_tx_desc), ioaddr+DCR4); /* Init CR4 */
/* rx descriptor start pointer */
db->first_rx_desc=(struct rx_desc *)
((u32)db->first_tx_desc+sizeof(struct rx_desc)*TX_DESC_CNT);
db->rx_insert_ptr=db->first_rx_desc;
db->rx_ready_ptr=db->first_rx_desc;
outl(virt_to_bus(db->first_rx_desc), ioaddr+DCR3); /* Init CR3 */
/* Init Transmit chain */
tmp_buf=db->buf_pool_start;
for (tmp_tx=db->first_tx_desc, i=0; i<TX_DESC_CNT; i++, tmp_tx++)
{
tmp_tx->tx_buf_ptr=(u32)tmp_buf;
tmp_tx->tdes0=0;
tmp_tx->tdes1=0x81000000; /* IC, chain */
tmp_tx->tdes2=(u32)virt_to_bus(tmp_buf);
tmp_tx->tdes3=(u32)virt_to_bus(tmp_tx)+sizeof(struct tx_desc);
tmp_tx->next_tx_desc=(u32)((u32)tmp_tx+sizeof(struct tx_desc));
tmp_buf=(unsigned char *)((u32)tmp_buf+TX_BUF_ALLOC);
}
(--tmp_tx)->tdes3=(u32)virt_to_bus(db->first_tx_desc);
tmp_tx->next_tx_desc=(u32)db->first_tx_desc;
/* Init Receive descriptor chain */
for (tmp_rx=db->first_rx_desc, i=0; i<RX_DESC_CNT; i++, tmp_rx++)
{
tmp_rx->rdes0=0;
tmp_rx->rdes1=0x01000600;
tmp_rx->rdes3=(u32)virt_to_bus(tmp_rx)+sizeof(struct rx_desc);
tmp_rx->next_rx_desc=(u32)((u32)tmp_rx+sizeof(struct rx_desc));
}
(--tmp_rx)->rdes3=(u32)virt_to_bus(db->first_rx_desc);
tmp_rx->next_rx_desc=(u32)db->first_rx_desc;
/* pre-allocated Rx buffer */
allocated_rx_buffer(db);
}
/*
Update CR6 vaule
Firstly stop DM910X , then written value and start
*/
static void update_cr6(u32 cr6_data, u32 ioaddr)
{
u32 cr6_tmp;
cr6_tmp=cr6_data & ~0x2002; /* stop Tx/Rx */
outl(cr6_tmp, ioaddr+DCR6);
DELAY_5US;
outl(cr6_data, ioaddr+DCR6);
DELAY_5US;
}
/* Send a setup frame for DM9132
This setup frame initilize DM910X addres filter mode
*/
static void dm9132_id_table(struct DEVICE *dev, int mc_cnt)
{
struct dev_mc_list *mcptr;
u16 * addrptr;
u32 ioaddr=dev->base_addr+0xc0; /* ID Table */
u32 hash_val;
u16 i, hash_table[4];
DMFE_DBUG(0, "dm9132_id_table()", 0);
/* Node address */
addrptr=(u16 *)dev->dev_addr;
outw(addrptr[0], ioaddr);
ioaddr+=4;
outw(addrptr[1], ioaddr);
ioaddr+=4;
outw(addrptr[2], ioaddr);
ioaddr+=4;
/* Clear Hash Table */
for (i=0; i<4; i++)
hash_table[i]=0x0;
/* broadcast address */
hash_table[3]=0x8000;
/* the multicast address in Hash Table : 64 bits */
for (mcptr=dev->mc_list, i=0; i<mc_cnt; i++, mcptr=mcptr->next)
{
hash_val=cal_CRC((char *)mcptr->dmi_addr, 6, 0) & 0x3f;
hash_table[hash_val/16] |= (u16) 1 << (hash_val % 16);
}
/* Write the hash table to MAC MD table */
for (i=0; i<4; i++, ioaddr+=4)
{
outw(hash_table[i], ioaddr);
}
}
/* Send a setup frame for DM9102/DM9102A
This setup frame initilize DM910X addres filter mode
*/
static void send_filter_frame(struct DEVICE *dev, int mc_cnt)
{
struct dmfe_board_info *db=dev->priv;
struct dev_mc_list *mcptr;
struct tx_desc *txptr;
u16 * addrptr;
u32 * suptr;
int i;
DMFE_DBUG(0, "send_filetr_frame()", 0);
txptr = db->tx_insert_ptr;
suptr=(u32 *)txptr->tx_buf_ptr;
/* Node address */
addrptr=(u16 *)dev->dev_addr;
*suptr++=addrptr[0];
*suptr++=addrptr[1];
*suptr++=addrptr[2];
/* broadcast address */
*suptr++=0xffff;
*suptr++=0xffff;
*suptr++=0xffff;
/* fit the multicast address */
for (mcptr=dev->mc_list, i=0; i<mc_cnt; i++, mcptr=mcptr->next)
{
addrptr=(u16 *)mcptr->dmi_addr;
*suptr++=addrptr[0];
*suptr++=addrptr[1];
*suptr++=addrptr[2];
}
for (; i<14; i++)
{
*suptr++=0xffff;
*suptr++=0xffff;
*suptr++=0xffff;
}
/* prepare the setup frame */
db->tx_insert_ptr=(struct tx_desc *)txptr->next_tx_desc;
txptr->tdes1=0x890000c0;
/* Resource Check and Send the setup packet */
if (!db->tx_packet_cnt)
{
/* Resource Empty */
db->tx_packet_cnt++;
txptr->tdes0=0x80000000;
update_cr6(db->cr6_data | 0x2000, dev->base_addr);
outl(0x1, dev->base_addr+DCR1); /* Issue Tx polling command */
update_cr6(db->cr6_data, dev->base_addr);
dev->trans_start=jiffies;
}
else
{
/* Put into TX queue */
db->tx_queue_cnt++;
}
}
/*
Allocate rx buffer,
As possible as allocated maxiumn Rx buffer
*/
static void allocated_rx_buffer(struct dmfe_board_info *db)
{
struct rx_desc *rxptr;
struct sk_buff *skb;
rxptr=db->rx_insert_ptr;
while(db->rx_avail_cnt<RX_DESC_CNT)
{
if ( (skb=dev_alloc_skb(RX_ALLOC_SIZE)) == NULL )
break;
rxptr->rx_skb_ptr=(u32)skb;
rxptr->rdes2=virt_to_bus(skb->tail);
rxptr->rdes0=0x80000000;
rxptr=(struct rx_desc *)rxptr->next_rx_desc;
db->rx_avail_cnt++;
}
db->rx_insert_ptr=rxptr;
}
/*
Read one word data from the serial ROM
*/
static u16 read_srom_word(long ioaddr, int offset)
{
int i;
u16 srom_data = 0;
long cr9_ioaddr = ioaddr + DCR9;
outl(CR9_SROM_READ, cr9_ioaddr);
outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
/* Send the Read Command 110b */
SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
/* Send the offset */
for (i = 5; i >= 0; i--)
{
srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
SROM_CLK_WRITE(srom_data, cr9_ioaddr);
}
outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
for (i = 16; i > 0; i--)
{
outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
DELAY_5US;
srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
DELAY_5US;
}
outl(CR9_SROM_READ, cr9_ioaddr);
return srom_data;
}
/*
Auto sense the media mode
*/
static u8 dmfe_sense_speed(struct dmfe_board_info * db)
{
u8 ErrFlag=0;
u16 phy_mode;
/* CR6 bit18=0, select 10/100M */
update_cr6( (db->cr6_data & ~0x40000), db->ioaddr);
phy_mode=phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
phy_mode=phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
if ( (phy_mode & 0x24) == 0x24 )
{
if (db->chip_id == PCI_DM9132_ID) /* DM9132 */
phy_mode=phy_read(db->ioaddr, db->phy_addr, 7, db->chip_id) &0xf000;
else /* DM9102/DM9102A */
phy_mode=phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) &0xf000;
/* printk("Phy_mode %x ",phy_mode); */
switch (phy_mode)
{
case 0x1000: db->op_mode=DMFE_10MHF; break;
case 0x2000: db->op_mode=DMFE_10MFD; break;
case 0x4000: db->op_mode=DMFE_100MHF; break;
case 0x8000: db->op_mode=DMFE_100MFD; break;
default: db->op_mode=DMFE_10MHF;
DMFE_DBUG(0, "Media Type error, phy reg17", phy_mode);
ErrFlag=1;
break;
}
}
else
{
db->op_mode=DMFE_10MHF;
DMFE_DBUG(0, "Link Failed :", phy_mode);
ErrFlag=1;
}
return ErrFlag;
}
/*
Set 10/100 phyxcer capability
AUTO mode : phyxcer register4 is NIC capability
Force mode: phyxcer register4 is the force media
*/
static void dmfe_set_phyxcer(struct dmfe_board_info *db)
{
u16 phy_reg;
/* Select 10/100M phyxcer */
db->cr6_data&=~0x40000;
update_cr6(db->cr6_data, db->ioaddr);
/* DM9009 Chip: Phyxcer reg18 bit12=0 */
if (db->chip_id == PCI_DM9009_ID)
{
phy_reg=phy_read(db->ioaddr, db->phy_addr, 18, db->chip_id) & ~0x1000;
phy_write(db->ioaddr, db->phy_addr, 18, phy_reg, db->chip_id);
}
/* Phyxcer capability setting */
phy_reg=phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
if (!(db->media_mode & DMFE_AUTO)) /* AUTO/Force Mode Check */
{ /* Force Mode */
switch(db->media_mode)
{
case DMFE_10MHF: phy_reg|=0x20; break;
case DMFE_10MFD: phy_reg|=0x40; break;
case DMFE_100MHF: phy_reg|=0x80; break;
case DMFE_100MFD: phy_reg|=0x100; break;
}
if (db->chip_id==PCI_DM9009_ID) phy_reg&=0x61;
}
/* Write new capability to Phyxcer Reg4 */
if (!(phy_reg & 0x01e0)) {phy_reg|=db->PHY_reg4; db->media_mode|=DMFE_AUTO;}
phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
/* Restart Auto-Negotiation */
if ( db->chip_type && (db->chip_id==PCI_DM9102_ID) )
phy_write(db->ioaddr, db->phy_addr, 0, 0x1800, db->chip_id);
if (!db->chip_type)
phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -