--- upstream/dynamips-0.2.6-RC1/dev_dec21140.c 2007/10/06 16:03:58 2 +++ upstream/dynamips-0.2.7-RC2/dev_dec21140.c 2007/10/06 16:24:54 8 @@ -1,5 +1,5 @@ /* - * Cisco C7200 (Predator) DEC21140 Module. + * Cisco router simlation platform. * Copyright (C) 2005,2006 Christophe Fillot. All rights reserved. * * DEC21140 FastEthernet chip emulation. @@ -31,7 +31,8 @@ #include "crc.h" #include "utils.h" -#include "mips64.h" +#include "cpu.h" +#include "vm.h" #include "dynamips.h" #include "memory.h" #include "device.h" @@ -65,8 +66,28 @@ #define DEC21140_CSR_NR 16 /* CSR5: Status Register */ -#define DEC21140_CSR5_TI 0x00000001 -#define DEC21140_CSR5_RI 0x00000040 +#define DEC21140_CSR5_TI 0x00000001 /* TX Interrupt */ +#define DEC21140_CSR5_TPS 0x00000002 /* TX Process Stopped */ +#define DEC21140_CSR5_TU 0x00000004 /* TX Buffer Unavailable */ +#define DEC21140_CSR5_TJT 0x00000008 /* TX Jabber Timeout */ +#define DEC21140_CSR5_UNF 0x00000020 /* TX Underflow */ +#define DEC21140_CSR5_RI 0x00000040 /* RX Interrupt */ +#define DEC21140_CSR5_RU 0x00000080 /* RX Buffer Unavailable */ +#define DEC21140_CSR5_RPS 0x00000100 /* RX Process Stopped */ +#define DEC21140_CSR5_RWT 0x00000200 /* RX Watchdog Timeout */ +#define DEC21140_CSR5_GTE 0x00000800 /* Gen Purpose Timer Expired */ +#define DEC21140_CSR5_FBE 0x00002000 /* Fatal Bus Error */ +#define DEC21140_CSR5_AIS 0x00008000 /* Abnormal Interrupt Summary */ +#define DEC21140_CSR5_NIS 0x00010000 /* Normal Interrupt Summary */ + +#define DEC21140_NIS_BITS \ + (DEC21140_CSR5_TI|DEC21140_CSR5_RI|DEC21140_CSR5_TU) + +#define DEC21140_AIS_BITS \ + (DEC21140_CSR5_TPS|DEC21140_CSR5_TJT|DEC21140_CSR5_UNF| \ + DEC21140_CSR5_RU|DEC21140_CSR5_RPS|DEC21140_CSR5_RWT| \ + DEC21140_CSR5_GTE|DEC21140_CSR5_FBE) + #define DEC21140_CSR5_RS_SHIFT 17 #define DEC21140_CSR5_TS_SHIFT 20 @@ -206,11 +227,6 @@ n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt; int i; - /* Ignore traffic sent by us */ - for(i=0;imac_addr_count;i++) - if (!memcmp(&d->mac_addr[i],&hdr->saddr,N_ETH_ALEN)) - return(FALSE); - /* Accept systematically frames if we are running is promiscuous mode */ if (d->csr[6] & DEC21140_CSR6_PROMISC) return(TRUE); @@ -397,10 +413,40 @@ #endif } +/* Update the interrupt status */ +static inline void dev_dec21140_update_irq_status(struct dec21140_data *d) +{ + int trigger = FALSE; + m_uint32_t csr5; + + /* Work on a temporary copy of csr5 */ + csr5 = d->csr[5]; + + /* Compute Interrupt Summary */ + csr5 &= ~(DEC21140_CSR5_AIS|DEC21140_CSR5_NIS); + + if (csr5 & DEC21140_NIS_BITS) { + csr5 |= DEC21140_CSR5_NIS; + trigger = TRUE; + } + + if (csr5 & DEC21140_AIS_BITS) { + csr5 |= DEC21140_CSR5_AIS; + trigger = TRUE; + } + + d->csr[5] = csr5; + + if (trigger) + pci_dev_trigger_irq(d->vm,d->pci_dev); + else + pci_dev_clear_irq(d->vm,d->pci_dev); +} + /* * dev_dec21140_access() */ -void *dev_dec21140_access(cpu_mips_t *cpu,struct vdevice *dev, +void *dev_dec21140_access(cpu_gen_t *cpu,struct vdevice *dev, m_uint32_t offset,u_int op_size,u_int op_type, m_uint64_t *data) { @@ -430,12 +476,13 @@ if (d->csr[6] & DEC21140_CSR6_START_TX) *data |= 0x03 << DEC21140_CSR5_TS_SHIFT; - *data |= d->csr[5] & (DEC21140_CSR5_TI|DEC21140_CSR5_RI); + *data |= d->csr[5]; break; case 8: - /* CSR8 is cleared when read */ + /* CSR8 is cleared when read (missed frame counter) */ d->csr[reg] = 0; + *data = 0; break; default: @@ -445,15 +492,19 @@ #if DEBUG_CSR_REGS cpu_log(cpu,d->name,"write CSR%u value 0x%x\n",reg,(m_uint32_t)*data); #endif - d->csr[reg] = *data; - switch(reg) { case 3: + d->csr[reg] = *data; d->rx_current = d->csr[reg]; break; case 4: + d->csr[reg] = *data; d->tx_current = d->csr[reg]; break; + case 5: + d->csr[reg] &= ~(*data); + dev_dec21140_update_irq_status(d); + break; case 9: /* * CSR9, probably they want to mess with MII PHY @@ -465,7 +516,9 @@ * * Also it makes "sh contr f0/0" happy. */ - if ((*data&~DEC21140_CSR9_TX_BIT) == (DEC21140_CSR9_MII_READ| + d->csr[reg] = *data; + + if ((*data & ~DEC21140_CSR9_TX_BIT) == (DEC21140_CSR9_MII_READ| DEC21140_CSR9_READ|DEC21140_CSR9_MDC_CLOCK)) { /* * read, pop one bit from mii_outbits @@ -483,6 +536,9 @@ mii_newbit(d,(*data&DEC21140_CSR9_TX_BIT) ? 1 : 0); } break; + + default: + d->csr[reg] = *data; } } @@ -510,7 +566,7 @@ return(nrxd_addr); } -/* Read an RX descriptor */ +/* Read a RX descriptor */ static void rxdesc_read(struct dec21140_data *d,m_uint32_t rxd_addr, struct rx_desc *rxd) { @@ -650,9 +706,7 @@ /* Indicate that we have a frame ready */ d->csr[5] |= DEC21140_CSR5_RI; - - /* Generate IRQ on CPU */ - pci_dev_trigger_irq(d->vm,d->pci_dev); + dev_dec21140_update_irq_status(d); return(TRUE); } @@ -678,9 +732,9 @@ * for this virtual machine. */ if (dec21140_handle_mac_addr(d,pkt)) - dev_dec21140_receive_pkt(d,pkt,pkt_len); + return(dev_dec21140_receive_pkt(d,pkt,pkt_len)); - return(TRUE); + return(FALSE); } /* Read a TX descriptor */ @@ -729,7 +783,7 @@ /* Copy the current txring descriptor */ tx_start = d->tx_current; ptxd = &txd0; - txdesc_read(d,d->tx_current,ptxd); + txdesc_read(d,tx_start,ptxd); /* If we don't own the first descriptor, we cannot transmit */ if (!(txd0.tdes[0] & DEC21140_TXDESC_OWN)) @@ -829,9 +883,9 @@ physmem_copy_u32_to_vm(d->vm,tx_start,0); /* Interrupt on completion ? */ - if (!(txd0.tdes[1] & DEC21140_TXDESC_IC)) { + if (txd0.tdes[1] & DEC21140_TXDESC_IC) { d->csr[5] |= DEC21140_CSR5_TI; - pci_dev_trigger_irq(d->vm,d->pci_dev); + dev_dec21140_update_irq_status(d); } return(TRUE); @@ -854,7 +908,7 @@ * * Read a PCI register. */ -static m_uint32_t pci_dec21140_read(cpu_mips_t *cpu,struct pci_device *dev, +static m_uint32_t pci_dec21140_read(cpu_gen_t *cpu,struct pci_device *dev, int reg) { struct dec21140_data *d = dev->priv_data; @@ -880,7 +934,7 @@ * * Write a PCI register. */ -static void pci_dec21140_write(cpu_mips_t *cpu,struct pci_device *dev, +static void pci_dec21140_write(cpu_gen_t *cpu,struct pci_device *dev, int reg,m_uint32_t value) { struct dec21140_data *d = dev->priv_data;