xref: /freebsd/sys/i386/pci/pci_cfgreg.c (revision a3adc4f8c58ca74ae2a7badd891622780fae16c1)
1ac19f918SStefan Eßer /**************************************************************************
2ac19f918SStefan Eßer **
3a3adc4f8SStefan Eßer **  $Id: pcibus.c,v 1.13 1995/09/15 21:43:45 se Exp $
4ac19f918SStefan Eßer **
5ac19f918SStefan Eßer **  pci bus subroutines for i386 architecture.
6ac19f918SStefan Eßer **
7ac19f918SStefan Eßer **  FreeBSD
8ac19f918SStefan Eßer **
9ac19f918SStefan Eßer **-------------------------------------------------------------------------
10ac19f918SStefan Eßer **
11ac19f918SStefan Eßer ** Copyright (c) 1994 Wolfgang Stanglmeier.  All rights reserved.
12ac19f918SStefan Eßer **
13ac19f918SStefan Eßer ** Redistribution and use in source and binary forms, with or without
14ac19f918SStefan Eßer ** modification, are permitted provided that the following conditions
15ac19f918SStefan Eßer ** are met:
16ac19f918SStefan Eßer ** 1. Redistributions of source code must retain the above copyright
17ac19f918SStefan Eßer **    notice, this list of conditions and the following disclaimer.
18ac19f918SStefan Eßer ** 2. Redistributions in binary form must reproduce the above copyright
19ac19f918SStefan Eßer **    notice, this list of conditions and the following disclaimer in the
20ac19f918SStefan Eßer **    documentation and/or other materials provided with the distribution.
21ac19f918SStefan Eßer ** 3. The name of the author may not be used to endorse or promote products
22ac19f918SStefan Eßer **    derived from this software without specific prior written permission.
23ac19f918SStefan Eßer **
24ac19f918SStefan Eßer ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25ac19f918SStefan Eßer ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26ac19f918SStefan Eßer ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27ac19f918SStefan Eßer ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28ac19f918SStefan Eßer ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29ac19f918SStefan Eßer ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30ac19f918SStefan Eßer ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31ac19f918SStefan Eßer ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32ac19f918SStefan Eßer ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33ac19f918SStefan Eßer ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34ac19f918SStefan Eßer **
35ac19f918SStefan Eßer ***************************************************************************
36ac19f918SStefan Eßer */
37ac19f918SStefan Eßer 
38550f8550SBruce Evans #include <sys/param.h>
39550f8550SBruce Evans #include <sys/systm.h>
40550f8550SBruce Evans #include <sys/kernel.h>
41550f8550SBruce Evans 
422d144186SStefan Eßer #include <machine/cpu.h> /* bootverbose */
432d144186SStefan Eßer 
44550f8550SBruce Evans #include <i386/isa/icu.h>
45ac19f918SStefan Eßer #include <i386/isa/isa.h>
46ac19f918SStefan Eßer #include <i386/isa/isa_device.h>
47ac19f918SStefan Eßer 
48ac19f918SStefan Eßer #include <pci/pcivar.h>
49ac19f918SStefan Eßer #include <pci/pcireg.h>
50ac19f918SStefan Eßer #include <pci/pcibus.h>
51ac19f918SStefan Eßer 
52ac19f918SStefan Eßer /*-----------------------------------------------------------------
53ac19f918SStefan Eßer **
54ac19f918SStefan Eßer **	The following functions are provided by the pci bios.
55ac19f918SStefan Eßer **	They are used only by the pci configuration.
56ac19f918SStefan Eßer **
575b3f532eSStefan Eßer **	pcibus_setup():
58ac19f918SStefan Eßer **		Probes for a pci system.
595b3f532eSStefan Eßer **		Sets pci_maxdevice and pci_mechanism.
60ac19f918SStefan Eßer **
61ac19f918SStefan Eßer **	pcibus_tag():
625b3f532eSStefan Eßer **		Creates a handle for pci configuration space access.
635b3f532eSStefan Eßer **		This handle is given to the read/write functions.
645b3f532eSStefan Eßer **
655b3f532eSStefan Eßer **	pcibus_ftag():
665b3f532eSStefan Eßer **		Creates a modified handle.
67ac19f918SStefan Eßer **
68ac19f918SStefan Eßer **	pcibus_read():
69ac19f918SStefan Eßer **		Read a long word from the pci configuration space.
70ac19f918SStefan Eßer **		Requires a tag (from pcitag) and the register
71ac19f918SStefan Eßer **		number (should be a long word alligned one).
72ac19f918SStefan Eßer **
73ac19f918SStefan Eßer **	pcibus_write():
74ac19f918SStefan Eßer **		Writes a long word to the pci configuration space.
75ac19f918SStefan Eßer **		Requires a tag (from pcitag), the register number
76ac19f918SStefan Eßer **		(should be a long word alligned one), and a value.
77ac19f918SStefan Eßer **
78ac19f918SStefan Eßer **	pcibus_regirq():
79ac19f918SStefan Eßer **		Register an interupt handler for a pci device.
80ac19f918SStefan Eßer **		Requires a tag (from pcitag), the register number
81ac19f918SStefan Eßer **		(should be a long word alligned one), and a value.
82ac19f918SStefan Eßer **
83ac19f918SStefan Eßer **-----------------------------------------------------------------
84ac19f918SStefan Eßer */
85ac19f918SStefan Eßer 
86a3adc4f8SStefan Eßer static int
87a3adc4f8SStefan Eßer pcibus_check (void);
88a3adc4f8SStefan Eßer 
895b3f532eSStefan Eßer static void
905b3f532eSStefan Eßer pcibus_setup (void);
91ac19f918SStefan Eßer 
92ac19f918SStefan Eßer static pcici_t
93ac19f918SStefan Eßer pcibus_tag (u_char bus, u_char device, u_char func);
94ac19f918SStefan Eßer 
955b3f532eSStefan Eßer static pcici_t
965b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func);
975b3f532eSStefan Eßer 
98ac19f918SStefan Eßer static u_long
99ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg);
100ac19f918SStefan Eßer 
101ac19f918SStefan Eßer static void
102ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data);
103ac19f918SStefan Eßer 
104ac19f918SStefan Eßer static int
1055b3f532eSStefan Eßer pcibus_ihandler_attach (int irq, void(*ihandler)(), int arg, unsigned* maskp);
1065b3f532eSStefan Eßer 
1075b3f532eSStefan Eßer static int
1085b3f532eSStefan Eßer pcibus_ihandler_detach (int irq, void(*handler)());
1095b3f532eSStefan Eßer 
1105b3f532eSStefan Eßer static int
1115b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr);
1125b3f532eSStefan Eßer 
1135b3f532eSStefan Eßer static int
1145b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr);
115ac19f918SStefan Eßer 
116ac19f918SStefan Eßer struct pcibus i386pci = {
117ac19f918SStefan Eßer 	"pci",
1185b3f532eSStefan Eßer 	pcibus_setup,
119ac19f918SStefan Eßer 	pcibus_tag,
1205b3f532eSStefan Eßer 	pcibus_ftag,
121ac19f918SStefan Eßer 	pcibus_read,
122ac19f918SStefan Eßer 	pcibus_write,
1235b3f532eSStefan Eßer 	ICU_LEN,
1245b3f532eSStefan Eßer 	pcibus_ihandler_attach,
1255b3f532eSStefan Eßer 	pcibus_ihandler_detach,
1265b3f532eSStefan Eßer 	pcibus_imask_include,
1275b3f532eSStefan Eßer 	pcibus_imask_exclude,
128ac19f918SStefan Eßer };
129ac19f918SStefan Eßer 
130ac19f918SStefan Eßer /*
131ac19f918SStefan Eßer **	Announce structure to generic driver
132ac19f918SStefan Eßer */
133ac19f918SStefan Eßer 
134ac19f918SStefan Eßer DATA_SET (pcibus_set, i386pci);
135ac19f918SStefan Eßer 
136ac19f918SStefan Eßer /*--------------------------------------------------------------------
137ac19f918SStefan Eßer **
138ac19f918SStefan Eßer **      Determine configuration mode
139ac19f918SStefan Eßer **
140ac19f918SStefan Eßer **--------------------------------------------------------------------
141ac19f918SStefan Eßer */
142ac19f918SStefan Eßer 
143ac19f918SStefan Eßer 
144ac19f918SStefan Eßer #define CONF1_ADDR_PORT    0x0cf8
145ac19f918SStefan Eßer #define CONF1_DATA_PORT    0x0cfc
146ac19f918SStefan Eßer 
1472d144186SStefan Eßer #define CONF1_ENABLE       0x80000000ul
148a3adc4f8SStefan Eßer #define CONF1_ENABLE_CHK1  0xF0000001ul
149a3adc4f8SStefan Eßer #define CONF1_ENABLE_MSK1  0x80000001ul
150a3adc4f8SStefan Eßer #define CONF1_ENABLE_RES1  0x80000000ul
151a3adc4f8SStefan Eßer #define CONF1_ENABLE_CHK2  0xfffffffful
152a3adc4f8SStefan Eßer #define CONF1_ENABLE_RES2  0x80fffffcul
153ac19f918SStefan Eßer 
154ac19f918SStefan Eßer #define CONF2_ENABLE_PORT  0x0cf8
155ac19f918SStefan Eßer #define CONF2_FORWARD_PORT 0x0cfa
156ac19f918SStefan Eßer 
1572d144186SStefan Eßer #define CONF2_ENABLE_CHK   0x0e
1582d144186SStefan Eßer #define CONF2_ENABLE_RES   0x0e
159ac19f918SStefan Eßer 
160d7ea35fcSStefan Eßer 
161a3adc4f8SStefan Eßer static int
162a3adc4f8SStefan Eßer pcibus_check (void)
163a3adc4f8SStefan Eßer {
164a3adc4f8SStefan Eßer 	u_char device;
165a3adc4f8SStefan Eßer 
166a3adc4f8SStefan Eßer 	for (device = 0; device < pci_maxdevice; device++) {
167a3adc4f8SStefan Eßer 		if (pcibus_read (pcibus_tag (0,device,0), 0) != 0xfffffffful)
168a3adc4f8SStefan Eßer 			return 1;
169a3adc4f8SStefan Eßer 	}
170a3adc4f8SStefan Eßer 	return 0;
171a3adc4f8SStefan Eßer }
172d7ea35fcSStefan Eßer 
1735b3f532eSStefan Eßer static void
1745b3f532eSStefan Eßer pcibus_setup (void)
175ac19f918SStefan Eßer {
176ac19f918SStefan Eßer 	u_long result, oldval;
177ac19f918SStefan Eßer 
178ac19f918SStefan Eßer 	/*---------------------------------------
1790847c06dSStefan Eßer 	**      Configuration mode 1 ?
1800847c06dSStefan Eßer 	**---------------------------------------
1810847c06dSStefan Eßer 	*/
1820847c06dSStefan Eßer 
1830847c06dSStefan Eßer 	oldval = inl (CONF1_ADDR_PORT);
184a3adc4f8SStefan Eßer 	outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
185a3adc4f8SStefan Eßer 	outb (CONF1_ADDR_PORT +3, 0);
1860847c06dSStefan Eßer 	result = inl (CONF1_ADDR_PORT);
1870847c06dSStefan Eßer 	outl (CONF1_ADDR_PORT, oldval);
1880847c06dSStefan Eßer 
189a3adc4f8SStefan Eßer 	if ((result & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
1900847c06dSStefan Eßer 		pci_mechanism = 1;
1910847c06dSStefan Eßer 		pci_maxdevice = 32;
192a3adc4f8SStefan Eßer 		if (pcibus_check())
1930847c06dSStefan Eßer 			return;
1940847c06dSStefan Eßer 	};
1950847c06dSStefan Eßer 
1960847c06dSStefan Eßer 	/*---------------------------------------
197ac19f918SStefan Eßer 	**      Configuration mode 2 ?
198ac19f918SStefan Eßer 	**---------------------------------------
199ac19f918SStefan Eßer 	*/
200ac19f918SStefan Eßer 
2012d144186SStefan Eßer 	outb (CONF2_ENABLE_PORT,  CONF2_ENABLE_CHK);
202ac19f918SStefan Eßer 	outb (CONF2_FORWARD_PORT, 0);
2032d144186SStefan Eßer 	result = inb (CONF2_ENABLE_PORT);
2042d144186SStefan Eßer 
2052d144186SStefan Eßer 	outb (CONF2_ENABLE_PORT,  0);
206a3adc4f8SStefan Eßer 	outb (CONF2_FORWARD_PORT, 0);
2072d144186SStefan Eßer 	if ((result == CONF2_ENABLE_RES)
2082d144186SStefan Eßer 	    && !inb (CONF2_ENABLE_PORT)
2092d144186SStefan Eßer 	    && !inb (CONF2_FORWARD_PORT)) {
2105b3f532eSStefan Eßer 		pci_mechanism = 2;
2115b3f532eSStefan Eßer 		pci_maxdevice = 16;
212a3adc4f8SStefan Eßer 		if (pcibus_check())
2130f29bf01SStefan Eßer 			return;
214ac19f918SStefan Eßer 	};
215ac19f918SStefan Eßer 
216a3adc4f8SStefan Eßer 
217a3adc4f8SStefan Eßer 	/*-----------------------------------------------------
218a3adc4f8SStefan Eßer 	**      Well, is it Configuration mode 1, after all ?
219a3adc4f8SStefan Eßer 	**-----------------------------------------------------
220a3adc4f8SStefan Eßer 	*/
221a3adc4f8SStefan Eßer 
222a3adc4f8SStefan Eßer 	oldval = inl (CONF1_ADDR_PORT);
223a3adc4f8SStefan Eßer 	outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK2);
224a3adc4f8SStefan Eßer 	outl (CONF1_DATA_PORT, 0);
225a3adc4f8SStefan Eßer 	result = inl (CONF1_ADDR_PORT);
226a3adc4f8SStefan Eßer 	outl (CONF1_ADDR_PORT, oldval);
227a3adc4f8SStefan Eßer 
228a3adc4f8SStefan Eßer 	if (result == CONF1_ENABLE_RES2) {
229a3adc4f8SStefan Eßer 		pci_mechanism = 1;
230a3adc4f8SStefan Eßer 		pci_maxdevice = 32;
231a3adc4f8SStefan Eßer 		if (pcibus_check())
232a3adc4f8SStefan Eßer 			return;
233a3adc4f8SStefan Eßer 	}
234a3adc4f8SStefan Eßer 
235ac19f918SStefan Eßer 	/*---------------------------------------
236cda67911SStefan Eßer 	**      No PCI bus host bridge found
237ac19f918SStefan Eßer 	**---------------------------------------
238ac19f918SStefan Eßer 	*/
239cda67911SStefan Eßer 
240a3adc4f8SStefan Eßer 	if (bootverbose && (result != 0xfffffffful))
241a3adc4f8SStefan Eßer 		printf ("pcibus_setup: "
242a3adc4f8SStefan Eßer 			"wrote 0x%08x, read back 0x%08x, expected 0x%08x\n",
243a3adc4f8SStefan Eßer 			CONF1_ENABLE_CHK2, result, CONF1_ENABLE_RES2);
244a3adc4f8SStefan Eßer 
245cda67911SStefan Eßer 	pci_mechanism = 0;
246cda67911SStefan Eßer 	pci_maxdevice = 0;
247ac19f918SStefan Eßer }
2485b3f532eSStefan Eßer 
249ac19f918SStefan Eßer /*--------------------------------------------------------------------
250ac19f918SStefan Eßer **
251ac19f918SStefan Eßer **      Build a pcitag from bus, device and function number
252ac19f918SStefan Eßer **
253ac19f918SStefan Eßer **--------------------------------------------------------------------
254ac19f918SStefan Eßer */
255ac19f918SStefan Eßer 
256ac19f918SStefan Eßer static pcici_t
257ac19f918SStefan Eßer pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
258ac19f918SStefan Eßer {
259ac19f918SStefan Eßer 	pcici_t tag;
260ac19f918SStefan Eßer 
261ac19f918SStefan Eßer 	tag.cfg1 = 0;
262ac19f918SStefan Eßer 	if (func   >=  8) return tag;
263ac19f918SStefan Eßer 
2645b3f532eSStefan Eßer 	switch (pci_mechanism) {
265ac19f918SStefan Eßer 
266ac19f918SStefan Eßer 	case 1:
2672d144186SStefan Eßer 		if (device < 32) {
268ac19f918SStefan Eßer 			tag.cfg1 = CONF1_ENABLE
269ac19f918SStefan Eßer 				| (((u_long) bus   ) << 16ul)
270ac19f918SStefan Eßer 				| (((u_long) device) << 11ul)
271ac19f918SStefan Eßer 				| (((u_long) func  ) <<  8ul);
2722d144186SStefan Eßer 		}
273ac19f918SStefan Eßer 		break;
274ac19f918SStefan Eßer 	case 2:
2752d144186SStefan Eßer 		if (device < 16) {
276ac19f918SStefan Eßer 			tag.cfg2.port    = 0xc000 | (device << 8ul);
2772d144186SStefan Eßer 			tag.cfg2.enable  = 0xf0 | (func << 1ul);
278ac19f918SStefan Eßer 			tag.cfg2.forward = bus;
2792d144186SStefan Eßer 		}
280ac19f918SStefan Eßer 		break;
281ac19f918SStefan Eßer 	};
282ac19f918SStefan Eßer 	return tag;
283ac19f918SStefan Eßer }
2845b3f532eSStefan Eßer 
2855b3f532eSStefan Eßer static pcici_t
2865b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func)
2875b3f532eSStefan Eßer {
2885b3f532eSStefan Eßer 	switch (pci_mechanism) {
2895b3f532eSStefan Eßer 
2905b3f532eSStefan Eßer 	case 1:
2915b3f532eSStefan Eßer 		tag.cfg1 &= ~0x700ul;
2925b3f532eSStefan Eßer 		tag.cfg1 |= (((u_long) func) << 8ul);
2935b3f532eSStefan Eßer 		break;
2945b3f532eSStefan Eßer 	case 2:
2952d144186SStefan Eßer 		tag.cfg2.enable  = 0xf0 | (func << 1ul);
2965b3f532eSStefan Eßer 		break;
2975b3f532eSStefan Eßer 	};
2985b3f532eSStefan Eßer 	return tag;
2995b3f532eSStefan Eßer }
3005b3f532eSStefan Eßer 
301ac19f918SStefan Eßer /*--------------------------------------------------------------------
302ac19f918SStefan Eßer **
303ac19f918SStefan Eßer **      Read register from configuration space.
304ac19f918SStefan Eßer **
305ac19f918SStefan Eßer **--------------------------------------------------------------------
306ac19f918SStefan Eßer */
307ac19f918SStefan Eßer 
308ac19f918SStefan Eßer static u_long
309ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg)
310ac19f918SStefan Eßer {
311ac19f918SStefan Eßer 	u_long addr, data = 0;
312ac19f918SStefan Eßer 
313ac19f918SStefan Eßer 	if (!tag.cfg1) return (0xfffffffful);
314ac19f918SStefan Eßer 
3155b3f532eSStefan Eßer 	switch (pci_mechanism) {
316ac19f918SStefan Eßer 
317ac19f918SStefan Eßer 	case 1:
318ac19f918SStefan Eßer 		addr = tag.cfg1 | (reg & 0xfc);
319ac19f918SStefan Eßer #ifdef PCI_DEBUG
320ac19f918SStefan Eßer 		printf ("pci_conf_read(1): addr=%x ", addr);
321ac19f918SStefan Eßer #endif
322ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, addr);
323ac19f918SStefan Eßer 		data = inl (CONF1_DATA_PORT);
324ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, 0   );
325ac19f918SStefan Eßer 		break;
326ac19f918SStefan Eßer 
327ac19f918SStefan Eßer 	case 2:
328ac19f918SStefan Eßer 		addr = tag.cfg2.port | (reg & 0xfc);
329ac19f918SStefan Eßer #ifdef PCI_DEBUG
330ac19f918SStefan Eßer 		printf ("pci_conf_read(2): addr=%x ", addr);
331ac19f918SStefan Eßer #endif
332ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
333ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
334ac19f918SStefan Eßer 
335ac19f918SStefan Eßer 		data = inl ((u_short) addr);
336ac19f918SStefan Eßer 
337ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  0);
338ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, 0);
339ac19f918SStefan Eßer 		break;
340ac19f918SStefan Eßer 	};
341ac19f918SStefan Eßer 
342ac19f918SStefan Eßer #ifdef PCI_DEBUG
343ac19f918SStefan Eßer 	printf ("data=%x\n", data);
344ac19f918SStefan Eßer #endif
345ac19f918SStefan Eßer 
346ac19f918SStefan Eßer 	return (data);
347ac19f918SStefan Eßer }
3485b3f532eSStefan Eßer 
349ac19f918SStefan Eßer /*--------------------------------------------------------------------
350ac19f918SStefan Eßer **
351ac19f918SStefan Eßer **      Write register into configuration space.
352ac19f918SStefan Eßer **
353ac19f918SStefan Eßer **--------------------------------------------------------------------
354ac19f918SStefan Eßer */
355ac19f918SStefan Eßer 
356ac19f918SStefan Eßer static void
357ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data)
358ac19f918SStefan Eßer {
359ac19f918SStefan Eßer 	u_long addr;
360ac19f918SStefan Eßer 
361ac19f918SStefan Eßer 	if (!tag.cfg1) return;
362ac19f918SStefan Eßer 
3635b3f532eSStefan Eßer 	switch (pci_mechanism) {
364ac19f918SStefan Eßer 
365ac19f918SStefan Eßer 	case 1:
366ac19f918SStefan Eßer 		addr = tag.cfg1 | (reg & 0xfc);
367ac19f918SStefan Eßer #ifdef PCI_DEBUG
368ac19f918SStefan Eßer 		printf ("pci_conf_write(1): addr=%x data=%x\n",
369ac19f918SStefan Eßer 			addr, data);
370ac19f918SStefan Eßer #endif
371ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, addr);
372ac19f918SStefan Eßer 		outl (CONF1_DATA_PORT, data);
373ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT,   0 );
374ac19f918SStefan Eßer 		break;
375ac19f918SStefan Eßer 
376ac19f918SStefan Eßer 	case 2:
377ac19f918SStefan Eßer 		addr = tag.cfg2.port | (reg & 0xfc);
378ac19f918SStefan Eßer #ifdef PCI_DEBUG
379ac19f918SStefan Eßer 		printf ("pci_conf_write(2): addr=%x data=%x\n",
380ac19f918SStefan Eßer 			addr, data);
381ac19f918SStefan Eßer #endif
382ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  tag.cfg2.enable);
383ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
384ac19f918SStefan Eßer 
385ac19f918SStefan Eßer 		outl ((u_short) addr, data);
386ac19f918SStefan Eßer 
387ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  0);
388ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, 0);
389ac19f918SStefan Eßer 		break;
390ac19f918SStefan Eßer 	};
391ac19f918SStefan Eßer }
3925b3f532eSStefan Eßer 
393ac19f918SStefan Eßer /*-----------------------------------------------------------------------
394ac19f918SStefan Eßer **
395ac19f918SStefan Eßer **	Register an interupt handler for a pci device.
396ac19f918SStefan Eßer **
397ac19f918SStefan Eßer **-----------------------------------------------------------------------
398ac19f918SStefan Eßer */
399ac19f918SStefan Eßer 
400ac19f918SStefan Eßer static int
4015b3f532eSStefan Eßer pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr)
402ac19f918SStefan Eßer {
4035b3f532eSStefan Eßer 	int result;
4045b3f532eSStefan Eßer 	result = register_intr(
405ac19f918SStefan Eßer 		irq,		    /* isa irq	    */
406ac19f918SStefan Eßer 		0,		    /* deviced??    */
407ac19f918SStefan Eßer 		0,		    /* flags?	    */
408ac19f918SStefan Eßer 		(inthand2_t*) func, /* handler	    */
409ac19f918SStefan Eßer 		maskptr,	    /* mask pointer */
4105b3f532eSStefan Eßer 		arg);		    /* handler arg  */
411ac19f918SStefan Eßer 
4125b3f532eSStefan Eßer 	if (result) {
4135b3f532eSStefan Eßer 		printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
4145b3f532eSStefan Eßer 		return (result);
415ac19f918SStefan Eßer 	};
4165b3f532eSStefan Eßer 	update_intr_masks();
417ac19f918SStefan Eßer 
4185b3f532eSStefan Eßer 	INTREN ((1ul<<irq));
4195b3f532eSStefan Eßer 	return (0);
4205b3f532eSStefan Eßer }
421ac19f918SStefan Eßer 
4225b3f532eSStefan Eßer static int
4235b3f532eSStefan Eßer pcibus_ihandler_detach (int irq, void(*func)())
4245b3f532eSStefan Eßer {
4255b3f532eSStefan Eßer 	int result;
4265b3f532eSStefan Eßer 
4275b3f532eSStefan Eßer 	INTRDIS ((1ul<<irq));
4285b3f532eSStefan Eßer 
4295b3f532eSStefan Eßer 	result = unregister_intr (irq, (inthand2_t*) func);
4305b3f532eSStefan Eßer 
4315b3f532eSStefan Eßer 	if (result)
4325b3f532eSStefan Eßer 		printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
4335b3f532eSStefan Eßer 
4345b3f532eSStefan Eßer 	update_intr_masks();
4355b3f532eSStefan Eßer 
4365b3f532eSStefan Eßer 	return (result);
4375b3f532eSStefan Eßer }
4385b3f532eSStefan Eßer 
4395b3f532eSStefan Eßer static int
4405b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr)
4415b3f532eSStefan Eßer {
4425b3f532eSStefan Eßer 	unsigned mask;
4435b3f532eSStefan Eßer 
4445b3f532eSStefan Eßer 	if (!maskptr) return (0);
4455b3f532eSStefan Eßer 
4465b3f532eSStefan Eßer 	mask = 1ul << irq;
4475b3f532eSStefan Eßer 
4485b3f532eSStefan Eßer 	if (*maskptr & mask)
4495b3f532eSStefan Eßer 		return (-1);
4505b3f532eSStefan Eßer 
4515b3f532eSStefan Eßer 	INTRMASK (*maskptr, mask);
4525b3f532eSStefan Eßer 	update_intr_masks();
4535b3f532eSStefan Eßer 
4545b3f532eSStefan Eßer 	return (0);
4555b3f532eSStefan Eßer }
4565b3f532eSStefan Eßer 
4575b3f532eSStefan Eßer static int
4585b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr)
4595b3f532eSStefan Eßer {
4605b3f532eSStefan Eßer 	unsigned mask;
4615b3f532eSStefan Eßer 
4625b3f532eSStefan Eßer 	if (!maskptr) return (0);
4635b3f532eSStefan Eßer 
4645b3f532eSStefan Eßer 	mask = 1ul << irq;
4655b3f532eSStefan Eßer 
4665b3f532eSStefan Eßer 	if (! (*maskptr & mask))
4675b3f532eSStefan Eßer 		return (-1);
4685b3f532eSStefan Eßer 
4695b3f532eSStefan Eßer 	*maskptr &= ~mask;
4705b3f532eSStefan Eßer 	update_intr_masks();
4715b3f532eSStefan Eßer 
4725b3f532eSStefan Eßer 	return (0);
473ac19f918SStefan Eßer }
474