platform.c revision f29dbc25
1/* Copyright (c) 2005 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 *
21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 * */
25
26/*
27 * File Contents:   This file contains platform dependent functions
28 *                  which provide interface to that platform.
29 *
30 * SubModule:       Geode FlatPanel library
31 * */
32
33
34#define LINUX_ROM_SEGMENT 0x000F
35#define SEGMENT_LENGTH  0xFFFF
36#define PAGE_LENGTH     0x1000
37#define SYS_BOARD_NAME_LEN 24
38
39#define PLT_UNKNOWN     0xFFFF
40
41typedef struct
42{
43    char sys_board_name[SYS_BOARD_NAME_LEN];
44    SYS_BOARD sys_board;
45}
46SYS_BOARD_INFO;
47
48static SYS_BOARD_INFO Sys_info;
49
50/*
51 * The names in the sys_board_name string must exactly match the names in the
52 * BIOS header. These names are used by FindStringInSeg() to find the names
53 * in the BIOS header space. The BIOS does not use OTHER; it is a dummy value
54 * for program useonly.
55 */
56
57SYS_BOARD_INFO Sys_board_info_array[] = {
58    {"Marmot", MARMOT_PLATFORM},
59    {"Unicorn", UNICORN_PLATFORM},
60    {"Centaurus", CENTAURUS_PLATFORM},
61    {"Aries", ARIES_PLATFORM},
62    {"Carmel", CARMEL_PLATFORM},
63    {"Hyrda", HYDRA_PLATFORM},
64    {"Dorado", DORADO_PLATFORM},
65    {"Redcloud", REDCLOUD_PLATFORM},
66    {"Other", OTHER_PLATFORM}
67};
68
69#define NUM_SYS_BOARD_TYPES		\
70		sizeof(Sys_board_info_array)/sizeof(SYS_BOARD_INFO)
71
72static int Num_sys_board_type = NUM_SYS_BOARD_TYPES;
73SYS_BOARD_INFO *Sys_board_array_base = Sys_board_info_array;
74int FindStringInSeg(unsigned int, char *);
75static unsigned char get_sys_board_type(SYS_BOARD_INFO *, SYS_BOARD_INFO *);
76
77/* Detect the Platform */
78int
79Detect_Platform(void)
80{
81    /* See if we can find the board name using Xpressrom */
82    get_sys_board_type(&Sys_info, Sys_board_array_base);
83    return (Sys_info.sys_board);
84}
85
86static int
87Strncmp(char *str1, char *str2, int len)
88{
89    int i;
90
91    if ((str1 == 0x0) || (str2 == 0x0) || (len == 0))
92        return (1);
93    for (i = 0; i < len; i++) {
94        if (*(str1 + i) > *(str2 + i)) {
95            return 1;
96        } else if (*(str1 + i) < *(str2 + i)) {
97            return -1;
98        }
99    }
100    return 0;
101}
102
103static char *
104Strcpy(char *dst, char *src)
105{
106    int i;
107
108    if ((dst == 0x0) || (src == 0x0))
109        return (0);
110    for (i = 0; src[i] != 0x0; i++) {
111        dst[i] = src[i];
112    }
113    dst[i] = 0x0;                      /* NULL termination */
114    return dst;
115}
116
117static int
118Strlen(char *str)
119{
120    int i;
121
122    if (str == 0x0)
123        return 0;
124    for (i = 0; str[i] != 0x0; i++) ;
125    return i;
126}
127
128/* Platform Detection Code */
129
130/************************************************************************
131 * int FindStringInSeg( unsigned int segment_address, char *string_ptr )
132 *
133 * Returns the offset where the NULL terminated string pointed to by
134 * string_ptr is located in the segment passed in segment_address.
135 * Segment_address must be of the form 0xXXXX (i.e 0xf000 for segment f).
136 * Returns NULL if the string is not found.
137 ************************************************************************
138 */
139int
140FindStringInSeg(unsigned int segment_address, char *string_ptr)
141{
142    int string_length = Strlen(string_ptr);
143    char *psegment_buf;
144    unsigned long mem_ptr = (unsigned long)segment_address << 16;
145    unsigned int i;
146
147    /* silence compiler */
148    (void)mem_ptr;
149
150    psegment_buf = (char *)XpressROMPtr;
151
152    /* Now search for the first character of the string_ptr */
153    for (i = 0; i < SEGMENT_LENGTH + 1; i++) {
154        if (*(psegment_buf + i) == *string_ptr) {
155
156            /* If we match the first character, do a
157             * string compare.
158             */
159
160            if (!Strncmp(string_ptr, (psegment_buf + i), string_length)) {
161                /* They match! */
162                return (1);
163            }
164        }
165    }
166    /* if we got this far we didn't find anything.  Return NULL. */
167    return (0);
168
169}                                      /* end FindStringInSeg() */
170
171/**********************************************************************
172
173 * TRUE_FALSE get_sys_board_type( SYS_BOARD_INFO *sys_info,
174 * SYS_BOARD_INFO *sys_board_array_base)
175 *
176 * Checks the system BIOS area for Xpressrom information. If found, searches
177 * the  BIOS area for one of names in the array pointed to by
178 * sys_board_array_ptr.
179 * If a match is found, sets the SYS_INFO system_board_name string
180 * and the system_board variable to the board name and returns TRUE.
181 * If Xpressrom or a board is not found, sets the variables to
182 * their default values and returns FALSE.
183 * Uses the global string pointer *xpress_rom_string_ptr.
184 ***********************************************************************
185 */
186static unsigned char
187get_sys_board_type(SYS_BOARD_INFO * sys_info,
188    SYS_BOARD_INFO * sys_board_array_base)
189{
190    int index;
191    char *xpress_rom_string_ptr = "XpressStart";
192    unsigned int segment = LINUX_ROM_SEGMENT;
193
194    /* See if XpressStart is present in the BIOS area.
195     * If it is, search for a board string.  If not, Xpressrom is
196     * not present, set system_board information to UNKNOWN and
197     * return FALSE.
198     */
199
200    if (!FindStringInSeg(segment, xpress_rom_string_ptr)) {
201        sys_info->sys_board = PLT_UNKNOWN;
202        Strcpy(sys_info->sys_board_name, "Unknown");
203        return (FALSE);
204    } else {
205
206        /* we have Xpressrom, so look for a board */
207        for (index = 0; index < Num_sys_board_type; index++) {
208            if (!FindStringInSeg(segment, (sys_board_array_base +
209                        index)->sys_board_name)) {
210                continue;
211            } else {
212
213                /* a match!! */
214                sys_info->sys_board =
215                    (sys_board_array_base + index)->sys_board;
216                Strcpy(sys_info->sys_board_name,
217                    (sys_board_array_base + index)->sys_board_name);
218                return (TRUE);
219            }
220        }                              /* end for() */
221    }                                  /* end else */
222
223    /* if we are here we have failed */
224    sys_info->sys_board = PLT_UNKNOWN;
225    Strcpy(sys_info->sys_board_name, "Unknown");
226    return (FALSE);
227}                                      /* end get_sys_board_type() */
228