1ac19f918SStefan Eßer /************************************************************************** 2ac19f918SStefan Eßer ** 377b57314SStefan Eßer ** $Id: pcibus.c,v 1.14 1995/09/18 21:48:39 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 15077b57314SStefan Eßer #define CONF1_ENABLE_MSK1 0x80000000ul 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++) { 16777b57314SStefan Eßer if (bootverbose) printf ("%d ", device); 16877b57314SStefan Eßer if (pcibus_read (pcibus_tag (0,device,0), 0) != 0xfffffffful) { 16977b57314SStefan Eßer if (bootverbose) printf ("is there\n"); 170a3adc4f8SStefan Eßer return 1; 171a3adc4f8SStefan Eßer } 17277b57314SStefan Eßer } 17377b57314SStefan Eßer if (bootverbose) printf ("-- nothing found\n"); 174a3adc4f8SStefan Eßer return 0; 175a3adc4f8SStefan Eßer } 176d7ea35fcSStefan Eßer 1775b3f532eSStefan Eßer static void 1785b3f532eSStefan Eßer pcibus_setup (void) 179ac19f918SStefan Eßer { 18077b57314SStefan Eßer unsigned long mode1res,oldval; 18177b57314SStefan Eßer unsigned char mode2res; 1820847c06dSStefan Eßer 1830847c06dSStefan Eßer oldval = inl (CONF1_ADDR_PORT); 18477b57314SStefan Eßer outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 1852d144186SStefan Eßer outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 18677b57314SStefan Eßer mode1res = inl(CONF1_ADDR_PORT); 18777b57314SStefan Eßer mode2res = inb(CONF2_ENABLE_PORT); 188a3adc4f8SStefan Eßer outl (CONF1_ADDR_PORT, oldval); 189a3adc4f8SStefan Eßer 19077b57314SStefan Eßer if (bootverbose) { 19177b57314SStefan Eßer printf ("pcibus_setup(1):\tmode1res=0x%08lx (0x%08lx), " 19277b57314SStefan Eßer "mode2res=0x%02x (0x%02x)\n", 19377b57314SStefan Eßer mode1res,CONF1_ENABLE_CHK, 19477b57314SStefan Eßer (int)mode2res,CONF2_ENABLE_CHK); 19577b57314SStefan Eßer } 19677b57314SStefan Eßer 19777b57314SStefan Eßer /*--------------------------------------- 19877b57314SStefan Eßer ** No PCI, if neither mode1res nor mode2res could be read back 19977b57314SStefan Eßer **--------------------------------------- 20077b57314SStefan Eßer */ 20177b57314SStefan Eßer 20277b57314SStefan Eßer if ((mode1res != CONF1_ENABLE_CHK) && (mode2res != CONF2_ENABLE_CHK)) { 203a3adc4f8SStefan Eßer return; 204a3adc4f8SStefan Eßer } 205a3adc4f8SStefan Eßer 206ac19f918SStefan Eßer /*--------------------------------------- 20777b57314SStefan Eßer ** Assume configuration mechanism 1 for now ... 20877b57314SStefan Eßer **--------------------------------------- 20977b57314SStefan Eßer */ 21077b57314SStefan Eßer 21177b57314SStefan Eßer pci_mechanism = 1; 21277b57314SStefan Eßer pci_maxdevice = 32; 21377b57314SStefan Eßer 21477b57314SStefan Eßer outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 21577b57314SStefan Eßer outb (CONF1_ADDR_PORT +3, 0); 21677b57314SStefan Eßer mode1res = inl (CONF1_ADDR_PORT); 21777b57314SStefan Eßer outl (CONF1_ADDR_PORT, oldval); 21877b57314SStefan Eßer 21977b57314SStefan Eßer if (bootverbose) 22077b57314SStefan Eßer printf ("pcibus_setup(2):\tmode1res=0x%08lx (0x%08lx)\n", 22177b57314SStefan Eßer mode1res, CONF1_ENABLE_CHK); 22277b57314SStefan Eßer 22377b57314SStefan Eßer if (mode1res) { 22477b57314SStefan Eßer if (pcibus_check()) 22577b57314SStefan Eßer return; 22677b57314SStefan Eßer }; 22777b57314SStefan Eßer 22877b57314SStefan Eßer outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 22977b57314SStefan Eßer outl (CONF1_DATA_PORT, 0); 23077b57314SStefan Eßer mode1res = inl(CONF1_ADDR_PORT); 23177b57314SStefan Eßer outl (CONF1_ADDR_PORT, oldval); 23277b57314SStefan Eßer 23377b57314SStefan Eßer if (bootverbose) 23477b57314SStefan Eßer printf ("pcibus_setup(3):\tmode1res=0x%08lx (0x%08lx)\n", 23577b57314SStefan Eßer mode1res, CONF1_ENABLE_CHK1); 23677b57314SStefan Eßer 23777b57314SStefan Eßer if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_CHK1) { 23877b57314SStefan Eßer if (pcibus_check()) 23977b57314SStefan Eßer return; 24077b57314SStefan Eßer }; 24177b57314SStefan Eßer 24277b57314SStefan Eßer /*--------------------------------------- 24377b57314SStefan Eßer ** Try configuration mechanism 2 ... 24477b57314SStefan Eßer **--------------------------------------- 24577b57314SStefan Eßer */ 24677b57314SStefan Eßer 24777b57314SStefan Eßer pci_mechanism = 2; 24877b57314SStefan Eßer pci_maxdevice = 16; 24977b57314SStefan Eßer 25077b57314SStefan Eßer if (pcibus_check()) 25177b57314SStefan Eßer return; 25277b57314SStefan Eßer 25377b57314SStefan Eßer /*--------------------------------------- 254cda67911SStefan Eßer ** No PCI bus host bridge found 255ac19f918SStefan Eßer **--------------------------------------- 256ac19f918SStefan Eßer */ 257cda67911SStefan Eßer 258cda67911SStefan Eßer pci_mechanism = 0; 259cda67911SStefan Eßer pci_maxdevice = 0; 260ac19f918SStefan Eßer } 2615b3f532eSStefan Eßer 262ac19f918SStefan Eßer /*-------------------------------------------------------------------- 263ac19f918SStefan Eßer ** 264ac19f918SStefan Eßer ** Build a pcitag from bus, device and function number 265ac19f918SStefan Eßer ** 266ac19f918SStefan Eßer **-------------------------------------------------------------------- 267ac19f918SStefan Eßer */ 268ac19f918SStefan Eßer 269ac19f918SStefan Eßer static pcici_t 270ac19f918SStefan Eßer pcibus_tag (unsigned char bus, unsigned char device, unsigned char func) 271ac19f918SStefan Eßer { 272ac19f918SStefan Eßer pcici_t tag; 273ac19f918SStefan Eßer 274ac19f918SStefan Eßer tag.cfg1 = 0; 275ac19f918SStefan Eßer if (func >= 8) return tag; 276ac19f918SStefan Eßer 2775b3f532eSStefan Eßer switch (pci_mechanism) { 278ac19f918SStefan Eßer 279ac19f918SStefan Eßer case 1: 2802d144186SStefan Eßer if (device < 32) { 281ac19f918SStefan Eßer tag.cfg1 = CONF1_ENABLE 282ac19f918SStefan Eßer | (((u_long) bus ) << 16ul) 283ac19f918SStefan Eßer | (((u_long) device) << 11ul) 284ac19f918SStefan Eßer | (((u_long) func ) << 8ul); 2852d144186SStefan Eßer } 286ac19f918SStefan Eßer break; 287ac19f918SStefan Eßer case 2: 2882d144186SStefan Eßer if (device < 16) { 289ac19f918SStefan Eßer tag.cfg2.port = 0xc000 | (device << 8ul); 2902d144186SStefan Eßer tag.cfg2.enable = 0xf0 | (func << 1ul); 291ac19f918SStefan Eßer tag.cfg2.forward = bus; 2922d144186SStefan Eßer } 293ac19f918SStefan Eßer break; 294ac19f918SStefan Eßer }; 295ac19f918SStefan Eßer return tag; 296ac19f918SStefan Eßer } 2975b3f532eSStefan Eßer 2985b3f532eSStefan Eßer static pcici_t 2995b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func) 3005b3f532eSStefan Eßer { 3015b3f532eSStefan Eßer switch (pci_mechanism) { 3025b3f532eSStefan Eßer 3035b3f532eSStefan Eßer case 1: 3045b3f532eSStefan Eßer tag.cfg1 &= ~0x700ul; 3055b3f532eSStefan Eßer tag.cfg1 |= (((u_long) func) << 8ul); 3065b3f532eSStefan Eßer break; 3075b3f532eSStefan Eßer case 2: 3082d144186SStefan Eßer tag.cfg2.enable = 0xf0 | (func << 1ul); 3095b3f532eSStefan Eßer break; 3105b3f532eSStefan Eßer }; 3115b3f532eSStefan Eßer return tag; 3125b3f532eSStefan Eßer } 3135b3f532eSStefan Eßer 314ac19f918SStefan Eßer /*-------------------------------------------------------------------- 315ac19f918SStefan Eßer ** 316ac19f918SStefan Eßer ** Read register from configuration space. 317ac19f918SStefan Eßer ** 318ac19f918SStefan Eßer **-------------------------------------------------------------------- 319ac19f918SStefan Eßer */ 320ac19f918SStefan Eßer 321ac19f918SStefan Eßer static u_long 322ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg) 323ac19f918SStefan Eßer { 324ac19f918SStefan Eßer u_long addr, data = 0; 325ac19f918SStefan Eßer 326ac19f918SStefan Eßer if (!tag.cfg1) return (0xfffffffful); 327ac19f918SStefan Eßer 3285b3f532eSStefan Eßer switch (pci_mechanism) { 329ac19f918SStefan Eßer 330ac19f918SStefan Eßer case 1: 331ac19f918SStefan Eßer addr = tag.cfg1 | (reg & 0xfc); 332ac19f918SStefan Eßer #ifdef PCI_DEBUG 333ac19f918SStefan Eßer printf ("pci_conf_read(1): addr=%x ", addr); 334ac19f918SStefan Eßer #endif 335ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, addr); 336ac19f918SStefan Eßer data = inl (CONF1_DATA_PORT); 337ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, 0 ); 338ac19f918SStefan Eßer break; 339ac19f918SStefan Eßer 340ac19f918SStefan Eßer case 2: 341ac19f918SStefan Eßer addr = tag.cfg2.port | (reg & 0xfc); 342ac19f918SStefan Eßer #ifdef PCI_DEBUG 343ac19f918SStefan Eßer printf ("pci_conf_read(2): addr=%x ", addr); 344ac19f918SStefan Eßer #endif 345ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT , tag.cfg2.enable ); 346ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 347ac19f918SStefan Eßer 348ac19f918SStefan Eßer data = inl ((u_short) addr); 349ac19f918SStefan Eßer 350ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, 0); 351ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 352ac19f918SStefan Eßer break; 353ac19f918SStefan Eßer }; 354ac19f918SStefan Eßer 355ac19f918SStefan Eßer #ifdef PCI_DEBUG 356ac19f918SStefan Eßer printf ("data=%x\n", data); 357ac19f918SStefan Eßer #endif 358ac19f918SStefan Eßer 359ac19f918SStefan Eßer return (data); 360ac19f918SStefan Eßer } 3615b3f532eSStefan Eßer 362ac19f918SStefan Eßer /*-------------------------------------------------------------------- 363ac19f918SStefan Eßer ** 364ac19f918SStefan Eßer ** Write register into configuration space. 365ac19f918SStefan Eßer ** 366ac19f918SStefan Eßer **-------------------------------------------------------------------- 367ac19f918SStefan Eßer */ 368ac19f918SStefan Eßer 369ac19f918SStefan Eßer static void 370ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data) 371ac19f918SStefan Eßer { 372ac19f918SStefan Eßer u_long addr; 373ac19f918SStefan Eßer 374ac19f918SStefan Eßer if (!tag.cfg1) return; 375ac19f918SStefan Eßer 3765b3f532eSStefan Eßer switch (pci_mechanism) { 377ac19f918SStefan Eßer 378ac19f918SStefan Eßer case 1: 379ac19f918SStefan Eßer addr = tag.cfg1 | (reg & 0xfc); 380ac19f918SStefan Eßer #ifdef PCI_DEBUG 381ac19f918SStefan Eßer printf ("pci_conf_write(1): addr=%x data=%x\n", 382ac19f918SStefan Eßer addr, data); 383ac19f918SStefan Eßer #endif 384ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, addr); 385ac19f918SStefan Eßer outl (CONF1_DATA_PORT, data); 386ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, 0 ); 387ac19f918SStefan Eßer break; 388ac19f918SStefan Eßer 389ac19f918SStefan Eßer case 2: 390ac19f918SStefan Eßer addr = tag.cfg2.port | (reg & 0xfc); 391ac19f918SStefan Eßer #ifdef PCI_DEBUG 392ac19f918SStefan Eßer printf ("pci_conf_write(2): addr=%x data=%x\n", 393ac19f918SStefan Eßer addr, data); 394ac19f918SStefan Eßer #endif 395ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, tag.cfg2.enable); 396ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 397ac19f918SStefan Eßer 398ac19f918SStefan Eßer outl ((u_short) addr, data); 399ac19f918SStefan Eßer 400ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, 0); 401ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 402ac19f918SStefan Eßer break; 403ac19f918SStefan Eßer }; 404ac19f918SStefan Eßer } 4055b3f532eSStefan Eßer 406ac19f918SStefan Eßer /*----------------------------------------------------------------------- 407ac19f918SStefan Eßer ** 408ac19f918SStefan Eßer ** Register an interupt handler for a pci device. 409ac19f918SStefan Eßer ** 410ac19f918SStefan Eßer **----------------------------------------------------------------------- 411ac19f918SStefan Eßer */ 412ac19f918SStefan Eßer 413ac19f918SStefan Eßer static int 4145b3f532eSStefan Eßer pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr) 415ac19f918SStefan Eßer { 4165b3f532eSStefan Eßer int result; 4175b3f532eSStefan Eßer result = register_intr( 418ac19f918SStefan Eßer irq, /* isa irq */ 419ac19f918SStefan Eßer 0, /* deviced?? */ 420ac19f918SStefan Eßer 0, /* flags? */ 421ac19f918SStefan Eßer (inthand2_t*) func, /* handler */ 422ac19f918SStefan Eßer maskptr, /* mask pointer */ 4235b3f532eSStefan Eßer arg); /* handler arg */ 424ac19f918SStefan Eßer 4255b3f532eSStefan Eßer if (result) { 4265b3f532eSStefan Eßer printf ("@@@ pcibus_ihandler_attach: result=%d\n", result); 4275b3f532eSStefan Eßer return (result); 428ac19f918SStefan Eßer }; 4295b3f532eSStefan Eßer update_intr_masks(); 430ac19f918SStefan Eßer 4315b3f532eSStefan Eßer INTREN ((1ul<<irq)); 4325b3f532eSStefan Eßer return (0); 4335b3f532eSStefan Eßer } 434ac19f918SStefan Eßer 4355b3f532eSStefan Eßer static int 4365b3f532eSStefan Eßer pcibus_ihandler_detach (int irq, void(*func)()) 4375b3f532eSStefan Eßer { 4385b3f532eSStefan Eßer int result; 4395b3f532eSStefan Eßer 4405b3f532eSStefan Eßer INTRDIS ((1ul<<irq)); 4415b3f532eSStefan Eßer 4425b3f532eSStefan Eßer result = unregister_intr (irq, (inthand2_t*) func); 4435b3f532eSStefan Eßer 4445b3f532eSStefan Eßer if (result) 4455b3f532eSStefan Eßer printf ("@@@ pcibus_ihandler_detach: result=%d\n", result); 4465b3f532eSStefan Eßer 4475b3f532eSStefan Eßer update_intr_masks(); 4485b3f532eSStefan Eßer 4495b3f532eSStefan Eßer return (result); 4505b3f532eSStefan Eßer } 4515b3f532eSStefan Eßer 4525b3f532eSStefan Eßer static int 4535b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr) 4545b3f532eSStefan Eßer { 4555b3f532eSStefan Eßer unsigned mask; 4565b3f532eSStefan Eßer 4575b3f532eSStefan Eßer if (!maskptr) return (0); 4585b3f532eSStefan Eßer 4595b3f532eSStefan Eßer mask = 1ul << irq; 4605b3f532eSStefan Eßer 4615b3f532eSStefan Eßer if (*maskptr & mask) 4625b3f532eSStefan Eßer return (-1); 4635b3f532eSStefan Eßer 4645b3f532eSStefan Eßer INTRMASK (*maskptr, mask); 4655b3f532eSStefan Eßer update_intr_masks(); 4665b3f532eSStefan Eßer 4675b3f532eSStefan Eßer return (0); 4685b3f532eSStefan Eßer } 4695b3f532eSStefan Eßer 4705b3f532eSStefan Eßer static int 4715b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr) 4725b3f532eSStefan Eßer { 4735b3f532eSStefan Eßer unsigned mask; 4745b3f532eSStefan Eßer 4755b3f532eSStefan Eßer if (!maskptr) return (0); 4765b3f532eSStefan Eßer 4775b3f532eSStefan Eßer mask = 1ul << irq; 4785b3f532eSStefan Eßer 4795b3f532eSStefan Eßer if (! (*maskptr & mask)) 4805b3f532eSStefan Eßer return (-1); 4815b3f532eSStefan Eßer 4825b3f532eSStefan Eßer *maskptr &= ~mask; 4835b3f532eSStefan Eßer update_intr_masks(); 4845b3f532eSStefan Eßer 4855b3f532eSStefan Eßer return (0); 486ac19f918SStefan Eßer } 487