184124Sdfr/*- 2203106Smarcel * Copyright (c) 2010 Marcel Moolenaar 384124Sdfr * Copyright (c) 2001 Doug Rabson 484124Sdfr * All rights reserved. 584124Sdfr * 684124Sdfr * Redistribution and use in source and binary forms, with or without 784124Sdfr * modification, are permitted provided that the following conditions 884124Sdfr * are met: 984124Sdfr * 1. Redistributions of source code must retain the above copyright 1084124Sdfr * notice, this list of conditions and the following disclaimer. 1184124Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1284124Sdfr * notice, this list of conditions and the following disclaimer in the 1384124Sdfr * documentation and/or other materials provided with the distribution. 1484124Sdfr * 1584124Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1684124Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1784124Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1884124Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1984124Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2084124Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2184124Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2284124Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2384124Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2484124Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2584124Sdfr * SUCH DAMAGE. 2684124Sdfr * 2784124Sdfr * $FreeBSD$ 2884124Sdfr */ 2984124Sdfr 3084124Sdfr#include <sys/param.h> 31205432Smarcel#include <machine/cpufunc.h> 3284124Sdfr#include <machine/pci_cfgreg.h> 3384124Sdfr#include <machine/sal.h> 3484124Sdfr 35203106Smarcelstatic u_long 36203106Smarcelpci_sal_address(int dom, int bus, int slot, int func, int reg) 37203106Smarcel{ 38203106Smarcel u_long addr; 3984124Sdfr 40203106Smarcel addr = ~0ul; 41203106Smarcel if (dom >= 0 && dom <= 255 && bus >= 0 && bus <= 255 && 42203106Smarcel slot >= 0 && slot <= 31 && func >= 0 && func <= 7 && 43203106Smarcel reg >= 0 && reg <= 255) { 44203106Smarcel addr = ((u_long)dom << 24) | ((u_long)bus << 16) | 45203106Smarcel ((u_long)slot << 11) | ((u_long)func << 8) | (u_long)reg; 46203106Smarcel } 47203106Smarcel return (addr); 48203106Smarcel} 49203106Smarcel 50203106Smarcelstatic int 51203106Smarcelpci_valid_access(int reg, int len) 52203106Smarcel{ 53203106Smarcel int ok; 54203106Smarcel 55203106Smarcel ok = ((len == 1 || len == 2 || len == 4) && (reg & (len - 1)) == 0) 56203106Smarcel ? 1 : 0; 57203106Smarcel return (ok); 58203106Smarcel} 59203106Smarcel 6084124Sdfrint 6184124Sdfrpci_cfgregopen(void) 6284124Sdfr{ 63203106Smarcel return (1); 6484124Sdfr} 6584124Sdfr 66203106Smarceluint32_t 67203106Smarcelpci_cfgregread(int bus, int slot, int func, int reg, int len) 6884124Sdfr{ 6984124Sdfr struct ia64_sal_result res; 70205432Smarcel register_t is; 71203106Smarcel u_long addr; 7284124Sdfr 73253560Smarcel addr = pci_sal_address(bus >> 8, bus & 0xff, slot, func, reg); 74203106Smarcel if (addr == ~0ul) 75203106Smarcel return (~0); 76203106Smarcel 77203106Smarcel if (!pci_valid_access(reg, len)) 78203106Smarcel return (~0); 79203106Smarcel 80205432Smarcel is = intr_disable(); 81203106Smarcel res = ia64_sal_entry(SAL_PCI_CONFIG_READ, addr, len, 0, 0, 0, 0, 0); 82205432Smarcel intr_restore(is); 83203106Smarcel 84205432Smarcel return ((res.sal_status < 0) ? ~0 : res.sal_result[0]); 8584412Sdfr} 8684124Sdfr 8784124Sdfrvoid 88203106Smarcelpci_cfgregwrite(int bus, int slot, int func, int reg, uint32_t data, int len) 8984124Sdfr{ 9084124Sdfr struct ia64_sal_result res; 91205432Smarcel register_t is; 92203106Smarcel u_long addr; 9384124Sdfr 94253560Smarcel addr = pci_sal_address(bus >> 8, bus & 0xff, slot, func, reg); 95203106Smarcel if (addr == ~0ul) 96203106Smarcel return; 97203106Smarcel 98203106Smarcel if (!pci_valid_access(reg, len)) 99203106Smarcel return; 100203106Smarcel 101205432Smarcel is = intr_disable(); 102203106Smarcel res = ia64_sal_entry(SAL_PCI_CONFIG_WRITE, addr, len, data, 0, 0, 0, 0); 103205432Smarcel intr_restore(is); 10484124Sdfr} 105