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

📄 dev_gt.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 4 页
字号:
            }            /* Abort RX DMA */            if (*data & GT_SDCMR_AR)               port->sdcmr &= ~GT_SDCMR_ERD;            /* Start TX High */            if (*data & GT_SDCMR_TXDH) {               port->sdcmr |= GT_SDCMR_TXDH;               port->sdcmr &= ~GT_SDCMR_STDH;            }            /* Start TX Low */            if (*data & GT_SDCMR_TXDL) {               port->sdcmr |= GT_SDCMR_TXDL;               port->sdcmr &= ~GT_SDCMR_STDL;            }            /* Stop TX High */            if (*data & GT_SDCMR_STDH) {               port->sdcmr &= ~GT_SDCMR_TXDH;               port->sdcmr |= GT_SDCMR_STDH;            }            /* Stop TX Low */            if (*data & GT_SDCMR_STDL) {               port->sdcmr &= ~GT_SDCMR_TXDL;               port->sdcmr |= GT_SDCMR_STDL;            }         } else {            *data = port->sdcmr;         }         break;      case 0x85800:      case 0x89800:         if (op_type == MTS_READ) {            *data = port->rx_bytes;            port->rx_bytes = 0;         }         break;      case 0x85804:      case 0x89804:         if (op_type == MTS_READ) {            *data = port->tx_bytes;            port->tx_bytes = 0;         }         break;      case 0x85808:      case 0x89808:         if (op_type == MTS_READ) {            *data = port->rx_frames;            port->rx_frames = 0;         }         break;      case 0x8580C:      case 0x8980C:         if (op_type == MTS_READ) {            *data = port->tx_frames;            port->tx_frames = 0;         }         break;#if DEBUG_UNKNOWN      default:         if (op_type == MTS_READ) {            cpu_log(cpu,"GT96100/ETH",                    "read access to unknown register 0x%x, pc=0x%llx\n",                    offset,cpu->pc);         } else {            cpu_log(cpu,"GT96100/ETH",                    "write access to unknown register 0x%x, value=0x%llx, "                    "pc=0x%llx\n",offset,*data,cpu->pc);         }#endif   }   if (op_type == MTS_READ)      *data = swap32(*data);   return(TRUE);}/* * dev_gt96100_access() */void *dev_gt96100_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset,                         u_int op_size,u_int op_type,m_uint64_t *data){   struct gt_data *gt_data = dev->priv_data;      if (op_type == MTS_READ)      *data = 0;   if (gt_dma_access(cpu,dev,offset,op_size,op_type,data) != 0)      return NULL;   if (gt_eth_access(cpu,dev,offset,op_size,op_type,data) != 0)      return NULL;   switch(offset) {      /* Watchdog configuration register */      case 0x101a80:         break;               /* Watchdog value register */      case 0x101a84:         break;      case 0x008:    /* ras10_low */         if (op_type == MTS_READ)            *data = swap32(0x000);         break;      case 0x010:    /* ras10_high */         if (op_type == MTS_READ)            *data = swap32(0x7F);         break;      case 0x018:    /* ras32_low */         if (op_type == MTS_READ)            *data = swap32(0x100);         break;      case 0x020:    /* ras32_high */         if (op_type == MTS_READ)            *data = swap32(0x7F);         break;      case 0x400:    /* ras0_low */         if (op_type == MTS_READ)            *data = swap32(0x00);         break;      case 0x404:    /* ras0_high */         if (op_type == MTS_READ)            *data = swap32(0xFF);         break;      case 0x408:    /* ras1_low */         if (op_type == MTS_READ)            *data = swap32(0x7F);         break;      case 0x40c:    /* ras1_high */         if (op_type == MTS_READ)            *data = swap32(0x00);         break;      case 0x410:    /* ras2_low */         if (op_type == MTS_READ)            *data = swap32(0x00);         break;      case 0x414:    /* ras2_high */         if (op_type == MTS_READ)            *data = swap32(0xFF);         break;      case 0x418:    /* ras3_low */         if (op_type == MTS_READ)            *data = swap32(0x7F);         break;      case 0x41c:    /* ras3_high */         if (op_type == MTS_READ)            *data = swap32(0x00);         break;      case 0xc08:    /* pci0_cs10 */         if (op_type == MTS_READ)            *data = swap32(0xFFF);         break;      case 0xc0c:    /* pci0_cs32 */         if (op_type == MTS_READ)            *data = swap32(0xFFF);         break;      case 0xc00:    /* pci_cmd */         if (op_type == MTS_READ)            *data = swap32(0x00008001);         break;      /* ===== Interrupt Main Cause Register ===== */      case 0xc18:         if (op_type == MTS_READ) {            *data = gt_data->int_cause_reg;                     /* TODO: signal Eth0/Eth1 */            //*data |= (1 << 30) | (1 << 31) | 1;            *data = swap32(*data);         } else {            gt_data->int_cause_reg &= swap32(*data);            gt_update_irq_status(gt_data);         }         break;      /* ===== Interrupt Mask Register ===== */      case 0xc1c:         if (op_type == MTS_READ) {            *data = swap32(gt_data->int_mask_reg);         } else {            gt_data->int_mask_reg = swap32(*data);            gt_update_irq_status(gt_data);         }         break;      /* ===== Interrupt High Cause Register ===== */      case 0xc98:         if (op_type == MTS_READ) {            *data = 0;            /* interrupt on ethernet port 0 ? */            if (gt_data->eth_ports[0].icr & GT_ICR_INT_SUM)               *data |= GT_IHCR_ETH0_SUM;            /* interrupt on ethernet port 1 ? */            if (gt_data->eth_ports[1].icr & GT_ICR_INT_SUM)               *data |= GT_IHCR_ETH1_SUM;            *data = swap32(*data);         }         break;      /* Serial Cause Register */      case 0x103a00:         if (op_type == MTS_READ) {            *data = 0;            /* interrupt on ethernet port 0 ? */            if (gt_data->eth_ports[0].icr & GT_ICR_INT_SUM)               *data |= GT_SCR_ETH0_SUM;            /* interrupt on ethernet port 1 ? */            if (gt_data->eth_ports[1].icr & GT_ICR_INT_SUM)               *data |= GT_SCR_ETH1_SUM;            *data = swap32(*data);         }         break;      /* ===== PCI Bus 1 ===== */      case 0xcf0:         pci_dev_addr_handler(cpu,gt_data->bus[1],op_type,TRUE,data);         break;      case 0xcf4:         pci_dev_data_handler(cpu,gt_data->bus[1],op_type,TRUE,data);         break;               /* ===== PCI Bus 0 ===== */      case PCI_BUS_ADDR:    /* pci configuration address (0xcf8) */         pci_dev_addr_handler(cpu,gt_data->bus[0],op_type,TRUE,data);         break;      case PCI_BUS_DATA:    /* pci data address (0xcfc) */         pci_dev_data_handler(cpu,gt_data->bus[0],op_type,TRUE,data);         break;#if DEBUG_UNKNOWN      default:         if (op_type == MTS_READ) {            cpu_log(cpu,"GT96100","read from addr 0x%x, pc=0x%llx\n",                    offset,cpu->pc);         } else {            cpu_log(cpu,"GT96100","write to addr 0x%x, value=0x%llx, "                    "pc=0x%llx\n",offset,*data,cpu->pc);         }#endif   }   return NULL;}/* Read an Ethernet descriptor */static void gt_eth_desc_read(struct gt_data *d,m_uint32_t addr,                             struct eth_desc *desc){   physmem_copy_from_vm(d->vm,desc,addr,sizeof(struct eth_desc));      /* byte-swapping */   desc->cmd_stat = vmtoh32(desc->cmd_stat);   desc->buf_size = vmtoh32(desc->buf_size);   desc->next_ptr = vmtoh32(desc->next_ptr);   desc->buf_ptr  = vmtoh32(desc->buf_ptr);}/* Write an Ethernet descriptor */static void gt_eth_desc_write(struct gt_data *d,m_uint32_t addr,                              struct eth_desc *desc){   struct eth_desc tmp;      /* byte-swapping */   tmp.cmd_stat = vmtoh32(desc->cmd_stat);   tmp.buf_size = vmtoh32(desc->buf_size);   tmp.next_ptr = vmtoh32(desc->next_ptr);   tmp.buf_ptr  = vmtoh32(desc->buf_ptr);   physmem_copy_to_vm(d->vm,&tmp,addr,sizeof(struct eth_desc));}/* Handle a TX queue (single packet) */static int gt_eth_handle_txqueue(struct gt_data *d,struct eth_port *port,                                 int queue){      u_char pkt[GT_MAX_PKT_SIZE],*pkt_ptr;   struct eth_desc txd0,ctxd,*ptxd;   m_uint32_t tx_start,tx_current;   m_uint32_t len,tot_len;   int abort = FALSE;   /* Check if this TX queue is active */   if ((queue == 0) && (port->sdcmr & GT_SDCMR_STDL))      return(FALSE);   if ((queue == 1) && (port->sdcmr & GT_SDCMR_STDH))      return(FALSE);   /* Copy the current txring descriptor */   tx_start = tx_current = port->tx_current[queue];   if (!tx_start)      goto done;   ptxd = &txd0;   gt_eth_desc_read(d,tx_start,ptxd);   /* If we don't own the first descriptor, we cannot transmit */   if (!(txd0.cmd_stat & GT_TXDESC_OWN))      goto done;   /* Empty packet for now */   pkt_ptr = pkt;   tot_len = 0;   for(;;) {#if DEBUG_ETH_TX      GT_LOG(d,"gt_eth_handle_txqueue: loop: "             "cmd_stat=0x%x, buf_size=0x%x, next_ptr=0x%x, buf_ptr=0x%x\n",             ptxd->cmd_stat,ptxd->buf_size,ptxd->next_ptr,ptxd->buf_ptr);#endif      if (!(ptxd->cmd_stat & GT_TXDESC_OWN)) {         GT_LOG(d,"gt_eth_handle_txqueue: descriptor not owned!\n");         abort = TRUE;         break;      }      /* Copy packet data to the buffer */      len = (ptxd->buf_size & GT_TXDESC_BC_MASK) >> GT_TXDESC_BC_SHIFT;      physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->buf_ptr,len);      pkt_ptr += len;      tot_len += len;      /* Clear the OWN bit if this is not the first descriptor */      if (!(ptxd->cmd_stat & GT_TXDESC_F)) {         ptxd->cmd_stat &= ~GT_TXDESC_OWN;         physmem_copy_u32_to_vm(d->vm,tx_current,ptxd->cmd_stat);      }      tx_current = ptxd->next_ptr;      /* Last descriptor or no more desc available ? */      if (ptxd->cmd_stat & GT_TXDESC_L)         break;      if (!tx_current) {         abort = TRUE;         break;      }      /* Fetch the next descriptor */      gt_eth_desc_read(d,tx_current,&ctxd);      ptxd = &ctxd;   }   if ((tot_len != 0) && !abort) {#if DEBUG_ETH_TX      GT_LOG(d,"Ethernet: sending packet of %u bytes\n",tot_len);      mem_dump(log_file,pkt,tot_len);#endif      /* send it on wire */      netio_send(port->nio,pkt,tot_len);      /* Update MIB counters */      port->tx_bytes += tot_len;      port->tx_frames++;   }   /* Clear the OWN flag of the first descriptor */   txd0.cmd_stat &= ~GT_TXDESC_OWN;   physmem_copy_u32_to_vm(d->vm,tx_start+4,txd0.cmd_stat);   port->tx_current[queue] = tx_current;      /* Notify host about transmitted packet */   if (queue == 0)      port->icr |= GT_ICR_TXBUFL;   else      port->icr |= GT_ICR_TXBUFH; done:   if (abort) {      /* TX underrun */      port->icr |= GT_ICR_TXUDR;      if (queue == 0)         port->icr |= GT_ICR_TXERRL;      else         port->icr |= GT_ICR_TXERRH;   } else {      /* End of queue has been reached */      if (!tx_current) {         if (queue == 0)            port->icr |= GT_ICR_TXENDL;         else            port->icr |= GT_ICR_TXENDH;      }   }   /* Update the interrupt status */   gt_eth_update_int_status(d,port);    return(TRUE);}/* Handle TX ring of the specified port */static void gt_eth_handle_port_txqueues(struct gt_data *d,u_int port){   gt_eth_handle_txqueue(d,&d->eth_ports[port],0);  /* TX Low */   gt_eth_handle_txqueue(d,&d->eth_ports[port],1);  /* TX High */}/* Handle all TX rings of all Ethernet ports */static int gt_eth_handle_txqueues(struct gt_data *d){   int i;   for(i=0;i<GT_ETH_PORTS;i++)      gt_eth_handle_port_txqueues(d,i);   return(TRUE);}/* Inverse a nibble */static const int inv_nibble[16] = {    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF };/* Inverse a 9-bit value */static inline u_int gt_hash_inv_9bit(u_int val){   u_int res;   res  = inv_nibble[val & 0x0F] << 5;   res |= inv_nibble[(val & 0xF0) >> 4] << 1;   res |= (val & 0x100) >> 8;   return(res);}/*  * Compute hash value for Ethernet address filtering. * Two modes are available (p.271 of the GT96100 doc). */static u_int gt_eth_hash_value(n_eth_addr_t *addr,int mode){   m_uint64_t tmp;   u_int res;   int i;   /* Swap the nibbles */   for(i=0,tmp=0;i<N_ETH_ALEN;i++) {      tmp <<= 8;      tmp |= (inv_nibble[addr->eth_addr_byte[i] & 0x0F]) << 4;      tmp |= inv_nibble[(addr->eth_addr_byte[i] & 0xF0) >> 4];   }   if (mode == 0) {      /* Fill bits 0:8 */      res  = (tmp & 0x00000003) | ((tmp & 0x00007f00) >> 6);      res ^= (tmp & 0x00ff8000) >> 15;      res ^= (tmp & 0x1ff000000ULL) >> 24;      /* Fill bits 9:14 */      res |= (tmp & 0xfc) << 7;   } else {      /* Fill bits 0:8 */      res  = gt_hash_inv_9bit((tmp & 0x00007fc0) >> 6);      res ^= gt_hash_inv_9bit((tmp & 0x00ff8000) >> 15);      res ^= gt_hash_inv_9bit((tmp & 0x1ff000000ULL) >> 24);

⌨️ 快捷键说明

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