xref: /titanic_50/usr/src/uts/intel/io/amd8111s/amd8111s_hw.c (revision 99dda20867d903eec23291ba1ecb18a82d70096b)
1*75ab5f91Slh155975 /*
2*75ab5f91Slh155975  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3*75ab5f91Slh155975  * Use is subject to license terms.
4*75ab5f91Slh155975  */
5*75ab5f91Slh155975 
6*75ab5f91Slh155975 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*75ab5f91Slh155975 
8*75ab5f91Slh155975 /*
9*75ab5f91Slh155975  * Copyright (c) 2001-2006 Advanced Micro Devices, Inc.  All rights reserved.
10*75ab5f91Slh155975  *
11*75ab5f91Slh155975  * Redistribution and use in source and binary forms, with or without
12*75ab5f91Slh155975  * modification, are permitted provided that the following conditions are met:
13*75ab5f91Slh155975  *
14*75ab5f91Slh155975  * + Redistributions of source code must retain the above copyright notice,
15*75ab5f91Slh155975  * + this list of conditions and the following disclaimer.
16*75ab5f91Slh155975  *
17*75ab5f91Slh155975  * + Redistributions in binary form must reproduce the above copyright
18*75ab5f91Slh155975  * + notice, this list of conditions and the following disclaimer in the
19*75ab5f91Slh155975  * + documentation and/or other materials provided with the distribution.
20*75ab5f91Slh155975  *
21*75ab5f91Slh155975  * + Neither the name of Advanced Micro Devices, Inc. nor the names of its
22*75ab5f91Slh155975  * + contributors may be used to endorse or promote products derived from
23*75ab5f91Slh155975  * + this software without specific prior written permission.
24*75ab5f91Slh155975  *
25*75ab5f91Slh155975  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
26*75ab5f91Slh155975  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
27*75ab5f91Slh155975  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28*75ab5f91Slh155975  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29*75ab5f91Slh155975  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. OR
30*75ab5f91Slh155975  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31*75ab5f91Slh155975  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32*75ab5f91Slh155975  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33*75ab5f91Slh155975  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34*75ab5f91Slh155975  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35*75ab5f91Slh155975  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36*75ab5f91Slh155975  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
37*75ab5f91Slh155975  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38*75ab5f91Slh155975  *
39*75ab5f91Slh155975  * Import/Export/Re-Export/Use/Release/Transfer Restrictions and
40*75ab5f91Slh155975  * Compliance with Applicable Laws.  Notice is hereby given that
41*75ab5f91Slh155975  * the software may be subject to restrictions on use, release,
42*75ab5f91Slh155975  * transfer, importation, exportation and/or re-exportation under
43*75ab5f91Slh155975  * the laws and regulations of the United States or other
44*75ab5f91Slh155975  * countries ("Applicable Laws"), which include but are not
45*75ab5f91Slh155975  * limited to U.S. export control laws such as the Export
46*75ab5f91Slh155975  * Administration Regulations and national security controls as
47*75ab5f91Slh155975  * defined thereunder, as well as State Department controls under
48*75ab5f91Slh155975  * the U.S. Munitions List.  Permission to use and/or
49*75ab5f91Slh155975  * redistribute the software is conditioned upon compliance with
50*75ab5f91Slh155975  * all Applicable Laws, including U.S. export control laws
51*75ab5f91Slh155975  * regarding specifically designated persons, countries and
52*75ab5f91Slh155975  * nationals of countries subject to national security controls.
53*75ab5f91Slh155975  */
54*75ab5f91Slh155975 
55*75ab5f91Slh155975 
56*75ab5f91Slh155975 #include <sys/types.h>
57*75ab5f91Slh155975 #include <sys/cmn_err.h>
58*75ab5f91Slh155975 #include <sys/debug.h>
59*75ab5f91Slh155975 #include <sys/ddi.h>
60*75ab5f91Slh155975 #include <sys/sunddi.h>
61*75ab5f91Slh155975 #include "amd8111s_hw.h"
62*75ab5f91Slh155975 #include "amd8111s_main.h"
63*75ab5f91Slh155975 
64*75ab5f91Slh155975 
65*75ab5f91Slh155975 #pragma inline(mdlTransmit)
66*75ab5f91Slh155975 #pragma inline(mdlReceive)
67*75ab5f91Slh155975 
68*75ab5f91Slh155975 #pragma inline(mdlReadInterrupt)
69*75ab5f91Slh155975 #pragma inline(mdlEnableInterrupt)
70*75ab5f91Slh155975 #pragma inline(mdlDisableInterrupt)
71*75ab5f91Slh155975 
72*75ab5f91Slh155975 
73*75ab5f91Slh155975 static void mdlEnableMagicPacketWakeUp(struct LayerPointers *);
74*75ab5f91Slh155975 
75*75ab5f91Slh155975 /* PMR (Pattern Match RAM) */
76*75ab5f91Slh155975 static void mdlAddWakeUpPattern(struct LayerPointers *, unsigned char *,
77*75ab5f91Slh155975     unsigned char *, unsigned long, unsigned long, int *);
78*75ab5f91Slh155975 static void mdlRemoveWakeUpPattern(struct LayerPointers *, unsigned char *,
79*75ab5f91Slh155975     unsigned long, int *);
80*75ab5f91Slh155975 
81*75ab5f91Slh155975 static int mdlMulticastBitMapping(struct LayerPointers *, unsigned char *, int);
82*75ab5f91Slh155975 
83*75ab5f91Slh155975 static unsigned int mdlCalculateCRC(unsigned int, unsigned char *);
84*75ab5f91Slh155975 
85*75ab5f91Slh155975 static void mdlChangeFilter(struct LayerPointers *, unsigned long *);
86*75ab5f91Slh155975 static void mdlReceiveBroadCast(struct LayerPointers *);
87*75ab5f91Slh155975 static void mdlDisableReceiveBroadCast(struct LayerPointers *);
88*75ab5f91Slh155975 
89*75ab5f91Slh155975 static void mdlRequestResources(ULONG *);
90*75ab5f91Slh155975 static void mdlSetResources(struct LayerPointers *, ULONG *);
91*75ab5f91Slh155975 static void mdlFreeResources(struct LayerPointers *, ULONG *);
92*75ab5f91Slh155975 
93*75ab5f91Slh155975 /*
94*75ab5f91Slh155975  *	Initialises the data used in Mdl.
95*75ab5f91Slh155975  */
96*75ab5f91Slh155975 static void
mdlInitGlbds(struct LayerPointers * pLayerPointers)97*75ab5f91Slh155975 mdlInitGlbds(struct LayerPointers *pLayerPointers)
98*75ab5f91Slh155975 {
99*75ab5f91Slh155975 	struct mdl *pMdl = pLayerPointers->pMdl;
100*75ab5f91Slh155975 
101*75ab5f91Slh155975 	/* Disable Rx and Tx. */
102*75ab5f91Slh155975 	pMdl->init_blk->MODE = 0x0000;
103*75ab5f91Slh155975 
104*75ab5f91Slh155975 	/* Set Interrupt Delay Parameters */
105*75ab5f91Slh155975 	pMdl->IntrCoalescFlag = 1;
106*75ab5f91Slh155975 	pMdl->rx_intrcoalesc_time = 0xC8;	/* 200 */
107*75ab5f91Slh155975 	pMdl->rx_intrcoalesc_events = 5;
108*75ab5f91Slh155975 }
109*75ab5f91Slh155975 
110*75ab5f91Slh155975 void
mdlPHYAutoNegotiation(struct LayerPointers * pLayerPointers,unsigned int type)111*75ab5f91Slh155975 mdlPHYAutoNegotiation(struct LayerPointers *pLayerPointers, unsigned int type)
112*75ab5f91Slh155975 {
113*75ab5f91Slh155975 	int iData = 0;
114*75ab5f91Slh155975 	struct mdl *pMdl = pLayerPointers->pMdl;
115*75ab5f91Slh155975 
116*75ab5f91Slh155975 	/* PHY auto negotiation or force speed/duplex */
117*75ab5f91Slh155975 	switch (type) {
118*75ab5f91Slh155975 	case PHY_AUTO_NEGOTIATION: /* Auto Negotiation */
119*75ab5f91Slh155975 		/* EN_PMGR: Disable the Port Manager */
120*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
121*75ab5f91Slh155975 		drv_usecwait(100000);
122*75ab5f91Slh155975 
123*75ab5f91Slh155975 		/*
124*75ab5f91Slh155975 		 * Enable Autonegotiation the Phy now
125*75ab5f91Slh155975 		 *	XPHYANE(eXternal PHY Auto Negotiation Enable)
126*75ab5f91Slh155975 		 */
127*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2,
128*75ab5f91Slh155975 		    XPHYANE | XPHYRST);
129*75ab5f91Slh155975 
130*75ab5f91Slh155975 		/* EN_PMGR: Enable the Port Manager */
131*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
132*75ab5f91Slh155975 		    VAL1 | EN_PMGR);
133*75ab5f91Slh155975 
134*75ab5f91Slh155975 		drv_usecwait(500000);
135*75ab5f91Slh155975 
136*75ab5f91Slh155975 		pMdl->Speed = 100;
137*75ab5f91Slh155975 		pMdl->FullDuplex = B_TRUE;
138*75ab5f91Slh155975 
139*75ab5f91Slh155975 		break;
140*75ab5f91Slh155975 
141*75ab5f91Slh155975 	case PHY_FORCE_HD_100:	/* 100Mbps HD */
142*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
143*75ab5f91Slh155975 
144*75ab5f91Slh155975 		/* Force 100 Mbps, half duplex */
145*75ab5f91Slh155975 		iData |= XPHYSP;
146*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2, iData);
147*75ab5f91Slh155975 
148*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
149*75ab5f91Slh155975 		    VAL1 | EN_PMGR);
150*75ab5f91Slh155975 
151*75ab5f91Slh155975 		drv_usecwait(500000);
152*75ab5f91Slh155975 
153*75ab5f91Slh155975 		pMdl->Speed = 100;
154*75ab5f91Slh155975 		pMdl->FullDuplex = B_FALSE;
155*75ab5f91Slh155975 
156*75ab5f91Slh155975 		break;
157*75ab5f91Slh155975 
158*75ab5f91Slh155975 	case PHY_FORCE_FD_100:	/* 100Mbps FD */
159*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
160*75ab5f91Slh155975 
161*75ab5f91Slh155975 		/* Force 100 Mbps, full duplex */
162*75ab5f91Slh155975 		iData |= (XPHYSP | XPHYFD);
163*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2, iData);
164*75ab5f91Slh155975 
165*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
166*75ab5f91Slh155975 		    VAL1 | EN_PMGR);
167*75ab5f91Slh155975 
168*75ab5f91Slh155975 		drv_usecwait(500000);
169*75ab5f91Slh155975 
170*75ab5f91Slh155975 		pMdl->Speed = 100;
171*75ab5f91Slh155975 		pMdl->FullDuplex = B_TRUE;
172*75ab5f91Slh155975 
173*75ab5f91Slh155975 		break;
174*75ab5f91Slh155975 
175*75ab5f91Slh155975 	case PHY_FORCE_HD_10: /* 10 Mbps HD  */
176*75ab5f91Slh155975 		/* Disable the Port Manager */
177*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
178*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2, iData);
179*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
180*75ab5f91Slh155975 		    VAL1 | EN_PMGR);
181*75ab5f91Slh155975 
182*75ab5f91Slh155975 		drv_usecwait(500000);
183*75ab5f91Slh155975 
184*75ab5f91Slh155975 		pMdl->Speed = 10;
185*75ab5f91Slh155975 		pMdl->FullDuplex = B_FALSE;
186*75ab5f91Slh155975 
187*75ab5f91Slh155975 		break;
188*75ab5f91Slh155975 
189*75ab5f91Slh155975 	case PHY_FORCE_FD_10: /* 10Mbps FD  */
190*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
191*75ab5f91Slh155975 
192*75ab5f91Slh155975 		iData |= XPHYFD;
193*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2, iData);
194*75ab5f91Slh155975 
195*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
196*75ab5f91Slh155975 		    VAL1 | EN_PMGR);
197*75ab5f91Slh155975 
198*75ab5f91Slh155975 		drv_usecwait(500000);
199*75ab5f91Slh155975 
200*75ab5f91Slh155975 		pMdl->Speed = 10;
201*75ab5f91Slh155975 		pMdl->FullDuplex = B_TRUE;
202*75ab5f91Slh155975 
203*75ab5f91Slh155975 		break;
204*75ab5f91Slh155975 	}
205*75ab5f91Slh155975 }
206*75ab5f91Slh155975 
207*75ab5f91Slh155975 /*
208*75ab5f91Slh155975  *	Clear HW configuration.
209*75ab5f91Slh155975  */
210*75ab5f91Slh155975 static void
mdlClearHWConfig(struct LayerPointers * pLayerPointers)211*75ab5f91Slh155975 mdlClearHWConfig(struct LayerPointers *pLayerPointers)
212*75ab5f91Slh155975 {
213*75ab5f91Slh155975 	/*
214*75ab5f91Slh155975 	 * Before the network controller is ready for operation,
215*75ab5f91Slh155975 	 * several registers must be initialized.
216*75ab5f91Slh155975 	 */
217*75ab5f91Slh155975 	unsigned int data32;
218*75ab5f91Slh155975 	int JumboFlag = JUMBO_DISABLED;
219*75ab5f91Slh155975 	ULONG MemBaseAddress;
220*75ab5f91Slh155975 
221*75ab5f91Slh155975 	MemBaseAddress = pLayerPointers->pMdl->Mem_Address;
222*75ab5f91Slh155975 
223*75ab5f91Slh155975 	/* AUTOPOLL0 Register */
224*75ab5f91Slh155975 	WRITE_REG16(pLayerPointers, MemBaseAddress + AUTOPOLL0, 0x8101);
225*75ab5f91Slh155975 
226*75ab5f91Slh155975 	/* Clear RCV_RING_BASE_ADDR */
227*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR0, 0);
228*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR1, 0);
229*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR0, 0);
230*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR2, 0);
231*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR3, 0);
232*75ab5f91Slh155975 
233*75ab5f91Slh155975 	/* Clear XMT_RING_BASE_ADDR */
234*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_BASE_ADDR0, 0);
235*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_BASE_ADDR1, 0);
236*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_BASE_ADDR2, 0);
237*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_BASE_ADDR3, 0);
238*75ab5f91Slh155975 
239*75ab5f91Slh155975 	/* Clear CMD0 / CMD2 */
240*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + CMD0, 0x000F0F7F);
241*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + CMD2, 0x3F7F3F7F);
242*75ab5f91Slh155975 
243*75ab5f91Slh155975 	/* Enable Port Management */
244*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + CMD3, VAL1 | EN_PMGR);
245*75ab5f91Slh155975 
246*75ab5f91Slh155975 	/* Clear CMD7 */
247*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + CMD7, 0x1B);
248*75ab5f91Slh155975 
249*75ab5f91Slh155975 	/* Clear CTRL0/1 */
250*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + CTRL1, XMTSP_MASK);
251*75ab5f91Slh155975 
252*75ab5f91Slh155975 	/* Clear DLY_INT_A/B */
253*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_A, 0);
254*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_B, 0);
255*75ab5f91Slh155975 
256*75ab5f91Slh155975 	/* Clear FLOW_CONTROL */
257*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + FLOW_CONTROL, 0);
258*75ab5f91Slh155975 
259*75ab5f91Slh155975 	/* Clear INT0 */
260*75ab5f91Slh155975 	data32 = READ_REG32(pLayerPointers, MemBaseAddress + INT0);
261*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + INT0, data32);
262*75ab5f91Slh155975 
263*75ab5f91Slh155975 	/* Clear STVAL */
264*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + STVAL, 0);
265*75ab5f91Slh155975 
266*75ab5f91Slh155975 	/* Clear INTEN0 */
267*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + INTEN0, 0x1F7F7F1F);
268*75ab5f91Slh155975 
269*75ab5f91Slh155975 	/* Clear LADRF */
270*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + LADRF1, 0);
271*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + LADRF1 + 4, 0);
272*75ab5f91Slh155975 
273*75ab5f91Slh155975 	/* Clear LED0 */
274*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + LED0, 0);
275*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + LED1, 0);
276*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + LED2, 0);
277*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + LED3, 0);
278*75ab5f91Slh155975 
279*75ab5f91Slh155975 	/* Set RCV_RING_CFG */
280*75ab5f91Slh155975 	WRITE_REG16(pLayerPointers, MemBaseAddress + RCV_RING_CFG, 1);
281*75ab5f91Slh155975 
282*75ab5f91Slh155975 	/* SRAM_SIZE & SRAM_BOUNDARY register combined */
283*75ab5f91Slh155975 	if (JumboFlag == JUMBO_ENABLED) {
284*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, MemBaseAddress + SRAM_SIZE,
285*75ab5f91Slh155975 		    0xc0010);
286*75ab5f91Slh155975 	} else {
287*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, MemBaseAddress + SRAM_SIZE,
288*75ab5f91Slh155975 		    0x80010);
289*75ab5f91Slh155975 	}
290*75ab5f91Slh155975 
291*75ab5f91Slh155975 	/* Clear XMT_RING0/1/2/3_LEN */
292*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LEN0, 0);
293*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LEN1, 0);
294*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LEN2, 0);
295*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LEN3, 0);
296*75ab5f91Slh155975 
297*75ab5f91Slh155975 	/* Clear XMT_RING_LIMIT */
298*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LIMIT, 0);
299*75ab5f91Slh155975 
300*75ab5f91Slh155975 	WRITE_REG16(pLayerPointers, MemBaseAddress + MIB_ADDR, MIB_CLEAR);
301*75ab5f91Slh155975 }
302*75ab5f91Slh155975 
303*75ab5f91Slh155975 unsigned int
mdlReadMib(struct LayerPointers * pLayerPointers,char MIB_COUNTER)304*75ab5f91Slh155975 mdlReadMib(struct LayerPointers *pLayerPointers, char MIB_COUNTER)
305*75ab5f91Slh155975 {
306*75ab5f91Slh155975 	unsigned int status;
307*75ab5f91Slh155975 	unsigned int data;
308*75ab5f91Slh155975 	unsigned long mmio = pLayerPointers->pMdl->Mem_Address;
309*75ab5f91Slh155975 
310*75ab5f91Slh155975 	WRITE_REG16(pLayerPointers, mmio + MIB_ADDR, MIB_RD_CMD | MIB_COUNTER);
311*75ab5f91Slh155975 	do {
312*75ab5f91Slh155975 		status = READ_REG16(pLayerPointers, mmio + MIB_ADDR);
313*75ab5f91Slh155975 	} while ((status & MIB_CMD_ACTIVE));
314*75ab5f91Slh155975 
315*75ab5f91Slh155975 	data = READ_REG32(pLayerPointers, mmio + MIB_DATA);
316*75ab5f91Slh155975 	return (data);
317*75ab5f91Slh155975 }
318*75ab5f91Slh155975 
319*75ab5f91Slh155975 /* Return 1 on success, return 0 on fail */
320*75ab5f91Slh155975 unsigned int
mdlReadPHY(struct LayerPointers * pLayerPointers,unsigned char phyid,unsigned char regaddr,unsigned int * value)321*75ab5f91Slh155975 mdlReadPHY(struct LayerPointers *pLayerPointers, unsigned char phyid,
322*75ab5f91Slh155975     unsigned char regaddr, unsigned int *value)
323*75ab5f91Slh155975 {
324*75ab5f91Slh155975 	unsigned int status, data, count;
325*75ab5f91Slh155975 	unsigned long mmio = pLayerPointers->pMdl->Mem_Address;
326*75ab5f91Slh155975 
327*75ab5f91Slh155975 	count = 0;
328*75ab5f91Slh155975 	do {
329*75ab5f91Slh155975 		status = READ_REG16(pLayerPointers, mmio + PHY_ACCESS);
330*75ab5f91Slh155975 		count ++;
331*75ab5f91Slh155975 		drv_usecwait(10);
332*75ab5f91Slh155975 	} while ((status & PHY_CMD_ACTIVE) & (count < PHY_MAX_RETRY));
333*75ab5f91Slh155975 
334*75ab5f91Slh155975 	if (count == PHY_MAX_RETRY) {
335*75ab5f91Slh155975 		return (0);
336*75ab5f91Slh155975 	}
337*75ab5f91Slh155975 
338*75ab5f91Slh155975 	data = ((regaddr & 0x1f) << 16) | ((phyid & 0x1f) << 21) | PHY_RD_CMD;
339*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, mmio + PHY_ACCESS, data);
340*75ab5f91Slh155975 	do {
341*75ab5f91Slh155975 		status = READ_REG16(pLayerPointers, mmio + PHY_ACCESS);
342*75ab5f91Slh155975 		drv_usecwait(10);
343*75ab5f91Slh155975 		count ++;
344*75ab5f91Slh155975 	} while ((status & PHY_CMD_ACTIVE) & (count < PHY_MAX_RETRY));
345*75ab5f91Slh155975 
346*75ab5f91Slh155975 	if ((count == PHY_MAX_RETRY) || (status & PHY_RD_ERR)) {
347*75ab5f91Slh155975 		return (0);
348*75ab5f91Slh155975 	}
349*75ab5f91Slh155975 
350*75ab5f91Slh155975 	*value = status & 0xffff;
351*75ab5f91Slh155975 	return (1);
352*75ab5f91Slh155975 }
353*75ab5f91Slh155975 
354*75ab5f91Slh155975 void
mdlGetPHYID(struct LayerPointers * pLayerPointers)355*75ab5f91Slh155975 mdlGetPHYID(struct LayerPointers *pLayerPointers)
356*75ab5f91Slh155975 {
357*75ab5f91Slh155975 	unsigned int id1, id2, i;
358*75ab5f91Slh155975 	for (i = 1; i < 32; i++) {
359*75ab5f91Slh155975 		if (mdlReadPHY(pLayerPointers, i, MII_PHYSID1, &id1) == 0)
360*75ab5f91Slh155975 			continue;
361*75ab5f91Slh155975 		if (mdlReadPHY(pLayerPointers, i, MII_PHYSID2, &id2) == 0)
362*75ab5f91Slh155975 			continue;
363*75ab5f91Slh155975 		if ((id1 != 0xffff) & (id2 != 0xffff)) {
364*75ab5f91Slh155975 			pLayerPointers->pMdl->phy_id = i;
365*75ab5f91Slh155975 			return;
366*75ab5f91Slh155975 		}
367*75ab5f91Slh155975 	}
368*75ab5f91Slh155975 }
369*75ab5f91Slh155975 
370*75ab5f91Slh155975 /* Return 1 on success, return 0 on fail */
371*75ab5f91Slh155975 unsigned int
mdlWritePHY(struct LayerPointers * pLayerPointers,unsigned char phyid,unsigned char regaddr,unsigned int value)372*75ab5f91Slh155975 mdlWritePHY(struct LayerPointers *pLayerPointers, unsigned char phyid,
373*75ab5f91Slh155975     unsigned char regaddr, unsigned int value)
374*75ab5f91Slh155975 {
375*75ab5f91Slh155975 	unsigned int status, data, count;
376*75ab5f91Slh155975 	unsigned long mmio = pLayerPointers->pMdl->Mem_Address;
377*75ab5f91Slh155975 
378*75ab5f91Slh155975 	count = 0;
379*75ab5f91Slh155975 	do {
380*75ab5f91Slh155975 		status = READ_REG16(pLayerPointers, mmio + PHY_ACCESS);
381*75ab5f91Slh155975 		count ++;
382*75ab5f91Slh155975 		drv_usecwait(10);
383*75ab5f91Slh155975 	} while ((status & PHY_CMD_ACTIVE) & (count < PHY_MAX_RETRY));
384*75ab5f91Slh155975 
385*75ab5f91Slh155975 	if (count == PHY_MAX_RETRY) {
386*75ab5f91Slh155975 		return (0);
387*75ab5f91Slh155975 	}
388*75ab5f91Slh155975 
389*75ab5f91Slh155975 	data = ((regaddr & 0x1f) << 16) | ((phyid & 0x1f) << 21) |
390*75ab5f91Slh155975 	    (value & 0xffff) | PHY_WR_CMD;
391*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, mmio + PHY_ACCESS, data);
392*75ab5f91Slh155975 
393*75ab5f91Slh155975 	do {
394*75ab5f91Slh155975 		status = READ_REG16(pLayerPointers, mmio + PHY_ACCESS);
395*75ab5f91Slh155975 		drv_usecwait(10);
396*75ab5f91Slh155975 		count ++;
397*75ab5f91Slh155975 	} while ((status & PHY_CMD_ACTIVE) & (count < PHY_MAX_RETRY));
398*75ab5f91Slh155975 
399*75ab5f91Slh155975 	if ((count == PHY_MAX_RETRY) && (status & PHY_RD_ERR)) {
400*75ab5f91Slh155975 		return (0);
401*75ab5f91Slh155975 	}
402*75ab5f91Slh155975 
403*75ab5f91Slh155975 	return (1);
404*75ab5f91Slh155975 }
405*75ab5f91Slh155975 
406*75ab5f91Slh155975 /*
407*75ab5f91Slh155975  *	To Send the packet.
408*75ab5f91Slh155975  */
409*75ab5f91Slh155975 void
mdlTransmit(struct LayerPointers * pLayerPointers)410*75ab5f91Slh155975 mdlTransmit(struct LayerPointers *pLayerPointers)
411*75ab5f91Slh155975 {
412*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
413*75ab5f91Slh155975 	    VAL1 | TDMD0);
414*75ab5f91Slh155975 }
415*75ab5f91Slh155975 
416*75ab5f91Slh155975 /*
417*75ab5f91Slh155975  *	To Receive a packet.
418*75ab5f91Slh155975  */
419*75ab5f91Slh155975 void
mdlReceive(struct LayerPointers * pLayerPointers)420*75ab5f91Slh155975 mdlReceive(struct LayerPointers *pLayerPointers)
421*75ab5f91Slh155975 {
422*75ab5f91Slh155975 	/*
423*75ab5f91Slh155975 	 * Receive Demand for ring 0, which when set causes the Descriptor
424*75ab5f91Slh155975 	 * Management Unit to access the Receive Descriptor Ring if it does
425*75ab5f91Slh155975 	 * not already own the next descriptor.
426*75ab5f91Slh155975 	 */
427*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
428*75ab5f91Slh155975 	    VAL2 | RDMD0);
429*75ab5f91Slh155975 }
430*75ab5f91Slh155975 
431*75ab5f91Slh155975 /*
432*75ab5f91Slh155975  * Read the NIC interrupt.
433*75ab5f91Slh155975  *
434*75ab5f91Slh155975  * Returns:
435*75ab5f91Slh155975  *	the value of interrupt causes register
436*75ab5f91Slh155975  */
437*75ab5f91Slh155975 unsigned int
mdlReadInterrupt(struct LayerPointers * pLayerPointers)438*75ab5f91Slh155975 mdlReadInterrupt(struct LayerPointers *pLayerPointers)
439*75ab5f91Slh155975 {
440*75ab5f91Slh155975 	unsigned int nINT0;
441*75ab5f91Slh155975 	struct mdl *pMdl = 0;
442*75ab5f91Slh155975 
443*75ab5f91Slh155975 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
444*75ab5f91Slh155975 
445*75ab5f91Slh155975 	/*
446*75ab5f91Slh155975 	 * INT0 identifies the source or sources of an interrupt. With the
447*75ab5f91Slh155975 	 * exception of INTR and INTPN, all bits in this register are "write
448*75ab5f91Slh155975 	 * 1 to clear" so that the CPU can clear the interrupt condition by
449*75ab5f91Slh155975 	 * reading the register and then writing back the same data that it
450*75ab5f91Slh155975 	 * read. Writing a 0 to a bit in this register has no effect.
451*75ab5f91Slh155975 	 */
452*75ab5f91Slh155975 
453*75ab5f91Slh155975 	/* Read interrupt status */
454*75ab5f91Slh155975 	nINT0 = READ_REG32(pLayerPointers, pMdl->Mem_Address + INT0);
455*75ab5f91Slh155975 
456*75ab5f91Slh155975 	/* Process all the INT event until INTR bit is clear. */
457*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INT0, nINT0);
458*75ab5f91Slh155975 	return (nINT0);
459*75ab5f91Slh155975 }
460*75ab5f91Slh155975 
461*75ab5f91Slh155975 void
mdlHWReset(struct LayerPointers * pLayerPointers)462*75ab5f91Slh155975 mdlHWReset(struct LayerPointers *pLayerPointers)
463*75ab5f91Slh155975 {
464*75ab5f91Slh155975 	struct mdl *pMdl = pLayerPointers->pMdl;
465*75ab5f91Slh155975 	unsigned int ulData, i = 0;
466*75ab5f91Slh155975 	int  JumboFlag = JUMBO_DISABLED;
467*75ab5f91Slh155975 	ULONG Mem_Address = pMdl->Mem_Address;
468*75ab5f91Slh155975 
469*75ab5f91Slh155975 	/*
470*75ab5f91Slh155975 	 * Stop the Card:
471*75ab5f91Slh155975 	 *	First we make sure that the device is stopped and no
472*75ab5f91Slh155975 	 *	more interrupts come out. Also some registers must be
473*75ab5f91Slh155975 	 *	programmed with CSR0 STOP bit set.
474*75ab5f91Slh155975 	 */
475*75ab5f91Slh155975 	mdlStopChip(pLayerPointers);
476*75ab5f91Slh155975 
477*75ab5f91Slh155975 	/*
478*75ab5f91Slh155975 	 * MAC Address Setup:
479*75ab5f91Slh155975 	 *	MAC Physical Address register. All bits in this register are
480*75ab5f91Slh155975 	 *	restored to default values when the RST pin is asserted.
481*75ab5f91Slh155975 	 */
482*75ab5f91Slh155975 	for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++) {
483*75ab5f91Slh155975 		WRITE_REG8(pLayerPointers, pMdl->Mem_Address + PADR + i,
484*75ab5f91Slh155975 		    pMdl->Mac[i]);
485*75ab5f91Slh155975 	}
486*75ab5f91Slh155975 
487*75ab5f91Slh155975 	/* Set RCV_RING_CFG */
488*75ab5f91Slh155975 
489*75ab5f91Slh155975 	if (JumboFlag == JUMBO_ENABLED) {
490*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD2,
491*75ab5f91Slh155975 		    VAL0 | APAD_XMT | REX_RTRY | VAL1 | DXMTFCS | RPA | VAL2);
492*75ab5f91Slh155975 
493*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
494*75ab5f91Slh155975 		    VAL2 | JUMBO);
495*75ab5f91Slh155975 	} else {
496*75ab5f91Slh155975 		/*
497*75ab5f91Slh155975 		 * APAD_XMT: Auto Pad Transmit. When set, APAD_XMT enables
498*75ab5f91Slh155975 		 * the automatic padding feature. Transmit frames are padded
499*75ab5f91Slh155975 		 * to extend them to 64 bytes including FCS.
500*75ab5f91Slh155975 		 *
501*75ab5f91Slh155975 		 * DXMTFCS: Disable Transmit CRC. When DXMTFCS is set to 1, no
502*75ab5f91Slh155975 		 * Transmit CRC is generated. DXMTFCS is overridden when
503*75ab5f91Slh155975 		 * ADD_FCS and ENP bits are set in the transmit descriptor.
504*75ab5f91Slh155975 		 *
505*75ab5f91Slh155975 		 * ASTRIP_RCV: Auto Strip Receive. When ASTRP_RCV is set to 1,
506*75ab5f91Slh155975 		 * the receiver automatically strips pad bytes from the
507*75ab5f91Slh155975 		 * received message by observing the value in the length field
508*75ab5f91Slh155975 		 * and by stripping excess bytes if this value is below the
509*75ab5f91Slh155975 		 * minimum data size (46 bytes).
510*75ab5f91Slh155975 		 */
511*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD2,
512*75ab5f91Slh155975 		    VAL0 | APAD_XMT | REX_RTRY | REX_UFLO | VAL1 | DXMTFCS
513*75ab5f91Slh155975 		    | ASTRIP_RCV | RPA | VAL2);
514*75ab5f91Slh155975 	}
515*75ab5f91Slh155975 
516*75ab5f91Slh155975 	/* Transmit Start Point setting (csr80) */
517*75ab5f91Slh155975 	ulData = READ_REG32(pLayerPointers, Mem_Address + CTRL1);
518*75ab5f91Slh155975 	ulData &= ~XMTSP_MASK;
519*75ab5f91Slh155975 
520*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL1,
521*75ab5f91Slh155975 	    ulData | XMTSP_128);
522*75ab5f91Slh155975 	/* Disable Prom  */
523*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD2, PROM);
524*75ab5f91Slh155975 
525*75ab5f91Slh155975 	mdlPHYAutoNegotiation(pLayerPointers, pMdl->External_Phy);
526*75ab5f91Slh155975 
527*75ab5f91Slh155975 	pMdl->IpgValue = MIN_IPG_DEFAULT;
528*75ab5f91Slh155975 	/* Set the IPG value */
529*75ab5f91Slh155975 	WRITE_REG16(pLayerPointers, pMdl->Mem_Address + IFS,
530*75ab5f91Slh155975 	    pMdl->IpgValue);
531*75ab5f91Slh155975 
532*75ab5f91Slh155975 	/* Disable Following Interrupts. */
533*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INTEN0,
534*75ab5f91Slh155975 	    APINT5EN | APINT4EN | APINT3EN |
535*75ab5f91Slh155975 	    APINT2EN | APINT1EN | APINT0EN | MIIPDTINTEN |
536*75ab5f91Slh155975 	    MCCIINTEN | MCCINTEN | MREINTEN |
537*75ab5f91Slh155975 	    TINTEN0 |
538*75ab5f91Slh155975 	    SPNDINTEN | MPINTEN | SINTEN | LCINTEN);
539*75ab5f91Slh155975 
540*75ab5f91Slh155975 	/* Enable Following Interrupt */
541*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INTEN0,
542*75ab5f91Slh155975 	    VAL0 | RINTEN0);
543*75ab5f91Slh155975 
544*75ab5f91Slh155975 	/* Base Address of Transmit Descriptor Ring 0. */
545*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + XMT_RING_BASE_ADDR0,
546*75ab5f91Slh155975 	    pMdl->init_blk->TDRA);
547*75ab5f91Slh155975 
548*75ab5f91Slh155975 	/* Base Address of Receive Descriptor Ring. */
549*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + RCV_RING_BASE_ADDR0,
550*75ab5f91Slh155975 	    pMdl->init_blk->RDRA);
551*75ab5f91Slh155975 
552*75ab5f91Slh155975 	/* The number of descriptors in Transmit Descriptor Ring 0 */
553*75ab5f91Slh155975 	WRITE_REG16(pLayerPointers, pMdl->Mem_Address + XMT_RING_LEN0,
554*75ab5f91Slh155975 	    (unsigned short)pLayerPointers->pMdl->TxRingSize);
555*75ab5f91Slh155975 
556*75ab5f91Slh155975 	/*
557*75ab5f91Slh155975 	 * Receive Descriptor Ring Length. All bits in this register are
558*75ab5f91Slh155975 	 * restored to default values when the RST pin is asserted.
559*75ab5f91Slh155975 	 */
560*75ab5f91Slh155975 	WRITE_REG16(pLayerPointers, pMdl->Mem_Address + RCV_RING_LEN0,
561*75ab5f91Slh155975 	    (unsigned short)pLayerPointers->pMdl->RxRingSize);
562*75ab5f91Slh155975 
563*75ab5f91Slh155975 	if (pLayerPointers->pMdl->IntrCoalescFlag) {
564*75ab5f91Slh155975 		SetIntrCoalesc(pLayerPointers, B_TRUE);
565*75ab5f91Slh155975 	}
566*75ab5f91Slh155975 
567*75ab5f91Slh155975 	/* Start the chip */
568*75ab5f91Slh155975 	mdlStartChip(pLayerPointers);
569*75ab5f91Slh155975 }
570*75ab5f91Slh155975 
571*75ab5f91Slh155975 /*
572*75ab5f91Slh155975  * Perform the open oerations on the adapter.
573*75ab5f91Slh155975  */
574*75ab5f91Slh155975 void
mdlOpen(struct LayerPointers * pLayerPointers)575*75ab5f91Slh155975 mdlOpen(struct LayerPointers *pLayerPointers)
576*75ab5f91Slh155975 {
577*75ab5f91Slh155975 	int i, sum;
578*75ab5f91Slh155975 	struct mdl *pMdl = pLayerPointers->pMdl;
579*75ab5f91Slh155975 
580*75ab5f91Slh155975 	/* Get Mac address */
581*75ab5f91Slh155975 	sum = 0;
582*75ab5f91Slh155975 	for (i = 0; i < 6; i++) {
583*75ab5f91Slh155975 		pMdl->Mac[i] = READ_REG8(pLayerPointers,
584*75ab5f91Slh155975 		    pMdl->Mem_Address + PADR + i);
585*75ab5f91Slh155975 		sum += pMdl->Mac[i];
586*75ab5f91Slh155975 	}
587*75ab5f91Slh155975 	if (sum == 0) {
588*75ab5f91Slh155975 		for (i = 0; i < 6; i++) {
589*75ab5f91Slh155975 			pMdl->Mac[i] = 0;
590*75ab5f91Slh155975 		}
591*75ab5f91Slh155975 	}
592*75ab5f91Slh155975 
593*75ab5f91Slh155975 	/* Initialize the hardware */
594*75ab5f91Slh155975 	mdlClearHWConfig(pLayerPointers);
595*75ab5f91Slh155975 	mdlGetPHYID(pLayerPointers);
596*75ab5f91Slh155975 
597*75ab5f91Slh155975 }
598*75ab5f91Slh155975 
599*75ab5f91Slh155975 void
mdlGetMacAddress(struct LayerPointers * pLayerPointers,unsigned char * macAddress)600*75ab5f91Slh155975 mdlGetMacAddress(struct LayerPointers *pLayerPointers,
601*75ab5f91Slh155975     unsigned char *macAddress)
602*75ab5f91Slh155975 {
603*75ab5f91Slh155975 	struct mdl *pMdl = pLayerPointers->pMdl;
604*75ab5f91Slh155975 	int i;
605*75ab5f91Slh155975 
606*75ab5f91Slh155975 	for (i = 0; i < 6; i++) {
607*75ab5f91Slh155975 		macAddress[i] =	pMdl->Mac[i] = READ_REG8(pLayerPointers,
608*75ab5f91Slh155975 		    pMdl->Mem_Address + PADR + i);
609*75ab5f91Slh155975 	}
610*75ab5f91Slh155975 
611*75ab5f91Slh155975 }
612*75ab5f91Slh155975 
613*75ab5f91Slh155975 
614*75ab5f91Slh155975 void
mdlSetMacAddress(struct LayerPointers * pLayerPointers,unsigned char * macAddress)615*75ab5f91Slh155975 mdlSetMacAddress(struct LayerPointers *pLayerPointers,
616*75ab5f91Slh155975     unsigned char *macAddress)
617*75ab5f91Slh155975 {
618*75ab5f91Slh155975 	int i;
619*75ab5f91Slh155975 	struct mdl *pMdl = 0;
620*75ab5f91Slh155975 
621*75ab5f91Slh155975 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
622*75ab5f91Slh155975 
623*75ab5f91Slh155975 	pMdl->Mac[0] = macAddress[0];
624*75ab5f91Slh155975 	pMdl->Mac[1] = macAddress[1];
625*75ab5f91Slh155975 	pMdl->Mac[2] = macAddress[2];
626*75ab5f91Slh155975 	pMdl->Mac[3] = macAddress[3];
627*75ab5f91Slh155975 	pMdl->Mac[4] = macAddress[4];
628*75ab5f91Slh155975 	pMdl->Mac[5] = macAddress[5];
629*75ab5f91Slh155975 
630*75ab5f91Slh155975 	/*
631*75ab5f91Slh155975 	 * MAC Address Setup:
632*75ab5f91Slh155975 	 *	MAC Physical Address register. All bits in this register are
633*75ab5f91Slh155975 	 *	restored to default values when the RST pin is asserted.
634*75ab5f91Slh155975 	 */
635*75ab5f91Slh155975 	for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++) {
636*75ab5f91Slh155975 		WRITE_REG8(pLayerPointers, pMdl->Mem_Address + PADR + i,
637*75ab5f91Slh155975 		    pMdl->Mac[i]);
638*75ab5f91Slh155975 	}
639*75ab5f91Slh155975 }
640*75ab5f91Slh155975 
641*75ab5f91Slh155975 /*
642*75ab5f91Slh155975  * This array is filled with the size of the memory required for
643*75ab5f91Slh155975  * allocating purposes.
644*75ab5f91Slh155975  */
645*75ab5f91Slh155975 static void
mdlRequestResources(ULONG * mem_req_array)646*75ab5f91Slh155975 mdlRequestResources(ULONG *mem_req_array)
647*75ab5f91Slh155975 {
648*75ab5f91Slh155975 	/* 1) For mdl structure */
649*75ab5f91Slh155975 	*mem_req_array = VIRTUAL;		/* Type */
650*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (struct mdl); /* Size */
651*75ab5f91Slh155975 
652*75ab5f91Slh155975 	/* 2) For PMR PtrList array (PMR_ptrList) */
653*75ab5f91Slh155975 	*(++mem_req_array) = VIRTUAL;		/* Type */
654*75ab5f91Slh155975 	/* Size */
655*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (unsigned int) * (MAX_ALLOWED_PATTERNS + 2);
656*75ab5f91Slh155975 
657*75ab5f91Slh155975 	/* 3) For PMR Pattern List array (PatternList) */
658*75ab5f91Slh155975 	*(++mem_req_array) = VIRTUAL;			/* Type */
659*75ab5f91Slh155975 	/* Size */
660*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (unsigned char) * (MAX_PATTERNS + 2);
661*75ab5f91Slh155975 
662*75ab5f91Slh155975 	/* 4) For pmr PatternLength array (PatternLength) */
663*75ab5f91Slh155975 	*(++mem_req_array) = VIRTUAL;			/* Type */
664*75ab5f91Slh155975 	/* Size */
665*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (unsigned int) * (MAX_ALLOWED_PATTERNS + 2);
666*75ab5f91Slh155975 
667*75ab5f91Slh155975 	/*
668*75ab5f91Slh155975 	 * 5) For the init_block (init_blk)
669*75ab5f91Slh155975 	 */
670*75ab5f91Slh155975 	*(++mem_req_array) = VIRTUAL;
671*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (struct init_block);
672*75ab5f91Slh155975 
673*75ab5f91Slh155975 	*(++mem_req_array) = 0;
674*75ab5f91Slh155975 	mem_req_array++;
675*75ab5f91Slh155975 }
676*75ab5f91Slh155975 
677*75ab5f91Slh155975 
678*75ab5f91Slh155975 /*
679*75ab5f91Slh155975  *	Purpose  :
680*75ab5f91Slh155975  *		This array contains the details of the allocated memory. The
681*75ab5f91Slh155975  *		pointers are taken from the respective locations in the array &
682*75ab5f91Slh155975  *		assigned appropriately to the respective structures.
683*75ab5f91Slh155975  *
684*75ab5f91Slh155975  *	Arguments :
685*75ab5f91Slh155975  *		pLayerPointers
686*75ab5f91Slh155975  *			Pointer to the adapter structure.
687*75ab5f91Slh155975  *		pmem_set_array
688*75ab5f91Slh155975  *			Pointer to the array that holds the data after required
689*75ab5f91Slh155975  *			allocating memory.
690*75ab5f91Slh155975  */
691*75ab5f91Slh155975 static void
mdlSetResources(struct LayerPointers * pLayerPointers,ULONG * pmem_set_array)692*75ab5f91Slh155975 mdlSetResources(struct LayerPointers *pLayerPointers, ULONG *pmem_set_array)
693*75ab5f91Slh155975 {
694*75ab5f91Slh155975 	struct mdl *pMdl = 0;
695*75ab5f91Slh155975 
696*75ab5f91Slh155975 	/* 1) For mdl structure */
697*75ab5f91Slh155975 	pmem_set_array++;	/* Type */
698*75ab5f91Slh155975 	pmem_set_array++;	/* Size */
699*75ab5f91Slh155975 	pLayerPointers->pMdl = (struct mdl *)(*pmem_set_array);
700*75ab5f91Slh155975 
701*75ab5f91Slh155975 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
702*75ab5f91Slh155975 
703*75ab5f91Slh155975 	pMdl->RxRingLenBits = RX_RING_LEN_BITS;
704*75ab5f91Slh155975 	pMdl->TxRingLenBits = TX_RING_LEN_BITS;
705*75ab5f91Slh155975 	pMdl->TxRingSize = TX_RING_SIZE;
706*75ab5f91Slh155975 	pMdl->RxRingSize = RX_RING_SIZE;
707*75ab5f91Slh155975 
708*75ab5f91Slh155975 	/*
709*75ab5f91Slh155975 	 * Default values that would be used if it does not enable
710*75ab5f91Slh155975 	 * enable dynamic ipg.
711*75ab5f91Slh155975 	 */
712*75ab5f91Slh155975 
713*75ab5f91Slh155975 	/*  2) Set the pointers to the PMR Pointer List */
714*75ab5f91Slh155975 	pmem_set_array++;	/* Type */
715*75ab5f91Slh155975 	pmem_set_array++;	/* Size */
716*75ab5f91Slh155975 	pmem_set_array++;	/* Virtual Addr of PtrList */
717*75ab5f91Slh155975 	pMdl->PMR_PtrList = (unsigned int *)(*pmem_set_array);
718*75ab5f91Slh155975 
719*75ab5f91Slh155975 	/* 3) Set the pointers to the PMR Pattern List */
720*75ab5f91Slh155975 	pmem_set_array++;	/* Type */
721*75ab5f91Slh155975 	pmem_set_array++;	/* Size */
722*75ab5f91Slh155975 	pmem_set_array++;	/* Virtual Addr of PatternList */
723*75ab5f91Slh155975 	pMdl->PatternList = (unsigned char *)(*pmem_set_array);
724*75ab5f91Slh155975 
725*75ab5f91Slh155975 	/* 4) Set the pointers to the PMR Pattern Length */
726*75ab5f91Slh155975 	pmem_set_array++;	/* Type */
727*75ab5f91Slh155975 	pmem_set_array++;	/* Size */
728*75ab5f91Slh155975 	pmem_set_array++;	/* Virtual Addr of PatternLength */
729*75ab5f91Slh155975 	pMdl->PatternLength = (unsigned int *)(*pmem_set_array);
730*75ab5f91Slh155975 
731*75ab5f91Slh155975 	/* 5) Set the pointers to the init block */
732*75ab5f91Slh155975 	pmem_set_array++;	/* Type  */
733*75ab5f91Slh155975 	pmem_set_array++;	/* Size */
734*75ab5f91Slh155975 	pmem_set_array++;	/* Virtual Addr of init_block */
735*75ab5f91Slh155975 	pMdl->init_blk = (struct init_block *)(*pmem_set_array);
736*75ab5f91Slh155975 
737*75ab5f91Slh155975 	pMdl->init_blk->TLEN = pMdl->TxRingLenBits;
738*75ab5f91Slh155975 	pMdl->init_blk->RLEN = pMdl->RxRingLenBits;
739*75ab5f91Slh155975 
740*75ab5f91Slh155975 	pmem_set_array++;
741*75ab5f91Slh155975 
742*75ab5f91Slh155975 	*pmem_set_array = 0;
743*75ab5f91Slh155975 }
744*75ab5f91Slh155975 
745*75ab5f91Slh155975 /*
746*75ab5f91Slh155975  *	Purpose:
747*75ab5f91Slh155975  *		This array is filled with the size of the structure & its
748*75ab5f91Slh155975  *		pointer for freeing purposes.
749*75ab5f91Slh155975  *
750*75ab5f91Slh155975  *	Arguments:
751*75ab5f91Slh155975  *		pLayerPointers
752*75ab5f91Slh155975  *			Pointer to the adapter structure.
753*75ab5f91Slh155975  *		mem_free_array
754*75ab5f91Slh155975  *			Pointer to the array that holds the data required for
755*75ab5f91Slh155975  *			freeing.
756*75ab5f91Slh155975  */
757*75ab5f91Slh155975 static void
mdlFreeResources(struct LayerPointers * pLayerPointers,ULONG * pmem_free_array)758*75ab5f91Slh155975 mdlFreeResources(struct LayerPointers *pLayerPointers, ULONG *pmem_free_array)
759*75ab5f91Slh155975 {
760*75ab5f91Slh155975 	struct mdl *pMdl = 0;
761*75ab5f91Slh155975 
762*75ab5f91Slh155975 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
763*75ab5f91Slh155975 
764*75ab5f91Slh155975 	/* 1) For mdl structure */
765*75ab5f91Slh155975 	*(pmem_free_array) = VIRTUAL;		/* Type */
766*75ab5f91Slh155975 	*(++pmem_free_array) = sizeof (struct mdl); /* Size */
767*75ab5f91Slh155975 	*(++pmem_free_array) = (ULONG)pMdl;  /* VA */
768*75ab5f91Slh155975 
769*75ab5f91Slh155975 	/* 2) For ptr list */
770*75ab5f91Slh155975 	*(++pmem_free_array) = VIRTUAL;		/* Type */
771*75ab5f91Slh155975 	*(++pmem_free_array) =  sizeof (unsigned int)
772*75ab5f91Slh155975 	    * (MAX_ALLOWED_PATTERNS + 2);  /* Size */
773*75ab5f91Slh155975 	*(++pmem_free_array) = (ULONG)pMdl->PMR_PtrList;  /* VA */
774*75ab5f91Slh155975 
775*75ab5f91Slh155975 	/* 3) For pattern list */
776*75ab5f91Slh155975 	*(++pmem_free_array) = VIRTUAL;		/* Type	 */
777*75ab5f91Slh155975 	/* Size */
778*75ab5f91Slh155975 	*(++pmem_free_array) =  sizeof (unsigned char) * (MAX_PATTERNS + 2);
779*75ab5f91Slh155975 	*(++pmem_free_array) = (ULONG)pMdl->PatternList;  /* VA */
780*75ab5f91Slh155975 
781*75ab5f91Slh155975 	/* 4) For pattern length */
782*75ab5f91Slh155975 	*(++pmem_free_array) = VIRTUAL;				/* Type */
783*75ab5f91Slh155975 	*(++pmem_free_array) =  sizeof (unsigned int)
784*75ab5f91Slh155975 	    * (MAX_ALLOWED_PATTERNS + 2);			/* Size */
785*75ab5f91Slh155975 	*(++pmem_free_array) = (ULONG)pMdl->PatternLength;	/* VA */
786*75ab5f91Slh155975 
787*75ab5f91Slh155975 	/* 5) For init_blk structure */
788*75ab5f91Slh155975 	*(++pmem_free_array) = VIRTUAL;				/* Type */
789*75ab5f91Slh155975 	/* Size */
790*75ab5f91Slh155975 	*(++pmem_free_array) = sizeof (struct init_block);
791*75ab5f91Slh155975 	*(++pmem_free_array) = (ULONG)pMdl->init_blk;		/* VA */
792*75ab5f91Slh155975 
793*75ab5f91Slh155975 	*(++pmem_free_array) = 0;
794*75ab5f91Slh155975 }
795*75ab5f91Slh155975 
796*75ab5f91Slh155975 void
mdlStartChip(struct LayerPointers * pLayerPointers)797*75ab5f91Slh155975 mdlStartChip(struct LayerPointers *pLayerPointers)
798*75ab5f91Slh155975 {
799*75ab5f91Slh155975 	/* Enable Receiver */
800*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
801*75ab5f91Slh155975 	    VAL2 | RDMD0);
802*75ab5f91Slh155975 
803*75ab5f91Slh155975 	/* Enable Interrupt and Start processing descriptor, Rx and Tx */
804*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
805*75ab5f91Slh155975 	    VAL0 | INTREN | RUN);
806*75ab5f91Slh155975 }
807*75ab5f91Slh155975 
808*75ab5f91Slh155975 /*
809*75ab5f91Slh155975  *	Stops the chip.
810*75ab5f91Slh155975  */
811*75ab5f91Slh155975 void
mdlStopChip(struct LayerPointers * pLayerPointers)812*75ab5f91Slh155975 mdlStopChip(struct LayerPointers *pLayerPointers)
813*75ab5f91Slh155975 {
814*75ab5f91Slh155975 	int nINT0;
815*75ab5f91Slh155975 	struct mdl *pMdl = 0;
816*75ab5f91Slh155975 
817*75ab5f91Slh155975 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
818*75ab5f91Slh155975 
819*75ab5f91Slh155975 	/* Disable interrupt */
820*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD0, INTREN);
821*75ab5f91Slh155975 
822*75ab5f91Slh155975 	/* Clear interrupt status */
823*75ab5f91Slh155975 	nINT0 = READ_REG32(pLayerPointers, pMdl->Mem_Address + INT0);
824*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INT0, nINT0);
825*75ab5f91Slh155975 
826*75ab5f91Slh155975 	/*
827*75ab5f91Slh155975 	 * Setting the RUN bit enables the controller to start processing
828*75ab5f91Slh155975 	 * descriptors and transmitting and  receiving packets. Clearing
829*75ab5f91Slh155975 	 * the RUN bit to 0 abruptly disables the transmitter, receiver, and
830*75ab5f91Slh155975 	 * descriptor processing logic, possibly while a frame is being
831*75ab5f91Slh155975 	 * transmitted or received.
832*75ab5f91Slh155975 	 * The act of changing the RUN bit from 1 to 0 causes the following
833*75ab5f91Slh155975 	 * bits to be reset to 0: TX_SPND, RX_SPND, TX_FAST_SPND, RX_FAST_SPND,
834*75ab5f91Slh155975 	 * RDMD, all TDMD bits, RINT, all TINT bits, MPINT, and SPNDINT.
835*75ab5f91Slh155975 	 */
836*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD0, RUN);
837*75ab5f91Slh155975 }
838*75ab5f91Slh155975 
839*75ab5f91Slh155975 /*
840*75ab5f91Slh155975  *	Enables the interrupt.
841*75ab5f91Slh155975  */
842*75ab5f91Slh155975 void
mdlEnableInterrupt(struct LayerPointers * pLayerPointers)843*75ab5f91Slh155975 mdlEnableInterrupt(struct LayerPointers *pLayerPointers)
844*75ab5f91Slh155975 {
845*75ab5f91Slh155975 	/*
846*75ab5f91Slh155975 	 * Interrupt Enable Bit:
847*75ab5f91Slh155975 	 * This bit allows INTA to be asserted if any bit in the interrupt
848*75ab5f91Slh155975 	 * register is set. If INTREN is cleared to 0, INTA will not be
849*75ab5f91Slh155975 	 * asserted, regardless of the state of the interrupt register.
850*75ab5f91Slh155975 	 */
851*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
852*75ab5f91Slh155975 	    VAL0 | INTREN);
853*75ab5f91Slh155975 }
854*75ab5f91Slh155975 
855*75ab5f91Slh155975 #ifdef AMD8111S_DEBUG
856*75ab5f91Slh155975 static void
mdlClearInterrupt(struct LayerPointers * pLayerPointers)857*75ab5f91Slh155975 mdlClearInterrupt(struct LayerPointers *pLayerPointers)
858*75ab5f91Slh155975 {
859*75ab5f91Slh155975 	unsigned int nINT0;
860*75ab5f91Slh155975 	struct mdl *pMdl = 0;
861*75ab5f91Slh155975 
862*75ab5f91Slh155975 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
863*75ab5f91Slh155975 
864*75ab5f91Slh155975 	/* Clear interrupt status */
865*75ab5f91Slh155975 	nINT0 = READ_REG32(pLayerPointers, pMdl->Mem_Address + INT0);
866*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INT0, nINT0);
867*75ab5f91Slh155975 
868*75ab5f91Slh155975 }
869*75ab5f91Slh155975 #endif
870*75ab5f91Slh155975 
871*75ab5f91Slh155975 /*
872*75ab5f91Slh155975  *	Disables the interrupt.
873*75ab5f91Slh155975  */
874*75ab5f91Slh155975 void
mdlDisableInterrupt(struct LayerPointers * pLayerPointers)875*75ab5f91Slh155975 mdlDisableInterrupt(struct LayerPointers *pLayerPointers)
876*75ab5f91Slh155975 {
877*75ab5f91Slh155975 	/* Disable interrupt */
878*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers,
879*75ab5f91Slh155975 	    pLayerPointers->pMdl->Mem_Address + CMD0, INTREN);
880*75ab5f91Slh155975 }
881*75ab5f91Slh155975 
882*75ab5f91Slh155975 /*
883*75ab5f91Slh155975  *	Reads the link status
884*75ab5f91Slh155975  */
885*75ab5f91Slh155975 int
mdlReadLink(struct LayerPointers * pLayerPointers)886*75ab5f91Slh155975 mdlReadLink(struct LayerPointers *pLayerPointers)
887*75ab5f91Slh155975 {
888*75ab5f91Slh155975 	unsigned int link_status = 0;
889*75ab5f91Slh155975 
890*75ab5f91Slh155975 	link_status = READ_REG32(pLayerPointers,
891*75ab5f91Slh155975 	    pLayerPointers->pMdl->Mem_Address + STAT0);
892*75ab5f91Slh155975 
893*75ab5f91Slh155975 	if ((link_status & LINK_STAT)) {
894*75ab5f91Slh155975 		return (LINK_UP);
895*75ab5f91Slh155975 	} else {
896*75ab5f91Slh155975 		return (LINK_DOWN);
897*75ab5f91Slh155975 	}
898*75ab5f91Slh155975 }
899*75ab5f91Slh155975 
900*75ab5f91Slh155975 /*
901*75ab5f91Slh155975  *	Purpose  :
902*75ab5f91Slh155975  *		Adds the wakeup pattern given by the upper layer.
903*75ab5f91Slh155975  *
904*75ab5f91Slh155975  *	Arguments :
905*75ab5f91Slh155975  *		pLayerPointers
906*75ab5f91Slh155975  *			Pointer to the Adapter structure.
907*75ab5f91Slh155975  *		PatternMask
908*75ab5f91Slh155975  *			The mask for the pattern to be added.
909*75ab5f91Slh155975  *		Pattern
910*75ab5f91Slh155975  *			The Pattern to be added.
911*75ab5f91Slh155975  *		InfoBuffer_MaskSize
912*75ab5f91Slh155975  *			The mask size as specified in the Information Buffer.
913*75ab5f91Slh155975  *		PatternSize
914*75ab5f91Slh155975  *			The PatternSize as specified in the Information Buffer.
915*75ab5f91Slh155975  */
916*75ab5f91Slh155975 static void
mdlAddWakeUpPattern(struct LayerPointers * pLayerPointers,unsigned char * PatternMask,unsigned char * Pattern,unsigned long InfoBuffer_MaskSize,unsigned long PatternSize,int * retval)917*75ab5f91Slh155975 mdlAddWakeUpPattern(struct LayerPointers *pLayerPointers,
918*75ab5f91Slh155975     unsigned char *PatternMask, unsigned char *Pattern,
919*75ab5f91Slh155975     unsigned long InfoBuffer_MaskSize, unsigned long PatternSize, int *retval)
920*75ab5f91Slh155975 {
921*75ab5f91Slh155975 	unsigned long MaskSize;
922*75ab5f91Slh155975 	unsigned long ReqSize;
923*75ab5f91Slh155975 	unsigned char byteData = 0, tmpData;
924*75ab5f91Slh155975 	unsigned char Skip = 0;
925*75ab5f91Slh155975 	unsigned int i = 0, flag = 1, count = 1;
926*75ab5f91Slh155975 	unsigned int j;
927*75ab5f91Slh155975 	int PatternOffset, SearchForStartOfPattern = 1;
928*75ab5f91Slh155975 	struct mdl *pMdl = 0;
929*75ab5f91Slh155975 
930*75ab5f91Slh155975 	pMdl = pLayerPointers->pMdl;
931*75ab5f91Slh155975 
932*75ab5f91Slh155975 	if (pMdl->TotalPatterns >= MAX_ALLOWED_PATTERNS) {
933*75ab5f91Slh155975 		*retval = -1;
934*75ab5f91Slh155975 		return;
935*75ab5f91Slh155975 	}
936*75ab5f91Slh155975 
937*75ab5f91Slh155975 	MaskSize = PatternSize/4 + (PatternSize%4 ? 1 : 0);
938*75ab5f91Slh155975 
939*75ab5f91Slh155975 	ReqSize = PatternSize + MaskSize;
940*75ab5f91Slh155975 	if (((PatternSize+MaskSize)%5) != 0)
941*75ab5f91Slh155975 		ReqSize +=  5 - ((PatternSize+MaskSize)%5);
942*75ab5f91Slh155975 
943*75ab5f91Slh155975 	if (ReqSize >
944*75ab5f91Slh155975 	    (unsigned long)(MAX_PATTERNS - pMdl->PatternList_FreeIndex)) {
945*75ab5f91Slh155975 		*retval = -1;
946*75ab5f91Slh155975 		return;
947*75ab5f91Slh155975 	}
948*75ab5f91Slh155975 
949*75ab5f91Slh155975 	if (InfoBuffer_MaskSize != PatternSize/8 + (PatternSize%8 ? 1 : 0)) {
950*75ab5f91Slh155975 		*retval = -1;
951*75ab5f91Slh155975 		return;
952*75ab5f91Slh155975 	}
953*75ab5f91Slh155975 
954*75ab5f91Slh155975 	i = pMdl->PatternList_FreeIndex;
955*75ab5f91Slh155975 
956*75ab5f91Slh155975 	pMdl->PMR_PtrList[pMdl->TotalPatterns] = i;
957*75ab5f91Slh155975 
958*75ab5f91Slh155975 	pMdl->PatternLength[pMdl->TotalPatterns] = (unsigned int)PatternSize;
959*75ab5f91Slh155975 
960*75ab5f91Slh155975 	while (i < (pMdl->PatternList_FreeIndex + PatternSize + MaskSize)) {
961*75ab5f91Slh155975 		if (flag) {
962*75ab5f91Slh155975 			byteData = *PatternMask;
963*75ab5f91Slh155975 			pMdl->PatternList[i++] =
964*75ab5f91Slh155975 			    (unsigned int)((byteData & 0x0F) | (Skip<< 4));
965*75ab5f91Slh155975 			flag = 0;
966*75ab5f91Slh155975 		} else {
967*75ab5f91Slh155975 			pMdl->PatternList[i++] = (unsigned int)
968*75ab5f91Slh155975 			    (((unsigned)(byteData & 0xF0) >> 4) | (Skip << 4));
969*75ab5f91Slh155975 			PatternMask++;
970*75ab5f91Slh155975 			flag = 1;
971*75ab5f91Slh155975 		}
972*75ab5f91Slh155975 		count = 1;
973*75ab5f91Slh155975 		while ((count < 5) && (i <
974*75ab5f91Slh155975 		    pMdl->PatternList_FreeIndex + PatternSize + MaskSize)) {
975*75ab5f91Slh155975 			tmpData = *Pattern;
976*75ab5f91Slh155975 			Pattern++;
977*75ab5f91Slh155975 			pMdl->PatternList[i++] = tmpData;
978*75ab5f91Slh155975 			count++;
979*75ab5f91Slh155975 		}
980*75ab5f91Slh155975 	}
981*75ab5f91Slh155975 
982*75ab5f91Slh155975 	/* Filling up the extra byte blocks in the row to 0. */
983*75ab5f91Slh155975 	for (i = (pMdl->PatternList_FreeIndex + PatternSize + MaskSize);
984*75ab5f91Slh155975 	    i < (pMdl->PatternList_FreeIndex + ReqSize); i++)
985*75ab5f91Slh155975 		pMdl->PatternList[i] = 0;
986*75ab5f91Slh155975 
987*75ab5f91Slh155975 	/* Set the EOP bit for the last mask!!! */
988*75ab5f91Slh155975 	pMdl->PatternList[pMdl->PatternList_FreeIndex + ReqSize - 5] |= 0x80;
989*75ab5f91Slh155975 
990*75ab5f91Slh155975 	for (j = 0; j < 8; j++) {
991*75ab5f91Slh155975 		pMdl->tmpPtrArray[j] = 0;
992*75ab5f91Slh155975 	}
993*75ab5f91Slh155975 
994*75ab5f91Slh155975 	/* Zeroing the skip value of all the pattern masks */
995*75ab5f91Slh155975 	j = 0;
996*75ab5f91Slh155975 	while (j < (pMdl->PatternList_FreeIndex + ReqSize)) {
997*75ab5f91Slh155975 		pMdl->PatternList[j] &= 0x8f;
998*75ab5f91Slh155975 		j += 5;
999*75ab5f91Slh155975 	}
1000*75ab5f91Slh155975 
1001*75ab5f91Slh155975 	/*
1002*75ab5f91Slh155975 	 * Scan the whole array & update the start offset of the pattern in the
1003*75ab5f91Slh155975 	 * PMR and update the skip value.
1004*75ab5f91Slh155975 	 */
1005*75ab5f91Slh155975 	j = 0;
1006*75ab5f91Slh155975 	i = 0;
1007*75ab5f91Slh155975 
1008*75ab5f91Slh155975 	PatternOffset = 1;
1009*75ab5f91Slh155975 	Skip = 0;
1010*75ab5f91Slh155975 
1011*75ab5f91Slh155975 	while (j < (pMdl->PatternList_FreeIndex + ReqSize)) {
1012*75ab5f91Slh155975 
1013*75ab5f91Slh155975 		if (pMdl->PatternList[j] & 0x0f) {
1014*75ab5f91Slh155975 			PatternOffset ++;
1015*75ab5f91Slh155975 			if (SearchForStartOfPattern == 1) {
1016*75ab5f91Slh155975 				SearchForStartOfPattern = 0;
1017*75ab5f91Slh155975 				pMdl->tmpPtrArray[i++] = PatternOffset;
1018*75ab5f91Slh155975 			} else if (pMdl->PatternList[j] & 0x80) {
1019*75ab5f91Slh155975 				SearchForStartOfPattern = 1;
1020*75ab5f91Slh155975 			}
1021*75ab5f91Slh155975 			pMdl->PatternList[j] |= (Skip << 4);
1022*75ab5f91Slh155975 			Skip = 0;
1023*75ab5f91Slh155975 		} else {
1024*75ab5f91Slh155975 			Skip++;
1025*75ab5f91Slh155975 		}
1026*75ab5f91Slh155975 		j += 5;
1027*75ab5f91Slh155975 	}
1028*75ab5f91Slh155975 
1029*75ab5f91Slh155975 	/* valid pattern.. so update the house keeping info. */
1030*75ab5f91Slh155975 	pMdl->PatternList_FreeIndex += (unsigned short)ReqSize;
1031*75ab5f91Slh155975 	pMdl->TotalPatterns++;
1032*75ab5f91Slh155975 
1033*75ab5f91Slh155975 	*retval = 0;
1034*75ab5f91Slh155975 }
1035*75ab5f91Slh155975 
1036*75ab5f91Slh155975 /*
1037*75ab5f91Slh155975  *	Purpose:
1038*75ab5f91Slh155975  *		Removes the specified wakeup pattern.
1039*75ab5f91Slh155975  *
1040*75ab5f91Slh155975  *	Arguments :
1041*75ab5f91Slh155975  *		pLayerPointers
1042*75ab5f91Slh155975  *			Pointer to the Adapter structure.
1043*75ab5f91Slh155975  *		Pattern
1044*75ab5f91Slh155975  *			The Pattern to be added.
1045*75ab5f91Slh155975  *		PatternSize
1046*75ab5f91Slh155975  *			The PatternSize as specified in the Information Buffer.
1047*75ab5f91Slh155975  */
1048*75ab5f91Slh155975 static void
mdlRemoveWakeUpPattern(struct LayerPointers * pLayerPointers,unsigned char * Pattern,unsigned long PatternSize,int * retval)1049*75ab5f91Slh155975 mdlRemoveWakeUpPattern(struct LayerPointers *pLayerPointers,
1050*75ab5f91Slh155975     unsigned char *Pattern, unsigned long PatternSize, int *retval)
1051*75ab5f91Slh155975 {
1052*75ab5f91Slh155975 	unsigned long ReqSize, MaskSize;
1053*75ab5f91Slh155975 	unsigned char tmpData;
1054*75ab5f91Slh155975 	unsigned long Data;
1055*75ab5f91Slh155975 	unsigned short Data1, Data2, Data3, Data4, Data5, Data6, Data7, Data8;
1056*75ab5f91Slh155975 	int PatternMismatch = 0;
1057*75ab5f91Slh155975 	int count, StartIndex, index = 0;
1058*75ab5f91Slh155975 	unsigned int i, j;
1059*75ab5f91Slh155975 	unsigned char Skip = 0;
1060*75ab5f91Slh155975 	struct mdl *pMdl = 0;
1061*75ab5f91Slh155975 	int PatternOffset, SearchForStartOfPattern = 1;
1062*75ab5f91Slh155975 	unsigned long tmpPtrArray[8];
1063*75ab5f91Slh155975 	int offset;
1064*75ab5f91Slh155975 
1065*75ab5f91Slh155975 	Data1 = Data2 = Data3 = Data4 = Data5 = Data6 = Data7 = Data8 = 0;
1066*75ab5f91Slh155975 
1067*75ab5f91Slh155975 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
1068*75ab5f91Slh155975 
1069*75ab5f91Slh155975 	/* Find the pattern to be removed. */
1070*75ab5f91Slh155975 	if (pMdl->TotalPatterns == 0) {
1071*75ab5f91Slh155975 		*retval = -1;
1072*75ab5f91Slh155975 		return;
1073*75ab5f91Slh155975 	}
1074*75ab5f91Slh155975 
1075*75ab5f91Slh155975 	MaskSize = PatternSize/4 + (PatternSize%4 ? 1 : 0);
1076*75ab5f91Slh155975 
1077*75ab5f91Slh155975 	ReqSize = PatternSize + MaskSize;
1078*75ab5f91Slh155975 	if (((PatternSize+MaskSize)%5) != 0)
1079*75ab5f91Slh155975 		ReqSize +=  5 - ((PatternSize+MaskSize)%5);
1080*75ab5f91Slh155975 
1081*75ab5f91Slh155975 	count = pMdl->TotalPatterns;
1082*75ab5f91Slh155975 
1083*75ab5f91Slh155975 	while (count--) {
1084*75ab5f91Slh155975 		PatternMismatch = 0;
1085*75ab5f91Slh155975 		StartIndex = pMdl->PMR_PtrList[index];
1086*75ab5f91Slh155975 
1087*75ab5f91Slh155975 		if (pMdl->PatternLength[index] != PatternSize) {
1088*75ab5f91Slh155975 			index++;
1089*75ab5f91Slh155975 			PatternMismatch = 1;
1090*75ab5f91Slh155975 			continue;
1091*75ab5f91Slh155975 		}
1092*75ab5f91Slh155975 
1093*75ab5f91Slh155975 		for (i = StartIndex; i < (StartIndex+ReqSize); i++) {
1094*75ab5f91Slh155975 			if (!(i%5))
1095*75ab5f91Slh155975 				i++;
1096*75ab5f91Slh155975 
1097*75ab5f91Slh155975 			tmpData = *Pattern;
1098*75ab5f91Slh155975 			if (pMdl->PatternList[i] != tmpData) {
1099*75ab5f91Slh155975 				PatternMismatch = 1;
1100*75ab5f91Slh155975 				break;
1101*75ab5f91Slh155975 			}
1102*75ab5f91Slh155975 			Pattern++;
1103*75ab5f91Slh155975 		}
1104*75ab5f91Slh155975 
1105*75ab5f91Slh155975 		if (PatternMismatch == 0) {
1106*75ab5f91Slh155975 			i = StartIndex + ReqSize;
1107*75ab5f91Slh155975 
1108*75ab5f91Slh155975 			/* Pattern found remove it from the arrays */
1109*75ab5f91Slh155975 			while (i < pMdl->PatternList_FreeIndex) {
1110*75ab5f91Slh155975 				pMdl->PatternList[StartIndex] =
1111*75ab5f91Slh155975 				    pMdl->PatternList[i];
1112*75ab5f91Slh155975 				i++;
1113*75ab5f91Slh155975 				StartIndex++;
1114*75ab5f91Slh155975 			}
1115*75ab5f91Slh155975 
1116*75ab5f91Slh155975 			pMdl->PatternList_FreeIndex =
1117*75ab5f91Slh155975 			    (unsigned short)(StartIndex);
1118*75ab5f91Slh155975 
1119*75ab5f91Slh155975 			while (StartIndex < MAX_PATTERNS)
1120*75ab5f91Slh155975 				pMdl->PatternList[StartIndex++] = 0;
1121*75ab5f91Slh155975 
1122*75ab5f91Slh155975 			while (index < (int)pMdl->TotalPatterns) {
1123*75ab5f91Slh155975 				pMdl->PMR_PtrList[index] =
1124*75ab5f91Slh155975 				    pMdl->PMR_PtrList[index+1] - ReqSize;
1125*75ab5f91Slh155975 
1126*75ab5f91Slh155975 				pMdl->PatternLength[index] =
1127*75ab5f91Slh155975 				    pMdl->PatternLength[index+1];
1128*75ab5f91Slh155975 
1129*75ab5f91Slh155975 				index ++;
1130*75ab5f91Slh155975 			}
1131*75ab5f91Slh155975 
1132*75ab5f91Slh155975 			index--;
1133*75ab5f91Slh155975 			while (index < MAX_ALLOWED_PATTERNS) {
1134*75ab5f91Slh155975 				pMdl->PMR_PtrList[index+1] = 0;
1135*75ab5f91Slh155975 				pMdl->PatternLength[index+1] = 0;
1136*75ab5f91Slh155975 				index++;
1137*75ab5f91Slh155975 			}
1138*75ab5f91Slh155975 
1139*75ab5f91Slh155975 			break;
1140*75ab5f91Slh155975 		}
1141*75ab5f91Slh155975 		index++;
1142*75ab5f91Slh155975 	}
1143*75ab5f91Slh155975 
1144*75ab5f91Slh155975 	if (PatternMismatch) {
1145*75ab5f91Slh155975 		*retval = -1;
1146*75ab5f91Slh155975 		return;
1147*75ab5f91Slh155975 	}
1148*75ab5f91Slh155975 
1149*75ab5f91Slh155975 
1150*75ab5f91Slh155975 	for (j = 0; j < 8; j++) {
1151*75ab5f91Slh155975 		tmpPtrArray[j] = 0;
1152*75ab5f91Slh155975 	}
1153*75ab5f91Slh155975 
1154*75ab5f91Slh155975 	/* Zeroing the skip value of all the pattern masks */
1155*75ab5f91Slh155975 	j = 0;
1156*75ab5f91Slh155975 	while (j < (pMdl->PatternList_FreeIndex)) {
1157*75ab5f91Slh155975 		pMdl->PatternList[j] &= 0x8f;
1158*75ab5f91Slh155975 		j += 5;
1159*75ab5f91Slh155975 	}
1160*75ab5f91Slh155975 
1161*75ab5f91Slh155975 	/*
1162*75ab5f91Slh155975 	 * Scan the whole array & update the start offset of the pattern in the
1163*75ab5f91Slh155975 	 * PMR and update the skip value.
1164*75ab5f91Slh155975 	 */
1165*75ab5f91Slh155975 	j = 0;
1166*75ab5f91Slh155975 	i = 0;
1167*75ab5f91Slh155975 	Skip = 0;
1168*75ab5f91Slh155975 	PatternOffset = 1;
1169*75ab5f91Slh155975 
1170*75ab5f91Slh155975 	while (j < (pMdl->PatternList_FreeIndex)) {
1171*75ab5f91Slh155975 		if (pMdl->PatternList[j] & 0x0f) {
1172*75ab5f91Slh155975 
1173*75ab5f91Slh155975 			PatternOffset++;
1174*75ab5f91Slh155975 			if (SearchForStartOfPattern == 1) {
1175*75ab5f91Slh155975 				SearchForStartOfPattern = 0;
1176*75ab5f91Slh155975 				tmpPtrArray[i++] = PatternOffset;
1177*75ab5f91Slh155975 			} else if (pMdl->PatternList[j] & 0x80) {
1178*75ab5f91Slh155975 				SearchForStartOfPattern = 1;
1179*75ab5f91Slh155975 			}
1180*75ab5f91Slh155975 			pMdl->PatternList[j] |= (Skip << 4);
1181*75ab5f91Slh155975 			Skip = 0;
1182*75ab5f91Slh155975 		} else {
1183*75ab5f91Slh155975 			Skip++;
1184*75ab5f91Slh155975 		}
1185*75ab5f91Slh155975 		j += 5;
1186*75ab5f91Slh155975 	}
1187*75ab5f91Slh155975 
1188*75ab5f91Slh155975 
1189*75ab5f91Slh155975 	/* Write back the arrays to the PMR & lock the pmr */
1190*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address+CMD7, PMAT_MODE);
1191*75ab5f91Slh155975 
1192*75ab5f91Slh155975 	/* Write the data & ctrl patterns from the array to the PMR */
1193*75ab5f91Slh155975 	i = 0;
1194*75ab5f91Slh155975 
1195*75ab5f91Slh155975 	offset = 2;
1196*75ab5f91Slh155975 
1197*75ab5f91Slh155975 	while (i < MAX_PATTERNS) {
1198*75ab5f91Slh155975 		if (pMdl->PatternList[i] != 0) {
1199*75ab5f91Slh155975 			Data = pMdl->PatternList[i+3] << 24 |
1200*75ab5f91Slh155975 			    pMdl->PatternList[i+2] << 16 |
1201*75ab5f91Slh155975 			    pMdl->PatternList[i+1] << 8  |
1202*75ab5f91Slh155975 			    pMdl->PatternList[i];
1203*75ab5f91Slh155975 
1204*75ab5f91Slh155975 			WRITE_REG32(pLayerPointers,
1205*75ab5f91Slh155975 			    pMdl->Mem_Address+PMAT1, Data);
1206*75ab5f91Slh155975 
1207*75ab5f91Slh155975 			Data = (unsigned long) ((1<<30) | (offset << 16) |
1208*75ab5f91Slh155975 			    pMdl->PatternList[i+4]);
1209*75ab5f91Slh155975 
1210*75ab5f91Slh155975 			WRITE_REG32(pLayerPointers,
1211*75ab5f91Slh155975 			    pMdl->Mem_Address+PMAT0, Data);
1212*75ab5f91Slh155975 
1213*75ab5f91Slh155975 			offset++;
1214*75ab5f91Slh155975 
1215*75ab5f91Slh155975 			if (offset >= 64) {
1216*75ab5f91Slh155975 				/* PMR is full !!!! */
1217*75ab5f91Slh155975 				*retval = -1;
1218*75ab5f91Slh155975 				return;
1219*75ab5f91Slh155975 
1220*75ab5f91Slh155975 			}
1221*75ab5f91Slh155975 		}
1222*75ab5f91Slh155975 		i += 5;
1223*75ab5f91Slh155975 	}
1224*75ab5f91Slh155975 
1225*75ab5f91Slh155975 	/* Valid pattern.. so update the house keeping info. */
1226*75ab5f91Slh155975 	pMdl->TotalPatterns--;
1227*75ab5f91Slh155975 
1228*75ab5f91Slh155975 	/* Update the pointer in the PMR */
1229*75ab5f91Slh155975 	pMdl->PatternEnableBit = 0;
1230*75ab5f91Slh155975 	for (i = 0; i < pMdl->TotalPatterns; i++) {
1231*75ab5f91Slh155975 		pMdl->PatternEnableBit |= (0x0001 << i);
1232*75ab5f91Slh155975 	}
1233*75ab5f91Slh155975 
1234*75ab5f91Slh155975 	Data1 = Data2 = Data3 = Data4 = Data5 = Data6 = Data7 = Data8 = 0;
1235*75ab5f91Slh155975 
1236*75ab5f91Slh155975 	switch (pMdl->TotalPatterns) {
1237*75ab5f91Slh155975 	case 8 :
1238*75ab5f91Slh155975 		Data8 = (unsigned short)tmpPtrArray[7];
1239*75ab5f91Slh155975 		/* FALLTHROUGH */
1240*75ab5f91Slh155975 	case 7 :
1241*75ab5f91Slh155975 		Data7 = (unsigned short)tmpPtrArray[6];
1242*75ab5f91Slh155975 		/* FALLTHROUGH */
1243*75ab5f91Slh155975 	case 6 :
1244*75ab5f91Slh155975 		Data6 = (unsigned short)tmpPtrArray[5];
1245*75ab5f91Slh155975 		/* FALLTHROUGH */
1246*75ab5f91Slh155975 	case 5 :
1247*75ab5f91Slh155975 		Data5 = (unsigned short)tmpPtrArray[4];
1248*75ab5f91Slh155975 		/* FALLTHROUGH */
1249*75ab5f91Slh155975 	case 4 :
1250*75ab5f91Slh155975 		Data4 = (unsigned short)tmpPtrArray[3];
1251*75ab5f91Slh155975 		/* FALLTHROUGH */
1252*75ab5f91Slh155975 	case 3 :
1253*75ab5f91Slh155975 		Data3 = (unsigned short)tmpPtrArray[2];
1254*75ab5f91Slh155975 		/* FALLTHROUGH */
1255*75ab5f91Slh155975 	case 2 :
1256*75ab5f91Slh155975 		Data2 = (unsigned short)tmpPtrArray[1];
1257*75ab5f91Slh155975 		/* FALLTHROUGH */
1258*75ab5f91Slh155975 	case 1 :
1259*75ab5f91Slh155975 		Data1 = (unsigned short)tmpPtrArray[0];
1260*75ab5f91Slh155975 		break;
1261*75ab5f91Slh155975 	}
1262*75ab5f91Slh155975 
1263*75ab5f91Slh155975 	Data = pMdl->PatternEnableBit & 0x0f;
1264*75ab5f91Slh155975 
1265*75ab5f91Slh155975 	/* Updating the pointers 1,2,3 & 4 */
1266*75ab5f91Slh155975 	Data = (Data3 << 24 |   Data2 << 16 |   Data1 << 8  |   Data);
1267*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + PMAT1, Data);
1268*75ab5f91Slh155975 
1269*75ab5f91Slh155975 	Data = (unsigned long) ((1<<30) | Data4);
1270*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + PMAT0, Data);
1271*75ab5f91Slh155975 
1272*75ab5f91Slh155975 	/* Updating the pointers 4,5,6 & 7 */
1273*75ab5f91Slh155975 	Data = (unsigned short)((unsigned)(pMdl->PatternEnableBit & 0xf0) >> 4);
1274*75ab5f91Slh155975 
1275*75ab5f91Slh155975 	Data = (Data7 << 24 |   Data6 << 16 |   Data5 << 8  |   Data);
1276*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + PMAT1, Data);
1277*75ab5f91Slh155975 
1278*75ab5f91Slh155975 	Data = (unsigned long) ((1<<30) | (1<<16) | Data8);
1279*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + PMAT0, Data);
1280*75ab5f91Slh155975 
1281*75ab5f91Slh155975 	/* Unlock the PMR */
1282*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD7, VAL0 | PMAT_MODE);
1283*75ab5f91Slh155975 
1284*75ab5f91Slh155975 	*retval = 0;
1285*75ab5f91Slh155975 }
1286*75ab5f91Slh155975 
1287*75ab5f91Slh155975 
1288*75ab5f91Slh155975 /*
1289*75ab5f91Slh155975  *	Checks the control register for the speed and the type of the
1290*75ab5f91Slh155975  *	network connection.
1291*75ab5f91Slh155975  */
1292*75ab5f91Slh155975 void
mdlGetActiveMediaInfo(struct LayerPointers * pLayerPointers)1293*75ab5f91Slh155975 mdlGetActiveMediaInfo(struct LayerPointers *pLayerPointers)
1294*75ab5f91Slh155975 {
1295*75ab5f91Slh155975 
1296*75ab5f91Slh155975 	unsigned long  ulData;
1297*75ab5f91Slh155975 	struct mdl *pMdl = 0;
1298*75ab5f91Slh155975 
1299*75ab5f91Slh155975 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
1300*75ab5f91Slh155975 
1301*75ab5f91Slh155975 	ulData = READ_REG32(pLayerPointers, pMdl->Mem_Address + STAT0);
1302*75ab5f91Slh155975 
1303*75ab5f91Slh155975 	switch (ulData & SPEED_MASK) {
1304*75ab5f91Slh155975 	case SPEED_100Mbps:
1305*75ab5f91Slh155975 		pMdl->Speed = 100;
1306*75ab5f91Slh155975 		break;
1307*75ab5f91Slh155975 	case SPEED_10Mbps:
1308*75ab5f91Slh155975 		pMdl->Speed = 10;
1309*75ab5f91Slh155975 		break;
1310*75ab5f91Slh155975 	default:
1311*75ab5f91Slh155975 		pMdl->Speed = 100;
1312*75ab5f91Slh155975 		break;
1313*75ab5f91Slh155975 	}
1314*75ab5f91Slh155975 
1315*75ab5f91Slh155975 	if (ulData & FULL_DPLX) {
1316*75ab5f91Slh155975 		pMdl->FullDuplex = B_TRUE;
1317*75ab5f91Slh155975 	} else {
1318*75ab5f91Slh155975 		pMdl->FullDuplex = B_FALSE;
1319*75ab5f91Slh155975 	}
1320*75ab5f91Slh155975 }
1321*75ab5f91Slh155975 
1322*75ab5f91Slh155975 void
mdlChangeFilter(struct LayerPointers * pLayerPointers,unsigned long * ArrayPtr)1323*75ab5f91Slh155975 mdlChangeFilter(struct LayerPointers *pLayerPointers, unsigned long  *ArrayPtr)
1324*75ab5f91Slh155975 {
1325*75ab5f91Slh155975 	unsigned long *Ptr;
1326*75ab5f91Slh155975 	unsigned char *MulticastArray;
1327*75ab5f91Slh155975 	unsigned char *Pattern, *PatternMask;
1328*75ab5f91Slh155975 	unsigned int InfoBuffer_MaskSize, PatternSize;
1329*75ab5f91Slh155975 	int *retval;
1330*75ab5f91Slh155975 	int NumberOfAddress, i;
1331*75ab5f91Slh155975 	unsigned int j, CRCValue = 0;
1332*75ab5f91Slh155975 	unsigned char HashCode = 0, FilterByte = 0;
1333*75ab5f91Slh155975 	int BitMapIndex = 0;
1334*75ab5f91Slh155975 
1335*75ab5f91Slh155975 	Ptr = ArrayPtr;
1336*75ab5f91Slh155975 
1337*75ab5f91Slh155975 	while (*Ptr) {
1338*75ab5f91Slh155975 		switch (*Ptr) {
1339*75ab5f91Slh155975 		case DISABLE_BROADCAST:
1340*75ab5f91Slh155975 			mdlDisableReceiveBroadCast(pLayerPointers);
1341*75ab5f91Slh155975 			break;
1342*75ab5f91Slh155975 
1343*75ab5f91Slh155975 		case ENABLE_BROADCAST:
1344*75ab5f91Slh155975 			mdlReceiveBroadCast(pLayerPointers);
1345*75ab5f91Slh155975 			break;
1346*75ab5f91Slh155975 
1347*75ab5f91Slh155975 		case ENABLE_ALL_MULTICAST:
1348*75ab5f91Slh155975 			for (i = 0; i < 8; i++) {
1349*75ab5f91Slh155975 				pLayerPointers->pMdl->init_blk->LADRF[i] = 0xff;
1350*75ab5f91Slh155975 			}
1351*75ab5f91Slh155975 			WRITE_REG64(pLayerPointers,
1352*75ab5f91Slh155975 			    (unsigned long)pLayerPointers->pMdl
1353*75ab5f91Slh155975 			    ->Mem_Address + LADRF1,
1354*75ab5f91Slh155975 			    (char *)pLayerPointers->pMdl->init_blk->LADRF);
1355*75ab5f91Slh155975 			break;
1356*75ab5f91Slh155975 
1357*75ab5f91Slh155975 		case DISABLE_ALL_MULTICAST:
1358*75ab5f91Slh155975 			if (pLayerPointers->pMdl->EnableMulticast == 1) {
1359*75ab5f91Slh155975 				for (i = 0; i < 8; i++) {
1360*75ab5f91Slh155975 					pLayerPointers->pMdl->init_blk
1361*75ab5f91Slh155975 					    ->LADRF[i] =
1362*75ab5f91Slh155975 					    pLayerPointers->pMdl->TempLADRF[i];
1363*75ab5f91Slh155975 				}
1364*75ab5f91Slh155975 			}
1365*75ab5f91Slh155975 
1366*75ab5f91Slh155975 			WRITE_REG64(pLayerPointers,
1367*75ab5f91Slh155975 			    (unsigned long)pLayerPointers->pMdl->Mem_Address
1368*75ab5f91Slh155975 			    + LADRF1,
1369*75ab5f91Slh155975 			    (char *)pLayerPointers->pMdl->init_blk->LADRF);
1370*75ab5f91Slh155975 			break;
1371*75ab5f91Slh155975 
1372*75ab5f91Slh155975 
1373*75ab5f91Slh155975 		case ADD_MULTICAST:
1374*75ab5f91Slh155975 			NumberOfAddress = *(++Ptr);
1375*75ab5f91Slh155975 			MulticastArray = (unsigned char *)(*(++Ptr));
1376*75ab5f91Slh155975 			mdlAddMulticastAddresses(pLayerPointers,
1377*75ab5f91Slh155975 			    NumberOfAddress, MulticastArray);
1378*75ab5f91Slh155975 			break;
1379*75ab5f91Slh155975 
1380*75ab5f91Slh155975 
1381*75ab5f91Slh155975 		case ENABLE_MULTICAST:
1382*75ab5f91Slh155975 			for (i = 0; i < 8; i++) {
1383*75ab5f91Slh155975 				pLayerPointers->pMdl->init_blk->LADRF[i]  =
1384*75ab5f91Slh155975 				    pLayerPointers->pMdl->TempLADRF[i];
1385*75ab5f91Slh155975 			}
1386*75ab5f91Slh155975 			pLayerPointers->pMdl->EnableMulticast = 1;
1387*75ab5f91Slh155975 
1388*75ab5f91Slh155975 			WRITE_REG64(pLayerPointers,
1389*75ab5f91Slh155975 			    (unsigned long)pLayerPointers->pMdl->Mem_Address
1390*75ab5f91Slh155975 			    + LADRF1,
1391*75ab5f91Slh155975 			    (char *)pLayerPointers->pMdl->init_blk->LADRF);
1392*75ab5f91Slh155975 			break;
1393*75ab5f91Slh155975 
1394*75ab5f91Slh155975 		case DISABLE_MULTICAST:
1395*75ab5f91Slh155975 			for (i = 0; i < 8; i++) {
1396*75ab5f91Slh155975 				pLayerPointers->pMdl->init_blk->LADRF[i] = 0;
1397*75ab5f91Slh155975 			}
1398*75ab5f91Slh155975 
1399*75ab5f91Slh155975 			pLayerPointers->pMdl->EnableMulticast = 0;
1400*75ab5f91Slh155975 
1401*75ab5f91Slh155975 			for (BitMapIndex = 0; BitMapIndex <
1402*75ab5f91Slh155975 			    MULTICAST_BITMAP_ARRAY_SIZE; BitMapIndex++)
1403*75ab5f91Slh155975 				pLayerPointers->pMdl->MulticastBitMapArray
1404*75ab5f91Slh155975 				    [BitMapIndex] = 0;
1405*75ab5f91Slh155975 			WRITE_REG64(pLayerPointers,
1406*75ab5f91Slh155975 			    (unsigned long)pLayerPointers->pMdl->Mem_Address
1407*75ab5f91Slh155975 			    + LADRF1,
1408*75ab5f91Slh155975 			    (char *)pLayerPointers->pMdl->init_blk->LADRF);
1409*75ab5f91Slh155975 			break;
1410*75ab5f91Slh155975 
1411*75ab5f91Slh155975 
1412*75ab5f91Slh155975 		case ADD_WAKE_UP_PATTERN:
1413*75ab5f91Slh155975 			PatternMask = (unsigned char *)(*(++Ptr));
1414*75ab5f91Slh155975 			Pattern = (unsigned char *)(*(++Ptr));
1415*75ab5f91Slh155975 			InfoBuffer_MaskSize = (*(++Ptr));
1416*75ab5f91Slh155975 			PatternSize = (*(++Ptr));
1417*75ab5f91Slh155975 			retval = (int *)(*(++Ptr));
1418*75ab5f91Slh155975 
1419*75ab5f91Slh155975 			mdlAddWakeUpPattern(pLayerPointers,
1420*75ab5f91Slh155975 			    PatternMask,
1421*75ab5f91Slh155975 			    Pattern,
1422*75ab5f91Slh155975 			    InfoBuffer_MaskSize,
1423*75ab5f91Slh155975 			    PatternSize,
1424*75ab5f91Slh155975 			    retval);
1425*75ab5f91Slh155975 			break;
1426*75ab5f91Slh155975 
1427*75ab5f91Slh155975 		case REMOVE_WAKE_UP_PATTERN:
1428*75ab5f91Slh155975 			Pattern = (unsigned char *)(*(++Ptr));
1429*75ab5f91Slh155975 			PatternSize = *(++Ptr);
1430*75ab5f91Slh155975 			retval = (int *)(*(++Ptr));
1431*75ab5f91Slh155975 			mdlRemoveWakeUpPattern(pLayerPointers,
1432*75ab5f91Slh155975 			    Pattern,
1433*75ab5f91Slh155975 			    PatternSize,
1434*75ab5f91Slh155975 			    retval);
1435*75ab5f91Slh155975 			break;
1436*75ab5f91Slh155975 
1437*75ab5f91Slh155975 		case ENABLE_MAGIC_PACKET_WAKE_UP:
1438*75ab5f91Slh155975 			mdlEnableMagicPacketWakeUp(pLayerPointers);
1439*75ab5f91Slh155975 			break;
1440*75ab5f91Slh155975 
1441*75ab5f91Slh155975 		case SET_SINGLE_MULTICAST:
1442*75ab5f91Slh155975 			NumberOfAddress = *(++Ptr);
1443*75ab5f91Slh155975 			MulticastArray = (unsigned char *)(*(++Ptr));
1444*75ab5f91Slh155975 
1445*75ab5f91Slh155975 			for (i = 0; i < 8; i++) {
1446*75ab5f91Slh155975 				pLayerPointers->pMdl->TempLADRF[i] =
1447*75ab5f91Slh155975 				    pLayerPointers->pMdl->init_blk->LADRF[i];
1448*75ab5f91Slh155975 			}
1449*75ab5f91Slh155975 			CRCValue = mdlCalculateCRC(ETH_LENGTH_OF_ADDRESS,
1450*75ab5f91Slh155975 			    MulticastArray);
1451*75ab5f91Slh155975 			for (j = 0; j < 6; j++) {
1452*75ab5f91Slh155975 				HashCode = (HashCode << 1) +
1453*75ab5f91Slh155975 				    (((unsigned char)CRCValue >> j) & 0x01);
1454*75ab5f91Slh155975 			}
1455*75ab5f91Slh155975 			/*
1456*75ab5f91Slh155975 			 * Bits 3-5 of HashCode point to byte in address
1457*75ab5f91Slh155975 			 * filter.
1458*75ab5f91Slh155975 			 * Bits 0-2 point to bit within that byte.
1459*75ab5f91Slh155975 			 */
1460*75ab5f91Slh155975 			FilterByte = HashCode >> 3;
1461*75ab5f91Slh155975 			pLayerPointers->pMdl->TempLADRF[FilterByte] |=
1462*75ab5f91Slh155975 			    (1 << (HashCode & 0x07));
1463*75ab5f91Slh155975 			break;
1464*75ab5f91Slh155975 
1465*75ab5f91Slh155975 		case UNSET_SINGLE_MULTICAST:
1466*75ab5f91Slh155975 			NumberOfAddress = *(++Ptr);
1467*75ab5f91Slh155975 			MulticastArray = (unsigned char *)(*(++Ptr));
1468*75ab5f91Slh155975 			for (i = 0; i < 8; i++) {
1469*75ab5f91Slh155975 				pLayerPointers->pMdl->TempLADRF[i] =
1470*75ab5f91Slh155975 				    pLayerPointers->pMdl->init_blk->LADRF[i];
1471*75ab5f91Slh155975 			}
1472*75ab5f91Slh155975 			CRCValue = mdlCalculateCRC(ETH_LENGTH_OF_ADDRESS,
1473*75ab5f91Slh155975 			    MulticastArray);
1474*75ab5f91Slh155975 			for (j = 0; j < 6; j++) {
1475*75ab5f91Slh155975 				HashCode = ((HashCode << 1) +
1476*75ab5f91Slh155975 				    (((unsigned char)CRCValue >> j) & 0x01));
1477*75ab5f91Slh155975 			}
1478*75ab5f91Slh155975 
1479*75ab5f91Slh155975 			/*
1480*75ab5f91Slh155975 			 * Bits 3-5 of HashCode point to byte in address
1481*75ab5f91Slh155975 			 * filter.
1482*75ab5f91Slh155975 			 * Bits 0-2 point to bit within that byte.
1483*75ab5f91Slh155975 			 */
1484*75ab5f91Slh155975 			FilterByte = HashCode >> 3;
1485*75ab5f91Slh155975 			pLayerPointers->pMdl->TempLADRF[FilterByte] &=
1486*75ab5f91Slh155975 			    !(1 << (HashCode & 0x07));
1487*75ab5f91Slh155975 			break;
1488*75ab5f91Slh155975 
1489*75ab5f91Slh155975 		default:
1490*75ab5f91Slh155975 			break;
1491*75ab5f91Slh155975 		}
1492*75ab5f91Slh155975 		Ptr++;
1493*75ab5f91Slh155975 	}
1494*75ab5f91Slh155975 }
1495*75ab5f91Slh155975 
1496*75ab5f91Slh155975 
1497*75ab5f91Slh155975 void
mdlAddMulticastAddresses(struct LayerPointers * pLayerPointers,int NumberOfAddress,unsigned char * MulticastAddresses)1498*75ab5f91Slh155975 mdlAddMulticastAddresses(struct LayerPointers *pLayerPointers,
1499*75ab5f91Slh155975     int NumberOfAddress, unsigned char *MulticastAddresses)
1500*75ab5f91Slh155975 {
1501*75ab5f91Slh155975 	unsigned int j, CRCValue;
1502*75ab5f91Slh155975 	unsigned char HashCode, FilterByte;
1503*75ab5f91Slh155975 	int i;
1504*75ab5f91Slh155975 
1505*75ab5f91Slh155975 	for (i = 0; i < 8; i++) {
1506*75ab5f91Slh155975 		pLayerPointers->pMdl->TempLADRF[i]  = 0x00;
1507*75ab5f91Slh155975 	}
1508*75ab5f91Slh155975 
1509*75ab5f91Slh155975 
1510*75ab5f91Slh155975 	for (i = 0; i < NumberOfAddress; i++) {
1511*75ab5f91Slh155975 		HashCode = 0;
1512*75ab5f91Slh155975 
1513*75ab5f91Slh155975 		/* Calculate CRC value */
1514*75ab5f91Slh155975 		CRCValue = mdlCalculateCRC(ETH_LENGTH_OF_ADDRESS,
1515*75ab5f91Slh155975 		    MulticastAddresses);
1516*75ab5f91Slh155975 
1517*75ab5f91Slh155975 		for (j = 0; j < 6; j++) {
1518*75ab5f91Slh155975 			HashCode = (HashCode << 1) +
1519*75ab5f91Slh155975 			    (((unsigned char)CRCValue >> j) & 0x01);
1520*75ab5f91Slh155975 		}
1521*75ab5f91Slh155975 
1522*75ab5f91Slh155975 		/* Bits 3-5 of HashCode point to byte in address filter. */
1523*75ab5f91Slh155975 		/* Bits 0-2 point to bit within that byte. */
1524*75ab5f91Slh155975 		FilterByte = HashCode >> 3;
1525*75ab5f91Slh155975 		pLayerPointers->pMdl->TempLADRF[FilterByte] |=
1526*75ab5f91Slh155975 		    (1 << (HashCode & 0x07));
1527*75ab5f91Slh155975 		MulticastAddresses += ETH_LENGTH_OF_ADDRESS;
1528*75ab5f91Slh155975 	}
1529*75ab5f91Slh155975 }
1530*75ab5f91Slh155975 
1531*75ab5f91Slh155975 /* Receive all packets  */
1532*75ab5f91Slh155975 void
mdlSetPromiscuous(struct LayerPointers * pLayerPointers)1533*75ab5f91Slh155975 mdlSetPromiscuous(struct LayerPointers *pLayerPointers)
1534*75ab5f91Slh155975 {
1535*75ab5f91Slh155975 	/*
1536*75ab5f91Slh155975 	 * Writable N == Can Be Written only when device is not running
1537*75ab5f91Slh155975 	 * (RUN == 0)
1538*75ab5f91Slh155975 	 */
1539*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD2,
1540*75ab5f91Slh155975 	    VAL2 | PROM);
1541*75ab5f91Slh155975 	pLayerPointers->pMdl->FLAGS |= PROM;	/* B16_MASK */
1542*75ab5f91Slh155975 }
1543*75ab5f91Slh155975 
1544*75ab5f91Slh155975 /* Stop Receiving all packets  */
1545*75ab5f91Slh155975 void
mdlDisablePromiscuous(struct LayerPointers * pLayerPointers)1546*75ab5f91Slh155975 mdlDisablePromiscuous(struct LayerPointers *pLayerPointers)
1547*75ab5f91Slh155975 {
1548*75ab5f91Slh155975 	/*
1549*75ab5f91Slh155975 	 * Writable N == Can Be Written only when device is not running
1550*75ab5f91Slh155975 	 * (RUN == 0)
1551*75ab5f91Slh155975 	 */
1552*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD2,
1553*75ab5f91Slh155975 	    PROM);
1554*75ab5f91Slh155975 	pLayerPointers->pMdl->FLAGS &= (~ PROM); /* B16_MASK */
1555*75ab5f91Slh155975 }
1556*75ab5f91Slh155975 
1557*75ab5f91Slh155975 /*
1558*75ab5f91Slh155975  * Disable Receive Broadcast. When set, disables the controller from receiving
1559*75ab5f91Slh155975  * broadcast messages. Used for protocols that do not support broadcast
1560*75ab5f91Slh155975  * addressing, except as a function of multicast.
1561*75ab5f91Slh155975  * DRCVBC is cleared by activation of H_RESET (broadcast messages will be
1562*75ab5f91Slh155975  * received) and is unaffected by the clearing of the RUN bit.
1563*75ab5f91Slh155975  */
1564*75ab5f91Slh155975 static void
mdlReceiveBroadCast(struct LayerPointers * pLayerPointers)1565*75ab5f91Slh155975 mdlReceiveBroadCast(struct LayerPointers *pLayerPointers)
1566*75ab5f91Slh155975 {
1567*75ab5f91Slh155975 	ULONG MappedMemBaseAddress;
1568*75ab5f91Slh155975 
1569*75ab5f91Slh155975 	MappedMemBaseAddress = pLayerPointers->pMdl->Mem_Address;
1570*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MappedMemBaseAddress + CMD2, DRCVBC);
1571*75ab5f91Slh155975 	pLayerPointers->pMdl->FLAGS |= DRCVBC;
1572*75ab5f91Slh155975 }
1573*75ab5f91Slh155975 
1574*75ab5f91Slh155975 static void
mdlDisableReceiveBroadCast(struct LayerPointers * pLayerPointers)1575*75ab5f91Slh155975 mdlDisableReceiveBroadCast(struct LayerPointers *pLayerPointers)
1576*75ab5f91Slh155975 {
1577*75ab5f91Slh155975 	ULONG MappedMemBaseAddress;
1578*75ab5f91Slh155975 
1579*75ab5f91Slh155975 	MappedMemBaseAddress = pLayerPointers->pMdl->Mem_Address;
1580*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, MappedMemBaseAddress + CMD2, VAL2 | DRCVBC);
1581*75ab5f91Slh155975 	pLayerPointers->pMdl->FLAGS &= (~DRCVBC);
1582*75ab5f91Slh155975 }
1583*75ab5f91Slh155975 
1584*75ab5f91Slh155975 static void
mdlEnableMagicPacketWakeUp(struct LayerPointers * pLayerPointers)1585*75ab5f91Slh155975 mdlEnableMagicPacketWakeUp(struct LayerPointers *pLayerPointers)
1586*75ab5f91Slh155975 {
1587*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD3,
1588*75ab5f91Slh155975 	    VAL1 | MPPLBA);
1589*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD7,
1590*75ab5f91Slh155975 	    VAL0 | MPEN_SW);
1591*75ab5f91Slh155975 }
1592*75ab5f91Slh155975 
1593*75ab5f91Slh155975 /*
1594*75ab5f91Slh155975  * BitMap for add/del the Multicast address Since more than one M/C address
1595*75ab5f91Slh155975  * can map to same bit in the filter matrix, we should maintain the count for
1596*75ab5f91Slh155975  * # of M/C addresses associated with each bit. Only when the bit<->count
1597*75ab5f91Slh155975  * becomes zero, we should go ahead with changing/reseting the bit, else just
1598*75ab5f91Slh155975  * reduce the count associated with each bit and return.
1599*75ab5f91Slh155975  */
1600*75ab5f91Slh155975 static int
mdlMulticastBitMapping(struct LayerPointers * pLayerPointers,unsigned char * MulticastAddress,int FLAG)1601*75ab5f91Slh155975 mdlMulticastBitMapping(struct LayerPointers *pLayerPointers,
1602*75ab5f91Slh155975     unsigned char *MulticastAddress, int FLAG)
1603*75ab5f91Slh155975 {
1604*75ab5f91Slh155975 	unsigned char HashCode, FilterByte;
1605*75ab5f91Slh155975 	int j = 0, BitMapIndex = 0;
1606*75ab5f91Slh155975 	unsigned int CRCValue = 0;
1607*75ab5f91Slh155975 
1608*75ab5f91Slh155975 	HashCode = 0;
1609*75ab5f91Slh155975 	/* Calculate the Bit Map location for the given Address */
1610*75ab5f91Slh155975 	CRCValue = mdlCalculateCRC(ETH_LENGTH_OF_ADDRESS, MulticastAddress);
1611*75ab5f91Slh155975 	for (j = 0; j < 6; j++) {
1612*75ab5f91Slh155975 		HashCode = (HashCode << 1) +
1613*75ab5f91Slh155975 		    (((unsigned char)CRCValue >> j) & 0x01);
1614*75ab5f91Slh155975 	}
1615*75ab5f91Slh155975 
1616*75ab5f91Slh155975 	/*
1617*75ab5f91Slh155975 	 * Bits 3-5 of HashCode point to byte in address filter.
1618*75ab5f91Slh155975 	 * Bits 0-2 point to bit within that byte.
1619*75ab5f91Slh155975 	 */
1620*75ab5f91Slh155975 	FilterByte = HashCode & 0x38;
1621*75ab5f91Slh155975 	FilterByte = FilterByte >> 3;
1622*75ab5f91Slh155975 	BitMapIndex =  (int)FilterByte * 8 + (HashCode & 0x7);
1623*75ab5f91Slh155975 
1624*75ab5f91Slh155975 	if (FLAG == DELETE_MULTICAST) {
1625*75ab5f91Slh155975 		if ((pLayerPointers->pMdl->MulticastBitMapArray[BitMapIndex]
1626*75ab5f91Slh155975 		    == 0) || (--pLayerPointers->pMdl->MulticastBitMapArray
1627*75ab5f91Slh155975 		    [BitMapIndex] == 0)) {
1628*75ab5f91Slh155975 			return (0);
1629*75ab5f91Slh155975 		} else {
1630*75ab5f91Slh155975 			return (-1);
1631*75ab5f91Slh155975 		}
1632*75ab5f91Slh155975 	}
1633*75ab5f91Slh155975 
1634*75ab5f91Slh155975 	if (FLAG == ADD_MULTICAST) {
1635*75ab5f91Slh155975 		if (pLayerPointers->pMdl
1636*75ab5f91Slh155975 		    ->MulticastBitMapArray[BitMapIndex] > 0) {
1637*75ab5f91Slh155975 			pLayerPointers->pMdl
1638*75ab5f91Slh155975 			    ->MulticastBitMapArray[BitMapIndex]++;
1639*75ab5f91Slh155975 			return (-1);
1640*75ab5f91Slh155975 		} else if (pLayerPointers->pMdl
1641*75ab5f91Slh155975 		    ->MulticastBitMapArray[BitMapIndex] == 0) {
1642*75ab5f91Slh155975 			pLayerPointers->pMdl
1643*75ab5f91Slh155975 			    ->MulticastBitMapArray[BitMapIndex]++;
1644*75ab5f91Slh155975 			return (0);
1645*75ab5f91Slh155975 		}
1646*75ab5f91Slh155975 	}
1647*75ab5f91Slh155975 	return (0);
1648*75ab5f91Slh155975 }
1649*75ab5f91Slh155975 
1650*75ab5f91Slh155975 /*
1651*75ab5f91Slh155975  * Set Interrupt Coalescing registers:
1652*75ab5f91Slh155975  *	To reduce the host CPU interrupt service overhead the network
1653*75ab5f91Slh155975  *	controller can be programmed to postpone the interrupt to the host
1654*75ab5f91Slh155975  *	CPU until either a programmable number of receive or transmit
1655*75ab5f91Slh155975  *	interrupt events have occurred or a programmable amount of time has
1656*75ab5f91Slh155975  *	elapsed since the first interrupt event occurred.
1657*75ab5f91Slh155975  */
1658*75ab5f91Slh155975 void
SetIntrCoalesc(struct LayerPointers * pLayerPointers,boolean_t on)1659*75ab5f91Slh155975 SetIntrCoalesc(struct LayerPointers *pLayerPointers, boolean_t on)
1660*75ab5f91Slh155975 {
1661*75ab5f91Slh155975 	long MemBaseAddress = pLayerPointers->pMdl->Mem_Address;
1662*75ab5f91Slh155975 	struct mdl *pMdl = 0;
1663*75ab5f91Slh155975 	unsigned int timeout, event_count;
1664*75ab5f91Slh155975 
1665*75ab5f91Slh155975 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
1666*75ab5f91Slh155975 
1667*75ab5f91Slh155975 	if (on) {
1668*75ab5f91Slh155975 		/* Set Rx Interrupt Coalescing */
1669*75ab5f91Slh155975 		timeout = pLayerPointers->pMdl->rx_intrcoalesc_time;
1670*75ab5f91Slh155975 		event_count = 0;
1671*75ab5f91Slh155975 		event_count |= pLayerPointers->pMdl->rx_intrcoalesc_events;
1672*75ab5f91Slh155975 		if (timeout > 0x7ff) {
1673*75ab5f91Slh155975 			timeout = 0x7ff;
1674*75ab5f91Slh155975 		}
1675*75ab5f91Slh155975 		if (event_count > 0x1f) {
1676*75ab5f91Slh155975 			event_count = 0x1f;
1677*75ab5f91Slh155975 		}
1678*75ab5f91Slh155975 
1679*75ab5f91Slh155975 		event_count =  event_count << 16;
1680*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_A,
1681*75ab5f91Slh155975 		    DLY_INT_A_R0 | event_count | timeout);
1682*75ab5f91Slh155975 
1683*75ab5f91Slh155975 	} else {
1684*75ab5f91Slh155975 		/* Disable Software Timer Interrupt */
1685*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, MemBaseAddress + STVAL, 0);
1686*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INTEN0,
1687*75ab5f91Slh155975 		    STINTEN);
1688*75ab5f91Slh155975 
1689*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_A, 0);
1690*75ab5f91Slh155975 		WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_B, 0);
1691*75ab5f91Slh155975 	}
1692*75ab5f91Slh155975 }
1693*75ab5f91Slh155975 
1694*75ab5f91Slh155975 void
mdlSendPause(struct LayerPointers * pLayerPointers)1695*75ab5f91Slh155975 mdlSendPause(struct LayerPointers *pLayerPointers)
1696*75ab5f91Slh155975 {
1697*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address
1698*75ab5f91Slh155975 	    + FLOW_CONTROL, VAL2 | FIXP | FCCMD | 0x200);
1699*75ab5f91Slh155975 }
1700*75ab5f91Slh155975 
1701*75ab5f91Slh155975 /* Reset all Tx descriptors and Tx buffers */
1702*75ab5f91Slh155975 void
milResetTxQ(struct LayerPointers * pLayerPointers)1703*75ab5f91Slh155975 milResetTxQ(struct LayerPointers *pLayerPointers)
1704*75ab5f91Slh155975 {
1705*75ab5f91Slh155975 	struct nonphysical *pNonphysical = pLayerPointers->pMil->pNonphysical;
1706*75ab5f91Slh155975 	int i;
1707*75ab5f91Slh155975 
1708*75ab5f91Slh155975 	pNonphysical->TxDescQRead = pNonphysical->TxDescQStart;
1709*75ab5f91Slh155975 	pNonphysical->TxDescQWrite = pNonphysical->TxDescQStart;
1710*75ab5f91Slh155975 
1711*75ab5f91Slh155975 	/* Clean all Tx descriptors */
1712*75ab5f91Slh155975 	for (i = 0; i < TX_RING_SIZE; i++) {
1713*75ab5f91Slh155975 		pNonphysical->TxDescQWrite->Tx_OWN = 0;
1714*75ab5f91Slh155975 		pNonphysical->TxDescQWrite->Tx_SOP = 0;
1715*75ab5f91Slh155975 		pNonphysical->TxDescQWrite->Tx_EOP = 0;
1716*75ab5f91Slh155975 		pNonphysical->TxDescQWrite++;
1717*75ab5f91Slh155975 	}
1718*75ab5f91Slh155975 	pNonphysical->TxDescQWrite = pNonphysical->TxDescQStart;
1719*75ab5f91Slh155975 
1720*75ab5f91Slh155975 	/* Re-init Tx Buffers */
1721*75ab5f91Slh155975 	pLayerPointers->pOdl->tx_buf.free =
1722*75ab5f91Slh155975 	    pLayerPointers->pOdl->tx_buf.msg_buf;
1723*75ab5f91Slh155975 	pLayerPointers->pOdl->tx_buf.next =
1724*75ab5f91Slh155975 	    pLayerPointers->pOdl->tx_buf.msg_buf;
1725*75ab5f91Slh155975 	pLayerPointers->pOdl->tx_buf.curr =
1726*75ab5f91Slh155975 	    pLayerPointers->pOdl->tx_buf.msg_buf;
1727*75ab5f91Slh155975 }
1728*75ab5f91Slh155975 
1729*75ab5f91Slh155975 /*
1730*75ab5f91Slh155975  *	Initialises the data used in Mil.
1731*75ab5f91Slh155975  */
1732*75ab5f91Slh155975 void
milInitGlbds(struct LayerPointers * pLayerPointers)1733*75ab5f91Slh155975 milInitGlbds(struct LayerPointers *pLayerPointers)
1734*75ab5f91Slh155975 {
1735*75ab5f91Slh155975 	pLayerPointers->pMil->name = DEVICE_CHIPNAME;
1736*75ab5f91Slh155975 
1737*75ab5f91Slh155975 	mdlInitGlbds(pLayerPointers);
1738*75ab5f91Slh155975 }
1739*75ab5f91Slh155975 
1740*75ab5f91Slh155975 /*
1741*75ab5f91Slh155975  *	Purpose  :
1742*75ab5f91Slh155975  *		Initialises the RxBufDescQ with the packet pointer and physical
1743*75ab5f91Slh155975  *		address filled in the FreeQ.
1744*75ab5f91Slh155975  *
1745*75ab5f91Slh155975  *	Arguments :
1746*75ab5f91Slh155975  *		pLayerPointers
1747*75ab5f91Slh155975  *			Pointer to the Adapter structure.
1748*75ab5f91Slh155975  */
1749*75ab5f91Slh155975 void
milInitRxQ(struct LayerPointers * pLayerPointers)1750*75ab5f91Slh155975 milInitRxQ(struct LayerPointers *pLayerPointers)
1751*75ab5f91Slh155975 {
1752*75ab5f91Slh155975 	struct mil *pMil = pLayerPointers->pMil;
1753*75ab5f91Slh155975 	struct nonphysical *pNonphysical = pMil->pNonphysical;
1754*75ab5f91Slh155975 	int i;
1755*75ab5f91Slh155975 
1756*75ab5f91Slh155975 	pNonphysical->RxBufDescQRead->descriptor = pMil->Rx_desc;
1757*75ab5f91Slh155975 	pNonphysical->RxBufDescQStart->descriptor = pMil->Rx_desc;
1758*75ab5f91Slh155975 	pNonphysical->RxBufDescQEnd->descriptor =
1759*75ab5f91Slh155975 	    &(pMil->Rx_desc[pMil->RxRingSize - 1]);
1760*75ab5f91Slh155975 
1761*75ab5f91Slh155975 	pNonphysical->RxBufDescQRead->USpaceMap = pMil->USpaceMapArray;
1762*75ab5f91Slh155975 	pNonphysical->RxBufDescQStart->USpaceMap = pMil->USpaceMapArray;
1763*75ab5f91Slh155975 	pNonphysical->RxBufDescQEnd->USpaceMap =
1764*75ab5f91Slh155975 	    &(pMil->USpaceMapArray[pMil->RxRingSize - 1]);
1765*75ab5f91Slh155975 
1766*75ab5f91Slh155975 	/* Initialize the adapter rx descriptor Q and rx buffer Q */
1767*75ab5f91Slh155975 	for (i = 0; i < pMil->RxRingSize; i++) {
1768*75ab5f91Slh155975 		pNonphysical->RxBufDescQRead->descriptor->Rx_BCNT
1769*75ab5f91Slh155975 		    = (unsigned)pMil->RxBufSize;
1770*75ab5f91Slh155975 
1771*75ab5f91Slh155975 		*(pNonphysical->RxBufDescQRead->USpaceMap) =
1772*75ab5f91Slh155975 		    (long)(pLayerPointers->pOdl->rx_buf.next->vir_addr);
1773*75ab5f91Slh155975 
1774*75ab5f91Slh155975 		pNonphysical->RxBufDescQRead->descriptor->Rx_Base_Addr
1775*75ab5f91Slh155975 		    = pLayerPointers->pOdl->rx_buf.next->phy_addr;
1776*75ab5f91Slh155975 
1777*75ab5f91Slh155975 		pNonphysical->RxBufDescQRead->descriptor->Rx_OWN = 1;
1778*75ab5f91Slh155975 		pNonphysical->RxBufDescQRead->descriptor++;
1779*75ab5f91Slh155975 		pNonphysical->RxBufDescQRead->USpaceMap++;
1780*75ab5f91Slh155975 		pLayerPointers->pOdl->rx_buf.next =
1781*75ab5f91Slh155975 		    NEXT(pLayerPointers->pOdl->rx_buf, next);
1782*75ab5f91Slh155975 	}
1783*75ab5f91Slh155975 
1784*75ab5f91Slh155975 	pNonphysical->RxBufDescQRead->descriptor =
1785*75ab5f91Slh155975 	    pNonphysical->RxBufDescQStart->descriptor;
1786*75ab5f91Slh155975 	pNonphysical->RxBufDescQRead->USpaceMap =
1787*75ab5f91Slh155975 	    pNonphysical->RxBufDescQStart->USpaceMap;
1788*75ab5f91Slh155975 	pLayerPointers->pOdl->rx_buf.next =
1789*75ab5f91Slh155975 	    pLayerPointers->pOdl->rx_buf.msg_buf;
1790*75ab5f91Slh155975 }
1791*75ab5f91Slh155975 
1792*75ab5f91Slh155975 /*
1793*75ab5f91Slh155975  *	Purpose		:
1794*75ab5f91Slh155975  *		This array is filled with the size of the structure & its
1795*75ab5f91Slh155975  *		pointer for freeing purposes.
1796*75ab5f91Slh155975  *
1797*75ab5f91Slh155975  *	Arguments	:
1798*75ab5f91Slh155975  *		pLayerPointers
1799*75ab5f91Slh155975  *			Pointer to the adapter structure.
1800*75ab5f91Slh155975  *		mem_free_array
1801*75ab5f91Slh155975  *			Pointer to the array that holds the data required
1802*75ab5f91Slh155975  *			for freeing.
1803*75ab5f91Slh155975  */
1804*75ab5f91Slh155975 void
milFreeResources(struct LayerPointers * pLayerPointers,ULONG * mem_free_array)1805*75ab5f91Slh155975 milFreeResources(struct LayerPointers *pLayerPointers, ULONG *mem_free_array)
1806*75ab5f91Slh155975 {
1807*75ab5f91Slh155975 	/* 1) For mil structure (pLayerPointers->pMil) */
1808*75ab5f91Slh155975 	/* Type */
1809*75ab5f91Slh155975 	*(mem_free_array) = VIRTUAL;
1810*75ab5f91Slh155975 	/* Size */
1811*75ab5f91Slh155975 	*(++mem_free_array) = sizeof (struct mil);
1812*75ab5f91Slh155975 	/* VA */
1813*75ab5f91Slh155975 	*(++mem_free_array) = (ULONG)pLayerPointers->pMil;
1814*75ab5f91Slh155975 
1815*75ab5f91Slh155975 
1816*75ab5f91Slh155975 	/* 2) For USpaceMapArray queue */
1817*75ab5f91Slh155975 	/* Type */
1818*75ab5f91Slh155975 	*(++mem_free_array) = VIRTUAL;
1819*75ab5f91Slh155975 	/* Size */
1820*75ab5f91Slh155975 	*(++mem_free_array) = pLayerPointers->pMil->RxRingSize *
1821*75ab5f91Slh155975 	    sizeof (unsigned long);
1822*75ab5f91Slh155975 	/* VA */
1823*75ab5f91Slh155975 	*(++mem_free_array) = (ULONG)pLayerPointers->pMil->USpaceMapArray;
1824*75ab5f91Slh155975 
1825*75ab5f91Slh155975 
1826*75ab5f91Slh155975 	/* 3) For non_physical structure */
1827*75ab5f91Slh155975 	/* Type */
1828*75ab5f91Slh155975 	*(++mem_free_array) = VIRTUAL;
1829*75ab5f91Slh155975 	/* Size */
1830*75ab5f91Slh155975 	*(++mem_free_array) =  sizeof (struct nonphysical);
1831*75ab5f91Slh155975 	/* VA */
1832*75ab5f91Slh155975 	*(++mem_free_array) = (ULONG)pLayerPointers->pMil->pNonphysical;
1833*75ab5f91Slh155975 
1834*75ab5f91Slh155975 	/*
1835*75ab5f91Slh155975 	 * 4~6) For four allocation are for abstracting the Rx_Descritor ring
1836*75ab5f91Slh155975 	 */
1837*75ab5f91Slh155975 
1838*75ab5f91Slh155975 	/* 4) Type */
1839*75ab5f91Slh155975 	*(++mem_free_array) = VIRTUAL;
1840*75ab5f91Slh155975 	/* Size */
1841*75ab5f91Slh155975 	*(++mem_free_array) =  sizeof (struct Rx_Buf_Desc);
1842*75ab5f91Slh155975 	/* VA */
1843*75ab5f91Slh155975 	*(++mem_free_array) =
1844*75ab5f91Slh155975 	    (ULONG)pLayerPointers->pMil->pNonphysical->RxBufDescQRead;
1845*75ab5f91Slh155975 
1846*75ab5f91Slh155975 	/* 5) Type */
1847*75ab5f91Slh155975 	*(++mem_free_array) = VIRTUAL;
1848*75ab5f91Slh155975 	/* Size */
1849*75ab5f91Slh155975 	*(++mem_free_array) =  sizeof (struct Rx_Buf_Desc);
1850*75ab5f91Slh155975 	/* VA */
1851*75ab5f91Slh155975 	*(++mem_free_array) =
1852*75ab5f91Slh155975 	    (ULONG)pLayerPointers->pMil->pNonphysical->RxBufDescQStart;
1853*75ab5f91Slh155975 
1854*75ab5f91Slh155975 	/* 6) Type */
1855*75ab5f91Slh155975 	*(++mem_free_array) = VIRTUAL;
1856*75ab5f91Slh155975 	/* Size */
1857*75ab5f91Slh155975 	*(++mem_free_array) =  sizeof (struct Rx_Buf_Desc);
1858*75ab5f91Slh155975 	/* VA */
1859*75ab5f91Slh155975 	*(++mem_free_array) =
1860*75ab5f91Slh155975 	    (ULONG)pLayerPointers->pMil->pNonphysical->RxBufDescQEnd;
1861*75ab5f91Slh155975 
1862*75ab5f91Slh155975 	*(++mem_free_array) = 0;
1863*75ab5f91Slh155975 
1864*75ab5f91Slh155975 	mdlFreeResources(pLayerPointers, mem_free_array);
1865*75ab5f91Slh155975 }
1866*75ab5f91Slh155975 
1867*75ab5f91Slh155975 
1868*75ab5f91Slh155975 
1869*75ab5f91Slh155975 /*
1870*75ab5f91Slh155975  *	Purpose  :
1871*75ab5f91Slh155975  *		This array is filled with the size of the memory required for
1872*75ab5f91Slh155975  *		allocating purposes.
1873*75ab5f91Slh155975  *
1874*75ab5f91Slh155975  *	Arguments :
1875*75ab5f91Slh155975  *		pLayerPointers
1876*75ab5f91Slh155975  *			Pointer to the adapter structure.
1877*75ab5f91Slh155975  *		mem_req_array
1878*75ab5f91Slh155975  *			Pointer to the array that holds the data required for
1879*75ab5f91Slh155975  *			allocating memory.
1880*75ab5f91Slh155975  */
1881*75ab5f91Slh155975 void
milRequestResources(ULONG * mem_req_array)1882*75ab5f91Slh155975 milRequestResources(ULONG *mem_req_array)
1883*75ab5f91Slh155975 {
1884*75ab5f91Slh155975 	int RxRingSize;
1885*75ab5f91Slh155975 
1886*75ab5f91Slh155975 	RxRingSize = RX_RING_SIZE;	/* 128 */
1887*75ab5f91Slh155975 
1888*75ab5f91Slh155975 	/* 1) For mil structure (pLayerPointers->pMil) */
1889*75ab5f91Slh155975 	/* Type */
1890*75ab5f91Slh155975 	*mem_req_array   = VIRTUAL;
1891*75ab5f91Slh155975 	/* Size */
1892*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (struct mil);
1893*75ab5f91Slh155975 
1894*75ab5f91Slh155975 	/* 2) For USpaceMapArray queue (pLayerPointers->pMil->USpaceMapArray) */
1895*75ab5f91Slh155975 	/* Type */
1896*75ab5f91Slh155975 	*(++mem_req_array) = VIRTUAL;
1897*75ab5f91Slh155975 	/* Size */
1898*75ab5f91Slh155975 	*(++mem_req_array) = RxRingSize * sizeof (unsigned long);
1899*75ab5f91Slh155975 
1900*75ab5f91Slh155975 
1901*75ab5f91Slh155975 	/* 3) For pNonphysical structure */
1902*75ab5f91Slh155975 	/* Type */
1903*75ab5f91Slh155975 	*(++mem_req_array) = VIRTUAL;
1904*75ab5f91Slh155975 	/* Size */
1905*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (struct nonphysical);
1906*75ab5f91Slh155975 
1907*75ab5f91Slh155975 	/*
1908*75ab5f91Slh155975 	 * 4~6) For four allocation are for abstracting the Rx_Descritor ring
1909*75ab5f91Slh155975 	 */
1910*75ab5f91Slh155975 	/* 4) Type */
1911*75ab5f91Slh155975 	*(++mem_req_array) = VIRTUAL;
1912*75ab5f91Slh155975 	/* Size */
1913*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (struct Rx_Buf_Desc);
1914*75ab5f91Slh155975 
1915*75ab5f91Slh155975 	/* 5) Type */
1916*75ab5f91Slh155975 	*(++mem_req_array) = VIRTUAL;
1917*75ab5f91Slh155975 	/* Size */
1918*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (struct Rx_Buf_Desc);
1919*75ab5f91Slh155975 
1920*75ab5f91Slh155975 	/* 6) Type */
1921*75ab5f91Slh155975 	*(++mem_req_array) = VIRTUAL;
1922*75ab5f91Slh155975 	/* Size */
1923*75ab5f91Slh155975 	*(++mem_req_array) = sizeof (struct Rx_Buf_Desc);
1924*75ab5f91Slh155975 
1925*75ab5f91Slh155975 	*(++mem_req_array) = 0;
1926*75ab5f91Slh155975 
1927*75ab5f91Slh155975 	mdlRequestResources(mem_req_array);
1928*75ab5f91Slh155975 }
1929*75ab5f91Slh155975 
1930*75ab5f91Slh155975 
1931*75ab5f91Slh155975 
1932*75ab5f91Slh155975 /*
1933*75ab5f91Slh155975  *	Purpose  :
1934*75ab5f91Slh155975  *		This array contains the details of the allocated memory. The
1935*75ab5f91Slh155975  *		pointers are taken from the respective locations in the array
1936*75ab5f91Slh155975  *		& assigne appropriately to the respective structures.
1937*75ab5f91Slh155975  *
1938*75ab5f91Slh155975  *	Arguments :
1939*75ab5f91Slh155975  *		pLayerPointers
1940*75ab5f91Slh155975  *			Pointer to the adapter structure.
1941*75ab5f91Slh155975  *		pmem_set_array
1942*75ab5f91Slh155975  *			Pointer to the array that holds the data after required
1943*75ab5f91Slh155975  *			allocating memory.
1944*75ab5f91Slh155975  */
1945*75ab5f91Slh155975 void
milSetResources(struct LayerPointers * pLayerPointers,ULONG * pmem_set_array)1946*75ab5f91Slh155975 milSetResources(struct LayerPointers *pLayerPointers, ULONG *pmem_set_array)
1947*75ab5f91Slh155975 {
1948*75ab5f91Slh155975 	int RxRingSize, TxRingSize;
1949*75ab5f91Slh155975 	int RxBufSize;
1950*75ab5f91Slh155975 	struct mil *pMil;
1951*75ab5f91Slh155975 
1952*75ab5f91Slh155975 	RxRingSize = RX_RING_SIZE;
1953*75ab5f91Slh155975 	TxRingSize = TX_RING_SIZE;
1954*75ab5f91Slh155975 	RxBufSize = RX_BUF_SIZE;
1955*75ab5f91Slh155975 
1956*75ab5f91Slh155975 	/* 1) Set the pointers to the mil pointers */
1957*75ab5f91Slh155975 	/* Type */
1958*75ab5f91Slh155975 	pmem_set_array++;
1959*75ab5f91Slh155975 	/* Size */
1960*75ab5f91Slh155975 	pmem_set_array++;
1961*75ab5f91Slh155975 	pMil = (struct mil *)(*pmem_set_array);
1962*75ab5f91Slh155975 	pLayerPointers->pMil = pMil;
1963*75ab5f91Slh155975 
1964*75ab5f91Slh155975 	pMil->RxRingSize = RxRingSize;
1965*75ab5f91Slh155975 	pMil->TxRingSize = TxRingSize;
1966*75ab5f91Slh155975 	pMil->RxBufSize = RxBufSize;
1967*75ab5f91Slh155975 
1968*75ab5f91Slh155975 	/* 2) Type */
1969*75ab5f91Slh155975 	pmem_set_array++;
1970*75ab5f91Slh155975 	/* Size */
1971*75ab5f91Slh155975 	pmem_set_array++;
1972*75ab5f91Slh155975 	pmem_set_array++;
1973*75ab5f91Slh155975 	pMil->USpaceMapArray = (long *)(*pmem_set_array);
1974*75ab5f91Slh155975 
1975*75ab5f91Slh155975 	/* 3) Set the pointers to the NonPhysical part */
1976*75ab5f91Slh155975 	/* Type */
1977*75ab5f91Slh155975 	pmem_set_array++;
1978*75ab5f91Slh155975 	/* Size */
1979*75ab5f91Slh155975 	pmem_set_array++;
1980*75ab5f91Slh155975 	/* Virtual Addr of NonPhysical */
1981*75ab5f91Slh155975 	pmem_set_array++;
1982*75ab5f91Slh155975 	pMil->pNonphysical =
1983*75ab5f91Slh155975 	    (struct nonphysical *)(*pmem_set_array);
1984*75ab5f91Slh155975 
1985*75ab5f91Slh155975 	/*
1986*75ab5f91Slh155975 	 * 4~6) Following four allocation are for abstracting the Rx_Descritor
1987*75ab5f91Slh155975 	 * Ring.
1988*75ab5f91Slh155975 	 */
1989*75ab5f91Slh155975 	/* 4) Type */
1990*75ab5f91Slh155975 	pmem_set_array++;
1991*75ab5f91Slh155975 	/* Size */
1992*75ab5f91Slh155975 	pmem_set_array++;
1993*75ab5f91Slh155975 	/* Virtual Addr of Abstracted RxDesc */
1994*75ab5f91Slh155975 	pmem_set_array++;
1995*75ab5f91Slh155975 	pMil->pNonphysical->RxBufDescQRead =
1996*75ab5f91Slh155975 	    (struct Rx_Buf_Desc *)(*pmem_set_array);
1997*75ab5f91Slh155975 
1998*75ab5f91Slh155975 	/* 5) Type */
1999*75ab5f91Slh155975 	pmem_set_array++;
2000*75ab5f91Slh155975 	/* Size */
2001*75ab5f91Slh155975 	pmem_set_array++;
2002*75ab5f91Slh155975 	/* Virtual Addr of Abstracted RxDesc */
2003*75ab5f91Slh155975 	pmem_set_array++;
2004*75ab5f91Slh155975 	pMil->pNonphysical->RxBufDescQStart =
2005*75ab5f91Slh155975 	    (struct Rx_Buf_Desc *)(*pmem_set_array);
2006*75ab5f91Slh155975 
2007*75ab5f91Slh155975 	/* 6) Type */
2008*75ab5f91Slh155975 	pmem_set_array++;
2009*75ab5f91Slh155975 	/* Size */
2010*75ab5f91Slh155975 	pmem_set_array++;
2011*75ab5f91Slh155975 	/* Virtual Addr of Abstracted RxDesc */
2012*75ab5f91Slh155975 	pmem_set_array++;
2013*75ab5f91Slh155975 	pMil->pNonphysical->RxBufDescQEnd =
2014*75ab5f91Slh155975 	    (struct Rx_Buf_Desc *)(*pmem_set_array);
2015*75ab5f91Slh155975 
2016*75ab5f91Slh155975 	pmem_set_array++;
2017*75ab5f91Slh155975 
2018*75ab5f91Slh155975 	mdlSetResources(pLayerPointers, pmem_set_array);
2019*75ab5f91Slh155975 }
2020*75ab5f91Slh155975 
2021*75ab5f91Slh155975 /*
2022*75ab5f91Slh155975  *	Purpose  :
2023*75ab5f91Slh155975  *		This routine adds the Multicast addresses to the filter
2024*75ab5f91Slh155975  *
2025*75ab5f91Slh155975  *	Arguments :
2026*75ab5f91Slh155975  *		pLayerPointers
2027*75ab5f91Slh155975  *			Pointer to Layer pointers structure.
2028*75ab5f91Slh155975  *		pucMulticastAddress
2029*75ab5f91Slh155975  *			Pointer to the array of multicast addresses
2030*75ab5f91Slh155975  */
2031*75ab5f91Slh155975 void
mdlAddMulticastAddress(struct LayerPointers * pLayerPointers,UCHAR * pucMulticastAddress)2032*75ab5f91Slh155975 mdlAddMulticastAddress(struct LayerPointers *pLayerPointers,
2033*75ab5f91Slh155975     UCHAR *pucMulticastAddress)
2034*75ab5f91Slh155975 {
2035*75ab5f91Slh155975 	unsigned long MODE[10];
2036*75ab5f91Slh155975 	unsigned long tmp1;
2037*75ab5f91Slh155975 	unsigned long tmp2;
2038*75ab5f91Slh155975 
2039*75ab5f91Slh155975 	if (mdlMulticastBitMapping(pLayerPointers, pucMulticastAddress,
2040*75ab5f91Slh155975 	    ADD_MULTICAST) != 0)
2041*75ab5f91Slh155975 		return;
2042*75ab5f91Slh155975 
2043*75ab5f91Slh155975 	tmp2 = SET_SINGLE_MULTICAST;
2044*75ab5f91Slh155975 	MODE[0] = (unsigned long)tmp2;
2045*75ab5f91Slh155975 	MODE[1] = 1;
2046*75ab5f91Slh155975 	tmp1 = (unsigned long)pucMulticastAddress;
2047*75ab5f91Slh155975 	MODE[2] = tmp1;
2048*75ab5f91Slh155975 	MODE[3] = ENABLE_MULTICAST;
2049*75ab5f91Slh155975 	MODE[4] = 0;
2050*75ab5f91Slh155975 	mdlChangeFilter(pLayerPointers, (unsigned long *)MODE);
2051*75ab5f91Slh155975 }
2052*75ab5f91Slh155975 
2053*75ab5f91Slh155975 
2054*75ab5f91Slh155975 /*
2055*75ab5f91Slh155975  *	Purpose  :
2056*75ab5f91Slh155975  *		This routine deletes the Multicast addresses requested by OS.
2057*75ab5f91Slh155975  *
2058*75ab5f91Slh155975  *	Arguments :
2059*75ab5f91Slh155975  *		pLayerPointers
2060*75ab5f91Slh155975  *			Pointer to Layer pointers structure.
2061*75ab5f91Slh155975  *		pucMulticastAddress
2062*75ab5f91Slh155975  *			Pointer to the array of multicast addresses
2063*75ab5f91Slh155975  */
2064*75ab5f91Slh155975 void
mdlDeleteMulticastAddress(struct LayerPointers * pLayerPointers,UCHAR * pucMulticastAddress)2065*75ab5f91Slh155975 mdlDeleteMulticastAddress(struct LayerPointers *pLayerPointers,
2066*75ab5f91Slh155975     UCHAR *pucMulticastAddress)
2067*75ab5f91Slh155975 {
2068*75ab5f91Slh155975 	unsigned long MODE[10];
2069*75ab5f91Slh155975 	unsigned long tmp;
2070*75ab5f91Slh155975 
2071*75ab5f91Slh155975 	if (mdlMulticastBitMapping(pLayerPointers, pucMulticastAddress,
2072*75ab5f91Slh155975 	    DELETE_MULTICAST) != 0)
2073*75ab5f91Slh155975 		return;
2074*75ab5f91Slh155975 
2075*75ab5f91Slh155975 	MODE[0] = UNSET_SINGLE_MULTICAST;
2076*75ab5f91Slh155975 	MODE[1] = 1;
2077*75ab5f91Slh155975 	tmp = (unsigned long)pucMulticastAddress;
2078*75ab5f91Slh155975 	MODE[2] = tmp;
2079*75ab5f91Slh155975 	MODE[3] = ENABLE_MULTICAST;
2080*75ab5f91Slh155975 	MODE[4] = 0;
2081*75ab5f91Slh155975 	mdlChangeFilter(pLayerPointers, (unsigned long *)MODE);
2082*75ab5f91Slh155975 }
2083*75ab5f91Slh155975 
2084*75ab5f91Slh155975 /*
2085*75ab5f91Slh155975  *	Purpose  :
2086*75ab5f91Slh155975  *		Calculates the CRC value over the input number of bytes.
2087*75ab5f91Slh155975  *
2088*75ab5f91Slh155975  *	Arguments :
2089*75ab5f91Slh155975  *		NumberOfBytes
2090*75ab5f91Slh155975  *			The number of bytes in the input.
2091*75ab5f91Slh155975  *		Input
2092*75ab5f91Slh155975  *			An input "string" to calculate a CRC over.
2093*75ab5f91Slh155975  */
2094*75ab5f91Slh155975 static unsigned int
mdlCalculateCRC(unsigned int NumberOfBytes,unsigned char * Input)2095*75ab5f91Slh155975 mdlCalculateCRC(unsigned int NumberOfBytes, unsigned char *Input)
2096*75ab5f91Slh155975 {
2097*75ab5f91Slh155975 	const unsigned int POLY = 0x04c11db7;
2098*75ab5f91Slh155975 	unsigned int CRCValue = 0xffffffff;
2099*75ab5f91Slh155975 	unsigned int CurrentBit, CurrentCRCHigh;
2100*75ab5f91Slh155975 	unsigned char CurrentByte;
2101*75ab5f91Slh155975 
2102*75ab5f91Slh155975 	for (; NumberOfBytes; NumberOfBytes--) {
2103*75ab5f91Slh155975 		CurrentByte = *Input;
2104*75ab5f91Slh155975 		Input++;
2105*75ab5f91Slh155975 
2106*75ab5f91Slh155975 		for (CurrentBit = 8; CurrentBit; CurrentBit--) {
2107*75ab5f91Slh155975 			CurrentCRCHigh = CRCValue >> 31;
2108*75ab5f91Slh155975 			CRCValue <<= 1;
2109*75ab5f91Slh155975 
2110*75ab5f91Slh155975 			if (CurrentCRCHigh ^ (CurrentByte & 0x01)) {
2111*75ab5f91Slh155975 				CRCValue ^= POLY;
2112*75ab5f91Slh155975 				CRCValue |= 0x00000001;
2113*75ab5f91Slh155975 			}
2114*75ab5f91Slh155975 			CurrentByte >>= 1;
2115*75ab5f91Slh155975 		}
2116*75ab5f91Slh155975 	}
2117*75ab5f91Slh155975 	return (CRCValue);
2118*75ab5f91Slh155975 }
2119*75ab5f91Slh155975 
2120*75ab5f91Slh155975 void
mdlRxFastSuspend(struct LayerPointers * pLayerPointers)2121*75ab5f91Slh155975 mdlRxFastSuspend(struct LayerPointers *pLayerPointers)
2122*75ab5f91Slh155975 {
2123*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
2124*75ab5f91Slh155975 	    VAL0 | RX_FAST_SPND);
2125*75ab5f91Slh155975 }
2126*75ab5f91Slh155975 
2127*75ab5f91Slh155975 void
mdlRxFastSuspendClear(struct LayerPointers * pLayerPointers)2128*75ab5f91Slh155975 mdlRxFastSuspendClear(struct LayerPointers *pLayerPointers)
2129*75ab5f91Slh155975 {
2130*75ab5f91Slh155975 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
2131*75ab5f91Slh155975 	    RX_FAST_SPND);
2132*75ab5f91Slh155975 }
2133