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

📄 dev_nm_16esw.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 5 页
字号:
};/* Return port status (up or down), based on the MII register */static int bcm5600_mii_port_status(struct nm_16esw_data *d,u_int port){   u_int mii_ctrl;   mii_ctrl = d->mii_regs[port][0x00];   /* Isolate bit */   return(!(mii_ctrl & 0x400));}/* Build port status bitmap */static m_uint32_t bcm5600_mii_port_status_bmp(struct nm_16esw_data *d){   m_uint32_t bmp;   int i;      for(i=0,bmp=0;i<d->nr_port;i++)      if (bcm5600_mii_port_status(d,i))         bmp |= 1 << i;   return(bmp);}/* Read a MII register */static void bcm5600_mii_read(struct nm_16esw_data *d){   m_uint8_t port,reg;   port = (d->mii_input >> 16) & 0xFF;   reg  = (d->mii_input >> 24) & 0xFF;   if ((port < 32) && (reg < 32)) {      d->mii_output = d->mii_regs[port][reg];      switch(reg) {         case 0x00:            d->mii_output &= ~0x8200;            break;         case 0x01:            if (d->ports[port].nio && bcm5600_mii_port_status(d,port))               d->mii_output = 0x782C;            else               d->mii_output = 0;            break;         case 0x02:            d->mii_output = 0x40;            break;         case 0x03:            d->mii_output = 0x61d4;            break;         case 0x04:            d->mii_output = 0x1E1;            break;         case 0x05:            d->mii_output = 0x41E1;            break;         default:            d->mii_output = 0;      }   }}/* Write a MII register */static void bcm5600_mii_write(struct nm_16esw_data *d){   m_uint8_t port,reg;   m_uint16_t isolation;   port = (d->mii_input >> 16) & 0xFF;   reg  = (d->mii_input >> 24) & 0xFF;   if ((port < 32) && (reg < 32))   {#if DEBUG_MII      BCM_LOG(d,"MII: port 0x%4.4x, reg 0x%2.2x: writing 0x%4.4x\n",              port,reg,d->mii_input & 0xFFFF);#endif      /* Check if PHY isolation status is changing */      if (reg == 0) {         isolation = (d->mii_input ^ d->mii_regs[port][reg]) & 0x400;         if (isolation) {#if DEBUG_MII            BCM_LOG(d,"MII: port 0x%4.4x: generating IRQ\n",port);#endif            d->mii_intr = TRUE;            pci_dev_trigger_irq(d->vm,d->pci_dev);         }      }            d->mii_regs[port][reg] = d->mii_input & 0xFFFF;   }}/* Hash function for register */static u_int bcm5600_reg_get_hash(m_uint32_t addr){   return((addr ^ (addr >> 16)) & (BCM5600_REG_HASH_SIZE - 1));}/* Find a register entry */static struct bcm5600_reg *bcm5600_reg_find(struct nm_16esw_data *d,                                            m_uint32_t addr){      struct bcm5600_reg *reg;   u_int h_index;   h_index = bcm5600_reg_get_hash(addr);   for(reg=d->reg_hash_table[h_index];reg;reg=reg->next)      if (reg->addr == addr)         return reg;   return NULL;}/* Read a register */static m_uint32_t bcm5600_reg_read(struct nm_16esw_data *d,m_uint32_t addr){   struct bcm5600_reg *reg;   if (!(reg = bcm5600_reg_find(d,addr)))      return(0);   return(reg->value);}/* Write a register */static int bcm5600_reg_write(struct nm_16esw_data *d,m_uint32_t addr,                             m_uint32_t value){   struct bcm5600_reg *reg;   u_int h_index;   if ((reg = bcm5600_reg_find(d,addr))) {      reg->value = value;      return(0);   }   /* create a new register */   if (!(reg = malloc(sizeof(*reg))))      return(-1);   reg->addr  = addr;   reg->value = value;   /* insert new register in hash table */   h_index = bcm5600_reg_get_hash(addr);   reg->next = d->reg_hash_table[h_index];   d->reg_hash_table[h_index] = reg;   return(0);}/* Register special handling */static void bcm5600_reg_write_special(struct nm_16esw_data *d,                                      m_uint32_t addr,m_uint32_t value){   switch(addr) {      case 0x80006:         d->mirror_dst_port = value;         break;      case 0x8000d:         d->mirror_egress_ports = value;         break;      case 0x80009:         /* age timer */         break;   }}/* Free memory used to store register info */static void bcm5600_reg_free(struct nm_16esw_data *d){     struct bcm5600_reg *reg,*next;   int i;   for(i=0;i<BCM5600_REG_HASH_SIZE;i++)      for(reg=d->reg_hash_table[i];reg;reg=next) {         next = reg->next;         free(reg);      }}/* Dump all known registers */static void bcm5600_reg_dump(struct nm_16esw_data *d,int show_null){   struct bcm5600_reg *reg;   int i;   printf("%s: dumping registers:\n",d->name);   for(i=0;i<BCM5600_REG_HASH_SIZE;i++)      for(reg=d->reg_hash_table[i];reg;reg=reg->next) {         if (reg->value || show_null)            printf("  0x%8.8x: 0x%8.8x\n",reg->addr,reg->value);      }}/* Fill a string buffer with all ports of the specified bitmap */static char *bcm5600_port_bitmap_str(struct nm_16esw_data *d,                                     char *buffer,m_uint32_t bitmap){   char *ptr = buffer;   int i;   *ptr = 0;   for(i=0;i<d->nr_port;i++)      if (bitmap & (1 << i)) {         ptr += sprintf(ptr,"%s ",d->ports[i].name);      }   return buffer;}/* BCM5600 tables */#define BCM_OFFSET(x) (OFFSET(struct nm_16esw_data,x))static struct bcm5600_table bcm5600_tables[] = {   /* ARL tables */   { "arlcnt0", BCM_OFFSET(arl_cnt), BCM5600_ADDR_ARLCNT0, 0, 0, 1 },   { "arlcnt1", BCM_OFFSET(arl_cnt), BCM5600_ADDR_ARLCNT1, 0, 0, 1 },   { "arlcnt2", BCM_OFFSET(arl_cnt), BCM5600_ADDR_ARLCNT2, 0, 0, 1 },   /* ARL tables */   { "arl0", BCM_OFFSET(arl_table), BCM5600_ADDR_ARL0, 0, 8191, 3 },   { "arl1", BCM_OFFSET(arl_table), BCM5600_ADDR_ARL1, 0, 8191, 3 },   { "arl2", BCM_OFFSET(arl_table), BCM5600_ADDR_ARL2, 0, 8191, 3 },   /* Multicast ARL tables */   { "marl0", BCM_OFFSET(marl_table), BCM5600_ADDR_MARL0, 1, 255, 5 },   { "marl1", BCM_OFFSET(marl_table), BCM5600_ADDR_MARL1, 1, 255, 5 },   { "marl2", BCM_OFFSET(marl_table), BCM5600_ADDR_MARL2, 1, 255, 5 },   /* PTABLE - Physical Ports */   { "ptable0", BCM_OFFSET(ptable), BCM5600_ADDR_PTABLE0, 0, 31, 6 },   { "ptable1", BCM_OFFSET(ptable), BCM5600_ADDR_PTABLE1, 0, 31, 6 },   { "ptable2", BCM_OFFSET(ptable), BCM5600_ADDR_PTABLE2, 0, 31, 6 },   /* VTABLE - VLANs */   { "vtable0", BCM_OFFSET(vtable), BCM5600_ADDR_VTABLE0, 1, 255, 4 },   { "vtable1", BCM_OFFSET(vtable), BCM5600_ADDR_VTABLE1, 1, 255, 4 },   { "vtable2", BCM_OFFSET(vtable), BCM5600_ADDR_VTABLE2, 1, 255, 4 },   /* TTR */   { "ttr0", BCM_OFFSET(ttr), BCM5600_ADDR_TTR0, 0, 5, 3 },   { "ttr1", BCM_OFFSET(ttr), BCM5600_ADDR_TTR1, 0, 5, 3 },   { "ttr2", BCM_OFFSET(ttr), BCM5600_ADDR_TTR2, 0, 5, 3 },   /* TBMAP */   { "tbmap0", BCM_OFFSET(tbmap), BCM5600_ADDR_TBMAP0, 0, 5, 1 },   { "tbmap1", BCM_OFFSET(tbmap), BCM5600_ADDR_TBMAP1, 0, 5, 1 },   { "tbmap2", BCM_OFFSET(tbmap), BCM5600_ADDR_TBMAP2, 0, 5, 1 },   { NULL, -1, 0, 0, 0 },};/* Get table size (in number of words) */static inline u_int bcm5600_table_get_size(struct bcm5600_table *table){   return(table->nr_words * (table->max_index + 1));}/* Create automatically tables */static int bcm5600_table_create(struct nm_16esw_data *d){   struct bcm5600_table *table;   m_uint32_t *array;   size_t nr_words;   int i;   for(i=0;bcm5600_tables[i].name;i++)   {      table = &bcm5600_tables[i];      nr_words = bcm5600_table_get_size(table);      if (!(array = calloc(nr_words,sizeof(m_uint32_t)))) {         fprintf(stderr,"BCM5600: unable to create table '%s'\n",table->name);         return(-1);      }               *(PTR_ADJUST(m_uint32_t **,d,table->offset)) = array;   }   return(0);}/* Free tables */static void bcm5600_table_free(struct nm_16esw_data *d){   struct bcm5600_table *table;   m_uint32_t **array;   int i;   for(i=0;bcm5600_tables[i].name;i++) {      table = &bcm5600_tables[i];      array = (PTR_ADJUST(m_uint32_t **,d,table->offset));      free(*array);            /* avoid freeing the same table multiple times */      *array = NULL;   }}/* Find a table given its address */static struct bcm5600_table *bcm5600_table_find(struct nm_16esw_data *d,                                                m_uint32_t addr){   int i;   for(i=0;bcm5600_tables[i].name;i++)      if (bcm5600_tables[i].addr == addr)         return(&bcm5600_tables[i]);#if DEBUG_UNKNOWN   BCM_LOG(d,"unknown table at address 0x%8.8x\n",addr);#endif   return NULL;}/* Get a table entry */static inline m_uint32_t *bcm5600_table_get_entry(struct nm_16esw_data *d,                                                  struct bcm5600_table *table,                                                  m_uint32_t index){   m_uint32_t *array;   if ((index < table->min_index) || (index > table->max_index))      return NULL;   array = *(PTR_ADJUST(m_uint32_t **,d,table->offset));   return(&array[index*table->nr_words]);}/* Read a table entry */static int bcm5600_table_read_entry(struct nm_16esw_data *d){   struct bcm5600_table *table;   m_uint32_t addr,index,*entry;   int i;   addr  = d->dw[1] & 0xFFFF0000;   index = d->dw[1] & 0x0000FFFF;   if (!(table = bcm5600_table_find(d,addr))) {#if DEBUG_UNKNOWN      BCM_LOG(d,"unknown mem address at address 0x%8.8x\n",d->dw[1]);#endif      return(-1);   }   if (!(entry = bcm5600_table_get_entry(d,table,index)))      return(-1);#if DEBUG_MEM   BCM_LOG(d,"READ_MEM: addr=0x%8.8x (table %s)\n",d->dw[1],table->name);#endif   for(i=0;i<table->nr_words;i++)      d->dw[i+1] = entry[i];   return(0);}/* Write a table entry */static int bcm5600_table_write_entry(struct nm_16esw_data *d){   struct bcm5600_table *table;   m_uint32_t addr,index,*entry;   int i;   addr  = d->dw[1] & 0xFFFF0000;   index = d->dw[1] & 0x0000FFFF;   if (!(table = bcm5600_table_find(d,addr)))      return(-1);   if (!(entry = bcm5600_table_get_entry(d,table,index)))      return(-1);   for(i=0;i<table->nr_words;i++)      entry[i] = d->dw[i+2];#if DEBUG_MEM   {      char buffer[512],*ptr = buffer;      for(i=0;i<table->nr_words;i++)         ptr += sprintf(ptr,"data[%d]=0x%8.8x ",i,entry[i]);      BCM_LOG(d,"WRITE_MEM: addr=0x%8.8x (table %s) %s\n",              d->dw[1],table->name,buffer);   }#endif   return(0);}/* Dump a table (for debugging) */static int bcm5600_table_dump(struct nm_16esw_data *d,m_uint32_t addr){   struct bcm5600_table *table;   m_uint32_t *entry;   int i,j;   if (!(table = bcm5600_table_find(d,addr)))      return(-1);   printf("%s: dumping table \"%s\":\n",d->name,table->name);   for(i=table->min_index;i<=table->max_index;i++) {      if (!(entry = bcm5600_table_get_entry(d,table,i)))         break;      printf("  %4d:",i);      for(j=0;j<table->nr_words;j++)         printf("0x%8.8x ",entry[j]);      printf("\n");   }   printf("\n");   return(0);}/* Dump the VLAN table */static int bcm5600_dump_vtable(struct nm_16esw_data *d){      struct bcm5600_table *table;   struct bcm5600_port *port;   m_uint32_t *entry,tbmp,ubmp;   u_int vlan;   int i,j;   if (!(table = bcm5600_table_find(d,BCM5600_ADDR_VTABLE0)))      return(-1);   printf("%s: dumping VLAN table:\n",d->name);   for(i=table->min_index;i<=table->max_index;i++) {      if (!(entry = bcm5600_table_get_entry(d,table,i)))         break;      /* Extract the VLAN info */      vlan = entry[0] & BCM5600_VTABLE_VLAN_TAG_MASK;      if (vlan == VLAN_INVALID)         continue;      printf("  VLAN %4u: ",vlan);      for(j=0;j<d->nr_port;j++) {         tbmp = entry[1] & (1 << j);         ubmp = entry[2] & (1 << j);         if (tbmp || ubmp) {            port = &d->ports[j];            printf("%s (",port->name);            if (tbmp)                printf("T%s",ubmp ? "/" : ") ");            if (ubmp)               printf("UT) ");         }

⌨️ 快捷键说明

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