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

📄 dev_i8254x.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 3 页
字号:
         else            *data = d->fcal;         break;      /* Flow Control Address High */      case I8254X_REG_FCAH:         if (op_type == MTS_WRITE)            d->fcah = *data & 0xFFFF;         else            *data = d->fcah;         break;      /* Flow Control Type */      case I8254X_REG_FCT:         if (op_type == MTS_WRITE)            d->fct = *data & 0xFFFF;         else            *data = d->fct;         break;      /* RX Delay Timer */      case I8254X_REG_RDTR:      case I82542_REG_RDTR:         if (op_type == MTS_WRITE)            d->rdtr = *data & 0xFFFF;         else            *data = d->rdtr;         break;#if DEBUG_UNKNOWN      default:         if (op_type == MTS_READ) {            cpu_log(cpu,d->name,                    "read access to unknown offset=0x%x, "                    "pc=0x%llx (size=%u)\n",                    offset,cpu_get_pc(cpu),op_size);         } else {            cpu_log(cpu,d->name,                    "write access to unknown offset=0x%x, pc=0x%llx, "                    "val=0x%llx (size=%u)\n",                    offset,cpu_get_pc(cpu),*data,op_size);         }#endif   }   LVG_UNLOCK(d);   return NULL;}/* Read a TX descriptor */static void txdesc_read(struct i8254x_data *d,m_uint64_t txd_addr,                        struct tx_desc *txd){   /* Get the descriptor from VM physical RAM */   physmem_copy_from_vm(d->vm,txd,txd_addr,sizeof(struct tx_desc));   /* byte-swapping */   txd->tdes[0] = vmtoh32(txd->tdes[0]);   txd->tdes[1] = vmtoh32(txd->tdes[1]);   txd->tdes[2] = vmtoh32(txd->tdes[2]);   txd->tdes[3] = vmtoh32(txd->tdes[3]);}/* Handle the TX ring */static int dev_i8254x_handle_txring(struct i8254x_data *d){   m_uint64_t txd_addr,buf_addr;   m_uint32_t buf_len,tot_len;   m_uint32_t norm_len,icr;   struct tx_desc txd;   m_uint8_t *pkt_ptr;   /* Transmit Enabled ? */   if (!(d->tctl & I8254X_TCTL_EN))      return(FALSE);   /* If Head is at same position than Tail, the ring is empty */   if (d->tdh == d->tdt)      return(FALSE);   LVG_LOCK(d);      /* Empty packet for now */   pkt_ptr = d->tx_buffer;   tot_len = 0;   icr = 0;   while(d->tdh != d->tdt) {      txd_addr = d->tx_addr + (d->tdh * sizeof(struct tx_desc));      txdesc_read(d,txd_addr,&txd);      /* Copy the packet buffer */      buf_addr = ((m_uint64_t)txd.tdes[1] << 32) | txd.tdes[0];      buf_len  = txd.tdes[2] & I8254X_TXDESC_LEN_MASK;      //printf("COPYING DATA FROM 0x%8.8llx\n",buf_addr);      norm_len = normalize_size(buf_len,4,0);      physmem_copy_from_vm(d->vm,pkt_ptr,buf_addr,norm_len);      mem_bswap32(pkt_ptr,norm_len);      pkt_ptr += buf_len;      tot_len += buf_len;      /* Write the descriptor done bit if required */      if (txd.tdes[2] & I8254X_TXDESC_RS) {         txd.tdes[3] |= I8254X_TXDESC_DD;         icr |= I8254X_ICR_TXDW;         physmem_copy_u32_to_vm(d->vm,txd_addr+0x0c,txd.tdes[3]);      }      /* Go to the next descriptor. Wrap ring if we are at end */      if (++d->tdh == (d->tdlen / sizeof(struct tx_desc)))         d->tdh = 0;      /* End of packet ? */      if (txd.tdes[2] & I8254X_TXDESC_EOP) {#if DEBUG_TRANSMIT         LVG_LOG(d,"sending packet of %u bytes\n",tot_len);         mem_dump(log_file,d->tx_buffer,tot_len);#endif         netio_send(d->nio,d->tx_buffer,tot_len);         break;      }   }   if (d->tdh == d->tdt)      icr |= I8254X_ICR_TXQE;   /* Update the interrupt cause register and trigger IRQ if needed */   d->icr |= icr;   dev_i8254x_update_irq_status(d);   LVG_UNLOCK(d);   return(TRUE);}/* Read a RX descriptor */static void rxdesc_read(struct i8254x_data *d,m_uint64_t rxd_addr,                        struct rx_desc *rxd){   /* Get the descriptor from VM physical RAM */   physmem_copy_from_vm(d->vm,rxd,rxd_addr,sizeof(struct rx_desc));   /* byte-swapping */   rxd->rdes[0] = vmtoh32(rxd->rdes[0]);   rxd->rdes[1] = vmtoh32(rxd->rdes[1]);   rxd->rdes[2] = vmtoh32(rxd->rdes[2]);   rxd->rdes[3] = vmtoh32(rxd->rdes[3]);}/* * Put a packet in the RX ring. */static int dev_i8254x_receive_pkt(struct i8254x_data *d,                                  u_char *pkt,ssize_t pkt_len){   m_uint64_t rxd_addr,buf_addr;   m_uint32_t cur_len,norm_len,tot_len;   struct rx_desc rxd;   m_uint32_t icr;   u_char *pkt_ptr;   if (!d->rx_buf_size)      return(FALSE);   LVG_LOCK(d);   pkt_ptr = pkt;   tot_len = pkt_len;   icr = 0;   while(tot_len > 0) {      /* No descriptor available: RX overrun condition */      if (d->rdh == d->rdt) {         icr |= I8254X_ICR_RXO;         break;      }      rxd_addr = d->rx_addr + (d->rdh * sizeof(struct rx_desc));      rxdesc_read(d,rxd_addr,&rxd);      cur_len = (tot_len > d->rx_buf_size) ? d->rx_buf_size : tot_len;      /* Copy the packet data into the RX buffer */      buf_addr = ((m_uint64_t)rxd.rdes[1] << 32) | rxd.rdes[0];      norm_len = normalize_size(cur_len,4,0);      mem_bswap32(pkt_ptr,norm_len);      physmem_copy_to_vm(d->vm,pkt_ptr,buf_addr,norm_len);      tot_len -= cur_len;      pkt_ptr += cur_len;      /* Set length field */      rxd.rdes[2] = cur_len;      /* Set the status */      rxd.rdes[3] = I8254X_RXDESC_IXSM|I8254X_RXDESC_DD;          if (!tot_len) {         rxd.rdes[3] |= I8254X_RXDESC_EOP;         icr |= I8254X_ICR_RXT0;         d->rx_irq_cnt++;         rxd.rdes[2] += 4;   /* FCS */      }      /* Write back updated descriptor */      physmem_copy_u32_to_vm(d->vm,rxd_addr+0x08,rxd.rdes[2]);      physmem_copy_u32_to_vm(d->vm,rxd_addr+0x0c,rxd.rdes[3]);      /* Goto to the next descriptor, and wrap if necessary */      if (++d->rdh == (d->rdlen / sizeof(struct rx_desc)))         d->rdh = 0;   }   /* Update the interrupt cause register and trigger IRQ if needed */   d->icr |= icr;   dev_i8254x_update_irq_status(d);   LVG_UNLOCK(d);   return(TRUE);}/* Handle the RX ring */static int dev_i8254x_handle_rxring(netio_desc_t *nio,                                    u_char *pkt,ssize_t pkt_len,                                    struct i8254x_data *d){   /*     * Don't start receive if RX has not been enabled in RCTL register.    */   if (!(d->rctl & I8254X_RCTL_EN))      return(FALSE);#if DEBUG_RECEIVE   LVG_LOG(d,"receiving a packet of %d bytes\n",pkt_len);   mem_dump(log_file,pkt,pkt_len);#endif   /*     * Receive only multicast/broadcast trafic + unicast traffic     * for this virtual machine.    */   //if (dec21140_handle_mac_addr(d,pkt))   return(dev_i8254x_receive_pkt(d,pkt,pkt_len));   return(FALSE);}/* * pci_i8254x_read() * * Read a PCI register. */static m_uint32_t pci_i8254x_read(cpu_gen_t *cpu,struct pci_device *dev,                                  int reg){   struct i8254x_data *d = dev->priv_data;#if DEBUG_PCI_REGS   I8254X_LOG(d,"read PCI register 0x%x\n",reg);#endif   switch (reg) {      case 0x00:         return((I8254X_PCI_PRODUCT_ID << 16) | I8254X_PCI_VENDOR_ID);      case 0x08:         return(0x02000003);      case PCI_REG_BAR0:         return(d->dev->phys_addr);      default:         return(0);   }}/* * pci_i8254x_write() * * Write a PCI register. */static void pci_i8254x_write(cpu_gen_t *cpu,struct pci_device *dev,                             int reg,m_uint32_t value){   struct i8254x_data *d = dev->priv_data;#if DEBUG_PCI_REGS   LVG_LOG(d,"write PCI register 0x%x, value 0x%x\n",reg,value);#endif   switch(reg) {      case PCI_REG_BAR0:         vm_map_device(cpu->vm,d->dev,(m_uint64_t)value);         LVG_LOG(d,"registers are mapped at 0x%x\n",value);         break;   }}/* * dev_i8254x_init() */struct i8254x_data *dev_i8254x_init(vm_instance_t *vm,char *name,int interface_type,                struct pci_bus *pci_bus,int pci_device,int irq){   struct i8254x_data *d;   struct pci_device *pci_dev;   struct vdevice *dev;   /* Allocate the private data structure for I8254X */   if (!(d = malloc(sizeof(*d)))) {      fprintf(stderr,"%s (i8254x): out of memory\n",name);      return NULL;   }   memset(d,0,sizeof(*d));   pthread_mutex_init(&d->lock,NULL);   /* Add as PCI device */   pci_dev = pci_dev_add(pci_bus,name,                         I8254X_PCI_VENDOR_ID,I8254X_PCI_PRODUCT_ID,                         pci_device,0,irq,                         d,NULL,pci_i8254x_read,pci_i8254x_write);   if (!pci_dev) {      fprintf(stderr,"%s (i8254x): unable to create PCI device.\n",name);      goto err_pci_dev;   }   /* Create the device itself */   if (!(dev = dev_create(name))) {      fprintf(stderr,"%s (i8254x): unable to create device.\n",name);      goto err_dev;   }   d->name     = name;   d->vm       = vm;   d->pci_dev  = pci_dev;   d->dev      = dev;   dev->phys_addr = 0;   dev->phys_len  = 0x10000;   dev->handler   = dev_i8254x_access;   dev->priv_data = d;   return(d); err_dev:   pci_dev_remove(pci_dev); err_pci_dev:   free(d);   return NULL;}/* Remove an Intel i8254x device */void dev_i8254x_remove(struct i8254x_data *d){   if (d != NULL) {      pci_dev_remove(d->pci_dev);      vm_unbind_device(d->vm,d->dev);      cpu_group_rebuild_mts(d->vm->cpu_group);      free(d->dev);      free(d);   }}/* Bind a NIO to an Intel i8254x device */int dev_i8254x_set_nio(struct i8254x_data *d,netio_desc_t *nio){   /* check that a NIO is not already bound */   if (d->nio != NULL)      return(-1);   d->nio = nio;   d->tx_tid = ptask_add((ptask_callback)dev_i8254x_handle_txring,d,NULL);   netio_rxl_add(nio,(netio_rx_handler_t)dev_i8254x_handle_rxring,d,NULL);   return(0);}/* Unbind a NIO from an Intel i8254x device */void dev_i8254x_unset_nio(struct i8254x_data *d){   if (d->nio != NULL) {      ptask_remove(d->tx_tid);      netio_rxl_remove(d->nio);      d->nio = NULL;   }}

⌨️ 快捷键说明

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