xref: /freebsd/sys/i386/pci/pci_cfgreg.c (revision d7ea35fc88131dcebc4006de25e92424cbf6bc63)
1ac19f918SStefan Eßer /**************************************************************************
2ac19f918SStefan Eßer **
3d7ea35fcSStefan Eßer **  $Id: pcibus.c,v 1.11 1995/09/13 17:03:47 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 
385b3f532eSStefan Eßer #define	__PCIBUS_C___	"pl4 95/03/21"
39ac19f918SStefan Eßer 
40550f8550SBruce Evans #include <sys/param.h>
41550f8550SBruce Evans #include <sys/systm.h>
42550f8550SBruce Evans #include <sys/kernel.h>
43550f8550SBruce Evans 
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 
86d7ea35fcSStefan Eßer static int
87d7ea35fcSStefan Eßer pcibus_check (void);
88d7ea35fcSStefan 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_ENABLE       0x80000000ul
145cda67911SStefan Eßer #define CONF1_ENABLE_CHK1  0xF0000000ul
146cda67911SStefan Eßer #define CONF1_ENABLE_CHK2  0xfffffffful
147cda67911SStefan Eßer #define CONF1_ENABLE_RES2  0x80fffffcul
148ac19f918SStefan Eßer #define CONF1_ADDR_PORT    0x0cf8
149ac19f918SStefan Eßer #define CONF1_DATA_PORT    0x0cfc
150ac19f918SStefan Eßer 
151ac19f918SStefan Eßer 
152ac19f918SStefan Eßer #define CONF2_ENABLE_PORT  0x0cf8
153ac19f918SStefan Eßer #define CONF2_FORWARD_PORT 0x0cfa
154ac19f918SStefan Eßer 
155ac19f918SStefan Eßer 
156d7ea35fcSStefan Eßer static int
157d7ea35fcSStefan Eßer pcibus_check (void)
158d7ea35fcSStefan Eßer {
159d7ea35fcSStefan Eßer 	u_char device;
160d7ea35fcSStefan Eßer 
161d7ea35fcSStefan Eßer 	for (device = 0; device < pci_maxdevice; device++) {
162d7ea35fcSStefan Eßer 		if (pcibus_read (pcibus_tag (0,device,0), 0) != 0xfffffffful)
163d7ea35fcSStefan Eßer 			return 1;
164d7ea35fcSStefan Eßer 	}
165d7ea35fcSStefan Eßer 	return 0;
166d7ea35fcSStefan Eßer }
167d7ea35fcSStefan Eßer 
1685b3f532eSStefan Eßer static void
1695b3f532eSStefan Eßer pcibus_setup (void)
170ac19f918SStefan Eßer {
171ac19f918SStefan Eßer 	u_long result, oldval;
172ac19f918SStefan Eßer 
173ac19f918SStefan Eßer 	/*---------------------------------------
1740847c06dSStefan Eßer 	**      Configuration mode 1 ?
1750847c06dSStefan Eßer 	**---------------------------------------
1760847c06dSStefan Eßer 	*/
1770847c06dSStefan Eßer 
1780847c06dSStefan Eßer 	oldval = inl (CONF1_ADDR_PORT);
179cda67911SStefan Eßer 	outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
1800847c06dSStefan Eßer 	outb (CONF1_ADDR_PORT +3, 0);
1810847c06dSStefan Eßer 	result = inl (CONF1_ADDR_PORT);
1820847c06dSStefan Eßer 	outl (CONF1_ADDR_PORT, oldval);
1830847c06dSStefan Eßer 
184d2a2d5ecSStefan Eßer 	if (result & CONF1_ENABLE) {
1850847c06dSStefan Eßer 		pci_mechanism = 1;
1860847c06dSStefan Eßer 		pci_maxdevice = 32;
187d7ea35fcSStefan Eßer 		if (pcibus_check())
1880847c06dSStefan Eßer 			return;
1890847c06dSStefan Eßer 	};
1900847c06dSStefan Eßer 
1910847c06dSStefan Eßer 	/*---------------------------------------
192ac19f918SStefan Eßer 	**      Configuration mode 2 ?
193ac19f918SStefan Eßer 	**---------------------------------------
194ac19f918SStefan Eßer 	*/
195ac19f918SStefan Eßer 
196ac19f918SStefan Eßer 	outb (CONF2_ENABLE_PORT,  0);
197ac19f918SStefan Eßer 	outb (CONF2_FORWARD_PORT, 0);
198ac19f918SStefan Eßer 	if (!inb (CONF2_ENABLE_PORT) && !inb (CONF2_FORWARD_PORT)) {
1995b3f532eSStefan Eßer 		pci_mechanism = 2;
2005b3f532eSStefan Eßer 		pci_maxdevice = 16;
201d7ea35fcSStefan Eßer 		if (pcibus_check())
2020f29bf01SStefan Eßer 			return;
203ac19f918SStefan Eßer 	};
204ac19f918SStefan Eßer 
205cda67911SStefan Eßer 
206cda67911SStefan Eßer 	/*-----------------------------------------------------
207cda67911SStefan Eßer 	**      Well, is it Configuration mode 1, after all ?
208cda67911SStefan Eßer 	**-----------------------------------------------------
209cda67911SStefan Eßer 	*/
210cda67911SStefan Eßer 
211cda67911SStefan Eßer 	oldval = inl (CONF1_ADDR_PORT);
212cda67911SStefan Eßer 	outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK2);
213cda67911SStefan Eßer 	result = inl (CONF1_ADDR_PORT);
214cda67911SStefan Eßer 	outl (CONF1_ADDR_PORT, oldval);
215cda67911SStefan Eßer 
216cda67911SStefan Eßer 	if (result == CONF1_ENABLE_RES2) {
217cda67911SStefan Eßer 		pci_mechanism = 1;
218cda67911SStefan Eßer 		pci_maxdevice = 32;
219d7ea35fcSStefan Eßer 		if (pcibus_check())
220cda67911SStefan Eßer 			return;
221cda67911SStefan Eßer 	}
222cda67911SStefan Eßer 	if (result != 0xfffffffful)
223cda67911SStefan Eßer 		printf ("pcibus_setup: "
224cda67911SStefan Eßer 			"wrote 0x%08x, read back 0x%08x, expected 0x%08x\n",
225cda67911SStefan Eßer 			CONF1_ENABLE_CHK2, result, CONF1_ENABLE_RES2);
226cda67911SStefan Eßer 
227ac19f918SStefan Eßer 	/*---------------------------------------
228cda67911SStefan Eßer 	**      No PCI bus host bridge found
229ac19f918SStefan Eßer 	**---------------------------------------
230ac19f918SStefan Eßer 	*/
231cda67911SStefan Eßer 
232cda67911SStefan Eßer 	pci_mechanism = 0;
233cda67911SStefan Eßer 	pci_maxdevice = 0;
234ac19f918SStefan Eßer }
2355b3f532eSStefan Eßer 
236ac19f918SStefan Eßer /*--------------------------------------------------------------------
237ac19f918SStefan Eßer **
238ac19f918SStefan Eßer **      Build a pcitag from bus, device and function number
239ac19f918SStefan Eßer **
240ac19f918SStefan Eßer **--------------------------------------------------------------------
241ac19f918SStefan Eßer */
242ac19f918SStefan Eßer 
243ac19f918SStefan Eßer static pcici_t
244ac19f918SStefan Eßer pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
245ac19f918SStefan Eßer {
246ac19f918SStefan Eßer 	pcici_t tag;
247ac19f918SStefan Eßer 
248ac19f918SStefan Eßer 	tag.cfg1 = 0;
249ac19f918SStefan Eßer 	if (device >= 32) return tag;
250ac19f918SStefan Eßer 	if (func   >=  8) return tag;
251ac19f918SStefan Eßer 
2525b3f532eSStefan Eßer 	switch (pci_mechanism) {
253ac19f918SStefan Eßer 
254ac19f918SStefan Eßer 	case 1:
255ac19f918SStefan Eßer 		tag.cfg1 = CONF1_ENABLE
256ac19f918SStefan Eßer 			| (((u_long) bus   ) << 16ul)
257ac19f918SStefan Eßer 			| (((u_long) device) << 11ul)
258ac19f918SStefan Eßer 			| (((u_long) func  ) <<  8ul);
259ac19f918SStefan Eßer 		break;
260ac19f918SStefan Eßer 	case 2:
261ac19f918SStefan Eßer 		if (device >= 16) break;
262ac19f918SStefan Eßer 		tag.cfg2.port    = 0xc000 | (device << 8ul);
263ac19f918SStefan Eßer 		tag.cfg2.enable  = 0xf1 | (func << 1ul);
264ac19f918SStefan Eßer 		tag.cfg2.forward = bus;
265ac19f918SStefan Eßer 		break;
266ac19f918SStefan Eßer 	};
267ac19f918SStefan Eßer 	return tag;
268ac19f918SStefan Eßer }
2695b3f532eSStefan Eßer 
2705b3f532eSStefan Eßer static pcici_t
2715b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func)
2725b3f532eSStefan Eßer {
2735b3f532eSStefan Eßer 	switch (pci_mechanism) {
2745b3f532eSStefan Eßer 
2755b3f532eSStefan Eßer 	case 1:
2765b3f532eSStefan Eßer 		tag.cfg1 &= ~0x700ul;
2775b3f532eSStefan Eßer 		tag.cfg1 |= (((u_long) func) << 8ul);
2785b3f532eSStefan Eßer 		break;
2795b3f532eSStefan Eßer 	case 2:
2805b3f532eSStefan Eßer 		tag.cfg2.enable  = 0xf1 | (func << 1ul);
2815b3f532eSStefan Eßer 		break;
2825b3f532eSStefan Eßer 	};
2835b3f532eSStefan Eßer 	return tag;
2845b3f532eSStefan Eßer }
2855b3f532eSStefan Eßer 
286ac19f918SStefan Eßer /*--------------------------------------------------------------------
287ac19f918SStefan Eßer **
288ac19f918SStefan Eßer **      Read register from configuration space.
289ac19f918SStefan Eßer **
290ac19f918SStefan Eßer **--------------------------------------------------------------------
291ac19f918SStefan Eßer */
292ac19f918SStefan Eßer 
293ac19f918SStefan Eßer static u_long
294ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg)
295ac19f918SStefan Eßer {
296ac19f918SStefan Eßer 	u_long addr, data = 0;
297ac19f918SStefan Eßer 
298ac19f918SStefan Eßer 	if (!tag.cfg1) return (0xfffffffful);
299ac19f918SStefan Eßer 
3005b3f532eSStefan Eßer 	switch (pci_mechanism) {
301ac19f918SStefan Eßer 
302ac19f918SStefan Eßer 	case 1:
303ac19f918SStefan Eßer 		addr = tag.cfg1 | (reg & 0xfc);
304ac19f918SStefan Eßer #ifdef PCI_DEBUG
305ac19f918SStefan Eßer 		printf ("pci_conf_read(1): addr=%x ", addr);
306ac19f918SStefan Eßer #endif
307ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, addr);
308ac19f918SStefan Eßer 		data = inl (CONF1_DATA_PORT);
309ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, 0   );
310ac19f918SStefan Eßer 		break;
311ac19f918SStefan Eßer 
312ac19f918SStefan Eßer 	case 2:
313ac19f918SStefan Eßer 		addr = tag.cfg2.port | (reg & 0xfc);
314ac19f918SStefan Eßer #ifdef PCI_DEBUG
315ac19f918SStefan Eßer 		printf ("pci_conf_read(2): addr=%x ", addr);
316ac19f918SStefan Eßer #endif
317ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
318ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
319ac19f918SStefan Eßer 
320ac19f918SStefan Eßer 		data = inl ((u_short) addr);
321ac19f918SStefan Eßer 
322ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  0);
323ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, 0);
324ac19f918SStefan Eßer 		break;
325ac19f918SStefan Eßer 	};
326ac19f918SStefan Eßer 
327ac19f918SStefan Eßer #ifdef PCI_DEBUG
328ac19f918SStefan Eßer 	printf ("data=%x\n", data);
329ac19f918SStefan Eßer #endif
330ac19f918SStefan Eßer 
331ac19f918SStefan Eßer 	return (data);
332ac19f918SStefan Eßer }
3335b3f532eSStefan Eßer 
334ac19f918SStefan Eßer /*--------------------------------------------------------------------
335ac19f918SStefan Eßer **
336ac19f918SStefan Eßer **      Write register into configuration space.
337ac19f918SStefan Eßer **
338ac19f918SStefan Eßer **--------------------------------------------------------------------
339ac19f918SStefan Eßer */
340ac19f918SStefan Eßer 
341ac19f918SStefan Eßer static void
342ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data)
343ac19f918SStefan Eßer {
344ac19f918SStefan Eßer 	u_long addr;
345ac19f918SStefan Eßer 
346ac19f918SStefan Eßer 	if (!tag.cfg1) return;
347ac19f918SStefan Eßer 
3485b3f532eSStefan Eßer 	switch (pci_mechanism) {
349ac19f918SStefan Eßer 
350ac19f918SStefan Eßer 	case 1:
351ac19f918SStefan Eßer 		addr = tag.cfg1 | (reg & 0xfc);
352ac19f918SStefan Eßer #ifdef PCI_DEBUG
353ac19f918SStefan Eßer 		printf ("pci_conf_write(1): addr=%x data=%x\n",
354ac19f918SStefan Eßer 			addr, data);
355ac19f918SStefan Eßer #endif
356ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT, addr);
357ac19f918SStefan Eßer 		outl (CONF1_DATA_PORT, data);
358ac19f918SStefan Eßer 		outl (CONF1_ADDR_PORT,   0 );
359ac19f918SStefan Eßer 		break;
360ac19f918SStefan Eßer 
361ac19f918SStefan Eßer 	case 2:
362ac19f918SStefan Eßer 		addr = tag.cfg2.port | (reg & 0xfc);
363ac19f918SStefan Eßer #ifdef PCI_DEBUG
364ac19f918SStefan Eßer 		printf ("pci_conf_write(2): addr=%x data=%x\n",
365ac19f918SStefan Eßer 			addr, data);
366ac19f918SStefan Eßer #endif
367ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  tag.cfg2.enable);
368ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
369ac19f918SStefan Eßer 
370ac19f918SStefan Eßer 		outl ((u_short) addr, data);
371ac19f918SStefan Eßer 
372ac19f918SStefan Eßer 		outb (CONF2_ENABLE_PORT,  0);
373ac19f918SStefan Eßer 		outb (CONF2_FORWARD_PORT, 0);
374ac19f918SStefan Eßer 		break;
375ac19f918SStefan Eßer 	};
376ac19f918SStefan Eßer }
3775b3f532eSStefan Eßer 
378ac19f918SStefan Eßer /*-----------------------------------------------------------------------
379ac19f918SStefan Eßer **
380ac19f918SStefan Eßer **	Register an interupt handler for a pci device.
381ac19f918SStefan Eßer **
382ac19f918SStefan Eßer **-----------------------------------------------------------------------
383ac19f918SStefan Eßer */
384ac19f918SStefan Eßer 
385ac19f918SStefan Eßer static int
3865b3f532eSStefan Eßer pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr)
387ac19f918SStefan Eßer {
3885b3f532eSStefan Eßer 	int result;
3895b3f532eSStefan Eßer 	result = register_intr(
390ac19f918SStefan Eßer 		irq,		    /* isa irq	    */
391ac19f918SStefan Eßer 		0,		    /* deviced??    */
392ac19f918SStefan Eßer 		0,		    /* flags?	    */
393ac19f918SStefan Eßer 		(inthand2_t*) func, /* handler	    */
394ac19f918SStefan Eßer 		maskptr,	    /* mask pointer */
3955b3f532eSStefan Eßer 		arg);		    /* handler arg  */
396ac19f918SStefan Eßer 
3975b3f532eSStefan Eßer 	if (result) {
3985b3f532eSStefan Eßer 		printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
3995b3f532eSStefan Eßer 		return (result);
400ac19f918SStefan Eßer 	};
4015b3f532eSStefan Eßer 	update_intr_masks();
402ac19f918SStefan Eßer 
4035b3f532eSStefan Eßer 	INTREN ((1ul<<irq));
4045b3f532eSStefan Eßer 	return (0);
4055b3f532eSStefan Eßer }
406ac19f918SStefan Eßer 
4075b3f532eSStefan Eßer static int
4085b3f532eSStefan Eßer pcibus_ihandler_detach (int irq, void(*func)())
4095b3f532eSStefan Eßer {
4105b3f532eSStefan Eßer 	int result;
4115b3f532eSStefan Eßer 
4125b3f532eSStefan Eßer 	INTRDIS ((1ul<<irq));
4135b3f532eSStefan Eßer 
4145b3f532eSStefan Eßer 	result = unregister_intr (irq, (inthand2_t*) func);
4155b3f532eSStefan Eßer 
4165b3f532eSStefan Eßer 	if (result)
4175b3f532eSStefan Eßer 		printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
4185b3f532eSStefan Eßer 
4195b3f532eSStefan Eßer 	update_intr_masks();
4205b3f532eSStefan Eßer 
4215b3f532eSStefan Eßer 	return (result);
4225b3f532eSStefan Eßer }
4235b3f532eSStefan Eßer 
4245b3f532eSStefan Eßer static int
4255b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr)
4265b3f532eSStefan Eßer {
4275b3f532eSStefan Eßer 	unsigned mask;
4285b3f532eSStefan Eßer 
4295b3f532eSStefan Eßer 	if (!maskptr) return (0);
4305b3f532eSStefan Eßer 
4315b3f532eSStefan Eßer 	mask = 1ul << irq;
4325b3f532eSStefan Eßer 
4335b3f532eSStefan Eßer 	if (*maskptr & mask)
4345b3f532eSStefan Eßer 		return (-1);
4355b3f532eSStefan Eßer 
4365b3f532eSStefan Eßer 	INTRMASK (*maskptr, mask);
4375b3f532eSStefan Eßer 	update_intr_masks();
4385b3f532eSStefan Eßer 
4395b3f532eSStefan Eßer 	return (0);
4405b3f532eSStefan Eßer }
4415b3f532eSStefan Eßer 
4425b3f532eSStefan Eßer static int
4435b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr)
4445b3f532eSStefan Eßer {
4455b3f532eSStefan Eßer 	unsigned mask;
4465b3f532eSStefan Eßer 
4475b3f532eSStefan Eßer 	if (!maskptr) return (0);
4485b3f532eSStefan Eßer 
4495b3f532eSStefan Eßer 	mask = 1ul << irq;
4505b3f532eSStefan Eßer 
4515b3f532eSStefan Eßer 	if (! (*maskptr & mask))
4525b3f532eSStefan Eßer 		return (-1);
4535b3f532eSStefan Eßer 
4545b3f532eSStefan Eßer 	*maskptr &= ~mask;
4555b3f532eSStefan Eßer 	update_intr_masks();
4565b3f532eSStefan Eßer 
4575b3f532eSStefan Eßer 	return (0);
458ac19f918SStefan Eßer }
459