📄 enetlib.c
字号:
} /*-----------------------------------------------------------------------+ | Frame data starts at byte 16 (2 for aligment 12 for addresses 2 for | frame type). +-----------------------------------------------------------------------*/ if (rc>0) { (void)memcpy(p, &inframe[read_bufnum].data[16], rc); inframe[read_bufnum].inframe_len=0; read_bufnum=(read_bufnum+ 1)% NUMRECV_BUFF; (void)ppcMtmsr(msr); return(rc); } (void)ppcMtmsr(msr); (void)ppcMftb(&tb_end); if (tbmilisec_dif(&tb_end, &tb_start)>9000) { return(-1); } }}/*-----------------------------------------------------------------------------+| Write_port.+-----------------------------------------------------------------------------*/static void write_port(unsigned char value){ while(1) { if (in8(NIC_DMA)&ACC_MASK) { (void)out8(NIC_PORT, value); break; } } return;}/*-----------------------------------------------------------------------------+| Read_port.+-----------------------------------------------------------------------------*/static unsigned char read_port(){ unsigned char cr; while(1) { if (in8(NIC_DMA)&ACC_MASK) { cr=in8(NIC_PORT); break; } } return(cr);}/*-----------------------------------------------------------------------------+| Enet_send_macframe.+-----------------------------------------------------------------------------*/int enet_send_macframe(char *frame, int frame_len){ struct enet_frame *ef_ptr=(struct enet_frame *)frame; unsigned long i; unsigned char enet_reg; tb_t tb_start; tb_t tb_end; /*--------------------------------------------------------------------------+ | Copy in our address into the frame. +--------------------------------------------------------------------------*/ (void)memcpy(ef_ptr->source_addr, hwd_addr, ENET_ADDR_LENGTH); /*--------------------------------------------------------------------------+ | If frame is too long or too short, modify length. +--------------------------------------------------------------------------*/ if (frame_len>ENET_MAX_MTU) { frame_len=ENET_MAX_MTU; } else if (frame_len<ENET_MINPACKET) { frame_len=ENET_MINPACKET; } /*--------------------------------------------------------------------------+ | Data sheet page 1-107 specifies this arcane procedute to do a remote | write (first you have to do remote read). +--------------------------------------------------------------------------*/ (void)write_nic(RBCR0, 0x10, PAGE0); (void)write_nic(RBCR1, 0x00, PAGE0); (void)write_nic(RSAR0, 0x00, PAGE0); (void)write_nic(RSAR1, 0x00, PAGE0); (void)write_cr(RD0); /*--------------------------------------------------------------------------+ | Set up DMA to transfer packet to the controller chip. Do not inline | write port, compiler will optimize it in such a way that machine check | will result the first time this is run. +--------------------------------------------------------------------------*/ (void)write_nic(RBCR0, frame_len&0x000000FF, PAGE0); (void)write_nic(RBCR1, (frame_len&0x0000FF00)>>8, PAGE0); (void)write_nic(RSAR0, 0x00, PAGE0); (void)write_nic(RSAR1, 0x00, PAGE0); (void)write_cr(RD1); for (i=0; i<frame_len; i++) { (void)write_port(frame[i]); } /*--------------------------------------------------------------------------+ | Issue transmit command. +--------------------------------------------------------------------------*/ (void)write_nic(TPSR, 0x00, PAGE0); (void)write_nic(TBCR0, frame_len&0x000000FF, PAGE0); (void)write_nic(TBCR1, (frame_len&0x0000FF00)>>8, PAGE0); (void)write_nic(ISR, PTX|TXE, PAGE0); (void)write_cr(TXP); (void)ppcMftb(&tb_start); while(1) { enet_reg=read_nic(ISR, PAGE0); if ((enet_reg&PTX)!=0x0) { (void)write_nic(ISR, PTX, PAGE0); return(0); } else if ((enet_reg&TXE)!=0x0) { (void)write_nic(ISR, TXE, PAGE0); return(-1); } (void)ppcMftb(&tb_end); if (tbmilisec_dif(&tb_end, &tb_start)>3000) { return(-1); } }}/*-----------------------------------------------------------------------------+| Enet_rcv_packet.+-----------------------------------------------------------------------------*/static int enet_rcv_packet(char *inframe, int max){ unsigned char recv_status; unsigned char next_packet; unsigned char bp; unsigned long count; unsigned long dma_count; unsigned long addr; unsigned long residual; unsigned long j; /*--------------------------------------------------------------------------+ | Receive first 4 bytes giving us the receive packet statistics. +--------------------------------------------------------------------------*/ (void)write_nic(RBCR0, 0x04, PAGE0); (void)write_nic(RBCR1, 0x00, PAGE0); (void)write_nic(RSAR0, 0x00, PAGE0); (void)write_nic(RSAR1, (next_packet_ptr* 256)>>8, PAGE0); (void)write_cr(RD0); recv_status=read_port(); next_packet=read_port(); count=read_port(); count|=read_port()<<8; /*--------------------------------------------------------------------------+ | We already got 4 bytes. Set up addr where the next packet resides. Check | count if too big. +--------------------------------------------------------------------------*/ count-=4; if (count>max) { (void)s1printf("ENET: CE.\n"); (void)enetInit(ip_addr, NULL, NULL); return(0); } addr=(next_packet_ptr* 256)+ 4; if ((recv_status&PRXS)==0x0) { /*-----------------------------------------------------------------------+ | We should never get bad packets. +-----------------------------------------------------------------------*/ (void)s1printf("ENET: SE.\n"); (void)enetInit(ip_addr, NULL, NULL); return(0); } /*--------------------------------------------------------------------------+ | Pull packet out of memory. If we do not hit the end boundry handle it | in one transfer. Packet is received starting at byte 3 so that the ip | packet will be word aligned and we do not have to do memmove later. +--------------------------------------------------------------------------*/ if ((addr+ count)<(PSTOP_VALUE* PACKET_SIZE)) { /*-----------------------------------------------------------------------+ | Set up DMA address and count. +-----------------------------------------------------------------------*/ (void)write_nic(RBCR0, count&0x000000FF, PAGE0); (void)write_nic(RBCR1, (count&0x0000FF00)>>8, PAGE0); (void)write_nic(RSAR0, addr&0x000000FF, PAGE0); (void)write_nic(RSAR1, (addr&0x0000FF00)>>8, PAGE0); (void)write_cr(RD0); for (j=2; j<count+ 2; j++) { inframe[j]=read_port(); } } else { /*-----------------------------------------------------------------------+ | Pull out all the bytes to the end boundry then do another transfer to | get the rest of the packet. +-----------------------------------------------------------------------*/ residual=(addr+ count)- (PSTOP_VALUE* PACKET_SIZE); dma_count=count- residual; /*-----------------------------------------------------------------------+ | Set up DMA address, and count. +-----------------------------------------------------------------------*/ (void)write_nic(RBCR0, dma_count&0x000000FF, PAGE0); (void)write_nic(RBCR1, (dma_count&0x0000FF00)>>8, PAGE0); (void)write_nic(RSAR0, addr&0x000000FF, PAGE0); (void)write_nic(RSAR1, (addr&0x0000FF00)>>8, PAGE0); (void)write_cr(RD0); inframe[210+2+14+20+8]=0x00; for (j=2; j<(dma_count+ 2); j++) { inframe[j]=read_port(); } /*-----------------------------------------------------------------------+ | Set up DMA address and count (start transfer at start page). +-----------------------------------------------------------------------*/ (void)write_nic(RBCR0, residual&0x000000FF, PAGE0); (void)write_nic(RBCR1, (residual&0x0000FF00)>>8, PAGE0); (void)write_nic(RSAR0, 0x00, PAGE0); (void)write_nic(RSAR1, (PSTART_VALUE* 256)>>8, PAGE0); (void)write_cr(RD0); for (j=(dma_count+ 2); j<(dma_count+ residual+ 2); j++) { inframe[j]=read_port(); } } /*--------------------------------------------------------------------------+ | Advance boundry pointer using algorighm on page 1-56 AT/LANTIC data sheet. | If "next_packet" is outside bouns signal error. +--------------------------------------------------------------------------*/ if ((next_packet>PSTOP_VALUE) || (next_packet<PSTART_VALUE)) { (void)s1printf("ENET: NE.\n"); (void)enetInit(ip_addr, NULL, NULL); return(0); } next_packet_ptr=next_packet; bp=next_packet_ptr- 1; if (bp<PSTART_VALUE) { bp=PSTOP_VALUE- 1; } (void)write_nic(BNRY, bp, PAGE0); /*--------------------------------------------------------------------------+ | Return number of bytes read. +--------------------------------------------------------------------------*/ return(count);}/*-----------------------------------------------------------------------------+| Enet_register.+-----------------------------------------------------------------------------*/int enet_register(void (*recv_function)(char *frame, unsigned long frame_len), unsigned long ip_addr){ osopen_enet.recv_function=recv_function; osopen_enet.ip_addr=ip_addr; return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -