📄 ethernet.c
字号:
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 *)ðerhdr->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 + -