Browse Source

[vmxnet3] Add VMware vmxnet3 driver

Reviewed-by: Pete Holland <pholland27@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
55f6c88a27
3 changed files with 1167 additions and 0 deletions
  1. 669
    0
      src/drivers/net/vmxnet3.c
  2. 497
    0
      src/drivers/net/vmxnet3.h
  3. 1
    0
      src/include/ipxe/errfile.h

+ 669
- 0
src/drivers/net/vmxnet3.c View File

@@ -0,0 +1,669 @@
1
+/*
2
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <stdint.h>
22
+#include <errno.h>
23
+#include <assert.h>
24
+#include <byteswap.h>
25
+#include <ipxe/pci.h>
26
+#include <ipxe/io.h>
27
+#include <ipxe/malloc.h>
28
+#include <ipxe/iobuf.h>
29
+#include <ipxe/netdevice.h>
30
+#include <ipxe/if_ether.h>
31
+#include <ipxe/ethernet.h>
32
+#include "vmxnet3.h"
33
+
34
+/**
35
+ * @file
36
+ *
37
+ * VMware vmxnet3 virtual NIC driver
38
+ *
39
+ */
40
+
41
+/**
42
+ * Issue command
43
+ *
44
+ * @v vmxnet		vmxnet3 NIC
45
+ * @v command		Command to issue
46
+ * @ret result		Command result
47
+ */
48
+static inline uint32_t vmxnet3_command ( struct vmxnet3_nic *vmxnet,
49
+					 uint32_t command ) {
50
+
51
+	/* Issue command */
52
+	writel ( command, ( vmxnet->vd + VMXNET3_VD_CMD ) );
53
+	return readl ( vmxnet->vd + VMXNET3_VD_CMD );
54
+}
55
+
56
+/**
57
+ * Transmit packet
58
+ *
59
+ * @v netdev		Network device
60
+ * @v iobuf		I/O buffer
61
+ * @ret rc		Return status code
62
+ */
63
+static int vmxnet3_transmit ( struct net_device *netdev,
64
+			      struct io_buffer *iobuf ) {
65
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
66
+	struct vmxnet3_tx_desc *tx_desc;
67
+	unsigned int desc_idx;
68
+	unsigned int generation;
69
+
70
+	/* Check that we have a free transmit descriptor */
71
+	desc_idx = ( vmxnet->count.tx_prod % VMXNET3_NUM_TX_DESC );
72
+	generation = ( ( vmxnet->count.tx_prod & VMXNET3_NUM_TX_DESC ) ?
73
+		       0 : cpu_to_le32 ( VMXNET3_TXF_GEN ) );
74
+	if ( vmxnet->tx_iobuf[desc_idx] ) {
75
+		DBGC ( vmxnet, "VMXNET3 %p out of transmit descriptors\n",
76
+		       vmxnet );
77
+		return -ENOBUFS;
78
+	}
79
+
80
+	/* Increment producer counter */
81
+	vmxnet->count.tx_prod++;
82
+
83
+	/* Store I/O buffer for later completion */
84
+	vmxnet->tx_iobuf[desc_idx] = iobuf;
85
+
86
+	/* Populate transmit descriptor */
87
+	tx_desc = &vmxnet->dma->tx_desc[desc_idx];
88
+	tx_desc->address = cpu_to_le64 ( virt_to_bus ( iobuf->data ) );
89
+	tx_desc->flags[0] = ( generation | cpu_to_le32 ( iob_len ( iobuf ) ) );
90
+	tx_desc->flags[1] = cpu_to_le32 ( VMXNET3_TXF_CQ | VMXNET3_TXF_EOP );
91
+
92
+	/* Hand over descriptor to NIC */
93
+	wmb();
94
+	writel ( ( vmxnet->count.tx_prod % VMXNET3_NUM_TX_DESC ),
95
+		 ( vmxnet->pt + VMXNET3_PT_TXPROD ) );
96
+
97
+	return 0;
98
+}
99
+
100
+/**
101
+ * Poll for completed transmissions
102
+ *
103
+ * @v netdev		Network device
104
+ */
105
+static void vmxnet3_poll_tx ( struct net_device *netdev ) {
106
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
107
+	struct vmxnet3_tx_comp *tx_comp;
108
+	struct io_buffer *iobuf;
109
+	unsigned int comp_idx;
110
+	unsigned int desc_idx;
111
+	unsigned int generation;
112
+
113
+	while ( 1 ) {
114
+
115
+		/* Look for completed descriptors */
116
+		comp_idx = ( vmxnet->count.tx_cons % VMXNET3_NUM_TX_COMP );
117
+		generation = ( ( vmxnet->count.tx_cons & VMXNET3_NUM_TX_COMP ) ?
118
+			       0 : cpu_to_le32 ( VMXNET3_TXCF_GEN ) );
119
+		tx_comp = &vmxnet->dma->tx_comp[comp_idx];
120
+		if ( generation != ( tx_comp->flags &
121
+				     cpu_to_le32 ( VMXNET3_TXCF_GEN ) ) ) {
122
+			break;
123
+		}
124
+
125
+		/* Increment consumer counter */
126
+		vmxnet->count.tx_cons++;
127
+
128
+		/* Locate corresponding transmit descriptor */
129
+		desc_idx = ( le32_to_cpu ( tx_comp->index ) %
130
+			     VMXNET3_NUM_TX_DESC );
131
+		iobuf = vmxnet->tx_iobuf[desc_idx];
132
+		if ( ! iobuf ) {
133
+			DBGC ( vmxnet, "VMXNET3 %p completed on empty transmit "
134
+			       "buffer %#x/%#x\n", vmxnet, comp_idx, desc_idx );
135
+			netdev_tx_err ( netdev, NULL, -ENOTTY );
136
+			continue;
137
+		}
138
+
139
+		/* Remove I/O buffer from transmit queue */
140
+		vmxnet->tx_iobuf[desc_idx] = NULL;
141
+
142
+		/* Report transmission completion to network layer */
143
+		DBGC2 ( vmxnet, "VMXNET3 %p completed TX %#x/%#x (len %#zx)\n",
144
+			vmxnet, comp_idx, desc_idx, iob_len ( iobuf ) );
145
+		netdev_tx_complete ( netdev, iobuf );
146
+	}
147
+}
148
+
149
+/**
150
+ * Flush any uncompleted transmit buffers
151
+ *
152
+ * @v netdev		Network device
153
+ */
154
+static void vmxnet3_flush_tx ( struct net_device *netdev ) {
155
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
156
+	unsigned int i;
157
+
158
+	for ( i = 0 ; i < VMXNET3_NUM_TX_DESC ; i++ ) {
159
+		if ( vmxnet->tx_iobuf[i] ) {
160
+			netdev_tx_complete_err ( netdev, vmxnet->tx_iobuf[i],
161
+						 -ECANCELED );
162
+			vmxnet->tx_iobuf[i] = NULL;
163
+		}
164
+	}
165
+}
166
+
167
+/**
168
+ * Refill receive ring
169
+ *
170
+ * @v netdev		Network device
171
+ */
172
+static void vmxnet3_refill_rx ( struct net_device *netdev ) {
173
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
174
+	struct vmxnet3_rx_desc *rx_desc;
175
+	struct io_buffer *iobuf;
176
+	unsigned int orig_rx_prod = vmxnet->count.rx_prod;
177
+	unsigned int desc_idx;
178
+	unsigned int generation;
179
+
180
+	/* Fill receive ring to specified fill level */
181
+	while ( vmxnet->count.rx_fill < VMXNET3_RX_FILL ) {
182
+
183
+		/* Locate receive descriptor */
184
+		desc_idx = ( vmxnet->count.rx_prod % VMXNET3_NUM_RX_DESC );
185
+		generation = ( ( vmxnet->count.rx_prod & VMXNET3_NUM_RX_DESC ) ?
186
+			       0 : cpu_to_le32 ( VMXNET3_RXF_GEN ) );
187
+		assert ( vmxnet->rx_iobuf[desc_idx] == NULL );
188
+
189
+		/* Allocate I/O buffer */
190
+		iobuf = alloc_iob ( VMXNET3_MTU + NET_IP_ALIGN );
191
+		if ( ! iobuf ) {
192
+			/* Non-fatal low memory condition */
193
+			break;
194
+		}
195
+		iob_reserve ( iobuf, NET_IP_ALIGN );
196
+
197
+		/* Increment producer counter and fill level */
198
+		vmxnet->count.rx_prod++;
199
+		vmxnet->count.rx_fill++;
200
+
201
+		/* Store I/O buffer for later completion */
202
+		vmxnet->rx_iobuf[desc_idx] = iobuf;
203
+
204
+		/* Populate receive descriptor */
205
+		rx_desc = &vmxnet->dma->rx_desc[desc_idx];
206
+		rx_desc->address = cpu_to_le64 ( virt_to_bus ( iobuf->data ) );
207
+		rx_desc->flags = ( generation | cpu_to_le32 ( VMXNET3_MTU ) );
208
+
209
+	}
210
+
211
+	/* Hand over any new descriptors to NIC */
212
+	if ( vmxnet->count.rx_prod != orig_rx_prod ) {
213
+		wmb();
214
+		writel ( ( vmxnet->count.rx_prod % VMXNET3_NUM_RX_DESC ),
215
+			 ( vmxnet->pt + VMXNET3_PT_RXPROD ) );
216
+	}
217
+}
218
+
219
+/**
220
+ * Poll for received packets
221
+ *
222
+ * @v netdev		Network device
223
+ */
224
+static void vmxnet3_poll_rx ( struct net_device *netdev ) {
225
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
226
+	struct vmxnet3_rx_comp *rx_comp;
227
+	struct io_buffer *iobuf;
228
+	unsigned int comp_idx;
229
+	unsigned int desc_idx;
230
+	unsigned int generation;
231
+	size_t len;
232
+
233
+	while ( 1 ) {
234
+
235
+		/* Look for completed descriptors */
236
+		comp_idx = ( vmxnet->count.rx_cons % VMXNET3_NUM_RX_COMP );
237
+		generation = ( ( vmxnet->count.rx_cons & VMXNET3_NUM_RX_COMP ) ?
238
+			       0 : cpu_to_le32 ( VMXNET3_RXCF_GEN ) );
239
+		rx_comp = &vmxnet->dma->rx_comp[comp_idx];
240
+		if ( generation != ( rx_comp->flags &
241
+				     cpu_to_le32 ( VMXNET3_RXCF_GEN ) ) ) {
242
+			break;
243
+		}
244
+
245
+		/* Increment consumer counter */
246
+		vmxnet->count.rx_cons++;
247
+
248
+		/* Locate corresponding receive descriptor */
249
+		desc_idx = ( le32_to_cpu ( rx_comp->index ) %
250
+			     VMXNET3_NUM_RX_DESC );
251
+		iobuf = vmxnet->rx_iobuf[desc_idx];
252
+		if ( ! iobuf ) {
253
+			DBGC ( vmxnet, "VMXNET3 %p completed on empty receive "
254
+			       "buffer %#x/%#x\n", vmxnet, comp_idx, desc_idx );
255
+			netdev_rx_err ( netdev, NULL, -ENOTTY );
256
+			continue;
257
+		}
258
+
259
+		/* Remove I/O buffer from receive queue */
260
+		vmxnet->rx_iobuf[desc_idx] = NULL;
261
+		vmxnet->count.rx_fill--;
262
+
263
+		/* Deliver packet to network layer */
264
+		len = ( le32_to_cpu ( rx_comp->len ) &
265
+			( VMXNET3_MAX_PACKET_LEN - 1 ) );
266
+		DBGC2 ( vmxnet, "VMXNET3 %p completed RX %#x/%#x (len %#zx)\n",
267
+			vmxnet, comp_idx, desc_idx, len );
268
+		iob_put ( iobuf, len );
269
+		netdev_rx ( netdev, iobuf );
270
+	}
271
+}
272
+
273
+/**
274
+ * Flush any uncompleted receive buffers
275
+ *
276
+ * @v netdev		Network device
277
+ */
278
+static void vmxnet3_flush_rx ( struct net_device *netdev ) {
279
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
280
+	struct io_buffer *iobuf;
281
+	unsigned int i;
282
+
283
+	for ( i = 0 ; i < VMXNET3_NUM_RX_DESC ; i++ ) {
284
+		if ( ( iobuf = vmxnet->rx_iobuf[i] ) != NULL ) {
285
+			netdev_rx_err ( netdev, iobuf, -ECANCELED );
286
+			vmxnet->rx_iobuf[i] = NULL;
287
+		}
288
+	}
289
+}
290
+
291
+/**
292
+ * Check link state
293
+ *
294
+ * @v netdev		Network device
295
+ */
296
+static void vmxnet3_check_link ( struct net_device *netdev ) {
297
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
298
+	uint32_t state;
299
+	int link_up;
300
+	unsigned int link_speed;
301
+
302
+	/* Get link state */
303
+	state = vmxnet3_command ( vmxnet, VMXNET3_CMD_GET_LINK );
304
+	link_up = ( state & 1 );
305
+	link_speed = ( state >> 16 );
306
+
307
+	/* Report link state to network device */
308
+	if ( link_up ) {
309
+		DBGC ( vmxnet, "VMXNET3 %p link is up at %d Mbps\n",
310
+		       vmxnet, link_speed );
311
+		netdev_link_up ( netdev );
312
+	} else {
313
+		DBGC ( vmxnet, "VMXNET3 %p link is down\n", vmxnet );
314
+		netdev_link_down ( netdev );
315
+	}
316
+}
317
+
318
+/**
319
+ * Poll for events
320
+ *
321
+ * @v netdev		Network device
322
+ */
323
+static void vmxnet3_poll_events ( struct net_device *netdev ) {
324
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
325
+	uint32_t events;
326
+
327
+	/* Do nothing unless there are events to process */
328
+	if ( ! vmxnet->dma->shared.ecr )
329
+		return;
330
+	events = le32_to_cpu ( vmxnet->dma->shared.ecr );
331
+
332
+	/* Acknowledge these events */
333
+	writel ( events, ( vmxnet->vd + VMXNET3_VD_ECR ) );
334
+
335
+	/* Check for link state change */
336
+	if ( events & VMXNET3_ECR_LINK ) {
337
+		vmxnet3_check_link ( netdev );
338
+		events &= ~VMXNET3_ECR_LINK;
339
+	}
340
+
341
+	/* Check for queue errors */
342
+	if ( events & ( VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR ) ) {
343
+		vmxnet3_command ( vmxnet, VMXNET3_CMD_GET_QUEUE_STATUS );
344
+		DBGC ( vmxnet, "VMXNET3 %p queue error status (TX %08x, RX "
345
+		       "%08x)\n", vmxnet,
346
+		       le32_to_cpu ( vmxnet->dma->queues.tx.status.error ),
347
+		       le32_to_cpu ( vmxnet->dma->queues.rx.status.error ) );
348
+		/* Report errors to allow for visibility via "ifstat" */
349
+		if ( events & VMXNET3_ECR_TQERR )
350
+			netdev_tx_err ( netdev, NULL, -EPIPE );
351
+		if ( events & VMXNET3_ECR_RQERR )
352
+			netdev_rx_err ( netdev, NULL, -EPIPE );
353
+		events &= ~( VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR );
354
+	}
355
+
356
+	/* Check for unknown events */
357
+	if ( events ) {
358
+		DBGC ( vmxnet, "VMXNET3 %p unknown events %08x\n",
359
+		       vmxnet, events );
360
+		/* Report error to allow for visibility via "ifstat" */
361
+		netdev_rx_err ( netdev, NULL, -ENODEV );
362
+	}
363
+}
364
+
365
+/**
366
+ * Poll network device
367
+ *
368
+ * @v netdev		Network device
369
+ */
370
+static void vmxnet3_poll ( struct net_device *netdev ) {
371
+
372
+	vmxnet3_poll_events ( netdev );
373
+	vmxnet3_poll_tx ( netdev );
374
+	vmxnet3_poll_rx ( netdev );
375
+	vmxnet3_refill_rx ( netdev );
376
+}
377
+
378
+/**
379
+ * Enable/disable interrupts
380
+ *
381
+ * @v netdev		Network device
382
+ * @v enable		Interrupts should be enabled
383
+ */
384
+static void vmxnet3_irq ( struct net_device *netdev, int enable ) {
385
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
386
+
387
+	DBGC ( vmxnet, "VMXNET3 %p %s IRQ not implemented\n",
388
+	       vmxnet, ( enable ? "enable" : "disable" ) );
389
+}
390
+
391
+/**
392
+ * Set MAC address
393
+ *
394
+ * @v vmxnet		vmxnet3 NIC
395
+ * @v ll_addr		Link-layer address to set
396
+ */
397
+static void vmxnet3_set_ll_addr ( struct vmxnet3_nic *vmxnet,
398
+				  const void *ll_addr ) {
399
+	struct {
400
+		uint32_t low;
401
+		uint32_t high;
402
+	} __attribute__ (( packed )) mac;
403
+
404
+	memset ( &mac, 0, sizeof ( mac ) );
405
+	memcpy ( &mac, ll_addr, ETH_ALEN );
406
+	writel ( cpu_to_le32 ( mac.low ), ( vmxnet->vd + VMXNET3_VD_MACL ) );
407
+	writel ( cpu_to_le32 ( mac.high ), ( vmxnet->vd + VMXNET3_VD_MACH ) );
408
+}
409
+
410
+/**
411
+ * Open NIC
412
+ *
413
+ * @v netdev		Network device
414
+ * @ret rc		Return status code
415
+ */
416
+static int vmxnet3_open ( struct net_device *netdev ) {
417
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
418
+	struct vmxnet3_shared *shared;
419
+	struct vmxnet3_queues *queues;
420
+	uint64_t shared_bus;
421
+	uint64_t queues_bus;
422
+	uint32_t status;
423
+	int rc;
424
+
425
+	/* Allocate DMA areas */
426
+	vmxnet->dma = malloc_dma ( sizeof ( *vmxnet->dma ), VMXNET3_DMA_ALIGN );
427
+	if ( ! vmxnet->dma ) {
428
+		DBGC ( vmxnet, "VMXNET3 %p could not allocate DMA area\n",
429
+		       vmxnet );
430
+		rc = -ENOMEM;
431
+		goto err_alloc_dma;
432
+	}
433
+	memset ( vmxnet->dma, 0, sizeof ( *vmxnet->dma ) );
434
+
435
+	/* Populate queue descriptors */
436
+	queues = &vmxnet->dma->queues;
437
+	queues->tx.cfg.desc_address =
438
+		cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->tx_desc ) );
439
+	queues->tx.cfg.comp_address =
440
+		cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->tx_comp ) );
441
+	queues->tx.cfg.num_desc = cpu_to_le32 ( VMXNET3_NUM_TX_DESC );
442
+	queues->tx.cfg.num_comp = cpu_to_le32 ( VMXNET3_NUM_TX_COMP );
443
+	queues->rx.cfg.desc_address[0] =
444
+		cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->rx_desc ) );
445
+	queues->rx.cfg.comp_address =
446
+		cpu_to_le64 ( virt_to_bus ( &vmxnet->dma->rx_comp ) );
447
+	queues->rx.cfg.num_desc[0] = cpu_to_le32 ( VMXNET3_NUM_RX_DESC );
448
+	queues->rx.cfg.num_comp = cpu_to_le32 ( VMXNET3_NUM_RX_COMP );
449
+	queues_bus = virt_to_bus ( queues );
450
+	DBGC ( vmxnet, "VMXNET3 %p queue descriptors at %08llx+%zx\n",
451
+	       vmxnet, queues_bus, sizeof ( *queues ) );
452
+
453
+	/* Populate shared area */
454
+	shared = &vmxnet->dma->shared;
455
+	shared->magic = cpu_to_le32 ( VMXNET3_SHARED_MAGIC );
456
+	shared->misc.version = cpu_to_le32 ( VMXNET3_VERSION_MAGIC );
457
+	shared->misc.version_support = cpu_to_le32 ( VMXNET3_VERSION_SELECT );
458
+	shared->misc.upt_version_support =
459
+		cpu_to_le32 ( VMXNET3_UPT_VERSION_SELECT );
460
+	shared->misc.queue_desc_address = cpu_to_le64 ( queues_bus );
461
+	shared->misc.queue_desc_len = cpu_to_le32 ( sizeof ( *queues ) );
462
+	shared->misc.mtu = cpu_to_le32 ( VMXNET3_MTU );
463
+	shared->misc.num_tx_queues = 1;
464
+	shared->misc.num_rx_queues = 1;
465
+	shared->interrupt.num_intrs = 1;
466
+	shared->interrupt.control = cpu_to_le32 ( VMXNET3_IC_DISABLE_ALL );
467
+	shared->rx_filter.mode = cpu_to_le32 ( VMXNET3_RXM_UCAST |
468
+					       VMXNET3_RXM_BCAST |
469
+					       VMXNET3_RXM_ALL_MULTI );
470
+	shared_bus = virt_to_bus ( shared );
471
+	DBGC ( vmxnet, "VMXNET3 %p shared area at %08llx+%zx\n",
472
+	       vmxnet, shared_bus, sizeof ( *shared ) );
473
+
474
+	/* Zero counters */
475
+	memset ( &vmxnet->count, 0, sizeof ( vmxnet->count ) );
476
+
477
+	/* Set MAC address */
478
+	vmxnet3_set_ll_addr ( vmxnet, &netdev->ll_addr );
479
+
480
+	/* Pass shared area to device */
481
+	writel ( ( shared_bus >> 0 ), ( vmxnet->vd + VMXNET3_VD_DSAL ) );
482
+	writel ( ( shared_bus >> 32 ), ( vmxnet->vd + VMXNET3_VD_DSAH ) );
483
+
484
+	/* Activate device */
485
+	if ( ( status = vmxnet3_command ( vmxnet,
486
+					  VMXNET3_CMD_ACTIVATE_DEV ) ) != 0 ) {
487
+		DBGC ( vmxnet, "VMXNET3 %p could not activate (status %#x)\n",
488
+		       vmxnet, status );
489
+		rc = -EIO;
490
+		goto err_activate;
491
+	}
492
+
493
+	/* Fill receive ring */
494
+	vmxnet3_refill_rx ( netdev );
495
+
496
+	return 0;
497
+
498
+	vmxnet3_command ( vmxnet, VMXNET3_CMD_QUIESCE_DEV );
499
+	vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV );
500
+ err_activate:
501
+	vmxnet3_flush_tx ( netdev );
502
+	vmxnet3_flush_rx ( netdev );
503
+	free_dma ( vmxnet->dma, sizeof ( *vmxnet->dma ) );
504
+ err_alloc_dma:
505
+	return rc;
506
+}
507
+
508
+/**
509
+ * Close NIC
510
+ *
511
+ * @v netdev		Network device
512
+ */
513
+static void vmxnet3_close ( struct net_device *netdev ) {
514
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
515
+
516
+	vmxnet3_command ( vmxnet, VMXNET3_CMD_QUIESCE_DEV );
517
+	vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV );
518
+	vmxnet3_flush_tx ( netdev );
519
+	vmxnet3_flush_rx ( netdev );
520
+	free_dma ( vmxnet->dma, sizeof ( *vmxnet->dma ) );
521
+}
522
+
523
+/** vmxnet3 net device operations */
524
+static struct net_device_operations vmxnet3_operations = {
525
+	.open		= vmxnet3_open,
526
+	.close		= vmxnet3_close,
527
+	.transmit	= vmxnet3_transmit,
528
+	.poll		= vmxnet3_poll,
529
+	.irq		= vmxnet3_irq,
530
+};
531
+
532
+/**
533
+ * Check version
534
+ *
535
+ * @v vmxnet		vmxnet3 NIC
536
+ * @ret rc		Return status code
537
+ */
538
+static int vmxnet3_check_version ( struct vmxnet3_nic *vmxnet ) {
539
+	uint32_t version;
540
+	uint32_t upt_version;
541
+
542
+	/* Read version */
543
+	version = readl ( vmxnet->vd + VMXNET3_VD_VRRS );
544
+	upt_version = readl ( vmxnet->vd + VMXNET3_VD_UVRS );
545
+	DBGC ( vmxnet, "VMXNET3 %p is version %d (UPT version %d)\n",
546
+	       vmxnet, version, upt_version );
547
+
548
+	/* Inform NIC of driver version */
549
+	writel ( VMXNET3_VERSION_SELECT, ( vmxnet->vd + VMXNET3_VD_VRRS ) );
550
+	writel ( VMXNET3_UPT_VERSION_SELECT, ( vmxnet->vd + VMXNET3_VD_UVRS ) );
551
+
552
+	return 0;
553
+}
554
+
555
+/**
556
+ * Get permanent MAC address
557
+ *
558
+ * @v vmxnet		vmxnet3 NIC
559
+ * @v hw_addr		Hardware address to fill in
560
+ */
561
+static void vmxnet3_get_hw_addr ( struct vmxnet3_nic *vmxnet, void *hw_addr ) {
562
+	struct {
563
+		uint32_t low;
564
+		uint32_t high;
565
+	} __attribute__ (( packed )) mac;
566
+
567
+	mac.low = le32_to_cpu ( vmxnet3_command ( vmxnet,
568
+					       VMXNET3_CMD_GET_PERM_MAC_LO ) );
569
+	mac.high = le32_to_cpu ( vmxnet3_command ( vmxnet,
570
+					       VMXNET3_CMD_GET_PERM_MAC_HI ) );
571
+	memcpy ( hw_addr, &mac, ETH_ALEN );
572
+}
573
+
574
+/**
575
+ * Probe PCI device
576
+ *
577
+ * @v pci		PCI device
578
+ * @v id		PCI ID
579
+ * @ret rc		Return status code
580
+ */
581
+static int vmxnet3_probe ( struct pci_device *pci ) {
582
+	struct net_device *netdev;
583
+	struct vmxnet3_nic *vmxnet;
584
+	int rc;
585
+
586
+	/* Allocate network device */
587
+	netdev = alloc_etherdev ( sizeof ( *vmxnet ) );
588
+	if ( ! netdev ) {
589
+		rc = -ENOMEM;
590
+		goto err_alloc_etherdev;
591
+	}
592
+	netdev_init ( netdev, &vmxnet3_operations );
593
+	vmxnet = netdev_priv ( netdev );
594
+	pci_set_drvdata ( pci, netdev );
595
+	netdev->dev = &pci->dev;
596
+	memset ( vmxnet, 0, sizeof ( *vmxnet ) );
597
+
598
+	/* Fix up PCI device */
599
+	adjust_pci_device ( pci );
600
+
601
+	/* Map PCI BARs */
602
+	vmxnet->pt = ioremap ( pci_bar_start ( pci, VMXNET3_PT_BAR ),
603
+			       VMXNET3_PT_LEN );
604
+	vmxnet->vd = ioremap ( pci_bar_start ( pci, VMXNET3_VD_BAR ),
605
+			       VMXNET3_VD_LEN );
606
+
607
+	/* Version check */
608
+	if ( ( rc = vmxnet3_check_version ( vmxnet ) ) != 0 )
609
+		goto err_check_version;
610
+
611
+	/* Reset device */
612
+	if ( ( rc = vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV ) ) != 0 )
613
+		goto err_reset;
614
+
615
+	/* Read initial MAC address */
616
+	vmxnet3_get_hw_addr ( vmxnet, &netdev->hw_addr );
617
+
618
+	/* Register network device */
619
+	if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
620
+		DBGC ( vmxnet, "VMXNET3 %p could not register net device: "
621
+		       "%s\n", vmxnet, strerror ( rc ) );
622
+		goto err_register_netdev;
623
+	}
624
+
625
+	/* Get initial link state */
626
+	vmxnet3_check_link ( netdev );
627
+
628
+	return 0;
629
+
630
+	unregister_netdev ( netdev );
631
+ err_register_netdev:
632
+ err_reset:
633
+ err_check_version:
634
+	iounmap ( vmxnet->vd );
635
+	iounmap ( vmxnet->pt );
636
+	netdev_nullify ( netdev );
637
+	netdev_put ( netdev );
638
+ err_alloc_etherdev:
639
+	return rc;
640
+}
641
+
642
+/**
643
+ * Remove PCI device
644
+ *
645
+ * @v pci		PCI device
646
+ */
647
+static void vmxnet3_remove ( struct pci_device *pci ) {
648
+	struct net_device *netdev = pci_get_drvdata ( pci );
649
+	struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
650
+
651
+	unregister_netdev ( netdev );
652
+	iounmap ( vmxnet->vd );
653
+	iounmap ( vmxnet->pt );
654
+	netdev_nullify ( netdev );
655
+	netdev_put ( netdev );
656
+}
657
+
658
+/** vmxnet3 PCI IDs */
659
+static struct pci_device_id vmxnet3_nics[] = {
660
+	PCI_ROM ( 0x15ad, 0x07b0, "vmxnet3", "vmxnet3 virtual NIC", 0 ),
661
+};
662
+
663
+/** vmxnet3 PCI driver */
664
+struct pci_driver vmxnet3_driver __pci_driver = {
665
+	.ids = vmxnet3_nics,
666
+	.id_count = ( sizeof ( vmxnet3_nics ) / sizeof ( vmxnet3_nics[0] ) ),
667
+	.probe = vmxnet3_probe,
668
+	.remove = vmxnet3_remove,
669
+};

+ 497
- 0
src/drivers/net/vmxnet3.h View File

@@ -0,0 +1,497 @@
1
+#ifndef _VMXNET3_H
2
+#define _VMXNET3_H
3
+
4
+/*
5
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
6
+ *
7
+ * This program is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU General Public License as
9
+ * published by the Free Software Foundation; either version 2 of the
10
+ * License, or any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful, but
13
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
+ * General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
+ */
21
+
22
+FILE_LICENCE ( GPL2_OR_LATER );
23
+
24
+/**
25
+ * @file
26
+ *
27
+ * VMware vmxnet3 virtual NIC driver
28
+ *
29
+ */
30
+
31
+#include <ipxe/pci.h>
32
+
33
+/** Maximum number of TX queues */
34
+#define VMXNET3_MAX_TX_QUEUES 8
35
+
36
+/** Maximum number of RX queues */
37
+#define VMXNET3_MAX_RX_QUEUES 16
38
+
39
+/** Maximum number of interrupts */
40
+#define VMXNET3_MAX_INTRS 25
41
+
42
+/** Maximum packet size */
43
+#define VMXNET3_MAX_PACKET_LEN 0x4000
44
+
45
+/** "PT" PCI BAR address */
46
+#define VMXNET3_PT_BAR PCI_BASE_ADDRESS_0
47
+
48
+/** "PT" PCI BAR size */
49
+#define VMXNET3_PT_LEN 0x1000
50
+
51
+/** Interrupt Mask Register */
52
+#define VMXNET3_PT_IMR 0x0
53
+
54
+/** Transmit producer index */
55
+#define VMXNET3_PT_TXPROD 0x600
56
+
57
+/** Rx producer index for ring 1 */
58
+#define VMXNET3_PT_RXPROD 0x800
59
+
60
+/** Rx producer index for ring 2 */
61
+#define VMXNET3_PT_RXPROD2 0xa00
62
+
63
+/** "VD" PCI BAR address */
64
+#define VMXNET3_VD_BAR PCI_BASE_ADDRESS_1
65
+
66
+/** "VD" PCI BAR size */
67
+#define VMXNET3_VD_LEN 0x1000
68
+
69
+/** vmxnet3 Revision Report Selection */
70
+#define VMXNET3_VD_VRRS	0x0
71
+
72
+/** UPT Version Report Selection */
73
+#define VMXNET3_VD_UVRS 0x8
74
+
75
+/** Driver Shared Address Low */
76
+#define VMXNET3_VD_DSAL 0x10
77
+
78
+/** Driver Shared Address High */
79
+#define VMXNET3_VD_DSAH 0x18
80
+
81
+/** Command */
82
+#define VMXNET3_VD_CMD	0x20
83
+
84
+/** MAC Address Low */
85
+#define VMXNET3_VD_MACL 0x28
86
+
87
+/** MAC Address High */
88
+#define VMXNET3_VD_MACH 0x30
89
+
90
+/** Interrupt Cause Register */
91
+#define VMXNET3_VD_ICR	0x38
92
+
93
+/** Event Cause Register */
94
+#define VMXNET3_VD_ECR	0x40
95
+
96
+/** Commands */
97
+enum vmxnet3_command {
98
+	VMXNET3_CMD_FIRST_SET = 0xcafe0000,
99
+	VMXNET3_CMD_ACTIVATE_DEV = VMXNET3_CMD_FIRST_SET,
100
+	VMXNET3_CMD_QUIESCE_DEV,
101
+	VMXNET3_CMD_RESET_DEV,
102
+	VMXNET3_CMD_UPDATE_RX_MODE,
103
+	VMXNET3_CMD_UPDATE_MAC_FILTERS,
104
+	VMXNET3_CMD_UPDATE_VLAN_FILTERS,
105
+	VMXNET3_CMD_UPDATE_RSSIDT,
106
+	VMXNET3_CMD_UPDATE_IML,
107
+	VMXNET3_CMD_UPDATE_PMCFG,
108
+	VMXNET3_CMD_UPDATE_FEATURE,
109
+	VMXNET3_CMD_LOAD_PLUGIN,
110
+
111
+	VMXNET3_CMD_FIRST_GET = 0xf00d0000,
112
+	VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET,
113
+	VMXNET3_CMD_GET_STATS,
114
+	VMXNET3_CMD_GET_LINK,
115
+	VMXNET3_CMD_GET_PERM_MAC_LO,
116
+	VMXNET3_CMD_GET_PERM_MAC_HI,
117
+	VMXNET3_CMD_GET_DID_LO,
118
+	VMXNET3_CMD_GET_DID_HI,
119
+	VMXNET3_CMD_GET_DEV_EXTRA_INFO,
120
+	VMXNET3_CMD_GET_CONF_INTR
121
+};
122
+
123
+/** Events */
124
+enum vmxnet3_event {
125
+	VMXNET3_ECR_RQERR = 0x00000001,
126
+	VMXNET3_ECR_TQERR = 0x00000002,
127
+	VMXNET3_ECR_LINK = 0x00000004,
128
+	VMXNET3_ECR_DIC = 0x00000008,
129
+	VMXNET3_ECR_DEBUG = 0x00000010,
130
+};
131
+
132
+/** Miscellaneous configuration descriptor */
133
+struct vmxnet3_misc_config {
134
+	/** Driver version */
135
+	uint32_t version;
136
+	/** Guest information */
137
+	uint32_t guest_info;
138
+	/** Version supported */
139
+	uint32_t version_support;
140
+	/** UPT version supported */
141
+	uint32_t upt_version_support;
142
+	/** UPT features supported */
143
+	uint64_t upt_features;
144
+	/** Driver-private data address */
145
+	uint64_t driver_data_address;
146
+	/** Queue descriptors data address */
147
+	uint64_t queue_desc_address;
148
+	/** Driver-private data length */
149
+	uint32_t driver_data_len;
150
+	/** Queue descriptors data length */
151
+	uint32_t queue_desc_len;
152
+	/** Maximum transmission unit */
153
+	uint32_t mtu;
154
+	/** Maximum number of RX scatter-gather */
155
+	uint16_t max_num_rx_sg;
156
+	/** Number of TX queues */
157
+	uint8_t num_tx_queues;
158
+	/** Number of RX queues */
159
+	uint8_t num_rx_queues;
160
+	/** Reserved */
161
+	uint32_t reserved0[4];
162
+} __attribute__ (( packed ));
163
+
164
+/** Driver version magic */
165
+#define VMXNET3_VERSION_MAGIC 0x69505845
166
+
167
+/** Interrupt configuration */
168
+struct vmxnet3_interrupt_config {
169
+	uint8_t mask_mode;
170
+	uint8_t num_intrs;
171
+	uint8_t event_intr_index;
172
+	uint8_t moderation_level[VMXNET3_MAX_INTRS];
173
+	uint32_t control;
174
+	uint32_t reserved0[2];
175
+} __attribute__ (( packed ));
176
+
177
+/** Interrupt control - disable all interrupts */
178
+#define VMXNET3_IC_DISABLE_ALL 0x1
179
+
180
+/** Receive filter configuration */
181
+struct vmxnet3_rx_filter_config {
182
+	/** Receive filter mode */
183
+	uint32_t mode;
184
+	/** Multicast filter table length */
185
+	uint16_t multicast_len;
186
+	/** Reserved */
187
+	uint16_t reserved0;
188
+	/** Multicast filter table address */
189
+	uint64_t multicast_address;
190
+	/** VLAN filter table (one bit per possible VLAN) */
191
+	uint8_t vlan_filter[512];
192
+} __attribute__ (( packed ));
193
+
194
+/** Receive filter mode */
195
+enum vmxnet3_rx_filter_mode {
196
+	VMXNET3_RXM_UCAST	= 0x01,  /**< Unicast only */
197
+	VMXNET3_RXM_MCAST	= 0x02,  /**< Multicast passing the filters */
198
+	VMXNET3_RXM_BCAST	= 0x04,  /**< Broadcast only */
199
+	VMXNET3_RXM_ALL_MULTI	= 0x08,  /**< All multicast */
200
+	VMXNET3_RXM_PROMISC	= 0x10,  /**< Promiscuous */
201
+};
202
+
203
+/** Variable-length configuration descriptor */
204
+struct vmxnet3_variable_config {
205
+	uint32_t version;
206
+	uint32_t length;
207
+	uint64_t address;
208
+} __attribute__ (( packed ));
209
+
210
+/** Driver shared area */
211
+struct vmxnet3_shared {
212
+	/** Magic signature */
213
+	uint32_t magic;
214
+	/** Reserved */
215
+	uint32_t reserved0;
216
+	/** Miscellaneous configuration */
217
+	struct vmxnet3_misc_config misc;
218
+	/** Interrupt configuration */
219
+	struct vmxnet3_interrupt_config interrupt;
220
+	/** Receive filter configuration */
221
+	struct vmxnet3_rx_filter_config rx_filter;
222
+	/** RSS configuration */
223
+	struct vmxnet3_variable_config rss;
224
+	/** Pattern-matching configuration */
225
+	struct vmxnet3_variable_config pattern;
226
+	/** Plugin configuration */
227
+	struct vmxnet3_variable_config plugin;
228
+	/** Event notifications */
229
+	uint32_t ecr;
230
+	/** Reserved */
231
+	uint32_t reserved1[5];
232
+} __attribute__ (( packed ));
233
+
234
+/** Alignment of driver shared area */
235
+#define VMXNET3_SHARED_ALIGN 8
236
+
237
+/** Driver shared area magic */
238
+#define VMXNET3_SHARED_MAGIC 0xbabefee1
239
+
240
+/** Transmit descriptor */
241
+struct vmxnet3_tx_desc {
242
+	/** Address */
243
+	uint64_t address;
244
+	/** Flags */
245
+	uint32_t flags[2];
246
+} __attribute__ (( packed ));
247
+
248
+/** Transmit generation flag */
249
+#define VMXNET3_TXF_GEN 0x00004000UL
250
+
251
+/** Transmit end-of-packet flag */
252
+#define VMXNET3_TXF_EOP 0x000001000UL
253
+
254
+/** Transmit completion request flag */
255
+#define VMXNET3_TXF_CQ 0x000002000UL
256
+
257
+/** Transmit completion descriptor */
258
+struct vmxnet3_tx_comp {
259
+	/** Index of the end-of-packet descriptor */
260
+	uint32_t index;
261
+	/** Reserved */
262
+	uint32_t reserved0[2];
263
+	/** Flags */
264
+	uint32_t flags;
265
+} __attribute__ (( packed ));
266
+
267
+/** Transmit completion generation flag */
268
+#define VMXNET3_TXCF_GEN 0x80000000UL
269
+
270
+/** Transmit queue control */
271
+struct vmxnet3_tx_queue_control {
272
+	uint32_t num_deferred;
273
+	uint32_t threshold;
274
+	uint64_t reserved0;
275
+} __attribute__ (( packed ));
276
+
277
+/** Transmit queue configuration */
278
+struct vmxnet3_tx_queue_config {
279
+	/** Descriptor ring address */
280
+	uint64_t desc_address;
281
+	/** Data ring address */
282
+	uint64_t immediate_address;
283
+	/** Completion ring address */
284
+	uint64_t comp_address;
285
+	/** Driver-private data address */
286
+	uint64_t driver_data_address;
287
+	/** Reserved */
288
+	uint64_t reserved0;
289
+	/** Number of descriptors */
290
+	uint32_t num_desc;
291
+	/** Number of data descriptors */
292
+	uint32_t num_immediate;
293
+	/** Number of completion descriptors */
294
+	uint32_t num_comp;
295
+	/** Driver-private data length */
296
+	uint32_t driver_data_len;
297
+	/** Interrupt index */
298
+	uint8_t intr_index;
299
+	/** Reserved */
300
+	uint8_t reserved[7];
301
+} __attribute__ (( packed ));
302
+
303
+/** Transmit queue statistics */
304
+struct vmxnet3_tx_stats {
305
+	/** Reserved */
306
+	uint64_t reserved[10];
307
+} __attribute__ (( packed ));
308
+
309
+/** Receive descriptor */
310
+struct vmxnet3_rx_desc {
311
+	/** Address */
312
+	uint64_t address;
313
+	/** Flags */
314
+	uint32_t flags;
315
+	/** Reserved */
316
+	uint32_t reserved0;
317
+} __attribute__ (( packed ));
318
+
319
+/** Receive generation flag */
320
+#define VMXNET3_RXF_GEN 0x80000000UL
321
+
322
+/** Receive completion descriptor */
323
+struct vmxnet3_rx_comp {
324
+	/** Descriptor index */
325
+	uint32_t index;
326
+	/** RSS hash value */
327
+	uint32_t rss;
328
+	/** Length */
329
+	uint32_t len;
330
+	/** Flags */
331
+	uint32_t flags;
332
+} __attribute__ (( packed ));
333
+
334
+/** Receive completion generation flag */
335
+#define VMXNET3_RXCF_GEN 0x80000000UL
336
+
337
+/** Receive queue control */
338
+struct vmxnet3_rx_queue_control {
339
+	uint8_t update_prod;
340
+	uint8_t reserved0[7];
341
+	uint64_t reserved1;
342
+} __attribute__ (( packed ));
343
+
344
+/** Receive queue configuration */
345
+struct vmxnet3_rx_queue_config {
346
+	/** Descriptor ring addresses */
347
+	uint64_t desc_address[2];
348
+	/** Completion ring address */
349
+	uint64_t comp_address;
350
+	/** Driver-private data address */
351
+	uint64_t driver_data_address;
352
+	/** Reserved */
353
+	uint64_t reserved0;
354
+	/** Number of descriptors */
355
+	uint32_t num_desc[2];
356
+	/** Number of completion descriptors */
357
+	uint32_t num_comp;
358
+	/** Driver-private data length */
359
+	uint32_t driver_data_len;
360
+	/** Interrupt index */
361
+	uint8_t intr_index;
362
+	/** Reserved */
363
+	uint8_t reserved[7];
364
+} __attribute__ (( packed ));
365
+
366
+/** Receive queue statistics */
367
+struct vmxnet3_rx_stats {
368
+	/** Reserved */
369
+	uint64_t reserved[10];
370
+} __attribute__ (( packed ));
371
+
372
+/** Queue status */
373
+struct vmxnet3_queue_status {
374
+	uint8_t stopped;
375
+	uint8_t reserved0[3];
376
+	uint32_t error;
377
+} __attribute__ (( packed ));
378
+
379
+/** Transmit queue descriptor */
380
+struct vmxnet3_tx_queue {
381
+	struct vmxnet3_tx_queue_control ctrl;
382
+	struct vmxnet3_tx_queue_config cfg;
383
+	struct vmxnet3_queue_status status;
384
+	struct vmxnet3_tx_stats state;
385
+	uint8_t reserved[88];
386
+} __attribute__ (( packed ));
387
+
388
+/** Receive queue descriptor */
389
+struct vmxnet3_rx_queue {
390
+	struct vmxnet3_rx_queue_control ctrl;
391
+	struct vmxnet3_rx_queue_config cfg;
392
+	struct vmxnet3_queue_status status;
393
+	struct vmxnet3_rx_stats stats;
394
+	uint8_t reserved[88];
395
+} __attribute__ (( packed ));
396
+
397
+/**
398
+ * Queue descriptor set
399
+ *
400
+ * We use only a single TX and RX queue
401
+ */
402
+struct vmxnet3_queues {
403
+	/** Transmit queue descriptor(s) */
404
+	struct vmxnet3_tx_queue tx;
405
+	/** Receive queue descriptor(s) */
406
+	struct vmxnet3_rx_queue rx;
407
+} __attribute__ (( packed ));
408
+
409
+/** Alignment of queue descriptor set */
410
+#define VMXNET3_QUEUES_ALIGN 128
411
+
412
+/** Alignment of rings */
413
+#define VMXNET3_RING_ALIGN 512
414
+
415
+/** Number of TX descriptors */
416
+#define VMXNET3_NUM_TX_DESC 32
417
+
418
+/** Number of TX completion descriptors */
419
+#define VMXNET3_NUM_TX_COMP 32
420
+
421
+/** Number of RX descriptors */
422
+#define VMXNET3_NUM_RX_DESC 32
423
+
424
+/** Number of RX completion descriptors */
425
+#define VMXNET3_NUM_RX_COMP 32
426
+
427
+/**
428
+ * DMA areas
429
+ *
430
+ * These are arranged in order of decreasing alignment, to allow for a
431
+ * single allocation
432
+ */
433
+struct vmxnet3_dma {
434
+	/** TX descriptor ring */
435
+	struct vmxnet3_tx_desc tx_desc[VMXNET3_NUM_TX_DESC];
436
+	/** TX completion ring */
437
+	struct vmxnet3_tx_comp tx_comp[VMXNET3_NUM_TX_COMP];
438
+	/** RX descriptor ring */
439
+	struct vmxnet3_rx_desc rx_desc[VMXNET3_NUM_RX_DESC];
440
+	/** RX completion ring */
441
+	struct vmxnet3_rx_comp rx_comp[VMXNET3_NUM_RX_COMP];
442
+	/** Queue descriptors */
443
+	struct vmxnet3_queues queues;
444
+	/** Shared area */
445
+	struct vmxnet3_shared shared;
446
+} __attribute__ (( packed ));
447
+
448
+/** DMA area alignment */
449
+#define VMXNET3_DMA_ALIGN 512
450
+
451
+/** Producer and consumer counters */
452
+struct vmxnet3_counters {
453
+	/** Transmit producer counter */
454
+	unsigned int tx_prod;
455
+	/** Transmit completion consumer counter */
456
+	unsigned int tx_cons;
457
+	/** Receive producer counter */
458
+	unsigned int rx_prod;
459
+	/** Receive fill level */
460
+	unsigned int rx_fill;
461
+	/** Receive consumer counter */
462
+	unsigned int rx_cons;
463
+};
464
+
465
+/** A vmxnet3 NIC */
466
+struct vmxnet3_nic {
467
+	/** "PT" register base address */
468
+	void *pt;
469
+	/** "VD" register base address */
470
+	void *vd;
471
+
472
+	/** DMA area */
473
+	struct vmxnet3_dma *dma;
474
+	/** Producer and consumer counters */
475
+	struct vmxnet3_counters count;
476
+	/** Transmit I/O buffers */
477
+	struct io_buffer *tx_iobuf[VMXNET3_NUM_TX_DESC];
478
+	/** Receive I/O buffers */
479
+	struct io_buffer *rx_iobuf[VMXNET3_NUM_RX_DESC];
480
+};
481
+
482
+/** vmxnet3 version that we support */
483
+#define VMXNET3_VERSION_SELECT 1
484
+
485
+/** UPT version that we support */
486
+#define VMXNET3_UPT_VERSION_SELECT 1
487
+
488
+/** MTU size */
489
+#define VMXNET3_MTU ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* FCS */ )
490
+
491
+/** Receive ring maximum fill level */
492
+#define VMXNET3_RX_FILL 8
493
+
494
+/** Received packet alignment padding */
495
+#define NET_IP_ALIGN 2
496
+
497
+#endif /* _VMXNET3_H */

+ 1
- 0
src/include/ipxe/errfile.h View File

@@ -139,6 +139,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
139 139
 #define ERRFILE_igbvf_main	     ( ERRFILE_DRIVER | 0x005e0000 )
140 140
 #define ERRFILE_ath9k		     ( ERRFILE_DRIVER | 0x005f0000 )
141 141
 #define ERRFILE_ath		     ( ERRFILE_DRIVER | 0x00600000 )
142
+#define ERRFILE_vmxnet3		     ( ERRFILE_DRIVER | 0x00610000 )
142 143
 
143 144
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
144 145
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )

Loading…
Cancel
Save