~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to drivers/net/bcm570x.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Broadcom BCM570x Ethernet Driver for U-Boot.
 
3
 * Support 5701, 5702, 5703, and 5704. Single instance driver.
 
4
 * Copyright (C) 2002 James F. Dougherty (jfd@broadcom.com)
 
5
 */
 
6
 
 
7
#include <common.h>
 
8
 
 
9
#ifdef CONFIG_BMW
 
10
#include <mpc824x.h>
 
11
#endif
 
12
#include <net.h>
 
13
#include "bcm570x_mm.h"
 
14
#include "bcm570x_autoneg.h"
 
15
#include <pci.h>
 
16
#include <malloc.h>
 
17
 
 
18
/*
 
19
 * PCI Registers and definitions.
 
20
 */
 
21
#define PCI_CMD_MASK    0xffff0000      /* mask to save status bits */
 
22
#define PCI_ANY_ID (~0)
 
23
 
 
24
/*
 
25
 * PCI memory base for Ethernet device as well as device Interrupt.
 
26
 */
 
27
#define BCM570X_MBAR    0x80100000
 
28
#define BCM570X_ILINE   1
 
29
 
 
30
#define SECOND_USEC     1000000
 
31
#define MAX_PACKET_SIZE 1600
 
32
#define MAX_UNITS       4
 
33
 
 
34
/* Globals to this module */
 
35
int initialized = 0;
 
36
unsigned int ioBase = 0;
 
37
volatile PLM_DEVICE_BLOCK pDevice = NULL;       /* 570x softc */
 
38
volatile PUM_DEVICE_BLOCK pUmDevice = NULL;
 
39
 
 
40
/* Used to pass the full-duplex flag, etc. */
 
41
int line_speed[MAX_UNITS] = { 0, 0, 0, 0 };
 
42
static int full_duplex[MAX_UNITS] = { 1, 1, 1, 1 };
 
43
static int rx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
 
44
static int tx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
 
45
static int auto_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
 
46
static int tx_checksum[MAX_UNITS] = { 1, 1, 1, 1 };
 
47
static int rx_checksum[MAX_UNITS] = { 1, 1, 1, 1 };
 
48
static int auto_speed[MAX_UNITS] = { 1, 1, 1, 1 };
 
49
 
 
50
#if JUMBO_FRAMES
 
51
/* Jumbo MTU for interfaces. */
 
52
static int mtu[MAX_UNITS] = { 0, 0, 0, 0 };
 
53
#endif
 
54
 
 
55
/* Turn on Wake-on lan for a device unit */
 
56
static int enable_wol[MAX_UNITS] = { 0, 0, 0, 0 };
 
57
 
 
58
#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
 
59
static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
 
60
    { TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT };
 
61
 
 
62
#define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT
 
63
static unsigned int rx_std_desc_cnt[MAX_UNITS] =
 
64
    { RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT };
 
65
 
 
66
static unsigned int rx_adaptive_coalesce[MAX_UNITS] = { 1, 1, 1, 1 };
 
67
 
 
68
#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
 
69
#define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT
 
70
static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] =
 
71
    { JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT };
 
72
#endif
 
73
#define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS
 
74
static unsigned int rx_coalesce_ticks[MAX_UNITS] =
 
75
    { RX_COAL_TK, RX_COAL_TK, RX_COAL_TK, RX_COAL_TK };
 
76
 
 
77
#define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES
 
78
static unsigned int rx_max_coalesce_frames[MAX_UNITS] =
 
79
    { RX_COAL_FM, RX_COAL_FM, RX_COAL_FM, RX_COAL_FM };
 
80
 
 
81
#define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS
 
82
static unsigned int tx_coalesce_ticks[MAX_UNITS] =
 
83
    { TX_COAL_TK, TX_COAL_TK, TX_COAL_TK, TX_COAL_TK };
 
84
 
 
85
#define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES
 
86
static unsigned int tx_max_coalesce_frames[MAX_UNITS] =
 
87
    { TX_COAL_FM, TX_COAL_FM, TX_COAL_FM, TX_COAL_FM };
 
88
 
 
89
#define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS
 
90
static unsigned int stats_coalesce_ticks[MAX_UNITS] =
 
91
    { ST_COAL_TK, ST_COAL_TK, ST_COAL_TK, ST_COAL_TK };
 
92
 
 
93
/*
 
94
 * Legitimate values for BCM570x device types
 
95
 */
 
96
typedef enum {
 
97
        BCM5700VIGIL = 0,
 
98
        BCM5700A6,
 
99
        BCM5700T6,
 
100
        BCM5700A9,
 
101
        BCM5700T9,
 
102
        BCM5700,
 
103
        BCM5701A5,
 
104
        BCM5701T1,
 
105
        BCM5701T8,
 
106
        BCM5701A7,
 
107
        BCM5701A10,
 
108
        BCM5701A12,
 
109
        BCM5701,
 
110
        BCM5702,
 
111
        BCM5703,
 
112
        BCM5703A31,
 
113
        TC996T,
 
114
        TC996ST,
 
115
        TC996SSX,
 
116
        TC996SX,
 
117
        TC996BT,
 
118
        TC997T,
 
119
        TC997SX,
 
120
        TC1000T,
 
121
        TC940BR01,
 
122
        TC942BR01,
 
123
        NC6770,
 
124
        NC7760,
 
125
        NC7770,
 
126
        NC7780
 
127
} board_t;
 
128
 
 
129
/* Chip-Rev names for each device-type */
 
130
static struct {
 
131
        char *name;
 
132
} chip_rev[] = {
 
133
        {
 
134
        "BCM5700VIGIL"}, {
 
135
        "BCM5700A6"}, {
 
136
        "BCM5700T6"}, {
 
137
        "BCM5700A9"}, {
 
138
        "BCM5700T9"}, {
 
139
        "BCM5700"}, {
 
140
        "BCM5701A5"}, {
 
141
        "BCM5701T1"}, {
 
142
        "BCM5701T8"}, {
 
143
        "BCM5701A7"}, {
 
144
        "BCM5701A10"}, {
 
145
        "BCM5701A12"}, {
 
146
        "BCM5701"}, {
 
147
        "BCM5702"}, {
 
148
        "BCM5703"}, {
 
149
        "BCM5703A31"}, {
 
150
        "TC996T"}, {
 
151
        "TC996ST"}, {
 
152
        "TC996SSX"}, {
 
153
        "TC996SX"}, {
 
154
        "TC996BT"}, {
 
155
        "TC997T"}, {
 
156
        "TC997SX"}, {
 
157
        "TC1000T"}, {
 
158
        "TC940BR01"}, {
 
159
        "TC942BR01"}, {
 
160
        "NC6770"}, {
 
161
        "NC7760"}, {
 
162
        "NC7770"}, {
 
163
        "NC7780"}, {
 
164
        0}
 
165
};
 
166
 
 
167
/* indexed by board_t, above */
 
168
static struct {
 
169
        char *name;
 
170
} board_info[] = {
 
171
        {
 
172
        "Broadcom Vigil B5700 1000Base-T"}, {
 
173
        "Broadcom BCM5700 1000Base-T"}, {
 
174
        "Broadcom BCM5700 1000Base-SX"}, {
 
175
        "Broadcom BCM5700 1000Base-SX"}, {
 
176
        "Broadcom BCM5700 1000Base-T"}, {
 
177
        "Broadcom BCM5700"}, {
 
178
        "Broadcom BCM5701 1000Base-T"}, {
 
179
        "Broadcom BCM5701 1000Base-T"}, {
 
180
        "Broadcom BCM5701 1000Base-T"}, {
 
181
        "Broadcom BCM5701 1000Base-SX"}, {
 
182
        "Broadcom BCM5701 1000Base-T"}, {
 
183
        "Broadcom BCM5701 1000Base-T"}, {
 
184
        "Broadcom BCM5701"}, {
 
185
        "Broadcom BCM5702 1000Base-T"}, {
 
186
        "Broadcom BCM5703 1000Base-T"}, {
 
187
        "Broadcom BCM5703 1000Base-SX"}, {
 
188
        "3Com 3C996 10/100/1000 Server NIC"}, {
 
189
        "3Com 3C996 10/100/1000 Server NIC"}, {
 
190
        "3Com 3C996 Gigabit Fiber-SX Server NIC"}, {
 
191
        "3Com 3C996 Gigabit Fiber-SX Server NIC"}, {
 
192
        "3Com 3C996B Gigabit Server NIC"}, {
 
193
        "3Com 3C997 Gigabit Server NIC"}, {
 
194
        "3Com 3C997 Gigabit Fiber-SX Server NIC"}, {
 
195
        "3Com 3C1000 Gigabit NIC"}, {
 
196
        "3Com 3C940 Gigabit LOM (21X21)"}, {
 
197
        "3Com 3C942 Gigabit LOM (31X31)"}, {
 
198
        "Compaq NC6770 Gigabit Server Adapter"}, {
 
199
        "Compaq NC7760 Gigabit Server Adapter"}, {
 
200
        "Compaq NC7770 Gigabit Server Adapter"}, {
 
201
        "Compaq NC7780 Gigabit Server Adapter"}, {
 
202
0},};
 
203
 
 
204
/* PCI Devices which use the 570x chipset */
 
205
struct pci_device_table {
 
206
        unsigned short vendor_id, device_id;    /* Vendor/DeviceID */
 
207
        unsigned short subvendor, subdevice;    /* Subsystem ID's or PCI_ANY_ID */
 
208
        unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
 
209
        unsigned long board_id; /* Data private to the driver */
 
210
        int io_size, min_latency;
 
211
} bcm570xDevices[] = {
 
212
        {
 
213
        0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL, 128, 32}, {
 
214
        0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6, 128, 32}, {
 
215
        0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6, 128, 32}, {
 
216
        0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9, 128, 32}, {
 
217
        0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9, 128, 32}, {
 
218
        0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700, 128, 32}, {
 
219
        0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700, 128, 32}, {
 
220
        0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700, 128, 32}, {
 
221
        0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700, 128, 32}, {
 
222
        0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T, 128, 32}, {
 
223
        0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST, 128, 32}, {
 
224
        0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX, 128, 32}, {
 
225
        0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T, 128, 32}, {
 
226
        0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX, 128, 32}, {
 
227
        0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01, 128, 32}, {
 
228
        0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700, 128, 32}, {
 
229
        0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5, 128, 32}, {
 
230
        0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1, 128, 32}, {
 
231
        0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8, 128, 32}, {
 
232
        0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7, 128, 32}, {
 
233
        0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10, 128, 32}, {
 
234
        0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12, 128, 32}, {
 
235
        0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770, 128, 32}, {
 
236
        0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770, 128, 32}, {
 
237
        0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780, 128, 32}, {
 
238
        0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701, 128, 32}, {
 
239
        0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX, 128, 32}, {
 
240
        0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT, 128, 32}, {
 
241
        0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T, 128, 32}, {
 
242
        0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01, 128, 32}, {
 
243
        0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701, 128, 32}, {
 
244
        0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, {
 
245
        0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, {
 
246
        0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, {
 
247
        0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, {
 
248
        0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, {
 
249
        0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, {
 
250
        0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, {
 
251
        0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, {
 
252
        0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, {
 
253
        0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, {
 
254
        0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, {
 
255
        0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, {
 
256
        0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}, {
 
257
        0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, {
 
258
        0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, {
 
259
        0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, {
 
260
        0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, {
 
261
        0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, {
 
262
        0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, {
 
263
        0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}
 
264
};
 
265
 
 
266
#define n570xDevices   (sizeof(bcm570xDevices)/sizeof(bcm570xDevices[0]))
 
267
 
 
268
/*
 
269
 * Allocate a packet buffer from the bcm570x packet pool.
 
270
 */
 
271
void *bcm570xPktAlloc (int u, int pksize)
 
272
{
 
273
        return malloc (pksize);
 
274
}
 
275
 
 
276
/*
 
277
 * Free a packet previously allocated from the bcm570x packet
 
278
 * buffer pool.
 
279
 */
 
280
void bcm570xPktFree (int u, void *p)
 
281
{
 
282
        free (p);
 
283
}
 
284
 
 
285
int bcm570xReplenishRxBuffers (PUM_DEVICE_BLOCK pUmDevice)
 
286
{
 
287
        PLM_PACKET pPacket;
 
288
        PUM_PACKET pUmPacket;
 
289
        void *skb;
 
290
        int queue_rx = 0;
 
291
        int ret = 0;
 
292
 
 
293
        while ((pUmPacket = (PUM_PACKET)
 
294
                QQ_PopHead (&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
 
295
 
 
296
                pPacket = (PLM_PACKET) pUmPacket;
 
297
 
 
298
                /* reuse an old skb */
 
299
                if (pUmPacket->skbuff) {
 
300
                        QQ_PushTail (&pDevice->RxPacketFreeQ.Container,
 
301
                                     pPacket);
 
302
                        queue_rx = 1;
 
303
                        continue;
 
304
                }
 
305
                if ((skb = bcm570xPktAlloc (pUmDevice->index,
 
306
                                            pPacket->u.Rx.RxBufferSize + 2)) ==
 
307
                    0) {
 
308
                        QQ_PushHead (&pUmDevice->rx_out_of_buf_q.Container,
 
309
                                     pPacket);
 
310
                        printf ("NOTICE: Out of RX memory.\n");
 
311
                        ret = 1;
 
312
                        break;
 
313
                }
 
314
 
 
315
                pUmPacket->skbuff = skb;
 
316
                QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
 
317
                queue_rx = 1;
 
318
        }
 
319
 
 
320
        if (queue_rx) {
 
321
                LM_QueueRxPackets (pDevice);
 
322
        }
 
323
 
 
324
        return ret;
 
325
}
 
326
 
 
327
/*
 
328
 * Probe, Map, and Init 570x device.
 
329
 */
 
330
int eth_init (bd_t * bis)
 
331
{
 
332
        int i, rv, devFound = FALSE;
 
333
        pci_dev_t devbusfn;
 
334
        unsigned short status;
 
335
 
 
336
        /* Find PCI device, if it exists, configure ...  */
 
337
        for (i = 0; i < n570xDevices; i++) {
 
338
                devbusfn = pci_find_device (bcm570xDevices[i].vendor_id,
 
339
                                            bcm570xDevices[i].device_id, 0);
 
340
                if (devbusfn == -1) {
 
341
                        continue;       /* No device of that vendor/device ID */
 
342
                } else {
 
343
 
 
344
                        /* Set ILINE */
 
345
                        pci_write_config_byte (devbusfn,
 
346
                                               PCI_INTERRUPT_LINE,
 
347
                                               BCM570X_ILINE);
 
348
 
 
349
                        /*
 
350
                         * 0x10 - 0x14 define one 64-bit MBAR.
 
351
                         * 0x14 is the higher-order address bits of the BAR.
 
352
                         */
 
353
                        pci_write_config_dword (devbusfn,
 
354
                                                PCI_BASE_ADDRESS_1, 0);
 
355
 
 
356
                        ioBase = BCM570X_MBAR;
 
357
 
 
358
                        pci_write_config_dword (devbusfn,
 
359
                                                PCI_BASE_ADDRESS_0, ioBase);
 
360
 
 
361
                        /*
 
362
                         * Enable PCI memory, IO, and Master -- don't
 
363
                         * reset any status bits in doing so.
 
364
                         */
 
365
                        pci_read_config_word (devbusfn, PCI_COMMAND, &status);
 
366
 
 
367
                        status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
 
368
 
 
369
                        pci_write_config_word (devbusfn, PCI_COMMAND, status);
 
370
 
 
371
                        printf
 
372
                            ("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n",
 
373
                             board_info[bcm570xDevices[i].board_id].name,
 
374
                             PCI_BUS (devbusfn), PCI_DEV (devbusfn),
 
375
                             PCI_FUNC (devbusfn), ioBase);
 
376
 
 
377
                        /* Allocate once, but always clear on init */
 
378
                        if (!pDevice) {
 
379
                                pDevice = malloc (sizeof (UM_DEVICE_BLOCK));
 
380
                                pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
381
                                memset (pDevice, 0x0, sizeof (UM_DEVICE_BLOCK));
 
382
                        }
 
383
 
 
384
                        /* Configure pci dev structure */
 
385
                        pUmDevice->pdev = devbusfn;
 
386
                        pUmDevice->index = 0;
 
387
                        pUmDevice->tx_pkt = 0;
 
388
                        pUmDevice->rx_pkt = 0;
 
389
                        devFound = TRUE;
 
390
                        break;
 
391
                }
 
392
        }
 
393
 
 
394
        if (!devFound) {
 
395
                printf
 
396
                    ("eth_init: FAILURE: no BCM570x Ethernet devices found.\n");
 
397
                return -1;
 
398
        }
 
399
 
 
400
        /* Setup defaults for chip */
 
401
        pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
 
402
 
 
403
        if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) {
 
404
                pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
 
405
        } else {
 
406
 
 
407
                if (rx_checksum[i]) {
 
408
                        pDevice->TaskToOffload |=
 
409
                            LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
 
410
                            LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
 
411
                }
 
412
 
 
413
                if (tx_checksum[i]) {
 
414
                        pDevice->TaskToOffload |=
 
415
                            LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
 
416
                            LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
 
417
                        pDevice->NoTxPseudoHdrChksum = TRUE;
 
418
                }
 
419
        }
 
420
 
 
421
        /* Set Device PCI Memory base address */
 
422
        pDevice->pMappedMemBase = (PLM_UINT8) ioBase;
 
423
 
 
424
        /* Pull down adapter info */
 
425
        if ((rv = LM_GetAdapterInfo (pDevice)) != LM_STATUS_SUCCESS) {
 
426
                printf ("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv);
 
427
                return -2;
 
428
        }
 
429
 
 
430
        /* Lock not needed */
 
431
        pUmDevice->do_global_lock = 0;
 
432
 
 
433
        if (T3_ASIC_REV (pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
 
434
                /* The 5700 chip works best without interleaved register */
 
435
                /* accesses on certain machines. */
 
436
                pUmDevice->do_global_lock = 1;
 
437
        }
 
438
 
 
439
        /* Setup timer delays */
 
440
        if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) {
 
441
                pDevice->UseTaggedStatus = TRUE;
 
442
                pUmDevice->timer_interval = CONFIG_SYS_HZ;
 
443
        } else {
 
444
                pUmDevice->timer_interval = CONFIG_SYS_HZ / 50;
 
445
        }
 
446
 
 
447
        /* Grab name .... */
 
448
        pUmDevice->name =
 
449
            (char *)malloc (strlen (board_info[bcm570xDevices[i].board_id].name)
 
450
                            + 1);
 
451
        strcpy (pUmDevice->name, board_info[bcm570xDevices[i].board_id].name);
 
452
 
 
453
        eth_getenv_enetaddr("ethaddr", pDevice->NodeAddress);
 
454
        LM_SetMacAddress (pDevice);
 
455
        /* Init queues  .. */
 
456
        QQ_InitQueue (&pUmDevice->rx_out_of_buf_q.Container,
 
457
                      MAX_RX_PACKET_DESC_COUNT);
 
458
        pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0;
 
459
 
 
460
        /* delay for 4 seconds */
 
461
        pUmDevice->delayed_link_ind = (4 * CONFIG_SYS_HZ) / pUmDevice->timer_interval;
 
462
 
 
463
        pUmDevice->adaptive_expiry = CONFIG_SYS_HZ / pUmDevice->timer_interval;
 
464
 
 
465
        /* Sometimes we get spurious ints. after reset when link is down. */
 
466
        /* This field tells the isr to service the int. even if there is */
 
467
        /* no status block update. */
 
468
        pUmDevice->adapter_just_inited =
 
469
            (3 * CONFIG_SYS_HZ) / pUmDevice->timer_interval;
 
470
 
 
471
        /* Initialize 570x */
 
472
        if (LM_InitializeAdapter (pDevice) != LM_STATUS_SUCCESS) {
 
473
                printf ("ERROR: Adapter initialization failed.\n");
 
474
                return ERROR;
 
475
        }
 
476
 
 
477
        /* Enable chip ISR */
 
478
        LM_EnableInterrupt (pDevice);
 
479
 
 
480
        /* Clear MC table */
 
481
        LM_MulticastClear (pDevice);
 
482
 
 
483
        /* Enable Multicast */
 
484
        LM_SetReceiveMask (pDevice,
 
485
                           pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
 
486
 
 
487
        pUmDevice->opened = 1;
 
488
        pUmDevice->tx_full = 0;
 
489
        pUmDevice->tx_pkt = 0;
 
490
        pUmDevice->rx_pkt = 0;
 
491
        printf ("eth%d: %s @0x%lx,",
 
492
                pDevice->index, pUmDevice->name, (unsigned long)ioBase);
 
493
        printf ("node addr ");
 
494
        for (i = 0; i < 6; i++) {
 
495
                printf ("%2.2x", pDevice->NodeAddress[i]);
 
496
        }
 
497
        printf ("\n");
 
498
 
 
499
        printf ("eth%d: ", pDevice->index);
 
500
        printf ("%s with ", chip_rev[bcm570xDevices[i].board_id].name);
 
501
 
 
502
        if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
 
503
                printf ("Broadcom BCM5400 Copper ");
 
504
        else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
 
505
                printf ("Broadcom BCM5401 Copper ");
 
506
        else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
 
507
                printf ("Broadcom BCM5411 Copper ");
 
508
        else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID)
 
509
                printf ("Broadcom BCM5701 Integrated Copper ");
 
510
        else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID)
 
511
                printf ("Broadcom BCM5703 Integrated Copper ");
 
512
        else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
 
513
                printf ("Broadcom BCM8002 SerDes ");
 
514
        else if (pDevice->EnableTbi)
 
515
                printf ("Agilent HDMP-1636 SerDes ");
 
516
        else
 
517
                printf ("Unknown ");
 
518
        printf ("transceiver found\n");
 
519
 
 
520
        printf ("eth%d: %s, MTU: %d,",
 
521
                pDevice->index, pDevice->BusSpeedStr, 1500);
 
522
 
 
523
        if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) && rx_checksum[i])
 
524
                printf ("Rx Checksum ON\n");
 
525
        else
 
526
                printf ("Rx Checksum OFF\n");
 
527
        initialized++;
 
528
 
 
529
        return 0;
 
530
}
 
531
 
 
532
/* Ethernet Interrupt service routine */
 
533
void eth_isr (void)
 
534
{
 
535
        LM_UINT32 oldtag, newtag;
 
536
        int i;
 
537
 
 
538
        pUmDevice->interrupt = 1;
 
539
 
 
540
        if (pDevice->UseTaggedStatus) {
 
541
                if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
 
542
                    pUmDevice->adapter_just_inited) {
 
543
                        MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 1);
 
544
                        oldtag = pDevice->pStatusBlkVirt->StatusTag;
 
545
 
 
546
                        for (i = 0;; i++) {
 
547
                                pDevice->pStatusBlkVirt->Status &=
 
548
                                    ~STATUS_BLOCK_UPDATED;
 
549
                                LM_ServiceInterrupts (pDevice);
 
550
                                newtag = pDevice->pStatusBlkVirt->StatusTag;
 
551
                                if ((newtag == oldtag) || (i > 50)) {
 
552
                                        MB_REG_WR (pDevice,
 
553
                                                   Mailbox.Interrupt[0].Low,
 
554
                                                   newtag << 24);
 
555
                                        if (pDevice->UndiFix) {
 
556
                                                REG_WR (pDevice, Grc.LocalCtrl,
 
557
                                                        pDevice->
 
558
                                                        GrcLocalCtrl | 0x2);
 
559
                                        }
 
560
                                        break;
 
561
                                }
 
562
                                oldtag = newtag;
 
563
                        }
 
564
                }
 
565
        } else {
 
566
                while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
 
567
                        unsigned int dummy;
 
568
 
 
569
                        pDevice->pMemView->Mailbox.Interrupt[0].Low = 1;
 
570
                        pDevice->pStatusBlkVirt->Status &=
 
571
                            ~STATUS_BLOCK_UPDATED;
 
572
                        LM_ServiceInterrupts (pDevice);
 
573
                        pDevice->pMemView->Mailbox.Interrupt[0].Low = 0;
 
574
                        dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low;
 
575
                }
 
576
        }
 
577
 
 
578
        /* Allocate new RX buffers */
 
579
        if (QQ_GetEntryCnt (&pUmDevice->rx_out_of_buf_q.Container)) {
 
580
                bcm570xReplenishRxBuffers (pUmDevice);
 
581
        }
 
582
 
 
583
        /* Queue packets */
 
584
        if (QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container)) {
 
585
                LM_QueueRxPackets (pDevice);
 
586
        }
 
587
 
 
588
        if (pUmDevice->tx_queued) {
 
589
                pUmDevice->tx_queued = 0;
 
590
        }
 
591
 
 
592
        if (pUmDevice->tx_full) {
 
593
                if (pDevice->LinkStatus != LM_STATUS_LINK_DOWN) {
 
594
                        printf
 
595
                            ("NOTICE: tx was previously blocked, restarting MUX\n");
 
596
                        pUmDevice->tx_full = 0;
 
597
                }
 
598
        }
 
599
 
 
600
        pUmDevice->interrupt = 0;
 
601
 
 
602
}
 
603
 
 
604
int eth_send (volatile void *packet, int length)
 
605
{
 
606
        int status = 0;
 
607
#if ET_DEBUG
 
608
        unsigned char *ptr = (unsigned char *)packet;
 
609
#endif
 
610
        PLM_PACKET pPacket;
 
611
        PUM_PACKET pUmPacket;
 
612
 
 
613
        /* Link down, return */
 
614
        while (pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {
 
615
#if 0
 
616
                printf ("eth%d: link down - check cable or link partner.\n",
 
617
                        pUmDevice->index);
 
618
#endif
 
619
                eth_isr ();
 
620
 
 
621
                /* Wait to see link for one-half a second before sending ... */
 
622
                udelay (1500000);
 
623
 
 
624
        }
 
625
 
 
626
        /* Clear sent flag */
 
627
        pUmDevice->tx_pkt = 0;
 
628
 
 
629
        /* Previously blocked */
 
630
        if (pUmDevice->tx_full) {
 
631
                printf ("eth%d: tx blocked.\n", pUmDevice->index);
 
632
                return 0;
 
633
        }
 
634
 
 
635
        pPacket = (PLM_PACKET)
 
636
            QQ_PopHead (&pDevice->TxPacketFreeQ.Container);
 
637
 
 
638
        if (pPacket == 0) {
 
639
                pUmDevice->tx_full = 1;
 
640
                printf ("bcm570xEndSend: TX full!\n");
 
641
                return 0;
 
642
        }
 
643
 
 
644
        if (pDevice->SendBdLeft.counter == 0) {
 
645
                pUmDevice->tx_full = 1;
 
646
                printf ("bcm570xEndSend: no more TX descriptors!\n");
 
647
                QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
 
648
                return 0;
 
649
        }
 
650
 
 
651
        if (length <= 0) {
 
652
                printf ("eth: bad packet size: %d\n", length);
 
653
                goto out;
 
654
        }
 
655
 
 
656
        /* Get packet buffers and fragment list */
 
657
        pUmPacket = (PUM_PACKET) pPacket;
 
658
        /* Single DMA Descriptor transmit.
 
659
         * Fragments may be provided, but one DMA descriptor max is
 
660
         * used to send the packet.
 
661
         */
 
662
        if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) {
 
663
                if (pUmPacket->skbuff == NULL) {
 
664
                        /* Packet was discarded */
 
665
                        printf ("TX: failed (1)\n");
 
666
                        status = 1;
 
667
                } else {
 
668
                        printf ("TX: failed (2)\n");
 
669
                        status = 2;
 
670
                }
 
671
                QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
 
672
                return status;
 
673
        }
 
674
 
 
675
        /* Copy packet to DMA buffer */
 
676
        memset (pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE);
 
677
        memcpy ((void *)pUmPacket->skbuff, (void *)packet, length);
 
678
        pPacket->PacketSize = length;
 
679
        pPacket->Flags |= SND_BD_FLAG_END | SND_BD_FLAG_COAL_NOW;
 
680
        pPacket->u.Tx.FragCount = 1;
 
681
        /* We've already provided a frame ready for transmission */
 
682
        pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
 
683
 
 
684
        if (LM_SendPacket (pDevice, pPacket) == LM_STATUS_FAILURE) {
 
685
                /*
 
686
                 *  A lower level send failure will push the packet descriptor back
 
687
                 *  in the free queue, so just deal with the VxWorks clusters.
 
688
                 */
 
689
                if (pUmPacket->skbuff == NULL) {
 
690
                        printf ("TX failed (1)!\n");
 
691
                        /* Packet was discarded */
 
692
                        status = 3;
 
693
                } else {
 
694
                        /* A resource problem ... */
 
695
                        printf ("TX failed (2)!\n");
 
696
                        status = 4;
 
697
                }
 
698
 
 
699
                if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) == 0) {
 
700
                        printf ("TX: emptyQ!\n");
 
701
                        pUmDevice->tx_full = 1;
 
702
                }
 
703
        }
 
704
 
 
705
        while (pUmDevice->tx_pkt == 0) {
 
706
                /* Service TX */
 
707
                eth_isr ();
 
708
        }
 
709
#if ET_DEBUG
 
710
        printf ("eth_send: 0x%x, %d bytes\n"
 
711
                "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n",
 
712
                (int)pPacket, length,
 
713
                ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5],
 
714
                ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12],
 
715
                ptr[13], ptr[14], ptr[15]);
 
716
#endif
 
717
        pUmDevice->tx_pkt = 0;
 
718
        QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
 
719
 
 
720
        /* Done with send */
 
721
      out:
 
722
        return status;
 
723
}
 
724
 
 
725
/* Ethernet receive */
 
726
int eth_rx (void)
 
727
{
 
728
        PLM_PACKET pPacket = NULL;
 
729
        PUM_PACKET pUmPacket = NULL;
 
730
        void *skb;
 
731
        int size = 0;
 
732
 
 
733
        while (TRUE) {
 
734
 
 
735
              bcm570x_service_isr:
 
736
                /* Pull down packet if it is there */
 
737
                eth_isr ();
 
738
 
 
739
                /* Indicate RX packets called */
 
740
                if (pUmDevice->rx_pkt) {
 
741
                        /* printf("eth_rx: got a packet...\n"); */
 
742
                        pUmDevice->rx_pkt = 0;
 
743
                } else {
 
744
                        /* printf("eth_rx: waiting for packet...\n"); */
 
745
                        goto bcm570x_service_isr;
 
746
                }
 
747
 
 
748
                pPacket = (PLM_PACKET)
 
749
                    QQ_PopHead (&pDevice->RxPacketReceivedQ.Container);
 
750
 
 
751
                if (pPacket == 0) {
 
752
                        printf ("eth_rx: empty packet!\n");
 
753
                        goto bcm570x_service_isr;
 
754
                }
 
755
 
 
756
                pUmPacket = (PUM_PACKET) pPacket;
 
757
#if ET_DEBUG
 
758
                printf ("eth_rx: packet @0x%x\n", (int)pPacket);
 
759
#endif
 
760
                /* If the packet generated an error, reuse buffer */
 
761
                if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
 
762
                    ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
 
763
 
 
764
                        /* reuse skb */
 
765
                        QQ_PushTail (&pDevice->RxPacketFreeQ.Container,
 
766
                                     pPacket);
 
767
                        printf ("eth_rx: error in packet dma!\n");
 
768
                        goto bcm570x_service_isr;
 
769
                }
 
770
 
 
771
                /* Set size and address */
 
772
                skb = pUmPacket->skbuff;
 
773
                size = pPacket->PacketSize;
 
774
 
 
775
                /* Pass the packet up to the protocol
 
776
                 * layers.
 
777
                 */
 
778
                NetReceive (skb, size);
 
779
 
 
780
                /* Free packet buffer */
 
781
                bcm570xPktFree (pUmDevice->index, skb);
 
782
                pUmPacket->skbuff = NULL;
 
783
 
 
784
                /* Reuse SKB */
 
785
                QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
 
786
 
 
787
                return 0;       /* Got a packet, bail ... */
 
788
        }
 
789
        return size;
 
790
}
 
791
 
 
792
/* Shut down device */
 
793
void eth_halt (void)
 
794
{
 
795
        int i;
 
796
        if (initialized)
 
797
                if (pDevice && pUmDevice && pUmDevice->opened) {
 
798
                        printf ("\neth%d:%s,", pUmDevice->index,
 
799
                                pUmDevice->name);
 
800
                        printf ("HALT,");
 
801
                        /* stop device */
 
802
                        LM_Halt (pDevice);
 
803
                        printf ("POWER DOWN,");
 
804
                        LM_SetPowerState (pDevice, LM_POWER_STATE_D3);
 
805
 
 
806
                        /* Free the memory allocated by the device in tigon3 */
 
807
                        for (i = 0; i < pUmDevice->mem_list_num; i++) {
 
808
                                if (pUmDevice->mem_list[i]) {
 
809
                                        /* sanity check */
 
810
                                        if (pUmDevice->dma_list[i]) {   /* cache-safe memory */
 
811
                                                free (pUmDevice->mem_list[i]);
 
812
                                        } else {
 
813
                                                free (pUmDevice->mem_list[i]);  /* normal memory   */
 
814
                                        }
 
815
                                }
 
816
                        }
 
817
                        pUmDevice->opened = 0;
 
818
                        free (pDevice);
 
819
                        pDevice = NULL;
 
820
                        pUmDevice = NULL;
 
821
                        initialized = 0;
 
822
                        printf ("done - offline.\n");
 
823
                }
 
824
}
 
825
 
 
826
/*
 
827
 *
 
828
 * Middle Module: Interface between the HW driver (tigon3 modules) and
 
829
 * the native (SENS) driver.  These routines implement the system
 
830
 * interface for tigon3 on VxWorks.
 
831
 */
 
832
 
 
833
/* Middle module dependency - size of a packet descriptor */
 
834
int MM_Packet_Desc_Size = sizeof (UM_PACKET);
 
835
 
 
836
LM_STATUS
 
837
MM_ReadConfig32 (PLM_DEVICE_BLOCK pDevice,
 
838
                 LM_UINT32 Offset, LM_UINT32 * pValue32)
 
839
{
 
840
        UM_DEVICE_BLOCK *pUmDevice;
 
841
        pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
 
842
        pci_read_config_dword (pUmDevice->pdev, Offset, (u32 *) pValue32);
 
843
        return LM_STATUS_SUCCESS;
 
844
}
 
845
 
 
846
LM_STATUS
 
847
MM_WriteConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 Value32)
 
848
{
 
849
        UM_DEVICE_BLOCK *pUmDevice;
 
850
        pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
 
851
        pci_write_config_dword (pUmDevice->pdev, Offset, Value32);
 
852
        return LM_STATUS_SUCCESS;
 
853
}
 
854
 
 
855
LM_STATUS
 
856
MM_ReadConfig16 (PLM_DEVICE_BLOCK pDevice,
 
857
                 LM_UINT32 Offset, LM_UINT16 * pValue16)
 
858
{
 
859
        UM_DEVICE_BLOCK *pUmDevice;
 
860
        pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
 
861
        pci_read_config_word (pUmDevice->pdev, Offset, (u16 *) pValue16);
 
862
        return LM_STATUS_SUCCESS;
 
863
}
 
864
 
 
865
LM_STATUS
 
866
MM_WriteConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT16 Value16)
 
867
{
 
868
        UM_DEVICE_BLOCK *pUmDevice;
 
869
        pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
 
870
        pci_write_config_word (pUmDevice->pdev, Offset, Value16);
 
871
        return LM_STATUS_SUCCESS;
 
872
}
 
873
 
 
874
LM_STATUS
 
875
MM_AllocateSharedMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
 
876
                         PLM_VOID * pMemoryBlockVirt,
 
877
                         PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, LM_BOOL Cached)
 
878
{
 
879
        PLM_VOID pvirt;
 
880
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
881
        dma_addr_t mapping;
 
882
 
 
883
        pvirt = malloc (BlockSize);
 
884
        mapping = (dma_addr_t) (pvirt);
 
885
        if (!pvirt)
 
886
                return LM_STATUS_FAILURE;
 
887
 
 
888
        pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
 
889
        pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
 
890
        pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
 
891
        memset (pvirt, 0, BlockSize);
 
892
 
 
893
        *pMemoryBlockVirt = (PLM_VOID) pvirt;
 
894
        MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping);
 
895
 
 
896
        return LM_STATUS_SUCCESS;
 
897
}
 
898
 
 
899
LM_STATUS
 
900
MM_AllocateMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
 
901
                   PLM_VOID * pMemoryBlockVirt)
 
902
{
 
903
        PLM_VOID pvirt;
 
904
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
905
 
 
906
        pvirt = malloc (BlockSize);
 
907
 
 
908
        if (!pvirt)
 
909
                return LM_STATUS_FAILURE;
 
910
 
 
911
        pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
 
912
        pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
 
913
        pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
 
914
        memset (pvirt, 0, BlockSize);
 
915
        *pMemoryBlockVirt = pvirt;
 
916
 
 
917
        return LM_STATUS_SUCCESS;
 
918
}
 
919
 
 
920
LM_STATUS MM_MapMemBase (PLM_DEVICE_BLOCK pDevice)
 
921
{
 
922
        printf ("BCM570x PCI Memory base address @0x%x\n",
 
923
                (unsigned int)pDevice->pMappedMemBase);
 
924
        return LM_STATUS_SUCCESS;
 
925
}
 
926
 
 
927
LM_STATUS MM_InitializeUmPackets (PLM_DEVICE_BLOCK pDevice)
 
928
{
 
929
        int i;
 
930
        void *skb;
 
931
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
932
        PUM_PACKET pUmPacket = NULL;
 
933
        PLM_PACKET pPacket = NULL;
 
934
 
 
935
        for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
 
936
                pPacket = QQ_PopHead (&pDevice->RxPacketFreeQ.Container);
 
937
                pUmPacket = (PUM_PACKET) pPacket;
 
938
 
 
939
                if (pPacket == 0) {
 
940
                        printf ("MM_InitializeUmPackets: Bad RxPacketFreeQ\n");
 
941
                }
 
942
 
 
943
                skb = bcm570xPktAlloc (pUmDevice->index,
 
944
                                       pPacket->u.Rx.RxBufferSize + 2);
 
945
 
 
946
                if (skb == 0) {
 
947
                        pUmPacket->skbuff = 0;
 
948
                        QQ_PushTail (&pUmDevice->rx_out_of_buf_q.Container,
 
949
                                     pPacket);
 
950
                        printf ("MM_InitializeUmPackets: out of buffer.\n");
 
951
                        continue;
 
952
                }
 
953
 
 
954
                pUmPacket->skbuff = skb;
 
955
                QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
 
956
        }
 
957
 
 
958
        pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8;
 
959
 
 
960
        return LM_STATUS_SUCCESS;
 
961
}
 
962
 
 
963
LM_STATUS MM_GetConfig (PLM_DEVICE_BLOCK pDevice)
 
964
{
 
965
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
966
        int index = pDevice->index;
 
967
 
 
968
        if (auto_speed[index] == 0)
 
969
                pDevice->DisableAutoNeg = TRUE;
 
970
        else
 
971
                pDevice->DisableAutoNeg = FALSE;
 
972
 
 
973
        if (line_speed[index] == 0) {
 
974
                pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO;
 
975
                pDevice->DisableAutoNeg = FALSE;
 
976
        } else {
 
977
                if (line_speed[index] == 1000) {
 
978
                        if (pDevice->EnableTbi) {
 
979
                                pDevice->RequestedMediaType =
 
980
                                    LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX;
 
981
                        } else if (full_duplex[index]) {
 
982
                                pDevice->RequestedMediaType =
 
983
                                    LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX;
 
984
                        } else {
 
985
                                pDevice->RequestedMediaType =
 
986
                                    LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS;
 
987
                        }
 
988
                        if (!pDevice->EnableTbi)
 
989
                                pDevice->DisableAutoNeg = FALSE;
 
990
                } else if (line_speed[index] == 100) {
 
991
                        if (full_duplex[index]) {
 
992
                                pDevice->RequestedMediaType =
 
993
                                    LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX;
 
994
                        } else {
 
995
                                pDevice->RequestedMediaType =
 
996
                                    LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS;
 
997
                        }
 
998
                } else if (line_speed[index] == 10) {
 
999
                        if (full_duplex[index]) {
 
1000
                                pDevice->RequestedMediaType =
 
1001
                                    LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX;
 
1002
                        } else {
 
1003
                                pDevice->RequestedMediaType =
 
1004
                                    LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
 
1005
                        }
 
1006
                } else {
 
1007
                        pDevice->RequestedMediaType =
 
1008
                            LM_REQUESTED_MEDIA_TYPE_AUTO;
 
1009
                        pDevice->DisableAutoNeg = FALSE;
 
1010
                }
 
1011
 
 
1012
        }
 
1013
        pDevice->FlowControlCap = 0;
 
1014
        if (rx_flow_control[index] != 0) {
 
1015
                pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
 
1016
        }
 
1017
        if (tx_flow_control[index] != 0) {
 
1018
                pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
 
1019
        }
 
1020
        if ((auto_flow_control[index] != 0) &&
 
1021
            (pDevice->DisableAutoNeg == FALSE)) {
 
1022
 
 
1023
                pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
 
1024
                if ((tx_flow_control[index] == 0) &&
 
1025
                    (rx_flow_control[index] == 0)) {
 
1026
                        pDevice->FlowControlCap |=
 
1027
                            LM_FLOW_CONTROL_TRANSMIT_PAUSE |
 
1028
                            LM_FLOW_CONTROL_RECEIVE_PAUSE;
 
1029
                }
 
1030
        }
 
1031
 
 
1032
        /* Default MTU for now */
 
1033
        pUmDevice->mtu = 1500;
 
1034
 
 
1035
#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
 
1036
        if (pUmDevice->mtu > 1500) {
 
1037
                pDevice->RxMtu = pUmDevice->mtu;
 
1038
                pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
 
1039
        } else {
 
1040
                pDevice->RxJumboDescCnt = 0;
 
1041
        }
 
1042
        pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
 
1043
#else
 
1044
        pDevice->RxMtu = pUmDevice->mtu;
 
1045
#endif
 
1046
 
 
1047
        if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) {
 
1048
                pDevice->UseTaggedStatus = TRUE;
 
1049
                pUmDevice->timer_interval = CONFIG_SYS_HZ;
 
1050
        } else {
 
1051
                pUmDevice->timer_interval = CONFIG_SYS_HZ / 50;
 
1052
        }
 
1053
 
 
1054
        pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
 
1055
        pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
 
1056
        /* Note:  adaptive coalescence really isn't adaptive in this driver */
 
1057
        pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index];
 
1058
        if (!pUmDevice->rx_adaptive_coalesce) {
 
1059
                pDevice->RxCoalescingTicks = rx_coalesce_ticks[index];
 
1060
                if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS)
 
1061
                        pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS;
 
1062
                pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks;
 
1063
 
 
1064
                pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index];
 
1065
                if (pDevice->RxMaxCoalescedFrames > MAX_RX_MAX_COALESCED_FRAMES)
 
1066
                        pDevice->RxMaxCoalescedFrames =
 
1067
                            MAX_RX_MAX_COALESCED_FRAMES;
 
1068
                pUmDevice->rx_curr_coalesce_frames =
 
1069
                    pDevice->RxMaxCoalescedFrames;
 
1070
                pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
 
1071
                if (pDevice->StatsCoalescingTicks > MAX_STATS_COALESCING_TICKS)
 
1072
                        pDevice->StatsCoalescingTicks =
 
1073
                            MAX_STATS_COALESCING_TICKS;
 
1074
        } else {
 
1075
                pUmDevice->rx_curr_coalesce_frames =
 
1076
                    DEFAULT_RX_MAX_COALESCED_FRAMES;
 
1077
                pUmDevice->rx_curr_coalesce_ticks = DEFAULT_RX_COALESCING_TICKS;
 
1078
        }
 
1079
        pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
 
1080
        if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS)
 
1081
                pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS;
 
1082
        pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
 
1083
        if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES)
 
1084
                pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES;
 
1085
 
 
1086
        if (enable_wol[index]) {
 
1087
                pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
 
1088
                pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
 
1089
        }
 
1090
        pDevice->NicSendBd = TRUE;
 
1091
 
 
1092
        /* Don't update status blocks during interrupt */
 
1093
        pDevice->RxCoalescingTicksDuringInt = 0;
 
1094
        pDevice->TxCoalescingTicksDuringInt = 0;
 
1095
 
 
1096
        return LM_STATUS_SUCCESS;
 
1097
 
 
1098
}
 
1099
 
 
1100
LM_STATUS MM_StartTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
 
1101
{
 
1102
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
1103
        printf ("Start TX DMA: dev=%d packet @0x%x\n",
 
1104
                (int)pUmDevice->index, (unsigned int)pPacket);
 
1105
 
 
1106
        return LM_STATUS_SUCCESS;
 
1107
}
 
1108
 
 
1109
LM_STATUS MM_CompleteTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
 
1110
{
 
1111
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
1112
        printf ("Complete TX DMA: dev=%d packet @0x%x\n",
 
1113
                (int)pUmDevice->index, (unsigned int)pPacket);
 
1114
        return LM_STATUS_SUCCESS;
 
1115
}
 
1116
 
 
1117
LM_STATUS MM_IndicateStatus (PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
 
1118
{
 
1119
        char buf[128];
 
1120
        char lcd[4];
 
1121
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
1122
        LM_FLOW_CONTROL flow_control;
 
1123
 
 
1124
        pUmDevice->delayed_link_ind = 0;
 
1125
        memset (lcd, 0x0, 4);
 
1126
 
 
1127
        if (Status == LM_STATUS_LINK_DOWN) {
 
1128
                sprintf (buf, "eth%d: %s: NIC Link is down\n",
 
1129
                         pUmDevice->index, pUmDevice->name);
 
1130
                lcd[0] = 'L';
 
1131
                lcd[1] = 'N';
 
1132
                lcd[2] = 'K';
 
1133
                lcd[3] = '?';
 
1134
        } else if (Status == LM_STATUS_LINK_ACTIVE) {
 
1135
                sprintf (buf, "eth%d:%s: ", pUmDevice->index, pUmDevice->name);
 
1136
 
 
1137
                if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) {
 
1138
                        strcat (buf, "1000 Mbps ");
 
1139
                        lcd[0] = '1';
 
1140
                        lcd[1] = 'G';
 
1141
                        lcd[2] = 'B';
 
1142
                } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) {
 
1143
                        strcat (buf, "100 Mbps ");
 
1144
                        lcd[0] = '1';
 
1145
                        lcd[1] = '0';
 
1146
                        lcd[2] = '0';
 
1147
                } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) {
 
1148
                        strcat (buf, "10 Mbps ");
 
1149
                        lcd[0] = '1';
 
1150
                        lcd[1] = '0';
 
1151
                        lcd[2] = ' ';
 
1152
                }
 
1153
                if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) {
 
1154
                        strcat (buf, "full duplex");
 
1155
                        lcd[3] = 'F';
 
1156
                } else {
 
1157
                        strcat (buf, "half duplex");
 
1158
                        lcd[3] = 'H';
 
1159
                }
 
1160
                strcat (buf, " link up");
 
1161
 
 
1162
                flow_control = pDevice->FlowControl &
 
1163
                    (LM_FLOW_CONTROL_RECEIVE_PAUSE |
 
1164
                     LM_FLOW_CONTROL_TRANSMIT_PAUSE);
 
1165
 
 
1166
                if (flow_control) {
 
1167
                        if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
 
1168
                                strcat (buf, ", receive ");
 
1169
                                if (flow_control &
 
1170
                                    LM_FLOW_CONTROL_TRANSMIT_PAUSE)
 
1171
                                        strcat (buf, " & transmit ");
 
1172
                        } else {
 
1173
                                strcat (buf, ", transmit ");
 
1174
                        }
 
1175
                        strcat (buf, "flow control ON");
 
1176
                } else {
 
1177
                        strcat (buf, ", flow control OFF");
 
1178
                }
 
1179
                strcat (buf, "\n");
 
1180
                printf ("%s", buf);
 
1181
        }
 
1182
#if 0
 
1183
        sysLedDsply (lcd[0], lcd[1], lcd[2], lcd[3]);
 
1184
#endif
 
1185
        return LM_STATUS_SUCCESS;
 
1186
}
 
1187
 
 
1188
LM_STATUS MM_FreeRxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
 
1189
{
 
1190
 
 
1191
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
1192
        PUM_PACKET pUmPacket;
 
1193
        void *skb;
 
1194
 
 
1195
        pUmPacket = (PUM_PACKET) pPacket;
 
1196
 
 
1197
        if ((skb = pUmPacket->skbuff))
 
1198
                bcm570xPktFree (pUmDevice->index, skb);
 
1199
 
 
1200
        pUmPacket->skbuff = 0;
 
1201
 
 
1202
        return LM_STATUS_SUCCESS;
 
1203
}
 
1204
 
 
1205
unsigned long MM_AnGetCurrentTime_us (PAN_STATE_INFO pAnInfo)
 
1206
{
 
1207
        return get_timer (0);
 
1208
}
 
1209
 
 
1210
/*
 
1211
 *   Transform an MBUF chain into a single MBUF.
 
1212
 *   This routine will fail if the amount of data in the
 
1213
 *   chain overflows a transmit buffer.  In that case,
 
1214
 *   the incoming MBUF chain will be freed.  This routine can
 
1215
 *   also fail by not being able to allocate a new MBUF (including
 
1216
 *   cluster and mbuf headers).  In that case the failure is
 
1217
 *   non-fatal.  The incoming cluster chain is not freed, giving
 
1218
 *   the caller the choice of whether to try a retransmit later.
 
1219
 */
 
1220
LM_STATUS MM_CoalesceTxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
 
1221
{
 
1222
        PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
 
1223
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
1224
        void *skbnew;
 
1225
        int len = 0;
 
1226
 
 
1227
        if (len == 0)
 
1228
                return (LM_STATUS_SUCCESS);
 
1229
 
 
1230
        if (len > MAX_PACKET_SIZE) {
 
1231
                printf ("eth%d: xmit frame discarded, too big!, size = %d\n",
 
1232
                        pUmDevice->index, len);
 
1233
                return (LM_STATUS_FAILURE);
 
1234
        }
 
1235
 
 
1236
        skbnew = bcm570xPktAlloc (pUmDevice->index, MAX_PACKET_SIZE);
 
1237
 
 
1238
        if (skbnew == NULL) {
 
1239
                pUmDevice->tx_full = 1;
 
1240
                printf ("eth%d: out of transmit buffers", pUmDevice->index);
 
1241
                return (LM_STATUS_FAILURE);
 
1242
        }
 
1243
 
 
1244
        /* New packet values */
 
1245
        pUmPacket->skbuff = skbnew;
 
1246
        pUmPacket->lm_packet.u.Tx.FragCount = 1;
 
1247
 
 
1248
        return (LM_STATUS_SUCCESS);
 
1249
}
 
1250
 
 
1251
LM_STATUS MM_IndicateRxPackets (PLM_DEVICE_BLOCK pDevice)
 
1252
{
 
1253
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
1254
        pUmDevice->rx_pkt = 1;
 
1255
        return LM_STATUS_SUCCESS;
 
1256
}
 
1257
 
 
1258
LM_STATUS MM_IndicateTxPackets (PLM_DEVICE_BLOCK pDevice)
 
1259
{
 
1260
        PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
 
1261
        PLM_PACKET pPacket;
 
1262
        PUM_PACKET pUmPacket;
 
1263
        void *skb;
 
1264
        while (TRUE) {
 
1265
 
 
1266
                pPacket = (PLM_PACKET)
 
1267
                    QQ_PopHead (&pDevice->TxPacketXmittedQ.Container);
 
1268
 
 
1269
                if (pPacket == 0)
 
1270
                        break;
 
1271
 
 
1272
                pUmPacket = (PUM_PACKET) pPacket;
 
1273
                skb = (void *)pUmPacket->skbuff;
 
1274
 
 
1275
                /*
 
1276
                 * Free MBLK if we transmitted a fragmented packet or a
 
1277
                 * non-fragmented packet straight from the VxWorks
 
1278
                 * buffer pool. If packet was copied to a local transmit
 
1279
                 * buffer, then there's no MBUF to free, just free
 
1280
                 * the transmit buffer back to the cluster pool.
 
1281
                 */
 
1282
 
 
1283
                if (skb)
 
1284
                        bcm570xPktFree (pUmDevice->index, skb);
 
1285
 
 
1286
                pUmPacket->skbuff = 0;
 
1287
                QQ_PushTail (&pDevice->TxPacketFreeQ.Container, pPacket);
 
1288
                pUmDevice->tx_pkt = 1;
 
1289
        }
 
1290
        if (pUmDevice->tx_full) {
 
1291
                if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) >=
 
1292
                    (QQ_GetSize (&pDevice->TxPacketFreeQ.Container) >> 1))
 
1293
                        pUmDevice->tx_full = 0;
 
1294
        }
 
1295
        return LM_STATUS_SUCCESS;
 
1296
}
 
1297
 
 
1298
/*
 
1299
 *  Scan an MBUF chain until we reach fragment number "frag"
 
1300
 *  Return its length and physical address.
 
1301
 */
 
1302
void MM_MapTxDma
 
1303
    (PLM_DEVICE_BLOCK pDevice,
 
1304
     struct _LM_PACKET *pPacket,
 
1305
     T3_64BIT_HOST_ADDR * paddr, LM_UINT32 * len, int frag) {
 
1306
        PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
 
1307
        *len = pPacket->PacketSize;
 
1308
        MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff);
 
1309
}
 
1310
 
 
1311
/*
 
1312
 *  Convert an mbuf address, a CPU local virtual address,
 
1313
 *  to a physical address as seen from a PCI device.  Store the
 
1314
 *  result at paddr.
 
1315
 */
 
1316
void MM_MapRxDma (PLM_DEVICE_BLOCK pDevice,
 
1317
                  struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR * paddr)
 
1318
{
 
1319
        PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
 
1320
        MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff);
 
1321
}
 
1322
 
 
1323
void MM_SetAddr (LM_PHYSICAL_ADDRESS * paddr, dma_addr_t addr)
 
1324
{
 
1325
#if (BITS_PER_LONG == 64)
 
1326
        paddr->High = ((unsigned long)addr) >> 32;
 
1327
        paddr->Low = ((unsigned long)addr) & 0xffffffff;
 
1328
#else
 
1329
        paddr->High = 0;
 
1330
        paddr->Low = (unsigned long)addr;
 
1331
#endif
 
1332
}
 
1333
 
 
1334
void MM_SetT3Addr (T3_64BIT_HOST_ADDR * paddr, dma_addr_t addr)
 
1335
{
 
1336
        unsigned long baddr = (unsigned long)addr;
 
1337
#if (BITS_PER_LONG == 64)
 
1338
        set_64bit_addr (paddr, baddr & 0xffffffff, baddr >> 32);
 
1339
#else
 
1340
        set_64bit_addr (paddr, baddr, 0);
 
1341
#endif
 
1342
}
 
1343
 
 
1344
/*
 
1345
 * This combination of `inline' and `extern' has almost the effect of a
 
1346
 * macro.  The way to use it is to put a function definition in a header
 
1347
 * file with these keywords, and put another copy of the definition
 
1348
 * (lacking `inline' and `extern') in a library file.  The definition in
 
1349
 * the header file will cause most calls to the function to be inlined.
 
1350
 * If any uses of the function remain, they will refer to the single copy
 
1351
 * in the library.
 
1352
 */
 
1353
void atomic_set (atomic_t * entry, int val)
 
1354
{
 
1355
        entry->counter = val;
 
1356
}
 
1357
 
 
1358
int atomic_read (atomic_t * entry)
 
1359
{
 
1360
        return entry->counter;
 
1361
}
 
1362
 
 
1363
void atomic_inc (atomic_t * entry)
 
1364
{
 
1365
        if (entry)
 
1366
                entry->counter++;
 
1367
}
 
1368
 
 
1369
void atomic_dec (atomic_t * entry)
 
1370
{
 
1371
        if (entry)
 
1372
                entry->counter--;
 
1373
}
 
1374
 
 
1375
void atomic_sub (int a, atomic_t * entry)
 
1376
{
 
1377
        if (entry)
 
1378
                entry->counter -= a;
 
1379
}
 
1380
 
 
1381
void atomic_add (int a, atomic_t * entry)
 
1382
{
 
1383
        if (entry)
 
1384
                entry->counter += a;
 
1385
}
 
1386
 
 
1387
/******************************************************************************/
 
1388
/* Description:                                                               */
 
1389
/*                                                                            */
 
1390
/* Return:                                                                    */
 
1391
/******************************************************************************/
 
1392
void QQ_InitQueue (PQQ_CONTAINER pQueue, unsigned int QueueSize)
 
1393
{
 
1394
        pQueue->Head = 0;
 
1395
        pQueue->Tail = 0;
 
1396
        pQueue->Size = QueueSize + 1;
 
1397
        atomic_set (&pQueue->EntryCnt, 0);
 
1398
}                               /* QQ_InitQueue */
 
1399
 
 
1400
/******************************************************************************/
 
1401
/* Description:                                                               */
 
1402
/*                                                                            */
 
1403
/* Return:                                                                    */
 
1404
/******************************************************************************/
 
1405
char QQ_Full (PQQ_CONTAINER pQueue)
 
1406
{
 
1407
        unsigned int NewHead;
 
1408
 
 
1409
        NewHead = (pQueue->Head + 1) % pQueue->Size;
 
1410
 
 
1411
        return (NewHead == pQueue->Tail);
 
1412
}                               /* QQ_Full */
 
1413
 
 
1414
/******************************************************************************/
 
1415
/* Description:                                                               */
 
1416
/*                                                                            */
 
1417
/* Return:                                                                    */
 
1418
/******************************************************************************/
 
1419
char QQ_Empty (PQQ_CONTAINER pQueue)
 
1420
{
 
1421
        return (pQueue->Head == pQueue->Tail);
 
1422
}                               /* QQ_Empty */
 
1423
 
 
1424
/******************************************************************************/
 
1425
/* Description:                                                               */
 
1426
/*                                                                            */
 
1427
/* Return:                                                                    */
 
1428
/******************************************************************************/
 
1429
unsigned int QQ_GetSize (PQQ_CONTAINER pQueue)
 
1430
{
 
1431
        return pQueue->Size;
 
1432
}                               /* QQ_GetSize */
 
1433
 
 
1434
/******************************************************************************/
 
1435
/* Description:                                                               */
 
1436
/*                                                                            */
 
1437
/* Return:                                                                    */
 
1438
/******************************************************************************/
 
1439
unsigned int QQ_GetEntryCnt (PQQ_CONTAINER pQueue)
 
1440
{
 
1441
        return atomic_read (&pQueue->EntryCnt);
 
1442
}                               /* QQ_GetEntryCnt */
 
1443
 
 
1444
/******************************************************************************/
 
1445
/* Description:                                                               */
 
1446
/*                                                                            */
 
1447
/* Return:                                                                    */
 
1448
/*    TRUE entry was added successfully.                                      */
 
1449
/*    FALSE queue is full.                                                    */
 
1450
/******************************************************************************/
 
1451
char QQ_PushHead (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)
 
1452
{
 
1453
        unsigned int Head;
 
1454
 
 
1455
        Head = (pQueue->Head + 1) % pQueue->Size;
 
1456
 
 
1457
#if !defined(QQ_NO_OVERFLOW_CHECK)
 
1458
        if (Head == pQueue->Tail) {
 
1459
                return 0;
 
1460
        }                       /* if */
 
1461
#endif                          /* QQ_NO_OVERFLOW_CHECK */
 
1462
 
 
1463
        pQueue->Array[pQueue->Head] = pEntry;
 
1464
        wmb ();
 
1465
        pQueue->Head = Head;
 
1466
        atomic_inc (&pQueue->EntryCnt);
 
1467
 
 
1468
        return -1;
 
1469
}                               /* QQ_PushHead */
 
1470
 
 
1471
/******************************************************************************/
 
1472
/* Description:                                                               */
 
1473
/*                                                                            */
 
1474
/* Return:                                                                    */
 
1475
/*    TRUE entry was added successfully.                                      */
 
1476
/*    FALSE queue is full.                                                    */
 
1477
/******************************************************************************/
 
1478
char QQ_PushTail (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)
 
1479
{
 
1480
        unsigned int Tail;
 
1481
 
 
1482
        Tail = pQueue->Tail;
 
1483
        if (Tail == 0) {
 
1484
                Tail = pQueue->Size;
 
1485
        }                       /* if */
 
1486
        Tail--;
 
1487
 
 
1488
#if !defined(QQ_NO_OVERFLOW_CHECK)
 
1489
        if (Tail == pQueue->Head) {
 
1490
                return 0;
 
1491
        }                       /* if */
 
1492
#endif                          /* QQ_NO_OVERFLOW_CHECK */
 
1493
 
 
1494
        pQueue->Array[Tail] = pEntry;
 
1495
        wmb ();
 
1496
        pQueue->Tail = Tail;
 
1497
        atomic_inc (&pQueue->EntryCnt);
 
1498
 
 
1499
        return -1;
 
1500
}                               /* QQ_PushTail */
 
1501
 
 
1502
/******************************************************************************/
 
1503
/* Description:                                                               */
 
1504
/*                                                                            */
 
1505
/* Return:                                                                    */
 
1506
/******************************************************************************/
 
1507
PQQ_ENTRY QQ_PopHead (PQQ_CONTAINER pQueue)
 
1508
{
 
1509
        unsigned int Head;
 
1510
        PQQ_ENTRY Entry;
 
1511
 
 
1512
        Head = pQueue->Head;
 
1513
 
 
1514
#if !defined(QQ_NO_UNDERFLOW_CHECK)
 
1515
        if (Head == pQueue->Tail) {
 
1516
                return (PQQ_ENTRY) 0;
 
1517
        }                       /* if */
 
1518
#endif                          /* QQ_NO_UNDERFLOW_CHECK */
 
1519
 
 
1520
        if (Head == 0) {
 
1521
                Head = pQueue->Size;
 
1522
        }                       /* if */
 
1523
        Head--;
 
1524
 
 
1525
        Entry = pQueue->Array[Head];
 
1526
        membar ();
 
1527
 
 
1528
        pQueue->Head = Head;
 
1529
        atomic_dec (&pQueue->EntryCnt);
 
1530
 
 
1531
        return Entry;
 
1532
}                               /* QQ_PopHead */
 
1533
 
 
1534
/******************************************************************************/
 
1535
/* Description:                                                               */
 
1536
/*                                                                            */
 
1537
/* Return:                                                                    */
 
1538
/******************************************************************************/
 
1539
PQQ_ENTRY QQ_PopTail (PQQ_CONTAINER pQueue)
 
1540
{
 
1541
        unsigned int Tail;
 
1542
        PQQ_ENTRY Entry;
 
1543
 
 
1544
        Tail = pQueue->Tail;
 
1545
 
 
1546
#if !defined(QQ_NO_UNDERFLOW_CHECK)
 
1547
        if (Tail == pQueue->Head) {
 
1548
                return (PQQ_ENTRY) 0;
 
1549
        }                       /* if */
 
1550
#endif                          /* QQ_NO_UNDERFLOW_CHECK */
 
1551
 
 
1552
        Entry = pQueue->Array[Tail];
 
1553
        membar ();
 
1554
        pQueue->Tail = (Tail + 1) % pQueue->Size;
 
1555
        atomic_dec (&pQueue->EntryCnt);
 
1556
 
 
1557
        return Entry;
 
1558
}                               /* QQ_PopTail */
 
1559
 
 
1560
/******************************************************************************/
 
1561
/* Description:                                                               */
 
1562
/*                                                                            */
 
1563
/* Return:                                                                    */
 
1564
/******************************************************************************/
 
1565
PQQ_ENTRY QQ_GetHead (PQQ_CONTAINER pQueue, unsigned int Idx)
 
1566
{
 
1567
        if (Idx >= atomic_read (&pQueue->EntryCnt)) {
 
1568
                return (PQQ_ENTRY) 0;
 
1569
        }
 
1570
 
 
1571
        if (pQueue->Head > Idx) {
 
1572
                Idx = pQueue->Head - Idx;
 
1573
        } else {
 
1574
                Idx = pQueue->Size - (Idx - pQueue->Head);
 
1575
        }
 
1576
        Idx--;
 
1577
 
 
1578
        return pQueue->Array[Idx];
 
1579
}
 
1580
 
 
1581
/******************************************************************************/
 
1582
/* Description:                                                               */
 
1583
/*                                                                            */
 
1584
/* Return:                                                                    */
 
1585
/******************************************************************************/
 
1586
PQQ_ENTRY QQ_GetTail (PQQ_CONTAINER pQueue, unsigned int Idx)
 
1587
{
 
1588
        if (Idx >= atomic_read (&pQueue->EntryCnt)) {
 
1589
                return (PQQ_ENTRY) 0;
 
1590
        }
 
1591
 
 
1592
        Idx += pQueue->Tail;
 
1593
        if (Idx >= pQueue->Size) {
 
1594
                Idx = Idx - pQueue->Size;
 
1595
        }
 
1596
 
 
1597
        return pQueue->Array[Idx];
 
1598
}