int dm9000_send(unsigned char *datas, int len) { int i; unsigned short *ds = (unsigned short *)datas; dm9000_reg_write(DM9000_ISR, 1 << 1); //把数据包写到TX FIFO SRAM writeb(DM9000_MWCMD, DM9000_ADDR_PORT); for(i = 0; i < len; i += 2) writew(*ds++, DM9000_DATA_PORT); //设定发送数据包的长度 dm9000_reg_write(DM9000_TXPLL, len & 0xff); dm9000_reg_write(DM9000_TXPLH, (len >> 8) & 0xff); //启动发送功能 dm9000_reg_write(DM9000_TCR, 0x1); //等待数据包发送完成 while(!(dm9000_reg_read(DM9000_ISR) & (1 << 1))); while(!(dm9000_reg_read(DM9000_NSR) & 0xc)); return len; }
/* interrupt service routine */ void rt_dm9000_isr() { rt_uint16_t isr_status; rt_uint16_t save_reg; save_reg = DM9000_REG_ADDR; /* Disable all interrupts */ dm9000_reg_write(DM9000_REG_IMR, IMR_PAR); /* Got DM9000 interrupt status */ isr_status = dm9000_reg_read(DM9000_REG_ISR); /* Got ISR */ dm9000_reg_write(DM9000_REG_ISR, isr_status); /* Clear ISR status */ DM9000_TRACE("dm9000 isr: int status %04x\n", isr_status); /* receive overflow */ if (isr_status & ISR_ROS) { rt_kprintf("overflow\n"); } if (isr_status & ISR_ROOS) { rt_kprintf("overflow counter overflow\n"); } /* Received the coming packet */ if (isr_status & ISR_PRS) { /* disable receive interrupt */ dm9000_device.imr_all = IMR_PAR | IMR_PTI; /* a frame has been received */ eth_device_ready(&(dm9000_device.parent)); } /* Transmit Interrupt check */ if (isr_status & ISR_PTS) { /* transmit done */ int tx_status = dm9000_reg_read(DM9000_REG_NSR); /* Got TX status */ if (tx_status & (NSR_TX2END | NSR_TX1END)) { dm9000_device.packet_cnt --; if (dm9000_device.packet_cnt > 0) { DM9000_TRACE("dm9000 isr: tx second packet\n"); /* transmit packet II */ /* Set TX length to DM9000 */ dm9000_reg_write(DM9000_REG_TXPLL, dm9000_device.queue_packet_len & 0xff); dm9000_reg_write(DM9000_REG_TXPLH, (dm9000_device.queue_packet_len >> 8) & 0xff); /* Issue TX polling command */ dm9000_reg_write(DM9000_REG_TCR, TCR_TXREQ); /* Cleared after TX complete */ }
/* Read a word from phyxcer */ rt_inline rt_uint16_t dm9000_phy_read(rt_uint16_t reg) { rt_uint16_t val; /* Fill the phyxcer register into REG_0C */ dm9000_reg_write(DM9000_REG_EPAR, DM9000_PHY | reg); dm9000_reg_write(DM9000_REG_EPCR, 0xc); /* Issue phyxcer read command */ delay_ms(100); /* Wait read complete */ dm9000_reg_write(DM9000_REG_EPCR, 0x0); /* Clear phyxcer read command */ val = (dm9000_reg_read(DM9000_REG_EPDRH) << 8) | dm9000_reg_read(DM9000_REG_EPDRL); return val; }
int dm9000_rx(unsigned char *datas) { unsigned char ready; int len, status; int i; unsigned short *ds = (unsigned short *)datas; ready = dm9000_reg_read(DM9000_MRCMDX); if(ready > 0x01) { dm9000_init(); return 0; } if(ready != 0x01) return 0; writeb(DM9000_MRCMD, DM9000_ADDR_PORT); status = readw(DM9000_DATA_PORT); len = readw(DM9000_DATA_PORT); for(i = 0; i < len; i += 2) *ds++ = readw(DM9000_DATA_PORT); return len; }
void dm9000_init() { unsigned short vid; int i; vid = (dm9000_reg_read(DM9000_VIDH) << 8) | dm9000_reg_read(DM9000_VIDL); if(0x0a46 == vid) printf("dm9000 device found ... \r\n"); else { printf("dm9000 device not found ... \r\n"); return; } //激活内部PHY dm9000_reg_write(DM9000_GPCR, 0x01); dm9000_reg_write(DM9000_GPR, 0x0); //reset dm9000 dm9000_reg_write(DM9000_NCR, 0x3); delayms(1); dm9000_reg_write(DM9000_NCR, 0x0); dm9000_reg_write(DM9000_NCR, 0x3); delayms(1); dm9000_reg_write(DM9000_NCR, 0x0); //clear TX status dm9000_reg_write(DM9000_NSR, 0x2c); //设置mac地址 for(i = 0; i < 6; i++) dm9000_reg_write(DM9000_PAR + i, mac_addr[i]); dm9000_reg_write(DM9000_IMR, 0x80); /* 屏蔽所有中断,采用查询方式 */ dm9000_reg_write(DM9000_RCR, 0x31); /* 使能接收数据包功能 */ }
/* Write a word to phyxcer */ rt_inline void dm9000_phy_write(rt_uint16_t phy_reg, rt_uint16_t value) { /* Fill the phyxcer register into REG_0C */ dm9000_reg_write(DM9000_REG_EPAR, DM9000_PHY | phy_reg); /* Fill the written data into REG_0D & REG_0E */ dm9000_reg_write(DM9000_REG_EPDRL, (value & 0xff)); dm9000_reg_write(DM9000_REG_EPDRH, ((value >> 8) & 0xff)); dm9000_reg_write(DM9000_REG_EPCR, 0xa); /* Issue phyxcer write command */ delay_ms(500); /* Wait write complete */ //dm9000_reg_write(DM9000_REG_EPCR, 0x0); /* Clear phyxcer write command */ while (dm9000_reg_read(DM9000_REG_EPCR) & 0x01); /* 查寻是否执行结束 */ dm9000_reg_write(DM9000_REG_EPCR, 0x08); /* 清除写入命令 */ }