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

📄 dev_am79c971.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 2 页
字号:
         if (op_type == MTS_WRITE) {            d->rap = *data & 0xFF;         } else {            *data = d->rap;         }         break;      case 0x10:  /* RDP (Register Data Port) */         am79c971_rdp_access(cpu,d,op_type,data);         break;      case 0x1c:  /* BDP (BCR Data Port) */         am79c971_bdp_access(cpu,d,op_type,data);         break;   }   return NULL;}/* Read a RX descriptor */static int rxdesc_read(struct am79c971_data *d,m_uint32_t rxd_addr,                       struct rx_desc *rxd){   m_uint32_t buf[4];   m_uint8_t sw_style;   /* Get the software style */   sw_style = d->bcr[20];   /* Read the descriptor from VM physical RAM */   physmem_copy_from_vm(d->vm,&buf,rxd_addr,sizeof(struct rx_desc));   switch(sw_style) {      case 2:         rxd->rmd[0] = vmtoh32(buf[0]);  /* rb addr */         rxd->rmd[1] = vmtoh32(buf[1]);  /* own flag, ... */         rxd->rmd[2] = vmtoh32(buf[2]);  /* rfrtag, mcnt, ... */         rxd->rmd[3] = vmtoh32(buf[3]);  /* user */         break;      case 3:         rxd->rmd[0] = vmtoh32(buf[2]);  /* rb addr */         rxd->rmd[1] = vmtoh32(buf[1]);  /* own flag, ... */         rxd->rmd[2] = vmtoh32(buf[0]);  /* rfrtag, mcnt, ... */         rxd->rmd[3] = vmtoh32(buf[3]);  /* user */         break;      default:         AM79C971_LOG(d,"invalid software style %u!\n",sw_style);         return(-1);        }   return(0);}/* Set the address of the next RX descriptor */static inline void rxdesc_set_next(struct am79c971_data *d){   d->rx_pos++;   if (d->rx_pos == d->rx_len)      d->rx_pos = 0;}/* Compute the address of the current RX descriptor */static inline m_uint32_t rxdesc_get_current(struct am79c971_data *d){   return(d->rx_start + (d->rx_pos * sizeof(struct rx_desc)));}/* Put a packet in buffer of a descriptor */static void rxdesc_put_pkt(struct am79c971_data *d,struct rx_desc *rxd,                           u_char **pkt,ssize_t *pkt_len){   ssize_t len,cp_len;   /* Compute the data length to copy */   len = ~((rxd->rmd[1] & AM79C971_RMD1_LEN) - 1);   len &= AM79C971_RMD1_LEN;   cp_len = m_min(len,*pkt_len);         /* Copy packet data to the VM physical RAM */#if DEBUG_RECEIVE   AM79C971_LOG(d,"am79c971_handle_rxring: storing %u bytes at 0x%8.8x\n",                cp_len, rxd->rmd[0]);#endif   physmem_copy_to_vm(d->vm,*pkt,rxd->rmd[0],cp_len);   *pkt += cp_len;   *pkt_len -= cp_len;}/* * Put a packet in the RX ring. */static int am79c971_receive_pkt(struct am79c971_data *d,                                u_char *pkt,ssize_t pkt_len){    m_uint32_t rx_start,rx_current,rx_next,rxdn_rmd1;   struct rx_desc rxd0,rxdn,*rxdc;   ssize_t tot_len = pkt_len;   u_char *pkt_ptr = pkt;   m_uint8_t sw_style;   int i;      /* Truncate the packet if it is too big */   pkt_len = m_min(pkt_len,AM79C971_MAX_PKT_SIZE);   /* Copy the current rxring descriptor */   rx_start = rx_current = rxdesc_get_current(d);   rxdesc_read(d,rx_start,&rxd0);      /* We must have the first descriptor... */   if (!(rxd0.rmd[1] & AM79C971_RMD1_OWN))      return(FALSE);   for(i=0,rxdc=&rxd0;;i++)   {#if DEBUG_RECEIVE      AM79C971_LOG(d,"am79c971_handle_rxring: i=%d, addr=0x%8.8x: "                   "rmd[0]=0x%x, rmd[1]=0x%x, rmd[2]=0x%x, rmd[3]=0x%x\n",                   i,rx_current,                   rxdc->rmd[0],rxdc->rmd[1],rxdc->rmd[2],rxdc->rmd[3]);#endif      /* Put data into the descriptor buffer */      rxdesc_put_pkt(d,rxdc,&pkt_ptr,&tot_len);      /* Go to the next descriptor */      rxdesc_set_next(d);      /* If this is not the first descriptor, clear the OWN bit */      if (i != 0)         rxdc->rmd[1] &= ~AM79C971_RMD1_OWN;      /* If we have finished, mark the descriptor as end of packet */      if (tot_len == 0) {         rxdc->rmd[1] |= AM79C971_RMD1_ENP;         physmem_copy_u32_to_vm(d->vm,rx_current+4,rxdc->rmd[1]);         /* Get the software style */         sw_style = d->bcr[20];         /* Update the message byte count field */         rxdc->rmd[2] &= ~AM79C971_RMD2_LEN;         rxdc->rmd[2] |= pkt_len + 4;         switch(sw_style) {            case 2:               physmem_copy_u32_to_vm(d->vm,rx_current+8,rxdc->rmd[2]);               break;            case 3:               physmem_copy_u32_to_vm(d->vm,rx_current,rxdc->rmd[2]);               break;            default:               AM79C971_LOG(d,"invalid software style %u!\n",sw_style);         }         break;      }      /* Try to acquire the next descriptor */      rx_next = rxdesc_get_current(d);      rxdn_rmd1 = physmem_copy_u32_from_vm(d->vm,rx_next+4);      if (!(rxdn_rmd1 & AM79C971_RMD1_OWN)) {         rxdc->rmd[1] |= AM79C971_RMD1_ERR | AM79C971_RMD1_BUFF;         rxdc->rmd[1] |= AM79C971_RMD1_ENP;         physmem_copy_u32_to_vm(d->vm,rx_current+4,rxdc->rmd[1]);         break;      }      /* Update rmd1 to store change of OWN bit */      physmem_copy_u32_to_vm(d->vm,rx_current+4,rxdc->rmd[1]);      /* Read the next descriptor from VM physical RAM */      rxdesc_read(d,rx_next,&rxdn);      rxdc = &rxdn;      rx_current = rx_next;   }   /* Update the first RX descriptor */   rxd0.rmd[1] &= ~AM79C971_RMD1_OWN;   rxd0.rmd[1] |= AM79C971_RMD1_STP;   physmem_copy_u32_to_vm(d->vm,rx_start+4,rxd0.rmd[1]);   d->csr[0] |= AM79C971_CSR0_RINT;   am79c971_update_intr_flag(d);   am79c971_trigger_irq(d);   return(TRUE);}/* Handle the RX ring */static int am79c971_handle_rxring(netio_desc_t *nio,                                  u_char *pkt,ssize_t pkt_len,                                  struct am79c971_data *d){         n_eth_hdr_t *hdr;   /*     * Don't start receive if the RX ring address has not been set    * and if RX ON is not set.    */   if ((d->rx_start == 0) || !(d->csr[0] & AM79C971_CSR0_TXON))      return(FALSE);#if DEBUG_RECEIVE   AM79C971_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.    */   hdr = (n_eth_hdr_t *)pkt;   if (am79c971_handle_mac_addr(d,pkt))      am79c971_receive_pkt(d,pkt,pkt_len);   return(TRUE);}/* Read a TX descriptor */static int txdesc_read(struct am79c971_data *d,m_uint32_t txd_addr,                       struct tx_desc *txd){   m_uint32_t buf[4];   m_uint8_t sw_style;   /* Get the software style */   sw_style = d->bcr[20];   /* Read the descriptor from VM physical RAM */   physmem_copy_from_vm(d->vm,&buf,txd_addr,sizeof(struct tx_desc));   switch(sw_style) {      case 2:         txd->tmd[0] = vmtoh32(buf[0]);  /* tb addr */         txd->tmd[1] = vmtoh32(buf[1]);  /* own flag, ... */         txd->tmd[2] = vmtoh32(buf[2]);  /* buff, uflo, ... */         txd->tmd[3] = vmtoh32(buf[3]);  /* user */         break;      case 3:         txd->tmd[0] = vmtoh32(buf[2]);  /* tb addr */         txd->tmd[1] = vmtoh32(buf[1]);  /* own flag, ... */         txd->tmd[2] = vmtoh32(buf[0]);  /* buff, uflo, ... */         txd->tmd[3] = vmtoh32(buf[3]);  /* user */         break;      default:         AM79C971_LOG(d,"invalid software style %u!\n",sw_style);         return(-1);        }   return(0);}/* Set the address of the next TX descriptor */static inline void txdesc_set_next(struct am79c971_data *d){   d->tx_pos++;   if (d->tx_pos == d->tx_len)      d->tx_pos = 0;}/* Compute the address of the current TX descriptor */static inline m_uint32_t txdesc_get_current(struct am79c971_data *d){   return(d->tx_start + (d->tx_pos * sizeof(struct tx_desc)));}/* Handle the TX ring (single packet) */static int am79c971_handle_txring_single(struct am79c971_data *d){   u_char pkt[AM79C971_MAX_PKT_SIZE],*pkt_ptr;   struct tx_desc txd0,ctxd,ntxd,*ptxd;   m_uint32_t tx_start,tx_current;   m_uint32_t clen,tot_len;   if ((d->tx_start == 0) || !(d->csr[0] & AM79C971_CSR0_TXON))      return(FALSE);      /* Copy the current txring descriptor */   tx_start = tx_current = txdesc_get_current(d);   ptxd = &txd0;   txdesc_read(d,tx_start,ptxd);   /* If we don't own the first descriptor, we cannot transmit */   if (!(ptxd->tmd[1] & AM79C971_TMD1_OWN))      return(FALSE);   #if DEBUG_TRANSMIT   AM79C971_LOG(d,"am79c971_handle_txring: 1st desc: "                "tmd[0]=0x%x, tmd[1]=0x%x, tmd[2]=0x%x, tmd[3]=0x%x\n",                ptxd->tmd[0],ptxd->tmd[1],ptxd->tmd[2],ptxd->tmd[3]);#endif   /* Empty packet for now */   pkt_ptr = pkt;   tot_len = 0;   for(;;) {#if DEBUG_TRANSMIT      AM79C971_LOG(d,"am79c971_handle_txring: loop: "                   "tmd[0]=0x%x, tmd[1]=0x%x, tmd[2]=0x%x, tmd[3]=0x%x\n",                   ptxd->tmd[0],ptxd->tmd[1],ptxd->tmd[2],ptxd->tmd[3]);#endif      /* Copy packet data */      clen = ~((ptxd->tmd[1] & AM79C971_TMD1_LEN) - 1);      clen &= AM79C971_TMD1_LEN;      physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->tmd[0],clen);      pkt_ptr += clen;      tot_len += clen;      /* Clear the OWN bit if this is not the first descriptor */      if (!(ptxd->tmd[1] & AM79C971_TMD1_STP)) {         ptxd->tmd[1] &= ~AM79C971_TMD1_OWN;         physmem_copy_u32_to_vm(d->vm,tx_current+4,ptxd->tmd[1]);      }      /* Set the next descriptor */      txdesc_set_next(d);      /* Stop now if end of packet has been reached */      if (ptxd->tmd[1] & AM79C971_TMD1_ENP)         break;      /* Read the next descriptor and try to acquire it */      tx_current = txdesc_get_current(d);      txdesc_read(d,tx_current,&ntxd);      if (!(ntxd.tmd[1] & AM79C971_TMD1_OWN)) {         AM79C971_LOG(d,"am79c971_handle_txring: UNDERFLOW!\n");         return(FALSE);      }      memcpy(&ctxd,&ntxd,sizeof(struct tx_desc));      ptxd = &ctxd;   }   if (tot_len != 0) {#if DEBUG_TRANSMIT      AM79C971_LOG(d,"sending packet of %u bytes\n",tot_len);      mem_dump(log_file,pkt,tot_len);#endif      /* send it on wire */      netio_send(d->nio,pkt,tot_len);   }   /* Clear the OWN flag of the first descriptor */   txd0.tmd[1] &= ~AM79C971_TMD1_OWN;   physmem_copy_u32_to_vm(d->vm,tx_start+4,txd0.tmd[1]);   /* Generate TX interrupt */   d->csr[0] |= AM79C971_CSR0_TINT;   am79c971_update_intr_flag(d);   am79c971_trigger_irq(d);   return(TRUE);}/* Handle the TX ring */static int am79c971_handle_txring(struct am79c971_data *d){   int i;   for(i=0;i<AM79C971_TXRING_PASS_COUNT;i++)      if (!am79c971_handle_txring_single(d))         break;   return(TRUE);}/* * pci_am79c971_read() * * Read a PCI register. */static m_uint32_t pci_am79c971_read(cpu_mips_t *cpu,struct pci_device *dev,                                    int reg){      struct am79c971_data *d = dev->priv_data;#if DEBUG_PCI_REGS   AM79C971_LOG(d,"read PCI register 0x%x\n",reg);#endif   switch (reg) {      case 0x00:         return((AM79C971_PCI_PRODUCT_ID << 16) | AM79C971_PCI_VENDOR_ID);      case 0x08:         return(0x02000002);      case PCI_REG_BAR1:         return(d->dev->phys_addr);      default:         return(0);   }}/* * pci_am79c971_write() * * Write a PCI register. */static void pci_am79c971_write(cpu_mips_t *cpu,struct pci_device *dev,                               int reg,m_uint32_t value){   struct am79c971_data *d = dev->priv_data;#if DEBUG_PCI_REGS   AM79C971_LOG(d,"write PCI register 0x%x, value 0x%x\n",reg,value);#endif   switch(reg) {      case PCI_REG_BAR1:         vm_map_device(cpu->vm,d->dev,(m_uint64_t)value);         AM79C971_LOG(d,"registers are mapped at 0x%x\n",value);         break;   }}/*  * dev_am79c971_init() * * Generic AMD Am79c971 initialization code. */struct am79c971_data *dev_am79c971_init(vm_instance_t *vm,char *name,int interface_type,                  struct pci_bus *pci_bus,int pci_device,int irq){   struct am79c971_data *d;   struct pci_device *pci_dev;   struct vdevice *dev;   /* Allocate the private data structure for AM79C971 */   if (!(d = malloc(sizeof(*d)))) {      fprintf(stderr,"%s (AM79C971): out of memory\n",name);      return NULL;   }   memset(d,0,sizeof(*d));   memcpy(d->mii_regs[0],mii_reg_values,sizeof(mii_reg_values));   /* Add as PCI device */   pci_dev = pci_dev_add(pci_bus,name,                         AM79C971_PCI_VENDOR_ID,AM79C971_PCI_PRODUCT_ID,                         pci_device,0,irq,                         d,NULL,pci_am79c971_read,pci_am79c971_write);   if (!pci_dev) {      fprintf(stderr,"%s (AM79C971): unable to create PCI device.\n",name);      goto err_pci_dev;   }   /* Create the device itself */   if (!(dev = dev_create(name))) {      fprintf(stderr,"%s (AM79C971): unable to create device.\n",name);      goto err_dev;   }   d->name     = name;   d->vm       = vm;   d->type     = interface_type;   d->pci_dev  = pci_dev;   d->dev      = dev;   dev->phys_addr = 0;   dev->phys_len  = 0x4000;   dev->handler   = dev_am79c971_access;   dev->priv_data = d;   return(d); err_dev:   pci_dev_remove(pci_dev); err_pci_dev:   free(d);   return NULL;}/* Remove an AMD Am79c971 device */void dev_am79c971_remove(struct am79c971_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 AMD Am79c971 device */int dev_am79c971_set_nio(struct am79c971_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)am79c971_handle_txring,d,NULL);   netio_rxl_add(nio,(netio_rx_handler_t)am79c971_handle_rxring,d,NULL);   return(0);}/* Unbind a NIO from an AMD Am79c971 device */void dev_am79c971_unset_nio(struct am79c971_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 + -