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

📄 dev_pa_a1.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 4 页
字号:
#endif   /* Read the TX buffer from host memory */   ti1570_read_tx_buffer(d,buf_addr,&tx_buf);   /* The buffer must be ready to be acquired */   if (!(tx_buf.ctrl_buf & TI1570_TX_BUFFER_RDY))      return(FALSE);   /* Put the TX buffer data into the TX DMA state entry */   tde->ctrl_buf  = tx_buf.ctrl_buf;   tde->nb_addr   = tx_buf.nb_addr << 2;   /* Read the ATM header only from the first buffer */   if (tx_buf.ctrl_buf & TI1570_TX_BUFFER_SOP) {      tde->atm_hdr   = tx_buf.atm_hdr;      tde->aal5_ctrl = tx_buf.aal5_ctrl;      tde->aal5_crc  = 0xFFFFFFFF;   }   /* Compute the current-buffer-data address */   buf_offset = tx_buf.ctrl_buf & TI1570_TX_BUFFER_OFFSET_MASK;   buf_offset >>= TI1570_TX_BUFFER_OFFSET_SHIFT;   tde->cb_addr = buf_addr + sizeof(tx_buf) + buf_offset;   /* Remember the start address of the buffer */   tde->sb_addr = buf_addr;   return(TRUE);}/* Returns TRUE if the TX DMA entry is for an AAL5 packet */static inline int ti1570_is_tde_aal5(ti1570_tx_dma_entry_t *tde){   m_uint32_t pkt_type;   pkt_type = tde->ctrl_buf & TI1570_TX_DMA_AAL_TYPE_MASK;   return(pkt_type == TI1570_TX_DMA_AAL_AAL5);}/* Update the AAL5 partial CRC */static void ti1570_update_aal5_crc(struct pa_a1_data *d,                                   ti1570_tx_dma_entry_t *tde){   tde->aal5_crc = crc32_compute(tde->aal5_crc,                                 &d->txfifo_cell[ATM_HDR_SIZE],                                 ATM_PAYLOAD_SIZE);}/*  * Update the TX DMA entry buffer offset and count when "data_len" bytes * have been transmitted. */static void ti1570_update_tx_dma_bufinfo(ti1570_tx_dma_entry_t *tde,                                         m_uint32_t buf_size,                                         m_uint32_t data_len){   m_uint32_t tmp,tot_len;   /* update the current buffer address */   tde->cb_addr += data_len;      /* set the remaining byte count */   tmp = tde->ctrl_buf & ~TI1570_TX_BUFFER_DCOUNT_MASK;   tde->ctrl_buf = tmp + (buf_size - data_len);   /* update the AAL5 count */   if (ti1570_is_tde_aal5(tde)) {      tot_len = tde->aal5_ctrl & TI1570_TX_DMA_RING_AAL5_LEN_MASK;      tot_len += data_len;      tmp = (tde->aal5_ctrl & ~TI1570_TX_DMA_RING_AAL5_LEN_MASK) + tot_len;      tde->aal5_ctrl = tmp;   }}/* Clear the TX fifo */static void ti1570_clear_tx_fifo(struct pa_a1_data *d){   d->txfifo_avail = ATM_PAYLOAD_SIZE;   d->txfifo_pos   = ATM_HDR_SIZE;   memset(d->txfifo_cell,0,ATM_CELL_SIZE);}/*  * Transmit the TX FIFO cell through the NETIO infrastructure if  * it is full. */static void ti1570_send_tx_fifo(struct pa_a1_data *d,                                ti1570_tx_dma_entry_t *tde,                                int update_aal5_crc){   if (d->txfifo_avail == 0) {#if DEBUG_TRANSMIT      TI1570_LOG(d,"ti1570_transmit_cell: transmitting to NETIO device\n");      mem_dump(log_file,d->txfifo_cell,ATM_CELL_SIZE);#endif      if (update_aal5_crc)         ti1570_update_aal5_crc(d,tde);      netio_send(d->nio,d->txfifo_cell,ATM_CELL_SIZE);      ti1570_clear_tx_fifo(d);   }}/* Add padding to the FIFO */static void ti1570_add_tx_padding(struct pa_a1_data *d,m_uint32_t len){   if (len > d->txfifo_avail) {      TI1570_LOG(d,"ti1570_add_tx_padding: trying to add too large "                 "padding (avail: 0x%x, pad: 0x%x)\n",d->txfifo_avail,len);      len = d->txfifo_avail;   }   memset(&d->txfifo_cell[d->txfifo_pos],0,len);   d->txfifo_pos += len;   d->txfifo_avail -= len;}/* Initialize an ATM cell for tranmitting */static m_uint32_t ti1570_init_tx_atm_cell(struct pa_a1_data *d,                                          ti1570_tx_dma_entry_t *tde,                                          int set_pti){   m_uint32_t buf_size,len,atm_hdr;   buf_size = tde->ctrl_buf & TI1570_TX_DMA_DCOUNT_MASK;   len = m_min(buf_size,d->txfifo_avail);#if DEBUG_TRANSMIT   TI1570_LOG(d,"ti1570_init_tx_atm_cell: data ptr=0x%x, "              "buf_size=%u (0x%x), len=%u (0x%x), atm_hdr=0x%x\n",              tde->cb_addr,buf_size,buf_size,len,len,tde->atm_hdr);#endif   /* copy the ATM header */   atm_hdr = tde->atm_hdr;   if (set_pti) {      atm_hdr &= ~ATM_PTI_NETWORK;      atm_hdr |= ATM_PTI_EOP;   }      *(m_uint32_t *)d->txfifo_cell = htonl(atm_hdr);   /* compute HEC field */   atm_insert_hec(d->txfifo_cell);   /* copy the payload and try to transmit if the FIFO is full */   if (len > 0) {      physmem_copy_from_vm(d->vm,&d->txfifo_cell[d->txfifo_pos],                           tde->cb_addr,len);      d->txfifo_pos += len;      d->txfifo_avail -= len;   }   ti1570_update_tx_dma_bufinfo(tde,buf_size,len);   return(len);}/*  * Transmit an Transparent-AAL ATM cell through the NETIO infrastructure. */static int ti1570_transmit_transp_cell(struct pa_a1_data *d,                                       ti1570_tx_dma_entry_t *tde,                                       int atm_set_eop,int *buf_end){   m_uint32_t buf_size,len;   int pkt_end,last_cell;   pkt_end = tde->ctrl_buf & TI1570_TX_DMA_EOP;   buf_size = tde->ctrl_buf & TI1570_TX_DMA_DCOUNT_MASK;   last_cell = FALSE;   if (!pkt_end) {      len = ti1570_init_tx_atm_cell(d,tde,FALSE);      ti1570_send_tx_fifo(d,tde,FALSE);      if ((buf_size - len) == 0)          *buf_end = TRUE;      return(FALSE);   }   /* this is the end of packet and the last buffer */   if (buf_size <= d->txfifo_avail)      last_cell = TRUE;   len = ti1570_init_tx_atm_cell(d,tde,last_cell & atm_set_eop);   if (last_cell) ti1570_add_tx_padding(d,d->txfifo_avail);   ti1570_send_tx_fifo(d,tde,FALSE);   return(last_cell);}/* Add the AAL5 trailer to the TX FIFO */static void ti1570_add_aal5_trailer(struct pa_a1_data *d,                                    ti1570_tx_dma_entry_t *tde){   m_uint8_t *trailer;   trailer = &d->txfifo_cell[ATM_AAL5_TRAILER_POS];   /* Control field + Length */   *(m_uint32_t *)trailer = htonl(tde->aal5_ctrl);   /* Final CRC-32 computation */   tde->aal5_crc = crc32_compute(tde->aal5_crc,                                 &d->txfifo_cell[ATM_HDR_SIZE],                                 ATM_PAYLOAD_SIZE - 4);   *(m_uint32_t *)(trailer+4) = htonl(~tde->aal5_crc);   /* Consider the FIFO as full */   d->txfifo_avail = 0;}/* * Tranmit an AAL5 cell through the NETIO infrastructure. * * Returns TRUE if this is the real end of packet. */static int ti1570_transmit_aal5_cell(struct pa_a1_data *d,                                     ti1570_tx_dma_entry_t *tde,                                     int *buf_end){   m_uint32_t buf_size,len;   int pkt_end;   pkt_end = tde->ctrl_buf & TI1570_TX_DMA_EOP;   buf_size = tde->ctrl_buf & TI1570_TX_DMA_DCOUNT_MASK;#if DEBUG_TRANSMIT   TI1570_LOG(d,"ti1570_transmit_aal5_cell: data ptr=0x%x, "              "buf_size=0x%x (%u)\n",tde->cb_addr,buf_size,buf_size);#endif   /* If this is not the end of packet, transmit the cell normally */   if (!pkt_end) {      len = ti1570_init_tx_atm_cell(d,tde,FALSE);      ti1570_send_tx_fifo(d,tde,TRUE);      if ((buf_size - len) == 0)         *buf_end = TRUE;      return(FALSE);   }   /*     * This is the end of packet, check if we need to emit a special cell    * for the AAL5 trailer.    */   if ((buf_size + ATM_AAL5_TRAILER_SIZE) <= d->txfifo_avail) {      len = ti1570_init_tx_atm_cell(d,tde,TRUE);      /* add the padding */      ti1570_add_tx_padding(d,d->txfifo_avail - ATM_AAL5_TRAILER_SIZE);      /* add the AAL5 trailer at offset 40 */      ti1570_add_aal5_trailer(d,tde);      /* we can transmit the cell */      ti1570_send_tx_fifo(d,tde,FALSE);      *buf_end = TRUE;      return(TRUE);   }   /* Transmit the cell normally */   len = ti1570_init_tx_atm_cell(d,tde,FALSE);   ti1570_add_tx_padding(d,d->txfifo_avail);   ti1570_send_tx_fifo(d,tde,TRUE);   return(FALSE);}/* Update the TX completion ring */static void ti1570_update_tx_cring(struct pa_a1_data *d,                                   ti1570_tx_dma_entry_t *tde){   m_uint32_t tcr_addr,tcr_end,val;   if (tde->ctrl_buf & TI1570_TX_DMA_TCR_SELECT) {      /* TX completion ring with interrupt */      tcr_addr = d->iregs[TI1570_REG_TCR_WI_ADDR] + (d->tcr_wi_pos * 4);   } else {      /* TX completion ring without interrupt */      tcr_addr = d->iregs[TI1570_REG_TCR_WOI_ADDR] + (d->tcr_woi_pos * 4);   }#if DEBUG_TRANSMIT   TI1570_LOG(d,"ti1570_update_tx_cring: posting 0x%x at address 0x%x\n",              tde->sb_addr,tcr_addr);   physmem_dump_vm(d->vm,tde->sb_addr,sizeof(ti1570_tx_buffer_t) >> 2);#endif   /* we have a TX freeze if the buffer belongs to the host */   val = physmem_copy_u32_from_vm(d->vm,tcr_addr);   if (!(val & TI1570_TCR_OWN)) {      d->iregs[TI1570_REG_STATUS] |= TI1570_STAT_TX_FRZ;      return;   }   /* put the buffer address in the ring */   val = tde->sb_addr >> 2;   if (tde->ctrl_buf & TI1570_TX_DMA_ABORT)      val |= TI1570_TCR_ABORT;   physmem_copy_u32_to_vm(d->vm,tcr_addr,val);   /* update the internal position pointer */   if (tde->ctrl_buf & TI1570_TX_DMA_TCR_SELECT) {      tcr_end = d->iregs[TI1570_REG_TX_CRING_SIZE] & TI1570_TCR_SIZE_MASK;      if ((d->tcr_wi_pos++) == tcr_end)         d->tcr_wi_pos = 0;   } else  {      tcr_end = (d->iregs[TI1570_REG_TX_CRING_SIZE] >> 16);      tcr_end &= TI1570_TCR_SIZE_MASK;      if ((d->tcr_woi_pos++) == tcr_end)         d->tcr_woi_pos = 0;   }}/* Analyze a TX DMA state table entry */static int ti1570_scan_tx_dma_entry_single(struct pa_a1_data *d,                                           m_uint32_t index){   ti1570_tx_dma_entry_t *tde;   m_uint32_t psr_base,psr_addr,psr_entry,psr_end;   m_uint32_t buf_addr,buf_size,pkt_type,tmp;   m_uint32_t psr_index;   int atm_set_eop = 0;   int pkt_end,buf_end = 0;   tde = &d->tx_dma_table[index];   /* The DMA channel state flag must be ON */   if (!(tde->dma_state & TI1570_TX_DMA_ON))      return(FALSE);#if DEBUG_TX_DMA   /* We have a running DMA channel */   TI1570_LOG(d,"ti1570_scan_tx_dma_entry: TX DMA entry %u is ON "              "(ctrl_buf = 0x%x)\n",index,tde->ctrl_buf);#endif   /* Is this the start of a new packet ? */   if (!(tde->ctrl_buf & TI1570_TX_DMA_ACT))   {#if DEBUG_TX_DMA      TI1570_LOG(d,"ti1570_scan_tx_dma_entry: TX DMA entry %u is not ACT\n",                 index);#endif      /* No packet yet, fetch it from the packet-segmentation ring */      psr_base = tde->dma_state & TI1570_TX_DMA_RING_OFFSET_MASK;      psr_index = tde->dma_state & TI1570_TX_DMA_RING_INDEX_MASK;      /* Compute address of the current packet segmentation ring entry */      psr_addr = (psr_base + psr_index) << 2;      psr_entry = physmem_copy_u32_from_vm(d->vm,psr_addr);#if DEBUG_TX_DMA      TI1570_LOG(d,"ti1570_scan_tx_dma_entry: psr_addr = 0x%x, "                 "psr_entry = 0x%x\n",psr_addr,psr_entry);#endif      /* The packet-segmentation-ring entry is owned by host, quit now */      if (!(psr_entry & TI1570_TX_RING_OWN))         return(FALSE);      /* Acquire the first buffer (it MUST be in the ready state) */      buf_addr = (psr_entry & TI1570_TX_RING_PTR_MASK) << 2;      if (!ti1570_acquire_tx_buffer(d,tde,buf_addr)) {         TI1570_LOG(d,"ti1570_scan_tx_dma_entry: PSR entry with OWN bit set "                    "but buffer without RDY bit set.\n");         return(FALSE);      }      /* Set ACT bit for the DMA channel */      tde->ctrl_buf |= TI1570_TX_DMA_ACT;   }   /* Compute the remaining size and determine the packet type */   buf_size = tde->ctrl_buf & TI1570_TX_DMA_DCOUNT_MASK;   pkt_type = tde->ctrl_buf & TI1570_TX_DMA_AAL_TYPE_MASK;   pkt_end  = tde->ctrl_buf & TI1570_TX_DMA_EOP;#if DEBUG_TRANSMIT   TI1570_LOG(d,"ti1570_scan_tx_dma_entry: ctrl_buf=0x%8.8x, "              "cb_addr=0x%8.8x, atm_hdr=0x%8.8x, dma_state=0x%8.8x\n",              tde->ctrl_buf, tde->cb_addr, tde->atm_hdr, tde->dma_state);   TI1570_LOG(d,"ti1570_scan_tx_dma_entry: nb_addr=0x%8.8x, "              "sb_addr=0x%8.8x, aal5_crc=0x%8.8x, aal5_ctrl=0x%8.8x\n",              tde->nb_addr, tde->sb_addr, tde->aal5_crc, tde->aal5_ctrl);#endif   /*     * If the current buffer is now empty and if this is not the last    * buffer in the current packet, try to fetch a new buffer.    * If the next buffer is not yet ready, we have finished.    */   if (!buf_size && !pkt_end && !ti1570_acquire_tx_buffer(d,tde,tde->nb_addr))      return(FALSE);   switch(pkt_type) {      case TI1570_TX_DMA_AAL_TRWPTI:         atm_set_eop = 1;      case TI1570_TX_DMA_AAL_TRWOPTI:         /* Transmit the ATM cell transparently */         pkt_end = ti1570_transmit_transp_cell(d,tde,atm_set_eop,&buf_end);         break;      case TI1570_TX_DMA_AAL_AAL5:         pkt_end = ti1570_transmit_aal5_cell(d,tde,&buf_end);

⌨️ 快捷键说明

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