📄 dm9000xend.c
字号:
* Open the interface. * The interface is opened whenever "ifconfig" actives it. */static intdmfe_open(DM9000_END_DEVICE *pDrvCtrl){ /* Initialize DM9000 board */ dmfe_reset(pDrvCtrl); dmfe_init_dm9000(pDrvCtrl); return OK;}/* * Set PHY operating mode */static voidset_PHY_mode(DM9000_END_DEVICE *pDrvCtrl){ u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000; UINT32 id; id = dmfe_phy_read(pDrvCtrl, 0, MII_PHYSID1);/* printf("id = 0x%x\n\r", id); */ if (!(pDrvCtrl->op_mode & DM9000_AUTO)) { switch (pDrvCtrl->op_mode) { case DM9000_10MHD: phy_reg4 = ADVERTISE_10HALF | ADVERTISE_CSMA; phy_reg0 = 0; break; case DM9000_10MFD: phy_reg4 = ADVERTISE_10FULL | ADVERTISE_CSMA; phy_reg0 = BMCR_ANENABLE | BMCR_FULLDPLX; break; case DM9000_100MHD: phy_reg4 = ADVERTISE_100HALF | ADVERTISE_CSMA; phy_reg0 = BMCR_SPEED100; break; case DM9000_100MFD: phy_reg4 = ADVERTISE_100FULL | ADVERTISE_CSMA; phy_reg0 = BMCR_SPEED100 | BMCR_ANENABLE | BMCR_FULLDPLX; break; } dmfe_phy_write(pDrvCtrl, 0, MII_ADVERTISE, phy_reg4); /* Set PHY media mode */ dmfe_phy_write(pDrvCtrl, 0, MII_BMCR, phy_reg0); /* Tmp */ } iow(pDrvCtrl, DMFE_GPCR, 0x01); /* Let GPIO0 output ?*/ iow(pDrvCtrl, DMFE_GPR, 0x00); /* Enable PHY */}/* * Initilize dm9000 board */static voiddmfe_init_dm9000(DM9000_END_DEVICE *pDrvCtrl){ /* I/O mode */ pDrvCtrl->io_mode = ior(pDrvCtrl, DMFE_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ /* GPIO0 on pre-activate PHY */ iow(pDrvCtrl, DMFE_GPR, 0x00); /*REG_1F bit0 activate phyxcer */ /* Set PHY */ pDrvCtrl->op_mode = media_mode; set_PHY_mode(pDrvCtrl); /* Init needed register value */ pDrvCtrl->reg0 = DM9000_REG00; /* User passed argument */ pDrvCtrl->reg5 = reg5; pDrvCtrl->reg8 = reg8; pDrvCtrl->reg9 = reg9; pDrvCtrl->rega = rega; /* Program operating register */ iow(pDrvCtrl, DMFE_NCR, pDrvCtrl->reg0);/*关闭唤醒,全双工*/ iow(pDrvCtrl, DMFE_TCR, 0); /* TX Polling clear */ iow(pDrvCtrl, DMFE_BPTR, 0x3f); /* Less 3Kb, 200us */ iow(pDrvCtrl, DMFE_FCTR, pDrvCtrl->reg9); /* Flow Control : High/Low Water */ iow(pDrvCtrl, DMFE_FCR, pDrvCtrl->rega); /* Flow Control */ iow(pDrvCtrl, DMFE_SMCR, 0); /* Special Mode */ iow(pDrvCtrl, DMFE_NSR, 0x2c); /* clear TX status */ iow(pDrvCtrl, DMFE_ISR, ISR_CLR_STATUS); /* Clear interrupt status */ /* Set address filter table */ dm9000_hash_table(pDrvCtrl); /* Activate DM9000 */ iow(pDrvCtrl, DMFE_RCR, pDrvCtrl->reg5 | 0x1); /* RX enable *//*丢弃长包和CRC错误包,接收使能*/ iow(pDrvCtrl, DMFE_IMR, DM9000_REGFF); /* Enable TX/RX interrupt mask */ }/* * Hardware start transmission. * Send a packet to media from the upper layer. */static intdmfe_start_xmit(M_BLK* pMblk, DM9000_END_DEVICE *pDrvCtrl){ char *data_ptr; int i,packetLenAlign = 0, packetLen = 0; u32 tempdata; u8 reg_value; M_BLK* sendPacket = pMblk; int freeFlag = 0; END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); reg_value = ior(pDrvCtrl, DMFE_IMR); /* Disable all interrupts */ iow(pDrvCtrl, DMFE_IMR, IMR_PAR); /* Move data to DM9000 TX RAM */ DM9000_outb(DMFE_MWCMD, pDrvCtrl->ioaddr); if((sendPacket->m_next != NULL) && (sendPacket->mBlkPktHdr.len > sendPacket->m_len)) { char *tmp_buffer; packetLen = sendPacket->mBlkPktHdr.len; packetLenAlign = (packetLen + 3) / 4; tmp_buffer = data_ptr = (char *)memalign (4, packetLenAlign*4+4); do { memcpy(tmp_buffer, (char *)sendPacket->m_data, sendPacket->m_len); tmp_buffer += sendPacket->m_len; sendPacket = sendPacket->m_next; }while(sendPacket != NULL); freeFlag = 1; } else { data_ptr = (char *) sendPacket->m_data; packetLen = sendPacket->m_len; packetLenAlign = (sendPacket->m_len + 3) / 4; } for (i = 0; i < packetLenAlign; i++) { memcpy(&tempdata, data_ptr+i*sizeof(tempdata),sizeof(tempdata)); DM9000_outl(tempdata, pDrvCtrl->io_data); } /* TX control: First packet immediately send, second packet queue */ /* Set TX length to DM9000 */ iow(pDrvCtrl, DMFE_TXPLL, (packetLen) & 0xff); iow(pDrvCtrl, DMFE_TXPLH, ((packetLen)>> 8) & 0xff); /* Issue TX polling command */ tempdata = ior(pDrvCtrl, DMFE_TCR); iow(pDrvCtrl, DMFE_TCR, tempdata|TCR_TXREQ); /* Cleared after TX complete */ while(ior(pDrvCtrl, DMFE_TCR) & 0x1); /* free this MBLK */ netMblkClChainFree (pMblk); if(freeFlag) free(data_ptr); /* Re-enable interrupt */ iow(pDrvCtrl, DMFE_IMR, reg_value); END_TX_SEM_GIVE (&pDrvCtrl->endObj); /* iow(pDrvCtrl, DMFE_IMR, IMR_PAR | IMR_PTM | IMR_PRM); */ return OK;}static voiddmfe_shutdown(DM9000_END_DEVICE *pDrvCtrl){ /* RESET devie */ dmfe_phy_write(pDrvCtrl, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ iow(pDrvCtrl, DMFE_GPR, 0x01); /* Power-Down PHY */ iow(pDrvCtrl, DMFE_IMR, IMR_PAR); /* Disable all interrupt */ iow(pDrvCtrl, DMFE_RCR, 0x00); /* Disable RX */}/* Stop the interface. The interface is stopped when it is brought.*/static intdmfe_stop(DM9000_END_DEVICE *pDrvCtrl){ dmfe_shutdown(pDrvCtrl); return 0;}/* DM9000 interrupt handler receive the packet to upper layer, free the transmitted packet*/voiddmfe_tx_done(DM9000_END_DEVICE *pDrvCtrl){ int tx_status = ior(pDrvCtrl, DMFE_NSR); /* Got TX status *//*读网络状态寄存器*/ if (tx_status & 0xc) { } }static voiddmfe_interrupt(DM9000_END_DEVICE *pDrvCtrl){ int int_status; u8 reg_save, reg_save1; /* Save previous register address */ reg_save = DM9000_inb(pDrvCtrl->ioaddr); /* Disable all interrupts */ reg_save1 = ior(pDrvCtrl, DMFE_IMR);/*读出中断屏蔽寄存器内容*/ iow(pDrvCtrl, DMFE_IMR, IMR_PAR);/*使能SRAM读写指针*/ /* Got DM9000 interrupt status */ int_status = ior(pDrvCtrl, DMFE_ISR); /* Got ISR *//*读中断状态寄存器*/ iow(pDrvCtrl, DMFE_ISR, int_status); /* Clear ISR status *//*写中断状态寄存器*/ /* Received the coming packet */ if (int_status & ISR_PRS)/*包接收*/ {/* logMsg("rx\n\r",1,2,3,4,5,6); */ netJobAdd ((FUNCPTR) dmfe_rx, (int) pDrvCtrl, 0, 0, 0, 0); iow(pDrvCtrl, DMFE_IMR, reg_save1&(~IMR_PRM)); /*关闭包接收中断*/ goto intr_end; } /* Trnasmit Interrupt check */ if (int_status & ISR_PTS)/*包发送*/ {/* logMsg("tx\n\r",1,2,3,4,5,6); */ dmfe_tx_done(pDrvCtrl); } iow(pDrvCtrl, DMFE_IMR, reg_save1);/*恢复中断屏蔽寄存器内容*/intr_end: /* Restore previous register address */ DM9000_outb(reg_save, pDrvCtrl->ioaddr);}/* * Received a packet and pass to upper layer */static voiddmfe_rx(DM9000_END_DEVICE *pDrvCtrl){ char * pCluster ; u8 rxbyte; u16 i, RxStatus, RxLen, GoodPacket, tmplen;#ifdef DM9000_DWORD_MODE u32 tmpdata;#endif u8 reg_save1; reg_save1 = ior(pDrvCtrl, DMFE_IMR);/*读中断屏蔽寄存器*/ /* Check packet ready or not */ do { ior(pDrvCtrl, DMFE_MRCMDX); /* Dummy read */ /* Get most updated data */ rxbyte = DM9000_inb(pDrvCtrl->io_data); /* Status check: this byte must be 0 or 1 */ if (rxbyte > DM9000_PKT_RDY) { iow(pDrvCtrl, DMFE_RCR, 0x00); /* Stop Device *//*接收计数寄存器写0*/ iow(pDrvCtrl, DMFE_ISR, IMR_PAR); /* Stop INT request *//*设置io模式为8位模式*/ printf("status check failed: %d\n", rxbyte); iow(pDrvCtrl, DMFE_IMR, reg_save1| IMR_PRM); return; } if (rxbyte != DM9000_PKT_RDY) { iow(pDrvCtrl, DMFE_IMR, reg_save1| IMR_PRM);/*使能包接收中断*/ return; } /* A packet ready now & Get status/length */ GoodPacket = TRUE; DM9000_outb(DMFE_MRCMD, pDrvCtrl->ioaddr);/*读内存数据指令,地址自增*/#ifdef DM9000_BYTE_MODE RxStatus = DM9000_inb(pDrvCtrl->io_data) + (DM9000_inb(pDrvCtrl->io_data) << 8); RxLen = DM9000_inb(pDrvCtrl->io_data) + (DM9000_inb(pDrvCtrl->io_data) << 8);#elif defined DM9000_WORD_MODE RxStatus = DM9000_inw(pDrvCtrl->io_data); RxLen = DM9000_inw(pDrvCtrl->io_data);#elif defined DM9000_DWORD_MODE tmpdata = DM9000_inl(pDrvCtrl->io_data); RxStatus = tmpdata; RxLen = tmpdata >> 16;#endif /* Packet Status check */ if (RxLen < 0x40) {/*如果包长小于64,坏包*/ GoodPacket = FALSE; printf("Baaaad Packet received\n"); } if (RxLen > DM9000_PKT_MAX) { printf("RST: RX Len:%x\n", RxLen); } if (RxStatus & 0xbf00) { GoodPacket = FALSE; if (RxStatus & 0x100) { printf("fifo error\n"); } if (RxStatus & 0x200) { printf("crc error\n"); } if (RxStatus & 0x8000) { printf("length error\n"); } } /* Move data from DM9000 */ if (GoodPacket && (pCluster = netClusterGet (pDrvCtrl->endObj.pNetPool,pDrvCtrl->pClPoolId)) ) { /* Read received packet from RX SRAM */ dmfe_mx1_ins( pDrvCtrl->io_data, pCluster, RxLen); dm9000Recv(pDrvCtrl, pCluster,RxLen); } else {#ifdef DM9000_BYTE_MODE for (i = 0; i < RxLen; i++) DM9000_inb(pDrvCtrl->io_data);#elif defined DM9000_WORD_MODE tmplen = (RxLen + 1) / 2; for (i = 0; i < tmplen; i++) DM9000_inw(pDrvCtrl->io_data);#elif defined DM9000_DWORD_MODE tmplen = (RxLen + 3) / 4; for (i = 0; i < tmplen; i++) DM9000_inl(pDrvCtrl->io_data);#endif }}while (rxbyte == DM9000_PKT_RDY); /* Re-enable interrupt mask */ iow(pDrvCtrl, DMFE_IMR, reg_save1| IMR_PRM);}/* * Read a word data from SROM */static u16read_srom_word(DM9000_END_DEVICE *pDrvCtrl, int offset){ iow(pDrvCtrl, DMFE_EPAR, offset); iow(pDrvCtrl, DMFE_EPCR, EPCR_ERPRR); taskDelay(8); /* according to the datasheet 200us should be enough, but it doesn't work */ iow(pDrvCtrl, DMFE_EPCR, 0x0); return (ior(pDrvCtrl, DMFE_EPDRL) + (ior(pDrvCtrl, DMFE_EPDRH) << 8));}/* * Set DM9000 multicast address */static voiddm9000_hash_table(DM9000_END_DEVICE *pDrvCtrl){ u16 i, oft, hash_table[4]; /* MULTI_TABLE * mcptr = */ for (i = 0, oft = 0x10; i < 6; i++, oft++)/*写物理地址寄存器*/ iow(pDrvCtrl, oft, pDrvCtrl->enetAddr[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++) {/*wriet muticast address register*/ iow(pDrvCtrl, oft++, hash_table[i] & 0xff); iow(pDrvCtrl, oft++, (hash_table[i] >> 8) & 0xff); }}/* * Read a byte from I/O port */static u8ior(DM9000_END_DEVICE *pDrvCtrl, int reg){ DM9000_outb(reg, pDrvCtrl->ioaddr); return DM9000_inb(pDrvCtrl->io_data);}static u8ior1( int reg){ DM9000_outb(reg, CONFIG_DM9K_BASE); return DM9000_inb(CONFIG_DM9K_BASE+4);}/* * Write a byte to I/O port */static voidiow(DM9000_END_DEVICE *pDrvCtrl, int reg, int value){ DM9000_outb(reg, pDrvCtrl->ioaddr); DM9000_outb(value, pDrvCtrl->io_data);}void dm9000Read(int reg){ UINT8 value; value = ior(temp, reg); printf("reg 0x%x = 0x%x\n\r", reg, value); }void dm9000Read1(int reg){ UINT8 value; value = ior1(reg); printf("reg 0x%x = 0x%x\n\r", reg, value); }void dm9kReadAll(void){ int i; for(i=0;i<0x100;i++) { dm9000Read(i); }}void dm9kReadAll1(void){ int i; for(i=0;i<0x100;i++) { dm9000Read1(i); }}void dm9000Write(int reg, int value){ iow(temp, reg, value);}/* * Read a word from phyxcer */static intdmfe_phy_read(DM9000_END_DEVICE *pDrvCtrl, int phy_reg_unused, int reg){ UINT8 value; /* Fill the phyxcer register into REG_0C */ iow(pDrvCtrl, DMFE_EPAR, DM9000_PHY | reg); iow(pDrvCtrl, DMFE_EPCR, 0xc); /* Issue phyxcer read command */ value = ior(pDrvCtrl, DMFE_EPCR); while(value & 0x1) /* Wait read complete */ { taskDelay(1); value = ior(pDrvCtrl, DMFE_EPCR); } iow(pDrvCtrl, DMFE_EPCR, 0x8); /* Clear phyxcer read command */ /* The read data keeps on REG_0D & REG_0E */ return (ior(pDrvCtrl, DMFE_EPDRH) << 8) | ior(pDrvCtrl, DMFE_EPDRL);}void dm9k_phy_read(int reg){ int value; value = dmfe_phy_read(temp, 0 , reg); printf("phy addr 0x%x = 0x%x\n\r", reg, value);}/* * Write a word to phyxcer */static voiddmfe_phy_write(DM9000_END_DEVICE *pDrvCtrl, int phyaddr_unused, int reg, int value){ /* Fill the phyxcer register into REG_0C */ iow(pDrvCtrl, DMFE_EPAR, DM9000_PHY | reg); /* Fill the written data into REG_0D & REG_0E */ iow(pDrvCtrl, DMFE_EPDRL, (value & 0xff)); iow(pDrvCtrl, DMFE_EPDRH, ((value >> 8) & 0xff)); iow(pDrvCtrl, DMFE_EPCR, 0xa); /* Issue phyxcer write command */ value = ior(pDrvCtrl, DMFE_EPCR); /* Wait write complete */ while(value & 0x1) { taskDelay(1); value = ior(pDrvCtrl, DMFE_EPCR); } iow(pDrvCtrl, DMFE_EPCR, 0x8); /* Clear phyxcer write command */}static voiddmfe_mx1_ins(u_long ioaddr, u_char * buf, int len){ u16 tmplen, i; u32 tempdata; tmplen = (len + 3) / 4; for (i = 0; i < tmplen; i++) { tempdata = *((volatile u32*)((u32)ioaddr)); memcpy(buf+2+i*sizeof(tempdata), &tempdata, sizeof(tempdata)); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -