📄 ethernet driver for linux.txt
字号:
#define DRV_NAME "dmfe"
#define DRV_VERSION "1.0.1"
#define DRV_RELDATE "2006-5-23"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <asm/processor.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
#include <asm/soc-soc/soc_soc.h>
#include <asm/soc-soc/soc_soc_int.h>
/* Board/System/Debug information/definition ---------------- */
#define PCI_DM9132_ID 0x91321282 /* Davicom DM9132 ID */
#define PCI_DM9102_ID 0x91021282 /* Davicom DM9102 ID */
#define PCI_DM9100_ID 0x91001282 /* Davicom DM9100 ID */
#define PCI_DM9009_ID 0x90091282 /* Davicom DM9009 ID */
#define DM9102_IO_SIZE 0x80
#define DM9102A_IO_SIZE 0x100
#define TX_MAX_SEND_CNT 0x1 /* Maximum tx packet per time */
#define TX_DESC_CNT 0x10 /* Allocated Tx descriptors */
#define RX_DESC_CNT 0x40 /* Allocated Rx descriptors */
#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2) /* Max TX packet count */
#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3) /* TX wakeup count */
#define DESC_ALL_CNT (TX_DESC_CNT + RX_DESC_CNT)
#define TX_BUF_ALLOC 0x600
#define RX_ALLOC_SIZE 0x620
#define DM910X_RESET 1
#define CR0_DEFAULT 0x00E00000 /* TX & RX burst mode */
#define CR6_DEFAULT 0x00080000 /* HD */
#define CR7_DEFAULT 0x180c1 /* Interrupt enable */
#define CR15_DEFAULT 0x06 /* TxJabber RxWatchdog */
#define TDES0_ERR_MASK 0x4302 /* TXJT, LC, EC, FUE */
#define MAX_PACKET_SIZE 1514
#define DMFE_MAX_MULTICAST 14
#define RX_COPY_SIZE 0x620 //100 //make RX_COPY_SIZE>MAX_PACKET_SIZE to use copy mode.copy mode ok now,noncopy mode will panic,strange.
#define MAX_CHECK_PACKET 0x8000
#define DM9801_NOISE_FLOOR 8
#define DM9802_NOISE_FLOOR 5
#define DMFE_10MHF 0
#define DMFE_100MHF 1
#define DMFE_10MFD 4
#define DMFE_100MFD 5
#define DMFE_AUTO 8
#define DMFE_1M_HPNA 0x10
#define DMFE_TXTH_72 0x400000 /* TX TH 72 byte */
#define DMFE_TXTH_96 0x404000 /* TX TH 96 byte */
#define DMFE_TXTH_128 0x0000 /* TX TH 128 byte */
#define DMFE_TXTH_256 0x4000 /* TX TH 256 byte */
#define DMFE_TXTH_512 0x8000 /* TX TH 512 byte */
#define DMFE_TXTH_1K 0xC000 /* TX TH 1K byte */
#define DMFE_TIMER_WUT (jiffies + HZ * 1)/* timer wakeup time : 1 second */
#define DMFE_TX_TIMEOUT ((3*HZ)/2) /* tx packet time-out time 1.5 s" */
#define DMFE_TX_KICK (HZ/2) /* tx packet Kick-out time 0.5 s" */
#define DMFE_DBUG(dbug_now, msg, value) if (dmfe_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value))
#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
/* CR9 definition: SROM/MII */
#define CR9_SROM_READ 0x4800
#define CR9_SRCS 0x1
#define CR9_SRCLK 0x2
#define CR9_CRDOUT 0x8
#define SROM_DATA_0 0x0
#define SROM_DATA_1 0x4
#define PHY_DATA_1 0x20000
#define PHY_DATA_0 0x00000
#define MDCLKH 0x10000
#define PHY_POWER_DOWN 0x800
#define SROM_V41_CODE 0x14
#define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);
/* Sten Check */
#define DEVICE net_device
//----------------------------------------------------------------
// #define NO_PHY_PROBE
//----------------------------------------------------------------
/* Structure/enum declaration ------------------------------- */
#define SOC_SOC_DMFE1_BASE SOC_SOC_MAC1_BASE
#define SOC_SOC_DMFE2_BASE SOC_SOC_MAC2_BASE
#define SOC_SOC_DMFE_SIZE 0x80
#define SOC_SOC_DMFE1_IRQ SOC_SOC_MAC1_IRQ
#define SOC_SOC_DMFE2_IRQ SOC_SOC_MAC2_IRQ
//static char hwaddr[ETH_ALEN]={0xaa,0x02, 0x03, 0x04, 0x05, 0x06};
char hwaddr[6];//={0xaa,0x02, 0x03, 0x04, 0x05, 0x06};
struct tx_desc {
volatile u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
char *tx_buf_ptr; /* Data for us */
struct tx_desc *next_tx_desc;
} __attribute__(( aligned(32) ));
struct rx_desc {
u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
struct sk_buff *rx_skb_ptr; /* Data for us */
struct rx_desc *next_rx_desc;
} __attribute__(( aligned(32) ));
struct dmfe_board_info {
u32 chip_id; /* Chip vendor/Device ID */
u32 chip_revision; /* Chip revision */
struct DEVICE *next_dev; /* next device */
struct pci_dev *pdev; /* PCI device */
spinlock_t lock;
long ioaddr; /* I/O base address */
u32 cr0_data;
u32 cr5_data;
u32 cr6_data;
u32 cr7_data;
u32 cr15_data;
/* pointer for memory physical address */
dma_addr_t buf_pool_dma_ptr; /* Tx buffer pool memory */
dma_addr_t buf_pool_dma_start; /* Tx buffer pool align dword */
dma_addr_t desc_pool_dma_ptr; /* descriptor pool memory */
dma_addr_t first_tx_desc_dma;
dma_addr_t first_rx_desc_dma;
/* descriptor pointer */
unsigned char *buf_pool_ptr; /* Tx buffer pool memory */
unsigned char *buf_pool_start; /* Tx buffer pool align dword */
unsigned char *desc_pool_ptr; /* descriptor pool memory */
struct tx_desc *first_tx_desc;
struct tx_desc *tx_insert_ptr;
struct tx_desc *tx_remove_ptr;
struct rx_desc *first_rx_desc;
struct rx_desc *rx_insert_ptr;
struct rx_desc *rx_ready_ptr; /* packet come pointer */
unsigned long tx_packet_cnt; /* transmitted packet count */
unsigned long tx_queue_cnt; /* wait to send packet count */
unsigned long rx_avail_cnt; /* available rx descriptor count */
unsigned long interval_rx_cnt; /* rx packet count a callback time */
u16 HPNA_command; /* For HPNA register 16 */
u16 HPNA_timer; /* For HPNA remote device check */
u16 dbug_cnt;
u16 NIC_capability; /* NIC media capability */
u16 PHY_reg4; /* Saved Phyxcer register 4 value */
u8 HPNA_present; /* 0:none, 1:DM9801, 2:DM9802 */
u8 chip_type; /* Keep DM9102A chip type */
u8 media_mode; /* user specify media mode */
u8 op_mode; /* real work media mode */
u8 phy_addr;
u8 link_failed; /* Ever link failed */
u8 wait_reset; /* Hardware failed, need to reset */
u8 dm910x_chk_mode; /* Operating mode check */
u8 first_in_callback; /* Flag to record state */
struct timer_list timer;
/* System defined statistic counter */
struct net_device_stats stats;
/* Driver defined statistic counter */
unsigned long tx_fifo_underrun;
unsigned long tx_loss_carrier;
unsigned long tx_no_carrier;
unsigned long tx_late_collision;
unsigned long tx_excessive_collision;
unsigned long tx_jabber_timeout;
unsigned long reset_count;
unsigned long reset_cr8;
unsigned long reset_fatal;
unsigned long reset_TXtimeout;
/* NIC SROM data */
unsigned char srom[128];
};
enum dmfe_offsets {
DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20,
DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48,
DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70,
DCR15 = 0x78
};
enum dmfe_CR6_bits {
CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80,
CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000,
CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000
};
/* Global variable declaration ----------------------------- */
static int __devinitdata printed_version;
static char version[] __devinitdata =
KERN_INFO DRV_NAME ":SOC3210 SOC soc net driver, version "
DRV_VERSION " (" DRV_RELDATE ")\n";
static int dmfe_debug;
static unsigned char dmfe_media_mode = DMFE_AUTO;
static u32 dmfe_cr6_user_set;
/* For module input parameter */
static int debug;
static u32 cr6set;
static unsigned char mode = 8;
static u8 chkmode = 1;
static u8 HPNA_mode; /* Default: Low Power/High Speed */
static u8 HPNA_rx_cmd; /* Default: Disable Rx remote command */
static u8 HPNA_tx_cmd; /* Default: Don't issue remote command */
static u8 HPNA_NoiseFloor; /* Default: HPNA NoiseFloor */
static u8 SF_mode; /* Special Function: 1:VLAN, 2:RX Flow Control
4: TX pause packet */
static struct net_device *soc_soc_dmfe_dev;
unsigned long CrcTable[256] = {
0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
0x14015C4FL, 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,
0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
0x4ADFA541L, 0x3DD895D7L, 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, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
0x9B64C2B0L, 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, 0x53B39330L, 0x24B4A3A6L,
0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
};
/* function declaration ------------------------------------- */
static int dmfe_open(struct DEVICE *);
static int dmfe_start_xmit(struct sk_buff *, struct DEVICE *);
static int dmfe_stop(struct DEVICE *);
static struct net_device_stats * dmfe_get_stats(struct DEVICE *);
static void dmfe_set_filter_mode(struct DEVICE *);
static int dmfe_do_ioctl(struct DEVICE *, struct ifreq *, int);
static u16 read_srom_word(long ,int);
static irqreturn_t dmfe_interrupt(int , void *, struct pt_regs *);
static void dmfe_descriptor_init(struct dmfe_board_info *, unsigned long);
static void allocate_rx_buffer(struct dmfe_board_info *);
static void update_cr6(u32, unsigned long);
static void send_filter_frame(struct DEVICE * ,int);
static u16 phy_read(unsigned long, u8, u8, u32);
static void phy_write(unsigned long, u8, u8, u16, u32);
static void phy_write_1bit(unsigned long, u32);
static u16 phy_read_1bit(unsigned long);
static u8 dmfe_sense_speed(struct dmfe_board_info *);
static void dmfe_process_mode(struct dmfe_board_info *);
static void dmfe_timer(unsigned long);
static void dmfe_rx_packet(struct DEVICE *, struct dmfe_board_info *);
static void dmfe_free_tx_pkt(struct DEVICE *, struct dmfe_board_info *);
static void dmfe_reuse_skb(struct dmfe_board_info *, struct sk_buff *);
static void dmfe_dynamic_reset(struct DEVICE *);
static void dmfe_free_rxbuffer(struct dmfe_board_info *);
static void dmfe_init_dm910x(struct DEVICE *);
static unsigned long cal_CRC(unsigned char *, unsigned int, u8);
static void dmfe_set_phyxcer(struct dmfe_board_info *);
static int gc_dmfe_info_read (char *page, char **start, off_t off,
int count, int *eof, void *data);
/* DM910X network baord routine ---------------------------- */
/*
* Search DM910X board ,allocate space and register it
*/
void *dmfe_alloc_consistent(size_t size, dma_addr_t *dma_handle)
{
void *ret;
int gfp = GFP_ATOMIC;
ret = (void *) __get_free_pages(gfp, get_order(size));
if (ret != NULL) {
memset(ret, 0, size);
#ifdef CONFIG_NONCOHERENT_IO
dma_cache_wback_inv((unsigned long) ret, size);
ret = (void *)KSEG1ADDR(ret);
#endif
*dma_handle = virt_to_bus(ret);
}
return ret;
}
void dmfe_free_consistent(size_t size,
void *vaddr, dma_addr_t dma_handle)
{
unsigned long addr = (unsigned long) vaddr;
#ifdef CONFIG_NONCOHERENT_IO
addr = KSEG0ADDR(addr);
#endif
free_pages(addr, get_order(size));
}
#include <linux/proc_fs.h>
#define IRQ2CHIPID(irq) irq
#define IRQ2PHYADDR(irq) (irq + 4) //(irq?1:5)
static struct proc_dir_entry *proc_entry;
static int __devinit dmfe_init_one (int mac_base,int irq)
{
struct dmfe_board_info *db; /* board information structure */
struct net_device *dev;
u32 dev_rev, pci_pmr;
int i, err;
char mystr[100];
DMFE_DBUG(0, "dmfe_init_one()", 0);
if (!printed_version++)
printk(version);
/* Init network device */
dev = alloc_etherdev(sizeof(*db));
if (dev == NULL)
return -ENOMEM;
SET_MODULE_OWNER(dev);
soc_soc_dmfe_dev = dev;
if (!request_region(mac_base, SOC_SOC_DMFE_SIZE, "dmfe eth")) {
printk(KERN_ERR DRV_NAME ": Failed to request I/O regions\n");
err = -ENODEV;
goto err_out_disable;
}
/* Init system & device */
// db = dev->priv;
db = netdev_priv(dev);
/* Allocate Tx/Rx descriptor memory */
// add by tfl
// db->desc_pool_ptr = dmfe_alloc_consistent(sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
// db->buf_pool_ptr = dmfe_alloc_consistent(TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
db->desc_pool_ptr = (unsigned char *)dma_alloc_coherent(NULL,sizeof(struct tx_desc)*TX_DESC_CNT+ 0x20,&db->desc_pool_dma_ptr, GFP_ATOMIC);
db->buf_pool_ptr = (unsigned char *)dma_alloc_coherent(NULL,TX_BUF_ALLOC * TX_DESC_CNT + 4,&db->buf_pool_dma_ptr, GFP_ATOMIC);
db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
db->first_tx_desc_dma = db->desc_pool_dma_ptr;
db->buf_pool_start = db->buf_pool_ptr;
db->buf_pool_dma_start = db->buf_pool_dma_ptr;
db->chip_id = IRQ2CHIPID(irq);
db->ioaddr = mac_base;
db->chip_revision = 0;
dev->base_addr = db->ioaddr;
dev->irq = irq;
dev->open = &dmfe_open;
dev->hard_start_xmit = &dmfe_start_xmit;
dev->stop = &dmfe_stop;
dev->get_stats = &dmfe_get_stats;
dev->set_multicast_list = &dmfe_set_filter_mode;
dev->do_ioctl = &dmfe_do_ioctl;
spin_lock_init(&db->lock);
db->chip_type = 0;
/* Set Node address */
//get_random_bytes(hwaddr+4,2);
// hwaddr[5]=irq;
memcpy(dev->dev_addr, hwaddr, ETH_ALEN);
err = register_netdev (dev);
if (err)
goto err_out_res;
printk(KERN_INFO "%s: SOC3210 soc Davicom DM ",dev->name);
for (i = 0; i < 6; i++)
printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
printk(", irq %d.\n", dev->irq);
sprintf(mystr,"dmfe%d",irq);
proc_entry = create_proc_entry(mystr, S_IRUGO, NULL);
proc_entry->read_proc = gc_dmfe_info_read;
proc_entry->data = db;
return 0;
err_out_res:
release_region(mac_base, SOC_SOC_DMFE_SIZE);
err_out_disable:
// kfree(dev);
free_netdev(dev);
return err;
}
static void __devexit dmfe_remove_one (int mac_base)
{
struct net_device *dev = soc_soc_dmfe_dev;
// struct dmfe_board_info *db = dev->priv;
struct dmfe_board_info *db = netdev_priv(dev);
DMFE_DBUG(0, "dmfe_remove_one()", 0);
if (dev) {
// add by tfl
/*
dmfe_free_consistent(sizeof(struct tx_desc) *
DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
db->desc_pool_dma_ptr);
dmfe_free_consistent(TX_BUF_ALLOC * TX_DESC_CNT + 4,
db->buf_pool_ptr, db->buf_pool_dma_ptr);
*/
dma_free_coherent(NULL,sizeof(struct tx_desc)*TX_DESC_CNT+ 0x20,db->desc_pool_ptr ,db->desc_pool_dma_ptr);
dma_free_coherent(NULL,TX_BUF_ALLOC * TX_DESC_CNT + 4,db->buf_pool_ptr, db->buf_pool_dma_ptr);
unregister_netdev(dev);
release_region(mac_base, SOC_SOC_DMFE_SIZE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -