📄 enetlib.c
字号:
| pointer to page start. +--------------------------------------------------------------------------*/ (void)write_nic(PAR0, hwd_addr[0], PAGE1); (void)write_nic(PAR1, hwd_addr[1], PAGE1); (void)write_nic(PAR2, hwd_addr[2], PAGE1); (void)write_nic(PAR3, hwd_addr[3], PAGE1); (void)write_nic(PAR4, hwd_addr[4], PAGE1); (void)write_nic(PAR5, hwd_addr[5], PAGE1); (void)write_nic(MAR0, 0x00, PAGE1); (void)write_nic(MAR1, 0x00, PAGE1); (void)write_nic(MAR2, 0x00, PAGE1); (void)write_nic(MAR3, 0x00, PAGE1); (void)write_nic(MAR4, 0x00, PAGE1); (void)write_nic(MAR5, 0x00, PAGE1); (void)write_nic(CURR, PSTART_VALUE+ 1, PAGE1); /*--------------------------------------------------------------------------+ | Start controller and take it out of loopback. +--------------------------------------------------------------------------*/ (void)write_cr(STA|RD2); (void)write_nic(TCR, LBM0, PAGE0); /*--------------------------------------------------------------------------+ | Enable and configure the pocessor interrupts in level 1. | Copy the IP address. +--------------------------------------------------------------------------*/ temp = ppcMfuiccr(); ppcMtuiccr(temp & (~(0x80000000>>ENET_INT))); temp = ppcMfuictr(); ppcMtuictr(temp & (~(0x80000000>>ENET_INT))); temp = ppcMfuicpr(); ppcMtuicpr(temp & (0x7fffffff>>ENET_INT)); ppcMtuicsr(0x80000000>>ENET_INT); temp = ppcMfuicer(); ppcMtuicer(temp | (0x80000000>>ENET_INT)); ip_addr=srcaddr; (void)ppcMtmsr(msr); return(0);}/*-----------------------------------------------------------------------------+| EnetInt.+-----------------------------------------------------------------------------*/int enetInt(){ struct ip *ip_ptr; struct enet_frame *ef_ptr; struct arp_frame *af_p; unsigned long data_len; unsigned char isr; while (1) { isr=read_nic(ISR, PAGE0); if ((isr&(PRX|OVW))==0x0) { break; } if ((isr&PRX)!=0x0) {#if 0 // YYD, check for CURR mistake isr=read_nic(CURR, PAGE1); if(isr < PSTART_VALUE) // how can this be wrong { s1printf("CURR wrong %02x\n", isr); (void)write_nic(ISR, PRX, PAGE0); break; }#endif if (inframe[flih_bufnum].inframe_len!=0) { (void)s1printf("ENET: hold frame collision, inbound frame.\n"); inframe[flih_bufnum].inframe_len=0; } data_len=enet_rcv_packet(inframe[flih_bufnum].data, ENET_MAX_MTU); if (data_len==0x0) { continue; } /*--------------------------------------------------------------------+ | Clear interrupt only if there is no more packets in ring buffer. +--------------------------------------------------------------------*/ isr=read_nic(CURR, PAGE1); if (next_packet_ptr==isr) { (void)write_nic(ISR, PRX, PAGE0); ppcSync(); ppcMtuicsr(0x80000000>>ENET_INT); /* clear at uicc too */ } ef_ptr=(struct enet_frame *)&inframe[flih_bufnum].data[2]; switch(ef_ptr->type) { /*-----------------------------------------------------------------+ | Forward packet to OS Open if destined for that IP address. +-----------------------------------------------------------------*/ case ENET_ARPTYPE: af_p=(struct arp_frame *)ef_ptr->enet_data; if ((osopen_enet.ip_addr!=0x0) && (memcmp(af_p->ar_tpa, &osopen_enet.ip_addr, af_p->ar_pln)==0)) { _callxlc((int)(*osopen_enet.recv_function),(char *)ef_ptr, data_len); } else { if (af_p->ar_op==ARP_REQUEST) { /*--------------------------------------------------------+ | If ARP_REQUEST is looking for us then send response. +--------------------------------------------------------*/ if (memcmp(af_p->ar_tpa, ip_addr, af_p->ar_pln)==0) { (void)enetarp_input(af_p); /*-----------------------------------------------------+ | Formulate reply, using same buffer. +-----------------------------------------------------*/ (void)memcpy(af_p->ar_tha, af_p->ar_sha, af_p->ar_hln); (void)memcpy(af_p->ar_tpa, af_p->ar_spa, af_p->ar_pln); (void)memcpy(af_p->ar_sha, hwd_addr, af_p->ar_hln); (void)memcpy(af_p->ar_spa, ip_addr, af_p->ar_pln); af_p->ar_op=ARP_REPLY; (void)memcpy(ef_ptr->dest_addr, af_p->ar_tha, ENET_ADDR_LENGTH); if (enet_send_macframe((char *)ef_ptr, data_len)) { (void)s1printf("ENET: send frame error.\n"); } } } else if (af_p->ar_op==ARP_REPLY) { (void)enetarp_input(af_p); /*--------------------------------------------------------+ | Real arp processing here, try retransmission if a packet | is in the holding pen. +--------------------------------------------------------*/ ef_ptr=(struct enet_frame *)outframe; ip_ptr=(struct ip *)ef_ptr->enet_data; if ((outframe_len!=0) && (memcmp(&ip_ptr->ip_dst, af_p->ar_spa, sizeof(ip_ptr->ip_dst))==0)) { (void)memcpy(ef_ptr->dest_addr, af_p->ar_sha, ENET_ADDR_LENGTH); if (enet_send_macframe((char *)outframe, outframe_len)) { (void)s1printf("ENET: send frame error.\n"); } else { outframe_len=0; } } } } break; /*-----------------------------------------------------------------+ | Some kind of IP packet. +-----------------------------------------------------------------*/ case ENET_IPTYPE: ip_ptr=(struct ip *)ef_ptr->enet_data; if ((osopen_enet.ip_addr!=0x0) && (memcmp(&ip_ptr->ip_dst.s_addr, &osopen_enet.ip_addr, sizeof(ip_ptr->ip_dst.s_addr))==0)) { _callxlc((int)(*osopen_enet.recv_function), (char *)ef_ptr, data_len); } else if (memcmp(&ip_ptr->ip_dst.s_addr, ip_addr, sizeof(ip_ptr->ip_dst.s_addr))==0 || ( (*ip_addr == 0) && (memcmp(ef_ptr->dest_addr, hwd_addr, // YYD ENET_ADDR_LENGTH)==0) )) { // enable to get packet when ip is not set if ((route_packet((char *)ip_ptr, data_len, (int *)&ef_ptr->dest_addr)==0) && (memcmp(ef_ptr->dest_addr,brd_addr, ENET_ADDR_LENGTH)!=0)) { inframe[flih_bufnum].inframe_len=data_len; flih_bufnum=(flih_bufnum+ 1)% NUMRECV_BUFF; } } break; /*-----------------------------------------------------------------+ | Not IP or ARP discard it. +-----------------------------------------------------------------*/ default: break; } } else if ((isr&OVW)!=0x0) { /*--------------------------------------------------------------------+ | All the packets are removed from the buffer, so reinitialize | controller. +--------------------------------------------------------------------*/ (void)s1printf("ENET: Receive Buffer Overflow.\n"); (void)enetInit(ip_addr, NULL, NULL); } } /* clear interrupt bit in universal interrupt controller */ ppcMtuicsr(0x80000000>>ENET_INT); return(0);}/*-----------------------------------------------------------------------------+| EnetSend.+-----------------------------------------------------------------------------*/int enetSend(char *p, int len, int *parmp){ struct enet_frame *e_frame=(struct enet_frame *)outframe; struct arp_frame *a_frame; unsigned char *datap=e_frame->enet_data; unsigned long msr; struct ip *ip_ptr=(struct ip *)p; unsigned long target_address=ip_ptr->ip_dst.s_addr; unsigned long fake_length; unsigned char outbarp[ENET_MINPACKET]; /*--------------------------------------------------------------------------+ | Disable interrupts. +--------------------------------------------------------------------------*/ msr=ppcAndMsr(~ppcMsrEE); if (outframe_len!=0) { (void)s1printf("ENET: hold frame collision, outbound frame.\n"); outframe_len=0; } e_frame->type=ENET_IPTYPE; /*--------------------------------------------------------------------------+ | Destination is a broadcast address. +--------------------------------------------------------------------------*/ if (target_address==0xFFFFFFFF) { (void)memset(e_frame->dest_addr, 0xFF, ENET_ADDR_LENGTH); } else { if (enetarp_resolve(target_address, (char *)e_frame->dest_addr)==0) { /*--------------------------------------------------------------------+ | Build arp packet and send it instead of data packet. +--------------------------------------------------------------------*/ e_frame=(struct enet_frame *)outbarp; (void)memset(e_frame->dest_addr, 0xFF, ENET_ADDR_LENGTH); e_frame->type=ENET_ARPTYPE; a_frame=(struct arp_frame *)e_frame->enet_data; (void)memset(a_frame, 0x00, sizeof(struct arp_frame)); a_frame->ar_hrd=1; a_frame->ar_pro=0x800; a_frame->ar_hln=6; a_frame->ar_pln=4; (void)memcpy(a_frame->ar_tpa, &target_address, a_frame->ar_pln); (void)memcpy(a_frame->ar_sha, hwd_addr, a_frame->ar_hln); (void)memcpy(a_frame->ar_spa, ip_addr, a_frame->ar_pln); a_frame->ar_op=ARP_REQUEST; /*--------------------------------------------------------------------+ | Stack current frame in holding pen (-2 for XLC sizeof). +--------------------------------------------------------------------*/ outframe_len=len+ sizeof(struct enet_frame)- 2; (void)memcpy(datap, p, len); if (enet_send_macframe((char *)outbarp, sizeof(outbarp))) { (void)s1printf("ENET: send frame error.\n"); } (void)ppcMtmsr(msr); return(-1); } } (void)memcpy(datap, p, len); fake_length=len+ sizeof(struct enet_frame)- 2; if (fake_length<ENET_MINPACKET) { fake_length=ENET_MINPACKET; } if (enet_send_macframe((char *)outframe, fake_length)) { (void)s1printf("ENET: send frame error.\n"); (void)ppcMtmsr(msr); return(-1); } (void)ppcMtmsr(msr); return(len+ sizeof(struct enet_frame)- 2);}/*-----------------------------------------------------------------------------+| EnetRecv.+-----------------------------------------------------------------------------*/int enetRecv(char *p, int len, int *parmp){ int rc; tb_t tb_start; tb_t tb_end; unsigned long msr; (void)ppcMftb(&tb_start); while (1) { msr=ppcAndMsr(~ppcMsrEE); /*-----------------------------------------------------------------------+ | Frame length is reduced by 14 (6 for dest addr, 6 for source addr, and | 2 for frame type fields) since we only want to copy the data portion | of the packet. +-----------------------------------------------------------------------*/ if (inframe[read_bufnum].inframe_len<len) { rc=inframe[read_bufnum].inframe_len - 14; } else { rc=len - 14; } /*-----------------------------------------------------------------------+ | 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -