1/* $NetBSD: alpha_pci_mem.c,v 1.4 2002/07/19 22:03:39 mycroft Exp $ */ 2 3/*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Support for mapping PCI/EISA/ISA memory space. This is currently used 34 * to provide such support for XFree86. In a perfect world, this would go 35 * away in favor of a real bus space mapping framework. 36 */ 37 38#include <sys/param.h> 39#include <sys/mman.h> 40 41#include <machine/sysarch.h> 42 43#include <fcntl.h> 44#include <paths.h> 45#include <stdlib.h> 46#include <string.h> 47#include <unistd.h> 48 49struct alpha_bus_window *alpha_pci_mem_windows; 50int alpha_pci_mem_window_count; 51 52void * 53alpha_pci_mem_map(bus_addr_t memaddr, bus_size_t memsize, int flags, 54 struct alpha_bus_space_translation *rabst) 55{ 56 struct alpha_bus_window *abw; 57 void *addr; 58 int prefetchable = flags & BUS_SPACE_MAP_PREFETCHABLE; 59 int linear = flags & BUS_SPACE_MAP_LINEAR; 60 bus_size_t offset; 61 int i, fd; 62 63 /* 64 * Can't have linear without prefetchable. 65 */ 66 if (linear && !prefetchable) 67 return (MAP_FAILED); 68 69 if (alpha_pci_mem_windows == NULL) { 70 i = alpha_bus_getwindows(ALPHA_BUS_TYPE_PCI_MEM, &abw); 71 if (i <= 0) 72 return (MAP_FAILED); 73 74 alpha_pci_mem_windows = abw; 75 alpha_pci_mem_window_count = i; 76 } 77 78 for (i = 0; i < alpha_pci_mem_window_count; i++) { 79 abw = &alpha_pci_mem_windows[i]; 80 if (memaddr < abw->abw_abst.abst_bus_start || 81 (memaddr + (memsize - 1)) > abw->abw_abst.abst_bus_end) 82 continue; 83 84 /* 85 * Prefetchable memory must be mapped in dense space; 86 * otherwise use sparse space. 87 */ 88 if (prefetchable && 89 (abw->abw_abst.abst_flags & ABST_DENSE) == 0) 90 continue; 91 if (!prefetchable && 92 (abw->abw_abst.abst_flags & ABST_DENSE) != 0) 93 continue; 94 95 /* Looks like we have a winner! */ 96 goto found; 97 } 98 99 /* Not found in any of the windows. */ 100 return (MAP_FAILED); 101 102 found: 103 fd = open(_PATH_MEM, O_RDWR, 0600); 104 if (fd == -1) 105 return (MAP_FAILED); 106 107 if (prefetchable) 108 abw->abw_abst.abst_addr_shift = 0; 109 memsize <<= abw->abw_abst.abst_addr_shift; 110 offset = (memaddr - abw->abw_abst.abst_bus_start) << 111 abw->abw_abst.abst_addr_shift; 112 113 addr = mmap(NULL, memsize, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, 114 fd, (off_t) (abw->abw_abst.abst_sys_start + offset)); 115 116 (void) close(fd); 117 118 if (addr != MAP_FAILED) { 119 /* 120 * Make a copy of the space translation so that the caller 121 * can do the correct access. 122 */ 123 *rabst = abw->abw_abst; 124 } 125 return (addr); 126} 127 128void 129alpha_pci_mem_unmap(struct alpha_bus_space_translation *abst, void *addr, 130 bus_size_t size) 131{ 132 133 (void) munmap(addr, size << abst->abst_addr_shift); 134} 135