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

📄 dev_mv64460.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 3 页
字号:
                                   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 mv64460_sdma_desc_write(struct mv64460_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 mv64460_sdma_send_buffer(struct mv64460_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 = mv64460_mpsc_get_channel_mode(d,chan_id);      switch(mode) {      case MV64460_MPSC_MODE_HDLC:         if (channel->nio != NULL)            netio_send(channel->nio,buffer,len);         break;      case MV64460_MPSC_MODE_UART:         if (channel->vtty != NULL)            vtty_put_buffer(channel->vtty,(char *)buffer,len);                     break;   }}/* Start TX DMA process */static int mv64460_sdma_tx_start(struct mv64460_data *d,                                 struct sdma_channel *chan){      u_char pkt[MV64460_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;   mv64460_sdma_desc_read(d,tx_start,ptxd);   /* If we don't own the first descriptor, we cannot transmit */   if (!(txd0.cmd_stat & MV64460_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 & MV64460_TXDESC_BC_MASK;      len >>= MV64460_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 & MV64460_TXDESC_F)) {         ptxd->cmd_stat &= ~MV64460_TXDESC_OWN;         physmem_copy_u32_to_vm(d->vm,tx_current+4,ptxd->cmd_stat);      }      //ptxd->buf_size &= 0xFFFF0000;      //physmem_copy_u32_to_vm(d->vm,tx_current,ptxd->buf_size);      tx_current = ptxd->next_ptr;      /* Last descriptor or no more desc available ? */      if (ptxd->cmd_stat & MV64460_TXDESC_L)         break;      if (!tx_current) {         abort = TRUE;         break;      }      /* Fetch the next descriptor */      mv64460_sdma_desc_read(d,tx_current,&ctxd);      ptxd = &ctxd;   }   if ((tot_len != 0) && !abort) {#if DEBUG_SDMA      MV64460_LOG(d,"SDMA%u: sending packet of %u bytes\n",tot_len);      mem_dump(log_file,pkt,tot_len);#endif      /* send it on wire */      mv64460_sdma_send_buffer(d,chan->id,pkt,tot_len);      /* Signal that a TX buffer has been transmitted */      mv64460_sdma_set_cause(d,chan->id,MV64460_SDMA_CAUSE_TXBUF0);   }   /* Clear the OWN flag of the first descriptor */   txd0.cmd_stat &= ~MV64460_TXDESC_OWN;   physmem_copy_u32_to_vm(d->vm,tx_start+4,txd0.cmd_stat);   chan->sctdp = tx_current;   if (abort || !tx_current) {      mv64460_sdma_set_cause(d,chan->id,MV64460_SDMA_CAUSE_TXEND0);      chan->sdcm &= ~MV64460_SDCMR_TXD;   }   /* Update interrupt status */   mv64460_sdma_update_int_status(d);   return(TRUE);}/* Put a packet in buffer of a descriptor */static void mv64460_sdma_rxdesc_put_pkt(struct mv64460_data *d,                                        struct sdma_desc *rxd,                                        u_char **pkt,ssize_t *pkt_len){   ssize_t len,cp_len;   len = (rxd->buf_size & MV64460_RXDESC_BS_MASK) >> MV64460_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 mv64460_sdma_handle_rxqueue(struct mv64460_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,MV64460_MAX_PKT_SIZE);   /* Copy the first RX descriptor */   if (!(rx_start = rx_current = channel->scrdp))      goto dma_error;   /* Load the first RX descriptor */   mv64460_sdma_desc_read(d,rx_start,&rxd0);#if DEBUG_SDMA   MV64460_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 & MV64460_RXDESC_OWN))         goto dma_error;      /* Put data into the descriptor buffer */      mv64460_sdma_rxdesc_put_pkt(d,rxdc,&pkt_ptr,&tot_len);      /* Clear the OWN bit */      rxdc->cmd_stat &= ~MV64460_RXDESC_OWN;      /* We have finished if the complete packet has been stored */      if (tot_len == 0) {         rxdc->cmd_stat |= MV64460_RXDESC_L;         /* Fake HDLC CRC */         if (mv64460_mpsc_get_channel_mode(d,channel->id) ==              MV64460_MPSC_MODE_HDLC)          {            rxdc->buf_size += 2;  /* Add 2 bytes for CRC */         }      }      /* Update the descriptor in host memory (but not the 1st) */      if (i != 0)         mv64460_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 */      mv64460_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 |= MV64460_RXDESC_F;   mv64460_sdma_desc_write(d,rx_start,&rxd0);   /* Indicate that we have a frame ready */   mv64460_sdma_set_cause(d,channel->id,MV64460_SDMA_CAUSE_RXBUF0);   mv64460_sdma_update_int_status(d);   return(TRUE); dma_error:   mv64460_sdma_set_cause(d,channel->id,MV64460_SDMA_CAUSE_RXERR0);   mv64460_sdma_update_int_status(d);   return(FALSE);}/* Handle RX packet for a SDMA channel */static int mv64460_sdma_handle_rx_pkt(netio_desc_t *nio,                                      u_char *pkt,ssize_t pkt_len,                                      struct mv64460_data *d,void *arg){   u_int chan_id = (int)arg;   MV64460_LOCK(d);      mv64460_sdma_handle_rxqueue(d,&d->sdma[chan_id],pkt,pkt_len);   MV64460_UNLOCK(d);   return(TRUE);}/* Input on VTTY */static void mv64460_sdma_vtty_input(vtty_t *vtty){   struct mv64460_data *d = vtty->priv_data;   struct sdma_channel *chan = &d->sdma[vtty->user_arg];   u_char c;   c = vtty_get_char(vtty);   mv64460_sdma_handle_rxqueue(d,chan,&c,1);}/* Bind a VTTY to a SDMA/MPSC channel */int mv64460_sdma_bind_vtty(struct mv64460_data *d,u_int chan_id,vtty_t *vtty){   if (chan_id >= MV64460_MPSC_CHANNELS)      return(-1);   vtty->priv_data = d;   vtty->user_arg = chan_id;   vtty->read_notifier = mv64460_sdma_vtty_input;   d->mpsc[chan_id].vtty = vtty;   return(0);}/* * SDMA registers access. */static int mv64460_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 mv64460_data *mv_data = dev->priv_data;   struct sdma_channel *channel;   int id = -1;   /* Access to SDMA channel 0 registers ? */   if ((offset >= MV64460_REG_SDMA0) &&        (offset < (MV64460_REG_SDMA0 + 0x1000)))    {      offset -= MV64460_REG_SDMA0;      id = 0;   }   /* Access to SDMA channel 1 registers ? */   if ((offset >= MV64460_REG_SDMA1) &&        (offset < (MV64460_REG_SDMA1 + 0x1000)))    {      offset -= MV64460_REG_SDMA1;      id = 1;   }      if (id == -1)      return(FALSE);   channel = &mv_data->sdma[id];   switch(offset) {      case MV64460_SDMA_SDCM:         if (op_type == MTS_READ)            ; //*data = chan->sdcm;         else {            channel->sdcm = *data;            if (channel->sdcm & MV64460_SDCMR_TXD) {               while(mv64460_sdma_tx_start(mv_data,channel))                  ;            }         }         break;      case MV64460_SDMA_SCRDP:         if (op_type == MTS_READ)            *data = channel->scrdp;         else            channel->scrdp = *data;         break;      case MV64460_SDMA_SCTDP:         if (op_type == MTS_READ)            *data = channel->sctdp;         else            channel->sctdp = *data;         break;      case MV64460_SDMA_SFTDP:         if (op_type == MTS_READ)            *data = channel->sftdp;         else            channel->sftdp = *data;         break;#if DEBUG_UNKNOWN      default:         if (op_type == MTS_READ) {            cpu_log(cpu,"MV64460/SDMA",                    "read access to unknown register 0x%x, pc=0x%llx\n",                    offset,cpu_get_pc(cpu));         } else {            cpu_log(cpu,"MV64460/SDMA",                    "write access to unknown register 0x%x, value=0x%llx, "                    "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu));         }#endif   }   return(TRUE);}/* ======================================================================== *//* MPSC (MultiProtocol Serial Controller)                                   *//* ======================================================================== *//* Get mode (HDLC,UART,...) of the specified channel */static u_int mv64460_mpsc_get_channel_mode(struct mv64460_data *d,u_int id){   struct mpsc_channel *channel;         channel = &d->mpsc[id];   return(channel->mmcrl & MV64460_MMCRL_MODE_MASK);}/* Handle a MPSC channel */static int mv64460_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 mv64460_data *mv_data = dev->priv_data;   struct mpsc_channel *channel;   u_int reg;   int id = -1;   /* Access to MPSC channel 0 registers ? */   if ((offset >= MV64460_REG_MPSC0) &&        (offset < (MV64460_REG_MPSC0 + 0x1000)))    {      offset -= MV64460_REG_MPSC0;      id = 0;   }   /* Access to SDMA channel 1 registers ? */   if ((offset >= MV64460_REG_MPSC1) &&        (offset < (MV64460_REG_MPSC1 + 0x1000)))    {      offset -= MV64460_REG_MPSC1;      id = 1;   }      if (id == -1)      return(FALSE);   channel = &mv_data->mpsc[id];   switch(offset) {      /* Main Config Register Low */      case MV64460_MPSC_MMCRL:         if (op_type == MTS_READ) {            *data = channel->mmcrl;         } else {#if DEBUG_MPSC                        MV64460_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 MV64460_MPSC_MMCRH:         if (op_type == MTS_READ)            *data = channel->mmcrh;         else            channel->mmcrh = *data;         break;      /* Protocol Config Register */      case MV64460_MPSC_MPCR:         if (op_type == MTS_READ)            *data = channel->mpcr;         else            channel->mpcr = *data;

⌨️ 快捷键说明

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