2 * This file is part of the coreboot project.
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #define FILECODE 0xCCCC
25 *---------------------------------------------------------------------------
28 *---------------------------------------------------------------------------
31 void CALLCONV AmdPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
33 ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0);
35 AmdPCIRead(loc, pValue);
36 *pValue = *pValue >> lowbit; /* Shift */
38 /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
39 if ((highbit-lowbit) != 31)
40 *pValue &= (((u32)1 << (highbit-lowbit+1))-1);
44 void CALLCONV AmdPCIWriteBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
48 ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0);
50 /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
51 if ((highbit-lowbit) != 31)
52 mask = (((u32)1 << (highbit-lowbit+1))-1);
54 mask = (u32)0xFFFFFFFF;
56 AmdPCIRead(loc, &temp);
57 temp &= ~(mask << lowbit);
58 temp |= (*pValue & mask) << lowbit;
59 AmdPCIWrite(loc, &temp);
64 * Given a SBDFO this routine will find the next PCI capabilities list entry.
65 * If the end of the list of reached, or if a problem is detected, then
66 * ILLEGAL_SBDFO is returned.
68 * To start a new search from the beginning of head of the list, specify a
69 * SBDFO with a offset of zero.
71 void CALLCONV AmdPCIFindNextCap(SBDFO *pCurrent)
77 if (*pCurrent == ILLEGAL_SBDFO)
80 offset = SBDFO_OFF(*pCurrent);
81 base = *pCurrent - offset;
82 *pCurrent = ILLEGAL_SBDFO;
84 /* Verify that the SBDFO points to a valid PCI device SANITY CHECK */
85 AmdPCIRead(base, &temp);
86 if (temp == 0xFFFFFFFF)
87 return; /* There is no device at this address */
89 /* Verify that the device supports a capability list */
90 AmdPCIReadBits(base + 0x04, 20, 20, &temp);
92 return; /* This PCI device does not support capability lists */
96 /* If we are continuing on an existing list */
97 AmdPCIReadBits(base + offset, 15, 8, &temp);
101 /* We are starting on a new list */
102 AmdPCIReadBits(base + 0x34, 7, 0, &temp);
106 return; /* We have reached the end of the capabilties list */
108 /* Error detection and recovery- The statement below protects against
109 PCI devices with broken PCI capabilities lists. Detect a pointer
110 that is not u32 aligned, points into the first 64 reserved DWORDs
111 or points back to itself.
113 if (((temp & 3) != 0) || (temp == offset) || (temp < 0x40))
116 *pCurrent = base + temp;
121 void CALLCONV Amdmemcpy(void *pDst, const void *pSrc, u32 length)
123 ASSERT(length <= 32768);
124 ASSERT(pDst != NULL);
125 ASSERT(pSrc != NULL);
128 // *(((u8*)pDst)++) = *(((u8*)pSrc)++);
129 *((u8*)pDst) = *((u8*)pSrc);
136 void CALLCONV Amdmemset(void *pBuf, u8 val, u32 length)
138 ASSERT(length <= 32768);
139 ASSERT(pBuf != NULL);
142 //*(((u8*)pBuf)++) = val;
143 *(((u8*)pBuf)) = val;
149 u8 CALLCONV AmdBitScanReverse(u32 value)
153 for (i = 31; i != 0xFF; i--)
155 if (value & ((u32)1 << i))
163 u32 CALLCONV AmdRotateRight(u32 value, u8 size, u32 count)
166 ASSERT(size > 0 && size <= 32);
168 msb = (u32)1 << (size-1);
169 mask = ((msb-1) << 1) + 1;
171 value = value & mask;
176 value = (value >> 1) | msb;
185 u32 CALLCONV AmdRotateLeft(u32 value, u8 size, u32 count)
188 ASSERT(size > 0 && size <= 32);
190 msb = (u32)1 << (size-1);
191 mask = ((msb-1) << 1) + 1;
193 value = value & mask;
198 value = ((value << 1) & mask) | (u32)1;
200 value = ((value << 1) & mask);
207 void CALLCONV AmdPCIRead(SBDFO loc, u32 *Value)
209 /* Use coreboot PCI functions */
210 *Value = pci_read_config32((loc & 0xFFFFF000), SBDFO_OFF(loc));
214 void CALLCONV AmdPCIWrite(SBDFO loc, u32 *Value)
216 /* Use coreboot PCI functions */
217 pci_write_config32((loc & 0xFFFFF000), SBDFO_OFF(loc), *Value);
221 void CALLCONV AmdMSRRead(uint32 Address, uint64 *Value)
225 msr = rdmsr(Address);
231 void CALLCONV AmdMSRWrite(uint32 Address, uint64 *Value)
241 void ErrorStop(u32 value)
243 printk_debug("Error: %08x ", value);
247 /*;----------------------------------------------------------------------------
248 ; void __pascal ErrorStop(DWORD Value);
250 ; This implementation provides a rotating display of the error code on the
251 ; a port 80h POST display card. The rotation is used to make it easier to
252 ; view the error on both a 16-bit as well as a 32-bit display card.
254 ; For use with SimNow the unrotated error code is also written to port 84h
255 ErrorStop PROC FAR PASCAL PUBLIC Value:DWORD
264 mov cx, 4 ; Rotate the display by one nibble
272 push eax ; Delay a few hundred milliseconds
275 db 00Fh, 032h ; RDMSR
278 db 00Fh, 032h ; RDMSR