xref: /freebsd/sys/i386/pci/pci_cfgreg.c (revision 287911bd502c3637bd3b7eaec5dd74cc15e7f2b8)
1ac19f918SStefan Eßer /**************************************************************************
2ac19f918SStefan Eßer **
3287911bdSStefan Eßer **  $Id: pcibus.c,v 1.16 1995/10/09 21:56:24 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
150287911bdSStefan Eßer #define CONF1_ENABLE_MSK1  0x80000001ul
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++) {
167c7483249SStefan Eßer 		unsigned long id;
168c7483249SStefan Eßer 		if (bootverbose)
169c7483249SStefan Eßer 			printf ("%d ", device);
170c7483249SStefan Eßer 		id = pcibus_read (pcibus_tag (0,device,0), 0);
171c7483249SStefan Eßer 		if (id != 0xfffffffful) {
172c7483249SStefan Eßer 			if (bootverbose) printf ("is there (id=%08lx)\n", id);
173a3adc4f8SStefan Eßer 			return 1;
174a3adc4f8SStefan Eßer 		}
17577b57314SStefan Eßer 	}
176c7483249SStefan Eßer 	if (bootverbose)
177c7483249SStefan Eßer 		printf ("-- nothing found\n");
178a3adc4f8SStefan Eßer 	return 0;
179a3adc4f8SStefan Eßer }
180d7ea35fcSStefan Eßer 
1815b3f532eSStefan Eßer static void
1825b3f532eSStefan Eßer pcibus_setup (void)
183ac19f918SStefan Eßer {
184287911bdSStefan Eßer 	unsigned long mode1res,oldval1;
185287911bdSStefan Eßer 	unsigned char mode2res,oldval2;
1860847c06dSStefan Eßer 
187287911bdSStefan Eßer 	oldval1 = inl (CONF1_ADDR_PORT);
188a3adc4f8SStefan Eßer 
18977b57314SStefan Eßer 	if (bootverbose) {
190287911bdSStefan Eßer 		printf ("pcibus_setup(1):\tmode1 addr port (0x0cf8) is 0x%08lx\n", oldval1);
191a3adc4f8SStefan Eßer 	}
192a3adc4f8SStefan Eßer 
193ac19f918SStefan Eßer 	/*---------------------------------------
19477b57314SStefan Eßer 	**      Assume configuration mechanism 1 for now ...
19577b57314SStefan Eßer 	**---------------------------------------
19677b57314SStefan Eßer 	*/
19777b57314SStefan Eßer 
198287911bdSStefan Eßer 	if ((oldval1 & CONF1_ENABLE) == 0) {
199287911bdSStefan Eßer 
20077b57314SStefan Eßer 		pci_mechanism = 1;
20177b57314SStefan Eßer 		pci_maxdevice = 32;
20277b57314SStefan Eßer 
20377b57314SStefan Eßer 		outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
20477b57314SStefan Eßer 		outb (CONF1_ADDR_PORT +3, 0);
20577b57314SStefan Eßer 		mode1res = inl (CONF1_ADDR_PORT);
206287911bdSStefan Eßer 		outl (CONF1_ADDR_PORT, oldval1);
20777b57314SStefan Eßer 
20877b57314SStefan Eßer 		if (bootverbose)
209287911bdSStefan Eßer 		    printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n",
21077b57314SStefan Eßer 			    mode1res, CONF1_ENABLE_CHK);
21177b57314SStefan Eßer 
21277b57314SStefan Eßer 		if (mode1res) {
21377b57314SStefan Eßer 			if (pcibus_check())
21477b57314SStefan Eßer 				return;
21577b57314SStefan Eßer 		};
21677b57314SStefan Eßer 
21777b57314SStefan Eßer 		outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
21877b57314SStefan Eßer 		mode1res = inl(CONF1_ADDR_PORT);
219287911bdSStefan Eßer 		outl (CONF1_ADDR_PORT, oldval1);
22077b57314SStefan Eßer 
22177b57314SStefan Eßer 		if (bootverbose)
222287911bdSStefan Eßer 		    printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n",
22377b57314SStefan Eßer 			    mode1res, CONF1_ENABLE_CHK1);
22477b57314SStefan Eßer 
225c7483249SStefan Eßer 		if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
22677b57314SStefan Eßer 			if (pcibus_check())
22777b57314SStefan Eßer 				return;
22877b57314SStefan Eßer 		};
229287911bdSStefan Eßer 	}
23077b57314SStefan Eßer 
23177b57314SStefan Eßer 	/*---------------------------------------
23277b57314SStefan Eßer 	**      Try configuration mechanism 2 ...
23377b57314SStefan Eßer 	**---------------------------------------
23477b57314SStefan Eßer 	*/
23577b57314SStefan Eßer 
236287911bdSStefan Eßer 	oldval2 = inb (CONF2_ENABLE_PORT);
237287911bdSStefan Eßer 
238287911bdSStefan Eßer 	if (bootverbose) {
239287911bdSStefan Eßer 		printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2);
240287911bdSStefan Eßer 	}
241287911bdSStefan Eßer 
242287911bdSStefan Eßer 	if ((oldval2 & 0xf0) == 0) {
243c7483249SStefan Eßer 
24477b57314SStefan Eßer 		pci_mechanism = 2;
24577b57314SStefan Eßer 		pci_maxdevice = 16;
24677b57314SStefan Eßer 
247287911bdSStefan Eßer 		outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
248287911bdSStefan Eßer 		mode2res = inb(CONF2_ENABLE_PORT);
249287911bdSStefan Eßer 		outb (CONF2_ENABLE_PORT, oldval2);
250287911bdSStefan Eßer 
251287911bdSStefan Eßer 		if (bootverbose)
252287911bdSStefan Eßer 		    printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n",
253287911bdSStefan Eßer 			    mode2res, CONF2_ENABLE_CHK);
254287911bdSStefan Eßer 
255287911bdSStefan Eßer 		if (mode2res == CONF2_ENABLE_RES) {
256287911bdSStefan Eßer 		    if (bootverbose)
257287911bdSStefan Eßer 			printf ("pcibus_setup(2a):\tnow trying mechanism 2\n");
258287911bdSStefan Eßer 
25977b57314SStefan Eßer 			if (pcibus_check())
26077b57314SStefan Eßer 				return;
261287911bdSStefan Eßer 		}
262287911bdSStefan Eßer 	}
26377b57314SStefan Eßer 
26477b57314SStefan Eßer 	/*---------------------------------------
265cda67911SStefan Eßer 	**      No PCI bus host bridge found
266ac19f918SStefan Eßer 	**---------------------------------------
267ac19f918SStefan Eßer 	*/
268cda67911SStefan Eßer 
269cda67911SStefan Eßer 	pci_mechanism = 0;
270cda67911SStefan Eßer 	pci_maxdevice = 0;
271ac19f918SStefan Eßer }
2725b3f532eSStefan Eßer 
273ac19f918SStefan Eßer /*--------------------------------------------------------------------
274ac19f918SStefan Eßer **
275ac19f918SStefan Eßer **      Build a pcitag from bus, device and function number
276ac19f918SStefan Eßer **
277ac19f918SStefan Eßer **--------------------------------------------------------------------
278ac19f918SStefan Eßer */
279ac19f918SStefan Eßer 
280ac19f918SStefan Eßer static pcici_t
281ac19f918SStefan Eßer pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
282ac19f918SStefan Eßer {
283ac19f918SStefan Eßer 	pcici_t tag;
284ac19f918SStefan Eßer 
285ac19f918SStefan Eßer 	tag.cfg1 = 0;
286ac19f918SStefan Eßer 	if (func   >=  8) return tag;
287ac19f918SStefan Eßer 
2885b3f532eSStefan Eßer 	switch (pci_mechanism) {
289ac19f918SStefan Eßer 
290ac19f918SStefan Eßer 	case 1:
2912d144186SStefan Eßer 		if (device < 32) {
292ac19f918SStefan Eßer 			tag.cfg1 = CONF1_ENABLE
293ac19f918SStefan Eßer 				| (((u_long) bus   ) << 16ul)
294ac19f918SStefan Eßer 				| (((u_long) device) << 11ul)
295ac19f918SStefan Eßer 				| (((u_long) func  ) <<  8ul);
2962d144186SStefan Eßer 		}
297ac19f918SStefan Eßer 		break;
298ac19f918SStefan Eßer 	case 2:
2992d144186SStefan Eßer 		if (device < 16) {
300ac19f918SStefan Eßer 			tag.cfg2.port    = 0xc000 | (device << 8ul);
3012d144186SStefan Eßer 			tag.cfg2.enable  = 0xf0 | (func << 1ul);
302ac19f918SStefan Eßer 			tag.cfg2.forward = bus;
3032d144186SStefan Eßer 		}
304ac19f918SStefan Eßer 		break;
305ac19f918SStefan Eßer 	};
306ac19f918SStefan Eßer 	return tag;
307ac19f918SStefan Eßer }
3085b3f532eSStefan Eßer 
3095b3f532eSStefan Eßer static pcici_t
3105b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func)
3115b3f532eSStefan Eßer {
3125b3f532eSStefan Eßer 	switch (pci_mechanism) {
3135b3f532eSStefan Eßer 
3145b3f532eSStefan Eßer 	case 1:
3155b3f532eSStefan Eßer 		tag.cfg1 &= ~0x700ul;
3165b3f532eSStefan Eßer 		tag.cfg1 |= (((u_long) func) << 8ul);
3175b3f532eSStefan Eßer 		break;
3185b3f532eSStefan Eßer 	case 2:
3192d144186SStefan Eßer 		tag.cfg2.enable  = 0xf0 | (func << 1ul);
3205b3f532eSStefan Eßer 		break;
3215b3f532eSStefan Eßer 	};
3225b3f532eSStefan Eßer 	return tag;
3235b3f532eSStefan Eßer }
3245b3f532eSStefan Eßer 
325ac19f918SStefan Eßer /*--------------------------------------------------------------------
326ac19f918SStefan Eßer **
327ac19f918SStefan Eßer **      Read register from configuration space.
328ac19f918SStefan Eßer **
329ac19f918SStefan Eßer **--------------------------------------------------------------------
330ac19f918SStefan Eßer */
331ac19f918SStefan Eßer 
332ac19f918SStefan Eßer static u_long
333ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg)
334ac19f918SStefan Eßer {
335ac19f918SStefan Eßer 	u_long addr, data = 0;
336ac19f918SStefan Eßer 
337ac19f918SStefan Eßer 	if (!tag.cfg1) return (0xfffffffful);
338ac19f918SStefan Eßer 
3395b3f532eSStefan Eßer 	switch (pci_mechanism) {
340ac19f918SStefan Eßer 
341ac19f918SStefan Eßer 	case 1:
342ac19f918SStefan Eßer 		addr = tag.cfg1 | (reg & 0xfc);
343ac19f918SStefan Eßer #ifdef PCI_DEBUG
344ac19f918SStefan Eßer 		printf ("pci_conf_read(1): addr=%x ", addr);
345ac19f918SStefan Eßer #endif
346ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, addr);
347ac19f918SStefan Eßer 		data = inl (CONF1_DATA_PORT);
348ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, 0   );
349ac19f918SStefan Eßer 		break;
350ac19f918SStefan Eßer 
351ac19f918SStefan Eßer 	case 2:
352ac19f918SStefan Eßer 		addr = tag.cfg2.port | (reg & 0xfc);
353ac19f918SStefan Eßer #ifdef PCI_DEBUG
354ac19f918SStefan Eßer 		printf ("pci_conf_read(2): addr=%x ", addr);
355ac19f918SStefan Eßer #endif
356ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
357ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
358ac19f918SStefan Eßer 
359ac19f918SStefan Eßer 		data = inl ((u_short) addr);
360ac19f918SStefan Eßer 
361ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  0);
362ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, 0);
363ac19f918SStefan Eßer 		break;
364ac19f918SStefan Eßer 	};
365ac19f918SStefan Eßer 
366ac19f918SStefan Eßer #ifdef PCI_DEBUG
367ac19f918SStefan Eßer 	printf ("data=%x\n", data);
368ac19f918SStefan Eßer #endif
369ac19f918SStefan Eßer 
370ac19f918SStefan Eßer 	return (data);
371ac19f918SStefan Eßer }
3725b3f532eSStefan Eßer 
373ac19f918SStefan Eßer /*--------------------------------------------------------------------
374ac19f918SStefan Eßer **
375ac19f918SStefan Eßer **      Write register into configuration space.
376ac19f918SStefan Eßer **
377ac19f918SStefan Eßer **--------------------------------------------------------------------
378ac19f918SStefan Eßer */
379ac19f918SStefan Eßer 
380ac19f918SStefan Eßer static void
381ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data)
382ac19f918SStefan Eßer {
383ac19f918SStefan Eßer 	u_long addr;
384ac19f918SStefan Eßer 
385ac19f918SStefan Eßer 	if (!tag.cfg1) return;
386ac19f918SStefan Eßer 
3875b3f532eSStefan Eßer 	switch (pci_mechanism) {
388ac19f918SStefan Eßer 
389ac19f918SStefan Eßer 	case 1:
390ac19f918SStefan Eßer 		addr = tag.cfg1 | (reg & 0xfc);
391ac19f918SStefan Eßer #ifdef PCI_DEBUG
392ac19f918SStefan Eßer 		printf ("pci_conf_write(1): addr=%x data=%x\n",
393ac19f918SStefan Eßer 			addr, data);
394ac19f918SStefan Eßer #endif
395ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, addr);
396ac19f918SStefan Eßer 		outl (CONF1_DATA_PORT, data);
397ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT,   0 );
398ac19f918SStefan Eßer 		break;
399ac19f918SStefan Eßer 
400ac19f918SStefan Eßer 	case 2:
401ac19f918SStefan Eßer 		addr = tag.cfg2.port | (reg & 0xfc);
402ac19f918SStefan Eßer #ifdef PCI_DEBUG
403ac19f918SStefan Eßer 		printf ("pci_conf_write(2): addr=%x data=%x\n",
404ac19f918SStefan Eßer 			addr, data);
405ac19f918SStefan Eßer #endif
406ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  tag.cfg2.enable);
407ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
408ac19f918SStefan Eßer 
409ac19f918SStefan Eßer 		outl ((u_short) addr, data);
410ac19f918SStefan Eßer 
411ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  0);
412ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, 0);
413ac19f918SStefan Eßer 		break;
414ac19f918SStefan Eßer 	};
415ac19f918SStefan Eßer }
4165b3f532eSStefan Eßer 
417ac19f918SStefan Eßer /*-----------------------------------------------------------------------
418ac19f918SStefan Eßer **
419ac19f918SStefan Eßer **	Register an interupt handler for a pci device.
420ac19f918SStefan Eßer **
421ac19f918SStefan Eßer **-----------------------------------------------------------------------
422ac19f918SStefan Eßer */
423ac19f918SStefan Eßer 
424ac19f918SStefan Eßer static int
4255b3f532eSStefan Eßer pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr)
426ac19f918SStefan Eßer {
4275b3f532eSStefan Eßer 	int result;
4285b3f532eSStefan Eßer 	result = register_intr(
429ac19f918SStefan Eßer 		irq,		    /* isa irq	    */
430ac19f918SStefan Eßer 		0,		    /* deviced??    */
431ac19f918SStefan Eßer 		0,		    /* flags?	    */
432ac19f918SStefan Eßer 		(inthand2_t*) func, /* handler	    */
433ac19f918SStefan Eßer 		maskptr,	    /* mask pointer */
4345b3f532eSStefan Eßer 		arg);		    /* handler arg  */
435ac19f918SStefan Eßer 
4365b3f532eSStefan Eßer 	if (result) {
4375b3f532eSStefan Eßer 		printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
4385b3f532eSStefan Eßer 		return (result);
439ac19f918SStefan Eßer 	};
4405b3f532eSStefan Eßer 	update_intr_masks();
441ac19f918SStefan Eßer 
4425b3f532eSStefan Eßer 	INTREN ((1ul<<irq));
4435b3f532eSStefan Eßer 	return (0);
4445b3f532eSStefan Eßer }
445ac19f918SStefan Eßer 
4465b3f532eSStefan Eßer static int
4475b3f532eSStefan Eßer pcibus_ihandler_detach (int irq, void(*func)())
4485b3f532eSStefan Eßer {
4495b3f532eSStefan Eßer 	int result;
4505b3f532eSStefan Eßer 
4515b3f532eSStefan Eßer 	INTRDIS ((1ul<<irq));
4525b3f532eSStefan Eßer 
4535b3f532eSStefan Eßer 	result = unregister_intr (irq, (inthand2_t*) func);
4545b3f532eSStefan Eßer 
4555b3f532eSStefan Eßer 	if (result)
4565b3f532eSStefan Eßer 		printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
4575b3f532eSStefan Eßer 
4585b3f532eSStefan Eßer 	update_intr_masks();
4595b3f532eSStefan Eßer 
4605b3f532eSStefan Eßer 	return (result);
4615b3f532eSStefan Eßer }
4625b3f532eSStefan Eßer 
4635b3f532eSStefan Eßer static int
4645b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr)
4655b3f532eSStefan Eßer {
4665b3f532eSStefan Eßer 	unsigned mask;
4675b3f532eSStefan Eßer 
4685b3f532eSStefan Eßer 	if (!maskptr) return (0);
4695b3f532eSStefan Eßer 
4705b3f532eSStefan Eßer 	mask = 1ul << irq;
4715b3f532eSStefan Eßer 
4725b3f532eSStefan Eßer 	if (*maskptr & mask)
4735b3f532eSStefan Eßer 		return (-1);
4745b3f532eSStefan Eßer 
4755b3f532eSStefan Eßer 	INTRMASK (*maskptr, mask);
4765b3f532eSStefan Eßer 	update_intr_masks();
4775b3f532eSStefan Eßer 
4785b3f532eSStefan Eßer 	return (0);
4795b3f532eSStefan Eßer }
4805b3f532eSStefan Eßer 
4815b3f532eSStefan Eßer static int
4825b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr)
4835b3f532eSStefan Eßer {
4845b3f532eSStefan Eßer 	unsigned mask;
4855b3f532eSStefan Eßer 
4865b3f532eSStefan Eßer 	if (!maskptr) return (0);
4875b3f532eSStefan Eßer 
4885b3f532eSStefan Eßer 	mask = 1ul << irq;
4895b3f532eSStefan Eßer 
4905b3f532eSStefan Eßer 	if (! (*maskptr & mask))
4915b3f532eSStefan Eßer 		return (-1);
4925b3f532eSStefan Eßer 
4935b3f532eSStefan Eßer 	*maskptr &= ~mask;
4945b3f532eSStefan Eßer 	update_intr_masks();
4955b3f532eSStefan Eßer 
4965b3f532eSStefan Eßer 	return (0);
497ac19f918SStefan Eßer }
498