*/
/** Maximum number of ports */
-#define PHN_MAX_NUM_PORTS 4
+#define PHN_MAX_NUM_PORTS 8
/** Maximum time to wait for command PEG to initialise
*
unsigned long rds_producer_crb;
/** RX status descriptor consumer CRB offset */
unsigned long sds_consumer_crb;
+ /** RX interrupt mask CRB offset */
+ unsigned long sds_irq_mask_crb;
+ /** RX interrupts enabled */
+ unsigned int sds_irq_enabled;
/** RX producer index */
unsigned int rds_producer_idx;
struct settings settings;
};
+/** Interrupt mask registers */
+static const unsigned long phantom_irq_mask_reg[PHN_MAX_NUM_PORTS] = {
+ UNM_PCIE_IRQ_MASK_F0,
+ UNM_PCIE_IRQ_MASK_F1,
+ UNM_PCIE_IRQ_MASK_F2,
+ UNM_PCIE_IRQ_MASK_F3,
+ UNM_PCIE_IRQ_MASK_F4,
+ UNM_PCIE_IRQ_MASK_F5,
+ UNM_PCIE_IRQ_MASK_F6,
+ UNM_PCIE_IRQ_MASK_F7,
+};
+
+/** Interrupt status registers */
+static const unsigned long phantom_irq_status_reg[PHN_MAX_NUM_PORTS] = {
+ UNM_PCIE_IRQ_STATUS_F0,
+ UNM_PCIE_IRQ_STATUS_F1,
+ UNM_PCIE_IRQ_STATUS_F2,
+ UNM_PCIE_IRQ_STATUS_F3,
+ UNM_PCIE_IRQ_STATUS_F4,
+ UNM_PCIE_IRQ_STATUS_F5,
+ UNM_PCIE_IRQ_STATUS_F6,
+ UNM_PCIE_IRQ_STATUS_F7,
+};
+
/***************************************************************************
*
* CRB register access
le16_to_cpu ( buf->cardrsp.rx_ctx.context_id );
phantom->rds_producer_crb =
( UNM_CAM_RAM +
- le32_to_cpu ( buf->cardrsp.rds.host_producer_crb ));
+ le32_to_cpu ( buf->cardrsp.rds.host_producer_crb ) );
phantom->sds_consumer_crb =
( UNM_CAM_RAM +
- le32_to_cpu ( buf->cardrsp.sds.host_consumer_crb ));
+ le32_to_cpu ( buf->cardrsp.sds.host_consumer_crb ) );
+ phantom->sds_irq_mask_crb =
+ ( UNM_CAM_RAM +
+ le32_to_cpu ( buf->cardrsp.sds.interrupt_crb ) );
DBGC ( phantom, "Phantom %p created RX context (id %04x, port phys "
"%02x virt %02x)\n", phantom, phantom->rx_context_id,
phantom, phantom->rds_producer_crb );
DBGC ( phantom, "Phantom %p SDS consumer CRB is %08lx\n",
phantom, phantom->sds_consumer_crb );
+ DBGC ( phantom, "Phantom %p SDS interrupt mask CRB is %08lx\n",
+ phantom, phantom->sds_irq_mask_crb );
out:
free_dma ( buf, sizeof ( *buf ) );
static void phantom_poll ( struct net_device *netdev ) {
struct phantom_nic *phantom = netdev_priv ( netdev );
struct io_buffer *iobuf;
+ unsigned int irq_vector;
+ unsigned int irq_state;
unsigned int cds_consumer_idx;
unsigned int raw_new_cds_consumer_idx;
unsigned int new_cds_consumer_idx;
unsigned int sds_handle;
unsigned int sds_opcode;
+ /* Occasionally poll the link state */
+ if ( phantom->link_poll_timer-- == 0 ) {
+ phantom_poll_link_state ( netdev );
+ /* Reset the link poll timer */
+ phantom->link_poll_timer = PHN_LINK_POLL_FREQUENCY;
+ }
+
+ /* Check for interrupts */
+ if ( phantom->sds_irq_enabled ) {
+
+ /* Do nothing unless an interrupt is asserted */
+ irq_vector = phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR );
+ if ( ! ( irq_vector & UNM_PCIE_IRQ_VECTOR_BIT( phantom->port )))
+ return;
+
+ /* Do nothing unless interrupt state machine has stabilised */
+ irq_state = phantom_readl ( phantom, UNM_PCIE_IRQ_STATE );
+ if ( ! UNM_PCIE_IRQ_STATE_TRIGGERED ( irq_state ) )
+ return;
+
+ /* Acknowledge interrupt */
+ phantom_writel ( phantom, UNM_PCIE_IRQ_STATUS_MAGIC,
+ phantom_irq_status_reg[phantom->port] );
+ phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR );
+ }
+
/* Check for TX completions */
cds_consumer_idx = phantom->cds_consumer_idx;
raw_new_cds_consumer_idx = phantom->desc->cmd_cons;
/* Refill the RX descriptor ring */
phantom_refill_rx_ring ( netdev );
-
- /* Occasionally poll the link state */
- if ( phantom->link_poll_timer-- == 0 ) {
- phantom_poll_link_state ( netdev );
- /* Reset the link poll timer */
- phantom->link_poll_timer = PHN_LINK_POLL_FREQUENCY;
- }
}
/**
*/
static void phantom_irq ( struct net_device *netdev, int enable ) {
struct phantom_nic *phantom = netdev_priv ( netdev );
- static const unsigned long sw_int_mask_reg[PHN_MAX_NUM_PORTS] = {
- UNM_NIC_REG_SW_INT_MASK_0,
- UNM_NIC_REG_SW_INT_MASK_1,
- UNM_NIC_REG_SW_INT_MASK_2,
- UNM_NIC_REG_SW_INT_MASK_3
- };
- phantom_writel ( phantom,
- ( enable ? 1 : 0 ),
- sw_int_mask_reg[phantom->port] );
+ phantom_writel ( phantom, ( enable ? 1 : 0 ),
+ phantom->sds_irq_mask_crb );
+ phantom_writel ( phantom, UNM_PCIE_IRQ_MASK_MAGIC,
+ phantom_irq_mask_reg[phantom->port] );
+ phantom->sds_irq_enabled = enable;
}
/** Phantom net device operations */
#define UNM_CRB_PCIE UNM_CRB_BASE ( UNM_CRB_BLK_PCIE )
#define UNM_PCIE_SEM2_LOCK ( UNM_CRB_PCIE + 0x1c010 )
#define UNM_PCIE_SEM2_UNLOCK ( UNM_CRB_PCIE + 0x1c014 )
+#define UNM_PCIE_IRQ_VECTOR ( UNM_CRB_PCIE + 0x10100 )
+#define UNM_PCIE_IRQ_VECTOR_BIT(n) ( 1 << ( (n) + 7 ) )
+#define UNM_PCIE_IRQ_STATE ( UNM_CRB_PCIE + 0x1206c )
+#define UNM_PCIE_IRQ_STATE_TRIGGERED(state) (( (state) & 0x300 ) == 0x200 )
+#define UNM_PCIE_IRQ_MASK_F0 ( UNM_CRB_PCIE + 0x10128 )
+#define UNM_PCIE_IRQ_MASK_F1 ( UNM_CRB_PCIE + 0x10170 )
+#define UNM_PCIE_IRQ_MASK_F2 ( UNM_CRB_PCIE + 0x10174 )
+#define UNM_PCIE_IRQ_MASK_F3 ( UNM_CRB_PCIE + 0x10178 )
+#define UNM_PCIE_IRQ_MASK_F4 ( UNM_CRB_PCIE + 0x10370 )
+#define UNM_PCIE_IRQ_MASK_F5 ( UNM_CRB_PCIE + 0x10374 )
+#define UNM_PCIE_IRQ_MASK_F6 ( UNM_CRB_PCIE + 0x10378 )
+#define UNM_PCIE_IRQ_MASK_F7 ( UNM_CRB_PCIE + 0x1037c )
+#define UNM_PCIE_IRQ_MASK_MAGIC 0x0000fbffUL
+#define UNM_PCIE_IRQ_STATUS_F0 ( UNM_CRB_PCIE + 0x10118 )
+#define UNM_PCIE_IRQ_STATUS_F1 ( UNM_CRB_PCIE + 0x10160 )
+#define UNM_PCIE_IRQ_STATUS_F2 ( UNM_CRB_PCIE + 0x10164 )
+#define UNM_PCIE_IRQ_STATUS_F3 ( UNM_CRB_PCIE + 0x10168 )
+#define UNM_PCIE_IRQ_STATUS_F4 ( UNM_CRB_PCIE + 0x10360 )
+#define UNM_PCIE_IRQ_STATUS_F5 ( UNM_CRB_PCIE + 0x10364 )
+#define UNM_PCIE_IRQ_STATUS_F6 ( UNM_CRB_PCIE + 0x10368 )
+#define UNM_PCIE_IRQ_STATUS_F7 ( UNM_CRB_PCIE + 0x1036c )
+#define UNM_PCIE_IRQ_STATUS_MAGIC 0xffffffffUL
#define UNM_CRB_CAM UNM_CRB_BASE ( UNM_CRB_BLK_CAM )
#define UNM_NIC_REG_XG_STATE_P3_LINK_DOWN 0x02
#define UNM_NIC_REG_RCVPEG_STATE ( UNM_NIC_REG + 0x0013c )
#define UNM_NIC_REG_RCVPEG_STATE_INITIALIZED 0xff01
-#define UNM_NIC_REG_SW_INT_MASK_0 ( UNM_NIC_REG + 0x001d8 )
-#define UNM_NIC_REG_SW_INT_MASK_1 ( UNM_NIC_REG + 0x001e0 )
-#define UNM_NIC_REG_SW_INT_MASK_2 ( UNM_NIC_REG + 0x001e4 )
-#define UNM_NIC_REG_SW_INT_MASK_3 ( UNM_NIC_REG + 0x001e8 )
#define UNM_CRB_ROMUSB UNM_CRB_BASE ( UNM_CRB_BLK_ROMUSB )