175ab5f91Slh /*
275ab5f91Slh  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
375ab5f91Slh  * Use is subject to license terms.
475ab5f91Slh  */
575ab5f91Slh 
675ab5f91Slh /*
775ab5f91Slh  * Copyright (c) 2001-2006 Advanced Micro Devices, Inc.  All rights reserved.
875ab5f91Slh  *
975ab5f91Slh  * Redistribution and use in source and binary forms, with or without
1075ab5f91Slh  * modification, are permitted provided that the following conditions are met:
1175ab5f91Slh  *
1275ab5f91Slh  * + Redistributions of source code must retain the above copyright notice,
1375ab5f91Slh  * + this list of conditions and the following disclaimer.
1475ab5f91Slh  *
1575ab5f91Slh  * + Redistributions in binary form must reproduce the above copyright
1675ab5f91Slh  * + notice, this list of conditions and the following disclaimer in the
1775ab5f91Slh  * + documentation and/or other materials provided with the distribution.
1875ab5f91Slh  *
1975ab5f91Slh  * + Neither the name of Advanced Micro Devices, Inc. nor the names of its
2075ab5f91Slh  * + contributors may be used to endorse or promote products derived from
2175ab5f91Slh  * + this software without specific prior written permission.
2275ab5f91Slh  *
2375ab5f91Slh  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
2475ab5f91Slh  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
2575ab5f91Slh  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2675ab5f91Slh  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2775ab5f91Slh  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. OR
2875ab5f91Slh  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2975ab5f91Slh  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3075ab5f91Slh  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3175ab5f91Slh  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3275ab5f91Slh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3375ab5f91Slh  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3475ab5f91Slh  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
3575ab5f91Slh  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3675ab5f91Slh  *
3775ab5f91Slh  * Import/Export/Re-Export/Use/Release/Transfer Restrictions and
3875ab5f91Slh  * Compliance with Applicable Laws.  Notice is hereby given that
3975ab5f91Slh  * the software may be subject to restrictions on use, release,
4075ab5f91Slh  * transfer, importation, exportation and/or re-exportation under
4175ab5f91Slh  * the laws and regulations of the United States or other
4275ab5f91Slh  * countries ("Applicable Laws"), which include but are not
4375ab5f91Slh  * limited to U.S. export control laws such as the Export
4475ab5f91Slh  * Administration Regulations and national security controls as
4575ab5f91Slh  * defined thereunder, as well as State Department controls under
4675ab5f91Slh  * the U.S. Munitions List.  Permission to use and/or
4775ab5f91Slh  * redistribute the software is conditioned upon compliance with
4875ab5f91Slh  * all Applicable Laws, including U.S. export control laws
4975ab5f91Slh  * regarding specifically designated persons, countries and
5075ab5f91Slh  * nationals of countries subject to national security controls.
5175ab5f91Slh  */
5275ab5f91Slh 
5375ab5f91Slh 
5475ab5f91Slh #include <sys/types.h>
5575ab5f91Slh #include <sys/cmn_err.h>
5675ab5f91Slh #include <sys/debug.h>
5775ab5f91Slh #include <sys/ddi.h>
5875ab5f91Slh #include <sys/sunddi.h>
5975ab5f91Slh #include "amd8111s_hw.h"
6075ab5f91Slh #include "amd8111s_main.h"
6175ab5f91Slh 
6275ab5f91Slh 
6375ab5f91Slh #pragma inline(mdlTransmit)
6475ab5f91Slh #pragma inline(mdlReceive)
6575ab5f91Slh 
6675ab5f91Slh #pragma inline(mdlReadInterrupt)
6775ab5f91Slh #pragma inline(mdlEnableInterrupt)
6875ab5f91Slh #pragma inline(mdlDisableInterrupt)
6975ab5f91Slh 
7075ab5f91Slh 
7175ab5f91Slh static void mdlEnableMagicPacketWakeUp(struct LayerPointers *);
7275ab5f91Slh 
7375ab5f91Slh /* PMR (Pattern Match RAM) */
7475ab5f91Slh static void mdlAddWakeUpPattern(struct LayerPointers *, unsigned char *,
7575ab5f91Slh     unsigned char *, unsigned long, unsigned long, int *);
7675ab5f91Slh static void mdlRemoveWakeUpPattern(struct LayerPointers *, unsigned char *,
7775ab5f91Slh     unsigned long, int *);
7875ab5f91Slh 
7975ab5f91Slh static int mdlMulticastBitMapping(struct LayerPointers *, unsigned char *, int);
8075ab5f91Slh 
8175ab5f91Slh static unsigned int mdlCalculateCRC(unsigned int, unsigned char *);
8275ab5f91Slh 
8375ab5f91Slh static void mdlChangeFilter(struct LayerPointers *, unsigned long *);
8475ab5f91Slh static void mdlReceiveBroadCast(struct LayerPointers *);
8575ab5f91Slh static void mdlDisableReceiveBroadCast(struct LayerPointers *);
8675ab5f91Slh 
8775ab5f91Slh static void mdlRequestResources(ULONG *);
8875ab5f91Slh static void mdlSetResources(struct LayerPointers *, ULONG *);
8975ab5f91Slh static void mdlFreeResources(struct LayerPointers *, ULONG *);
9075ab5f91Slh 
9175ab5f91Slh /*
9275ab5f91Slh  *	Initialises the data used in Mdl.
9375ab5f91Slh  */
9475ab5f91Slh static void
mdlInitGlbds(struct LayerPointers * pLayerPointers)9575ab5f91Slh mdlInitGlbds(struct LayerPointers *pLayerPointers)
9675ab5f91Slh {
9775ab5f91Slh 	struct mdl *pMdl = pLayerPointers->pMdl;
9875ab5f91Slh 
9975ab5f91Slh 	/* Disable Rx and Tx. */
10075ab5f91Slh 	pMdl->init_blk->MODE = 0x0000;
10175ab5f91Slh 
10275ab5f91Slh 	/* Set Interrupt Delay Parameters */
10375ab5f91Slh 	pMdl->IntrCoalescFlag = 1;
10475ab5f91Slh 	pMdl->rx_intrcoalesc_time = 0xC8;	/* 200 */
10575ab5f91Slh 	pMdl->rx_intrcoalesc_events = 5;
10675ab5f91Slh }
10775ab5f91Slh 
10875ab5f91Slh void
mdlPHYAutoNegotiation(struct LayerPointers * pLayerPointers,unsigned int type)10975ab5f91Slh mdlPHYAutoNegotiation(struct LayerPointers *pLayerPointers, unsigned int type)
11075ab5f91Slh {
11175ab5f91Slh 	int iData = 0;
11275ab5f91Slh 	struct mdl *pMdl = pLayerPointers->pMdl;
11375ab5f91Slh 
11475ab5f91Slh 	/* PHY auto negotiation or force speed/duplex */
11575ab5f91Slh 	switch (type) {
11675ab5f91Slh 	case PHY_AUTO_NEGOTIATION: /* Auto Negotiation */
11775ab5f91Slh 		/* EN_PMGR: Disable the Port Manager */
11875ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
11975ab5f91Slh 		drv_usecwait(100000);
12075ab5f91Slh 
12175ab5f91Slh 		/*
12275ab5f91Slh 		 * Enable Autonegotiation the Phy now
12375ab5f91Slh 		 *	XPHYANE(eXternal PHY Auto Negotiation Enable)
12475ab5f91Slh 		 */
12575ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2,
12675ab5f91Slh 		    XPHYANE | XPHYRST);
12775ab5f91Slh 
12875ab5f91Slh 		/* EN_PMGR: Enable the Port Manager */
12975ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
13075ab5f91Slh 		    VAL1 | EN_PMGR);
13175ab5f91Slh 
13275ab5f91Slh 		drv_usecwait(500000);
13375ab5f91Slh 
13475ab5f91Slh 		pMdl->Speed = 100;
13575ab5f91Slh 		pMdl->FullDuplex = B_TRUE;
13675ab5f91Slh 
13775ab5f91Slh 		break;
13875ab5f91Slh 
13975ab5f91Slh 	case PHY_FORCE_HD_100:	/* 100Mbps HD */
14075ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
14175ab5f91Slh 
14275ab5f91Slh 		/* Force 100 Mbps, half duplex */
14375ab5f91Slh 		iData |= XPHYSP;
14475ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2, iData);
14575ab5f91Slh 
14675ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
14775ab5f91Slh 		    VAL1 | EN_PMGR);
14875ab5f91Slh 
14975ab5f91Slh 		drv_usecwait(500000);
15075ab5f91Slh 
15175ab5f91Slh 		pMdl->Speed = 100;
15275ab5f91Slh 		pMdl->FullDuplex = B_FALSE;
15375ab5f91Slh 
15475ab5f91Slh 		break;
15575ab5f91Slh 
15675ab5f91Slh 	case PHY_FORCE_FD_100:	/* 100Mbps FD */
15775ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
15875ab5f91Slh 
15975ab5f91Slh 		/* Force 100 Mbps, full duplex */
16075ab5f91Slh 		iData |= (XPHYSP | XPHYFD);
16175ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2, iData);
16275ab5f91Slh 
16375ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
16475ab5f91Slh 		    VAL1 | EN_PMGR);
16575ab5f91Slh 
16675ab5f91Slh 		drv_usecwait(500000);
16775ab5f91Slh 
16875ab5f91Slh 		pMdl->Speed = 100;
16975ab5f91Slh 		pMdl->FullDuplex = B_TRUE;
17075ab5f91Slh 
17175ab5f91Slh 		break;
17275ab5f91Slh 
17375ab5f91Slh 	case PHY_FORCE_HD_10: /* 10 Mbps HD  */
17475ab5f91Slh 		/* Disable the Port Manager */
17575ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
17675ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2, iData);
17775ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
17875ab5f91Slh 		    VAL1 | EN_PMGR);
17975ab5f91Slh 
18075ab5f91Slh 		drv_usecwait(500000);
18175ab5f91Slh 
18275ab5f91Slh 		pMdl->Speed = 10;
18375ab5f91Slh 		pMdl->FullDuplex = B_FALSE;
18475ab5f91Slh 
18575ab5f91Slh 		break;
18675ab5f91Slh 
18775ab5f91Slh 	case PHY_FORCE_FD_10: /* 10Mbps FD  */
18875ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3, EN_PMGR);
18975ab5f91Slh 
19075ab5f91Slh 		iData |= XPHYFD;
19175ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL2, iData);
19275ab5f91Slh 
19375ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
19475ab5f91Slh 		    VAL1 | EN_PMGR);
19575ab5f91Slh 
19675ab5f91Slh 		drv_usecwait(500000);
19775ab5f91Slh 
19875ab5f91Slh 		pMdl->Speed = 10;
19975ab5f91Slh 		pMdl->FullDuplex = B_TRUE;
20075ab5f91Slh 
20175ab5f91Slh 		break;
20275ab5f91Slh 	}
20375ab5f91Slh }
20475ab5f91Slh 
20575ab5f91Slh /*
20675ab5f91Slh  *	Clear HW configuration.
20775ab5f91Slh  */
20875ab5f91Slh static void
mdlClearHWConfig(struct LayerPointers * pLayerPointers)20975ab5f91Slh mdlClearHWConfig(struct LayerPointers *pLayerPointers)
21075ab5f91Slh {
21175ab5f91Slh 	/*
21275ab5f91Slh 	 * Before the network controller is ready for operation,
21375ab5f91Slh 	 * several registers must be initialized.
21475ab5f91Slh 	 */
21575ab5f91Slh 	unsigned int data32;
21675ab5f91Slh 	int JumboFlag = JUMBO_DISABLED;
21775ab5f91Slh 	ULONG MemBaseAddress;
21875ab5f91Slh 
21975ab5f91Slh 	MemBaseAddress = pLayerPointers->pMdl->Mem_Address;
22075ab5f91Slh 
22175ab5f91Slh 	/* AUTOPOLL0 Register */
22275ab5f91Slh 	WRITE_REG16(pLayerPointers, MemBaseAddress + AUTOPOLL0, 0x8101);
22375ab5f91Slh 
22475ab5f91Slh 	/* Clear RCV_RING_BASE_ADDR */
22575ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR0, 0);
22675ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR1, 0);
22775ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR0, 0);
22875ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR2, 0);
22975ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + RCV_RING_BASE_ADDR3, 0);
23075ab5f91Slh 
23175ab5f91Slh 	/* Clear XMT_RING_BASE_ADDR */
23275ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_BASE_ADDR0, 0);
23375ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_BASE_ADDR1, 0);
23475ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_BASE_ADDR2, 0);
23575ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_BASE_ADDR3, 0);
23675ab5f91Slh 
23775ab5f91Slh 	/* Clear CMD0 / CMD2 */
23875ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + CMD0, 0x000F0F7F);
23975ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + CMD2, 0x3F7F3F7F);
24075ab5f91Slh 
24175ab5f91Slh 	/* Enable Port Management */
24275ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + CMD3, VAL1 | EN_PMGR);
24375ab5f91Slh 
24475ab5f91Slh 	/* Clear CMD7 */
24575ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + CMD7, 0x1B);
24675ab5f91Slh 
24775ab5f91Slh 	/* Clear CTRL0/1 */
24875ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + CTRL1, XMTSP_MASK);
24975ab5f91Slh 
25075ab5f91Slh 	/* Clear DLY_INT_A/B */
25175ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_A, 0);
25275ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_B, 0);
25375ab5f91Slh 
25475ab5f91Slh 	/* Clear FLOW_CONTROL */
25575ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + FLOW_CONTROL, 0);
25675ab5f91Slh 
25775ab5f91Slh 	/* Clear INT0 */
25875ab5f91Slh 	data32 = READ_REG32(pLayerPointers, MemBaseAddress + INT0);
25975ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + INT0, data32);
26075ab5f91Slh 
26175ab5f91Slh 	/* Clear STVAL */
26275ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + STVAL, 0);
26375ab5f91Slh 
26475ab5f91Slh 	/* Clear INTEN0 */
26575ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + INTEN0, 0x1F7F7F1F);
26675ab5f91Slh 
26775ab5f91Slh 	/* Clear LADRF */
26875ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + LADRF1, 0);
26975ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + LADRF1 + 4, 0);
27075ab5f91Slh 
27175ab5f91Slh 	/* Clear LED0 */
27275ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + LED0, 0);
27375ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + LED1, 0);
27475ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + LED2, 0);
27575ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + LED3, 0);
27675ab5f91Slh 
27775ab5f91Slh 	/* Set RCV_RING_CFG */
27875ab5f91Slh 	WRITE_REG16(pLayerPointers, MemBaseAddress + RCV_RING_CFG, 1);
27975ab5f91Slh 
28075ab5f91Slh 	/* SRAM_SIZE & SRAM_BOUNDARY register combined */
28175ab5f91Slh 	if (JumboFlag == JUMBO_ENABLED) {
28275ab5f91Slh 		WRITE_REG32(pLayerPointers, MemBaseAddress + SRAM_SIZE,
28375ab5f91Slh 		    0xc0010);
28475ab5f91Slh 	} else {
28575ab5f91Slh 		WRITE_REG32(pLayerPointers, MemBaseAddress + SRAM_SIZE,
28675ab5f91Slh 		    0x80010);
28775ab5f91Slh 	}
28875ab5f91Slh 
28975ab5f91Slh 	/* Clear XMT_RING0/1/2/3_LEN */
29075ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LEN0, 0);
29175ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LEN1, 0);
29275ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LEN2, 0);
29375ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LEN3, 0);
29475ab5f91Slh 
29575ab5f91Slh 	/* Clear XMT_RING_LIMIT */
29675ab5f91Slh 	WRITE_REG32(pLayerPointers, MemBaseAddress + XMT_RING_LIMIT, 0);
29775ab5f91Slh 
29875ab5f91Slh 	WRITE_REG16(pLayerPointers, MemBaseAddress + MIB_ADDR, MIB_CLEAR);
29975ab5f91Slh }
30075ab5f91Slh 
30175ab5f91Slh unsigned int
mdlReadMib(struct LayerPointers * pLayerPointers,char MIB_COUNTER)30275ab5f91Slh mdlReadMib(struct LayerPointers *pLayerPointers, char MIB_COUNTER)
30375ab5f91Slh {
30475ab5f91Slh 	unsigned int status;
30575ab5f91Slh 	unsigned int data;
30675ab5f91Slh 	unsigned long mmio = pLayerPointers->pMdl->Mem_Address;
30775ab5f91Slh 
30875ab5f91Slh 	WRITE_REG16(pLayerPointers, mmio + MIB_ADDR, MIB_RD_CMD | MIB_COUNTER);
30975ab5f91Slh 	do {
31075ab5f91Slh 		status = READ_REG16(pLayerPointers, mmio + MIB_ADDR);
31175ab5f91Slh 	} while ((status & MIB_CMD_ACTIVE));
31275ab5f91Slh 
31375ab5f91Slh 	data = READ_REG32(pLayerPointers, mmio + MIB_DATA);
31475ab5f91Slh 	return (data);
31575ab5f91Slh }
31675ab5f91Slh 
31775ab5f91Slh /* Return 1 on success, return 0 on fail */
31875ab5f91Slh unsigned int
mdlReadPHY(struct LayerPointers * pLayerPointers,unsigned char phyid,unsigned char regaddr,unsigned int * value)31975ab5f91Slh mdlReadPHY(struct LayerPointers *pLayerPointers, unsigned char phyid,
32075ab5f91Slh     unsigned char regaddr, unsigned int *value)
32175ab5f91Slh {
32275ab5f91Slh 	unsigned int status, data, count;
32375ab5f91Slh 	unsigned long mmio = pLayerPointers->pMdl->Mem_Address;
32475ab5f91Slh 
32575ab5f91Slh 	count = 0;
32675ab5f91Slh 	do {
32775ab5f91Slh 		status = READ_REG16(pLayerPointers, mmio + PHY_ACCESS);
32875ab5f91Slh 		count ++;
32975ab5f91Slh 		drv_usecwait(10);
33075ab5f91Slh 	} while ((status & PHY_CMD_ACTIVE) & (count < PHY_MAX_RETRY));
33175ab5f91Slh 
33275ab5f91Slh 	if (count == PHY_MAX_RETRY) {
33375ab5f91Slh 		return (0);
33475ab5f91Slh 	}
33575ab5f91Slh 
33675ab5f91Slh 	data = ((regaddr & 0x1f) << 16) | ((phyid & 0x1f) << 21) | PHY_RD_CMD;
33775ab5f91Slh 	WRITE_REG32(pLayerPointers, mmio + PHY_ACCESS, data);
33875ab5f91Slh 	do {
33975ab5f91Slh 		status = READ_REG16(pLayerPointers, mmio + PHY_ACCESS);
34075ab5f91Slh 		drv_usecwait(10);
34175ab5f91Slh 		count ++;
34275ab5f91Slh 	} while ((status & PHY_CMD_ACTIVE) & (count < PHY_MAX_RETRY));
34375ab5f91Slh 
34475ab5f91Slh 	if ((count == PHY_MAX_RETRY) || (status & PHY_RD_ERR)) {
34575ab5f91Slh 		return (0);
34675ab5f91Slh 	}
34775ab5f91Slh 
34875ab5f91Slh 	*value = status & 0xffff;
34975ab5f91Slh 	return (1);
35075ab5f91Slh }
35175ab5f91Slh 
35275ab5f91Slh void
mdlGetPHYID(struct LayerPointers * pLayerPointers)35375ab5f91Slh mdlGetPHYID(struct LayerPointers *pLayerPointers)
35475ab5f91Slh {
35575ab5f91Slh 	unsigned int id1, id2, i;
35675ab5f91Slh 	for (i = 1; i < 32; i++) {
35775ab5f91Slh 		if (mdlReadPHY(pLayerPointers, i, MII_PHYSID1, &id1) == 0)
35875ab5f91Slh 			continue;
35975ab5f91Slh 		if (mdlReadPHY(pLayerPointers, i, MII_PHYSID2, &id2) == 0)
36075ab5f91Slh 			continue;
36175ab5f91Slh 		if ((id1 != 0xffff) & (id2 != 0xffff)) {
36275ab5f91Slh 			pLayerPointers->pMdl->phy_id = i;
36375ab5f91Slh 			return;
36475ab5f91Slh 		}
36575ab5f91Slh 	}
36675ab5f91Slh }
36775ab5f91Slh 
36875ab5f91Slh /* Return 1 on success, return 0 on fail */
36975ab5f91Slh unsigned int
mdlWritePHY(struct LayerPointers * pLayerPointers,unsigned char phyid,unsigned char regaddr,unsigned int value)37075ab5f91Slh mdlWritePHY(struct LayerPointers *pLayerPointers, unsigned char phyid,
37175ab5f91Slh     unsigned char regaddr, unsigned int value)
37275ab5f91Slh {
37375ab5f91Slh 	unsigned int status, data, count;
37475ab5f91Slh 	unsigned long mmio = pLayerPointers->pMdl->Mem_Address;
37575ab5f91Slh 
37675ab5f91Slh 	count = 0;
37775ab5f91Slh 	do {
37875ab5f91Slh 		status = READ_REG16(pLayerPointers, mmio + PHY_ACCESS);
37975ab5f91Slh 		count ++;
38075ab5f91Slh 		drv_usecwait(10);
38175ab5f91Slh 	} while ((status & PHY_CMD_ACTIVE) & (count < PHY_MAX_RETRY));
38275ab5f91Slh 
38375ab5f91Slh 	if (count == PHY_MAX_RETRY) {
38475ab5f91Slh 		return (0);
38575ab5f91Slh 	}
38675ab5f91Slh 
38775ab5f91Slh 	data = ((regaddr & 0x1f) << 16) | ((phyid & 0x1f) << 21) |
38875ab5f91Slh 	    (value & 0xffff) | PHY_WR_CMD;
38975ab5f91Slh 	WRITE_REG32(pLayerPointers, mmio + PHY_ACCESS, data);
39075ab5f91Slh 
39175ab5f91Slh 	do {
39275ab5f91Slh 		status = READ_REG16(pLayerPointers, mmio + PHY_ACCESS);
39375ab5f91Slh 		drv_usecwait(10);
39475ab5f91Slh 		count ++;
39575ab5f91Slh 	} while ((status & PHY_CMD_ACTIVE) & (count < PHY_MAX_RETRY));
39675ab5f91Slh 
39775ab5f91Slh 	if ((count == PHY_MAX_RETRY) && (status & PHY_RD_ERR)) {
39875ab5f91Slh 		return (0);
39975ab5f91Slh 	}
40075ab5f91Slh 
40175ab5f91Slh 	return (1);
40275ab5f91Slh }
40375ab5f91Slh 
40475ab5f91Slh /*
40575ab5f91Slh  *	To Send the packet.
40675ab5f91Slh  */
40775ab5f91Slh void
mdlTransmit(struct LayerPointers * pLayerPointers)40875ab5f91Slh mdlTransmit(struct LayerPointers *pLayerPointers)
40975ab5f91Slh {
41075ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
41175ab5f91Slh 	    VAL1 | TDMD0);
41275ab5f91Slh }
41375ab5f91Slh 
41475ab5f91Slh /*
41575ab5f91Slh  *	To Receive a packet.
41675ab5f91Slh  */
41775ab5f91Slh void
mdlReceive(struct LayerPointers * pLayerPointers)41875ab5f91Slh mdlReceive(struct LayerPointers *pLayerPointers)
41975ab5f91Slh {
42075ab5f91Slh 	/*
42175ab5f91Slh 	 * Receive Demand for ring 0, which when set causes the Descriptor
42275ab5f91Slh 	 * Management Unit to access the Receive Descriptor Ring if it does
42375ab5f91Slh 	 * not already own the next descriptor.
42475ab5f91Slh 	 */
42575ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
42675ab5f91Slh 	    VAL2 | RDMD0);
42775ab5f91Slh }
42875ab5f91Slh 
42975ab5f91Slh /*
43075ab5f91Slh  * Read the NIC interrupt.
43175ab5f91Slh  *
43275ab5f91Slh  * Returns:
43375ab5f91Slh  *	the value of interrupt causes register
43475ab5f91Slh  */
43575ab5f91Slh unsigned int
mdlReadInterrupt(struct LayerPointers * pLayerPointers)43675ab5f91Slh mdlReadInterrupt(struct LayerPointers *pLayerPointers)
43775ab5f91Slh {
43875ab5f91Slh 	unsigned int nINT0;
43975ab5f91Slh 	struct mdl *pMdl = 0;
44075ab5f91Slh 
44175ab5f91Slh 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
44275ab5f91Slh 
44375ab5f91Slh 	/*
44475ab5f91Slh 	 * INT0 identifies the source or sources of an interrupt. With the
44575ab5f91Slh 	 * exception of INTR and INTPN, all bits in this register are "write
44675ab5f91Slh 	 * 1 to clear" so that the CPU can clear the interrupt condition by
44775ab5f91Slh 	 * reading the register and then writing back the same data that it
44875ab5f91Slh 	 * read. Writing a 0 to a bit in this register has no effect.
44975ab5f91Slh 	 */
45075ab5f91Slh 
45175ab5f91Slh 	/* Read interrupt status */
45275ab5f91Slh 	nINT0 = READ_REG32(pLayerPointers, pMdl->Mem_Address + INT0);
45375ab5f91Slh 
45475ab5f91Slh 	/* Process all the INT event until INTR bit is clear. */
45575ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INT0, nINT0);
45675ab5f91Slh 	return (nINT0);
45775ab5f91Slh }
45875ab5f91Slh 
45975ab5f91Slh void
mdlHWReset(struct LayerPointers * pLayerPointers)46075ab5f91Slh mdlHWReset(struct LayerPointers *pLayerPointers)
46175ab5f91Slh {
46275ab5f91Slh 	struct mdl *pMdl = pLayerPointers->pMdl;
46375ab5f91Slh 	unsigned int ulData, i = 0;
46475ab5f91Slh 	int  JumboFlag = JUMBO_DISABLED;
46575ab5f91Slh 	ULONG Mem_Address = pMdl->Mem_Address;
46675ab5f91Slh 
46775ab5f91Slh 	/*
46875ab5f91Slh 	 * Stop the Card:
46975ab5f91Slh 	 *	First we make sure that the device is stopped and no
47075ab5f91Slh 	 *	more interrupts come out. Also some registers must be
47175ab5f91Slh 	 *	programmed with CSR0 STOP bit set.
47275ab5f91Slh 	 */
47375ab5f91Slh 	mdlStopChip(pLayerPointers);
47475ab5f91Slh 
47575ab5f91Slh 	/*
47675ab5f91Slh 	 * MAC Address Setup:
47775ab5f91Slh 	 *	MAC Physical Address register. All bits in this register are
47875ab5f91Slh 	 *	restored to default values when the RST pin is asserted.
47975ab5f91Slh 	 */
48075ab5f91Slh 	for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++) {
48175ab5f91Slh 		WRITE_REG8(pLayerPointers, pMdl->Mem_Address + PADR + i,
48275ab5f91Slh 		    pMdl->Mac[i]);
48375ab5f91Slh 	}
48475ab5f91Slh 
48575ab5f91Slh 	/* Set RCV_RING_CFG */
48675ab5f91Slh 
48775ab5f91Slh 	if (JumboFlag == JUMBO_ENABLED) {
48875ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD2,
48975ab5f91Slh 		    VAL0 | APAD_XMT | REX_RTRY | VAL1 | DXMTFCS | RPA | VAL2);
49075ab5f91Slh 
49175ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD3,
49275ab5f91Slh 		    VAL2 | JUMBO);
49375ab5f91Slh 	} else {
49475ab5f91Slh 		/*
49575ab5f91Slh 		 * APAD_XMT: Auto Pad Transmit. When set, APAD_XMT enables
49675ab5f91Slh 		 * the automatic padding feature. Transmit frames are padded
49775ab5f91Slh 		 * to extend them to 64 bytes including FCS.
49875ab5f91Slh 		 *
49975ab5f91Slh 		 * DXMTFCS: Disable Transmit CRC. When DXMTFCS is set to 1, no
50075ab5f91Slh 		 * Transmit CRC is generated. DXMTFCS is overridden when
50175ab5f91Slh 		 * ADD_FCS and ENP bits are set in the transmit descriptor.
50275ab5f91Slh 		 *
50375ab5f91Slh 		 * ASTRIP_RCV: Auto Strip Receive. When ASTRP_RCV is set to 1,
50475ab5f91Slh 		 * the receiver automatically strips pad bytes from the
50575ab5f91Slh 		 * received message by observing the value in the length field
50675ab5f91Slh 		 * and by stripping excess bytes if this value is below the
50775ab5f91Slh 		 * minimum data size (46 bytes).
50875ab5f91Slh 		 */
50975ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD2,
51075ab5f91Slh 		    VAL0 | APAD_XMT | REX_RTRY | REX_UFLO | VAL1 | DXMTFCS
51175ab5f91Slh 		    | ASTRIP_RCV | RPA | VAL2);
51275ab5f91Slh 	}
51375ab5f91Slh 
51475ab5f91Slh 	/* Transmit Start Point setting (csr80) */
51575ab5f91Slh 	ulData = READ_REG32(pLayerPointers, Mem_Address + CTRL1);
51675ab5f91Slh 	ulData &= ~XMTSP_MASK;
51775ab5f91Slh 
51875ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CTRL1,
51975ab5f91Slh 	    ulData | XMTSP_128);
52075ab5f91Slh 	/* Disable Prom  */
52175ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD2, PROM);
52275ab5f91Slh 
52375ab5f91Slh 	mdlPHYAutoNegotiation(pLayerPointers, pMdl->External_Phy);
52475ab5f91Slh 
52575ab5f91Slh 	pMdl->IpgValue = MIN_IPG_DEFAULT;
52675ab5f91Slh 	/* Set the IPG value */
52775ab5f91Slh 	WRITE_REG16(pLayerPointers, pMdl->Mem_Address + IFS,
52875ab5f91Slh 	    pMdl->IpgValue);
52975ab5f91Slh 
53075ab5f91Slh 	/* Disable Following Interrupts. */
53175ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INTEN0,
53275ab5f91Slh 	    APINT5EN | APINT4EN | APINT3EN |
53375ab5f91Slh 	    APINT2EN | APINT1EN | APINT0EN | MIIPDTINTEN |
53475ab5f91Slh 	    MCCIINTEN | MCCINTEN | MREINTEN |
53575ab5f91Slh 	    TINTEN0 |
53675ab5f91Slh 	    SPNDINTEN | MPINTEN | SINTEN | LCINTEN);
53775ab5f91Slh 
53875ab5f91Slh 	/* Enable Following Interrupt */
53975ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INTEN0,
54075ab5f91Slh 	    VAL0 | RINTEN0);
54175ab5f91Slh 
54275ab5f91Slh 	/* Base Address of Transmit Descriptor Ring 0. */
54375ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + XMT_RING_BASE_ADDR0,
54475ab5f91Slh 	    pMdl->init_blk->TDRA);
54575ab5f91Slh 
54675ab5f91Slh 	/* Base Address of Receive Descriptor Ring. */
54775ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + RCV_RING_BASE_ADDR0,
54875ab5f91Slh 	    pMdl->init_blk->RDRA);
54975ab5f91Slh 
55075ab5f91Slh 	/* The number of descriptors in Transmit Descriptor Ring 0 */
55175ab5f91Slh 	WRITE_REG16(pLayerPointers, pMdl->Mem_Address + XMT_RING_LEN0,
55275ab5f91Slh 	    (unsigned short)pLayerPointers->pMdl->TxRingSize);
55375ab5f91Slh 
55475ab5f91Slh 	/*
55575ab5f91Slh 	 * Receive Descriptor Ring Length. All bits in this register are
55675ab5f91Slh 	 * restored to default values when the RST pin is asserted.
55775ab5f91Slh 	 */
55875ab5f91Slh 	WRITE_REG16(pLayerPointers, pMdl->Mem_Address + RCV_RING_LEN0,
55975ab5f91Slh 	    (unsigned short)pLayerPointers->pMdl->RxRingSize);
56075ab5f91Slh 
56175ab5f91Slh 	if (pLayerPointers->pMdl->IntrCoalescFlag) {
56275ab5f91Slh 		SetIntrCoalesc(pLayerPointers, B_TRUE);
56375ab5f91Slh 	}
56475ab5f91Slh 
56575ab5f91Slh 	/* Start the chip */
56675ab5f91Slh 	mdlStartChip(pLayerPointers);
56775ab5f91Slh }
56875ab5f91Slh 
56975ab5f91Slh /*
57075ab5f91Slh  * Perform the open oerations on the adapter.
57175ab5f91Slh  */
57275ab5f91Slh void
mdlOpen(struct LayerPointers * pLayerPointers)57375ab5f91Slh mdlOpen(struct LayerPointers *pLayerPointers)
57475ab5f91Slh {
57575ab5f91Slh 	int i, sum;
57675ab5f91Slh 	struct mdl *pMdl = pLayerPointers->pMdl;
57775ab5f91Slh 
57875ab5f91Slh 	/* Get Mac address */
57975ab5f91Slh 	sum = 0;
58075ab5f91Slh 	for (i = 0; i < 6; i++) {
58175ab5f91Slh 		pMdl->Mac[i] = READ_REG8(pLayerPointers,
58275ab5f91Slh 		    pMdl->Mem_Address + PADR + i);
58375ab5f91Slh 		sum += pMdl->Mac[i];
58475ab5f91Slh 	}
58575ab5f91Slh 	if (sum == 0) {
58675ab5f91Slh 		for (i = 0; i < 6; i++) {
58775ab5f91Slh 			pMdl->Mac[i] = 0;
58875ab5f91Slh 		}
58975ab5f91Slh 	}
59075ab5f91Slh 
59175ab5f91Slh 	/* Initialize the hardware */
59275ab5f91Slh 	mdlClearHWConfig(pLayerPointers);
59375ab5f91Slh 	mdlGetPHYID(pLayerPointers);
59475ab5f91Slh 
59575ab5f91Slh }
59675ab5f91Slh 
59775ab5f91Slh void
mdlGetMacAddress(struct LayerPointers * pLayerPointers,unsigned char * macAddress)59875ab5f91Slh mdlGetMacAddress(struct LayerPointers *pLayerPointers,
59975ab5f91Slh     unsigned char *macAddress)
60075ab5f91Slh {
60175ab5f91Slh 	struct mdl *pMdl = pLayerPointers->pMdl;
60275ab5f91Slh 	int i;
60375ab5f91Slh 
60475ab5f91Slh 	for (i = 0; i < 6; i++) {
60575ab5f91Slh 		macAddress[i] =	pMdl->Mac[i] = READ_REG8(pLayerPointers,
60675ab5f91Slh 		    pMdl->Mem_Address + PADR + i);
60775ab5f91Slh 	}
60875ab5f91Slh 
60975ab5f91Slh }
61075ab5f91Slh 
61175ab5f91Slh 
61275ab5f91Slh void
mdlSetMacAddress(struct LayerPointers * pLayerPointers,unsigned char * macAddress)61375ab5f91Slh mdlSetMacAddress(struct LayerPointers *pLayerPointers,
61475ab5f91Slh     unsigned char *macAddress)
61575ab5f91Slh {
61675ab5f91Slh 	int i;
61775ab5f91Slh 	struct mdl *pMdl = 0;
61875ab5f91Slh 
61975ab5f91Slh 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
62075ab5f91Slh 
62175ab5f91Slh 	pMdl->Mac[0] = macAddress[0];
62275ab5f91Slh 	pMdl->Mac[1] = macAddress[1];
62375ab5f91Slh 	pMdl->Mac[2] = macAddress[2];
62475ab5f91Slh 	pMdl->Mac[3] = macAddress[3];
62575ab5f91Slh 	pMdl->Mac[4] = macAddress[4];
62675ab5f91Slh 	pMdl->Mac[5] = macAddress[5];
62775ab5f91Slh 
62875ab5f91Slh 	/*
62975ab5f91Slh 	 * MAC Address Setup:
63075ab5f91Slh 	 *	MAC Physical Address register. All bits in this register are
63175ab5f91Slh 	 *	restored to default values when the RST pin is asserted.
63275ab5f91Slh 	 */
63375ab5f91Slh 	for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++) {
63475ab5f91Slh 		WRITE_REG8(pLayerPointers, pMdl->Mem_Address + PADR + i,
63575ab5f91Slh 		    pMdl->Mac[i]);
63675ab5f91Slh 	}
63775ab5f91Slh }
63875ab5f91Slh 
63975ab5f91Slh /*
64075ab5f91Slh  * This array is filled with the size of the memory required for
64175ab5f91Slh  * allocating purposes.
64275ab5f91Slh  */
64375ab5f91Slh static void
mdlRequestResources(ULONG * mem_req_array)64475ab5f91Slh mdlRequestResources(ULONG *mem_req_array)
64575ab5f91Slh {
64675ab5f91Slh 	/* 1) For mdl structure */
64775ab5f91Slh 	*mem_req_array = VIRTUAL;		/* Type */
64875ab5f91Slh 	*(++mem_req_array) = sizeof (struct mdl); /* Size */
64975ab5f91Slh 
65075ab5f91Slh 	/* 2) For PMR PtrList array (PMR_ptrList) */
65175ab5f91Slh 	*(++mem_req_array) = VIRTUAL;		/* Type */
65275ab5f91Slh 	/* Size */
65375ab5f91Slh 	*(++mem_req_array) = sizeof (unsigned int) * (MAX_ALLOWED_PATTERNS + 2);
65475ab5f91Slh 
65575ab5f91Slh 	/* 3) For PMR Pattern List array (PatternList) */
65675ab5f91Slh 	*(++mem_req_array) = VIRTUAL;			/* Type */
65775ab5f91Slh 	/* Size */
65875ab5f91Slh 	*(++mem_req_array) = sizeof (unsigned char) * (MAX_PATTERNS + 2);
65975ab5f91Slh 
66075ab5f91Slh 	/* 4) For pmr PatternLength array (PatternLength) */
66175ab5f91Slh 	*(++mem_req_array) = VIRTUAL;			/* Type */
66275ab5f91Slh 	/* Size */
66375ab5f91Slh 	*(++mem_req_array) = sizeof (unsigned int) * (MAX_ALLOWED_PATTERNS + 2);
66475ab5f91Slh 
66575ab5f91Slh 	/*
66675ab5f91Slh 	 * 5) For the init_block (init_blk)
66775ab5f91Slh 	 */
66875ab5f91Slh 	*(++mem_req_array) = VIRTUAL;
66975ab5f91Slh 	*(++mem_req_array) = sizeof (struct init_block);
67075ab5f91Slh 
67175ab5f91Slh 	*(++mem_req_array) = 0;
67275ab5f91Slh 	mem_req_array++;
67375ab5f91Slh }
67475ab5f91Slh 
67575ab5f91Slh 
67675ab5f91Slh /*
67775ab5f91Slh  *	Purpose  :
67875ab5f91Slh  *		This array contains the details of the allocated memory. The
67975ab5f91Slh  *		pointers are taken from the respective locations in the array &
68075ab5f91Slh  *		assigned appropriately to the respective structures.
68175ab5f91Slh  *
68275ab5f91Slh  *	Arguments :
68375ab5f91Slh  *		pLayerPointers
68475ab5f91Slh  *			Pointer to the adapter structure.
68575ab5f91Slh  *		pmem_set_array
68675ab5f91Slh  *			Pointer to the array that holds the data after required
68775ab5f91Slh  *			allocating memory.
68875ab5f91Slh  */
68975ab5f91Slh static void
mdlSetResources(struct LayerPointers * pLayerPointers,ULONG * pmem_set_array)69075ab5f91Slh mdlSetResources(struct LayerPointers *pLayerPointers, ULONG *pmem_set_array)
69175ab5f91Slh {
69275ab5f91Slh 	struct mdl *pMdl = 0;
69375ab5f91Slh 
69475ab5f91Slh 	/* 1) For mdl structure */
69575ab5f91Slh 	pmem_set_array++;	/* Type */
69675ab5f91Slh 	pmem_set_array++;	/* Size */
69775ab5f91Slh 	pLayerPointers->pMdl = (struct mdl *)(*pmem_set_array);
69875ab5f91Slh 
69975ab5f91Slh 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
70075ab5f91Slh 
70175ab5f91Slh 	pMdl->RxRingLenBits = RX_RING_LEN_BITS;
70275ab5f91Slh 	pMdl->TxRingLenBits = TX_RING_LEN_BITS;
70375ab5f91Slh 	pMdl->TxRingSize = TX_RING_SIZE;
70475ab5f91Slh 	pMdl->RxRingSize = RX_RING_SIZE;
70575ab5f91Slh 
70675ab5f91Slh 	/*
70775ab5f91Slh 	 * Default values that would be used if it does not enable
70875ab5f91Slh 	 * enable dynamic ipg.
70975ab5f91Slh 	 */
71075ab5f91Slh 
71175ab5f91Slh 	/*  2) Set the pointers to the PMR Pointer List */
71275ab5f91Slh 	pmem_set_array++;	/* Type */
71375ab5f91Slh 	pmem_set_array++;	/* Size */
71475ab5f91Slh 	pmem_set_array++;	/* Virtual Addr of PtrList */
71575ab5f91Slh 	pMdl->PMR_PtrList = (unsigned int *)(*pmem_set_array);
71675ab5f91Slh 
71775ab5f91Slh 	/* 3) Set the pointers to the PMR Pattern List */
71875ab5f91Slh 	pmem_set_array++;	/* Type */
71975ab5f91Slh 	pmem_set_array++;	/* Size */
72075ab5f91Slh 	pmem_set_array++;	/* Virtual Addr of PatternList */
72175ab5f91Slh 	pMdl->PatternList = (unsigned char *)(*pmem_set_array);
72275ab5f91Slh 
72375ab5f91Slh 	/* 4) Set the pointers to the PMR Pattern Length */
72475ab5f91Slh 	pmem_set_array++;	/* Type */
72575ab5f91Slh 	pmem_set_array++;	/* Size */
72675ab5f91Slh 	pmem_set_array++;	/* Virtual Addr of PatternLength */
72775ab5f91Slh 	pMdl->PatternLength = (unsigned int *)(*pmem_set_array);
72875ab5f91Slh 
72975ab5f91Slh 	/* 5) Set the pointers to the init block */
73075ab5f91Slh 	pmem_set_array++;	/* Type  */
73175ab5f91Slh 	pmem_set_array++;	/* Size */
73275ab5f91Slh 	pmem_set_array++;	/* Virtual Addr of init_block */
73375ab5f91Slh 	pMdl->init_blk = (struct init_block *)(*pmem_set_array);
73475ab5f91Slh 
73575ab5f91Slh 	pMdl->init_blk->TLEN = pMdl->TxRingLenBits;
73675ab5f91Slh 	pMdl->init_blk->RLEN = pMdl->RxRingLenBits;
73775ab5f91Slh 
73875ab5f91Slh 	pmem_set_array++;
73975ab5f91Slh 
74075ab5f91Slh 	*pmem_set_array = 0;
74175ab5f91Slh }
74275ab5f91Slh 
74375ab5f91Slh /*
74475ab5f91Slh  *	Purpose:
74575ab5f91Slh  *		This array is filled with the size of the structure & its
74675ab5f91Slh  *		pointer for freeing purposes.
74775ab5f91Slh  *
74875ab5f91Slh  *	Arguments:
74975ab5f91Slh  *		pLayerPointers
75075ab5f91Slh  *			Pointer to the adapter structure.
75175ab5f91Slh  *		mem_free_array
75275ab5f91Slh  *			Pointer to the array that holds the data required for
75375ab5f91Slh  *			freeing.
75475ab5f91Slh  */
75575ab5f91Slh static void
mdlFreeResources(struct LayerPointers * pLayerPointers,ULONG * pmem_free_array)75675ab5f91Slh mdlFreeResources(struct LayerPointers *pLayerPointers, ULONG *pmem_free_array)
75775ab5f91Slh {
75875ab5f91Slh 	struct mdl *pMdl = 0;
75975ab5f91Slh 
76075ab5f91Slh 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
76175ab5f91Slh 
76275ab5f91Slh 	/* 1) For mdl structure */
76375ab5f91Slh 	*(pmem_free_array) = VIRTUAL;		/* Type */
76475ab5f91Slh 	*(++pmem_free_array) = sizeof (struct mdl); /* Size */
76575ab5f91Slh 	*(++pmem_free_array) = (ULONG)pMdl;  /* VA */
76675ab5f91Slh 
76775ab5f91Slh 	/* 2) For ptr list */
76875ab5f91Slh 	*(++pmem_free_array) = VIRTUAL;		/* Type */
76975ab5f91Slh 	*(++pmem_free_array) =  sizeof (unsigned int)
77075ab5f91Slh 	    * (MAX_ALLOWED_PATTERNS + 2);  /* Size */
77175ab5f91Slh 	*(++pmem_free_array) = (ULONG)pMdl->PMR_PtrList;  /* VA */
77275ab5f91Slh 
77375ab5f91Slh 	/* 3) For pattern list */
77475ab5f91Slh 	*(++pmem_free_array) = VIRTUAL;		/* Type	 */
77575ab5f91Slh 	/* Size */
77675ab5f91Slh 	*(++pmem_free_array) =  sizeof (unsigned char) * (MAX_PATTERNS + 2);
77775ab5f91Slh 	*(++pmem_free_array) = (ULONG)pMdl->PatternList;  /* VA */
77875ab5f91Slh 
77975ab5f91Slh 	/* 4) For pattern length */
78075ab5f91Slh 	*(++pmem_free_array) = VIRTUAL;				/* Type */
78175ab5f91Slh 	*(++pmem_free_array) =  sizeof (unsigned int)
78275ab5f91Slh 	    * (MAX_ALLOWED_PATTERNS + 2);			/* Size */
78375ab5f91Slh 	*(++pmem_free_array) = (ULONG)pMdl->PatternLength;	/* VA */
78475ab5f91Slh 
78575ab5f91Slh 	/* 5) For init_blk structure */
78675ab5f91Slh 	*(++pmem_free_array) = VIRTUAL;				/* Type */
78775ab5f91Slh 	/* Size */
78875ab5f91Slh 	*(++pmem_free_array) = sizeof (struct init_block);
78975ab5f91Slh 	*(++pmem_free_array) = (ULONG)pMdl->init_blk;		/* VA */
79075ab5f91Slh 
79175ab5f91Slh 	*(++pmem_free_array) = 0;
79275ab5f91Slh }
79375ab5f91Slh 
79475ab5f91Slh void
mdlStartChip(struct LayerPointers * pLayerPointers)79575ab5f91Slh mdlStartChip(struct LayerPointers *pLayerPointers)
79675ab5f91Slh {
79775ab5f91Slh 	/* Enable Receiver */
79875ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
79975ab5f91Slh 	    VAL2 | RDMD0);
80075ab5f91Slh 
80175ab5f91Slh 	/* Enable Interrupt and Start processing descriptor, Rx and Tx */
80275ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
80375ab5f91Slh 	    VAL0 | INTREN | RUN);
80475ab5f91Slh }
80575ab5f91Slh 
80675ab5f91Slh /*
80775ab5f91Slh  *	Stops the chip.
80875ab5f91Slh  */
80975ab5f91Slh void
mdlStopChip(struct LayerPointers * pLayerPointers)81075ab5f91Slh mdlStopChip(struct LayerPointers *pLayerPointers)
81175ab5f91Slh {
81275ab5f91Slh 	int nINT0;
81375ab5f91Slh 	struct mdl *pMdl = 0;
81475ab5f91Slh 
81575ab5f91Slh 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
81675ab5f91Slh 
81775ab5f91Slh 	/* Disable interrupt */
81875ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD0, INTREN);
81975ab5f91Slh 
82075ab5f91Slh 	/* Clear interrupt status */
82175ab5f91Slh 	nINT0 = READ_REG32(pLayerPointers, pMdl->Mem_Address + INT0);
82275ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INT0, nINT0);
82375ab5f91Slh 
82475ab5f91Slh 	/*
82575ab5f91Slh 	 * Setting the RUN bit enables the controller to start processing
82675ab5f91Slh 	 * descriptors and transmitting and  receiving packets. Clearing
82775ab5f91Slh 	 * the RUN bit to 0 abruptly disables the transmitter, receiver, and
82875ab5f91Slh 	 * descriptor processing logic, possibly while a frame is being
82975ab5f91Slh 	 * transmitted or received.
83075ab5f91Slh 	 * The act of changing the RUN bit from 1 to 0 causes the following
83175ab5f91Slh 	 * bits to be reset to 0: TX_SPND, RX_SPND, TX_FAST_SPND, RX_FAST_SPND,
83275ab5f91Slh 	 * RDMD, all TDMD bits, RINT, all TINT bits, MPINT, and SPNDINT.
83375ab5f91Slh 	 */
83475ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD0, RUN);
83575ab5f91Slh }
83675ab5f91Slh 
83775ab5f91Slh /*
83875ab5f91Slh  *	Enables the interrupt.
83975ab5f91Slh  */
84075ab5f91Slh void
mdlEnableInterrupt(struct LayerPointers * pLayerPointers)84175ab5f91Slh mdlEnableInterrupt(struct LayerPointers *pLayerPointers)
84275ab5f91Slh {
84375ab5f91Slh 	/*
84475ab5f91Slh 	 * Interrupt Enable Bit:
84575ab5f91Slh 	 * This bit allows INTA to be asserted if any bit in the interrupt
84675ab5f91Slh 	 * register is set. If INTREN is cleared to 0, INTA will not be
84775ab5f91Slh 	 * asserted, regardless of the state of the interrupt register.
84875ab5f91Slh 	 */
84975ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
85075ab5f91Slh 	    VAL0 | INTREN);
85175ab5f91Slh }
85275ab5f91Slh 
85375ab5f91Slh #ifdef AMD8111S_DEBUG
85475ab5f91Slh static void
mdlClearInterrupt(struct LayerPointers * pLayerPointers)85575ab5f91Slh mdlClearInterrupt(struct LayerPointers *pLayerPointers)
85675ab5f91Slh {
85775ab5f91Slh 	unsigned int nINT0;
85875ab5f91Slh 	struct mdl *pMdl = 0;
85975ab5f91Slh 
86075ab5f91Slh 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
86175ab5f91Slh 
86275ab5f91Slh 	/* Clear interrupt status */
86375ab5f91Slh 	nINT0 = READ_REG32(pLayerPointers, pMdl->Mem_Address + INT0);
86475ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INT0, nINT0);
86575ab5f91Slh 
86675ab5f91Slh }
86775ab5f91Slh #endif
86875ab5f91Slh 
86975ab5f91Slh /*
87075ab5f91Slh  *	Disables the interrupt.
87175ab5f91Slh  */
87275ab5f91Slh void
mdlDisableInterrupt(struct LayerPointers * pLayerPointers)87375ab5f91Slh mdlDisableInterrupt(struct LayerPointers *pLayerPointers)
87475ab5f91Slh {
87575ab5f91Slh 	/* Disable interrupt */
87675ab5f91Slh 	WRITE_REG32(pLayerPointers,
87775ab5f91Slh 	    pLayerPointers->pMdl->Mem_Address + CMD0, INTREN);
87875ab5f91Slh }
87975ab5f91Slh 
88075ab5f91Slh /*
88175ab5f91Slh  *	Reads the link status
88275ab5f91Slh  */
88375ab5f91Slh int
mdlReadLink(struct LayerPointers * pLayerPointers)88475ab5f91Slh mdlReadLink(struct LayerPointers *pLayerPointers)
88575ab5f91Slh {
88675ab5f91Slh 	unsigned int link_status = 0;
88775ab5f91Slh 
88875ab5f91Slh 	link_status = READ_REG32(pLayerPointers,
88975ab5f91Slh 	    pLayerPointers->pMdl->Mem_Address + STAT0);
89075ab5f91Slh 
89175ab5f91Slh 	if ((link_status & LINK_STAT)) {
89275ab5f91Slh 		return (LINK_UP);
89375ab5f91Slh 	} else {
89475ab5f91Slh 		return (LINK_DOWN);
89575ab5f91Slh 	}
89675ab5f91Slh }
89775ab5f91Slh 
89875ab5f91Slh /*
89975ab5f91Slh  *	Purpose  :
90075ab5f91Slh  *		Adds the wakeup pattern given by the upper layer.
90175ab5f91Slh  *
90275ab5f91Slh  *	Arguments :
90375ab5f91Slh  *		pLayerPointers
90475ab5f91Slh  *			Pointer to the Adapter structure.
90575ab5f91Slh  *		PatternMask
90675ab5f91Slh  *			The mask for the pattern to be added.
90775ab5f91Slh  *		Pattern
90875ab5f91Slh  *			The Pattern to be added.
90975ab5f91Slh  *		InfoBuffer_MaskSize
91075ab5f91Slh  *			The mask size as specified in the Information Buffer.
91175ab5f91Slh  *		PatternSize
91275ab5f91Slh  *			The PatternSize as specified in the Information Buffer.
91375ab5f91Slh  */
91475ab5f91Slh static void
mdlAddWakeUpPattern(struct LayerPointers * pLayerPointers,unsigned char * PatternMask,unsigned char * Pattern,unsigned long InfoBuffer_MaskSize,unsigned long PatternSize,int * retval)91575ab5f91Slh mdlAddWakeUpPattern(struct LayerPointers *pLayerPointers,
91675ab5f91Slh     unsigned char *PatternMask, unsigned char *Pattern,
91775ab5f91Slh     unsigned long InfoBuffer_MaskSize, unsigned long PatternSize, int *retval)
91875ab5f91Slh {
91975ab5f91Slh 	unsigned long MaskSize;
92075ab5f91Slh 	unsigned long ReqSize;
92175ab5f91Slh 	unsigned char byteData = 0, tmpData;
92275ab5f91Slh 	unsigned char Skip = 0;
92375ab5f91Slh 	unsigned int i = 0, flag = 1, count = 1;
92475ab5f91Slh 	unsigned int j;
92575ab5f91Slh 	int PatternOffset, SearchForStartOfPattern = 1;
92675ab5f91Slh 	struct mdl *pMdl = 0;
92775ab5f91Slh 
92875ab5f91Slh 	pMdl = pLayerPointers->pMdl;
92975ab5f91Slh 
93075ab5f91Slh 	if (pMdl->TotalPatterns >= MAX_ALLOWED_PATTERNS) {
93175ab5f91Slh 		*retval = -1;
93275ab5f91Slh 		return;
93375ab5f91Slh 	}
93475ab5f91Slh 
93575ab5f91Slh 	MaskSize = PatternSize/4 + (PatternSize%4 ? 1 : 0);
93675ab5f91Slh 
93775ab5f91Slh 	ReqSize = PatternSize + MaskSize;
93875ab5f91Slh 	if (((PatternSize+MaskSize)%5) != 0)
93975ab5f91Slh 		ReqSize +=  5 - ((PatternSize+MaskSize)%5);
94075ab5f91Slh 
94175ab5f91Slh 	if (ReqSize >
94275ab5f91Slh 	    (unsigned long)(MAX_PATTERNS - pMdl->PatternList_FreeIndex)) {
94375ab5f91Slh 		*retval = -1;
94475ab5f91Slh 		return;
94575ab5f91Slh 	}
94675ab5f91Slh 
94775ab5f91Slh 	if (InfoBuffer_MaskSize != PatternSize/8 + (PatternSize%8 ? 1 : 0)) {
94875ab5f91Slh 		*retval = -1;
94975ab5f91Slh 		return;
95075ab5f91Slh 	}
95175ab5f91Slh 
95275ab5f91Slh 	i = pMdl->PatternList_FreeIndex;
95375ab5f91Slh 
95475ab5f91Slh 	pMdl->PMR_PtrList[pMdl->TotalPatterns] = i;
95575ab5f91Slh 
95675ab5f91Slh 	pMdl->PatternLength[pMdl->TotalPatterns] = (unsigned int)PatternSize;
95775ab5f91Slh 
95875ab5f91Slh 	while (i < (pMdl->PatternList_FreeIndex + PatternSize + MaskSize)) {
95975ab5f91Slh 		if (flag) {
96075ab5f91Slh 			byteData = *PatternMask;
96175ab5f91Slh 			pMdl->PatternList[i++] =
96275ab5f91Slh 			    (unsigned int)((byteData & 0x0F) | (Skip<< 4));
96375ab5f91Slh 			flag = 0;
96475ab5f91Slh 		} else {
96575ab5f91Slh 			pMdl->PatternList[i++] = (unsigned int)
96675ab5f91Slh 			    (((unsigned)(byteData & 0xF0) >> 4) | (Skip << 4));
96775ab5f91Slh 			PatternMask++;
96875ab5f91Slh 			flag = 1;
96975ab5f91Slh 		}
97075ab5f91Slh 		count = 1;
97175ab5f91Slh 		while ((count < 5) && (i <
97275ab5f91Slh 		    pMdl->PatternList_FreeIndex + PatternSize + MaskSize)) {
97375ab5f91Slh 			tmpData = *Pattern;
97475ab5f91Slh 			Pattern++;
97575ab5f91Slh 			pMdl->PatternList[i++] = tmpData;
97675ab5f91Slh 			count++;
97775ab5f91Slh 		}
97875ab5f91Slh 	}
97975ab5f91Slh 
98075ab5f91Slh 	/* Filling up the extra byte blocks in the row to 0. */
98175ab5f91Slh 	for (i = (pMdl->PatternList_FreeIndex + PatternSize + MaskSize);
98275ab5f91Slh 	    i < (pMdl->PatternList_FreeIndex + ReqSize); i++)
98375ab5f91Slh 		pMdl->PatternList[i] = 0;
98475ab5f91Slh 
98575ab5f91Slh 	/* Set the EOP bit for the last mask!!! */
98675ab5f91Slh 	pMdl->PatternList[pMdl->PatternList_FreeIndex + ReqSize - 5] |= 0x80;
98775ab5f91Slh 
98875ab5f91Slh 	for (j = 0; j < 8; j++) {
98975ab5f91Slh 		pMdl->tmpPtrArray[j] = 0;
99075ab5f91Slh 	}
99175ab5f91Slh 
99275ab5f91Slh 	/* Zeroing the skip value of all the pattern masks */
99375ab5f91Slh 	j = 0;
99475ab5f91Slh 	while (j < (pMdl->PatternList_FreeIndex + ReqSize)) {
99575ab5f91Slh 		pMdl->PatternList[j] &= 0x8f;
99675ab5f91Slh 		j += 5;
99775ab5f91Slh 	}
99875ab5f91Slh 
99975ab5f91Slh 	/*
100075ab5f91Slh 	 * Scan the whole array & update the start offset of the pattern in the
100175ab5f91Slh 	 * PMR and update the skip value.
100275ab5f91Slh 	 */
100375ab5f91Slh 	j = 0;
100475ab5f91Slh 	i = 0;
100575ab5f91Slh 
100675ab5f91Slh 	PatternOffset = 1;
100775ab5f91Slh 	Skip = 0;
100875ab5f91Slh 
100975ab5f91Slh 	while (j < (pMdl->PatternList_FreeIndex + ReqSize)) {
101075ab5f91Slh 
101175ab5f91Slh 		if (pMdl->PatternList[j] & 0x0f) {
101275ab5f91Slh 			PatternOffset ++;
101375ab5f91Slh 			if (SearchForStartOfPattern == 1) {
101475ab5f91Slh 				SearchForStartOfPattern = 0;
101575ab5f91Slh 				pMdl->tmpPtrArray[i++] = PatternOffset;
101675ab5f91Slh 			} else if (pMdl->PatternList[j] & 0x80) {
101775ab5f91Slh 				SearchForStartOfPattern = 1;
101875ab5f91Slh 			}
101975ab5f91Slh 			pMdl->PatternList[j] |= (Skip << 4);
102075ab5f91Slh 			Skip = 0;
102175ab5f91Slh 		} else {
102275ab5f91Slh 			Skip++;
102375ab5f91Slh 		}
102475ab5f91Slh 		j += 5;
102575ab5f91Slh 	}
102675ab5f91Slh 
102775ab5f91Slh 	/* valid pattern.. so update the house keeping info. */
102875ab5f91Slh 	pMdl->PatternList_FreeIndex += (unsigned short)ReqSize;
102975ab5f91Slh 	pMdl->TotalPatterns++;
103075ab5f91Slh 
103175ab5f91Slh 	*retval = 0;
103275ab5f91Slh }
103375ab5f91Slh 
103475ab5f91Slh /*
103575ab5f91Slh  *	Purpose:
103675ab5f91Slh  *		Removes the specified wakeup pattern.
103775ab5f91Slh  *
103875ab5f91Slh  *	Arguments :
103975ab5f91Slh  *		pLayerPointers
104075ab5f91Slh  *			Pointer to the Adapter structure.
104175ab5f91Slh  *		Pattern
104275ab5f91Slh  *			The Pattern to be added.
104375ab5f91Slh  *		PatternSize
104475ab5f91Slh  *			The PatternSize as specified in the Information Buffer.
104575ab5f91Slh  */
104675ab5f91Slh static void
mdlRemoveWakeUpPattern(struct LayerPointers * pLayerPointers,unsigned char * Pattern,unsigned long PatternSize,int * retval)104775ab5f91Slh mdlRemoveWakeUpPattern(struct LayerPointers *pLayerPointers,
104875ab5f91Slh     unsigned char *Pattern, unsigned long PatternSize, int *retval)
104975ab5f91Slh {
105075ab5f91Slh 	unsigned long ReqSize, MaskSize;
105175ab5f91Slh 	unsigned char tmpData;
105275ab5f91Slh 	unsigned long Data;
105375ab5f91Slh 	unsigned short Data1, Data2, Data3, Data4, Data5, Data6, Data7, Data8;
105475ab5f91Slh 	int PatternMismatch = 0;
105575ab5f91Slh 	int count, StartIndex, index = 0;
105675ab5f91Slh 	unsigned int i, j;
105775ab5f91Slh 	unsigned char Skip = 0;
105875ab5f91Slh 	struct mdl *pMdl = 0;
105975ab5f91Slh 	int PatternOffset, SearchForStartOfPattern = 1;
106075ab5f91Slh 	unsigned long tmpPtrArray[8];
106175ab5f91Slh 	int offset;
106275ab5f91Slh 
106375ab5f91Slh 	Data1 = Data2 = Data3 = Data4 = Data5 = Data6 = Data7 = Data8 = 0;
106475ab5f91Slh 
106575ab5f91Slh 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
106675ab5f91Slh 
106775ab5f91Slh 	/* Find the pattern to be removed. */
106875ab5f91Slh 	if (pMdl->TotalPatterns == 0) {
106975ab5f91Slh 		*retval = -1;
107075ab5f91Slh 		return;
107175ab5f91Slh 	}
107275ab5f91Slh 
107375ab5f91Slh 	MaskSize = PatternSize/4 + (PatternSize%4 ? 1 : 0);
107475ab5f91Slh 
107575ab5f91Slh 	ReqSize = PatternSize + MaskSize;
107675ab5f91Slh 	if (((PatternSize+MaskSize)%5) != 0)
107775ab5f91Slh 		ReqSize +=  5 - ((PatternSize+MaskSize)%5);
107875ab5f91Slh 
107975ab5f91Slh 	count = pMdl->TotalPatterns;
108075ab5f91Slh 
108175ab5f91Slh 	while (count--) {
108275ab5f91Slh 		PatternMismatch = 0;
108375ab5f91Slh 		StartIndex = pMdl->PMR_PtrList[index];
108475ab5f91Slh 
108575ab5f91Slh 		if (pMdl->PatternLength[index] != PatternSize) {
108675ab5f91Slh 			index++;
108775ab5f91Slh 			PatternMismatch = 1;
108875ab5f91Slh 			continue;
108975ab5f91Slh 		}
109075ab5f91Slh 
109175ab5f91Slh 		for (i = StartIndex; i < (StartIndex+ReqSize); i++) {
109275ab5f91Slh 			if (!(i%5))
109375ab5f91Slh 				i++;
109475ab5f91Slh 
109575ab5f91Slh 			tmpData = *Pattern;
109675ab5f91Slh 			if (pMdl->PatternList[i] != tmpData) {
109775ab5f91Slh 				PatternMismatch = 1;
109875ab5f91Slh 				break;
109975ab5f91Slh 			}
110075ab5f91Slh 			Pattern++;
110175ab5f91Slh 		}
110275ab5f91Slh 
110375ab5f91Slh 		if (PatternMismatch == 0) {
110475ab5f91Slh 			i = StartIndex + ReqSize;
110575ab5f91Slh 
110675ab5f91Slh 			/* Pattern found remove it from the arrays */
110775ab5f91Slh 			while (i < pMdl->PatternList_FreeIndex) {
110875ab5f91Slh 				pMdl->PatternList[StartIndex] =
110975ab5f91Slh 				    pMdl->PatternList[i];
111075ab5f91Slh 				i++;
111175ab5f91Slh 				StartIndex++;
111275ab5f91Slh 			}
111375ab5f91Slh 
111475ab5f91Slh 			pMdl->PatternList_FreeIndex =
111575ab5f91Slh 			    (unsigned short)(StartIndex);
111675ab5f91Slh 
111775ab5f91Slh 			while (StartIndex < MAX_PATTERNS)
111875ab5f91Slh 				pMdl->PatternList[StartIndex++] = 0;
111975ab5f91Slh 
112075ab5f91Slh 			while (index < (int)pMdl->TotalPatterns) {
112175ab5f91Slh 				pMdl->PMR_PtrList[index] =
112275ab5f91Slh 				    pMdl->PMR_PtrList[index+1] - ReqSize;
112375ab5f91Slh 
112475ab5f91Slh 				pMdl->PatternLength[index] =
112575ab5f91Slh 				    pMdl->PatternLength[index+1];
112675ab5f91Slh 
112775ab5f91Slh 				index ++;
112875ab5f91Slh 			}
112975ab5f91Slh 
113075ab5f91Slh 			index--;
113175ab5f91Slh 			while (index < MAX_ALLOWED_PATTERNS) {
113275ab5f91Slh 				pMdl->PMR_PtrList[index+1] = 0;
113375ab5f91Slh 				pMdl->PatternLength[index+1] = 0;
113475ab5f91Slh 				index++;
113575ab5f91Slh 			}
113675ab5f91Slh 
113775ab5f91Slh 			break;
113875ab5f91Slh 		}
113975ab5f91Slh 		index++;
114075ab5f91Slh 	}
114175ab5f91Slh 
114275ab5f91Slh 	if (PatternMismatch) {
114375ab5f91Slh 		*retval = -1;
114475ab5f91Slh 		return;
114575ab5f91Slh 	}
114675ab5f91Slh 
114775ab5f91Slh 
114875ab5f91Slh 	for (j = 0; j < 8; j++) {
114975ab5f91Slh 		tmpPtrArray[j] = 0;
115075ab5f91Slh 	}
115175ab5f91Slh 
115275ab5f91Slh 	/* Zeroing the skip value of all the pattern masks */
115375ab5f91Slh 	j = 0;
115475ab5f91Slh 	while (j < (pMdl->PatternList_FreeIndex)) {
115575ab5f91Slh 		pMdl->PatternList[j] &= 0x8f;
115675ab5f91Slh 		j += 5;
115775ab5f91Slh 	}
115875ab5f91Slh 
115975ab5f91Slh 	/*
116075ab5f91Slh 	 * Scan the whole array & update the start offset of the pattern in the
116175ab5f91Slh 	 * PMR and update the skip value.
116275ab5f91Slh 	 */
116375ab5f91Slh 	j = 0;
116475ab5f91Slh 	i = 0;
116575ab5f91Slh 	Skip = 0;
116675ab5f91Slh 	PatternOffset = 1;
116775ab5f91Slh 
116875ab5f91Slh 	while (j < (pMdl->PatternList_FreeIndex)) {
116975ab5f91Slh 		if (pMdl->PatternList[j] & 0x0f) {
117075ab5f91Slh 
117175ab5f91Slh 			PatternOffset++;
117275ab5f91Slh 			if (SearchForStartOfPattern == 1) {
117375ab5f91Slh 				SearchForStartOfPattern = 0;
117475ab5f91Slh 				tmpPtrArray[i++] = PatternOffset;
117575ab5f91Slh 			} else if (pMdl->PatternList[j] & 0x80) {
117675ab5f91Slh 				SearchForStartOfPattern = 1;
117775ab5f91Slh 			}
117875ab5f91Slh 			pMdl->PatternList[j] |= (Skip << 4);
117975ab5f91Slh 			Skip = 0;
118075ab5f91Slh 		} else {
118175ab5f91Slh 			Skip++;
118275ab5f91Slh 		}
118375ab5f91Slh 		j += 5;
118475ab5f91Slh 	}
118575ab5f91Slh 
118675ab5f91Slh 
118775ab5f91Slh 	/* Write back the arrays to the PMR & lock the pmr */
118875ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address+CMD7, PMAT_MODE);
118975ab5f91Slh 
119075ab5f91Slh 	/* Write the data & ctrl patterns from the array to the PMR */
119175ab5f91Slh 	i = 0;
119275ab5f91Slh 
119375ab5f91Slh 	offset = 2;
119475ab5f91Slh 
119575ab5f91Slh 	while (i < MAX_PATTERNS) {
119675ab5f91Slh 		if (pMdl->PatternList[i] != 0) {
119775ab5f91Slh 			Data = pMdl->PatternList[i+3] << 24 |
119875ab5f91Slh 			    pMdl->PatternList[i+2] << 16 |
119975ab5f91Slh 			    pMdl->PatternList[i+1] << 8  |
120075ab5f91Slh 			    pMdl->PatternList[i];
120175ab5f91Slh 
120275ab5f91Slh 			WRITE_REG32(pLayerPointers,
120375ab5f91Slh 			    pMdl->Mem_Address+PMAT1, Data);
120475ab5f91Slh 
120575ab5f91Slh 			Data = (unsigned long) ((1<<30) | (offset << 16) |
120675ab5f91Slh 			    pMdl->PatternList[i+4]);
120775ab5f91Slh 
120875ab5f91Slh 			WRITE_REG32(pLayerPointers,
120975ab5f91Slh 			    pMdl->Mem_Address+PMAT0, Data);
121075ab5f91Slh 
121175ab5f91Slh 			offset++;
121275ab5f91Slh 
121375ab5f91Slh 			if (offset >= 64) {
121475ab5f91Slh 				/* PMR is full !!!! */
121575ab5f91Slh 				*retval = -1;
121675ab5f91Slh 				return;
121775ab5f91Slh 
121875ab5f91Slh 			}
121975ab5f91Slh 		}
122075ab5f91Slh 		i += 5;
122175ab5f91Slh 	}
122275ab5f91Slh 
122375ab5f91Slh 	/* Valid pattern.. so update the house keeping info. */
122475ab5f91Slh 	pMdl->TotalPatterns--;
122575ab5f91Slh 
122675ab5f91Slh 	/* Update the pointer in the PMR */
122775ab5f91Slh 	pMdl->PatternEnableBit = 0;
122875ab5f91Slh 	for (i = 0; i < pMdl->TotalPatterns; i++) {
122975ab5f91Slh 		pMdl->PatternEnableBit |= (0x0001 << i);
123075ab5f91Slh 	}
123175ab5f91Slh 
123275ab5f91Slh 	Data1 = Data2 = Data3 = Data4 = Data5 = Data6 = Data7 = Data8 = 0;
123375ab5f91Slh 
123475ab5f91Slh 	switch (pMdl->TotalPatterns) {
123575ab5f91Slh 	case 8 :
123675ab5f91Slh 		Data8 = (unsigned short)tmpPtrArray[7];
123775ab5f91Slh 		/* FALLTHROUGH */
123875ab5f91Slh 	case 7 :
123975ab5f91Slh 		Data7 = (unsigned short)tmpPtrArray[6];
124075ab5f91Slh 		/* FALLTHROUGH */
124175ab5f91Slh 	case 6 :
124275ab5f91Slh 		Data6 = (unsigned short)tmpPtrArray[5];
124375ab5f91Slh 		/* FALLTHROUGH */
124475ab5f91Slh 	case 5 :
124575ab5f91Slh 		Data5 = (unsigned short)tmpPtrArray[4];
124675ab5f91Slh 		/* FALLTHROUGH */
124775ab5f91Slh 	case 4 :
124875ab5f91Slh 		Data4 = (unsigned short)tmpPtrArray[3];
124975ab5f91Slh 		/* FALLTHROUGH */
125075ab5f91Slh 	case 3 :
125175ab5f91Slh 		Data3 = (unsigned short)tmpPtrArray[2];
125275ab5f91Slh 		/* FALLTHROUGH */
125375ab5f91Slh 	case 2 :
125475ab5f91Slh 		Data2 = (unsigned short)tmpPtrArray[1];
125575ab5f91Slh 		/* FALLTHROUGH */
125675ab5f91Slh 	case 1 :
125775ab5f91Slh 		Data1 = (unsigned short)tmpPtrArray[0];
125875ab5f91Slh 		break;
125975ab5f91Slh 	}
126075ab5f91Slh 
126175ab5f91Slh 	Data = pMdl->PatternEnableBit & 0x0f;
126275ab5f91Slh 
126375ab5f91Slh 	/* Updating the pointers 1,2,3 & 4 */
126475ab5f91Slh 	Data = (Data3 << 24 |   Data2 << 16 |   Data1 << 8  |   Data);
126575ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + PMAT1, Data);
126675ab5f91Slh 
126775ab5f91Slh 	Data = (unsigned long) ((1<<30) | Data4);
126875ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + PMAT0, Data);
126975ab5f91Slh 
127075ab5f91Slh 	/* Updating the pointers 4,5,6 & 7 */
127175ab5f91Slh 	Data = (unsigned short)((unsigned)(pMdl->PatternEnableBit & 0xf0) >> 4);
127275ab5f91Slh 
127375ab5f91Slh 	Data = (Data7 << 24 |   Data6 << 16 |   Data5 << 8  |   Data);
127475ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + PMAT1, Data);
127575ab5f91Slh 
127675ab5f91Slh 	Data = (unsigned long) ((1<<30) | (1<<16) | Data8);
127775ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + PMAT0, Data);
127875ab5f91Slh 
127975ab5f91Slh 	/* Unlock the PMR */
128075ab5f91Slh 	WRITE_REG32(pLayerPointers, pMdl->Mem_Address + CMD7, VAL0 | PMAT_MODE);
128175ab5f91Slh 
128275ab5f91Slh 	*retval = 0;
128375ab5f91Slh }
128475ab5f91Slh 
128575ab5f91Slh 
128675ab5f91Slh /*
128775ab5f91Slh  *	Checks the control register for the speed and the type of the
128875ab5f91Slh  *	network connection.
128975ab5f91Slh  */
129075ab5f91Slh void
mdlGetActiveMediaInfo(struct LayerPointers * pLayerPointers)129175ab5f91Slh mdlGetActiveMediaInfo(struct LayerPointers *pLayerPointers)
129275ab5f91Slh {
129375ab5f91Slh 
129475ab5f91Slh 	unsigned long  ulData;
129575ab5f91Slh 	struct mdl *pMdl = 0;
129675ab5f91Slh 
129775ab5f91Slh 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
129875ab5f91Slh 
129975ab5f91Slh 	ulData = READ_REG32(pLayerPointers, pMdl->Mem_Address + STAT0);
130075ab5f91Slh 
130175ab5f91Slh 	switch (ulData & SPEED_MASK) {
130275ab5f91Slh 	case SPEED_100Mbps:
130375ab5f91Slh 		pMdl->Speed = 100;
130475ab5f91Slh 		break;
130575ab5f91Slh 	case SPEED_10Mbps:
130675ab5f91Slh 		pMdl->Speed = 10;
130775ab5f91Slh 		break;
130875ab5f91Slh 	default:
130975ab5f91Slh 		pMdl->Speed = 100;
131075ab5f91Slh 		break;
131175ab5f91Slh 	}
131275ab5f91Slh 
131375ab5f91Slh 	if (ulData & FULL_DPLX) {
131475ab5f91Slh 		pMdl->FullDuplex = B_TRUE;
131575ab5f91Slh 	} else {
131675ab5f91Slh 		pMdl->FullDuplex = B_FALSE;
131775ab5f91Slh 	}
131875ab5f91Slh }
131975ab5f91Slh 
132075ab5f91Slh void
mdlChangeFilter(struct LayerPointers * pLayerPointers,unsigned long * ArrayPtr)132175ab5f91Slh mdlChangeFilter(struct LayerPointers *pLayerPointers, unsigned long  *ArrayPtr)
132275ab5f91Slh {
132375ab5f91Slh 	unsigned long *Ptr;
132475ab5f91Slh 	unsigned char *MulticastArray;
132575ab5f91Slh 	unsigned char *Pattern, *PatternMask;
132675ab5f91Slh 	unsigned int InfoBuffer_MaskSize, PatternSize;
132775ab5f91Slh 	int *retval;
132875ab5f91Slh 	int NumberOfAddress, i;
132975ab5f91Slh 	unsigned int j, CRCValue = 0;
133075ab5f91Slh 	unsigned char HashCode = 0, FilterByte = 0;
133175ab5f91Slh 	int BitMapIndex = 0;
133275ab5f91Slh 
133375ab5f91Slh 	Ptr = ArrayPtr;
133475ab5f91Slh 
133575ab5f91Slh 	while (*Ptr) {
133675ab5f91Slh 		switch (*Ptr) {
133775ab5f91Slh 		case DISABLE_BROADCAST:
133875ab5f91Slh 			mdlDisableReceiveBroadCast(pLayerPointers);
133975ab5f91Slh 			break;
134075ab5f91Slh 
134175ab5f91Slh 		case ENABLE_BROADCAST:
134275ab5f91Slh 			mdlReceiveBroadCast(pLayerPointers);
134375ab5f91Slh 			break;
134475ab5f91Slh 
134575ab5f91Slh 		case ENABLE_ALL_MULTICAST:
134675ab5f91Slh 			for (i = 0; i < 8; i++) {
134775ab5f91Slh 				pLayerPointers->pMdl->init_blk->LADRF[i] = 0xff;
134875ab5f91Slh 			}
134975ab5f91Slh 			WRITE_REG64(pLayerPointers,
135075ab5f91Slh 			    (unsigned long)pLayerPointers->pMdl
135175ab5f91Slh 			    ->Mem_Address + LADRF1,
135275ab5f91Slh 			    (char *)pLayerPointers->pMdl->init_blk->LADRF);
135375ab5f91Slh 			break;
135475ab5f91Slh 
135575ab5f91Slh 		case DISABLE_ALL_MULTICAST:
135675ab5f91Slh 			if (pLayerPointers->pMdl->EnableMulticast == 1) {
135775ab5f91Slh 				for (i = 0; i < 8; i++) {
135875ab5f91Slh 					pLayerPointers->pMdl->init_blk
135975ab5f91Slh 					    ->LADRF[i] =
136075ab5f91Slh 					    pLayerPointers->pMdl->TempLADRF[i];
136175ab5f91Slh 				}
136275ab5f91Slh 			}
136375ab5f91Slh 
136475ab5f91Slh 			WRITE_REG64(pLayerPointers,
136575ab5f91Slh 			    (unsigned long)pLayerPointers->pMdl->Mem_Address
136675ab5f91Slh 			    + LADRF1,
136775ab5f91Slh 			    (char *)pLayerPointers->pMdl->init_blk->LADRF);
136875ab5f91Slh 			break;
136975ab5f91Slh 
137075ab5f91Slh 
137175ab5f91Slh 		case ADD_MULTICAST:
137275ab5f91Slh 			NumberOfAddress = *(++Ptr);
137375ab5f91Slh 			MulticastArray = (unsigned char *)(*(++Ptr));
137475ab5f91Slh 			mdlAddMulticastAddresses(pLayerPointers,
137575ab5f91Slh 			    NumberOfAddress, MulticastArray);
137675ab5f91Slh 			break;
137775ab5f91Slh 
137875ab5f91Slh 
137975ab5f91Slh 		case ENABLE_MULTICAST:
138075ab5f91Slh 			for (i = 0; i < 8; i++) {
138175ab5f91Slh 				pLayerPointers->pMdl->init_blk->LADRF[i]  =
138275ab5f91Slh 				    pLayerPointers->pMdl->TempLADRF[i];
138375ab5f91Slh 			}
138475ab5f91Slh 			pLayerPointers->pMdl->EnableMulticast = 1;
138575ab5f91Slh 
138675ab5f91Slh 			WRITE_REG64(pLayerPointers,
138775ab5f91Slh 			    (unsigned long)pLayerPointers->pMdl->Mem_Address
138875ab5f91Slh 			    + LADRF1,
138975ab5f91Slh 			    (char *)pLayerPointers->pMdl->init_blk->LADRF);
139075ab5f91Slh 			break;
139175ab5f91Slh 
139275ab5f91Slh 		case DISABLE_MULTICAST:
139375ab5f91Slh 			for (i = 0; i < 8; i++) {
139475ab5f91Slh 				pLayerPointers->pMdl->init_blk->LADRF[i] = 0;
139575ab5f91Slh 			}
139675ab5f91Slh 
139775ab5f91Slh 			pLayerPointers->pMdl->EnableMulticast = 0;
139875ab5f91Slh 
139975ab5f91Slh 			for (BitMapIndex = 0; BitMapIndex <
140075ab5f91Slh 			    MULTICAST_BITMAP_ARRAY_SIZE; BitMapIndex++)
140175ab5f91Slh 				pLayerPointers->pMdl->MulticastBitMapArray
140275ab5f91Slh 				    [BitMapIndex] = 0;
140375ab5f91Slh 			WRITE_REG64(pLayerPointers,
140475ab5f91Slh 			    (unsigned long)pLayerPointers->pMdl->Mem_Address
140575ab5f91Slh 			    + LADRF1,
140675ab5f91Slh 			    (char *)pLayerPointers->pMdl->init_blk->LADRF);
140775ab5f91Slh 			break;
140875ab5f91Slh 
140975ab5f91Slh 
141075ab5f91Slh 		case ADD_WAKE_UP_PATTERN:
141175ab5f91Slh 			PatternMask = (unsigned char *)(*(++Ptr));
141275ab5f91Slh 			Pattern = (unsigned char *)(*(++Ptr));
141375ab5f91Slh 			InfoBuffer_MaskSize = (*(++Ptr));
141475ab5f91Slh 			PatternSize = (*(++Ptr));
141575ab5f91Slh 			retval = (int *)(*(++Ptr));
141675ab5f91Slh 
141775ab5f91Slh 			mdlAddWakeUpPattern(pLayerPointers,
141875ab5f91Slh 			    PatternMask,
141975ab5f91Slh 			    Pattern,
142075ab5f91Slh 			    InfoBuffer_MaskSize,
142175ab5f91Slh 			    PatternSize,
142275ab5f91Slh 			    retval);
142375ab5f91Slh 			break;
142475ab5f91Slh 
142575ab5f91Slh 		case REMOVE_WAKE_UP_PATTERN:
142675ab5f91Slh 			Pattern = (unsigned char *)(*(++Ptr));
142775ab5f91Slh 			PatternSize = *(++Ptr);
142875ab5f91Slh 			retval = (int *)(*(++Ptr));
142975ab5f91Slh 			mdlRemoveWakeUpPattern(pLayerPointers,
143075ab5f91Slh 			    Pattern,
143175ab5f91Slh 			    PatternSize,
143275ab5f91Slh 			    retval);
143375ab5f91Slh 			break;
143475ab5f91Slh 
143575ab5f91Slh 		case ENABLE_MAGIC_PACKET_WAKE_UP:
143675ab5f91Slh 			mdlEnableMagicPacketWakeUp(pLayerPointers);
143775ab5f91Slh 			break;
143875ab5f91Slh 
143975ab5f91Slh 		case SET_SINGLE_MULTICAST:
144075ab5f91Slh 			NumberOfAddress = *(++Ptr);
144175ab5f91Slh 			MulticastArray = (unsigned char *)(*(++Ptr));
144275ab5f91Slh 
144375ab5f91Slh 			for (i = 0; i < 8; i++) {
144475ab5f91Slh 				pLayerPointers->pMdl->TempLADRF[i] =
144575ab5f91Slh 				    pLayerPointers->pMdl->init_blk->LADRF[i];
144675ab5f91Slh 			}
144775ab5f91Slh 			CRCValue = mdlCalculateCRC(ETH_LENGTH_OF_ADDRESS,
144875ab5f91Slh 			    MulticastArray);
144975ab5f91Slh 			for (j = 0; j < 6; j++) {
145075ab5f91Slh 				HashCode = (HashCode << 1) +
145175ab5f91Slh 				    (((unsigned char)CRCValue >> j) & 0x01);
145275ab5f91Slh 			}
145375ab5f91Slh 			/*
145475ab5f91Slh 			 * Bits 3-5 of HashCode point to byte in address
145575ab5f91Slh 			 * filter.
145675ab5f91Slh 			 * Bits 0-2 point to bit within that byte.
145775ab5f91Slh 			 */
145875ab5f91Slh 			FilterByte = HashCode >> 3;
145975ab5f91Slh 			pLayerPointers->pMdl->TempLADRF[FilterByte] |=
146075ab5f91Slh 			    (1 << (HashCode & 0x07));
146175ab5f91Slh 			break;
146275ab5f91Slh 
146375ab5f91Slh 		case UNSET_SINGLE_MULTICAST:
146475ab5f91Slh 			NumberOfAddress = *(++Ptr);
146575ab5f91Slh 			MulticastArray = (unsigned char *)(*(++Ptr));
146675ab5f91Slh 			for (i = 0; i < 8; i++) {
146775ab5f91Slh 				pLayerPointers->pMdl->TempLADRF[i] =
146875ab5f91Slh 				    pLayerPointers->pMdl->init_blk->LADRF[i];
146975ab5f91Slh 			}
147075ab5f91Slh 			CRCValue = mdlCalculateCRC(ETH_LENGTH_OF_ADDRESS,
147175ab5f91Slh 			    MulticastArray);
147275ab5f91Slh 			for (j = 0; j < 6; j++) {
147375ab5f91Slh 				HashCode = ((HashCode << 1) +
147475ab5f91Slh 				    (((unsigned char)CRCValue >> j) & 0x01));
147575ab5f91Slh 			}
147675ab5f91Slh 
147775ab5f91Slh 			/*
147875ab5f91Slh 			 * Bits 3-5 of HashCode point to byte in address
147975ab5f91Slh 			 * filter.
148075ab5f91Slh 			 * Bits 0-2 point to bit within that byte.
148175ab5f91Slh 			 */
148275ab5f91Slh 			FilterByte = HashCode >> 3;
148375ab5f91Slh 			pLayerPointers->pMdl->TempLADRF[FilterByte] &=
1484*e916f0dcSToomas Soome 			    ~(1 << (HashCode & 0x07));
148575ab5f91Slh 			break;
148675ab5f91Slh 
148775ab5f91Slh 		default:
148875ab5f91Slh 			break;
148975ab5f91Slh 		}
149075ab5f91Slh 		Ptr++;
149175ab5f91Slh 	}
149275ab5f91Slh }
149375ab5f91Slh 
149475ab5f91Slh 
149575ab5f91Slh void
mdlAddMulticastAddresses(struct LayerPointers * pLayerPointers,int NumberOfAddress,unsigned char * MulticastAddresses)149675ab5f91Slh mdlAddMulticastAddresses(struct LayerPointers *pLayerPointers,
149775ab5f91Slh     int NumberOfAddress, unsigned char *MulticastAddresses)
149875ab5f91Slh {
149975ab5f91Slh 	unsigned int j, CRCValue;
150075ab5f91Slh 	unsigned char HashCode, FilterByte;
150175ab5f91Slh 	int i;
150275ab5f91Slh 
150375ab5f91Slh 	for (i = 0; i < 8; i++) {
150475ab5f91Slh 		pLayerPointers->pMdl->TempLADRF[i]  = 0x00;
150575ab5f91Slh 	}
150675ab5f91Slh 
150775ab5f91Slh 
150875ab5f91Slh 	for (i = 0; i < NumberOfAddress; i++) {
150975ab5f91Slh 		HashCode = 0;
151075ab5f91Slh 
151175ab5f91Slh 		/* Calculate CRC value */
151275ab5f91Slh 		CRCValue = mdlCalculateCRC(ETH_LENGTH_OF_ADDRESS,
151375ab5f91Slh 		    MulticastAddresses);
151475ab5f91Slh 
151575ab5f91Slh 		for (j = 0; j < 6; j++) {
151675ab5f91Slh 			HashCode = (HashCode << 1) +
151775ab5f91Slh 			    (((unsigned char)CRCValue >> j) & 0x01);
151875ab5f91Slh 		}
151975ab5f91Slh 
152075ab5f91Slh 		/* Bits 3-5 of HashCode point to byte in address filter. */
152175ab5f91Slh 		/* Bits 0-2 point to bit within that byte. */
152275ab5f91Slh 		FilterByte = HashCode >> 3;
152375ab5f91Slh 		pLayerPointers->pMdl->TempLADRF[FilterByte] |=
152475ab5f91Slh 		    (1 << (HashCode & 0x07));
152575ab5f91Slh 		MulticastAddresses += ETH_LENGTH_OF_ADDRESS;
152675ab5f91Slh 	}
152775ab5f91Slh }
152875ab5f91Slh 
152975ab5f91Slh /* Receive all packets  */
153075ab5f91Slh void
mdlSetPromiscuous(struct LayerPointers * pLayerPointers)153175ab5f91Slh mdlSetPromiscuous(struct LayerPointers *pLayerPointers)
153275ab5f91Slh {
153375ab5f91Slh 	/*
153475ab5f91Slh 	 * Writable N == Can Be Written only when device is not running
153575ab5f91Slh 	 * (RUN == 0)
153675ab5f91Slh 	 */
153775ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD2,
153875ab5f91Slh 	    VAL2 | PROM);
153975ab5f91Slh 	pLayerPointers->pMdl->FLAGS |= PROM;	/* B16_MASK */
154075ab5f91Slh }
154175ab5f91Slh 
154275ab5f91Slh /* Stop Receiving all packets  */
154375ab5f91Slh void
mdlDisablePromiscuous(struct LayerPointers * pLayerPointers)154475ab5f91Slh mdlDisablePromiscuous(struct LayerPointers *pLayerPointers)
154575ab5f91Slh {
154675ab5f91Slh 	/*
154775ab5f91Slh 	 * Writable N == Can Be Written only when device is not running
154875ab5f91Slh 	 * (RUN == 0)
154975ab5f91Slh 	 */
155075ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD2,
155175ab5f91Slh 	    PROM);
155275ab5f91Slh 	pLayerPointers->pMdl->FLAGS &= (~ PROM); /* B16_MASK */
155375ab5f91Slh }
155475ab5f91Slh 
155575ab5f91Slh /*
155675ab5f91Slh  * Disable Receive Broadcast. When set, disables the controller from receiving
155775ab5f91Slh  * broadcast messages. Used for protocols that do not support broadcast
155875ab5f91Slh  * addressing, except as a function of multicast.
155975ab5f91Slh  * DRCVBC is cleared by activation of H_RESET (broadcast messages will be
156075ab5f91Slh  * received) and is unaffected by the clearing of the RUN bit.
156175ab5f91Slh  */
156275ab5f91Slh static void
mdlReceiveBroadCast(struct LayerPointers * pLayerPointers)156375ab5f91Slh mdlReceiveBroadCast(struct LayerPointers *pLayerPointers)
156475ab5f91Slh {
156575ab5f91Slh 	ULONG MappedMemBaseAddress;
156675ab5f91Slh 
156775ab5f91Slh 	MappedMemBaseAddress = pLayerPointers->pMdl->Mem_Address;
156875ab5f91Slh 	WRITE_REG32(pLayerPointers, MappedMemBaseAddress + CMD2, DRCVBC);
156975ab5f91Slh 	pLayerPointers->pMdl->FLAGS |= DRCVBC;
157075ab5f91Slh }
157175ab5f91Slh 
157275ab5f91Slh static void
mdlDisableReceiveBroadCast(struct LayerPointers * pLayerPointers)157375ab5f91Slh mdlDisableReceiveBroadCast(struct LayerPointers *pLayerPointers)
157475ab5f91Slh {
157575ab5f91Slh 	ULONG MappedMemBaseAddress;
157675ab5f91Slh 
157775ab5f91Slh 	MappedMemBaseAddress = pLayerPointers->pMdl->Mem_Address;
157875ab5f91Slh 	WRITE_REG32(pLayerPointers, MappedMemBaseAddress + CMD2, VAL2 | DRCVBC);
157975ab5f91Slh 	pLayerPointers->pMdl->FLAGS &= (~DRCVBC);
158075ab5f91Slh }
158175ab5f91Slh 
158275ab5f91Slh static void
mdlEnableMagicPacketWakeUp(struct LayerPointers * pLayerPointers)158375ab5f91Slh mdlEnableMagicPacketWakeUp(struct LayerPointers *pLayerPointers)
158475ab5f91Slh {
158575ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD3,
158675ab5f91Slh 	    VAL1 | MPPLBA);
158775ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD7,
158875ab5f91Slh 	    VAL0 | MPEN_SW);
158975ab5f91Slh }
159075ab5f91Slh 
159175ab5f91Slh /*
159275ab5f91Slh  * BitMap for add/del the Multicast address Since more than one M/C address
159375ab5f91Slh  * can map to same bit in the filter matrix, we should maintain the count for
159475ab5f91Slh  * # of M/C addresses associated with each bit. Only when the bit<->count
159575ab5f91Slh  * becomes zero, we should go ahead with changing/reseting the bit, else just
159675ab5f91Slh  * reduce the count associated with each bit and return.
159775ab5f91Slh  */
159875ab5f91Slh static int
mdlMulticastBitMapping(struct LayerPointers * pLayerPointers,unsigned char * MulticastAddress,int FLAG)159975ab5f91Slh mdlMulticastBitMapping(struct LayerPointers *pLayerPointers,
160075ab5f91Slh     unsigned char *MulticastAddress, int FLAG)
160175ab5f91Slh {
160275ab5f91Slh 	unsigned char HashCode, FilterByte;
160375ab5f91Slh 	int j = 0, BitMapIndex = 0;
160475ab5f91Slh 	unsigned int CRCValue = 0;
160575ab5f91Slh 
160675ab5f91Slh 	HashCode = 0;
160775ab5f91Slh 	/* Calculate the Bit Map location for the given Address */
160875ab5f91Slh 	CRCValue = mdlCalculateCRC(ETH_LENGTH_OF_ADDRESS, MulticastAddress);
160975ab5f91Slh 	for (j = 0; j < 6; j++) {
161075ab5f91Slh 		HashCode = (HashCode << 1) +
161175ab5f91Slh 		    (((unsigned char)CRCValue >> j) & 0x01);
161275ab5f91Slh 	}
161375ab5f91Slh 
161475ab5f91Slh 	/*
161575ab5f91Slh 	 * Bits 3-5 of HashCode point to byte in address filter.
161675ab5f91Slh 	 * Bits 0-2 point to bit within that byte.
161775ab5f91Slh 	 */
161875ab5f91Slh 	FilterByte = HashCode & 0x38;
161975ab5f91Slh 	FilterByte = FilterByte >> 3;
162075ab5f91Slh 	BitMapIndex =  (int)FilterByte * 8 + (HashCode & 0x7);
162175ab5f91Slh 
162275ab5f91Slh 	if (FLAG == DELETE_MULTICAST) {
162375ab5f91Slh 		if ((pLayerPointers->pMdl->MulticastBitMapArray[BitMapIndex]
162475ab5f91Slh 		    == 0) || (--pLayerPointers->pMdl->MulticastBitMapArray
162575ab5f91Slh 		    [BitMapIndex] == 0)) {
162675ab5f91Slh 			return (0);
162775ab5f91Slh 		} else {
162875ab5f91Slh 			return (-1);
162975ab5f91Slh 		}
163075ab5f91Slh 	}
163175ab5f91Slh 
163275ab5f91Slh 	if (FLAG == ADD_MULTICAST) {
163375ab5f91Slh 		if (pLayerPointers->pMdl
163475ab5f91Slh 		    ->MulticastBitMapArray[BitMapIndex] > 0) {
163575ab5f91Slh 			pLayerPointers->pMdl
163675ab5f91Slh 			    ->MulticastBitMapArray[BitMapIndex]++;
163775ab5f91Slh 			return (-1);
163875ab5f91Slh 		} else if (pLayerPointers->pMdl
163975ab5f91Slh 		    ->MulticastBitMapArray[BitMapIndex] == 0) {
164075ab5f91Slh 			pLayerPointers->pMdl
164175ab5f91Slh 			    ->MulticastBitMapArray[BitMapIndex]++;
164275ab5f91Slh 			return (0);
164375ab5f91Slh 		}
164475ab5f91Slh 	}
164575ab5f91Slh 	return (0);
164675ab5f91Slh }
164775ab5f91Slh 
164875ab5f91Slh /*
164975ab5f91Slh  * Set Interrupt Coalescing registers:
165075ab5f91Slh  *	To reduce the host CPU interrupt service overhead the network
165175ab5f91Slh  *	controller can be programmed to postpone the interrupt to the host
165275ab5f91Slh  *	CPU until either a programmable number of receive or transmit
165375ab5f91Slh  *	interrupt events have occurred or a programmable amount of time has
165475ab5f91Slh  *	elapsed since the first interrupt event occurred.
165575ab5f91Slh  */
165675ab5f91Slh void
SetIntrCoalesc(struct LayerPointers * pLayerPointers,boolean_t on)165775ab5f91Slh SetIntrCoalesc(struct LayerPointers *pLayerPointers, boolean_t on)
165875ab5f91Slh {
165975ab5f91Slh 	long MemBaseAddress = pLayerPointers->pMdl->Mem_Address;
166075ab5f91Slh 	struct mdl *pMdl = 0;
166175ab5f91Slh 	unsigned int timeout, event_count;
166275ab5f91Slh 
166375ab5f91Slh 	pMdl = (struct mdl *)(pLayerPointers->pMdl);
166475ab5f91Slh 
166575ab5f91Slh 	if (on) {
166675ab5f91Slh 		/* Set Rx Interrupt Coalescing */
166775ab5f91Slh 		timeout = pLayerPointers->pMdl->rx_intrcoalesc_time;
166875ab5f91Slh 		event_count = 0;
166975ab5f91Slh 		event_count |= pLayerPointers->pMdl->rx_intrcoalesc_events;
167075ab5f91Slh 		if (timeout > 0x7ff) {
167175ab5f91Slh 			timeout = 0x7ff;
167275ab5f91Slh 		}
167375ab5f91Slh 		if (event_count > 0x1f) {
167475ab5f91Slh 			event_count = 0x1f;
167575ab5f91Slh 		}
167675ab5f91Slh 
167775ab5f91Slh 		event_count =  event_count << 16;
167875ab5f91Slh 		WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_A,
167975ab5f91Slh 		    DLY_INT_A_R0 | event_count | timeout);
168075ab5f91Slh 
168175ab5f91Slh 	} else {
168275ab5f91Slh 		/* Disable Software Timer Interrupt */
168375ab5f91Slh 		WRITE_REG32(pLayerPointers, MemBaseAddress + STVAL, 0);
168475ab5f91Slh 		WRITE_REG32(pLayerPointers, pMdl->Mem_Address + INTEN0,
168575ab5f91Slh 		    STINTEN);
168675ab5f91Slh 
168775ab5f91Slh 		WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_A, 0);
168875ab5f91Slh 		WRITE_REG32(pLayerPointers, MemBaseAddress + DLY_INT_B, 0);
168975ab5f91Slh 	}
169075ab5f91Slh }
169175ab5f91Slh 
169275ab5f91Slh void
mdlSendPause(struct LayerPointers * pLayerPointers)169375ab5f91Slh mdlSendPause(struct LayerPointers *pLayerPointers)
169475ab5f91Slh {
169575ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address
169675ab5f91Slh 	    + FLOW_CONTROL, VAL2 | FIXP | FCCMD | 0x200);
169775ab5f91Slh }
169875ab5f91Slh 
169975ab5f91Slh /* Reset all Tx descriptors and Tx buffers */
170075ab5f91Slh void
milResetTxQ(struct LayerPointers * pLayerPointers)170175ab5f91Slh milResetTxQ(struct LayerPointers *pLayerPointers)
170275ab5f91Slh {
170375ab5f91Slh 	struct nonphysical *pNonphysical = pLayerPointers->pMil->pNonphysical;
170475ab5f91Slh 	int i;
170575ab5f91Slh 
170675ab5f91Slh 	pNonphysical->TxDescQRead = pNonphysical->TxDescQStart;
170775ab5f91Slh 	pNonphysical->TxDescQWrite = pNonphysical->TxDescQStart;
170875ab5f91Slh 
170975ab5f91Slh 	/* Clean all Tx descriptors */
171075ab5f91Slh 	for (i = 0; i < TX_RING_SIZE; i++) {
171175ab5f91Slh 		pNonphysical->TxDescQWrite->Tx_OWN = 0;
171275ab5f91Slh 		pNonphysical->TxDescQWrite->Tx_SOP = 0;
171375ab5f91Slh 		pNonphysical->TxDescQWrite->Tx_EOP = 0;
171475ab5f91Slh 		pNonphysical->TxDescQWrite++;
171575ab5f91Slh 	}
171675ab5f91Slh 	pNonphysical->TxDescQWrite = pNonphysical->TxDescQStart;
171775ab5f91Slh 
171875ab5f91Slh 	/* Re-init Tx Buffers */
171975ab5f91Slh 	pLayerPointers->pOdl->tx_buf.free =
172075ab5f91Slh 	    pLayerPointers->pOdl->tx_buf.msg_buf;
172175ab5f91Slh 	pLayerPointers->pOdl->tx_buf.next =
172275ab5f91Slh 	    pLayerPointers->pOdl->tx_buf.msg_buf;
172375ab5f91Slh 	pLayerPointers->pOdl->tx_buf.curr =
172475ab5f91Slh 	    pLayerPointers->pOdl->tx_buf.msg_buf;
172575ab5f91Slh }
172675ab5f91Slh 
172775ab5f91Slh /*
172875ab5f91Slh  *	Initialises the data used in Mil.
172975ab5f91Slh  */
173075ab5f91Slh void
milInitGlbds(struct LayerPointers * pLayerPointers)173175ab5f91Slh milInitGlbds(struct LayerPointers *pLayerPointers)
173275ab5f91Slh {
173375ab5f91Slh 	pLayerPointers->pMil->name = DEVICE_CHIPNAME;
173475ab5f91Slh 
173575ab5f91Slh 	mdlInitGlbds(pLayerPointers);
173675ab5f91Slh }
173775ab5f91Slh 
173875ab5f91Slh /*
173975ab5f91Slh  *	Purpose  :
174075ab5f91Slh  *		Initialises the RxBufDescQ with the packet pointer and physical
174175ab5f91Slh  *		address filled in the FreeQ.
174275ab5f91Slh  *
174375ab5f91Slh  *	Arguments :
174475ab5f91Slh  *		pLayerPointers
174575ab5f91Slh  *			Pointer to the Adapter structure.
174675ab5f91Slh  */
174775ab5f91Slh void
milInitRxQ(struct LayerPointers * pLayerPointers)174875ab5f91Slh milInitRxQ(struct LayerPointers *pLayerPointers)
174975ab5f91Slh {
175075ab5f91Slh 	struct mil *pMil = pLayerPointers->pMil;
175175ab5f91Slh 	struct nonphysical *pNonphysical = pMil->pNonphysical;
175275ab5f91Slh 	int i;
175375ab5f91Slh 
175475ab5f91Slh 	pNonphysical->RxBufDescQRead->descriptor = pMil->Rx_desc;
175575ab5f91Slh 	pNonphysical->RxBufDescQStart->descriptor = pMil->Rx_desc;
175675ab5f91Slh 	pNonphysical->RxBufDescQEnd->descriptor =
175775ab5f91Slh 	    &(pMil->Rx_desc[pMil->RxRingSize - 1]);
175875ab5f91Slh 
175975ab5f91Slh 	pNonphysical->RxBufDescQRead->USpaceMap = pMil->USpaceMapArray;
176075ab5f91Slh 	pNonphysical->RxBufDescQStart->USpaceMap = pMil->USpaceMapArray;
176175ab5f91Slh 	pNonphysical->RxBufDescQEnd->USpaceMap =
176275ab5f91Slh 	    &(pMil->USpaceMapArray[pMil->RxRingSize - 1]);
176375ab5f91Slh 
176475ab5f91Slh 	/* Initialize the adapter rx descriptor Q and rx buffer Q */
176575ab5f91Slh 	for (i = 0; i < pMil->RxRingSize; i++) {
176675ab5f91Slh 		pNonphysical->RxBufDescQRead->descriptor->Rx_BCNT
176775ab5f91Slh 		    = (unsigned)pMil->RxBufSize;
176875ab5f91Slh 
176975ab5f91Slh 		*(pNonphysical->RxBufDescQRead->USpaceMap) =
177075ab5f91Slh 		    (long)(pLayerPointers->pOdl->rx_buf.next->vir_addr);
177175ab5f91Slh 
177275ab5f91Slh 		pNonphysical->RxBufDescQRead->descriptor->Rx_Base_Addr
177375ab5f91Slh 		    = pLayerPointers->pOdl->rx_buf.next->phy_addr;
177475ab5f91Slh 
177575ab5f91Slh 		pNonphysical->RxBufDescQRead->descriptor->Rx_OWN = 1;
177675ab5f91Slh 		pNonphysical->RxBufDescQRead->descriptor++;
177775ab5f91Slh 		pNonphysical->RxBufDescQRead->USpaceMap++;
177875ab5f91Slh 		pLayerPointers->pOdl->rx_buf.next =
177975ab5f91Slh 		    NEXT(pLayerPointers->pOdl->rx_buf, next);
178075ab5f91Slh 	}
178175ab5f91Slh 
178275ab5f91Slh 	pNonphysical->RxBufDescQRead->descriptor =
178375ab5f91Slh 	    pNonphysical->RxBufDescQStart->descriptor;
178475ab5f91Slh 	pNonphysical->RxBufDescQRead->USpaceMap =
178575ab5f91Slh 	    pNonphysical->RxBufDescQStart->USpaceMap;
178675ab5f91Slh 	pLayerPointers->pOdl->rx_buf.next =
178775ab5f91Slh 	    pLayerPointers->pOdl->rx_buf.msg_buf;
178875ab5f91Slh }
178975ab5f91Slh 
179075ab5f91Slh /*
179175ab5f91Slh  *	Purpose		:
179275ab5f91Slh  *		This array is filled with the size of the structure & its
179375ab5f91Slh  *		pointer for freeing purposes.
179475ab5f91Slh  *
179575ab5f91Slh  *	Arguments	:
179675ab5f91Slh  *		pLayerPointers
179775ab5f91Slh  *			Pointer to the adapter structure.
179875ab5f91Slh  *		mem_free_array
179975ab5f91Slh  *			Pointer to the array that holds the data required
180075ab5f91Slh  *			for freeing.
180175ab5f91Slh  */
180275ab5f91Slh void
milFreeResources(struct LayerPointers * pLayerPointers,ULONG * mem_free_array)180375ab5f91Slh milFreeResources(struct LayerPointers *pLayerPointers, ULONG *mem_free_array)
180475ab5f91Slh {
180575ab5f91Slh 	/* 1) For mil structure (pLayerPointers->pMil) */
180675ab5f91Slh 	/* Type */
180775ab5f91Slh 	*(mem_free_array) = VIRTUAL;
180875ab5f91Slh 	/* Size */
180975ab5f91Slh 	*(++mem_free_array) = sizeof (struct mil);
181075ab5f91Slh 	/* VA */
181175ab5f91Slh 	*(++mem_free_array) = (ULONG)pLayerPointers->pMil;
181275ab5f91Slh 
181375ab5f91Slh 
181475ab5f91Slh 	/* 2) For USpaceMapArray queue */
181575ab5f91Slh 	/* Type */
181675ab5f91Slh 	*(++mem_free_array) = VIRTUAL;
181775ab5f91Slh 	/* Size */
181875ab5f91Slh 	*(++mem_free_array) = pLayerPointers->pMil->RxRingSize *
181975ab5f91Slh 	    sizeof (unsigned long);
182075ab5f91Slh 	/* VA */
182175ab5f91Slh 	*(++mem_free_array) = (ULONG)pLayerPointers->pMil->USpaceMapArray;
182275ab5f91Slh 
182375ab5f91Slh 
182475ab5f91Slh 	/* 3) For non_physical structure */
182575ab5f91Slh 	/* Type */
182675ab5f91Slh 	*(++mem_free_array) = VIRTUAL;
182775ab5f91Slh 	/* Size */
182875ab5f91Slh 	*(++mem_free_array) =  sizeof (struct nonphysical);
182975ab5f91Slh 	/* VA */
183075ab5f91Slh 	*(++mem_free_array) = (ULONG)pLayerPointers->pMil->pNonphysical;
183175ab5f91Slh 
183275ab5f91Slh 	/*
183375ab5f91Slh 	 * 4~6) For four allocation are for abstracting the Rx_Descritor ring
183475ab5f91Slh 	 */
183575ab5f91Slh 
183675ab5f91Slh 	/* 4) Type */
183775ab5f91Slh 	*(++mem_free_array) = VIRTUAL;
183875ab5f91Slh 	/* Size */
183975ab5f91Slh 	*(++mem_free_array) =  sizeof (struct Rx_Buf_Desc);
184075ab5f91Slh 	/* VA */
184175ab5f91Slh 	*(++mem_free_array) =
184275ab5f91Slh 	    (ULONG)pLayerPointers->pMil->pNonphysical->RxBufDescQRead;
184375ab5f91Slh 
184475ab5f91Slh 	/* 5) Type */
184575ab5f91Slh 	*(++mem_free_array) = VIRTUAL;
184675ab5f91Slh 	/* Size */
184775ab5f91Slh 	*(++mem_free_array) =  sizeof (struct Rx_Buf_Desc);
184875ab5f91Slh 	/* VA */
184975ab5f91Slh 	*(++mem_free_array) =
185075ab5f91Slh 	    (ULONG)pLayerPointers->pMil->pNonphysical->RxBufDescQStart;
185175ab5f91Slh 
185275ab5f91Slh 	/* 6) Type */
185375ab5f91Slh 	*(++mem_free_array) = VIRTUAL;
185475ab5f91Slh 	/* Size */
185575ab5f91Slh 	*(++mem_free_array) =  sizeof (struct Rx_Buf_Desc);
185675ab5f91Slh 	/* VA */
185775ab5f91Slh 	*(++mem_free_array) =
185875ab5f91Slh 	    (ULONG)pLayerPointers->pMil->pNonphysical->RxBufDescQEnd;
185975ab5f91Slh 
186075ab5f91Slh 	*(++mem_free_array) = 0;
186175ab5f91Slh 
186275ab5f91Slh 	mdlFreeResources(pLayerPointers, mem_free_array);
186375ab5f91Slh }
186475ab5f91Slh 
186575ab5f91Slh 
186675ab5f91Slh 
186775ab5f91Slh /*
186875ab5f91Slh  *	Purpose  :
186975ab5f91Slh  *		This array is filled with the size of the memory required for
187075ab5f91Slh  *		allocating purposes.
187175ab5f91Slh  *
187275ab5f91Slh  *	Arguments :
187375ab5f91Slh  *		pLayerPointers
187475ab5f91Slh  *			Pointer to the adapter structure.
187575ab5f91Slh  *		mem_req_array
187675ab5f91Slh  *			Pointer to the array that holds the data required for
187775ab5f91Slh  *			allocating memory.
187875ab5f91Slh  */
187975ab5f91Slh void
milRequestResources(ULONG * mem_req_array)188075ab5f91Slh milRequestResources(ULONG *mem_req_array)
188175ab5f91Slh {
188275ab5f91Slh 	int RxRingSize;
188375ab5f91Slh 
188475ab5f91Slh 	RxRingSize = RX_RING_SIZE;	/* 128 */
188575ab5f91Slh 
188675ab5f91Slh 	/* 1) For mil structure (pLayerPointers->pMil) */
188775ab5f91Slh 	/* Type */
188875ab5f91Slh 	*mem_req_array   = VIRTUAL;
188975ab5f91Slh 	/* Size */
189075ab5f91Slh 	*(++mem_req_array) = sizeof (struct mil);
189175ab5f91Slh 
189275ab5f91Slh 	/* 2) For USpaceMapArray queue (pLayerPointers->pMil->USpaceMapArray) */
189375ab5f91Slh 	/* Type */
189475ab5f91Slh 	*(++mem_req_array) = VIRTUAL;
189575ab5f91Slh 	/* Size */
189675ab5f91Slh 	*(++mem_req_array) = RxRingSize * sizeof (unsigned long);
189775ab5f91Slh 
189875ab5f91Slh 
189975ab5f91Slh 	/* 3) For pNonphysical structure */
190075ab5f91Slh 	/* Type */
190175ab5f91Slh 	*(++mem_req_array) = VIRTUAL;
190275ab5f91Slh 	/* Size */
190375ab5f91Slh 	*(++mem_req_array) = sizeof (struct nonphysical);
190475ab5f91Slh 
190575ab5f91Slh 	/*
190675ab5f91Slh 	 * 4~6) For four allocation are for abstracting the Rx_Descritor ring
190775ab5f91Slh 	 */
190875ab5f91Slh 	/* 4) Type */
190975ab5f91Slh 	*(++mem_req_array) = VIRTUAL;
191075ab5f91Slh 	/* Size */
191175ab5f91Slh 	*(++mem_req_array) = sizeof (struct Rx_Buf_Desc);
191275ab5f91Slh 
191375ab5f91Slh 	/* 5) Type */
191475ab5f91Slh 	*(++mem_req_array) = VIRTUAL;
191575ab5f91Slh 	/* Size */
191675ab5f91Slh 	*(++mem_req_array) = sizeof (struct Rx_Buf_Desc);
191775ab5f91Slh 
191875ab5f91Slh 	/* 6) Type */
191975ab5f91Slh 	*(++mem_req_array) = VIRTUAL;
192075ab5f91Slh 	/* Size */
192175ab5f91Slh 	*(++mem_req_array) = sizeof (struct Rx_Buf_Desc);
192275ab5f91Slh 
192375ab5f91Slh 	*(++mem_req_array) = 0;
192475ab5f91Slh 
192575ab5f91Slh 	mdlRequestResources(mem_req_array);
192675ab5f91Slh }
192775ab5f91Slh 
192875ab5f91Slh 
192975ab5f91Slh 
193075ab5f91Slh /*
193175ab5f91Slh  *	Purpose  :
193275ab5f91Slh  *		This array contains the details of the allocated memory. The
193375ab5f91Slh  *		pointers are taken from the respective locations in the array
193475ab5f91Slh  *		& assigne appropriately to the respective structures.
193575ab5f91Slh  *
193675ab5f91Slh  *	Arguments :
193775ab5f91Slh  *		pLayerPointers
193875ab5f91Slh  *			Pointer to the adapter structure.
193975ab5f91Slh  *		pmem_set_array
194075ab5f91Slh  *			Pointer to the array that holds the data after required
194175ab5f91Slh  *			allocating memory.
194275ab5f91Slh  */
194375ab5f91Slh void
milSetResources(struct LayerPointers * pLayerPointers,ULONG * pmem_set_array)194475ab5f91Slh milSetResources(struct LayerPointers *pLayerPointers, ULONG *pmem_set_array)
194575ab5f91Slh {
194675ab5f91Slh 	int RxRingSize, TxRingSize;
194775ab5f91Slh 	int RxBufSize;
194875ab5f91Slh 	struct mil *pMil;
194975ab5f91Slh 
195075ab5f91Slh 	RxRingSize = RX_RING_SIZE;
195175ab5f91Slh 	TxRingSize = TX_RING_SIZE;
195275ab5f91Slh 	RxBufSize = RX_BUF_SIZE;
195375ab5f91Slh 
195475ab5f91Slh 	/* 1) Set the pointers to the mil pointers */
195575ab5f91Slh 	/* Type */
195675ab5f91Slh 	pmem_set_array++;
195775ab5f91Slh 	/* Size */
195875ab5f91Slh 	pmem_set_array++;
195975ab5f91Slh 	pMil = (struct mil *)(*pmem_set_array);
196075ab5f91Slh 	pLayerPointers->pMil = pMil;
196175ab5f91Slh 
196275ab5f91Slh 	pMil->RxRingSize = RxRingSize;
196375ab5f91Slh 	pMil->TxRingSize = TxRingSize;
196475ab5f91Slh 	pMil->RxBufSize = RxBufSize;
196575ab5f91Slh 
196675ab5f91Slh 	/* 2) Type */
196775ab5f91Slh 	pmem_set_array++;
196875ab5f91Slh 	/* Size */
196975ab5f91Slh 	pmem_set_array++;
197075ab5f91Slh 	pmem_set_array++;
197175ab5f91Slh 	pMil->USpaceMapArray = (long *)(*pmem_set_array);
197275ab5f91Slh 
197375ab5f91Slh 	/* 3) Set the pointers to the NonPhysical part */
197475ab5f91Slh 	/* Type */
197575ab5f91Slh 	pmem_set_array++;
197675ab5f91Slh 	/* Size */
197775ab5f91Slh 	pmem_set_array++;
197875ab5f91Slh 	/* Virtual Addr of NonPhysical */
197975ab5f91Slh 	pmem_set_array++;
198075ab5f91Slh 	pMil->pNonphysical =
198175ab5f91Slh 	    (struct nonphysical *)(*pmem_set_array);
198275ab5f91Slh 
198375ab5f91Slh 	/*
198475ab5f91Slh 	 * 4~6) Following four allocation are for abstracting the Rx_Descritor
198575ab5f91Slh 	 * Ring.
198675ab5f91Slh 	 */
198775ab5f91Slh 	/* 4) Type */
198875ab5f91Slh 	pmem_set_array++;
198975ab5f91Slh 	/* Size */
199075ab5f91Slh 	pmem_set_array++;
199175ab5f91Slh 	/* Virtual Addr of Abstracted RxDesc */
199275ab5f91Slh 	pmem_set_array++;
199375ab5f91Slh 	pMil->pNonphysical->RxBufDescQRead =
199475ab5f91Slh 	    (struct Rx_Buf_Desc *)(*pmem_set_array);
199575ab5f91Slh 
199675ab5f91Slh 	/* 5) Type */
199775ab5f91Slh 	pmem_set_array++;
199875ab5f91Slh 	/* Size */
199975ab5f91Slh 	pmem_set_array++;
200075ab5f91Slh 	/* Virtual Addr of Abstracted RxDesc */
200175ab5f91Slh 	pmem_set_array++;
200275ab5f91Slh 	pMil->pNonphysical->RxBufDescQStart =
200375ab5f91Slh 	    (struct Rx_Buf_Desc *)(*pmem_set_array);
200475ab5f91Slh 
200575ab5f91Slh 	/* 6) Type */
200675ab5f91Slh 	pmem_set_array++;
200775ab5f91Slh 	/* Size */
200875ab5f91Slh 	pmem_set_array++;
200975ab5f91Slh 	/* Virtual Addr of Abstracted RxDesc */
201075ab5f91Slh 	pmem_set_array++;
201175ab5f91Slh 	pMil->pNonphysical->RxBufDescQEnd =
201275ab5f91Slh 	    (struct Rx_Buf_Desc *)(*pmem_set_array);
201375ab5f91Slh 
201475ab5f91Slh 	pmem_set_array++;
201575ab5f91Slh 
201675ab5f91Slh 	mdlSetResources(pLayerPointers, pmem_set_array);
201775ab5f91Slh }
201875ab5f91Slh 
201975ab5f91Slh /*
202075ab5f91Slh  *	Purpose  :
202175ab5f91Slh  *		This routine adds the Multicast addresses to the filter
202275ab5f91Slh  *
202375ab5f91Slh  *	Arguments :
202475ab5f91Slh  *		pLayerPointers
202575ab5f91Slh  *			Pointer to Layer pointers structure.
202675ab5f91Slh  *		pucMulticastAddress
202775ab5f91Slh  *			Pointer to the array of multicast addresses
202875ab5f91Slh  */
202975ab5f91Slh void
mdlAddMulticastAddress(struct LayerPointers * pLayerPointers,UCHAR * pucMulticastAddress)203075ab5f91Slh mdlAddMulticastAddress(struct LayerPointers *pLayerPointers,
203175ab5f91Slh     UCHAR *pucMulticastAddress)
203275ab5f91Slh {
203375ab5f91Slh 	unsigned long MODE[10];
203475ab5f91Slh 	unsigned long tmp1;
203575ab5f91Slh 	unsigned long tmp2;
203675ab5f91Slh 
203775ab5f91Slh 	if (mdlMulticastBitMapping(pLayerPointers, pucMulticastAddress,
203875ab5f91Slh 	    ADD_MULTICAST) != 0)
203975ab5f91Slh 		return;
204075ab5f91Slh 
204175ab5f91Slh 	tmp2 = SET_SINGLE_MULTICAST;
204275ab5f91Slh 	MODE[0] = (unsigned long)tmp2;
204375ab5f91Slh 	MODE[1] = 1;
204475ab5f91Slh 	tmp1 = (unsigned long)pucMulticastAddress;
204575ab5f91Slh 	MODE[2] = tmp1;
204675ab5f91Slh 	MODE[3] = ENABLE_MULTICAST;
204775ab5f91Slh 	MODE[4] = 0;
204875ab5f91Slh 	mdlChangeFilter(pLayerPointers, (unsigned long *)MODE);
204975ab5f91Slh }
205075ab5f91Slh 
205175ab5f91Slh 
205275ab5f91Slh /*
205375ab5f91Slh  *	Purpose  :
205475ab5f91Slh  *		This routine deletes the Multicast addresses requested by OS.
205575ab5f91Slh  *
205675ab5f91Slh  *	Arguments :
205775ab5f91Slh  *		pLayerPointers
205875ab5f91Slh  *			Pointer to Layer pointers structure.
205975ab5f91Slh  *		pucMulticastAddress
206075ab5f91Slh  *			Pointer to the array of multicast addresses
206175ab5f91Slh  */
206275ab5f91Slh void
mdlDeleteMulticastAddress(struct LayerPointers * pLayerPointers,UCHAR * pucMulticastAddress)206375ab5f91Slh mdlDeleteMulticastAddress(struct LayerPointers *pLayerPointers,
206475ab5f91Slh     UCHAR *pucMulticastAddress)
206575ab5f91Slh {
206675ab5f91Slh 	unsigned long MODE[10];
206775ab5f91Slh 	unsigned long tmp;
206875ab5f91Slh 
206975ab5f91Slh 	if (mdlMulticastBitMapping(pLayerPointers, pucMulticastAddress,
207075ab5f91Slh 	    DELETE_MULTICAST) != 0)
207175ab5f91Slh 		return;
207275ab5f91Slh 
207375ab5f91Slh 	MODE[0] = UNSET_SINGLE_MULTICAST;
207475ab5f91Slh 	MODE[1] = 1;
207575ab5f91Slh 	tmp = (unsigned long)pucMulticastAddress;
207675ab5f91Slh 	MODE[2] = tmp;
207775ab5f91Slh 	MODE[3] = ENABLE_MULTICAST;
207875ab5f91Slh 	MODE[4] = 0;
207975ab5f91Slh 	mdlChangeFilter(pLayerPointers, (unsigned long *)MODE);
208075ab5f91Slh }
208175ab5f91Slh 
208275ab5f91Slh /*
208375ab5f91Slh  *	Purpose  :
208475ab5f91Slh  *		Calculates the CRC value over the input number of bytes.
208575ab5f91Slh  *
208675ab5f91Slh  *	Arguments :
208775ab5f91Slh  *		NumberOfBytes
208875ab5f91Slh  *			The number of bytes in the input.
208975ab5f91Slh  *		Input
209075ab5f91Slh  *			An input "string" to calculate a CRC over.
209175ab5f91Slh  */
209275ab5f91Slh static unsigned int
mdlCalculateCRC(unsigned int NumberOfBytes,unsigned char * Input)209375ab5f91Slh mdlCalculateCRC(unsigned int NumberOfBytes, unsigned char *Input)
209475ab5f91Slh {
209575ab5f91Slh 	const unsigned int POLY = 0x04c11db7;
209675ab5f91Slh 	unsigned int CRCValue = 0xffffffff;
209775ab5f91Slh 	unsigned int CurrentBit, CurrentCRCHigh;
209875ab5f91Slh 	unsigned char CurrentByte;
209975ab5f91Slh 
210075ab5f91Slh 	for (; NumberOfBytes; NumberOfBytes--) {
210175ab5f91Slh 		CurrentByte = *Input;
210275ab5f91Slh 		Input++;
210375ab5f91Slh 
210475ab5f91Slh 		for (CurrentBit = 8; CurrentBit; CurrentBit--) {
210575ab5f91Slh 			CurrentCRCHigh = CRCValue >> 31;
210675ab5f91Slh 			CRCValue <<= 1;
210775ab5f91Slh 
210875ab5f91Slh 			if (CurrentCRCHigh ^ (CurrentByte & 0x01)) {
210975ab5f91Slh 				CRCValue ^= POLY;
211075ab5f91Slh 				CRCValue |= 0x00000001;
211175ab5f91Slh 			}
211275ab5f91Slh 			CurrentByte >>= 1;
211375ab5f91Slh 		}
211475ab5f91Slh 	}
211575ab5f91Slh 	return (CRCValue);
211675ab5f91Slh }
211775ab5f91Slh 
211875ab5f91Slh void
mdlRxFastSuspend(struct LayerPointers * pLayerPointers)211975ab5f91Slh mdlRxFastSuspend(struct LayerPointers *pLayerPointers)
212075ab5f91Slh {
212175ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
212275ab5f91Slh 	    VAL0 | RX_FAST_SPND);
212375ab5f91Slh }
212475ab5f91Slh 
212575ab5f91Slh void
mdlRxFastSuspendClear(struct LayerPointers * pLayerPointers)212675ab5f91Slh mdlRxFastSuspendClear(struct LayerPointers *pLayerPointers)
212775ab5f91Slh {
212875ab5f91Slh 	WRITE_REG32(pLayerPointers, pLayerPointers->pMdl->Mem_Address + CMD0,
212975ab5f91Slh 	    RX_FAST_SPND);
213075ab5f91Slh }
2131