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