1/*-
2 * Copyright (c) 2010 Marcel Moolenaar
3 * Copyright (c) 2001 Doug Rabson
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD$
28 */
29
30#include <sys/param.h>
31#include <machine/cpufunc.h>
32#include <machine/pci_cfgreg.h>
33#include <machine/sal.h>
34
35static u_long
36pci_sal_address(int dom, int bus, int slot, int func, int reg)
37{
38	u_long addr;
39
40	addr = ~0ul;
41	if (dom >= 0 && dom <= 255 && bus >= 0 && bus <= 255 &&
42	    slot >= 0 && slot <= 31 && func >= 0 && func <= 7 &&
43	    reg >= 0 && reg <= 255) {
44		addr = ((u_long)dom << 24) | ((u_long)bus << 16) |
45		    ((u_long)slot << 11) | ((u_long)func << 8) | (u_long)reg;
46	}
47	return (addr);
48}
49
50static int
51pci_valid_access(int reg, int len)
52{
53	int ok;
54
55	ok = ((len == 1 || len == 2 || len == 4) && (reg & (len - 1)) == 0)
56	    ? 1 : 0;
57	return (ok);
58}
59
60int
61pci_cfgregopen(void)
62{
63	return (1);
64}
65
66uint32_t
67pci_cfgregread(int bus, int slot, int func, int reg, int len)
68{
69	struct ia64_sal_result res;
70	register_t is;
71	u_long addr;
72
73	addr = pci_sal_address(bus >> 8, bus & 0xff, slot, func, reg);
74	if (addr == ~0ul)
75		return (~0);
76
77	if (!pci_valid_access(reg, len))
78		return (~0);
79
80	is = intr_disable();
81	res = ia64_sal_entry(SAL_PCI_CONFIG_READ, addr, len, 0, 0, 0, 0, 0);
82	intr_restore(is);
83
84	return ((res.sal_status < 0) ? ~0 : res.sal_result[0]);
85}
86
87void
88pci_cfgregwrite(int bus, int slot, int func, int reg, uint32_t data, int len)
89{
90	struct ia64_sal_result res;
91	register_t is;
92	u_long addr;
93
94	addr = pci_sal_address(bus >> 8, bus & 0xff, slot, func, reg);
95	if (addr == ~0ul)
96		return;
97
98	if (!pci_valid_access(reg, len))
99		return;
100
101	is = intr_disable();
102	res = ia64_sal_entry(SAL_PCI_CONFIG_WRITE, addr, len, data, 0, 0, 0, 0);
103	intr_restore(is);
104}
105