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

📄 dev_pa_a1.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 4 页
字号:
         break;      default:         TI1570_LOG(d,"ti1570_scan_tx_dma_entry: invalid AAL-type\n");         return(FALSE);   }   /* Re-read the remaining buffer size */   buf_size = tde->ctrl_buf & TI1570_TX_DMA_DCOUNT_MASK;   /* Put the buffer address in the transmit completion ring */   if (buf_end) ti1570_update_tx_cring(d,tde);      /*     * If we have reached end of packet (EOP): clear the ACT bit,    * give back the packet-segmentation ring entry to the host,    * and increment the PSR index.    */   if (pkt_end) {      tde->ctrl_buf &= ~TI1570_TX_DMA_ACT;      /* Clear the OWN bit of the packet-segmentation ring entry */      psr_base = tde->dma_state & TI1570_TX_DMA_RING_OFFSET_MASK;      psr_index = (tde->dma_state & TI1570_TX_DMA_RING_INDEX_MASK);      psr_addr = (psr_base + psr_index) << 2;      psr_entry = physmem_copy_u32_from_vm(d->vm,psr_addr);      psr_entry &= ~TI1570_TX_RING_OWN;      physmem_copy_u32_to_vm(d->vm,psr_addr,psr_entry);            /* Increment the packet-segmentation ring index */      psr_index++;      psr_end = d->iregs[TI1570_REG_TX_PSR_SIZE] >> 16;      psr_end &= TI1570_PSR_SIZE_MASK;      if (psr_index > psr_end) {         psr_index = 0;#if DEBUG_TX_DMA         TI1570_LOG(d,"ti1570_scan_tx_dma_entry: PSR ring rotation "                    "(psr_end = %u)\n",psr_end);#endif      }      tmp = (tde->dma_state & ~TI1570_TX_DMA_RING_INDEX_MASK);      tmp |= (psr_index & TI1570_TX_DMA_RING_INDEX_MASK);      tde->dma_state = tmp;   }   /* Generate an interrupt if required */   if (tde->ctrl_buf & TI1570_TX_DMA_TCR_SELECT)    {      if (((d->iregs[TI1570_REG_STATUS] & TI1570_CFG_BP_SEL) && buf_end) ||          pkt_end)      {         d->iregs[TI1570_REG_STATUS] |= TI1570_STAT_CP_TX;         pci_dev_trigger_irq(d->vm,d->pci_dev_ti);      }   }   return(TRUE);}/* Analyze a TX DMA state table entry */static void ti1570_scan_tx_dma_entry(struct pa_a1_data *d,m_uint32_t index){   int i;   for(i=0;i<TI1570_TXDMA_PASS_COUNT;i++)      if (!ti1570_scan_tx_dma_entry_single(d,index))         break;}/* Analyze the TX schedule table */static void ti1570_scan_tx_sched_table(struct pa_a1_data *d){   m_uint32_t cw,index0,index1;   u_int i;   for(i=0;i<TI1570_TX_SCHED_ENTRY_COUNT>>1;i++) {      cw = d->tx_sched_table[i];      /* We have 2 index in TX DMA state table per word */      index0 = (cw >> TI1570_TX_SCHED_E0_SHIFT) & TI1570_TX_SCHED_ENTRY_MASK;      index1 = (cw >> TI1570_TX_SCHED_E1_SHIFT) & TI1570_TX_SCHED_ENTRY_MASK;      /* Scan the two entries (null entry => nothing to do) */      if (index0) ti1570_scan_tx_dma_entry(d,index0);      if (index1) ti1570_scan_tx_dma_entry(d,index1);   }}/* * Read a RX buffer from the host memory. */static void ti1570_read_rx_buffer(struct pa_a1_data *d,m_uint32_t addr,                                  ti1570_rx_buffer_t *rx_buf){   physmem_copy_from_vm(d->vm,rx_buf,addr,sizeof(ti1570_rx_buffer_t));   /* byte-swapping */   rx_buf->reserved = vmtoh32(rx_buf->reserved);   rx_buf->ctrl     = vmtoh32(rx_buf->ctrl);   rx_buf->atm_hdr  = vmtoh32(rx_buf->atm_hdr);   rx_buf->user     = vmtoh32(rx_buf->user);}/* Update the RX completion ring */static void ti1570_update_rx_cring(struct pa_a1_data *d,                                   ti1570_rx_dma_entry_t *rde,                                   m_uint32_t atm_hdr,                                   m_uint32_t aal5_trailer,                                   m_uint32_t err_ind,                                   m_uint32_t fbuf_valid){   m_uint32_t rcr_addr,rcr_end,aal_type,ptr,val;   ti1570_rcr_entry_t rcre;   if (rde->ctrl & TI1570_RX_DMA_RCR_SELECT) {      /* RX completion ring with interrupt */      rcr_addr = d->iregs[TI1570_REG_RCR_WI_ADDR];      rcr_addr += (d->rcr_wi_pos * sizeof(rcre));   } else {      /* RX completion ring without interrupt */      rcr_addr = d->iregs[TI1570_REG_RCR_WOI_ADDR];      rcr_addr += (d->rcr_woi_pos * sizeof(rcre));   }#if DEBUG_RECEIVE   TI1570_LOG(d,"ti1570_update_rx_cring: posting 0x%x at address 0x%x\n",              (rde->sp_ptr << 2),rcr_addr);   physmem_dump_vm(d->vm,rde->sp_ptr<<2,sizeof(ti1570_rx_buffer_t) >> 2);#endif   /* we have a RX freeze if the buffer belongs to the host */   ptr = rcr_addr + OFFSET(ti1570_rcr_entry_t,fbr_entry);   val = physmem_copy_u32_from_vm(d->vm,ptr);   if (!(val & TI1570_RCR_OWN)) {      TI1570_LOG(d,"ti1570_update_rx_cring: RX freeze...\n");      d->iregs[TI1570_REG_STATUS] |= TI1570_STAT_RX_FRZ;      return;   }   /* fill the RX completion ring entry and write it back to the host */   memset(&rcre,0,sizeof(rcre));      /* word 0: atm header from last cell received */   rcre.atm_hdr = atm_hdr;   /* word 1: error indicator */   aal_type = rde->ctrl & TI1570_RX_DMA_AAL_TYPE_MASK;   if (aal_type == TI1570_RX_DMA_AAL_AAL5)      rcre.error |= TI1570_RCR_AAL5;      rcre.error |= err_ind;   /* word 2: Start of packet */   if (fbuf_valid)      rcre.sp_addr = TI1570_RCR_VALID | rde->sp_ptr;    /* word 3: AAL5 trailer */   rcre.aal5_trailer = aal5_trailer;      /* word 4: OWN + error entry + free-buffer ring pointer */   rcre.fbr_entry = rde->fbr_entry & TI1570_RX_DMA_FB_PTR_MASK;   if (err_ind) rcre.fbr_entry |= TI1570_RCR_ERROR;   /* byte-swap and write this back to the host memory */   rcre.atm_hdr      = htonl(rcre.atm_hdr);   rcre.error        = htonl(rcre.error);   rcre.sp_addr      = htonl(rcre.sp_addr);   rcre.aal5_trailer = htonl(rcre.aal5_trailer);   rcre.fbr_entry    = htonl(rcre.fbr_entry);   physmem_copy_to_vm(d->vm,&rcre,rcr_addr,sizeof(rcre));   /* clear the active bit of the RX DMA entry */   rde->ctrl &= ~TI1570_RX_DMA_ACT;   /* update the internal position pointer */   if (rde->ctrl & TI1570_RX_DMA_RCR_SELECT) {      rcr_end = d->iregs[TI1570_REG_RX_CRING_SIZE] & TI1570_RCR_SIZE_MASK;      if ((d->rcr_wi_pos++) == rcr_end)         d->rcr_wi_pos = 0;      /* generate the appropriate IRQ */      d->iregs[TI1570_REG_STATUS] |= TI1570_STAT_CP_RX;      pci_dev_trigger_irq(d->vm,d->pci_dev_ti);   } else  {      rcr_end = (d->iregs[TI1570_REG_RX_CRING_SIZE] >> 16);      rcr_end &= TI1570_RCR_SIZE_MASK;      if ((d->rcr_woi_pos++) == rcr_end)         d->rcr_woi_pos = 0;   }}/*  * Acquire a free RX buffer. * * Returns FALSE if no buffer is available (buffer starvation). */static int ti1570_acquire_rx_buffer(struct pa_a1_data *d,                                    ti1570_rx_dma_entry_t *rde,                                    ti1570_rx_buf_holder_t *rbh,                                    m_uint32_t atm_hdr){     ti1570_rx_fbr_entry_t *fbr_entry = NULL;   m_uint32_t bp_addr,buf_addr,buf_size,buf_idx;   m_uint32_t ring_index,ring_size;   m_uint32_t buf_ptr,val;   int fifo = FALSE;   /* To keep this fucking compiler quiet */   ring_size = 0;   buf_idx = 0;   if (rde->ctrl & TI1570_RX_DMA_FIFO) {       bp_addr  = (rde->fbr_entry & TI1570_RX_DMA_FB_PTR_MASK) << 2;      buf_ptr  = physmem_copy_u32_from_vm(d->vm,bp_addr);      buf_size = d->iregs[TI1570_REG_TX_PSR_SIZE] & 0xFFFF;      fifo = TRUE;#if DEBUG_RECEIVE      TI1570_LOG(d,"ti1570_acquire_rx_buffer: acquiring FIFO buffer\n");#endif   }    else    {      ring_index = rde->fbr_entry & TI1570_RX_DMA_FB_INDEX_MASK;      fbr_entry = &d->rx_fbr_table[ring_index];#if DEBUG_RECEIVE      TI1570_LOG(d,"ti1570_acquire_rx_buffer: acquiring non-FIFO buffer, "                 "ring index=%u (0x%x)\n",ring_index,ring_index);#endif      /* Compute the number of entries in ring */      ring_size = fbr_entry->ring_size & TI1570_RX_FBR_RS_MASK;      ring_size >>= TI1570_RX_FBR_RS_SHIFT;      ring_size = (ring_size << 4) + 15 + 1;      /* Compute the buffer size */      buf_size = fbr_entry->ring_size & TI1570_RX_FBR_BS_MASK;      buf_size >>= TI1570_RX_FBR_BS_SHIFT;      /* Compute the buffer address */      buf_idx  = fbr_entry->ring_size & TI1570_RX_FBR_IDX_MASK;      bp_addr = fbr_entry->fbr_ptr + (buf_idx << 2);#if DEBUG_RECEIVE      TI1570_LOG(d,"ti1570_acquire_rx_buffer: ring size=%u (0x%x), "                 "buf size=%u ATM cells\n",ring_size,ring_size,buf_size);      TI1570_LOG(d,"ti1570_acquire_rx_buffer: buffer index=%u (0x%x), "                 "buffer ptr address = 0x%x\n",buf_idx,buf_idx,bp_addr);#endif      buf_ptr = physmem_copy_u32_from_vm(d->vm,bp_addr);   }#if DEBUG_RECEIVE   TI1570_LOG(d,"ti1570_acquire_rx_buffer: buf_ptr = 0x%x\n",buf_ptr);#endif   /* The TI1570 must own the buffer */   if (!(buf_ptr & TI1570_RX_BUFPTR_OWN)) {      TI1570_LOG(d,"ti1570_acquire_rx_buffer: no free buffer available.\n");      return(FALSE);   }   /*     * If we are using a ring, we have to clear the OWN bit and increment    * the index field.    */   if (!fifo) {      buf_ptr &= ~TI1570_RX_BUFPTR_OWN;      physmem_copy_u32_to_vm(d->vm,bp_addr,buf_ptr);      if (++buf_idx == ring_size) {#if DEBUG_RECEIVE         TI1570_LOG(d,"ti1570_acquire_rx_buffer: buf_idx=0x%x, "                    "ring_size=0x%x -> resetting buf_idx\n",                    buf_idx-1,ring_size);#endif         buf_idx = 0;      }      val = fbr_entry->ring_size & ~TI1570_RX_FBR_IDX_MASK;      val |= buf_idx;      fbr_entry->ring_size = val;   }   /* Get the buffer address */   buf_addr = (buf_ptr & TI1570_RX_BUFPTR_MASK) << 2;#if DEBUG_RECEIVE   TI1570_LOG(d,"ti1570_acquire_rx_buffer: buf_addr = 0x%x\n",buf_addr);#endif   /* Read the buffer descriptor itself and store info for caller */   rbh->buf_addr = buf_addr;   rbh->buf_size = buf_size;   ti1570_read_rx_buffer(d,buf_addr,&rbh->rx_buf);   /* Clear the control field */   physmem_copy_u32_to_vm(d->vm,buf_addr+OFFSET(ti1570_rx_buffer_t,ctrl),0);   /* Store the ATM header in data buffer */   physmem_copy_u32_to_vm(d->vm,buf_addr+OFFSET(ti1570_rx_buffer_t,atm_hdr),                          atm_hdr);   return(TRUE);}/* Insert a new free buffer in a RX DMA entry */static void ti1570_insert_rx_free_buf(struct pa_a1_data *d,                                      ti1570_rx_dma_entry_t *rde,                                      ti1570_rx_buf_holder_t *rbh){   m_uint32_t val,aal_type;   aal_type = rde->ctrl & TI1570_RX_DMA_AAL_TYPE_MASK;   /* Set current and start of buffer addresses */   rde->cb_addr = rbh->buf_addr + sizeof(ti1570_rx_buffer_t);   rde->sb_addr = rbh->buf_addr >> 2;      /* Set the buffer length */   val = rbh->buf_size;   if (aal_type == TI1570_RX_DMA_AAL_CNT)      val |= (rde->aal5_crc & 0xFFFF) << 16;   rde->cb_len = val;}/* Store a RX cell */static int ti1570_store_rx_cell(struct pa_a1_data *d,                                ti1570_rx_dma_entry_t *rde,                                m_uint8_t *atm_cell){   m_uint32_t aal_type,atm_hdr,aal5_trailer,pti,real_eop,pti_eop;   m_uint32_t prev_buf_addr,buf_len,val,ptr,cnt;   ti1570_rx_buf_holder_t rbh;      real_eop = pti_eop = FALSE;   aal_type = rde->ctrl & TI1570_RX_DMA_AAL_TYPE_MASK;         /* Extract PTI from the ATM header */   atm_hdr = ntohl(*(m_uint32_t *)&atm_cell[0]);   pti = (atm_hdr & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;   /* PTI == 0x1 => EOP */   if ((pti == 0x01) || (pti == 0x03))      pti_eop = TRUE;      if (rde->ctrl & TI1570_RX_DMA_WAIT_EOP) {      TI1570_LOG(d,"ti1570_store_rx_cell: EOP processing, not handled yet.\n");      return(FALSE);   }   /* AAL5 special processing */   if (aal_type == TI1570_RX_DMA_AAL_AAL5)   {      /* Check that we don't exceed 1366 cells for AAL5 */      /* XXX TODO */   }    else   {      /* EOP processing for non counter-based transparent-AAL packets */      if ((rde->ctrl & TI1570_RX_DMA_WAIT_EOP) && pti_eop)      {         /* XXX TODO */      }   }   /* do we have enough room in buffer ? */   buf_len = rde->cb_len & TI1570_RX_DMA_CB_LEN_MASK;   if (!buf_len) {      prev_buf_addr = rde->sb_addr << 2;      /* acquire a new 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);      /* chain the buffers (keep SOP/EOP bits intact) */      ptr = prev_buf_addr + OFFSET(ti1570_rx_buffer_t,ctrl);      val = physmem_copy_u32_from_vm(d->vm,ptr);      val |= rde->sb_addr;      physmem_copy_u32_to_vm(d->vm,ptr,val);      /* read the new buffer length */      buf_len = rde->cb_len & TI1570_RX_DMA_CB_LEN_MASK;   }   /* copy the ATM payload */#if DEBUG_RECEIVE   TI1570_LOG(d,"ti1570_store_rx_cell: storing cell payload at 0x%x "              "(buf_addr=0x%x)\n",rde->cb_addr,rde->sb_addr << 2);#endif   physmem_copy_to_vm(d->vm,&atm_cell[ATM_HDR_SIZE],                      rde->cb_addr,ATM_PAYLOAD_SIZE);   rde->cb_addr += ATM_PAYLOAD_SIZE;   /* update the current buffer length */   val = rde->cb_len & ~TI1570_RX_DMA_CB_LEN_MASK;   rde->cb_len = val | (--buf_len);#if DEBUG_RECEIVE   TI1570_LOG(d,"ti1570_store_rx_cell: new rde->cb_len = 0x%x, "

⌨️ 快捷键说明

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