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