blob: c8f4064224dc1b2022dc4e2adc9e88fec8ee7b9d [file] [log] [blame]
wdenkcc1c8a12002-11-02 22:58:18 +00001/*
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
Jon Loeligerb1d408a2007-07-09 17:30:01 -05009#if defined(CONFIG_CMD_NET) \
Jon Loeligerd8c86302007-06-11 19:02:10 -050010 && (!defined(CONFIG_NET_MULTI)) && defined(CONFIG_BCM570x)
wdenkcc1c8a12002-11-02 22:58:18 +000011
12#ifdef CONFIG_BMW
13#include <mpc824x.h>
14#endif
15#include <net.h>
16#include "bcm570x_mm.h"
17#include "bcm570x_autoneg.h"
18#include <pci.h>
19#include <malloc.h>
20
wdenkcc1c8a12002-11-02 22:58:18 +000021/*
22 * PCI Registers and definitions.
23 */
24#define PCI_CMD_MASK 0xffff0000 /* mask to save status bits */
25#define PCI_ANY_ID (~0)
26
27/*
28 * PCI memory base for Ethernet device as well as device Interrupt.
29 */
30#define BCM570X_MBAR 0x80100000
31#define BCM570X_ILINE 1
32
wdenkcc1c8a12002-11-02 22:58:18 +000033#define SECOND_USEC 1000000
34#define MAX_PACKET_SIZE 1600
35#define MAX_UNITS 4
36
37/* Globals to this module */
38int initialized = 0;
39unsigned int ioBase = 0;
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070040volatile PLM_DEVICE_BLOCK pDevice = NULL; /* 570x softc */
41volatile PUM_DEVICE_BLOCK pUmDevice = NULL;
wdenkcc1c8a12002-11-02 22:58:18 +000042
43/* Used to pass the full-duplex flag, etc. */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070044int line_speed[MAX_UNITS] = { 0, 0, 0, 0 };
45static int full_duplex[MAX_UNITS] = { 1, 1, 1, 1 };
46static int rx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
47static int tx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
48static int auto_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
49static int tx_checksum[MAX_UNITS] = { 1, 1, 1, 1 };
50static int rx_checksum[MAX_UNITS] = { 1, 1, 1, 1 };
51static int auto_speed[MAX_UNITS] = { 1, 1, 1, 1 };
wdenkcc1c8a12002-11-02 22:58:18 +000052
53#if JUMBO_FRAMES
54/* Jumbo MTU for interfaces. */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070055static int mtu[MAX_UNITS] = { 0, 0, 0, 0 };
wdenkcc1c8a12002-11-02 22:58:18 +000056#endif
57
58/* Turn on Wake-on lan for a device unit */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070059static int enable_wol[MAX_UNITS] = { 0, 0, 0, 0 };
wdenkcc1c8a12002-11-02 22:58:18 +000060
61#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
62static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070063 { TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT };
wdenkcc1c8a12002-11-02 22:58:18 +000064
65#define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT
66static unsigned int rx_std_desc_cnt[MAX_UNITS] =
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070067 { RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT };
wdenkcc1c8a12002-11-02 22:58:18 +000068
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070069static unsigned int rx_adaptive_coalesce[MAX_UNITS] = { 1, 1, 1, 1 };
wdenkcc1c8a12002-11-02 22:58:18 +000070
71#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
72#define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT
73static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] =
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070074 { JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT };
wdenkcc1c8a12002-11-02 22:58:18 +000075#endif
76#define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS
77static unsigned int rx_coalesce_ticks[MAX_UNITS] =
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070078 { RX_COAL_TK, RX_COAL_TK, RX_COAL_TK, RX_COAL_TK };
wdenkcc1c8a12002-11-02 22:58:18 +000079
80#define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES
81static unsigned int rx_max_coalesce_frames[MAX_UNITS] =
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070082 { RX_COAL_FM, RX_COAL_FM, RX_COAL_FM, RX_COAL_FM };
wdenkcc1c8a12002-11-02 22:58:18 +000083
84#define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS
85static unsigned int tx_coalesce_ticks[MAX_UNITS] =
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070086 { TX_COAL_TK, TX_COAL_TK, TX_COAL_TK, TX_COAL_TK };
wdenkcc1c8a12002-11-02 22:58:18 +000087
88#define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES
89static unsigned int tx_max_coalesce_frames[MAX_UNITS] =
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070090 { TX_COAL_FM, TX_COAL_FM, TX_COAL_FM, TX_COAL_FM };
wdenkcc1c8a12002-11-02 22:58:18 +000091
92#define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS
93static unsigned int stats_coalesce_ticks[MAX_UNITS] =
Vadim Bendebury6ddfee52007-05-24 15:52:25 -070094 { ST_COAL_TK, ST_COAL_TK, ST_COAL_TK, ST_COAL_TK };
wdenkcc1c8a12002-11-02 22:58:18 +000095
wdenkcc1c8a12002-11-02 22:58:18 +000096/*
97 * Legitimate values for BCM570x device types
98 */
99typedef enum {
100 BCM5700VIGIL = 0,
101 BCM5700A6,
102 BCM5700T6,
103 BCM5700A9,
104 BCM5700T9,
105 BCM5700,
106 BCM5701A5,
107 BCM5701T1,
108 BCM5701T8,
109 BCM5701A7,
110 BCM5701A10,
111 BCM5701A12,
112 BCM5701,
113 BCM5702,
114 BCM5703,
115 BCM5703A31,
116 TC996T,
117 TC996ST,
118 TC996SSX,
119 TC996SX,
120 TC996BT,
121 TC997T,
122 TC997SX,
123 TC1000T,
124 TC940BR01,
125 TC942BR01,
126 NC6770,
127 NC7760,
128 NC7770,
129 NC7780
130} board_t;
131
132/* Chip-Rev names for each device-type */
133static struct {
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700134 char *name;
wdenkcc1c8a12002-11-02 22:58:18 +0000135} chip_rev[] = {
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700136 {
137 "BCM5700VIGIL"}, {
138 "BCM5700A6"}, {
139 "BCM5700T6"}, {
140 "BCM5700A9"}, {
141 "BCM5700T9"}, {
142 "BCM5700"}, {
143 "BCM5701A5"}, {
144 "BCM5701T1"}, {
145 "BCM5701T8"}, {
146 "BCM5701A7"}, {
147 "BCM5701A10"}, {
148 "BCM5701A12"}, {
149 "BCM5701"}, {
150 "BCM5702"}, {
151 "BCM5703"}, {
152 "BCM5703A31"}, {
153 "TC996T"}, {
154 "TC996ST"}, {
155 "TC996SSX"}, {
156 "TC996SX"}, {
157 "TC996BT"}, {
158 "TC997T"}, {
159 "TC997SX"}, {
160 "TC1000T"}, {
161 "TC940BR01"}, {
162 "TC942BR01"}, {
163 "NC6770"}, {
164 "NC7760"}, {
165 "NC7770"}, {
166 "NC7780"}, {
167 0}
wdenkcc1c8a12002-11-02 22:58:18 +0000168};
169
wdenkcc1c8a12002-11-02 22:58:18 +0000170/* indexed by board_t, above */
171static struct {
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700172 char *name;
wdenkcc1c8a12002-11-02 22:58:18 +0000173} board_info[] = {
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700174 {
175 "Broadcom Vigil B5700 1000Base-T"}, {
176 "Broadcom BCM5700 1000Base-T"}, {
177 "Broadcom BCM5700 1000Base-SX"}, {
178 "Broadcom BCM5700 1000Base-SX"}, {
179 "Broadcom BCM5700 1000Base-T"}, {
180 "Broadcom BCM5700"}, {
181 "Broadcom BCM5701 1000Base-T"}, {
182 "Broadcom BCM5701 1000Base-T"}, {
183 "Broadcom BCM5701 1000Base-T"}, {
184 "Broadcom BCM5701 1000Base-SX"}, {
185 "Broadcom BCM5701 1000Base-T"}, {
186 "Broadcom BCM5701 1000Base-T"}, {
187 "Broadcom BCM5701"}, {
188 "Broadcom BCM5702 1000Base-T"}, {
189 "Broadcom BCM5703 1000Base-T"}, {
190 "Broadcom BCM5703 1000Base-SX"}, {
191 "3Com 3C996 10/100/1000 Server NIC"}, {
192 "3Com 3C996 10/100/1000 Server NIC"}, {
193 "3Com 3C996 Gigabit Fiber-SX Server NIC"}, {
194 "3Com 3C996 Gigabit Fiber-SX Server NIC"}, {
195 "3Com 3C996B Gigabit Server NIC"}, {
196 "3Com 3C997 Gigabit Server NIC"}, {
197 "3Com 3C997 Gigabit Fiber-SX Server NIC"}, {
198 "3Com 3C1000 Gigabit NIC"}, {
199 "3Com 3C940 Gigabit LOM (21X21)"}, {
200 "3Com 3C942 Gigabit LOM (31X31)"}, {
201 "Compaq NC6770 Gigabit Server Adapter"}, {
202 "Compaq NC7760 Gigabit Server Adapter"}, {
203 "Compaq NC7770 Gigabit Server Adapter"}, {
204 "Compaq NC7780 Gigabit Server Adapter"}, {
2050},};
wdenkcc1c8a12002-11-02 22:58:18 +0000206
207/* PCI Devices which use the 570x chipset */
208struct pci_device_table {
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700209 unsigned short vendor_id, device_id; /* Vendor/DeviceID */
210 unsigned short subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
211 unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
212 unsigned long board_id; /* Data private to the driver */
213 int io_size, min_latency;
wdenkcc1c8a12002-11-02 22:58:18 +0000214} bcm570xDevices[] = {
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700215 {
216 0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL, 128, 32}, {
217 0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6, 128, 32}, {
218 0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6, 128, 32}, {
219 0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9, 128, 32}, {
220 0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9, 128, 32}, {
221 0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700, 128, 32}, {
222 0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700, 128, 32}, {
223 0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700, 128, 32}, {
224 0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700, 128, 32}, {
225 0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T, 128, 32}, {
226 0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST, 128, 32}, {
227 0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX, 128, 32}, {
228 0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T, 128, 32}, {
229 0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX, 128, 32}, {
230 0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01, 128, 32}, {
231 0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700, 128, 32}, {
232 0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5, 128, 32}, {
233 0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1, 128, 32}, {
234 0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8, 128, 32}, {
235 0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7, 128, 32}, {
236 0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10, 128, 32}, {
237 0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12, 128, 32}, {
238 0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770, 128, 32}, {
239 0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770, 128, 32}, {
240 0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780, 128, 32}, {
241 0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701, 128, 32}, {
242 0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX, 128, 32}, {
243 0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT, 128, 32}, {
244 0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T, 128, 32}, {
245 0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01, 128, 32}, {
246 0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701, 128, 32}, {
247 0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, {
248 0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, {
249 0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, {
250 0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, {
251 0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, {
252 0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, {
253 0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, {
254 0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, {
255 0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, {
256 0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, {
257 0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, {
258 0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, {
259 0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}, {
260 0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, {
261 0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, {
262 0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, {
263 0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, {
264 0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, {
265 0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, {
266 0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}
wdenkcc1c8a12002-11-02 22:58:18 +0000267};
268
269#define n570xDevices (sizeof(bcm570xDevices)/sizeof(bcm570xDevices[0]))
270
wdenkcc1c8a12002-11-02 22:58:18 +0000271/*
272 * Allocate a packet buffer from the bcm570x packet pool.
273 */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700274void *bcm570xPktAlloc (int u, int pksize)
wdenkcc1c8a12002-11-02 22:58:18 +0000275{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700276 return malloc (pksize);
wdenkcc1c8a12002-11-02 22:58:18 +0000277}
278
279/*
280 * Free a packet previously allocated from the bcm570x packet
281 * buffer pool.
282 */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700283void bcm570xPktFree (int u, void *p)
wdenkcc1c8a12002-11-02 22:58:18 +0000284{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700285 free (p);
wdenkcc1c8a12002-11-02 22:58:18 +0000286}
287
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700288int bcm570xReplenishRxBuffers (PUM_DEVICE_BLOCK pUmDevice)
wdenkcc1c8a12002-11-02 22:58:18 +0000289{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700290 PLM_PACKET pPacket;
291 PUM_PACKET pUmPacket;
292 void *skb;
293 int queue_rx = 0;
294 int ret = 0;
wdenkcc1c8a12002-11-02 22:58:18 +0000295
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700296 while ((pUmPacket = (PUM_PACKET)
297 QQ_PopHead (&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
wdenkcc1c8a12002-11-02 22:58:18 +0000298
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700299 pPacket = (PLM_PACKET) pUmPacket;
wdenkcc1c8a12002-11-02 22:58:18 +0000300
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700301 /* reuse an old skb */
302 if (pUmPacket->skbuff) {
303 QQ_PushTail (&pDevice->RxPacketFreeQ.Container,
304 pPacket);
305 queue_rx = 1;
306 continue;
307 }
308 if ((skb = bcm570xPktAlloc (pUmDevice->index,
309 pPacket->u.Rx.RxBufferSize + 2)) ==
310 0) {
311 QQ_PushHead (&pUmDevice->rx_out_of_buf_q.Container,
312 pPacket);
313 printf ("NOTICE: Out of RX memory.\n");
314 ret = 1;
315 break;
316 }
wdenkcc1c8a12002-11-02 22:58:18 +0000317
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700318 pUmPacket->skbuff = skb;
319 QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
320 queue_rx = 1;
321 }
wdenkcc1c8a12002-11-02 22:58:18 +0000322
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700323 if (queue_rx) {
324 LM_QueueRxPackets (pDevice);
325 }
wdenkcc1c8a12002-11-02 22:58:18 +0000326
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700327 return ret;
wdenkcc1c8a12002-11-02 22:58:18 +0000328}
329
330/*
331 * Probe, Map, and Init 570x device.
332 */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700333int eth_init (bd_t * bis)
wdenkcc1c8a12002-11-02 22:58:18 +0000334{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700335 int i, rv, devFound = FALSE;
336 pci_dev_t devbusfn;
337 unsigned short status;
wdenkcc1c8a12002-11-02 22:58:18 +0000338
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700339 /* Find PCI device, if it exists, configure ... */
340 for (i = 0; i < n570xDevices; i++) {
341 devbusfn = pci_find_device (bcm570xDevices[i].vendor_id,
342 bcm570xDevices[i].device_id, 0);
343 if (devbusfn == -1) {
344 continue; /* No device of that vendor/device ID */
345 } else {
wdenkcc1c8a12002-11-02 22:58:18 +0000346
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700347 /* Set ILINE */
348 pci_write_config_byte (devbusfn,
349 PCI_INTERRUPT_LINE,
350 BCM570X_ILINE);
wdenkcc1c8a12002-11-02 22:58:18 +0000351
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700352 /*
353 * 0x10 - 0x14 define one 64-bit MBAR.
354 * 0x14 is the higher-order address bits of the BAR.
355 */
356 pci_write_config_dword (devbusfn,
357 PCI_BASE_ADDRESS_1, 0);
wdenkcc1c8a12002-11-02 22:58:18 +0000358
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700359 ioBase = BCM570X_MBAR;
wdenkcc1c8a12002-11-02 22:58:18 +0000360
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700361 pci_write_config_dword (devbusfn,
362 PCI_BASE_ADDRESS_0, ioBase);
wdenkcc1c8a12002-11-02 22:58:18 +0000363
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700364 /*
365 * Enable PCI memory, IO, and Master -- don't
366 * reset any status bits in doing so.
367 */
368 pci_read_config_word (devbusfn, PCI_COMMAND, &status);
wdenkcc1c8a12002-11-02 22:58:18 +0000369
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700370 status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
wdenkcc1c8a12002-11-02 22:58:18 +0000371
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700372 pci_write_config_word (devbusfn, PCI_COMMAND, status);
wdenkcc1c8a12002-11-02 22:58:18 +0000373
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700374 printf
375 ("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n",
376 board_info[bcm570xDevices[i].board_id].name,
377 PCI_BUS (devbusfn), PCI_DEV (devbusfn),
378 PCI_FUNC (devbusfn), ioBase);
wdenkcc1c8a12002-11-02 22:58:18 +0000379
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700380 /* Allocate once, but always clear on init */
381 if (!pDevice) {
382 pDevice = malloc (sizeof (UM_DEVICE_BLOCK));
383 pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
384 memset (pDevice, 0x0, sizeof (UM_DEVICE_BLOCK));
385 }
wdenkcc1c8a12002-11-02 22:58:18 +0000386
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700387 /* Configure pci dev structure */
388 pUmDevice->pdev = devbusfn;
389 pUmDevice->index = 0;
390 pUmDevice->tx_pkt = 0;
391 pUmDevice->rx_pkt = 0;
392 devFound = TRUE;
393 break;
394 }
wdenkcc1c8a12002-11-02 22:58:18 +0000395 }
wdenkcc1c8a12002-11-02 22:58:18 +0000396
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700397 if (!devFound) {
398 printf
399 ("eth_init: FAILURE: no BCM570x Ethernet devices found.\n");
400 return -1;
401 }
wdenkcc1c8a12002-11-02 22:58:18 +0000402
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700403 /* Setup defaults for chip */
wdenkcc1c8a12002-11-02 22:58:18 +0000404 pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
wdenkcc1c8a12002-11-02 22:58:18 +0000405
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700406 if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) {
407 pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
408 } else {
409
410 if (rx_checksum[i]) {
411 pDevice->TaskToOffload |=
412 LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
413 LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
414 }
wdenkcc1c8a12002-11-02 22:58:18 +0000415
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700416 if (tx_checksum[i]) {
417 pDevice->TaskToOffload |=
418 LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
419 LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
420 pDevice->NoTxPseudoHdrChksum = TRUE;
421 }
wdenkcc1c8a12002-11-02 22:58:18 +0000422 }
wdenkcc1c8a12002-11-02 22:58:18 +0000423
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700424 /* Set Device PCI Memory base address */
425 pDevice->pMappedMemBase = (PLM_UINT8) ioBase;
wdenkcc1c8a12002-11-02 22:58:18 +0000426
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700427 /* Pull down adapter info */
428 if ((rv = LM_GetAdapterInfo (pDevice)) != LM_STATUS_SUCCESS) {
429 printf ("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv);
430 return -2;
431 }
wdenkcc1c8a12002-11-02 22:58:18 +0000432
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700433 /* Lock not needed */
434 pUmDevice->do_global_lock = 0;
wdenkcc1c8a12002-11-02 22:58:18 +0000435
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700436 if (T3_ASIC_REV (pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
437 /* The 5700 chip works best without interleaved register */
438 /* accesses on certain machines. */
439 pUmDevice->do_global_lock = 1;
440 }
wdenkcc1c8a12002-11-02 22:58:18 +0000441
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700442 /* Setup timer delays */
443 if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) {
444 pDevice->UseTaggedStatus = TRUE;
445 pUmDevice->timer_interval = CFG_HZ;
446 } else {
447 pUmDevice->timer_interval = CFG_HZ / 50;
448 }
wdenkcc1c8a12002-11-02 22:58:18 +0000449
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700450 /* Grab name .... */
451 pUmDevice->name =
452 (char *)malloc (strlen (board_info[bcm570xDevices[i].board_id].name)
453 + 1);
454 strcpy (pUmDevice->name, board_info[bcm570xDevices[i].board_id].name);
wdenkcc1c8a12002-11-02 22:58:18 +0000455
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700456 memcpy (pDevice->NodeAddress, bis->bi_enetaddr, 6);
457 LM_SetMacAddress (pDevice, bis->bi_enetaddr);
458 /* Init queues .. */
459 QQ_InitQueue (&pUmDevice->rx_out_of_buf_q.Container,
460 MAX_RX_PACKET_DESC_COUNT);
461 pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0;
wdenkcc1c8a12002-11-02 22:58:18 +0000462
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700463 /* delay for 4 seconds */
464 pUmDevice->delayed_link_ind = (4 * CFG_HZ) / pUmDevice->timer_interval;
wdenkcc1c8a12002-11-02 22:58:18 +0000465
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700466 pUmDevice->adaptive_expiry = CFG_HZ / pUmDevice->timer_interval;
wdenkcc1c8a12002-11-02 22:58:18 +0000467
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700468 /* Sometimes we get spurious ints. after reset when link is down. */
469 /* This field tells the isr to service the int. even if there is */
470 /* no status block update. */
471 pUmDevice->adapter_just_inited =
472 (3 * CFG_HZ) / pUmDevice->timer_interval;
wdenkcc1c8a12002-11-02 22:58:18 +0000473
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700474 /* Initialize 570x */
475 if (LM_InitializeAdapter (pDevice) != LM_STATUS_SUCCESS) {
476 printf ("ERROR: Adapter initialization failed.\n");
477 return ERROR;
478 }
wdenkcc1c8a12002-11-02 22:58:18 +0000479
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700480 /* Enable chip ISR */
481 LM_EnableInterrupt (pDevice);
wdenkcc1c8a12002-11-02 22:58:18 +0000482
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700483 /* Clear MC table */
484 LM_MulticastClear (pDevice);
wdenkcc1c8a12002-11-02 22:58:18 +0000485
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700486 /* Enable Multicast */
487 LM_SetReceiveMask (pDevice,
488 pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
wdenkcc1c8a12002-11-02 22:58:18 +0000489
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700490 pUmDevice->opened = 1;
491 pUmDevice->tx_full = 0;
492 pUmDevice->tx_pkt = 0;
493 pUmDevice->rx_pkt = 0;
494 printf ("eth%d: %s @0x%lx,",
495 pDevice->index, pUmDevice->name, (unsigned long)ioBase);
496 printf ("node addr ");
497 for (i = 0; i < 6; i++) {
498 printf ("%2.2x", pDevice->NodeAddress[i]);
499 }
500 printf ("\n");
wdenkcc1c8a12002-11-02 22:58:18 +0000501
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700502 printf ("eth%d: ", pDevice->index);
503 printf ("%s with ", chip_rev[bcm570xDevices[i].board_id].name);
wdenkcc1c8a12002-11-02 22:58:18 +0000504
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700505 if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
506 printf ("Broadcom BCM5400 Copper ");
507 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
508 printf ("Broadcom BCM5401 Copper ");
509 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
510 printf ("Broadcom BCM5411 Copper ");
511 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID)
512 printf ("Broadcom BCM5701 Integrated Copper ");
513 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID)
514 printf ("Broadcom BCM5703 Integrated Copper ");
515 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
516 printf ("Broadcom BCM8002 SerDes ");
517 else if (pDevice->EnableTbi)
518 printf ("Agilent HDMP-1636 SerDes ");
519 else
520 printf ("Unknown ");
521 printf ("transceiver found\n");
wdenkcc1c8a12002-11-02 22:58:18 +0000522
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700523 printf ("eth%d: %s, MTU: %d,",
524 pDevice->index, pDevice->BusSpeedStr, 1500);
wdenkcc1c8a12002-11-02 22:58:18 +0000525
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700526 if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) && rx_checksum[i])
527 printf ("Rx Checksum ON\n");
528 else
529 printf ("Rx Checksum OFF\n");
530 initialized++;
wdenkcc1c8a12002-11-02 22:58:18 +0000531
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700532 return 0;
wdenkcc1c8a12002-11-02 22:58:18 +0000533}
534
535/* Ethernet Interrupt service routine */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700536void eth_isr (void)
wdenkcc1c8a12002-11-02 22:58:18 +0000537{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700538 LM_UINT32 oldtag, newtag;
539 int i;
wdenkcc1c8a12002-11-02 22:58:18 +0000540
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700541 pUmDevice->interrupt = 1;
wdenkcc1c8a12002-11-02 22:58:18 +0000542
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700543 if (pDevice->UseTaggedStatus) {
544 if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
545 pUmDevice->adapter_just_inited) {
546 MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 1);
547 oldtag = pDevice->pStatusBlkVirt->StatusTag;
wdenkcc1c8a12002-11-02 22:58:18 +0000548
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700549 for (i = 0;; i++) {
550 pDevice->pStatusBlkVirt->Status &=
551 ~STATUS_BLOCK_UPDATED;
552 LM_ServiceInterrupts (pDevice);
553 newtag = pDevice->pStatusBlkVirt->StatusTag;
554 if ((newtag == oldtag) || (i > 50)) {
555 MB_REG_WR (pDevice,
556 Mailbox.Interrupt[0].Low,
557 newtag << 24);
558 if (pDevice->UndiFix) {
559 REG_WR (pDevice, Grc.LocalCtrl,
560 pDevice->
561 GrcLocalCtrl | 0x2);
562 }
563 break;
564 }
565 oldtag = newtag;
566 }
567 }
568 } else {
569 while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
570 unsigned int dummy;
wdenkcc1c8a12002-11-02 22:58:18 +0000571
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700572 pDevice->pMemView->Mailbox.Interrupt[0].Low = 1;
573 pDevice->pStatusBlkVirt->Status &=
574 ~STATUS_BLOCK_UPDATED;
575 LM_ServiceInterrupts (pDevice);
576 pDevice->pMemView->Mailbox.Interrupt[0].Low = 0;
577 dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low;
578 }
wdenkcc1c8a12002-11-02 22:58:18 +0000579 }
wdenkcc1c8a12002-11-02 22:58:18 +0000580
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700581 /* Allocate new RX buffers */
582 if (QQ_GetEntryCnt (&pUmDevice->rx_out_of_buf_q.Container)) {
583 bcm570xReplenishRxBuffers (pUmDevice);
584 }
wdenkcc1c8a12002-11-02 22:58:18 +0000585
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700586 /* Queue packets */
587 if (QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container)) {
588 LM_QueueRxPackets (pDevice);
589 }
wdenkcc1c8a12002-11-02 22:58:18 +0000590
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700591 if (pUmDevice->tx_queued) {
592 pUmDevice->tx_queued = 0;
593 }
wdenkcc1c8a12002-11-02 22:58:18 +0000594
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700595 if (pUmDevice->tx_full) {
596 if (pDevice->LinkStatus != LM_STATUS_LINK_DOWN) {
597 printf
598 ("NOTICE: tx was previously blocked, restarting MUX\n");
599 pUmDevice->tx_full = 0;
600 }
wdenkcc1c8a12002-11-02 22:58:18 +0000601 }
wdenkcc1c8a12002-11-02 22:58:18 +0000602
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700603 pUmDevice->interrupt = 0;
wdenkcc1c8a12002-11-02 22:58:18 +0000604
605}
606
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700607int eth_send (volatile void *packet, int length)
wdenkcc1c8a12002-11-02 22:58:18 +0000608{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700609 int status = 0;
wdenkcc1c8a12002-11-02 22:58:18 +0000610#if ET_DEBUG
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700611 unsigned char *ptr = (unsigned char *)packet;
wdenkcc1c8a12002-11-02 22:58:18 +0000612#endif
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700613 PLM_PACKET pPacket;
614 PUM_PACKET pUmPacket;
wdenkcc1c8a12002-11-02 22:58:18 +0000615
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700616 /* Link down, return */
617 while (pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {
wdenkcc1c8a12002-11-02 22:58:18 +0000618#if 0
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700619 printf ("eth%d: link down - check cable or link partner.\n",
620 pUmDevice->index);
wdenkcc1c8a12002-11-02 22:58:18 +0000621#endif
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700622 eth_isr ();
wdenkcc1c8a12002-11-02 22:58:18 +0000623
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700624 /* Wait to see link for one-half a second before sending ... */
625 udelay (1500000);
wdenkcc1c8a12002-11-02 22:58:18 +0000626
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700627 }
wdenkcc1c8a12002-11-02 22:58:18 +0000628
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700629 /* Clear sent flag */
630 pUmDevice->tx_pkt = 0;
wdenkcc1c8a12002-11-02 22:58:18 +0000631
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700632 /* Previously blocked */
633 if (pUmDevice->tx_full) {
634 printf ("eth%d: tx blocked.\n", pUmDevice->index);
635 return 0;
636 }
wdenkcc1c8a12002-11-02 22:58:18 +0000637
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700638 pPacket = (PLM_PACKET)
639 QQ_PopHead (&pDevice->TxPacketFreeQ.Container);
wdenkcc1c8a12002-11-02 22:58:18 +0000640
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700641 if (pPacket == 0) {
642 pUmDevice->tx_full = 1;
643 printf ("bcm570xEndSend: TX full!\n");
644 return 0;
645 }
wdenkcc1c8a12002-11-02 22:58:18 +0000646
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700647 if (pDevice->SendBdLeft.counter == 0) {
648 pUmDevice->tx_full = 1;
649 printf ("bcm570xEndSend: no more TX descriptors!\n");
650 QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
651 return 0;
wdenkcc1c8a12002-11-02 22:58:18 +0000652 }
wdenkcc1c8a12002-11-02 22:58:18 +0000653
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700654 if (length <= 0) {
655 printf ("eth: bad packet size: %d\n", length);
656 goto out;
657 }
wdenkcc1c8a12002-11-02 22:58:18 +0000658
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700659 /* Get packet buffers and fragment list */
660 pUmPacket = (PUM_PACKET) pPacket;
661 /* Single DMA Descriptor transmit.
662 * Fragments may be provided, but one DMA descriptor max is
663 * used to send the packet.
wdenk57b2d802003-06-27 21:31:46 +0000664 */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700665 if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) {
666 if (pUmPacket->skbuff == NULL) {
667 /* Packet was discarded */
668 printf ("TX: failed (1)\n");
669 status = 1;
670 } else {
671 printf ("TX: failed (2)\n");
672 status = 2;
673 }
674 QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
675 return status;
wdenkcc1c8a12002-11-02 22:58:18 +0000676 }
677
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700678 /* Copy packet to DMA buffer */
679 memset (pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE);
680 memcpy ((void *)pUmPacket->skbuff, (void *)packet, length);
681 pPacket->PacketSize = length;
682 pPacket->Flags |= SND_BD_FLAG_END | SND_BD_FLAG_COAL_NOW;
683 pPacket->u.Tx.FragCount = 1;
684 /* We've already provided a frame ready for transmission */
685 pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
686
687 if (LM_SendPacket (pDevice, pPacket) == LM_STATUS_FAILURE) {
688 /*
689 * A lower level send failure will push the packet descriptor back
690 * in the free queue, so just deal with the VxWorks clusters.
691 */
692 if (pUmPacket->skbuff == NULL) {
693 printf ("TX failed (1)!\n");
694 /* Packet was discarded */
695 status = 3;
696 } else {
697 /* A resource problem ... */
698 printf ("TX failed (2)!\n");
699 status = 4;
700 }
701
702 if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) == 0) {
703 printf ("TX: emptyQ!\n");
704 pUmDevice->tx_full = 1;
705 }
wdenkcc1c8a12002-11-02 22:58:18 +0000706 }
wdenkcc1c8a12002-11-02 22:58:18 +0000707
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700708 while (pUmDevice->tx_pkt == 0) {
709 /* Service TX */
710 eth_isr ();
711 }
wdenkcc1c8a12002-11-02 22:58:18 +0000712#if ET_DEBUG
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700713 printf ("eth_send: 0x%x, %d bytes\n"
714 "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n",
715 (int)pPacket, length,
716 ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5],
717 ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12],
718 ptr[13], ptr[14], ptr[15]);
wdenkcc1c8a12002-11-02 22:58:18 +0000719#endif
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700720 pUmDevice->tx_pkt = 0;
721 QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
wdenkcc1c8a12002-11-02 22:58:18 +0000722
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700723 /* Done with send */
724 out:
725 return status;
wdenkcc1c8a12002-11-02 22:58:18 +0000726}
727
wdenkcc1c8a12002-11-02 22:58:18 +0000728/* Ethernet receive */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700729int eth_rx (void)
wdenkcc1c8a12002-11-02 22:58:18 +0000730{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700731 PLM_PACKET pPacket = NULL;
732 PUM_PACKET pUmPacket = NULL;
733 void *skb;
734 int size = 0;
wdenkcc1c8a12002-11-02 22:58:18 +0000735
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700736 while (TRUE) {
wdenkcc1c8a12002-11-02 22:58:18 +0000737
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700738 bcm570x_service_isr:
739 /* Pull down packet if it is there */
740 eth_isr ();
wdenkcc1c8a12002-11-02 22:58:18 +0000741
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700742 /* Indicate RX packets called */
743 if (pUmDevice->rx_pkt) {
744 /* printf("eth_rx: got a packet...\n"); */
745 pUmDevice->rx_pkt = 0;
746 } else {
747 /* printf("eth_rx: waiting for packet...\n"); */
748 goto bcm570x_service_isr;
749 }
wdenkcc1c8a12002-11-02 22:58:18 +0000750
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700751 pPacket = (PLM_PACKET)
752 QQ_PopHead (&pDevice->RxPacketReceivedQ.Container);
wdenkcc1c8a12002-11-02 22:58:18 +0000753
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700754 if (pPacket == 0) {
755 printf ("eth_rx: empty packet!\n");
756 goto bcm570x_service_isr;
757 }
wdenkcc1c8a12002-11-02 22:58:18 +0000758
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700759 pUmPacket = (PUM_PACKET) pPacket;
wdenkcc1c8a12002-11-02 22:58:18 +0000760#if ET_DEBUG
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700761 printf ("eth_rx: packet @0x%x\n", (int)pPacket);
wdenkcc1c8a12002-11-02 22:58:18 +0000762#endif
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700763 /* If the packet generated an error, reuse buffer */
764 if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
765 ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
wdenkcc1c8a12002-11-02 22:58:18 +0000766
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700767 /* reuse skb */
768 QQ_PushTail (&pDevice->RxPacketFreeQ.Container,
769 pPacket);
770 printf ("eth_rx: error in packet dma!\n");
771 goto bcm570x_service_isr;
772 }
wdenkcc1c8a12002-11-02 22:58:18 +0000773
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700774 /* Set size and address */
775 skb = pUmPacket->skbuff;
776 size = pPacket->PacketSize;
wdenkcc1c8a12002-11-02 22:58:18 +0000777
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700778 /* Pass the packet up to the protocol
779 * layers.
780 */
781 NetReceive (skb, size);
wdenkcc1c8a12002-11-02 22:58:18 +0000782
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700783 /* Free packet buffer */
784 bcm570xPktFree (pUmDevice->index, skb);
785 pUmPacket->skbuff = NULL;
wdenkcc1c8a12002-11-02 22:58:18 +0000786
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700787 /* Reuse SKB */
788 QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
wdenkcc1c8a12002-11-02 22:58:18 +0000789
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700790 return 0; /* Got a packet, bail ... */
791 }
792 return size;
wdenkcc1c8a12002-11-02 22:58:18 +0000793}
794
wdenkcc1c8a12002-11-02 22:58:18 +0000795/* Shut down device */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700796void eth_halt (void)
wdenkcc1c8a12002-11-02 22:58:18 +0000797{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700798 int i;
799 if (initialized)
800 if (pDevice && pUmDevice && pUmDevice->opened) {
801 printf ("\neth%d:%s,", pUmDevice->index,
802 pUmDevice->name);
803 printf ("HALT,");
804 /* stop device */
805 LM_Halt (pDevice);
806 printf ("POWER DOWN,");
807 LM_SetPowerState (pDevice, LM_POWER_STATE_D3);
wdenkcc1c8a12002-11-02 22:58:18 +0000808
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700809 /* Free the memory allocated by the device in tigon3 */
810 for (i = 0; i < pUmDevice->mem_list_num; i++) {
811 if (pUmDevice->mem_list[i]) {
812 /* sanity check */
813 if (pUmDevice->dma_list[i]) { /* cache-safe memory */
814 free (pUmDevice->mem_list[i]);
815 } else {
816 free (pUmDevice->mem_list[i]); /* normal memory */
817 }
818 }
819 }
820 pUmDevice->opened = 0;
821 free (pDevice);
822 pDevice = NULL;
823 pUmDevice = NULL;
824 initialized = 0;
825 printf ("done - offline.\n");
wdenkcc1c8a12002-11-02 22:58:18 +0000826 }
wdenkcc1c8a12002-11-02 22:58:18 +0000827}
828
wdenkcc1c8a12002-11-02 22:58:18 +0000829/*
830 *
831 * Middle Module: Interface between the HW driver (tigon3 modules) and
832 * the native (SENS) driver. These routines implement the system
833 * interface for tigon3 on VxWorks.
834 */
835
836/* Middle module dependency - size of a packet descriptor */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700837int MM_Packet_Desc_Size = sizeof (UM_PACKET);
wdenkcc1c8a12002-11-02 22:58:18 +0000838
839LM_STATUS
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700840MM_ReadConfig32 (PLM_DEVICE_BLOCK pDevice,
841 LM_UINT32 Offset, LM_UINT32 * pValue32)
wdenkcc1c8a12002-11-02 22:58:18 +0000842{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700843 UM_DEVICE_BLOCK *pUmDevice;
844 pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
845 pci_read_config_dword (pUmDevice->pdev, Offset, (u32 *) pValue32);
846 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +0000847}
848
wdenkcc1c8a12002-11-02 22:58:18 +0000849LM_STATUS
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700850MM_WriteConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 Value32)
wdenkcc1c8a12002-11-02 22:58:18 +0000851{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700852 UM_DEVICE_BLOCK *pUmDevice;
853 pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
854 pci_write_config_dword (pUmDevice->pdev, Offset, Value32);
855 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +0000856}
857
wdenkcc1c8a12002-11-02 22:58:18 +0000858LM_STATUS
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700859MM_ReadConfig16 (PLM_DEVICE_BLOCK pDevice,
860 LM_UINT32 Offset, LM_UINT16 * pValue16)
wdenkcc1c8a12002-11-02 22:58:18 +0000861{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700862 UM_DEVICE_BLOCK *pUmDevice;
863 pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
864 pci_read_config_word (pUmDevice->pdev, Offset, (u16 *) pValue16);
865 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +0000866}
867
868LM_STATUS
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700869MM_WriteConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT16 Value16)
wdenkcc1c8a12002-11-02 22:58:18 +0000870{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700871 UM_DEVICE_BLOCK *pUmDevice;
872 pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
873 pci_write_config_word (pUmDevice->pdev, Offset, Value16);
874 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +0000875}
876
wdenkcc1c8a12002-11-02 22:58:18 +0000877LM_STATUS
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700878MM_AllocateSharedMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
879 PLM_VOID * pMemoryBlockVirt,
880 PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, LM_BOOL Cached)
wdenkcc1c8a12002-11-02 22:58:18 +0000881{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700882 PLM_VOID pvirt;
883 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
884 dma_addr_t mapping;
wdenkcc1c8a12002-11-02 22:58:18 +0000885
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700886 pvirt = malloc (BlockSize);
887 mapping = (dma_addr_t) (pvirt);
888 if (!pvirt)
889 return LM_STATUS_FAILURE;
wdenkcc1c8a12002-11-02 22:58:18 +0000890
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700891 pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
892 pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
893 pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
894 memset (pvirt, 0, BlockSize);
wdenkcc1c8a12002-11-02 22:58:18 +0000895
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700896 *pMemoryBlockVirt = (PLM_VOID) pvirt;
897 MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping);
wdenkcc1c8a12002-11-02 22:58:18 +0000898
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700899 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +0000900}
901
wdenkcc1c8a12002-11-02 22:58:18 +0000902LM_STATUS
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700903MM_AllocateMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
904 PLM_VOID * pMemoryBlockVirt)
wdenkcc1c8a12002-11-02 22:58:18 +0000905{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700906 PLM_VOID pvirt;
907 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
wdenkcc1c8a12002-11-02 22:58:18 +0000908
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700909 pvirt = malloc (BlockSize);
wdenkcc1c8a12002-11-02 22:58:18 +0000910
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700911 if (!pvirt)
912 return LM_STATUS_FAILURE;
wdenkcc1c8a12002-11-02 22:58:18 +0000913
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700914 pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
915 pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
916 pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
917 memset (pvirt, 0, BlockSize);
918 *pMemoryBlockVirt = pvirt;
wdenkcc1c8a12002-11-02 22:58:18 +0000919
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700920 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +0000921}
922
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700923LM_STATUS MM_MapMemBase (PLM_DEVICE_BLOCK pDevice)
wdenkcc1c8a12002-11-02 22:58:18 +0000924{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700925 printf ("BCM570x PCI Memory base address @0x%x\n",
926 (unsigned int)pDevice->pMappedMemBase);
927 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +0000928}
929
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700930LM_STATUS MM_InitializeUmPackets (PLM_DEVICE_BLOCK pDevice)
wdenkcc1c8a12002-11-02 22:58:18 +0000931{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700932 int i;
933 void *skb;
934 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
935 PUM_PACKET pUmPacket = NULL;
936 PLM_PACKET pPacket = NULL;
wdenkcc1c8a12002-11-02 22:58:18 +0000937
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700938 for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
939 pPacket = QQ_PopHead (&pDevice->RxPacketFreeQ.Container);
940 pUmPacket = (PUM_PACKET) pPacket;
wdenkcc1c8a12002-11-02 22:58:18 +0000941
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700942 if (pPacket == 0) {
943 printf ("MM_InitializeUmPackets: Bad RxPacketFreeQ\n");
944 }
wdenkcc1c8a12002-11-02 22:58:18 +0000945
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700946 skb = bcm570xPktAlloc (pUmDevice->index,
947 pPacket->u.Rx.RxBufferSize + 2);
wdenkcc1c8a12002-11-02 22:58:18 +0000948
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700949 if (skb == 0) {
950 pUmPacket->skbuff = 0;
951 QQ_PushTail (&pUmDevice->rx_out_of_buf_q.Container,
952 pPacket);
953 printf ("MM_InitializeUmPackets: out of buffer.\n");
954 continue;
955 }
wdenkcc1c8a12002-11-02 22:58:18 +0000956
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700957 pUmPacket->skbuff = skb;
958 QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
959 }
wdenkcc1c8a12002-11-02 22:58:18 +0000960
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700961 pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8;
wdenkcc1c8a12002-11-02 22:58:18 +0000962
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700963 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +0000964}
965
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700966LM_STATUS MM_GetConfig (PLM_DEVICE_BLOCK pDevice)
wdenkcc1c8a12002-11-02 22:58:18 +0000967{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700968 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
969 int index = pDevice->index;
wdenkcc1c8a12002-11-02 22:58:18 +0000970
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700971 if (auto_speed[index] == 0)
972 pDevice->DisableAutoNeg = TRUE;
973 else
974 pDevice->DisableAutoNeg = FALSE;
wdenkcc1c8a12002-11-02 22:58:18 +0000975
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700976 if (line_speed[index] == 0) {
977 pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO;
wdenkcc1c8a12002-11-02 22:58:18 +0000978 pDevice->DisableAutoNeg = FALSE;
Vadim Bendebury6ddfee52007-05-24 15:52:25 -0700979 } else {
980 if (line_speed[index] == 1000) {
981 if (pDevice->EnableTbi) {
982 pDevice->RequestedMediaType =
983 LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX;
984 } else if (full_duplex[index]) {
985 pDevice->RequestedMediaType =
986 LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX;
987 } else {
988 pDevice->RequestedMediaType =
989 LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS;
990 }
991 if (!pDevice->EnableTbi)
992 pDevice->DisableAutoNeg = FALSE;
993 } else if (line_speed[index] == 100) {
994 if (full_duplex[index]) {
995 pDevice->RequestedMediaType =
996 LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX;
997 } else {
998 pDevice->RequestedMediaType =
999 LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS;
1000 }
1001 } else if (line_speed[index] == 10) {
1002 if (full_duplex[index]) {
1003 pDevice->RequestedMediaType =
1004 LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX;
1005 } else {
1006 pDevice->RequestedMediaType =
1007 LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
1008 }
1009 } else {
1010 pDevice->RequestedMediaType =
1011 LM_REQUESTED_MEDIA_TYPE_AUTO;
1012 pDevice->DisableAutoNeg = FALSE;
1013 }
1014
wdenkcc1c8a12002-11-02 22:58:18 +00001015 }
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001016 pDevice->FlowControlCap = 0;
1017 if (rx_flow_control[index] != 0) {
1018 pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
wdenkcc1c8a12002-11-02 22:58:18 +00001019 }
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001020 if (tx_flow_control[index] != 0) {
1021 pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
wdenkcc1c8a12002-11-02 22:58:18 +00001022 }
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001023 if ((auto_flow_control[index] != 0) &&
1024 (pDevice->DisableAutoNeg == FALSE)) {
wdenkcc1c8a12002-11-02 22:58:18 +00001025
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001026 pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
1027 if ((tx_flow_control[index] == 0) &&
1028 (rx_flow_control[index] == 0)) {
1029 pDevice->FlowControlCap |=
1030 LM_FLOW_CONTROL_TRANSMIT_PAUSE |
1031 LM_FLOW_CONTROL_RECEIVE_PAUSE;
1032 }
wdenkcc1c8a12002-11-02 22:58:18 +00001033 }
wdenkcc1c8a12002-11-02 22:58:18 +00001034
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001035 /* Default MTU for now */
1036 pUmDevice->mtu = 1500;
wdenkcc1c8a12002-11-02 22:58:18 +00001037
1038#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001039 if (pUmDevice->mtu > 1500) {
1040 pDevice->RxMtu = pUmDevice->mtu;
1041 pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
1042 } else {
1043 pDevice->RxJumboDescCnt = 0;
1044 }
1045 pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
wdenkcc1c8a12002-11-02 22:58:18 +00001046#else
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001047 pDevice->RxMtu = pUmDevice->mtu;
wdenkcc1c8a12002-11-02 22:58:18 +00001048#endif
1049
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001050 if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) {
1051 pDevice->UseTaggedStatus = TRUE;
1052 pUmDevice->timer_interval = CFG_HZ;
1053 } else {
1054 pUmDevice->timer_interval = CFG_HZ / 50;
1055 }
wdenkcc1c8a12002-11-02 22:58:18 +00001056
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001057 pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
1058 pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
1059 /* Note: adaptive coalescence really isn't adaptive in this driver */
1060 pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index];
1061 if (!pUmDevice->rx_adaptive_coalesce) {
1062 pDevice->RxCoalescingTicks = rx_coalesce_ticks[index];
1063 if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS)
1064 pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS;
1065 pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks;
wdenkcc1c8a12002-11-02 22:58:18 +00001066
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001067 pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index];
1068 if (pDevice->RxMaxCoalescedFrames > MAX_RX_MAX_COALESCED_FRAMES)
1069 pDevice->RxMaxCoalescedFrames =
1070 MAX_RX_MAX_COALESCED_FRAMES;
1071 pUmDevice->rx_curr_coalesce_frames =
1072 pDevice->RxMaxCoalescedFrames;
1073 pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
1074 if (pDevice->StatsCoalescingTicks > MAX_STATS_COALESCING_TICKS)
1075 pDevice->StatsCoalescingTicks =
1076 MAX_STATS_COALESCING_TICKS;
1077 } else {
1078 pUmDevice->rx_curr_coalesce_frames =
1079 DEFAULT_RX_MAX_COALESCED_FRAMES;
1080 pUmDevice->rx_curr_coalesce_ticks = DEFAULT_RX_COALESCING_TICKS;
wdenkcc1c8a12002-11-02 22:58:18 +00001081 }
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001082 pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
1083 if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS)
1084 pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS;
1085 pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
1086 if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES)
1087 pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES;
wdenkcc1c8a12002-11-02 22:58:18 +00001088
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001089 if (enable_wol[index]) {
1090 pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
1091 pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
1092 }
1093 pDevice->NicSendBd = TRUE;
wdenkcc1c8a12002-11-02 22:58:18 +00001094
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001095 /* Don't update status blocks during interrupt */
1096 pDevice->RxCoalescingTicksDuringInt = 0;
1097 pDevice->TxCoalescingTicksDuringInt = 0;
wdenkcc1c8a12002-11-02 22:58:18 +00001098
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001099 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +00001100
1101}
1102
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001103LM_STATUS MM_StartTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
wdenkcc1c8a12002-11-02 22:58:18 +00001104{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001105 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1106 printf ("Start TX DMA: dev=%d packet @0x%x\n",
1107 (int)pUmDevice->index, (unsigned int)pPacket);
wdenkcc1c8a12002-11-02 22:58:18 +00001108
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001109 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +00001110}
1111
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001112LM_STATUS MM_CompleteTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
wdenkcc1c8a12002-11-02 22:58:18 +00001113{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001114 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1115 printf ("Complete TX DMA: dev=%d packet @0x%x\n",
1116 (int)pUmDevice->index, (unsigned int)pPacket);
1117 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +00001118}
1119
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001120LM_STATUS MM_IndicateStatus (PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
wdenkcc1c8a12002-11-02 22:58:18 +00001121{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001122 char buf[128];
1123 char lcd[4];
1124 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1125 LM_FLOW_CONTROL flow_control;
wdenkcc1c8a12002-11-02 22:58:18 +00001126
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001127 pUmDevice->delayed_link_ind = 0;
1128 memset (lcd, 0x0, 4);
wdenkcc1c8a12002-11-02 22:58:18 +00001129
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001130 if (Status == LM_STATUS_LINK_DOWN) {
1131 sprintf (buf, "eth%d: %s: NIC Link is down\n",
1132 pUmDevice->index, pUmDevice->name);
1133 lcd[0] = 'L';
1134 lcd[1] = 'N';
1135 lcd[2] = 'K';
1136 lcd[3] = '?';
1137 } else if (Status == LM_STATUS_LINK_ACTIVE) {
1138 sprintf (buf, "eth%d:%s: ", pUmDevice->index, pUmDevice->name);
wdenkcc1c8a12002-11-02 22:58:18 +00001139
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001140 if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) {
1141 strcat (buf, "1000 Mbps ");
1142 lcd[0] = '1';
1143 lcd[1] = 'G';
1144 lcd[2] = 'B';
1145 } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) {
1146 strcat (buf, "100 Mbps ");
1147 lcd[0] = '1';
1148 lcd[1] = '0';
1149 lcd[2] = '0';
1150 } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) {
1151 strcat (buf, "10 Mbps ");
1152 lcd[0] = '1';
1153 lcd[1] = '0';
1154 lcd[2] = ' ';
1155 }
1156 if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) {
1157 strcat (buf, "full duplex");
1158 lcd[3] = 'F';
1159 } else {
1160 strcat (buf, "half duplex");
1161 lcd[3] = 'H';
1162 }
1163 strcat (buf, " link up");
wdenkcc1c8a12002-11-02 22:58:18 +00001164
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001165 flow_control = pDevice->FlowControl &
1166 (LM_FLOW_CONTROL_RECEIVE_PAUSE |
1167 LM_FLOW_CONTROL_TRANSMIT_PAUSE);
wdenkcc1c8a12002-11-02 22:58:18 +00001168
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001169 if (flow_control) {
1170 if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
1171 strcat (buf, ", receive ");
1172 if (flow_control &
1173 LM_FLOW_CONTROL_TRANSMIT_PAUSE)
1174 strcat (buf, " & transmit ");
1175 } else {
1176 strcat (buf, ", transmit ");
1177 }
1178 strcat (buf, "flow control ON");
1179 } else {
1180 strcat (buf, ", flow control OFF");
1181 }
1182 strcat (buf, "\n");
1183 printf ("%s", buf);
wdenkcc1c8a12002-11-02 22:58:18 +00001184 }
wdenkcc1c8a12002-11-02 22:58:18 +00001185#if 0
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001186 sysLedDsply (lcd[0], lcd[1], lcd[2], lcd[3]);
wdenkcc1c8a12002-11-02 22:58:18 +00001187#endif
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001188 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +00001189}
1190
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001191LM_STATUS MM_FreeRxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
wdenkcc1c8a12002-11-02 22:58:18 +00001192{
1193
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001194 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1195 PUM_PACKET pUmPacket;
1196 void *skb;
wdenkcc1c8a12002-11-02 22:58:18 +00001197
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001198 pUmPacket = (PUM_PACKET) pPacket;
wdenkcc1c8a12002-11-02 22:58:18 +00001199
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001200 if ((skb = pUmPacket->skbuff))
1201 bcm570xPktFree (pUmDevice->index, skb);
wdenkcc1c8a12002-11-02 22:58:18 +00001202
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001203 pUmPacket->skbuff = 0;
wdenkcc1c8a12002-11-02 22:58:18 +00001204
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001205 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +00001206}
1207
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001208unsigned long MM_AnGetCurrentTime_us (PAN_STATE_INFO pAnInfo)
wdenkcc1c8a12002-11-02 22:58:18 +00001209{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001210 return get_timer (0);
wdenkcc1c8a12002-11-02 22:58:18 +00001211}
1212
1213/*
1214 * Transform an MBUF chain into a single MBUF.
1215 * This routine will fail if the amount of data in the
1216 * chain overflows a transmit buffer. In that case,
1217 * the incoming MBUF chain will be freed. This routine can
1218 * also fail by not being able to allocate a new MBUF (including
1219 * cluster and mbuf headers). In that case the failure is
1220 * non-fatal. The incoming cluster chain is not freed, giving
1221 * the caller the choice of whether to try a retransmit later.
1222 */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001223LM_STATUS MM_CoalesceTxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
wdenkcc1c8a12002-11-02 22:58:18 +00001224{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001225 PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
1226 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1227 void *skbnew;
1228 int len = 0;
wdenkcc1c8a12002-11-02 22:58:18 +00001229
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001230 if (len == 0)
1231 return (LM_STATUS_SUCCESS);
wdenkcc1c8a12002-11-02 22:58:18 +00001232
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001233 if (len > MAX_PACKET_SIZE) {
1234 printf ("eth%d: xmit frame discarded, too big!, size = %d\n",
1235 pUmDevice->index, len);
1236 return (LM_STATUS_FAILURE);
1237 }
wdenkcc1c8a12002-11-02 22:58:18 +00001238
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001239 skbnew = bcm570xPktAlloc (pUmDevice->index, MAX_PACKET_SIZE);
wdenkcc1c8a12002-11-02 22:58:18 +00001240
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001241 if (skbnew == NULL) {
1242 pUmDevice->tx_full = 1;
1243 printf ("eth%d: out of transmit buffers", pUmDevice->index);
1244 return (LM_STATUS_FAILURE);
1245 }
wdenkcc1c8a12002-11-02 22:58:18 +00001246
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001247 /* New packet values */
1248 pUmPacket->skbuff = skbnew;
1249 pUmPacket->lm_packet.u.Tx.FragCount = 1;
wdenkcc1c8a12002-11-02 22:58:18 +00001250
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001251 return (LM_STATUS_SUCCESS);
wdenkcc1c8a12002-11-02 22:58:18 +00001252}
1253
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001254LM_STATUS MM_IndicateRxPackets (PLM_DEVICE_BLOCK pDevice)
wdenkcc1c8a12002-11-02 22:58:18 +00001255{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001256 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1257 pUmDevice->rx_pkt = 1;
1258 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +00001259}
1260
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001261LM_STATUS MM_IndicateTxPackets (PLM_DEVICE_BLOCK pDevice)
wdenkcc1c8a12002-11-02 22:58:18 +00001262{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001263 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1264 PLM_PACKET pPacket;
1265 PUM_PACKET pUmPacket;
1266 void *skb;
1267 while (TRUE) {
wdenkcc1c8a12002-11-02 22:58:18 +00001268
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001269 pPacket = (PLM_PACKET)
1270 QQ_PopHead (&pDevice->TxPacketXmittedQ.Container);
wdenkcc1c8a12002-11-02 22:58:18 +00001271
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001272 if (pPacket == 0)
1273 break;
wdenkcc1c8a12002-11-02 22:58:18 +00001274
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001275 pUmPacket = (PUM_PACKET) pPacket;
1276 skb = (void *)pUmPacket->skbuff;
wdenkcc1c8a12002-11-02 22:58:18 +00001277
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001278 /*
1279 * Free MBLK if we transmitted a fragmented packet or a
1280 * non-fragmented packet straight from the VxWorks
1281 * buffer pool. If packet was copied to a local transmit
1282 * buffer, then there's no MBUF to free, just free
1283 * the transmit buffer back to the cluster pool.
1284 */
wdenkcc1c8a12002-11-02 22:58:18 +00001285
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001286 if (skb)
1287 bcm570xPktFree (pUmDevice->index, skb);
wdenkcc1c8a12002-11-02 22:58:18 +00001288
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001289 pUmPacket->skbuff = 0;
1290 QQ_PushTail (&pDevice->TxPacketFreeQ.Container, pPacket);
1291 pUmDevice->tx_pkt = 1;
1292 }
1293 if (pUmDevice->tx_full) {
1294 if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) >=
1295 (QQ_GetSize (&pDevice->TxPacketFreeQ.Container) >> 1))
1296 pUmDevice->tx_full = 0;
1297 }
1298 return LM_STATUS_SUCCESS;
wdenkcc1c8a12002-11-02 22:58:18 +00001299}
1300
1301/*
1302 * Scan an MBUF chain until we reach fragment number "frag"
1303 * Return its length and physical address.
1304 */
1305void MM_MapTxDma
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001306 (PLM_DEVICE_BLOCK pDevice,
1307 struct _LM_PACKET *pPacket,
1308 T3_64BIT_HOST_ADDR * paddr, LM_UINT32 * len, int frag) {
1309 PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
1310 *len = pPacket->PacketSize;
1311 MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff);
wdenkcc1c8a12002-11-02 22:58:18 +00001312}
1313
1314/*
1315 * Convert an mbuf address, a CPU local virtual address,
1316 * to a physical address as seen from a PCI device. Store the
1317 * result at paddr.
1318 */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001319void MM_MapRxDma (PLM_DEVICE_BLOCK pDevice,
1320 struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR * paddr)
wdenkcc1c8a12002-11-02 22:58:18 +00001321{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001322 PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
1323 MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff);
wdenkcc1c8a12002-11-02 22:58:18 +00001324}
1325
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001326void MM_SetAddr (LM_PHYSICAL_ADDRESS * paddr, dma_addr_t addr)
wdenkcc1c8a12002-11-02 22:58:18 +00001327{
1328#if (BITS_PER_LONG == 64)
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001329 paddr->High = ((unsigned long)addr) >> 32;
1330 paddr->Low = ((unsigned long)addr) & 0xffffffff;
wdenkcc1c8a12002-11-02 22:58:18 +00001331#else
wdenk57b2d802003-06-27 21:31:46 +00001332 paddr->High = 0;
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001333 paddr->Low = (unsigned long)addr;
wdenkcc1c8a12002-11-02 22:58:18 +00001334#endif
1335}
1336
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001337void MM_SetT3Addr (T3_64BIT_HOST_ADDR * paddr, dma_addr_t addr)
wdenkcc1c8a12002-11-02 22:58:18 +00001338{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001339 unsigned long baddr = (unsigned long)addr;
wdenkcc1c8a12002-11-02 22:58:18 +00001340#if (BITS_PER_LONG == 64)
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001341 set_64bit_addr (paddr, baddr & 0xffffffff, baddr >> 32);
wdenkcc1c8a12002-11-02 22:58:18 +00001342#else
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001343 set_64bit_addr (paddr, baddr, 0);
wdenkcc1c8a12002-11-02 22:58:18 +00001344#endif
1345}
1346
1347/*
1348 * This combination of `inline' and `extern' has almost the effect of a
1349 * macro. The way to use it is to put a function definition in a header
1350 * file with these keywords, and put another copy of the definition
1351 * (lacking `inline' and `extern') in a library file. The definition in
1352 * the header file will cause most calls to the function to be inlined.
1353 * If any uses of the function remain, they will refer to the single copy
1354 * in the library.
1355 */
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001356void atomic_set (atomic_t * entry, int val)
wdenkcc1c8a12002-11-02 22:58:18 +00001357{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001358 entry->counter = val;
wdenkcc1c8a12002-11-02 22:58:18 +00001359}
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001360
1361int atomic_read (atomic_t * entry)
wdenkcc1c8a12002-11-02 22:58:18 +00001362{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001363 return entry->counter;
wdenkcc1c8a12002-11-02 22:58:18 +00001364}
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001365
1366void atomic_inc (atomic_t * entry)
wdenkcc1c8a12002-11-02 22:58:18 +00001367{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001368 if (entry)
1369 entry->counter++;
wdenkcc1c8a12002-11-02 22:58:18 +00001370}
1371
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001372void atomic_dec (atomic_t * entry)
wdenkcc1c8a12002-11-02 22:58:18 +00001373{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001374 if (entry)
1375 entry->counter--;
wdenkcc1c8a12002-11-02 22:58:18 +00001376}
1377
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001378void atomic_sub (int a, atomic_t * entry)
wdenkcc1c8a12002-11-02 22:58:18 +00001379{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001380 if (entry)
1381 entry->counter -= a;
wdenkcc1c8a12002-11-02 22:58:18 +00001382}
1383
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001384void atomic_add (int a, atomic_t * entry)
wdenkcc1c8a12002-11-02 22:58:18 +00001385{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001386 if (entry)
1387 entry->counter += a;
wdenkcc1c8a12002-11-02 22:58:18 +00001388}
1389
1390/******************************************************************************/
1391/* Description: */
1392/* */
1393/* Return: */
1394/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001395void QQ_InitQueue (PQQ_CONTAINER pQueue, unsigned int QueueSize)
1396{
1397 pQueue->Head = 0;
1398 pQueue->Tail = 0;
1399 pQueue->Size = QueueSize + 1;
1400 atomic_set (&pQueue->EntryCnt, 0);
1401} /* QQ_InitQueue */
wdenkcc1c8a12002-11-02 22:58:18 +00001402
wdenkcc1c8a12002-11-02 22:58:18 +00001403/******************************************************************************/
1404/* Description: */
1405/* */
1406/* Return: */
1407/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001408char QQ_Full (PQQ_CONTAINER pQueue)
1409{
1410 unsigned int NewHead;
wdenkcc1c8a12002-11-02 22:58:18 +00001411
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001412 NewHead = (pQueue->Head + 1) % pQueue->Size;
wdenkcc1c8a12002-11-02 22:58:18 +00001413
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001414 return (NewHead == pQueue->Tail);
1415} /* QQ_Full */
wdenkcc1c8a12002-11-02 22:58:18 +00001416
wdenkcc1c8a12002-11-02 22:58:18 +00001417/******************************************************************************/
1418/* Description: */
1419/* */
1420/* Return: */
1421/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001422char QQ_Empty (PQQ_CONTAINER pQueue)
1423{
1424 return (pQueue->Head == pQueue->Tail);
1425} /* QQ_Empty */
wdenkcc1c8a12002-11-02 22:58:18 +00001426
wdenkcc1c8a12002-11-02 22:58:18 +00001427/******************************************************************************/
1428/* Description: */
1429/* */
1430/* Return: */
1431/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001432unsigned int QQ_GetSize (PQQ_CONTAINER pQueue)
1433{
1434 return pQueue->Size;
1435} /* QQ_GetSize */
wdenkcc1c8a12002-11-02 22:58:18 +00001436
wdenkcc1c8a12002-11-02 22:58:18 +00001437/******************************************************************************/
1438/* Description: */
1439/* */
1440/* Return: */
1441/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001442unsigned int QQ_GetEntryCnt (PQQ_CONTAINER pQueue)
1443{
1444 return atomic_read (&pQueue->EntryCnt);
1445} /* QQ_GetEntryCnt */
wdenkcc1c8a12002-11-02 22:58:18 +00001446
wdenkcc1c8a12002-11-02 22:58:18 +00001447/******************************************************************************/
1448/* Description: */
1449/* */
1450/* Return: */
1451/* TRUE entry was added successfully. */
1452/* FALSE queue is full. */
1453/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001454char QQ_PushHead (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)
1455{
1456 unsigned int Head;
wdenkcc1c8a12002-11-02 22:58:18 +00001457
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001458 Head = (pQueue->Head + 1) % pQueue->Size;
wdenkcc1c8a12002-11-02 22:58:18 +00001459
1460#if !defined(QQ_NO_OVERFLOW_CHECK)
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001461 if (Head == pQueue->Tail) {
1462 return 0;
1463 } /* if */
1464#endif /* QQ_NO_OVERFLOW_CHECK */
wdenkcc1c8a12002-11-02 22:58:18 +00001465
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001466 pQueue->Array[pQueue->Head] = pEntry;
1467 wmb ();
1468 pQueue->Head = Head;
1469 atomic_inc (&pQueue->EntryCnt);
wdenkcc1c8a12002-11-02 22:58:18 +00001470
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001471 return -1;
1472} /* QQ_PushHead */
wdenkcc1c8a12002-11-02 22:58:18 +00001473
wdenkcc1c8a12002-11-02 22:58:18 +00001474/******************************************************************************/
1475/* Description: */
1476/* */
1477/* Return: */
1478/* TRUE entry was added successfully. */
1479/* FALSE queue is full. */
1480/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001481char QQ_PushTail (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)
1482{
1483 unsigned int Tail;
wdenkcc1c8a12002-11-02 22:58:18 +00001484
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001485 Tail = pQueue->Tail;
1486 if (Tail == 0) {
1487 Tail = pQueue->Size;
1488 } /* if */
1489 Tail--;
wdenkcc1c8a12002-11-02 22:58:18 +00001490
1491#if !defined(QQ_NO_OVERFLOW_CHECK)
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001492 if (Tail == pQueue->Head) {
1493 return 0;
1494 } /* if */
1495#endif /* QQ_NO_OVERFLOW_CHECK */
wdenkcc1c8a12002-11-02 22:58:18 +00001496
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001497 pQueue->Array[Tail] = pEntry;
1498 wmb ();
1499 pQueue->Tail = Tail;
1500 atomic_inc (&pQueue->EntryCnt);
wdenkcc1c8a12002-11-02 22:58:18 +00001501
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001502 return -1;
1503} /* QQ_PushTail */
wdenkcc1c8a12002-11-02 22:58:18 +00001504
wdenkcc1c8a12002-11-02 22:58:18 +00001505/******************************************************************************/
1506/* Description: */
1507/* */
1508/* Return: */
1509/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001510PQQ_ENTRY QQ_PopHead (PQQ_CONTAINER pQueue)
1511{
1512 unsigned int Head;
1513 PQQ_ENTRY Entry;
wdenkcc1c8a12002-11-02 22:58:18 +00001514
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001515 Head = pQueue->Head;
wdenkcc1c8a12002-11-02 22:58:18 +00001516
1517#if !defined(QQ_NO_UNDERFLOW_CHECK)
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001518 if (Head == pQueue->Tail) {
1519 return (PQQ_ENTRY) 0;
1520 } /* if */
1521#endif /* QQ_NO_UNDERFLOW_CHECK */
wdenkcc1c8a12002-11-02 22:58:18 +00001522
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001523 if (Head == 0) {
1524 Head = pQueue->Size;
1525 } /* if */
1526 Head--;
wdenkcc1c8a12002-11-02 22:58:18 +00001527
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001528 Entry = pQueue->Array[Head];
1529 membar ();
wdenkcc1c8a12002-11-02 22:58:18 +00001530
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001531 pQueue->Head = Head;
1532 atomic_dec (&pQueue->EntryCnt);
wdenkcc1c8a12002-11-02 22:58:18 +00001533
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001534 return Entry;
1535} /* QQ_PopHead */
wdenkcc1c8a12002-11-02 22:58:18 +00001536
wdenkcc1c8a12002-11-02 22:58:18 +00001537/******************************************************************************/
1538/* Description: */
1539/* */
1540/* Return: */
1541/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001542PQQ_ENTRY QQ_PopTail (PQQ_CONTAINER pQueue)
1543{
1544 unsigned int Tail;
1545 PQQ_ENTRY Entry;
wdenkcc1c8a12002-11-02 22:58:18 +00001546
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001547 Tail = pQueue->Tail;
wdenkcc1c8a12002-11-02 22:58:18 +00001548
1549#if !defined(QQ_NO_UNDERFLOW_CHECK)
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001550 if (Tail == pQueue->Head) {
1551 return (PQQ_ENTRY) 0;
1552 } /* if */
1553#endif /* QQ_NO_UNDERFLOW_CHECK */
wdenkcc1c8a12002-11-02 22:58:18 +00001554
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001555 Entry = pQueue->Array[Tail];
1556 membar ();
1557 pQueue->Tail = (Tail + 1) % pQueue->Size;
1558 atomic_dec (&pQueue->EntryCnt);
wdenkcc1c8a12002-11-02 22:58:18 +00001559
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001560 return Entry;
1561} /* QQ_PopTail */
wdenkcc1c8a12002-11-02 22:58:18 +00001562
wdenkcc1c8a12002-11-02 22:58:18 +00001563/******************************************************************************/
1564/* Description: */
1565/* */
1566/* Return: */
1567/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001568PQQ_ENTRY QQ_GetHead (PQQ_CONTAINER pQueue, unsigned int Idx)
wdenkcc1c8a12002-11-02 22:58:18 +00001569{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001570 if (Idx >= atomic_read (&pQueue->EntryCnt)) {
1571 return (PQQ_ENTRY) 0;
1572 }
wdenkcc1c8a12002-11-02 22:58:18 +00001573
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001574 if (pQueue->Head > Idx) {
1575 Idx = pQueue->Head - Idx;
1576 } else {
1577 Idx = pQueue->Size - (Idx - pQueue->Head);
1578 }
1579 Idx--;
wdenkcc1c8a12002-11-02 22:58:18 +00001580
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001581 return pQueue->Array[Idx];
wdenkcc1c8a12002-11-02 22:58:18 +00001582}
1583
wdenkcc1c8a12002-11-02 22:58:18 +00001584/******************************************************************************/
1585/* Description: */
1586/* */
1587/* Return: */
1588/******************************************************************************/
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001589PQQ_ENTRY QQ_GetTail (PQQ_CONTAINER pQueue, unsigned int Idx)
wdenkcc1c8a12002-11-02 22:58:18 +00001590{
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001591 if (Idx >= atomic_read (&pQueue->EntryCnt)) {
1592 return (PQQ_ENTRY) 0;
1593 }
wdenkcc1c8a12002-11-02 22:58:18 +00001594
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001595 Idx += pQueue->Tail;
1596 if (Idx >= pQueue->Size) {
1597 Idx = Idx - pQueue->Size;
1598 }
wdenkcc1c8a12002-11-02 22:58:18 +00001599
Vadim Bendebury6ddfee52007-05-24 15:52:25 -07001600 return pQueue->Array[Idx];
wdenkcc1c8a12002-11-02 22:58:18 +00001601}
1602
Jon Loeliger30c2f242007-07-10 11:13:21 -05001603#endif