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}
| |
| |