1ac19f918SStefan Eßer /************************************************************************** 2ac19f918SStefan Eßer ** 3a3adc4f8SStefan Eßer ** $Id: pcibus.c,v 1.13 1995/09/15 21:43:45 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 148a3adc4f8SStefan Eßer #define CONF1_ENABLE_CHK1 0xF0000001ul 149a3adc4f8SStefan Eßer #define CONF1_ENABLE_MSK1 0x80000001ul 150a3adc4f8SStefan Eßer #define CONF1_ENABLE_RES1 0x80000000ul 151a3adc4f8SStefan Eßer #define CONF1_ENABLE_CHK2 0xfffffffful 152a3adc4f8SStefan Eßer #define CONF1_ENABLE_RES2 0x80fffffcul 153ac19f918SStefan Eßer 154ac19f918SStefan Eßer #define CONF2_ENABLE_PORT 0x0cf8 155ac19f918SStefan Eßer #define CONF2_FORWARD_PORT 0x0cfa 156ac19f918SStefan Eßer 1572d144186SStefan Eßer #define CONF2_ENABLE_CHK 0x0e 1582d144186SStefan Eßer #define CONF2_ENABLE_RES 0x0e 159ac19f918SStefan Eßer 160d7ea35fcSStefan Eßer 161a3adc4f8SStefan Eßer static int 162a3adc4f8SStefan Eßer pcibus_check (void) 163a3adc4f8SStefan Eßer { 164a3adc4f8SStefan Eßer u_char device; 165a3adc4f8SStefan Eßer 166a3adc4f8SStefan Eßer for (device = 0; device < pci_maxdevice; device++) { 167a3adc4f8SStefan Eßer if (pcibus_read (pcibus_tag (0,device,0), 0) != 0xfffffffful) 168a3adc4f8SStefan Eßer return 1; 169a3adc4f8SStefan Eßer } 170a3adc4f8SStefan Eßer return 0; 171a3adc4f8SStefan Eßer } 172d7ea35fcSStefan Eßer 1735b3f532eSStefan Eßer static void 1745b3f532eSStefan Eßer pcibus_setup (void) 175ac19f918SStefan Eßer { 176ac19f918SStefan Eßer u_long result, oldval; 177ac19f918SStefan Eßer 178ac19f918SStefan Eßer /*--------------------------------------- 1790847c06dSStefan Eßer ** Configuration mode 1 ? 1800847c06dSStefan Eßer **--------------------------------------- 1810847c06dSStefan Eßer */ 1820847c06dSStefan Eßer 1830847c06dSStefan Eßer oldval = inl (CONF1_ADDR_PORT); 184a3adc4f8SStefan Eßer outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 185a3adc4f8SStefan Eßer outb (CONF1_ADDR_PORT +3, 0); 1860847c06dSStefan Eßer result = inl (CONF1_ADDR_PORT); 1870847c06dSStefan Eßer outl (CONF1_ADDR_PORT, oldval); 1880847c06dSStefan Eßer 189a3adc4f8SStefan Eßer if ((result & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 1900847c06dSStefan Eßer pci_mechanism = 1; 1910847c06dSStefan Eßer pci_maxdevice = 32; 192a3adc4f8SStefan Eßer if (pcibus_check()) 1930847c06dSStefan Eßer return; 1940847c06dSStefan Eßer }; 1950847c06dSStefan Eßer 1960847c06dSStefan Eßer /*--------------------------------------- 197ac19f918SStefan Eßer ** Configuration mode 2 ? 198ac19f918SStefan Eßer **--------------------------------------- 199ac19f918SStefan Eßer */ 200ac19f918SStefan Eßer 2012d144186SStefan Eßer outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 202ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 2032d144186SStefan Eßer result = inb (CONF2_ENABLE_PORT); 2042d144186SStefan Eßer 2052d144186SStefan Eßer outb (CONF2_ENABLE_PORT, 0); 206a3adc4f8SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 2072d144186SStefan Eßer if ((result == CONF2_ENABLE_RES) 2082d144186SStefan Eßer && !inb (CONF2_ENABLE_PORT) 2092d144186SStefan Eßer && !inb (CONF2_FORWARD_PORT)) { 2105b3f532eSStefan Eßer pci_mechanism = 2; 2115b3f532eSStefan Eßer pci_maxdevice = 16; 212a3adc4f8SStefan Eßer if (pcibus_check()) 2130f29bf01SStefan Eßer return; 214ac19f918SStefan Eßer }; 215ac19f918SStefan Eßer 216a3adc4f8SStefan Eßer 217a3adc4f8SStefan Eßer /*----------------------------------------------------- 218a3adc4f8SStefan Eßer ** Well, is it Configuration mode 1, after all ? 219a3adc4f8SStefan Eßer **----------------------------------------------------- 220a3adc4f8SStefan Eßer */ 221a3adc4f8SStefan Eßer 222a3adc4f8SStefan Eßer oldval = inl (CONF1_ADDR_PORT); 223a3adc4f8SStefan Eßer outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK2); 224a3adc4f8SStefan Eßer outl (CONF1_DATA_PORT, 0); 225a3adc4f8SStefan Eßer result = inl (CONF1_ADDR_PORT); 226a3adc4f8SStefan Eßer outl (CONF1_ADDR_PORT, oldval); 227a3adc4f8SStefan Eßer 228a3adc4f8SStefan Eßer if (result == CONF1_ENABLE_RES2) { 229a3adc4f8SStefan Eßer pci_mechanism = 1; 230a3adc4f8SStefan Eßer pci_maxdevice = 32; 231a3adc4f8SStefan Eßer if (pcibus_check()) 232a3adc4f8SStefan Eßer return; 233a3adc4f8SStefan Eßer } 234a3adc4f8SStefan Eßer 235ac19f918SStefan Eßer /*--------------------------------------- 236cda67911SStefan Eßer ** No PCI bus host bridge found 237ac19f918SStefan Eßer **--------------------------------------- 238ac19f918SStefan Eßer */ 239cda67911SStefan Eßer 240a3adc4f8SStefan Eßer if (bootverbose && (result != 0xfffffffful)) 241a3adc4f8SStefan Eßer printf ("pcibus_setup: " 242a3adc4f8SStefan Eßer "wrote 0x%08x, read back 0x%08x, expected 0x%08x\n", 243a3adc4f8SStefan Eßer CONF1_ENABLE_CHK2, result, CONF1_ENABLE_RES2); 244a3adc4f8SStefan Eßer 245cda67911SStefan Eßer pci_mechanism = 0; 246cda67911SStefan Eßer pci_maxdevice = 0; 247ac19f918SStefan Eßer } 2485b3f532eSStefan Eßer 249ac19f918SStefan Eßer /*-------------------------------------------------------------------- 250ac19f918SStefan Eßer ** 251ac19f918SStefan Eßer ** Build a pcitag from bus, device and function number 252ac19f918SStefan Eßer ** 253ac19f918SStefan Eßer **-------------------------------------------------------------------- 254ac19f918SStefan Eßer */ 255ac19f918SStefan Eßer 256ac19f918SStefan Eßer static pcici_t 257ac19f918SStefan Eßer pcibus_tag (unsigned char bus, unsigned char device, unsigned char func) 258ac19f918SStefan Eßer { 259ac19f918SStefan Eßer pcici_t tag; 260ac19f918SStefan Eßer 261ac19f918SStefan Eßer tag.cfg1 = 0; 262ac19f918SStefan Eßer if (func >= 8) return tag; 263ac19f918SStefan Eßer 2645b3f532eSStefan Eßer switch (pci_mechanism) { 265ac19f918SStefan Eßer 266ac19f918SStefan Eßer case 1: 2672d144186SStefan Eßer if (device < 32) { 268ac19f918SStefan Eßer tag.cfg1 = CONF1_ENABLE 269ac19f918SStefan Eßer | (((u_long) bus ) << 16ul) 270ac19f918SStefan Eßer | (((u_long) device) << 11ul) 271ac19f918SStefan Eßer | (((u_long) func ) << 8ul); 2722d144186SStefan Eßer } 273ac19f918SStefan Eßer break; 274ac19f918SStefan Eßer case 2: 2752d144186SStefan Eßer if (device < 16) { 276ac19f918SStefan Eßer tag.cfg2.port = 0xc000 | (device << 8ul); 2772d144186SStefan Eßer tag.cfg2.enable = 0xf0 | (func << 1ul); 278ac19f918SStefan Eßer tag.cfg2.forward = bus; 2792d144186SStefan Eßer } 280ac19f918SStefan Eßer break; 281ac19f918SStefan Eßer }; 282ac19f918SStefan Eßer return tag; 283ac19f918SStefan Eßer } 2845b3f532eSStefan Eßer 2855b3f532eSStefan Eßer static pcici_t 2865b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func) 2875b3f532eSStefan Eßer { 2885b3f532eSStefan Eßer switch (pci_mechanism) { 2895b3f532eSStefan Eßer 2905b3f532eSStefan Eßer case 1: 2915b3f532eSStefan Eßer tag.cfg1 &= ~0x700ul; 2925b3f532eSStefan Eßer tag.cfg1 |= (((u_long) func) << 8ul); 2935b3f532eSStefan Eßer break; 2945b3f532eSStefan Eßer case 2: 2952d144186SStefan Eßer tag.cfg2.enable = 0xf0 | (func << 1ul); 2965b3f532eSStefan Eßer break; 2975b3f532eSStefan Eßer }; 2985b3f532eSStefan Eßer return tag; 2995b3f532eSStefan Eßer } 3005b3f532eSStefan Eßer 301ac19f918SStefan Eßer /*-------------------------------------------------------------------- 302ac19f918SStefan Eßer ** 303ac19f918SStefan Eßer ** Read register from configuration space. 304ac19f918SStefan Eßer ** 305ac19f918SStefan Eßer **-------------------------------------------------------------------- 306ac19f918SStefan Eßer */ 307ac19f918SStefan Eßer 308ac19f918SStefan Eßer static u_long 309ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg) 310ac19f918SStefan Eßer { 311ac19f918SStefan Eßer u_long addr, data = 0; 312ac19f918SStefan Eßer 313ac19f918SStefan Eßer if (!tag.cfg1) return (0xfffffffful); 314ac19f918SStefan Eßer 3155b3f532eSStefan Eßer switch (pci_mechanism) { 316ac19f918SStefan Eßer 317ac19f918SStefan Eßer case 1: 318ac19f918SStefan Eßer addr = tag.cfg1 | (reg & 0xfc); 319ac19f918SStefan Eßer #ifdef PCI_DEBUG 320ac19f918SStefan Eßer printf ("pci_conf_read(1): addr=%x ", addr); 321ac19f918SStefan Eßer #endif 322ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, addr); 323ac19f918SStefan Eßer data = inl (CONF1_DATA_PORT); 324ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, 0 ); 325ac19f918SStefan Eßer break; 326ac19f918SStefan Eßer 327ac19f918SStefan Eßer case 2: 328ac19f918SStefan Eßer addr = tag.cfg2.port | (reg & 0xfc); 329ac19f918SStefan Eßer #ifdef PCI_DEBUG 330ac19f918SStefan Eßer printf ("pci_conf_read(2): addr=%x ", addr); 331ac19f918SStefan Eßer #endif 332ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT , tag.cfg2.enable ); 333ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 334ac19f918SStefan Eßer 335ac19f918SStefan Eßer data = inl ((u_short) addr); 336ac19f918SStefan Eßer 337ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, 0); 338ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 339ac19f918SStefan Eßer break; 340ac19f918SStefan Eßer }; 341ac19f918SStefan Eßer 342ac19f918SStefan Eßer #ifdef PCI_DEBUG 343ac19f918SStefan Eßer printf ("data=%x\n", data); 344ac19f918SStefan Eßer #endif 345ac19f918SStefan Eßer 346ac19f918SStefan Eßer return (data); 347ac19f918SStefan Eßer } 3485b3f532eSStefan Eßer 349ac19f918SStefan Eßer /*-------------------------------------------------------------------- 350ac19f918SStefan Eßer ** 351ac19f918SStefan Eßer ** Write register into configuration space. 352ac19f918SStefan Eßer ** 353ac19f918SStefan Eßer **-------------------------------------------------------------------- 354ac19f918SStefan Eßer */ 355ac19f918SStefan Eßer 356ac19f918SStefan Eßer static void 357ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data) 358ac19f918SStefan Eßer { 359ac19f918SStefan Eßer u_long addr; 360ac19f918SStefan Eßer 361ac19f918SStefan Eßer if (!tag.cfg1) return; 362ac19f918SStefan Eßer 3635b3f532eSStefan Eßer switch (pci_mechanism) { 364ac19f918SStefan Eßer 365ac19f918SStefan Eßer case 1: 366ac19f918SStefan Eßer addr = tag.cfg1 | (reg & 0xfc); 367ac19f918SStefan Eßer #ifdef PCI_DEBUG 368ac19f918SStefan Eßer printf ("pci_conf_write(1): addr=%x data=%x\n", 369ac19f918SStefan Eßer addr, data); 370ac19f918SStefan Eßer #endif 371ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, addr); 372ac19f918SStefan Eßer outl (CONF1_DATA_PORT, data); 373ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, 0 ); 374ac19f918SStefan Eßer break; 375ac19f918SStefan Eßer 376ac19f918SStefan Eßer case 2: 377ac19f918SStefan Eßer addr = tag.cfg2.port | (reg & 0xfc); 378ac19f918SStefan Eßer #ifdef PCI_DEBUG 379ac19f918SStefan Eßer printf ("pci_conf_write(2): addr=%x data=%x\n", 380ac19f918SStefan Eßer addr, data); 381ac19f918SStefan Eßer #endif 382ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, tag.cfg2.enable); 383ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 384ac19f918SStefan Eßer 385ac19f918SStefan Eßer outl ((u_short) addr, data); 386ac19f918SStefan Eßer 387ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, 0); 388ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 389ac19f918SStefan Eßer break; 390ac19f918SStefan Eßer }; 391ac19f918SStefan Eßer } 3925b3f532eSStefan Eßer 393ac19f918SStefan Eßer /*----------------------------------------------------------------------- 394ac19f918SStefan Eßer ** 395ac19f918SStefan Eßer ** Register an interupt handler for a pci device. 396ac19f918SStefan Eßer ** 397ac19f918SStefan Eßer **----------------------------------------------------------------------- 398ac19f918SStefan Eßer */ 399ac19f918SStefan Eßer 400ac19f918SStefan Eßer static int 4015b3f532eSStefan Eßer pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr) 402ac19f918SStefan Eßer { 4035b3f532eSStefan Eßer int result; 4045b3f532eSStefan Eßer result = register_intr( 405ac19f918SStefan Eßer irq, /* isa irq */ 406ac19f918SStefan Eßer 0, /* deviced?? */ 407ac19f918SStefan Eßer 0, /* flags? */ 408ac19f918SStefan Eßer (inthand2_t*) func, /* handler */ 409ac19f918SStefan Eßer maskptr, /* mask pointer */ 4105b3f532eSStefan Eßer arg); /* handler arg */ 411ac19f918SStefan Eßer 4125b3f532eSStefan Eßer if (result) { 4135b3f532eSStefan Eßer printf ("@@@ pcibus_ihandler_attach: result=%d\n", result); 4145b3f532eSStefan Eßer return (result); 415ac19f918SStefan Eßer }; 4165b3f532eSStefan Eßer update_intr_masks(); 417ac19f918SStefan Eßer 4185b3f532eSStefan Eßer INTREN ((1ul<<irq)); 4195b3f532eSStefan Eßer return (0); 4205b3f532eSStefan Eßer } 421ac19f918SStefan Eßer 4225b3f532eSStefan Eßer static int 4235b3f532eSStefan Eßer pcibus_ihandler_detach (int irq, void(*func)()) 4245b3f532eSStefan Eßer { 4255b3f532eSStefan Eßer int result; 4265b3f532eSStefan Eßer 4275b3f532eSStefan Eßer INTRDIS ((1ul<<irq)); 4285b3f532eSStefan Eßer 4295b3f532eSStefan Eßer result = unregister_intr (irq, (inthand2_t*) func); 4305b3f532eSStefan Eßer 4315b3f532eSStefan Eßer if (result) 4325b3f532eSStefan Eßer printf ("@@@ pcibus_ihandler_detach: result=%d\n", result); 4335b3f532eSStefan Eßer 4345b3f532eSStefan Eßer update_intr_masks(); 4355b3f532eSStefan Eßer 4365b3f532eSStefan Eßer return (result); 4375b3f532eSStefan Eßer } 4385b3f532eSStefan Eßer 4395b3f532eSStefan Eßer static int 4405b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr) 4415b3f532eSStefan Eßer { 4425b3f532eSStefan Eßer unsigned mask; 4435b3f532eSStefan Eßer 4445b3f532eSStefan Eßer if (!maskptr) return (0); 4455b3f532eSStefan Eßer 4465b3f532eSStefan Eßer mask = 1ul << irq; 4475b3f532eSStefan Eßer 4485b3f532eSStefan Eßer if (*maskptr & mask) 4495b3f532eSStefan Eßer return (-1); 4505b3f532eSStefan Eßer 4515b3f532eSStefan Eßer INTRMASK (*maskptr, mask); 4525b3f532eSStefan Eßer update_intr_masks(); 4535b3f532eSStefan Eßer 4545b3f532eSStefan Eßer return (0); 4555b3f532eSStefan Eßer } 4565b3f532eSStefan Eßer 4575b3f532eSStefan Eßer static int 4585b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr) 4595b3f532eSStefan Eßer { 4605b3f532eSStefan Eßer unsigned mask; 4615b3f532eSStefan Eßer 4625b3f532eSStefan Eßer if (!maskptr) return (0); 4635b3f532eSStefan Eßer 4645b3f532eSStefan Eßer mask = 1ul << irq; 4655b3f532eSStefan Eßer 4665b3f532eSStefan Eßer if (! (*maskptr & mask)) 4675b3f532eSStefan Eßer return (-1); 4685b3f532eSStefan Eßer 4695b3f532eSStefan Eßer *maskptr &= ~mask; 4705b3f532eSStefan Eßer update_intr_masks(); 4715b3f532eSStefan Eßer 4725b3f532eSStefan Eßer return (0); 473ac19f918SStefan Eßer } 474