视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
dm9000驱动程序
2025-09-24 07:15:37 责编:小OO
文档
dm9000x.c in S3C2410_UBOOT_DM9000

S3C2410硬件平台下的UBOOT下的DM9000E驱动-S3C2410 hardware platforms und...原文链接

/*

dm9000.c: Version 1.1 09/11/2001

A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.

Copyright (C) 1997 Sten Wang

This program is free software; you can redistribute it and/or

modify it under the terms of the GNU General Public License

as published by the Free Software Foundation; either version 2

of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

Author: Sten Wang, 886-3-5798797-8517, E-mail: sten_wang@davicom.com.tw

Date: 10/28,1998

(C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.

V0.1106/20/2001REG_0A bit3=1, default enable BP with DA match

06/22/2001 Support DM9801 progrmming

E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000

E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200

R17 = (R17 & 0xfff0) | NF + 3

E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200

R17 = (R17 & 0xfff0) | NF

v1.00 modify by simon 2001.9.5

change for kernel 2.4.x

v1.1 11/09/2001 fix force mode bug

*/

/* Board/System/Debug information/definition ---------------- */

#if 0

typedef unsigned long ulong;

typedef unsigned char uchar;

typedef unsigned char u8;

typedef unsigned long u32;

typedef unsigned short ushort;

typedef unsigned short u16;

typedef unsigned int uint;

#endif

#include

#include

#include

//#include

#include

#include "net.h"

#include

//#include

#if 0

#include "type.h"

#include "net.h"

#include

#include

#include

#include

#include

#endif

#define DM9000_ID0x90000A46

#define DM9000_REG000x00

#define DM9000_REG050x30/* SKIP_CRC/SKIP_LONG */

#define DM9000_REG080x27

#define DM9000_REG090x38

#define DM9000_REG0A0x08

#define DM9000_REGFF0x83/* IMR */

#define DM9000_PHY0x40/* PHY address 0x01 */

#define DM9000_PKT_MAX1536/* Received packet max size */

#define DM9000_PKT_RDY0x01/* Packet ready to receive */

#define DM9000_ADDR_BASE0x08000000 //nGCS1

#define DM9000_MIN_IODM9000_ADDR_BASE+0x300

#define DM9000_MAX_IODM9000_ADDR_BASE+0x370

#define DM9000_INT_MII0x00

#define DM9000_EXT_MII0x80

#define DM9000_VID_L0x28

#define DM9000_VID_H0x29

#define DM9000_PID_L0x2A

#define DM9000_PID_H0x2B

#define DM9801_NOISE_FLOOR0x08

#define DM9802_NOISE_FLOOR0x05

#define DMFE_SUCC 0

#define MAX_PACKET_SIZE 1514

#define DMFE_MAX_MULTICAST 14

#if defined(DM9000_DEBUG)

#define DMFE_DBUG(dbug_now, msg, vaule) printf("dm

fe: %s %x\

4015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,

0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,

0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,

0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,

0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,

0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,

0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,

0x2802BEL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,

0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,

0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,

0x71B185L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,

0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,

0x7F6A0DBBL, 0x086D3D2DL, 0x916C97L, 0xE6635C01L,

0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,

0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,

0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,

0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,

0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,

0x4ADFA541L, 0x3DD5D7L, 0xA4D1C46DL, 0xD3D6F4FBL,

0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,

0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,

0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,

0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,

0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,

0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,

0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,

0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,

0xE3630B12L, 0x943B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,

0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,

0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,

0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,

0xFED41B76L, 0xD32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,

0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,

0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,

0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B23BL,

0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,

0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,

0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,

0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,

0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,

0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,

0x9BC2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,

0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,

0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,

0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,

0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,

0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,

0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,

0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,

0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,

0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,

0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,

0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,

0xBDBDF21CL, 0xCABAC28AL, 0x53B3933

0L, 0x24B4A3A6L,

0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,

0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,

0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL

};

/* function declaration ------------------------------------- */

int eth_init/*dmfe_probe*/();

static int dmfe_open(DEVICE *);

static int dmfe_recv(DEVICE *dev);

static int dmfe_start_xmit(DEVICE *, volatile void* packet, int length);

//static void dmfe_stop(DEVICE *);

//static struct enet_statistics * dmfe_get_stats(struct DEVICE *); make by simon 2001.9.4 for kernel 2.4

static struct net_device_stats * dmfe_get_stats(DEVICE *); // add by simon 2001.94 for kernel 2.4

//static int dmfe_do_ioctl(struct DEVICE *, struct ifreq *, int);

static void dmfe_interrupt(int , void *);

static void dmfe_timer(unsigned long);

static void dmfe_init_dm9000(DEVICE *);

static unsigned long cal_CRC(unsigned char *, unsigned int, u8);

static u8 ior(board_info_t *, int);

static void iow(board_info_t *, int, u8);

static u16 phy_read(board_info_t *, int);

static void phy_write(board_info_t *, int, u16);

static u16 read_srom_word(board_info_t *, int);

static void dmfe_packet_receive(DEVICE *);

static void dm9000_hash_table(DEVICE *);

#define SWAP_HARDWARE

/* DM9000 network baord routine ---------------------------- */

//extern void *malloc(int len);

//extern void free(void *p);

#define DATA(a) (a) //Don't swap Because s3c2410 use little endian

inline void outw(unsigned short value, unsigned long addr)

{

#ifndef SWAP_HARDWARE

unsigned char a,b=0;

unsigned short c=DATA(value);

int i,j=7,k=1,m=128;

a=c & 0x00ff;

for(i=1;i<=4;i++)

{

b=b|((a&k)<>j);

k*=2;

m/=2;

j--;

j--;

}

*(volatile unsigned short *)(addr)=b|(c&0xff00) ;/*((unsigned short)b)<<8;*/

#else

*(volatile unsigned short*)addr = DATA(value);

#endif

}

//inline void outb(unsigned char value, unsigned long addr)

inline void outb(unsigned char value, unsigned long addr)

{

#ifndef SWAP_HARDWARE

unsigned char a=value,b=0;

int i,j=7,k=1,m=128;

for(i=1;i<=4;i++)

{

b=b|((a&k)<>j);

k*=2;

m/=2;

j--;

j--;

}

*(volatile unsigned short *)(addr)=/*DATA((*/b /*) & 0x00ff)*/;/*((unsigned short)b)<<8;*/

#else

*(volatile unsigned short*)addr = (value & 0x00ff);

#endif

}

inline unsigned char inb(unsigned long addr)

{

#ifndef SWAP_HARDWARE

unsigned char b=0,a=(*(volatile unsigned short *)(addr)) &0x00ff;

int i,j=7,k=1,m=128;

for(i=1;i<=4;i++)

{

b=b|((a&k)<>j);

k*=2;

m/=2;

j--;

j--;

}

return b;

#else

//return (((*(volatile unsigned short *)(

p))) &0x00ff);

unsigned short val;

val = *(volatile unsigned short*)addr;

return (unsigned char)( val & 0x00ff );

#endif

}

inline unsigned short inw(unsigned long addr)

{

#ifndef SWAP_HARDWARE

unsigned char b=0,a;

unsigned short c=DATA((*(volatile unsigned short *)(addr)));

int i,j=7,k=1,m=128;

a=c & 0x00ff;

for(i=1;i<=4;i++)

{

b=b|((a&k)<>j);

k*=2;

m/=2;

j--;

j--;

}

return b|(c&0xff00);

#else

unsigned short val;

val = *(volatile unsigned short*)addr;

return (DATA(val));

#endif

}

struct rx_buff {

u16 rx_busy[PKTBUFSRX];

u32 rx_pkt_len[PKTBUFSRX];

int rxIdx;

};

static struct rx_buff rx_pkt;

//extern void memset(void*,int,int);

#if 0

void outb(char byte, unsigned long addr)

{

}

unsigned char inb(unsigned long addr)

{

}

void outw(unsigned short value, unsigned long addr)

{

}

unsigned short inw(unsigned long addr)

{

}

void delay(int ms)

{

}

#endif

/*

Search DM9000 board, allocate space and register it

*/

struct board_info *db; /* Point a board information structure */

DEVICE *dev;

u32 iobase = DM9000_MIN_IO;

void cs00_get_enetaddr (uchar *addr)

{

int i;

/* Set Node Address */

for (i=0; i<6; i++)

addr[i] = enetaddr[i];//db->srom[i];

}

int eth_init/*dmfe_probe*/()

{

//struct board_info *db; /* Point a board information structure */

//DEVICE *dev;

//struct eth_device *dev,dev_t;

u32 id_val;

//u32 iobase = DM9000_MIN_IO;

u16 oft,i, dm9000_count = 0;

DMFE_DBUG(0, "dmfe_probe()

r system function */

dev->iobase = iobase;

dev->init = dmfe_open;

dev->send = dmfe_start_xmit;

//dev->halt = dmfe_stop;

dev->recv = dmfe_recv;

#endif

/* Read SROM content */

//for (i=0; i<; i++)

//((u16 *)db->srom)[i] = read_srom_word(db, i);

/* Set Node Address */

for (i=0; i<6; i++)

dev->enetaddr[i] = enetaddr[i];//db->srom[i];

for (i = 0, oft = 0x10; i < 6; i++, oft++)

iow(db, oft, dev->enetaddr[i]);

dmfe_init_dm9000(dev);

//dmfe_init_dm9000

//eth_register(dev);

}

//}while(iobase <= DM9000_MAX_IO);

if (dm9000_count) {

//request_irq(db->irq, &dmfe_interrupt,0,"DM9000 device

}

//status = get_reg(PP_RER);

// if ((status & PP_RER_RxOK) == 0)

// return 0;

outb(0xf2, db->ioaddr);

RxStatus = inw(DM9000_MIN_IO + 4);

RxLen = inw(DM9000_MIN_IO + 4);

//status = CS00_RTDATA; /* stat */

// rxlen = CS00_RTDATA; /* len */

// if(rxlen > PKTSIZE_ALIGN + PKTALIGN)

// printf("packet too big!\

");

if (RxLen > DM9000_PKT_MAX){

printk(" RST: RX Len:%x\

//phy_reg0 = 0x2100;

phy_reg0 =0x3100; //add by simon 2001.11.8

break;

}

phy_write(db, 4, phy_reg4);/* Set PHY media mode */

phy_write(db, 0, phy_reg0);/* Tmp */

}

iow(db, 0x1e, 0x01);/* Let GPIO0 output */

iow(db, 0x1f, 0x00);/* 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;

break;

}

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(DEVICE *dev)

{

board_info_t *db = (board_info_t *)dev->priv;

DMFE_DBUG(0, "dmfe_init_dm9000()

errupt status */

/* 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;

}

/*

Hardware start transmission.

Send a packet to media from the upper layer.

*/

static int dmfe_start_xmit(DEVICE *dev, volatile void* packet, int len)

{

board_info_t *db = (board_info_t *)(dev->priv);

char * data_ptr;

int i, tmplen;

unsigned long flags;

printk("Enter dmfe_start_xmit\

");

DMFE_DBUG(0, "dmfe_start_xmit

/

//del_timer(&db->timer);

/* disable system */

//dev->start = 0;/* interface disable */

//dev->tbusy = 1;/* can't transmit */

//mark above by simon 2001.9.4

/* 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 */

/* Dump Statistic counter */

#if 0

printk("\

RX FIFO OVERFLOW %lx\

tats;

}

/*

A periodic timer routine

Dynamic media sense, allocated Rx buffer...

*/

static void dmfe_timer(unsigned long data)

{

DEVICE *dev = (DEVICE *)data;

board_info_t *db = (board_info_t *)dev->priv;

u8 reg_save, tmp_reg;

DMFE_DBUG(0, "dmfe_timer()

8);

} else {

/* Word mode */

outb(0xf2, db->ioaddr);

/*

for(i=0; i<80; i+=2){

if(!(i % 10)) printf("\

");

printf(" %4x

0;

/* broadcast address */

//hash_table[3] = 0x8000;

/* the multicast address in Hash Table : 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)

{

unsigned long Crc = 0xffffffff;

while (Len--) {

Crc = CrcTable[(Crc ^ *Data++) & 0xFF] ^ (Crc >> 8);

}

if (flag) return ~Crc;

else return Crc;

}

/*

Read a byte from I/O port

*/

static u8 ior(board_info_t *db, int reg)

{

outb(reg, db->ioaddr);

return inb(db->io_data);

}

/*

Write a byte to I/O port

*/

static void iow(board_info_t *db, int reg, u8 value)

{

outb(reg, db->ioaddr);

outb(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, 0xc, DM9000_PHY | reg);

iow(db, 0xb, 0xc); /* Issue phyxcer read command */

udelay(100);/* Wait read complete */

iow(db, 0xb, 0x0); /* Clear phyxcer read command */

/* The read data keeps on REG_0D & REG_0E */

return ( ior(db, 0xe) << 8 ) | ior(db, 0xd);

}

/*

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, 0xc, DM9000_PHY | reg);

/* Fill the written data into REG_0D & REG_0E */

iow(db, 0xd, (value & 0xff));

iow(db, 0xe, ( (value >> 8) & 0xff));

iow(db, 0xb, 0xa);/* Issue phyxcer write command */

udelay(500);/* Wait write complete */

iow(db, 0xb, 0x0);/* Clear phyxcer write command */

}

#ifdef MODULE

MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");

MODULE_DESCRIPTION("Davicom DM9000 ISA/uP Fast Ethernet Driver");

MODULE_PARM(debug, "i");

MODULE_PARM(mode, "i");

MODULE_PARM(reg5, "i");

MODULE_PARM(reg9, "i");

MODULE_PARM(rega, "i");

MODULE_PARM(nfloor, "i");

/* Description:

when user used insmod to add module, system invoked init_module()

to initilize and register.

*/

int init_module(void)

{

DMFE_DBUG(0, "init_module()

n:

when user used rmmod to delete module, system invoked clean_module()

to un-register DEVICE.

*/

void cleanup_module(void)

{

DEVICE *next_dev;

board_info_t * db;

DMFE_DBUG(0, "clean_module()下载本文

显示全文
专题