コード例 #1
0
ファイル: xiltemac.c プロジェクト: AlexShiLucky/rtems
void xilTemacStop(struct ifnet *ifp)
{
  struct XilTemac* xilTemac = ifp->if_softc;
  uint32_t base = xilTemac->iAddr;

  /* Disable ipif interrupts */
  OUT32(base + XTE_DGIE_OFFSET, 0);

  /* Disable the receiver */
  uint32_t rxc1 = IN32(base + XTE_ERXC1_OFFSET);
  rxc1 &= ~XTE_ERXC1_RXEN_MASK;
  OUT32(base + XTE_ERXC1_OFFSET, rxc1);

  /* If receiver was receiving a packet when we disabled it, it will be
   * rejected, clear appropriate status bit */
  uint32_t ipisr = IN32(base + XTE_IPISR_OFFSET);
  if( ipisr & XTE_IPXR_RECV_REJECT_MASK ) {
    OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_RECV_REJECT_MASK);
  }

#if PPC_HAS_CLASSIC_EXCEPTIONS
  if( xilTemac->iOldHandler )
  {
    opb_intc_set_vector( xilTemac->iOldHandler, xilTemac->iIsrVector, NULL );
    xilTemac->iOldHandler = 0;
  }
#else
  if( xilTemac->iOldHandler.name != 0)
  {
    BSP_install_rtems_irq_handler (&xilTemac->iOldHandler);
  }
#endif

  ifp->if_flags &= ~IFF_RUNNING;
}
コード例 #2
0
int is_sd_accessible(void)
{
	volatile unsigned int present_state;
	int timer=0;

	xil_printf("check SD card accessibility \n");
	#if 0
	IN8(XPAR_LOGISDHC_0_REGS_BASEADDR+0x2F) = 0x01;  	// Soft reset
	IN16(XPAR_LOGISDHC_0_REGS_BASEADDR+0x2C) = 0x205; 	// Clock ctrl reg; SD clock frequency = 50MHz/2, SD clk en, Internal clk en
	IN8(XPAR_LOGISDHC_0_REGS_BASEADDR+0x28) = 0x00;  	// Host ctrl reg; High speed disabled, Data trans width = 1, (0x06; Host ctrl reg; High speed enabled, Data trans width = 4)  ; 0x04 High speed
	IN8(XPAR_LOGISDHC_0_REGS_BASEADDR+0x29) = 0x0F;  	// Power ctrl reg; SD Bus voltage select, SD Bus Power
	IN16(XPAR_LOGISDHC_0_REGS_BASEADDR+0x36) = 0xFFFF;  // Error interrupt status en reg; Enable all
	IN16(XPAR_LOGISDHC_0_REGS_BASEADDR+0x34) = 0xFFFF;  // Normal interrupt status en reg; Enable all
	IN16(XPAR_LOGISDHC_0_REGS_BASEADDR+0x38) = 0x0008;  // Normal interrupt signal en reg; Enable all
	IN16(XPAR_LOGISDHC_0_REGS_BASEADDR+0x3A) = 0x0000;  // Error interrupt signal en reg; dis Enable all
	#endif

   for(timer=0; timer < 100; timer++)
   {
	   present_state = IN32(XPAR_LOGISDHC_0_REGS_BASEADDR+0x24+0);  //Check Present state reg (bit 0 and 1) before doing anything
	   if((present_state & 0x3) == 0)
		   break;
   }
   present_state = IN32(XPAR_LOGISDHC_0_REGS_BASEADDR+0x24+0);  //Check Present state reg (bit 0 and 1) before doing anything
   if((present_state & 0x3) != 0)
	   return -1;	// BAD, SD card is not accessible.

   return 0;		// GOOD, SD card is accessible.
}
コード例 #3
0
ファイル: xiltemac.c プロジェクト: AlexShiLucky/rtems
void xilTemacFifoRead64(uint32_t aBaseAddr, uint32_t* aBuf, uint32_t aBytes)
{
  uint32_t numqwords = aBytes / 8;
  uint32_t xtrabytes = aBytes % 8;
  uint32_t i;

  for(i = 0; i < numqwords; i++)
  {
    aBuf[ (i*2)   ] = IN32(aBaseAddr + XTE_PFIFO_RX_DATA_OFFSET);
    aBuf[ (i*2)+1 ] = IN32(aBaseAddr + XTE_PFIFO_RX_DATA_OFFSET + 4);
  }

  /* If there was a non qword sized read */
  if( xtrabytes != 0 )
  {
    uint32_t lastdwordMS = IN32(aBaseAddr + XTE_PFIFO_RX_DATA_OFFSET);
    uint32_t lastdwordLS = IN32(aBaseAddr + XTE_PFIFO_RX_DATA_OFFSET + 4);
    uint8_t* finalbytes = (uint8_t *)&aBuf[ (numqwords*2) ];
    uint8_t* ptr8;
    int32_t  offset = 0;

    ptr8 = (uint8_t *)&lastdwordMS;
    if( xtrabytes >= 4 )
    {
      finalbytes[ offset++ ] = ptr8[0];
      finalbytes[ offset++ ] = ptr8[1];
      finalbytes[ offset++ ] = ptr8[2];
      finalbytes[ offset++ ] = ptr8[3];

      xtrabytes -= 4;
      ptr8 = (uint8_t *)&lastdwordLS;
    }

    if( xtrabytes == 1 )
    {
      finalbytes[ offset++ ] = ptr8[0];
    }
    else if ( xtrabytes == 2 )
    {
      finalbytes[ offset++ ] = ptr8[0];
      finalbytes[ offset++ ] = ptr8[1];
    }
    else if ( xtrabytes == 3 )
    {
      finalbytes[ offset++ ] = ptr8[0];
      finalbytes[ offset++ ] = ptr8[1];
      finalbytes[ offset++ ] = ptr8[2];
    }
  }
}
コード例 #4
0
ファイル: xiltemac.c プロジェクト: AlexShiLucky/rtems
uint32_t xilTemacTxFifoVacancyBytes(uint32_t aBaseAddr)
{
  uint32_t ipisr = IN32(aBaseAddr + XTE_IPISR_OFFSET);
  uint32_t bytes = 0;
  if(ipisr & XTE_IPXR_XMIT_LFIFO_FULL_MASK) {
    /* If there's no room in the transmit length fifo, then any room in the
     * data fifo is irrelevant, return 0 */
  } else {
    bytes = IN32(aBaseAddr + XTE_PFIFO_TX_VACANCY_OFFSET);
    bytes &= XTE_PFIFO_COUNT_MASK;
    bytes *= 8;
  }
  return bytes;
}
コード例 #5
0
ファイル: xiltemac.c プロジェクト: AlexShiLucky/rtems
void xilTemacTxThreadSingle(struct ifnet* ifp)
{
  struct XilTemac* xilTemac = ifp->if_softc;
  struct mbuf*     m;
  uint32_t base = xilTemac->iAddr;

#ifdef DEBUG
  printk("%s: tx send packet, interface '%s'\n", DRIVER_PREFIX, xilTemac->iUnitName );
#endif

  /* Send packets till mbuf queue empty or tx fifo full */
  for(;;) {
    uint32_t i = 0;

    /* 1) clear out any statuses from previously sent tx frames */
    while( IN32(base + XTE_IPISR_OFFSET) & XTE_IPXR_XMIT_DONE_MASK ) {
      IN32(base + XTE_TSR_OFFSET);
      OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_XMIT_DONE_MASK);
      i++;
    }
    if( i > xilTemac->iStats.iTxMaxDrained ) {
      xilTemac->iStats.iTxMaxDrained = i;
    }

    /* 2) Check if enough space in tx data fifo _and_ tx tplr for an entire
       ethernet frame */
    if( xilTemacTxFifoVacancyBytes( xilTemac->iAddr ) <= ifp->if_mtu ) {
      /* 2a) If not, enable transmit done interrupt and break out of loop to
         wait for space */
      uint32_t ipier = IN32(base + XTE_IPIER_OFFSET);
      ipier |= (XTE_IPXR_XMIT_DONE_MASK);
      OUT32(base + XTE_IPIER_OFFSET, ipier);
      break;
    }

    /* 3) Contuine to dequeue mbuf chains till none left */
    IF_DEQUEUE( &(ifp->if_snd), m);
    if( !m ) {
      break;
    }

    /* 4) Send dequeued mbuf chain */
    xilTemacSendPacket( ifp, m );

    /* 5) Free mbuf chain */
    m_freem( m );
  }
  ifp->if_flags &= ~IFF_OACTIVE;
}
コード例 #6
0
ファイル: xiltemac.c プロジェクト: AlexShiLucky/rtems
void xilTemacSetMacAddress(struct ifnet *ifp, unsigned char* aAddr)
{
  struct XilTemac* xilTemac = ifp->if_softc;
  uint32_t base = xilTemac->iAddr;

  /* You can't change the mac address while the card is in operation */
  if( (ifp->if_flags & IFF_RUNNING) != 0 ) {
    printk("%s: attempted to change MAC while up, interface '%s'\n", DRIVER_PREFIX, xilTemac->iUnitName );
    assert(0);
  }
  uint32_t mac;
  mac  = aAddr[0] & 0x000000FF;
  mac |= aAddr[1] << 8;
  mac |= aAddr[2] << 16;
  mac |= aAddr[3] << 24;
  OUT32(base + XTE_EUAW0_OFFSET, mac);

  mac = IN32(base + XTE_EUAW1_OFFSET);
  mac &= ~XTE_EUAW1_MASK;
  mac |= aAddr[4] & 0x000000FF;
  mac |= aAddr[5] << 8;
  OUT32(base + XTE_EUAW1_OFFSET, mac);
}
コード例 #7
0
ファイル: xiltemac.c プロジェクト: AlexShiLucky/rtems
void xilTemacRxThreadSingle(struct ifnet* ifp)
{
  struct XilTemac* xilTemac = ifp->if_softc;

  uint32_t npkts = 0;
#ifdef DEBUG
  printk("%s: rxthread, packet rx on interface %s\n", DRIVER_PREFIX, xilTemac->iUnitName );
#endif

  uint32_t base = xilTemac->iAddr;

  /* While RECV_DONE_MASK in ipisr stays set */
  while( IN32(base + XTE_IPISR_OFFSET) & XTE_IPXR_RECV_DONE_MASK ) {

    /* 1) Read the length of the packet */
    uint32_t bytes = IN32(base + XTE_RPLR_OFFSET);

    /* 2) Read the Read Status Register (which contains no information).  When
     * all of these in the fifo have been read, then XTE_IPXR_RECV_DONE_MASK
     * will stay turned off, after it's written to */
    IN32(base + XTE_RSR_OFFSET);
    npkts++;

    struct mbuf* m;
    struct ether_header* eh;

    /* 3) Get some memory from the ip stack to store the packet in */
    MGETHDR(m, M_WAIT, MT_DATA);
    MCLGET(m, M_WAIT);

    m->m_pkthdr.rcvif = ifp;

    /* 4) Copy the packet into the ip stack's memory */
    xilTemacFifoRead64( base, mtod(m, uint32_t*), bytes);

    m->m_len = bytes - sizeof(struct ether_header);
    m->m_pkthdr.len = bytes - sizeof(struct ether_header);

    eh = mtod(m, struct ether_header*);

    m->m_data += sizeof(struct ether_header);

    /* 5) Tell the ip stack about the received packet */
    ether_input(ifp, eh, m);

    /* 6) Try and turn off XTE_IPXR_RECV_DONE bit in the ipisr.  If there's
     * still more packets (ie RSR ! empty), then it will stay asserted.  If
     * there's no more packets, this will turn it off.
     */
    OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_RECV_DONE_MASK);
  }

  /* End) All Rx packets serviced, renable rx interrupt */
  uint32_t ipier = IN32(base + XTE_IPIER_OFFSET);
  ipier |= XTE_IPXR_RECV_DONE_MASK;
  OUT32(base + XTE_IPIER_OFFSET, ipier);

#ifdef DEBUG
  printk("%s: rxthread, retrieved %d packets\n", DRIVER_PREFIX, npkts );
#endif
  if(npkts > xilTemac->iStats.iRxMaxDrained) {
    xilTemac->iStats.iRxMaxDrained = npkts;
  }
  /* ??) Very very occasionally, under extremely high stress, I get a situation
   * where we process no packets.  That is, the rx thread was evented, but
   * there was no packet available.  I'm not sure how this happens.  Ideally,
   * it shouldn't ocurr, and I suspect a minor bug in the driver.  However, for
   * me it's happenning 3 times in several hunderd million interrupts.  Nothing
   * bad happens, as long as we don't read from the rx fifo's if nothing is
   * there.  It is just not as efficient as possible (rx thread being evented
   * pointlessly) and a bit disconcerting about how it's ocurring.
   * The best way to reproduce this is to have two clients run:
   * $ ping <host> -f -s 65507
   * This flood pings the device from two clients with the maximum size ping
   * packet.  It absolutely hammers the device under test.  Eventually, (if
   * you leave it running overnight for instance), you'll get a couple of these
   * stray rx events. */
  if(npkts == 0) {
    /*printk("%s: RxThreadSingle: fatal error: event received, but no packets available\n", DRIVER_PREFIX);
    assert(0); */
    xilTemac->iStats.iRxStrayEvents++;
  }
}
コード例 #8
0
ファイル: xiltemac.c プロジェクト: AlexShiLucky/rtems
void xilTemacIsrSingle(struct XilTemac* xilTemac)
{
  uint32_t base = xilTemac->iAddr;
  uint32_t disr = IN32( base + XTE_DISR_OFFSET );
  struct ifnet* ifp = xilTemac->iIfp;

  if( disr && (ifp->if_flags & IFF_RUNNING) == 0 ) {
    /* some interrupt status bits are asserted but card is down */
    printk("%s: Fatal error, disr 0 or this emac not running\n", DRIVER_PREFIX);
    /*assert(0);*/
  } else {
    /* Handle all error conditions first */
    if( disr & (XTE_DXR_DPTO_MASK | XTE_DXR_TERR_MASK |
                XTE_DXR_RECV_FIFO_MASK | XTE_DXR_SEND_FIFO_MASK) ) {
      printk("%s: Fatal Bus error, disr: %08x\n", DRIVER_PREFIX, disr);
      /*assert(0);*/
    }
    if( disr & XTE_DXR_CORE_MASK ) {
      /* Normal case, temac interrupt */
      uint32_t ipisr = IN32(base + XTE_IPISR_OFFSET);
      uint32_t ipier = IN32(base + XTE_IPIER_OFFSET);
      uint32_t newipier = ipier;
      uint32_t pending = ipisr & ipier;
      xilTemac->iStats.iInterrupts++;

      /* Check for all fatal errors, even if that error is not enabled in ipier */
      if(ipisr & XTE_IPXR_FIFO_FATAL_ERROR_MASK) {
        printk("%s: Fatal Fifo Error ipisr: %08x\n", DRIVER_PREFIX, ipisr);
        /*assert(0);*/
      }

      if(pending & XTE_IPXR_RECV_DONE_MASK) {
        /* We've received a packet
           - inc stats
           - disable rx interrupt
           - signal rx thread to empty out fifo
             (rx thread must renable interrupt)
        */
        xilTemac->iStats.iRxInterrupts++;

        newipier &= ~XTE_IPXR_RECV_DONE_MASK;

        rtems_bsdnet_event_send(gXilRxThread, xilTemac->iIoEvent);
      }
      if(pending & XTE_IPXR_XMIT_DONE_MASK) {
        /* We've transmitted a packet.  This interrupt is only ever enabled in
           the ipier if the tx thread didn't have enough space in the data fifo
           or the tplr fifo.  If that's the case, we:
           - inc stats
           - disable tx interrupt
           - signal tx thread that a transmit has completed and thus there is now
             room to send again.
        */
        xilTemac->iStats.iTxInterrupts++;

        newipier &= ~XTE_IPXR_XMIT_DONE_MASK;

        rtems_bsdnet_event_send(gXilTxThread, xilTemac->iIoEvent);
      }
      if(pending & XTE_IPXR_RECV_DROPPED_MASK) {
        /* A packet was dropped (because it was invalid, or receiving it
           have overflowed one of the rx fifo's).
           - Increment stats.
           - Clear interrupt condition.
        */
        uint32_t toggle = 0;
        if(pending & XTE_IPXR_RECV_REJECT_MASK) {
          xilTemac->iStats.iRxRejectedInvalidFrame++;
          toggle |= XTE_IPXR_RECV_REJECT_MASK;
        }
        if(pending & XTE_IPXR_RECV_PFIFO_ABORT_MASK) {
          xilTemac->iStats.iRxRejectedDataFifoFull++;
          toggle |= XTE_IPXR_RECV_PFIFO_ABORT_MASK;
        }
        if(pending & XTE_IPXR_RECV_LFIFO_ABORT_MASK) {
          xilTemac->iStats.iRxRejectedLengthFifoFull++;
          toggle |= XTE_IPXR_RECV_LFIFO_ABORT_MASK;
        }
        xilTemac->iStats.iRxRejectedInterrupts++;
        OUT32(base + XTE_IPISR_OFFSET, toggle);
      }
      if(pending & XTE_IPXR_AUTO_NEG_MASK) {
        printk("%s: Autonegotiation finished\n", DRIVER_PREFIX);
        OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_AUTO_NEG_MASK);
      }
      if(newipier != ipier) {
        OUT32(base + XTE_IPIER_OFFSET, newipier);
      }
    }
  }
}
コード例 #9
0
ファイル: xiltemac.c プロジェクト: AlexShiLucky/rtems
void xilTemacStart(struct ifnet *ifp)
{
  if( (ifp->if_flags & IFF_RUNNING) == 0 )
  {
    struct XilTemac* xilTemac = ifp->if_softc;
    uint32_t base = xilTemac->iAddr;

    /* Reset plb temac */
    OUT32(base + XTE_DSR_OFFSET, XTE_DSR_RESET_MASK);
    /* Don't have usleep on rtems 4.6
    usleep(1);
    */
    /* @ fastest ppc clock of 500 MHz = 2ns clk */
    uint32_t i = 0;
    for( i = 0; i < 1 * 500; i++) {
    }

    /* Reset hard temac */
    OUT32(base + XTE_CR_OFFSET, XTE_CR_HTRST_MASK);
    /* Don't have usleep on rtems 4.6
    usleep(4);
    */
    for( i = 0; i < 4 * 500; i++) {
    }

    /* Disable the receiver -- no need to disable xmit as we control that ;) */
    uint32_t rxc1 = IN32(base + XTE_ERXC1_OFFSET);
    rxc1 &= ~XTE_ERXC1_RXEN_MASK;
    OUT32(base + XTE_ERXC1_OFFSET, rxc1);

    /* If receiver was receiving a packet when we disabled it, it will be
     * rejected, clear appropriate status bit */
    uint32_t ipisr = IN32(base + XTE_IPISR_OFFSET);
    if( ipisr & XTE_IPXR_RECV_REJECT_MASK ) {
      OUT32(base + XTE_IPISR_OFFSET, XTE_IPXR_RECV_REJECT_MASK);
    }

    /* Setup IPIF interrupt enables */
    uint32_t dier = XTE_DXR_CORE_MASK | XTE_DXR_DPTO_MASK | XTE_DXR_TERR_MASK;
    dier |= XTE_DXR_RECV_FIFO_MASK | XTE_DXR_SEND_FIFO_MASK;
    OUT32(base + XTE_DIER_OFFSET, dier);

    /* Set the mac address */
    xilTemacSetMacAddress( ifp, xilTemac->iArpcom.ac_enaddr);

    /* Set the link speed */
    uint32_t emcfg = IN32(base + XTE_ECFG_OFFSET);
    printk("xiltemacStart, default linkspeed: %08x\n", emcfg);
    emcfg = (emcfg & ~XTE_ECFG_LINKSPD_MASK) | XTE_ECFG_LINKSPD_100;
    OUT32(base + XTE_ECFG_OFFSET, emcfg);

    /* Set phy divisor and enable mdio.  For a plb bus freq of 150MHz (the
       maximum as of Virtex4 Fx), a divisor of 29 gives a mdio clk freq of
       2.5MHz (see Xilinx docs for equation), the maximum in the phy standard.
       For slower plb frequencies, slower mkdio clks will result.  They may not
       be optimal, but they should work.  */
    uint32_t divisor = 29;
    OUT32(base + XTE_EMC_OFFSET, divisor | XTE_EMC_MDIO_MASK);

#if PPC_HAS_CLASSIC_EXCEPTIONS /* old connect code */
    /* Connect isr vector */
    rtems_status_code   sc;
    extern rtems_isr xilTemacIsr( rtems_vector_number aVector );
    sc = opb_intc_set_vector( xilTemacIsr, xilTemac->iIsrVector, &xilTemac->iOldHandler );
    if( sc != RTEMS_SUCCESSFUL )
    {
      xilTemac->iOldHandler = 0;
      printk("%s: Could not set interrupt vector for interface '%s' opb_intc_set_vector ret: %d\n", DRIVER_PREFIX, xilTemac->iUnitName, sc );
      assert(0);
    }
#else
    {
      rtems_irq_connect_data IrqConnData;

      /*
       *get old irq handler
       */
      xilTemac->iOldHandler.name = xilTemac->iIsrVector;
      if (!BSP_get_current_rtems_irq_handler (&xilTemac->iOldHandler)) {
	xilTemac->iOldHandler.name = 0;
	printk("%s: Unable to detect previous Irq handler\n",DRIVER_PREFIX);
	rtems_fatal_error_occurred(1);
      }

      IrqConnData.on     = xilTemacIsrOn;
      IrqConnData.off    = xilTemacIsrOff;
      IrqConnData.isOn   = xilTemacIsrIsOn;
      IrqConnData.name   = xilTemac->iIsrVector;
      IrqConnData.hdl    = xilTemacIsr;
      IrqConnData.handle = xilTemac;

      if (!BSP_install_rtems_irq_handler (&IrqConnData)) {
	printk("%s: Unable to connect Irq handler\n",DRIVER_PREFIX);
	rtems_fatal_error_occurred(1);
      }
    }
#endif
    /* Enable promiscuous mode -- The temac only supports full duplex, which
       means we're plugged into a switch.  Thus promiscuous mode simply means
       we get all multicast addresses*/
    OUT32(base + XTE_EAFM_OFFSET, XTE_EAFM_EPPRM_MASK);

    /* Setup and enable receiver */
    rxc1 = XTE_ERXC1_RXFCS_MASK | XTE_ERXC1_RXEN_MASK | XTE_ERXC1_RXVLAN_MASK;
    OUT32(base + XTE_ERXC1_OFFSET, rxc1);

    /* Setup and enable transmitter */
    uint32_t txc = XTE_ETXC_TXEN_MASK | XTE_ETXC_TXVLAN_MASK;
    OUT32(base + XTE_ETXC_OFFSET, txc);

    /* Enable interrupts for temac */
    uint32_t ipier = IN32(base + XTE_IPIER_OFFSET);
    ipier |= (XTE_IPXR_XMIT_ERROR_MASK);
    ipier |= (XTE_IPXR_RECV_ERROR_MASK | XTE_IPXR_RECV_DONE_MASK);
    ipier |= (XTE_IPXR_AUTO_NEG_MASK);
    OUT32(base + XTE_IPIER_OFFSET, ipier);

    printk("%s: xiltemacStart, ipier: %08x\n",DRIVER_PREFIX, ipier);

    /* Enable device global interrutps */
    OUT32(base + XTE_DGIE_OFFSET, XTE_DGIE_ENABLE_MASK);
    ifp->if_flags |= IFF_RUNNING;
  }
}