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