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

📄 dev_mpc860.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 4 页
字号:
   scc_chan_info_t *scc_info;   m_uint16_t bd_offset;   ssize_t clen,tot_len;   u_char *pkt_ptr;   u_int mrblr;   int irq = FALSE;      scc_info = &scc_chan_info[scc_chan];   chan = &d->scc_chan[scc_chan];   /* Get the RBPTR (offset 0x10) register */   bd_offset = dpram_r16(d,scc_info->dpram_base+0x10);   /* Get the maximum buffer size */   mrblr = dpram_r16(d,scc_info->dpram_base+0x06);   /* Try to acquire the first descriptor */   prxd = &rxd0;   mpc860_scc_fetch_bd(d,bd_offset,prxd);   /* If we don't own the first descriptor, we cannot transmit */   if (!(rxd0.ctrl & MPC860_SCC_RXBD_CTRL_E))      return(FALSE);   pkt_ptr = pkt;   tot_len = pkt_len;   while(tot_len > 0) {      /* Write data into the RX buffer */      clen = m_min(mrblr,tot_len);      physmem_copy_to_vm(d->vm,pkt_ptr,prxd->bp,clen);      pkt_ptr += clen;      tot_len -= clen;      /* Signal IRQ ? */      if (prxd->ctrl & MPC860_SCC_RXBD_CTRL_I)         irq = TRUE;      /* Set the Last flag if we have finished */      if (!tot_len) {         /* Set the full length */         switch(chan->gsmr_lo & MPC860_GSMRL_MODE_MASK) {            case MPC860_SCC_MODE_ETH:               pkt_len += 4;               break;            case MPC860_SCC_MODE_HDLC:               pkt_len += 2;               break;         }         dpram_w16(d,prxd->offset+0x02,pkt_len);         prxd->ctrl |= MPC860_SCC_RXBD_CTRL_L;      } else {         /* Update the length field */         dpram_w16(d,prxd->offset+0x02,clen);      }      /*        * Clear the empty bit (except for the first descriptor,        * which is cleared when the full packet has been stored).       */      if (prxd != &rxd0) {         prxd->ctrl &= ~MPC860_SCC_RXBD_CTRL_E;         dpram_w16(d,prxd->offset+0x00,prxd->ctrl);      }      /* Set pointer on next RX descriptor (wrap ring if necessary) */      if (prxd->ctrl & MPC860_SCC_RXBD_CTRL_W) {         bd_offset = dpram_r16(d,scc_info->dpram_base+0x00);      } else {         bd_offset += MPC860_SCC_BD_SIZE;      }      dpram_w16(d,scc_info->dpram_base+0x10,bd_offset);      /* If this is the last descriptor, we have finished */      if (!tot_len) {         mpc860_scc_fetch_bd(d,bd_offset,&crxd);         prxd = &crxd;      }   }   /* Clear the Empty bit of the first RX descriptor and set First bit */   rxd0.ctrl &= ~MPC860_SCC_RXBD_CTRL_E;   rxd0.ctrl |= MPC860_SCC_RXBD_CTRL_F;   dpram_w16(d,rxd0.offset+0x00,rxd0.ctrl);   /* Trigger SCC IRQ */   if (irq) {      d->scc_chan[scc_chan].scce |= MPC860_SCCE_RXB;      mpc860_scc_update_irq(d,scc_chan);   }   return(TRUE);}/* Set NIO for the specified SCC channel */int mpc860_scc_set_nio(struct mpc860_data *d,u_int scc_chan,netio_desc_t *nio){   struct mpc860_scc_chan *chan;   if (!d || (scc_chan >= MPC860_SCC_NR_CHAN))      return(-1);   chan = &d->scc_chan[scc_chan];   /* check that a NIO is not already bound */   if (chan->nio != NULL)      return(-1);   chan->nio = nio;   netio_rxl_add(nio,(netio_rx_handler_t)mpc860_scc_handle_rx_pkt,                 d,(void *)scc_chan);   return(0);}/* Unset NIO of the specified SCC channel */int mpc860_scc_unset_nio(struct mpc860_data *d,u_int scc_chan){   struct mpc860_scc_chan *chan;   if (!d || (scc_chan >= MPC860_SCC_NR_CHAN))      return(-1);   chan = &d->scc_chan[scc_chan];    if (chan->nio != NULL) {      netio_rxl_remove(chan->nio);      chan->nio = NULL;   }   return(0);}/*  * SCC register access. * * SCC1: 0x0a00 to 0x0a1f * SCC2: 0x0a20 to 0x0a3f * SCC3: 0x0a40 to 0x0a5f * SCC4: 0x0a60 to 0x0a7f */static int dev_mpc860_scc_access(struct mpc860_data *d,m_uint32_t offset,                                 u_int op_size,u_int op_type,m_uint64_t *data){   struct mpc860_scc_chan *chan;   u_int scc_chan,reg;   /* Extract channel ID and register */   scc_chan = (offset >> 5) & 0x03;   reg = offset & 0x1F;   chan = &d->scc_chan[scc_chan];   switch(reg) {      /* GSMRL - General SCC mode register (Low part) */      case 0x00:         if (op_type == MTS_READ)            *data = chan->gsmr_lo;         else            chan->gsmr_lo = *data;         break;      /* GSMRH - General SCC mode register (High part) */      case 0x04:         if (op_type == MTS_READ)            *data = chan->gsmr_hi;         else            chan->gsmr_hi = *data;         break;      /* PSMR - Protocol-Specific Mode Register */      case 0x08:         if (op_type == MTS_READ)            *data = chan->psmr;         else            chan->psmr = *data;         break;      /* TOD - Transmit On Demand */      case 0x0c:         if ((op_type == MTS_WRITE) && (*data & 0x8000))            mpc860_scc_handle_tx_ring(d,scc_chan);         break;      /* SCCE - SCC Event Register */      case 0x10:         if (op_type == MTS_READ)            *data = chan->scce;         else {            chan->scce &= ~(*data);            mpc860_scc_update_irq(d,scc_chan);         }         break;      /* SCCM - SCC Mask Register */      case 0x14:         if (op_type == MTS_READ)            *data = chan->sccm;         else {            chan->sccm = *data;            mpc860_scc_update_irq(d,scc_chan);         }         break;   }   return(0);}/* ======================================================================== *//* FEC (Fast Ethernet Controller)                                           *//* ======================================================================== *//* Trigger interrupt for FEC */static void mpc860_fec_update_irq_status(struct mpc860_data *d){   u_int level,siu_bit;   level = (d->fec_ivec & MPC860_IVEC_ILEVEL_MASK) >> MPC860_IVEC_ILEVEL_SHIFT;   siu_bit = mpc860_get_siu_lvl(level);   if (d->fec_ievent & d->fec_imask)      mpc860_set_pending_irq(d,siu_bit);   else      mpc860_clear_pending_irq(d,siu_bit);}/* Fetch a FEC buffer descriptor, located in external memory */static int mpc860_fec_fetch_bd(struct mpc860_data *d,m_uint32_t bd_addr,                               struct mpc860_fec_bd *bd){   m_uint32_t w0,w1;   /* Set BD address */   bd->bd_addr = bd_addr;   w0 = physmem_copy_u32_from_vm(d->vm,bd_addr);   w1 = physmem_copy_u32_from_vm(d->vm,bd_addr+4);   bd->ctrl    = w0 >> 16;   bd->buf_len = w0 & 0xFFFF;   bd->bp      = w1;#if DEBUG_FEC   MPC_LOG(d,"fetched FEC BD at 0x%8.8x, bp=0x%8.8x, len=%d\n",           bd->bd_addr,bd->bp,bd->buf_len);#endif   return(0);}/* Handle the TX ring of the FEC (transmit a single packet) */static int mpc860_fec_handle_tx_ring_single(struct mpc860_data *d){     u_char tx_pkt[MPC860_FEC_MAX_PKT_SIZE];   struct mpc860_fec_bd txd0,ctxd,*ptxd;   m_uint32_t clen,tot_len;   u_char *pkt_ptr;   int done = FALSE;   if (!d->fec_xdes_current)      return(FALSE);        /* Try to acquire the first descriptor */   ptxd = &txd0;   mpc860_fec_fetch_bd(d,d->fec_xdes_current,ptxd);   /* If we don't own the first descriptor, we cannot transmit */   if (!(txd0.ctrl & MPC860_FEC_TXBD_CTRL_R))      return(FALSE);   /* Empty packet for now */   pkt_ptr = tx_pkt;   tot_len = 0;   do {      /* Copy data into the buffer */      clen = ptxd->buf_len;      physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->bp,clen);      pkt_ptr += clen;      tot_len += clen;      /*        * Clear the ready bit (except for the first descriptor,        * which is cleared when the full packet has been sent).       */      if (ptxd != &txd0) {         ptxd->ctrl &= ~MPC860_FEC_TXBD_CTRL_R;         physmem_copy_u16_to_vm(d->vm,ptxd->bd_addr+0x00,ptxd->ctrl);      }      /* Set pointer on next TX descriptor (wrap ring if necessary) */      if (ptxd->ctrl & MPC860_FEC_TXBD_CTRL_W) {         d->fec_xdes_current = d->fec_xdes_start;      } else {         d->fec_xdes_current += MPC860_FEC_BD_SIZE;      }      /* If this is the last descriptor, we have finished */      if (!(ptxd->ctrl & MPC860_FEC_TXBD_CTRL_L)) {         mpc860_fec_fetch_bd(d,d->fec_xdes_current,&ctxd);         ptxd = &ctxd;      } else {         done = TRUE;      }   }while(!done);   if (tot_len != 0) {#if DEBUG_FEC      MPC_LOG(d,"FEC: sending packet of %u bytes\n",tot_len);      mem_dump(log_file,tx_pkt,tot_len);#endif      /* send packet on wire */      netio_send(d->fec_nio,tx_pkt,tot_len);   }   /* Clear the Ready bit of the first TX descriptor */   txd0.ctrl &= ~MPC860_FEC_TXBD_CTRL_R;   physmem_copy_u16_to_vm(d->vm,txd0.bd_addr+0x00,txd0.ctrl);   /* Trigger FEC IRQ */   d->fec_ievent |= MPC860_IEVENT_TFINT | MPC860_IEVENT_TXB;   mpc860_fec_update_irq_status(d);   return(TRUE);}/* Handle the TX ring of the FEC (multiple pkts possible) */static int mpc860_fec_handle_tx_ring(struct mpc860_data *d){   int i;   for(i=0;i<MPC860_TXRING_PASS_COUNT;i++)      if (!mpc860_fec_handle_tx_ring_single(d))         break;   return(TRUE);}/* Handle RX packet for the Fast Ethernet Controller */static int mpc860_fec_handle_rx_pkt(netio_desc_t *nio,                                    u_char *pkt,ssize_t pkt_len,                                    struct mpc860_data *d,void *arg){   n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt;   struct mpc860_fec_bd rxd0,crxd,*prxd;   ssize_t clen,tot_len;   u_char *pkt_ptr;   if (!d->fec_rdes_current)      return(FALSE);   /* Try to acquire the first descriptor */   prxd = &rxd0;   mpc860_fec_fetch_bd(d,d->fec_rdes_current,prxd);   /* If we don't own the first descriptor, we cannot transmit */   if (!(rxd0.ctrl & MPC860_FEC_RXBD_CTRL_E))      return(FALSE);   pkt_ptr = pkt;   tot_len = pkt_len;   while(tot_len > 0) {      /* Write data into the RX buffer */      clen = m_min(d->fec_rbuf_size,tot_len);      physmem_copy_to_vm(d->vm,pkt_ptr,prxd->bp,clen);      pkt_ptr += clen;      tot_len -= clen;      /* Set the Last flag if we have finished */      if (!tot_len) {         /* Set the full length */         physmem_copy_u16_to_vm(d->vm,prxd->bd_addr+0x02,pkt_len+4);         prxd->ctrl |= MPC860_FEC_RXBD_CTRL_L;                  if (eth_addr_is_bcast(&hdr->daddr))            prxd->ctrl |= MPC860_FEC_RXBD_CTRL_BC;         else if (eth_addr_is_mcast(&hdr->daddr))            prxd->ctrl |= MPC860_FEC_RXBD_CTRL_MC;      } else {         /* Update the length field */         physmem_copy_u16_to_vm(d->vm,prxd->bd_addr+0x02,clen);      }      /*        * Clear the empty bit (except for the first descriptor,        * which is cleared when the full packet has been stored).       */      if (prxd != &rxd0) {         prxd->ctrl &= ~MPC860_FEC_RXBD_CTRL_E;         physmem_copy_u16_to_vm(d->vm,prxd->bd_addr+0x00,prxd->ctrl);      }      /* Set pointer on next RX descriptor (wrap ring if necessary) */      if (prxd->ctrl & MPC860_FEC_RXBD_CTRL_W) {         d->fec_rdes_current = d->fec_rdes_start;      } else {         d->fec_rdes_current += MPC860_FEC_BD_SIZE;      }      /* If this is the last descriptor, we have finished */      if (!tot_len) {         mpc860_fec_fetch_bd(d,d->fec_rdes_current,&crxd);         prxd = &crxd;      }   }   /* Clear the Empty bit of the first RX descriptor */   rxd0.ctrl &= ~MPC860_FEC_RXBD_CTRL_E;   physmem_copy_u16_to_vm(d->vm,rxd0.bd_addr+0x00,rxd0.ctrl);   /* Trigger FEC IRQ */   d->fec_ievent |= MPC860_IEVENT_RFINT | MPC860_IEVENT_RXB;   mpc860_fec_update_irq_status(d);   return(TRUE);}/* MII register read access */static void mpc860_fec_mii_read_access(struct mpc860_data *d,                                       u_int phy,u_int reg){   m_uint16_t res;   res = d->fec_mii_regs[reg];   switch(reg) {      case 0x00:         res = 0x1100;         break;      case 0x01:         if (d->fec_nio)            res = 0x7829;         else            res = 0;         break;      case 0x02:         res = 0x7810;         break;      case 0x03:         res = 0x0003;         break;      case 0x04:         res = 0x1E1;         break;      case 0x05:         res = 0x41E1;         break;      case 0x06:         res = 0x0004;         break;      case 0x10:         res = 0x0084;         break;      case 0x11:         res = 0x4780;         break;      case 0x12:         res = 0x4000;         break;      case 0x13:         res = 0x0094;         break;      case 0x14:         res = 0x28c8;         break;      default:         res = 0;   }   d->fec_mii_data &= 0xFFFF0000;   d->fec_mii_data |= res;}/* MII register read access */static void mpc860_fec_mii_write_access(struct mpc860_data *d,                                        u_int phy,u_int reg){#if DEBUG_FEC   MPC_LOG(d,"FEC: Writing 0x%8.8x to MII reg %d\n",           d->fec_mii_data & 0xFFFF,reg);#endif   d->fec_mii_regs[reg] = d->fec_mii_data & 0xFFFF;}/* MII register access */static void mpc860_fec_mii_access(struct mpc860_data *d){   u_int op,phy,reg;   op =  (d->fec_mii_data & MPC860_MII_OP_MASK)  >> MPC860_MII_OP_SHIFT;   phy = (d->fec_mii_data & MPC860_MII_PHY_MASK) >> MPC860_MII_PHY_SHIFT;   reg = (d->fec_mii_data & MPC860_MII_REG_MASK) >> MPC860_MII_REG_SHIFT;   switch(op) {      /* MII write */      case 0x01:            mpc860_fec_mii_write_access(d,phy,reg);         break;      /* MII read */

⌨️ 快捷键说明

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