1*748Sdmick /*
2*748Sdmick * CDDL HEADER START
3*748Sdmick *
4*748Sdmick * The contents of this file are subject to the terms of the
5*748Sdmick * Common Development and Distribution License, Version 1.0 only
6*748Sdmick * (the "License"). You may not use this file except in compliance
7*748Sdmick * with the License.
8*748Sdmick *
9*748Sdmick * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*748Sdmick * or http://www.opensolaris.org/os/licensing.
11*748Sdmick * See the License for the specific language governing permissions
12*748Sdmick * and limitations under the License.
13*748Sdmick *
14*748Sdmick * When distributing Covered Code, include this CDDL HEADER in each
15*748Sdmick * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*748Sdmick * If applicable, add the following below this CDDL HEADER, with the
17*748Sdmick * fields enclosed by brackets "[]" replaced with your own identifying
18*748Sdmick * information: Portions Copyright [yyyy] [name of copyright owner]
19*748Sdmick *
20*748Sdmick * CDDL HEADER END
21*748Sdmick */
22*748Sdmick /*
23*748Sdmick * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*748Sdmick * Use is subject to license terms.
25*748Sdmick */
26*748Sdmick
27*748Sdmick #pragma ident "%Z%%M% %I% %E% SMI"
28*748Sdmick
29*748Sdmick /*
30*748Sdmick * PCI Mechanism 2 primitives
31*748Sdmick */
32*748Sdmick
33*748Sdmick #include <sys/types.h>
34*748Sdmick #include <sys/sunddi.h>
35*748Sdmick #include <sys/pci_impl.h>
36*748Sdmick #include <sys/pci_cfgspace_impl.h>
37*748Sdmick
38*748Sdmick /*
39*748Sdmick * The "mechanism 2" interface only has 4 bits for device number. To
40*748Sdmick * hide this implementation detail, we return all ones for accesses to
41*748Sdmick * devices 16..31.
42*748Sdmick */
43*748Sdmick #define PCI_MAX_DEVS_2 16
44*748Sdmick
45*748Sdmick /*
46*748Sdmick * the PCI LOCAL BUS SPECIFICATION 2.0 does not say that you need to
47*748Sdmick * save the value of the register and restore them. The Intel chip
48*748Sdmick * set documentation indicates that you should.
49*748Sdmick */
50*748Sdmick static uint8_t
pci_mech2_config_enable(uchar_t bus,uchar_t function)51*748Sdmick pci_mech2_config_enable(uchar_t bus, uchar_t function)
52*748Sdmick {
53*748Sdmick uint8_t old;
54*748Sdmick
55*748Sdmick mutex_enter(&pcicfg_mutex);
56*748Sdmick old = inb(PCI_CSE_PORT);
57*748Sdmick
58*748Sdmick outb(PCI_CSE_PORT,
59*748Sdmick PCI_MECH2_CONFIG_ENABLE | ((function & PCI_FUNC_MASK) << 1));
60*748Sdmick outb(PCI_FORW_PORT, bus);
61*748Sdmick
62*748Sdmick return (old);
63*748Sdmick }
64*748Sdmick
65*748Sdmick static void
pci_mech2_config_restore(uint8_t oldstatus)66*748Sdmick pci_mech2_config_restore(uint8_t oldstatus)
67*748Sdmick {
68*748Sdmick outb(PCI_CSE_PORT, oldstatus);
69*748Sdmick mutex_exit(&pcicfg_mutex);
70*748Sdmick }
71*748Sdmick
72*748Sdmick uint8_t
pci_mech2_getb(int bus,int device,int function,int reg)73*748Sdmick pci_mech2_getb(int bus, int device, int function, int reg)
74*748Sdmick {
75*748Sdmick uint8_t tmp;
76*748Sdmick uint8_t val;
77*748Sdmick
78*748Sdmick if (device >= PCI_MAX_DEVS_2)
79*748Sdmick return (0xff);
80*748Sdmick
81*748Sdmick tmp = pci_mech2_config_enable(bus, function);
82*748Sdmick val = inb(PCI_CADDR2(device, reg));
83*748Sdmick pci_mech2_config_restore(tmp);
84*748Sdmick
85*748Sdmick return (val);
86*748Sdmick }
87*748Sdmick
88*748Sdmick uint16_t
pci_mech2_getw(int bus,int device,int function,int reg)89*748Sdmick pci_mech2_getw(int bus, int device, int function, int reg)
90*748Sdmick {
91*748Sdmick uint8_t tmp;
92*748Sdmick uint16_t val;
93*748Sdmick
94*748Sdmick if (device >= PCI_MAX_DEVS_2)
95*748Sdmick return (0xffff);
96*748Sdmick
97*748Sdmick tmp = pci_mech2_config_enable(bus, function);
98*748Sdmick val = inw(PCI_CADDR2(device, reg));
99*748Sdmick pci_mech2_config_restore(tmp);
100*748Sdmick
101*748Sdmick return (val);
102*748Sdmick }
103*748Sdmick
104*748Sdmick uint32_t
pci_mech2_getl(int bus,int device,int function,int reg)105*748Sdmick pci_mech2_getl(int bus, int device, int function, int reg)
106*748Sdmick {
107*748Sdmick uint8_t tmp;
108*748Sdmick uint32_t val;
109*748Sdmick
110*748Sdmick if (device >= PCI_MAX_DEVS_2)
111*748Sdmick return (0xffffffffu);
112*748Sdmick
113*748Sdmick tmp = pci_mech2_config_enable(bus, function);
114*748Sdmick val = inl(PCI_CADDR2(device, reg));
115*748Sdmick pci_mech2_config_restore(tmp);
116*748Sdmick
117*748Sdmick return (val);
118*748Sdmick }
119*748Sdmick
120*748Sdmick void
pci_mech2_putb(int bus,int device,int function,int reg,uint8_t val)121*748Sdmick pci_mech2_putb(int bus, int device, int function, int reg, uint8_t val)
122*748Sdmick {
123*748Sdmick uint8_t tmp;
124*748Sdmick
125*748Sdmick if (device >= PCI_MAX_DEVS_2)
126*748Sdmick return;
127*748Sdmick
128*748Sdmick tmp = pci_mech2_config_enable(bus, function);
129*748Sdmick outb(PCI_CADDR2(device, reg), val);
130*748Sdmick pci_mech2_config_restore(tmp);
131*748Sdmick }
132*748Sdmick
133*748Sdmick void
pci_mech2_putw(int bus,int device,int function,int reg,uint16_t val)134*748Sdmick pci_mech2_putw(int bus, int device, int function, int reg, uint16_t val)
135*748Sdmick {
136*748Sdmick uint8_t tmp;
137*748Sdmick
138*748Sdmick if (device >= PCI_MAX_DEVS_2)
139*748Sdmick return;
140*748Sdmick
141*748Sdmick tmp = pci_mech2_config_enable(bus, function);
142*748Sdmick outw(PCI_CADDR2(device, reg), val);
143*748Sdmick pci_mech2_config_restore(tmp);
144*748Sdmick }
145*748Sdmick
146*748Sdmick void
pci_mech2_putl(int bus,int device,int function,int reg,uint32_t val)147*748Sdmick pci_mech2_putl(int bus, int device, int function, int reg, uint32_t val)
148*748Sdmick {
149*748Sdmick uint8_t tmp;
150*748Sdmick
151*748Sdmick if (device >= PCI_MAX_DEVS_2)
152*748Sdmick return;
153*748Sdmick
154*748Sdmick tmp = pci_mech2_config_enable(bus, function);
155*748Sdmick outl(PCI_CADDR2(device, reg), val);
156*748Sdmick pci_mech2_config_restore(tmp);
157*748Sdmick }
158