소스 검색

[phantom] Update interrupt support to match current firmware

The interrupt control mechanism on Phantom cards has changed
substantially since the driver was initially written.  This updates
the code to match the mechanism used in production firmware.

This is sufficient to allow DOS wget to function successfully using
the 3Com UNDI/NDIS, Intel UNDI/NDIS, and UNDIPD.COM UNDI/PD stacks.

Signed-off-by: Michael Brown <mcb30@etherboot.org>
tags/v1.20.1
Michael Brown 14 년 전
부모
커밋
b3533dd2bb
2개의 변경된 파일91개의 추가작업 그리고 23개의 파일을 삭제
  1. 69
    19
      src/drivers/net/phantom/phantom.c
  2. 22
    4
      src/drivers/net/phantom/phantom.h

+ 69
- 19
src/drivers/net/phantom/phantom.c 파일 보기

@@ -45,7 +45,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
45 45
  */
46 46
 
47 47
 /** Maximum number of ports */
48
-#define PHN_MAX_NUM_PORTS 4
48
+#define PHN_MAX_NUM_PORTS 8
49 49
 
50 50
 /** Maximum time to wait for command PEG to initialise
51 51
  *
@@ -154,6 +154,10 @@ struct phantom_nic {
154 154
 	unsigned long rds_producer_crb;
155 155
 	/** RX status descriptor consumer CRB offset */
156 156
 	unsigned long sds_consumer_crb;
157
+	/** RX interrupt mask CRB offset */
158
+	unsigned long sds_irq_mask_crb;
159
+	/** RX interrupts enabled */
160
+	unsigned int sds_irq_enabled;
157 161
 
158 162
 	/** RX producer index */
159 163
 	unsigned int rds_producer_idx;
@@ -192,6 +196,30 @@ struct phantom_nic {
192 196
 	struct settings settings;
193 197
 };
194 198
 
199
+/** Interrupt mask registers */
200
+static const unsigned long phantom_irq_mask_reg[PHN_MAX_NUM_PORTS] = {
201
+	UNM_PCIE_IRQ_MASK_F0,
202
+	UNM_PCIE_IRQ_MASK_F1,
203
+	UNM_PCIE_IRQ_MASK_F2,
204
+	UNM_PCIE_IRQ_MASK_F3,
205
+	UNM_PCIE_IRQ_MASK_F4,
206
+	UNM_PCIE_IRQ_MASK_F5,
207
+	UNM_PCIE_IRQ_MASK_F6,
208
+	UNM_PCIE_IRQ_MASK_F7,
209
+};
210
+
211
+/** Interrupt status registers */
212
+static const unsigned long phantom_irq_status_reg[PHN_MAX_NUM_PORTS] = {
213
+	UNM_PCIE_IRQ_STATUS_F0,
214
+	UNM_PCIE_IRQ_STATUS_F1,
215
+	UNM_PCIE_IRQ_STATUS_F2,
216
+	UNM_PCIE_IRQ_STATUS_F3,
217
+	UNM_PCIE_IRQ_STATUS_F4,
218
+	UNM_PCIE_IRQ_STATUS_F5,
219
+	UNM_PCIE_IRQ_STATUS_F6,
220
+	UNM_PCIE_IRQ_STATUS_F7,
221
+};
222
+
195 223
 /***************************************************************************
196 224
  *
197 225
  * CRB register access
@@ -664,10 +692,13 @@ static int phantom_create_rx_ctx ( struct phantom_nic *phantom ) {
664 692
 		le16_to_cpu ( buf->cardrsp.rx_ctx.context_id );
665 693
 	phantom->rds_producer_crb =
666 694
 		( UNM_CAM_RAM +
667
-		  le32_to_cpu ( buf->cardrsp.rds.host_producer_crb ));
695
+		  le32_to_cpu ( buf->cardrsp.rds.host_producer_crb ) );
668 696
 	phantom->sds_consumer_crb =
669 697
 		( UNM_CAM_RAM +
670
-		  le32_to_cpu ( buf->cardrsp.sds.host_consumer_crb ));
698
+		  le32_to_cpu ( buf->cardrsp.sds.host_consumer_crb ) );
699
+	phantom->sds_irq_mask_crb =
700
+		( UNM_CAM_RAM +
701
+		  le32_to_cpu ( buf->cardrsp.sds.interrupt_crb ) );
671 702
 
672 703
 	DBGC ( phantom, "Phantom %p created RX context (id %04x, port phys "
673 704
 	       "%02x virt %02x)\n", phantom, phantom->rx_context_id,
@@ -678,6 +709,8 @@ static int phantom_create_rx_ctx ( struct phantom_nic *phantom ) {
678 709
 	       phantom, phantom->rds_producer_crb );
679 710
 	DBGC ( phantom, "Phantom %p SDS consumer CRB is %08lx\n",
680 711
 	       phantom, phantom->sds_consumer_crb );
712
+	DBGC ( phantom, "Phantom %p SDS interrupt mask CRB is %08lx\n",
713
+	       phantom, phantom->sds_irq_mask_crb );
681 714
 
682 715
  out:
683 716
 	free_dma ( buf, sizeof ( *buf ) );
@@ -1263,6 +1296,8 @@ static int phantom_transmit ( struct net_device *netdev,
1263 1296
 static void phantom_poll ( struct net_device *netdev ) {
1264 1297
 	struct phantom_nic *phantom = netdev_priv ( netdev );
1265 1298
 	struct io_buffer *iobuf;
1299
+	unsigned int irq_vector;
1300
+	unsigned int irq_state;
1266 1301
 	unsigned int cds_consumer_idx;
1267 1302
 	unsigned int raw_new_cds_consumer_idx;
1268 1303
 	unsigned int new_cds_consumer_idx;
@@ -1272,6 +1307,32 @@ static void phantom_poll ( struct net_device *netdev ) {
1272 1307
 	unsigned int sds_handle;
1273 1308
 	unsigned int sds_opcode;
1274 1309
 
1310
+	/* Occasionally poll the link state */
1311
+	if ( phantom->link_poll_timer-- == 0 ) {
1312
+		phantom_poll_link_state ( netdev );
1313
+		/* Reset the link poll timer */
1314
+		phantom->link_poll_timer = PHN_LINK_POLL_FREQUENCY;
1315
+	}
1316
+
1317
+	/* Check for interrupts */
1318
+	if ( phantom->sds_irq_enabled ) {
1319
+
1320
+		/* Do nothing unless an interrupt is asserted */
1321
+		irq_vector = phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR );
1322
+		if ( ! ( irq_vector & UNM_PCIE_IRQ_VECTOR_BIT( phantom->port )))
1323
+			return;
1324
+
1325
+		/* Do nothing unless interrupt state machine has stabilised */
1326
+		irq_state = phantom_readl ( phantom, UNM_PCIE_IRQ_STATE );
1327
+		if ( ! UNM_PCIE_IRQ_STATE_TRIGGERED ( irq_state ) )
1328
+			return;
1329
+
1330
+		/* Acknowledge interrupt */
1331
+		phantom_writel ( phantom, UNM_PCIE_IRQ_STATUS_MAGIC,
1332
+				 phantom_irq_status_reg[phantom->port] );
1333
+		phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR );
1334
+	}
1335
+
1275 1336
 	/* Check for TX completions */
1276 1337
 	cds_consumer_idx = phantom->cds_consumer_idx;
1277 1338
 	raw_new_cds_consumer_idx = phantom->desc->cmd_cons;
@@ -1361,13 +1422,6 @@ static void phantom_poll ( struct net_device *netdev ) {
1361 1422
 
1362 1423
 	/* Refill the RX descriptor ring */
1363 1424
 	phantom_refill_rx_ring ( netdev );
1364
-
1365
-	/* Occasionally poll the link state */
1366
-	if ( phantom->link_poll_timer-- == 0 ) {
1367
-		phantom_poll_link_state ( netdev );
1368
-		/* Reset the link poll timer */
1369
-		phantom->link_poll_timer = PHN_LINK_POLL_FREQUENCY;
1370
-	}
1371 1425
 }
1372 1426
 
1373 1427
 /**
@@ -1378,16 +1432,12 @@ static void phantom_poll ( struct net_device *netdev ) {
1378 1432
  */
1379 1433
 static void phantom_irq ( struct net_device *netdev, int enable ) {
1380 1434
 	struct phantom_nic *phantom = netdev_priv ( netdev );
1381
-	static const unsigned long sw_int_mask_reg[PHN_MAX_NUM_PORTS] = {
1382
-		UNM_NIC_REG_SW_INT_MASK_0,
1383
-		UNM_NIC_REG_SW_INT_MASK_1,
1384
-		UNM_NIC_REG_SW_INT_MASK_2,
1385
-		UNM_NIC_REG_SW_INT_MASK_3
1386
-	};
1387 1435
 
1388
-	phantom_writel ( phantom,
1389
-			 ( enable ? 1 : 0 ),
1390
-			 sw_int_mask_reg[phantom->port] );
1436
+	phantom_writel ( phantom, ( enable ? 1 : 0 ),
1437
+			 phantom->sds_irq_mask_crb );
1438
+	phantom_writel ( phantom, UNM_PCIE_IRQ_MASK_MAGIC,
1439
+			 phantom_irq_mask_reg[phantom->port] );
1440
+	phantom->sds_irq_enabled = enable;
1391 1441
 }
1392 1442
 
1393 1443
 /** Phantom net device operations */

+ 22
- 4
src/drivers/net/phantom/phantom.h 파일 보기

@@ -89,6 +89,28 @@ enum unm_reg_blocks {
89 89
 #define UNM_CRB_PCIE			UNM_CRB_BASE ( UNM_CRB_BLK_PCIE )
90 90
 #define UNM_PCIE_SEM2_LOCK		( UNM_CRB_PCIE + 0x1c010 )
91 91
 #define UNM_PCIE_SEM2_UNLOCK		( UNM_CRB_PCIE + 0x1c014 )
92
+#define UNM_PCIE_IRQ_VECTOR		( UNM_CRB_PCIE + 0x10100 )
93
+#define UNM_PCIE_IRQ_VECTOR_BIT(n)		( 1 << ( (n) + 7 ) )
94
+#define UNM_PCIE_IRQ_STATE		( UNM_CRB_PCIE + 0x1206c )
95
+#define UNM_PCIE_IRQ_STATE_TRIGGERED(state)	(( (state) & 0x300 ) == 0x200 )
96
+#define UNM_PCIE_IRQ_MASK_F0		( UNM_CRB_PCIE + 0x10128 )
97
+#define UNM_PCIE_IRQ_MASK_F1		( UNM_CRB_PCIE + 0x10170 )
98
+#define UNM_PCIE_IRQ_MASK_F2		( UNM_CRB_PCIE + 0x10174 )
99
+#define UNM_PCIE_IRQ_MASK_F3		( UNM_CRB_PCIE + 0x10178 )
100
+#define UNM_PCIE_IRQ_MASK_F4		( UNM_CRB_PCIE + 0x10370 )
101
+#define UNM_PCIE_IRQ_MASK_F5		( UNM_CRB_PCIE + 0x10374 )
102
+#define UNM_PCIE_IRQ_MASK_F6		( UNM_CRB_PCIE + 0x10378 )
103
+#define UNM_PCIE_IRQ_MASK_F7		( UNM_CRB_PCIE + 0x1037c )
104
+#define UNM_PCIE_IRQ_MASK_MAGIC			0x0000fbffUL
105
+#define UNM_PCIE_IRQ_STATUS_F0		( UNM_CRB_PCIE + 0x10118 )
106
+#define UNM_PCIE_IRQ_STATUS_F1		( UNM_CRB_PCIE + 0x10160 )
107
+#define UNM_PCIE_IRQ_STATUS_F2		( UNM_CRB_PCIE + 0x10164 )
108
+#define UNM_PCIE_IRQ_STATUS_F3		( UNM_CRB_PCIE + 0x10168 )
109
+#define UNM_PCIE_IRQ_STATUS_F4		( UNM_CRB_PCIE + 0x10360 )
110
+#define UNM_PCIE_IRQ_STATUS_F5		( UNM_CRB_PCIE + 0x10364 )
111
+#define UNM_PCIE_IRQ_STATUS_F6		( UNM_CRB_PCIE + 0x10368 )
112
+#define UNM_PCIE_IRQ_STATUS_F7		( UNM_CRB_PCIE + 0x1036c )
113
+#define UNM_PCIE_IRQ_STATUS_MAGIC		0xffffffffUL
92 114
 
93 115
 #define UNM_CRB_CAM			UNM_CRB_BASE ( UNM_CRB_BLK_CAM )
94 116
 
@@ -137,10 +159,6 @@ enum unm_reg_blocks {
137 159
 #define UNM_NIC_REG_XG_STATE_P3_LINK_DOWN	0x02
138 160
 #define UNM_NIC_REG_RCVPEG_STATE	( UNM_NIC_REG + 0x0013c )
139 161
 #define UNM_NIC_REG_RCVPEG_STATE_INITIALIZED	0xff01
140
-#define UNM_NIC_REG_SW_INT_MASK_0	( UNM_NIC_REG + 0x001d8 )
141
-#define UNM_NIC_REG_SW_INT_MASK_1	( UNM_NIC_REG + 0x001e0 )
142
-#define UNM_NIC_REG_SW_INT_MASK_2	( UNM_NIC_REG + 0x001e4 )
143
-#define UNM_NIC_REG_SW_INT_MASK_3	( UNM_NIC_REG + 0x001e8 )
144 162
 
145 163
 #define UNM_CRB_ROMUSB			UNM_CRB_BASE ( UNM_CRB_BLK_ROMUSB )
146 164
 

Loading…
취소
저장