Deleted Added
full compact
pci_bus.c (24743) pci_bus.c (26159)
1/**************************************************************************
2**
3** $Id: pcibus.c,v 1.34 1997/04/09 09:16:27 se Exp $
4**
5** pci bus subroutines for i386 architecture.
6**
7** FreeBSD
8**
9**-------------------------------------------------------------------------
10**
11** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved.
12**
13** Redistribution and use in source and binary forms, with or without
14** modification, are permitted provided that the following conditions
15** are met:
16** 1. Redistributions of source code must retain the above copyright
17** notice, this list of conditions and the following disclaimer.
18** 2. Redistributions in binary form must reproduce the above copyright
19** notice, this list of conditions and the following disclaimer in the
20** documentation and/or other materials provided with the distribution.
21** 3. The name of the author may not be used to endorse or promote products
22** derived from this software without specific prior written permission.
23**
24** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34**
35***************************************************************************
36*/
1/*
2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $Id$
27 *
28 */
37
29
38#include "vector.h"
39
40#include <sys/param.h>
30#include <sys/types.h>
41#include <sys/systm.h>
31#include <sys/systm.h>
42#include <sys/kernel.h>
43
32
44#include <i386/isa/icu.h>
45#include <i386/isa/isa_device.h>
46
47#include <pci/pcivar.h>
48#include <pci/pcireg.h>
33#include <pci/pcireg.h>
49#include <pci/pcibus.h>
34#include <pci/pcivar.h>
35#include <i386/isa/pcibus.h>
50
36
51/*-----------------------------------------------------------------
52**
53** The following functions are provided by the pci bios.
54** They are used only by the pci configuration.
55**
56** pcibus_setup():
57** Probes for a pci system.
58** Sets pci_maxdevice and pci_mechanism.
59**
60** pcibus_tag():
61** Creates a handle for pci configuration space access.
62** This handle is given to the read/write functions.
63**
64** pcibus_ftag():
65** Creates a modified handle.
66**
67** pcibus_read():
68** Read a long word from the pci configuration space.
69** Requires a tag (from pcitag) and the register
70** number (should be a long word aligned one).
71**
72** pcibus_write():
73** Writes a long word to the pci configuration space.
74** Requires a tag (from pcitag), the register number
75** (should be a long word aligned one), and a value.
76**
77** pcibus_regirq():
78** Register an interrupt handler for a pci device.
79** Requires a tag (from pcitag), the register number
80** (should be a long word aligned one), and a value.
81**
82**-----------------------------------------------------------------
83*/
37#ifdef PCI_COMPAT
38/* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */
39#define cfgmech pci_mechanism
40int cfgmech;
41#else
42static int cfgmech;
43#endif /* PCI_COMPAT */
44static int devmax;
84
45
46/* enable configuration space accesses and return data port address */
47
85static int
48static int
86pcibus_check (void);
49pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
50{
51 int dataport = 0;
87
52
88static void
89pcibus_setup (void);
53 if (bus <= PCI_BUSMAX
54 && slot < devmax
55 && func <= PCI_FUNCMAX
56 && reg <= PCI_REGMAX
57 && bytes != 3
58 && (unsigned) bytes <= 4
59 && (reg & (bytes -1)) == 0) {
60 switch (cfgmech) {
61 case 1:
62 outl(CONF1_ADDR_PORT,
63 (bus << 16) | (slot << 11) | (func << 8) | reg);
64 dataport = CONF1_DATA_PORT;
65 break;
66 case 2:
67 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
68 outb(CONF2_FORWARD_PORT, bus);
69 dataport = 0xc000 | (slot << 8) | reg;
70 break;
71 }
72 }
73 return (dataport);
74}
90
75
91static pcici_t
92pcibus_tag (u_char bus, u_char device, u_char func);
76/* disable configuration space accesses */
93
77
94static pcici_t
95pcibus_ftag (pcici_t tag, u_char func);
96
97static u_long
98pcibus_read (pcici_t tag, u_long reg);
99
100static void
78static void
101pcibus_write (pcici_t tag, u_long reg, u_long data);
79pci_cfgdisable(void)
80{
81 switch (cfgmech) {
82 case 1:
83 outl(CONF1_ADDR_PORT, 0);
84 break;
85 case 2:
86 outb(CONF2_ENABLE_PORT, 0);
87 outb(CONF2_FORWARD_PORT, 0);
88 break;
89 }
90}
102
91
103static int
104pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned* maskptr);
92/* read configuration space register */
105
93
106static int
107pcibus_ihandler_detach (int irq, inthand2_t *func);
94int
95pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
96{
97 int data = -1;
98 int port;
108
99
109static int
110pcibus_imask_include (int irq, unsigned* maskptr);
100 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
111
101
112static int
113pcibus_imask_exclude (int irq, unsigned* maskptr);
102 if (port != 0) {
103 switch (bytes) {
104 case 1:
105 data = inb(port);
106 break;
107 case 2:
108 data = inw(port);
109 break;
110 case 4:
111 data = inl(port);
112 break;
113 }
114 pci_cfgdisable();
115 }
116 return (data);
117}
114
118
115static struct pcibus i386pci = {
116 "pci",
117 pcibus_setup,
118 pcibus_tag,
119 pcibus_ftag,
120 pcibus_read,
121 pcibus_write,
122 pcibus_ihandler_attach,
123 pcibus_ihandler_detach,
124 pcibus_imask_include,
125 pcibus_imask_exclude,
126};
119/* write configuration space register */
127
120
128/*
129** Announce structure to generic driver
130*/
121void
122pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
123{
124 int port;
131
125
132DATA_SET (pcibus_set, i386pci);
126 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
127 if (port != 0) {
128 switch (bytes) {
129 case 1:
130 outb(port, data);
131 break;
132 case 2:
133 outw(port, data);
134 break;
135 case 4:
136 outl(port, data);
137 break;
138 }
139 pci_cfgdisable();
140 }
141}
133
142
134/*--------------------------------------------------------------------
135**
136** Determine configuration mode
137**
138**--------------------------------------------------------------------
139*/
143/* check whether the configuration mechanism has been correct identified */
140
144
141
142#define CONF1_ADDR_PORT 0x0cf8
143#define CONF1_DATA_PORT 0x0cfc
144
145#define CONF1_ENABLE 0x80000000ul
146#define CONF1_ENABLE_CHK 0x80000000ul
147#define CONF1_ENABLE_MSK 0x7ff00000ul
148#define CONF1_ENABLE_CHK1 0xff000001ul
149#define CONF1_ENABLE_MSK1 0x80000001ul
150#define CONF1_ENABLE_RES1 0x80000000ul
151
152#define CONF2_ENABLE_PORT 0x0cf8
153#ifdef PC98
154#define CONF2_FORWARD_PORT 0x0cf9
155#else
156#define CONF2_FORWARD_PORT 0x0cfa
157#endif
158
159#define CONF2_ENABLE_CHK 0x0e
160#define CONF2_ENABLE_RES 0x0e
161
162static int
145static int
163pcibus_check (void)
146pci_cfgcheck(int maxdev)
164{
165 u_char device;
166
147{
148 u_char device;
149
167 if (bootverbose) printf ("pcibus_check:\tdevice ");
150 if (bootverbose)
151 printf("pci_cfgcheck:\tdevice ");
168
152
169 for (device = 0; device < pci_maxdevice; device++) {
170 unsigned long id, class, header;
153 for (device = 0; device < maxdev; device++) {
154 unsigned id, class, header;
171 if (bootverbose)
155 if (bootverbose)
172 printf ("%d ", device);
173 id = pcibus_read (pcibus_tag (0,device,0), 0);
174 if ((id == 0) || (id == 0xfffffffful))
156 printf("%d ", device);
157
158 id = inl(pci_cfgenable(0, device, 0, 0, 4));
159 if (id == 0 || id == -1)
175 continue;
176
160 continue;
161
177 class = pcibus_read (pcibus_tag (0,device,0), 8);
162 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
178 if (bootverbose)
163 if (bootverbose)
179 printf ("[class=%x] ", class >> 8);
180 if ((class & 0xffffff00) == 0 || (class & 0xf8f0ff00) != 0)
164 printf("[class=%06x] ", class);
165 if (class == 0 || (class & 0xf8f0ff) != 0)
181 continue;
182
166 continue;
167
183 header = pcibus_read (pcibus_tag (0,device,0), 12);
168 header = inb(pci_cfgenable(0, device, 0, 14, 1));
184 if (bootverbose)
169 if (bootverbose)
185 printf ("[hdr=%x] ", (header >> 16) & 0xff);
186 if ((header & 0x007e0000) != 0)
170 printf("[hdr=%02x] ", header);
171 if ((header & 0x7e) != 0)
187 continue;
188
172 continue;
173
189 if (bootverbose) printf ("is there (id=%08lx)\n", id);
190 return 1;
174 if (bootverbose)
175 printf("is there (id=%08x)\n", id);
176
177 pci_cfgdisable();
178 return (1);
191 }
192 if (bootverbose)
179 }
180 if (bootverbose)
193 printf ("-- nothing found\n");
194 return 0;
181 printf("-- nothing found\n");
182
183 pci_cfgdisable();
184 return (0);
195}
196
185}
186
197static void
198pcibus_setup (void)
187int
188pci_cfgopen(void)
199{
200 unsigned long mode1res,oldval1;
201 unsigned char mode2res,oldval2;
202
189{
190 unsigned long mode1res,oldval1;
191 unsigned char mode2res,oldval2;
192
203 oldval1 = inl (CONF1_ADDR_PORT);
193 oldval1 = inl(CONF1_ADDR_PORT);
204
205 if (bootverbose) {
194
195 if (bootverbose) {
206 printf ("pcibus_setup(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", oldval1);
196 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
197 oldval1);
207 }
208
198 }
199
209 /*---------------------------------------
210 ** Assume configuration mechanism 1 for now ...
211 **---------------------------------------
212 */
213
214 if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
215
200 if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
201
216 pci_mechanism = 1;
217 pci_maxdevice = 32;
202 cfgmech = 1;
203 devmax = 32;
218
204
219 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
220 outb (CONF1_ADDR_PORT +3, 0);
221 mode1res = inl (CONF1_ADDR_PORT);
222 outl (CONF1_ADDR_PORT, oldval1);
205 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
206 outb(CONF1_ADDR_PORT +3, 0);
207 mode1res = inl(CONF1_ADDR_PORT);
208 outl(CONF1_ADDR_PORT, oldval1);
223
224 if (bootverbose)
209
210 if (bootverbose)
225 printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n",
226 mode1res, CONF1_ENABLE_CHK);
211 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n",
212 mode1res, CONF1_ENABLE_CHK);
227
228 if (mode1res) {
213
214 if (mode1res) {
229 if (pcibus_check())
230 return;
231 };
215 if (pci_cfgcheck(32))
216 return (cfgmech);
217 }
232
218
233 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
219 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
234 mode1res = inl(CONF1_ADDR_PORT);
220 mode1res = inl(CONF1_ADDR_PORT);
235 outl (CONF1_ADDR_PORT, oldval1);
221 outl(CONF1_ADDR_PORT, oldval1);
236
237 if (bootverbose)
222
223 if (bootverbose)
238 printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n",
239 mode1res, CONF1_ENABLE_CHK1);
224 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n",
225 mode1res, CONF1_ENABLE_CHK1);
240
241 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
226
227 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
242 if (pcibus_check())
243 return;
244 };
228 if (pci_cfgcheck(32))
229 return (cfgmech);
230 }
245 }
246
231 }
232
247 /*---------------------------------------
248 ** Try configuration mechanism 2 ...
249 **---------------------------------------
250 */
233 oldval2 = inb(CONF2_ENABLE_PORT);
251
234
252 oldval2 = inb (CONF2_ENABLE_PORT);
253
254 if (bootverbose) {
235 if (bootverbose) {
255 printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2);
236 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
237 oldval2);
256 }
257
258 if ((oldval2 & 0xf0) == 0) {
259
238 }
239
240 if ((oldval2 & 0xf0) == 0) {
241
260 pci_mechanism = 2;
261 pci_maxdevice = 16;
262
263 outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
242 cfgmech = 2;
243 devmax = 16;
244
245 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
264 mode2res = inb(CONF2_ENABLE_PORT);
246 mode2res = inb(CONF2_ENABLE_PORT);
265 outb (CONF2_ENABLE_PORT, oldval2);
247 outb(CONF2_ENABLE_PORT, oldval2);
266
267 if (bootverbose)
248
249 if (bootverbose)
268 printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n",
269 mode2res, CONF2_ENABLE_CHK);
250 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
251 mode2res, CONF2_ENABLE_CHK);
270
271 if (mode2res == CONF2_ENABLE_RES) {
252
253 if (mode2res == CONF2_ENABLE_RES) {
272 if (bootverbose)
273 printf ("pcibus_setup(2a):\tnow trying mechanism 2\n");
254 if (bootverbose)
255 printf("pci_open(2a):\tnow trying mechanism 2\n");
274
256
275 if (pcibus_check())
276 return;
257 if (pci_cfgcheck(16))
258 return (cfgmech);
277 }
278 }
279
259 }
260 }
261
280 /*---------------------------------------
281 ** No PCI bus host bridge found
282 **---------------------------------------
283 */
284
285 pci_mechanism = 0;
286 pci_maxdevice = 0;
262 cfgmech = 0;
263 devmax = 0;
264 return (cfgmech);
287}
265}
288
289/*--------------------------------------------------------------------
290**
291** Build a pcitag from bus, device and function number
292**
293**--------------------------------------------------------------------
294*/
295
296static pcici_t
297pcibus_tag (unsigned char bus, unsigned char device, unsigned char func)
298{
299 pcici_t tag;
300
301 tag.cfg1 = 0;
302 if (func >= 8) return tag;
303
304 switch (pci_mechanism) {
305
306 case 1:
307 if (device < 32) {
308 tag.cfg1 = CONF1_ENABLE
309 | (((u_long) bus ) << 16ul)
310 | (((u_long) device) << 11ul)
311 | (((u_long) func ) << 8ul);
312 }
313 break;
314 case 2:
315 if (device < 16) {
316 tag.cfg2.port = 0xc000 | (device << 8ul);
317 tag.cfg2.enable = 0xf0 | (func << 1ul);
318 tag.cfg2.forward = bus;
319 }
320 break;
321 };
322 return tag;
323}
324
325static pcici_t
326pcibus_ftag (pcici_t tag, u_char func)
327{
328 switch (pci_mechanism) {
329
330 case 1:
331 tag.cfg1 &= ~0x700ul;
332 tag.cfg1 |= (((u_long) func) << 8ul);
333 break;
334 case 2:
335 tag.cfg2.enable = 0xf0 | (func << 1ul);
336 break;
337 };
338 return tag;
339}
340
341/*--------------------------------------------------------------------
342**
343** Read register from configuration space.
344**
345**--------------------------------------------------------------------
346*/
347
348static u_long
349pcibus_read (pcici_t tag, u_long reg)
350{
351 u_long addr, data = 0;
352
353 if (!tag.cfg1) return (0xfffffffful);
354
355 switch (pci_mechanism) {
356
357 case 1:
358 addr = tag.cfg1 | (reg & 0xfc);
359#ifdef PCI_DEBUG
360 printf ("pci_conf_read(1): addr=%x ", addr);
361#endif
362 outl (CONF1_ADDR_PORT, addr);
363 data = inl (CONF1_DATA_PORT);
364 outl (CONF1_ADDR_PORT, 0 );
365 break;
366
367 case 2:
368 addr = tag.cfg2.port | (reg & 0xfc);
369#ifdef PCI_DEBUG
370 printf ("pci_conf_read(2): addr=%x ", addr);
371#endif
372 outb (CONF2_ENABLE_PORT , tag.cfg2.enable );
373 outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
374
375 data = inl ((u_short) addr);
376
377 outb (CONF2_ENABLE_PORT, 0);
378 outb (CONF2_FORWARD_PORT, 0);
379 break;
380 };
381
382#ifdef PCI_DEBUG
383 printf ("data=%x\n", data);
384#endif
385
386 return (data);
387}
388
389/*--------------------------------------------------------------------
390**
391** Write register into configuration space.
392**
393**--------------------------------------------------------------------
394*/
395
396static void
397pcibus_write (pcici_t tag, u_long reg, u_long data)
398{
399 u_long addr;
400
401 if (!tag.cfg1) return;
402
403 switch (pci_mechanism) {
404
405 case 1:
406 addr = tag.cfg1 | (reg & 0xfc);
407#ifdef PCI_DEBUG
408 printf ("pci_conf_write(1): addr=%x data=%x\n",
409 addr, data);
410#endif
411 outl (CONF1_ADDR_PORT, addr);
412 outl (CONF1_DATA_PORT, data);
413 outl (CONF1_ADDR_PORT, 0 );
414 break;
415
416 case 2:
417 addr = tag.cfg2.port | (reg & 0xfc);
418#ifdef PCI_DEBUG
419 printf ("pci_conf_write(2): addr=%x data=%x\n",
420 addr, data);
421#endif
422 outb (CONF2_ENABLE_PORT, tag.cfg2.enable);
423 outb (CONF2_FORWARD_PORT, tag.cfg2.forward);
424
425 outl ((u_short) addr, data);
426
427 outb (CONF2_ENABLE_PORT, 0);
428 outb (CONF2_FORWARD_PORT, 0);
429 break;
430 };
431}
432
433/*-----------------------------------------------------------------------
434**
435** Register an interrupt handler for a pci device.
436**
437**-----------------------------------------------------------------------
438*/
439
440static int
441pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned * maskptr)
442{
443 char buf[16];
444 char *cp;
445 int free_id, id, result;
446
447 sprintf(buf, "pci irq%d", irq);
448 for (cp = intrnames, free_id = 0, id = 0; id < NR_DEVICES; id++) {
449 if (strcmp(cp, buf) == 0)
450 break;
451 if (free_id <= 0 && strcmp(cp, "pci irqnn") == 0)
452 free_id = id;
453 while (*cp++ != '\0')
454 ;
455 }
456 if (id == NR_DEVICES) {
457 id = free_id;
458 if (id == 0) {
459 /*
460 * All pci irq counters are in use, perhaps because
461 * config is old so there aren't any. Abuse the
462 * clk0 counter.
463 */
464 printf (
465 "pcibus_ihandler_attach: counting pci irq%d's as clk0 irqs\n",
466 irq);
467 }
468 }
469 result = register_intr(
470 irq, /* isa irq */
471 id, /* device id */
472 0, /* flags? */
473 func, /* handler */
474 maskptr, /* mask pointer */
475 arg); /* handler arg */
476
477 if (result) {
478 printf ("@@@ pcibus_ihandler_attach: result=%d\n", result);
479 return (result);
480 };
481 update_intr_masks();
482
483 INTREN ((1ul<<irq));
484 return (0);
485}
486
487static int
488pcibus_ihandler_detach (int irq, inthand2_t *func)
489{
490 int result;
491
492 INTRDIS ((1ul<<irq));
493
494 result = unregister_intr (irq, func);
495
496 if (result)
497 printf ("@@@ pcibus_ihandler_detach: result=%d\n", result);
498
499 update_intr_masks();
500
501 return (result);
502}
503
504static int
505pcibus_imask_include (int irq, unsigned* maskptr)
506{
507 unsigned mask;
508
509 if (!maskptr) return (0);
510
511 mask = 1ul << irq;
512
513 if (*maskptr & mask)
514 return (-1);
515
516 INTRMASK (*maskptr, mask);
517 update_intr_masks();
518
519 return (0);
520}
521
522static int
523pcibus_imask_exclude (int irq, unsigned* maskptr)
524{
525 unsigned mask;
526
527 if (!maskptr) return (0);
528
529 mask = 1ul << irq;
530
531 if (! (*maskptr & mask))
532 return (-1);
533
534 INTRUNMASK (*maskptr, mask);
535 update_intr_masks();
536
537 return (0);
538}