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

📄 ethernet.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
   bcopy(packet,         (void *)PHYS_TO_MEMADDR(M_FROM_CPU(cpuNum),                                 state->copy.rcvEntries[state->rcvPtr].pAddr),         packetSize);        #if 0    CPUPrint(" ------ incoming packet DMA-ed to : 0x%x len=%i  ----------\n",             PHYS_TO_MEMADDR(M_FROM_CPU(cpuNum),                             (char*)state->copy.rcvEntries[state->rcvPtr].pAddr),             packetSize  );    for(i=0;i<packetSize;i++) {       char  x =  packet[i];      if( x && x < 127 ) {         CPUPrint("%c",x);      } else {         CPUPrint("(%x)", x);      }      CPUPrint("\n");    }    CPUPrint("\n------------------------------------\n");#endif    /* Update ring buffer */   state->copy.rcvEntries[state->rcvPtr].len = packetSize;   state->copy.rcvEntries[state->rcvPtr].flag = OS_OWNED;   state->rcvPtr++;   if( state->rcvPtr >= state->copy.numRcvEntries  ) {      state->rcvPtr -=  state->copy.numRcvEntries ;   }    /* timing model ? */   if( 1 ) {      /* uses UPD. No use for a timing model */      SimetherRaiseSlot( state, "receive" );      if( packetSize > 0 )         LogEntry("ETHER-receive",                  cpuNum,                  "controller=%d len=%4i ring \n",                  state->ethernum, packetSize);   }   return packetSize;#else   Sim_Warning("Uh oh.. in SimetherReceivePacket\n");   return 0;#endif}/********************************************************************** * OS interface **********************************************************************/EthRegisterSimetherIO(int iface_num, int offset, int is_write, EthRegister data){  SimetherRegisters *regs  = &simetherState[iface_num].copy;  SimetherState     *state = simetherState + iface_num;  int                index = simetherIndex[offset];  int                copy  = 1;  EthRegister  newVal, oldVal;  int                cpuNum=FIRST_CPU(state->machine);  if (iface_num >= numEtherInterfaces) {     CPUPrint("ETHER: cpu=%i accessed out-of-range controller num %i ",              cpuNum, iface_num);     return 0;  }  ASSERT( offset < sizeof(SimetherRegisters) );  ASSERT( iface_num < ETHER_MAX_CONTROLLERS );  ASSERT( index >= 0 );  newVal = data;  oldVal = *(EthRegister *) ((char*)regs+offset);#ifdef notdef  if( SimConfigGetBool("Ether.Trace")) {     if( !is_write ) {      CPUPrint("ETHER-trace: %lld cpu=%i intr=%i controller=%d "	       "RD (%-10s %2i) val=%3d\n", 	       (CPUVec.CycleCount ?		(uint)CPUVec.CycleCount(cpuNum) : 0 ),	       cpuNum,  state->intrPosted, state->ethernum,	       simetherRegisterNamesStr[simetherOffset[offset]],	       index, oldVal);    } else {       CPUPrint("ETHER-trace: %lld cpu=%i intr=%i controller=%d "	       "WR (%-10s %2i) val=%3d newVal=%3d\n", 	       (CPUVec.CycleCount ?		(uint)CPUVec.CycleCount(cpuNum) : 0 ), 	       cpuNum,  state->intrPosted, state->ethernum,	       simetherRegisterNamesStr[simetherOffset[offset]],	       index, oldVal,newVal);    }  }#endif  SIM_DEBUG(('e', "ETHER-trace: %d IO %-6s (%-10s,%2d) val=%3d newVal=%3d \n",              state->ethernum,             (is_write?"WRITE":"READ"),              simetherRegisterNamesStr[simetherOffset[offset]],              index, oldVal,newVal));                 switch( simetherOffset[offset] ) {   case NONE:          ASSERT(0); copy = 0; break;  case ETHER_ADDR:    ASSERT( !is_write ); return regs->etheraddr[index];  case NUM_RCV:  case NUM_SND:  case NUM_CHUNKS:    ASSERT( !is_write ); break;  case INTR_CPU:     ASSERT( state->copy.intrCPU == SIM_MAXCPUS );    ASSERT( !state->intrPosted );    regs->intrCPU = newVal;  /* must be set before SimmpVec->intrCon..			      * increment */       break; /* simply copy. */  case RCV_ADDR:   case RCV_MAXLEN:    ASSERT( regs->rcvEntries[index].flag == OS_OWNED );    ASSERT( is_write );    break;  case RCV_LEN:    ASSERT( regs->rcvEntries[index].flag == OS_OWNED );    ASSERT( !is_write );  case RCV_FLAG:     ASSERT( index >= 0 && index < regs->numRcvEntries );    ASSERT( !is_write || regs->rcvEntries[index].flag == OS_OWNED );    ASSERT( !is_write || newVal == CONTROLLER_OWNED );    SimetherClearSlot(state); /* ClearSlot if everything is received. ** */    break;  case SND_FIRST:  case SND_LAST:     ASSERT( regs->sndEntries[index].flag == OS_OWNED );    ASSERT( is_write );    break;  case SND_FLAG:     ASSERT( index >= 0 && index < regs->numSndEntries );    ASSERT( !is_write || regs->sndEntries[index].flag == OS_OWNED );    ASSERT( !is_write || newVal == CONTROLLER_OWNED );    if( !is_write ) {      if( regs->sndEntries[index].flag == OS_OWNED ) { 	ASSERT( !state->sndAcks[index] );	state->sndAcks[index] = 1;	/* ClearSlot if everything is received */	SimetherClearSlot(state);         }    } else {        int i;      state->sndAcks[index] = 0;      i = regs->sndEntries[index].firstChunk;      while( 1 ) { 	ASSERT( state->chunkOwner[i] == OS_OWNED );	state->chunkOwner[i] = CONTROLLER_OWNED;	if( i == regs->sndEntries[index].lastChunk )	  break;	i++;	if( i>= state->copy.numSndChunks   ) 	  i -= state->copy.numSndChunks ;      }      copy = SimetherSendPacket(state,index);    }    break;  case CHUNK_ADDR:   case CHUNK_LEN:     ASSERT( index >= 0 && index < regs->numSndChunks );    ASSERT( state->chunkOwner[index] == OS_OWNED );    break;  default:     ASSERT( 0 );  }  if( copy && is_write )      *(EthRegister *)(((char *)regs) + offset) = newVal;  return oldVal;}/* NOTE: * For checkpoint format compatibility with the old version, we checkpoint * the ether state as ints, instead of as uint's. At some point, this * should be changed. */static intSimetherCheckpointCB(CptDescriptor *cptd){  int          if_num,i;  unsigned int tmp;    numEtherInterfaces = TOTAL_ETHER_CONTROLLERS;  if (cptVersion.ver == 3) {     Simcpt_CptInt(cptd,"NumControllers",NO_INDEX,NO_INDEX,&(numEtherInterfaces));  }  if (cptd->mode == CPT_RESTORE) {    ASSERT( !simetherState );    simetherState = (SimetherState *)      ZMALLOC(sizeof(SimetherState)*numEtherInterfaces,"SimetherState");  }   for(if_num = 0; if_num< numEtherInterfaces; if_num++) {    SimetherState     *state = simetherState + if_num;    SimetherRegisters *regs  = &state->copy;    /*      * I/O accessible state      */    for(i=0;i<6;i++) {      char c = regs->etheraddr[i];      Simcpt_CptChar(cptd,"etheraddr",if_num,i,&c);      regs->etheraddr[i] = c;    }    tmp = regs->numRcvEntries;    Simcpt_CptUint(cptd, "numRcvEntries",if_num, NO_INDEX,&tmp);    regs->numRcvEntries = tmp;    tmp = regs->numSndEntries;    Simcpt_CptUint(cptd, "numSndEntries",if_num, NO_INDEX,&tmp);    regs->numSndEntries = tmp;    tmp = regs->numSndChunks;    Simcpt_CptUint(cptd, "numChunks",if_num, NO_INDEX,&tmp);    regs->numSndChunks = tmp;    for(i=0;i<regs->numRcvEntries;i++) {      tmp = regs->rcvEntries[i].pAddr;      Simcpt_CptHex(cptd, "rcvpAddr",if_num, i,&tmp);      regs->rcvEntries[i].pAddr = tmp;            tmp = regs->rcvEntries[i].maxLen;      Simcpt_CptHex(cptd, "rcvmaxLen",if_num, i,&tmp);      regs->rcvEntries[i].maxLen = tmp;      tmp = regs->rcvEntries[i].len;      Simcpt_CptHex(cptd, "rcvlen",if_num, i,&tmp);      regs->rcvEntries[i].len = tmp;      tmp = regs->rcvEntries[i].flag;      Simcpt_CptHex(cptd, "rcvflag",if_num, i,&tmp);      regs->rcvEntries[i].flag = tmp;    }    for(i=0;i<regs->numSndEntries;i++) {       tmp = regs->sndEntries[i].firstChunk;      Simcpt_CptHex(cptd, "sndfirst",if_num, i,&tmp);      regs->sndEntries[i].firstChunk = tmp;      tmp = regs->sndEntries[i].lastChunk;      Simcpt_CptHex(cptd, "sndlast",if_num, i,&tmp);      regs->sndEntries[i].lastChunk = tmp;      tmp = regs->sndEntries[i].flag;      Simcpt_CptHex(cptd, "sndflag",if_num, i,&tmp);      regs->sndEntries[i].flag = tmp;    }    for(i=0;i<regs->numSndChunks;i++) {      tmp = regs->sndChunks[i].pAddr;      Simcpt_CptHex(cptd, "chunkspAddr",if_num, i,&tmp);      regs->sndChunks[i].pAddr = tmp;      tmp = regs->sndChunks[i].len;      Simcpt_CptHex(cptd, "chunklen",if_num, i,&tmp);      regs->sndChunks[i].len = tmp;    }                       Simcpt_CptInt(cptd, "ethernum",if_num, NO_INDEX, &(state->ethernum));    ASSERT( state->ethernum == if_num );    /* Formerly placed in the prom checkpoint file */    tmp = regs->intrCPU;    Simcpt_CptUint(cptd, "etherIntrCPU", if_num, NO_INDEX, &tmp);    regs->intrCPU = tmp;          Simcpt_CptInt(cptd, "intrPosted",if_num, NO_INDEX, &(state->intrPosted));    Simcpt_CptInt(cptd,"rcvPtr",if_num, NO_INDEX, &(state->rcvPtr));          for(i=0;i<regs->numSndChunks;i++) {      Simcpt_CptInt(cptd, "chunkOwner",if_num, i,&state->chunkOwner[i]);    }    for(i=0;i<regs->numSndEntries;i++) {      Simcpt_CptInt(cptd, "sndAcks",if_num, i,&state->sndAcks[i]);    }  }  return 0;}static intLocalClusterSendPacket(int cpuNum, int src_if_num,                       struct iovec *iov, int io_len){#ifndef linux    LocalClusterMessage *cmsg;    List_Links *itemPtr;    struct ether_header* etherhdr =  (struct ether_header*)iov[0].iov_base;    unsigned char *destaddr = (unsigned char *)&etherhdr->ether_dhost;    int broadcast = 0;    int if_num, j, len = 0;    SimTime time;    if (!LocalClusterActive)        return 0;/* * Find out if the controller we want is in this simulation. If not, use ethersim, * otherwise determine the interface number we want */        CPUPrint("LOCAL_CLUSTER: cpu %d looking for dest etheraddr = %i:%i:%i:%i:%i:%i\n ",                cpuNum,destaddr[0],destaddr[1],destaddr[2],                destaddr[3],destaddr[4],destaddr[5]);        ASSERT(iov[0].iov_len >= sizeof(struct ether_header));    for (if_num = 0; if_num < numEtherInterfaces; if_num++) {        for (j = 0; j < 6; j++) {            if (destaddr[j] != simetherState[if_num].copy.etheraddr[j]) {                break;            }        }        if (j == 6) break; /* found */    }    if (if_num == numEtherInterfaces) {        for (j = 0; j < 6; j++) {            if (destaddr[j] != 0xff) {                break;            }        }        if (j == 6) {           CPUPrint("LOCAL_CLUSTER: found broadcast address (from interface %d)\n",                     src_if_num);            if_num = src_if_num;   /* Don't send back to me */            broadcast = 1;        } else {            /* Address is not within this simulation */           CPUPrint("LOCAL_CLUSTER: Could not find etheraddr = %i:%i:%i:%i:%i:%i, going through ethersim \n",               destaddr[0],destaddr[1],destaddr[2],               destaddr[3],destaddr[4],destaddr[5]);         return 0; /* can't find the etheraddr */        }          } else {        /* destination is controller if_num */         CPUPrint("LOCAL_CLUSTER: found at contr=%i  etheraddr = %i:%i:%i:%i:%i:%i \n",                   if_num,                   simetherState[if_num].copy.etheraddr[0],                   simetherState[if_num].copy.etheraddr[1],                   simetherState[if_num].copy.etheraddr[2],                   simetherState[if_num].copy.etheraddr[3],                   simetherState[if_num].copy.etheraddr[4],                   simetherState[if_num].copy.etheraddr[5]);     }        /* * Create the event callback */    if (List_IsEmpty(&freeMessageList)) {        CPUWarning("LOCAL_CLUSTER: Ethernet buffer overflowed (increase size or reduce latency)\n");        ASSERT(0);    }    itemPtr = List_First(&freeMessageList);    ASSERT(itemPtr);    List_Remove(itemPtr);    cmsg = LIST_TO_CMSG(itemPtr);    cmsg->if_num = if_num;    cmsg->broadcast = broadcast;    for(j=0;j<io_len;j++) {        bcopy(iov[j].iov_base,cmsg->data+len,iov[j].iov_len);        len += iov[j].iov_len;    }    cmsg->len = len;    /* Simulate DMA time */    time = (NanoSecsToCycles(LOCAL_CLUSTER_DMA_LATENCY) * len) /        SCACHE_LINE_SIZE;    /* Add transfer delay time */    time += NanoSecsToCycles(((SimTime)len * 8000) / LOCAL_CLUSTER_MBIT);    EventDoCallback(cpuNum, LocalClusterMessageArrive,                    (EventCallbackHdr *)cmsg, NULL, time); #else    CPUError("Not ported to linux\n");#endif     return 1;}static voidLocalClusterMessageArrive(int cpuNum, EventCallbackHdr *hdr, void *arg){    LocalClusterMessage *cmsg = (LocalClusterMessage *)hdr;    int i;        ASSERT(cmsg->if_num >= 0 && cmsg->if_num < numEtherInterfaces);        if (cmsg->broadcast) {       /*       CPUPrint("LOCAL_CLUSTER: Broadcast message arrived from %d.\n",                 cmsg->if_num);                 */        for (i = 0; i < numEtherInterfaces; i++) {            if (i != cmsg->if_num) {                SimetherReceivePacket(i, cmsg->data, cmsg->len);            }        }    } else {       /*        CPUWarning("LOCAL_CLUSTER: message arrived at %d from %d.\n",                   cpuNum, cmsg->if_num);                  */       SimetherReceivePacket(cmsg->if_num, cmsg->data, cmsg->len);    }    List_Insert(CMSG_TO_LIST(cmsg), LIST_ATREAR(&freeMessageList));}

⌨️ 快捷键说明

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