⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 enetlib.c

📁 Ibmstb02500 miniboot 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                        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 + -