Bläddra i källkod

[b44] Add driver for Broadcom bcm44xx cards

This driver is based on Stefan Hajnoczi's summer work, which
is in turn based on version 1.01 of the linux b44 driver.
I just assembled the pieces and fixed/added a few pieces
here and there to make it work for my hardware.

The most major limitation is that this driver won't work
on systems with >1GB RAM due to the card not having enough
address bits for that and gPXE not working around this
limitation.

Still, other than that the driver works well enough for
at least 2 users :) and the above limitation can always
be fixed when somebody wants it bad enough :)

Signed-off-by: Pantelis Koukousoulas <pktoss@gmail.com>
tags/v0.9.6
Pantelis Koukousoulas 16 år sedan
förälder
incheckning
7166bc7b2d
3 ändrade filer med 1417 tillägg och 0 borttagningar
  1. 949
    0
      src/drivers/net/b44.c
  2. 467
    0
      src/drivers/net/b44.h
  3. 1
    0
      src/include/gpxe/errfile.h

+ 949
- 0
src/drivers/net/b44.c Visa fil

@@ -0,0 +1,949 @@
1
+/*
2
+ * Copyright (c) 2008 Stefan Hajnoczi <stefanha@gmail.com>
3
+ * Copyright (c) 2008 Pantelis Koukousoulas <pktoss@gmail.com>
4
+ *
5
+ * This program is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU General Public License as
7
+ * published by the Free Software Foundation; either version 2 of the
8
+ * License, or any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful, but
11
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program; if not, write to the Free Software
17
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
+ *
19
+ * This driver is a port of the b44 linux driver version 1.01
20
+ *
21
+ * Copyright (c) 2002 David S. Miller <davem@redhat.com>
22
+ * Copyright (c) Pekka Pietikainen <pp@ee.oulu.fi>
23
+ * Copyright (C) 2006 Broadcom Corporation.
24
+ *
25
+ * Some ssb bits copied from version 2.0 of the b44 driver
26
+ * Copyright (c) Michael Buesch
27
+ *
28
+ * Copyright (c) a lot of people too. Please respect their work.
29
+ */
30
+
31
+#include <errno.h>
32
+#include <assert.h>
33
+#include <stdio.h>
34
+#include <unistd.h>
35
+#include <byteswap.h>
36
+#include <gpxe/io.h>
37
+#include <mii.h>
38
+#include <gpxe/iobuf.h>
39
+#include <gpxe/malloc.h>
40
+#include <gpxe/pci.h>
41
+#include <gpxe/netdevice.h>
42
+#include <gpxe/ethernet.h>
43
+#include <gpxe/if_ether.h>
44
+#include <gpxe/memmap.h>
45
+#include "b44.h"
46
+
47
+
48
+static inline int ring_next(int index)
49
+{
50
+	/* B44_RING_SIZE is a power of 2 :) */
51
+	return (index + 1) & (B44_RING_SIZE - 1);
52
+}
53
+
54
+
55
+/* Memory-mapped I/O wrappers */
56
+
57
+static inline u32 br32(const struct b44_private *bp, u32 reg)
58
+{
59
+	return readl(bp->regs + reg);
60
+}
61
+
62
+
63
+static inline void bw32(const struct b44_private *bp, u32 reg, u32 val)
64
+{
65
+	writel(val, bp->regs + reg);
66
+}
67
+
68
+
69
+static inline void bflush(const struct b44_private *bp, u32 reg, u32 timeout)
70
+{
71
+	readl(bp->regs + reg);
72
+	udelay(timeout);
73
+}
74
+
75
+
76
+#define VIRT_TO_B44(addr)	( virt_to_bus(addr) + SB_PCI_DMA )
77
+
78
+
79
+/**
80
+ * Return non-zero if the installed RAM is within
81
+ * the limit given and zero if it is outside.
82
+ * Hopefully will be removed soon.
83
+ */
84
+int phys_ram_within_limit(u64 limit)
85
+{
86
+	struct memory_map memmap;
87
+	struct memory_region *highest = NULL;
88
+	get_memmap(&memmap);
89
+
90
+	highest = &memmap.regions[memmap.count - 1];
91
+
92
+	return (highest->end < limit);
93
+}
94
+
95
+
96
+/**
97
+ * Ring cells waiting to be processed are between 'tx_cur' and 'pending'
98
+ * indexes in the ring.
99
+ */
100
+static u32 pending_tx_index(struct b44_private *bp)
101
+{
102
+	u32 pending = br32(bp, B44_DMATX_STAT);
103
+	pending &= DMATX_STAT_CDMASK;
104
+
105
+	pending /= sizeof(struct dma_desc);
106
+	return pending & (B44_RING_SIZE - 1);
107
+}
108
+
109
+
110
+/**
111
+ * Ring cells waiting to be processed are between 'rx_cur' and 'pending'
112
+ * indexes in the ring.
113
+ */
114
+static u32 pending_rx_index(struct b44_private *bp)
115
+{
116
+	u32 pending = br32(bp, B44_DMARX_STAT);
117
+	pending &= DMARX_STAT_CDMASK;
118
+
119
+	pending /= sizeof(struct dma_desc);
120
+	return pending & (B44_RING_SIZE - 1);
121
+}
122
+
123
+
124
+/**
125
+ * Wait until the given bit is set/cleared.
126
+ */
127
+static int b44_wait_bit(struct b44_private *bp, unsigned long reg, u32 bit,
128
+			            unsigned long timeout, const int clear)
129
+{
130
+	unsigned long i;
131
+
132
+	for (i = 0; i < timeout; i++) {
133
+		u32 val = br32(bp, reg);
134
+
135
+		if (clear && !(val & bit))
136
+			break;
137
+
138
+		if (!clear && (val & bit))
139
+			break;
140
+
141
+		udelay(10);
142
+	}
143
+	if (i == timeout) {
144
+		return -ENODEV;
145
+	}
146
+	return 0;
147
+}
148
+
149
+
150
+/*
151
+ * Sonics Silicon Backplane support. SSB is a mini-bus interconnecting
152
+ * so-called IP Cores. One of those cores implements the Fast Ethernet
153
+ * functionality and another one the PCI engine.
154
+ *
155
+ * You need to switch to the core you want to talk to before actually
156
+ * sending commands.
157
+ *
158
+ * See: http://bcm-v4.sipsolutions.net/Backplane for (reverse-engineered)
159
+ * specs.
160
+ */
161
+
162
+static inline u32 ssb_get_core_rev(struct b44_private *bp)
163
+{
164
+	return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
165
+}
166
+
167
+
168
+static inline int ssb_is_core_up(struct b44_private *bp)
169
+{
170
+	return ((br32(bp, B44_SBTMSLOW) & (SSB_CORE_DOWN | SBTMSLOW_CLOCK))
171
+	                                                == SBTMSLOW_CLOCK);
172
+}
173
+
174
+
175
+static u32 ssb_pci_setup(struct b44_private *bp, u32 cores)
176
+{
177
+	u32 bar_orig, pci_rev, val;
178
+
179
+	pci_read_config_dword(bp->pci, SSB_BAR0_WIN, &bar_orig);
180
+	pci_write_config_dword(bp->pci, SSB_BAR0_WIN,
181
+	                       BCM4400_PCI_CORE_ADDR);
182
+	pci_rev = ssb_get_core_rev(bp);
183
+
184
+	val = br32(bp, B44_SBINTVEC);
185
+	val |= cores;
186
+	bw32(bp, B44_SBINTVEC, val);
187
+
188
+	val = br32(bp, SSB_PCI_TRANS_2);
189
+	val |= SSB_PCI_PREF | SSB_PCI_BURST;
190
+	bw32(bp, SSB_PCI_TRANS_2, val);
191
+
192
+	pci_write_config_dword(bp->pci, SSB_BAR0_WIN, bar_orig);
193
+
194
+	return pci_rev;
195
+}
196
+
197
+
198
+static void ssb_core_disable(struct b44_private *bp)
199
+{
200
+	if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET)
201
+		return;
202
+
203
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
204
+	b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0);
205
+	b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1);
206
+
207
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
208
+	                                        SSB_CORE_DOWN));
209
+	bflush(bp, B44_SBTMSLOW, 1);
210
+
211
+	bw32(bp, B44_SBTMSLOW, SSB_CORE_DOWN);
212
+	bflush(bp, B44_SBTMSLOW, 1);
213
+}
214
+
215
+
216
+static void ssb_core_reset(struct b44_private *bp)
217
+{
218
+	u32 val;
219
+	const u32 mask = (SBTMSLOW_CLOCK | SBTMSLOW_FGC | SBTMSLOW_RESET);
220
+
221
+	ssb_core_disable(bp);
222
+
223
+	bw32(bp, B44_SBTMSLOW, mask);
224
+	bflush(bp, B44_SBTMSLOW, 1);
225
+
226
+	/* Clear SERR if set, this is a hw bug workaround.  */
227
+	if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR)
228
+		bw32(bp, B44_SBTMSHIGH, 0);
229
+
230
+	val = br32(bp, B44_SBIMSTATE);
231
+	if (val & (SBIMSTATE_BAD)) {
232
+		bw32(bp, B44_SBIMSTATE, val & ~SBIMSTATE_BAD);
233
+	}
234
+
235
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
236
+	bflush(bp, B44_SBTMSLOW, 1);
237
+
238
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK));
239
+	bflush(bp, B44_SBTMSLOW, 1);
240
+}
241
+
242
+
243
+/*
244
+ * Driver helper functions
245
+ */
246
+
247
+/*
248
+ * Chip reset provides power to the b44 MAC & PCI cores, which
249
+ * is necessary for MAC register access. We only do a partial
250
+ * reset in case of transmit/receive errors (ISTAT_ERRORS) to
251
+ * avoid the chip being hung for an unnecessary long time in
252
+ * this case.
253
+ *
254
+ * Called-by: b44_close, b44_halt, b44_inithw(b44_open), b44_probe
255
+ */
256
+static void b44_chip_reset(struct b44_private *bp, int reset_kind)
257
+{
258
+	if (ssb_is_core_up(bp)) {
259
+		bw32(bp, B44_RCV_LAZY, 0);
260
+
261
+		bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
262
+
263
+		b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
264
+
265
+		bw32(bp, B44_DMATX_CTRL, 0);
266
+
267
+		bp->tx_dirty = bp->tx_cur = 0;
268
+
269
+		if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK)
270
+			b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
271
+			                                          100, 0);
272
+
273
+		bw32(bp, B44_DMARX_CTRL, 0);
274
+
275
+		bp->rx_cur = 0;
276
+	} else {
277
+		ssb_pci_setup(bp, SBINTVEC_ENET0);
278
+	}
279
+
280
+	ssb_core_reset(bp);
281
+
282
+	/* Don't enable PHY if we are only doing a partial reset. */
283
+	if (reset_kind == B44_CHIP_RESET_PARTIAL)
284
+		return;
285
+
286
+	/* Make PHY accessible. */
287
+	bw32(bp, B44_MDIO_CTRL,
288
+	     (MDIO_CTRL_PREAMBLE | (0x0d & MDIO_CTRL_MAXF_MASK)));
289
+	bflush(bp, B44_MDIO_CTRL, 1);
290
+
291
+	/* Enable internal or external PHY */
292
+	if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
293
+		bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
294
+		bflush(bp, B44_ENET_CTRL, 1);
295
+	} else {
296
+		u32 val = br32(bp, B44_DEVCTRL);
297
+		if (val & DEVCTRL_EPR) {
298
+			bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
299
+			bflush(bp, B44_DEVCTRL, 100);
300
+		}
301
+	}
302
+}
303
+
304
+
305
+/**
306
+ * called by b44_poll in the error path
307
+ */
308
+static void b44_halt(struct b44_private *bp)
309
+{
310
+	/* disable ints */
311
+	bw32(bp, B44_IMASK, 0);
312
+	bflush(bp, B44_IMASK, 1);
313
+
314
+	DBG("b44: powering down PHY\n");
315
+	bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);
316
+
317
+	/*
318
+	 * Now reset the chip, but without enabling
319
+	 * the MAC&PHY part of it.
320
+	 * This has to be done _after_ we shut down the PHY
321
+	 */
322
+	b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
323
+}
324
+
325
+
326
+
327
+/*
328
+ * Called at device open time to get the chip ready for
329
+ * packet processing.
330
+ *
331
+ * Called-by: b44_open
332
+ */
333
+static void b44_init_hw(struct b44_private *bp, int reset_kind)
334
+{
335
+	u32 val;
336
+#define CTRL_MASK (DMARX_CTRL_ENABLE | (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))
337
+
338
+	b44_chip_reset(bp, B44_CHIP_RESET_FULL);
339
+	if (reset_kind == B44_FULL_RESET) {
340
+		b44_phy_reset(bp);
341
+	}
342
+
343
+	/* Enable CRC32, set proper LED modes and power on PHY */
344
+	bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
345
+	bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
346
+
347
+	/* This sets the MAC address too.  */
348
+	b44_set_rx_mode(bp->netdev);
349
+
350
+	/* MTU + eth header + possible VLAN tag + struct rx_header */
351
+	bw32(bp, B44_RXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
352
+	bw32(bp, B44_TXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
353
+
354
+	bw32(bp, B44_TX_HIWMARK, TX_HIWMARK_DEFLT);
355
+	if (reset_kind == B44_PARTIAL_RESET) {
356
+		bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
357
+	} else {
358
+		bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
359
+		bw32(bp, B44_DMATX_ADDR, VIRT_TO_B44(bp->tx));
360
+
361
+		bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
362
+		bw32(bp, B44_DMARX_ADDR, VIRT_TO_B44(bp->rx));
363
+		bw32(bp, B44_DMARX_PTR, B44_RX_RING_LEN_BYTES);
364
+
365
+		bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
366
+	}
367
+
368
+	val = br32(bp, B44_ENET_CTRL);
369
+	bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
370
+#undef CTRL_MASK
371
+}
372
+
373
+
374
+/***  Management of ring descriptors  ***/
375
+
376
+
377
+static void b44_populate_rx_descriptor(struct b44_private *bp, u32 idx)
378
+{
379
+	struct rx_header *rh;
380
+	u32 ctrl, addr;
381
+
382
+	rh = bp->rx_iobuf[idx]->data;
383
+	rh->len = 0;
384
+	rh->flags = 0;
385
+	ctrl = DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET);
386
+	if (idx == B44_RING_LAST) {
387
+		ctrl |= DESC_CTRL_EOT;
388
+	}
389
+	addr = VIRT_TO_B44(bp->rx_iobuf[idx]->data);
390
+
391
+	bp->rx[idx].ctrl = cpu_to_le32(ctrl);
392
+	bp->rx[idx].addr = cpu_to_le32(addr);
393
+	bw32(bp, B44_DMARX_PTR, idx * sizeof(struct dma_desc));
394
+}
395
+
396
+
397
+/*
398
+ * Refill RX ring descriptors with buffers. This is needed
399
+ * because during rx we are passing ownership of descriptor
400
+ * buffers to the network stack.
401
+ */
402
+static void b44_rx_refill(struct b44_private *bp, u32 pending)
403
+{
404
+	u32 i;
405
+
406
+	// skip pending
407
+	for (i = pending + 1; i != bp->rx_cur; i = ring_next(i)) {
408
+		if (bp->rx_iobuf[i] != NULL)
409
+			continue;
410
+
411
+		bp->rx_iobuf[i] = alloc_iob(RX_PKT_BUF_SZ);
412
+		if (!bp->rx_iobuf[i]) {
413
+			DBG("Refill rx ring failed!!\n");
414
+			break;
415
+		}
416
+
417
+		b44_populate_rx_descriptor(bp, i);
418
+	}
419
+}
420
+
421
+
422
+static void b44_free_rx_ring(struct b44_private *bp)
423
+{
424
+	u32 i;
425
+
426
+	if (bp->rx) {
427
+		for (i = 0; i < B44_RING_SIZE; i++) {
428
+			free_iob(bp->rx_iobuf[i]);
429
+			bp->rx_iobuf[i] = NULL;
430
+		}
431
+		free_dma(bp->rx, B44_RX_RING_LEN_BYTES);
432
+		bp->rx = NULL;
433
+	}
434
+}
435
+
436
+
437
+static int b44_init_rx_ring(struct b44_private *bp)
438
+{
439
+	b44_free_rx_ring(bp);
440
+
441
+	bp->rx = malloc_dma(B44_RX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
442
+	if (!bp->rx)
443
+		return -ENOMEM;
444
+
445
+	memset(bp->rx_iobuf, 0, sizeof(bp->rx_iobuf));
446
+
447
+	bp->rx_iobuf[0] = alloc_iob(RX_PKT_BUF_SZ);
448
+	b44_populate_rx_descriptor(bp, 0);
449
+	b44_rx_refill(bp, 0);
450
+
451
+	DBG("Init RX rings: rx=0x%08lx\n", VIRT_TO_B44(bp->rx));
452
+	return 0;
453
+}
454
+
455
+
456
+static void b44_free_tx_ring(struct b44_private *bp)
457
+{
458
+	if (bp->tx) {
459
+		free_dma(bp->tx, B44_TX_RING_LEN_BYTES);
460
+		bp->tx = NULL;
461
+	}
462
+}
463
+
464
+
465
+static int b44_init_tx_ring(struct b44_private *bp)
466
+{
467
+	b44_free_tx_ring(bp);
468
+
469
+	bp->tx = malloc_dma(B44_TX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
470
+	if (!bp->tx)
471
+		return -ENOMEM;
472
+
473
+	memset(bp->tx, 0, B44_TX_RING_LEN_BYTES);
474
+	memset(bp->tx_iobuf, 0, sizeof(bp->tx_iobuf));
475
+
476
+	DBG("Init TX rings: tx=0x%08lx\n", VIRT_TO_B44(bp->tx));
477
+	return 0;
478
+}
479
+
480
+
481
+/*** Interaction with the PHY ***/
482
+
483
+
484
+static int b44_phy_read(struct b44_private *bp, int reg, u32 * val)
485
+{
486
+	int err;
487
+
488
+	u32 arg1 = (MDIO_OP_READ << MDIO_DATA_OP_SHIFT);
489
+	u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
490
+	u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
491
+	u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
492
+	u32 argv = arg1 | arg2 | arg3 | arg4;
493
+
494
+	bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
495
+	bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
496
+	err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
497
+	*val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;
498
+
499
+	return err;
500
+}
501
+
502
+
503
+static int b44_phy_write(struct b44_private *bp, int reg, u32 val)
504
+{
505
+	u32 arg1 = (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT);
506
+	u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
507
+	u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
508
+	u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
509
+	u32 arg5 = (val & MDIO_DATA_DATA);
510
+	u32 argv = arg1 | arg2 | arg3 | arg4 | arg5;
511
+
512
+
513
+	bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
514
+	bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
515
+	return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
516
+}
517
+
518
+
519
+static int b44_phy_reset(struct b44_private *bp)
520
+{
521
+	u32 val;
522
+	int err;
523
+
524
+	err = b44_phy_write(bp, MII_BMCR, BMCR_RESET);
525
+	if (err)
526
+		return err;
527
+
528
+	udelay(100);
529
+	err = b44_phy_read(bp, MII_BMCR, &val);
530
+	if (!err) {
531
+		if (val & BMCR_RESET) {
532
+			return -ENODEV;
533
+		}
534
+	}
535
+
536
+	return 0;
537
+}
538
+
539
+
540
+/*
541
+ * The BCM44xx CAM (Content Addressable Memory) stores the MAC
542
+ * and PHY address.
543
+ */
544
+static void b44_cam_write(struct b44_private *bp, unsigned char *data,
545
+			                                    int index)
546
+{
547
+	u32 val;
548
+
549
+	val  = ((u32) data[2]) << 24;
550
+	val |= ((u32) data[3]) << 16;
551
+	val |= ((u32) data[4]) << 8;
552
+	val |= ((u32) data[5]) << 0;
553
+	bw32(bp, B44_CAM_DATA_LO, val);
554
+
555
+
556
+	val = (CAM_DATA_HI_VALID |
557
+	       (((u32) data[0]) << 8) | (((u32) data[1]) << 0));
558
+
559
+	bw32(bp, B44_CAM_DATA_HI, val);
560
+
561
+	val = CAM_CTRL_WRITE | (index << CAM_CTRL_INDEX_SHIFT);
562
+	bw32(bp, B44_CAM_CTRL, val);
563
+
564
+	b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
565
+}
566
+
567
+
568
+static void b44_set_mac_addr(struct b44_private *bp)
569
+{
570
+	u32 val;
571
+	bw32(bp, B44_CAM_CTRL, 0);
572
+	b44_cam_write(bp, bp->netdev->ll_addr, 0);
573
+	val = br32(bp, B44_CAM_CTRL);
574
+	bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
575
+}
576
+
577
+
578
+/* Read 128-bytes of EEPROM. */
579
+static void b44_read_eeprom(struct b44_private *bp, u8 * data)
580
+{
581
+	long i;
582
+	u16 *ptr = (u16 *) data;
583
+
584
+	for (i = 0; i < 128; i += 2)
585
+		ptr[i / 2] = cpu_to_le16(readw(bp->regs + 4096 + i));
586
+}
587
+
588
+
589
+static void b44_load_mac_and_phy_addr(struct b44_private *bp)
590
+{
591
+	u8 eeprom[128];
592
+
593
+	/* Load MAC address, note byteswapping */
594
+	b44_read_eeprom(bp, &eeprom[0]);
595
+	bp->netdev->ll_addr[0] = eeprom[79];
596
+	bp->netdev->ll_addr[1] = eeprom[78];
597
+	bp->netdev->ll_addr[2] = eeprom[81];
598
+	bp->netdev->ll_addr[3] = eeprom[80];
599
+	bp->netdev->ll_addr[4] = eeprom[83];
600
+	bp->netdev->ll_addr[5] = eeprom[82];
601
+
602
+	/* Load PHY address */
603
+	bp->phy_addr = eeprom[90] & 0x1f;
604
+}
605
+
606
+
607
+static void b44_set_rx_mode(struct net_device *netdev)
608
+{
609
+	struct b44_private *bp = netdev_priv(netdev);
610
+	unsigned char zero[6] = { 0, 0, 0, 0, 0, 0 };
611
+	u32 val;
612
+	int i;
613
+
614
+	val = br32(bp, B44_RXCONFIG);
615
+	val &= ~RXCONFIG_PROMISC;
616
+	val |= RXCONFIG_ALLMULTI;
617
+
618
+	b44_set_mac_addr(bp);
619
+
620
+	for (i = 1; i < 64; i++)
621
+		b44_cam_write(bp, zero, i);
622
+
623
+	bw32(bp, B44_RXCONFIG, val);
624
+	val = br32(bp, B44_CAM_CTRL);
625
+	bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
626
+}
627
+
628
+
629
+/*** Implementation of gPXE driver callbacks ***/
630
+
631
+/**
632
+ * Probe device
633
+ *
634
+ * @v pci	PCI device
635
+ * @v id	Matching entry in ID table
636
+ * @ret rc	Return status code
637
+ */
638
+static int b44_probe(struct pci_device *pci, const struct pci_device_id *id)
639
+{
640
+	struct net_device *netdev;
641
+	struct b44_private *bp;
642
+	int rc;
643
+
644
+	/*
645
+	 * Bail out if more than 1GB of physical RAM is installed.
646
+	 * This limitation will be removed later when dma mapping
647
+	 * is merged into mainline.
648
+	 */
649
+	if (!phys_ram_within_limit(B44_30BIT_DMA_MASK)) {
650
+		DBG("Sorry, this version of the driver does not\n"
651
+		    "support systems with more than 1GB of RAM.\n");
652
+		return -ENOMEM;
653
+	}
654
+
655
+	/* Set up netdev */
656
+	netdev = alloc_etherdev(sizeof(*bp));
657
+	if (!netdev)
658
+		return -ENOMEM;
659
+
660
+	netdev_init(netdev, &b44_operations);
661
+	pci_set_drvdata(pci, netdev);
662
+	netdev->dev = &pci->dev;
663
+
664
+	/* Set up private data */
665
+	bp = netdev_priv(netdev);
666
+	memset(bp, 0, sizeof(*bp));
667
+	bp->netdev = netdev;
668
+	bp->pci = pci;
669
+
670
+	/* Map device registers */
671
+	bp->regs = ioremap(pci->membase, B44_REGS_SIZE);
672
+	if (!bp->regs) {
673
+		netdev_put(netdev);
674
+		return -ENOMEM;
675
+	}
676
+
677
+	/* Enable PCI bus mastering */
678
+	adjust_pci_device(pci);
679
+
680
+	b44_load_mac_and_phy_addr(bp);
681
+
682
+	/* Link management currently not implemented */
683
+	netdev_link_up(netdev);
684
+
685
+	rc = register_netdev(netdev);
686
+	if (rc != 0) {
687
+		iounmap(bp->regs);
688
+		netdev_put(netdev);
689
+		return rc;
690
+	}
691
+
692
+	b44_chip_reset(bp, B44_CHIP_RESET_FULL);
693
+
694
+	DBG("b44 %s (%04x:%04x) regs=%p MAC=%s\n", id->name, id->vendor,
695
+	    id->device, bp->regs, eth_ntoa(netdev->ll_addr));
696
+
697
+	return 0;
698
+}
699
+
700
+
701
+/**
702
+ * Remove device
703
+ *
704
+ * @v pci	PCI device
705
+ */
706
+static void b44_remove(struct pci_device *pci)
707
+{
708
+	struct net_device *netdev = pci_get_drvdata(pci);
709
+	struct b44_private *bp = netdev_priv(netdev);
710
+
711
+	ssb_core_disable(bp);
712
+	unregister_netdev(netdev);
713
+	iounmap(bp->regs);
714
+	netdev_nullify(netdev);
715
+	netdev_put(netdev);
716
+}
717
+
718
+
719
+/** Enable or disable interrupts
720
+ *
721
+ * @v netdev	Network device
722
+ * @v enable	Interrupts should be enabled
723
+ */
724
+static void b44_irq(struct net_device *netdev, int enable)
725
+{
726
+	struct b44_private *bp = netdev_priv(netdev);
727
+
728
+	/* Interrupt mask specifies which events generate interrupts */
729
+	bw32(bp, B44_IMASK, enable ? IMASK_DEF : IMASK_DISABLE);
730
+}
731
+
732
+
733
+/** Open network device
734
+ *
735
+ * @v netdev	Network device
736
+ * @ret rc	Return status code
737
+ */
738
+static int b44_open(struct net_device *netdev)
739
+{
740
+	struct b44_private *bp = netdev_priv(netdev);
741
+	int rc;
742
+
743
+	rc = b44_init_tx_ring(bp);
744
+	if (rc != 0)
745
+		return rc;
746
+
747
+	rc = b44_init_rx_ring(bp);
748
+	if (rc != 0)
749
+		return rc;
750
+
751
+	b44_init_hw(bp, B44_FULL_RESET);
752
+
753
+	/* Disable interrupts */
754
+	b44_irq(netdev, 0);
755
+
756
+	return 0;
757
+}
758
+
759
+
760
+/** Close network device
761
+ *
762
+ * @v netdev	Network device
763
+ */
764
+static void b44_close(struct net_device *netdev)
765
+{
766
+	struct b44_private *bp = netdev_priv(netdev);
767
+
768
+	b44_chip_reset(bp, B44_FULL_RESET);
769
+	b44_free_tx_ring(bp);
770
+	b44_free_rx_ring(bp);
771
+}
772
+
773
+
774
+/** Transmit packet
775
+ *
776
+ * @v netdev	Network device
777
+ * @v iobuf	I/O buffer
778
+ * @ret rc	Return status code
779
+ */
780
+static int b44_transmit(struct net_device *netdev, struct io_buffer *iobuf)
781
+{
782
+	struct b44_private *bp = netdev_priv(netdev);
783
+	u32 cur = bp->tx_cur;
784
+	u32 ctrl;
785
+
786
+	/* Check for TX ring overflow */
787
+	if (bp->tx[cur].ctrl) {
788
+		DBG("tx overflow\n");
789
+		return -ENOBUFS;
790
+	}
791
+
792
+	/* Will call netdev_tx_complete() on the iobuf later */
793
+	bp->tx_iobuf[cur] = iobuf;
794
+
795
+	/* Set up TX descriptor */
796
+	ctrl = (iob_len(iobuf) & DESC_CTRL_LEN) |
797
+	    DESC_CTRL_IOC | DESC_CTRL_SOF | DESC_CTRL_EOF;
798
+
799
+	if (cur == B44_RING_LAST)
800
+		ctrl |= DESC_CTRL_EOT;
801
+
802
+	bp->tx[cur].ctrl = cpu_to_le32(ctrl);
803
+	bp->tx[cur].addr = cpu_to_le32(VIRT_TO_B44(iobuf->data));
804
+
805
+	/* Update next available descriptor index */
806
+	cur = ring_next(cur);
807
+	bp->tx_cur = cur;
808
+	wmb();
809
+
810
+	/* Tell card that a new TX descriptor is ready */
811
+	bw32(bp, B44_DMATX_PTR, cur * sizeof(struct dma_desc));
812
+	return 0;
813
+}
814
+
815
+
816
+/** Recycles sent TX descriptors and notifies network stack
817
+ *
818
+ * @v bp Driver state
819
+ */
820
+static void b44_tx_complete(struct b44_private *bp)
821
+{
822
+	u32 cur, i;
823
+
824
+	cur = pending_tx_index(bp);
825
+
826
+	for (i = bp->tx_dirty; i != cur; i = ring_next(i)) {
827
+		/* Free finished frame */
828
+		netdev_tx_complete(bp->netdev, bp->tx_iobuf[i]);
829
+		bp->tx_iobuf[i] = NULL;
830
+
831
+		/* Clear TX descriptor */
832
+		bp->tx[i].ctrl = 0;
833
+		bp->tx[i].addr = 0;
834
+	}
835
+	bp->tx_dirty = cur;
836
+}
837
+
838
+
839
+static void b44_process_rx_packets(struct b44_private *bp)
840
+{
841
+	struct io_buffer *iob;	/* received data */
842
+	struct rx_header *rh;
843
+	u32 pending, i;
844
+	u16 len;
845
+
846
+	pending = pending_rx_index(bp);
847
+
848
+	for (i = bp->rx_cur; i != pending; i = ring_next(i)) {
849
+		iob = bp->rx_iobuf[i];
850
+		if (iob == NULL)
851
+			break;
852
+
853
+		rh = iob->data;
854
+		len = le16_to_cpu(rh->len);
855
+
856
+		/*
857
+		 * Guard against incompletely written RX descriptors.
858
+		 * Without this, things can get really slow!
859
+		 */
860
+		if (len == 0)
861
+			break;
862
+
863
+		/* Discard CRC that is generated by the card */
864
+		len -= 4;
865
+
866
+		/* Check for invalid packets and errors */
867
+		if (len > RX_PKT_BUF_SZ - RX_PKT_OFFSET ||
868
+		    (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
869
+			DBG("rx error len=%d flags=%04x\n", len,
870
+			                 cpu_to_le16(rh->flags));
871
+			rh->len = 0;
872
+			rh->flags = 0;
873
+			netdev_rx_err(bp->netdev, iob, -EINVAL);
874
+			continue;
875
+		}
876
+
877
+		/* Clear RX descriptor */
878
+		rh->len = 0;
879
+		rh->flags = 0;
880
+		bp->rx_iobuf[i] = NULL;
881
+
882
+		/* Hand off the IO buffer to the network stack */
883
+		iob_reserve(iob, RX_PKT_OFFSET);
884
+		iob_put(iob, len);
885
+		netdev_rx(bp->netdev, iob);
886
+	}
887
+	bp->rx_cur = i;
888
+	b44_rx_refill(bp, pending_rx_index(bp));
889
+}
890
+
891
+
892
+/** Poll for completed and received packets
893
+ *
894
+ * @v netdev	Network device
895
+ */
896
+static void b44_poll(struct net_device *netdev)
897
+{
898
+	struct b44_private *bp = netdev_priv(netdev);
899
+	u32 istat;
900
+
901
+	/* Interrupt status */
902
+	istat = br32(bp, B44_ISTAT);
903
+	istat &= IMASK_DEF;	/* only the events we care about */
904
+
905
+	if (!istat)
906
+		return;
907
+	if (istat & ISTAT_TX)
908
+		b44_tx_complete(bp);
909
+	if (istat & ISTAT_RX)
910
+		b44_process_rx_packets(bp);
911
+	if (istat & ISTAT_ERRORS) {
912
+		DBG("b44 error istat=0x%08x\n", istat);
913
+
914
+		/* Reset B44 core partially to avoid long waits */
915
+		b44_irq(bp->netdev, 0);
916
+		b44_halt(bp);
917
+		b44_init_tx_ring(bp);
918
+		b44_init_rx_ring(bp);
919
+		b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
920
+	}
921
+
922
+	/* Acknowledge interrupt */
923
+	bw32(bp, B44_ISTAT, 0);
924
+	bflush(bp, B44_ISTAT, 1);
925
+}
926
+
927
+
928
+static struct net_device_operations b44_operations = {
929
+	.open = b44_open,
930
+	.close = b44_close,
931
+	.transmit = b44_transmit,
932
+	.poll = b44_poll,
933
+	.irq = b44_irq,
934
+};
935
+
936
+
937
+static struct pci_device_id b44_nics[] = {
938
+	PCI_ROM(0x14e4, 0x4401, "BCM4401", "BCM4401"),
939
+	PCI_ROM(0x14e4, 0x170c, "BCM4401-B0", "BCM4401-B0"),
940
+	PCI_ROM(0x14e4, 0x4402, "BCM4401-B1", "BCM4401-B1"),
941
+};
942
+
943
+
944
+struct pci_driver b44_driver __pci_driver = {
945
+	.ids = b44_nics,
946
+	.id_count = sizeof b44_nics / sizeof b44_nics[0],
947
+	.probe = b44_probe,
948
+	.remove = b44_remove,
949
+};

+ 467
- 0
src/drivers/net/b44.h Visa fil

@@ -0,0 +1,467 @@
1
+/*
2
+ * Copyright (c) 2008 Stefan Hajnoczi <stefanha@gmail.com>
3
+ * Copyright (c) 2008 Pantelis Koukousoulas <pktoss@gmail.com>
4
+ *
5
+ * This program is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU General Public License as
7
+ * published by the Free Software Foundation; either version 2 of the
8
+ * License, or any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful, but
11
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program; if not, write to the Free Software
17
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
+ *
19
+ * This driver is a port of the b44 linux driver version 1.01
20
+ *
21
+ * Copyright (c) 2002 David S. Miller <davem@redhat.com>
22
+ * Copyright (c) Pekka Pietikainen <pp@ee.oulu.fi>
23
+ * Copyright (C) 2006 Broadcom Corporation.
24
+ *
25
+ * Some ssb bits copied from version 2.0 of the b44 driver
26
+ * Copyright (c) Michael Buesch
27
+ *
28
+ * Copyright (c) a lot of people too. Please respect their work.
29
+ */
30
+#ifndef _B44_H
31
+#define _B44_H
32
+
33
+/* BCM44xx Register layout */
34
+#define	B44_DEVCTRL		0x0000UL /* Device Control */
35
+#define  DEVCTRL_MPM		0x00000040 /* MP PME Enable (B0 only) */
36
+#define  DEVCTRL_PFE		0x00000080 /* Pattern Filtering Enable */
37
+#define  DEVCTRL_IPP		0x00000400 /* Internal EPHY Present */
38
+#define  DEVCTRL_EPR		0x00008000 /* EPHY Reset */
39
+#define  DEVCTRL_PME		0x00001000 /* PHY Mode Enable */
40
+#define  DEVCTRL_PMCE		0x00002000 /* PHY Mode Clocks Enable */
41
+#define  DEVCTRL_PADDR		0x0007c000 /* PHY Address */
42
+#define  DEVCTRL_PADDR_SHIFT	18
43
+#define B44_BIST_STAT		0x000CUL /* Built-In Self-Test Status */
44
+#define B44_WKUP_LEN		0x0010UL /* Wakeup Length */
45
+#define  WKUP_LEN_P0_MASK	0x0000007f /* Pattern 0 */
46
+#define  WKUP_LEN_D0		0x00000080
47
+#define  WKUP_LEN_P1_MASK	0x00007f00 /* Pattern 1 */
48
+#define  WKUP_LEN_P1_SHIFT	8
49
+#define  WKUP_LEN_D1		0x00008000
50
+#define  WKUP_LEN_P2_MASK	0x007f0000 /* Pattern 2 */
51
+#define  WKUP_LEN_P2_SHIFT	16
52
+#define  WKUP_LEN_D2		0x00000000
53
+#define  WKUP_LEN_P3_MASK	0x7f000000 /* Pattern 3 */
54
+#define  WKUP_LEN_P3_SHIFT	24
55
+#define  WKUP_LEN_D3		0x80000000
56
+#define  WKUP_LEN_DISABLE	0x80808080
57
+#define  WKUP_LEN_ENABLE_TWO	0x80800000
58
+#define  WKUP_LEN_ENABLE_THREE	0x80000000
59
+#define B44_ISTAT		0x0020UL /* Interrupt Status */
60
+#define  ISTAT_LS		0x00000020 /* Link Change (B0 only) */
61
+#define  ISTAT_PME		0x00000040 /* Power Management Event */
62
+#define  ISTAT_TO		0x00000080 /* General Purpose Timeout */
63
+#define  ISTAT_DSCE		0x00000400 /* Descriptor Error */
64
+#define  ISTAT_DATAE		0x00000800 /* Data Error */
65
+#define  ISTAT_DPE		0x00001000 /* Descr. Protocol Error */
66
+#define  ISTAT_RDU		0x00002000 /* Receive Descr. Underflow */
67
+#define  ISTAT_RFO		0x00004000 /* Receive FIFO Overflow */
68
+#define  ISTAT_TFU		0x00008000 /* Transmit FIFO Underflow */
69
+#define  ISTAT_RX		0x00010000 /* RX Interrupt */
70
+#define  ISTAT_TX		0x01000000 /* TX Interrupt */
71
+#define  ISTAT_EMAC		0x04000000 /* EMAC Interrupt */
72
+#define  ISTAT_MII_WRITE	0x08000000 /* MII Write Interrupt */
73
+#define  ISTAT_MII_READ		0x10000000 /* MII Read Interrupt */
74
+#define  ISTAT_ERRORS           (ISTAT_DSCE|ISTAT_DATAE|ISTAT_DPE|\
75
+                                 ISTAT_RDU|ISTAT_RFO|ISTAT_TFU)
76
+#define B44_IMASK		0x0024UL /* Interrupt Mask */
77
+#define  IMASK_DEF		(ISTAT_ERRORS | ISTAT_RX | ISTAT_TX)
78
+#define  IMASK_DISABLE          0
79
+#define B44_GPTIMER		0x0028UL /* General Purpose Timer */
80
+#define B44_ADDR_LO		0x0088UL /* ENET Address Lo (B0 only) */
81
+#define B44_ADDR_HI		0x008CUL /* ENET Address Hi (B0 only) */
82
+#define B44_FILT_ADDR		0x0090UL /* ENET Filter Address */
83
+#define B44_FILT_DATA		0x0094UL /* ENET Filter Data */
84
+#define B44_TXBURST		0x00A0UL /* TX Max Burst Length */
85
+#define B44_RXBURST		0x00A4UL /* RX Max Burst Length */
86
+#define B44_MAC_CTRL		0x00A8UL /* MAC Control */
87
+#define  MAC_CTRL_CRC32_ENAB	0x00000001 /* CRC32 Generation Enable */
88
+#define  MAC_CTRL_PHY_PDOWN	0x00000004 /* Onchip EPHY Powerdown */
89
+#define  MAC_CTRL_PHY_EDET	0x00000008 /* Onchip EPHY Energy Detected*/
90
+#define  MAC_CTRL_PHY_LEDCTRL	0x000000e0 /* Onchip EPHY LED Control */
91
+#define  MAC_CTRL_PHY_LEDCTRL_SHIFT 5
92
+#define B44_MAC_FLOW		0x00ACUL /* MAC Flow Control */
93
+#define  MAC_FLOW_RX_HI_WATER	0x000000ff /* Receive FIFO HI Water Mark */
94
+#define  MAC_FLOW_PAUSE_ENAB	0x00008000 /* Enbl Pause Frm Generation */
95
+#define B44_RCV_LAZY		0x0100UL /* Lazy Interrupt Control */
96
+#define  RCV_LAZY_TO_MASK	0x00ffffff /* Timeout */
97
+#define  RCV_LAZY_FC_MASK	0xff000000 /* Frame Count */
98
+#define  RCV_LAZY_FC_SHIFT	24
99
+#define B44_DMATX_CTRL		0x0200UL /* DMA TX Control */
100
+#define  DMATX_CTRL_ENABLE	0x00000001 /* Enable */
101
+#define  DMATX_CTRL_SUSPEND	0x00000002 /* Suepend Request */
102
+#define  DMATX_CTRL_LPBACK	0x00000004 /* Loopback Enable */
103
+#define  DMATX_CTRL_FAIRPRIOR	0x00000008 /* Fair Priority */
104
+#define  DMATX_CTRL_FLUSH	0x00000010 /* Flush Request */
105
+#define B44_DMATX_ADDR		0x0204UL /* DMA TX Descriptor Ring Addr */
106
+#define B44_DMATX_PTR		0x0208UL /* DMA TX Last Posted Desc. */
107
+#define B44_DMATX_STAT		0x020CUL /* DMA TX Cur Actve Desc. + Sts */
108
+#define  DMATX_STAT_CDMASK	0x00000fff /* Current Descriptor Mask */
109
+#define  DMATX_STAT_SMASK	0x0000f000 /* State Mask */
110
+#define  DMATX_STAT_SDISABLED	0x00000000 /* State Disabled */
111
+#define  DMATX_STAT_SACTIVE	0x00001000 /* State Active */
112
+#define  DMATX_STAT_SIDLE	0x00002000 /* State Idle Wait */
113
+#define  DMATX_STAT_SSTOPPED	0x00003000 /* State Stopped */
114
+#define  DMATX_STAT_SSUSP	0x00004000 /* State Suspend Pending */
115
+#define  DMATX_STAT_EMASK	0x000f0000 /* Error Mask */
116
+#define  DMATX_STAT_ENONE	0x00000000 /* Error None */
117
+#define  DMATX_STAT_EDPE	0x00010000 /* Error Desc. Protocol Error */
118
+#define  DMATX_STAT_EDFU	0x00020000 /* Error Data FIFO Underrun */
119
+#define  DMATX_STAT_EBEBR	0x00030000 /* Bus Error on Buffer Read */
120
+#define  DMATX_STAT_EBEDA	0x00040000 /* Bus Error on Desc. Access */
121
+#define  DMATX_STAT_FLUSHED	0x00100000 /* Flushed */
122
+#define B44_DMARX_CTRL		0x0210UL /* DMA RX Control */
123
+#define  DMARX_CTRL_ENABLE	0x00000001 /* Enable */
124
+#define  DMARX_CTRL_ROMASK	0x000000fe /* Receive Offset Mask */
125
+#define  DMARX_CTRL_ROSHIFT	1 	   /* Receive Offset Shift */
126
+#define B44_DMARX_ADDR		0x0214UL /* DMA RX Descriptor Ring Addr */
127
+#define B44_DMARX_PTR		0x0218UL /* DMA RX Last Posted Desc */
128
+#define B44_DMARX_STAT		0x021CUL /* Cur Active Desc. + Status */
129
+#define  DMARX_STAT_CDMASK	0x00000fff /* Current Descriptor Mask */
130
+#define  DMARX_STAT_SMASK	0x0000f000 /* State Mask */
131
+#define  DMARX_STAT_SDISABLED	0x00000000 /* State Disbaled */
132
+#define  DMARX_STAT_SACTIVE	0x00001000 /* State Active */
133
+#define  DMARX_STAT_SIDLE	0x00002000 /* State Idle Wait */
134
+#define  DMARX_STAT_SSTOPPED	0x00003000 /* State Stopped */
135
+#define  DMARX_STAT_EMASK	0x000f0000 /* Error Mask */
136
+#define  DMARX_STAT_ENONE	0x00000000 /* Error None */
137
+#define  DMARX_STAT_EDPE	0x00010000 /* Error Desc. Protocol Error */
138
+#define  DMARX_STAT_EDFO	0x00020000 /* Error Data FIFO Overflow */
139
+#define  DMARX_STAT_EBEBW	0x00030000 /* Error on Buffer Write */
140
+#define  DMARX_STAT_EBEDA	0x00040000 /* Bus Error on Desc. Access */
141
+#define B44_DMAFIFO_AD		0x0220UL /* DMA FIFO Diag Address */
142
+#define  DMAFIFO_AD_OMASK	0x0000ffff /* Offset Mask */
143
+#define  DMAFIFO_AD_SMASK	0x000f0000 /* Select Mask */
144
+#define  DMAFIFO_AD_SXDD	0x00000000 /* Select Transmit DMA Data */
145
+#define  DMAFIFO_AD_SXDP	0x00010000 /* Sel Transmit DMA Pointers */
146
+#define  DMAFIFO_AD_SRDD	0x00040000 /* Select Receive DMA Data */
147
+#define  DMAFIFO_AD_SRDP	0x00050000 /* Sel Receive DMA Pointers */
148
+#define  DMAFIFO_AD_SXFD	0x00080000 /* Select Transmit FIFO Data */
149
+#define  DMAFIFO_AD_SXFP	0x00090000 /* Sel Transmit FIFO Pointers */
150
+#define  DMAFIFO_AD_SRFD	0x000c0000 /* Select Receive FIFO Data */
151
+#define  DMAFIFO_AD_SRFP	0x000c0000 /* Sel Receive FIFO Pointers */
152
+#define B44_DMAFIFO_LO		0x0224UL /* DMA FIFO Diag Low Data */
153
+#define B44_DMAFIFO_HI		0x0228UL /* DMA FIFO Diag High Data */
154
+#define B44_RXCONFIG		0x0400UL /* EMAC RX Config */
155
+#define  RXCONFIG_DBCAST	0x00000001 /* Disable Broadcast */
156
+#define  RXCONFIG_ALLMULTI	0x00000002 /* Accept All Multicast */
157
+#define  RXCONFIG_NORX_WHILE_TX	0x00000004 /* Rcv Disble While TX */
158
+#define  RXCONFIG_PROMISC	0x00000008 /* Promiscuous Enable */
159
+#define  RXCONFIG_LPBACK	0x00000010 /* Loopback Enable */
160
+#define  RXCONFIG_FLOW		0x00000020 /* Flow Control Enable */
161
+#define  RXCONFIG_FLOW_ACCEPT	0x00000040 /* Accept UFC Frame */
162
+#define  RXCONFIG_RFILT		0x00000080 /* Reject Filter */
163
+#define B44_RXMAXLEN		0x0404UL /* EMAC RX Max Packet Length */
164
+#define B44_TXMAXLEN		0x0408UL /* EMAC TX Max Packet Length */
165
+#define B44_MDIO_CTRL		0x0410UL /* EMAC MDIO Control */
166
+#define  MDIO_CTRL_MAXF_MASK	0x0000007f /* MDC Frequency */
167
+#define  MDIO_CTRL_PREAMBLE	0x00000080 /* MII Preamble Enable */
168
+#define B44_MDIO_DATA		0x0414UL /* EMAC MDIO Data */
169
+#define  MDIO_DATA_DATA		0x0000ffff /* R/W Data */
170
+#define  MDIO_DATA_TA_MASK	0x00030000 /* Turnaround Value */
171
+#define  MDIO_DATA_TA_SHIFT	16
172
+#define  MDIO_TA_VALID		2
173
+#define  MDIO_DATA_RA_MASK	0x007c0000 /* Register Address */
174
+#define  MDIO_DATA_RA_SHIFT	18
175
+#define  MDIO_DATA_PMD_MASK	0x0f800000 /* Physical Media Device */
176
+#define  MDIO_DATA_PMD_SHIFT	23
177
+#define  MDIO_DATA_OP_MASK	0x30000000 /* Opcode */
178
+#define  MDIO_DATA_OP_SHIFT	28
179
+#define  MDIO_OP_WRITE		1
180
+#define  MDIO_OP_READ		2
181
+#define  MDIO_DATA_SB_MASK	0xc0000000 /* Start Bits */
182
+#define  MDIO_DATA_SB_SHIFT	30
183
+#define  MDIO_DATA_SB_START	0x40000000 /* Start Of Frame */
184
+#define B44_EMAC_IMASK		0x0418UL /* EMAC Interrupt Mask */
185
+#define B44_EMAC_ISTAT		0x041CUL /* EMAC Interrupt Status */
186
+#define  EMAC_INT_MII		0x00000001 /* MII MDIO Interrupt */
187
+#define  EMAC_INT_MIB		0x00000002 /* MIB Interrupt */
188
+#define  EMAC_INT_FLOW		0x00000003 /* Flow Control Interrupt */
189
+#define B44_CAM_DATA_LO		0x0420UL /* EMAC CAM Data Low */
190
+#define B44_CAM_DATA_HI		0x0424UL /* EMAC CAM Data High */
191
+#define  CAM_DATA_HI_VALID	0x00010000 /* Valid Bit */
192
+#define B44_CAM_CTRL		0x0428UL /* EMAC CAM Control */
193
+#define  CAM_CTRL_ENABLE	0x00000001 /* CAM Enable */
194
+#define  CAM_CTRL_MSEL		0x00000002 /* Mask Select */
195
+#define  CAM_CTRL_READ		0x00000004 /* Read */
196
+#define  CAM_CTRL_WRITE		0x00000008 /* Read */
197
+#define  CAM_CTRL_INDEX_MASK	0x003f0000 /* Index Mask */
198
+#define  CAM_CTRL_INDEX_SHIFT	16
199
+#define  CAM_CTRL_BUSY		0x80000000 /* CAM Busy */
200
+#define B44_ENET_CTRL		0x042CUL /* EMAC ENET Control */
201
+#define  ENET_CTRL_ENABLE	0x00000001 /* EMAC Enable */
202
+#define  ENET_CTRL_DISABLE	0x00000002 /* EMAC Disable */
203
+#define  ENET_CTRL_SRST		0x00000004 /* EMAC Soft Reset */
204
+#define  ENET_CTRL_EPSEL	0x00000008 /* External PHY Select */
205
+#define B44_TX_CTRL		0x0430UL /* EMAC TX Control */
206
+#define  TX_CTRL_DUPLEX		0x00000001 /* Full Duplex */
207
+#define  TX_CTRL_FMODE		0x00000002 /* Flow Mode */
208
+#define  TX_CTRL_SBENAB		0x00000004 /* Single Backoff Enable */
209
+#define  TX_CTRL_SMALL_SLOT	0x00000008 /* Small Slottime */
210
+#define B44_TX_HIWMARK		0x0434UL /* EMAC TX High Watermark */
211
+#define  TX_HIWMARK_DEFLT	56  /* Default used in all drivers */
212
+#define B44_MIB_CTRL		0x0438UL /* EMAC MIB Control */
213
+#define  MIB_CTRL_CLR_ON_READ	0x00000001 /* Autoclear on Read */
214
+#define B44_TX_GOOD_O		0x0500UL /* MIB TX Good Octets */
215
+#define B44_TX_GOOD_P		0x0504UL /* MIB TX Good Packets */
216
+#define B44_TX_O		0x0508UL /* MIB TX Octets */
217
+#define B44_TX_P		0x050CUL /* MIB TX Packets */
218
+#define B44_TX_BCAST		0x0510UL /* MIB TX Broadcast Packets */
219
+#define B44_TX_MCAST		0x0514UL /* MIB TX Multicast Packets */
220
+#define B44_TX_64		0x0518UL /* MIB TX <= 64 byte Packets */
221
+#define B44_TX_65_127		0x051CUL /* MIB TX 65 to 127 byte Pkts */
222
+#define B44_TX_128_255		0x0520UL /* MIB TX 128 to 255 byte Pkts */
223
+#define B44_TX_256_511		0x0524UL /* MIB TX 256 to 511 byte Pkts */
224
+#define B44_TX_512_1023		0x0528UL /* MIB TX 512 to 1023 byte Pkts */
225
+#define B44_TX_1024_MAX		0x052CUL /* MIB TX 1024 to max byte Pkts */
226
+#define B44_TX_JABBER		0x0530UL /* MIB TX Jabber Packets */
227
+#define B44_TX_OSIZE		0x0534UL /* MIB TX Oversize Packets */
228
+#define B44_TX_FRAG		0x0538UL /* MIB TX Fragment Packets */
229
+#define B44_TX_URUNS		0x053CUL /* MIB TX Underruns */
230
+#define B44_TX_TCOLS		0x0540UL /* MIB TX Total Collisions */
231
+#define B44_TX_SCOLS		0x0544UL /* MIB TX Single Collisions */
232
+#define B44_TX_MCOLS		0x0548UL /* MIB TX Multiple Collisions */
233
+#define B44_TX_ECOLS		0x054CUL /* MIB TX Excessive Collisions */
234
+#define B44_TX_LCOLS		0x0550UL /* MIB TX Late Collisions */
235
+#define B44_TX_DEFERED		0x0554UL /* MIB TX Defered Packets */
236
+#define B44_TX_CLOST		0x0558UL /* MIB TX Carrier Lost */
237
+#define B44_TX_PAUSE		0x055CUL /* MIB TX Pause Packets */
238
+#define B44_RX_GOOD_O		0x0580UL /* MIB RX Good Octets */
239
+#define B44_RX_GOOD_P		0x0584UL /* MIB RX Good Packets */
240
+#define B44_RX_O		0x0588UL /* MIB RX Octets */
241
+#define B44_RX_P		0x058CUL /* MIB RX Packets */
242
+#define B44_RX_BCAST		0x0590UL /* MIB RX Broadcast Packets */
243
+#define B44_RX_MCAST		0x0594UL /* MIB RX Multicast Packets */
244
+#define B44_RX_64		0x0598UL /* MIB RX <= 64 byte Packets */
245
+#define B44_RX_65_127		0x059CUL /* MIB RX 65 to 127 byte Pkts */
246
+#define B44_RX_128_255		0x05A0UL /* MIB RX 128 to 255 byte Pkts */
247
+#define B44_RX_256_511		0x05A4UL /* MIB RX 256 to 511 byte Pkts */
248
+#define B44_RX_512_1023		0x05A8UL /* MIB RX 512 to 1023 byte Pkts */
249
+#define B44_RX_1024_MAX		0x05ACUL /* MIB RX 1024 to max byte Pkts */
250
+#define B44_RX_JABBER		0x05B0UL /* MIB RX Jabber Packets */
251
+#define B44_RX_OSIZE		0x05B4UL /* MIB RX Oversize Packets */
252
+#define B44_RX_FRAG		0x05B8UL /* MIB RX Fragment Packets */
253
+#define B44_RX_MISS		0x05BCUL /* MIB RX Missed Packets */
254
+#define B44_RX_CRCA		0x05C0UL /* MIB RX CRC Align Errors */
255
+#define B44_RX_USIZE		0x05C4UL /* MIB RX Undersize Packets */
256
+#define B44_RX_CRC		0x05C8UL /* MIB RX CRC Errors */
257
+#define B44_RX_ALIGN		0x05CCUL /* MIB RX Align Errors */
258
+#define B44_RX_SYM		0x05D0UL /* MIB RX Symbol Errors */
259
+#define B44_RX_PAUSE		0x05D4UL /* MIB RX Pause Packets */
260
+#define B44_RX_NPAUSE		0x05D8UL /* MIB RX Non-Pause Packets */
261
+
262
+/* Sonics Silicon backplane register definitions */
263
+#define B44_SBIMSTATE		0x0F90UL /* SB Initiator Agent State */
264
+#define  SBIMSTATE_PC		0x0000000f /* Pipe Count */
265
+#define  SBIMSTATE_AP_MASK	0x00000030 /* Arbitration Priority */
266
+#define  SBIMSTATE_AP_BOTH	0x00000000 /* both timeslices and token */
267
+#define  SBIMSTATE_AP_TS	0x00000010 /* Use timeslices only */
268
+#define  SBIMSTATE_AP_TK	0x00000020 /* Use token only */
269
+#define  SBIMSTATE_AP_RSV	0x00000030 /* Reserved */
270
+#define  SBIMSTATE_IBE		0x00020000 /* In Band Error */
271
+#define  SBIMSTATE_TO		0x00040000 /* Timeout */
272
+#define  SBIMSTATE_BAD      ( SBIMSTATE_IBE | SBIMSTATE_TO )
273
+#define B44_SBINTVEC		0x0F94UL /* SB Interrupt Mask */
274
+#define  SBINTVEC_PCI		0x00000001 /* Enable interrupts for PCI */
275
+#define  SBINTVEC_ENET0		0x00000002 /* Enable ints for enet 0 */
276
+#define  SBINTVEC_ILINE20	0x00000004 /* Enable ints for iline20 */
277
+#define  SBINTVEC_CODEC		0x00000008 /* Enable ints for v90 codec */
278
+#define  SBINTVEC_USB		0x00000010 /* Enable intts for usb */
279
+#define  SBINTVEC_EXTIF		0x00000020 /* Enable ints for ext i/f */
280
+#define  SBINTVEC_ENET1		0x00000040 /* Enable ints for enet 1 */
281
+#define B44_SBTMSLOW		0x0F98UL /* SB Target State Low */
282
+#define  SBTMSLOW_RESET		0x00000001 /* Reset */
283
+#define  SBTMSLOW_REJECT	0x00000002 /* Reject */
284
+#define  SBTMSLOW_CLOCK		0x00010000 /* Clock Enable */
285
+#define  SBTMSLOW_FGC		0x00020000 /* Force Gated Clocks On */
286
+#define  SBTMSLOW_PE		0x40000000 /* Power Management Enable */
287
+#define  SBTMSLOW_BE		0x80000000 /* BIST Enable */
288
+#define B44_SBTMSHIGH		0x0F9CUL /* SB Target State High */
289
+#define  SBTMSHIGH_SERR		0x00000001 /* S-error */
290
+#define  SBTMSHIGH_INT		0x00000002 /* Interrupt */
291
+#define  SBTMSHIGH_BUSY		0x00000004 /* Busy */
292
+#define  SBTMSHIGH_GCR		0x20000000 /* Gated Clock Request */
293
+#define  SBTMSHIGH_BISTF	0x40000000 /* BIST Failed */
294
+#define  SBTMSHIGH_BISTD	0x80000000 /* BIST Done */
295
+#define B44_SBIDHIGH		0x0FFCUL /* SB Identification High */
296
+#define  SBIDHIGH_RC_MASK	0x0000000f /* Revision Code */
297
+#define  SBIDHIGH_CC_MASK	0x0000fff0 /* Core Code */
298
+#define  SBIDHIGH_CC_SHIFT	4
299
+#define  SBIDHIGH_VC_MASK	0xffff0000 /* Vendor Code */
300
+#define  SBIDHIGH_VC_SHIFT	16
301
+
302
+/* SSB PCI config space registers.  */
303
+#define SSB_PMCSR		0x44
304
+#define  SSB_PE			0x100
305
+#define	SSB_BAR0_WIN		0x80
306
+#define	SSB_BAR1_WIN		0x84
307
+#define	SSB_SPROM_CONTROL	0x88
308
+#define	SSB_BAR1_CONTROL	0x8c
309
+
310
+/* SSB core and host control registers.  */
311
+#define SSB_CONTROL		0x0000UL
312
+#define SSB_ARBCONTROL		0x0010UL
313
+#define SSB_ISTAT		0x0020UL
314
+#define SSB_IMASK		0x0024UL
315
+#define SSB_MBOX		0x0028UL
316
+#define SSB_BCAST_ADDR		0x0050UL
317
+#define SSB_BCAST_DATA		0x0054UL
318
+#define SSB_PCI_TRANS_0		0x0100UL
319
+#define SSB_PCI_TRANS_1		0x0104UL
320
+#define SSB_PCI_TRANS_2		0x0108UL
321
+#define SSB_SPROM		0x0800UL
322
+
323
+#define SSB_PCI_MEM		0x00000000
324
+#define SSB_PCI_IO		0x00000001
325
+#define SSB_PCI_CFG0		0x00000002
326
+#define SSB_PCI_CFG1		0x00000003
327
+#define SSB_PCI_PREF		0x00000004
328
+#define SSB_PCI_BURST		0x00000008
329
+#define SSB_PCI_MASK0		0xfc000000
330
+#define SSB_PCI_MASK1		0xfc000000
331
+#define SSB_PCI_MASK2		0xc0000000
332
+
333
+/* 4400 PHY registers */
334
+#define B44_MII_AUXCTRL		24	/* Auxiliary Control */
335
+#define  MII_AUXCTRL_DUPLEX	0x0001  /* Full Duplex */
336
+#define  MII_AUXCTRL_SPEED	0x0002  /* 1=100Mbps, 0=10Mbps */
337
+#define  MII_AUXCTRL_FORCED	0x0004	/* Forced 10/100 */
338
+#define B44_MII_ALEDCTRL	26	/* Activity LED */
339
+#define  MII_ALEDCTRL_ALLMSK	0x7fff
340
+#define B44_MII_TLEDCTRL	27	/* Traffic Meter LED */
341
+#define  MII_TLEDCTRL_ENABLE	0x0040
342
+
343
+/* RX/TX descriptor */
344
+struct dma_desc {
345
+	u32 ctrl; /* length of data and flags */
346
+	u32 addr; /* address of data */
347
+};
348
+
349
+/* There are only 12 bits in the DMA engine for descriptor offsetting
350
+ * so the table must be aligned on a boundary of this.
351
+ */
352
+#define B44_DMA_ALIGNMENT	4096
353
+
354
+/* The DMA engine can only address the first gigabyte of address space
355
+ */
356
+#define B44_30BIT_DMA_MASK	0x3fffffff
357
+
358
+#define DESC_CTRL_LEN		0x00001fff
359
+#define DESC_CTRL_CMASK		0x0ff00000 /* Core specific bits */
360
+#define DESC_CTRL_EOT		0x10000000 /* End of Table */
361
+#define DESC_CTRL_IOC		0x20000000 /* Interrupt On Completion */
362
+#define DESC_CTRL_EOF		0x40000000 /* End of Frame */
363
+#define DESC_CTRL_SOF		0x80000000 /* Start of Frame */
364
+
365
+struct rx_header {
366
+	u16 len;
367
+	u16 flags;
368
+	u16 pad[12];
369
+};
370
+#define RX_HEADER_LEN	28
371
+
372
+#define RX_FLAG_OFIFO	0x00000001 /* FIFO Overflow */
373
+#define RX_FLAG_CRCERR	0x00000002 /* CRC Error */
374
+#define RX_FLAG_SERR	0x00000004 /* Receive Symbol Error */
375
+#define RX_FLAG_ODD	0x00000008 /* Frame has odd number of nibbles */
376
+#define RX_FLAG_LARGE	0x00000010 /* Frame is > RX MAX Length */
377
+#define RX_FLAG_MCAST	0x00000020 /* Dest is Multicast Address */
378
+#define RX_FLAG_BCAST	0x00000040 /* Dest is Broadcast Address */
379
+#define RX_FLAG_MISS	0x00000080 /* Received due to promisc mode */
380
+#define RX_FLAG_LAST	0x00000800 /* Last buffer in frame */
381
+#define RX_FLAG_ERRORS	(RX_FLAG_ODD | RX_FLAG_SERR |\
382
+                         RX_FLAG_CRCERR | RX_FLAG_OFIFO)
383
+
384
+/* Client Mode PCI memory access space (1 GB) */
385
+#define SB_PCI_DMA              0x40000000
386
+
387
+ /* Address of PCI core on BCM4400 cards */
388
+#define BCM4400_PCI_CORE_ADDR   0x18002000
389
+
390
+/* Hardware minimum and maximum for a single frame's data payload */
391
+#define B44_MIN_MTU		60
392
+#define B44_MAX_MTU		1500
393
+
394
+#define B44_RING_SIZE           8
395
+#define B44_RING_LAST           ( B44_RING_SIZE - 1 )
396
+
397
+#define B44_RX_RING_LEN_BYTES	( sizeof bp->rx[0] * B44_RING_SIZE )
398
+#define B44_TX_RING_LEN_BYTES	( sizeof bp->tx[0] * B44_RING_SIZE )
399
+
400
+#define RX_PKT_OFFSET		30
401
+#define RX_PKT_BUF_SZ		(1536 + RX_PKT_OFFSET + 64)
402
+
403
+#define B44_FULL_RESET		1
404
+#define B44_FULL_RESET_SKIP_PHY	2
405
+#define B44_PARTIAL_RESET	3
406
+#define B44_CHIP_RESET_FULL     4
407
+#define B44_CHIP_RESET_PARTIAL  5
408
+
409
+#define SSB_CORE_DOWN           ( SBTMSLOW_RESET | SBTMSLOW_REJECT )
410
+
411
+#define B44_REGS_SIZE           8192
412
+
413
+/** Driver private state */
414
+struct b44_private {
415
+	struct net_device *netdev;
416
+	struct pci_device *pci;
417
+	u8 *regs; /* memory-mapped registers */
418
+	u8 phy_addr;
419
+
420
+	struct dma_desc *tx;
421
+	struct io_buffer *tx_iobuf[B44_RING_SIZE];
422
+	u32 tx_cur; /* next available descriptor */
423
+	u32 tx_dirty; /* oldest pending descriptor */
424
+
425
+	struct dma_desc *rx;
426
+	struct io_buffer *rx_iobuf[B44_RING_SIZE];
427
+	u32 rx_cur; /* next descriptor to read */
428
+};
429
+
430
+
431
+static void ssb_core_reset ( struct b44_private *bp );
432
+static void ssb_core_disable ( struct b44_private *bp );
433
+static u32 ssb_pci_setup ( struct b44_private *bp, u32 cores );
434
+
435
+static void b44_chip_reset ( struct b44_private *bp, int reset_kind );
436
+static void b44_init_hw ( struct b44_private *bp, int reset_kind );
437
+static void b44_cam_write ( struct b44_private *bp, u8 *data, int index );
438
+static void b44_set_mac_addr ( struct b44_private *bp );
439
+static void b44_set_rx_mode ( struct net_device *netdev );
440
+static void b44_halt(struct b44_private *);
441
+
442
+static int b44_phy_reset ( struct b44_private *bp );
443
+static int b44_phy_write ( struct b44_private *bp, int reg, u32 val );
444
+static int b44_phy_read ( struct b44_private *bp, int reg, u32 *val );
445
+
446
+static int b44_init_tx_ring ( struct b44_private *bp );
447
+static void b44_free_tx_ring ( struct b44_private *bp );
448
+static int b44_init_rx_ring ( struct b44_private *bp );
449
+static void b44_free_rx_ring ( struct b44_private *bp );
450
+static void b44_rx_refill ( struct b44_private *bp, u32 pending );
451
+static void b44_populate_rx_descriptor (struct b44_private *bp, u32 index);
452
+
453
+static int b44_probe ( struct pci_device *pci,
454
+                       const struct pci_device_id *id );
455
+static void b44_remove ( struct pci_device *pci );
456
+
457
+static int b44_open ( struct net_device *netdev );
458
+static void b44_close ( struct net_device *netdev );
459
+static void b44_irq ( struct net_device *netdev, int enable );
460
+static void b44_poll ( struct net_device *netdev );
461
+static void b44_process_rx_packets ( struct b44_private *bp );
462
+static int b44_transmit ( struct net_device *netdev,
463
+                          struct io_buffer *iobuf );
464
+
465
+static struct net_device_operations b44_operations;
466
+
467
+#endif /* _B44_H */

+ 1
- 0
src/include/gpxe/errfile.h Visa fil

@@ -107,6 +107,7 @@
107 107
 #define ERRFILE_mtnic		     ( ERRFILE_DRIVER | 0x004a0000 )
108 108
 #define ERRFILE_phantom		     ( ERRFILE_DRIVER | 0x004b0000 )
109 109
 #define ERRFILE_ne2k_isa	     ( ERRFILE_DRIVER | 0x004c0000 )
110
+#define ERRFILE_b44		     ( ERRFILE_DRIVER | 0x004d0000 )
110 111
 
111 112
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
112 113
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )

Laddar…
Avbryt
Spara