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

📄 enetlib.c

📁 Ibmstb02500 miniboot 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
      rtn = ( in16(ENET_IO_ADDR + MII_REG) & MII_MDI ) >> 1;      nsdelay(200);      out16(ENET_IO_ADDR + MII_REG, MII_MGMTval);      nsdelay(200);      wData |= ( rtn << i );    }    out16(ENET_IO_ADDR + MII_REG, MII_MGMTval);    out16(ENET_IO_ADDR + MII_REG, MII_MGMTval |                            MII_MCLK |                            MII_MDOE |                            MII_MDO );    nsdelay(200);    out16(ENET_IO_ADDR + MII_REG, MII_MGMTval);    nsdelay(200);    nsdelay(1000*1000);     // delay 1ms#ifdef DEBUG_MSG_PHYREAD   s1printf("phy_readreg:  phyaddr=%x phyreg=%x phydata=%x\n",                  PHYAddr, RegAdd, wData);#endif    return (wData);}// YYDstatic int enet_alloc_page(int length){    unsigned int numPages, mask;    int timeout;    //    s1printf("Alloc page\n");    // calcualte num pages (256) bytes required     length = ENET_MINPACKET < length ? length : ENET_MINPACKET;    numPages =  ((length & 0xfffffffe) + 6);    numPages >>= 8; // Divide by 256, the actual page is numPages+1        if(numPages > ENET_MAX_MTU/256)    {        s1printf("SMC91111 Error: alloc_page: Packet size %d too big!\n", length);        return -1;    }    /* now, try to allocate the memory */    out16( ENET_IO_ADDR + BANK_SELECT, 0x02 );    out16( ENET_IO_ADDR + MMU_CMD_REG,  MC_ALLOC | numPages );        // enable the ALLOC int    mask = in16( ENET_IO_ADDR + INT_REG)&0xff00;        timeout = ALLOC_TIMEOUT;    while(!(in16( ENET_IO_ADDR + INT_REG) & IM_ALLOC_INT) && timeout > 0)    {        timeout--;        nsdelay(1000*1000);    }            if(in16( ENET_IO_ADDR + INT_REG) & IM_ALLOC_INT)    {        // ack the int signal        out16( ENET_IO_ADDR + INT_REG, mask | IM_ALLOC_INT);    }    else    {        s1printf("SMC91111 Error: alloc_page: Failed to alloc page!\n", length);        return -1;    }    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;#ifdef DEBUG_MSG_ENETSEND   s1printf("%s: ENETSEND: Entered....\n", dev.name);#endif   /*--------------------------------------------------------------------------+   | Disable interrupts.   +--------------------------------------------------------------------------*/   msr=ppcAndMsr(~ppcMsrEE);   if (outframe_len!=0) {      (void)s1printf("%s: ENETSEND: hold frame collision, outbound frame.\n",dev.name);      outframe_len=0;   }   e_frame->type=ENET_IPTYPE;    out16( ENET_IO_ADDR + BANK_SELECT, 0x02 );    if(!(in16( ENET_IO_ADDR + INT_REG) & IM_ALLOC_INT))    {        if(enet_alloc_page(len))        {            return -1;        }    }   /*--------------------------------------------------------------------------+   | 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) {         unsigned char        outbarp[ENET_MINPACKET];         /*--------------------------------------------------------------------+         | 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("%s: ENETSEND: send frame error.\n",dev.name);         }         (void)ppcMtmsr(msr); #if 0                  // YYD, timeout delay         {             int timeout = 30000;             int len = outframe_len;             while(outframe_len > 0 && timeout > 0)             {                 nsdelay(100*1000); // 100 us delay                 timeout --;             }             if(outframe_len ==0) return len;         }#endif         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("%s: ENETSEND: send frame error.\n",dev.name);      (void)ppcMtmsr(msr);      return(-1);   }   (void)ppcMtmsr(msr);   return(len+ sizeof(struct enet_frame)- 2);}/*-----------------------------------------------------------------------------+ . Function: Enet_send_macframe . . Purpose: .      This sends the actual packet to the SMC9xxx chip. . . Algorithm: .      First, see if a buf is available. .      Now, find the packet number that the chip allocated .      Point the data pointers at it in memory .      Set the length word in the chip's memory .      Dump the packet to chip memory .      Check if a last byte is needed ( odd length packet ) .              if so, set the control flag right .      Tell the card to send it .      Enable the transmit interrupt, so I know if it failed+-----------------------------------------------------------------------------*/int enet_send_macframe(char * frame, int frame_len){   struct enet_frame    *ef_ptr=(struct enet_frame *)frame;   char                    packet_no;   unsigned int            length;   char                    *buf;   char                    mask;#ifdef DEBUG_MSG_MACFRAME   s1printf("%s: SEND_MACFRAME: Entered...\n", dev.name);#endif   /*--------------------------------------------------------------------------+   | 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;   }   if ( !frame_len ) {      s1printf("%s: SEND_MACFRAME: In XMIT with no packet to send \n", dev.name);      return(1);   }   length = frame_len;   buf = frame;   /* If I get here, I _know_ there is a packet slot waiting for me */   packet_no = in16( ENET_IO_ADDR + PN_REG )>>8; // YYD   if ( packet_no & AR_FAILED ) {           /* or isn't there?  BAD CHIP! */           s1printf("%s: SEND_MACFRAME: Memory allocation failed. \n",                   dev.name);           dev.tbusy = 0;           return(1);   }//   s1printf("Send pkt no = %x\n", packet_no);   /* we have a packet address, so tell the card to use it */   out16( ENET_IO_ADDR + PN_REG, packet_no );   /* point to the beginning of the packet */   out16( ENET_IO_ADDR + PTR_REG, PTR_AUTOINC);#ifdef DEBUG_MSG_MACFRAME   s1printf("%s: SEND_MACFRAME: Trying to xmit packet of length 0x%x\n",           dev.name, length);   dump( buf, length );#endif   /* send the packet length ( +6 for status, length and ctl byte )      and the status word ( set to zeros ) */   out16( ENET_IO_ADDR + DATA_REG, 0x00 );   /* send the packet length ( +6 for status words, length, and ctl*/   out16( ENET_IO_ADDR + DATA_REG, (length+6) );   /* send the actual data    . I _think_ it's faster to send the longs first, and then    . mop up by sending the last word.  It depends heavily    . on alignment, at least on the 486.  Maybe it would be    . a good idea to check which is optimal?  But that could take    . almost as much time as is saved?   */   outsw(ENET_IO_ADDR + DATA_REG, buf, (length ) >> 1);   /* Send the last byte, if there is one.   */   if ( (length & 1) == 0 ) {           out16( ENET_IO_ADDR + DATA_REG, 0x00);   } else {           out16( ENET_IO_ADDR + DATA_REG, 0x2000 | buf[length -1 ]);          // Set odd bit in CONTROL BYTE   }   /* enable the interrupts */   out16( ENET_IO_ADDR + BANK_SELECT, 0x02 );   mask = in16( ENET_IO_ADDR + INT_REG )>>8;   mask |= IM_TX_INT | IM_TX_EMPTY_INT;   out16( ENET_IO_ADDR + INT_REG, (mask<<8) );  // YYD, IM_TX_EMPTY_INT//   out16( ENET_IO_ADDR + INT_REG, IM_TX_EMPTY_INT );   /* and let the chipset deal with it */   out16( ENET_IO_ADDR + MMU_CMD_REG, MC_ENQUEUE);   nsdelay(1000);   // YYD wait for status update//   out16( ENET_IO_ADDR + INT_REG, (mask<<8) );  // YYD, IM_TX_EMPTY_INT#ifdef DEBUG_MSG_MACFRAME   s1printf("%s: SEND_MACFRAME: Sent packet of length 0x%x \n",                                dev.name, length);#endif   /* we can send another packet */   dev.tbusy = 0;   return(0);}/************************************************************************* . phy_interrupt . . Purpose:  Handle interrupts relating to PHY register 18. This is .  called from the "hard" interrupt handler. . ************************************************************************/static void phy_interrupt(){        char phyaddr = dev.phyaddr;        unsigned int phy18;#ifdef DEBUG_MSG_PHYINT        s1printf("%s: phy_interrupt\n", dev.name);#endif  while (1)        {        // Read PHY Register 18, Status Output        phy18 = phy_readreg(phyaddr, PHY_INT_REG);        // Exit if not more changes        if (phy18 == dev.lastPhy18)                break;#if (PHY_DEBUG > 1 )        s1printf("%s:     phy18=0x%x\n", dev.name, phy18);        s1printf("%s: lastPhy18=0x%x\n", dev.name, dev.lastPhy18);        // Handle events        if ((phy18 & PHY_INT_LNKFAIL) != (dev.lastPhy18 & PHY_INT_LNKFAIL))                {                s1printf("%s: PHY Link Fail=%x\n", dev.name,                        phy18 & PHY_INT_LNKFAIL);                }        if ((phy18 & PHY_INT_LOSSSYNC) != (dev.lastPhy18 & PHY_INT_LOSSSYNC))                {                s1printf("%s: PHY LOSS SYNC=%x\n", dev.name,                        phy18 & PHY_INT_LOSSSYNC);                }        if ((phy18 & PHY_INT_CWRD) != (dev.lastPhy18 & PHY_INT_CWRD))                {                s1printf("%s: PHY INVALID 4B5B code=%x\n", dev.name,                        phy18 & PHY_INT_CWRD);                }        if ((phy18 & PHY_INT_SSD) != (dev.lastPhy18 & PHY_INT_SSD))                {                s1printf("%s: PHY No Start Of Stream=%x\n", dev.name,                        phy18 & PHY_INT_SSD);                }        if ((phy18 & PHY_INT_ESD) != (dev.lastPhy18 & PHY_INT_ESD))                {                s1printf("%s: PHY No End Of Stream=%x\n", dev.name,                        phy18 & PHY_INT_ESD);                }        if ((phy18 & PHY_INT_RPOL) != (dev.lastPhy18 & PHY_INT_RPOL))                {                s1printf("%s: PHY Reverse Polarity Detected=%x\n", dev.name,                        phy18 & PHY_INT_RPOL);                }        if ((phy18 & PHY_INT_JAB) != (dev.lastPhy18 & PHY_INT_JAB))                {                s1printf("%s: PHY Jabber Detected=%x\n", dev.name,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -