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

📄 dev_am79c971.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 3 页
字号:
   } else {      cpu_log(cpu,d->name,"write access to CSR %d, value=0x%x\n",d->rap,*data);   }#endif   switch(d->rap) {      case 0:  /* CSR0: Controller Status and Control Register */         if (op_type == MTS_READ) {            //AM79C971_LOG(d,"reading CSR0 (val=0x%4.4x)\n",d->csr[0]);            *data = d->csr[0];         } else {            /*              * The STOP bit clears other bits.             * It has precedence over INIT and START bits.             */            if (*data & AM79C971_CSR0_STOP) {               //AM79C971_LOG(d,"stopping interface!\n");               d->csr[0] = AM79C971_CSR0_STOP;               d->tx_pos = d->rx_pos = 0;               am79c971_update_irq_status(d);               break;            }                        /* These bits are cleared when set to 1 */            mask  = AM79C971_CSR0_BABL | AM79C971_CSR0_CERR;            mask |= AM79C971_CSR0_MISS | AM79C971_CSR0_MERR;            mask |= AM79C971_CSR0_IDON;            if (++d->rx_tx_clear_count == 3) {               mask |= AM79C971_CSR0_RINT | AM79C971_CSR0_TINT;               d->rx_tx_clear_count = 0;            }            d->csr[0] &= ~(*data & mask);            /* Save the Interrupt Enable bit */            d->csr[0] |= *data & AM79C971_CSR0_IENA;            /* If INIT bit is set, fetch the initialization block */            if (*data & AM79C971_CSR0_INIT) {               d->csr[0] |= AM79C971_CSR0_INIT;               d->csr[0] &= ~AM79C971_CSR0_STOP;               am79c971_fetch_init_block(d);            }            /* If STRT bit is set, clear the stop bit */            if (*data & AM79C971_CSR0_STRT) {               //AM79C971_LOG(d,"enabling interface!\n");               d->csr[0] |= AM79C971_CSR0_STRT;               d->csr[0] &= ~AM79C971_CSR0_STOP;               am79c971_update_rx_tx_on_bits(d);            }            /* Update IRQ status */            am79c971_update_irq_status(d);         }         break;      case 6:   /* CSR6: RX/TX Descriptor Table Length */         if (op_type == MTS_WRITE) {            d->rx_l2len = (*data >> 8) & 0x0F;            d->tx_l2len = (*data >> 12) & 0x0F;            am79c971_update_rx_tx_len(d);         } else {            *data = (d->tx_l2len << 12) | (d->rx_l2len << 8);         }         break;                  case 15:  /* CSR15: Mode */         if (op_type == MTS_WRITE) {            d->csr[15] = *data;            am79c971_update_rx_tx_on_bits(d);         } else {            *data = d->csr[15];         }         break;      case 88:         if (op_type == MTS_READ) {            switch(d->type) {               case AM79C971_TYPE_100BASE_TX:                  *data = 0x2623003;                  break;               default:                  *data = 0;                  break;            }         }         break;      default:         if (op_type == MTS_READ) {            *data = d->csr[d->rap];         } else {            d->csr[d->rap] = *data;         }#if DEBUG_UNKNOWN         if (op_type == MTS_READ) {            cpu_log(cpu,d->name,"read access to unknown CSR %d\n",d->rap);         } else {            cpu_log(cpu,d->name,"write access to unknown CSR %d, value=0x%x\n",                    d->rap,*data);         }#endif   }}/* BDP (BCR Data Port) access */static void am79c971_bdp_access(cpu_gen_t *cpu,struct am79c971_data *d,                                u_int op_type,m_uint64_t *data){   u_int mii_phy,mii_reg;#if DEBUG_BCR_REGS   if (op_type == MTS_READ) {      cpu_log(cpu,d->name,"read access to BCR %d\n",d->rap);   } else {      cpu_log(cpu,d->name,"write access to BCR %d, value=0x%x\n",d->rap,*data);   }#endif   switch(d->rap) {      case 9:         if (op_type == MTS_READ)            *data = 1;         break;      case 34:  /* BCR34: MII Management Data Register */         mii_phy = (d->bcr[33] >> 5) & 0x1F;         mii_reg = (d->bcr[33] >> 0) & 0x1F;         if (op_type == MTS_READ)            *data = mii_reg_read(d,mii_phy,mii_reg);         //else         //mii_reg_write(d,mii_phy,mii_reg,*data);         break;      default:         if (op_type == MTS_READ) {            *data = d->bcr[d->rap];         } else {            d->bcr[d->rap] = *data;         }#if DEBUG_UNKNOWN         if (op_type == MTS_READ) {            cpu_log(cpu,d->name,"read access to unknown BCR %d\n",d->rap);         } else {            cpu_log(cpu,d->name,                    "write access to unknown BCR %d, value=0x%x\n",                    d->rap,*data);         }#endif   }}/* * dev_am79c971_access() */void *dev_am79c971_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 am79c971_data *d = dev->priv_data;   if (op_type == MTS_READ)      *data = 0;#if DEBUG_ACCESS   if (op_type == MTS_READ) {      cpu_log(cpu,d->name,"read  access to offset=0x%x, pc=0x%llx, size=%u\n",              offset,cpu_get_pc(cpu),op_size);   } else {      cpu_log(cpu,d->name,"write access to offset=0x%x, pc=0x%llx, "              "val=0x%llx, size=%u\n",offset,cpu_get_pc(cpu),*data,op_size);   }#endif   AM79C971_LOCK(d);   switch(offset) {      case 0x14:  /* RAP (Register Address Pointer) */         if (op_type == MTS_WRITE) {            d->rap = *data & 0xFF;         } else {            *data = d->rap;         }         break;      case 0x10:  /* RDP (Register Data Port) */         am79c971_rdp_access(cpu,d,op_type,data);         break;      case 0x1c:  /* BDP (BCR Data Port) */         am79c971_bdp_access(cpu,d,op_type,data);         break;   }   AM79C971_UNLOCK(d);   return NULL;}/* Read a RX descriptor */static int rxdesc_read(struct am79c971_data *d,m_uint32_t rxd_addr,                       struct rx_desc *rxd){   m_uint32_t buf[4];   m_uint8_t sw_style;   /* Get the software style */   sw_style = d->bcr[20];   /* Read the descriptor from VM physical RAM */   physmem_copy_from_vm(d->vm,&buf,rxd_addr,sizeof(struct rx_desc));   switch(sw_style) {      case 2:         rxd->rmd[0] = vmtoh32(buf[0]);  /* rb addr */         rxd->rmd[1] = vmtoh32(buf[1]);  /* own flag, ... */         rxd->rmd[2] = vmtoh32(buf[2]);  /* rfrtag, mcnt, ... */         rxd->rmd[3] = vmtoh32(buf[3]);  /* user */         break;      case 3:         rxd->rmd[0] = vmtoh32(buf[2]);  /* rb addr */         rxd->rmd[1] = vmtoh32(buf[1]);  /* own flag, ... */         rxd->rmd[2] = vmtoh32(buf[0]);  /* rfrtag, mcnt, ... */         rxd->rmd[3] = vmtoh32(buf[3]);  /* user */         break;      default:         AM79C971_LOG(d,"invalid software style %u!\n",sw_style);         return(-1);        }   return(0);}/* Set the address of the next RX descriptor */static inline void rxdesc_set_next(struct am79c971_data *d){   d->rx_pos++;   if (d->rx_pos == d->rx_len)      d->rx_pos = 0;}/* Compute the address of the current RX descriptor */static inline m_uint32_t rxdesc_get_current(struct am79c971_data *d){   return(d->rx_start + (d->rx_pos * sizeof(struct rx_desc)));}/* Put a packet in buffer of a descriptor */static void rxdesc_put_pkt(struct am79c971_data *d,struct rx_desc *rxd,                           u_char **pkt,ssize_t *pkt_len){   ssize_t len,cp_len;   /* Compute the data length to copy */   len = ~((rxd->rmd[1] & AM79C971_RMD1_LEN) - 1);   len &= AM79C971_RMD1_LEN;   cp_len = m_min(len,*pkt_len);         /* Copy packet data to the VM physical RAM */#if DEBUG_RECEIVE   AM79C971_LOG(d,"am79c971_handle_rxring: storing %u bytes at 0x%8.8x\n",                cp_len, rxd->rmd[0]);#endif   physmem_copy_to_vm(d->vm,*pkt,rxd->rmd[0],cp_len);   *pkt += cp_len;   *pkt_len -= cp_len;}/* * Put a packet in the RX ring. */static int am79c971_receive_pkt(struct am79c971_data *d,                                u_char *pkt,ssize_t pkt_len){    m_uint32_t rx_start,rx_current,rx_next,rxdn_rmd1;   struct rx_desc rxd0,rxdn,*rxdc;   ssize_t tot_len = pkt_len;   u_char *pkt_ptr = pkt;   m_uint8_t sw_style;   int i;   /* Truncate the packet if it is too big */   pkt_len = m_min(pkt_len,AM79C971_MAX_PKT_SIZE);   /* Copy the current rxring descriptor */   rx_start = rx_current = rxdesc_get_current(d);   rxdesc_read(d,rx_start,&rxd0);      /* We must have the first descriptor... */   if (!(rxd0.rmd[1] & AM79C971_RMD1_OWN))      return(FALSE);   for(i=0,rxdc=&rxd0;;i++)   {#if DEBUG_RECEIVE      AM79C971_LOG(d,"am79c971_handle_rxring: i=%d, addr=0x%8.8x: "                   "rmd[0]=0x%x, rmd[1]=0x%x, rmd[2]=0x%x, rmd[3]=0x%x\n",                   i,rx_current,                   rxdc->rmd[0],rxdc->rmd[1],rxdc->rmd[2],rxdc->rmd[3]);#endif      /* Put data into the descriptor buffer */      rxdesc_put_pkt(d,rxdc,&pkt_ptr,&tot_len);      /* Go to the next descriptor */      rxdesc_set_next(d);      /* If this is not the first descriptor, clear the OWN bit */      if (i != 0)         rxdc->rmd[1] &= ~AM79C971_RMD1_OWN;      /* If we have finished, mark the descriptor as end of packet */      if (tot_len == 0) {         rxdc->rmd[1] |= AM79C971_RMD1_ENP;         physmem_copy_u32_to_vm(d->vm,rx_current+4,rxdc->rmd[1]);         /* Get the software style */         sw_style = d->bcr[20];         /* Update the message byte count field */         rxdc->rmd[2] &= ~AM79C971_RMD2_LEN;         rxdc->rmd[2] |= pkt_len + 4;         switch(sw_style) {            case 2:               physmem_copy_u32_to_vm(d->vm,rx_current+8,rxdc->rmd[2]);               break;            case 3:               physmem_copy_u32_to_vm(d->vm,rx_current,rxdc->rmd[2]);               break;            default:               AM79C971_LOG(d,"invalid software style %u!\n",sw_style);         }         break;      }      /* Try to acquire the next descriptor */      rx_next = rxdesc_get_current(d);      rxdn_rmd1 = physmem_copy_u32_from_vm(d->vm,rx_next+4);      if (!(rxdn_rmd1 & AM79C971_RMD1_OWN)) {         rxdc->rmd[1] |= AM79C971_RMD1_ERR | AM79C971_RMD1_BUFF;         rxdc->rmd[1] |= AM79C971_RMD1_ENP;         physmem_copy_u32_to_vm(d->vm,rx_current+4,rxdc->rmd[1]);         break;      }

⌨️ 快捷键说明

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