Browse Source

[myson] Replace driver for Myson Technology NICs

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
1fe27a3e0e
4 changed files with 869 additions and 1022 deletions
  1. 0
    1022
      src/drivers/net/mtd80x.c
  2. 668
    0
      src/drivers/net/myson.c
  3. 200
    0
      src/drivers/net/myson.h
  4. 1
    0
      src/include/ipxe/errfile.h

+ 0
- 1022
src/drivers/net/mtd80x.c
File diff suppressed because it is too large
View File


+ 668
- 0
src/drivers/net/myson.c View File

@@ -0,0 +1,668 @@
1
+/*
2
+ * Copyright (C) 2012 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+#include <stdint.h>
23
+#include <string.h>
24
+#include <unistd.h>
25
+#include <errno.h>
26
+#include <byteswap.h>
27
+#include <ipxe/netdevice.h>
28
+#include <ipxe/ethernet.h>
29
+#include <ipxe/if_ether.h>
30
+#include <ipxe/iobuf.h>
31
+#include <ipxe/malloc.h>
32
+#include <ipxe/pci.h>
33
+#include <ipxe/mii.h>
34
+#include "myson.h"
35
+
36
+/** @file
37
+ *
38
+ * Myson Technology network card driver
39
+ *
40
+ */
41
+
42
+/******************************************************************************
43
+ *
44
+ * Device reset
45
+ *
46
+ ******************************************************************************
47
+ */
48
+
49
+/**
50
+ * Reset controller chip
51
+ *
52
+ * @v myson		Myson device
53
+ * @ret rc		Return status code
54
+ */
55
+static int myson_soft_reset ( struct myson_nic *myson ) {
56
+	uint32_t bcr;
57
+	unsigned int i;
58
+
59
+	/* Initiate reset */
60
+	bcr = readl ( myson->regs + MYSON_BCR );
61
+	writel ( ( bcr | MYSON_BCR_SWR ), myson->regs + MYSON_BCR );
62
+
63
+	/* Wait for reset to complete */
64
+	for ( i = 0 ; i < MYSON_RESET_MAX_WAIT_MS ; i++ ) {
65
+
66
+		/* If reset is not complete, delay 1ms and retry */
67
+		if ( readl ( myson->regs + MYSON_BCR ) & MYSON_BCR_SWR ) {
68
+			mdelay ( 1 );
69
+			continue;
70
+		}
71
+
72
+		/* Apply a sensible default bus configuration */
73
+		bcr = readl ( myson->regs + MYSON_BCR );
74
+		bcr &= ~MYSON_BCR_PBL_MASK;
75
+		bcr |= ( MYSON_BCR_RLE | MYSON_BCR_RME | MYSON_BCR_WIE |
76
+			 MYSON_BCR_PBL_DEFAULT );
77
+		writel ( bcr, myson->regs + MYSON_BCR );
78
+		DBGC ( myson, "MYSON %p using configuration %08x\n",
79
+		       myson, bcr );
80
+
81
+		return 0;
82
+	}
83
+
84
+	DBGC ( myson, "MYSON %p timed out waiting for reset\n", myson );
85
+	return -ETIMEDOUT;
86
+}
87
+
88
+/**
89
+ * Reload configuration from EEPROM
90
+ *
91
+ * @v myson		Myson device
92
+ * @ret rc		Return status code
93
+ */
94
+static int myson_reload_config ( struct myson_nic *myson ) {
95
+	unsigned int i;
96
+
97
+	/* Initiate reload */
98
+	writel ( MYSON_ROM_AUTOLD, myson->regs + MYSON_ROM_MII );
99
+
100
+	/* Wait for reload to complete */
101
+	for ( i = 0 ; i < MYSON_AUTOLD_MAX_WAIT_MS ; i++ ) {
102
+
103
+		/* If reload is not complete, delay 1ms and retry */
104
+		if ( readl ( myson->regs + MYSON_ROM_MII ) & MYSON_ROM_AUTOLD ){
105
+			mdelay ( 1 );
106
+			continue;
107
+		}
108
+
109
+		return 0;
110
+	}
111
+
112
+	DBGC ( myson, "MYSON %p timed out waiting for configuration "
113
+	       "reload\n", myson );
114
+	return -ETIMEDOUT;
115
+}
116
+
117
+/**
118
+ * Reset hardware
119
+ *
120
+ * @v myson		Myson device
121
+ * @ret rc		Return status code
122
+ */
123
+static int myson_reset ( struct myson_nic *myson ) {
124
+	int rc;
125
+
126
+	/* Disable all interrupts */
127
+	writel ( 0, myson->regs + MYSON_IMR );
128
+
129
+	/* Perform soft reset */
130
+	if ( ( rc = myson_soft_reset ( myson ) ) != 0 )
131
+		return rc;
132
+
133
+	/* Reload configuration from EEPROM */
134
+	if ( ( rc = myson_reload_config ( myson ) ) != 0 )
135
+		return rc;
136
+
137
+	return 0;
138
+}
139
+
140
+/******************************************************************************
141
+ *
142
+ * Network device interface
143
+ *
144
+ ******************************************************************************
145
+ */
146
+
147
+/**
148
+ * Create descriptor ring
149
+ *
150
+ * @v myson		Myson device
151
+ * @v ring		Descriptor ring
152
+ * @ret rc		Return status code
153
+ */
154
+static int myson_create_ring ( struct myson_nic *myson,
155
+			       struct myson_ring *ring ) {
156
+	size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
157
+	struct myson_descriptor *desc;
158
+	struct myson_descriptor *next;
159
+	physaddr_t address;
160
+	unsigned int i;
161
+	int rc;
162
+
163
+	/* Allocate descriptor ring */
164
+	ring->desc = malloc_dma ( len, MYSON_RING_ALIGN );
165
+	if ( ! ring->desc ) {
166
+		rc = -ENOMEM;
167
+		goto err_alloc;
168
+	}
169
+	address = virt_to_bus ( ring->desc );
170
+
171
+	/* Check address is usable by card */
172
+	if ( ! myson_address_ok ( address + len ) ) {
173
+		DBGC ( myson, "MYSON %p cannot support 64-bit ring address\n",
174
+		       myson );
175
+		rc = -ENOTSUP;
176
+		goto err_64bit;
177
+	}
178
+
179
+	/* Initialise descriptor ring */
180
+	memset ( ring->desc, 0, len );
181
+	for ( i = 0 ; i < ring->count ; i++ ) {
182
+		desc = &ring->desc[i];
183
+		next = &ring->desc[ ( i + 1 ) % ring->count ];
184
+		desc->next = cpu_to_le32 ( virt_to_bus ( next ) );
185
+	}
186
+
187
+	/* Program ring address */
188
+	writel ( address, myson->regs + ring->reg );
189
+	DBGC ( myson, "MYSON %p ring %02x is at [%08llx,%08llx)\n",
190
+	       myson, ring->reg, ( ( unsigned long long ) address ),
191
+	       ( ( unsigned long long ) address + len ) );
192
+
193
+	return 0;
194
+
195
+ err_64bit:
196
+	free_dma ( ring->desc, len );
197
+	ring->desc = NULL;
198
+ err_alloc:
199
+	return rc;
200
+}
201
+
202
+/**
203
+ * Destroy descriptor ring
204
+ *
205
+ * @v myson		Myson device
206
+ * @v ring		Descriptor ring
207
+ */
208
+static void myson_destroy_ring ( struct myson_nic *myson,
209
+				 struct myson_ring *ring ) {
210
+	size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
211
+
212
+	/* Clear ring address */
213
+	writel ( 0, myson->regs + ring->reg );
214
+
215
+	/* Free descriptor ring */
216
+	free_dma ( ring->desc, len );
217
+	ring->desc = NULL;
218
+	ring->prod = 0;
219
+	ring->cons = 0;
220
+}
221
+
222
+/**
223
+ * Refill receive descriptor ring
224
+ *
225
+ * @v netdev		Network device
226
+ */
227
+static void myson_refill_rx ( struct net_device *netdev ) {
228
+	struct myson_nic *myson = netdev->priv;
229
+	struct myson_descriptor *rx;
230
+	struct io_buffer *iobuf;
231
+	unsigned int rx_idx;
232
+	physaddr_t address;
233
+
234
+	while ( ( myson->rx.prod - myson->rx.cons ) < MYSON_NUM_RX_DESC ) {
235
+
236
+		/* Allocate I/O buffer */
237
+		iobuf = alloc_iob ( MYSON_RX_MAX_LEN );
238
+		if ( ! iobuf ) {
239
+			/* Wait for next refill */
240
+			return;
241
+		}
242
+
243
+		/* Check address is usable by card */
244
+		address = virt_to_bus ( iobuf->data );
245
+		if ( ! myson_address_ok ( address ) ) {
246
+			DBGC ( myson, "MYSON %p cannot support 64-bit RX "
247
+			       "buffer address\n", myson );
248
+			netdev_rx_err ( netdev, iobuf, -ENOTSUP );
249
+			return;
250
+		}
251
+
252
+		/* Get next receive descriptor */
253
+		rx_idx = ( myson->rx.prod++ % MYSON_NUM_RX_DESC );
254
+		rx = &myson->rx.desc[rx_idx];
255
+
256
+		/* Populate receive descriptor */
257
+		rx->address = cpu_to_le32 ( address );
258
+		rx->control =
259
+			cpu_to_le32 ( MYSON_RX_CTRL_RBS ( MYSON_RX_MAX_LEN ) );
260
+		wmb();
261
+		rx->status = cpu_to_le32 ( MYSON_RX_STAT_OWN );
262
+		wmb();
263
+
264
+		/* Record I/O buffer */
265
+		assert ( myson->rx_iobuf[rx_idx] == NULL );
266
+		myson->rx_iobuf[rx_idx] = iobuf;
267
+
268
+		/* Notify card that there are descriptors available */
269
+		writel ( 0, myson->regs + MYSON_RXPDR );
270
+
271
+		DBGC2 ( myson, "MYSON %p RX %d is [%llx,%llx)\n", myson,
272
+			rx_idx, ( ( unsigned long long ) address ),
273
+			( ( unsigned long long ) address + MYSON_RX_MAX_LEN ) );
274
+	}
275
+}
276
+
277
+/**
278
+ * Open network device
279
+ *
280
+ * @v netdev		Network device
281
+ * @ret rc		Return status code
282
+ */
283
+static int myson_open ( struct net_device *netdev ) {
284
+	struct myson_nic *myson = netdev->priv;
285
+	union myson_physical_address mac;
286
+	int rc;
287
+
288
+	/* Set MAC address */
289
+	memset ( &mac, 0, sizeof ( mac ) );
290
+	memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN );
291
+	writel ( le32_to_cpu ( mac.reg.low ), myson->regs + MYSON_PAR0 );
292
+	writel ( le32_to_cpu ( mac.reg.high ), myson->regs + MYSON_PAR4 );
293
+
294
+	/* Create transmit descriptor ring */
295
+	if ( ( rc = myson_create_ring ( myson, &myson->tx ) ) != 0 )
296
+		goto err_create_tx;
297
+
298
+	/* Create receive descriptor ring */
299
+	if ( ( rc = myson_create_ring ( myson, &myson->rx ) ) != 0 )
300
+		goto err_create_rx;
301
+
302
+	/* Configure transmitter and receiver */
303
+	writel ( ( MYSON_TCR_TE | MYSON_RCR_PROM | MYSON_RCR_AB | MYSON_RCR_AM |
304
+		   MYSON_RCR_ARP | MYSON_RCR_ALP | MYSON_RCR_RE ),
305
+		 myson->regs + MYSON_TCR_RCR );
306
+
307
+	/* Fill receive ring */
308
+	myson_refill_rx ( netdev );
309
+
310
+	return 0;
311
+
312
+	myson_destroy_ring ( myson, &myson->rx );
313
+ err_create_rx:
314
+	myson_destroy_ring ( myson, &myson->tx );
315
+ err_create_tx:
316
+	return rc;
317
+}
318
+
319
+/**
320
+ * Wait for transmit and receive to become idle
321
+ *
322
+ * @v myson		Myson device
323
+ * @ret rc		Return status code
324
+ */
325
+static int myson_wait_idle ( struct myson_nic *myson ) {
326
+	uint32_t tcr_rcr;
327
+	unsigned int i;
328
+
329
+	/* Wait for both transmit and receive to be idle */
330
+	for ( i = 0 ; i < MYSON_IDLE_MAX_WAIT_MS ; i++ ) {
331
+
332
+		/* If either process is running, delay 1ms and retry */
333
+		tcr_rcr = readl ( myson->regs + MYSON_TCR_RCR );
334
+		if ( tcr_rcr & ( MYSON_TCR_TXS | MYSON_RCR_RXS ) ) {
335
+			mdelay ( 1 );
336
+			continue;
337
+		}
338
+
339
+		return 0;
340
+	}
341
+
342
+	DBGC ( myson, "MYSON %p timed out waiting for idle state (status "
343
+	       "%08x)\n", myson, tcr_rcr );
344
+	return -ETIMEDOUT;
345
+}
346
+
347
+/**
348
+ * Close network device
349
+ *
350
+ * @v netdev		Network device
351
+ */
352
+static void myson_close ( struct net_device *netdev ) {
353
+	struct myson_nic *myson = netdev->priv;
354
+	unsigned int i;
355
+
356
+	/* Disable receiver and transmitter */
357
+	writel ( 0, myson->regs + MYSON_TCR_RCR );
358
+
359
+	/* Allow time for receiver and transmitter to become idle */
360
+	myson_wait_idle ( myson );
361
+
362
+	/* Destroy receive descriptor ring */
363
+	myson_destroy_ring ( myson, &myson->rx );
364
+
365
+	/* Discard any unused receive buffers */
366
+	for ( i = 0 ; i < MYSON_NUM_RX_DESC ; i++ ) {
367
+		if ( myson->rx_iobuf[i] )
368
+			free_iob ( myson->rx_iobuf[i] );
369
+		myson->rx_iobuf[i] = NULL;
370
+	}
371
+
372
+	/* Destroy transmit descriptor ring */
373
+	myson_destroy_ring ( myson, &myson->tx );
374
+}
375
+
376
+/**
377
+ * Transmit packet
378
+ *
379
+ * @v netdev		Network device
380
+ * @v iobuf		I/O buffer
381
+ * @ret rc		Return status code
382
+ */
383
+static int myson_transmit ( struct net_device *netdev,
384
+			    struct io_buffer *iobuf ) {
385
+	struct myson_nic *myson = netdev->priv;
386
+	struct myson_descriptor *tx;
387
+	unsigned int tx_idx;
388
+	physaddr_t address;
389
+
390
+	/* Check address is usable by card */
391
+	address = virt_to_bus ( iobuf->data );
392
+	if ( ! myson_address_ok ( address ) ) {
393
+		DBGC ( myson, "MYSON %p cannot support 64-bit TX buffer "
394
+		       "address\n", myson );
395
+		return -ENOTSUP;
396
+	}
397
+
398
+	/* Get next transmit descriptor */
399
+	if ( ( myson->tx.prod - myson->tx.cons ) >= MYSON_NUM_TX_DESC ) {
400
+		DBGC ( myson, "MYSON %p out of transmit descriptors\n",
401
+		       myson );
402
+		return -ENOBUFS;
403
+	}
404
+	tx_idx = ( myson->tx.prod++ % MYSON_NUM_TX_DESC );
405
+	tx = &myson->tx.desc[tx_idx];
406
+
407
+	/* Populate transmit descriptor */
408
+	tx->address = cpu_to_le32 ( address );
409
+	tx->control = cpu_to_le32 ( MYSON_TX_CTRL_IC | MYSON_TX_CTRL_LD |
410
+				    MYSON_TX_CTRL_FD | MYSON_TX_CTRL_CRC |
411
+				    MYSON_TX_CTRL_PAD | MYSON_TX_CTRL_RTLC |
412
+				    MYSON_TX_CTRL_PKTS ( iob_len ( iobuf ) ) |
413
+				    MYSON_TX_CTRL_TBS ( iob_len ( iobuf ) ) );
414
+	wmb();
415
+	tx->status = cpu_to_le32 ( MYSON_TX_STAT_OWN );
416
+	wmb();
417
+
418
+	/* Notify card that there are packets ready to transmit */
419
+	writel ( 0, myson->regs + MYSON_TXPDR );
420
+
421
+	DBGC2 ( myson, "MYSON %p TX %d is [%llx,%llx)\n", myson, tx_idx,
422
+		( ( unsigned long long ) address ),
423
+		( ( unsigned long long ) address + iob_len ( iobuf ) ) );
424
+
425
+	return 0;
426
+}
427
+
428
+/**
429
+ * Poll for completed packets
430
+ *
431
+ * @v netdev		Network device
432
+ */
433
+static void myson_poll_tx ( struct net_device *netdev ) {
434
+	struct myson_nic *myson = netdev->priv;
435
+	struct myson_descriptor *tx;
436
+	unsigned int tx_idx;
437
+
438
+	/* Check for completed packets */
439
+	while ( myson->tx.cons != myson->tx.prod ) {
440
+
441
+		/* Get next transmit descriptor */
442
+		tx_idx = ( myson->tx.cons % MYSON_NUM_TX_DESC );
443
+		tx = &myson->tx.desc[tx_idx];
444
+
445
+		/* Stop if descriptor is still in use */
446
+		if ( tx->status & cpu_to_le32 ( MYSON_TX_STAT_OWN ) )
447
+			return;
448
+
449
+		/* Complete TX descriptor */
450
+		if ( tx->status & cpu_to_le32 ( MYSON_TX_STAT_ABORT |
451
+						MYSON_TX_STAT_CSL ) ) {
452
+			DBGC ( myson, "MYSON %p TX %d completion error "
453
+			       "(%08x)\n", myson, tx_idx,
454
+			       le32_to_cpu ( tx->status ) );
455
+			netdev_tx_complete_next_err ( netdev, -EIO );
456
+		} else {
457
+			DBGC2 ( myson, "MYSON %p TX %d complete\n",
458
+				myson, tx_idx );
459
+			netdev_tx_complete_next ( netdev );
460
+		}
461
+		myson->tx.cons++;
462
+	}
463
+}
464
+
465
+/**
466
+ * Poll for received packets
467
+ *
468
+ * @v netdev		Network device
469
+ */
470
+static void myson_poll_rx ( struct net_device *netdev ) {
471
+	struct myson_nic *myson = netdev->priv;
472
+	struct myson_descriptor *rx;
473
+	struct io_buffer *iobuf;
474
+	unsigned int rx_idx;
475
+	size_t len;
476
+
477
+	/* Check for received packets */
478
+	while ( myson->rx.cons != myson->rx.prod ) {
479
+
480
+		/* Get next receive descriptor */
481
+		rx_idx = ( myson->rx.cons % MYSON_NUM_RX_DESC );
482
+		rx = &myson->rx.desc[rx_idx];
483
+
484
+		/* Stop if descriptor is still in use */
485
+		if ( rx->status & MYSON_RX_STAT_OWN )
486
+			return;
487
+
488
+		/* Populate I/O buffer */
489
+		iobuf = myson->rx_iobuf[rx_idx];
490
+		myson->rx_iobuf[rx_idx] = NULL;
491
+		len = MYSON_RX_STAT_FLNG ( le32_to_cpu ( rx->status ) );
492
+		iob_put ( iobuf, len - 4 /* strip CRC */ );
493
+
494
+		/* Hand off to network stack */
495
+		if ( rx->status & cpu_to_le32 ( MYSON_RX_STAT_ES ) ) {
496
+			DBGC ( myson, "MYSON %p RX %d error (length %zd, "
497
+			       "status %08x)\n", myson, rx_idx, len,
498
+			       le32_to_cpu ( rx->status ) );
499
+			netdev_rx_err ( netdev, iobuf, -EIO );
500
+		} else {
501
+			DBGC2 ( myson, "MYSON %p RX %d complete (length "
502
+				"%zd)\n", myson, rx_idx, len );
503
+			netdev_rx ( netdev, iobuf );
504
+		}
505
+		myson->rx.cons++;
506
+	}
507
+}
508
+
509
+/**
510
+ * Poll for completed and received packets
511
+ *
512
+ * @v netdev		Network device
513
+ */
514
+static void myson_poll ( struct net_device *netdev ) {
515
+	struct myson_nic *myson = netdev->priv;
516
+	uint32_t isr;
517
+	unsigned int i;
518
+
519
+	/* Polling the ISR seems to really upset this card; it ends up
520
+	 * getting no useful PCI transfers done and, for some reason,
521
+	 * flooding the network with invalid packets.  Work around
522
+	 * this by introducing deliberate delays between ISR reads.
523
+	 */
524
+	for ( i = 0 ; i < MYSON_ISR_IODELAY_COUNT ; i++ )
525
+		iodelay();
526
+
527
+	/* Check for and acknowledge interrupts */
528
+	isr = readl ( myson->regs + MYSON_ISR );
529
+	if ( ! isr )
530
+		return;
531
+	writel ( isr, myson->regs + MYSON_ISR );
532
+
533
+	/* Poll for TX completions, if applicable */
534
+	if ( isr & MYSON_IRQ_TI )
535
+		myson_poll_tx ( netdev );
536
+
537
+	/* Poll for RX completionsm, if applicable */
538
+	if ( isr & MYSON_IRQ_RI )
539
+		myson_poll_rx ( netdev );
540
+
541
+	/* Refill RX ring */
542
+	myson_refill_rx ( netdev );
543
+}
544
+
545
+/**
546
+ * Enable or disable interrupts
547
+ *
548
+ * @v netdev		Network device
549
+ * @v enable		Interrupts should be enabled
550
+ */
551
+static void myson_irq ( struct net_device *netdev, int enable ) {
552
+	struct myson_nic *myson = netdev->priv;
553
+	uint32_t imr;
554
+
555
+	imr = ( enable ? ( MYSON_IRQ_TI | MYSON_IRQ_RI ) : 0 );
556
+	writel ( imr, myson->regs + MYSON_IMR );
557
+}
558
+
559
+/** Myson network device operations */
560
+static struct net_device_operations myson_operations = {
561
+	.open		= myson_open,
562
+	.close		= myson_close,
563
+	.transmit	= myson_transmit,
564
+	.poll		= myson_poll,
565
+	.irq		= myson_irq,
566
+};
567
+
568
+/******************************************************************************
569
+ *
570
+ * PCI interface
571
+ *
572
+ ******************************************************************************
573
+ */
574
+
575
+/**
576
+ * Probe PCI device
577
+ *
578
+ * @v pci		PCI device
579
+ * @ret rc		Return status code
580
+ */
581
+static int myson_probe ( struct pci_device *pci ) {
582
+	struct net_device *netdev;
583
+	struct myson_nic *myson;
584
+	union myson_physical_address mac;
585
+	int rc;
586
+
587
+	/* Allocate and initialise net device */
588
+	netdev = alloc_etherdev ( sizeof ( *myson ) );
589
+	if ( ! netdev ) {
590
+		rc = -ENOMEM;
591
+		goto err_alloc;
592
+	}
593
+	netdev_init ( netdev, &myson_operations );
594
+	myson = netdev->priv;
595
+	pci_set_drvdata ( pci, netdev );
596
+	netdev->dev = &pci->dev;
597
+	memset ( myson, 0, sizeof ( *myson ) );
598
+	myson_init_ring ( &myson->tx, MYSON_NUM_TX_DESC, MYSON_TXLBA );
599
+	myson_init_ring ( &myson->rx, MYSON_NUM_RX_DESC, MYSON_RXLBA );
600
+
601
+	/* Fix up PCI device */
602
+	adjust_pci_device ( pci );
603
+
604
+	/* Map registers */
605
+	myson->regs = ioremap ( pci->membase, MYSON_BAR_SIZE );
606
+
607
+	/* Reset the NIC */
608
+	if ( ( rc = myson_reset ( myson ) ) != 0 )
609
+		goto err_reset;
610
+
611
+	/* Read MAC address */
612
+	mac.reg.low = cpu_to_le32 ( readl ( myson->regs + MYSON_PAR0 ) );
613
+	mac.reg.high = cpu_to_le32 ( readl ( myson->regs + MYSON_PAR4 ) );
614
+	memcpy ( netdev->hw_addr, mac.raw, ETH_ALEN );
615
+
616
+	/* Register network device */
617
+	if ( ( rc = register_netdev ( netdev ) ) != 0 )
618
+		goto err_register_netdev;
619
+
620
+	/* Mark as link up; we don't yet handle link state */
621
+	netdev_link_up ( netdev );
622
+
623
+	return 0;
624
+
625
+	unregister_netdev ( netdev );
626
+ err_register_netdev:
627
+	myson_reset ( myson );
628
+ err_reset:
629
+	netdev_nullify ( netdev );
630
+	netdev_put ( netdev );
631
+ err_alloc:
632
+	return rc;
633
+}
634
+
635
+/**
636
+ * Remove PCI device
637
+ *
638
+ * @v pci		PCI device
639
+ */
640
+static void myson_remove ( struct pci_device *pci ) {
641
+	struct net_device *netdev = pci_get_drvdata ( pci );
642
+	struct myson_nic *myson = netdev->priv;
643
+
644
+	/* Unregister network device */
645
+	unregister_netdev ( netdev );
646
+
647
+	/* Reset card */
648
+	myson_reset ( myson );
649
+
650
+	/* Free network device */
651
+	netdev_nullify ( netdev );
652
+	netdev_put ( netdev );
653
+}
654
+
655
+/** Myson PCI device IDs */
656
+static struct pci_device_id myson_nics[] = {
657
+        PCI_ROM ( 0x1516, 0x0800, "mtd800", "MTD-8xx", 0 ),
658
+        PCI_ROM ( 0x1516, 0x0803, "mtd803", "Surecom EP-320X-S", 0 ),
659
+        PCI_ROM ( 0x1516, 0x0891, "mtd891", "MTD-8xx", 0 ),
660
+};
661
+
662
+/** Myson PCI driver */
663
+struct pci_driver myson_driver __pci_driver = {
664
+	.ids = myson_nics,
665
+	.id_count = ( sizeof ( myson_nics ) / sizeof ( myson_nics[0] ) ),
666
+	.probe = myson_probe,
667
+	.remove = myson_remove,
668
+};

+ 200
- 0
src/drivers/net/myson.h View File

@@ -0,0 +1,200 @@
1
+#ifndef _MYSON_H
2
+#define _MYSON_H
3
+
4
+/** @file
5
+ *
6
+ * Myson Technology network card driver
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <stdint.h>
13
+#include <ipxe/if_ether.h>
14
+
15
+/** BAR size */
16
+#define MYSON_BAR_SIZE 256
17
+
18
+/** A packet descriptor */
19
+struct myson_descriptor {
20
+	/** Status */
21
+	uint32_t status;
22
+	/** Control */
23
+	uint32_t control;
24
+	/** Buffer start address */
25
+	uint32_t address;
26
+	/** Next descriptor address */
27
+	uint32_t next;
28
+} __attribute__ (( packed ));
29
+
30
+/* Transmit status */
31
+#define MYSON_TX_STAT_OWN	0x80000000UL	/**< Owner */
32
+#define MYSON_TX_STAT_ABORT	0x00002000UL	/**< Abort */
33
+#define MYSON_TX_STAT_CSL	0x00001000UL	/**< Carrier sense lost */
34
+
35
+/* Transmit control */
36
+#define MYSON_TX_CTRL_IC	0x80000000UL	/**< Interrupt control */
37
+#define MYSON_TX_CTRL_LD	0x20000000UL	/**< Last descriptor */
38
+#define MYSON_TX_CTRL_FD	0x10000000UL	/**< First descriptor */
39
+#define MYSON_TX_CTRL_CRC	0x08000000UL	/**< CRC append */
40
+#define MYSON_TX_CTRL_PAD	0x04000000UL	/**< Pad control */
41
+#define MYSON_TX_CTRL_RTLC	0x02000000UL	/**< Retry late collision */
42
+#define MYSON_TX_CTRL_PKTS(x)	( (x) << 11 )	/**< Packet size */
43
+#define MYSON_TX_CTRL_TBS(x)	( (x) << 0 )	/**< Transmit buffer size */
44
+
45
+/* Receive status */
46
+#define MYSON_RX_STAT_OWN	0x80000000UL	/**< Owner */
47
+#define MYSON_RX_STAT_FLNG(status) ( ( (status) >> 16 ) & 0xfff )
48
+#define MYSON_RX_STAT_ES	0x00000080UL	/**< Error summary */
49
+
50
+/* Receive control */
51
+#define MYSON_RX_CTRL_RBS(x)	( (x) << 0 )	/**< Receive buffer size */
52
+
53
+/** Descriptor ring alignment */
54
+#define MYSON_RING_ALIGN 4
55
+
56
+/** Physical Address Register 0 */
57
+#define MYSON_PAR0 0x00
58
+
59
+/** Physical Address Register 4 */
60
+#define MYSON_PAR4 0x04
61
+
62
+/** Physical address */
63
+union myson_physical_address {
64
+	struct {
65
+		uint32_t low;
66
+		uint32_t high;
67
+	} __attribute__ (( packed )) reg;
68
+	uint8_t raw[ETH_ALEN];
69
+};
70
+
71
+/** Transmit and Receive Configuration Register */
72
+#define MYSON_TCR_RCR 0x18
73
+#define MYSON_TCR_TXS		0x80000000UL	/**< Transmit status */
74
+#define MYSON_TCR_TE		0x00040000UL	/**< Transmit enable */
75
+#define MYSON_RCR_RXS		0x00008000UL	/**< Receive status */
76
+#define MYSON_RCR_PROM		0x00000080UL	/**< Promiscuous mode */
77
+#define MYSON_RCR_AB		0x00000040UL	/**< Accept broadcast */
78
+#define MYSON_RCR_AM		0x00000020UL	/**< Accept multicast */
79
+#define MYSON_RCR_ARP		0x00000008UL	/**< Accept runt packet */
80
+#define MYSON_RCR_ALP		0x00000004UL	/**< Accept long packet */
81
+#define MYSON_RCR_RE		0x00000001UL	/**< Receive enable */
82
+
83
+/** Maximum time to wait for transmit and receive to be idle, in milliseconds */
84
+#define MYSON_IDLE_MAX_WAIT_MS 100
85
+
86
+/** Bus Command Register */
87
+#define MYSON_BCR 0x1c
88
+#define MYSON_BCR_RLE		0x00000100UL	/**< Read line enable */
89
+#define MYSON_BCR_RME		0x00000080UL	/**< Read multiple enable */
90
+#define MYSON_BCR_WIE		0x00000040UL	/**< Write and invalidate */
91
+#define MYSON_BCR_PBL(x)	( (x) << 3 )	/**< Burst length */
92
+#define MYSON_BCR_PBL_MASK	MYSON_BCR_PBL ( 0x7 )
93
+#define MYSON_BCR_PBL_DEFAULT	MYSON_BCR_PBL ( 0x6 )
94
+#define MYSON_BCR_SWR		0x00000001UL	/**< Software reset */
95
+
96
+/** Maximum time to wait for a reset, in milliseconds */
97
+#define MYSON_RESET_MAX_WAIT_MS 100
98
+
99
+/** Transmit Poll Demand Register */
100
+#define MYSON_TXPDR 0x20
101
+
102
+/** Receive Poll Demand Register */
103
+#define MYSON_RXPDR 0x24
104
+
105
+/** Transmit List Base Address */
106
+#define MYSON_TXLBA 0x2c
107
+
108
+/** Number of transmit descriptors */
109
+#define MYSON_NUM_TX_DESC 4
110
+
111
+/** Receive List Base Address */
112
+#define MYSON_RXLBA 0x30
113
+
114
+/** Number of receive descriptors */
115
+#define MYSON_NUM_RX_DESC 4
116
+
117
+/** Receive buffer length */
118
+#define MYSON_RX_MAX_LEN ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ )
119
+
120
+/** Interrupt Status Register */
121
+#define MYSON_ISR 0x34
122
+#define MYSON_IRQ_TI		0x00000008UL	/**< Transmit interrupt */
123
+#define MYSON_IRQ_RI		0x00000004UL	/**< Receive interrupt */
124
+
125
+/** Number of I/O delays between ISR reads */
126
+#define MYSON_ISR_IODELAY_COUNT 4
127
+
128
+/** Interrupt Mask Register */
129
+#define MYSON_IMR 0x38
130
+
131
+/** Boot ROM / EEPROM / MII Management Register */
132
+#define MYSON_ROM_MII 0x40
133
+#define MYSON_ROM_AUTOLD	0x00100000UL	/**< Auto load */
134
+
135
+/** Maximum time to wait for a configuration reload, in milliseconds */
136
+#define MYSON_AUTOLD_MAX_WAIT_MS 100
137
+
138
+/** A Myson descriptor ring */
139
+struct myson_ring {
140
+	/** Descriptors */
141
+	struct myson_descriptor *desc;
142
+	/** Producer index */
143
+	unsigned int prod;
144
+	/** Consumer index */
145
+	unsigned int cons;
146
+
147
+	/** Number of descriptors */
148
+	unsigned int count;
149
+	/** Descriptor start address register */
150
+	unsigned int reg;
151
+};
152
+
153
+/**
154
+ * Initialise descriptor ring
155
+ *
156
+ * @v ring		Descriptor ring
157
+ * @v count		Number of descriptors
158
+ * @v reg		Descriptor base address register
159
+ */
160
+static inline __attribute__ (( always_inline)) void
161
+myson_init_ring ( struct myson_ring *ring, unsigned int count,
162
+		  unsigned int reg ) {
163
+	ring->count = count;
164
+	ring->reg = reg;
165
+}
166
+
167
+/** A myson network card */
168
+struct myson_nic {
169
+	/** Registers */
170
+	void *regs;
171
+
172
+	/** Transmit descriptor ring */
173
+	struct myson_ring tx;
174
+	/** Receive descriptor ring */
175
+	struct myson_ring rx;
176
+	/** Receive I/O buffers */
177
+	struct io_buffer *rx_iobuf[MYSON_NUM_RX_DESC];
178
+};
179
+
180
+/**
181
+ * Check if card can access physical address
182
+ *
183
+ * @v address		Physical address
184
+ * @v address_ok	Card can access physical address
185
+ */
186
+static inline __attribute__ (( always_inline )) int
187
+myson_address_ok ( physaddr_t address ) {
188
+
189
+	/* In a 32-bit build, all addresses can be accessed */
190
+	if ( sizeof ( physaddr_t ) <= sizeof ( uint32_t ) )
191
+		return 1;
192
+
193
+	/* Card can access all addresses below 4GB */
194
+	if ( ( address & ~0xffffffffULL ) == 0 )
195
+		return 1;
196
+
197
+	return 0;
198
+}
199
+
200
+#endif /* _MYSON_H */

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

@@ -145,6 +145,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
145 145
 #define ERRFILE_realtek		     ( ERRFILE_DRIVER | 0x00630000 )
146 146
 #define ERRFILE_skeleton	     ( ERRFILE_DRIVER | 0x00640000 )
147 147
 #define ERRFILE_intel		     ( ERRFILE_DRIVER | 0x00650000 )
148
+#define ERRFILE_myson		     ( ERRFILE_DRIVER | 0x00660000 )
148 149
 
149 150
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
150 151
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )

Loading…
Cancel
Save