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

📄 dev_mueslix.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 2 页
字号:
#endif   }   return NULL;}/* * Get the address of the next RX descriptor. */static m_uint32_t rxdesc_get_next(struct mueslix_channel *channel,                                  m_uint32_t rxd_addr){   m_uint32_t nrxd_addr;   switch(channel->parent->chip_mode) {      case 0:         nrxd_addr = rxd_addr + sizeof(struct rx_desc);         if (nrxd_addr == channel->rx_end)            nrxd_addr = channel->rx_start;         break;      case 1:      default:         if (rxd_addr == channel->rx_end)            nrxd_addr = channel->rx_start;         else            nrxd_addr = rxd_addr + sizeof(struct rx_desc);         break;            }   return(nrxd_addr);}/* Read an RX descriptor */static void rxdesc_read(struct mueslix_data *d,m_uint32_t rxd_addr,                        struct rx_desc *rxd){#if DEBUG_RECEIVE   MUESLIX_LOG(d,"reading RX descriptor at address 0x%x\n",rxd_addr);#endif   /* 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]);}/*  * 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 & MUESLIX_RXDESC_OWN);}/* Put a packet in buffer of a descriptor */static ssize_t rxdesc_put_pkt(struct mueslix_data *d,struct rx_desc *rxd,                              u_char **pkt,ssize_t *pkt_len){   ssize_t len,cp_len;   len = rxd->rdes[0] & MUESLIX_RXDESC_LEN_MASK;   /* compute the data length to copy */   cp_len = m_min(len,*pkt_len);#if DEBUG_RECEIVE   MUESLIX_LOG(d,"copying %d bytes at 0x%x\n",cp_len,rxd->rdes[1]);#endif         /* copy packet data to the VM physical RAM */   physmem_copy_to_vm(d->vm,*pkt,rxd->rdes[1],cp_len);         *pkt += cp_len;   *pkt_len -= cp_len;   return(cp_len);}/* * Put a packet in the RX ring of the Mueslix specified channel. */static void dev_mueslix_receive_pkt(struct mueslix_channel *channel,                                    u_char *pkt,ssize_t pkt_len){   struct mueslix_data *d = channel->parent;   m_uint32_t rx_start,rxdn_addr,rxdn_rdes0;   struct rx_desc rxd0,rxdn,*rxdc;   ssize_t cp_len,tot_len = pkt_len;   u_char *pkt_ptr = pkt;   int i;   if ((channel->rx_start == 0) || (channel->status == 0) ||       (channel->nio == NULL))      return;   /* Don't make anything if RX is not enabled for this channel */   if (!(dev_mueslix_is_rx_tx_enabled(d,channel->id) & MUESLIX_RX_ENABLE))      return;   /* Truncate the packet if it is too big */   pkt_len = m_min(pkt_len,MUESLIX_MAX_PKT_SIZE);   /* Copy the current rxring descriptor */   rxdesc_read(d,channel->rx_current,&rxd0);      /* We must have the first descriptor... */   if (!rxdesc_acquire(rxd0.rdes[0]))      return;   /* Remember the first RX descriptor address */   rx_start = channel->rx_current;   for(i=0,rxdc=&rxd0;tot_len>0;i++)   {      /* Put data into the descriptor buffers */      cp_len = rxdesc_put_pkt(d,rxdc,&pkt_ptr,&tot_len);      /* Get address of the next descriptor */      rxdn_addr = rxdesc_get_next(channel,channel->rx_current);      /* We have finished if the complete packet has been stored */      if (tot_len == 0) {         rxdc->rdes[0] = MUESLIX_RXDESC_LS;         rxdc->rdes[0] |= cp_len;         if (i != 0)            physmem_copy_u32_to_vm(d->vm,channel->rx_current,rxdc->rdes[0]);         channel->rx_current = rxdn_addr;         break;      }#if DEBUG_RECEIVE      MUESLIX_LOG(d,"trying to acquire new descriptor at 0x%x\n",rxdn_addr);#endif      /* 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] = MUESLIX_RXDESC_LS | MUESLIX_RXDESC_OVERRUN;      else         rxdc->rdes[0] = 0x00000000;  /* ok, no special flag */      rxdc->rdes[0] |= cp_len;      /* Update the new status (only if we are not on the first desc) */      if (i != 0)         physmem_copy_u32_to_vm(d->vm,channel->rx_current,rxdc->rdes[0]);      /* Update the RX pointer */      channel->rx_current = rxdn_addr;      if (rxdc->rdes[0] & MUESLIX_RXDESC_LS)         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] |= MUESLIX_RXDESC_FS;   physmem_copy_u32_to_vm(d->vm,rx_start,rxd0.rdes[0]);   /* Indicate that we have a frame ready (XXX something to do ?) */   /* Generate IRQ on CPU */   channel->rx_tx_status |= MUESLIX_CHANNEL_STATUS_RX;   pci_dev_trigger_irq(d->vm,d->pci_dev);}/* Handle the Mueslix RX ring of the specified channel */static int dev_mueslix_handle_rxring(netio_desc_t *nio,                                     u_char *pkt,ssize_t pkt_len,                                     struct mueslix_channel *channel){#if DEBUG_RECEIVE   struct mueslix_data *d = channel->parent;   MUESLIX_LOG(d,"channel %u: receiving a packet of %d bytes\n",               channel->id,pkt_len);   mem_dump(log_file,pkt,pkt_len);#endif   dev_mueslix_receive_pkt(channel,pkt,pkt_len);   return(TRUE);}/* Read a TX descriptor */static void txdesc_read(struct mueslix_data *d,m_uint32_t txd_addr,                        struct tx_desc *txd){   /* get the next 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]);}/* Set the address of the next TX descriptor */static void txdesc_set_next(struct mueslix_channel *channel){   switch(channel->parent->chip_mode) {      case 0:         channel->tx_current += sizeof(struct tx_desc);         if (channel->tx_current == channel->tx_end)            channel->tx_current = channel->tx_start;         break;      case 1:      default:         if (channel->tx_current == channel->tx_end)            channel->tx_current = channel->tx_start;         else            channel->tx_current += sizeof(struct tx_desc);   }}/* Handle the TX ring of a specific channel (single packet) */static int dev_mueslix_handle_txring_single(struct mueslix_channel *channel){   struct mueslix_data *d = channel->parent;   u_char pkt[MUESLIX_MAX_PKT_SIZE],*pkt_ptr;   m_uint32_t tx_start,clen,sub_len,tot_len,pad;   struct tx_desc txd0,ctxd,*ptxd;   int done = FALSE;   if ((channel->tx_start == 0) || (channel->status == 0))      return(FALSE);   /* Copy the current txring descriptor */   tx_start = channel->tx_current;      ptxd = &txd0;   txdesc_read(d,channel->tx_current,ptxd);   /* If we don't own the descriptor, we cannot transmit */   if (!(txd0.tdes[0] & MUESLIX_TXDESC_OWN))      return(FALSE);#if DEBUG_TRANSMIT   MUESLIX_LOG(d,"mueslix_handle_txring: 1st desc: "               "tdes[0]=0x%x, tdes[1]=0x%x\n",               ptxd->tdes[0],ptxd->tdes[1]);#endif   pkt_ptr = pkt;   tot_len = 0;   do {#if DEBUG_TRANSMIT      MUESLIX_LOG(d,"mueslix_handle_txring: loop: "                  "tdes[0]=0x%x, tdes[1]=0x%x\n",                  ptxd->tdes[0],ptxd->tdes[1]);#endif      if (!(ptxd->tdes[0] & MUESLIX_TXDESC_OWN)) {         MUESLIX_LOG(d,"mueslix_handle_txring: descriptor not owned!\n");         return(FALSE);      }      switch(channel->parent->chip_mode) {         case 0:            clen = ptxd->tdes[0] & MUESLIX_TXDESC_LEN_MASK;            break;         case 1:         default:            clen = (ptxd->tdes[0] & MUESLIX_TXDESC_LEN_MASK) << 2;            if (ptxd->tdes[0] & MUESLIX_TXDESC_SUB) {               sub_len = ptxd->tdes[0] & MUESLIX_TXDESC_SUB_LEN;               sub_len >>= MUESLIX_TXDESC_SUB_SHIFT;               clen -= sub_len;            }      }            /* Be sure that we have length not null */      if (clen != 0) {         //printf("pkt_ptr = %p, ptxd->tdes[1] = 0x%x, clen = %d\n",         //pkt_ptr, ptxd->tdes[1], clen);         physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->tdes[1],clen);      }      pkt_ptr += clen;      tot_len += clen;      /* Clear the OWN bit if this is not the first descriptor */      if (!(ptxd->tdes[0] & MUESLIX_TXDESC_FS))         physmem_copy_u32_to_vm(d->vm,channel->tx_current,0);      /* Go to the next descriptor */      txdesc_set_next(channel);      /* Copy the next txring descriptor */      if (!(ptxd->tdes[0] & MUESLIX_TXDESC_LS)) {         txdesc_read(d,channel->tx_current,&ctxd);         ptxd = &ctxd;      } else         done = TRUE;   }while(!done);   if (tot_len != 0) {#if DEBUG_TRANSMIT      MUESLIX_LOG(d,"sending packet of %u bytes (flags=0x%4.4x)\n",                  tot_len,txd0.tdes[0]);      mem_dump(log_file,pkt,tot_len);#endif      pad = ptxd->tdes[0] & MUESLIX_TXDESC_PAD;      pad >>= MUESLIX_TXDESC_PAD_SHIFT;      tot_len += (pad - 1) & 0x03;       /* send it on wire */      netio_send(channel->nio,pkt,tot_len);   }   /* Clear the OWN flag of the first descriptor */   physmem_copy_u32_to_vm(d->vm,tx_start,0);   /* Interrupt on completion ? */   channel->rx_tx_status |= MUESLIX_CHANNEL_STATUS_TX;   pci_dev_trigger_irq(d->vm,d->pci_dev);      return(TRUE);}/* Handle the TX ring of a specific channel */static int dev_mueslix_handle_txring(struct mueslix_channel *channel){   int i;   for(i=0;i<MUESLIX_TXRING_PASS_COUNT;i++)      if (!dev_mueslix_handle_txring_single(channel))         break;   return(TRUE);}/* pci_mueslix_read() */static m_uint32_t pci_mueslix_read(cpu_mips_t *cpu,struct pci_device *dev,                                   int reg){      struct mueslix_data *d = dev->priv_data;   switch(reg) {      case 0x08:  /* Rev ID */         return(0x2800001);      case PCI_REG_BAR0:         return(d->dev->phys_addr);      default:         return(0);   }}/* pci_mueslix_write() */static void pci_mueslix_write(cpu_mips_t *cpu,struct pci_device *dev,                              int reg,m_uint32_t value){      struct mueslix_data *d = dev->priv_data;   switch(reg) {      case PCI_REG_BAR0:         vm_map_device(cpu->vm,d->dev,(m_uint64_t)value);         MUESLIX_LOG(d,"registers are mapped at 0x%x\n",value);         break;   }}/* Initialize a Mueslix chip */struct mueslix_data *dev_mueslix_init(vm_instance_t *vm,char *name,int chip_mode,                 struct pci_bus *pci_bus,int pci_device,int irq){   struct pci_device *pci_dev;   struct mueslix_data *d;   struct vdevice *dev;   int i;   /* Allocate the private data structure for Mueslix chip */   if (!(d = malloc(sizeof(*d)))) {      fprintf(stderr,"%s (Mueslix): out of memory\n",name);      return NULL;   }   memset(d,0,sizeof(*d));   d->chip_mode = chip_mode;   for(i=0;i<MUESLIX_NR_CHANNELS;i++)      d->channel[i].id = i;   /* Add as PCI device */   pci_dev = pci_dev_add(pci_bus,name,                         MUESLIX_PCI_VENDOR_ID,MUESLIX_PCI_PRODUCT_ID,                         pci_device,0,irq,                         d,NULL,pci_mueslix_read,pci_mueslix_write);   if (!pci_dev) {      fprintf(stderr,"%s (Mueslix): unable to create PCI device.\n",name);      return NULL;   }   /* Create the device itself */   if (!(dev = dev_create(name))) {      fprintf(stderr,"%s (Mueslix): unable to create device.\n",name);      return NULL;   }   d->name        = name;   d->pci_dev     = pci_dev;   d->vm          = vm;   dev->phys_addr = 0;   dev->phys_len  = 0x4000;   dev->handler   = dev_mueslix_access;   dev->priv_data = d;   /* Store device info */   dev->priv_data = d;   d->dev = dev;   return(d);}/* Remove a Mueslix device */void dev_mueslix_remove(struct mueslix_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 a Mueslix channel */int dev_mueslix_set_nio(struct mueslix_data *d,u_int channel_id,                        netio_desc_t *nio){   struct mueslix_channel *channel;   if (channel_id >= MUESLIX_NR_CHANNELS)      return(-1);   channel = &d->channel[channel_id];   /* check that a NIO is not already bound */   if (channel->nio != NULL)      return(-1);   /* define the new NIO */   channel->nio = nio;   channel->parent = d;   channel->tx_tid = ptask_add((ptask_callback)dev_mueslix_handle_txring,                               channel,NULL);   netio_rxl_add(nio,(netio_rx_handler_t)dev_mueslix_handle_rxring,                 channel,NULL);   return(0);}/* Unbind a NIO from a Mueslix channel */int dev_mueslix_unset_nio(struct mueslix_data *d,u_int channel_id){   struct mueslix_channel *channel;   if (channel_id >= MUESLIX_NR_CHANNELS)      return(-1);   channel = &d->channel[channel_id];   if (channel->nio) {      ptask_remove(channel->tx_tid);      netio_rxl_remove(channel->nio);      channel->nio = NULL;   }   return(0);}

⌨️ 快捷键说明

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