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

📄 dev_dec21140.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 2 页
字号:
   if (rxd->rdes[1] & DEC21140_RXDESC_RER)      nrxd_addr = d->csr[3];   else {      if (rxd->rdes[1] & DEC21140_RXDESC_RCH)         nrxd_addr = rxd->rdes[3];      else         nrxd_addr = rxd_addr + sizeof(struct rx_desc);   }   return(nrxd_addr);}/* Read a RX descriptor */static void rxdesc_read(struct dec21140_data *d,m_uint32_t rxd_addr,                        struct rx_desc *rxd){   /* get the next 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]);}/*  * Try to acquire the specified RX descriptor. Returns TRUE if we have it. * It assumes that the byte-swapping is done. */static inline int rxdesc_acquire(m_uint32_t rdes0){   return(rdes0 & DEC21140_RXDESC_OWN);}/* Put a packet in buffer(s) of a descriptor */static void rxdesc_put_pkt(struct dec21140_data *d,struct rx_desc *rxd,                           u_char **pkt,ssize_t *pkt_len){   ssize_t len1,len2,cp_len;   /* get rbs1 and rbs2 */   len1 = rxd->rdes[1] & DEC21140_RXDESC_LEN_MASK;   len2 = (rxd->rdes[1] >> 10) & DEC21140_RXDESC_LEN_MASK;      /* try with buffer #1 */   if (len1 != 0)   {      /* compute the data length to copy */      cp_len = m_min(len1,*pkt_len);            /* copy packet data to the VM physical RAM */      physmem_copy_to_vm(d->vm,*pkt,rxd->rdes[2],cp_len);            *pkt += cp_len;      *pkt_len -= cp_len;   }   /* try with buffer #2 */   if ((len2 != 0) && !(rxd->rdes[1] & DEC21140_RXDESC_RCH))   {      /* compute the data length to copy */      cp_len = m_min(len2,*pkt_len);            /* copy packet data to the VM physical RAM */      physmem_copy_to_vm(d->vm,*pkt,rxd->rdes[3],cp_len);            *pkt += cp_len;      *pkt_len -= cp_len;   }}/* * Put a packet in the RX ring of the DEC21140. */static int dev_dec21140_receive_pkt(struct dec21140_data *d,                                    u_char *pkt,ssize_t pkt_len){   m_uint32_t rx_start,rxdn_addr,rxdn_rdes0;   struct rx_desc rxd0,rxdn,*rxdc;   ssize_t tot_len = pkt_len;   u_char *pkt_ptr = pkt;   n_eth_hdr_t *hdr;   int i;   /* Truncate the packet if it is too big */   pkt_len = m_min(pkt_len,DEC21140_MAX_PKT_SIZE);   /* Copy the current rxring descriptor */   rxdesc_read(d,d->rx_current,&rxd0);   /* We must have the first descriptor... */   if (!rxdesc_acquire(rxd0.rdes[0]))      return(FALSE);   /* Remember the first RX descriptor address */   rx_start = d->rx_current;   for(i=0,rxdc=&rxd0;tot_len>0;i++)   {      /* Put data into the descriptor buffers */      rxdesc_put_pkt(d,rxdc,&pkt_ptr,&tot_len);      /* Get address of the next descriptor */      rxdn_addr = rxdesc_get_next(d,d->rx_current,rxdc);      /* We have finished if the complete packet has been stored */      if (tot_len == 0) {         rxdc->rdes[0] = DEC21140_RXDESC_LS;         rxdc->rdes[0] |= (pkt_len + 4) << DEC21140_RXDESC_FL_SHIFT;         /* if this is a multicast frame, set the appropriate bit */         hdr = (n_eth_hdr_t *)pkt;         if (eth_addr_is_mcast(&hdr->daddr))            rxdc->rdes[0] |= DEC21140_RXDESC_MF;         if (i != 0)            physmem_copy_u32_to_vm(d->vm,d->rx_current,rxdc->rdes[0]);         d->rx_current = rxdn_addr;         break;      }      /* Get status of the next descriptor to see if we can acquire it */      rxdn_rdes0 = physmem_copy_u32_from_vm(d->vm,rxdn_addr);      if (!rxdesc_acquire(rxdn_rdes0))         rxdc->rdes[0] = DEC21140_RXDESC_LS | DEC21140_RXDESC_DE;      else         rxdc->rdes[0] = 0;  /* ok, no special flag */      /* Update the new status (only if we are not on the first desc) */      if (i != 0)         physmem_copy_u32_to_vm(d->vm,d->rx_current,rxdc->rdes[0]);      /* Update the RX pointer */      d->rx_current = rxdn_addr;      if (rxdc->rdes[0] != 0)         break;      /* Read the next descriptor from VM physical RAM */      rxdesc_read(d,rxdn_addr,&rxdn);      rxdc = &rxdn;   }   /* Update the first RX descriptor */   rxd0.rdes[0] |= DEC21140_RXDESC_FS;   physmem_copy_u32_to_vm(d->vm,rx_start,rxd0.rdes[0]);   /* Indicate that we have a frame ready */   d->csr[5] |= DEC21140_CSR5_RI;   /* Generate IRQ on CPU */   pci_dev_trigger_irq(d->vm,d->pci_dev);   return(TRUE);}/* Handle the DEC21140 RX ring */static int dev_dec21140_handle_rxring(netio_desc_t *nio,                                      u_char *pkt,ssize_t pkt_len,                                      struct dec21140_data *d){   /*     * Don't start receive if the RX ring address has not been set    * and if the SR bit in CSR6 is not set yet.    */   if ((d->csr[3] == 0) || !(d->csr[6] & DEC21140_CSR6_START_RX))      return(FALSE);#if DEBUG_RECEIVE   DEC21140_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_dec21140_receive_pkt(d,pkt,pkt_len));   return(FALSE);}/* Read a TX descriptor */static void txdesc_read(struct dec21140_data *d,m_uint32_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]);}/* Set the address of the next TX descriptor */static void txdesc_set_next(struct dec21140_data *d,struct tx_desc *txd){   if (txd->tdes[1] & DEC21140_TXDESC_TER)      d->tx_current = d->csr[4];   else {      if (txd->tdes[1] & DEC21140_TXDESC_TCH)         d->tx_current = txd->tdes[3];      else         d->tx_current += sizeof(struct tx_desc);   }}/* Handle the TX ring (single packet) */static int dev_dec21140_handle_txring_single(struct dec21140_data *d){      u_char pkt[DEC21140_MAX_PKT_SIZE],*pkt_ptr;   u_char setup_frame[DEC21140_SETUP_FRAME_SIZE];   m_uint32_t tx_start,len1,len2,clen,tot_len;   struct tx_desc txd0,ctxd,*ptxd;   int done = FALSE;   /*     * Don't start transmit if the txring address has not been set    * and if the ST bit in CSR6 is not set yet.    */   if ((d->csr[4] == 0) || (!(d->csr[6] & DEC21140_CSR6_START_TX)))      return(FALSE);   /* Copy the current txring descriptor */   tx_start = d->tx_current;      ptxd = &txd0;   txdesc_read(d,tx_start,ptxd);   /* If we don't own the first descriptor, we cannot transmit */   if (!(txd0.tdes[0] & DEC21140_TXDESC_OWN))      return(FALSE);   /*     * Ignore setup frames (clear the own bit and skip).    * We extract unicast MAC addresses to allow only appropriate traffic    * to pass.    */   if (!(txd0.tdes[1] & (DEC21140_TXDESC_FS|DEC21140_TXDESC_LS)))    {      len1 = ptxd->tdes[1] & DEC21140_TXDESC_LEN_MASK;      len2 = (ptxd->tdes[1] >> 11) & DEC21140_TXDESC_LEN_MASK;      if (txd0.tdes[1] & DEC21140_TXDESC_SET) {         physmem_copy_from_vm(d->vm,setup_frame,ptxd->tdes[2],                              sizeof(setup_frame));         dec21140_update_mac_addr(d,setup_frame);      }      txdesc_set_next(d,ptxd);      goto clear_txd0_own_bit;   }#if DEBUG_TRANSMIT   DEC21140_LOG(d,"dec21140_handle_txring: 1st desc: "                "tdes[0]=0x%x, tdes[1]=0x%x, tdes[2]=0x%x, tdes[3]=0x%x\n",                ptxd->tdes[0],ptxd->tdes[1],ptxd->tdes[2],ptxd->tdes[3]);#endif   /* Empty packet for now */   pkt_ptr = pkt;   tot_len = 0;   do {#if DEBUG_TRANSMIT      DEC21140_LOG(d,"dec21140_handle_txring: loop: "                   "tdes[0]=0x%x, tdes[1]=0x%x, tdes[2]=0x%x, tdes[3]=0x%x\n",                   ptxd->tdes[0],ptxd->tdes[1],ptxd->tdes[2],ptxd->tdes[3]);#endif      if (!(ptxd->tdes[0] & DEC21140_TXDESC_OWN)) {         DEC21140_LOG(d,"dec21140_handle_txring: descriptor not owned!\n");         return(FALSE);      }      len1 = ptxd->tdes[1] & DEC21140_TXDESC_LEN_MASK;      len2 = (ptxd->tdes[1] >> 11) & DEC21140_TXDESC_LEN_MASK;      clen = len1 + len2;      /* Be sure that we have either len1 or len2 not null */      if (clen != 0)      {         if (len1 != 0)            physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->tdes[2],len1);                  if ((len2 != 0) && !(ptxd->tdes[1] & DEC21140_TXDESC_TCH))            physmem_copy_from_vm(d->vm,pkt_ptr+len1,ptxd->tdes[3],len2);      }      pkt_ptr += clen;      tot_len += clen;      /* Clear the OWN bit if this is not the first descriptor */      if (!(ptxd->tdes[1] & DEC21140_TXDESC_FS))         physmem_copy_u32_to_vm(d->vm,d->tx_current,0);      /* Go to the next descriptor */      txdesc_set_next(d,ptxd);      /*        * Copy the next txring descriptor (ignore setup frames that        * have both FS and LS bit cleared).       */      if (!(ptxd->tdes[1] & (DEC21140_TXDESC_LS|DEC21140_TXDESC_SET))) {         txdesc_read(d,d->tx_current,&ctxd);         ptxd = &ctxd;      } else         done = TRUE;   }while(!done);   if (tot_len != 0) {#if DEBUG_TRANSMIT      DEC21140_LOG(d,"sending packet of %u bytes\n",tot_len);      mem_dump(log_file,pkt,tot_len);#endif      /* rewrite ISL header if required */      dec21140_isl_rewrite(pkt,tot_len);      /* send it on wire */      netio_send(d->nio,pkt,tot_len);   } clear_txd0_own_bit:   /* Clear the OWN flag of the first descriptor */   physmem_copy_u32_to_vm(d->vm,tx_start,0);   /* Interrupt on completion ? */   if (!(txd0.tdes[1] & DEC21140_TXDESC_IC)) {      d->csr[5] |= DEC21140_CSR5_TI;      pci_dev_trigger_irq(d->vm,d->pci_dev);   }      return(TRUE);}/* Handle the TX ring */static int dev_dec21140_handle_txring(struct dec21140_data *d){     int i;   for(i=0;i<DEC21140_TXRING_PASS_COUNT;i++)      if (!dev_dec21140_handle_txring_single(d))         break;   return(TRUE);}/* * pci_dec21140_read() * * Read a PCI register. */static m_uint32_t pci_dec21140_read(cpu_mips_t *cpu,struct pci_device *dev,                                    int reg){      struct dec21140_data *d = dev->priv_data;#if DEBUG_PCI_REGS   DEC21140_LOG(d,"read C%s(%u)\n",pci_cfgreg_name(reg),reg);#endif   switch (reg) {      case DEC21140_PCI_CFID_REG_OFFSET:         return(0x00091011);      case DEC21140_PCI_CFRV_REG_OFFSET:         return(0x02000011);      case DEC21140_PCI_CBMA_REG_OFFSET:         return(d->dev->phys_addr);      default:         return(0);   }}/* * pci_dec21140_write() * * Write a PCI register. */static void pci_dec21140_write(cpu_mips_t *cpu,struct pci_device *dev,                               int reg,m_uint32_t value){   struct dec21140_data *d = dev->priv_data;#if DEBUG_PCI_REGS   DEC21140_LOG(d,"write C%s(%u) value 0x%x\n",pci_cfgreg_name(reg),reg,value);#endif   switch(reg) {      case DEC21140_PCI_CBMA_REG_OFFSET:         vm_map_device(cpu->vm,d->dev,(m_uint64_t)value);         DEC21140_LOG(d,"registers are mapped at 0x%x\n",value);         break;   }}/*  * dev_dec21140_init() * * Generic DEC21140 initialization code. */struct dec21140_data *dev_dec21140_init(vm_instance_t *vm,char *name,                                        struct pci_bus *pci_bus,int pci_device,                                        int irq){   struct dec21140_data *d;   struct pci_device *pci_dev;   struct vdevice *dev;   /* Allocate the private data structure for DEC21140 */   if (!(d = malloc(sizeof(*d)))) {      fprintf(stderr,"%s (DEC21140): out of memory\n",name);      return NULL;   }   memset(d,0,sizeof(*d));   /* Add as PCI device */   pci_dev = pci_dev_add(pci_bus,name,                         DEC21140_PCI_VENDOR_ID,DEC21140_PCI_PRODUCT_ID,                         pci_device,0,irq,                         d,NULL,pci_dec21140_read,pci_dec21140_write);   if (!pci_dev) {      fprintf(stderr,"%s (DEC21140): unable to create PCI device.\n",name);      goto err_pci_dev;   }   /* Create the device itself */   if (!(dev = dev_create(name))) {      fprintf(stderr,"%s (DEC21140): unable to create device.\n",name);      goto err_dev;   }   d->name     = name;   d->vm       = vm;   d->pci_dev  = pci_dev;   d->dev      = dev;   /* Basic register setup */   d->csr[0]   = 0xfff80000;   d->csr[5]   = 0xfc000000;   d->csr[8]   = 0xfffe0000;   dev->phys_addr = 0;   dev->phys_len  = 0x20000;   dev->handler   = dev_dec21140_access;   dev->priv_data = d;   return(d); err_dev:   pci_dev_remove(pci_dev); err_pci_dev:   free(d);   return NULL;}/* Remove a DEC21140 device */void dev_dec21140_remove(struct dec21140_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 DEC21140 device */int dev_dec21140_set_nio(struct dec21140_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_dec21140_handle_txring,d,NULL);   netio_rxl_add(nio,(netio_rx_handler_t)dev_dec21140_handle_rxring,d,NULL);   return(0);}/* Unbind a NIO from a DEC21140 device */void dev_dec21140_unset_nio(struct dec21140_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 + -