xref: /freebsd/sys/i386/pci/pci_cfgreg.c (revision 77b573149a6df870e2bdf23af7b324fe8f381505)
1ac19f918SStefan Eßer /**************************************************************************
2ac19f918SStefan Eßer **
377b57314SStefan Eßer **  $Id: pcibus.c,v 1.14 1995/09/18 21:48:39 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
14877b57314SStefan Eßer #define CONF1_ENABLE_CHK   0x80000000ul
14977b57314SStefan Eßer #define CONF1_ENABLE_CHK1  0xFF000001ul
15077b57314SStefan Eßer #define CONF1_ENABLE_MSK1  0x80000000ul
151a3adc4f8SStefan Eßer #define CONF1_ENABLE_RES1  0x80000000ul
152ac19f918SStefan Eßer 
153ac19f918SStefan Eßer #define CONF2_ENABLE_PORT  0x0cf8
154ac19f918SStefan Eßer #define CONF2_FORWARD_PORT 0x0cfa
155ac19f918SStefan Eßer 
1562d144186SStefan Eßer #define CONF2_ENABLE_CHK   0x0e
1572d144186SStefan Eßer #define CONF2_ENABLE_RES   0x0e
158ac19f918SStefan Eßer 
159a3adc4f8SStefan Eßer static int
160a3adc4f8SStefan Eßer pcibus_check (void)
161a3adc4f8SStefan Eßer {
162a3adc4f8SStefan Eßer 	u_char device;
163a3adc4f8SStefan Eßer 
16477b57314SStefan Eßer 	if (bootverbose) printf ("pcibus_check:\tdevice ");
16577b57314SStefan Eßer 
166a3adc4f8SStefan Eßer 	for (device = 0; device < pci_maxdevice; device++) {
16777b57314SStefan Eßer 		if (bootverbose) printf ("%d ", device);
16877b57314SStefan Eßer 		if (pcibus_read (pcibus_tag (0,device,0), 0) != 0xfffffffful) {
16977b57314SStefan Eßer 			if (bootverbose) printf ("is there\n");
170a3adc4f8SStefan Eßer 			return 1;
171a3adc4f8SStefan Eßer 		}
17277b57314SStefan Eßer 	}
17377b57314SStefan Eßer 	if (bootverbose) printf ("-- nothing found\n");
174a3adc4f8SStefan Eßer 	return 0;
175a3adc4f8SStefan Eßer }
176d7ea35fcSStefan Eßer 
1775b3f532eSStefan Eßer static void
1785b3f532eSStefan Eßer pcibus_setup (void)
179ac19f918SStefan Eßer {
18077b57314SStefan Eßer 	unsigned long mode1res,oldval;
18177b57314SStefan Eßer 	unsigned char mode2res;
1820847c06dSStefan Eßer 
1830847c06dSStefan Eßer 	oldval = inl (CONF1_ADDR_PORT);
18477b57314SStefan Eßer 	outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
1852d144186SStefan Eßer 	outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
18677b57314SStefan Eßer 	mode1res = inl(CONF1_ADDR_PORT);
18777b57314SStefan Eßer 	mode2res = inb(CONF2_ENABLE_PORT);
188a3adc4f8SStefan Eßer 	outl (CONF1_ADDR_PORT, oldval);
189a3adc4f8SStefan Eßer 
19077b57314SStefan Eßer 	if (bootverbose) {
19177b57314SStefan Eßer 		printf ("pcibus_setup(1):\tmode1res=0x%08lx (0x%08lx), "
19277b57314SStefan Eßer 			"mode2res=0x%02x (0x%02x)\n",
19377b57314SStefan Eßer 			mode1res,CONF1_ENABLE_CHK,
19477b57314SStefan Eßer 			(int)mode2res,CONF2_ENABLE_CHK);
19577b57314SStefan Eßer 	}
19677b57314SStefan Eßer 
19777b57314SStefan Eßer 	/*---------------------------------------
19877b57314SStefan Eßer 	**	No PCI, if neither mode1res nor mode2res could be read back
19977b57314SStefan Eßer 	**---------------------------------------
20077b57314SStefan Eßer 	*/
20177b57314SStefan Eßer 
20277b57314SStefan Eßer 	if ((mode1res != CONF1_ENABLE_CHK) && (mode2res != CONF2_ENABLE_CHK)) {
203a3adc4f8SStefan Eßer 		return;
204a3adc4f8SStefan Eßer 	}
205a3adc4f8SStefan Eßer 
206ac19f918SStefan Eßer 	/*---------------------------------------
20777b57314SStefan Eßer 	**      Assume configuration mechanism 1 for now ...
20877b57314SStefan Eßer 	**---------------------------------------
20977b57314SStefan Eßer 	*/
21077b57314SStefan Eßer 
21177b57314SStefan Eßer 	pci_mechanism = 1;
21277b57314SStefan Eßer 	pci_maxdevice = 32;
21377b57314SStefan Eßer 
21477b57314SStefan Eßer 	outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
21577b57314SStefan Eßer 	outb (CONF1_ADDR_PORT +3, 0);
21677b57314SStefan Eßer 	mode1res = inl (CONF1_ADDR_PORT);
21777b57314SStefan Eßer 	outl (CONF1_ADDR_PORT, oldval);
21877b57314SStefan Eßer 
21977b57314SStefan Eßer 	if (bootverbose)
22077b57314SStefan Eßer 		printf ("pcibus_setup(2):\tmode1res=0x%08lx (0x%08lx)\n",
22177b57314SStefan Eßer 			mode1res, CONF1_ENABLE_CHK);
22277b57314SStefan Eßer 
22377b57314SStefan Eßer 	if (mode1res) {
22477b57314SStefan Eßer 		if (pcibus_check())
22577b57314SStefan Eßer 			return;
22677b57314SStefan Eßer 	};
22777b57314SStefan Eßer 
22877b57314SStefan Eßer 	outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
22977b57314SStefan Eßer 	outl (CONF1_DATA_PORT, 0);
23077b57314SStefan Eßer 	mode1res = inl(CONF1_ADDR_PORT);
23177b57314SStefan Eßer 	outl (CONF1_ADDR_PORT, oldval);
23277b57314SStefan Eßer 
23377b57314SStefan Eßer 	if (bootverbose)
23477b57314SStefan Eßer 		printf ("pcibus_setup(3):\tmode1res=0x%08lx (0x%08lx)\n",
23577b57314SStefan Eßer 			mode1res, CONF1_ENABLE_CHK1);
23677b57314SStefan Eßer 
23777b57314SStefan Eßer 	if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_CHK1) {
23877b57314SStefan Eßer 		if (pcibus_check())
23977b57314SStefan Eßer 			return;
24077b57314SStefan Eßer 	};
24177b57314SStefan Eßer 
24277b57314SStefan Eßer 	/*---------------------------------------
24377b57314SStefan Eßer 	**      Try configuration mechanism 2 ...
24477b57314SStefan Eßer 	**---------------------------------------
24577b57314SStefan Eßer 	*/
24677b57314SStefan Eßer 
24777b57314SStefan Eßer 	pci_mechanism = 2;
24877b57314SStefan Eßer 	pci_maxdevice = 16;
24977b57314SStefan Eßer 
25077b57314SStefan Eßer 	if (pcibus_check())
25177b57314SStefan Eßer 	    return;
25277b57314SStefan Eßer 
25377b57314SStefan Eßer 	/*---------------------------------------
254cda67911SStefan Eßer 	**      No PCI bus host bridge found
255ac19f918SStefan Eßer 	**---------------------------------------
256ac19f918SStefan Eßer 	*/
257cda67911SStefan Eßer 
258cda67911SStefan Eßer 	pci_mechanism = 0;
259cda67911SStefan Eßer 	pci_maxdevice = 0;
260ac19f918SStefan Eßer }
2615b3f532eSStefan Eßer 
262ac19f918SStefan Eßer /*--------------------------------------------------------------------
263ac19f918SStefan Eßer **
264ac19f918SStefan Eßer **      Build a pcitag from bus, device and function number
265ac19f918SStefan Eßer **
266ac19f918SStefan Eßer **--------------------------------------------------------------------
267ac19f918SStefan Eßer */
268ac19f918SStefan Eßer 
269ac19f918SStefan Eßer static pcici_t
270ac19f918SStefan Eßer pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
271ac19f918SStefan Eßer {
272ac19f918SStefan Eßer 	pcici_t tag;
273ac19f918SStefan Eßer 
274ac19f918SStefan Eßer 	tag.cfg1 = 0;
275ac19f918SStefan Eßer 	if (func   >=  8) return tag;
276ac19f918SStefan Eßer 
2775b3f532eSStefan Eßer 	switch (pci_mechanism) {
278ac19f918SStefan Eßer 
279ac19f918SStefan Eßer 	case 1:
2802d144186SStefan Eßer 		if (device < 32) {
281ac19f918SStefan Eßer 			tag.cfg1 = CONF1_ENABLE
282ac19f918SStefan Eßer 				| (((u_long) bus   ) << 16ul)
283ac19f918SStefan Eßer 				| (((u_long) device) << 11ul)
284ac19f918SStefan Eßer 				| (((u_long) func  ) <<  8ul);
2852d144186SStefan Eßer 		}
286ac19f918SStefan Eßer 		break;
287ac19f918SStefan Eßer 	case 2:
2882d144186SStefan Eßer 		if (device < 16) {
289ac19f918SStefan Eßer 			tag.cfg2.port    = 0xc000 | (device << 8ul);
2902d144186SStefan Eßer 			tag.cfg2.enable  = 0xf0 | (func << 1ul);
291ac19f918SStefan Eßer 			tag.cfg2.forward = bus;
2922d144186SStefan Eßer 		}
293ac19f918SStefan Eßer 		break;
294ac19f918SStefan Eßer 	};
295ac19f918SStefan Eßer 	return tag;
296ac19f918SStefan Eßer }
2975b3f532eSStefan Eßer 
2985b3f532eSStefan Eßer static pcici_t
2995b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func)
3005b3f532eSStefan Eßer {
3015b3f532eSStefan Eßer 	switch (pci_mechanism) {
3025b3f532eSStefan Eßer 
3035b3f532eSStefan Eßer 	case 1:
3045b3f532eSStefan Eßer 		tag.cfg1 &= ~0x700ul;
3055b3f532eSStefan Eßer 		tag.cfg1 |= (((u_long) func) << 8ul);
3065b3f532eSStefan Eßer 		break;
3075b3f532eSStefan Eßer 	case 2:
3082d144186SStefan Eßer 		tag.cfg2.enable  = 0xf0 | (func << 1ul);
3095b3f532eSStefan Eßer 		break;
3105b3f532eSStefan Eßer 	};
3115b3f532eSStefan Eßer 	return tag;
3125b3f532eSStefan Eßer }
3135b3f532eSStefan Eßer 
314ac19f918SStefan Eßer /*--------------------------------------------------------------------
315ac19f918SStefan Eßer **
316ac19f918SStefan Eßer **      Read register from configuration space.
317ac19f918SStefan Eßer **
318ac19f918SStefan Eßer **--------------------------------------------------------------------
319ac19f918SStefan Eßer */
320ac19f918SStefan Eßer 
321ac19f918SStefan Eßer static u_long
322ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg)
323ac19f918SStefan Eßer {
324ac19f918SStefan Eßer 	u_long addr, data = 0;
325ac19f918SStefan Eßer 
326ac19f918SStefan Eßer 	if (!tag.cfg1) return (0xfffffffful);
327ac19f918SStefan Eßer 
3285b3f532eSStefan Eßer 	switch (pci_mechanism) {
329ac19f918SStefan Eßer 
330ac19f918SStefan Eßer 	case 1:
331ac19f918SStefan Eßer 		addr = tag.cfg1 | (reg & 0xfc);
332ac19f918SStefan Eßer #ifdef PCI_DEBUG
333ac19f918SStefan Eßer 		printf ("pci_conf_read(1): addr=%x ", addr);
334ac19f918SStefan Eßer #endif
335ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, addr);
336ac19f918SStefan Eßer 		data = inl (CONF1_DATA_PORT);
337ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, 0   );
338ac19f918SStefan Eßer 		break;
339ac19f918SStefan Eßer 
340ac19f918SStefan Eßer 	case 2:
341ac19f918SStefan Eßer 		addr = tag.cfg2.port | (reg & 0xfc);
342ac19f918SStefan Eßer #ifdef PCI_DEBUG
343ac19f918SStefan Eßer 		printf ("pci_conf_read(2): addr=%x ", addr);
344ac19f918SStefan Eßer #endif
345ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
346ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
347ac19f918SStefan Eßer 
348ac19f918SStefan Eßer 		data = inl ((u_short) addr);
349ac19f918SStefan Eßer 
350ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  0);
351ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, 0);
352ac19f918SStefan Eßer 		break;
353ac19f918SStefan Eßer 	};
354ac19f918SStefan Eßer 
355ac19f918SStefan Eßer #ifdef PCI_DEBUG
356ac19f918SStefan Eßer 	printf ("data=%x\n", data);
357ac19f918SStefan Eßer #endif
358ac19f918SStefan Eßer 
359ac19f918SStefan Eßer 	return (data);
360ac19f918SStefan Eßer }
3615b3f532eSStefan Eßer 
362ac19f918SStefan Eßer /*--------------------------------------------------------------------
363ac19f918SStefan Eßer **
364ac19f918SStefan Eßer **      Write register into configuration space.
365ac19f918SStefan Eßer **
366ac19f918SStefan Eßer **--------------------------------------------------------------------
367ac19f918SStefan Eßer */
368ac19f918SStefan Eßer 
369ac19f918SStefan Eßer static void
370ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data)
371ac19f918SStefan Eßer {
372ac19f918SStefan Eßer 	u_long addr;
373ac19f918SStefan Eßer 
374ac19f918SStefan Eßer 	if (!tag.cfg1) return;
375ac19f918SStefan Eßer 
3765b3f532eSStefan Eßer 	switch (pci_mechanism) {
377ac19f918SStefan Eßer 
378ac19f918SStefan Eßer 	case 1:
379ac19f918SStefan Eßer 		addr = tag.cfg1 | (reg & 0xfc);
380ac19f918SStefan Eßer #ifdef PCI_DEBUG
381ac19f918SStefan Eßer 		printf ("pci_conf_write(1): addr=%x data=%x\n",
382ac19f918SStefan Eßer 			addr, data);
383ac19f918SStefan Eßer #endif
384ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, addr);
385ac19f918SStefan Eßer 		outl (CONF1_DATA_PORT, data);
386ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT,   0 );
387ac19f918SStefan Eßer 		break;
388ac19f918SStefan Eßer 
389ac19f918SStefan Eßer 	case 2:
390ac19f918SStefan Eßer 		addr = tag.cfg2.port | (reg & 0xfc);
391ac19f918SStefan Eßer #ifdef PCI_DEBUG
392ac19f918SStefan Eßer 		printf ("pci_conf_write(2): addr=%x data=%x\n",
393ac19f918SStefan Eßer 			addr, data);
394ac19f918SStefan Eßer #endif
395ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  tag.cfg2.enable);
396ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
397ac19f918SStefan Eßer 
398ac19f918SStefan Eßer 		outl ((u_short) addr, data);
399ac19f918SStefan Eßer 
400ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  0);
401ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, 0);
402ac19f918SStefan Eßer 		break;
403ac19f918SStefan Eßer 	};
404ac19f918SStefan Eßer }
4055b3f532eSStefan Eßer 
406ac19f918SStefan Eßer /*-----------------------------------------------------------------------
407ac19f918SStefan Eßer **
408ac19f918SStefan Eßer **	Register an interupt handler for a pci device.
409ac19f918SStefan Eßer **
410ac19f918SStefan Eßer **-----------------------------------------------------------------------
411ac19f918SStefan Eßer */
412ac19f918SStefan Eßer 
413ac19f918SStefan Eßer static int
4145b3f532eSStefan Eßer pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr)
415ac19f918SStefan Eßer {
4165b3f532eSStefan Eßer 	int result;
4175b3f532eSStefan Eßer 	result = register_intr(
418ac19f918SStefan Eßer 		irq,		    /* isa irq	    */
419ac19f918SStefan Eßer 		0,		    /* deviced??    */
420ac19f918SStefan Eßer 		0,		    /* flags?	    */
421ac19f918SStefan Eßer 		(inthand2_t*) func, /* handler	    */
422ac19f918SStefan Eßer 		maskptr,	    /* mask pointer */
4235b3f532eSStefan Eßer 		arg);		    /* handler arg  */
424ac19f918SStefan Eßer 
4255b3f532eSStefan Eßer 	if (result) {
4265b3f532eSStefan Eßer 		printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
4275b3f532eSStefan Eßer 		return (result);
428ac19f918SStefan Eßer 	};
4295b3f532eSStefan Eßer 	update_intr_masks();
430ac19f918SStefan Eßer 
4315b3f532eSStefan Eßer 	INTREN ((1ul<<irq));
4325b3f532eSStefan Eßer 	return (0);
4335b3f532eSStefan Eßer }
434ac19f918SStefan Eßer 
4355b3f532eSStefan Eßer static int
4365b3f532eSStefan Eßer pcibus_ihandler_detach (int irq, void(*func)())
4375b3f532eSStefan Eßer {
4385b3f532eSStefan Eßer 	int result;
4395b3f532eSStefan Eßer 
4405b3f532eSStefan Eßer 	INTRDIS ((1ul<<irq));
4415b3f532eSStefan Eßer 
4425b3f532eSStefan Eßer 	result = unregister_intr (irq, (inthand2_t*) func);
4435b3f532eSStefan Eßer 
4445b3f532eSStefan Eßer 	if (result)
4455b3f532eSStefan Eßer 		printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
4465b3f532eSStefan Eßer 
4475b3f532eSStefan Eßer 	update_intr_masks();
4485b3f532eSStefan Eßer 
4495b3f532eSStefan Eßer 	return (result);
4505b3f532eSStefan Eßer }
4515b3f532eSStefan Eßer 
4525b3f532eSStefan Eßer static int
4535b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr)
4545b3f532eSStefan Eßer {
4555b3f532eSStefan Eßer 	unsigned mask;
4565b3f532eSStefan Eßer 
4575b3f532eSStefan Eßer 	if (!maskptr) return (0);
4585b3f532eSStefan Eßer 
4595b3f532eSStefan Eßer 	mask = 1ul << irq;
4605b3f532eSStefan Eßer 
4615b3f532eSStefan Eßer 	if (*maskptr & mask)
4625b3f532eSStefan Eßer 		return (-1);
4635b3f532eSStefan Eßer 
4645b3f532eSStefan Eßer 	INTRMASK (*maskptr, mask);
4655b3f532eSStefan Eßer 	update_intr_masks();
4665b3f532eSStefan Eßer 
4675b3f532eSStefan Eßer 	return (0);
4685b3f532eSStefan Eßer }
4695b3f532eSStefan Eßer 
4705b3f532eSStefan Eßer static int
4715b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr)
4725b3f532eSStefan Eßer {
4735b3f532eSStefan Eßer 	unsigned mask;
4745b3f532eSStefan Eßer 
4755b3f532eSStefan Eßer 	if (!maskptr) return (0);
4765b3f532eSStefan Eßer 
4775b3f532eSStefan Eßer 	mask = 1ul << irq;
4785b3f532eSStefan Eßer 
4795b3f532eSStefan Eßer 	if (! (*maskptr & mask))
4805b3f532eSStefan Eßer 		return (-1);
4815b3f532eSStefan Eßer 
4825b3f532eSStefan Eßer 	*maskptr &= ~mask;
4835b3f532eSStefan Eßer 	update_intr_masks();
4845b3f532eSStefan Eßer 
4855b3f532eSStefan Eßer 	return (0);
486ac19f918SStefan Eßer }
487