1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/panel/platform.c,v 1.3tsi Exp $ */ 2/* 3 * $Workfile: platform.c $ 4 * $Revision: 1.1.1.1 $ 5 * 6 * File Contents: This file contains platform dependent functions 7 * which provide interface to that platform. 8 * 9 * 10 * SubModule: Geode FlatPanel library 11 * 12 */ 13 14/* 15 * NSC_LIC_ALTERNATIVE_PREAMBLE 16 * 17 * Revision 1.0 18 * 19 * National Semiconductor Alternative GPL-BSD License 20 * 21 * National Semiconductor Corporation licenses this software 22 * ("Software"): 23 * 24 * Panel Library 25 * 26 * under one of the two following licenses, depending on how the 27 * Software is received by the Licensee. 28 * 29 * If this Software is received as part of the Linux Framebuffer or 30 * other GPL licensed software, then the GPL license designated 31 * NSC_LIC_GPL applies to this Software; in all other circumstances 32 * then the BSD-style license designated NSC_LIC_BSD shall apply. 33 * 34 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */ 35 36/* NSC_LIC_BSD 37 * 38 * National Semiconductor Corporation Open Source License for 39 * 40 * Panel Library 41 * 42 * (BSD License with Export Notice) 43 * 44 * Copyright (c) 1999-2001 45 * National Semiconductor Corporation. 46 * All rights reserved. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions 50 * are met: 51 * 52 * * Redistributions of source code must retain the above copyright 53 * notice, this list of conditions and the following disclaimer. 54 * 55 * * Redistributions in binary form must reproduce the above 56 * copyright notice, this list of conditions and the following 57 * disclaimer in the documentation and/or other materials provided 58 * with the distribution. 59 * 60 * * Neither the name of the National Semiconductor Corporation nor 61 * the names of its contributors may be used to endorse or promote 62 * products derived from this software without specific prior 63 * written permission. 64 * 65 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 66 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 67 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 68 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 69 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 70 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 71 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 72 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 73 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 74 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 75 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 76 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 77 * OF SUCH DAMAGE. 78 * 79 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 80 * YOUR JURISDICTION. It is licensee's responsibility to comply with 81 * any export regulations applicable in licensee's jurisdiction. Under 82 * CURRENT (2001) U.S. export regulations this software 83 * is eligible for export from the U.S. and can be downloaded by or 84 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 85 * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 86 * Syria, Sudan, Afghanistan and any other country to which the U.S. 87 * has embargoed goods and services. 88 * 89 * END_NSC_LIC_BSD */ 90 91/* NSC_LIC_GPL 92 * 93 * National Semiconductor Corporation Gnu General Public License for 94 * 95 * Panel Library 96 * 97 * (GPL License with Export Notice) 98 * 99 * Copyright (c) 1999-2001 100 * National Semiconductor Corporation. 101 * All rights reserved. 102 * 103 * Redistribution and use in source and binary forms, with or without 104 * modification, are permitted under the terms of the GNU General 105 * Public License as published by the Free Software Foundation; either 106 * version 2 of the License, or (at your option) any later version 107 * 108 * In addition to the terms of the GNU General Public License, neither 109 * the name of the National Semiconductor Corporation nor the names of 110 * its contributors may be used to endorse or promote products derived 111 * from this software without specific prior written permission. 112 * 113 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 114 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 115 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 116 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 117 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 118 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 119 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 120 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 121 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 122 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 123 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 124 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 125 * OF SUCH DAMAGE. See the GNU General Public License for more details. 126 * 127 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 128 * YOUR JURISDICTION. It is licensee's responsibility to comply with 129 * any export regulations applicable in licensee's jurisdiction. Under 130 * CURRENT (2001) U.S. export regulations this software 131 * is eligible for export from the U.S. and can be downloaded by or 132 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 133 * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 134 * Syria, Sudan, Afghanistan and any other country to which the U.S. 135 * has embargoed goods and services. 136 * 137 * You should have received a copy of the GNU General Public License 138 * along with this file; if not, write to the Free Software Foundation, 139 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 140 * 141 * END_NSC_LIC_GPL */ 142 143#define LINUX_ROM_SEGMENT 0x000F 144#define SEGMENT_LENGTH 0xFFFF 145#define PAGE_LENGTH 0x1000 146#define SYS_BOARD_NAME_LEN 24 147 148#define PLT_READ 0 149#define PLT_WRITE 1 150#define PLT_WRITE_BYTES 2 151#define PLT_READ_BYTES 3 152#define PLT_WRITE_WORDS 4 153#define PLT_READ_WORDS 5 154#define PLT_WRITE_DWORDS 6 155#define PLT_READ_DWORDS 7 156#define PLT_UNKNOWN ((SYS_BOARD) 0xFFFF) 157 158typedef struct 159{ 160 char sys_board_name[SYS_BOARD_NAME_LEN]; 161 SYS_BOARD sys_board; 162} 163SYS_BOARD_INFO; 164 165static SYS_BOARD_INFO Sys_info; 166 167/* 168 * The names in the sys_board_name string must exactly match the names in the 169 * BIOS header. These names are used by FindStringInSeg() to find the names 170 * in the BIOS header space. The BIOS does not use OTHER; it is a dummy value 171 * for program useonly. 172 * 173 */ 174 175SYS_BOARD_INFO Sys_board_info_array[] = { 176 {"Marmot", MARMOT_PLATFORM}, 177 {"Unicorn", UNICORN_PLATFORM}, 178 {"Centaurus", CENTAURUS_PLATFORM}, 179 {"Aries", ARIES_PLATFORM}, 180 {"Carmel", CARMEL_PLATFORM}, 181 {"Hyrda", HYDRA_PLATFORM}, 182 {"Dorado", DORADO_PLATFORM}, 183 {"Redcloud", REDCLOUD_PLATFORM}, 184 {"Other", OTHER_PLATFORM} 185}; 186 187#define NUM_SYS_BOARD_TYPES sizeof(Sys_board_info_array)/sizeof(SYS_BOARD_INFO) 188 189static int Num_sys_board_type = NUM_SYS_BOARD_TYPES; 190SYS_BOARD_INFO *Sys_board_array_base = Sys_board_info_array; 191int FindStringInSeg(unsigned int, char *); 192static unsigned char get_sys_board_type(SYS_BOARD_INFO *, SYS_BOARD_INFO *); 193 194#if defined(linux) && !defined(__KERNEL__) 195#if !defined(XFree86Server) 196static void platform_protected_mode_access(unsigned int, unsigned int, 197 unsigned long, unsigned char *); 198static void setup_pma(); 199static void close_pma(); 200static int fd; 201#endif /* IN_MODULE */ 202#endif /* __KERNEL__ */ 203 204/* Detect the Platform */ 205int 206Detect_Platform(void) 207{ 208#if defined(linux) && !defined(__KERNEL__) 209#if !defined(XFree86Server) 210 setup_pma(); 211#endif /* IN_MODULE */ 212#endif /* __KERNEL__ */ 213 214 /* See if we can find the board name using Xpressrom */ 215 if (get_sys_board_type(&Sys_info, Sys_board_array_base) == TRUE) { 216#if 0 217 if (Sys_info.sys_board == CENTAURUS_PLATFORM) { 218 printk("CENTAURUS Platform Found\n"); 219 } else if (Sys_info.sys_board == DORADO_PLATFORM) { 220 printk("DORADO Platform Found \n"); 221 } else { 222 printk("UNKNOWN Platform Found \n"); 223 } 224#endif 225 } 226#if defined(linux) && !defined(__KERNEL__) 227#if !defined(XFree86Server) 228 close_pma(); 229#endif /* IN_MODULE */ 230#endif /* __KERNEL__ */ 231 232 return (Sys_info.sys_board); 233} 234 235static int 236Strncmp(char *str1, char *str2, int len) 237{ 238 int i; 239 240 if ((str1 == 0x0) || (str2 == 0x0) || (len == 0)) 241 return (1); 242 for (i = 0; i < len; i++) { 243 if (*(str1 + i) > *(str2 + i)) { 244 return 1; 245 } else if (*(str1 + i) < *(str2 + i)) { 246 return -1; 247 } 248 } 249 return 0; 250} 251 252static char * 253Strcpy(char *dst, char *src) 254{ 255 int i; 256 257 if ((dst == 0x0) || (src == 0x0)) 258 return (0); 259 for (i = 0; src[i] != 0x0; i++) { 260 dst[i] = src[i]; 261 } 262 dst[i] = 0x0; /* NULL termination */ 263 return dst; 264} 265 266static int 267Strlen(char *str) 268{ 269 int i; 270 271 if (str == 0x0) 272 return 0; 273 for (i = 0; str[i] != 0x0; i++) ; 274 return i; 275} 276 277/***********************************************************************/ 278 279/* Platform Detection Code */ 280 281/***********************************************************************/ 282 283/************************************************************************ 284 * int FindStringInSeg( unsigned int segment_address, char *string_ptr ) 285 * Returns the offset where the NULL terminated string pointed to by 286 * string_ptr is located in the segment passed in segment_address. 287 * Segment_address must be of the form 0xXXXX (i.e 0xf000 for segment f). 288 * Returns NULL if the string is not found. 289 ************************************************************************ 290 */ 291int 292FindStringInSeg(unsigned int segment_address, char *string_ptr) 293{ 294 int string_length = Strlen(string_ptr); 295 char *psegment_buf; 296 unsigned long mem_ptr = (unsigned long)segment_address << 16; 297 char segment_buffer[SEGMENT_LENGTH + 1]; 298 int i, cursor = 0; 299 300 /* silence compiler */ 301 (void)cursor; 302 (void)mem_ptr; 303 (void)segment_buffer; 304 305#if defined(linux) && !defined(XFree86Server) 306#ifdef __KERNEL__ 307 XpressROMPtr = (unsigned char *)ioremap(mem_ptr, SEGMENT_LENGTH + 1); 308 psegment_buf = (char *)XpressROMPtr; 309#else 310 /* Fill the segment_buffer with 16 page accesses */ 311 312 for (cursor = 0; (cursor * PAGE_LENGTH) < SEGMENT_LENGTH; cursor++) { 313 platform_protected_mode_access(PLT_READ_BYTES, PAGE_LENGTH, mem_ptr + 314 (cursor * PAGE_LENGTH), 315 &(segment_buffer[(cursor * PAGE_LENGTH)])); 316 } 317 psegment_buf = segment_buffer; 318#endif /* __KERNEL__ */ 319#elif defined (XFree86Server) 320 psegment_buf = (char *)XpressROMPtr; 321#elif defined(_WIN32) /* Windows */ 322 psegment_buf = XpressROMPtr; 323#endif 324 325 /* Now search for the first character of the string_ptr */ 326 for (i = 0; i < SEGMENT_LENGTH + 1; i++) { 327 if (*(psegment_buf + i) == *string_ptr) { 328 329 /* If we match the first character, do a 330 * string compare. 331 */ 332 333 if (!Strncmp(string_ptr, (psegment_buf + i), string_length)) { 334 /* They match! */ 335 return (1); 336 } 337 } 338 } 339 /* if we got this far we didn't find anything. Return NULL. */ 340 return (0); 341 342} /* end FindStringInSeg() */ 343 344/********************************************************************** 345 346 * TRUE_FALSE get_sys_board_type( SYS_BOARD_INFO *sys_info, 347 * SYS_BOARD_INFO *sys_board_array_base) Checks the system 348 * BIOS area for Xpressrom information. If found, searches the BIOS 349 * area for one of names in the array pointed to by sys_board_array_ptr. 350 * If a match is found, sets the SYS_INFO system_board_name string 351 * and the system_board variable to the board name and returns TRUE. 352 * If Xpressrom or a board is not found, sets the variables to 353 * their default values and returns FALSE. 354 * Uses the global string pointer *xpress_rom_string_ptr. 355 * 356 *********************************************************************** 357 */ 358 359static unsigned char 360get_sys_board_type(SYS_BOARD_INFO * sys_info, 361 SYS_BOARD_INFO * sys_board_array_base) 362{ 363 int index; 364 char *xpress_rom_string_ptr = "XpressStart"; 365 unsigned int segment = LINUX_ROM_SEGMENT; 366 367 /* See if XpressStart is present in the BIOS area. 368 * If it is, search for a board string. If not, Xpressrom is 369 * not present, set system_board information to UNKNOWN and 370 * return FALSE. 371 */ 372 373 if (!FindStringInSeg(segment, xpress_rom_string_ptr)) { 374 sys_info->sys_board = PLT_UNKNOWN; 375 Strcpy(sys_info->sys_board_name, "Unknown"); 376 return (FALSE); 377 } else { 378 379 /* we have Xpressrom, so look for a board */ 380 for (index = 0; index < Num_sys_board_type; index++) { 381 if (!FindStringInSeg(segment, (sys_board_array_base + 382 index)->sys_board_name)) { 383 continue; 384 } else { 385 386 /* a match!! */ 387 sys_info->sys_board = (sys_board_array_base + index)->sys_board; 388 Strcpy(sys_info->sys_board_name, 389 (sys_board_array_base + index)->sys_board_name); 390 return (TRUE); 391 } 392 } /* end for() */ 393 } /* end else */ 394 395 /* if we are here we have failed */ 396 sys_info->sys_board = PLT_UNKNOWN; 397 Strcpy(sys_info->sys_board_name, "Unknown"); 398 return (FALSE); 399} /* end get_sys_board_type() */ 400 401#if defined(linux) && !defined(__KERNEL__) 402#if !defined(XFree86Server) 403 404/****************************************************************** 405 * 406 * platform_protected_mode_access( unsigned int mode, unsigned int width, 407 * unsigned long addr, unsigned char* pdata ) 408 * This function provides access to physical memory 409 * at the requested address. 410 * mode is: PLT_READ or PLT_WRITE (accesses a single byte, word 411 * or double word depending on the value of "width". 412 * Only 1, 2 or 4 supported). 413 * PLT_READ_BYTES, PLT_WRITE_BYTES accesses "width" number 414 * of bytes (8 bits) 415 * PLT_READ_WORDS, PLT_WRITE_WORDS accesses "width" number 416 * of words (16 bits) PLT_READ_DWORDS, PLT_WRITE_DWORDS accesses 417 * "width" number of dwords (32 bits) 418 * width is: The size of the access. 419 * For PLT_READ or PLT_WRITE, only 1, 2 and 4 are 420 * supported. For other modes, width is not limited but 421 * will cause paging if the block traverses page boundaries. 422 * addr is: The physical address being accessed 423 * pdata is: A pointer to the data to be read or written into. 424 * NOTE! WORD or DWORD accesses can only be made on 425 * WORD or DWORD boundaries! 426 * 427 ****************************************************************** 428 */ 429 430static void 431platform_protected_mode_access(unsigned int mode, unsigned int width, 432 unsigned long addr, unsigned char *pdata) 433{ 434 435#define PMTRASH 0x12345678L 436 437 unsigned long base; /* The physical page address */ 438 int length = 0x1000; /* the page size is 4k */ 439 unsigned int offset = 0; /* The physical addr offset into page */ 440 unsigned int index = 0; /* Used to read/write from/to a block */ 441 unsigned int chunk = 0; /* The amount to read/wr from THIS block */ 442 unsigned int size = 0; /* Data size shift value (to avoid math) */ 443 static void *ptr; /* pointer to real memory location. */ 444 445 static unsigned long lastbase = PMTRASH; 446 447 /* temp storage of previous base used. */ 448 /* type specific buffer pointers */ 449 unsigned char *byte_data = (unsigned char *)pdata; 450 unsigned int *word_data = (unsigned int *)pdata; 451 unsigned long *dword_data = (unsigned long *)pdata; 452 453 switch (mode) { 454 455 case PLT_READ_WORDS: 456 case PLT_WRITE_WORDS: 457 458 size = 1; 459 break; 460 461 case PLT_READ_DWORDS: 462 case PLT_WRITE_DWORDS: 463 464 size = 2; 465 } 466 467 /* Check if we're in the user accessable range */ 468 if (addr < 0xFF000000L) { 469 470 /* We get physical memory in "pages", defined by the 471 * following "base" address and the "offset" into it. 472 * "base" will be used with mmap to get "ptr", which 473 * points to the memory mapped actual physical memory at 474 * the address pointed-to by "base". 475 * "width" and "chunk" are in units of whatever data 476 * type we're reading. 477 * "length" and "offset" are in units of bytes. 478 * "width" and "chunk" must be adjusted with "<<size" 479 * to use with "length" or "offset". Similarly, the 480 * result must be adjusted with ">>size" to make into the 481 * proper type units when done. 482 */ 483 base = addr & 0xFFFFF000L; 484 offset = addr & 0x00000FFFL; 485 do { 486 if ((offset + (width << size)) > length) { 487 488 /* Block being read extends beyond the 489 * page boundary. Adjust things. 490 */ 491 chunk = (length - offset) >> size; 492 493 /* Figure the chunk size */ 494 width -= chunk; 495 496 /* Reduce width by the current chunk */ 497 } else { 498 499 /* Block being read is within the 500 * page boundary. 501 */ 502 chunk = width; 503 width = 0; 504 505 /* set to zero so we'll exit at the end */ 506 507 } 508 /* We keep the page around in case we need to 509 * access it again. 510 * This saves us some time if we have consecutive 511 * accesses. 512 */ 513 514 if (base != lastbase) { 515 516 /* we haven't mmap'd this address 517 * Have to get a new page. Free the 518 * previous page, if it's valid (ie, not 519 * PMTRASH). If not, unmap it and get the 520 * new page. 521 */ 522 if (lastbase != PMTRASH) 523 munmap(ptr, length); 524 ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 525 base); 526 if ((int)ptr == -1) { 527 lastbase = PMTRASH; 528 return; /* error */ 529 } 530 } 531 532 /* Now we're ready to get the data. 533 * It's pure memory access now, no funny 534 * function calls, however we do cast things to get 535 * the right size data. 536 */ 537 538 /* Scale the offset for the data type size */ 539 index = offset >> size; 540 541 /* Note that the above line and below lines, 542 * which shift "offset", discard address information 543 * if you happen to be trying to write, for example, 544 * dwords on non-dword boundaries. 545 */ 546 /* Note that cases PLT_READ and PLT_WRITE don't 547 * use "index". They shift "offset" on their own. 548 * This is because in PLT_READ and PLT_WRITE modes, 549 * the information on the size of the data 550 * transaction is in the "width" variable not "size". 551 * We also need separate cases to cast the values 552 * right. 553 */ 554 switch (mode) { 555 556 case PLT_READ:{ 557 558 switch (chunk) { 559 560 case FOUR_BYTES: 561 562 *(dword_data) = (unsigned long) 563 (*(((unsigned long *)ptr) + (offset >> 2))); 564 break; 565 566 case TWO_BYTES: 567 568 *(word_data) = (unsigned int) 569 (*(((unsigned int *)ptr) + (offset >> 1))); 570 break; 571 572 default: 573 574 *(byte_data) = (unsigned char) 575 (*(((unsigned char *)ptr) + (offset))); 576 break; 577 578 } /* end switch() */ 579 break; 580 581 } /* end case PLT_READ */ 582 583 case PLT_WRITE:{ 584 585 switch (chunk) { 586 587 case FOUR_BYTES: 588 589 *(((unsigned long *)ptr) + (offset >> 2)) = *dword_data; 590 break; 591 592 case TWO_BYTES: 593 594 *(((unsigned int *)ptr) + (offset >> 1)) = *word_data; 595 break; 596 597 default: 598 599 *(((unsigned char *)ptr) + (offset)) = *byte_data; 600 break; 601 } /* end switch() */ 602 break; 603 604 } /* end case PLT_WRITE */ 605 606 case PLT_READ_BYTES:{ 607 608 for (; chunk > 0; chunk--) { 609 610 *(byte_data++) = (unsigned char)(*(((unsigned char *)ptr) + 611 (index++))); 612 } 613 break; 614 } /* end case PLT_READ_BYTES */ 615 616 case PLT_WRITE_BYTES:{ 617 618 for (; chunk > 0; chunk--) { 619 *(((unsigned char *)ptr) + (index++)) = *(byte_data++); 620 } 621 break; 622 623 } /* end case PLT_WRITE_BYTES */ 624 625 case PLT_READ_WORDS:{ 626 627 for (; chunk > 0; chunk--) { 628 629 *(word_data++) = (unsigned int) 630 (*(((unsigned int *)ptr) + (index++))); 631 } 632 break; 633 634 } /* end case PLT_READ_WORDS */ 635 636 case PLT_WRITE_WORDS:{ 637 638 for (; chunk > 0; chunk--) { 639 640 *(((unsigned int *)ptr) + (index++)) = *(word_data++); 641 } 642 break; 643 644 } /* end case PLT_WRITE_WORDS */ 645 646 case PLT_READ_DWORDS:{ 647 648 for (; chunk > 0; chunk--) { 649 650 *(dword_data++) = (*(((unsigned long *)ptr) + (index++))); 651 } 652 break; 653 654 } /* end case PLT_READ_DWORDS */ 655 656 case PLT_WRITE_DWORDS:{ 657 658 for (; chunk > 0; chunk--) { 659 660 *(((unsigned long *)ptr) + (index++)) 661 = *(dword_data++); 662 } 663 break; 664 665 } /* end case PLT_WRITE_DWORDS */ 666 667 } /* end switch(mode) */ 668 669 lastbase = base; 670 671 /* Save the page we've just processed. */ 672 673 if (width) { 674 675 /* If there's still width left to get. */ 676 677 base += length; 678 /* Increment to the next page. */ 679 680 offset = 0; 681 /* Set the offset to zero. */ 682 } 683 684 } while (width); /* While there's still data to get. */ 685 return; 686 687 } /* end for if addr */ 688 else { 689 690 printf("PMA error: Unable to read ROM address space\n"); 691 exit(1); 692 } 693 return; 694} 695 696/************************************************************************ 697 * setup_pma() loads the ROM memory access module and initializes 698 * memory access file descriptor (access is handled through a file-like 699 * interface). 700 ************************************************************************ 701 */ 702static void 703setup_pma() 704{ 705 fd = open("/dev/mem", 2); /* O_RDWR */ 706 if (fd == -1) { 707 708 printf("Error: Unable to open /dev/mem !\a\n"); 709 exit(1); 710 } 711 return; 712} 713 714/********************************************************************** 715 * close_pma() cleans up the open memory access devices and file 716 * descriptors. 717 ********************************************************************** 718 */ 719static void 720close_pma() 721{ 722 close(fd); 723 return; 724} 725#endif /* IN_MODULE */ 726#endif /* linux && !__KERNEL__ */ 727