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

📄 ethernet.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * *//***************************************************************** * ethernet.c - Routines to simulate an ethernet device. * * Ethernet interface emulation. * Created by: Ed Bugnion * Revised by: Dan Teodosiu, 07/96 * * NOTES: * This interface writes the data directly to memory (and doesn't * care about coherence). Should be changed to use DMA. * * Last modified by: $Author: bosch $ *****************************************************************/#include <stdio.h>#include <sys/types.h>#ifdef __alpha#include <sys/ioctl.h>#else#ifndef i386#include <sys/unistd.h>#endif#endif#ifdef i386#include <sys/ioctl.h>#endif#include <sys/mman.h>#include <sys/file.h>#include <sys/signal.h>#ifndef __alpha#ifndef linux#include <sys/ioccom.h>#include <sys/filio.h>#endif#endif#include <sys/time.h>#include <unistd.h>#include <string.h>#include <sys/socket.h>#include <net/if.h>#include <errno.h>#include <netinet/in.h>#include <stddef.h>#include <stdlib.h>#include <netdb.h>#ifndef linux#include <sys/uio.h>#include <netinet/if_ether.h>#include <poll.h>#endif#include "syslimits.h"#include "simtypes.h"#include "ethernet.h"#include "sim.h"#include "sim_error.h"#include "simutil.h"#include "cpu_interface.h"#include "checkpoint.h"#include "../../devices/network/cluster.h"#include "machine_params.h"#include "arch_specifics.h"#include "eventcallback.h"#include "list.h"#ifdef VCS_FAKE#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>void VcsFakeInit(void);#endifstatic int SimetherCheckpointCB(CptDescriptor *cptd);/* * Seems to be a bug in the SGI offsetof() at 6.2 */#if defined(sgi) && defined(_COMPILER_VERSION) && (_COMPILER_VERSION >= 400)#undef offsetof#define offsetof(s, m)  (size_t)(&(((s *)0)->m))#endif/********************************************************************** * offset computation **********************************************************************/static int simetherIndex[sizeof(SimetherRegisters)];typedef enum {  NONE,ETHER_ADDR,   NUM_RCV,NUM_SND,NUM_CHUNKS,  INTR_CPU,  RCV_ADDR, RCV_MAXLEN,RCV_LEN,RCV_FLAG,  SND_FIRST,SND_LAST,SND_FLAG,  CHUNK_ADDR, CHUNK_LEN} RegisterNames ;char* simetherRegisterNamesStr[] = {    "none","ether_addr",   "num_rcv","num_snd","num_chunk",   "intr_cpu",    "rcv_addr", "rcv_maxLen","rcv_len", "rcv_flag",   "snd_first", "snd_last", "snd_flag",   "chunk_addr", "chunk_len" };static RegisterNames simetherOffset[sizeof(SimetherRegisters)];static voidSimetherAddEntry(int offset, RegisterNames n, int index){   simetherOffset[offset] = n;   simetherIndex[offset] = index;}#define ADD_ENTRY(_f,_n,_i) \    SimetherAddEntry(offsetof(SimetherRegisters,_f),_n,_i)static void SimetherOffsetsInit(void){   int i;   for(i=0;i<sizeof(SimetherRegisters);i++) {      simetherOffset[i] = NONE;      simetherIndex[i] = -1;   }   for(i=0;i<6;i++) {       ADD_ENTRY(etheraddr[i],ETHER_ADDR,i);   }   ADD_ENTRY(intrCPU,INTR_CPU,0);   ADD_ENTRY(numRcvEntries,NUM_RCV,0);   ADD_ENTRY(numSndEntries,NUM_SND,0);   ADD_ENTRY(numSndChunks,NUM_CHUNKS,0);   for(i=0;i<ETHER_MAX_RCV_ENTRIES; i++) {      ADD_ENTRY(rcvEntries[i].pAddr,RCV_ADDR,i);      ADD_ENTRY(rcvEntries[i].maxLen,RCV_MAXLEN,i);      ADD_ENTRY(rcvEntries[i].len,RCV_LEN,i);      ADD_ENTRY(rcvEntries[i].flag,RCV_FLAG,i);   }   for(i=0;i<ETHER_MAX_SND_ENTRIES;i++) {       ADD_ENTRY(sndEntries[i].firstChunk,SND_FIRST,i);      ADD_ENTRY(sndEntries[i].lastChunk,SND_LAST,i);      ADD_ENTRY(sndEntries[i].flag,SND_FLAG,i);   }   for( i=0;i<ETHER_MAX_SND_CHUNKS;i++) {      ADD_ENTRY(sndChunks[i].pAddr,CHUNK_ADDR,i);      ADD_ENTRY(sndChunks[i].len,CHUNK_LEN,i);   }}/*************************************************************************** *  * local cluster structures * ***************************************************************************/#define USE_LOCAL_CLUSTER 1#define LOCAL_CLUSTER_DMA_LATENCY 300 /* Nanoseconds per cache-line */#define LOCAL_CLUSTER_MBIT 10 /* Megabit-per-second */#define LOCAL_CLUSTER_MAX_MSGS 1024/* If broadcast is 0, if_num is the interface to send to. *//* If broadcast is 1, if_num is the only interface not to send to. */typedef struct LocalClusterMessage {    EventCallbackHdr hdr;    List_Links link;    int if_num;    int broadcast;    int len;    char data[SIMETHER_MAX_TRANSFER_SIZE];} LocalClusterMessage;#define CMSG_TO_LIST(_m) (&((_m)->link))#define LIST_TO_CMSG(_l) ((LocalClusterMessage *) (((char *)(_l)) - sizeof(EventCallbackHdr)))static int LocalClusterActive = 0;static LocalClusterMessage messageStorage[LOCAL_CLUSTER_MAX_MSGS];/* List of available LocalClusterMessage structures */static List_Links freeMessageList;static int LocalClusterSendPacket(int cpuNum, int src_if_num,                                  struct iovec *iov, int io_len);static void LocalClusterMessageArrive(int cpuNum, EventCallbackHdr *hdr,                                      void *arg);/*************************************************************************** *  * simether internals * ***************************************************************************/static int disableEthernet = 0;static int numEtherInterfaces = 0;typedef struct SimetherState {    /*  ethersim/ UPD related  stuff */   int fd;   struct sockaddr_in  toaddr;  /* Address of ethernet simulator  process. */   int  toaddrlen;     /* Length of the address. */   int  ethernum;   int  machine;       /* Machine that this controller is on */   /* ethersim/cluster synchronization */   char rcvLock[128];   /* Interaction with the interrupt architecture */   int intrPosted;   EtherIntFunc int_f; /* function to call for raising/clearing an int */       /* Ring buffer managment */   int rcvPtr;   int chunkOwner[ETHER_MAX_SND_CHUNKS];   int sndAcks[ETHER_MAX_SND_ENTRIES];   /* Kernel-visible state (through uncached accesses */   SimetherRegisters copy;} SimetherState;static SimetherState* simetherState = 0;/* parameters */char *EthersimHostname;char *EtherAddress;int   EtherSendPort;int   RestoreEthernet;intSimetherInit(int restore, EtherIntFunc int_f){   SimetherState *state;    extern int errno;   struct sockaddr_in sin;   struct hostent *host;   int if_num;   int tmp[6];   int on,i;   /* Initialize each configured board */   SimetherOffsetsInit();   if (!RestoreEthernet) {      disableEthernet = 1;   }   Simcpt_Register("ether", SimetherCheckpointCB, ALL_CPUS);   if (restore) {      Simcpt_Restore("ether");   } else {       numEtherInterfaces = TOTAL_ETHER_CONTROLLERS;      simetherState = (SimetherState *)         ZMALLOC(sizeof(SimetherState)*numEtherInterfaces,"SimetherState");   }   if ((numEtherInterfaces > 1) && USE_LOCAL_CLUSTER) {       ASSERT(!LocalClusterActive);       LocalClusterActive = 1;       List_Init(&freeMessageList);       for (i = 0; i < LOCAL_CLUSTER_MAX_MSGS; i++) {           LocalClusterMessage *cmsg = messageStorage + i;           bzero((char *) (cmsg), sizeof(messageStorage[0]));           List_InitElement(CMSG_TO_LIST(cmsg));           List_Insert(CMSG_TO_LIST(cmsg), LIST_ATREAR(&freeMessageList));       }   }   for (if_num=0; if_num<numEtherInterfaces; if_num++) {          int j, machine;      state  = simetherState + if_num;      state->ethernum = if_num;      for (machine = 0; machine < NUM_MACHINES; machine++) {          if ((FIRST_ETHER_CONTROLLER(machine) <= if_num) &&              (LAST_ETHER_CONTROLLER(machine) >= if_num)) {              state->machine = machine;              break;          }      }      /*        * hardcoded values for now        */      if (!restore) {          state->copy.numRcvEntries = 16;         state->copy.numSndEntries = ETHER_MAX_SND_ENTRIES;         state->copy.numSndChunks  = ETHER_MAX_SND_CHUNKS;         for(j=0;j<state->copy.numRcvEntries;j++)            state->copy.rcvEntries[j].flag = OS_OWNED;         for(j=0;j<state->copy.numSndEntries;j++) {             state->copy.sndEntries[j].flag = OS_OWNED;            state->sndAcks[j] = 1;         }         for(j=0;j<state->copy.numSndChunks;j++)             state->chunkOwner[j] = OS_OWNED;      }      /*       * Create the UDP socket that will be used to send and receive packets`       * to and from the simulator.       */      if( disableEthernet ) {         state->fd = -1;         if( sscanf(EtherAddress,"%i:%i:%i:%i:%i:%i",                    &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5])!=6) {            CPUError("Simether: Parsing of '%'s failed \n", EtherAddress);         }         for(i=0;i<5;++i)            state->copy.etheraddr[i] = tmp[i];         state->copy.etheraddr[5] = if_num + tmp[5];	 state->int_f = int_f;      } else {         state->fd = socket(AF_INET, SOCK_DGRAM, 0);         if (state->fd < 0) {            perror("Simether_init:socket");            return -1;         }         bzero((char *)&sin, sizeof (sin));         sin.sin_port = htons(0);         sin.sin_family = AF_INET;         if (bind(state->fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) {            perror("Simether_init:bind");            return -1;         }          on = 1;         if (ioctl(state->fd, FIONBIO, &on) < 0) {            perror("Simether_init: FIOBIO");         }	                     host = gethostbyname(EthersimHostname);         if (!host) {            Sim_Warning("EthersimHostname : %s\n", EthersimHostname);            perror("Simether_init:gethostbyname EthersimHostname");            return -1;         }         state->toaddr.sin_family = host->h_addrtype;         bcopy(host->h_addr, (char*)&state->toaddr.sin_addr, host->h_length);         state->toaddr.sin_port = htons(EtherSendPort);         state->toaddrlen = sizeof(state->toaddr);         if( !restore )	    /* note: this is currently unused */            state->copy.intrCPU = SIM_MAXCPUS;         if( sscanf(EtherAddress,"%i:%i:%i:%i:%i:%i",                    &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5])!=6) {            CPUError("Simether: Parsing of '%'s failed \n", EtherAddress);         }         for(i=0;i<5;++i)            state->copy.etheraddr[i] = tmp[i];         state->copy.etheraddr[5] = if_num + tmp[5];	 state->int_f = int_f;      }   }   #ifdef VCS_FAKE   VcsFakeInit();#endif       return 0;}voidSimetherPoll(void){#ifndef linux   static struct pollfd fds[ETHER_MAX_CONTROLLERS];   SimetherState *state;    int i;   for (i=0; i < numEtherInterfaces; i++) {     state  = &simetherState[i];     ASSERT(state->fd != 0);     fds[i].fd = state->fd;     fds[i].events = POLLRDNORM;     fds[i].revents = 0;   }   poll(fds, numEtherInterfaces, 0);   for (i = 0; i < numEtherInterfaces; i++) {      SIM_DEBUG(('i', "SimetherPoll fd: 0x%x  events: 0x%x  revents: 0x%x\n",                 fds[i].fd, fds[i].events, fds[i].revents));   }      for(i = 0; i < numEtherInterfaces; i++)     if (fds[i].revents & POLLRDNORM) SimetherReceivePacket( i, 0 , 0 ) ;#else  Sim_Warning("Uh oh... SimetherPoll called\n");#endif}void SimetherInitCluster(void){   int i, j;   char etheraddr[6];   for (i = 0; i < numEtherInterfaces; i++) {     for (j = 0; j < 6; j++) etheraddr[j] = simetherState[i].copy.etheraddr[j];     ClusterSetEtherAddr(etheraddr, i);   }}char* SimetherAddr(int iface_num) {   static char etheraddr[6];   int i;   for (i = 0; i < 6; i++)     etheraddr[i] = simetherState[iface_num].copy.etheraddr[i];   return etheraddr;}static void SimetherClearSlot(SimetherState *state) {  int i;  SimetherRegisters *regs = &state->copy;  for(i=0;i<state->copy.numRcvEntries;i++) {     if( regs->rcvEntries[i].flag == OS_OWNED )       return;

⌨️ 快捷键说明

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