2 |
* Cisco router simulation platform. |
* Cisco router simulation platform. |
3 |
* Copyright (C) 2007 Christophe Fillot. All rights reserved. |
* Copyright (C) 2007 Christophe Fillot. All rights reserved. |
4 |
* |
* |
5 |
* Intel i8254x (Livengood) FastEthernet chip emulation. |
* Intel i8254x (Wiseman/Livengood) Ethernet chip emulation. |
6 |
*/ |
*/ |
7 |
|
|
8 |
#include <stdio.h> |
#include <stdio.h> |
27 |
|
|
28 |
/* Debugging flags */ |
/* Debugging flags */ |
29 |
#define DEBUG_MII_REGS 0 |
#define DEBUG_MII_REGS 0 |
30 |
#define DEBUG_ACCESS 1 |
#define DEBUG_ACCESS 0 |
31 |
#define DEBUG_TRANSMIT 0 |
#define DEBUG_TRANSMIT 0 |
32 |
#define DEBUG_RECEIVE 0 |
#define DEBUG_RECEIVE 0 |
33 |
#define DEBUG_UNKNOWN 1 |
#define DEBUG_UNKNOWN 0 |
34 |
|
|
35 |
/* Intel i8254x PCI vendor/product codes */ |
/* Intel i8254x PCI vendor/product codes */ |
36 |
#define I8254X_PCI_VENDOR_ID 0x8086 |
#define I8254X_PCI_VENDOR_ID 0x8086 |
68 |
#define I8254X_REG_RDLEN 0x2808 /* RX Descriptor Length */ |
#define I8254X_REG_RDLEN 0x2808 /* RX Descriptor Length */ |
69 |
#define I8254X_REG_RDH 0x2810 /* RX Descriptor Head */ |
#define I8254X_REG_RDH 0x2810 /* RX Descriptor Head */ |
70 |
#define I8254X_REG_RDT 0x2818 /* RX Descriptor Tail */ |
#define I8254X_REG_RDT 0x2818 /* RX Descriptor Tail */ |
|
#define I82542_REG_RDH 0x0120 /* RDH for i82542 */ |
|
|
#define I82542_REG_RDT 0x0128 /* RDT for i82542 */ |
|
71 |
#define I8254X_REG_RDTR 0x2820 /* RX Delay Timer Register */ |
#define I8254X_REG_RDTR 0x2820 /* RX Delay Timer Register */ |
72 |
#define I8254X_REG_RXDCTL 0x3828 /* RX Descriptor Control */ |
#define I8254X_REG_RXDCTL 0x3828 /* RX Descriptor Control */ |
73 |
#define I8254X_REG_RADV 0x282c /* RX Int. Absolute Delay Timer */ |
#define I8254X_REG_RADV 0x282c /* RX Int. Absolute Delay Timer */ |
79 |
#define I8254X_REG_TDLEN 0x3808 /* TX Descriptor Length */ |
#define I8254X_REG_TDLEN 0x3808 /* TX Descriptor Length */ |
80 |
#define I8254X_REG_TDH 0x3810 /* TX Descriptor Head */ |
#define I8254X_REG_TDH 0x3810 /* TX Descriptor Head */ |
81 |
#define I8254X_REG_TDT 0x3818 /* TX Descriptor Tail */ |
#define I8254X_REG_TDT 0x3818 /* TX Descriptor Tail */ |
|
#define I82542_REG_TDH 0x0430 /* TDH for i82542 */ |
|
|
#define I82542_REG_TDT 0x0438 /* TDT for i82542 */ |
|
82 |
#define I8254X_REG_TIDV 0x3820 /* TX Interrupt Delay Value */ |
#define I8254X_REG_TIDV 0x3820 /* TX Interrupt Delay Value */ |
83 |
#define I8254X_REG_TXDCTL 0x3828 /* TX Descriptor Control */ |
#define I8254X_REG_TXDCTL 0x3828 /* TX Descriptor Control */ |
84 |
#define I8254X_REG_TADV 0x382c /* TX Absolute Interrupt Delay Value */ |
#define I8254X_REG_TADV 0x382c /* TX Absolute Interrupt Delay Value */ |
86 |
|
|
87 |
#define I8254X_REG_RXCSUM 0x5000 /* RX Checksum Control */ |
#define I8254X_REG_RXCSUM 0x5000 /* RX Checksum Control */ |
88 |
|
|
89 |
|
/* Register list for i8254x */ |
90 |
|
#define I82542_REG_RDTR 0x0108 /* RX Delay Timer Register */ |
91 |
|
#define I82542_REG_RDBAL 0x0110 /* RX Descriptor Base Address Low */ |
92 |
|
#define I82542_REG_RDBAH 0x0114 /* RX Descriptor Base Address High */ |
93 |
|
#define I82542_REG_RDLEN 0x0118 /* RX Descriptor Length */ |
94 |
|
#define I82542_REG_RDH 0x0120 /* RDH for i82542 */ |
95 |
|
#define I82542_REG_RDT 0x0128 /* RDT for i82542 */ |
96 |
|
#define I82542_REG_TDBAL 0x0420 /* TX Descriptor Base Address Low */ |
97 |
|
#define I82542_REG_TDBAH 0x0424 /* TX Descriptor Base Address Low */ |
98 |
|
#define I82542_REG_TDLEN 0x0428 /* TX Descriptor Length */ |
99 |
|
#define I82542_REG_TDH 0x0430 /* TDH for i82542 */ |
100 |
|
#define I82542_REG_TDT 0x0438 /* TDT for i82542 */ |
101 |
|
|
102 |
/* CTRL - Control Register (0x0000) */ |
/* CTRL - Control Register (0x0000) */ |
103 |
#define I8254X_CTRL_FD 0x00000001 /* Full Duplex */ |
#define I8254X_CTRL_FD 0x00000001 /* Full Duplex */ |
283 |
/* Extended Control Register */ |
/* Extended Control Register */ |
284 |
m_uint32_t ctrl_ext; |
m_uint32_t ctrl_ext; |
285 |
|
|
286 |
|
/* Flow Control registers */ |
287 |
|
m_uint32_t fcal,fcah,fct; |
288 |
|
|
289 |
|
/* RX Delay Timer */ |
290 |
|
m_uint32_t rdtr; |
291 |
|
|
292 |
/* RX/TX Control Registers */ |
/* RX/TX Control Registers */ |
293 |
m_uint32_t rctl,tctl; |
m_uint32_t rctl,tctl; |
294 |
|
|
356 |
case 0x05: |
case 0x05: |
357 |
return(0x41e1); |
return(0x41e1); |
358 |
case 0x06: |
case 0x06: |
359 |
return(0x1); |
return(0x0001); |
360 |
case 0x11: |
case 0x11: |
361 |
return(0x4700); |
return(0x4700); |
362 |
default: |
default: |
477 |
{ |
{ |
478 |
if (d->icr & d->imr) |
if (d->icr & d->imr) |
479 |
pci_dev_trigger_irq(d->vm,d->pci_dev); |
pci_dev_trigger_irq(d->vm,d->pci_dev); |
480 |
|
else |
481 |
|
pci_dev_clear_irq(d->vm,d->pci_dev); |
482 |
} |
} |
483 |
|
|
484 |
/* Compute RX buffer size */ |
/* Compute RX buffer size */ |
548 |
LVG_LOCK(d); |
LVG_LOCK(d); |
549 |
|
|
550 |
switch(offset) { |
switch(offset) { |
551 |
|
#if 0 /* TODO */ |
552 |
|
case 0x180: |
553 |
|
if (op_type == MTS_READ) |
554 |
|
*data = 0xDC004020; //1 << 31; |
555 |
|
break; |
556 |
|
#endif |
557 |
|
|
558 |
/* Link is Up and Full Duplex */ |
/* Link is Up and Full Duplex */ |
559 |
case I8254X_REG_STATUS: |
case I8254X_REG_STATUS: |
560 |
if (op_type == MTS_READ) |
if (op_type == MTS_READ) |
561 |
*data = I8254X_STATUS_LU | I8254X_STATUS_FD ; |
*data = I8254X_STATUS_LU | I8254X_STATUS_FD; |
562 |
break; |
break; |
563 |
|
|
564 |
/* Device Control Register */ |
/* Device Control Register */ |
666 |
|
|
667 |
/* RX Descriptor Base Address Low */ |
/* RX Descriptor Base Address Low */ |
668 |
case I8254X_REG_RDBAL: |
case I8254X_REG_RDBAL: |
669 |
|
case I82542_REG_RDBAL: |
670 |
if (op_type == MTS_WRITE) { |
if (op_type == MTS_WRITE) { |
671 |
d->rx_addr &= 0xFFFFFFFF00000000ULL; |
d->rx_addr &= 0xFFFFFFFF00000000ULL; |
672 |
d->rx_addr |= (m_uint32_t)(*data); |
d->rx_addr |= (m_uint32_t)(*data); |
677 |
|
|
678 |
/* RX Descriptor Base Address High */ |
/* RX Descriptor Base Address High */ |
679 |
case I8254X_REG_RDBAH: |
case I8254X_REG_RDBAH: |
680 |
|
case I82542_REG_RDBAH: |
681 |
if (op_type == MTS_WRITE) { |
if (op_type == MTS_WRITE) { |
682 |
d->rx_addr &= 0x00000000FFFFFFFFULL; |
d->rx_addr &= 0x00000000FFFFFFFFULL; |
683 |
d->rx_addr |= *data << 32; |
d->rx_addr |= *data << 32; |
688 |
|
|
689 |
/* TX Descriptor Base Address Low */ |
/* TX Descriptor Base Address Low */ |
690 |
case I8254X_REG_TDBAL: |
case I8254X_REG_TDBAL: |
691 |
|
case I82542_REG_TDBAL: |
692 |
if (op_type == MTS_WRITE) { |
if (op_type == MTS_WRITE) { |
693 |
d->tx_addr &= 0xFFFFFFFF00000000ULL; |
d->tx_addr &= 0xFFFFFFFF00000000ULL; |
694 |
d->tx_addr |= (m_uint32_t)(*data); |
d->tx_addr |= (m_uint32_t)(*data); |
699 |
|
|
700 |
/* TX Descriptor Base Address High */ |
/* TX Descriptor Base Address High */ |
701 |
case I8254X_REG_TDBAH: |
case I8254X_REG_TDBAH: |
702 |
|
case I82542_REG_TDBAH: |
703 |
if (op_type == MTS_WRITE) { |
if (op_type == MTS_WRITE) { |
704 |
d->tx_addr &= 0x00000000FFFFFFFFULL; |
d->tx_addr &= 0x00000000FFFFFFFFULL; |
705 |
d->tx_addr |= *data << 32; |
d->tx_addr |= *data << 32; |
710 |
|
|
711 |
/* RX Descriptor Length */ |
/* RX Descriptor Length */ |
712 |
case I8254X_REG_RDLEN: |
case I8254X_REG_RDLEN: |
713 |
|
case I82542_REG_RDLEN: |
714 |
if (op_type == MTS_WRITE) |
if (op_type == MTS_WRITE) |
715 |
d->rdlen = *data & 0xFFF80; |
d->rdlen = *data & 0xFFF80; |
716 |
else |
else |
719 |
|
|
720 |
/* TX Descriptor Length */ |
/* TX Descriptor Length */ |
721 |
case I8254X_REG_TDLEN: |
case I8254X_REG_TDLEN: |
722 |
|
case I82542_REG_TDLEN: |
723 |
if (op_type == MTS_WRITE) |
if (op_type == MTS_WRITE) |
724 |
d->tdlen = *data & 0xFFF80; |
d->tdlen = *data & 0xFFF80; |
725 |
else |
else |
762 |
*data = d->tdt; |
*data = d->tdt; |
763 |
break; |
break; |
764 |
|
|
765 |
|
/* Flow Control Address Low */ |
766 |
|
case I8254X_REG_FCAL: |
767 |
|
if (op_type == MTS_WRITE) |
768 |
|
d->fcal = *data; |
769 |
|
else |
770 |
|
*data = d->fcal; |
771 |
|
break; |
772 |
|
|
773 |
|
/* Flow Control Address High */ |
774 |
|
case I8254X_REG_FCAH: |
775 |
|
if (op_type == MTS_WRITE) |
776 |
|
d->fcah = *data & 0xFFFF; |
777 |
|
else |
778 |
|
*data = d->fcah; |
779 |
|
break; |
780 |
|
|
781 |
|
/* Flow Control Type */ |
782 |
|
case I8254X_REG_FCT: |
783 |
|
if (op_type == MTS_WRITE) |
784 |
|
d->fct = *data & 0xFFFF; |
785 |
|
else |
786 |
|
*data = d->fct; |
787 |
|
break; |
788 |
|
|
789 |
|
/* RX Delay Timer */ |
790 |
|
case I8254X_REG_RDTR: |
791 |
|
case I82542_REG_RDTR: |
792 |
|
if (op_type == MTS_WRITE) |
793 |
|
d->rdtr = *data & 0xFFFF; |
794 |
|
else |
795 |
|
*data = d->rdtr; |
796 |
|
break; |
797 |
|
|
798 |
#if DEBUG_UNKNOWN |
#if DEBUG_UNKNOWN |
799 |
default: |
default: |
800 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
1024 |
case 0x00: |
case 0x00: |
1025 |
return((I8254X_PCI_PRODUCT_ID << 16) | I8254X_PCI_VENDOR_ID); |
return((I8254X_PCI_PRODUCT_ID << 16) | I8254X_PCI_VENDOR_ID); |
1026 |
case 0x08: |
case 0x08: |
1027 |
return(0x02000002); |
return(0x02000003); |
1028 |
case PCI_REG_BAR0: |
case PCI_REG_BAR0: |
1029 |
return(d->dev->phys_addr); |
return(d->dev->phys_addr); |
1030 |
default: |
default: |