diff --git a/repos/dde_ipxe/patches/intel_update.patch b/repos/dde_ipxe/patches/intel_update.patch new file mode 100644 index 000000000..40c5a5735 --- /dev/null +++ b/repos/dde_ipxe/patches/intel_update.patch @@ -0,0 +1,820 @@ +diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c +index 7cb268ac..dad8941a 100644 +--- a/src/drivers/net/intel.c ++++ b/src/drivers/net/intel.c +@@ -15,6 +15,10 @@ + * 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 ); +@@ -233,27 +237,6 @@ static int intel_fetch_mac ( struct intel_nic *intel, uint8_t *hw_addr ) { + return -ENOENT; + } + +-/****************************************************************************** +- * +- * Diagnostics +- * +- ****************************************************************************** +- */ +- +-/** +- * Dump diagnostic information +- * +- * @v intel Intel device +- */ +-static void __attribute__ (( unused )) intel_diag ( struct intel_nic *intel ) { +- +- DBGC ( intel, "INTEL %p TDH=%04x TDT=%04x RDH=%04x RDT=%04x\n", intel, +- readl ( intel->regs + intel->tx.reg + INTEL_xDH ), +- readl ( intel->regs + intel->tx.reg + INTEL_xDT ), +- readl ( intel->regs + intel->rx.reg + INTEL_xDH ), +- readl ( intel->regs + intel->rx.reg + INTEL_xDT ) ); +-} +- + /****************************************************************************** + * + * Device reset +@@ -269,39 +252,61 @@ static void __attribute__ (( unused )) intel_diag ( struct intel_nic *intel ) { + */ + static int intel_reset ( struct intel_nic *intel ) { + uint32_t pbs; ++ uint32_t pba; + uint32_t ctrl; + uint32_t status; ++ uint32_t orig_ctrl; ++ uint32_t orig_status; ++ ++ /* Record initial control and status register values */ ++ orig_ctrl = ctrl = readl ( intel->regs + INTEL_CTRL ); ++ orig_status = readl ( intel->regs + INTEL_STATUS ); + + /* Force RX and TX packet buffer allocation, to work around an + * errata in ICH devices. + */ +- pbs = readl ( intel->regs + INTEL_PBS ); +- if ( ( pbs == 0x14 ) || ( pbs == 0x18 ) ) { ++ if ( intel->flags & INTEL_PBS_ERRATA ) { + DBGC ( intel, "INTEL %p WARNING: applying ICH PBS/PBA errata\n", + intel ); ++ pbs = readl ( intel->regs + INTEL_PBS ); ++ pba = readl ( intel->regs + INTEL_PBA ); + writel ( 0x08, intel->regs + INTEL_PBA ); + writel ( 0x10, intel->regs + INTEL_PBS ); ++ DBGC ( intel, "INTEL %p PBS %#08x->%#08x PBA %#08x->%#08x\n", ++ intel, pbs, readl ( intel->regs + INTEL_PBS ), ++ pba, readl ( intel->regs + INTEL_PBA ) ); + } + + /* Always reset MAC. Required to reset the TX and RX rings. */ +- ctrl = readl ( intel->regs + INTEL_CTRL ); + writel ( ( ctrl | INTEL_CTRL_RST ), intel->regs + INTEL_CTRL ); + mdelay ( INTEL_RESET_DELAY_MS ); + + /* Set a sensible default configuration */ +- ctrl |= ( INTEL_CTRL_SLU | INTEL_CTRL_ASDE ); ++ if ( ! ( intel->flags & INTEL_NO_ASDE ) ) ++ ctrl |= INTEL_CTRL_ASDE; ++ ctrl |= INTEL_CTRL_SLU; + ctrl &= ~( INTEL_CTRL_LRST | INTEL_CTRL_FRCSPD | INTEL_CTRL_FRCDPLX ); + writel ( ctrl, intel->regs + INTEL_CTRL ); + mdelay ( INTEL_RESET_DELAY_MS ); + +- /* If link is already up, do not attempt to reset the PHY. On +- * some models (notably ICH), performing a PHY reset seems to +- * drop the link speed to 10Mbps. ++ /* On some models (notably ICH), the PHY reset mechanism ++ * appears to be broken. In particular, the PHY_CTRL register ++ * will be correctly loaded from NVM but the values will not ++ * be propagated to the "OEM bits" PHY register. This ++ * typically has the effect of dropping the link speed to ++ * 10Mbps. ++ * ++ * Work around this problem by skipping the PHY reset if ++ * either (a) the link is already up, or (b) this particular ++ * NIC is known to be broken. + */ + status = readl ( intel->regs + INTEL_STATUS ); +- if ( status & INTEL_STATUS_LU ) { +- DBGC ( intel, "INTEL %p MAC reset (ctrl %08x)\n", +- intel, ctrl ); ++ if ( ( intel->flags & INTEL_NO_PHY_RST ) || ++ ( status & INTEL_STATUS_LU ) ) { ++ DBGC ( intel, "INTEL %p %sMAC reset (%08x/%08x was " ++ "%08x/%08x)\n", intel, ++ ( ( intel->flags & INTEL_NO_PHY_RST ) ? "forced " : "" ), ++ ctrl, status, orig_ctrl, orig_status ); + return 0; + } + +@@ -316,8 +321,10 @@ static int intel_reset ( struct intel_nic *intel ) { + /* PHY reset is not self-clearing on all models */ + writel ( ctrl, intel->regs + INTEL_CTRL ); + mdelay ( INTEL_RESET_DELAY_MS ); ++ status = readl ( intel->regs + INTEL_STATUS ); + +- DBGC ( intel, "INTEL %p MAC+PHY reset (ctrl %08x)\n", intel, ctrl ); ++ DBGC ( intel, "INTEL %p MAC+PHY reset (%08x/%08x was %08x/%08x)\n", ++ intel, ctrl, status, orig_ctrl, orig_status ); + return 0; + } + +@@ -349,6 +356,67 @@ static void intel_check_link ( struct net_device *netdev ) { + } + } + ++/****************************************************************************** ++ * ++ * Descriptors ++ * ++ ****************************************************************************** ++ */ ++ ++/** ++ * Populate transmit descriptor ++ * ++ * @v tx Transmit descriptor ++ * @v addr Data buffer address ++ * @v len Length of data ++ */ ++void intel_describe_tx ( struct intel_descriptor *tx, physaddr_t addr, ++ size_t len ) { ++ ++ /* Populate transmit descriptor */ ++ tx->address = cpu_to_le64 ( addr ); ++ tx->length = cpu_to_le16 ( len ); ++ tx->flags = 0; ++ tx->command = ( INTEL_DESC_CMD_RS | INTEL_DESC_CMD_IFCS | ++ INTEL_DESC_CMD_EOP ); ++ tx->status = 0; ++} ++ ++/** ++ * Populate advanced transmit descriptor ++ * ++ * @v tx Transmit descriptor ++ * @v addr Data buffer address ++ * @v len Length of data ++ */ ++void intel_describe_tx_adv ( struct intel_descriptor *tx, physaddr_t addr, ++ size_t len ) { ++ ++ /* Populate advanced transmit descriptor */ ++ tx->address = cpu_to_le64 ( addr ); ++ tx->length = cpu_to_le16 ( len ); ++ tx->flags = INTEL_DESC_FL_DTYP_DATA; ++ tx->command = ( INTEL_DESC_CMD_DEXT | INTEL_DESC_CMD_RS | ++ INTEL_DESC_CMD_IFCS | INTEL_DESC_CMD_EOP ); ++ tx->status = cpu_to_le32 ( INTEL_DESC_STATUS_PAYLEN ( len ) ); ++} ++ ++/** ++ * Populate receive descriptor ++ * ++ * @v rx Receive descriptor ++ * @v addr Data buffer address ++ * @v len Length of data ++ */ ++void intel_describe_rx ( struct intel_descriptor *rx, physaddr_t addr, ++ size_t len __unused ) { ++ ++ /* Populate transmit descriptor */ ++ rx->address = cpu_to_le64 ( addr ); ++ rx->length = 0; ++ rx->status = 0; ++} ++ + /****************************************************************************** + * + * Network device interface +@@ -356,6 +424,61 @@ static void intel_check_link ( struct net_device *netdev ) { + ****************************************************************************** + */ + ++/** ++ * Disable descriptor ring ++ * ++ * @v intel Intel device ++ * @v reg Register block ++ * @ret rc Return status code ++ */ ++static int intel_disable_ring ( struct intel_nic *intel, unsigned int reg ) { ++ uint32_t dctl; ++ unsigned int i; ++ ++ /* Disable ring */ ++ writel ( 0, ( intel->regs + reg + INTEL_xDCTL ) ); ++ ++ /* Wait for disable to complete */ ++ for ( i = 0 ; i < INTEL_DISABLE_MAX_WAIT_MS ; i++ ) { ++ ++ /* Check if ring is disabled */ ++ dctl = readl ( intel->regs + reg + INTEL_xDCTL ); ++ if ( ! ( dctl & INTEL_xDCTL_ENABLE ) ) ++ return 0; ++ ++ /* Delay */ ++ mdelay ( 1 ); ++ } ++ ++ DBGC ( intel, "INTEL %p ring %05x timed out waiting for disable " ++ "(dctl %08x)\n", intel, reg, dctl ); ++ return -ETIMEDOUT; ++} ++ ++/** ++ * Reset descriptor ring ++ * ++ * @v intel Intel device ++ * @v reg Register block ++ * @ret rc Return status code ++ */ ++void intel_reset_ring ( struct intel_nic *intel, unsigned int reg ) { ++ ++ /* Disable ring. Ignore errors and continue to reset the ring anyway */ ++ intel_disable_ring ( intel, reg ); ++ ++ /* Clear ring length */ ++ writel ( 0, ( intel->regs + reg + INTEL_xDLEN ) ); ++ ++ /* Clear ring address */ ++ writel ( 0, ( intel->regs + reg + INTEL_xDBAH ) ); ++ writel ( 0, ( intel->regs + reg + INTEL_xDBAL ) ); ++ ++ /* Reset head and tail pointers */ ++ writel ( 0, ( intel->regs + reg + INTEL_xDH ) ); ++ writel ( 0, ( intel->regs + reg + INTEL_xDT ) ); ++} ++ + /** + * Create descriptor ring + * +@@ -416,12 +539,8 @@ int intel_create_ring ( struct intel_nic *intel, struct intel_ring *ring ) { + */ + void intel_destroy_ring ( struct intel_nic *intel, struct intel_ring *ring ) { + +- /* Clear ring length */ +- writel ( 0, ( intel->regs + ring->reg + INTEL_xDLEN ) ); +- +- /* Clear ring address */ +- writel ( 0, ( intel->regs + ring->reg + INTEL_xDBAL ) ); +- writel ( 0, ( intel->regs + ring->reg + INTEL_xDBAH ) ); ++ /* Reset ring */ ++ intel_reset_ring ( intel, ring->reg ); + + /* Free descriptor ring */ + free_dma ( ring->desc, ring->len ); +@@ -441,39 +560,41 @@ void intel_refill_rx ( struct intel_nic *intel ) { + unsigned int rx_idx; + unsigned int rx_tail; + physaddr_t address; ++ unsigned int refilled = 0; + ++ /* Refill ring */ + while ( ( intel->rx.prod - intel->rx.cons ) < INTEL_RX_FILL ) { + + /* Allocate I/O buffer */ + iobuf = alloc_iob ( INTEL_RX_MAX_LEN ); + if ( ! iobuf ) { + /* Wait for next refill */ +- return; ++ break; + } + + /* Get next receive descriptor */ + rx_idx = ( intel->rx.prod++ % INTEL_NUM_RX_DESC ); +- rx_tail = ( intel->rx.prod % INTEL_NUM_RX_DESC ); + rx = &intel->rx.desc[rx_idx]; + + /* Populate receive descriptor */ + address = virt_to_bus ( iobuf->data ); +- rx->address = cpu_to_le64 ( address ); +- rx->length = 0; +- rx->status = 0; +- rx->errors = 0; +- wmb(); ++ intel->rx.describe ( rx, address, 0 ); + + /* Record I/O buffer */ + assert ( intel->rx_iobuf[rx_idx] == NULL ); + intel->rx_iobuf[rx_idx] = iobuf; + +- /* Push descriptor to card */ +- writel ( rx_tail, intel->regs + intel->rx.reg + INTEL_xDT ); +- + DBGC2 ( intel, "INTEL %p RX %d is [%llx,%llx)\n", intel, rx_idx, + ( ( unsigned long long ) address ), + ( ( unsigned long long ) address + INTEL_RX_MAX_LEN ) ); ++ refilled++; ++ } ++ ++ /* Push descriptors to card, if applicable */ ++ if ( refilled ) { ++ wmb(); ++ rx_tail = ( intel->rx.prod % INTEL_NUM_RX_DESC ); ++ writel ( rx_tail, intel->regs + intel->rx.reg + INTEL_xDT ); + } + } + +@@ -501,10 +622,23 @@ void intel_empty_rx ( struct intel_nic *intel ) { + static int intel_open ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + union intel_receive_address mac; ++ uint32_t fextnvm11; + uint32_t tctl; + uint32_t rctl; + int rc; + ++ /* Set undocumented bit in FEXTNVM11 to work around an errata ++ * in i219 devices that will otherwise cause a complete ++ * datapath hang at the next device reset. ++ */ ++ if ( intel->flags & INTEL_RST_HANG ) { ++ DBGC ( intel, "INTEL %p WARNING: applying reset hang " ++ "workaround\n", intel ); ++ fextnvm11 = readl ( intel->regs + INTEL_FEXTNVM11 ); ++ fextnvm11 |= INTEL_FEXTNVM11_WTF; ++ writel ( fextnvm11, intel->regs + INTEL_FEXTNVM11 ); ++ } ++ + /* Create transmit descriptor ring */ + if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 ) + goto err_create_tx; +@@ -540,6 +674,13 @@ static int intel_open ( struct net_device *netdev ) { + /* Update link state */ + intel_check_link ( netdev ); + ++ /* Apply required errata */ ++ if ( intel->flags & INTEL_VMWARE ) { ++ DBGC ( intel, "INTEL %p applying VMware errata workaround\n", ++ intel ); ++ intel->force_icr = INTEL_IRQ_RXT0; ++ } ++ + return 0; + + intel_destroy_ring ( intel, &intel->rx ); +@@ -589,9 +730,10 @@ int intel_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { + unsigned int tx_idx; + unsigned int tx_tail; + physaddr_t address; ++ size_t len; + + /* Get next transmit descriptor */ +- if ( ( intel->tx.prod - intel->tx.cons ) >= INTEL_NUM_TX_DESC ) { ++ if ( ( intel->tx.prod - intel->tx.cons ) >= INTEL_TX_FILL ) { + DBGC ( intel, "INTEL %p out of transmit descriptors\n", intel ); + return -ENOBUFS; + } +@@ -601,11 +743,8 @@ int intel_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { + + /* Populate transmit descriptor */ + address = virt_to_bus ( iobuf->data ); +- tx->address = cpu_to_le64 ( address ); +- tx->length = cpu_to_le16 ( iob_len ( iobuf ) ); +- tx->command = ( INTEL_DESC_CMD_RS | INTEL_DESC_CMD_IFCS | +- INTEL_DESC_CMD_EOP ); +- tx->status = 0; ++ len = iob_len ( iobuf ); ++ intel->tx.describe ( tx, address, len ); + wmb(); + + /* Notify card that there are packets ready to transmit */ +@@ -613,7 +752,7 @@ int intel_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { + + DBGC2 ( intel, "INTEL %p TX %d is [%llx,%llx)\n", intel, tx_idx, + ( ( unsigned long long ) address ), +- ( ( unsigned long long ) address + iob_len ( iobuf ) ) ); ++ ( ( unsigned long long ) address + len ) ); + + return 0; + } +@@ -636,7 +775,7 @@ void intel_poll_tx ( struct net_device *netdev ) { + tx = &intel->tx.desc[tx_idx]; + + /* Stop if descriptor is still in use */ +- if ( ! ( tx->status & INTEL_DESC_STATUS_DD ) ) ++ if ( ! ( tx->status & cpu_to_le32 ( INTEL_DESC_STATUS_DD ) ) ) + return; + + DBGC2 ( intel, "INTEL %p TX %d complete\n", intel, tx_idx ); +@@ -667,7 +806,7 @@ void intel_poll_rx ( struct net_device *netdev ) { + rx = &intel->rx.desc[rx_idx]; + + /* Stop if descriptor is still in use */ +- if ( ! ( rx->status & INTEL_DESC_STATUS_DD ) ) ++ if ( ! ( rx->status & cpu_to_le32 ( INTEL_DESC_STATUS_DD ) ) ) + return; + + /* Populate I/O buffer */ +@@ -677,10 +816,10 @@ void intel_poll_rx ( struct net_device *netdev ) { + iob_put ( iobuf, len ); + + /* Hand off to network stack */ +- if ( rx->errors ) { ++ if ( rx->status & cpu_to_le32 ( INTEL_DESC_STATUS_RXE ) ) { + DBGC ( intel, "INTEL %p RX %d error (length %zd, " +- "errors %02x)\n", +- intel, rx_idx, len, rx->errors ); ++ "status %08x)\n", intel, rx_idx, len, ++ le32_to_cpu ( rx->status ) ); + netdev_rx_err ( netdev, iobuf, -EIO ); + } else { + DBGC2 ( intel, "INTEL %p RX %d complete (length %zd)\n", +@@ -721,6 +860,14 @@ static void intel_poll ( struct net_device *netdev ) { + if ( icr & INTEL_IRQ_LSC ) + intel_check_link ( netdev ); + ++ /* Check for unexpected interrupts */ ++ if ( icr & ~( INTEL_IRQ_TXDW | INTEL_IRQ_TXQE | INTEL_IRQ_LSC | ++ INTEL_IRQ_RXDMT0 | INTEL_IRQ_RXT0 | INTEL_IRQ_RXO ) ) { ++ DBGC ( intel, "INTEL %p unexpected ICR %08x\n", intel, icr ); ++ /* Report as a TX error */ ++ netdev_tx_err ( netdev, NULL, -ENOTSUP ); ++ } ++ + /* Refill RX ring */ + intel_refill_rx ( intel ); + } +@@ -782,14 +929,21 @@ static int intel_probe ( struct pci_device *pci ) { + netdev->dev = &pci->dev; + memset ( intel, 0, sizeof ( *intel ) ); + intel->port = PCI_FUNC ( pci->busdevfn ); +- intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTEL_TD ); +- intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTEL_RD ); ++ intel->flags = pci->id->driver_data; ++ intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTEL_TD, ++ intel_describe_tx ); ++ intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTEL_RD, ++ intel_describe_rx ); + + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Map registers */ + intel->regs = ioremap ( pci->membase, INTEL_BAR_SIZE ); ++ if ( ! intel->regs ) { ++ rc = -ENODEV; ++ goto err_ioremap; ++ } + + /* Reset the NIC */ + if ( ( rc = intel_reset ( intel ) ) != 0 ) +@@ -814,6 +968,7 @@ static int intel_probe ( struct pci_device *pci ) { + intel_reset ( intel ); + err_reset: + iounmap ( intel->regs ); ++ err_ioremap: + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: +@@ -855,7 +1010,7 @@ static struct pci_device_id intel_nics[] = { + PCI_ROM ( 0x8086, 0x100c, "82544gc", "82544GC (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x100d, "82544gc-l", "82544GC (LOM)", 0 ), + PCI_ROM ( 0x8086, 0x100e, "82540em", "82540EM", 0 ), +- PCI_ROM ( 0x8086, 0x100f, "82545em", "82545EM (Copper)", 0 ), ++ PCI_ROM ( 0x8086, 0x100f, "82545em", "82545EM (Copper)", INTEL_VMWARE ), + PCI_ROM ( 0x8086, 0x1010, "82546eb", "82546EB (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x1011, "82545em-f", "82545EM (Fiber)", 0 ), + PCI_ROM ( 0x8086, 0x1012, "82546eb-f", "82546EB (Fiber)", 0 ), +@@ -872,11 +1027,11 @@ static struct pci_device_id intel_nics[] = { + PCI_ROM ( 0x8086, 0x1026, "82545gm", "82545GM", 0 ), + PCI_ROM ( 0x8086, 0x1027, "82545gm-1", "82545GM", 0 ), + PCI_ROM ( 0x8086, 0x1028, "82545gm-2", "82545GM", 0 ), +- PCI_ROM ( 0x8086, 0x1049, "82566mm", "82566MM", 0 ), +- PCI_ROM ( 0x8086, 0x104a, "82566dm", "82566DM", 0 ), +- PCI_ROM ( 0x8086, 0x104b, "82566dc", "82566DC", 0 ), +- PCI_ROM ( 0x8086, 0x104c, "82562v", "82562V 10/100", 0 ), +- PCI_ROM ( 0x8086, 0x104d, "82566mc", "82566MC", 0 ), ++ PCI_ROM ( 0x8086, 0x1049, "82566mm", "82566MM", INTEL_PBS_ERRATA ), ++ PCI_ROM ( 0x8086, 0x104a, "82566dm", "82566DM", INTEL_PBS_ERRATA ), ++ PCI_ROM ( 0x8086, 0x104b, "82566dc", "82566DC", INTEL_PBS_ERRATA ), ++ PCI_ROM ( 0x8086, 0x104c, "82562v", "82562V", INTEL_PBS_ERRATA ), ++ PCI_ROM ( 0x8086, 0x104d, "82566mc", "82566MC", INTEL_PBS_ERRATA ), + PCI_ROM ( 0x8086, 0x105e, "82571eb", "82571EB", 0 ), + PCI_ROM ( 0x8086, 0x105f, "82571eb-1", "82571EB", 0 ), + PCI_ROM ( 0x8086, 0x1060, "82571eb-2", "82571EB", 0 ), +@@ -909,11 +1064,11 @@ static struct pci_device_id intel_nics[] = { + PCI_ROM ( 0x8086, 0x10bc, "82571eb", "82571EB (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x10bd, "82566dm-2", "82566DM-2", 0 ), + PCI_ROM ( 0x8086, 0x10bf, "82567lf", "82567LF", 0 ), +- PCI_ROM ( 0x8086, 0x10c0, "82562v-2", "82562V-2 10/100", 0 ), +- PCI_ROM ( 0x8086, 0x10c2, "82562g-2", "82562G-2 10/100", 0 ), +- PCI_ROM ( 0x8086, 0x10c3, "82562gt-2", "82562GT-2 10/100", 0 ), +- PCI_ROM ( 0x8086, 0x10c4, "82562gt", "82562GT 10/100", 0 ), +- PCI_ROM ( 0x8086, 0x10c5, "82562g", "82562G 10/100", 0 ), ++ PCI_ROM ( 0x8086, 0x10c0, "82562v-2", "82562V-2", 0 ), ++ PCI_ROM ( 0x8086, 0x10c2, "82562g-2", "82562G-2", 0 ), ++ PCI_ROM ( 0x8086, 0x10c3, "82562gt-2", "82562GT-2", 0 ), ++ PCI_ROM ( 0x8086, 0x10c4, "82562gt", "82562GT", INTEL_PBS_ERRATA ), ++ PCI_ROM ( 0x8086, 0x10c5, "82562g", "82562G", INTEL_PBS_ERRATA ), + PCI_ROM ( 0x8086, 0x10c9, "82576", "82576", 0 ), + PCI_ROM ( 0x8086, 0x10cb, "82567v", "82567V", 0 ), + PCI_ROM ( 0x8086, 0x10cc, "82567lm-2", "82567LM-2", 0 ), +@@ -936,8 +1091,8 @@ static struct pci_device_id intel_nics[] = { + PCI_ROM ( 0x8086, 0x10f0, "82578dc", "82578DC", 0 ), + PCI_ROM ( 0x8086, 0x10f5, "82567lm", "82567LM", 0 ), + PCI_ROM ( 0x8086, 0x10f6, "82574l", "82574L", 0 ), +- PCI_ROM ( 0x8086, 0x1501, "82567v-3", "82567V-3", 0 ), +- PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", 0 ), ++ PCI_ROM ( 0x8086, 0x1501, "82567v-3", "82567V-3", INTEL_PBS_ERRATA ), ++ PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", INTEL_NO_PHY_RST ), + PCI_ROM ( 0x8086, 0x1503, "82579v", "82579V", 0 ), + PCI_ROM ( 0x8086, 0x150a, "82576ns", "82576NS", 0 ), + PCI_ROM ( 0x8086, 0x150c, "82583v", "82583V", 0 ), +@@ -950,24 +1105,40 @@ static struct pci_device_id intel_nics[] = { + PCI_ROM ( 0x8086, 0x1518, "82576ns", "82576NS SerDes", 0 ), + PCI_ROM ( 0x8086, 0x1521, "i350", "I350", 0 ), + PCI_ROM ( 0x8086, 0x1522, "i350-f", "I350 Fiber", 0 ), +- PCI_ROM ( 0x8086, 0x1523, "i350-b", "I350 Backplane", 0 ), ++ PCI_ROM ( 0x8086, 0x1523, "i350-b", "I350 Backplane", INTEL_NO_ASDE ), + PCI_ROM ( 0x8086, 0x1524, "i350-2", "I350", 0 ), + PCI_ROM ( 0x8086, 0x1525, "82567v-4", "82567V-4", 0 ), + PCI_ROM ( 0x8086, 0x1526, "82576-5", "82576", 0 ), + PCI_ROM ( 0x8086, 0x1527, "82580-f2", "82580 Fiber", 0 ), + PCI_ROM ( 0x8086, 0x1533, "i210", "I210", 0 ), + PCI_ROM ( 0x8086, 0x1539, "i211", "I211", 0 ), +- PCI_ROM ( 0x8086, 0x153a, "i217lm", "I217LM", 0 ), +- PCI_ROM ( 0x8086, 0x1559, "i218v", "I218V", 0 ), +- PCI_ROM ( 0x8086, 0x155a, "i218lm", "I218LM", 0 ), +- PCI_ROM ( 0x8086, 0x15a1, "i218v", "I218V", 0 ), +- PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", 0 ), +- PCI_ROM ( 0x8086, 0x156f, "i219lm", "I219-LM", 0 ), +- PCI_ROM ( 0x8086, 0x15b7, "i219lm", "I219-LM", 0 ), +- PCI_ROM ( 0x8086, 0x15d7, "i219lm", "I219-LM", 0 ), +- PCI_ROM ( 0x8086, 0x15e3, "i219lm", "I219-LM", 0 ), +- PCI_ROM ( 0x8086, 0x1570, "i219v", "I219V", 0 ), ++ PCI_ROM ( 0x8086, 0x153a, "i217lm", "I217-LM", INTEL_NO_PHY_RST ), ++ PCI_ROM ( 0x8086, 0x153b, "i217v", "I217-V", 0 ), ++ PCI_ROM ( 0x8086, 0x1559, "i218v", "I218-V", 0), ++ PCI_ROM ( 0x8086, 0x155a, "i218lm", "I218-LM", 0), ++ PCI_ROM ( 0x8086, 0x156f, "i219lm", "I219-LM", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x1570, "i219v", "I219-V", INTEL_I219 ), + PCI_ROM ( 0x8086, 0x157b, "i210-2", "I210", 0 ), ++ PCI_ROM ( 0x8086, 0x15a0, "i218lm-2", "I218-LM", INTEL_NO_PHY_RST ), ++ PCI_ROM ( 0x8086, 0x15a1, "i218v-2", "I218-V", 0 ), ++ PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", INTEL_NO_PHY_RST ), ++ PCI_ROM ( 0x8086, 0x15a3, "i218v-3", "I218-V", INTEL_NO_PHY_RST ), ++ PCI_ROM ( 0x8086, 0x15b7, "i219lm-2", "I219-LM (2)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15b8, "i219v-2", "I219-V (2)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15b9, "i219lm-3", "I219-LM (3)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15bb, "i219lm-7", "I219-LM (7)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15bc, "i219v-7", "I219-V (7)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15bd, "i219lm-6", "I219-LM (6)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15be, "i219v-6", "I219-V (6)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15d6, "i219v-5", "I219-V (5)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15d7, "i219lm-4", "I219-LM (4)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15d8, "i219v-4", "I219-V (4)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15df, "i219lm-8", "I219-LM (8)", INTEL_I219 ), ++ PCI_ROM ( 0x8086, 0x15e0, "i219v-8", "I219-V (8)", INTEL_I219 ), ++ 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, 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/intel.h b/src/drivers/net/intel.h +index 2a11e1df..088a9fec 100644 +--- a/src/drivers/net/intel.h ++++ b/src/drivers/net/intel.h +@@ -22,33 +22,38 @@ struct intel_descriptor { + uint64_t address; + /** Length */ + uint16_t length; +- /** Reserved */ +- uint8_t reserved_a; ++ /** Flags */ ++ uint8_t flags; + /** Command */ + uint8_t command; + /** Status */ +- uint8_t status; +- /** Errors */ +- uint8_t errors; +- /** Reserved */ +- uint16_t reserved_b; ++ uint32_t status; + } __attribute__ (( packed )); + +-/** Packet descriptor command bits */ +-enum intel_descriptor_command { +- /** Report status */ +- INTEL_DESC_CMD_RS = 0x08, +- /** Insert frame checksum (CRC) */ +- INTEL_DESC_CMD_IFCS = 0x02, +- /** End of packet */ +- INTEL_DESC_CMD_EOP = 0x01, +-}; +- +-/** Packet descriptor status bits */ +-enum intel_descriptor_status { +- /** Descriptor done */ +- INTEL_DESC_STATUS_DD = 0x01, +-}; ++/** Descriptor type */ ++#define INTEL_DESC_FL_DTYP( dtyp ) ( (dtyp) << 4 ) ++#define INTEL_DESC_FL_DTYP_DATA INTEL_DESC_FL_DTYP ( 0x03 ) ++ ++/** Descriptor extension */ ++#define INTEL_DESC_CMD_DEXT 0x20 ++ ++/** Report status */ ++#define INTEL_DESC_CMD_RS 0x08 ++ ++/** Insert frame checksum (CRC) */ ++#define INTEL_DESC_CMD_IFCS 0x02 ++ ++/** End of packet */ ++#define INTEL_DESC_CMD_EOP 0x01 ++ ++/** Descriptor done */ ++#define INTEL_DESC_STATUS_DD 0x00000001UL ++ ++/** Receive error */ ++#define INTEL_DESC_STATUS_RXE 0x00000100UL ++ ++/** Payload length */ ++#define INTEL_DESC_STATUS_PAYLEN( len ) ( (len) << 14 ) + + /** Device Control Register */ + #define INTEL_CTRL 0x00000UL +@@ -91,9 +96,11 @@ enum intel_descriptor_status { + /** Interrupt Cause Read Register */ + #define INTEL_ICR 0x000c0UL + #define INTEL_IRQ_TXDW 0x00000001UL /**< Transmit descriptor done */ ++#define INTEL_IRQ_TXQE 0x00000002UL /**< Transmit queue empty */ + #define INTEL_IRQ_LSC 0x00000004UL /**< Link status change */ ++#define INTEL_IRQ_RXDMT0 0x00000010UL /**< Receive queue low */ ++#define INTEL_IRQ_RXO 0x00000040UL /**< Receive overrun */ + #define INTEL_IRQ_RXT0 0x00000080UL /**< Receive timer */ +-#define INTEL_IRQ_RXO 0x00000400UL /**< Receive overrun */ + + /** Interrupt Mask Set/Read Register */ + #define INTEL_IMS 0x000d0UL +@@ -156,6 +163,9 @@ enum intel_descriptor_status { + */ + #define INTEL_NUM_TX_DESC 256 + ++/** Transmit descriptor ring maximum fill level */ ++#define INTEL_TX_FILL ( INTEL_NUM_TX_DESC - 1 ) ++ + /** Receive/Transmit Descriptor Base Address Low (offset) */ + #define INTEL_xDBAL 0x00 + +@@ -175,6 +185,9 @@ enum intel_descriptor_status { + #define INTEL_xDCTL 0x28 + #define INTEL_xDCTL_ENABLE 0x02000000UL /**< Queue enable */ + ++/** Maximum time to wait for queue disable, in milliseconds */ ++#define INTEL_DISABLE_MAX_WAIT_MS 100 ++ + /** Receive Address Low */ + #define INTEL_RAL0 0x05400UL + +@@ -182,6 +195,10 @@ enum intel_descriptor_status { + #define INTEL_RAH0 0x05404UL + #define INTEL_RAH0_AV 0x80000000UL /**< Address valid */ + ++/** Future Extended NVM register 11 */ ++#define INTEL_FEXTNVM11 0x05bbcUL ++#define INTEL_FEXTNVM11_WTF 0x00002000UL /**< Don't ask */ ++ + /** Receive address */ + union intel_receive_address { + struct { +@@ -204,6 +221,15 @@ struct intel_ring { + unsigned int reg; + /** Length (in bytes) */ + size_t len; ++ ++ /** Populate descriptor ++ * ++ * @v desc Descriptor ++ * @v addr Data buffer address ++ * @v len Length of data ++ */ ++ void ( * describe ) ( struct intel_descriptor *desc, physaddr_t addr, ++ size_t len ); + }; + + /** +@@ -212,12 +238,39 @@ struct intel_ring { + * @v ring Descriptor ring + * @v count Number of descriptors + * @v reg Descriptor register block ++ * @v describe Method to populate descriptor + */ + static inline __attribute__ (( always_inline)) void +-intel_init_ring ( struct intel_ring *ring, unsigned int count, +- unsigned int reg ) { ++intel_init_ring ( struct intel_ring *ring, unsigned int count, unsigned int reg, ++ void ( * describe ) ( struct intel_descriptor *desc, ++ physaddr_t addr, size_t len ) ) { ++ + ring->len = ( count * sizeof ( ring->desc[0] ) ); + ring->reg = reg; ++ ring->describe = describe; ++} ++ ++/** An Intel virtual function mailbox */ ++struct intel_mailbox { ++ /** Mailbox control register */ ++ unsigned int ctrl; ++ /** Mailbox memory base */ ++ unsigned int mem; ++}; ++ ++/** ++ * Initialise mailbox ++ * ++ * @v mbox Mailbox ++ * @v ctrl Mailbox control register ++ * @v mem Mailbox memory register base ++ */ ++static inline __attribute__ (( always_inline )) void ++intel_init_mbox ( struct intel_mailbox *mbox, unsigned int ctrl, ++ unsigned int mem ) { ++ ++ mbox->ctrl = ctrl; ++ mbox->mem = mem; + } + + /** An Intel network card */ +@@ -226,6 +279,10 @@ struct intel_nic { + void *regs; + /** Port number (for multi-port devices) */ + unsigned int port; ++ /** Flags */ ++ unsigned int flags; ++ /** Forced interrupts */ ++ unsigned int force_icr; + + /** EEPROM */ + struct nvs_device eeprom; +@@ -234,6 +291,9 @@ struct intel_nic { + /** EEPROM address shift */ + unsigned int eerd_addr_shift; + ++ /** Mailbox */ ++ struct intel_mailbox mbox; ++ + /** Transmit descriptor ring */ + struct intel_ring tx; + /** Receive descriptor ring */ +@@ -242,6 +302,49 @@ struct intel_nic { + struct io_buffer *rx_iobuf[INTEL_NUM_RX_DESC]; + }; + ++/** Driver flags */ ++enum intel_flags { ++ /** PBS/PBA errata workaround required */ ++ INTEL_PBS_ERRATA = 0x0001, ++ /** VMware missing interrupt workaround required */ ++ INTEL_VMWARE = 0x0002, ++ /** PHY reset is broken */ ++ INTEL_NO_PHY_RST = 0x0004, ++ /** ASDE is broken */ ++ INTEL_NO_ASDE = 0x0008, ++ /** Reset may cause a complete device hang */ ++ INTEL_RST_HANG = 0x0010, ++}; ++ ++/** The i219 has a seriously broken reset mechanism */ ++#define INTEL_I219 ( INTEL_NO_PHY_RST | INTEL_RST_HANG ) ++ ++/** ++ * Dump diagnostic information ++ * ++ * @v intel Intel device ++ */ ++static inline void intel_diag ( struct intel_nic *intel ) { ++ ++ DBGC ( intel, "INTEL %p TX %04x(%02x)/%04x(%02x) " ++ "RX %04x(%02x)/%04x(%02x)\n", intel, ++ ( intel->tx.cons & 0xffff ), ++ readl ( intel->regs + intel->tx.reg + INTEL_xDH ), ++ ( intel->tx.prod & 0xffff ), ++ readl ( intel->regs + intel->tx.reg + INTEL_xDT ), ++ ( intel->rx.cons & 0xffff ), ++ readl ( intel->regs + intel->rx.reg + INTEL_xDH ), ++ ( intel->rx.prod & 0xffff ), ++ readl ( intel->regs + intel->rx.reg + INTEL_xDT ) ); ++} ++ ++extern void intel_describe_tx ( struct intel_descriptor *tx, ++ physaddr_t addr, size_t len ); ++extern void intel_describe_tx_adv ( struct intel_descriptor *tx, ++ physaddr_t addr, size_t len ); ++extern void intel_describe_rx ( struct intel_descriptor *rx, ++ physaddr_t addr, size_t len ); ++extern void intel_reset_ring ( struct intel_nic *intel, unsigned int reg ); + extern int intel_create_ring ( struct intel_nic *intel, + struct intel_ring *ring ); + extern void intel_destroy_ring ( struct intel_nic *intel, diff --git a/repos/dde_ipxe/ports/dde_ipxe.hash b/repos/dde_ipxe/ports/dde_ipxe.hash index bbeda7f19..221ddb919 100644 --- a/repos/dde_ipxe/ports/dde_ipxe.hash +++ b/repos/dde_ipxe/ports/dde_ipxe.hash @@ -1 +1 @@ -fc3380eff40122f956571bb8e6576c0bf0a92464 +b68f4e4dffa6e653b3025fc341c1796cdf90e5d4 diff --git a/repos/dde_ipxe/ports/dde_ipxe.port b/repos/dde_ipxe/ports/dde_ipxe.port index 728914d73..43cd32e0f 100644 --- a/repos/dde_ipxe/ports/dde_ipxe.port +++ b/repos/dde_ipxe/ports/dde_ipxe.port @@ -8,6 +8,7 @@ DIR(ipxe) := src/lib/dde_ipxe PATCHES := patches/dde_ipxe.patch \ patches/intel.patch \ + patches/intel_update.patch \ patches/tg3.patch PATCH_OPT := -p1 -d ${DIR(ipxe)}