📄 dev_gt.c
字号:
case GT_MPSC_CHR10: if (op_type == MTS_READ) *data = channel->chr[9] | 0x20; else channel->chr[9] = *data; break; default: /* unknown/unmanaged register */ return(FALSE); } return(TRUE);}/* Set NIO for a MPSC channel */int dev_gt96100_mpsc_set_nio(struct gt_data *d,u_int chan_id,netio_desc_t *nio){ struct mpsc_channel *channel; if (chan_id >= GT_MPSC_CHANNELS) return(-1); channel = &d->mpsc[chan_id]; if (channel->nio != NULL) return(-1); channel->nio = nio; netio_rxl_add(nio,(netio_rx_handler_t)gt_sdma_handle_rx_pkt, d,(void *)chan_id); return(0);}/* Unset NIO for a MPSC channel */int dev_gt96100_mpsc_unset_nio(struct gt_data *d,u_int chan_id){ struct mpsc_channel *channel; if (chan_id >= GT_MPSC_CHANNELS) return(-1); channel = &d->mpsc[chan_id]; if (channel->nio != NULL) { netio_rxl_remove(channel->nio); channel->nio = NULL; } return(0);}/* Set a VTTY for a MPSC channel */int dev_gt96100_mpsc_set_vtty(struct gt_data *d,u_int chan_id,vtty_t *vtty){ struct mpsc_channel *channel; if (chan_id >= GT_MPSC_CHANNELS) return(-1); channel = &d->mpsc[chan_id]; if (channel->vtty != NULL) return(-1); channel->vtty = vtty; return(0);}/* Unset a VTTY for a MPSC channel */int dev_gt96100_mpsc_unset_vtty(struct gt_data *d,u_int chan_id){ struct mpsc_channel *channel; if (chan_id >= GT_MPSC_CHANNELS) return(-1); channel = &d->mpsc[chan_id]; if (channel->vtty != NULL) { channel->vtty = NULL; } return(0);}/* ======================================================================== *//* Ethernet *//* ======================================================================== *//* Trigger/clear Ethernet interrupt if one or both port have pending events */static void gt_eth_set_int_status(struct gt_data *d){ /* Compute Ether0 summary */ if (d->eth_ports[0].icr & GT_ICR_INT_SUM) { d->ser_cause_reg |= GT_SCR_ETH0_SUM; d->int_high_cause_reg |= GT_IHCR_ETH0_SUM; } else { d->ser_cause_reg &= ~GT_SCR_ETH0_SUM; d->int_high_cause_reg &= ~GT_IHCR_ETH0_SUM; } /* Compute Ether1 summary */ if (d->eth_ports[1].icr & GT_ICR_INT_SUM) { d->ser_cause_reg |= GT_SCR_ETH1_SUM; d->int_high_cause_reg |= GT_IHCR_ETH1_SUM; } else { d->ser_cause_reg &= ~GT_SCR_ETH1_SUM; d->int_high_cause_reg &= ~GT_IHCR_ETH1_SUM; } gt96k_update_irq_status(d);}/* Update the Ethernet port interrupt status */static void gt_eth_update_int_status(struct gt_data *d,struct eth_port *port){ if (port->icr & port->imr & GT_ICR_MASK) { port->icr |= GT_ICR_INT_SUM; } else { port->icr &= ~GT_ICR_INT_SUM; } gt_eth_set_int_status(d);}/* Read a MII register */static m_uint32_t gt_mii_read(struct gt_data *d){ m_uint8_t port,reg; m_uint32_t res = 0; port = (d->smi_reg & GT_SMIR_PHYAD_MASK) >> GT_SMIR_PHYAD_SHIFT; reg = (d->smi_reg & GT_SMIR_REGAD_MASK) >> GT_SMIR_REGAD_SHIFT;#if DEBUG_MII GT_LOG(d,"MII: port 0x%4.4x, reg 0x%2.2x: reading.\n",port,reg);#endif if ((port < GT_ETH_PORTS) && (reg < 32)) { res = d->mii_regs[port][reg]; switch(reg) { case 0x00: res &= ~0x8200; /* clear reset bit and autoneg restart */ break; case 0x01:#if 0 if (d->ports[port].nio && bcm5600_mii_port_status(d,port)) d->mii_output = 0x782C; else d->mii_output = 0;#endif res = 0x782c; break; case 0x02: res = 0x40; break; case 0x03: res = 0x61d4; break; case 0x04: res = 0x1E1; break; case 0x05: res = 0x41E1; break; default: res = 0; } } /* Mark the data as ready */ res |= GT_SMIR_RVALID_FLAG; return(res);}/* Write a MII register */static void gt_mii_write(struct gt_data *d){ m_uint8_t port,reg; m_uint16_t isolation; port = (d->smi_reg & GT_SMIR_PHYAD_MASK) >> GT_SMIR_PHYAD_SHIFT; reg = (d->smi_reg & GT_SMIR_REGAD_MASK) >> GT_SMIR_REGAD_SHIFT; if ((port < GT_ETH_PORTS) && (reg < 32)) {#if DEBUG_MII GT_LOG(d,"MII: port 0x%4.4x, reg 0x%2.2x: writing 0x%4.4x\n", port,reg,d->smi_reg & GT_SMIR_DATA_MASK);#endif /* Check if PHY isolation status is changing */ if (reg == 0) { isolation = (d->smi_reg ^ d->mii_regs[port][reg]) & 0x400; if (isolation) {#if DEBUG_MII GT_LOG(d,"MII: port 0x%4.4x: generating IRQ\n",port);#endif d->eth_ports[port].icr |= GT_ICR_MII_STC; gt_eth_update_int_status(d,&d->eth_ports[port]); } } d->mii_regs[port][reg] = d->smi_reg & GT_SMIR_DATA_MASK; }}/* Handle registers of Ethernet ports */static int gt_eth_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 *d = dev->priv_data; struct eth_port *port = NULL; u_int queue; if ((offset < 0x80000) || (offset >= 0x90000)) return(FALSE); /* Determine the Ethernet port */ if ((offset >= 0x84800) && (offset < 0x88800)) port = &d->eth_ports[0]; else if ((offset >= 0x88800) && (offset < 0x8c800)) port = &d->eth_ports[1]; switch(offset) { /* SMI register */ case 0x80810: if (op_type == MTS_WRITE) { d->smi_reg = *data; if (!(d->smi_reg & GT_SMIR_OPCODE_READ)) gt_mii_write(d); } else { *data = 0; if (d->smi_reg & GT_SMIR_OPCODE_READ) *data = gt_mii_read(d); } break; /* ICR: Interrupt Cause Register */ case 0x84850: case 0x88850: if (op_type == MTS_READ) { *data = port->icr; } else { port->icr &= *data; gt_eth_update_int_status(d,port); } break; /* IMR: Interrupt Mask Register */ case 0x84858: case 0x88858: if (op_type == MTS_READ) { *data = port->imr; } else { port->imr = *data; gt_eth_update_int_status(d,port); } break; /* PCR: Port Configuration Register */ case 0x84800: case 0x88800: if (op_type == MTS_READ) *data = port->pcr; else port->pcr = *data; break; /* PCXR: Port Configuration Extend Register */ case 0x84808: case 0x88808: if (op_type == MTS_READ) { *data = port->pcxr; *data |= GT_PCXR_SPEED; } else port->pcxr = *data; break; /* PCMR: Port Command Register */ case 0x84810: case 0x88810: if (op_type == MTS_READ) *data = port->pcmr; else port->pcmr = *data; break; /* Port Status Register */ case 0x84818: case 0x88818: if (op_type == MTS_READ) *data = 0x0F; break; /* First RX descriptor */ case 0x84880: case 0x88880: case 0x84884: case 0x88884: case 0x84888: case 0x88888: case 0x8488C: case 0x8888C: queue = (offset >> 2) & 0x03; if (op_type == MTS_READ) *data = port->rx_start[queue]; else port->rx_start[queue] = *data; break; /* Current RX descriptor */ case 0x848A0: case 0x888A0: case 0x848A4: case 0x888A4: case 0x848A8: case 0x888A8: case 0x848AC: case 0x888AC: queue = (offset >> 2) & 0x03; if (op_type == MTS_READ) *data = port->rx_current[queue]; else port->rx_current[queue] = *data; break; /* Current TX descriptor */ case 0x848E0: case 0x888E0: case 0x848E4: case 0x888E4: queue = (offset >> 2) & 0x01; if (op_type == MTS_READ) *data = port->tx_current[queue]; else port->tx_current[queue] = *data; break; /* Hash Table Pointer */ case 0x84828: case 0x88828: if (op_type == MTS_READ) *data = port->ht_addr; else port->ht_addr = *data; break; /* SDCR: SDMA Configuration Register */ case 0x84840: case 0x88840: if (op_type == MTS_READ) *data = port->sdcr; else port->sdcr = *data; break; /* SDCMR: SDMA Command Register */ case 0x84848: case 0x88848: if (op_type == MTS_WRITE) { /* Start RX DMA */ if (*data & GT_SDCMR_ERD) { port->sdcmr |= GT_SDCMR_ERD; port->sdcmr &= ~GT_SDCMR_AR; } /* Abort RX DMA */ if (*data & GT_SDCMR_AR) port->sdcmr &= ~GT_SDCMR_ERD; /* Start TX High */ if (*data & GT_SDCMR_TXDH) { port->sdcmr |= GT_SDCMR_TXDH; port->sdcmr &= ~GT_SDCMR_STDH; } /* Start TX Low */ if (*data & GT_SDCMR_TXDL) { port->sdcmr |= GT_SDCMR_TXDL; port->sdcmr &= ~GT_SDCMR_STDL; } /* Stop TX High */ if (*data & GT_SDCMR_STDH) { port->sdcmr &= ~GT_SDCMR_TXDH; port->sdcmr |= GT_SDCMR_STDH; } /* Stop TX Low */ if (*data & GT_SDCMR_STDL) { port->sdcmr &= ~GT_SDCMR_TXDL; port->sdcmr |= GT_SDCMR_STDL; } } else { *data = port->sdcmr; } break; case 0x85800: case 0x89800: if (op_type == MTS_READ) { *data = port->rx_bytes; port->rx_bytes = 0; } break; case 0x85804: case 0x89804: if (op_type == MTS_READ) { *data = port->tx_bytes; port->tx_bytes = 0; } break; case 0x85808: case 0x89808: if (op_type == MTS_READ) { *data = port->rx_frames; port->rx_frames = 0; } break; case 0x8580C: case 0x8980C: if (op_type == MTS_READ) { *data = port->tx_frames; port->tx_frames = 0; } break;#if DEBUG_UNKNOWN default: if (op_type == MTS_READ) { cpu_log(cpu,"GT96100/ETH", "read access to unknown register 0x%x, pc=0x%llx\n", offset,cpu_get_pc(cpu)); } else { cpu_log(cpu,"GT96100/ETH",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -