字号:
/***************************************** Copyright (c) 2001-2002 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the Jasper DVD boot loader *//* * dm9000.c * * ethernet driver for DM9000 * * first revision by Ho Lee 11/05/2002 * EEPROM interface by Ho Lee 11/18/2002 */#include "config.h"#include "uart.h"#include "util.h"#include "quasar.h"#include "net.h"#include "specific.h"#ifdef SUPPORT_NETWORK#define DM9000_IGNOREID 0#define DM9000_RXDMA 0//// compatibility// typedef unsigned char u8;typedef unsigned short u16;typedef unsigned int u32;#define udelay(x) DELAY(x)#define virt_to_phys(x) ((unsigned int)(x))// // constant defitions related DM9000 chipset//#define DM9000_ID 0x90000A46#define DM9000_REG00 0x00#define DM9000_REG05 0x30 /* SKIP_CRC/SKIP_LONG */#define DM9000_REG08 0x27#define DM9000_REG09 0x38#define DM9000_REG0A 0x08#define DM9000_REGFF 0x83 /* IMR */#define DM9000_PHY 0x40 /* PHY address 0x01 */#define DM9000_PKT_MAX 1536 /* Received packet max size */#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */#define DM9000_MIN_IO 0x300#define DM9000_MAX_IO 0x370#define DM9000_INT_MII 0x00#define DM9000_EXT_MII 0x80#define DM9000_VID_L 0x28#define DM9000_VID_H 0x29#define DM9000_PID_L 0x2A#define DM9000_PID_H 0x2B#define DM9801_NOISE_FLOOR 0x08#define DM9802_NOISE_FLOOR 0x05enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD = 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO = 8, DM9000_1M_HPNA =0x10 };enum DM9000_NIC_TYPE { FASTETHER_NIC = 0, HOMERUN_NIC = 1, LONGRUN_NIC = 2 };//// type definitions// typedef struct board_info { u16 ioaddr; /* Register I/O base address */ u16 io_data; /* Data I/O address */ u16 irq; /* IRQ */ u16 tx_pkt_cnt; u16 queue_pkt_len; u8 op_mode; /* PHY operation mode */ u8 io_mode; /* 0:word, 2:byte */ u8 link_failed; /* Ever link failed */ u8 device_wait_reset; /* device state */ u8 nic_type; /* NIC type */} board_info_t;//// global variables// static board_info_t g_board_info;//// Basic I/O//static unsigned char __inline__ dmfe_inb(unsigned int addr){ return (unsigned char) (quasar_lbc_readl(addr) & 0x000000ff);}static unsigned short __inline__ dmfe_inw(unsigned int addr){ return (unsigned short) (quasar_lbc_readl(addr) & 0x0000ffff);}static void __inline__ dmfe_outb(unsigned int value, unsigned int addr){ quasar_lbc_writel(addr, value & 0x000000ff);}static void __inline__ dmfe_outw(unsigned int value, unsigned int addr){ quasar_lbc_writel(addr, value & 0x0000ffff);}static unsigned char ior(board_info_t *db, int reg){ dmfe_outb(reg, db->ioaddr); return dmfe_inb(db->io_data);}static void iow(board_info_t *db, int reg, u8 value){ dmfe_outb(reg, db->ioaddr); dmfe_outb(value, db->io_data);}// // Series I/O//#if !DM9000_RXDMAstatic void dmfe_insw(u16 *ptr, int len, int addr){ int i; volatile unsigned int *pquasar = (volatile unsigned int *) QUASAR_MAP_AREA; volatile unsigned int *paddr = pquasar + (QUASAR_LBC_READ_ADDR >> 2); volatile unsigned int *pdata = pquasar + (QUASAR_LBC_READ_DATA >> 2); volatile unsigned int *pstatus = pquasar + (QUASAR_LBC_STATUS >> 2); #define RX_ONETIME \ *paddr = addr; \ while (*pstatus & 0x01) \ ; \ ptr[i] = *pdata; for (i = 0; i < len; ++i) { RX_ONETIME }}#endifstatic void dmfe_outsw(u16 *ptr, int len, int addr){ int i; volatile unsigned int *pquasar = (volatile unsigned int *) QUASAR_MAP_AREA; volatile unsigned int *paddr = pquasar + (QUASAR_LBC_WRITE_ADDR >> 2); volatile unsigned int *pdata = pquasar + (QUASAR_LBC_WRITE_DATA >> 2); volatile unsigned int *pstatus = pquasar + (QUASAR_LBC_STATUS >> 2); #define TX_ONETIME \ *pdata = ptr[i]; \ while (*pstatus & 0x02) \ ; *paddr = addr; for (i = 0; i < len; ++i) { TX_ONETIME }}//// DMA//#if DM9000_RXDMAstatic void dmfe_start_rxdma(u16 *ptr, int len, int addr){ quasar_flush_cache_data_region((unsigned int) ptr, (unsigned int) ptr + (len << 1) + 8); quasar_setup_q2h_dma(1, virt_to_phys(ptr), len << 1); quasar_setup_lbc_readfifo(0, addr, len << 1); do { ; } while ((quasar_readl_reg(Q4_Q2H_int_status) & 0x08) == 0x08);}static void dmfe_cleanup_rxdma(void){ quasar_cleanup_lbc_fifo();}#endif//// Init & Main//int dmfe_probe(struct net_device *dev);static int dmfe_init(struct net_device *dev);static int dmfe_open(struct net_device *dev);static int dmfe_close(struct net_device *dev);static int dmfe_irq_pending(struct net_device *dev);static int dmfe_irq_clear(int irq_type, struct net_device *dev);static int dmfe_send_packet(struct sk_buff *skbuff, struct net_device *dev);static int dmfe_receive_packet(struct net_device *dev);static void dmfe_print_status(struct net_device *dev);static void identify_nic(board_info_t *db);static void program_dm9801(board_info_t *db, u16 HPNA_rev);static void program_dm9802(board_info_t *db);static void set_PHY_mode(board_info_t *db);static u16 phy_read(board_info_t *db, int reg);static void phy_write(board_info_t *db, int reg, u16 value);static unsigned short dmfe_eeprom_readw(struct net_device *dev, int reg);static void dmfe_eeprom_writew(struct net_device *dev, int reg, int data);int dmfe_probe(struct net_device *dev){ board_info_t *db = &g_board_info; u32 id_val; u16 iobase = DM9000_MIN_IO; quasar_init(); quasar_init_irq(); do { dmfe_outb(DM9000_VID_L, iobase); id_val = dmfe_inb(iobase + 4); dmfe_outb(DM9000_VID_H, iobase); id_val |= dmfe_inb(iobase + 4) << 8; dmfe_outb(DM9000_PID_L, iobase); id_val |= dmfe_inb(iobase + 4) << 16; dmfe_outb(DM9000_PID_H, iobase); id_val |= dmfe_inb(iobase + 4) << 24;#if DM9000_IGNOREID if (iobase == 0x300 && id_val != 0) { PrintFormat("IGNORE DM9000 chipset iobase=0x%x id=0x%x(90000A46)\n", iobase, id_val); id_val = DM9000_ID; }#endif// Ray added id_val = DM9000_ID; if (id_val == DM9000_ID) { PrintFormat("Found DM9000 chipset at I/O address %x\n", iobase); memset(db, 0, sizeof(*db)); dev->state = NETDEV_DOWN; dev->priv = db; dev->init = dmfe_init; dev->open = dmfe_open; dev->close = dmfe_close; dev->irq_pending = dmfe_irq_pending; dev->send_packet = dmfe_send_packet; dev->receive_packet = dmfe_receive_packet; dev->print_status = dmfe_print_status; dev->eeprom_size = 128; dev->eeprom_readw = dmfe_eeprom_readw; dev->eeprom_writew = dmfe_eeprom_writew; db->ioaddr = iobase; db->io_data = iobase + 4; // dev->irq = Q2H_LOC_IRQ; /* Set Node Address : now do not read from EEPROM */// memset(dev->dev_addr, 0, MACADDR_LEN); dev->dev_addr[0]=0x00; dev->dev_addr[1]=0x11; dev->dev_addr[2]=0x22; dev->dev_addr[3]=0x33; dev->dev_addr[4]=0x44; dev->dev_addr[5]=0x55; return 1; } iobase += 0x10; } while (iobase <= DM9000_MAX_IO); return 0;}int dmfe_reg_read(int reg){ board_info_t *db = (board_info_t *) dev->priv; db->io_mode = ior(db, 0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */}int dmfe_reg_write(int reg, unsigned char data){ board_info_t *db = (board_info_t *) dev->priv; iow(db, 0, 1);}int dmfe_init(struct net_device *dev){ int i; board_info_t *db = (board_info_t *) dev->priv; u8 reg0; /* RESET device */ iow(db, 0, 1); udelay(100); /* delay 100us */ /* 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 = DM9000_AUTO; set_PHY_mode(db); /* Init needed register value */ reg0 = DM9000_REG00; if ((db->nic_type != FASTETHER_NIC) && (db->op_mode & DM9000_1M_HPNA)) reg0 |= DM9000_EXT_MII; /* User passed argument */ /* Program operating register */ iow(db, 0x00, reg0); iow(db, 0x02, 0); /* TX Polling clear */ iow(db, 0x08, 0x3f); /* Less 3Kb, 200us */ iow(db, 0x09, DM9000_REG09);/* Flow Control : High/Low Water */ iow(db, 0x0a, DM9000_REG0A);/* Flow Control */ iow(db, 0x2f, 0); /* Special Mode */ iow(db, 0x01, 0x2c); /* clear TX status */ iow(db, 0xfe, 0x0f); /* Clear interrupt status */ /* Activate DM9000 */PrintFormat("RX Enable ....\n"); iow(db, 0x05, DM9000_REG05 | 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; /* Set node address */ PrintFormat("MAC = \n"); for (i = 0; i < 6; ++i) { PrintFormat("0x%x ", dev->dev_addr[i]); iow(db, 0x10 + i, dev->dev_addr[i]); } PrintFormat("\n"); return 0;}int dmfe_open(struct net_device *dev){ quasar_enable_irq(0, 0); dmfe_init(dev); dev->state = NETDEV_UP; return 0;}int dmfe_close(struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; quasar_disable_irq(0); /* 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 */ dev->state = NETDEV_DOWN; return 0;}int dmfe_irq_pending(struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; int irq_stat, irq_pend = 0; if (!quasar_irq_pending(0)) return 0; irq_stat = ior(db, 0xfe); if (irq_stat & 0x01) irq_pend |= ETHIRQ_RX; if (irq_stat & 0x02) irq_pend |= ETHIRQ_TX; return irq_pend;}int dmfe_irq_clear(int irq_type, struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; int irq_stat, irq_clear = 0; irq_stat = ior(db, 0xfe);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -