--- upstream/dynamips-0.2.6-RC5/dev_gt.c 2007/10/06 16:09:07 6 +++ upstream/dynamips-0.2.7/dev_gt.c 2007/10/06 16:29:14 10 @@ -1,5 +1,5 @@ /* - * Cisco 7200 (Predator) simulation platform. + * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * Galileo GT64010/GT64120A/GT96100A system controller. @@ -18,7 +18,8 @@ #include "utils.h" #include "net.h" -#include "mips64.h" +#include "cpu.h" +#include "vm.h" #include "dynamips.h" #include "memory.h" #include "device.h" @@ -386,9 +387,9 @@ *data = swap32(gt_data->dma[ch].reg_name); /* Handle a DMA channel */ -static int gt_dma_access(cpu_mips_t *cpu,struct vdevice *dev, - m_uint32_t offset,u_int op_size,u_int op_type, - m_uint64_t *data) +static int gt_dma_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 *gt_data = dev->priv_data; @@ -458,7 +459,7 @@ /* * dev_gt64010_access() */ -void *dev_gt64010_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, +void *dev_gt64010_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 *gt_data = dev->priv_data; @@ -566,10 +567,10 @@ default: if (op_type == MTS_READ) { cpu_log(cpu,"GT64010","read from addr 0x%x, pc=0x%llx\n", - offset,cpu->pc); + offset,cpu_get_pc(cpu)); } else { cpu_log(cpu,"GT64010","write to addr 0x%x, value=0x%llx, " - "pc=0x%llx\n",offset,*data,cpu->pc); + "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu)); } #endif } @@ -580,7 +581,7 @@ /* * dev_gt64120_access() */ -void *dev_gt64120_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, +void *dev_gt64120_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 *gt_data = dev->priv_data; @@ -696,10 +697,10 @@ default: if (op_type == MTS_READ) { cpu_log(cpu,"GT64120","read from addr 0x%x, pc=0x%llx\n", - offset,cpu->pc); + offset,cpu_get_pc(cpu)); } else { cpu_log(cpu,"GT64120","write to addr 0x%x, value=0x%llx, " - "pc=0x%llx\n",offset,*data,cpu->pc); + "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu)); } #endif } @@ -707,14 +708,26 @@ return NULL; } +/* Trigger/clear Ethernet interrupt if one or both port have pending events */ +static void gt_eth_set_int_status(struct gt_data *d) +{ + if ((d->eth_ports[0].icr & GT_ICR_INT_SUM) || + (d->eth_ports[1].icr & GT_ICR_INT_SUM)) + vm_set_irq(d->vm,d->eth_irq); + else + vm_clear_irq(d->vm,d->eth_irq); +} + /* Update the Ethernet port interrupt status */ static void gt_eth_update_int_status(struct gt_data *d,struct eth_port *port) { - if (port->icr & GT_ICR_MASK) + if (port->icr & port->imr & GT_ICR_MASK) { port->icr |= GT_ICR_INT_SUM; + } else { + port->icr &= ~GT_ICR_INT_SUM; + } - if (port->icr & port->imr & GT_ICR_MASK) - vm_set_irq(d->vm,d->eth_irq); + gt_eth_set_int_status(d); } /* Read a MII register */ @@ -803,7 +816,7 @@ } /* Handle registers of Ethernet ports */ -static int gt_eth_access(cpu_mips_t *cpu,struct vdevice *dev, +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) { @@ -846,19 +859,23 @@ /* ICR: Interrupt Cause Register */ case 0x84850: case 0x88850: - if (op_type == MTS_READ) + if (op_type == MTS_READ) { *data = port->icr; - else + } 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) + if (op_type == MTS_READ) { *data = port->imr; - else + } else { port->imr = *data; + gt_eth_update_int_status(d,port); + } break; /* PCR: Port Configuration Register */ @@ -1037,11 +1054,11 @@ if (op_type == MTS_READ) { cpu_log(cpu,"GT96100/ETH", "read access to unknown register 0x%x, pc=0x%llx\n", - offset,cpu->pc); + offset,cpu_get_pc(cpu)); } else { cpu_log(cpu,"GT96100/ETH", "write access to unknown register 0x%x, value=0x%llx, " - "pc=0x%llx\n",offset,*data,cpu->pc); + "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu)); } #endif } @@ -1055,7 +1072,7 @@ /* * dev_gt96100_access() */ -void *dev_gt96100_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, +void *dev_gt96100_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 *gt_data = dev->priv_data; @@ -1195,6 +1212,7 @@ if (gt_data->eth_ports[1].icr & GT_ICR_INT_SUM) *data |= GT_SCR_ETH1_SUM; + gt_update_irq_status(gt_data); *data = swap32(*data); } break; @@ -1221,10 +1239,10 @@ default: if (op_type == MTS_READ) { cpu_log(cpu,"GT96100","read from addr 0x%x, pc=0x%llx\n", - offset,cpu->pc); + offset,cpu_get_pc(cpu)); } else { cpu_log(cpu,"GT96100","write to addr 0x%x, value=0x%llx, " - "pc=0x%llx\n",offset,*data,cpu->pc); + "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu)); } #endif } @@ -1281,14 +1299,14 @@ tx_start = tx_current = port->tx_current[queue]; if (!tx_start) - goto done; + return(FALSE); ptxd = &txd0; gt_eth_desc_read(d,tx_start,ptxd); /* If we don't own the first descriptor, we cannot transmit */ if (!(txd0.cmd_stat & GT_TXDESC_OWN)) - goto done; + return(FALSE); /* Empty packet for now */ pkt_ptr = pkt; @@ -1361,7 +1379,6 @@ else port->icr |= GT_ICR_TXBUFH; - done: if (abort) { /* TX underrun */ port->icr |= GT_ICR_TXUDR; @@ -1772,7 +1789,7 @@ * * Read a PCI register. */ -static m_uint32_t pci_gt64120_read(cpu_mips_t *cpu,struct pci_device *dev, +static m_uint32_t pci_gt64120_read(cpu_gen_t *cpu,struct pci_device *dev, int reg) { switch (reg) { @@ -1833,7 +1850,7 @@ * * Read a PCI register. */ -static m_uint32_t pci_gt96100_read(cpu_mips_t *cpu,struct pci_device *dev, +static m_uint32_t pci_gt96100_read(cpu_gen_t *cpu,struct pci_device *dev, int reg) { switch (reg) {