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

📄 elnk.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 5 页
字号:
      rtems_id                  stat_timer_id;      unsigned32                stats_update_ticks;      struct xl_stats           xl_stats;      u_int8_t                  xl_unit;	/* interface number */      u_int8_t                  xl_type;      int			xl_flags;      u_int16_t                 xl_media;      u_int16_t                 xl_caps;      u_int32_t                 xl_xcvr;      u_int8_t                  xl_stats_no_timeout;      u_int16_t                 xl_tx_thresh;      int                       tx_idle;      short                     chain_lengths[NUM_CHAIN_LENGTHS];      int                       chlenIndex;      unsigned short            vendorID, deviceID;      int			acceptBroadcast;      int                       numTxbuffers, numRxbuffers;};static struct elnk_softc elnk_softc[NUM_UNITS];static rtems_id	rxDaemonTid;static rtems_id	txDaemonTid;static rtems_id chainRecoveryQueue;#if defined(__i386__)#define CSR_WRITE_4(sc, reg, val)	i386_outport_long( sc->ioaddr + reg, val )#define CSR_WRITE_2(sc, reg, val)	i386_outport_word( sc->ioaddr + reg, val )#define CSR_WRITE_1(sc, reg, val)	i386_outport_byte( sc->ioaddr + reg, val )inline unsigned int CSR_READ_4( struct elnk_softc *sc, int reg){   unsigned int myval;   i386_inport_long( sc->ioaddr + reg, myval );   return myval;}inline unsigned short  CSR_READ_2( struct elnk_softc *sc, int reg){   unsigned short myval;   i386_inport_word( sc->ioaddr + reg, myval );   return myval;}inline unsigned char CSR_READ_1( struct elnk_softc *sc, int reg){   unsigned char myval;   i386_inport_byte( sc->ioaddr + reg, myval );   return myval;}#endif#if defined(__PPC__)#define CSR_WRITE_4(sc, reg, val)	outl( val, sc->ioaddr + reg)#define CSR_WRITE_2(sc, reg, val)	outw( val, sc->ioaddr + reg)#define CSR_WRITE_1(sc, reg, val)	outb( val, sc->ioaddr + reg)#define CSR_READ_4(sc, reg)	        inl(sc->ioaddr + reg)#define CSR_READ_2(sc, reg)	        inw(sc->ioaddr + reg)#define CSR_READ_1(sc, reg)	        inb(sc->ioaddr + reg)#endif#define XL_SEL_WIN(x)                   CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_WINSEL | x)/* * Murphy's law says that it's possible the chip can wedge and * the 'command in progress' bit may never clear. Hence, we wait * only a finite amount of time to avoid getting caught in an * infinite loop. Normally this delay routine would be a macro, * but it isn't called during normal operation so we can afford * to make it a function. */static voidxl_wait(sc)   struct elnk_softc	*sc;{   register int		i;   for(i = 0; i < XL_TIMEOUT; i++)    {      if (!(CSR_READ_2(sc, XL_STATUS) & XL_STAT_CMDBUSY))         break;   }   if (i == XL_TIMEOUT)      printk("etherlink : unit elnk%d command never completed\n", sc->xl_unit );   return;}/* * MII access routines are provided for adapters with external * PHYs (3c905-TX, 3c905-T4, 3c905B-T4) and those with built-in * autoneg logic that's faked up to look like a PHY (3c905B-TX). * Note: if you don't perform the MDIO operations just right, * it's possible to end up with code that works correctly with * some chips/CPUs/processor speeds/bus speeds/etc but not * with others. */#define MII_SET(x)					\	CSR_WRITE_2(sc, XL_W4_PHY_MGMT,			\		CSR_READ_2(sc, XL_W4_PHY_MGMT) | (x))#define MII_CLR(x)					\	CSR_WRITE_2(sc, XL_W4_PHY_MGMT,			\		CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~(x))/* * Sync the PHYs by setting data bit and strobing the clock 32 times. */static voidxl_mii_sync(sc)   struct elnk_softc		*sc;{   register int		i;   XL_SEL_WIN(4);   MII_SET(XL_MII_DIR|XL_MII_DATA);   for (i = 0; i < 32; i++) {      MII_SET(XL_MII_CLK);      MII_SET(XL_MII_DATA);      MII_CLR(XL_MII_CLK);      MII_SET(XL_MII_DATA);   }   return;}/* * Clock a series of bits through the MII. */static voidxl_mii_send(sc, bits, cnt)   struct elnk_softc		*sc;   u_int32_t		bits;   int			cnt;{   int			i;   XL_SEL_WIN(4);   MII_CLR(XL_MII_CLK);   for (i = (0x1 << (cnt - 1)); i; i >>= 1) {      if (bits & i) {         MII_SET(XL_MII_DATA);      } else {         MII_CLR(XL_MII_DATA);      }      MII_CLR(XL_MII_CLK);      MII_SET(XL_MII_CLK);   }}/* * Read an PHY register through the MII. */static intxl_mii_readreg(sc, frame)   struct elnk_softc		*sc;   struct xl_mii_frame	*frame;	{   int			i, ack;   /*    * Set up frame for RX.    */   frame->mii_stdelim = XL_MII_STARTDELIM;   frame->mii_opcode = XL_MII_READOP;   frame->mii_turnaround = 0;   frame->mii_data = 0;	   /*    * Select register window 4.    */   XL_SEL_WIN(4);   CSR_WRITE_2(sc, XL_W4_PHY_MGMT, 0);   /*    * Turn on data xmit.    */   MII_SET(XL_MII_DIR);   xl_mii_sync(sc);   /*    * Send command/address info.    */   xl_mii_send(sc, frame->mii_stdelim, 2);   xl_mii_send(sc, frame->mii_opcode, 2);   xl_mii_send(sc, frame->mii_phyaddr, 5);   xl_mii_send(sc, frame->mii_regaddr, 5);   /* Idle bit */   MII_CLR((XL_MII_CLK|XL_MII_DATA));   MII_SET(XL_MII_CLK);   /* Turn off xmit. */   MII_CLR(XL_MII_DIR);   /* Check for ack */   MII_CLR(XL_MII_CLK);   ack = CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA;   MII_SET(XL_MII_CLK);   /*    * Now try reading data bits. If the ack failed, we still    * need to clock through 16 cycles to keep the PHY(s) in sync.    */   if (ack) {      for(i = 0; i < 16; i++) {         MII_CLR(XL_MII_CLK);         MII_SET(XL_MII_CLK);      }      goto fail;   }   for (i = 0x8000; i; i >>= 1) {      MII_CLR(XL_MII_CLK);      if (!ack) {         if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA)            frame->mii_data |= i;      }      MII_SET(XL_MII_CLK);   }  fail:   MII_CLR(XL_MII_CLK);   MII_SET(XL_MII_CLK);   if (ack)      return(1);   return(0);}/* * Write to a PHY register through the MII. */static intxl_mii_writereg(sc, frame)   struct elnk_softc		*sc;   struct xl_mii_frame	*frame;	{   /*    * Set up frame for TX.    */   frame->mii_stdelim = XL_MII_STARTDELIM;   frame->mii_opcode = XL_MII_WRITEOP;   frame->mii_turnaround = XL_MII_TURNAROUND;	   /*    * Select the window 4.    */   XL_SEL_WIN(4);   /*    * Turn on data output.    */   MII_SET(XL_MII_DIR);   xl_mii_sync(sc);   xl_mii_send(sc, frame->mii_stdelim, 2);   xl_mii_send(sc, frame->mii_opcode, 2);   xl_mii_send(sc, frame->mii_phyaddr, 5);   xl_mii_send(sc, frame->mii_regaddr, 5);   xl_mii_send(sc, frame->mii_turnaround, 2);   xl_mii_send(sc, frame->mii_data, 16);   /* Idle bit. */   MII_SET(XL_MII_CLK);   MII_CLR(XL_MII_CLK);   /*    * Turn off xmit.    */   MII_CLR(XL_MII_DIR);   return(0);}static intxl_miibus_readreg(sc, phy, reg)   struct elnk_softc	*sc;   int			phy, reg;{   struct xl_mii_frame	frame;   /*    * Pretend that PHYs are only available at MII address 24.    * This is to guard against problems with certain 3Com ASIC    * revisions that incorrectly map the internal transceiver    * control registers at all MII addresses. This can cause    * the miibus code to attach the same PHY several times over.    */   if ((!(sc->xl_flags & XL_FLAG_PHYOK)) && phy != 24)   {      printk("etherlink : unit elnk%d xl_miibus_readreg returned\n", sc->xl_unit);      return(0);   }   memset((char *)&frame, 0, sizeof(frame));   frame.mii_phyaddr = phy;   frame.mii_regaddr = reg;   xl_mii_readreg(sc, &frame);   return(frame.mii_data);}static intxl_miibus_writereg(sc, phy, reg, data)   struct elnk_softc		*sc;   int			phy, reg, data;{   struct xl_mii_frame	frame;   if ((!(sc->xl_flags & XL_FLAG_PHYOK)) && phy != 24)   {      printk("etherlink : unit elnk%d xl_miibus_writereg returned\n", sc->xl_unit);      return(0);   }   memset((char *)&frame, 0, sizeof(frame));   frame.mii_phyaddr = phy;   frame.mii_regaddr = reg;   frame.mii_data = data;   xl_mii_writereg(sc, &frame);   return(0);}/* * The EEPROM is slow: give it time to come ready after issuing * it a command. */static intxl_eeprom_wait(sc)   struct elnk_softc		*sc;{   int			i;   for (i = 0; i < 100; i++) {      if (CSR_READ_2(sc, XL_W0_EE_CMD) & XL_EE_BUSY)         DELAY(162);      else         break;   }   if (i == 100) {      printk("etherlink : unit elnk%d eeprom failed to come ready\n", sc->xl_unit);      return(1);   }   return(0);}/* * Read a sequence of words from the EEPROM. Note that ethernet address * data is stored in the EEPROM in network byte order. */static intxl_read_eeprom(sc, dest, off, cnt, swap)   struct elnk_softc		*sc;   caddr_t			dest;   int			off;   int			cnt;   int			swap;{   int			err = 0, i;   u_int16_t		word = 0, *ptr;#define EEPROM_5BIT_OFFSET(A) ((((A) << 2) & 0x7F00) | ((A) & 0x003F))#define EEPROM_8BIT_OFFSET(A) ((A) & 0x003F)   /* WARNING! DANGER!    * It's easy to accidentally overwrite the rom content!    * Note: the 3c575 uses 8bit EEPROM offsets.    */   XL_SEL_WIN(0);   if (xl_eeprom_wait(sc))      return(1);   if (sc->xl_flags & XL_FLAG_EEPROM_OFFSET_30)      off += 0x30;   for (i = 0; i < cnt; i++) {      if (sc->xl_flags & XL_FLAG_8BITROM)         CSR_WRITE_2(sc, XL_W0_EE_CMD,                      XL_EE_8BIT_READ | EEPROM_8BIT_OFFSET(off + i));      else         CSR_WRITE_2(sc, XL_W0_EE_CMD,                     XL_EE_READ | EEPROM_5BIT_OFFSET(off + i));      err = xl_eeprom_wait(sc);      if (err)         break;      word = CSR_READ_2(sc, XL_W0_EE_DATA);      ptr = (u_int16_t *)(dest + (i * 2));      if (swap)         *ptr = ntohs(word);      else         *ptr = word;	   }   return(err ? 1 : 0);}static voidxl_stats_update(timerid,xsc)   rtems_id timerid;   void *xsc;{   struct elnk_softc	*sc = (struct elnk_softc *)xsc;   struct ifnet         *ifp = &sc->arpcom.ac_if;   u_int32_t            t1;   sc->xl_stats.intstatus = CSR_READ_2(sc, XL_STATUS);      sc->xl_stats.miianr    = xl_miibus_readreg(sc, 0x18, MII_ANAR );   sc->xl_stats.miipar    = xl_miibus_readreg(sc, 0x18, MII_ANLPAR );   sc->xl_stats.miistatus = xl_miibus_readreg(sc, 0x18, MII_BMSR );   sc->xl_stats.miicmd    = xl_miibus_readreg(sc, 0x18, MII_BMCR );

⌨️ 快捷键说明

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