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