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

📄 simmagic.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
     * Writes to this register have no effect.     */      if (BDOOR_IS_LOAD(type)) *datap = (DevRegister)0;       } else if (doff >= offsetof(DevDiskRegisters, k0Addr[0]) &&              doff <= offsetof(DevDiskRegisters,                               k0Addr[DEV_DISK_MAX_DMA_LENGTH-1])) {          int ix = (doff-offsetof(DevDiskRegisters, k0Addr[0])) /         sizeof(DevRegister);      if (BDOOR_IS_LOAD(type)) {         *datap = DISK_SHADOW(node,ctrl,unit).k0Addr[ix];      } else {         DISK_SHADOW(node,ctrl,unit).k0Addr[ix] = *datap;      }       } else if (doff == offsetof(DevDiskRegisters, offset)) {          if (BDOOR_IS_LOAD(type)) {         *datap = DISK_SHADOW(node,ctrl,unit).offset;      } else {         DISK_SHADOW(node,ctrl,unit).offset = *datap;      }       } else if (doff >= offsetof(DevDiskRegisters, command[0]) &&              doff <= offsetof(DevDiskRegisters, command[DEV_DISK_CMD_SIZE-1])) {          int ix = (doff-offsetof(DevDiskRegisters, command[0])) /         sizeof(DevRegister);      if (BDOOR_IS_LOAD(type)) {         *datap = DISK_SHADOW(node,ctrl,unit).command[ix];      } else {         DISK_SHADOW(node,ctrl,unit).command[ix] = *datap;      }       } else if (doff == offsetof(DevDiskRegisters, startIO)) {          unsigned char cmd[SIM_DISK_CMD_SIZE];      PA            pages[SIM_DISK_MAX_DMA_LENGTH];      int           i;          if (BDOOR_IS_LOAD(type)) goto illegal;          /* note: bogus mapping (n,nd) -> SimOS disk #. To be improved */      ASSERT(DEV_DISK_MAX_DMA_LENGTH <= SIM_DISK_MAX_DMA_LENGTH);      ASSERT(DEV_DISK_CMD_SIZE <= SIM_DISK_CMD_SIZE);          for (i = 0; i < SIM_DISK_CMD_SIZE; i++)         cmd[i] = (unsigned char)DISK_SHADOW(node,ctrl,unit).command[i];      for (i = 0; i < SIM_DISK_MAX_DMA_LENGTH; i++)         pages[i] = DISK_SHADOW(node,ctrl,unit).k0Addr[i];          sim_disk_startio(node, ctrl, unit,                       cmd, pages, (int)DISK_SHADOW(node,ctrl,unit).offset);       } else if (doff == offsetof(DevDiskRegisters, doneIO)) {          if (BDOOR_IS_LOAD(type)) goto illegal;      /* write is (almost) a no-op */      DISK_SHADOW(node,ctrl,unit).doneIO = (DevRegister)0;       } else {      /* bad disk offset */      ASSERT(0);      return 0;   }   return 0;  illegal: /* illegal access type */   ASSERT(0);   return 1;}static voiddisk_interrupt(int node, int ctrl, int unit, int on){  int cpu;  /* cpu to which interrupt is directed */  if (inCellMode) {    /* in cell mode (1 machine), node is absolute CPU number.     * Must send interrupt to first CPU of that cell.     */    cpu = (node / CPUS_PER_CELL(0)) * CPUS_PER_CELL(0); /* CPU 0 in cell */  } else {    /* otherwise, node encodes both a machine number and a node.     * Must send interrupt to first CPU in that machine.     */    cpu = FIRST_CPU(M_FROM_CPU(node));  }#if (DEBUG_MAGIC == 1)  LogEntry("disk_interrupt", CPUVec.CurrentCpuNum(),	   "node=%d ctrl=%d unit=%d cpu=%d on=%d\n",	   node, ctrl, unit, cpu, on);#endif  if (on) RaiseSlot(cpu, DEV_PCI_DISK_SLOT);  else    ClearSlot(cpu, DEV_PCI_DISK_SLOT);}/* CONSOLE device. * */static intconsole_handler(int cpuNum, int n, int offs, int type, void* buff){  DevRegister* datap = (DevRegister*)buff;  int        console;  if (inCellMode) {    console = n / CPUS_PER_CELL(0); /* XXX one console / cell */  } else {    console = FIRST_CONSOLE(M_FROM_CPU(cpuNum)) + n;  }#ifdef TORNADO  ASSERT(n == cpuNum);#endif#if (DEBUG_MAGIC == 2) /* consoles are logged only if DEBUG_MAGIC is 2 -- PZ */  LogEntry("console_handler", cpuNum, "console=%d offs=0x%x t=%d data=0x%08x\n",	   console, offs, type, *datap);#endif  /* we only handle DevRegister accesses and buserror all others */  ASSERT (BDOOR_SIZE(type) == sizeof(DevRegister));  switch (offs) {  case offsetof(DevConsoleRegisters, intr_status):     if (BDOOR_IS_LOAD(type)) {        *datap = (DevRegister) sim_console_int_status(console);     } else {        sim_console_int_set(console, (int)*datap);     }     break;  case offsetof(DevConsoleRegisters, data):     if (BDOOR_IS_LOAD(type)) {        *datap = (DevRegister) sim_console_in(console);     } else {        sim_console_out(console, (char)*datap);     }     break;  default: ASSERT(0);  }  return 0;}static voidconsole_interrupt(int n, int on){  int cpu;  if (inCellMode) {     /* always interrupts first CPU in cell */     cpu = n * CPUS_PER_CELL(0);  } else {     cpu = FIRST_CPU(M_FROM_CONSOLE(n));  }#ifdef TORNADO  /* Give to cpu n */  cpu = n;#endif  if (on) RaiseSlot(cpu, DEV_PCI_CONSOLE_SLOT);  else    ClearSlot(cpu, DEV_PCI_CONSOLE_SLOT);}/* ETHERNET device. * */intether_handler(int cpuNum, int n, int offs, int type, void* buff){  DevRegister* datap = (DevRegister*)buff;  int          ctrl;  if (inCellMode) {    ctrl = n / CPUS_PER_CELL(0); /* XXX one console / cell */  } else {    ctrl = FIRST_ETHER_CONTROLLER(M_FROM_CPU(cpuNum)) + n;  }#if (DEBUG_MAGIC == 1)  LogEntry("ether_handler", cpuNum, "ctrl=%d offs=0x%x t=%d data=0x%08x\n",	   ctrl, offs, type, *datap);#endif  /* we only handle dword accesses and buserror all others */  ASSERT (BDOOR_SIZE(type) == sizeof(DevRegister));  /* NOTE: it so "happens" that the SimetherRegisters structure is   * isomorphic to DevEtherRegisters. This helps us simplify the   * mapping from the simulated registers to the ether simulator.   */  if (BDOOR_IS_LOAD(type)) {    *datap = (DevRegister)SimetherIO(ctrl, offs, 0, (DevRegister)0);  } else {    (void)SimetherIO(ctrl, offs, 1, (DevRegister)*datap);  }  return 0;}static voidether_interrupt(int n, int on){  /* always interrupt first cpu in cell */  int cpu;  if (inCellMode) {     cpu = n * CPUS_PER_CELL(0);  } else {     cpu = FIRST_CPU(M_FROM_ETHER_CONTROLLER(n));  }  if (on) RaiseSlot(cpu, DEV_PCI_ETHER_SLOT);  else    ClearSlot(cpu, DEV_PCI_ETHER_SLOT);}/* A fundamental assumption of simether.c is that the DevEtherRegisters * (machine_defs.h) and the SimetherRegisters structures are isomorphic. * We'd better check for this. */static voidcheck_ether_offs(void){  ASSERT(offsetof(DevEtherRegisters, etheraddr[0]) == 	 offsetof(SimetherRegisters, etheraddr[0]));  ASSERT(offsetof(DevEtherRegisters, numRcvEntries) == 	offsetof(SimetherRegisters, numRcvEntries));  ASSERT(offsetof(DevEtherRegisters, numSndEntries) ==	 offsetof(SimetherRegisters, numSndEntries));  ASSERT(offsetof(DevEtherRegisters, numSndChunks) ==	 offsetof(SimetherRegisters, numSndChunks));  ASSERT(offsetof(DevEtherRegisters, rcvEntries[0].pAddr) ==	 offsetof(SimetherRegisters, rcvEntries[0].pAddr));  ASSERT(offsetof(DevEtherRegisters, rcvEntries[0].maxLen) ==	 offsetof(SimetherRegisters, rcvEntries[0].maxLen));  ASSERT(offsetof(DevEtherRegisters, rcvEntries[0].len) ==	 offsetof(SimetherRegisters, rcvEntries[0].len));  ASSERT(offsetof(DevEtherRegisters, rcvEntries[0].flag) ==	 offsetof(SimetherRegisters, rcvEntries[0].flag));  ASSERT(offsetof(DevEtherRegisters, sndEntries[0].firstChunk) ==	 offsetof(SimetherRegisters, sndEntries[0].firstChunk));  ASSERT(offsetof(DevEtherRegisters, sndEntries[0].lastChunk) ==	 offsetof(SimetherRegisters, sndEntries[0].lastChunk));  ASSERT(offsetof(DevEtherRegisters, sndEntries[0].flag) ==	 offsetof(SimetherRegisters, sndEntries[0].flag));  ASSERT(offsetof(DevEtherRegisters, sndChunks[0].pAddr) ==	 offsetof(SimetherRegisters, sndChunks[0].pAddr));  ASSERT(offsetof(DevEtherRegisters, sndChunks[0].len) ==	 offsetof(SimetherRegisters, sndChunks[0].len));}/* CMOS RT clock device. * */static intclock_handler(int cpuNum, int n, int offs, int type, void* buff){  DevRegister* datap = (DevRegister*)buff;  ASSERT (BDOOR_SIZE(type) == sizeof(DevRegister));  if (BDOOR_IS_LOAD(type)) {     int secsSinceStart = CyclesToNanoSecs(CPUVec.CycleCount(cpuNum))/1000000000;    *datap = (DevRegister)(machines.InitialTime + secsSinceStart);  } else {    ASSERT(0); /* for debugging */    return 1;  /* clock register not writable */  }  return 0;}/**************************************************************************** * * MAGIC initialization / registry code * ****************************************************************************/#define VA_NODE(va) (((va) >> __MAGIC_NODE_OFFS) & \		     ((1<<__MAGIC_NODE_BITS)-1))#define VA_ZONE(va) (((va) >> __MAGIC_ZONE_OFFS) & \		     ((1<<__MAGIC_ZONE_BITS)-1))#define VA_REG(va) (((va) >> __MAGIC_REG_OFFS) & \		    ((1<<__MAGIC_REG_BITS)-1))#define VA_GRP(va) (((va) >> __MAGIC_PPC_GRP_OFFS) & \		    ((1<<__MAGIC_PPC_GRP_BITS)-1))#define VA_OPC(va) (((va) >> __MAGIC_PPC_OPC_OFFS) & \		    ((1<<__MAGIC_PPC_OPC_BITS)-1))#define VA_SEQ(va) (((va) >> __MAGIC_PPC_SEQ_OFFS) & \		    ((1<<__MAGIC_PPC_SEQ_BITS)-1))#define VA_OFFS(va) ((va) & ((1<<__MAGIC_ZONE_OFFS)-1))static intFPROM_access(int cpuNum, uint VA, int type, uint* buff){   /* boot prom must be initialized, else this is a bus error */   /* ASSERT(sim_misc.fprom != NULL); */   if (sim_misc.fprom[cpuNum] == NULL) {      return BUSERROR;     }  ASSERT(!USE_MAGIC() || !FPromUseFL);  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_FPROM_ALIAS);  ASSERT(type == BDOOR_LOAD_WORD);  ASSERT(VA_OFFS(VA) < FPROM_SIZE);  *(uint *)buff = *(uint *)(VA_OFFS(VA)+sim_misc.fprom[cpuNum]);  return 0;}static intFRAM_access(int cpuNum, uint VA, int type, uint* buff){  /* boot prom must be initialized */  ASSERT(sim_misc.fprom[cpuNum] != NULL);  ASSERT(!USE_MAGIC() || !FPromUseFL);  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_FRAM_ALIAS);#ifdef LARGE_SIMULATION  if (VA_NODE(VA) == 127) {     /* this is really a fprom access from VA 0xbfc0....  */     return FPROM_access(cpuNum, VA, type, buff);  }#endif  ASSERT(VA_OFFS(VA) < FRAM_SIZE);  switch (type) {  case BDOOR_LOAD_BYTE:     ASSERT(VA_OFFS(VA) < FRAM_SIZE);     *(byte *)buff = *(byte *)(VA_OFFS(VA)+sim_misc.fram[cpuNum]);     break;  case BDOOR_LOAD_HALF:     ASSERT(VA_OFFS(VA) < FRAM_SIZE);     *(unsigned short *)buff = *(unsigned short *)(VA_OFFS(VA)+sim_misc.fram[cpuNum]);     break;  case BDOOR_LOAD_WORD:     ASSERT(VA_OFFS(VA) < FRAM_SIZE);     *(uint *)buff = *(uint *)(VA_OFFS(VA)+sim_misc.fram[cpuNum]);     break;  case BDOOR_LOAD_DOUBLE:     ASSERT(VA_OFFS(VA) < FRAM_SIZE);     *(uint64*)buff = *(uint64*)(VA_OFFS(VA)+sim_misc.fram[cpuNum]);     break;  case BDOOR_STORE_BYTE:     /* also need to check if the fram is writeable during recovery,      but for now this will do... */     ASSERT(VA_OFFS(VA) < FRAM_SIZE);     *(byte *)(VA_OFFS(VA)+sim_misc.fram[cpuNum]) = *(byte *)buff;     break;  case BDOOR_STORE_HALF:     /* also need to check if the fram is writeable during recovery,      but for now this will do... */     ASSERT(VA_OFFS(VA) < FRAM_SIZE);     *(unsigned short *)(VA_OFFS(VA)+sim_misc.fram[cpuNum]) = *(unsigned short *)buff;     break;  case BDOOR_STORE_WORD:     /* also need to check if the fram is writeable during recovery,      but for now this will do... */     ASSERT(VA_OFFS(VA) < FRAM_SIZE);     *(uint *)(VA_OFFS(VA)+sim_misc.fram[cpuNum]) = *(uint *)buff;     break;  case BDOOR_STORE_DOUBLE:     /* also need to check if the fram is writeable during recovery,      but for now this will do... */     ASSERT(VA_OFFS(VA) < FRAM_SIZE);     *(uint64*)(VA_OFFS(VA)+sim_misc.fram[cpuNum]) = *(uint64*)buff;     break;  default:     CPUError("FRAM access is not supported by type %d", type);  }  return 0;}#ifdef SUPPORT_LINUXstatic int MILO_access(int cpuNum, uint VA, int type, void *buff){   ASSERT(VA_ZONE(VA) == MAGIC_ZONE_MILO_ALIAS);   switch (type) {   case BDOOR_LOAD_WORD:     if (!VA_OFFS(VA)) {        *(uint*)buff = sizeof(tagPairs);     } else {        *(uint *)buff = *(uint*)(VA_OFFS(VA)+(uint)&tagPairs-4);     }     CPUWarning("MILO: %x  val=%x \n",		VA_OFFS(VA), *(uint *)buff );		     break;   default:      ASSERT(0);   }   return 0; }#endifstatic intPPRALIAS_access(int cpuNum, uint VA, int type, void* buff){  /* PPR alias: always accesses local node PPR */  ASSERT(!USE_MAGIC());  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_PPR_ALIAS);  return PPR_handler(cpuNum, cpuNum, VA_REG(VA), type, buff);}static intPPCALIAS_access(int cpuNum, uint VA, int type, void* buff){  /* PPC alias: always accesses local node PPC *//* some PPC are not implemented in flashlite, so need to run them   through simmagic even with USE_MAGIC set..    ASSERT(!USE_MAGIC());   */  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_PPC_ALIAS);  return PPC_handler(cpuNum, cpuNum,		     VA_GRP(VA), VA_OPC(VA), VA_SEQ(VA), type, buff);}static intFIREWALL_access(int cpuNum, uint VA, int type, void* buff){  MagicRegister* datap = (MagicRegister*)buff;  int            node  = FIRST_CPU(M_FROM_CPU(cpuNum)) + VA_NODE(VA);  int            pg    = VA_OFFS(VA)/sizeof(MagicRegister);  ASSERT(!USE_MAGIC());

⌨️ 快捷键说明

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