1 |
/* |
/* |
2 |
* Cisco C7200 (Predator) DEC21140 Module. |
* Cisco router simlation platform. |
3 |
* Copyright (C) 2005,2006 Christophe Fillot. All rights reserved. |
* Copyright (C) 2005,2006 Christophe Fillot. All rights reserved. |
4 |
* |
* |
5 |
* DEC21140 FastEthernet chip emulation. |
* DEC21140 FastEthernet chip emulation. |
31 |
|
|
32 |
#include "crc.h" |
#include "crc.h" |
33 |
#include "utils.h" |
#include "utils.h" |
34 |
#include "mips64.h" |
#include "cpu.h" |
35 |
|
#include "vm.h" |
36 |
#include "dynamips.h" |
#include "dynamips.h" |
37 |
#include "memory.h" |
#include "memory.h" |
38 |
#include "device.h" |
#include "device.h" |
87 |
/* Maximum packet size */ |
/* Maximum packet size */ |
88 |
#define DEC21140_MAX_PKT_SIZE 2048 |
#define DEC21140_MAX_PKT_SIZE 2048 |
89 |
|
|
90 |
/* Send up to 16 packets in a TX ring scan pass */ |
/* Send up to 32 packets in a TX ring scan pass */ |
91 |
#define DEC21140_TXRING_PASS_COUNT 16 |
#define DEC21140_TXRING_PASS_COUNT 32 |
92 |
|
|
93 |
/* Setup frame size */ |
/* Setup frame size */ |
94 |
#define DEC21140_SETUP_FRAME_SIZE 192 |
#define DEC21140_SETUP_FRAME_SIZE 192 |
207 |
n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt; |
n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt; |
208 |
int i; |
int i; |
209 |
|
|
|
/* Ignore traffic sent by us */ |
|
|
for(i=0;i<d->mac_addr_count;i++) |
|
|
if (!memcmp(&d->mac_addr[i],&hdr->saddr,N_ETH_ALEN)) |
|
|
return(FALSE); |
|
|
|
|
210 |
/* Accept systematically frames if we are running is promiscuous mode */ |
/* Accept systematically frames if we are running is promiscuous mode */ |
211 |
if (d->csr[6] & DEC21140_CSR6_PROMISC) |
if (d->csr[6] & DEC21140_CSR6_PROMISC) |
212 |
return(TRUE); |
return(TRUE); |
396 |
/* |
/* |
397 |
* dev_dec21140_access() |
* dev_dec21140_access() |
398 |
*/ |
*/ |
399 |
void *dev_dec21140_access(cpu_mips_t *cpu,struct vdevice *dev, |
void *dev_dec21140_access(cpu_gen_t *cpu,struct vdevice *dev, |
400 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
401 |
m_uint64_t *data) |
m_uint64_t *data) |
402 |
{ |
{ |
415 |
#if DEBUG_CSR_REGS |
#if DEBUG_CSR_REGS |
416 |
cpu_log(cpu,d->name,"read CSR%u value 0x%x\n",reg,d->csr[reg]); |
cpu_log(cpu,d->name,"read CSR%u value 0x%x\n",reg,d->csr[reg]); |
417 |
#endif |
#endif |
418 |
|
switch(reg) { |
419 |
/* Dynamically construct CSR5 */ |
case 5: |
420 |
if (reg == 5) { |
/* Dynamically construct CSR5 */ |
421 |
*data = 0; |
*data = 0; |
422 |
|
|
423 |
if (d->csr[6] & DEC21140_CSR6_START_RX) |
if (d->csr[6] & DEC21140_CSR6_START_RX) |
424 |
*data |= 0x03 << DEC21140_CSR5_RS_SHIFT; |
*data |= 0x03 << DEC21140_CSR5_RS_SHIFT; |
425 |
|
|
426 |
if (d->csr[6] & DEC21140_CSR6_START_TX) |
if (d->csr[6] & DEC21140_CSR6_START_TX) |
427 |
*data |= 0x03 << DEC21140_CSR5_TS_SHIFT; |
*data |= 0x03 << DEC21140_CSR5_TS_SHIFT; |
428 |
|
|
429 |
*data |= d->csr[5] & (DEC21140_CSR5_TI|DEC21140_CSR5_RI); |
*data |= d->csr[5] & (DEC21140_CSR5_TI|DEC21140_CSR5_RI); |
430 |
} |
break; |
|
else |
|
|
*data = d->csr[reg]; |
|
431 |
|
|
432 |
/* CSR8 is cleared when read */ |
case 8: |
433 |
if (reg == 8) |
/* CSR8 is cleared when read (missed frame counter) */ |
434 |
d->csr[reg] = 0; |
d->csr[reg] = 0; |
435 |
|
*data = 0; |
436 |
|
break; |
437 |
|
|
438 |
|
default: |
439 |
|
*data = d->csr[reg]; |
440 |
|
} |
441 |
} else { |
} else { |
442 |
#if DEBUG_CSR_REGS |
#if DEBUG_CSR_REGS |
443 |
cpu_log(cpu,d->name,"write CSR%u value 0x%x\n",reg,(m_uint32_t)*data); |
cpu_log(cpu,d->name,"write CSR%u value 0x%x\n",reg,(m_uint32_t)*data); |
507 |
return(nrxd_addr); |
return(nrxd_addr); |
508 |
} |
} |
509 |
|
|
510 |
/* Read an RX descriptor */ |
/* Read a RX descriptor */ |
511 |
static void rxdesc_read(struct dec21140_data *d,m_uint32_t rxd_addr, |
static void rxdesc_read(struct dec21140_data *d,m_uint32_t rxd_addr, |
512 |
struct rx_desc *rxd) |
struct rx_desc *rxd) |
513 |
{ |
{ |
675 |
* for this virtual machine. |
* for this virtual machine. |
676 |
*/ |
*/ |
677 |
if (dec21140_handle_mac_addr(d,pkt)) |
if (dec21140_handle_mac_addr(d,pkt)) |
678 |
dev_dec21140_receive_pkt(d,pkt,pkt_len); |
return(dev_dec21140_receive_pkt(d,pkt,pkt_len)); |
679 |
|
|
680 |
return(TRUE); |
return(FALSE); |
681 |
} |
} |
682 |
|
|
683 |
/* Read a TX descriptor */ |
/* Read a TX descriptor */ |
726 |
/* Copy the current txring descriptor */ |
/* Copy the current txring descriptor */ |
727 |
tx_start = d->tx_current; |
tx_start = d->tx_current; |
728 |
ptxd = &txd0; |
ptxd = &txd0; |
729 |
txdesc_read(d,d->tx_current,ptxd); |
txdesc_read(d,tx_start,ptxd); |
730 |
|
|
731 |
/* If we don't own the first descriptor, we cannot transmit */ |
/* If we don't own the first descriptor, we cannot transmit */ |
732 |
if (!(txd0.tdes[0] & DEC21140_TXDESC_OWN)) |
if (!(txd0.tdes[0] & DEC21140_TXDESC_OWN)) |
851 |
* |
* |
852 |
* Read a PCI register. |
* Read a PCI register. |
853 |
*/ |
*/ |
854 |
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, |
855 |
int reg) |
int reg) |
856 |
{ |
{ |
857 |
struct dec21140_data *d = dev->priv_data; |
struct dec21140_data *d = dev->priv_data; |
877 |
* |
* |
878 |
* Write a PCI register. |
* Write a PCI register. |
879 |
*/ |
*/ |
880 |
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, |
881 |
int reg,m_uint32_t value) |
int reg,m_uint32_t value) |
882 |
{ |
{ |
883 |
struct dec21140_data *d = dev->priv_data; |
struct dec21140_data *d = dev->priv_data; |
939 |
|
|
940 |
/* Basic register setup */ |
/* Basic register setup */ |
941 |
d->csr[0] = 0xfff80000; |
d->csr[0] = 0xfff80000; |
942 |
|
d->csr[5] = 0xfc000000; |
943 |
d->csr[8] = 0xfffe0000; |
d->csr[8] = 0xfffe0000; |
944 |
|
|
945 |
dev->phys_addr = 0; |
dev->phys_addr = 0; |