171d7fec4Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/panel/platform.c,v 1.3tsi Exp $ */
271d7fec4Smrg/*
371d7fec4Smrg * $Workfile: platform.c $
471d7fec4Smrg * $Revision: 1.1.1.1 $
571d7fec4Smrg *
671d7fec4Smrg * File Contents: This file contains platform dependent functions
771d7fec4Smrg *                which provide interface to that platform.
871d7fec4Smrg *
971d7fec4Smrg *
1071d7fec4Smrg * SubModule:     Geode FlatPanel library
1171d7fec4Smrg *
1271d7fec4Smrg */
1371d7fec4Smrg
1471d7fec4Smrg/*
1571d7fec4Smrg * NSC_LIC_ALTERNATIVE_PREAMBLE
1671d7fec4Smrg *
1771d7fec4Smrg * Revision 1.0
1871d7fec4Smrg *
1971d7fec4Smrg * National Semiconductor Alternative GPL-BSD License
2071d7fec4Smrg *
2171d7fec4Smrg * National Semiconductor Corporation licenses this software
2271d7fec4Smrg * ("Software"):
2371d7fec4Smrg *
2471d7fec4Smrg * Panel Library
2571d7fec4Smrg *
2671d7fec4Smrg * under one of the two following licenses, depending on how the
2771d7fec4Smrg * Software is received by the Licensee.
2871d7fec4Smrg *
2971d7fec4Smrg * If this Software is received as part of the Linux Framebuffer or
3071d7fec4Smrg * other GPL licensed software, then the GPL license designated
3171d7fec4Smrg * NSC_LIC_GPL applies to this Software; in all other circumstances
3271d7fec4Smrg * then the BSD-style license designated NSC_LIC_BSD shall apply.
3371d7fec4Smrg *
3471d7fec4Smrg * END_NSC_LIC_ALTERNATIVE_PREAMBLE */
3571d7fec4Smrg
3671d7fec4Smrg/* NSC_LIC_BSD
3771d7fec4Smrg *
3871d7fec4Smrg * National Semiconductor Corporation Open Source License for
3971d7fec4Smrg *
4071d7fec4Smrg * Panel Library
4171d7fec4Smrg *
4271d7fec4Smrg * (BSD License with Export Notice)
4371d7fec4Smrg *
4471d7fec4Smrg * Copyright (c) 1999-2001
4571d7fec4Smrg * National Semiconductor Corporation.
4671d7fec4Smrg * All rights reserved.
4771d7fec4Smrg *
4871d7fec4Smrg * Redistribution and use in source and binary forms, with or without
4971d7fec4Smrg * modification, are permitted provided that the following conditions
5071d7fec4Smrg * are met:
5171d7fec4Smrg *
5271d7fec4Smrg *   * Redistributions of source code must retain the above copyright
5371d7fec4Smrg *     notice, this list of conditions and the following disclaimer.
5471d7fec4Smrg *
5571d7fec4Smrg *   * Redistributions in binary form must reproduce the above
5671d7fec4Smrg *     copyright notice, this list of conditions and the following
5771d7fec4Smrg *     disclaimer in the documentation and/or other materials provided
5871d7fec4Smrg *     with the distribution.
5971d7fec4Smrg *
6071d7fec4Smrg *   * Neither the name of the National Semiconductor Corporation nor
6171d7fec4Smrg *     the names of its contributors may be used to endorse or promote
6271d7fec4Smrg *     products derived from this software without specific prior
6371d7fec4Smrg *     written permission.
6471d7fec4Smrg *
6571d7fec4Smrg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6671d7fec4Smrg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6771d7fec4Smrg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
6871d7fec4Smrg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
6971d7fec4Smrg * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
7071d7fec4Smrg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7171d7fec4Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
7271d7fec4Smrg * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
7371d7fec4Smrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
7471d7fec4Smrg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
7571d7fec4Smrg * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
7671d7fec4Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
7771d7fec4Smrg * OF SUCH DAMAGE.
7871d7fec4Smrg *
7971d7fec4Smrg * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
8071d7fec4Smrg * YOUR JURISDICTION. It is licensee's responsibility to comply with
8171d7fec4Smrg * any export regulations applicable in licensee's jurisdiction. Under
8271d7fec4Smrg * CURRENT (2001) U.S. export regulations this software
8371d7fec4Smrg * is eligible for export from the U.S. and can be downloaded by or
8471d7fec4Smrg * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
8571d7fec4Smrg * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
8671d7fec4Smrg * Syria, Sudan, Afghanistan and any other country to which the U.S.
8771d7fec4Smrg * has embargoed goods and services.
8871d7fec4Smrg *
8971d7fec4Smrg * END_NSC_LIC_BSD */
9071d7fec4Smrg
9171d7fec4Smrg/* NSC_LIC_GPL
9271d7fec4Smrg *
9371d7fec4Smrg * National Semiconductor Corporation Gnu General Public License for
9471d7fec4Smrg *
9571d7fec4Smrg * Panel Library
9671d7fec4Smrg *
9771d7fec4Smrg * (GPL License with Export Notice)
9871d7fec4Smrg *
9971d7fec4Smrg * Copyright (c) 1999-2001
10071d7fec4Smrg * National Semiconductor Corporation.
10171d7fec4Smrg * All rights reserved.
10271d7fec4Smrg *
10371d7fec4Smrg * Redistribution and use in source and binary forms, with or without
10471d7fec4Smrg * modification, are permitted under the terms of the GNU General
10571d7fec4Smrg * Public License as published by the Free Software Foundation; either
10671d7fec4Smrg * version 2 of the License, or (at your option) any later version
10771d7fec4Smrg *
10871d7fec4Smrg * In addition to the terms of the GNU General Public License, neither
10971d7fec4Smrg * the name of the National Semiconductor Corporation nor the names of
11071d7fec4Smrg * its contributors may be used to endorse or promote products derived
11171d7fec4Smrg * from this software without specific prior written permission.
11271d7fec4Smrg *
11371d7fec4Smrg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
11471d7fec4Smrg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11571d7fec4Smrg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11671d7fec4Smrg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
11771d7fec4Smrg * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
11871d7fec4Smrg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
11971d7fec4Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
12071d7fec4Smrg * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
12171d7fec4Smrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
12271d7fec4Smrg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
12371d7fec4Smrg * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
12471d7fec4Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
12571d7fec4Smrg * OF SUCH DAMAGE. See the GNU General Public License for more details.
12671d7fec4Smrg *
12771d7fec4Smrg * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
12871d7fec4Smrg * YOUR JURISDICTION. It is licensee's responsibility to comply with
12971d7fec4Smrg * any export regulations applicable in licensee's jurisdiction. Under
13071d7fec4Smrg * CURRENT (2001) U.S. export regulations this software
13171d7fec4Smrg * is eligible for export from the U.S. and can be downloaded by or
13271d7fec4Smrg * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
13371d7fec4Smrg * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
13471d7fec4Smrg * Syria, Sudan, Afghanistan and any other country to which the U.S.
13571d7fec4Smrg * has embargoed goods and services.
13671d7fec4Smrg *
13771d7fec4Smrg * You should have received a copy of the GNU General Public License
13871d7fec4Smrg * along with this file; if not, write to the Free Software Foundation,
13971d7fec4Smrg * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14071d7fec4Smrg *
14171d7fec4Smrg * END_NSC_LIC_GPL */
14271d7fec4Smrg
14371d7fec4Smrg#define LINUX_ROM_SEGMENT 0x000F
14471d7fec4Smrg#define SEGMENT_LENGTH  0xFFFF
14571d7fec4Smrg#define PAGE_LENGTH     0x1000
14671d7fec4Smrg#define SYS_BOARD_NAME_LEN 24
14771d7fec4Smrg
14871d7fec4Smrg#define PLT_READ         0
14971d7fec4Smrg#define PLT_WRITE        1
15071d7fec4Smrg#define PLT_WRITE_BYTES  2
15171d7fec4Smrg#define PLT_READ_BYTES   3
15271d7fec4Smrg#define PLT_WRITE_WORDS  4
15371d7fec4Smrg#define PLT_READ_WORDS   5
15471d7fec4Smrg#define PLT_WRITE_DWORDS 6
15571d7fec4Smrg#define PLT_READ_DWORDS  7
15671d7fec4Smrg#define PLT_UNKNOWN	 ((SYS_BOARD) 0xFFFF)
15771d7fec4Smrg
15871d7fec4Smrgtypedef struct
15971d7fec4Smrg{
16071d7fec4Smrg   char sys_board_name[SYS_BOARD_NAME_LEN];
16171d7fec4Smrg   SYS_BOARD sys_board;
16271d7fec4Smrg}
16371d7fec4SmrgSYS_BOARD_INFO;
16471d7fec4Smrg
16571d7fec4Smrgstatic SYS_BOARD_INFO Sys_info;
16671d7fec4Smrg
16771d7fec4Smrg/*
16871d7fec4Smrg * The names in the sys_board_name string must exactly match the names in the
16971d7fec4Smrg * BIOS header. These names are used by FindStringInSeg() to find the names
17071d7fec4Smrg * in the BIOS header space. The BIOS does not use OTHER; it is a dummy value
17171d7fec4Smrg * for program useonly.
17271d7fec4Smrg *
17371d7fec4Smrg */
17471d7fec4Smrg
17571d7fec4SmrgSYS_BOARD_INFO Sys_board_info_array[] = {
17671d7fec4Smrg   {"Marmot", MARMOT_PLATFORM},
17771d7fec4Smrg   {"Unicorn", UNICORN_PLATFORM},
17871d7fec4Smrg   {"Centaurus", CENTAURUS_PLATFORM},
17971d7fec4Smrg   {"Aries", ARIES_PLATFORM},
18071d7fec4Smrg   {"Carmel", CARMEL_PLATFORM},
18171d7fec4Smrg   {"Hyrda", HYDRA_PLATFORM},
18271d7fec4Smrg   {"Dorado", DORADO_PLATFORM},
18371d7fec4Smrg   {"Redcloud", REDCLOUD_PLATFORM},
18471d7fec4Smrg   {"Other", OTHER_PLATFORM}
18571d7fec4Smrg};
18671d7fec4Smrg
18771d7fec4Smrg#define NUM_SYS_BOARD_TYPES sizeof(Sys_board_info_array)/sizeof(SYS_BOARD_INFO)
18871d7fec4Smrg
18971d7fec4Smrgstatic int Num_sys_board_type = NUM_SYS_BOARD_TYPES;
19071d7fec4SmrgSYS_BOARD_INFO *Sys_board_array_base = Sys_board_info_array;
19171d7fec4Smrgint FindStringInSeg(unsigned int, char *);
19271d7fec4Smrgstatic unsigned char get_sys_board_type(SYS_BOARD_INFO *, SYS_BOARD_INFO *);
19371d7fec4Smrg
19471d7fec4Smrg#if defined(linux) && !defined(__KERNEL__)
19571d7fec4Smrg#if !defined(XFree86Server)
19671d7fec4Smrgstatic void platform_protected_mode_access(unsigned int, unsigned int,
19771d7fec4Smrg					   unsigned long, unsigned char *);
19871d7fec4Smrgstatic void setup_pma();
19971d7fec4Smrgstatic void close_pma();
20071d7fec4Smrgstatic int fd;
20171d7fec4Smrg#endif /* IN_MODULE */
20271d7fec4Smrg#endif /* __KERNEL__ */
20371d7fec4Smrg
20471d7fec4Smrg/* Detect the Platform */
20571d7fec4Smrgint
20671d7fec4SmrgDetect_Platform(void)
20771d7fec4Smrg{
20871d7fec4Smrg#if defined(linux) && !defined(__KERNEL__)
20971d7fec4Smrg#if !defined(XFree86Server)
21071d7fec4Smrg   setup_pma();
21171d7fec4Smrg#endif /* IN_MODULE */
21271d7fec4Smrg#endif /* __KERNEL__ */
21371d7fec4Smrg
21471d7fec4Smrg   /* See if we can find the board name using Xpressrom */
21571d7fec4Smrg   if (get_sys_board_type(&Sys_info, Sys_board_array_base) == TRUE) {
21671d7fec4Smrg#if 0
21771d7fec4Smrg      if (Sys_info.sys_board == CENTAURUS_PLATFORM) {
21871d7fec4Smrg	 printk("CENTAURUS Platform Found\n");
21971d7fec4Smrg      } else if (Sys_info.sys_board == DORADO_PLATFORM) {
22071d7fec4Smrg	 printk("DORADO Platform Found \n");
22171d7fec4Smrg      } else {
22271d7fec4Smrg	 printk("UNKNOWN Platform Found \n");
22371d7fec4Smrg      }
22471d7fec4Smrg#endif
22571d7fec4Smrg   }
22671d7fec4Smrg#if defined(linux) && !defined(__KERNEL__)
22771d7fec4Smrg#if !defined(XFree86Server)
22871d7fec4Smrg   close_pma();
22971d7fec4Smrg#endif /* IN_MODULE */
23071d7fec4Smrg#endif /* __KERNEL__ */
23171d7fec4Smrg
23271d7fec4Smrg   return (Sys_info.sys_board);
23371d7fec4Smrg}
23471d7fec4Smrg
23571d7fec4Smrgstatic int
23671d7fec4SmrgStrncmp(char *str1, char *str2, int len)
23771d7fec4Smrg{
23871d7fec4Smrg   int i;
23971d7fec4Smrg
24071d7fec4Smrg   if ((str1 == 0x0) || (str2 == 0x0) || (len == 0))
24171d7fec4Smrg      return (1);
24271d7fec4Smrg   for (i = 0; i < len; i++) {
24371d7fec4Smrg      if (*(str1 + i) > *(str2 + i)) {
24471d7fec4Smrg	 return 1;
24571d7fec4Smrg      } else if (*(str1 + i) < *(str2 + i)) {
24671d7fec4Smrg	 return -1;
24771d7fec4Smrg      }
24871d7fec4Smrg   }
24971d7fec4Smrg   return 0;
25071d7fec4Smrg}
25171d7fec4Smrg
25271d7fec4Smrgstatic char *
25371d7fec4SmrgStrcpy(char *dst, char *src)
25471d7fec4Smrg{
25571d7fec4Smrg   int i;
25671d7fec4Smrg
25771d7fec4Smrg   if ((dst == 0x0) || (src == 0x0))
25871d7fec4Smrg      return (0);
25971d7fec4Smrg   for (i = 0; src[i] != 0x0; i++) {
26071d7fec4Smrg      dst[i] = src[i];
26171d7fec4Smrg   }
26271d7fec4Smrg   dst[i] = 0x0;			/* NULL termination */
26371d7fec4Smrg   return dst;
26471d7fec4Smrg}
26571d7fec4Smrg
26671d7fec4Smrgstatic int
26771d7fec4SmrgStrlen(char *str)
26871d7fec4Smrg{
26971d7fec4Smrg   int i;
27071d7fec4Smrg
27171d7fec4Smrg   if (str == 0x0)
27271d7fec4Smrg      return 0;
27371d7fec4Smrg   for (i = 0; str[i] != 0x0; i++) ;
27471d7fec4Smrg   return i;
27571d7fec4Smrg}
27671d7fec4Smrg
27771d7fec4Smrg/***********************************************************************/
27871d7fec4Smrg
27971d7fec4Smrg/* Platform Detection Code */
28071d7fec4Smrg
28171d7fec4Smrg/***********************************************************************/
28271d7fec4Smrg
28371d7fec4Smrg/************************************************************************
28471d7fec4Smrg * int FindStringInSeg( unsigned int segment_address, char *string_ptr )
28571d7fec4Smrg * Returns the offset where the NULL terminated string pointed to by
28671d7fec4Smrg * string_ptr is located in the segment passed in segment_address.
28771d7fec4Smrg * Segment_address must be of the form 0xXXXX (i.e 0xf000 for segment f).
28871d7fec4Smrg * Returns NULL if the string is not found.
28971d7fec4Smrg ************************************************************************
29071d7fec4Smrg */
29171d7fec4Smrgint
29271d7fec4SmrgFindStringInSeg(unsigned int segment_address, char *string_ptr)
29371d7fec4Smrg{
29471d7fec4Smrg   int string_length = Strlen(string_ptr);
29571d7fec4Smrg   char *psegment_buf;
29671d7fec4Smrg   unsigned long mem_ptr = (unsigned long)segment_address << 16;
29771d7fec4Smrg   char segment_buffer[SEGMENT_LENGTH + 1];
29871d7fec4Smrg   int i, cursor = 0;
29971d7fec4Smrg
30071d7fec4Smrg   /* silence compiler */
30171d7fec4Smrg   (void)cursor;
30271d7fec4Smrg   (void)mem_ptr;
30371d7fec4Smrg   (void)segment_buffer;
30471d7fec4Smrg
30571d7fec4Smrg#if defined(linux) && !defined(XFree86Server)
30671d7fec4Smrg#ifdef __KERNEL__
30771d7fec4Smrg   XpressROMPtr = (unsigned char *)ioremap(mem_ptr, SEGMENT_LENGTH + 1);
30871d7fec4Smrg   psegment_buf = (char *)XpressROMPtr;
30971d7fec4Smrg#else
31071d7fec4Smrg   /* Fill the segment_buffer with 16 page accesses */
31171d7fec4Smrg
31271d7fec4Smrg   for (cursor = 0; (cursor * PAGE_LENGTH) < SEGMENT_LENGTH; cursor++) {
31371d7fec4Smrg      platform_protected_mode_access(PLT_READ_BYTES, PAGE_LENGTH, mem_ptr +
31471d7fec4Smrg			    (cursor * PAGE_LENGTH),
31571d7fec4Smrg			    &(segment_buffer[(cursor * PAGE_LENGTH)]));
31671d7fec4Smrg   }
31771d7fec4Smrg   psegment_buf = segment_buffer;
31871d7fec4Smrg#endif /* __KERNEL__ */
31971d7fec4Smrg#elif defined (XFree86Server)
32071d7fec4Smrg   psegment_buf = (char *)XpressROMPtr;
32171d7fec4Smrg#elif defined(_WIN32)			/* Windows */
32271d7fec4Smrg   psegment_buf = XpressROMPtr;
32371d7fec4Smrg#endif
32471d7fec4Smrg
32571d7fec4Smrg   /* Now search for the first character of the string_ptr */
32671d7fec4Smrg   for (i = 0; i < SEGMENT_LENGTH + 1; i++) {
32771d7fec4Smrg      if (*(psegment_buf + i) == *string_ptr) {
32871d7fec4Smrg
32971d7fec4Smrg	 /* If we match the first character, do a
33071d7fec4Smrg	  * string compare.
33171d7fec4Smrg	  */
33271d7fec4Smrg
33371d7fec4Smrg	 if (!Strncmp(string_ptr, (psegment_buf + i), string_length)) {
33471d7fec4Smrg	    /* They match! */
33571d7fec4Smrg	    return (1);
33671d7fec4Smrg	 }
33771d7fec4Smrg      }
33871d7fec4Smrg   }
33971d7fec4Smrg   /* if we got this far we didn't find anything.  Return NULL. */
34071d7fec4Smrg   return (0);
34171d7fec4Smrg
34271d7fec4Smrg}					/* end FindStringInSeg() */
34371d7fec4Smrg
34471d7fec4Smrg/**********************************************************************
34571d7fec4Smrg
34671d7fec4Smrg * TRUE_FALSE get_sys_board_type( SYS_BOARD_INFO *sys_info,
34771d7fec4Smrg * SYS_BOARD_INFO *sys_board_array_base)  Checks the system
34871d7fec4Smrg * BIOS area for Xpressrom information. If found, searches the  BIOS
34971d7fec4Smrg * area for one of names in the array pointed to by sys_board_array_ptr.
35071d7fec4Smrg * If a match is found, sets the SYS_INFO system_board_name string
35171d7fec4Smrg * and the system_board variable to the board name and returns TRUE.
35271d7fec4Smrg * If Xpressrom or a board is not found, sets the variables to
35371d7fec4Smrg * their default values and returns FALSE.
35471d7fec4Smrg * Uses the global string pointer *xpress_rom_string_ptr.
35571d7fec4Smrg *
35671d7fec4Smrg ***********************************************************************
35771d7fec4Smrg */
35871d7fec4Smrg
35971d7fec4Smrgstatic unsigned char
36071d7fec4Smrgget_sys_board_type(SYS_BOARD_INFO * sys_info,
36171d7fec4Smrg		   SYS_BOARD_INFO * sys_board_array_base)
36271d7fec4Smrg{
36371d7fec4Smrg   int index;
36471d7fec4Smrg   char *xpress_rom_string_ptr = "XpressStart";
36571d7fec4Smrg   unsigned int segment = LINUX_ROM_SEGMENT;
36671d7fec4Smrg
36771d7fec4Smrg   /* See if XpressStart is present in the BIOS area.
36871d7fec4Smrg    * If it is, search for a board string.  If not, Xpressrom is
36971d7fec4Smrg    * not present, set system_board information to UNKNOWN and
37071d7fec4Smrg    * return FALSE.
37171d7fec4Smrg    */
37271d7fec4Smrg
37371d7fec4Smrg   if (!FindStringInSeg(segment, xpress_rom_string_ptr)) {
37471d7fec4Smrg      sys_info->sys_board = PLT_UNKNOWN;
37571d7fec4Smrg      Strcpy(sys_info->sys_board_name, "Unknown");
37671d7fec4Smrg      return (FALSE);
37771d7fec4Smrg   } else {
37871d7fec4Smrg
37971d7fec4Smrg      /* we have Xpressrom, so look for a board */
38071d7fec4Smrg      for (index = 0; index < Num_sys_board_type; index++) {
38171d7fec4Smrg	 if (!FindStringInSeg(segment, (sys_board_array_base +
38271d7fec4Smrg					index)->sys_board_name)) {
38371d7fec4Smrg	    continue;
38471d7fec4Smrg	 } else {
38571d7fec4Smrg
38671d7fec4Smrg	    /* a match!! */
38771d7fec4Smrg	    sys_info->sys_board = (sys_board_array_base + index)->sys_board;
38871d7fec4Smrg	    Strcpy(sys_info->sys_board_name,
38971d7fec4Smrg		   (sys_board_array_base + index)->sys_board_name);
39071d7fec4Smrg	    return (TRUE);
39171d7fec4Smrg	 }
39271d7fec4Smrg      }					/* end for() */
39371d7fec4Smrg   }					/* end else */
39471d7fec4Smrg
39571d7fec4Smrg   /* if we are here we have failed */
39671d7fec4Smrg   sys_info->sys_board = PLT_UNKNOWN;
39771d7fec4Smrg   Strcpy(sys_info->sys_board_name, "Unknown");
39871d7fec4Smrg   return (FALSE);
39971d7fec4Smrg}					/* end get_sys_board_type() */
40071d7fec4Smrg
40171d7fec4Smrg#if defined(linux) && !defined(__KERNEL__)
40271d7fec4Smrg#if !defined(XFree86Server)
40371d7fec4Smrg
40471d7fec4Smrg/******************************************************************
40571d7fec4Smrg *
40671d7fec4Smrg * platform_protected_mode_access( unsigned int mode, unsigned int width,
40771d7fec4Smrg * unsigned long addr, unsigned char* pdata )
40871d7fec4Smrg * This function provides access to physical memory
40971d7fec4Smrg * at the requested address.
41071d7fec4Smrg * mode is: PLT_READ or PLT_WRITE (accesses a single byte, word
41171d7fec4Smrg * or double word depending on the value of "width".
41271d7fec4Smrg * Only 1, 2 or 4 supported).
41371d7fec4Smrg * PLT_READ_BYTES, PLT_WRITE_BYTES accesses "width" number
41471d7fec4Smrg * of bytes (8 bits)
41571d7fec4Smrg * PLT_READ_WORDS, PLT_WRITE_WORDS accesses "width" number
41671d7fec4Smrg * of words (16 bits) PLT_READ_DWORDS, PLT_WRITE_DWORDS accesses
41771d7fec4Smrg * "width" number of dwords (32 bits)
41871d7fec4Smrg * width is: The size of the access.
41971d7fec4Smrg * For PLT_READ or PLT_WRITE, only 1, 2 and 4 are
42071d7fec4Smrg * supported.  For other modes, width is not limited but
42171d7fec4Smrg * will cause paging if the block traverses page boundaries.
42271d7fec4Smrg * addr is: The physical address being accessed
42371d7fec4Smrg * pdata is: A pointer to the data to be read or written into.
42471d7fec4Smrg * NOTE! WORD or DWORD accesses can only be made on
42571d7fec4Smrg * WORD or DWORD boundaries!
42671d7fec4Smrg *
42771d7fec4Smrg ******************************************************************
42871d7fec4Smrg */
42971d7fec4Smrg
43071d7fec4Smrgstatic void
43171d7fec4Smrgplatform_protected_mode_access(unsigned int mode, unsigned int width,
43271d7fec4Smrg		      unsigned long addr, unsigned char *pdata)
43371d7fec4Smrg{
43471d7fec4Smrg
43571d7fec4Smrg#define PMTRASH 0x12345678L
43671d7fec4Smrg
43771d7fec4Smrg   unsigned long base;			/* The physical page address */
43871d7fec4Smrg   int length = 0x1000;			/* the page size is 4k */
43971d7fec4Smrg   unsigned int offset = 0;		/* The physical addr offset into page */
44071d7fec4Smrg   unsigned int index = 0;		/* Used to read/write from/to a block */
44171d7fec4Smrg   unsigned int chunk = 0;		/* The amount to read/wr from THIS block */
44271d7fec4Smrg   unsigned int size = 0;		/* Data size shift value (to avoid math) */
44371d7fec4Smrg   static void *ptr;			/* pointer to real memory location. */
44471d7fec4Smrg
44571d7fec4Smrg   static unsigned long lastbase = PMTRASH;
44671d7fec4Smrg
44771d7fec4Smrg   /* temp storage of previous base used. */
44871d7fec4Smrg   /* type specific buffer pointers */
44971d7fec4Smrg   unsigned char *byte_data = (unsigned char *)pdata;
45071d7fec4Smrg   unsigned int *word_data = (unsigned int *)pdata;
45171d7fec4Smrg   unsigned long *dword_data = (unsigned long *)pdata;
45271d7fec4Smrg
45371d7fec4Smrg   switch (mode) {
45471d7fec4Smrg
45571d7fec4Smrg   case PLT_READ_WORDS:
45671d7fec4Smrg   case PLT_WRITE_WORDS:
45771d7fec4Smrg
45871d7fec4Smrg      size = 1;
45971d7fec4Smrg      break;
46071d7fec4Smrg
46171d7fec4Smrg   case PLT_READ_DWORDS:
46271d7fec4Smrg   case PLT_WRITE_DWORDS:
46371d7fec4Smrg
46471d7fec4Smrg      size = 2;
46571d7fec4Smrg   }
46671d7fec4Smrg
46771d7fec4Smrg   /* Check if we're in the user accessable range */
46871d7fec4Smrg   if (addr < 0xFF000000L) {
46971d7fec4Smrg
47071d7fec4Smrg      /* We get physical memory in "pages", defined by the
47171d7fec4Smrg       * following "base" address and the "offset" into it.
47271d7fec4Smrg       * "base" will be used with mmap to get "ptr", which
47371d7fec4Smrg       * points to the memory mapped actual physical memory at
47471d7fec4Smrg       * the address pointed-to by "base".
47571d7fec4Smrg       * "width" and "chunk" are in units of whatever data
47671d7fec4Smrg       * type we're reading.
47771d7fec4Smrg       * "length" and "offset" are in units of bytes.
47871d7fec4Smrg       * "width" and "chunk" must be adjusted with "<<size"
47971d7fec4Smrg       * to use with "length" or "offset".  Similarly, the
48071d7fec4Smrg       * result must be adjusted with ">>size" to make into the
48171d7fec4Smrg       * proper type units when done.
48271d7fec4Smrg       */
48371d7fec4Smrg      base = addr & 0xFFFFF000L;
48471d7fec4Smrg      offset = addr & 0x00000FFFL;
48571d7fec4Smrg      do {
48671d7fec4Smrg	 if ((offset + (width << size)) > length) {
48771d7fec4Smrg
48871d7fec4Smrg	    /* Block being read extends beyond the
48971d7fec4Smrg	     * page boundary. Adjust things.
49071d7fec4Smrg	     */
49171d7fec4Smrg	    chunk = (length - offset) >> size;
49271d7fec4Smrg
49371d7fec4Smrg	    /* Figure the chunk size */
49471d7fec4Smrg	    width -= chunk;
49571d7fec4Smrg
49671d7fec4Smrg	    /* Reduce width by the current chunk */
49771d7fec4Smrg	 } else {
49871d7fec4Smrg
49971d7fec4Smrg	    /* Block being read is within the
50071d7fec4Smrg	     * page boundary.
50171d7fec4Smrg	     */
50271d7fec4Smrg	    chunk = width;
50371d7fec4Smrg	    width = 0;
50471d7fec4Smrg
50571d7fec4Smrg	    /* set to zero so we'll exit at the end */
50671d7fec4Smrg
50771d7fec4Smrg	 }
50871d7fec4Smrg	 /* We keep the page around in case we need to
50971d7fec4Smrg	  * access it again.
51071d7fec4Smrg	  * This saves us some time if we have consecutive
51171d7fec4Smrg	  * accesses.
51271d7fec4Smrg	  */
51371d7fec4Smrg
51471d7fec4Smrg	 if (base != lastbase) {
51571d7fec4Smrg
51671d7fec4Smrg	    /* we haven't mmap'd this address
51771d7fec4Smrg	     * Have to get a new page.  Free the
51871d7fec4Smrg	     * previous page, if it's valid  (ie, not
51971d7fec4Smrg	     * PMTRASH). If not, unmap it and get the
52071d7fec4Smrg	     * new page.
52171d7fec4Smrg	     */
52271d7fec4Smrg	    if (lastbase != PMTRASH)
52371d7fec4Smrg	       munmap(ptr, length);
52471d7fec4Smrg	    ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
52571d7fec4Smrg		       base);
52671d7fec4Smrg	    if ((int)ptr == -1) {
52771d7fec4Smrg	       lastbase = PMTRASH;
52871d7fec4Smrg	       return;			/* error */
52971d7fec4Smrg	    }
53071d7fec4Smrg	 }
53171d7fec4Smrg
53271d7fec4Smrg	 /* Now we're ready to get the data.
53371d7fec4Smrg	  * It's pure memory access now, no funny
53471d7fec4Smrg	  * function calls, however we do cast things to get
53571d7fec4Smrg	  * the right size data.
53671d7fec4Smrg	  */
53771d7fec4Smrg
53871d7fec4Smrg	 /* Scale the offset for the data type size */
53971d7fec4Smrg	 index = offset >> size;
54071d7fec4Smrg
54171d7fec4Smrg	 /* Note that the above line and below lines,
54271d7fec4Smrg	  * which shift "offset", discard address information
54371d7fec4Smrg	  * if you happen to be trying to write, for example,
54471d7fec4Smrg	  * dwords on non-dword boundaries.
54571d7fec4Smrg	  */
54671d7fec4Smrg	 /* Note that cases PLT_READ and PLT_WRITE don't
54771d7fec4Smrg	  * use "index". They shift "offset"  on their own.
54871d7fec4Smrg	  * This is because in PLT_READ and PLT_WRITE modes,
54971d7fec4Smrg	  * the information on the size of the data
55071d7fec4Smrg	  * transaction is in the "width" variable not "size".
55171d7fec4Smrg	  * We also need separate cases to cast the values
55271d7fec4Smrg	  * right.
55371d7fec4Smrg	  */
55471d7fec4Smrg	 switch (mode) {
55571d7fec4Smrg
55671d7fec4Smrg	 case PLT_READ:{
55771d7fec4Smrg
55871d7fec4Smrg	       switch (chunk) {
55971d7fec4Smrg
56071d7fec4Smrg	       case FOUR_BYTES:
56171d7fec4Smrg
56271d7fec4Smrg		  *(dword_data) = (unsigned long)
56371d7fec4Smrg			(*(((unsigned long *)ptr) + (offset >> 2)));
56471d7fec4Smrg		  break;
56571d7fec4Smrg
56671d7fec4Smrg	       case TWO_BYTES:
56771d7fec4Smrg
56871d7fec4Smrg		  *(word_data) = (unsigned int)
56971d7fec4Smrg			(*(((unsigned int *)ptr) + (offset >> 1)));
57071d7fec4Smrg		  break;
57171d7fec4Smrg
57271d7fec4Smrg	       default:
57371d7fec4Smrg
57471d7fec4Smrg		  *(byte_data) = (unsigned char)
57571d7fec4Smrg			(*(((unsigned char *)ptr) + (offset)));
57671d7fec4Smrg		  break;
57771d7fec4Smrg
57871d7fec4Smrg	       }			/* end switch() */
57971d7fec4Smrg	       break;
58071d7fec4Smrg
58171d7fec4Smrg	    }				/* end case PLT_READ */
58271d7fec4Smrg
58371d7fec4Smrg	 case PLT_WRITE:{
58471d7fec4Smrg
58571d7fec4Smrg	       switch (chunk) {
58671d7fec4Smrg
58771d7fec4Smrg	       case FOUR_BYTES:
58871d7fec4Smrg
58971d7fec4Smrg		  *(((unsigned long *)ptr) + (offset >> 2)) = *dword_data;
59071d7fec4Smrg		  break;
59171d7fec4Smrg
59271d7fec4Smrg	       case TWO_BYTES:
59371d7fec4Smrg
59471d7fec4Smrg		  *(((unsigned int *)ptr) + (offset >> 1)) = *word_data;
59571d7fec4Smrg		  break;
59671d7fec4Smrg
59771d7fec4Smrg	       default:
59871d7fec4Smrg
59971d7fec4Smrg		  *(((unsigned char *)ptr) + (offset)) = *byte_data;
60071d7fec4Smrg		  break;
60171d7fec4Smrg	       }			/* end switch() */
60271d7fec4Smrg	       break;
60371d7fec4Smrg
60471d7fec4Smrg	    }				/* end case PLT_WRITE */
60571d7fec4Smrg
60671d7fec4Smrg	 case PLT_READ_BYTES:{
60771d7fec4Smrg
60871d7fec4Smrg	       for (; chunk > 0; chunk--) {
60971d7fec4Smrg
61071d7fec4Smrg		  *(byte_data++) = (unsigned char)(*(((unsigned char *)ptr) +
61171d7fec4Smrg						     (index++)));
61271d7fec4Smrg	       }
61371d7fec4Smrg	       break;
61471d7fec4Smrg	    }				/* end case PLT_READ_BYTES */
61571d7fec4Smrg
61671d7fec4Smrg	 case PLT_WRITE_BYTES:{
61771d7fec4Smrg
61871d7fec4Smrg	       for (; chunk > 0; chunk--) {
61971d7fec4Smrg		  *(((unsigned char *)ptr) + (index++)) = *(byte_data++);
62071d7fec4Smrg	       }
62171d7fec4Smrg	       break;
62271d7fec4Smrg
62371d7fec4Smrg	    }				/* end case PLT_WRITE_BYTES */
62471d7fec4Smrg
62571d7fec4Smrg	 case PLT_READ_WORDS:{
62671d7fec4Smrg
62771d7fec4Smrg	       for (; chunk > 0; chunk--) {
62871d7fec4Smrg
62971d7fec4Smrg		  *(word_data++) = (unsigned int)
63071d7fec4Smrg			(*(((unsigned int *)ptr) + (index++)));
63171d7fec4Smrg	       }
63271d7fec4Smrg	       break;
63371d7fec4Smrg
63471d7fec4Smrg	    }				/* end case PLT_READ_WORDS */
63571d7fec4Smrg
63671d7fec4Smrg	 case PLT_WRITE_WORDS:{
63771d7fec4Smrg
63871d7fec4Smrg	       for (; chunk > 0; chunk--) {
63971d7fec4Smrg
64071d7fec4Smrg		  *(((unsigned int *)ptr) + (index++)) = *(word_data++);
64171d7fec4Smrg	       }
64271d7fec4Smrg	       break;
64371d7fec4Smrg
64471d7fec4Smrg	    }				/* end case PLT_WRITE_WORDS */
64571d7fec4Smrg
64671d7fec4Smrg	 case PLT_READ_DWORDS:{
64771d7fec4Smrg
64871d7fec4Smrg	       for (; chunk > 0; chunk--) {
64971d7fec4Smrg
65071d7fec4Smrg		  *(dword_data++) = (*(((unsigned long *)ptr) + (index++)));
65171d7fec4Smrg	       }
65271d7fec4Smrg	       break;
65371d7fec4Smrg
65471d7fec4Smrg	    }				/* end case PLT_READ_DWORDS */
65571d7fec4Smrg
65671d7fec4Smrg	 case PLT_WRITE_DWORDS:{
65771d7fec4Smrg
65871d7fec4Smrg	       for (; chunk > 0; chunk--) {
65971d7fec4Smrg
66071d7fec4Smrg		  *(((unsigned long *)ptr) + (index++))
66171d7fec4Smrg			= *(dword_data++);
66271d7fec4Smrg	       }
66371d7fec4Smrg	       break;
66471d7fec4Smrg
66571d7fec4Smrg	    }				/* end case PLT_WRITE_DWORDS */
66671d7fec4Smrg
66771d7fec4Smrg	 }				/* end switch(mode) */
66871d7fec4Smrg
66971d7fec4Smrg	 lastbase = base;
67071d7fec4Smrg
67171d7fec4Smrg	 /* Save the page we've just processed. */
67271d7fec4Smrg
67371d7fec4Smrg	 if (width) {
67471d7fec4Smrg
67571d7fec4Smrg	    /* If there's still width left to get. */
67671d7fec4Smrg
67771d7fec4Smrg	    base += length;
67871d7fec4Smrg	    /* Increment to the next page. */
67971d7fec4Smrg
68071d7fec4Smrg	    offset = 0;
68171d7fec4Smrg	    /* Set the offset to zero. */
68271d7fec4Smrg	 }
68371d7fec4Smrg
68471d7fec4Smrg      } while (width);			/* While there's still data to get. */
68571d7fec4Smrg      return;
68671d7fec4Smrg
68771d7fec4Smrg   } /* end for if addr */
68871d7fec4Smrg   else {
68971d7fec4Smrg
69071d7fec4Smrg      printf("PMA error: Unable to read ROM address space\n");
69171d7fec4Smrg      exit(1);
69271d7fec4Smrg   }
69371d7fec4Smrg   return;
69471d7fec4Smrg}
69571d7fec4Smrg
69671d7fec4Smrg/************************************************************************
69771d7fec4Smrg * setup_pma() loads the ROM memory access module and initializes
69871d7fec4Smrg * memory access file descriptor (access is handled through a file-like
69971d7fec4Smrg * interface).
70071d7fec4Smrg ************************************************************************
70171d7fec4Smrg */
70271d7fec4Smrgstatic void
70371d7fec4Smrgsetup_pma()
70471d7fec4Smrg{
70571d7fec4Smrg   fd = open("/dev/mem", 2);		/*  O_RDWR */
70671d7fec4Smrg   if (fd == -1) {
70771d7fec4Smrg
70871d7fec4Smrg      printf("Error: Unable to open /dev/mem !\a\n");
70971d7fec4Smrg      exit(1);
71071d7fec4Smrg   }
71171d7fec4Smrg   return;
71271d7fec4Smrg}
71371d7fec4Smrg
71471d7fec4Smrg/**********************************************************************
71571d7fec4Smrg * close_pma() cleans up the open memory access devices and file
71671d7fec4Smrg * descriptors.
71771d7fec4Smrg **********************************************************************
71871d7fec4Smrg */
71971d7fec4Smrgstatic void
72071d7fec4Smrgclose_pma()
72171d7fec4Smrg{
72271d7fec4Smrg   close(fd);
72371d7fec4Smrg   return;
72471d7fec4Smrg}
72571d7fec4Smrg#endif /* IN_MODULE */
72671d7fec4Smrg#endif /* linux && !__KERNEL__ */
727