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

📄 dev_pa_a1.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 4 页
字号:
              "buf_len=0x%x\n",rde->cb_len,buf_len);#endif   /* determine if this is the end of the packet (EOP) */   if (aal_type == TI1570_RX_DMA_AAL_CNT)    {         /* counter-based tranparent-AAL packets */      cnt = rde->cb_len & TI1570_RX_DMA_TR_CNT_MASK;      cnt >>= TI1570_RX_DMA_TR_CNT_SHIFT;      /* if the counter reaches 0, this is the EOP */      if (--cnt == 0)         real_eop = TRUE;      val = rde->cb_len & ~TI1570_RX_DMA_TR_CNT_MASK;      val |= cnt << TI1570_RX_DMA_TR_CNT_SHIFT;   }   else {      /* PTI-based transparent AAL packets or AAL5 */      if (pti_eop)         real_eop = TRUE;   }   if (real_eop) {      /* mark the buffer as EOP */      ptr = (rde->sb_addr << 2) + OFFSET(ti1570_rx_buffer_t,ctrl);      val = physmem_copy_u32_from_vm(d->vm,ptr);      val |= TI1570_RX_BUFFER_EOP;      physmem_copy_u32_to_vm(d->vm,ptr,val);      /* get the aal5 trailer */      aal5_trailer = ntohl(*(m_uint32_t *)&atm_cell[ATM_AAL5_TRAILER_POS]);      /* post the entry into the appropriate RX completion ring */      ti1570_update_rx_cring(d,rde,atm_hdr,aal5_trailer,0,TRUE);   }   return(TRUE);}/* Handle a received ATM cell */static int ti1570_handle_rx_cell(netio_desc_t *nio,                                 u_char *atm_cell,ssize_t cell_len,                                 struct pa_a1_data *d){   m_uint32_t atm_hdr,vpi,vci,vci_idx,vci_mask;   m_uint32_t vci_max,rvd_entry,bptr,pti,ptr;   ti1570_rx_dma_entry_t *rde = NULL;   ti1570_rx_buf_holder_t rbh;   if (cell_len != ATM_CELL_SIZE) {      TI1570_LOG(d,"invalid RX cell size (%ld)\n",(long)cell_len);      return(FALSE);   }   /* Extract the VPI/VCI used as index in the RX VPI/VCI DMA pointer table */   atm_hdr = ntohl(*(m_uint32_t *)&atm_cell[0]);   vpi = (atm_hdr & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT;   vci = (atm_hdr & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT;   pti = (atm_hdr & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;#if DEBUG_RECEIVE   TI1570_LOG(d,"ti1570_handle_rx_cell: received cell with VPI/VCI=%u/%u\n",              vpi,vci);#endif   /* Get the entry corresponding to this VPI in RX VPI/VCI dma ptr table */   rvd_entry = d->rx_vpi_vci_dma_table[vpi];     if (!(rvd_entry & TI1570_RX_VPI_ENABLE)) {      TI1570_LOG(d,"ti1570_handle_rx_cell: received cell with "                 "unknown VPI %u (VCI=%u)\n",vpi,vci);      return(FALSE);   }   /*     * Special routing for OAM F4 cells:    *   - VCI 3 : OAM F4 segment cell    *   - VCI 4 : OAM F4 end-to-end cell    */   if ((vci == 3) || (vci == 4))      rde = &d->rx_dma_table[2];   else {      if ((atm_hdr & ATM_PTI_NETWORK) != 0) {               switch(pti) {            case 0x04:   /* OAM F5-segment cell */            case 0x05:   /* OAM F5 end-to-end cell */               rde = &d->rx_dma_table[0];               break;            case 0x06:            case 0x07:               rde = &d->rx_dma_table[1];               break;         }      } else {         /*           * Standard VPI/VCI.          * Apply the VCI mask if we don't have an OAM cell.          */         if (!(atm_hdr & ATM_PTI_NETWORK)) {            vci_mask = d->iregs[TI1570_REG_TX_RX_FIFO] >> 16;            vci_idx  = vci & (~vci_mask);            vci_max = rvd_entry & TI1570_RX_VCI_RANGE_MASK;            if (vci_idx > vci_max) {               TI1570_LOG(d,"ti1570_handle_rx_cell: out-of-range VCI %u "                          "(VPI=%u,vci_mask=%u,vci_max=%u)\n",                          vci,vpi,vci_mask,vci_max);               return(FALSE);            }#if DEBUG_RECEIVE            TI1570_LOG(d,"ti1570_handle_rx_cell: VPI/VCI=%u/%u, "                       "vci_mask=0x%x, vci_idx=%u (0x%x), vci_max=%u (0x%x)\n",                       vpi,vci,vci_mask,vci_idx,vci_idx,vci_max,vci_max);#endif            bptr = (rvd_entry & TI1570_RX_BASE_PTR_MASK);            bptr >>= TI1570_RX_BASE_PTR_SHIFT;            bptr = (bptr + vci) * sizeof(ti1570_rx_dma_entry_t);            if (bptr < TI1570_RX_DMA_TABLE_OFFSET) {               TI1570_LOG(d,"ti1570_handle_rx_cell: inconsistency in "                          "RX VPI/VCI table, VPI/VCI=%u/u, bptr=0x%x\n",                          vpi,vci,bptr);               return(FALSE);            }            bptr -= TI1570_RX_DMA_TABLE_OFFSET;                  rde = &d->rx_dma_table[bptr / sizeof(ti1570_rx_dma_entry_t)];         }      }   }   if (!rde) {      TI1570_LOG(d,"ti1570_handle_rx_cell: no RX DMA table entry found!\n");      return(FALSE);   }   /* The entry must be active */   if (!(rde->fbr_entry & TI1570_RX_DMA_ON))      return(FALSE);   /* Is this the start of a new packet ? */   if (!(rde->ctrl & TI1570_RX_DMA_ACT))    {      /* Try to acquire a free buffer */      if (!ti1570_acquire_rx_buffer(d,rde,&rbh,atm_hdr)) {         rde->ctrl |= TI1570_RX_DMA_WAIT_EOP;         return(FALSE);      }      /* Insert the free buffer in the RX DMA structure */      ti1570_insert_rx_free_buf(d,rde,&rbh);      rde->sp_ptr = rde->sb_addr;      /* Mark the RX buffer as the start of packet (SOP) */      ptr = (rde->sb_addr << 2) + OFFSET(ti1570_rx_buffer_t,ctrl);      physmem_copy_u32_to_vm(d->vm,ptr,TI1570_RX_BUFFER_SOP);      /* Set ACT bit for the DMA channel */      rde->ctrl |= TI1570_RX_DMA_ACT;   }   /* Store the received cell */   ti1570_store_rx_cell(d,rde,atm_cell);   return(TRUE);}/* * pci_ti1570_read() */static m_uint32_t pci_ti1570_read(cpu_mips_t *cpu,struct pci_device *dev,                                  int reg){   struct pa_a1_data *d = dev->priv_data;#if DEBUG_ACCESS   TI1570_LOG(d,"pci_ti1570_read: read reg 0x%x\n",reg);#endif   switch(reg) {      case PCI_REG_BAR0:         return(d->dev->phys_addr);      default:         return(0);   }}/* * pci_ti1570_write() */static void pci_ti1570_write(cpu_mips_t *cpu,struct pci_device *dev,                             int reg,m_uint32_t value){   struct pa_a1_data *d = dev->priv_data;#if DEBUG_ACCESS   TI1570_LOG(d,"pci_ti1570_write: write reg 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);         TI1570_LOG(d,"registers are mapped at 0x%x\n",value);         break;   }}/* * pci_plx9060es_read() */static m_uint32_t pci_plx9060es_read(cpu_mips_t *cpu,struct pci_device *dev,                                     int reg){#if DEBUG_ACCESS   TI1570_LOG(d,"PLX9060ES","read reg 0x%x\n",reg);#endif   switch(reg) {      default:         return(0);   }}/* * pci_plx9060es_write() */static void pci_plx9060es_write(cpu_mips_t *cpu,struct pci_device *dev,                                int reg,m_uint32_t value){#if DEBUG_ACCESS   TI1570_LOG(d,"PLX9060ES","write reg 0x%x, value 0x%x\n",reg,value);#endif   switch(reg) {   }}/* Reset the TI1570 */static void ti1570_reset(struct pa_a1_data *d,int clear_ctrl_mem){   ti1570_clear_tx_fifo(d);   d->tcr_wi_pos = d->tcr_woi_pos = 0;   d->rcr_wi_pos = d->rcr_woi_pos = 0;   if (clear_ctrl_mem)      memset(d->ctrl_mem_ptr,0,TI1570_CTRL_MEM_SIZE);}/* * dev_c7200_pa_a1_init() * * Add a PA-A1 port adapter into specified slot. */int dev_c7200_pa_a1_init(c7200_t *router,char *name,u_int pa_bay){      struct pci_device *pci_dev_ti,*pci_dev_plx;   struct pa_a1_data *d;   struct vdevice *dev;   m_uint8_t *p;   /* Allocate the private data structure for TI1570 chip */   if (!(d = malloc(sizeof(*d)))) {      fprintf(stderr,"%s (TI1570): out of memory\n",name);      return(-1);   }   memset(d,0,sizeof(*d));   /* Set the EEPROM */   c7200_pa_set_eeprom(router,pa_bay,cisco_eeprom_find_pa("PA-A1"));   /* Add PCI device TI1570 */   pci_dev_ti = pci_dev_add(router->pa_bay[pa_bay].pci_map,name,                            TI1570_PCI_VENDOR_ID,TI1570_PCI_PRODUCT_ID,                            0,0,C7200_NETIO_IRQ,d,                            NULL,pci_ti1570_read,pci_ti1570_write);   if (!pci_dev_ti) {      fprintf(stderr,"%s (TI1570): unable to create PCI device TI1570.\n",              name);      return(-1);   }   /* Add PCI device PLX9060ES */   pci_dev_plx = pci_dev_add(router->pa_bay[pa_bay].pci_map,name,                             PLX_9060ES_PCI_VENDOR_ID,                             PLX_9060ES_PCI_PRODUCT_ID,                             1,0,C7200_NETIO_IRQ,d,                             NULL,pci_plx9060es_read,pci_plx9060es_write);   if (!pci_dev_plx) {      fprintf(stderr,"%s (PLX_9060ES): unable to create PCI device "              "PLX 9060ES.\n",name);      return(-1);   }   /* Create the TI1570 structure */   d->name        = name;   d->vm          = router->vm;   d->pci_dev_ti  = pci_dev_ti;   d->pci_dev_plx = pci_dev_plx;   /* Allocate the control memory */   if (!(d->ctrl_mem_ptr = malloc(TI1570_CTRL_MEM_SIZE))) {      fprintf(stderr,"%s (PA-A1): unable to create control memory.\n",name);      return(-1);   }   /* Standard tables for the TI1570 */   p = (m_uint8_t *)d->ctrl_mem_ptr;   d->iregs = (m_uint32_t *)(p + TI1570_INTERNAL_REGS_OFFSET);   d->tx_sched_table = (m_uint32_t *)(p + TI1570_TX_SCHED_OFFSET);   d->tx_dma_table = (ti1570_tx_dma_entry_t *)(p + TI1570_TX_DMA_TABLE_OFFSET);   d->rx_vpi_vci_dma_table = (m_uint32_t *)(p+TI1570_RX_DMA_PTR_TABLE_OFFSET);   d->rx_dma_table = (ti1570_rx_dma_entry_t *)(p + TI1570_RX_DMA_TABLE_OFFSET);   d->rx_fbr_table = (ti1570_rx_fbr_entry_t *)(p + TI1570_FREE_BUFFERS_OFFSET);   ti1570_reset(d,TRUE);   /* Create the device itself */   if (!(dev = dev_create(name))) {      fprintf(stderr,"%s (PA-A1): unable to create device.\n",name);      return(-1);   }   dev->phys_addr = 0;   dev->phys_len  = 0x200000;   dev->handler   = dev_pa_a1_access;   /* Store device info */   dev->priv_data = d;   d->dev = dev;      /* Store device info into the router structure */   return(c7200_pa_set_drvinfo(router,pa_bay,d));}/* Remove a PA-A1 from the specified slot */int dev_c7200_pa_a1_shutdown(c7200_t *router,u_int pa_bay) {   struct c7200_pa_bay *bay;   struct pa_a1_data *d;   if (!(bay = c7200_pa_get_info(router,pa_bay)))      return(-1);   d = bay->drv_info;   /* Remove the PA EEPROM */   c7200_pa_unset_eeprom(router,pa_bay);   /* Remove the PCI devices */   pci_dev_remove(d->pci_dev_ti);   pci_dev_remove(d->pci_dev_plx);   /* Remove the device from the VM address space */   vm_unbind_device(router->vm,d->dev);   cpu_group_rebuild_mts(router->vm->cpu_group);   /* Free the control memory */   free(d->ctrl_mem_ptr);   /* Free the device structure itself */   free(d->dev);   free(d);   return(0);}/* Bind a Network IO descriptor to a specific port */int dev_c7200_pa_a1_set_nio(c7200_t *router,u_int pa_bay,u_int port_id,                            netio_desc_t *nio){   struct pa_a1_data *d;   if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay)))      return(-1);   if (d->nio != NULL)      return(-1);   d->nio = nio;   d->tx_tid = ptask_add((ptask_callback)ti1570_scan_tx_sched_table,d,NULL);   netio_rxl_add(nio,(netio_rx_handler_t)ti1570_handle_rx_cell,d,NULL);   return(0);}/* Unbind a Network IO descriptor to a specific port */int dev_c7200_pa_a1_unset_nio(c7200_t *router,u_int pa_bay,u_int port_id){   struct pa_a1_data *d;   if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay)))      return(-1);   if (d->nio) {      ptask_remove(d->tx_tid);      netio_rxl_remove(d->nio);      d->nio = NULL;   }   return(0);}/* PA-A1 driver */struct c7200_pa_driver dev_c7200_pa_a1_driver = {   "PA-A1", 1,    dev_c7200_pa_a1_init,   dev_c7200_pa_a1_shutdown,   dev_c7200_pa_a1_set_nio,   dev_c7200_pa_a1_unset_nio,   NULL,};

⌨️ 快捷键说明

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