a46a712610
In the file `COPYING` in the coreboot repository and upstream [1] just one space is used. The following command was used to convert all files. $ git grep -l 'MA 02' | xargs sed -i 's/MA 02/MA 02/' [1] http://www.gnu.org/licenses/gpl-2.0.txt Change-Id: Ic956dab2820a9e2ccb7841cab66966ba168f305f Signed-off-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-on: http://review.coreboot.org/2490 Tested-by: build bot (Jenkins) Reviewed-by: Anton Kochkov <anton.kochkov@gmail.com>
290 lines
6.4 KiB
C
290 lines
6.4 KiB
C
/*
|
|
* This file is part of the coreboot project.
|
|
*
|
|
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#undef FILECODE
|
|
#define FILECODE 0xCCCC
|
|
#include "comlib.h"
|
|
|
|
/*
|
|
*---------------------------------------------------------------------------
|
|
* EXPORTED FUNCTIONS
|
|
*
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
void CALLCONV AmdPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
|
|
{
|
|
ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0);
|
|
|
|
AmdPCIRead(loc, pValue);
|
|
*pValue = *pValue >> lowbit; /* Shift */
|
|
|
|
/* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
|
|
if ((highbit-lowbit) != 31)
|
|
*pValue &= (((u32)1 << (highbit-lowbit+1))-1);
|
|
}
|
|
|
|
|
|
void CALLCONV AmdPCIWriteBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
|
|
{
|
|
u32 temp, mask;
|
|
|
|
ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0);
|
|
|
|
/* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
|
|
if ((highbit-lowbit) != 31)
|
|
mask = (((u32)1 << (highbit-lowbit+1))-1);
|
|
else
|
|
mask = (u32)0xFFFFFFFF;
|
|
|
|
AmdPCIRead(loc, &temp);
|
|
temp &= ~(mask << lowbit);
|
|
temp |= (*pValue & mask) << lowbit;
|
|
AmdPCIWrite(loc, &temp);
|
|
}
|
|
|
|
|
|
/*
|
|
* Given a SBDFO this routine will find the next PCI capabilities list entry.
|
|
* If the end of the list of reached, or if a problem is detected, then
|
|
* ILLEGAL_SBDFO is returned.
|
|
*
|
|
* To start a new search from the beginning of head of the list, specify a
|
|
* SBDFO with a offset of zero.
|
|
*/
|
|
void CALLCONV AmdPCIFindNextCap(SBDFO *pCurrent)
|
|
{
|
|
SBDFO base;
|
|
u32 offset;
|
|
u32 temp;
|
|
|
|
if (*pCurrent == ILLEGAL_SBDFO)
|
|
return;
|
|
|
|
offset = SBDFO_OFF(*pCurrent);
|
|
base = *pCurrent - offset;
|
|
*pCurrent = ILLEGAL_SBDFO;
|
|
|
|
/* Verify that the SBDFO points to a valid PCI device SANITY CHECK */
|
|
AmdPCIRead(base, &temp);
|
|
if (temp == 0xFFFFFFFF)
|
|
return; /* There is no device at this address */
|
|
|
|
/* Verify that the device supports a capability list */
|
|
AmdPCIReadBits(base + 0x04, 20, 20, &temp);
|
|
if (temp == 0)
|
|
return; /* This PCI device does not support capability lists */
|
|
|
|
if (offset != 0)
|
|
{
|
|
/* If we are continuing on an existing list */
|
|
AmdPCIReadBits(base + offset, 15, 8, &temp);
|
|
}
|
|
else
|
|
{
|
|
/* We are starting on a new list */
|
|
AmdPCIReadBits(base + 0x34, 7, 0, &temp);
|
|
}
|
|
|
|
if (temp == 0)
|
|
return; /* We have reached the end of the capabilties list */
|
|
|
|
/* Error detection and recovery- The statement below protects against
|
|
PCI devices with broken PCI capabilities lists. Detect a pointer
|
|
that is not u32 aligned, points into the first 64 reserved DWORDs
|
|
or points back to itself.
|
|
*/
|
|
if (((temp & 3) != 0) || (temp == offset) || (temp < 0x40))
|
|
return;
|
|
|
|
*pCurrent = base + temp;
|
|
return;
|
|
}
|
|
|
|
|
|
void CALLCONV Amdmemcpy(void *pDst, const void *pSrc, u32 length)
|
|
{
|
|
ASSERT(length <= 32768);
|
|
ASSERT(pDst != NULL);
|
|
ASSERT(pSrc != NULL);
|
|
|
|
while (length--){
|
|
// *(((u8*)pDst)++) = *(((u8*)pSrc)++);
|
|
*((u8*)pDst) = *((u8*)pSrc);
|
|
pDst++;
|
|
pSrc++;
|
|
}
|
|
}
|
|
|
|
|
|
void CALLCONV Amdmemset(void *pBuf, u8 val, u32 length)
|
|
{
|
|
ASSERT(length <= 32768);
|
|
ASSERT(pBuf != NULL);
|
|
|
|
while (length--){
|
|
//*(((u8*)pBuf)++) = val;
|
|
*(((u8*)pBuf)) = val;
|
|
pBuf++;
|
|
}
|
|
}
|
|
|
|
|
|
u8 CALLCONV AmdBitScanReverse(u32 value)
|
|
{
|
|
u8 i;
|
|
|
|
for (i = 31; i != 0xFF; i--)
|
|
{
|
|
if (value & ((u32)1 << i))
|
|
break;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
|
|
u32 CALLCONV AmdRotateRight(u32 value, u8 size, u32 count)
|
|
{
|
|
u32 msb, mask;
|
|
ASSERT(size > 0 && size <= 32);
|
|
|
|
msb = (u32)1 << (size-1);
|
|
mask = ((msb-1) << 1) + 1;
|
|
|
|
value = value & mask;
|
|
|
|
while (count--)
|
|
{
|
|
if (value & 1)
|
|
value = (value >> 1) | msb;
|
|
else
|
|
value = value >> 1;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
u32 CALLCONV AmdRotateLeft(u32 value, u8 size, u32 count)
|
|
{
|
|
u32 msb, mask;
|
|
ASSERT(size > 0 && size <= 32);
|
|
|
|
msb = (u32)1 << (size-1);
|
|
mask = ((msb-1) << 1) + 1;
|
|
|
|
value = value & mask;
|
|
|
|
while (count--)
|
|
{
|
|
if (value & msb)
|
|
value = ((value << 1) & mask) | (u32)1;
|
|
else
|
|
value = ((value << 1) & mask);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
void CALLCONV AmdPCIRead(SBDFO loc, u32 *Value)
|
|
{
|
|
/* Use coreboot PCI functions */
|
|
*Value = pci_read_config32((loc & 0xFFFFF000), SBDFO_OFF(loc));
|
|
}
|
|
|
|
|
|
void CALLCONV AmdPCIWrite(SBDFO loc, u32 *Value)
|
|
{
|
|
/* Use coreboot PCI functions */
|
|
pci_write_config32((loc & 0xFFFFF000), SBDFO_OFF(loc), *Value);
|
|
}
|
|
|
|
|
|
void CALLCONV AmdMSRRead(uint32 Address, uint64 *Value)
|
|
{
|
|
msr_t msr;
|
|
|
|
msr = rdmsr(Address);
|
|
Value->lo = msr.lo;
|
|
Value->hi = msr.hi;
|
|
}
|
|
|
|
|
|
void CALLCONV AmdMSRWrite(uint32 Address, uint64 *Value)
|
|
{
|
|
msr_t msr;
|
|
|
|
msr.lo = Value->lo;
|
|
msr.hi = Value->hi;
|
|
wrmsr(Address, msr);
|
|
}
|
|
|
|
|
|
void ErrorStop(u32 value)
|
|
{
|
|
printk(BIOS_DEBUG, "Error: %08x ", value);
|
|
|
|
}
|
|
|
|
/*;----------------------------------------------------------------------------
|
|
; void __pascal ErrorStop(DWORD Value);
|
|
;
|
|
; This implementation provides a rotating display of the error code on the
|
|
; a port 80h POST display card. The rotation is used to make it easier to
|
|
; view the error on both a 16-bit as well as a 32-bit display card.
|
|
;
|
|
; For use with SimNow the unrotated error code is also written to port 84h
|
|
ErrorStop PROC FAR PASCAL PUBLIC Value:DWORD
|
|
pushad
|
|
mov eax, Value
|
|
mov bx, 0DEADh
|
|
out 84h, eax
|
|
|
|
ErrorStopTop:
|
|
out 80h, eax
|
|
|
|
mov cx, 4 ; Rotate the display by one nibble
|
|
@@:
|
|
bt bx, 15
|
|
rcl eax, 1
|
|
rcl bx, 1
|
|
loop @B
|
|
|
|
|
|
push eax ; Delay a few hundred milliseconds
|
|
push ebx
|
|
mov ecx, 10h ; TSC
|
|
db 00Fh, 032h ; RDMSR
|
|
mov ebx, eax
|
|
@@:
|
|
db 00Fh, 032h ; RDMSR
|
|
sub eax, ebx
|
|
cmp eax, 500000000
|
|
jb @B
|
|
pop ebx
|
|
pop eax
|
|
|
|
jmp ErrorStopTop
|
|
|
|
popad
|
|
ret
|
|
ErrorStop ENDP
|
|
*/
|