platform.c revision 71d7fec4
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