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

📄 net_3c509.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 4 页
字号:
  out8(0x0, id_port);		/* move to ID_WAIT state */  Machine::SpinWaitMs(1);	/* let things settle */  {    /* Output the card ID sequence: */    uint8_t bVal = 0xFF;    for (uint8_t loop = 255; loop; loop--) {      out8(bVal, id_port);      if (bVal & 0x80)	{	  bVal <<= 1;	  bVal ^= 0xCF;	}      else	bVal <<= 1;    }  }}    static voidISA_Probe(AutoConf * ac){#ifdef CONFIG_ISA  /* 3c509's ship with ISA PnP enabled by default, which means that   * most OSes cannot autoconfigure them correctly.  We want to use   * non-PnP configuration, since I have not had time to grok the PnP   * device configuration tree, so tell the PnP mechanism to bug off   * and leave us alone:   */    out8(PnpSelConfigCtrl, PnpAddress); /* select PnP config ctrl register */  out8(ElinkSetContention, PnpWrite); /* and disable PnP config */  Machine::SpinWaitMs(1);	/* let things settle */  /* Figure out where the 3c509 ID port went: */  for (id_port = 0x100; id_port < 0x200; id_port += 0x10) {    if (IoRegion::Allocate(id_port, 0x01, "3c509 contention"))      break;  }  if (id_port >= 0x200) {    MsgLog::dprintf(true, "Unable to configure ISA 3c509 -- "		    "no available ID port\n");    return;  }    /* If we did a warm boot, then we need to force the card to do a   * total reset to reset the previously tagged values.   * Unfortunately, this will completely reset the card, which will   * have the effect of restoring it to PnP mode too.   */    out8(0x0, id_port);		/* set ID PORT value */  Machine::SpinWaitMs(1);	/* let things settle */  /* The global reset doesn't work unless we first put the card in a   * receptive state such as ID_WAIT   */  out8(0x0, id_port);  Machine::SpinWaitMs(1);	/* let things settle */  out8(IdGlobalReset, id_port);  Machine::SpinWaitMs(1);	/* let things settle */  /* Get the card(s) out of PnP mode again: */    out8(PnpSelConfigCtrl, PnpAddress); /* select PnP config ctrl register */  out8(ElinkSetContention, PnpWrite); /* and disable PnP config */  Machine::SpinWaitMs(1);	/* let things settle */    /* ALL of the cards are now reset, which implies that they have a   * ZERO in their tag registers.  Identify all of the cards by   * tagging them:   */    /* NOW we can begin the ID sequence for real: */  for (uint8_t card = 0; ; card++) {    IdentifySequence();        /* If we have tagged any cards at all, make the cards that have     * already been tagged drop out of the contention sequence:     */    if (card == 0)      out8(IdSetTagReg + 0, id_port); /* set all tags to 0 */    else      out8(IdTestAdapter + 0, id_port);    /* Read the manufacturer ID.  If we don't get what we expect we     * are done with ISA probe:     */    if (IsaIdRdEEPROM(id_port, 7) != MANU_3COM) {      MsgLog::dprintf(false, "3c509 not found (manid)\n");      break;    }    NetInterface *ni = NetInterface::Alloc();        /* Contention resolution protocol: check link addr 0..2, address     * config register, resource config register, software config register     */    /* Get the adapter link-level address: */    ni->info.niAddrLen = 6;    for (int i = 0; i < 3; i++) {      uint16_t hw = IsaIdRdEEPROM(id_port, i);      ni->info.niAddr[i*2] = (hw >> 8) & 0xffu;      ni->info.niAddr[ i*2 + 1 ] = hw & 0xffu;    }    uint16_t prodId = IsaIdRdEEPROM(id_port, 0x03);    uint16_t addrCfg = IsaIdRdEEPROM(id_port, 0x08);    uint16_t rsrcCfg = IsaIdRdEEPROM(id_port, 0x09);    (void) IsaIdRdEEPROM(id_port, 0x0d); /* SW config */    uint8_t ioAddrBits = addrCfg & AddrCfgIoBase;        ni->tagValue = card + 1;	/* remember tag value */        /* Output the set tag command: */    out8(IdSetTagReg + ni->tagValue, id_port);    ni->irq = (rsrcCfg & RsrcCfgIrq) >> 12;    ni->ioAddr = ioAddrBits * 0x10 + 0x200;    ni->addr = 0;    ni->len = 0;    ni->xcvr = (addrCfg & AddrCfgXcvr) >> 14;    ni->name = "EtherLink III (ISA)";    ni->devClass = DEV_NET_ENET;    ni->Invoke = Invoke;    ni->info.niStatus = 0;    ni->watchDog.client_ptr = ni;    ni->updateStats = UpdateStatistics;    MsgLog::dprintf(false, "Found ISA 3c509 io=0x%x, irq=%d prod=0x%04x"		    "  link address is %02x:%02x:%02x:%02x:%02x:%02x\n",		    ni->ioAddr,		    ni->irq,		    prodId,		    ni->info.niAddr[0],		    ni->info.niAddr[1],		    ni->info.niAddr[2],		    ni->info.niAddr[3],		    ni->info.niAddr[4],		    ni->info.niAddr[5]);#if 0    /* Reserve I/O port addresses used by adapter. */    if ( IoRegion::Allocate(ni->ioAddr, 0x10, "3c509") == false ) {      MsgLog::dprintf(true, "Unable to enable 3c509 at io=0x%x: "		      "port range is taken\n",		      ni->ioAddr);      continue;    }    /* Activate adapter at preconfigured I/O base address.  After reset     * all interrupts are masked, so the device should not generate any.     */    out8(IdActivate | ioAddrBits, id_port);#endif        ac->present = true;  }#else  /* This will peephole out -- it suppresses a compiler warning. */  ac->present = ac->present;#endif}/* Probe for EtherLink III family cards.  Note that UNLIKE the * corresponding UNIX logic, this code is probing for the device * CLASS, not for device instances -- we do not have a per-instance * autoconfiguration structure, as the network interface capability * carries an instance number.  The job of probe is simply to locate * the instances so that we can later attach them. */static voidProbe(struct AutoConf * ac){  /* No EtherLink III family cards are present until proven otherwise. */  ac->present = false;  EISA_Probe(ac);  MCA_Probe(ac);  ISA_Probe(ac);}/* We assume that by attachment time the autoconfigurator domain has * taken it's shot at the device configuration information, and that * the attachment will either entirely succeed or entirely fail. *  * WARNING: There is a danger in the current implementation.  I do not * understand whether the ID sequence interrupts the in-progress * activities of the cards.  If so, activating one card requires * waiting for the others to quiesce.  This code does not do so.  In * particular I am concerned about diverting the processing of an * incoming interrupt. */static voidAttach(NetInterface* ni){  MsgLog::dprintf(false, "Attaching ISA 3c509 io=0x%x, irq=%d tag=%d"		  "  link address is %02x:%02x:%02x:%02x:%02x:%02x\n",		  ni->ioAddr,		  ni->irq,		  ni->tagValue,		  ni->info.niAddr[0],		  ni->info.niAddr[1],		  ni->info.niAddr[2],		  ni->info.niAddr[3],		  ni->info.niAddr[4],		  ni->info.niAddr[5]);  if (ni->info.niStatus & NI_ATTACHED) {    MsgLog::dprintf(true, "NI 0x%08x already attached\n", ni);    return;  }  /* Reserve I/O port addresses used by adapter. */  if ( IoRegion::Allocate(ni->ioAddr, 0x0f, "3c509") == false ) {    MsgLog::dprintf(true, "Unable to enable 3c509 at io=0x%x: "		    "port range is taken\n",		    ni->ioAddr);    return;  }  /* Reserve the IRQ: */  IntAction *ia = new (0) IntAction(ni->irq, "3c509", HandleInterrupt,				    (uint32_t) ni);  if ( IRQ::WireExclusive(ia) == false ) {    IoRegion::Release(ni->ioAddr, 0x0f);    MsgLog::dprintf(true, "Unable to enable 3c509 at io=0x%x: "		    "irq %d is taken\n",		    ni->ioAddr, ni->irq);    return;  }#if 0  /* DANGER, Will Robinson! -- this sequence keeps interrupts disabled   * for several milliseconds, which is BAD.   */  IRQ::DISABLE();#endif  IdentifySequence();    /* Select the adapter we actually want -- leave the rest alone. */  out8(IdTestAdapter + ni->tagValue, id_port);  /* Activate adapter at preconfigured I/O base address.  After reset   * all interrupts are masked, so the device should not generate any.   */#if 1  out8(IdActivate | (ni->ioAddr >> 4), id_port);#else  out8(IdActivatePreconf, id_port);#endif  Machine::SpinWaitMs(1);  #if 0  IRQ::ENABLE();#endif  /* Verify that it ended up in the right place by reading the   * manufacturer ID from window zero:   */  SetWindow(ni, 0);  uint16_t manid = in16(ni->ioAddr + El3ManufacturerID);    if ( manid != MANU_3COM ) {    MsgLog::dprintf(true, "Alleged adapter does not respond with"		    " proper manufacturer ID (got 0x%04x)\n", manid);    return;  }  /* Set the adaptor IRQ to 0: */  out16(0x0f00, ni->ioAddr + Wn0Irq);  /* Interrupt is reserved, but not enabled at this point. */  ni->info.niStatus |= NI_ATTACHED;  Enable(ni);}static voidAutoAttach(struct AutoConf * /* ac */){  for (uint32_t i = 0; i < KTUNE_NNETDEV; i++) {    NetInterface *ni;    if ( (ni = NetInterface::Get(i)) == 0 )      continue;    if (ni->updateStats != UpdateStatistics)      continue;    Attach(ni);  }}static voidHydrant(Timer* t){  NetInterface *ni = (NetInterface *) t->client_ptr;  SetWindow(ni, 1);  MsgLog::dprintf(false, "%s: elink xmit timeout. TxStatus: 0x%02x"		  " Status 0x%04x tx txFifo room %d\n",		  ni->name,		  in8(ni->ioAddr + Wn1TxStatus),		  in16(ni->ioAddr + El3Status),		  in16(ni->ioAddr + Wn1TxFree));  ni->stats.txWatchdog++;  OutCmd(ni, TxReset, true);	/* long-running cmd */  OutCmd(ni, TxEnable);  ni->wrQ.WakeAll();}static voidInvoke(NetInterface *ni, Invocation& inv){#ifndef OPTION_PURE_ENTRY_STRINGS  Thread::CurContext()->SetupEntryString(inv);#endif#ifndef OPTION_PURE_EXIT_STRINGS  inv.invokee->SetupExitString(inv, inv.validLen);#endif  COMMIT_POINT();    switch (inv.entry.code) {  case OC_NI_Read:    {      ReadPacket(ni, inv);      break;    }  case OC_NI_Write:    {      if (inv.entry.len >= MIN_ENET_PACKET_SZ &&	  inv.entry.len <= MAX_ENET_PACKET_SZ)	WritePacket(ni, inv);      else	inv.exit.code = RC_RequestError;      break;    }  case OC_NI_MultiRead:    {      MultiReadPacket(ni, inv);      break;    }  case OC_NI_MultiWrite:    {      inv.exit.code = RC_UnknownRequest;      return;    }  case OC_NI_GetInfo:    {      inv.CopyOut(sizeof(ni->info), &ni->info);      return;    }  case OC_NI_GetStats:    {      inv.CopyOut(sizeof(ni->stats), &ni->stats);      return;    }  case OC_NI_Reset:    {      inv.exit.code = RC_UnknownRequest;      return;    }  default:    inv.exit.code = RC_UnknownRequest;  }}/* #define ICMP_ECHO_TESTING */#ifdef ICMP_ECHO_TESTING#include <eros/endian.h>#if !defined(MODERATELY_SLOW)/* * Checksum routine for Internet Protocol family headers. * * This routine is very heavily used in the network * code and should be modified for each CPU to be as fast as possible. *  * This implementation is 386 version. */#define REDUCE          {sum = (sum & 0xffff) + (sum >> 16);}#define	ADDCARRY	{if (sum > 0xffff) sum -= 0xffff;}#define	SWAP		{sum <<= 8;}#define	ADVANCE(x)	{w += x; mlen -= x;}/* * Thanks to gcc we don't have to guess * which registers contain sum & w. */#define	Asm	__asm __volatile#define ADD(n)  Asm("addl " #n "(%2),%0" : "=r" (sum) : "0" (sum), "r" (w))#define ADC(n)  Asm("adcl " #n "(%2),%0" : "=r" (sum) : "0" (sum), "r" (w))#define MOP     Asm("adcl $0,%0" :         "=r" (sum) : "0" (sum))#define	UNSWAP	Asm("roll $8,%0" :	   "=r" (sum) : "0" (sum))#define	AOPTION_DDBYTE	{sum += *w; SWAP; byte_swapped ^= 1;}#define	ADDWORD	{sum += *(u_short *)w;}intin_cksum(uint16_t *buf, register int len){  register u_char *w = (u_char *) buf;  register unsigned sum = 0;  register int mlen = len;  int byte_swapped = 0;  len -= mlen;  if (mlen < 16)    goto short_mbuf;  /*   * Force to long boundary so we do longword aligned   * memory operations   */  if ((3 & (long)w) != 0) {    REDUCE;    if ((1 & (long)w) != 0) {      AOPTION_DDBYTE;      ADVANCE(1);    }    if ((2 & (long)w) != 0) {      ADDWORD;      ADVANCE(2);    }  }  /*   * Align 4 bytes past a 16-byte cache line boundary.   */  if ((4 & (long)w) == 0) {    ADD(0);    MOP;    ADVANCE(4);  }  if ((8 & (long)w) != 0) {    ADD(0);  ADC(4);    MOP;    ADVANCE(8);  }  /*   * Do as much of the checksum as possible 32 bits at at time.   * In fact, this loop is unrolled to make overhead from   * branches &c small.   */  while ((mlen -= 32) >= 0) {    /*     * Add with carry 16 words and fold in the last carry     * by adding a 0 with carry.     *     * We aligned the pointer above so that the out-of-     * order operations will cause the next cache line to     * be preloaded while we finish with the current one.     */    ADD(12); ADC(0);  ADC(4);  ADC(8);    ADC(28); ADC(16); ADC(20); ADC(24);    MOP;    w += 32;  }  mlen += 32;  if (mlen >= 16) {    ADD(12); ADC(0);  ADC(4);  ADC(8);    MOP;    ADVANCE(16);  }short_mbuf:  if (mlen >= 8) {    ADD(0);  ADC(4);    MOP;    ADVANCE(8);  }  if (mlen >= 4) {    ADD(0);    MOP;    ADVANCE(4);  }  if (mlen > 0) {    REDUCE;    if (mlen >= 2) {      ADDWORD;      ADVANCE(2);    }    if (mlen >= 1) {      AOPTION_DDBYTE;    }  }

⌨️ 快捷键说明

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