📄 dev_am79c971.c
字号:
} 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 + -