}
}
+/******************************************************************************
+ *
+ * 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
/* Populate receive descriptor */
address = virt_to_bus ( iobuf->data );
- rx->address = cpu_to_le64 ( address );
- rx->length = 0;
- rx->status = 0;
- rx->errors = 0;
+ intel->rx.describe ( rx, address, 0 );
/* Record I/O buffer */
assert ( intel->rx_iobuf[rx_idx] == NULL );
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_TX_FILL ) {
/* 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 */
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;
}
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 );
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 */
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",
memset ( intel, 0, sizeof ( *intel ) );
intel->port = PCI_FUNC ( pci->busdevfn );
intel->flags = pci->id->driver_data;
- intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTEL_TD );
- intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTEL_RD );
+ 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 );
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,
-};
+/** Descriptor type */
+#define INTEL_DESC_FL_DTYP( dtyp ) ( (dtyp) << 4 )
+#define INTEL_DESC_FL_DTYP_DATA INTEL_DESC_FL_DTYP ( 0x03 )
-/** Packet descriptor status bits */
-enum intel_descriptor_status {
- /** Descriptor done */
- INTEL_DESC_STATUS_DD = 0x01,
-};
+/** 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
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 );
};
/**
* @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 network card */
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 int intel_create_ring ( struct intel_nic *intel,
struct intel_ring *ring );
extern void intel_destroy_ring ( struct intel_nic *intel,