📄 enetlib.c
字号:
phy18 & PHY_INT_JAB); } if ((phy18 & PHY_INT_SPDDET) != (dev.lastPhy18 & PHY_INT_SPDDET)) { s1printf("%s: PHY Speed Detect=%x\n", dev.name, phy18 & PHY_INT_SPDDET); } if ((phy18 & PHY_INT_DPLXDET) != (dev.lastPhy18 & PHY_INT_DPLXDET)) { s1printf("%s: PHY Duplex Detect=%x\n", dev.name, phy18 & PHY_INT_DPLXDET); }#endif // Update the last phy 18 variable dev.lastPhy18 = phy18; } // end while}/************************************************************************* . smc_tx . . Purpose: Handle a transmit error message. This will only be called . when an error, because of the AUTO_RELEASE mode. . . Algorithm: . Save pointer and packet no . Get the packet no from the top of the queue . check if it's valid ( if not, is this an error??? ) . read the status word . record the error . ( resend? Not really, since we don't want old packets around ) . Restore saved values ************************************************************************/static void smc_tx(){ unsigned char saved_packet; unsigned char packet_no; unsigned int tx_status; s1printf("%s:smc_tx\n", dev.name); /* assume bank 2 */ saved_packet = in16( ENET_IO_ADDR + PN_REG ) & 0x000f; packet_no = in16( ENET_IO_ADDR + RXFIFO_REG ); packet_no &= 0x7F; /* If the TX FIFO is empty then nothing to do */ if ( packet_no & TXFIFO_TEMPTY ) return; /* select this as the packet to read from */ out16( ENET_IO_ADDR + PN_REG, packet_no & 0x000f); /* read the first word (status word) from this packet */ out16( ENET_IO_ADDR + PTR_REG, PTR_AUTOINC | PTR_READ ); tx_status = in16( ENET_IO_ADDR + DATA_REG ); s1printf("%s: TX DONE STATUS: %4x \n", dev.name, tx_status); dev.stats.tx_errors++; if ( tx_status & TS_LOSTCAR ) dev.stats.tx_carrier_errors++; if ( tx_status & TS_LATCOL ) { s1printf("%s: Late collision occurred on last xmit.\n", dev.name); dev.stats.tx_window_errors++; dev.ctl_forcol = 0; // Reset forced collsion } if ( tx_status & TS_SUCCESS ) { s1printf("%s: Successful packet caused interrupt \n", dev.name); } /* re-enable transmit */ out16( ENET_IO_ADDR + BANK_SELECT, 0x00 ); out16(ENET_IO_ADDR + TCR_REG, in16( ENET_IO_ADDR + TCR_REG ) | TCR_ENABLE ); /* kill the packet */ out16( ENET_IO_ADDR + BANK_SELECT, 0x02 ); out16( ENET_IO_ADDR + MMU_CMD_REG, MC_FREEPKT ); /* one less packet waiting for me */ dev.packets_waiting--; /* Don't change Packet Number Reg until busy bit is cleared */ /* Per LAN91C111 Spec, Page 50 */ while ( in16( ENET_IO_ADDR + MMU_CMD_REG ) & MC_BUSY ); out16( ENET_IO_ADDR + PN_REG, saved_packet & 0x000f); return;}/*-------------------------------------------------------------------- . . This is the main routine of the driver, to handle the device when . it needs some attention. . . So: . first, save state of the chipset . branch off into routines to handle each case, and acknowledge . each to the interrupt register . and finally restore state. . ---------------------------------------------------------------------*/int enetInt(){ unsigned char status; unsigned int card_stats; unsigned char mask; int timeout; unsigned int saved_bank; unsigned int saved_pointer; unsigned int data_len = 0; struct ip *ip_ptr; struct enet_frame *ef_ptr; struct arp_frame *af_p;// s1printf("%s: interrupt started \n", dev.name); if ( dev.interrupt ) { s1printf("%s: interrupt inside interrupt.\n", dev.name); return(1); } dev.interrupt = 1; saved_bank = in16( ENET_IO_ADDR + BANK_SELECT ); out16( ENET_IO_ADDR + BANK_SELECT, 0x02 ); saved_pointer = in16( ENET_IO_ADDR + PTR_REG ); /* read the interrupt status register */ mask = (in16( ENET_IO_ADDR + INT_REG ) >> 8); /* disable all interrupts */ out16( ENET_IO_ADDR + INT_REG, 0x00 ); /* set a timeout value, so I don't stay here forever */ timeout = 8; ppcSync();// YYD, rm ppcMtuicsr(0x80000000>>ENET_INT); /* clear at uicc too */// s1printf("%s: MASK IS %x \n", dev.name, mask); do { /* read the status flag, and mask it */ status = in16( ENET_IO_ADDR + INT_REG ) & mask; if (!status ) break;// s1printf("%s: Handling interrupt status %04x \n",// dev.name, status); if (status & IM_RCV_INT) { /* Got a packet(s). */// s1printf("%s: Receive Interrupt\n", dev.name); data_len = enet_rcv_packet(inframe[flih_bufnum].data, ENET_MAX_MTU); // inframe[flih_bufnum].inframe_len = data_len; // break; } else if (status & IM_TX_INT ) {// s1printf("%s: TX ERROR handled\n",// dev.name); smc_tx(); // Acknowledge the interrupt out16( ENET_IO_ADDR + INT_REG, IM_TX_INT ); } else if (status & IM_TX_EMPTY_INT ) { /* update stats */ out16( ENET_IO_ADDR + BANK_SELECT, 0x00 ); card_stats = in16( ENET_IO_ADDR + COUNTER_REG ); /* single collisions */ dev.stats.collisions += card_stats & 0xF; card_stats >>= 4; /* multiple collisions */ dev.stats.collisions += card_stats & 0xF; out16( ENET_IO_ADDR + BANK_SELECT, 0x02 );// s1printf("%s: TX_BUFFER_EMPTY handled\n",// dev.name); // Acknowledge the interrupt out16(ENET_IO_ADDR + INT_REG, IM_TX_EMPTY_INT ); mask &= ~IM_TX_EMPTY_INT; dev.stats.tx_packets += dev.packets_waiting; dev.packets_waiting = 0; } else if (status & IM_ALLOC_INT ) {// s1printf("%s: Allocation interrupt \n",// dev.name); /* clear this interrupt so it doesn't happen again */ mask &= ~IM_ALLOC_INT;#if 0 // YYD enet_send_macframe(outframe, outframe_len); /* enable xmit interrupts based on this */ mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); /* and let the card send more packets to me */ /* mark_bh( NET_BH ); */ s1printf("%s: Handoff done successfully.\n", dev.name);#endif } else if (status & IM_RX_OVRN_INT ) { dev.stats.rx_errors++; dev.stats.rx_fifo_errors++; // Acknowledge the interrupt out16( ENET_IO_ADDR + INT_REG, IM_RX_OVRN_INT ); } else if (status & IM_EPH_INT ) {// s1printf("%s: UNSUPPORTED: EPH INTERRUPT \n",// dev.name); } else if (status & IM_MDINT ) { phy_interrupt(); // Acknowledge the interrupt out16(ENET_IO_ADDR + INT_REG, IM_MDINT); } else if (status & IM_ERCV_INT ) {// s1printf("%s: UNSUPPORTED: ERCV INTERRUPT \n",// dev.name); // Acknowledge the interrupt out16( ENET_IO_ADDR + INT_REG, IM_ERCV_INT ); } } while ( timeout -- ); if(data_len > 0) { ef_ptr=(struct enet_frame *)&inframe[flih_bufnum].data[0];// s1printf("Handle packet length = %d, type = %4x\n", data_len, ef_ptr->type); 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; } } /* restore register states */ out16( ENET_IO_ADDR + BANK_SELECT, 0x02 ); out16( ENET_IO_ADDR + INT_REG, mask << 8);// s1printf("%s: MASK is now %x \n", dev.name, mask); out16( ENET_IO_ADDR + PTR_REG, saved_pointer); out16( ENET_IO_ADDR + BANK_SELECT, saved_bank ); dev.interrupt = 0; /* clear interrupt bit in universal interrupt controller */ ppcMtuicsr(0x80000000>>ENET_INT);// s1printf("%s: Interrupt done\n", dev.name); return(0);}/********************************************************************************* SetSpeed - sets the speed of the device** sets the speed of the device.** RETURNS: N/A*/static void SetSpeed ( int speed, /* speed to set */ int autoNeg /* auto negotiation flag */ ) { unsigned int rtn; unsigned int PHYAddr; PHYAddr = dev.phyaddr; /* Read PHY_CONTROL Register */ rtn = phy_readreg ( PHYAddr, PHY_CNTL_REG ); if( speed ) { dev.ctl_rspeed = 1;#ifdef DEBUG_MSG_SETSPEED s1printf ("Smsc91c110 SPEED: 100Mbs\n");#endif rtn |= PHY_CNTL_SPEED ; /* Write value to PHY_CONTROL */ phy_writereg ( PHYAddr, PHY_CNTL_REG, rtn); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -