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

📄 dev_c7200_mpfpga.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
字号:
/*  * Cisco router simulation platform. * Copyright (c) 2005-2007 Christophe Fillot (cf@utc.fr) * * Cisco c7200 Midplane FPGA. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "cpu.h"#include "vm.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "nmc93cX6.h"#include "dev_c7200.h"#define DEBUG_UNKNOWN  1#define DEBUG_ACCESS   0#define DEBUG_NET_IRQ  0#define DEBUG_OIR      1/* * Definitions for Port Adapter Status. */#define PCI_BAY0_3V_OK    0x00000002      /* IO card 3V */#define PCI_BAY0_5V_OK    0x00000004      /* IO card 5V */#define PCI_BAY1_5V_OK    0x00000200      /* Bay 1 5V */#define PCI_BAY1_3V_OK    0x00000400      /* Bay 1 3V */#define PCI_BAY2_5V_OK    0x00002000      /* Bay 2 5V */#define PCI_BAY2_3V_OK    0x00004000      /* Bay 2 3V */#define PCI_BAY3_5V_OK    0x02000000      /* Bay 3 5V */#define PCI_BAY3_3V_OK    0x04000000      /* Bay 3 3V */#define PCI_BAY4_5V_OK    0x00020000      /* Bay 4 5V */#define PCI_BAY4_3V_OK    0x00040000      /* Bay 4 3V */#define PCI_BAY5_5V_OK    0x20000000      /* Bay 5 5V */#define PCI_BAY5_3V_OK    0x40000000      /* Bay 5 3V */#define PCI_BAY6_5V_OK    0x00200000      /* Bay 6 5V */#define PCI_BAY6_3V_OK    0x00400000      /* Bay 6 3V *//* * Definitions for EEPROM access (slots 0,1,3,4) (0x60) */#define BAY0_EEPROM_SELECT_BIT	 1#define BAY0_EEPROM_CLOCK_BIT	 3#define BAY0_EEPROM_DIN_BIT      4#define BAY0_EEPROM_DOUT_BIT	 6#define BAY1_EEPROM_SELECT_BIT   9#define BAY1_EEPROM_CLOCK_BIT    11#define BAY1_EEPROM_DIN_BIT	 12#define BAY1_EEPROM_DOUT_BIT     14#define BAY3_EEPROM_SELECT_BIT   25#define BAY3_EEPROM_CLOCK_BIT    27#define BAY3_EEPROM_DIN_BIT      28#define BAY3_EEPROM_DOUT_BIT     30#define BAY4_EEPROM_SELECT_BIT   17#define BAY4_EEPROM_CLOCK_BIT    19#define BAY4_EEPROM_DIN_BIT      20#define BAY4_EEPROM_DOUT_BIT     22/* * Definitions for EEPROM access (slots 2,5,6) (0x68) */#define BAY2_EEPROM_SELECT_BIT   9#define BAY2_EEPROM_CLOCK_BIT    11#define BAY2_EEPROM_DIN_BIT      12#define BAY2_EEPROM_DOUT_BIT     14#define BAY5_EEPROM_SELECT_BIT   25#define BAY5_EEPROM_CLOCK_BIT    27#define BAY5_EEPROM_DIN_BIT      28#define BAY5_EEPROM_DOUT_BIT     30#define BAY6_EEPROM_SELECT_BIT   17#define BAY6_EEPROM_CLOCK_BIT    19#define BAY6_EEPROM_DIN_BIT      20#define BAY6_EEPROM_DOUT_BIT     22/* PA Bay EEPROM definitions */static const struct nmc93cX6_eeprom_def eeprom_bay_def[C7200_MAX_PA_BAYS] = {   /* Bay 0 */   { BAY0_EEPROM_CLOCK_BIT , BAY0_EEPROM_SELECT_BIT,     BAY0_EEPROM_DIN_BIT   , BAY0_EEPROM_DOUT_BIT,   },   /* Bay 1 */   { BAY1_EEPROM_CLOCK_BIT , BAY1_EEPROM_SELECT_BIT,     BAY1_EEPROM_DIN_BIT   , BAY1_EEPROM_DOUT_BIT,   },   /* Bay 2 */   { BAY2_EEPROM_CLOCK_BIT , BAY2_EEPROM_SELECT_BIT,     BAY2_EEPROM_DIN_BIT   , BAY2_EEPROM_DOUT_BIT,   },   /* Bay 3 */   { BAY3_EEPROM_CLOCK_BIT , BAY3_EEPROM_SELECT_BIT,     BAY3_EEPROM_DIN_BIT   , BAY3_EEPROM_DOUT_BIT,   },   /* Bay 4 */   { BAY4_EEPROM_CLOCK_BIT , BAY4_EEPROM_SELECT_BIT,     BAY4_EEPROM_DIN_BIT   , BAY4_EEPROM_DOUT_BIT,   },   /* Bay 5 */   { BAY5_EEPROM_CLOCK_BIT , BAY5_EEPROM_SELECT_BIT,     BAY5_EEPROM_DIN_BIT   , BAY5_EEPROM_DOUT_BIT,   },   /* Bay 6 */   { BAY6_EEPROM_CLOCK_BIT , BAY6_EEPROM_SELECT_BIT,     BAY6_EEPROM_DIN_BIT   , BAY6_EEPROM_DOUT_BIT,   },};/* EEPROM group #1 (Bays 0, 1, 3, 4) */static const struct nmc93cX6_group eeprom_bays_g1 = {   EEPROM_TYPE_NMC93C46, 4, 0,    EEPROM_DORD_NORMAL,   EEPROM_DOUT_HIGH,   EEPROM_DEBUG_DISABLED,   "PA Bays (Group #1) EEPROM",    { &eeprom_bay_def[0], &eeprom_bay_def[1],      &eeprom_bay_def[3], &eeprom_bay_def[4],   },};/* EEPROM group #2 (Bays 2, 5, 6) */static const struct nmc93cX6_group eeprom_bays_g2 = {   EEPROM_TYPE_NMC93C46, 3, 0,    EEPROM_DORD_NORMAL,   EEPROM_DOUT_HIGH,   EEPROM_DEBUG_DISABLED,   "PA Bays (Group #2) EEPROM",   { &eeprom_bay_def[2], &eeprom_bay_def[5], &eeprom_bay_def[6] },};/* Network IRQ distribution */struct net_irq_distrib  {   u_int reg;   u_int offset;};static struct net_irq_distrib net_irq_dist[C7200_MAX_PA_BAYS] = {   { 0,  0 },  /* Slot 0: reg 0x10, 0x000000XX */   { 0,  8 },  /* Slot 1: reg 0x10, 0x0000XX00 */   { 1,  8 },  /* Slot 2: reg 0x18, 0x0000XX00 */   { 0, 24 },  /* Slot 3: reg 0x10, 0xXX000000 */   { 0, 16 },  /* Slot 4: reg 0x10, 0x00XX0000 */   { 1, 24 },  /* Slot 5: reg 0x18, 0xXX000000 */   { 1, 16 },  /* Slot 6: reg 0x18, 0x00XX0000 */};/* Midplane FPGA private data */struct c7200_mpfpga_data {   vm_obj_t vm_obj;   struct vdevice dev;   c7200_t *router;   m_uint32_t pa_status_reg;   m_uint32_t pa_ctrl_reg;   m_uint32_t net_irq_status[2];   m_uint32_t net_irq_mask[2];};/* Update network interrupt status */static inline void dev_c7200_mpfpga_net_update_irq(struct c7200_mpfpga_data *d){   int status;   status = (d->net_irq_status[0] & d->net_irq_mask[0]) ||      (d->net_irq_status[1] & d->net_irq_mask[1]);      if (status) {      vm_set_irq(d->router->vm,C7200_NETIO_IRQ);   } else {      vm_clear_irq(d->router->vm,C7200_NETIO_IRQ);   }}/* Trigger a Network IRQ for the specified slot/port */void dev_c7200_mpfpga_net_set_irq(struct c7200_mpfpga_data *d,                                  u_int slot,u_int port){   struct net_irq_distrib *irq_dist;#if DEBUG_NET_IRQ   vm_log(d->router->vm,"MP_FPGA","setting NetIRQ for slot %u port %u\n",          slot,port);#endif   irq_dist = &net_irq_dist[slot];   d->net_irq_status[irq_dist->reg] |= 1 << (irq_dist->offset + port);   dev_c7200_mpfpga_net_update_irq(d);}/* Clear a Network IRQ for the specified slot/port */void dev_c7200_mpfpga_net_clear_irq(struct c7200_mpfpga_data *d,                                    u_int slot,u_int port){   struct net_irq_distrib *irq_dist;#if DEBUG_NET_IRQ   vm_log(d->router->vm,"MP_FPGA","clearing NetIRQ for slot %u port %u\n",          slot,port);#endif   irq_dist = &net_irq_dist[slot];   d->net_irq_status[irq_dist->reg] &= ~(1 << (irq_dist->offset + port));   dev_c7200_mpfpga_net_update_irq(d);}/* Update Port Adapter Status */static void pa_update_status_reg(struct c7200_mpfpga_data *d){   m_uint32_t res = 0;   /* PA Power. Bay 0 is always powered */   res |= PCI_BAY0_5V_OK | PCI_BAY0_3V_OK;   /* We fake power on bays defined by the final user */   if (vm_slot_check_eeprom(d->router->vm,1,0))      res |= PCI_BAY1_5V_OK | PCI_BAY1_3V_OK;      if (vm_slot_check_eeprom(d->router->vm,2,0))      res |= PCI_BAY2_5V_OK | PCI_BAY2_3V_OK;   if (vm_slot_check_eeprom(d->router->vm,3,0))      res |= PCI_BAY3_5V_OK | PCI_BAY3_3V_OK;      if (vm_slot_check_eeprom(d->router->vm,4,0))      res |= PCI_BAY4_5V_OK | PCI_BAY4_3V_OK;   if (vm_slot_check_eeprom(d->router->vm,5,0))      res |= PCI_BAY5_5V_OK | PCI_BAY5_3V_OK;         if (vm_slot_check_eeprom(d->router->vm,6,0))      res |= PCI_BAY6_5V_OK | PCI_BAY6_3V_OK;   d->pa_status_reg = res;}/* * dev_mpfpga_access() */void *dev_c7200_mpfpga_access(cpu_gen_t *cpu,struct vdevice *dev,                              m_uint32_t offset,u_int op_size,u_int op_type,                              m_uint64_t *data){   struct c7200_mpfpga_data *d = dev->priv_data;   if (op_type == MTS_READ)      *data = 0x0;   /* Optimization: this is written regularly */   if (offset == 0x7b)      return NULL;#if DEBUG_ACCESS   if (op_type == MTS_READ) {      cpu_log(cpu,"MP_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",              offset,cpu_get_pc(cpu),op_size);   } else {      cpu_log(cpu,"MP_FPGA",              "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",              offset,cpu_get_pc(cpu),*data,op_size);   }#endif   switch(offset) {      /* Interrupt status for slots 0, 1, 3, 4 */      case 0x10:      case 0x11:      case 0x12:      case 0x13:         if (op_type == MTS_READ)            *data = d->net_irq_status[0];         break;      /* Interrupt status for slots 2, 5, 6 */      case 0x18:      case 0x19:      case 0x1a:      case 0x1b:         if (op_type == MTS_READ)            *data = d->net_irq_status[1];         break;      /* Interrupt mask for slots 0, 1, 3, 4 */      case 0x20:         if (op_type == MTS_READ) {            *data = d->net_irq_mask[0];         } else {            d->net_irq_mask[0] = *data;            dev_c7200_mpfpga_net_update_irq(d);         }         break;      /* Interrupt mask for slots 2, 5, 6 */      case 0x28:         if (op_type == MTS_READ) {            *data = d->net_irq_mask[1];         } else {            d->net_irq_mask[1] = *data;            dev_c7200_mpfpga_net_update_irq(d);         }         break;      /*        * - PCI errors (seen with IRQ 6)       * - Used when PA Mgmt IRQ is triggered.       *        * If the PA Mgmt IRQ is triggered for an undefined slot, a crash       * occurs with "Error: Unexpected NM Interrupt received from slot: 6"       * So, we use the PA status reg as mask to return something safe        * (slot order is identical).       */      case 0x40:         if (op_type == MTS_READ)            *data = 0x66666600 & d->pa_status_reg;         vm_clear_irq(d->router->vm,C7200_PA_MGMT_IRQ);         break;      case 0x48:  /* ??? (test) */         if (op_type == MTS_READ)            *data = 0xFFFFFFFF;         break;      /*        * This corresponds to err_stat in error message when IRQ 6 is        * triggered.       *       * Bit 7 => SRAM error.       * Bits 1-6 => OIR on slot 1-6       */      case 0x70:         if (op_type == MTS_READ) {#if DEBUG_OIR            cpu_log(cpu,"MP_FPGA","reading reg 0x%x at pc=0x%llx, val=0x%x\n",                    offset,cpu_get_pc(cpu),d->router->oir_status);#endif            *data = d->router->oir_status;            vm_clear_irq(d->router->vm,C7200_OIR_IRQ);         } else {#if DEBUG_OIR            cpu_log(cpu,"MP_FPGA","writing reg 0x%x at pc=0x%llx "                    "(data=0x%llx)\n",offset,cpu_get_pc(cpu),*data);#endif            d->router->oir_status &= ~(*data);            vm_clear_irq(d->router->vm,C7200_OIR_IRQ);                             }         break;      /*        * This corresponds to err_enable in error message when IRQ 6 is        * triggered. No idea of what it really means.       */      case 0x78:         if (op_type == MTS_READ) {#if DEBUG_OIR            cpu_log(cpu,"MP_FPGA","reading 0x78 at pc=0x%llx\n",                    cpu_get_pc(cpu));#endif            *data = 0x00;         } else {#if DEBUG_OIR            cpu_log(cpu,"MP_FPGA","writing reg 0x78 at pc=0x%llx "                  "(data=0x%llx)\n",cpu_get_pc(cpu),*data);#endif         }         break;      case 0x38:   /* TDM status */         break;      case 0x50:   /* Port Adapter Status */         if (op_type == MTS_READ) {            pa_update_status_reg(d);            *data = d->pa_status_reg;         }         break;       case 0x58:   /* Port Adapter Control */         if (op_type == MTS_WRITE)            d->pa_ctrl_reg = *data;         else            *data = d->pa_ctrl_reg;         break;      case 0x60:   /* EEPROM for PA in slots 0,1,3,4 */         if (op_type == MTS_WRITE)            nmc93cX6_write(&d->router->pa_eeprom_g1,*data);         else            *data = nmc93cX6_read(&d->router->pa_eeprom_g1);         break;      case 0x68:   /* EEPROM for PA in slots 2,5,6 */         if (op_type == MTS_WRITE)            nmc93cX6_write(&d->router->pa_eeprom_g2,*data);         else            *data = nmc93cX6_read(&d->router->pa_eeprom_g2);         break;      case 0x7b:  /* ??? */         break;#if DEBUG_UNKNOWN      default:         if (op_type == MTS_READ) {            cpu_log(cpu,"MP_FPGA","read from addr 0x%x, pc=0x%llx\n",                    offset,cpu_get_pc(cpu));         } else {            cpu_log(cpu,"MP_FPGA","write to addr 0x%x, value=0x%llx, "                    "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu));         }#endif   }	   return NULL;}/* Initialize EEPROM groups */void c7200_init_mp_eeprom_groups(c7200_t *router){   /* Group 1: bays 0, 1, 3, 4 */   router->pa_eeprom_g1 = eeprom_bays_g1;   router->pa_eeprom_g1.eeprom[0] = NULL;   router->pa_eeprom_g1.eeprom[1] = NULL;   router->pa_eeprom_g1.eeprom[2] = NULL;   router->pa_eeprom_g1.eeprom[3] = NULL;   /* Group 2: bays 2, 5, 6 */   router->pa_eeprom_g2 = eeprom_bays_g2;   router->pa_eeprom_g2.eeprom[0] = NULL;   router->pa_eeprom_g2.eeprom[1] = NULL;   router->pa_eeprom_g2.eeprom[2] = NULL;}/* Shutdown the MP FPGA device */static void dev_c7200_mpfpga_shutdown(vm_instance_t *vm,struct c7200_mpfpga_data *d){   if (d != NULL) {      /* Remove the device */      dev_remove(vm,&d->dev);            /* Free the structure itself */      free(d);   }}/* Create the c7200 Midplane FPGA */int dev_c7200_mpfpga_init(c7200_t *router,m_uint64_t paddr,m_uint32_t len){      struct c7200_mpfpga_data *d;   /* Allocate private data structure */   if (!(d = malloc(sizeof(*d)))) {      fprintf(stderr,"MP_FPGA: out of memory\n");      return(-1);   }   memset(d,0,sizeof(*d));   d->router = router;   vm_object_init(&d->vm_obj);   d->vm_obj.name = "mp_fpga";   d->vm_obj.data = d;   d->vm_obj.shutdown = (vm_shutdown_t)dev_c7200_mpfpga_shutdown;   /* Set device properties */   dev_init(&d->dev);   d->dev.name      = "mp_fpga";   d->dev.phys_addr = paddr;   d->dev.phys_len  = len;   d->dev.handler   = dev_c7200_mpfpga_access;   d->dev.priv_data = d;   /* Map this device to the VM */   vm_bind_device(router->vm,&d->dev);   vm_object_add(router->vm,&d->vm_obj);   return(0);}

⌨️ 快捷键说明

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