📄 dm9000.c
字号:
*(ptr+1) = tmpdata >> 16;
break;
default:
break;
}
/* Packet status check */
if (rx.desc.status & 0xbf)
{
GoodPacket = FALSE;
if (rx.desc.status & 0x01)
{
db->stats.rx_fifo_errors++;
printk("<RX FIFO error>\n");
}
if (rx.desc.status & 0x02)
{
db->stats.rx_crc_errors++;
printk("<RX CRC error>\n");
}
if (rx.desc.status & 0x80)
{
db->stats.rx_length_errors++;
printk("<RX Length error>\n");
}
if (rx.desc.status & 0x08)
printk("<Physical Layer error>\n");
}
if (!GoodPacket)
{
// drop this packet!!!
switch (db->io_mode)
{
case DM9KS_BYTE_MODE:
for (i=0; i<rx.desc.length; i++)
GETB(db->io_data);
break;
case DM9KS_WORD_MODE:
tmplen = (rx.desc.length + 1) / 2;
for (i = 0; i < tmplen; i++)
GETW(db->io_data);
break;
case DM9KS_DWORD_MODE:
tmplen = (rx.desc.length + 3) / 4;
for (i = 0; i < tmplen; i++)
GETL(db->io_data);
break;
}
continue;/*next the packet*/
}
skb = dev_alloc_skb(rx.desc.length+4);
if (skb == NULL )
{
printk(KERN_INFO "%s: Memory squeeze.\n", dev->name);
/*re-load the value into Memory data read address register*/
iow(db,DM9KS_MDRAH,MDRAH);
iow(db,DM9KS_MDRAL,MDRAL);
return;
}
else
{
/* Move data from DM9000 */
skb->dev = dev;
skb_reserve(skb, 2);
rdptr = (u8*)skb_put(skb, rx.desc.length - 4);
/* Read received packet from RX SARM */
switch (db->io_mode)
{
case DM9KS_BYTE_MODE:
for (i=0; i<rx.desc.length; i++)
rdptr[i]=GETB(db->io_data);
break;
case DM9KS_WORD_MODE:
tmplen = (rx.desc.length + 1) / 2;
for (i = 0; i < tmplen; i++)
((u16 *)rdptr)[i] = GETW(db->io_data);
break;
case DM9KS_DWORD_MODE:
tmplen = (rx.desc.length + 3) / 4;
for (i = 0; i < tmplen; i++)
((u32 *)rdptr)[i] = GETL(db->io_data);
break;
}
/* Pass to upper layer */
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
dev->last_rx=jiffies;
db->stats.rx_packets++;
db->stats.rx_bytes += rx.desc.length;
db->cont_rx_pkt_cnt++;
if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)
{
dmfe_tx_done(0);
break;
}
}
}while((rxbyte & 0x01) == DM9KS_PKT_RDY);
}
/*
Set DM9000A/DM9010 multicast address
*/
static void dm9000_hash_table(struct net_device *dev)
{
board_info_t *db = (board_info_t *)dev->priv;
struct dev_mc_list *mcptr = dev->mc_list;
int mc_cnt = dev->mc_count;
u32 hash_val;
u16 i, oft, hash_table[4];
/* Set Node address */
for (i = 0, oft = 0x10; i < 6; i++, oft++)
iow(db, oft, dev->dev_addr[i]);
/* 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 (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, oft = 0x16; i < 4; i++) {
iow(db, oft++, hash_table[i] & 0xff);
iow(db, oft++, (hash_table[i] >> 8) & 0xff);
}
}
/*
Calculate the CRC valude of the Rx packet
flag = 1 : return the reverse CRC (for the received packet CRC)
0 : return the normal CRC (for Hash Table index)
*/
static unsigned long cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
{
u32 crc = ether_crc_le(Len, Data);
if (flag)
return ~crc;
return crc;
}
/*
Read a byte from I/O port
*/
static u8 ior(board_info_t *db, int reg)
{
PUTB(reg, db->io_addr);
return GETB(db->io_data);
}
/*
Write a byte to I/O port
*/
static void iow(board_info_t *db, int reg, u8 value)
{
PUTB(reg, db->io_addr);
PUTB(value, db->io_data);
}
/*
Read a word from phyxcer
*/
static u16 phy_read(board_info_t *db, int reg)
{
/* Fill the phyxcer register into REG_0C */
iow(db, DM9KS_EPAR, DM9KS_PHY | reg);
iow(db, DM9KS_EPCR, 0xc); /* Issue phyxcer read command */
udelay(100); /* Wait read complete */
iow(db, DM9KS_EPCR, 0x0); /* Clear phyxcer read command */
/* The read data keeps on REG_0D & REG_0E */
return ( ior(db, DM9KS_EPDRH) << 8 ) | ior(db, DM9KS_EPDRL);
}
/*
Write a word to phyxcer
*/
static void phy_write(board_info_t *db, int reg, u16 value)
{
/* Fill the phyxcer register into REG_0C */
iow(db, DM9KS_EPAR, DM9KS_PHY | reg);
/* Fill the written data into REG_0D & REG_0E */
iow(db, DM9KS_EPDRL, (value & 0xff));
iow(db, DM9KS_EPDRH, ( (value >> 8) & 0xff));
iow(db, DM9KS_EPCR, 0xa); /* Issue phyxcer write command */
udelay(500); /* Wait write complete */
iow(db, DM9KS_EPCR, 0x0); /* Clear phyxcer write command */
}
/*
* probe the driver
*/
static int __init dm9k_drv_probe(struct platform_device *pdev)
{
struct net_device *ndev;
unsigned long base;
unsigned int *addr = NULL;
int ret = -ENODEV;
ndev = alloc_etherdev(sizeof(struct board_info));
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
return -ENOMEM;
}
ndev->dma = (unsigned char)-1;
if (pdev->num_resources < 2 || pdev->num_resources > 3) {
printk("DM9000: Wrong num of resources %d\n", pdev->num_resources);
ret = -ENODEV;
goto out;
}
base = pdev->resource[0].start;
ndev->irq = pdev->resource[1].start;
/*
* Request the regions.
*/
if (!request_mem_region(base, 4, ndev->name)) {
ret = -EBUSY;
goto out;
}
addr = ioremap(base, 4);
if (!addr) {
ret = -ENOMEM;
goto release_mem;
}
ret = dm9k_probe(ndev, (unsigned long)addr);
if (ret != 0) {
iounmap(addr);
release_mem:
release_mem_region(base, 4);
out:
printk("%s: not found (%d).\n", CARDNAME, ret);
kfree(ndev);
}
return ret;
}
static int dm9k_drv_remove(struct platform_device *pdev)
{
return 0;
}
static int dm9k_drv_suspend(struct platform_device *dev, pm_message_t state )
{
return 0;
}
static int dm9k_drv_resume(struct platform_device *dev)
{
return 0;
}
static struct platform_driver dm9k_driver = {
.probe = dm9k_drv_probe,
.remove = dm9k_drv_remove,
.suspend = dm9k_drv_suspend,
.resume = dm9k_drv_resume,
.driver = {
.name = "s3c2410-dm9ks",
.owner = THIS_MODULE,
}
};
static void uptech_dm9k_init(void)
{
u32 bwscon;
bwscon = __raw_readl(S3C2410_BWSCON);
bwscon &= ~(S3C2410_BWSCON_WS2|S3C2410_BWSCON_ST2|S3C2410_BWSCON_DW2_32);
bwscon |= (S3C2410_BWSCON_ST2|S3C2410_BWSCON_DW2_16);
__raw_writel(bwscon, S3C2410_BWSCON);
__raw_writel(S3C2410_BANKCON_Tacs4|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh4|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm, S3C2410_BANKCON2);
set_irq_type(IRQ_EINT2,IRQ_TYPE_LEVEL_HIGH);
s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);
s3c2410_gpio_pullup(S3C2410_GPF2, 0);
printk(KERN_INFO "Board init for dm9000a finished!\n");
}
/* Description:
when user used insmod to add module, system invoked init_module()
to initilize and register.
*/
int dm9k_init_module(void)
{
printk("*************** DM9000: dm9k_init_module\n");
switch(mode) {
case DM9KS_10MHD:
case DM9KS_100MHD:
case DM9KS_10MFD:
case DM9KS_100MFD:
media_mode = mode;
break;
default:
media_mode = DM9KS_AUTO;
}
uptech_dm9k_init();
return platform_driver_register(&dm9k_driver);
}
/* Description:
when user used rmmod to delete module, system invoked clean_module()
to un-register DEVICE.
*/
void __exit dm9k_cleanup_module(void)
{
struct net_device *dev = dmfe_dev;
unregister_netdev(dmfe_dev);
release_region(dev->base_addr, 2);
free_netdev(dev);
}
MODULE_LICENSE ("GPL");
module_init(dm9k_init_module);
module_exit(dm9k_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -