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

📄 dev_gt.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 5 页
字号:
      d->int_high_cause_reg |= GT_IHCR_SDMA_SUM;   } else {      d->ser_cause_reg &= ~GT_SCR_SDMA_SUM;      d->int_high_cause_reg &= ~GT_IHCR_SDMA_SUM;   }   gt96k_update_irq_status(d);}/* Update SDMA interrupt status for the specified channel */static void gt_sdma_update_channel_int_status(struct gt_data *d,u_int chan_id){   m_uint32_t ch_st;   /* Get the status of the specified SDMA channel */   ch_st = d->sdma_cause_reg & (0x0000000F << (chan_id << 2));   if (ch_st)      d->ser_cause_reg |= GT_SCR_SDMA0_SUM << (chan_id << 1);   else      d->ser_cause_reg &= ~(GT_SCR_SDMA0_SUM << (chan_id << 1));   gt_sdma_update_int_status(d);}/* Set SDMA cause register for a channel */static inline void gt_sdma_set_cause(struct gt_data *d,u_int chan_id,                                     u_int value){   d->sdma_cause_reg |= value << (chan_id << 2);}/* Read a SDMA descriptor from memory */static void gt_sdma_desc_read(struct gt_data *d,m_uint32_t addr,                              struct sdma_desc *desc){   physmem_copy_from_vm(d->vm,desc,addr,sizeof(struct sdma_desc));   /* byte-swapping */   desc->buf_size = vmtoh32(desc->buf_size);   desc->cmd_stat = vmtoh32(desc->cmd_stat);   desc->next_ptr = vmtoh32(desc->next_ptr);   desc->buf_ptr  = vmtoh32(desc->buf_ptr);}/* Write a SDMA descriptor to memory */static void gt_sdma_desc_write(struct gt_data *d,m_uint32_t addr,                               struct sdma_desc *desc){   struct sdma_desc tmp;      /* byte-swapping */   tmp.cmd_stat = vmtoh32(desc->cmd_stat);   tmp.buf_size = vmtoh32(desc->buf_size);   tmp.next_ptr = vmtoh32(desc->next_ptr);   tmp.buf_ptr  = vmtoh32(desc->buf_ptr);   physmem_copy_to_vm(d->vm,&tmp,addr,sizeof(struct sdma_desc));}/* Send contents of a SDMA buffer */static void gt_sdma_send_buffer(struct gt_data *d,u_int chan_id,                                u_char *buffer,m_uint32_t len){   struct mpsc_channel *channel;   u_int mode;   channel = &d->mpsc[chan_id];   mode = channel->mmcrl & GT_MMCRL_MODE_MASK;   switch(mode) {      case GT_MPSC_MODE_HDLC:         if (channel->nio != NULL)            netio_send(channel->nio,buffer,len);         break;      case GT_MPSC_MODE_UART:         if (channel->vtty != NULL)            vtty_put_buffer(channel->vtty,(char *)buffer,len);         break;   }}/* Start TX DMA process */static int gt_sdma_tx_start(struct gt_data *d,struct sdma_channel *chan){      u_char pkt[GT_MAX_PKT_SIZE],*pkt_ptr;   struct sdma_desc txd0,ctxd,*ptxd;   m_uint32_t tx_start,tx_current;   m_uint32_t len,tot_len;   int abort = FALSE;   tx_start = tx_current = chan->sctdp;   if (!tx_start)      return(FALSE);   ptxd = &txd0;   gt_sdma_desc_read(d,tx_start,ptxd);   /* If we don't own the first descriptor, we cannot transmit */   if (!(txd0.cmd_stat & GT_TXDESC_OWN))      return(FALSE);   /* Empty packet for now */   pkt_ptr = pkt;   tot_len = 0;   for(;;)   {      /* Copy packet data to the buffer */      len = (ptxd->buf_size & GT_TXDESC_BC_MASK) >> GT_TXDESC_BC_SHIFT;      physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->buf_ptr,len);      pkt_ptr += len;      tot_len += len;      /* Clear the OWN bit if this is not the first descriptor */      if (!(ptxd->cmd_stat & GT_TXDESC_F)) {         ptxd->cmd_stat &= ~GT_TXDESC_OWN;         physmem_copy_u32_to_vm(d->vm,tx_current+4,ptxd->cmd_stat);      }      tx_current = ptxd->next_ptr;      /* Last descriptor or no more desc available ? */      if (ptxd->cmd_stat & GT_TXDESC_L)         break;      if (!tx_current) {         abort = TRUE;         break;      }      /* Fetch the next descriptor */      gt_sdma_desc_read(d,tx_current,&ctxd);      ptxd = &ctxd;   }   if ((tot_len != 0) && !abort) {#if DEBUG_SDMA      GT_LOG(d,"SDMA%u: sending packet of %u bytes\n",tot_len);      mem_dump(log_file,pkt,tot_len);#endif      /* send it on wire */      gt_sdma_send_buffer(d,chan->id,pkt,tot_len);      /* Signal that a TX buffer has been transmitted */      gt_sdma_set_cause(d,chan->id,GT_SDMA_CAUSE_TXBUF0);   }   /* Clear the OWN flag of the first descriptor */   txd0.cmd_stat &= ~GT_TXDESC_OWN;   physmem_copy_u32_to_vm(d->vm,tx_start+4,txd0.cmd_stat);   chan->sctdp = tx_current;   if (abort || !tx_current) {      gt_sdma_set_cause(d,chan->id,GT_SDMA_CAUSE_TXEND0);      chan->sdcm &= ~GT_SDCMR_TXD;   }   /* Update interrupt status */   gt_sdma_update_channel_int_status(d,chan->id);   return(TRUE);}/* Put a packet in buffer of a descriptor */static void gt_sdma_rxdesc_put_pkt(struct gt_data *d,struct sdma_desc *rxd,                                   u_char **pkt,ssize_t *pkt_len){   ssize_t len,cp_len;   len = (rxd->buf_size & GT_RXDESC_BS_MASK) >> GT_RXDESC_BS_SHIFT;      /* compute the data length to copy */   cp_len = m_min(len,*pkt_len);      /* copy packet data to the VM physical RAM */   physmem_copy_to_vm(d->vm,*pkt,rxd->buf_ptr,cp_len);         /* set the byte count in descriptor */   rxd->buf_size |= cp_len;   *pkt += cp_len;   *pkt_len -= cp_len;}/* Put a packet into SDMA buffers */static int gt_sdma_handle_rxqueue(struct gt_data *d,                                  struct sdma_channel *channel,                                  u_char *pkt,ssize_t pkt_len){   m_uint32_t rx_start,rx_current;   struct sdma_desc rxd0,rxdn,*rxdc;   ssize_t tot_len = pkt_len;   u_char *pkt_ptr = pkt;   int i;   /* Truncate the packet if it is too big */   pkt_len = m_min(pkt_len,GT_MAX_PKT_SIZE);   /* Copy the first RX descriptor */   if (!(rx_start = rx_current = channel->scrdp))      goto dma_error;   /* Load the first RX descriptor */   gt_sdma_desc_read(d,rx_start,&rxd0);#if DEBUG_SDMA   GT_LOG(d,"SDMA channel %u: reading desc at 0x%8.8x "          "[buf_size=0x%8.8x,cmd_stat=0x%8.8x,"          "next_ptr=0x%8.8x,buf_ptr=0x%8.8x]\n",          channel->id,rx_start,rxd0.buf_size,rxd0.cmd_stat,          rxd0.next_ptr,rxd0.buf_ptr);#endif   for(i=0,rxdc=&rxd0;tot_len>0;i++)   {      /* We must own the descriptor */      if (!(rxdc->cmd_stat & GT_RXDESC_OWN))         goto dma_error;      /* Put data into the descriptor buffer */      gt_sdma_rxdesc_put_pkt(d,rxdc,&pkt_ptr,&tot_len);      /* Clear the OWN bit */      rxdc->cmd_stat &= ~GT_RXDESC_OWN;      /* We have finished if the complete packet has been stored */      if (tot_len == 0) {         rxdc->cmd_stat |= GT_RXDESC_L;         rxdc->buf_size += 2;  /* Add 2 bytes for CRC */      }      /* Update the descriptor in host memory (but not the 1st) */      if (i != 0)         gt_sdma_desc_write(d,rx_current,rxdc);      /* Get address of the next descriptor */      rx_current = rxdc->next_ptr;      if (tot_len == 0)         break;      if (!rx_current)         goto dma_error;      /* Read the next descriptor from VM physical RAM */      gt_sdma_desc_read(d,rx_current,&rxdn);      rxdc = &rxdn;   }   /* Update the RX pointers */   channel->scrdp = rx_current;          /* Update the first RX descriptor */   rxd0.cmd_stat |= GT_RXDESC_F;   gt_sdma_desc_write(d,rx_start,&rxd0);   /* Indicate that we have a frame ready */   gt_sdma_set_cause(d,channel->id,GT_SDMA_CAUSE_RXBUF0);   gt_sdma_update_channel_int_status(d,channel->id);   return(TRUE); dma_error:   gt_sdma_set_cause(d,channel->id,GT_SDMA_CAUSE_RXERR0);   gt_sdma_update_channel_int_status(d,channel->id);   return(FALSE);}/* Handle RX packet for a SDMA channel */static int gt_sdma_handle_rx_pkt(netio_desc_t *nio,                                 u_char *pkt,ssize_t pkt_len,                                 struct gt_data *d,void *arg){   struct sdma_channel *channel;   u_int chan_id = (int)arg;   u_int group_id;   GT_LOCK(d);   /* Find the SDMA group associated to the MPSC channel for receiving */   group_id = (d->sgcr >> chan_id) & 0x01;   channel  = &d->sdma[group_id][chan_id];      gt_sdma_handle_rxqueue(d,channel,pkt,pkt_len);   GT_UNLOCK(d);   return(TRUE);}/* Handle a SDMA channel */static int gt_sdma_access(cpu_gen_t *cpu,struct vdevice *dev,                          m_uint32_t offset,u_int op_size,u_int op_type,                          m_uint64_t *data){   struct gt_data *gt_data = dev->priv_data;   struct sdma_channel *channel;   u_int group,chan_id,reg;   if ((offset & 0x000F00) != 0x000900)      return(FALSE);   /* Decode group, channel and register */   group   = (offset >> 20) & 0x0F;   chan_id = (offset >> 16) & 0x0F;   reg     = offset & 0xFFFF;   if ((group >= GT_SDMA_GROUPS) || (chan_id >= GT_SDMA_CHANNELS)) {      cpu_log(cpu,"GT96100","invalid SDMA register 0x%8.8x\n",offset);      return(TRUE);   }   channel = &gt_data->sdma[group][chan_id];#if 0   printf("SDMA: access to reg 0x%6.6x (group=%u, channel=%u)\n",          offset, group, chan_id);#endif      switch(reg) {      /* Configuration Register */      case GT_SDMA_SDC:         break;      /* Command Register */      case GT_SDMA_SDCM:            if (op_type == MTS_WRITE) {            channel->sdcm = *data;            if (channel->sdcm & GT_SDCMR_TXD) {#if DEBUG_SDMA               cpu_log(cpu,"GT96100-SDMA","starting TX transfer (%u/%u)\n",                       group,chan_id);#endif               while(gt_sdma_tx_start(gt_data,channel))                  ;            }         } else {            *data = 0xFF; //0xFFFFFFFF;         }         break;      /* Current RX descriptor */      case GT_SDMA_SCRDP:         if (op_type == MTS_READ)            *data = channel->scrdp;         else            channel->scrdp = *data;         break;      /* Current TX desc. pointer */      case GT_SDMA_SCTDP:         if (op_type == MTS_READ)            *data = channel->sctdp;         else            channel->sctdp = *data;         break;      /* First TX desc. pointer */      case GT_SDMA_SFTDP:         if (op_type == MTS_READ)            *data = channel->sftdp;         else            channel->sftdp = *data;         break;      default:         /* unknown/unmanaged register */         return(FALSE);   }   return(TRUE);}/* ======================================================================== *//* MPSC (MultiProtocol Serial Controller)                                   *//* ======================================================================== *//* Handle a MPSC channel */static int gt_mpsc_access(cpu_gen_t *cpu,struct vdevice *dev,                          m_uint32_t offset,u_int op_size,u_int op_type,                          m_uint64_t *data){   struct gt_data *gt_data = dev->priv_data;   struct mpsc_channel *channel;   u_int chan_id,reg,reg2;   if ((offset & 0x000F00) != 0x000A00)      return(FALSE);   /* Decode channel ID and register */   chan_id = offset >> 15;   reg     = offset & 0xFFF;   if (chan_id >= GT_MPSC_CHANNELS)      return(FALSE);   channel = &gt_data->mpsc[chan_id];   switch(reg) {      /* Main Config Register Low */      case GT_MPSC_MMCRL:         if (op_type == MTS_READ) {            *data = channel->mmcrl;         } else {#if DEBUG_MPSC                        GT_LOG(gt_data,"MPSC channel %u set in mode %llu\n",                   chan_id,*data & 0x07);#endif            channel->mmcrl = *data;         }         break;      /* Main Config Register High */      case GT_MPSC_MMCRH:         if (op_type == MTS_READ)            *data = channel->mmcrh;         else            channel->mmcrh = *data;         break;      /* Protocol Config Register */      case GT_MPSC_MPCR:         if (op_type == MTS_READ)            *data = channel->mpcr;         else            channel->mpcr = *data;         break;      /* Channel registers */      case GT_MPSC_CHR1:       case GT_MPSC_CHR2:       case GT_MPSC_CHR3:      case GT_MPSC_CHR4:       case GT_MPSC_CHR5:       case GT_MPSC_CHR6:      case GT_MPSC_CHR7:       case GT_MPSC_CHR8:       case GT_MPSC_CHR9:         //case GT_MPSC_CHR10:         reg2 = (reg - GT_MPSC_CHR1) >> 2;         if (op_type == MTS_READ)            *data = channel->chr[reg2];         else            channel->chr[reg2] = *data;         break;

⌨️ 快捷键说明

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