diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/net/ath/ath5k/ath5k_eeprom.c | 3 | ||||
| -rw-r--r-- | src/drivers/net/bnxt/bnxt.c | 68 | ||||
| -rw-r--r-- | src/drivers/net/bnxt/bnxt.h | 137 | ||||
| -rw-r--r-- | src/drivers/net/intel.c | 12 | ||||
| -rw-r--r-- | src/drivers/net/rdc.c | 694 | ||||
| -rw-r--r-- | src/drivers/net/rdc.h | 194 | ||||
| -rw-r--r-- | src/drivers/net/realtek.c | 10 |
7 files changed, 977 insertions, 141 deletions
diff --git a/src/drivers/net/ath/ath5k/ath5k_eeprom.c b/src/drivers/net/ath/ath5k/ath5k_eeprom.c index 12519bc59..46f33d1e8 100644 --- a/src/drivers/net/ath/ath5k/ath5k_eeprom.c +++ b/src/drivers/net/ath/ath5k/ath5k_eeprom.c @@ -39,6 +39,9 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) { u32 status, timeout; + /* Avoid returning uninitialised data on error */ + *data = 0xffff; + /* * Initialize EEPROM access */ diff --git a/src/drivers/net/bnxt/bnxt.c b/src/drivers/net/bnxt/bnxt.c index b8663c00a..e3876503f 100644 --- a/src/drivers/net/bnxt/bnxt.c +++ b/src/drivers/net/bnxt/bnxt.c @@ -23,16 +23,74 @@ static void bnxt_adv_cq_index ( struct bnxt *bp, u16 cnt ); static int bnxt_rx_complete ( struct net_device *dev, struct rx_pkt_cmpl *rx ); void bnxt_link_evt ( struct bnxt *bp, struct hwrm_async_event_cmpl *evt ); +static struct pci_device_id bnxt_nics[] = { + PCI_ROM( 0x14e4, 0x16c0, "14e4-16C0", "14e4-16C0", 0 ), + PCI_ROM( 0x14e4, 0x16c1, "14e4-16C1", "14e4-16C1", BNXT_FLAG_PCI_VF ), + PCI_ROM( 0x14e4, 0x16c8, "14e4-16C8", "14e4-16C8", 0 ), + PCI_ROM( 0x14e4, 0x16c9, "14e4-16C9", "14e4-16C9", 0 ), + PCI_ROM( 0x14e4, 0x16ca, "14e4-16CA", "14e4-16CA", 0 ), + PCI_ROM( 0x14e4, 0x16cc, "14e4-16CC", "14e4-16CC", 0 ), + PCI_ROM( 0x14e4, 0x16cd, "14e4-16CD", "14e4-16CD", 0 ), + PCI_ROM( 0x14e4, 0x16ce, "14e4-16CE", "14e4-16CE", 0 ), + PCI_ROM( 0x14e4, 0x16cf, "14e4-16CF", "14e4-16CF", 0 ), + PCI_ROM( 0x14e4, 0x16d0, "14e4-16D0", "14e4-16D0", 0 ), + PCI_ROM( 0x14e4, 0x16d1, "14e4-16D1", "14e4-16D1", 0 ), + PCI_ROM( 0x14e4, 0x16d2, "14e4-16D2", "14e4-16D2", 0 ), + PCI_ROM( 0x14e4, 0x16d4, "14e4-16D4", "14e4-16D4", 0 ), + PCI_ROM( 0x14e4, 0x16d5, "14e4-16D5", "14e4-16D5", 0 ), + PCI_ROM( 0x14e4, 0x16d6, "14e4-16D6", "14e4-16D6", 0 ), + PCI_ROM( 0x14e4, 0x16d7, "14e4-16D7", "14e4-16D7", 0 ), + PCI_ROM( 0x14e4, 0x16d8, "14e4-16D8", "14e4-16D8", 0 ), + PCI_ROM( 0x14e4, 0x16d9, "14e4-16D9", "14e4-16D9", 0 ), + PCI_ROM( 0x14e4, 0x16da, "14e4-16DA", "14e4-16DA", 0 ), + PCI_ROM( 0x14e4, 0x16db, "14e4-16DB", "14e4-16DB", 0 ), + PCI_ROM( 0x14e4, 0x16dc, "14e4-16DC", "14e4-16DC", BNXT_FLAG_PCI_VF ), + PCI_ROM( 0x14e4, 0x16de, "14e4-16DE", "14e4-16DE", 0 ), + PCI_ROM( 0x14e4, 0x16df, "14e4-16DF", "14e4-16DF", 0 ), + PCI_ROM( 0x14e4, 0x16e0, "14e4-16E0", "14e4-16E0", 0 ), + PCI_ROM( 0x14e4, 0x16e2, "14e4-16E2", "14e4-16E2", 0 ), + PCI_ROM( 0x14e4, 0x16e3, "14e4-16E3", "14e4-16E3", 0 ), + PCI_ROM( 0x14e4, 0x16e4, "14e4-16E4", "14e4-16E4", 0 ), + PCI_ROM( 0x14e4, 0x16e7, "14e4-16E7", "14e4-16E7", 0 ), + PCI_ROM( 0x14e4, 0x16e8, "14e4-16E8", "14e4-16E8", 0 ), + PCI_ROM( 0x14e4, 0x16e9, "14e4-16E9", "14e4-16E9", 0 ), + PCI_ROM( 0x14e4, 0x16ea, "14e4-16EA", "14e4-16EA", 0 ), + PCI_ROM( 0x14e4, 0x16eb, "14e4-16EB", "14e4-16EB", 0 ), + PCI_ROM( 0x14e4, 0x16ec, "14e4-16EC", "14e4-16EC", 0 ), + PCI_ROM( 0x14e4, 0x16ed, "14e4-16ED", "14e4-16ED", 0 ), + PCI_ROM( 0x14e4, 0x16ee, "14e4-16EE", "14e4-16EE", 0 ), + PCI_ROM( 0x14e4, 0x16ef, "14e4-16EF", "14e4-16EF", 0 ), + PCI_ROM( 0x14e4, 0x16f0, "14e4-16F0", "14e4-16F0", 0 ), + PCI_ROM( 0x14e4, 0x16f1, "14e4-16F1", "14e4-16F1", 0 ), + PCI_ROM( 0x14e4, 0x1604, "14e4-1604", "14e4-1604", 0 ), + PCI_ROM( 0x14e4, 0x1605, "14e4-1605", "14e4-1605", 0 ), + PCI_ROM( 0x14e4, 0x1606, "14e4-1606", "14e4-1606", 0 ), + PCI_ROM( 0x14e4, 0x1609, "14e4-1609", "14e4-1609", 0 ), + PCI_ROM( 0x14e4, 0x1614, "14e4-1614", "14e4-1614", 0 ), + PCI_ROM( 0x14e4, 0xd802, "14e4-D802", "14e4-D802", 0 ), + PCI_ROM( 0x14e4, 0xd804, "14e4-D804", "14e4-D804", 0 ), + PCI_ROM( 0x14e4, 0x1750, "14e4-1750", "14e4-1750", 0 ), + PCI_ROM( 0x14e4, 0x1802, "14e4-1802", "14e4-1802", 0 ), + PCI_ROM( 0x14e4, 0x1805, "14e4-1805", "14e4-1805", 0 ), + PCI_ROM( 0x14e4, 0x1751, "14e4-1751", "14e4-1751", 0 ), + PCI_ROM( 0x14e4, 0x1801, "14e4-1801", "14e4-1801", 0 ), + PCI_ROM( 0x14e4, 0x1804, "14e4-1804", "14e4-1804", 0 ), + PCI_ROM( 0x14e4, 0x1752, "14e4-1752", "14e4-1752", 0 ), + PCI_ROM( 0x14e4, 0x1800, "14e4-1800", "14e4-1800", 0 ), + PCI_ROM( 0x14e4, 0x1803, "14e4-1803", "14e4-1803", 0 ), + PCI_ROM( 0x14e4, 0x1806, "14e4-1806", "14e4-1806", BNXT_FLAG_PCI_VF ), + PCI_ROM( 0x14e4, 0x1807, "14e4-1807", "14e4-1807", BNXT_FLAG_PCI_VF ), + PCI_ROM( 0x14e4, 0x1808, "14e4-1808", "14e4-1808", BNXT_FLAG_PCI_VF ), + PCI_ROM( 0x14e4, 0x1809, "14e4-1809", "14e4-1809", BNXT_FLAG_PCI_VF ), +}; + /** * Check if Virtual Function */ u8 bnxt_is_pci_vf ( struct pci_device *pdev ) { - u16 i; - - for ( i = 0; i < ARRAY_SIZE ( bnxt_vf_nics ); i++ ) { - if ( pdev->device == bnxt_vf_nics[i] ) - return 1; + if ( FLAG_TEST ( pdev->id->driver_data, BNXT_FLAG_PCI_VF ) ) { + return 1; } return 0; } diff --git a/src/drivers/net/bnxt/bnxt.h b/src/drivers/net/bnxt/bnxt.h index 4cca07bd3..2cbaec5e5 100644 --- a/src/drivers/net/bnxt/bnxt.h +++ b/src/drivers/net/bnxt/bnxt.h @@ -51,6 +51,7 @@ union dma_addr64_t { #define BNXT_FLAG_MULTI_HOST 0x0008 #define BNXT_FLAG_NPAR_MODE 0x0010 #define BNXT_FLAG_ATOMICS_ENABLE 0x0020 +#define BNXT_FLAG_PCI_VF 0x0040 /******************************************************************************* * Status codes. ******************************************************************************/ @@ -867,140 +868,4 @@ struct bnxt { FUNC_VF_CFG_REQ_ENABLES_ASYNC_EVENT_CR | \ FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR) -/* Device ID's */ -#define PCI_VID_BCOM 0x14e4 #define CHIP_NUM_57500 0x1750 - -#define DID_57508 0x1750 -#define DID_57508_MF 0x1802 -#define DID_57508_MF_RDMA 0x1805 -#define DID_57504 0x1751 -#define DID_57504_MF 0x1801 -#define DID_57504_MF_RDMA 0x1804 -#define DID_57502 0x1752 -#define DID_57502_MF 0x1800 -#define DID_57502_MF_RDMA 0x1803 -#define DID_57508_VF 0x1806 -#define DID_57508_VF_RDMA 0x1807 -#define DID_57508_VF_HV 0x1806 -#define DID_57508_VF_RDMA_HV 0x1807 -/* Stratus Device IDs */ -#define DID_57320_1 0x16F0 -#define DID_57320_2 0x16F1 -#define DID_57454_MHB 0x1604 -#define DID_57454_MHB_RDMA 0x1605 -#define DID_57454_VF_RDMA 0x1606 -#define DID_57454_VF 0x1609 -#define DID_57454 0x1614 -#define DID_58802 0xD802 -#define DID_58804 0xD804 - -#define DID_57417_RDMA_MF 0x16C0 -#define DID_57417_VF_RDMA 0x16c1 -#define DID_57301 0x16C8 -#define DID_57302 0x16C9 -#define DID_57304 0x16CA -#define DID_57417_MF 0x16CC -#define DID_58700 0x16CD -#define DID_57311 0x16CE -#define DID_57312 0x16CF -#define DID_57402 0x16D0 -#define DID_57404 0x16D1 -#define DID_57406 0x16D2 -#define DID_57402_MF 0x16D4 -#define DID_57407C 0x16D5 -#define DID_57412 0x16D6 -#define DID_57414 0x16D7 -#define DID_57416C 0x16D8 -#define DID_57417C 0x16D9 -#define DID_57402L 0x16DA -#define DID_57404L 0x16DB -#define DID_57417_VF 0x16dc -#define DID_57412_MF 0x16DE -#define DID_57314 0x16DF -#define DID_57317C 0x16E0 -#define DID_57417F 0x16E2 -#define DID_57416F 0x16E3 -#define DID_57317F 0x16E4 -#define DID_57404_MF 0x16E7 -#define DID_57406_MF 0x16E8 -#define DID_57407F 0x16E9 -#define DID_57407_MF 0x16EA -#define DID_57412_RDMA_MF 0x16EB -#define DID_57414_MF 0x16EC -#define DID_57414_RDMA_MF 0x16ED -#define DID_57416_MF 0x16EE -#define DID_57416_RDMA_MF 0x16EF - -static struct pci_device_id bnxt_nics[] = { - PCI_ROM(PCI_VID_BCOM, DID_57417_RDMA_MF, "14e4-16C0", "14e4-16C0", 0), - PCI_ROM(PCI_VID_BCOM, DID_57417_VF_RDMA, "14e4-16C1", "14e4-16C1", 0), - PCI_ROM(PCI_VID_BCOM, DID_57301, "14e4-16C8", "14e4-16C8", 0), - PCI_ROM(PCI_VID_BCOM, DID_57302, "14e4-16C9", "14e4-16C9", 0), - PCI_ROM(PCI_VID_BCOM, DID_57304, "14e4-16CA", "14e4-16CA", 0), - PCI_ROM(PCI_VID_BCOM, DID_57417_MF, "14e4-16CC", "14e4-16CC", 0), - PCI_ROM(PCI_VID_BCOM, DID_58700, "14e4-16CD", "14e4-16CD", 0), - PCI_ROM(PCI_VID_BCOM, DID_57311, "14e4-16CE", "14e4-16CE", 0), - PCI_ROM(PCI_VID_BCOM, DID_57312, "14e4-16CF", "14e4-16CF", 0), - PCI_ROM(PCI_VID_BCOM, DID_57402, "14e4-16D0", "14e4-16D0", 0), - PCI_ROM(PCI_VID_BCOM, DID_57404, "14e4-16D1", "14e4-16D1", 0), - PCI_ROM(PCI_VID_BCOM, DID_57406, "14e4-16D2", "14e4-16D2", 0), - PCI_ROM(PCI_VID_BCOM, DID_57402_MF, "14e4-16D4", "14e4-16D4", 0), - PCI_ROM(PCI_VID_BCOM, DID_57407C, "14e4-16D5", "14e4-16D5", 0), - PCI_ROM(PCI_VID_BCOM, DID_57412, "14e4-16D6", "14e4-16D6", 0), - PCI_ROM(PCI_VID_BCOM, DID_57414, "14e4-16D7", "14e4-16D7", 0), - PCI_ROM(PCI_VID_BCOM, DID_57416C, "14e4-16D8", "14e4-16D8", 0), - PCI_ROM(PCI_VID_BCOM, DID_57417C, "14e4-16D9", "14e4-16D9", 0), - PCI_ROM(PCI_VID_BCOM, DID_57402L, "14e4-16DA", "14e4-16DA", 0), - PCI_ROM(PCI_VID_BCOM, DID_57404L, "14e4-16DB", "14e4-16DB", 0), - PCI_ROM(PCI_VID_BCOM, DID_57417_VF, "14e4-16DC", "14e4-16DC", 0), - PCI_ROM(PCI_VID_BCOM, DID_57412_MF, "14e4-16DE", "14e4-16DE", 0), - PCI_ROM(PCI_VID_BCOM, DID_57314, "14e4-16DF", "14e4-16DF", 0), - PCI_ROM(PCI_VID_BCOM, DID_57317C, "14e4-16E0", "14e4-16E0", 0), - PCI_ROM(PCI_VID_BCOM, DID_57417F, "14e4-16E2", "14e4-16E2", 0), - PCI_ROM(PCI_VID_BCOM, DID_57416F, "14e4-16E3", "14e4-16E3", 0), - PCI_ROM(PCI_VID_BCOM, DID_57317F, "14e4-16E4", "14e4-16E4", 0), - PCI_ROM(PCI_VID_BCOM, DID_57404_MF, "14e4-16E7", "14e4-16E7", 0), - PCI_ROM(PCI_VID_BCOM, DID_57406_MF, "14e4-16E8", "14e4-16E8", 0), - PCI_ROM(PCI_VID_BCOM, DID_57407F, "14e4-16E9", "14e4-16E9", 0), - PCI_ROM(PCI_VID_BCOM, DID_57407_MF, "14e4-16EA", "14e4-16EA", 0), - PCI_ROM(PCI_VID_BCOM, DID_57412_RDMA_MF, "14e4-16EB", "14e4-16EB", 0), - PCI_ROM(PCI_VID_BCOM, DID_57414_MF, "14e4-16EC", "14e4-16EC", 0), - PCI_ROM(PCI_VID_BCOM, DID_57414_RDMA_MF, "14e4-16ED", "14e4-16ED", 0), - PCI_ROM(PCI_VID_BCOM, DID_57416_MF, "14e4-16EE", "14e4-16EE", 0), - PCI_ROM(PCI_VID_BCOM, DID_57416_RDMA_MF, "14e4-16EF", "14e4-16EF", 0), - - PCI_ROM(PCI_VID_BCOM, DID_57320_1, "14e4-16F0", "14e4-16F0", 0), - PCI_ROM(PCI_VID_BCOM, DID_57320_2, "14e4-16F1", "14e4-16F1", 0), - PCI_ROM(PCI_VID_BCOM, DID_57454_MHB, "14e4-1604", "14e4-1604", 0), - PCI_ROM(PCI_VID_BCOM, DID_57454_MHB_RDMA, "14e4-1605", "14e4-1605", 0), - PCI_ROM(PCI_VID_BCOM, DID_57454_VF_RDMA, "14e4-1606", "14e4-1606", 0), - PCI_ROM(PCI_VID_BCOM, DID_57454_VF, "14e4-1609", "14e4-1609", 0), - PCI_ROM(PCI_VID_BCOM, DID_57454, "14e4-1614", "14e4-1614", 0), - PCI_ROM(PCI_VID_BCOM, DID_58802, "14e4-D802", "14e4-D802", 0), - PCI_ROM(PCI_VID_BCOM, DID_58804, "14e4-D804", "14e4-D804", 0), - - PCI_ROM(PCI_VID_BCOM, DID_57508, "14e4-1750", "14e4-1750", 0), - PCI_ROM(PCI_VID_BCOM, DID_57508_MF, "14e4-1802", "14e4-1802", 0), - PCI_ROM(PCI_VID_BCOM, DID_57508_MF_RDMA, "14e4-1805", "14e4-1805", 0), - PCI_ROM(PCI_VID_BCOM, DID_57504, "14e4-1751", "14e4-1751", 0), - PCI_ROM(PCI_VID_BCOM, DID_57504_MF, "14e4-1801", "14e4-1801", 0), - PCI_ROM(PCI_VID_BCOM, DID_57504_MF_RDMA, "14e4-1804", "14e4-1804", 0), - PCI_ROM(PCI_VID_BCOM, DID_57502, "14e4-1752", "14e4-1752", 0), - PCI_ROM(PCI_VID_BCOM, DID_57502_MF, "14e4-1800", "14e4-1800", 0), - PCI_ROM(PCI_VID_BCOM, DID_57502_MF_RDMA, "14e4-1803", "14e4-1803", 0), - PCI_ROM(PCI_VID_BCOM, DID_57508_VF, "14e4-1806", "14e4-1806", 0), - PCI_ROM(PCI_VID_BCOM, DID_57508_VF_RDMA, "14e4-1807", "14e4-1807", 0), - PCI_ROM(PCI_VID_BCOM, DID_57508_VF_HV, "14e4-1808", "14e4-1808", 0), - PCI_ROM(PCI_VID_BCOM, - DID_57508_VF_RDMA_HV, "14e4-1809", "14e4-1809", 0), -}; - -static u16 bnxt_vf_nics[] = { - DID_57508_VF, - DID_57508_VF_RDMA, - DID_57508_VF_HV, - DID_57508_VF_RDMA_HV, - DID_57417_VF, - DID_57417_VF_RDMA, -}; diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index 83492961f..ea3ebf68d 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -1025,6 +1025,12 @@ static struct pci_device_id intel_nics[] = { PCI_ROM ( 0x8086, 0x043a, "dh8900cc-f", "DH8900CC Fiber", 0 ), PCI_ROM ( 0x8086, 0x043c, "dh8900cc-b", "DH8900CC Backplane", 0 ), PCI_ROM ( 0x8086, 0x0440, "dh8900cc-s", "DH8900CC SFP", 0 ), + PCI_ROM ( 0x8086, 0x0d4c, "i219lm-11", "I219-LM (11)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x0d4d, "i219v-11", "I219-V (11)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x0d4e, "i219lm-10", "I219-LM (10)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x0d4f, "i219v-10", "I219-V (10)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x0d53, "i219lm-12", "I219-LM (12)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x0d55, "i219v-12", "I219-V (12)", INTEL_I219 ), PCI_ROM ( 0x8086, 0x1000, "82542-f", "82542 (Fiber)", 0 ), PCI_ROM ( 0x8086, 0x1001, "82543gc-f", "82543GC (Fiber)", 0 ), PCI_ROM ( 0x8086, 0x1004, "82543gc", "82543GC (Copper)", 0 ), @@ -1161,6 +1167,12 @@ static struct pci_device_id intel_nics[] = { PCI_ROM ( 0x8086, 0x15e1, "i219lm-9", "I219-LM (9)", INTEL_I219 ), PCI_ROM ( 0x8086, 0x15e2, "i219v-9", "I219-V (9)", INTEL_I219 ), PCI_ROM ( 0x8086, 0x15e3, "i219lm-5", "I219-LM (5)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x15f4, "i219lm-15", "I219-LM (15)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x15f5, "i219v-15", "I219-V (15)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x15f9, "i219lm-14", "I219-LM (14)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x15fa, "i219v-14", "I219-V (14)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x15fb, "i219lm-13", "I219-LM (13)", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x15fc, "i219v-13", "I219-V (13)", INTEL_I219 ), PCI_ROM ( 0x8086, 0x1f41, "i354", "I354", INTEL_NO_ASDE ), PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ), PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ), diff --git a/src/drivers/net/rdc.c b/src/drivers/net/rdc.c new file mode 100644 index 000000000..c3239c002 --- /dev/null +++ b/src/drivers/net/rdc.c @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <byteswap.h> +#include <ipxe/netdevice.h> +#include <ipxe/ethernet.h> +#include <ipxe/if_ether.h> +#include <ipxe/iobuf.h> +#include <ipxe/malloc.h> +#include <ipxe/pci.h> +#include "rdc.h" + +/** @file + * + * RDC R6040 network driver + * + */ + +/****************************************************************************** + * + * Device reset + * + ****************************************************************************** + */ + +/** + * Reset hardware + * + * @v rdc RDC device + * @ret rc Return status code + */ +static int rdc_reset ( struct rdc_nic *rdc ) { + unsigned int i; + + /* Reset NIC */ + writew ( RDC_MCR1_RST, rdc->regs + RDC_MCR1 ); + + /* Wait for reset to complete */ + for ( i = 0 ; i < RDC_RESET_MAX_WAIT_MS ; i++ ) { + + /* Check for reset completion */ + if ( readw ( rdc->regs + RDC_MCR1 ) & RDC_MCR1_RST ) { + mdelay ( 1 ); + continue; + } + + /* Reset internal state machine */ + writew ( RDC_MACSM_RST, rdc->regs + RDC_MACSM ); + writew ( 0, rdc->regs + RDC_MACSM ); + mdelay ( RDC_MACSM_RESET_DELAY_MS ); + + return 0; + } + + DBGC ( rdc, "RDC %p timed out waiting for reset\n", rdc ); + return -ETIMEDOUT; +} + +/****************************************************************************** + * + * MII interface + * + ****************************************************************************** + */ + +/** + * Read from MII register + * + * @v mdio MII interface + * @v phy PHY address + * @v reg Register address + * @ret value Data read, or negative error + */ +static int rdc_mii_read ( struct mii_interface *mdio, unsigned int phy, + unsigned int reg ) { + struct rdc_nic *rdc = container_of ( mdio, struct rdc_nic, mdio ); + uint16_t mmdio; + unsigned int i; + + /* Initiate read */ + mmdio = ( RDC_MMDIO_MIIRD | RDC_MMDIO_PHYAD ( phy ) | + RDC_MMDIO_REGAD ( reg ) ); + writew ( mmdio, rdc->regs + RDC_MMDIO ); + + /* Wait for read to complete */ + for ( i = 0 ; i < RDC_MII_MAX_WAIT_US ; i++ ) { + + /* Check for read completion */ + if ( readw ( rdc->regs + RDC_MMDIO ) & RDC_MMDIO_MIIRD ) { + udelay ( 1 ); + continue; + } + + /* Return register value */ + return ( readw ( rdc->regs + RDC_MMRD ) ); + } + + DBGC ( rdc, "RDC %p timed out waiting for MII read\n", rdc ); + return -ETIMEDOUT; +} + +/** + * Write to MII register + * + * @v mdio MII interface + * @v phy PHY address + * @v reg Register address + * @v data Data to write + * @ret rc Return status code + */ +static int rdc_mii_write ( struct mii_interface *mdio, unsigned int phy, + unsigned int reg, unsigned int data ) { + struct rdc_nic *rdc = container_of ( mdio, struct rdc_nic, mdio ); + uint16_t mmdio; + unsigned int i; + + /* Initiate write */ + mmdio = ( RDC_MMDIO_MIIWR | RDC_MMDIO_PHYAD ( phy ) | + RDC_MMDIO_REGAD ( reg ) ); + writew ( data, rdc->regs + RDC_MMWD ); + writew ( mmdio, rdc->regs + RDC_MMDIO ); + + /* Wait for write to complete */ + for ( i = 0 ; i < RDC_MII_MAX_WAIT_US ; i++ ) { + + /* Check for write completion */ + if ( readw ( rdc->regs + RDC_MMDIO ) & RDC_MMDIO_MIIWR ) { + udelay ( 1 ); + continue; + } + + return 0; + } + + DBGC ( rdc, "RDC %p timed out waiting for MII write\n", rdc ); + return -ETIMEDOUT; +} + +/** RDC MII operations */ +static struct mii_operations rdc_mii_operations = { + .read = rdc_mii_read, + .write = rdc_mii_write, +}; + +/****************************************************************************** + * + * Link state + * + ****************************************************************************** + */ + +/** + * Initialise PHY + * + * @v rdc RDC device + * @ret rc Return status code + */ +static int rdc_init_phy ( struct rdc_nic *rdc ) { + int rc; + + /* Find PHY address */ + if ( ( rc = mii_find ( &rdc->mii ) ) != 0 ) { + DBGC ( rdc, "RDC %p could not find PHY address: %s\n", + rdc, strerror ( rc ) ); + return rc; + } + + /* Reset PHY */ + if ( ( rc = mii_reset ( &rdc->mii ) ) != 0 ) { + DBGC ( rdc, "RDC %p could not reset PHY: %s\n", + rdc, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** + * Check link state + * + * @v netdev Network device + * @ret rc Return status code + */ +static int rdc_check_link ( struct net_device *netdev ) { + struct rdc_nic *rdc = netdev->priv; + int rc; + + /* Check link state */ + if ( ( rc = mii_check_link ( &rdc->mii, netdev ) ) != 0 ) { + DBGC ( rdc, "RDC %p could not check link: %s\n", + rdc, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/****************************************************************************** + * + * Network device interface + * + ****************************************************************************** + */ + +/** + * Create descriptor ring + * + * @v rdc RDC device + * @v ring Descriptor ring + * @ret rc Return status code + */ +static int rdc_create_ring ( struct rdc_nic *rdc, struct rdc_ring *ring ) { + size_t len = ( ring->count * sizeof ( ring->desc[0] ) ); + struct rdc_descriptor *desc; + struct rdc_descriptor *next; + physaddr_t start; + unsigned int i; + + /* Allocate descriptor ring */ + ring->desc = dma_alloc ( rdc->dma, &ring->map, len, len ); + if ( ! ring->desc ) + return -ENOMEM; + + /* Initialise descriptor ring */ + memset ( ring->desc, 0, len ); + for ( i = 0 ; i < ring->count ; i++ ) { + desc = &ring->desc[i]; + next = &ring->desc[ ( i + 1 ) & ( ring->count - 1 ) ]; + desc->next = cpu_to_le32 ( dma ( &ring->map, next ) ); + } + + /* Program ring address */ + start = dma ( &ring->map, ring->desc ); + writew ( ( start >> 0 ), ( rdc->regs + ring->reg + RDC_MxDSA_LO ) ); + writew ( ( start >> 16 ), ( rdc->regs + ring->reg + RDC_MxDSA_HI ) ); + + DBGC ( rdc, "RDC %p ring %#02x is at [%08lx,%08lx)\n", + rdc, ring->reg, virt_to_phys ( ring->desc ), + ( virt_to_phys ( ring->desc ) + len ) ); + return 0; +} + +/** + * Destroy descriptor ring + * + * @v rdc RDC device + * @v ring Descriptor ring + */ +static void rdc_destroy_ring ( struct rdc_nic *rdc, struct rdc_ring *ring ) { + size_t len = ( ring->count * sizeof ( ring->desc[0] ) ); + + /* Clear ring address */ + writew ( 0, ( rdc->regs + ring->reg + RDC_MxDSA_LO ) ); + writew ( 0, ( rdc->regs + ring->reg + RDC_MxDSA_HI ) ); + + /* Free descriptors */ + dma_free ( &ring->map, ring->desc, len ); + ring->desc = NULL; + + /* Reset ring */ + ring->prod = 0; + ring->cons = 0; +} + +/** + * Refill receive descriptor ring + * + * @v rdc RDC device + */ +static void rdc_refill_rx ( struct rdc_nic *rdc ) { + struct rdc_descriptor *rx; + struct io_buffer *iobuf; + unsigned int rx_idx; + + /* Refill ring */ + while ( ( rdc->rx.prod - rdc->rx.cons ) < RDC_NUM_RX_DESC ) { + + /* Allocate I/O buffer */ + iobuf = alloc_rx_iob ( RDC_RX_MAX_LEN, rdc->dma ); + if ( ! iobuf ) { + /* Wait for next refill */ + break; + } + + /* Get next receive descriptor */ + rx_idx = ( rdc->rx.prod++ % RDC_NUM_RX_DESC ); + rx = &rdc->rx.desc[rx_idx]; + + /* Populate receive descriptor */ + rx->len = cpu_to_le16 ( RDC_RX_MAX_LEN ); + rx->addr = cpu_to_le32 ( iob_dma ( iobuf ) ); + wmb(); + rx->flags = cpu_to_le16 ( RDC_FL_OWNED ); + + /* Record I/O buffer */ + assert ( rdc->rx_iobuf[rx_idx] == NULL ); + rdc->rx_iobuf[rx_idx] = iobuf; + + DBGC2 ( rdc, "RDC %p RX %d is [%lx,%lx)\n", + rdc, rx_idx, virt_to_phys ( iobuf->data ), + ( virt_to_phys ( iobuf->data ) + RDC_RX_MAX_LEN ) ); + } +} + +/** + * Open network device + * + * @v netdev Network device + * @ret rc Return status code + */ +static int rdc_open ( struct net_device *netdev ) { + struct rdc_nic *rdc = netdev->priv; + int rc; + + /* Create transmit descriptor ring */ + if ( ( rc = rdc_create_ring ( rdc, &rdc->tx ) ) != 0 ) + goto err_create_tx; + + /* Create receive descriptor ring */ + if ( ( rc = rdc_create_ring ( rdc, &rdc->rx ) ) != 0 ) + goto err_create_rx; + + /* Program receive buffer length */ + writew ( RDC_RX_MAX_LEN, rdc->regs + RDC_MRBSR ); + + /* Enable transmit and receive */ + writew ( ( RDC_MCR0_FD | RDC_MCR0_TXEN | RDC_MCR0_PROMISC | + RDC_MCR0_RXEN ), + rdc->regs + RDC_MCR0 ); + + /* Enable PHY status polling */ + writew ( ( RDC_MPSCCR_EN | RDC_MPSCCR_PHYAD ( rdc->mii.address ) | + RDC_MPSCCR_SLOW ), + rdc->regs + RDC_MPSCCR ); + + /* Fill receive ring */ + rdc_refill_rx ( rdc ); + + /* Update link state */ + rdc_check_link ( netdev ); + + return 0; + + rdc_destroy_ring ( rdc, &rdc->rx ); + err_create_rx: + rdc_destroy_ring ( rdc, &rdc->tx ); + err_create_tx: + return rc; +} + +/** + * Close network device + * + * @v netdev Network device + */ +static void rdc_close ( struct net_device *netdev ) { + struct rdc_nic *rdc = netdev->priv; + unsigned int i; + + /* Disable NIC */ + writew ( 0, rdc->regs + RDC_MCR0 ); + + /* Destroy receive descriptor ring */ + rdc_destroy_ring ( rdc, &rdc->rx ); + + /* Discard any unused receive buffers */ + for ( i = 0 ; i < RDC_NUM_RX_DESC ; i++ ) { + if ( rdc->rx_iobuf[i] ) + free_rx_iob ( rdc->rx_iobuf[i] ); + rdc->rx_iobuf[i] = NULL; + } + + /* Destroy transmit descriptor ring */ + rdc_destroy_ring ( rdc, &rdc->tx ); +} + +/** + * Transmit packet + * + * @v netdev Network device + * @v iobuf I/O buffer + * @ret rc Return status code + */ +static int rdc_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { + struct rdc_nic *rdc = netdev->priv; + struct rdc_descriptor *tx; + unsigned int tx_idx; + int rc; + + /* Get next transmit descriptor */ + if ( ( rdc->tx.prod - rdc->tx.cons ) >= RDC_NUM_TX_DESC ) { + DBGC ( rdc, "RDC %p out of transmit descriptors\n", rdc ); + return -ENOBUFS; + } + tx_idx = ( rdc->tx.prod % RDC_NUM_TX_DESC ); + tx = &rdc->tx.desc[tx_idx]; + + /* Pad to minimum length */ + iob_pad ( iobuf, ETH_ZLEN ); + + /* Map I/O buffer */ + if ( ( rc = iob_map_tx ( iobuf, rdc->dma ) ) != 0 ) + return rc; + + /* Update producer index */ + rdc->tx.prod++; + + /* Populate transmit descriptor */ + tx->len = cpu_to_le16 ( iob_len ( iobuf ) ); + tx->addr = cpu_to_le32 ( iob_dma ( iobuf ) ); + wmb(); + tx->flags = cpu_to_le16 ( RDC_FL_OWNED ); + wmb(); + + /* Notify card that there are packets ready to transmit */ + writew ( RDC_MTPR_TM2TX, rdc->regs + RDC_MTPR ); + + return 0; +} + +/** + * Poll for completed packets + * + * @v netdev Network device + */ +static void rdc_poll_tx ( struct net_device *netdev ) { + struct rdc_nic *rdc = netdev->priv; + struct rdc_descriptor *tx; + unsigned int tx_idx; + + /* Check for completed packets */ + while ( rdc->tx.cons != rdc->tx.prod ) { + + /* Get next transmit descriptor */ + tx_idx = ( rdc->tx.cons % RDC_NUM_TX_DESC ); + tx = &rdc->tx.desc[tx_idx]; + + /* Stop if descriptor is still in use */ + if ( tx->flags & cpu_to_le16 ( RDC_FL_OWNED ) ) + return; + DBGC2 ( rdc, "RDC %p TX %d complete\n", rdc, tx_idx ); + + /* Complete transmit descriptor */ + rdc->tx.cons++; + netdev_tx_complete_next ( netdev ); + } +} + +/** + * Poll for received packets + * + * @v netdev Network device + */ +static void rdc_poll_rx ( struct net_device *netdev ) { + struct rdc_nic *rdc = netdev->priv; + struct rdc_descriptor *rx; + struct io_buffer *iobuf; + unsigned int rx_idx; + size_t len; + + /* Check for received packets */ + while ( rdc->rx.cons != rdc->rx.prod ) { + + /* Get next receive descriptor */ + rx_idx = ( rdc->rx.cons % RDC_NUM_RX_DESC ); + rx = &rdc->rx.desc[rx_idx]; + + /* Stop if descriptor is still in use */ + if ( rx->flags & cpu_to_le16 ( RDC_FL_OWNED ) ) + return; + + /* Populate I/O buffer */ + iobuf = rdc->rx_iobuf[rx_idx]; + rdc->rx_iobuf[rx_idx] = NULL; + len = le16_to_cpu ( rx->len ); + iob_put ( iobuf, len ); + iob_unput ( iobuf, 4 /* strip CRC */ ); + + /* Hand off to network stack */ + if ( rx->flags & cpu_to_le16 ( RDC_FL_OK ) ) { + DBGC2 ( rdc, "RDC %p RX %d complete (length %zd)\n", + rdc, rx_idx, len ); + netdev_rx ( netdev, iobuf ); + } else { + DBGC2 ( rdc, "RDC %p RX %d error (length %zd, " + "flags %#04x)\n", rdc, rx_idx, len, + le16_to_cpu ( rx->flags ) ); + netdev_rx_err ( netdev, iobuf, -EIO ); + } + rdc->rx.cons++; + } +} + +/** + * Poll for completed and received packets + * + * @v netdev Network device + */ +static void rdc_poll ( struct net_device *netdev ) { + struct rdc_nic *rdc = netdev->priv; + uint16_t misr; + + /* Check for (and acknowledge) interrupts */ + misr = readw ( rdc->regs + RDC_MISR ); + + /* Poll for TX completions, if applicable */ + if ( misr & RDC_MIRQ_TX ) + rdc_poll_tx ( netdev ); + + /* Poll for RX completions, if applicable */ + if ( misr & RDC_MIRQ_RX ) + rdc_poll_rx ( netdev ); + + /* Check link state, if applicable */ + if ( misr & RDC_MIRQ_LINK ) + rdc_check_link ( netdev ); + + /* Check for unexpected interrupts */ + if ( misr & ~( RDC_MIRQ_LINK | RDC_MIRQ_TX | RDC_MIRQ_RX_EARLY | + RDC_MIRQ_RX_EMPTY | RDC_MIRQ_RX ) ) { + DBGC ( rdc, "RDC %p unexpected MISR %#04x\n", rdc, misr ); + /* Report as a TX error */ + netdev_tx_err ( netdev, NULL, -ENOTSUP ); + } + + /* Refill receive ring */ + rdc_refill_rx ( rdc ); +} + +/** + * Enable or disable interrupts + * + * @v netdev Network device + * @v enable Interrupts should be enabled + */ +static void rdc_irq ( struct net_device *netdev, int enable ) { + struct rdc_nic *rdc = netdev->priv; + uint16_t mier; + + /* Enable/disable interrupts */ + mier = ( enable ? ( RDC_MIRQ_LINK | RDC_MIRQ_TX | RDC_MIRQ_RX ) : 0 ); + writew ( mier, rdc->regs + RDC_MIER ); +} + +/** RDC network device operations */ +static struct net_device_operations rdc_operations = { + .open = rdc_open, + .close = rdc_close, + .transmit = rdc_transmit, + .poll = rdc_poll, + .irq = rdc_irq, +}; + +/****************************************************************************** + * + * PCI interface + * + ****************************************************************************** + */ + +/** + * Probe PCI device + * + * @v pci PCI device + * @ret rc Return status code + */ +static int rdc_probe ( struct pci_device *pci ) { + struct net_device *netdev; + struct rdc_nic *rdc; + union rdc_mac mac; + int rc; + + /* Allocate and initialise net device */ + netdev = alloc_etherdev ( sizeof ( *rdc ) ); + if ( ! netdev ) { + rc = -ENOMEM; + goto err_alloc; + } + netdev_init ( netdev, &rdc_operations ); + rdc = netdev->priv; + pci_set_drvdata ( pci, netdev ); + netdev->dev = &pci->dev; + memset ( rdc, 0, sizeof ( *rdc ) ); + rdc->dma = &pci->dma; + mdio_init ( &rdc->mdio, &rdc_mii_operations ); + mii_init ( &rdc->mii, &rdc->mdio, 0 ); + rdc_init_ring ( &rdc->tx, RDC_NUM_TX_DESC, RDC_MTDSA ); + rdc_init_ring ( &rdc->rx, RDC_NUM_RX_DESC, RDC_MRDSA ); + + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Map registers */ + rdc->regs = pci_ioremap ( pci, pci->membase, RDC_BAR_SIZE ); + if ( ! rdc->regs ) { + rc = -ENODEV; + goto err_ioremap; + } + + /* Fetch MAC address */ + mac.mid[0] = cpu_to_le16 ( readw ( rdc->regs + RDC_MID0 ) ); + mac.mid[1] = cpu_to_le16 ( readw ( rdc->regs + RDC_MID1 ) ); + mac.mid[2] = cpu_to_le16 ( readw ( rdc->regs + RDC_MID2 ) ); + memcpy ( netdev->hw_addr, mac.raw, ETH_ALEN ); + + /* Reset the NIC */ + if ( ( rc = rdc_reset ( rdc ) ) != 0 ) + goto err_reset; + + /* Initialise PHY */ + if ( ( rc = rdc_init_phy ( rdc ) ) != 0 ) + goto err_init_phy; + + /* Register network device */ + if ( ( rc = register_netdev ( netdev ) ) != 0 ) + goto err_register_netdev; + + /* Set initial link state */ + rdc_check_link ( netdev ); + + return 0; + + unregister_netdev ( netdev ); + err_register_netdev: + err_init_phy: + rdc_reset ( rdc ); + err_reset: + iounmap ( rdc->regs ); + err_ioremap: + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: + return rc; +} + +/** + * Remove PCI device + * + * @v pci PCI device + */ +static void rdc_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); + struct rdc_nic *rdc = netdev->priv; + + /* Unregister network device */ + unregister_netdev ( netdev ); + + /* Reset card */ + rdc_reset ( rdc ); + + /* Free network device */ + iounmap ( rdc->regs ); + netdev_nullify ( netdev ); + netdev_put ( netdev ); +} + +/** RDC PCI device IDs */ +static struct pci_device_id rdc_nics[] = { + PCI_ROM ( 0x17f3, 0x6040, "r6040", "RDC R6040", 0 ), +}; + +/** RDC PCI driver */ +struct pci_driver rdc_driver __pci_driver = { + .ids = rdc_nics, + .id_count = ( sizeof ( rdc_nics ) / sizeof ( rdc_nics[0] ) ), + .probe = rdc_probe, + .remove = rdc_remove, +}; diff --git a/src/drivers/net/rdc.h b/src/drivers/net/rdc.h new file mode 100644 index 000000000..ee1671fdd --- /dev/null +++ b/src/drivers/net/rdc.h @@ -0,0 +1,194 @@ +#ifndef _RDC_H +#define _RDC_H + +/** @file + * + * RDC R6040 network driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <stdint.h> +#include <ipxe/if_ether.h> +#include <ipxe/mii.h> + +/** RDC BAR size */ +#define RDC_BAR_SIZE 256 + +/** An RDC descriptor */ +struct rdc_descriptor { + /** Flags */ + uint16_t flags; + /** Length */ + uint16_t len; + /** Address */ + uint32_t addr; + /** Next descriptor */ + uint32_t next; + /** Reserved */ + uint32_t reserved; +} __attribute__ (( packed )); + +/** Descriptor is owned by NIC */ +#define RDC_FL_OWNED 0x8000 + +/** Packet OK */ +#define RDC_FL_OK 0x4000 + +/** MAC control register 0 */ +#define RDC_MCR0 0x00 +#define RDC_MCR0_FD 0x8000 /**< Full duplex */ +#define RDC_MCR0_TXEN 0x1000 /**< Transmit enable */ +#define RDC_MCR0_PROMISC 0x0020 /**< Promiscuous mode */ +#define RDC_MCR0_RXEN 0x0002 /**< Receive enable */ + +/** MAC control register 1 */ +#define RDC_MCR1 0x04 +#define RDC_MCR1_RST 0x0001 /**< MAC reset */ + +/** Maximum time to wait for reset */ +#define RDC_RESET_MAX_WAIT_MS 10 + +/** MAC transmit poll command register */ +#define RDC_MTPR 0x14 +#define RDC_MTPR_TM2TX 0x0001 /**< Trigger MAC to transmit */ + +/** MAC receive buffer size register */ +#define RDC_MRBSR 0x18 + +/** MAC MDIO control register */ +#define RDC_MMDIO 0x20 +#define RDC_MMDIO_MIIWR 0x4000 /**< MDIO write */ +#define RDC_MMDIO_MIIRD 0x2000 /**< MDIO read */ +#define RDC_MMDIO_PHYAD(x) ( (x) << 8 ) /**< PHY address */ +#define RDC_MMDIO_REGAD(x) ( (x) << 0 ) /**< Register address */ + +/** Maximum time to wait for an MII read or write */ +#define RDC_MII_MAX_WAIT_US 2048 + +/** MAC MDIO read data register */ +#define RDC_MMRD 0x24 + +/** MAC MDIO write data register */ +#define RDC_MMWD 0x28 + +/** MAC transmit descriptor start address */ +#define RDC_MTDSA 0x2c + +/** MAC receive descriptor start address */ +#define RDC_MRDSA 0x34 + +/** MAC descriptor start address low half */ +#define RDC_MxDSA_LO 0x0 + +/** MAC descriptor start address low half */ +#define RDC_MxDSA_HI 0x4 + +/** MAC interrupt status register */ +#define RDC_MISR 0x3c +#define RDC_MIRQ_LINK 0x0200 /**< Link status changed */ +#define RDC_MIRQ_TX 0x0010 /**< Transmit complete */ +#define RDC_MIRQ_RX_EARLY 0x0008 /**< Receive early interrupt */ +#define RDC_MIRQ_RX_EMPTY 0x0002 /**< Receive descriptor unavailable */ +#define RDC_MIRQ_RX 0x0001 /**< Receive complete */ + +/** MAC interrupt enable register */ +#define RDC_MIER 0x40 + +/** MAC address word 0 */ +#define RDC_MID0 0x68 + +/** MAC address word 1 */ +#define RDC_MID1 0x6a + +/** MAC address word 2 */ +#define RDC_MID2 0x6c + +/** MAC PHY status change configuration register */ +#define RDC_MPSCCR 0x88 +#define RDC_MPSCCR_EN 0x8000 /**< PHY status change enable */ +#define RDC_MPSCCR_PHYAD(x) ( (x) << 8 ) /**< PHY address */ +#define RDC_MPSCCR_SLOW 0x0007 /**< Poll slowly */ + +/** MAC state machine register */ +#define RDC_MACSM 0xac +#define RDC_MACSM_RST 0x0002 /**< Reset state machine */ + +/** Time to wait after resetting MAC state machine */ +#define RDC_MACSM_RESET_DELAY_MS 10 + +/** A MAC address */ +union rdc_mac { + /** Raw bytes */ + uint8_t raw[ETH_ALEN]; + /** MIDx registers */ + uint16_t mid[ ETH_ALEN / 2 ]; +}; + +/** A descriptor ring */ +struct rdc_ring { + /** Descriptors */ + struct rdc_descriptor *desc; + /** Descriptor ring DMA mapping */ + struct dma_mapping map; + /** Producer index */ + unsigned int prod; + /** Consumer index */ + unsigned int cons; + + /** Number of descriptors */ + unsigned int count; + /** Start address register 0 */ + unsigned int reg; +}; + +/** + * Initialise descriptor ring + * + * @v ring Descriptor ring + * @v count Number of descriptors + * @v reg Start address register 0 + */ +static inline __attribute__ (( always_inline )) void +rdc_init_ring ( struct rdc_ring *ring, unsigned int count, unsigned int reg ) { + + ring->count = count; + ring->reg = reg; +} + +/** Number of transmit descriptors + * + * This is a policy decision. + */ +#define RDC_NUM_TX_DESC 16 + +/** Number of receive descriptors + * + * This is a policy decision. + */ +#define RDC_NUM_RX_DESC 8 + +/** Receive buffer length */ +#define RDC_RX_MAX_LEN ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ ) + +/** An RDC network card */ +struct rdc_nic { + /** Registers */ + void *regs; + /** DMA device */ + struct dma_device *dma; + /** MII interface */ + struct mii_interface mdio; + /** MII device */ + struct mii_device mii; + + /** Transmit descriptor ring */ + struct rdc_ring tx; + /** Receive descriptor ring */ + struct rdc_ring rx; + /** Receive I/O buffers */ + struct io_buffer *rx_iobuf[RDC_NUM_RX_DESC]; +}; + +#endif /* _RDC_H */ diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 0af3416d5..a43efb68b 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -420,6 +420,16 @@ static int realtek_phy_reset ( struct realtek_nic *rtl ) { */ } + /* Some cards (e.g. RTL8211B) have a hardware errata that + * requires the MII_MMD_DATA register to be cleared before the + * link will come up. + */ + if ( ( rc = mii_write ( &rtl->mii, MII_MMD_DATA, 0 ) ) != 0 ) { + /* Ignore failures, since the register may not be + * present on all PHYs. + */ + } + /* Restart autonegotiation */ if ( ( rc = mii_restart ( &rtl->mii ) ) != 0 ) { DBGC ( rtl, "REALTEK %p could not restart MII: %s\n", |
