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