blob: 73e5c7cf69d3ce12b8dce14a4a7b29e0fc212229 [file] [log] [blame]
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001/****************************************************************************
2
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
5
6 Project: openPOWERLINK
7
8 Description: Ethernet driver for Realtek RTL8139 chips
9 except the RTL8139C+, because it has a different
10 Tx descriptor handling.
11
12 License:
13
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions
16 are met:
17
18 1. Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
20
21 2. Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
24
25 3. Neither the name of SYSTEC electronic GmbH nor the names of its
26 contributors may be used to endorse or promote products derived
27 from this software without prior written permission. For written
28 permission, please contact info@systec-electronic.com.
29
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 POSSIBILITY OF SUCH DAMAGE.
42
43 Severability Clause:
44
45 If a provision of this License is or becomes illegal, invalid or
46 unenforceable in any jurisdiction, that shall not affect:
47 1. the validity or enforceability in that jurisdiction of any other
48 provision of this License; or
49 2. the validity or enforceability in other jurisdictions of that or
50 any other provision of this License.
51
52 -------------------------------------------------------------------------
53
54 $RCSfile: Edrv8139.c,v $
55
56 $Author: D.Krueger $
57
58 $Revision: 1.10 $ $Date: 2008/11/21 09:00:38 $
59
60 $State: Exp $
61
62 Build Environment:
63 Dev C++ and GNU-Compiler for m68k
64
65 -------------------------------------------------------------------------
66
67 Revision History:
68
69 2008/02/05 d.k.: start of implementation
70
71****************************************************************************/
72
73#include "global.h"
74#include "EplInc.h"
75#include "edrv.h"
76
77#include <linux/module.h>
78#include <linux/kernel.h>
79#include <linux/pci.h>
80#include <linux/interrupt.h>
81#include <linux/init.h>
82#include <linux/errno.h>
83#include <linux/major.h>
84#include <linux/version.h>
85#include <asm/io.h>
86#include <asm/uaccess.h>
87#include <asm/atomic.h>
88#include <asm/irq.h>
89#include <linux/sched.h>
90#include <linux/delay.h>
91
Daniel Krueger9d7164c2008-12-19 11:41:57 -080092/***************************************************************************/
93/* */
94/* */
95/* G L O B A L D E F I N I T I O N S */
96/* */
97/* */
98/***************************************************************************/
99
100// Buffer handling:
101// All buffers are created statically (i.e. at compile time resp. at
102// initialisation via kmalloc() ) and not dynamically on request (i.e. via
103// EdrvAllocTxMsgBuffer().
104// EdrvAllocTxMsgBuffer() searches for an unused buffer which is large enough.
105// EdrvInit() may allocate some buffers with sizes less than maximum frame
106// size (i.e. 1514 bytes), e.g. for SoC, SoA, StatusResponse, IdentResponse,
107// NMT requests / commands. The less the size of the buffer the less the
108// number of the buffer.
109
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800110//---------------------------------------------------------------------------
111// const defines
112//---------------------------------------------------------------------------
113
114#ifndef EDRV_MAX_TX_BUFFERS
115#define EDRV_MAX_TX_BUFFERS 20
116#endif
117
118#define EDRV_MAX_FRAME_SIZE 0x600
119
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800120#define EDRV_RX_BUFFER_SIZE 0x8610 // 32 kB + 16 Byte + 1,5 kB (WRAP is enabled)
121#define EDRV_RX_BUFFER_LENGTH (EDRV_RX_BUFFER_SIZE & 0xF800) // buffer size cut down to 2 kB alignment
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800122
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800123#define EDRV_TX_BUFFER_SIZE (EDRV_MAX_TX_BUFFERS * EDRV_MAX_FRAME_SIZE) // n * (MTU + 14 + 4)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800124
125#define DRV_NAME "epl"
126
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800127#define EDRV_REGW_INT_MASK 0x3C // interrupt mask register
128#define EDRV_REGW_INT_STATUS 0x3E // interrupt status register
129#define EDRV_REGW_INT_ROK 0x0001 // Receive OK interrupt
130#define EDRV_REGW_INT_RER 0x0002 // Receive error interrupt
131#define EDRV_REGW_INT_TOK 0x0004 // Transmit OK interrupt
132#define EDRV_REGW_INT_TER 0x0008 // Transmit error interrupt
133#define EDRV_REGW_INT_RXOVW 0x0010 // Rx buffer overflow interrupt
134#define EDRV_REGW_INT_PUN 0x0020 // Packet underrun/ link change interrupt
135#define EDRV_REGW_INT_FOVW 0x0040 // Rx FIFO overflow interrupt
136#define EDRV_REGW_INT_LENCHG 0x2000 // Cable length change interrupt
137#define EDRV_REGW_INT_TIMEOUT 0x4000 // Time out interrupt
138#define EDRV_REGW_INT_SERR 0x8000 // System error interrupt
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800139#define EDRV_REGW_INT_MASK_DEF (EDRV_REGW_INT_ROK \
140 | EDRV_REGW_INT_RER \
141 | EDRV_REGW_INT_TOK \
142 | EDRV_REGW_INT_TER \
143 | EDRV_REGW_INT_RXOVW \
144 | EDRV_REGW_INT_FOVW \
145 | EDRV_REGW_INT_PUN \
146 | EDRV_REGW_INT_TIMEOUT \
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800147 | EDRV_REGW_INT_SERR) // default interrupt mask
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800148
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800149#define EDRV_REGB_COMMAND 0x37 // command register
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800150#define EDRV_REGB_COMMAND_RST 0x10
151#define EDRV_REGB_COMMAND_RE 0x08
152#define EDRV_REGB_COMMAND_TE 0x04
153#define EDRV_REGB_COMMAND_BUFE 0x01
154
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800155#define EDRV_REGB_CMD9346 0x50 // 93C46 command register
156#define EDRV_REGB_CMD9346_LOCK 0x00 // lock configuration registers
157#define EDRV_REGB_CMD9346_UNLOCK 0xC0 // unlock configuration registers
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800158
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800159#define EDRV_REGDW_RCR 0x44 // Rx configuration register
160#define EDRV_REGDW_RCR_NO_FTH 0x0000E000 // no receive FIFO threshold
161#define EDRV_REGDW_RCR_RBLEN32K 0x00001000 // 32 kB receive buffer
162#define EDRV_REGDW_RCR_MXDMAUNL 0x00000700 // unlimited maximum DMA burst size
163#define EDRV_REGDW_RCR_NOWRAP 0x00000080 // do not wrap frame at end of buffer
164#define EDRV_REGDW_RCR_AER 0x00000020 // accept error frames (CRC, alignment, collided)
165#define EDRV_REGDW_RCR_AR 0x00000010 // accept runt
166#define EDRV_REGDW_RCR_AB 0x00000008 // accept broadcast frames
167#define EDRV_REGDW_RCR_AM 0x00000004 // accept multicast frames
168#define EDRV_REGDW_RCR_APM 0x00000002 // accept physical match frames
169#define EDRV_REGDW_RCR_AAP 0x00000001 // accept all frames
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800170#define EDRV_REGDW_RCR_DEF (EDRV_REGDW_RCR_NO_FTH \
171 | EDRV_REGDW_RCR_RBLEN32K \
172 | EDRV_REGDW_RCR_MXDMAUNL \
173 | EDRV_REGDW_RCR_NOWRAP \
174 | EDRV_REGDW_RCR_AB \
175 | EDRV_REGDW_RCR_AM \
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800176 | EDRV_REGDW_RCR_APM) // default value
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800177
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800178#define EDRV_REGDW_TCR 0x40 // Tx configuration register
179#define EDRV_REGDW_TCR_VER_MASK 0x7CC00000 // mask for hardware version
180#define EDRV_REGDW_TCR_VER_C 0x74000000 // RTL8139C
181#define EDRV_REGDW_TCR_VER_D 0x74400000 // RTL8139D
182#define EDRV_REGDW_TCR_IFG96 0x03000000 // default interframe gap (960 ns)
183#define EDRV_REGDW_TCR_CRC 0x00010000 // disable appending of CRC by the controller
184#define EDRV_REGDW_TCR_MXDMAUNL 0x00000700 // maximum DMA burst size of 2048 b
185#define EDRV_REGDW_TCR_TXRETRY 0x00000000 // 16 retries
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800186#define EDRV_REGDW_TCR_DEF (EDRV_REGDW_TCR_IFG96 \
187 | EDRV_REGDW_TCR_MXDMAUNL \
188 | EDRV_REGDW_TCR_TXRETRY)
189
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800190#define EDRV_REGW_MULINT 0x5C // multiple interrupt select register
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800191
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800192#define EDRV_REGDW_MPC 0x4C // missed packet counter register
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800193
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800194#define EDRV_REGDW_TSAD0 0x20 // Transmit start address of descriptor 0
195#define EDRV_REGDW_TSAD1 0x24 // Transmit start address of descriptor 1
196#define EDRV_REGDW_TSAD2 0x28 // Transmit start address of descriptor 2
197#define EDRV_REGDW_TSAD3 0x2C // Transmit start address of descriptor 3
198#define EDRV_REGDW_TSD0 0x10 // Transmit status of descriptor 0
199#define EDRV_REGDW_TSD_CRS 0x80000000 // Carrier sense lost
200#define EDRV_REGDW_TSD_TABT 0x40000000 // Transmit Abort
201#define EDRV_REGDW_TSD_OWC 0x20000000 // Out of window collision
202#define EDRV_REGDW_TSD_TXTH_DEF 0x00020000 // Transmit FIFO threshold of 64 bytes
203#define EDRV_REGDW_TSD_TOK 0x00008000 // Transmit OK
204#define EDRV_REGDW_TSD_TUN 0x00004000 // Transmit FIFO underrun
205#define EDRV_REGDW_TSD_OWN 0x00002000 // Owner
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800206
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800207#define EDRV_REGDW_RBSTART 0x30 // Receive buffer start address
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800208
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800209#define EDRV_REGW_CAPR 0x38 // Current address of packet read
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800210
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800211#define EDRV_REGDW_IDR0 0x00 // ID register 0
212#define EDRV_REGDW_IDR4 0x04 // ID register 4
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800213
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800214#define EDRV_REGDW_MAR0 0x08 // Multicast address register 0
215#define EDRV_REGDW_MAR4 0x0C // Multicast address register 4
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800216
217// defines for the status word in the receive buffer
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800218#define EDRV_RXSTAT_MAR 0x8000 // Multicast address received
219#define EDRV_RXSTAT_PAM 0x4000 // Physical address matched
220#define EDRV_RXSTAT_BAR 0x2000 // Broadcast address received
221#define EDRV_RXSTAT_ISE 0x0020 // Invalid symbol error
222#define EDRV_RXSTAT_RUNT 0x0010 // Runt packet received
223#define EDRV_RXSTAT_LONG 0x0008 // Long packet
224#define EDRV_RXSTAT_CRC 0x0004 // CRC error
225#define EDRV_RXSTAT_FAE 0x0002 // Frame alignment error
226#define EDRV_RXSTAT_ROK 0x0001 // Receive OK
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800227
228#define EDRV_REGDW_WRITE(dwReg, dwVal) writel(dwVal, EdrvInstance_l.m_pIoAddr + dwReg)
229#define EDRV_REGW_WRITE(dwReg, wVal) writew(wVal, EdrvInstance_l.m_pIoAddr + dwReg)
230#define EDRV_REGB_WRITE(dwReg, bVal) writeb(bVal, EdrvInstance_l.m_pIoAddr + dwReg)
231#define EDRV_REGDW_READ(dwReg) readl(EdrvInstance_l.m_pIoAddr + dwReg)
232#define EDRV_REGW_READ(dwReg) readw(EdrvInstance_l.m_pIoAddr + dwReg)
233#define EDRV_REGB_READ(dwReg) readb(EdrvInstance_l.m_pIoAddr + dwReg)
234
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800235// TracePoint support for realtime-debugging
236#ifdef _DBG_TRACE_POINTS_
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700237void TgtDbgSignalTracePoint(u8 bTracePointNumber_p);
Greg Kroah-Hartmand10f4692009-03-23 10:45:12 -0700238void TgtDbgPostTraceValue(DWORD dwTraceValue_p);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800239#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
240#define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800241#else
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800242#define TGT_DBG_SIGNAL_TRACE_POINT(p)
243#define TGT_DBG_POST_TRACE_VALUE(v)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800244#endif
245
246#define EDRV_COUNT_SEND TGT_DBG_SIGNAL_TRACE_POINT(2)
247#define EDRV_COUNT_TIMEOUT TGT_DBG_SIGNAL_TRACE_POINT(3)
248#define EDRV_COUNT_PCI_ERR TGT_DBG_SIGNAL_TRACE_POINT(4)
249#define EDRV_COUNT_TX TGT_DBG_SIGNAL_TRACE_POINT(5)
250#define EDRV_COUNT_RX TGT_DBG_SIGNAL_TRACE_POINT(6)
251#define EDRV_COUNT_LATECOLLISION TGT_DBG_SIGNAL_TRACE_POINT(10)
252#define EDRV_COUNT_TX_COL_RL TGT_DBG_SIGNAL_TRACE_POINT(11)
253#define EDRV_COUNT_TX_FUN TGT_DBG_SIGNAL_TRACE_POINT(12)
254#define EDRV_COUNT_TX_ERR TGT_DBG_SIGNAL_TRACE_POINT(13)
255#define EDRV_COUNT_RX_CRC TGT_DBG_SIGNAL_TRACE_POINT(14)
256#define EDRV_COUNT_RX_ERR TGT_DBG_SIGNAL_TRACE_POINT(15)
257#define EDRV_COUNT_RX_FOVW TGT_DBG_SIGNAL_TRACE_POINT(16)
258#define EDRV_COUNT_RX_PUN TGT_DBG_SIGNAL_TRACE_POINT(17)
259#define EDRV_COUNT_RX_FAE TGT_DBG_SIGNAL_TRACE_POINT(18)
260#define EDRV_COUNT_RX_OVW TGT_DBG_SIGNAL_TRACE_POINT(19)
261
262#define EDRV_TRACE_CAPR(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x06000000)
263#define EDRV_TRACE_RX_CRC(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x0E000000)
264#define EDRV_TRACE_RX_ERR(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x0F000000)
265#define EDRV_TRACE_RX_PUN(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x11000000)
266#define EDRV_TRACE(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF0000) | 0x0000FEC0)
267
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800268//---------------------------------------------------------------------------
269// local types
270//---------------------------------------------------------------------------
271/*
272typedef struct
273{
274 BOOL m_fUsed;
275 unsigned int m_uiSize;
276 MCD_bufDescFec *m_pBufDescr;
277
278} tEdrvTxBufferIntern;
279*/
280
281// Private structure
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800282typedef struct {
283 struct pci_dev *m_pPciDev; // pointer to PCI device structure
284 void *m_pIoAddr; // pointer to register space of Ethernet controller
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700285 u8 *m_pbRxBuf; // pointer to Rx buffer
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800286 dma_addr_t m_pRxBufDma;
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700287 u8 *m_pbTxBuf; // pointer to Tx buffer
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800288 dma_addr_t m_pTxBufDma;
289 BOOL m_afTxBufUsed[EDRV_MAX_TX_BUFFERS];
290 unsigned int m_uiCurTxDesc;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800291
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800292 tEdrvInitParam m_InitParam;
293 tEdrvTxBuffer *m_pLastTransmittedTxBuffer;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800294
295} tEdrvInstance;
296
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800297//---------------------------------------------------------------------------
298// local function prototypes
299//---------------------------------------------------------------------------
300
301static int EdrvInitOne(struct pci_dev *pPciDev,
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800302 const struct pci_device_id *pId);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800303
304static void EdrvRemoveOne(struct pci_dev *pPciDev);
305
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800306//---------------------------------------------------------------------------
307// modul globale vars
308//---------------------------------------------------------------------------
309// buffers and buffer descriptors and pointers
310
311static struct pci_device_id aEdrvPciTbl[] = {
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800312 {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
313 {0,}
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800314};
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800315
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800316MODULE_DEVICE_TABLE(pci, aEdrvPciTbl);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800317
318static tEdrvInstance EdrvInstance_l;
319
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800320static struct pci_driver EdrvDriver = {
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800321 .name = DRV_NAME,
322 .id_table = aEdrvPciTbl,
323 .probe = EdrvInitOne,
324 .remove = EdrvRemoveOne,
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800325};
326
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800327/***************************************************************************/
328/* */
329/* */
330/* C L A S S <edrv> */
331/* */
332/* */
333/***************************************************************************/
334//
335// Description:
336//
337//
338/***************************************************************************/
339
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800340//=========================================================================//
341// //
342// P R I V A T E D E F I N I T I O N S //
343// //
344//=========================================================================//
345
346//---------------------------------------------------------------------------
347// const defines
348//---------------------------------------------------------------------------
349
350//---------------------------------------------------------------------------
351// local types
352//---------------------------------------------------------------------------
353
354//---------------------------------------------------------------------------
355// local vars
356//---------------------------------------------------------------------------
357
358//---------------------------------------------------------------------------
359// local function prototypes
360//---------------------------------------------------------------------------
361
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700362static u8 EdrvCalcHash(u8 * pbMAC_p);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800363
364//---------------------------------------------------------------------------
365//
366// Function: EdrvInit
367//
368// Description: function for init of the Ethernet controller
369//
370// Parameters: pEdrvInitParam_p = pointer to struct including the init-parameters
371//
372// Returns: Errorcode = kEplSuccessful
373// = kEplNoResource
374//
375// State:
376//
377//---------------------------------------------------------------------------
378tEplKernel EdrvInit(tEdrvInitParam * pEdrvInitParam_p)
379{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800380 tEplKernel Ret;
381 int iResult;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800382
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800383 Ret = kEplSuccessful;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800384
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800385 // clear instance structure
386 EPL_MEMSET(&EdrvInstance_l, 0, sizeof(EdrvInstance_l));
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800387
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800388 // save the init data
389 EdrvInstance_l.m_InitParam = *pEdrvInitParam_p;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800390
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800391 // register PCI driver
392 iResult = pci_register_driver(&EdrvDriver);
393 if (iResult != 0) {
Harvey Harrisond599edc2009-01-07 14:31:57 -0800394 printk("%s pci_register_driver failed with %d\n", __func__,
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800395 iResult);
396 Ret = kEplNoResource;
397 goto Exit;
398 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800399
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800400 if (EdrvInstance_l.m_pPciDev == NULL) {
Harvey Harrisond599edc2009-01-07 14:31:57 -0800401 printk("%s m_pPciDev=NULL\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800402 Ret = kEplNoResource;
403 goto Exit;
404 }
405 // read MAC address from controller
Harvey Harrisond599edc2009-01-07 14:31:57 -0800406 printk("%s local MAC = ", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800407 for (iResult = 0; iResult < 6; iResult++) {
408 pEdrvInitParam_p->m_abMyMacAddr[iResult] =
409 EDRV_REGB_READ((EDRV_REGDW_IDR0 + iResult));
410 printk("%02X ",
411 (unsigned int)pEdrvInitParam_p->m_abMyMacAddr[iResult]);
412 }
413 printk("\n");
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800414
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800415 Exit:
416 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800417
418}
419
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800420//---------------------------------------------------------------------------
421//
422// Function: EdrvShutdown
423//
424// Description: Shutdown the Ethernet controller
425//
426// Parameters: void
427//
428// Returns: Errorcode = kEplSuccessful
429//
430// State:
431//
432//---------------------------------------------------------------------------
433tEplKernel EdrvShutdown(void)
434{
435
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800436 // unregister PCI driver
Harvey Harrisond599edc2009-01-07 14:31:57 -0800437 printk("%s calling pci_unregister_driver()\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800438 pci_unregister_driver(&EdrvDriver);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800439
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800440 return kEplSuccessful;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800441}
442
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800443//---------------------------------------------------------------------------
444//
445// Function: EdrvDefineRxMacAddrEntry
446//
447// Description: Set a multicast entry into the Ethernet controller
448//
449// Parameters: pbMacAddr_p = pointer to multicast entry to set
450//
451// Returns: Errorcode = kEplSuccessful
452//
453// State:
454//
455//---------------------------------------------------------------------------
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700456tEplKernel EdrvDefineRxMacAddrEntry(u8 * pbMacAddr_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800457{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800458 tEplKernel Ret = kEplSuccessful;
459 DWORD dwData;
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700460 u8 bHash;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800461
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800462 bHash = EdrvCalcHash(pbMacAddr_p);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800463/*
464 dwData = ether_crc(6, pbMacAddr_p);
465
466 printk("EdrvDefineRxMacAddrEntry('%02X:%02X:%02X:%02X:%02X:%02X') hash = %u / %u ether_crc = 0x%08lX\n",
467 (WORD) pbMacAddr_p[0], (WORD) pbMacAddr_p[1], (WORD) pbMacAddr_p[2],
468 (WORD) pbMacAddr_p[3], (WORD) pbMacAddr_p[4], (WORD) pbMacAddr_p[5],
469 (WORD) bHash, (WORD) (dwData >> 26), dwData);
470*/
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800471 if (bHash > 31) {
472 dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR4);
473 dwData |= 1 << (bHash - 32);
474 EDRV_REGDW_WRITE(EDRV_REGDW_MAR4, dwData);
475 } else {
476 dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR0);
477 dwData |= 1 << bHash;
478 EDRV_REGDW_WRITE(EDRV_REGDW_MAR0, dwData);
479 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800480
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800481 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800482}
483
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800484//---------------------------------------------------------------------------
485//
486// Function: EdrvUndefineRxMacAddrEntry
487//
488// Description: Reset a multicast entry in the Ethernet controller
489//
490// Parameters: pbMacAddr_p = pointer to multicast entry to reset
491//
492// Returns: Errorcode = kEplSuccessful
493//
494// State:
495//
496//---------------------------------------------------------------------------
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700497tEplKernel EdrvUndefineRxMacAddrEntry(u8 * pbMacAddr_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800498{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800499 tEplKernel Ret = kEplSuccessful;
500 DWORD dwData;
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700501 u8 bHash;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800502
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800503 bHash = EdrvCalcHash(pbMacAddr_p);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800504
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800505 if (bHash > 31) {
506 dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR4);
507 dwData &= ~(1 << (bHash - 32));
508 EDRV_REGDW_WRITE(EDRV_REGDW_MAR4, dwData);
509 } else {
510 dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR0);
511 dwData &= ~(1 << bHash);
512 EDRV_REGDW_WRITE(EDRV_REGDW_MAR0, dwData);
513 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800514
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800515 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800516}
517
518//---------------------------------------------------------------------------
519//
520// Function: EdrvAllocTxMsgBuffer
521//
522// Description: Register a Tx-Buffer
523//
524// Parameters: pBuffer_p = pointer to Buffer structure
525//
526// Returns: Errorcode = kEplSuccessful
527// = kEplEdrvNoFreeBufEntry
528//
529// State:
530//
531//---------------------------------------------------------------------------
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800532tEplKernel EdrvAllocTxMsgBuffer(tEdrvTxBuffer * pBuffer_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800533{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800534 tEplKernel Ret = kEplSuccessful;
535 DWORD i;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800536
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800537 if (pBuffer_p->m_uiMaxBufferLen > EDRV_MAX_FRAME_SIZE) {
538 Ret = kEplEdrvNoFreeBufEntry;
539 goto Exit;
540 }
541 // search a free Tx buffer with appropriate size
542 for (i = 0; i < EDRV_MAX_TX_BUFFERS; i++) {
543 if (EdrvInstance_l.m_afTxBufUsed[i] == FALSE) {
544 // free channel found
545 EdrvInstance_l.m_afTxBufUsed[i] = TRUE;
546 pBuffer_p->m_uiBufferNumber = i;
547 pBuffer_p->m_pbBuffer =
548 EdrvInstance_l.m_pbTxBuf +
549 (i * EDRV_MAX_FRAME_SIZE);
550 pBuffer_p->m_uiMaxBufferLen = EDRV_MAX_FRAME_SIZE;
551 break;
552 }
553 }
554 if (i >= EDRV_MAX_TX_BUFFERS) {
555 Ret = kEplEdrvNoFreeBufEntry;
556 goto Exit;
557 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800558
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800559 Exit:
560 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800561
562}
563
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800564//---------------------------------------------------------------------------
565//
566// Function: EdrvReleaseTxMsgBuffer
567//
568// Description: Register a Tx-Buffer
569//
570// Parameters: pBuffer_p = pointer to Buffer structure
571//
572// Returns: Errorcode = kEplSuccessful
573//
574// State:
575//
576//---------------------------------------------------------------------------
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800577tEplKernel EdrvReleaseTxMsgBuffer(tEdrvTxBuffer * pBuffer_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800578{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800579 unsigned int uiBufferNumber;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800580
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800581 uiBufferNumber = pBuffer_p->m_uiBufferNumber;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800582
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800583 if (uiBufferNumber < EDRV_MAX_TX_BUFFERS) {
584 EdrvInstance_l.m_afTxBufUsed[uiBufferNumber] = FALSE;
585 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800586
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800587 return kEplSuccessful;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800588
589}
590
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800591//---------------------------------------------------------------------------
592//
593// Function: EdrvSendTxMsg
594//
595// Description: immediately starts the transmission of the buffer
596//
597// Parameters: pBuffer_p = buffer descriptor to transmit
598//
599// Returns: Errorcode = kEplSuccessful
600//
601// State:
602//
603//---------------------------------------------------------------------------
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800604tEplKernel EdrvSendTxMsg(tEdrvTxBuffer * pBuffer_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800605{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800606 tEplKernel Ret = kEplSuccessful;
607 unsigned int uiBufferNumber;
608 DWORD dwTemp;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800609
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800610 uiBufferNumber = pBuffer_p->m_uiBufferNumber;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800611
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800612 if ((uiBufferNumber >= EDRV_MAX_TX_BUFFERS)
613 || (EdrvInstance_l.m_afTxBufUsed[uiBufferNumber] == FALSE)) {
614 Ret = kEplEdrvBufNotExisting;
615 goto Exit;
616 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800617
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800618 if (EdrvInstance_l.m_pLastTransmittedTxBuffer != NULL) { // transmission is already active
619 Ret = kEplInvalidOperation;
620 dwTemp =
621 EDRV_REGDW_READ((EDRV_REGDW_TSD0 +
622 (EdrvInstance_l.m_uiCurTxDesc *
623 sizeof(DWORD))));
Harvey Harrisond599edc2009-01-07 14:31:57 -0800624 printk("%s InvOp TSD%u = 0x%08lX", __func__,
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800625 EdrvInstance_l.m_uiCurTxDesc, dwTemp);
626 printk(" Cmd = 0x%02X\n",
627 (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND));
628 goto Exit;
629 }
630 // save pointer to buffer structure for TxHandler
631 EdrvInstance_l.m_pLastTransmittedTxBuffer = pBuffer_p;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800632
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800633 EDRV_COUNT_SEND;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800634
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800635 // pad with zeros if necessary, because controller does not do it
636 if (pBuffer_p->m_uiTxMsgLen < MIN_ETH_SIZE) {
637 EPL_MEMSET(pBuffer_p->m_pbBuffer + pBuffer_p->m_uiTxMsgLen, 0,
638 MIN_ETH_SIZE - pBuffer_p->m_uiTxMsgLen);
639 pBuffer_p->m_uiTxMsgLen = MIN_ETH_SIZE;
640 }
641 // set DMA address of buffer
642 EDRV_REGDW_WRITE((EDRV_REGDW_TSAD0 +
643 (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))),
644 (EdrvInstance_l.m_pTxBufDma +
645 (uiBufferNumber * EDRV_MAX_FRAME_SIZE)));
646 dwTemp =
647 EDRV_REGDW_READ((EDRV_REGDW_TSAD0 +
648 (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))));
Harvey Harrisond599edc2009-01-07 14:31:57 -0800649// printk("%s TSAD%u = 0x%08lX", __func__, EdrvInstance_l.m_uiCurTxDesc, dwTemp);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800650
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800651 // start transmission
652 EDRV_REGDW_WRITE((EDRV_REGDW_TSD0 +
653 (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))),
654 (EDRV_REGDW_TSD_TXTH_DEF | pBuffer_p->m_uiTxMsgLen));
655 dwTemp =
656 EDRV_REGDW_READ((EDRV_REGDW_TSD0 +
657 (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))));
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800658// printk(" TSD%u = 0x%08lX / 0x%08lX\n", EdrvInstance_l.m_uiCurTxDesc, dwTemp, (DWORD)(EDRV_REGDW_TSD_TXTH_DEF | pBuffer_p->m_uiTxMsgLen));
659
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800660 Exit:
661 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800662}
663
664#if 0
665//---------------------------------------------------------------------------
666//
667// Function: EdrvTxMsgReady
668//
669// Description: starts copying the buffer to the ethernet controller's FIFO
670//
671// Parameters: pbBuffer_p - bufferdescriptor to transmit
672//
673// Returns: Errorcode - kEplSuccessful
674//
675// State:
676//
677//---------------------------------------------------------------------------
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800678tEplKernel EdrvTxMsgReady(tEdrvTxBuffer * pBuffer_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800679{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800680 tEplKernel Ret = kEplSuccessful;
681 unsigned int uiBufferNumber;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800682
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800683 Exit:
684 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800685}
686
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800687//---------------------------------------------------------------------------
688//
689// Function: EdrvTxMsgStart
690//
691// Description: starts transmission of the ethernet controller's FIFO
692//
693// Parameters: pbBuffer_p - bufferdescriptor to transmit
694//
695// Returns: Errorcode - kEplSuccessful
696//
697// State:
698//
699//---------------------------------------------------------------------------
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800700tEplKernel EdrvTxMsgStart(tEdrvTxBuffer * pBuffer_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800701{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800702 tEplKernel Ret = kEplSuccessful;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800703
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800704 return Ret;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800705}
706#endif
707
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800708//---------------------------------------------------------------------------
709//
710// Function: EdrvReinitRx
711//
712// Description: reinitialize the Rx process, because of error
713//
714// Parameters: void
715//
716// Returns: void
717//
718// State:
719//
720//---------------------------------------------------------------------------
721static void EdrvReinitRx(void)
722{
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700723 u8 bCmd;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800724
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800725 // simply switch off and on the receiver
726 // this will reset the CAPR register
727 bCmd = EDRV_REGB_READ(EDRV_REGB_COMMAND);
728 EDRV_REGB_WRITE(EDRV_REGB_COMMAND, (bCmd & ~EDRV_REGB_COMMAND_RE));
729 EDRV_REGB_WRITE(EDRV_REGB_COMMAND, bCmd);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800730
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800731 // set receive configuration register
732 EDRV_REGDW_WRITE(EDRV_REGDW_RCR, EDRV_REGDW_RCR_DEF);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800733}
734
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800735//---------------------------------------------------------------------------
736//
737// Function: EdrvInterruptHandler
738//
739// Description: interrupt handler
740//
741// Parameters: void
742//
743// Returns: void
744//
745// State:
746//
747//---------------------------------------------------------------------------
748#if 0
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800749void EdrvInterruptHandler(void)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800750{
751}
752#endif
753
754#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800755static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800756#else
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800757static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p,
758 struct pt_regs *ptRegs_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800759#endif
760{
761// EdrvInterruptHandler();
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800762 tEdrvRxBuffer RxBuffer;
763 tEdrvTxBuffer *pTxBuffer;
764 WORD wStatus;
765 DWORD dwTxStatus;
766 DWORD dwRxStatus;
767 WORD wCurRx;
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -0700768 u8 *pbRxBuf;
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800769 unsigned int uiLength;
770 int iHandled = IRQ_HANDLED;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800771
772// printk("¤");
773
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800774 // read the interrupt status
775 wStatus = EDRV_REGW_READ(EDRV_REGW_INT_STATUS);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800776
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800777 // acknowledge the interrupts
778 EDRV_REGW_WRITE(EDRV_REGW_INT_STATUS, wStatus);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800779
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800780 if (wStatus == 0) {
781 iHandled = IRQ_NONE;
782 goto Exit;
783 }
784 // process tasks
785 if ((wStatus & (EDRV_REGW_INT_TER | EDRV_REGW_INT_TOK)) != 0) { // transmit interrupt
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800786
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800787 if (EdrvInstance_l.m_pbTxBuf == NULL) {
788 printk("%s Tx buffers currently not allocated\n",
Harvey Harrisond599edc2009-01-07 14:31:57 -0800789 __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800790 goto Exit;
791 }
792 // read transmit status
793 dwTxStatus =
794 EDRV_REGDW_READ((EDRV_REGDW_TSD0 +
795 (EdrvInstance_l.m_uiCurTxDesc *
796 sizeof(DWORD))));
797 if ((dwTxStatus & (EDRV_REGDW_TSD_TOK | EDRV_REGDW_TSD_TABT | EDRV_REGDW_TSD_TUN)) != 0) { // transmit finished
798 EdrvInstance_l.m_uiCurTxDesc =
799 (EdrvInstance_l.m_uiCurTxDesc + 1) & 0x03;
800 pTxBuffer = EdrvInstance_l.m_pLastTransmittedTxBuffer;
801 EdrvInstance_l.m_pLastTransmittedTxBuffer = NULL;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800802
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800803 if ((dwTxStatus & EDRV_REGDW_TSD_TOK) != 0) {
804 EDRV_COUNT_TX;
805 } else if ((dwTxStatus & EDRV_REGDW_TSD_TUN) != 0) {
806 EDRV_COUNT_TX_FUN;
807 } else { // assume EDRV_REGDW_TSD_TABT
808 EDRV_COUNT_TX_COL_RL;
809 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800810
811// printk("T");
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800812 if (pTxBuffer != NULL) {
813 // call Tx handler of Data link layer
814 EdrvInstance_l.m_InitParam.
815 m_pfnTxHandler(pTxBuffer);
816 }
817 } else {
818 EDRV_COUNT_TX_ERR;
819 }
820 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800821
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800822 if ((wStatus & (EDRV_REGW_INT_RER | EDRV_REGW_INT_FOVW | EDRV_REGW_INT_RXOVW | EDRV_REGW_INT_PUN)) != 0) { // receive error interrupt
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800823
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800824 if ((wStatus & EDRV_REGW_INT_FOVW) != 0) {
825 EDRV_COUNT_RX_FOVW;
826 } else if ((wStatus & EDRV_REGW_INT_RXOVW) != 0) {
827 EDRV_COUNT_RX_OVW;
828 } else if ((wStatus & EDRV_REGW_INT_PUN) != 0) { // Packet underrun
829 EDRV_TRACE_RX_PUN(wStatus);
830 EDRV_COUNT_RX_PUN;
831 } else { /*if ((wStatus & EDRV_REGW_INT_RER) != 0) */
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800832
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800833 EDRV_TRACE_RX_ERR(wStatus);
834 EDRV_COUNT_RX_ERR;
835 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800836
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800837 // reinitialize Rx process
838 EdrvReinitRx();
839 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800840
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800841 if ((wStatus & EDRV_REGW_INT_ROK) != 0) { // receive interrupt
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800842
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800843 if (EdrvInstance_l.m_pbRxBuf == NULL) {
844 printk("%s Rx buffers currently not allocated\n",
Harvey Harrisond599edc2009-01-07 14:31:57 -0800845 __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800846 goto Exit;
847 }
848 // read current offset in receive buffer
849 wCurRx =
850 (EDRV_REGW_READ(EDRV_REGW_CAPR) +
851 0x10) % EDRV_RX_BUFFER_LENGTH;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800852
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800853 while ((EDRV_REGB_READ(EDRV_REGB_COMMAND) & EDRV_REGB_COMMAND_BUFE) == 0) { // frame available
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800854
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800855 // calculate pointer to current frame in receive buffer
856 pbRxBuf = EdrvInstance_l.m_pbRxBuf + wCurRx;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800857
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800858 // read receive status DWORD
859 dwRxStatus = le32_to_cpu(*((DWORD *) pbRxBuf));
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800860
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800861 // calculate length of received frame
862 uiLength = dwRxStatus >> 16;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800863
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800864 if (uiLength == 0xFFF0) { // frame is unfinished (maybe early Rx interrupt is active)
865 break;
866 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800867
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800868 if ((dwRxStatus & EDRV_RXSTAT_ROK) == 0) { // error occured while receiving this frame
869 // ignore it
870 if ((dwRxStatus & EDRV_RXSTAT_FAE) != 0) {
871 EDRV_COUNT_RX_FAE;
872 } else if ((dwRxStatus & EDRV_RXSTAT_CRC) != 0) {
873 EDRV_TRACE_RX_CRC(dwRxStatus);
874 EDRV_COUNT_RX_CRC;
875 } else {
876 EDRV_TRACE_RX_ERR(dwRxStatus);
877 EDRV_COUNT_RX_ERR;
878 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800879
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800880 // reinitialize Rx process
881 EdrvReinitRx();
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800882
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800883 break;
884 } else { // frame is OK
885 RxBuffer.m_BufferInFrame =
886 kEdrvBufferLastInFrame;
887 RxBuffer.m_uiRxMsgLen = uiLength - ETH_CRC_SIZE;
888 RxBuffer.m_pbBuffer =
889 pbRxBuf + sizeof(dwRxStatus);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800890
891// printk("R");
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800892 EDRV_COUNT_RX;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800893
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800894 // call Rx handler of Data link layer
895 EdrvInstance_l.m_InitParam.
896 m_pfnRxHandler(&RxBuffer);
897 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800898
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800899 // calulate new offset (DWORD aligned)
900 wCurRx =
901 (WORD) ((wCurRx + uiLength + sizeof(dwRxStatus) +
902 3) & ~0x3);
903 EDRV_TRACE_CAPR(wCurRx - 0x10);
904 EDRV_REGW_WRITE(EDRV_REGW_CAPR, wCurRx - 0x10);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800905
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800906 // reread current offset in receive buffer
907 wCurRx =
908 (EDRV_REGW_READ(EDRV_REGW_CAPR) +
909 0x10) % EDRV_RX_BUFFER_LENGTH;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800910
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800911 }
912 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800913
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800914 if ((wStatus & EDRV_REGW_INT_SERR) != 0) { // PCI error
915 EDRV_COUNT_PCI_ERR;
916 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800917
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800918 if ((wStatus & EDRV_REGW_INT_TIMEOUT) != 0) { // Timeout
919 EDRV_COUNT_TIMEOUT;
920 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800921
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800922 Exit:
923 return iHandled;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800924}
925
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800926//---------------------------------------------------------------------------
927//
928// Function: EdrvInitOne
929//
930// Description: initializes one PCI device
931//
932// Parameters: pPciDev = pointer to corresponding PCI device structure
933// pId = PCI device ID
934//
935// Returns: (int) = error code
936//
937// State:
938//
939//---------------------------------------------------------------------------
940
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800941static int EdrvInitOne(struct pci_dev *pPciDev, const struct pci_device_id *pId)
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800942{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800943 int iResult = 0;
944 DWORD dwTemp;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800945
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800946 if (EdrvInstance_l.m_pPciDev != NULL) { // Edrv is already connected to a PCI device
Harvey Harrisond599edc2009-01-07 14:31:57 -0800947 printk("%s device %s discarded\n", __func__,
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800948 pci_name(pPciDev));
949 iResult = -ENODEV;
950 goto Exit;
951 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800952
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800953 if (pPciDev->revision >= 0x20) {
954 printk
955 ("%s device %s is an enhanced 8139C+ version, which is not supported\n",
Harvey Harrisond599edc2009-01-07 14:31:57 -0800956 __func__, pci_name(pPciDev));
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800957 iResult = -ENODEV;
958 goto Exit;
959 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800960
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800961 EdrvInstance_l.m_pPciDev = pPciDev;
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800962
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800963 // enable device
Harvey Harrisond599edc2009-01-07 14:31:57 -0800964 printk("%s enable device\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800965 iResult = pci_enable_device(pPciDev);
966 if (iResult != 0) {
967 goto Exit;
968 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800969
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800970 if ((pci_resource_flags(pPciDev, 1) & IORESOURCE_MEM) == 0) {
971 iResult = -ENODEV;
972 goto Exit;
973 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800974
Harvey Harrisond599edc2009-01-07 14:31:57 -0800975 printk("%s request regions\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800976 iResult = pci_request_regions(pPciDev, DRV_NAME);
977 if (iResult != 0) {
978 goto Exit;
979 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800980
Harvey Harrisond599edc2009-01-07 14:31:57 -0800981 printk("%s ioremap\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800982 EdrvInstance_l.m_pIoAddr =
983 ioremap(pci_resource_start(pPciDev, 1),
984 pci_resource_len(pPciDev, 1));
985 if (EdrvInstance_l.m_pIoAddr == NULL) { // remap of controller's register space failed
986 iResult = -EIO;
987 goto Exit;
988 }
989 // enable PCI busmaster
Harvey Harrisond599edc2009-01-07 14:31:57 -0800990 printk("%s enable busmaster\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800991 pci_set_master(pPciDev);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800992
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800993 // reset controller
Harvey Harrisond599edc2009-01-07 14:31:57 -0800994 printk("%s reset controller\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800995 EDRV_REGB_WRITE(EDRV_REGB_COMMAND, EDRV_REGB_COMMAND_RST);
Daniel Krueger9d7164c2008-12-19 11:41:57 -0800996
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -0800997 // wait until reset has finished
998 for (iResult = 500; iResult > 0; iResult--) {
999 if ((EDRV_REGB_READ(EDRV_REGB_COMMAND) & EDRV_REGB_COMMAND_RST)
1000 == 0) {
1001 break;
1002 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001003
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001004 schedule_timeout(10);
1005 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001006
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001007 // check hardware version, i.e. chip ID
1008 dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TCR);
1009 if (((dwTemp & EDRV_REGDW_TCR_VER_MASK) != EDRV_REGDW_TCR_VER_C)
1010 && ((dwTemp & EDRV_REGDW_TCR_VER_MASK) != EDRV_REGDW_TCR_VER_D)) { // unsupported chip
Harvey Harrisond599edc2009-01-07 14:31:57 -08001011 printk("%s Unsupported chip! TCR = 0x%08lX\n", __func__,
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001012 dwTemp);
1013 iResult = -ENODEV;
1014 goto Exit;
1015 }
1016 // disable interrupts
Harvey Harrisond599edc2009-01-07 14:31:57 -08001017 printk("%s disable interrupts\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001018 EDRV_REGW_WRITE(EDRV_REGW_INT_MASK, 0);
1019 // acknowledge all pending interrupts
1020 EDRV_REGW_WRITE(EDRV_REGW_INT_STATUS,
1021 EDRV_REGW_READ(EDRV_REGW_INT_STATUS));
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001022
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001023 // install interrupt handler
Harvey Harrisond599edc2009-01-07 14:31:57 -08001024 printk("%s install interrupt handler\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001025 iResult =
1026 request_irq(pPciDev->irq, TgtEthIsr, IRQF_SHARED,
1027 DRV_NAME /*pPciDev->dev.name */ , pPciDev);
1028 if (iResult != 0) {
1029 goto Exit;
1030 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001031
1032/*
1033 // unlock configuration registers
Harvey Harrisond599edc2009-01-07 14:31:57 -08001034 printk("%s unlock configuration registers\n", __func__);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001035 EDRV_REGB_WRITE(EDRV_REGB_CMD9346, EDRV_REGB_CMD9346_UNLOCK);
1036
1037 // check if user specified a MAC address
Harvey Harrisond599edc2009-01-07 14:31:57 -08001038 printk("%s check specified MAC address\n", __func__);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001039 for (iResult = 0; iResult < 6; iResult++)
1040 {
1041 if (EdrvInstance_l.m_InitParam.m_abMyMacAddr[iResult] != 0)
1042 {
Harvey Harrisond599edc2009-01-07 14:31:57 -08001043 printk("%s set local MAC address\n", __func__);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001044 // write this MAC address to controller
1045 EDRV_REGDW_WRITE(EDRV_REGDW_IDR0,
1046 le32_to_cpu(*((DWORD*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[0])));
1047 dwTemp = EDRV_REGDW_READ(EDRV_REGDW_IDR0);
1048
1049 EDRV_REGDW_WRITE(EDRV_REGDW_IDR4,
1050 le32_to_cpu(*((DWORD*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[4])));
1051 dwTemp = EDRV_REGDW_READ(EDRV_REGDW_IDR4);
1052 break;
1053 }
1054 }
1055 iResult = 0;
1056
1057 // lock configuration registers
1058 EDRV_REGB_WRITE(EDRV_REGB_CMD9346, EDRV_REGB_CMD9346_LOCK);
1059*/
1060
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001061 // allocate buffers
Harvey Harrisond599edc2009-01-07 14:31:57 -08001062 printk("%s allocate buffers\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001063 EdrvInstance_l.m_pbTxBuf =
1064 pci_alloc_consistent(pPciDev, EDRV_TX_BUFFER_SIZE,
1065 &EdrvInstance_l.m_pTxBufDma);
1066 if (EdrvInstance_l.m_pbTxBuf == NULL) {
1067 iResult = -ENOMEM;
1068 goto Exit;
1069 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001070
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001071 EdrvInstance_l.m_pbRxBuf =
1072 pci_alloc_consistent(pPciDev, EDRV_RX_BUFFER_SIZE,
1073 &EdrvInstance_l.m_pRxBufDma);
1074 if (EdrvInstance_l.m_pbRxBuf == NULL) {
1075 iResult = -ENOMEM;
1076 goto Exit;
1077 }
1078 // reset pointers for Tx buffers
Harvey Harrisond599edc2009-01-07 14:31:57 -08001079 printk("%s reset pointers fo Tx buffers\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001080 EDRV_REGDW_WRITE(EDRV_REGDW_TSAD0, 0);
1081 dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD0);
1082 EDRV_REGDW_WRITE(EDRV_REGDW_TSAD1, 0);
1083 dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD1);
1084 EDRV_REGDW_WRITE(EDRV_REGDW_TSAD2, 0);
1085 dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD2);
1086 EDRV_REGDW_WRITE(EDRV_REGDW_TSAD3, 0);
1087 dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD3);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001088
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001089 printk(" Command = 0x%02X\n",
1090 (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND));
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001091
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001092 // set pointer for receive buffer in controller
Harvey Harrisond599edc2009-01-07 14:31:57 -08001093 printk("%s set pointer to Rx buffer\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001094 EDRV_REGDW_WRITE(EDRV_REGDW_RBSTART, EdrvInstance_l.m_pRxBufDma);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001095
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001096 // enable transmitter and receiver
Harvey Harrisond599edc2009-01-07 14:31:57 -08001097 printk("%s enable Tx and Rx", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001098 EDRV_REGB_WRITE(EDRV_REGB_COMMAND,
1099 (EDRV_REGB_COMMAND_RE | EDRV_REGB_COMMAND_TE));
1100 printk(" Command = 0x%02X\n",
1101 (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND));
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001102
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001103 // clear missed packet counter to enable Rx/Tx process
1104 EDRV_REGDW_WRITE(EDRV_REGDW_MPC, 0);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001105
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001106 // set transmit configuration register
Harvey Harrisond599edc2009-01-07 14:31:57 -08001107 printk("%s set Tx conf register", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001108 EDRV_REGDW_WRITE(EDRV_REGDW_TCR, EDRV_REGDW_TCR_DEF);
1109 printk(" = 0x%08X\n", EDRV_REGDW_READ(EDRV_REGDW_TCR));
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001110
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001111 // set receive configuration register
Harvey Harrisond599edc2009-01-07 14:31:57 -08001112 printk("%s set Rx conf register", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001113 EDRV_REGDW_WRITE(EDRV_REGDW_RCR, EDRV_REGDW_RCR_DEF);
1114 printk(" = 0x%08X\n", EDRV_REGDW_READ(EDRV_REGDW_RCR));
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001115
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001116 // reset multicast MAC address filter
1117 EDRV_REGDW_WRITE(EDRV_REGDW_MAR0, 0);
1118 dwTemp = EDRV_REGDW_READ(EDRV_REGDW_MAR0);
1119 EDRV_REGDW_WRITE(EDRV_REGDW_MAR4, 0);
1120 dwTemp = EDRV_REGDW_READ(EDRV_REGDW_MAR4);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001121
1122/*
1123 // enable transmitter and receiver
Harvey Harrisond599edc2009-01-07 14:31:57 -08001124 printk("%s enable Tx and Rx", __func__);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001125 EDRV_REGB_WRITE(EDRV_REGB_COMMAND, (EDRV_REGB_COMMAND_RE | EDRV_REGB_COMMAND_TE));
1126 printk(" Command = 0x%02X\n", (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND));
1127*/
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001128 // disable early interrupts
1129 EDRV_REGW_WRITE(EDRV_REGW_MULINT, 0);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001130
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001131 // enable interrupts
Harvey Harrisond599edc2009-01-07 14:31:57 -08001132 printk("%s enable interrupts\n", __func__);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001133 EDRV_REGW_WRITE(EDRV_REGW_INT_MASK, EDRV_REGW_INT_MASK_DEF);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001134
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001135 Exit:
Harvey Harrisond599edc2009-01-07 14:31:57 -08001136 printk("%s finished with %d\n", __func__, iResult);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001137 return iResult;
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001138}
1139
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001140//---------------------------------------------------------------------------
1141//
1142// Function: EdrvRemoveOne
1143//
1144// Description: shuts down one PCI device
1145//
1146// Parameters: pPciDev = pointer to corresponding PCI device structure
1147//
1148// Returns: (void)
1149//
1150// State:
1151//
1152//---------------------------------------------------------------------------
1153
1154static void EdrvRemoveOne(struct pci_dev *pPciDev)
1155{
1156
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001157 if (EdrvInstance_l.m_pPciDev != pPciDev) { // trying to remove unknown device
1158 BUG_ON(EdrvInstance_l.m_pPciDev != pPciDev);
1159 goto Exit;
1160 }
1161 // disable transmitter and receiver
1162 EDRV_REGB_WRITE(EDRV_REGB_COMMAND, 0);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001163
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001164 // disable interrupts
1165 EDRV_REGW_WRITE(EDRV_REGW_INT_MASK, 0);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001166
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001167 // remove interrupt handler
1168 free_irq(pPciDev->irq, pPciDev);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001169
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001170 // free buffers
1171 if (EdrvInstance_l.m_pbTxBuf != NULL) {
1172 pci_free_consistent(pPciDev, EDRV_TX_BUFFER_SIZE,
1173 EdrvInstance_l.m_pbTxBuf,
1174 EdrvInstance_l.m_pTxBufDma);
1175 EdrvInstance_l.m_pbTxBuf = NULL;
1176 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001177
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001178 if (EdrvInstance_l.m_pbRxBuf != NULL) {
1179 pci_free_consistent(pPciDev, EDRV_RX_BUFFER_SIZE,
1180 EdrvInstance_l.m_pbRxBuf,
1181 EdrvInstance_l.m_pRxBufDma);
1182 EdrvInstance_l.m_pbRxBuf = NULL;
1183 }
1184 // unmap controller's register space
1185 if (EdrvInstance_l.m_pIoAddr != NULL) {
1186 iounmap(EdrvInstance_l.m_pIoAddr);
1187 }
1188 // disable the PCI device
1189 pci_disable_device(pPciDev);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001190
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001191 // release memory regions
1192 pci_release_regions(pPciDev);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001193
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001194 EdrvInstance_l.m_pPciDev = NULL;
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001195
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001196 Exit:;
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001197}
1198
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001199//---------------------------------------------------------------------------
1200//
1201// Function: EdrvCalcHash
1202//
1203// Description: function calculates the entry for the hash-table from MAC
1204// address
1205//
1206// Parameters: pbMAC_p - pointer to MAC address
1207//
1208// Returns: hash value
1209//
1210// State:
1211//
1212//---------------------------------------------------------------------------
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001213#define HASH_BITS 6 // used bits in hash
1214#define CRC32_POLY 0x04C11DB6 //
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001215//#define CRC32_POLY 0xEDB88320 //
1216// G(x) = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
1217
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -07001218static u8 EdrvCalcHash(u8 * pbMAC_p)
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001219{
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001220 DWORD dwByteCounter;
1221 DWORD dwBitCounter;
1222 DWORD dwData;
1223 DWORD dwCrc;
1224 DWORD dwCarry;
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -07001225 u8 *pbData;
1226 u8 bHash;
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001227
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001228 pbData = pbMAC_p;
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001229
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001230 // calculate crc32 value of mac address
1231 dwCrc = 0xFFFFFFFF;
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001232
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001233 for (dwByteCounter = 0; dwByteCounter < 6; dwByteCounter++) {
1234 dwData = *pbData;
1235 pbData++;
1236 for (dwBitCounter = 0; dwBitCounter < 8;
1237 dwBitCounter++, dwData >>= 1) {
1238 dwCarry = (((dwCrc >> 31) ^ dwData) & 1);
1239 dwCrc = dwCrc << 1;
1240 if (dwCarry != 0) {
1241 dwCrc = (dwCrc ^ CRC32_POLY) | dwCarry;
1242 }
1243 }
1244 }
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001245
1246// printk("MyCRC = 0x%08lX\n", dwCrc);
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001247 // only upper 6 bits (HASH_BITS) are used
1248 // which point to specific bit in the hash registers
Greg Kroah-Hartman2ed53cf2009-03-23 12:36:38 -07001249 bHash = (u8) ((dwCrc >> (32 - HASH_BITS)) & 0x3f);
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001250
Greg Kroah-Hartman833dfbe2008-12-19 17:11:52 -08001251 return bHash;
Daniel Krueger9d7164c2008-12-19 11:41:57 -08001252}