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" |
66 |
#define DEC21140_CSR_NR 16 |
#define DEC21140_CSR_NR 16 |
67 |
|
|
68 |
/* CSR5: Status Register */ |
/* CSR5: Status Register */ |
69 |
#define DEC21140_CSR5_TI 0x00000001 |
#define DEC21140_CSR5_TI 0x00000001 /* TX Interrupt */ |
70 |
#define DEC21140_CSR5_RI 0x00000040 |
#define DEC21140_CSR5_TPS 0x00000002 /* TX Process Stopped */ |
71 |
|
#define DEC21140_CSR5_TU 0x00000004 /* TX Buffer Unavailable */ |
72 |
|
#define DEC21140_CSR5_TJT 0x00000008 /* TX Jabber Timeout */ |
73 |
|
#define DEC21140_CSR5_UNF 0x00000020 /* TX Underflow */ |
74 |
|
#define DEC21140_CSR5_RI 0x00000040 /* RX Interrupt */ |
75 |
|
#define DEC21140_CSR5_RU 0x00000080 /* RX Buffer Unavailable */ |
76 |
|
#define DEC21140_CSR5_RPS 0x00000100 /* RX Process Stopped */ |
77 |
|
#define DEC21140_CSR5_RWT 0x00000200 /* RX Watchdog Timeout */ |
78 |
|
#define DEC21140_CSR5_GTE 0x00000800 /* Gen Purpose Timer Expired */ |
79 |
|
#define DEC21140_CSR5_FBE 0x00002000 /* Fatal Bus Error */ |
80 |
|
#define DEC21140_CSR5_AIS 0x00008000 /* Abnormal Interrupt Summary */ |
81 |
|
#define DEC21140_CSR5_NIS 0x00010000 /* Normal Interrupt Summary */ |
82 |
|
|
83 |
|
#define DEC21140_NIS_BITS \ |
84 |
|
(DEC21140_CSR5_TI|DEC21140_CSR5_RI|DEC21140_CSR5_TU) |
85 |
|
|
86 |
|
#define DEC21140_AIS_BITS \ |
87 |
|
(DEC21140_CSR5_TPS|DEC21140_CSR5_TJT|DEC21140_CSR5_UNF| \ |
88 |
|
DEC21140_CSR5_RU|DEC21140_CSR5_RPS|DEC21140_CSR5_RWT| \ |
89 |
|
DEC21140_CSR5_GTE|DEC21140_CSR5_FBE) |
90 |
|
|
91 |
#define DEC21140_CSR5_RS_SHIFT 17 |
#define DEC21140_CSR5_RS_SHIFT 17 |
92 |
#define DEC21140_CSR5_TS_SHIFT 20 |
#define DEC21140_CSR5_TS_SHIFT 20 |
93 |
|
|
227 |
n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt; |
n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt; |
228 |
int i; |
int i; |
229 |
|
|
|
/* 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); |
|
|
|
|
230 |
/* Accept systematically frames if we are running is promiscuous mode */ |
/* Accept systematically frames if we are running is promiscuous mode */ |
231 |
if (d->csr[6] & DEC21140_CSR6_PROMISC) |
if (d->csr[6] & DEC21140_CSR6_PROMISC) |
232 |
return(TRUE); |
return(TRUE); |
413 |
#endif |
#endif |
414 |
} |
} |
415 |
|
|
416 |
|
/* Update the interrupt status */ |
417 |
|
static inline void dev_dec21140_update_irq_status(struct dec21140_data *d) |
418 |
|
{ |
419 |
|
int trigger = FALSE; |
420 |
|
m_uint32_t csr5; |
421 |
|
|
422 |
|
/* Work on a temporary copy of csr5 */ |
423 |
|
csr5 = d->csr[5]; |
424 |
|
|
425 |
|
/* Compute Interrupt Summary */ |
426 |
|
csr5 &= ~(DEC21140_CSR5_AIS|DEC21140_CSR5_NIS); |
427 |
|
|
428 |
|
if (csr5 & DEC21140_NIS_BITS) { |
429 |
|
csr5 |= DEC21140_CSR5_NIS; |
430 |
|
trigger = TRUE; |
431 |
|
} |
432 |
|
|
433 |
|
if (csr5 & DEC21140_AIS_BITS) { |
434 |
|
csr5 |= DEC21140_CSR5_AIS; |
435 |
|
trigger = TRUE; |
436 |
|
} |
437 |
|
|
438 |
|
d->csr[5] = csr5; |
439 |
|
|
440 |
|
if (trigger) |
441 |
|
pci_dev_trigger_irq(d->vm,d->pci_dev); |
442 |
|
else |
443 |
|
pci_dev_clear_irq(d->vm,d->pci_dev); |
444 |
|
} |
445 |
|
|
446 |
/* |
/* |
447 |
* dev_dec21140_access() |
* dev_dec21140_access() |
448 |
*/ |
*/ |
449 |
void *dev_dec21140_access(cpu_mips_t *cpu,struct vdevice *dev, |
void *dev_dec21140_access(cpu_gen_t *cpu,struct vdevice *dev, |
450 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
451 |
m_uint64_t *data) |
m_uint64_t *data) |
452 |
{ |
{ |
476 |
if (d->csr[6] & DEC21140_CSR6_START_TX) |
if (d->csr[6] & DEC21140_CSR6_START_TX) |
477 |
*data |= 0x03 << DEC21140_CSR5_TS_SHIFT; |
*data |= 0x03 << DEC21140_CSR5_TS_SHIFT; |
478 |
|
|
479 |
*data |= d->csr[5] & (DEC21140_CSR5_TI|DEC21140_CSR5_RI); |
*data |= d->csr[5]; |
480 |
break; |
break; |
481 |
|
|
482 |
case 8: |
case 8: |
483 |
/* CSR8 is cleared when read */ |
/* CSR8 is cleared when read (missed frame counter) */ |
484 |
d->csr[reg] = 0; |
d->csr[reg] = 0; |
485 |
|
*data = 0; |
486 |
break; |
break; |
487 |
|
|
488 |
default: |
default: |
492 |
#if DEBUG_CSR_REGS |
#if DEBUG_CSR_REGS |
493 |
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); |
494 |
#endif |
#endif |
|
d->csr[reg] = *data; |
|
|
|
|
495 |
switch(reg) { |
switch(reg) { |
496 |
case 3: |
case 3: |
497 |
|
d->csr[reg] = *data; |
498 |
d->rx_current = d->csr[reg]; |
d->rx_current = d->csr[reg]; |
499 |
break; |
break; |
500 |
case 4: |
case 4: |
501 |
|
d->csr[reg] = *data; |
502 |
d->tx_current = d->csr[reg]; |
d->tx_current = d->csr[reg]; |
503 |
break; |
break; |
504 |
|
case 5: |
505 |
|
d->csr[reg] &= ~(*data); |
506 |
|
dev_dec21140_update_irq_status(d); |
507 |
|
break; |
508 |
case 9: |
case 9: |
509 |
/* |
/* |
510 |
* CSR9, probably they want to mess with MII PHY |
* CSR9, probably they want to mess with MII PHY |
516 |
* |
* |
517 |
* Also it makes "sh contr f0/0" happy. |
* Also it makes "sh contr f0/0" happy. |
518 |
*/ |
*/ |
519 |
if ((*data&~DEC21140_CSR9_TX_BIT) == (DEC21140_CSR9_MII_READ| |
d->csr[reg] = *data; |
520 |
|
|
521 |
|
if ((*data & ~DEC21140_CSR9_TX_BIT) == (DEC21140_CSR9_MII_READ| |
522 |
DEC21140_CSR9_READ|DEC21140_CSR9_MDC_CLOCK)) { |
DEC21140_CSR9_READ|DEC21140_CSR9_MDC_CLOCK)) { |
523 |
/* |
/* |
524 |
* read, pop one bit from mii_outbits |
* read, pop one bit from mii_outbits |
536 |
mii_newbit(d,(*data&DEC21140_CSR9_TX_BIT) ? 1 : 0); |
mii_newbit(d,(*data&DEC21140_CSR9_TX_BIT) ? 1 : 0); |
537 |
} |
} |
538 |
break; |
break; |
539 |
|
|
540 |
|
default: |
541 |
|
d->csr[reg] = *data; |
542 |
} |
} |
543 |
} |
} |
544 |
|
|
566 |
return(nrxd_addr); |
return(nrxd_addr); |
567 |
} |
} |
568 |
|
|
569 |
/* Read an RX descriptor */ |
/* Read a RX descriptor */ |
570 |
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, |
571 |
struct rx_desc *rxd) |
struct rx_desc *rxd) |
572 |
{ |
{ |
706 |
|
|
707 |
/* Indicate that we have a frame ready */ |
/* Indicate that we have a frame ready */ |
708 |
d->csr[5] |= DEC21140_CSR5_RI; |
d->csr[5] |= DEC21140_CSR5_RI; |
709 |
|
dev_dec21140_update_irq_status(d); |
|
/* Generate IRQ on CPU */ |
|
|
pci_dev_trigger_irq(d->vm,d->pci_dev); |
|
710 |
return(TRUE); |
return(TRUE); |
711 |
} |
} |
712 |
|
|
783 |
/* Copy the current txring descriptor */ |
/* Copy the current txring descriptor */ |
784 |
tx_start = d->tx_current; |
tx_start = d->tx_current; |
785 |
ptxd = &txd0; |
ptxd = &txd0; |
786 |
txdesc_read(d,d->tx_current,ptxd); |
txdesc_read(d,tx_start,ptxd); |
787 |
|
|
788 |
/* If we don't own the first descriptor, we cannot transmit */ |
/* If we don't own the first descriptor, we cannot transmit */ |
789 |
if (!(txd0.tdes[0] & DEC21140_TXDESC_OWN)) |
if (!(txd0.tdes[0] & DEC21140_TXDESC_OWN)) |
883 |
physmem_copy_u32_to_vm(d->vm,tx_start,0); |
physmem_copy_u32_to_vm(d->vm,tx_start,0); |
884 |
|
|
885 |
/* Interrupt on completion ? */ |
/* Interrupt on completion ? */ |
886 |
if (!(txd0.tdes[1] & DEC21140_TXDESC_IC)) { |
if (txd0.tdes[1] & DEC21140_TXDESC_IC) { |
887 |
d->csr[5] |= DEC21140_CSR5_TI; |
d->csr[5] |= DEC21140_CSR5_TI; |
888 |
pci_dev_trigger_irq(d->vm,d->pci_dev); |
dev_dec21140_update_irq_status(d); |
889 |
} |
} |
890 |
|
|
891 |
return(TRUE); |
return(TRUE); |
908 |
* |
* |
909 |
* Read a PCI register. |
* Read a PCI register. |
910 |
*/ |
*/ |
911 |
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, |
912 |
int reg) |
int reg) |
913 |
{ |
{ |
914 |
struct dec21140_data *d = dev->priv_data; |
struct dec21140_data *d = dev->priv_data; |
934 |
* |
* |
935 |
* Write a PCI register. |
* Write a PCI register. |
936 |
*/ |
*/ |
937 |
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, |
938 |
int reg,m_uint32_t value) |
int reg,m_uint32_t value) |
939 |
{ |
{ |
940 |
struct dec21140_data *d = dev->priv_data; |
struct dec21140_data *d = dev->priv_data; |