/* Our watchdog timed out. Called by the networking layer */ static void dmfe_timeout(struct net_device *dev) { board_info_t *db = (board_info_t *)dev->priv; int i; DMFE_DBUG(0, "dmfe_TX_timeout()", 0); printk("TX time-out -- dmfe_timeout().\n"); db->reset_tx_timeout++; db->stats.tx_errors++; #if FALSE printk("TX packet count = %d\n", db->tx_pkt_cnt); printk("TX timeout = %d\n", db->reset_tx_timeout); printk("22H=0x%02x 23H=0x%02x\n",ior(db,0x22),ior(db,0x23)); printk("faH=0x%02x fbH=0x%02x\n",ior(db,0xfa),ior(db,0xfb)); #endif i=0; while((i++<100)&&(ior(db,DM9KS_TCR) & 0x01)) { udelay(30); } if(i<100) { db->tx_pkt_cnt = 0; netif_wake_queue(dev); } else { dmfe_reset(dev); } }
void __attribute__((interrupt("IRQ")))dm9000_isr(void) { unsigned char int_status,Rx_ready; unsigned short Rx_status,Rx_len; int i; if(EINT0PEND & (1 << 7)){ //dm9000 int_status = ior(0xfe); if(int_status & 1){ //rx Rx_ready = ior(0xf0); Rx_ready = ior(0xf0); if(Rx_ready == 1){ DM9000_INDEX = 0xf2; Rx_status = DM9000_DATA16; Rx_len = DM9000_DATA16; for(i = 0;i < (Rx_len + 1) / 2;i++){ ((unsigned short*)Net_Rxbuf)[i] = DM9000_DATA16; } /// uart_puts(Net_Rxbuf + 42); } iow(0xfe,1); } if(int_status & 2){//tx if(ior(0x01) & (4 | 8)){ uart_printf("dm9000 send complete\n"); } iow(0xfe,2); } EINT0PEND = (1 << 7); } VIC0ADDRESS = 0; VIC1ADDRESS = 0; }
static void dmfe_tx_done(unsigned long unused) { struct net_device *dev = dmfe_dev; board_info_t *db = (board_info_t *)dev->priv; int nsr; DMFE_DBUG(0, "dmfe_tx_done()", 0); nsr = ior(db, DM9KS_NSR); if (nsr & 0x0c) { if(nsr & 0x04) db->tx_pkt_cnt--; if(nsr & 0x08) db->tx_pkt_cnt--; if(db->tx_pkt_cnt < 0) { printk(KERN_DEBUG "DM9KS:tx_pkt_cnt ERROR!!\n"); while(ior(db,DM9KS_TCR) & 0x1){} db->tx_pkt_cnt = 0; } }else{ while(ior(db,DM9KS_TCR) & 0x1){} db->tx_pkt_cnt = 0; } netif_wake_queue(dev); return; }
/* Read a word data from SROM */ static u16 read_srom_word(board_info_t *db, int offset) { iow(db, DM9KS_EPAR, offset); iow(db, DM9KS_EPCR, 0x4); while(ior(db, DM9KS_EPCR)&0x1); /* Wait read complete */ iow(db, DM9KS_EPCR, 0x0); return (ior(db, DM9KS_EPDRL) + (ior(db, DM9KS_EPDRH) << 8) ); }
/* Open the interface. The interface is opened whenever "ifconfig" actives it. */ static int dmfe_open(struct net_device *dev) { board_info_t *db = (board_info_t *)dev->priv; u8 reg_nsr; int i; DMFE_DBUG(0, "dmfe_open", 0); /* [email protected] */ if (request_irq(dev->irq,&dmfe_interrupt, IRQF_TRIGGER_RISING,dev->name,dev)) return -EAGAIN; /* Initilize DM910X board */ dmfe_init_dm9000(dev); #ifdef DM8606 // control DM8606 printk("[8606]reg0=0x%04x\n",dm8606_read(db,0)); printk("[8606]reg1=0x%04x\n",dm8606_read(db,0x1)); #endif /* Init driver variable */ db->reset_counter = 0; db->reset_tx_timeout = 0; db->cont_rx_pkt_cnt = 0; /* check link state and media speed */ db->Speed =10; i=0; do { reg_nsr = ior(db,DM9KS_NSR); if(reg_nsr & 0x40) /* link OK!! */ { /* wait for detected Speed */ mdelay(200); reg_nsr = ior(db,DM9KS_NSR); if(reg_nsr & 0x80) db->Speed =10; else db->Speed =100; break; } i++; mdelay(1); }while(i<3000); /* wait 3 second */ //printk("i=%d Speed=%d\n",i,db->Speed); /* set and active a timer process */ init_timer(&db->timer); db->timer.expires = DMFE_TIMER_WUT; db->timer.data = (unsigned long)dev; db->timer.function = &dmfe_timer; add_timer(&db->timer); //Move to DM9000 initiallization was finished. netif_start_queue(dev); return 0; }
/* Set DM9000/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]; DMFE_DBUG(0, "dm9000_hash_table()", 0); /* enable promiscuous mode */ if (dev->flags & IFF_PROMISC){ //printk(KERN_INFO "DM9KS:enable promiscuous mode\n"); iow(db, DM9KS_RXCR, ior(db,DM9KS_RXCR)|(1<<1)); return; }else{ //printk(KERN_INFO "DM9KS:disable promiscuous mode\n"); iow(db, DM9KS_RXCR, ior(db,DM9KS_RXCR)&(~(1<<1))); } /* Receive all multicast packets */ if (dev->flags & IFF_ALLMULTI){ //printk(KERN_INFO "DM9KS:Pass all multicast\n"); iow(db, DM9KS_RXCR, ior(db,DM9KS_RXCR)|(1<<3)); }else{ //printk(KERN_INFO "DM9KS:Disable pass all multicast\n"); iow(db, DM9KS_RXCR, ior(db,DM9KS_RXCR)&(~(1<<3))); } /* 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); } }
/* 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 */ while(ior(db, DM9KS_EPCR)&0x1); /* 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); }
//----探测芯片的ID是否为DM9000A-------------------------------------------------- //功能:探测芯片的ID是否为DM9000A //参数:无 //返回:读取正确返回0,错误时返回错误号 //----------------------------------------------------------------------------- static u8 dm9000a_probe(void) { u32 id; // 读取厂商ID和产品ID号 id = ior(DM9000A_PIDL); id |= ior(DM9000A_PIDH)<<8; id |= ior(DM9000A_VIDL)<<16; id |= ior(DM9000A_VIDH)<<24; if (id != DM9000A_VID_PID) // 读出的ID应当为0x0A469000 { return -1; } return 0; }
//----DM9000A初始化------------------------------------------------------------- //功能:初始化DM9000A //参数:无 //返回:正常时返回0,错误时返回错误号 //----------------------------------------------------------------------------- u32 dm9000a_init(void) { u16 i; dm9000a_reset(); // 软件复位 if (dm9000a_probe() != 0) // 探查当前操作的芯片是否为DM9000A(读出ID进行对比) return -1; iow(DM9000A_GPR, 0x00); // PHYPD=0时使能PHY,默认为1表示不使能内部PHY Djy_DelayUs(20*mS); iow(DM9000A_NCR, 0x03); // 选择内部PHY Djy_DelayUs(20); iow(DM9000A_NCR, 0x03); // 选择内部PHY(重复一次) Djy_DelayUs(20); ior(DM9000A_NSR); // 清除发送状态(读取即可清除) dm9000a_set_macaddr(MyMAC); // 设置MAC地址 dm9000a_set_multicastaddr(); // 设置多播地址 set_phy_mode(); // 自动协商 while (!(phyr_h(1) & 0x20)) // 自动协商完成标志位 { Djy_EventDelay(5*mS); // 50mS } // 读回IO、Base模式 ehi.io = (ior(DM9000A_ISR)>>6) & 0x3; ehi.base = (phyr_h(17)>>12) & 0xF; semp_dm9000 = Lock_SempCreate(1, 1, NULL); if (semp_dm9000 == NULL) { return -1; } dm9000a_reset_to_new(); // TODO DM9000A具有IP、UDP、TCP的检验和自动计算功能 //... i = ior(DM9000A_NSR); // xxx del 需要等于0x40才表示连接成功 return 0; }
//----DM9000A复位--------------------------------------------------------------- //功能:软件复位DM9000A。某些寄存器的值不受软件复位的影响。 //参数:无 //返回:无 //----------------------------------------------------------------------------- void dm9000a_reset(void) { iow(DM9000A_NCR, 0x01); // RESET do { Djy_DelayUs(30); // 延时30us,应用手册上说至少20us } while (ior(DM9000A_NCR) & 0x01); iow(DM9000A_NCR, 0x00); }
//----读PHY(半字)-------------------------------------------------------------- //功能:从PHY中读取16位的数据 //参数:reg,寄存器偏移地址 //返回:读得的寄存器值 //----------------------------------------------------------------------------- static u16 phyr_h(u8 reg) { u16 tmp; iow(DM9000A_EPAR, reg|0x40); // 使用内部PHY时bit[7:6]要为01b iow(DM9000A_EPCR, 0x0C); // 选择PHY功能,读取功能 while (ior(DM9000A_EPCR) & 0x01) { Djy_DelayUs(10); } Djy_DelayUs(150); iow(DM9000A_EPCR, 0x00); // 由程序清零 tmp = ior(DM9000A_EPDRL); tmp |= ior(DM9000A_EPDRH)<<8; return tmp; }
static void dm9000_reset(struct board_info *db) { dev_dbg(db->dev, "resetting device\n"); /* Reset DM9000, see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 * The essential point is that we have to do a double reset, and the * instruction is to set LBK into MAC internal loopback mode. */ iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK); udelay(100); /* Application note says at least 20 us */ if (ior(db, DM9000_NCR) & 1) dev_err(db->dev, "dm9000 did not respond to first reset\n"); iow(db, DM9000_NCR, 0); iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK); udelay(100); if (ior(db, DM9000_NCR) & 1) dev_err(db->dev, "dm9000 did not respond to second reset\n"); }
//----写PHY(半字)-------------------------------------------------------------- //功能:向PHY中写入16位的数据 //参数:reg,寄存器偏移地址 // value,要写入的值 //返回:无 //----------------------------------------------------------------------------- static void phyw_h(u8 reg, u16 value) { iow(DM9000A_EPAR, reg|0x40);// 使用内部PHY时bit[7:6]要为01b iow(DM9000A_EPDRL, value&0xFF); iow(DM9000A_EPDRH, (value&0xFF00)>>8); iow(DM9000A_EPCR, 0x0A); // 选择PHY功能,写功能 while (ior(DM9000A_EPCR) & 0x01) { Djy_DelayUs(10); } Djy_DelayUs(150); iow(DM9000A_EPCR, 0x00); // 由程序清零 }
//#if defined(CONFIG_DM9000_16BIT) static void dm9000_reset(board_info_t *db) { dev_dbg(db->dev, "resetting device\n"); iow(db, DM9000_GPCR, 0x0f); iow(db, DM9000_GPR, 0); iow(db, DM9000_NCR, 3); do { udelay(100); } while (ior(db, DM9000_NCR) & 0x1); iow(db, DM9000_NCR, 0); iow(db, DM9000_NCR, 3); do { udelay(100); } while (ior(db, DM9000_NCR) & 0x1); if ((ior(db, DM9000_PIDL) != 0) || (ior(db, DM9000_PIDH) != 0x90)) printk(KERN_INFO "ERROR : resetting "); }
/* 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 */ while(ior(db, DM9KS_EPCR)&0x1); /* Wait read complete */ iow(db, DM9KS_EPCR, 0x0); /* Clear phyxcer write command */ }
//----------------------------------------------------------------------- int BspProxyImpl::registerRemoteIorWrapper(struct lua_State * state){ int n = lua_gettop(state); assert(n == 2); string ior(lua_tostring(state, 1)); int pid((int)lua_tonumber(state, 2)); while (BspProxyImpl::singleInstance->baseProcess_ == NULL) sleep(1); ((ProcessZero *) BspProxyImpl::singleInstance->baseProcess_)->registerRemoteIor(ior, pid); //std::cerr << "BspProxyImpl::registerRemoteIorWrapper --> Finished!!!" << std::endl; return 0; }
//----复位DM9000A到某一特定的原始状态--------------------------------------------- //功能:让DM9000A回到这样一个状态:除了中断未打开之外,其它有关于DM9000A的所有初始化工作 // 均已完成的地步。DM9000A芯片在从内部RAM中读数据时,如果读到的标志位不是1也不是0 // 时,会调用本函数,本函数需要清空RAM中的数据及使读写指针复位。 //参数:无 //返回:无 //----------------------------------------------------------------------------- void dm9000a_reset_to_new(void) { u8 flags; iow(DM9000A_IMR, 0x00); // 禁止发送、接收中断 ior(DM9000A_ISR); // 清除所有中断状态 flags = 0x80; // 读地址复位到0xC000,写地址复位到0x0000 flags |= 0x01; // 使能接收中断 iow(DM9000A_IMR, flags); iow(DM9000A_TCR, 0); iow(DM9000A_RCR, 0x3d); // 使能接收(广播、Runt包,不使用混杂模式) }
bool Node_Locator::process_cdd (const ACE_TCHAR *filename) { DANCE_TRACE ("Node_Locator::process_cdd"); if (!filename) { DANCE_ERROR (DANCE_LOG_ERROR, (LM_ERROR, DLINFO ACE_TEXT("Node_Locator::process_cdd - ") ACE_TEXT("Error: Provided with nil filename\n"))); return false; } ::DAnCE::Config_Handlers::XML_File_Intf file (filename); file.add_search_path (ACE_TEXT ("DANCE_ROOT"), ACE_TEXT ("/docs/schema/")); ::Deployment::Domain *plan = file.release_domain (); if (!plan) { DANCE_ERROR (DANCE_LOG_ERROR, (LM_ERROR, DLINFO ACE_TEXT("Node_Locator::process_cdd - ") ACE_TEXT("Error: Processing file <%C>\n"), filename)); return false; } // install nodes for (CORBA::ULong i=0; i < plan->node.length (); ++i) { ::Deployment::Resource resource; if (!get_resource_value (DAnCE::NODE_RESOURCE_TYPE, plan->node[i].resource, resource)) { DANCE_ERROR (DANCE_LOG_ERROR, (LM_ERROR, DLINFO ACE_TEXT("Node_Locator::process_cdd - ") ACE_TEXT("Error: Resource <%C> not found.\n"), DAnCE::NODE_RESOURCE_TYPE)); return false; } const ACE_TCHAR *val = 0; if (!::DAnCE::Utility::get_satisfierproperty_value (DAnCE::NODE_IOR, resource.property, val)) { DANCE_ERROR (DANCE_LOG_ERROR, (LM_ERROR, DLINFO ACE_TEXT("Node_Locator::process_cdd - ") ACE_TEXT("Error: Property <%C> not found.\n"), DAnCE::NODE_IOR)); return false; } ACE_CString ior(val); ior += "/"; ior += plan->node[i].name; ior += ".NodeManager"; ACE_CString destination (plan->node[i].name); DANCE_DEBUG (DANCE_LOG_MAJOR_DEBUG_INFO, (LM_INFO, DLINFO ACE_TEXT("Node_Locator::process_cdd - ") ACE_TEXT("Storing IOR %C for destination %C\n"), ior.c_str (), destination.c_str ())); this->nodes_.bind (destination, ior); } return true; }
bool_t debug_dm9000a_read_reg(char *param) { char *word, *next_param; int i; u32 reg = 0xFFFF; // 提取为SOCKET号 if (param) { next_param = param; word = Sh_GetWord(next_param, &next_param); reg = __sh_atol(word); word = Sh_GetWord(next_param, &next_param); if(word != NULL) { printf("\r\n参数错误\r\n"); return false; } } if (Lock_SempPend(semp_dm9000, 10000*mS) == true) { Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断 if (reg != 0xFFFF) { printf("\r\n读取DM9000A的【%4x】寄存器:", reg); printf("\r\n %4x:%4x", reg, ior(reg)); } else { printf("\r\n读取DM9000A的【所有】寄存器:"); printf("\r\n"); for (i=0; i<=0x1f; i++) { printf("\r\n %4x:%4x", i, ior(i)); } printf("\r\n"); for (i=0x22; i<=0x25; i++) { printf("\r\n %4x:%4x", i, ior(i)); } printf("\r\n"); for (i=0x28; i<=0x34; i++) { printf("\r\n %4x:%4x", i, ior(i)); } printf("\r\n"); i = 0x38; printf("\r\n %4x:%4x", i, ior(i)); i = 0x39; printf("\r\n %4x:%4x", i, ior(i)); printf("\r\n"); i = 0x50; printf("\r\n %4x:%4x", i, ior(i)); i = 0x51; printf("\r\n %4x:%4x", i, ior(i)); printf("\r\n"); i = 0xF0; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF1; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF2; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF4; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF5; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF6; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF8; printf("\r\n %4x:%4x", i, ior(i)); printf("\r\n"); for (i=0xFA; i<=0xFF; i++) { printf("\r\n %4x:%4x", i, ior(i)); } } printf("\r\n"); Int_RestoreAsynLine(cn_int_line_enet); // 打开DM9000A的外部中断 Lock_SempPost(semp_dm9000); } return true; }
/** * Reciving singlas from ethernet controller - * TX - transmited packet * RX - recived packet * LinkChange - Connected/Diconncted Ethernet Cable * */ void ethernet_interrupts_simple() { frame *curr_frame = 0; int filtered; uint8_t interruption =ior(ISR); //which interruption packet_num++; iow(IMR, 0); // iow(IMR, PAR_set); // printf("ISR 0x%2X \n",interruption); if( interruption & 0x01 ) //RX { iow(ISR,0x01); curr_frame = get_free_frame(); if(curr_frame == 0) { return; //ERROR no more free frames } aaa=ReceivePacket(curr_frame->f_data,&curr_frame->f_len); if(aaa == 0) { filtered = filter_packiets(curr_frame->f_data,curr_frame->f_len); if (filtered == 0) { printf(" RX:UDP \n"); add_rx_frame(curr_frame); } else if (filtered == 10) //arp { printf(" RX:ARP \n"); add_rx_frame(curr_frame); } else { release_frame(curr_frame); } curr_frame = 0; } else { printf("%s Recived Bad Frame \n",__FUNCTION__); release_frame(curr_frame); curr_frame = 0; } /* ethernet_header *tmp = (ethernet_header *) RXT; ether_addr adres = { 0x01, 0x60, 0x6E, 0x11, 0x01, 0x1F }; tmp->eth_src_addr = adres; TransmitPacket(RXT,rx_len);*/ } if(interruption & 0x02) //TX { iow(ISR,0x02); tx_control = 0; } if(interruption & 0x20) //LinkChange { iow(ISR,0x20); /* iow(0x00,0x01); // software reset usleep(10); enable interrupts to activate DM9000 ~on iow(IMR, INTR_set2); IMR REG. FFH PAR=1 only, or + PTM=1& PRM=1 enable RxTx interrupts iow(0xFF, 0x80); enable RX (Broadcast/ ALL_MULTICAST) ~go iow(RCR , RCR_set | RX_ENABLE | PASS_MULTICAST); RCR REG. 05 RXEN Bit [0] = 1 to enable the RX machine/ filter */ //printf(" LinkCHange \n"); if(link_control == 0) link_control = 1; else link_control = 0; } iow(IMR, INTR_set2); }
//--------------------------------------------------------------------------- void __fastcall TChatClientWindow::ReadIOR (String filename) { auto_ptr<TStringList> ior (new TStringList); ior->LoadFromFile (filename); ior_ = ior->Text; }
static irqreturn_t dmfe_interrupt(int irq, void *dev_id) /* for kernel 2.6.20*/ #endif #endif { struct net_device *dev = dev_id; board_info_t *db; int int_status,i; u8 reg_save; DMFE_DBUG(0, "dmfe_interrupt()", 0); /* A real interrupt coming */ db = (board_info_t *)dev->priv; spin_lock(&db->lock); /* Save previous register address */ reg_save = inb(db->io_addr); /* Disable all interrupt */ iow(db, DM9KS_IMR, DM9KS_DISINTR); /* Got DM9000/DM9010 interrupt status */ int_status = ior(db, DM9KS_ISR); /* Got ISR */ iow(db, DM9KS_ISR, int_status); /* Clear ISR status */ /* Link status change */ if (int_status & DM9KS_LINK_INTR) { netif_stop_queue(dev); for(i=0; i<500; i++) /*wait link OK, waiting time =0.5s */ { phy_read(db,0x1); if(phy_read(db,0x1) & 0x4) /*Link OK*/ { /* wait for detected Speed */ for(i=0; i<200;i++) udelay(1000); /* set media speed */ if(phy_read(db,0)&0x2000) db->Speed =100; else db->Speed =10; break; } udelay(1000); } netif_wake_queue(dev); //printk("[INTR]i=%d speed=%d\n",i, (int)(db->Speed)); } /* Received the coming packet */ if (int_status & DM9KS_RX_INTR) dmfe_packet_receive(dev); /* Trnasmit Interrupt check */ if (int_status & DM9KS_TX_INTR) dmfe_tx_done(0); if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT) { iow(db, DM9KS_IMR, 0xa2); } else { /* Re-enable interrupt mask */ iow(db, DM9KS_IMR, DM9KS_REGFF); } /* Restore previous register address */ outb(reg_save, db->io_addr); spin_unlock(&db->lock); #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) return IRQ_HANDLED; #endif }
//----从DM9000A中读出所有数据---------------------------------------------------- //功能:把DM9000A中的所有数据都读取出来,这些数据包会组织在lst链表中。 //参数:lst,数据包的接收链表头指针 //返回:数据包的接收链表头指针(可能与输入的lst不同) //----------------------------------------------------------------------------- struct enet_rcv_packet *__hw_read_in(struct enet_rcv_packet *lst) { u32 tmp; u32 len; u32 totlen = 0; static u32 times = 0; struct enet_rcv_packet *nlst = NULL; // 请求DM9000A硬件操作的信号量,等待5S秒如果没有发出去,则返回 if (Lock_SempPend(semp_dm9000, 0) == true) { // 接收过程中如果有中断发生,中断响应函数读 写DM9000的其他寄存器会打断接收过程。 Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断 ior(DM9000A_MRCMDX); // dummy read tmp = (u8)DATAR16(); if (tmp == 0x01) // 第一个字节读出为01h { switch (ehi.io) { case ENUM_DM9000A_IO_16BIT: // 16-bit while (tmp == 0x01) { len = dump_data16(lst, &nlst); if (len == -1) { dm9000a_reset_to_new(); totlen = 0; } else { totlen += len; // 试读下一帧数据,若为01h则继续读数,若为0则表示没有有效数据 ADDRW8(DM9000A_MRCMDX); tmp = (u8)DATAR16(); lst = nlst; } } __hw_ctrl(enum_enet_hw_ctrl_clear_rx_int); // 清除接收中断 break; case ENUM_DM9000A_IO_32BIT: // 32-bit break; case ENUM_DM9000A_IO_8BIT: // 8-bit break; default: break; } } else if (tmp != 0) { times++; if (times > 5) { debug_dm9000a_read_reg(NULL); } dm9000a_reset_to_new(); totlen = 0; if (times > 5) { debug_dm9000a_read_reg(NULL); times = 0; } } Int_RestoreAsynLine(cn_int_line_enet); // 打开DM9000A的外部中断 Lock_SempPost(semp_dm9000); } return nlst; }
/* Hardware start transmission. Send a packet to media from the upper layer. */ static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev) { board_info_t *db = (board_info_t *)dev->priv; char * data_ptr; int i, tmplen; u16 MDWAH, MDWAL; #ifdef TDBUG /* check TX FIFO pointer */ u16 MDWAH1, MDWAL1; u16 tx_ptr; #endif DMFE_DBUG(0, "dmfe_start_xmit", 0); if (db->chip_revision != 0x1A) { if(db->Speed == 10) {if (db->tx_pkt_cnt >= 1) return 1;} else {if (db->tx_pkt_cnt >= 2) return 1;} }else if (db->tx_pkt_cnt >= 2) return 1; /* packet counting */ db->tx_pkt_cnt++; db->stats.tx_packets++; db->stats.tx_bytes+=skb->len; if (db->chip_revision != 0x1A) { if (db->Speed == 10) {if (db->tx_pkt_cnt >= 1) netif_stop_queue(dev);} else {if (db->tx_pkt_cnt >= 2) netif_stop_queue(dev);} }else if (db->tx_pkt_cnt >= 2) netif_stop_queue(dev); /* Disable all interrupt */ iow(db, DM9KS_IMR, DM9KS_DISINTR); MDWAH = ior(db,DM9KS_MDWAH); MDWAL = ior(db,DM9KS_MDWAL); /* Set TX length to reg. 0xfc & 0xfd */ iow(db, DM9KS_TXPLL, (skb->len & 0xff)); iow(db, DM9KS_TXPLH, (skb->len >> 8) & 0xff); /* Move data to TX SRAM */ data_ptr = (char *)skb->data; outb(DM9KS_MWCMD, db->io_addr); // Write data into SRAM trigger switch(db->io_mode) { case DM9KS_BYTE_MODE: for (i = 0; i < skb->len; i++) outb((data_ptr[i] & 0xff), db->io_data); break; case DM9KS_WORD_MODE: tmplen = (skb->len + 1) / 2; for (i = 0; i < tmplen; i++) outw(((u16 *)data_ptr)[i], db->io_data); break; case DM9KS_DWORD_MODE: tmplen = (skb->len + 3) / 4; for (i = 0; i< tmplen; i++) outl(((u32 *)data_ptr)[i], db->io_data); break; } #ifndef ETRANS /* Issue TX polling command */ iow(db, DM9KS_TCR, 0x1); /* Cleared after TX complete*/ #endif #ifdef TDBUG /* check TX FIFO pointer */ MDWAH1 = ior(db,DM9KS_MDWAH); MDWAL1 = ior(db,DM9KS_MDWAL); tx_ptr = (MDWAH<<8)|MDWAL; switch (db->io_mode) { case DM9KS_BYTE_MODE: tx_ptr += skb->len; break; case DM9KS_WORD_MODE: tx_ptr += ((skb->len + 1) / 2)*2; break; case DM9KS_DWORD_MODE: tx_ptr += ((skb->len+3)/4)*4; break; } if (tx_ptr > 0x0bff) tx_ptr -= 0x0c00; if (tx_ptr != ((MDWAH1<<8)|MDWAL1)) printk("[dm9ks:TX FIFO ERROR\n"); #endif /* Saved the time stamp */ dev->trans_start = jiffies; db->cont_rx_pkt_cnt =0; /* Free this SKB */ dev_kfree_skb(skb); /* Re-enable interrupt */ iow(db, DM9KS_IMR, DM9KS_REGFF); return 0; }
int __init dmfe_probe1(struct net_device *dev) { struct board_info *db; /* Point a board information structure */ u32 id_val; u16 i, dm9000_found = FALSE; u8 MAC_addr[6]={0x00,0x60,0x6E,0x33,0x44,0x55}; u8 HasEEPROM=0,chip_info; DMFE_DBUG(0, "dmfe_probe1()",0); /* Search All DM9000 serial NIC */ do { outb(DM9KS_VID_L, iobase); id_val = inb(iobase + 4); outb(DM9KS_VID_H, iobase); id_val |= inb(iobase + 4) << 8; outb(DM9KS_PID_L, iobase); id_val |= inb(iobase + 4) << 16; outb(DM9KS_PID_H, iobase); id_val |= inb(iobase + 4) << 24; if (id_val == DM9KS_ID || id_val == DM9010_ID) { /* Request IO from system */ if(!request_region(iobase, 2, dev->name)) return -ENODEV; printk(KERN_ERR"<DM9KS> I/O: %x, VID: %x \n",iobase, id_val); dm9000_found = TRUE; /* Allocated board information structure */ memset(dev->priv, 0, sizeof(struct board_info)); db = (board_info_t *)dev->priv; dmfe_dev = dev; db->io_addr = iobase; db->io_data = iobase + 4; db->chip_revision = ior(db, DM9KS_CHIPR); chip_info = ior(db,0x43); if((db->chip_revision!=0x1A) || ((chip_info&(1<<5))!=0) || ((chip_info&(1<<2))!=1)) return -ENODEV; /* driver system function */ dev->base_addr = iobase; dev->irq = irq; dev->open = &dmfe_open; dev->hard_start_xmit = &dmfe_start_xmit; dev->watchdog_timeo = 5*HZ; dev->tx_timeout = dmfe_timeout; dev->stop = &dmfe_stop; dev->get_stats = &dmfe_get_stats; dev->set_multicast_list = &dm9000_hash_table; dev->do_ioctl = &dmfe_do_ioctl; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,28) dev->ethtool_ops = &dmfe_ethtool_ops; #endif #ifdef CHECKSUM //dev->features |= NETIF_F_IP_CSUM; dev->features |= NETIF_F_IP_CSUM|NETIF_F_SG; #endif db->mii.dev = dev; db->mii.mdio_read = mdio_read; db->mii.mdio_write = mdio_write; db->mii.phy_id = 1; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) db->mii.phy_id_mask = 0x1F; db->mii.reg_num_mask = 0x1F; #endif //db->msg_enable =(debug == 0 ? DMFE_DEF_MSG_ENABLE : ((1 << debug) - 1)); /* Read SROM content */ for (i=0; i<64; i++) ((u16 *)db->srom)[i] = read_srom_word(db, i); /* Get the PID and VID from EEPROM to check */ id_val = (((u16 *)db->srom)[4])|(((u16 *)db->srom)[5]<<16); printk("id_val=%x\n", id_val); if (id_val == DM9KS_ID || id_val == DM9010_ID) HasEEPROM =1; /* Set Node Address */ for (i=0; i<6; i++) { if (HasEEPROM) /* use EEPROM */ dev->dev_addr[i] = db->srom[i]; else /* No EEPROM */ dev->dev_addr[i] = MAC_addr[i]; } }//end of if() iobase += 0x10; }while(!dm9000_found && iobase <= DM9KS_MAX_IO); return dm9000_found ? 0:-ENODEV; }
//----发送一帧数据--------------------------------------------------------------- //功能:发送一个数据包到以太网上 //参数:upsec,上层数据包(一个链表结构)的头指针 //返回:正常时为发送的字节数;错误时为-1 //----------------------------------------------------------------------------- s32 __hw_write_out(struct enet_send_section *upsec) { u16 dat; u32 i, len, times, totlen; struct enet_send_section* pt_ssec; // 请求DM9000A硬件操作的信号量,如果没有发出去,则返回 if (Lock_SempPend(semp_dm9000, 0) == true) { Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断 totlen = 0; pt_ssec = upsec; ADDRW8(DM9000A_MWCMD); if (ehi.io == 0) // 16-bit { u8* pt_data; // 定义字节为8位的,下面进行强制转换 while (pt_ssec != NULL) { pt_data = (u8*)pt_ssec->data; len = pt_ssec->count; totlen += len; if ((ptu32_t)pt_data & 0x01) //判断指针是否双字节对齐 { for (i=0; i<len; i+=2) { dat = pt_data[i] + (pt_data[i+1]<<8); DATAW16(dat); } } else { times = (len+1)/2; for (i=0; i<times; i++) DATAW16(((u16*)pt_data)[i]); } pt_ssec = pt_ssec->next_data_ssection; } } else if (ehi.io == 1) // 32-bit { } else if (ehi.io == 2) // 8-bit { } if (totlen > 0) { iow(DM9000A_TXPLH, (totlen>>8) & 0xff); iow(DM9000A_TXPLL, totlen & 0xff); iow(DM9000A_NSR, 0x2c); // 清除状态寄存器 iow(DM9000A_TCR, ior(DM9000A_TCR) | 0x01); //发送数据到以太网上 // 等待发送完成 // NSR中TX1END及TX2END(发送完成) // ISR中PTM(发送完成) times = 100; // 相当等待于3S while (!(ior(DM9000A_NSR) & 0x0C) || !(ior(DM9000A_ISR) & 0x02)) { if (times == 0) { dm9000a_reset_to_new(); break ; } times--; Djy_DelayUs(10); } }
/* Received a packet and pass to upper layer */ static void dmfe_packet_receive(struct net_device *dev) { board_info_t *db = (board_info_t *)dev->priv; struct sk_buff *skb; u8 rxbyte; u16 i, GoodPacket, tmplen = 0, MDRAH, MDRAL; u32 tmpdata; rx_t rx; u16 * ptr = (u16*)℞ u8* rdptr; DMFE_DBUG(0, "dmfe_packet_receive()", 0); db->cont_rx_pkt_cnt=0; do { /*store the value of Memory Data Read address register*/ MDRAH=ior(db, DM9KS_MDRAH); MDRAL=ior(db, DM9KS_MDRAL); ior(db, DM9KS_MRCMDX); /* Dummy read */ rxbyte = inb(db->io_data); /* Got most updated data */ #ifdef CHECKSUM if (rxbyte&0x2) /* check RX byte */ { printk("dm9ks: abnormal!\n"); dmfe_reset(dev); break; }else { if (!(rxbyte&0x1)) break; } #else if (rxbyte==0) break; if (rxbyte>1) { printk("dm9ks: Rxbyte error!\n"); dmfe_reset(dev); break; } #endif /* A packet ready now & Get status/length */ GoodPacket = TRUE; outb(DM9KS_MRCMD, db->io_addr); /* Read packet status & length */ switch (db->io_mode) { case DM9KS_BYTE_MODE: *ptr = inb(db->io_data) + (inb(db->io_data) << 8); *(ptr+1) = inb(db->io_data) + (inb(db->io_data) << 8); break; case DM9KS_WORD_MODE: *ptr = inw(db->io_data); *(ptr+1) = inw(db->io_data); break; case DM9KS_DWORD_MODE: tmpdata = inl(db->io_data); *ptr = tmpdata; *(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(KERN_INFO"<RX FIFO error>\n"); } if (rx.desc.status & 0x02) { db->stats.rx_crc_errors++; printk(KERN_INFO"<RX CRC error>\n"); } if (rx.desc.status & 0x80) { db->stats.rx_length_errors++; printk(KERN_INFO"<RX Length error>\n"); } if (rx.desc.status & 0x08) printk(KERN_INFO"<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++) inb(db->io_data); break; case DM9KS_WORD_MODE: tmplen = (rx.desc.length + 1) / 2; for (i = 0; i < tmplen; i++) inw(db->io_data); break; case DM9KS_DWORD_MODE: tmplen = (rx.desc.length + 3) / 4; for (i = 0; i < tmplen; i++) inl(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]=inb(db->io_data); break; case DM9KS_WORD_MODE: tmplen = (rx.desc.length + 1) / 2; for (i = 0; i < tmplen; i++) ((u16 *)rdptr)[i] = inw(db->io_data); break; case DM9KS_DWORD_MODE: tmplen = (rx.desc.length + 3) / 4; for (i = 0; i < tmplen; i++) ((u32 *)rdptr)[i] = inl(db->io_data); break; } /* Pass to upper layer */ skb->protocol = eth_type_trans(skb,dev); #ifdef CHECKSUM if((rxbyte&0xe0)==0) /* receive packet no checksum fail */ skb->ip_summed = CHECKSUM_UNNECESSARY; #endif netif_rx(skb); dev->last_rx=jiffies; db->stats.rx_packets++; db->stats.rx_bytes += rx.desc.length; db->cont_rx_pkt_cnt++; #ifdef RDBG /* check RX FIFO pointer */ u16 MDRAH1, MDRAL1; u16 tmp_ptr; MDRAH1 = ior(db,DM9KS_MDRAH); MDRAL1 = ior(db,DM9KS_MDRAL); tmp_ptr = (MDRAH<<8)|MDRAL; switch (db->io_mode) { case DM9KS_BYTE_MODE: tmp_ptr += rx.desc.length+4; break; case DM9KS_WORD_MODE: tmp_ptr += ((rx.desc.length+1)/2)*2+4; break; case DM9KS_DWORD_MODE: tmp_ptr += ((rx.desc.length+3)/4)*4+4; break; } if (tmp_ptr >=0x4000) tmp_ptr = (tmp_ptr - 0x4000) + 0xc00; if (tmp_ptr != ((MDRAH1<<8)|MDRAL1)) printk("[dm9ks:RX FIFO ERROR\n"); #endif if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT) { dmfe_tx_done(0); break; } } }while((rxbyte & 0x01) == DM9KS_PKT_RDY); DMFE_DBUG(0, "[END]dmfe_packet_receive()", 0); }