📄 am79c973.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//------------------------------------------------------------------------------
//
// File: am79c973.c
//
#include <windows.h>
#include <halether.h>
#include <oal.h>
//------------------------------------------------------------------------------
#define BUFFER_SIZE 0x0600
#define DESC_SIZE 0x10
#define INIT_SIZE 0x20
#define ADDR_SIZE 6
#define TIMEOUT 2
#define RX_BUFFERS 32
#define TX_BUFFERS 4
//------------------------------------------------------------------------------
#define APROM 0x00
#define RDP 0x10
#define RAP 0x14
#define RESET 0x18
#define BDP 0x1C
//------------------------------------------------------------------------------
#define RMD1_OWN 0x80000000
#define RMD1_ERR 0x40000000
#define RMD1_FRAM 0x20000000
#define RMD1_OFLO 0x10000000
#define RMD1_CRC 0x08000000
#define RMD1_BUFF 0x04000000
#define RMD1_STP 0x02000000
#define RMD1_ENP 0x01000000
#define RMD1_BPE 0x00800000
#define RMD1_ONES 0x0000F000
#define TMD0_BUFF 0x80000000
#define TMD0_UFLO 0x40000000
#define TMD0_EXDEF 0x20000000
#define TMD0_LCOL 0x10000000
#define TMD0_LCAR 0x08000000
#define TMD0_RTRY 0x04000000
#define TMD1_OWN 0x80000000
#define TMD1_ERR 0x40000000
#define TMD1_ADD_FCS 0x20000000
#define TMD1_MORE 0x10000000
#define TMD1_LTINT 0x10000000
#define TMD1_ONE 0x08000000
#define TMD1_DEF 0x04000000
#define TMD1_STP 0x02000000
#define TMD1_ENP 0x01000000
#define TMD1_BPE 0x00800000
#define TMD1_ONES 0x0000F000
#define MODE_PROM (1 << 15)
#define MODE_DRCVBC (1 << 14)
//------------------------------------------------------------------------------
#define MAC_PHY_BMCR 0 // Basic Mode Control Register
#define MAC_PHY_BMSR 1 // Basic Mode Status Register
#define MAC_PHY_PHYIDR1 2 // PHY Identifier Register #1
#define MAC_PHY_PHYIDR2 3 // PHY Identifier Register #2
#define MAC_PHY_ANAR 4 // AutoNeg Advertisement Register
#define MAC_PHY_ANLPAR 5 // AutoNeg Link Partner Ability Reg
#define MAC_PHY_ANER 6 // AutoNeg Expansion Register
#define MAC_PHY_BMCR_RST (1 << 15)
#define MAC_PHY_BMCR_SS (1 << 13)
#define MAC_PHY_BMCR_ANE (1 << 12)
#define MAC_PHY_BMCR_RAN (1 << 9)
#define MAC_PHY_BMSR_ANC (1 << 5)
#define MAC_PHY_BMSR_LINK (1 << 2)
#define MAC_PHY_AN_100FD (1 << 8)
#define MAC_PHY_AN_100HD (1 << 7)
#define MAC_PHY_AN_10FD (1 << 6)
#define MAC_PHY_AN_10HD (1 << 5)
//------------------------------------------------------------------------------
static UINT32 g_base = 0; // The chip base address
static UINT32 g_dmaAddress = 0; // DMA buffer address
static UINT32 g_dmaSize = 0; // DMA buffer size
static UINT32 *g_pInit;
static UINT32 *g_pRxRing;
static UINT32 *g_pTxRing;
static UINT8 *g_pRxBuffer;
static UINT8 *g_pTxBuffer;
static UINT32 g_rxPos;
static UINT32 g_txPos;
//------------------------------------------------------------------------------
static UINT32 ReadCSR(UINT32 address)
{
OUTREG32((UINT32*)(g_base + RAP), address);
return INREG32((UINT32*)(g_base + RDP));
}
//------------------------------------------------------------------------------
static VOID WriteCSR(UINT32 address, UINT32 data)
{
OUTREG32((UINT32*)(g_base + RAP), address);
OUTREG32((UINT32*)(g_base + RDP), data);
}
//------------------------------------------------------------------------------
static UINT32 ReadBCR(UINT32 address)
{
OUTREG32((UINT32*)(g_base + RAP), address);
return INREG32((UINT32*)(g_base + BDP));
}
//------------------------------------------------------------------------------
static VOID WriteBCR(UINT32 address, UINT32 data)
{
OUTREG32((UINT32*)(g_base + RAP), address);
OUTREG32((UINT32*)(g_base + BDP), data);
}
//------------------------------------------------------------------------------
static UINT16 ReadPhy(UINT16 id, UINT16 reg)
{
UINT32 address;
OUTREG32((UINT32*)(g_base + RAP), 33);
address = INREG32((UINT32*)(g_base + BDP));
OUTREG32((UINT32*)(g_base + BDP), (UINT16)((id << 5)|(reg & 0x1F)));
OUTREG32((UINT32*)(g_base + RAP), 34);
return (UINT16)INREG32((UINT32*)(g_base + BDP));
}
//------------------------------------------------------------------------------
static VOID WritePhy(UINT16 id, UINT16 reg, UINT16 data)
{
UINT32 address;
OUTREG32((UINT32*)(g_base + RAP), 33);
address = INREG32((UINT32*)(g_base + BDP));
OUTREG32((UINT32*)(g_base + BDP), (UINT16)((id << 5)|(reg & 0x1F)));
OUTREG32((UINT32*)(g_base + RAP), 34);
OUTREG32((UINT32*)(g_base + BDP), data);
}
//------------------------------------------------------------------------------
static DWORD HashAddress(UCHAR* pAddress)
{
ULONG crc, carry;
UINT i, j;
UCHAR uc;
crc = 0xFFFFFFFF;
for (i = 0; i < ADDR_SIZE; i++) {
uc = pAddress[i];
for (j = 0; j < 8; j++) {
carry = ((crc & 0x80000000) ? 1 : 0) ^ (uc & 0x01);
crc <<= 1;
uc >>= 1;
if (carry) crc = (crc ^ 0x04c11db6) | carry;
}
}
return crc;
}
//------------------------------------------------------------------------------
static BOOL HWInit()
{
UINT32 i, pos;
// Wait for while...
OALStall(1000000);
// Switch to DWIO mode
OUTREG32((UINT32*)(g_base + RDP), 0);
// Reset
INREG32((UINT32*)(g_base + RESET));
// Wait 2ms
OALStall(2000);
// Set software style to 3 (32bit software structure)
WriteBCR(20, 0x0503);
// Stop adapter
WriteCSR(0, 0x0004);
// Divide DMA buffer
pos = g_dmaAddress;
g_pInit = (UINT32*)pos;
pos += INIT_SIZE;
g_pRxRing = (UINT32*)pos;
pos += RX_BUFFERS * DESC_SIZE;
g_pTxRing = (UINT32*)pos;
pos += TX_BUFFERS * DESC_SIZE;
g_pRxBuffer = (UINT8*)pos;
pos += RX_BUFFERS * BUFFER_SIZE;
g_pTxBuffer = (UINT8*)pos;
// Prepare initialization block
g_pInit[0] = 0x20500180;
g_pInit[1] = INREG32((UINT32*)g_base);
g_pInit[2] = INREG32((UINT32*)(g_base + 4));
g_pInit[3] = 0;
g_pInit[4] = 0;
g_pInit[5] = OALVAtoPA(g_pRxRing);
g_pInit[6] = OALVAtoPA(g_pTxRing);
// Initialize RX ring
for (i = 0; i < RX_BUFFERS; i++) {
g_pRxRing[4 * i + 0] = 0;
g_pRxRing[4 * i + 1] = RMD1_OWN | RMD1_ONES | (4096 - BUFFER_SIZE);
g_pRxRing[4 * i + 2] = OALVAtoPA(g_pRxBuffer + i * BUFFER_SIZE);
g_pRxRing[4 * i + 3] = (UINT32)(g_pRxBuffer + i * BUFFER_SIZE);
}
g_rxPos = 0;
// Initialize TX ring
for (i = 0; i < TX_BUFFERS; i++) {
g_pTxRing[4 * i + 0] = 0;
g_pTxRing[4 * i + 1] = 0;
g_pTxRing[4 * i + 2] = OALVAtoPA(g_pTxBuffer + i * BUFFER_SIZE);
g_pTxRing[4 * i + 3] = (UINT32)(g_pTxBuffer + i * BUFFER_SIZE);
}
g_txPos = 0;
// Set initialization block address
pos = OALVAtoPA(g_pInit);
WriteCSR(1, pos & 0xFFFF);
WriteCSR(2, pos >> 16);
// Mask everything
WriteCSR(3, 0x1F40); // Enable DXSUFLO to let it recover from underflow
WriteCSR(4, 0x0914);
// Start initialization
WriteCSR(0, 0x0001);
// Wait for initialization complete
while ((ReadCSR(0) & 0x0100) == 0) OALStall(10);
// Wait for link
OALMSGS(OAL_WARN, (L"Am79c973: Wait for link..."));
// First we must be out of reset
while ((ReadPhy(0x1E, MAC_PHY_BMCR) & MAC_PHY_BMCR_RST) != 0);
// Link status is lock low bit, so read it first time...
ReadPhy(0x1E, MAC_PHY_BMSR);
while ((ReadPhy(0x1E, MAC_PHY_BMSR) & MAC_PHY_BMSR_LINK) == 0);
OALMSGS(OAL_WARN, (L" Link detected\r\n"));
// Wait for while...
OALStall(1000000);
// Enable Tx/Rx
WriteCSR(0, 0x0002);
// Done
return TRUE;
}
//------------------------------------------------------------------------------
BOOL AM79C973InitDMABuffer(UINT32 address, UINT32 size)
{
BOOL rc = FALSE;
UINT32 offset, buffers;
OALMSGS(OAL_ETHER&&OAL_FUNC, (
L"+AM79C973InitDMABuffer(0x%08x, 0x%08x)\r\n", address, size
));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -