1ac19f918SStefan Eßer /************************************************************************** 2ac19f918SStefan Eßer ** 3287911bdSStefan Eßer ** $Id: pcibus.c,v 1.16 1995/10/09 21:56:24 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 150287911bdSStefan Eßer #define CONF1_ENABLE_MSK1 0x80000001ul 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++) { 167c7483249SStefan Eßer unsigned long id; 168c7483249SStefan Eßer if (bootverbose) 169c7483249SStefan Eßer printf ("%d ", device); 170c7483249SStefan Eßer id = pcibus_read (pcibus_tag (0,device,0), 0); 171c7483249SStefan Eßer if (id != 0xfffffffful) { 172c7483249SStefan Eßer if (bootverbose) printf ("is there (id=%08lx)\n", id); 173a3adc4f8SStefan Eßer return 1; 174a3adc4f8SStefan Eßer } 17577b57314SStefan Eßer } 176c7483249SStefan Eßer if (bootverbose) 177c7483249SStefan Eßer printf ("-- nothing found\n"); 178a3adc4f8SStefan Eßer return 0; 179a3adc4f8SStefan Eßer } 180d7ea35fcSStefan Eßer 1815b3f532eSStefan Eßer static void 1825b3f532eSStefan Eßer pcibus_setup (void) 183ac19f918SStefan Eßer { 184287911bdSStefan Eßer unsigned long mode1res,oldval1; 185287911bdSStefan Eßer unsigned char mode2res,oldval2; 1860847c06dSStefan Eßer 187287911bdSStefan Eßer oldval1 = inl (CONF1_ADDR_PORT); 188a3adc4f8SStefan Eßer 18977b57314SStefan Eßer if (bootverbose) { 190287911bdSStefan Eßer printf ("pcibus_setup(1):\tmode1 addr port (0x0cf8) is 0x%08lx\n", oldval1); 191a3adc4f8SStefan Eßer } 192a3adc4f8SStefan Eßer 193ac19f918SStefan Eßer /*--------------------------------------- 19477b57314SStefan Eßer ** Assume configuration mechanism 1 for now ... 19577b57314SStefan Eßer **--------------------------------------- 19677b57314SStefan Eßer */ 19777b57314SStefan Eßer 198287911bdSStefan Eßer if ((oldval1 & CONF1_ENABLE) == 0) { 199287911bdSStefan Eßer 20077b57314SStefan Eßer pci_mechanism = 1; 20177b57314SStefan Eßer pci_maxdevice = 32; 20277b57314SStefan Eßer 20377b57314SStefan Eßer outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 20477b57314SStefan Eßer outb (CONF1_ADDR_PORT +3, 0); 20577b57314SStefan Eßer mode1res = inl (CONF1_ADDR_PORT); 206287911bdSStefan Eßer outl (CONF1_ADDR_PORT, oldval1); 20777b57314SStefan Eßer 20877b57314SStefan Eßer if (bootverbose) 209287911bdSStefan Eßer printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n", 21077b57314SStefan Eßer mode1res, CONF1_ENABLE_CHK); 21177b57314SStefan Eßer 21277b57314SStefan Eßer if (mode1res) { 21377b57314SStefan Eßer if (pcibus_check()) 21477b57314SStefan Eßer return; 21577b57314SStefan Eßer }; 21677b57314SStefan Eßer 21777b57314SStefan Eßer outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 21877b57314SStefan Eßer mode1res = inl(CONF1_ADDR_PORT); 219287911bdSStefan Eßer outl (CONF1_ADDR_PORT, oldval1); 22077b57314SStefan Eßer 22177b57314SStefan Eßer if (bootverbose) 222287911bdSStefan Eßer printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n", 22377b57314SStefan Eßer mode1res, CONF1_ENABLE_CHK1); 22477b57314SStefan Eßer 225c7483249SStefan Eßer if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 22677b57314SStefan Eßer if (pcibus_check()) 22777b57314SStefan Eßer return; 22877b57314SStefan Eßer }; 229287911bdSStefan Eßer } 23077b57314SStefan Eßer 23177b57314SStefan Eßer /*--------------------------------------- 23277b57314SStefan Eßer ** Try configuration mechanism 2 ... 23377b57314SStefan Eßer **--------------------------------------- 23477b57314SStefan Eßer */ 23577b57314SStefan Eßer 236287911bdSStefan Eßer oldval2 = inb (CONF2_ENABLE_PORT); 237287911bdSStefan Eßer 238287911bdSStefan Eßer if (bootverbose) { 239287911bdSStefan Eßer printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2); 240287911bdSStefan Eßer } 241287911bdSStefan Eßer 242287911bdSStefan Eßer if ((oldval2 & 0xf0) == 0) { 243c7483249SStefan Eßer 24477b57314SStefan Eßer pci_mechanism = 2; 24577b57314SStefan Eßer pci_maxdevice = 16; 24677b57314SStefan Eßer 247287911bdSStefan Eßer outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 248287911bdSStefan Eßer mode2res = inb(CONF2_ENABLE_PORT); 249287911bdSStefan Eßer outb (CONF2_ENABLE_PORT, oldval2); 250287911bdSStefan Eßer 251287911bdSStefan Eßer if (bootverbose) 252287911bdSStefan Eßer printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n", 253287911bdSStefan Eßer mode2res, CONF2_ENABLE_CHK); 254287911bdSStefan Eßer 255287911bdSStefan Eßer if (mode2res == CONF2_ENABLE_RES) { 256287911bdSStefan Eßer if (bootverbose) 257287911bdSStefan Eßer printf ("pcibus_setup(2a):\tnow trying mechanism 2\n"); 258287911bdSStefan Eßer 25977b57314SStefan Eßer if (pcibus_check()) 26077b57314SStefan Eßer return; 261287911bdSStefan Eßer } 262287911bdSStefan Eßer } 26377b57314SStefan Eßer 26477b57314SStefan Eßer /*--------------------------------------- 265cda67911SStefan Eßer ** No PCI bus host bridge found 266ac19f918SStefan Eßer **--------------------------------------- 267ac19f918SStefan Eßer */ 268cda67911SStefan Eßer 269cda67911SStefan Eßer pci_mechanism = 0; 270cda67911SStefan Eßer pci_maxdevice = 0; 271ac19f918SStefan Eßer } 2725b3f532eSStefan Eßer 273ac19f918SStefan Eßer /*-------------------------------------------------------------------- 274ac19f918SStefan Eßer ** 275ac19f918SStefan Eßer ** Build a pcitag from bus, device and function number 276ac19f918SStefan Eßer ** 277ac19f918SStefan Eßer **-------------------------------------------------------------------- 278ac19f918SStefan Eßer */ 279ac19f918SStefan Eßer 280ac19f918SStefan Eßer static pcici_t 281ac19f918SStefan Eßer pcibus_tag (unsigned char bus, unsigned char device, unsigned char func) 282ac19f918SStefan Eßer { 283ac19f918SStefan Eßer pcici_t tag; 284ac19f918SStefan Eßer 285ac19f918SStefan Eßer tag.cfg1 = 0; 286ac19f918SStefan Eßer if (func >= 8) return tag; 287ac19f918SStefan Eßer 2885b3f532eSStefan Eßer switch (pci_mechanism) { 289ac19f918SStefan Eßer 290ac19f918SStefan Eßer case 1: 2912d144186SStefan Eßer if (device < 32) { 292ac19f918SStefan Eßer tag.cfg1 = CONF1_ENABLE 293ac19f918SStefan Eßer | (((u_long) bus ) << 16ul) 294ac19f918SStefan Eßer | (((u_long) device) << 11ul) 295ac19f918SStefan Eßer | (((u_long) func ) << 8ul); 2962d144186SStefan Eßer } 297ac19f918SStefan Eßer break; 298ac19f918SStefan Eßer case 2: 2992d144186SStefan Eßer if (device < 16) { 300ac19f918SStefan Eßer tag.cfg2.port = 0xc000 | (device << 8ul); 3012d144186SStefan Eßer tag.cfg2.enable = 0xf0 | (func << 1ul); 302ac19f918SStefan Eßer tag.cfg2.forward = bus; 3032d144186SStefan Eßer } 304ac19f918SStefan Eßer break; 305ac19f918SStefan Eßer }; 306ac19f918SStefan Eßer return tag; 307ac19f918SStefan Eßer } 3085b3f532eSStefan Eßer 3095b3f532eSStefan Eßer static pcici_t 3105b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func) 3115b3f532eSStefan Eßer { 3125b3f532eSStefan Eßer switch (pci_mechanism) { 3135b3f532eSStefan Eßer 3145b3f532eSStefan Eßer case 1: 3155b3f532eSStefan Eßer tag.cfg1 &= ~0x700ul; 3165b3f532eSStefan Eßer tag.cfg1 |= (((u_long) func) << 8ul); 3175b3f532eSStefan Eßer break; 3185b3f532eSStefan Eßer case 2: 3192d144186SStefan Eßer tag.cfg2.enable = 0xf0 | (func << 1ul); 3205b3f532eSStefan Eßer break; 3215b3f532eSStefan Eßer }; 3225b3f532eSStefan Eßer return tag; 3235b3f532eSStefan Eßer } 3245b3f532eSStefan Eßer 325ac19f918SStefan Eßer /*-------------------------------------------------------------------- 326ac19f918SStefan Eßer ** 327ac19f918SStefan Eßer ** Read register from configuration space. 328ac19f918SStefan Eßer ** 329ac19f918SStefan Eßer **-------------------------------------------------------------------- 330ac19f918SStefan Eßer */ 331ac19f918SStefan Eßer 332ac19f918SStefan Eßer static u_long 333ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg) 334ac19f918SStefan Eßer { 335ac19f918SStefan Eßer u_long addr, data = 0; 336ac19f918SStefan Eßer 337ac19f918SStefan Eßer if (!tag.cfg1) return (0xfffffffful); 338ac19f918SStefan Eßer 3395b3f532eSStefan Eßer switch (pci_mechanism) { 340ac19f918SStefan Eßer 341ac19f918SStefan Eßer case 1: 342ac19f918SStefan Eßer addr = tag.cfg1 | (reg & 0xfc); 343ac19f918SStefan Eßer #ifdef PCI_DEBUG 344ac19f918SStefan Eßer printf ("pci_conf_read(1): addr=%x ", addr); 345ac19f918SStefan Eßer #endif 346ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, addr); 347ac19f918SStefan Eßer data = inl (CONF1_DATA_PORT); 348ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, 0 ); 349ac19f918SStefan Eßer break; 350ac19f918SStefan Eßer 351ac19f918SStefan Eßer case 2: 352ac19f918SStefan Eßer addr = tag.cfg2.port | (reg & 0xfc); 353ac19f918SStefan Eßer #ifdef PCI_DEBUG 354ac19f918SStefan Eßer printf ("pci_conf_read(2): addr=%x ", addr); 355ac19f918SStefan Eßer #endif 356ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT , tag.cfg2.enable ); 357ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 358ac19f918SStefan Eßer 359ac19f918SStefan Eßer data = inl ((u_short) addr); 360ac19f918SStefan Eßer 361ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, 0); 362ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 363ac19f918SStefan Eßer break; 364ac19f918SStefan Eßer }; 365ac19f918SStefan Eßer 366ac19f918SStefan Eßer #ifdef PCI_DEBUG 367ac19f918SStefan Eßer printf ("data=%x\n", data); 368ac19f918SStefan Eßer #endif 369ac19f918SStefan Eßer 370ac19f918SStefan Eßer return (data); 371ac19f918SStefan Eßer } 3725b3f532eSStefan Eßer 373ac19f918SStefan Eßer /*-------------------------------------------------------------------- 374ac19f918SStefan Eßer ** 375ac19f918SStefan Eßer ** Write register into configuration space. 376ac19f918SStefan Eßer ** 377ac19f918SStefan Eßer **-------------------------------------------------------------------- 378ac19f918SStefan Eßer */ 379ac19f918SStefan Eßer 380ac19f918SStefan Eßer static void 381ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data) 382ac19f918SStefan Eßer { 383ac19f918SStefan Eßer u_long addr; 384ac19f918SStefan Eßer 385ac19f918SStefan Eßer if (!tag.cfg1) return; 386ac19f918SStefan Eßer 3875b3f532eSStefan Eßer switch (pci_mechanism) { 388ac19f918SStefan Eßer 389ac19f918SStefan Eßer case 1: 390ac19f918SStefan Eßer addr = tag.cfg1 | (reg & 0xfc); 391ac19f918SStefan Eßer #ifdef PCI_DEBUG 392ac19f918SStefan Eßer printf ("pci_conf_write(1): addr=%x data=%x\n", 393ac19f918SStefan Eßer addr, data); 394ac19f918SStefan Eßer #endif 395ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, addr); 396ac19f918SStefan Eßer outl (CONF1_DATA_PORT, data); 397ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, 0 ); 398ac19f918SStefan Eßer break; 399ac19f918SStefan Eßer 400ac19f918SStefan Eßer case 2: 401ac19f918SStefan Eßer addr = tag.cfg2.port | (reg & 0xfc); 402ac19f918SStefan Eßer #ifdef PCI_DEBUG 403ac19f918SStefan Eßer printf ("pci_conf_write(2): addr=%x data=%x\n", 404ac19f918SStefan Eßer addr, data); 405ac19f918SStefan Eßer #endif 406ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, tag.cfg2.enable); 407ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 408ac19f918SStefan Eßer 409ac19f918SStefan Eßer outl ((u_short) addr, data); 410ac19f918SStefan Eßer 411ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, 0); 412ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 413ac19f918SStefan Eßer break; 414ac19f918SStefan Eßer }; 415ac19f918SStefan Eßer } 4165b3f532eSStefan Eßer 417ac19f918SStefan Eßer /*----------------------------------------------------------------------- 418ac19f918SStefan Eßer ** 419ac19f918SStefan Eßer ** Register an interupt handler for a pci device. 420ac19f918SStefan Eßer ** 421ac19f918SStefan Eßer **----------------------------------------------------------------------- 422ac19f918SStefan Eßer */ 423ac19f918SStefan Eßer 424ac19f918SStefan Eßer static int 4255b3f532eSStefan Eßer pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr) 426ac19f918SStefan Eßer { 4275b3f532eSStefan Eßer int result; 4285b3f532eSStefan Eßer result = register_intr( 429ac19f918SStefan Eßer irq, /* isa irq */ 430ac19f918SStefan Eßer 0, /* deviced?? */ 431ac19f918SStefan Eßer 0, /* flags? */ 432ac19f918SStefan Eßer (inthand2_t*) func, /* handler */ 433ac19f918SStefan Eßer maskptr, /* mask pointer */ 4345b3f532eSStefan Eßer arg); /* handler arg */ 435ac19f918SStefan Eßer 4365b3f532eSStefan Eßer if (result) { 4375b3f532eSStefan Eßer printf ("@@@ pcibus_ihandler_attach: result=%d\n", result); 4385b3f532eSStefan Eßer return (result); 439ac19f918SStefan Eßer }; 4405b3f532eSStefan Eßer update_intr_masks(); 441ac19f918SStefan Eßer 4425b3f532eSStefan Eßer INTREN ((1ul<<irq)); 4435b3f532eSStefan Eßer return (0); 4445b3f532eSStefan Eßer } 445ac19f918SStefan Eßer 4465b3f532eSStefan Eßer static int 4475b3f532eSStefan Eßer pcibus_ihandler_detach (int irq, void(*func)()) 4485b3f532eSStefan Eßer { 4495b3f532eSStefan Eßer int result; 4505b3f532eSStefan Eßer 4515b3f532eSStefan Eßer INTRDIS ((1ul<<irq)); 4525b3f532eSStefan Eßer 4535b3f532eSStefan Eßer result = unregister_intr (irq, (inthand2_t*) func); 4545b3f532eSStefan Eßer 4555b3f532eSStefan Eßer if (result) 4565b3f532eSStefan Eßer printf ("@@@ pcibus_ihandler_detach: result=%d\n", result); 4575b3f532eSStefan Eßer 4585b3f532eSStefan Eßer update_intr_masks(); 4595b3f532eSStefan Eßer 4605b3f532eSStefan Eßer return (result); 4615b3f532eSStefan Eßer } 4625b3f532eSStefan Eßer 4635b3f532eSStefan Eßer static int 4645b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr) 4655b3f532eSStefan Eßer { 4665b3f532eSStefan Eßer unsigned mask; 4675b3f532eSStefan Eßer 4685b3f532eSStefan Eßer if (!maskptr) return (0); 4695b3f532eSStefan Eßer 4705b3f532eSStefan Eßer mask = 1ul << irq; 4715b3f532eSStefan Eßer 4725b3f532eSStefan Eßer if (*maskptr & mask) 4735b3f532eSStefan Eßer return (-1); 4745b3f532eSStefan Eßer 4755b3f532eSStefan Eßer INTRMASK (*maskptr, mask); 4765b3f532eSStefan Eßer update_intr_masks(); 4775b3f532eSStefan Eßer 4785b3f532eSStefan Eßer return (0); 4795b3f532eSStefan Eßer } 4805b3f532eSStefan Eßer 4815b3f532eSStefan Eßer static int 4825b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr) 4835b3f532eSStefan Eßer { 4845b3f532eSStefan Eßer unsigned mask; 4855b3f532eSStefan Eßer 4865b3f532eSStefan Eßer if (!maskptr) return (0); 4875b3f532eSStefan Eßer 4885b3f532eSStefan Eßer mask = 1ul << irq; 4895b3f532eSStefan Eßer 4905b3f532eSStefan Eßer if (! (*maskptr & mask)) 4915b3f532eSStefan Eßer return (-1); 4925b3f532eSStefan Eßer 4935b3f532eSStefan Eßer *maskptr &= ~mask; 4945b3f532eSStefan Eßer update_intr_masks(); 4955b3f532eSStefan Eßer 4965b3f532eSStefan Eßer return (0); 497ac19f918SStefan Eßer } 498