1/* 2 * Copyright 1992 by Rich Murphey <Rich@Rice.edu> 3 * Copyright 1993 by David Wexelblat <dwex@goblin.org> 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the names of Rich Murphey and David Wexelblat 10 * not be used in advertising or publicity pertaining to distribution of 11 * the software without specific, written prior permission. Rich Murphey and 12 * David Wexelblat make no representations about the suitability of this 13 * software for any purpose. It is provided "as is" without express or 14 * implied warranty. 15 * 16 * RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO 17 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 * FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT BE LIABLE FOR 19 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 20 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 21 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 23 * 24 */ 25 26/* 27 * The ARM32 code here carries the following copyright: 28 * 29 * Copyright 1997 30 * Digital Equipment Corporation. All rights reserved. 31 * This software is furnished under license and may be used and copied only in 32 * accordance with the following terms and conditions. Subject to these 33 * conditions, you may download, copy, install, use, modify and distribute 34 * this software in source and/or binary form. No title or ownership is 35 * transferred hereby. 36 * 37 * 1) Any source code used, modified or distributed must reproduce and retain 38 * this copyright notice and list of conditions as they appear in the 39 * source file. 40 * 41 * 2) No right is granted to use any trade name, trademark, or logo of Digital 42 * Equipment Corporation. Neither the "Digital Equipment Corporation" 43 * name nor any trademark or logo of Digital Equipment Corporation may be 44 * used to endorse or promote products derived from this software without 45 * the prior written permission of Digital Equipment Corporation. 46 * 47 * 3) This software is provided "AS-IS" and any express or implied warranties, 48 * including but not limited to, any implied warranties of merchantability, 49 * fitness for a particular purpose, or non-infringement are disclaimed. 50 * In no event shall DIGITAL be liable for any damages whatsoever, and in 51 * particular, DIGITAL shall not be liable for special, indirect, 52 * consequential, or incidental damages or damages for lost profits, loss 53 * of revenue or loss of use, whether such damages arise in contract, 54 * negligence, tort, under statute, in equity, at law or otherwise, even 55 * if advised of the possibility of such damage. 56 * 57 */ 58 59#ifdef HAVE_XORG_CONFIG_H 60#include <xorg-config.h> 61#endif 62 63#include <X11/X.h> 64#include "xf86.h" 65#include "xf86Priv.h" 66#include "xf86_OSlib.h" 67#include "xf86OSpriv.h" 68 69#ifdef __arm32__ 70#include "machine/devmap.h" 71struct memAccess 72{ 73 int ioctl; 74 struct map_info memInfo; 75 pointer regionVirtBase; 76 Bool Checked; 77 Bool OK; 78}; 79 80static pointer xf86MapInfoMap(); 81static void xf86MapInfoUnmap(); 82static struct memAccess *checkMapInfo(); 83extern int vgaPhysLinearBase; 84 85/* A memAccess structure is needed for each possible region */ 86struct memAccess vgaMemInfo = { CONSOLE_GET_MEM_INFO, NULL, NULL, 87 FALSE, FALSE }; 88struct memAccess linearMemInfo = { CONSOLE_GET_LINEAR_INFO, NULL, NULL, 89 FALSE, FALSE }; 90struct memAccess ioMemInfo = { CONSOLE_GET_IO_INFO, NULL, NULL, 91 FALSE, FALSE }; 92#endif /* __arm32__ */ 93 94#if defined(__NetBSD__) && !defined(MAP_FILE) 95#define MAP_FLAGS MAP_SHARED 96#else 97#define MAP_FLAGS (MAP_FILE | MAP_SHARED) 98#endif 99 100#ifndef MAP_FAILED 101#define MAP_FAILED ((caddr_t)-1) 102#endif 103 104 105#define BUS_BASE 0L 106#define BUS_BASE_BWX 0L 107 108 109/***************************************************************************/ 110/* Video Memory Mapping section */ 111/***************************************************************************/ 112 113static Bool useDevMem = FALSE; 114static int devMemFd = -1; 115 116#define DEV_MEM "/dev/mem" 117 118static pointer mapVidMem(int, unsigned long, unsigned long, int); 119static void unmapVidMem(int, pointer, unsigned long); 120 121/* 122 * Check if /dev/mem can be mmap'd. If it can't print a warning when 123 * "warn" is TRUE. 124 */ 125static void 126checkDevMem(Bool warn) 127{ 128 static Bool devMemChecked = FALSE; 129 int fd; 130 pointer base; 131 132 if (devMemChecked) 133 return; 134 devMemChecked = TRUE; 135 136 if ((fd = open(DEV_MEM, O_RDWR)) >= 0) 137 { 138 /* Try to map a page at the VGA address */ 139 base = mmap((caddr_t)0, 4096, PROT_READ | PROT_WRITE, 140 MAP_FLAGS, fd, (off_t)0xA0000 + BUS_BASE); 141 142 if (base != MAP_FAILED) 143 { 144 munmap((caddr_t)base, 4096); 145 devMemFd = fd; 146 useDevMem = TRUE; 147 return; 148 } else { 149 /* This should not happen */ 150 if (warn) 151 { 152 xf86Msg(X_WARNING, "checkDevMem: failed to mmap %s (%s)\n", 153 DEV_MEM, strerror(errno)); 154 } 155 useDevMem = FALSE; 156 return; 157 } 158 } 159 if (warn) 160 { 161 xf86Msg(X_WARNING, "checkDevMem: failed to open %s (%s)\n", 162 DEV_MEM, strerror(errno)); 163 } 164 useDevMem = FALSE; 165 return; 166} 167 168void 169xf86OSInitVidMem(VidMemInfoPtr pVidMem) 170{ 171 172 checkDevMem(TRUE); 173 pVidMem->linearSupported = useDevMem; 174 pVidMem->mapMem = armMapVidMem; 175 pVidMem->unmapVidMem = armUnmapVidMem; 176 177 pVidMem->initialised = TRUE; 178} 179 180static pointer 181mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) 182{ 183 pointer base; 184 185 checkDevMem(FALSE); 186 187 if (useDevMem) 188 { 189 if (devMemFd < 0) 190 { 191 FatalError("xf86MapVidMem: failed to open %s (%s)\n", 192 DEV_MEM, strerror(errno)); 193 } 194 base = mmap((caddr_t)0, Size, 195 (flags & VIDMEM_READONLY) ? 196 PROT_READ : (PROT_READ | PROT_WRITE), 197 MAP_FLAGS, devMemFd, (off_t)Base + BUS_BASE_BWX); 198 if (base == MAP_FAILED) 199 { 200 FatalError("%s: could not mmap %s [s=%x,a=%x] (%s)\n", 201 "xf86MapVidMem", DEV_MEM, Size, Base, 202 strerror(errno)); 203 } 204 return base; 205 } 206 207 /* else, mmap /dev/vga */ 208 if ((unsigned long)Base < 0xA0000 || (unsigned long)Base >= 0xC0000) 209 { 210 FatalError("%s: Address 0x%x outside allowable range\n", 211 "xf86MapVidMem", Base); 212 } 213 base = mmap(0, Size, 214 (flags & VIDMEM_READONLY) ? 215 PROT_READ : (PROT_READ | PROT_WRITE), 216 MAP_FLAGS, xf86Info.screenFd, 217 (unsigned long)Base - 0xA0000); 218 if (base == MAP_FAILED) 219 { 220 FatalError("xf86MapVidMem: Could not mmap /dev/vga (%s)\n", 221 strerror(errno)); 222 } 223 return base; 224} 225 226static void 227unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) 228{ 229 munmap((caddr_t)Base, Size); 230} 231 232/* 233 * Read BIOS via mmap()ing DEV_MEM 234 */ 235 236int 237xf86ReadBIOS(unsigned long Base, unsigned long Offset, unsigned char *Buf, 238 int Len) 239{ 240 unsigned char *ptr; 241 int psize; 242 int mlen; 243 244 checkDevMem(TRUE); 245 if (devMemFd == -1) { 246 return -1; 247 } 248 249 psize = getpagesize(); 250 Offset += Base & (psize - 1); 251 Base &= ~(psize - 1); 252 mlen = (Offset + Len + psize - 1) & ~(psize - 1); 253 ptr = (unsigned char *)mmap((caddr_t)0, mlen, PROT_READ, 254 MAP_SHARED, devMemFd, (off_t)Base+BUS_BASE); 255 if ((long)ptr == -1) 256 { 257 xf86Msg(X_WARNING, 258 "xf86ReadBIOS: %s mmap[s=%x,a=%x,o=%x] failed (%s)\n", 259 DEV_MEM, Len, Base, Offset, strerror(errno)); 260 return -1; 261 } 262#ifdef DEBUG 263 ErrorF("xf86ReadBIOS: BIOS at 0x%08x has signature 0x%04x\n", 264 Base, ptr[0] | (ptr[1] << 8)); 265#endif 266 (void)memcpy(Buf, (void *)(ptr + Offset), Len); 267 (void)munmap((caddr_t)ptr, mlen); 268#ifdef DEBUG 269 xf86MsgVerb(X_INFO, 3, "xf86ReadBIOS(%x, %x, Buf, %x)" 270 "-> %02x %02x %02x %02x...\n", 271 Base, Offset, Len, Buf[0], Buf[1], Buf[2], Buf[3]); 272#endif 273 return Len; 274} 275 276 277/* XXX This needs to be updated for the ND */ 278 279/* 280** Find out whether the console driver provides memory mapping information 281** for the specified region and return the map_info pointer. Print a warning if required. 282*/ 283static struct memAccess * 284checkMapInfo(Bool warn, int Region) 285{ 286 struct memAccess *memAccP; 287 288 switch (Region) 289 { 290 case VGA_REGION: 291 memAccP = &vgaMemInfo; 292 break; 293 294 case LINEAR_REGION: 295 memAccP = &linearMemInfo; 296 break; 297 298 case MMIO_REGION: 299 memAccP = &ioMemInfo; 300 break; 301 302 default: 303 return NULL; 304 break; 305 } 306 307 if(!memAccP->Checked) 308 { 309 if(ioctl(xf86Info.screenFd, memAccP->ioctl, &(memAccP->memInfo)) == -1) 310 { 311 if(warn) 312 { 313 xf86Msg(X_WARNING, 314 "checkMapInfo: failed to get map info for region %d\n\t(%s)\n", 315 Region, strerror(errno)); 316 } 317 } 318 else 319 { 320 if(memAccP->memInfo.u.map_info_mmap.map_offset 321 != MAP_INFO_UNKNOWN) 322 memAccP->OK = TRUE; 323 } 324 memAccP->Checked = TRUE; 325 } 326 if (memAccP->OK) 327 { 328 return memAccP; 329 } 330 else 331 { 332 return NULL; 333 } 334} 335 336static pointer 337xf86MapInfoMap(struct memAccess *memInfoP, pointer Base, unsigned long Size) 338{ 339 struct map_info *mapInfoP = &(memInfoP->memInfo); 340 341 if (mapInfoP->u.map_info_mmap.map_size == MAP_INFO_UNKNOWN) 342 { 343 Size = (unsigned long)Base + Size; 344 } 345 else 346 { 347 Size = mapInfoP->u.map_info_mmap.map_size; 348 } 349 350 switch(mapInfoP->method) 351 { 352 case MAP_MMAP: 353 /* Need to remap if size is unknown because we may not have 354 mapped the whole region initially */ 355 if(memInfoP->regionVirtBase == NULL || 356 mapInfoP->u.map_info_mmap.map_size == MAP_INFO_UNKNOWN) 357 { 358 if((memInfoP->regionVirtBase = 359 mmap((caddr_t)0, 360 Size, 361 PROT_READ | PROT_WRITE, 362 MAP_SHARED, 363 xf86Info.screenFd, 364 (unsigned long)mapInfoP->u.map_info_mmap.map_offset)) 365 == (pointer)-1) 366 { 367 FatalError("xf86MapInfoMap: Failed to map memory at 0x%x\n\t%s\n", 368 mapInfoP->u.map_info_mmap.map_offset, strerror(errno)); 369 } 370 if(mapInfoP->u.map_info_mmap.internal_offset > 0) 371 memInfoP->regionVirtBase += 372 mapInfoP->u.map_info_mmap.internal_offset; 373 } 374 break; 375 376 default: 377 FatalError("xf86MapInfoMap: Unsuported mapping method\n"); 378 break; 379 } 380 381 return (pointer)((int)memInfoP->regionVirtBase + (int)Base); 382} 383 384static void 385xf86MapInfoUnmap(struct memAccess *memInfoP, unsigned long Size) 386{ 387 struct map_info *mapInfoP = &(memInfoP->memInfo); 388 389 switch(mapInfoP->method) 390 { 391 case MAP_MMAP: 392 if(memInfoP->regionVirtBase != NULL) 393 { 394 if(mapInfoP->u.map_info_mmap.map_size != MAP_INFO_UNKNOWN) 395 Size = mapInfoP->u.map_info_mmap.map_size; 396 munmap((caddr_t)memInfoP->regionVirtBase, Size); 397 memInfoP->regionVirtBase = NULL; 398 } 399 break; 400 default: 401 FatalError("xf86MapInfoMap: Unsuported mapping method\n"); 402 break; 403 } 404} 405 406static pointer 407armMapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) 408{ 409 struct memAccess *memInfoP; 410 411 if((memInfoP = checkMapInfo(FALSE, Region)) != NULL) 412 { 413 /* 414 ** xf86 passes in a physical address offset from the start 415 ** of physical memory, but xf86MapInfoMap expects an 416 ** offset from the start of the specified region - it gets 417 ** the physical address of the region from the display driver. 418 */ 419 switch(Region) 420 { 421 case LINEAR_REGION: 422 if (vgaPhysLinearBase) 423 { 424 Base -= vgaPhysLinearBase; 425 } 426 break; 427 case VGA_REGION: 428 Base -= 0xA0000; 429 break; 430 } 431 432 base = xf86MapInfoMap(memInfoP, Base, Size); 433 return base; 434 } 435 return mapVidMem(ScreenNum, Base, Size, flags); 436} 437 438static void 439armUnmapVidMem(int ScreenNum, pointer Base, unsigned long Size) 440{ 441 struct memAccess *memInfoP; 442 443 if((memInfoP = checkMapInfo(FALSE, Region)) != NULL) 444 { 445 xf86MapInfoUnmap(memInfoP, Base, Size); 446 } 447 unmapVidMem(ScreenNum, Base, Size); 448} 449 450#ifdef USE_DEV_IO 451static int IoFd = -1; 452 453Bool 454xf86EnableIO() 455{ 456 if (IoFd >= 0) 457 return TRUE; 458 459 if ((IoFd = open("/dev/io", O_RDWR)) == -1) 460 { 461 xf86Msg(X_WARNING,"xf86EnableIO: " 462 "Failed to open /dev/io for extended I/O\n"); 463 return FALSE; 464 } 465 return TRUE; 466} 467 468void 469xf86DisableIO() 470{ 471 if (IoFd < 0) 472 return; 473 474 close(IoFd); 475 IoFd = -1; 476 return; 477} 478 479#endif 480 481#if defined(USE_ARC_MMAP) || defined(__arm32__) 482 483Bool 484xf86EnableIO() 485{ 486 int fd; 487 pointer base; 488 489 if (ExtendedEnabled) 490 return TRUE; 491 492 if ((fd = open("/dev/ttyC0", O_RDWR)) >= 0) { 493 /* Try to map a page at the pccons I/O space */ 494 base = (pointer)mmap((caddr_t)0, 65536, PROT_READ | PROT_WRITE, 495 MAP_FLAGS, fd, (off_t)0x0000); 496 497 if (base != (pointer)-1) { 498 IOPortBase = base; 499 } 500 else { 501 xf86Msg(X_WARNING,"EnableIO: failed to mmap %s (%s)\n", 502 "/dev/ttyC0", strerror(errno)); 503 return FALSE; 504 } 505 } 506 else { 507 xf86Msg("EnableIO: failed to open %s (%s)\n", 508 "/dev/ttyC0", strerror(errno)); 509 return FALSE; 510 } 511 512 ExtendedEnabled = TRUE; 513 514 return TRUE; 515} 516 517void 518xf86DisableIO() 519{ 520 return; 521} 522 523#endif /* USE_ARC_MMAP */ 524 525#if 0 526/* 527 * XXX This is here for reference. It needs to be handled differently for the 528 * ND. 529 */ 530#if defined(USE_ARC_MMAP) || defined(__arm32__) 531 532#ifdef USE_ARM32_MMAP 533#define DEV_MEM_IOBASE 0x43000000 534#endif 535 536static Bool ScreenEnabled[MAXSCREENS]; 537static Bool ExtendedEnabled = FALSE; 538static Bool InitDone = FALSE; 539 540Bool 541xf86EnableIOPorts(ScreenNum) 542int ScreenNum; 543{ 544 int i; 545 int fd; 546 pointer base; 547 548#ifdef __arm32__ 549 struct memAccess *memInfoP; 550 int *Size; 551#endif 552 553 ScreenEnabled[ScreenNum] = TRUE; 554 555 if (ExtendedEnabled) 556 return TRUE; 557 558#ifdef USE_ARC_MMAP 559 if ((fd = open("/dev/ttyC0", O_RDWR)) >= 0) { 560 /* Try to map a page at the pccons I/O space */ 561 base = (pointer)mmap((caddr_t)0, 65536, PROT_READ | PROT_WRITE, 562 MAP_FLAGS, fd, (off_t)0x0000); 563 564 if (base != (pointer)-1) { 565 IOPortBase = base; 566 } 567 else { 568 xf86Msg(X_ERROR, 569 "EnableIOPorts: failed to mmap %s (%s)\n", 570 "/dev/ttyC0", strerror(errno)); 571 } 572 } 573 else { 574 xf86Msg(X_ERROR, "EnableIOPorts: failed to open %s (%s)\n", 575 "/dev/ttyC0", strerror(errno)); 576 } 577#endif 578 579#ifdef __arm32__ 580 IOPortBase = (unsigned int)-1; 581 582 if((memInfoP = checkMapInfo(TRUE, MMIO_REGION)) != NULL) 583 { 584 /* 585 * xf86MapInfoMap maps an offset from the start of video IO 586 * space (e.g. 0x3B0), but IOPortBase is expected to map to 587 * physical address 0x000, so subtract the start of video I/O 588 * space from the result. This is safe for now becase we 589 * actually mmap the start of the page, then the start of video 590 * I/O space is added as an internal offset. 591 */ 592 IOPortBase = (unsigned int)xf86MapInfoMap(memInfoP, 593 (caddr_t)0x0, 0L) 594 - memInfoP->memInfo.u.map_info_mmap.internal_offset; 595 ExtendedEnabled = TRUE; 596 return TRUE; 597 } 598#ifdef USE_ARM32_MMAP 599 checkDevMem(TRUE); 600 601 if (devMemFd >= 0 && useDevMem) 602 { 603 base = (pointer)mmap((caddr_t)0, 0x400, PROT_READ | PROT_WRITE, 604 MAP_FLAGS, devMemFd, (off_t)DEV_MEM_IOBASE); 605 606 if (base != (pointer)-1) 607 IOPortBase = (unsigned int)base; 608 } 609 610 if (IOPortBase == (unsigned int)-1) 611 { 612 xf86Msg(X_WARNING,"xf86EnableIOPorts: failed to open mem device or map IO base. \n\ 613Make sure you have the Aperture Driver installed, or a kernel built with the INSECURE option\n"); 614 return FALSE; 615 } 616#else 617 /* We don't have the IOBASE, so we can't map the address */ 618 xf86Msg(X_WARNING,"xf86EnableIOPorts: failed to open mem device or map IO base. \n\ 619Try building the server with USE_ARM32_MMAP defined\n"); 620 return FALSE; 621#endif 622#endif 623 624 ExtendedEnabled = TRUE; 625 626 return TRUE; 627} 628 629void 630xf86DisableIOPorts(ScreenNum) 631int ScreenNum; 632{ 633 int i; 634#ifdef __arm32__ 635 struct memAccess *memInfoP; 636#endif 637 638 ScreenEnabled[ScreenNum] = FALSE; 639 640#ifdef __arm32__ 641 if((memInfoP = checkMapInfo(FALSE, MMIO_REGION)) != NULL) 642 { 643 xf86MapInfoUnmap(memInfoP, 0); 644 } 645#endif 646 647#ifdef USE_ARM32_MMAP 648 if (!ExtendedEnabled) 649 return; 650 651 for (i = 0; i < MAXSCREENS; i++) 652 if (ScreenEnabled[i]) 653 return; 654 655 munmap((caddr_t)IOPortBase, 0x400); 656 IOPortBase = (unsigned int)-1; 657 ExtendedEnabled = FALSE; 658#endif 659 660 return; 661} 662 663#endif /* USE_ARC_MMAP || USE_ARM32_MMAP */ 664#endif 665 666 667