:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / tables / tbxfroot.c
1 /******************************************************************************
2  *
3  * Module Name: tbxfroot - Find the root ACPI table (RSDT)
4  *              $Revision$
5  *
6  *****************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 R. Byron Moore
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include "acpi.h"
28 #include "achware.h"
29 #include "actables.h"
30
31
32 #define _COMPONENT          ACPI_TABLES
33          MODULE_NAME         ("tbxfroot")
34
35 #define RSDP_CHECKSUM_LENGTH 20
36
37
38 /*******************************************************************************
39  *
40  * FUNCTION:    Acpi_find_root_pointer
41  *
42  * PARAMETERS:  **Rsdp_physical_address     - Where to place the RSDP address
43  *
44  * RETURN:      Status, Physical address of the RSDP
45  *
46  * DESCRIPTION: Find the RSDP
47  *
48  ******************************************************************************/
49
50 ACPI_STATUS
51 acpi_find_root_pointer (
52         ACPI_PHYSICAL_ADDRESS   *rsdp_physical_address)
53 {
54         ACPI_TABLE_DESC         table_info;
55         ACPI_STATUS             status;
56
57
58         /* Get the RSDP */
59
60         status = acpi_tb_find_rsdp (&table_info);
61         if (ACPI_FAILURE (status)) {
62                 return (AE_NO_ACPI_TABLES);
63         }
64
65         *rsdp_physical_address = table_info.physical_address;
66
67         return (AE_OK);
68 }
69
70
71 /*******************************************************************************
72  *
73  * FUNCTION:    Acpi_tb_scan_memory_for_rsdp
74  *
75  * PARAMETERS:  Start_address       - Starting pointer for search
76  *              Length              - Maximum length to search
77  *
78  * RETURN:      Pointer to the RSDP if found, otherwise NULL.
79  *
80  * DESCRIPTION: Search a block of memory for the RSDP signature
81  *
82  ******************************************************************************/
83
84 u8 *
85 acpi_tb_scan_memory_for_rsdp (
86         u8                      *start_address,
87         u32                     length)
88 {
89         u32                     offset;
90         u8                      *mem_rover;
91
92
93         /* Search from given start addr for the requested length  */
94
95         for (offset = 0, mem_rover = start_address;
96                  offset < length;
97                  offset += RSDP_SCAN_STEP, mem_rover += RSDP_SCAN_STEP) {
98
99                 /* The signature and checksum must both be correct */
100
101                 if (STRNCMP ((NATIVE_CHAR *) mem_rover,
102                                 RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 &&
103                         acpi_tb_checksum (mem_rover, RSDP_CHECKSUM_LENGTH) == 0) {
104                         /* If so, we have found the RSDP */
105
106                         return (mem_rover);
107                 }
108         }
109
110         /* Searched entire block, no RSDP was found */
111
112         return (NULL);
113 }
114
115
116 /*******************************************************************************
117  *
118  * FUNCTION:    Acpi_tb_find_rsdp
119  *
120  * PARAMETERS:  *Buffer_ptr             - If == NULL, read data from buffer
121  *                                        rather than searching memory
122  *              *Table_info             - Where the table info is returned
123  *
124  * RETURN:      Status
125  *
126  * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
127  *              pointer structure.  If it is found, set *RSDP to point to it.
128  *
129  *              NOTE: The RSDP must be either in the first 1_k of the Extended
130  *              BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
131  *              5.2.2; assertion #421).
132  *
133  ******************************************************************************/
134
135 ACPI_STATUS
136 acpi_tb_find_rsdp (
137         ACPI_TABLE_DESC         *table_info)
138 {
139         u8                      *table_ptr;
140         u8                      *mem_rover;
141         UINT64                  phys_addr;
142         ACPI_STATUS             status = AE_OK;
143
144
145         /*
146          * Search memory for RSDP.  First map low physical memory.
147          */
148
149         status = acpi_os_map_memory (LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE,
150                           (void **)&table_ptr);
151
152         if (ACPI_FAILURE (status)) {
153                 return (status);
154         }
155
156         /*
157          * 1) Search EBDA (low memory) paragraphs
158          */
159
160         mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, LO_RSDP_WINDOW_SIZE);
161
162         /* This mapping is no longer needed */
163
164         acpi_os_unmap_memory (table_ptr, LO_RSDP_WINDOW_SIZE);
165
166         if (mem_rover) {
167                 /* Found it, return the physical address */
168
169                 phys_addr = LO_RSDP_WINDOW_BASE;
170                 phys_addr += (mem_rover - table_ptr);
171
172                 table_info->physical_address = phys_addr;
173
174                 return (AE_OK);
175         }
176
177
178         /*
179          * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
180          */
181
182         status = acpi_os_map_memory (HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE,
183                           (void **)&table_ptr);
184
185         if (ACPI_FAILURE (status)) {
186                 return (status);
187         }
188
189         mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, HI_RSDP_WINDOW_SIZE);
190
191         /* This mapping is no longer needed */
192
193         acpi_os_unmap_memory (table_ptr, HI_RSDP_WINDOW_SIZE);
194
195         if (mem_rover) {
196                 /* Found it, return the physical address */
197
198                 phys_addr = HI_RSDP_WINDOW_BASE;
199                 phys_addr += (mem_rover - table_ptr);
200
201                 table_info->physical_address = phys_addr;
202
203                 return (AE_OK);
204         }
205
206
207         /* RSDP signature was not found */
208
209         return (AE_NOT_FOUND);
210 }
211
212