1ac19f918SStefan Eßer /************************************************************************** 2ac19f918SStefan Eßer ** 381cf5d7aSStefan Eßer ** $Id: pcibus.c,v 1.31 1997/02/22 09:36:58 peter 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 38a680ab75SBruce Evans #include "vector.h" 39a680ab75SBruce Evans 40550f8550SBruce Evans #include <sys/param.h> 41550f8550SBruce Evans #include <sys/systm.h> 42550f8550SBruce Evans #include <sys/kernel.h> 43550f8550SBruce Evans 44550f8550SBruce Evans #include <i386/isa/icu.h> 45ac19f918SStefan Eßer #include <i386/isa/isa_device.h> 46ac19f918SStefan Eßer 47ac19f918SStefan Eßer #include <pci/pcivar.h> 48ac19f918SStefan Eßer #include <pci/pcireg.h> 49ac19f918SStefan Eßer #include <pci/pcibus.h> 50ac19f918SStefan Eßer 51ac19f918SStefan Eßer /*----------------------------------------------------------------- 52ac19f918SStefan Eßer ** 53ac19f918SStefan Eßer ** The following functions are provided by the pci bios. 54ac19f918SStefan Eßer ** They are used only by the pci configuration. 55ac19f918SStefan Eßer ** 565b3f532eSStefan Eßer ** pcibus_setup(): 57ac19f918SStefan Eßer ** Probes for a pci system. 585b3f532eSStefan Eßer ** Sets pci_maxdevice and pci_mechanism. 59ac19f918SStefan Eßer ** 60ac19f918SStefan Eßer ** pcibus_tag(): 615b3f532eSStefan Eßer ** Creates a handle for pci configuration space access. 625b3f532eSStefan Eßer ** This handle is given to the read/write functions. 635b3f532eSStefan Eßer ** 645b3f532eSStefan Eßer ** pcibus_ftag(): 655b3f532eSStefan Eßer ** Creates a modified handle. 66ac19f918SStefan Eßer ** 67ac19f918SStefan Eßer ** pcibus_read(): 68ac19f918SStefan Eßer ** Read a long word from the pci configuration space. 69ac19f918SStefan Eßer ** Requires a tag (from pcitag) and the register 70ac19f918SStefan Eßer ** number (should be a long word alligned one). 71ac19f918SStefan Eßer ** 72ac19f918SStefan Eßer ** pcibus_write(): 73ac19f918SStefan Eßer ** Writes a long word to the pci configuration space. 74ac19f918SStefan Eßer ** Requires a tag (from pcitag), the register number 75ac19f918SStefan Eßer ** (should be a long word alligned one), and a value. 76ac19f918SStefan Eßer ** 77ac19f918SStefan Eßer ** pcibus_regirq(): 78ac19f918SStefan Eßer ** Register an interupt handler for a pci device. 79ac19f918SStefan Eßer ** Requires a tag (from pcitag), the register number 80ac19f918SStefan Eßer ** (should be a long word alligned one), and a value. 81ac19f918SStefan Eßer ** 82ac19f918SStefan Eßer **----------------------------------------------------------------- 83ac19f918SStefan Eßer */ 84ac19f918SStefan Eßer 85a3adc4f8SStefan Eßer static int 86a3adc4f8SStefan Eßer pcibus_check (void); 87a3adc4f8SStefan Eßer 885b3f532eSStefan Eßer static void 895b3f532eSStefan Eßer pcibus_setup (void); 90ac19f918SStefan Eßer 91ac19f918SStefan Eßer static pcici_t 92ac19f918SStefan Eßer pcibus_tag (u_char bus, u_char device, u_char func); 93ac19f918SStefan Eßer 945b3f532eSStefan Eßer static pcici_t 955b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func); 965b3f532eSStefan Eßer 97ac19f918SStefan Eßer static u_long 98ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg); 99ac19f918SStefan Eßer 100ac19f918SStefan Eßer static void 101ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data); 102ac19f918SStefan Eßer 103ac19f918SStefan Eßer static int 1046ea3e9d8SBruce Evans pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned* maskptr); 1055b3f532eSStefan Eßer 1065b3f532eSStefan Eßer static int 1076ea3e9d8SBruce Evans pcibus_ihandler_detach (int irq, inthand2_t *func); 1085b3f532eSStefan Eßer 1095b3f532eSStefan Eßer static int 1105b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr); 1115b3f532eSStefan Eßer 1125b3f532eSStefan Eßer static int 1135b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr); 114ac19f918SStefan Eßer 1156f4e0bebSPoul-Henning Kamp static struct pcibus i386pci = { 116ac19f918SStefan Eßer "pci", 1175b3f532eSStefan Eßer pcibus_setup, 118ac19f918SStefan Eßer pcibus_tag, 1195b3f532eSStefan Eßer pcibus_ftag, 120ac19f918SStefan Eßer pcibus_read, 121ac19f918SStefan Eßer pcibus_write, 1225b3f532eSStefan Eßer pcibus_ihandler_attach, 1235b3f532eSStefan Eßer pcibus_ihandler_detach, 1245b3f532eSStefan Eßer pcibus_imask_include, 1255b3f532eSStefan Eßer pcibus_imask_exclude, 126ac19f918SStefan Eßer }; 127ac19f918SStefan Eßer 128ac19f918SStefan Eßer /* 129ac19f918SStefan Eßer ** Announce structure to generic driver 130ac19f918SStefan Eßer */ 131ac19f918SStefan Eßer 132ac19f918SStefan Eßer DATA_SET (pcibus_set, i386pci); 133ac19f918SStefan Eßer 134ac19f918SStefan Eßer /*-------------------------------------------------------------------- 135ac19f918SStefan Eßer ** 136ac19f918SStefan Eßer ** Determine configuration mode 137ac19f918SStefan Eßer ** 138ac19f918SStefan Eßer **-------------------------------------------------------------------- 139ac19f918SStefan Eßer */ 140ac19f918SStefan Eßer 141ac19f918SStefan Eßer 142ac19f918SStefan Eßer #define CONF1_ADDR_PORT 0x0cf8 143ac19f918SStefan Eßer #define CONF1_DATA_PORT 0x0cfc 144ac19f918SStefan Eßer 1452d144186SStefan Eßer #define CONF1_ENABLE 0x80000000ul 14677b57314SStefan Eßer #define CONF1_ENABLE_CHK 0x80000000ul 14721219d21SStefan Eßer #define CONF1_ENABLE_MSK 0x7ff00000ul 1480e2f699bSStefan Eßer #define CONF1_ENABLE_CHK1 0xff000001ul 149287911bdSStefan Eßer #define CONF1_ENABLE_MSK1 0x80000001ul 150a3adc4f8SStefan Eßer #define CONF1_ENABLE_RES1 0x80000000ul 151ac19f918SStefan Eßer 152ac19f918SStefan Eßer #define CONF2_ENABLE_PORT 0x0cf8 153e30f0011SSatoshi Asami #ifdef PC98 154e30f0011SSatoshi Asami #define CONF2_FORWARD_PORT 0x0cf9 155e30f0011SSatoshi Asami #else 156ac19f918SStefan Eßer #define CONF2_FORWARD_PORT 0x0cfa 157e30f0011SSatoshi Asami #endif 158ac19f918SStefan Eßer 1592d144186SStefan Eßer #define CONF2_ENABLE_CHK 0x0e 1602d144186SStefan Eßer #define CONF2_ENABLE_RES 0x0e 161ac19f918SStefan Eßer 162a3adc4f8SStefan Eßer static int 163a3adc4f8SStefan Eßer pcibus_check (void) 164a3adc4f8SStefan Eßer { 165a3adc4f8SStefan Eßer u_char device; 166a3adc4f8SStefan Eßer 16777b57314SStefan Eßer if (bootverbose) printf ("pcibus_check:\tdevice "); 16877b57314SStefan Eßer 169a3adc4f8SStefan Eßer for (device = 0; device < pci_maxdevice; device++) { 17081cf5d7aSStefan Eßer unsigned long id, class, header; 171c7483249SStefan Eßer if (bootverbose) 172c7483249SStefan Eßer printf ("%d ", device); 173c7483249SStefan Eßer id = pcibus_read (pcibus_tag (0,device,0), 0); 17481cf5d7aSStefan Eßer if ((id == 0) || (id == 0xfffffffful)) 17581cf5d7aSStefan Eßer continue; 17681cf5d7aSStefan Eßer 17781cf5d7aSStefan Eßer class = pcibus_read (pcibus_tag (0,device,0), 8); 17881cf5d7aSStefan Eßer if (bootverbose) 17981cf5d7aSStefan Eßer printf ("[class=%x] ", class >> 8); 18081cf5d7aSStefan Eßer if ((class & 0xfff0ff00) != 0x06000000) 18181cf5d7aSStefan Eßer continue; 18281cf5d7aSStefan Eßer 18381cf5d7aSStefan Eßer header = pcibus_read (pcibus_tag (0,device,0), 12); 18481cf5d7aSStefan Eßer if (bootverbose) 18581cf5d7aSStefan Eßer printf ("[hdr=%x] ", (header >> 16) & 0xff); 18681cf5d7aSStefan Eßer if ((header & 0x007e0000) != 0) 18781cf5d7aSStefan Eßer continue; 18881cf5d7aSStefan Eßer 189c7483249SStefan Eßer if (bootverbose) printf ("is there (id=%08lx)\n", id); 190a3adc4f8SStefan Eßer return 1; 191a3adc4f8SStefan Eßer } 192c7483249SStefan Eßer if (bootverbose) 193c7483249SStefan Eßer printf ("-- nothing found\n"); 194a3adc4f8SStefan Eßer return 0; 195a3adc4f8SStefan Eßer } 196d7ea35fcSStefan Eßer 1975b3f532eSStefan Eßer static void 1985b3f532eSStefan Eßer pcibus_setup (void) 199ac19f918SStefan Eßer { 200287911bdSStefan Eßer unsigned long mode1res,oldval1; 201287911bdSStefan Eßer unsigned char mode2res,oldval2; 2020847c06dSStefan Eßer 203287911bdSStefan Eßer oldval1 = inl (CONF1_ADDR_PORT); 204a3adc4f8SStefan Eßer 20577b57314SStefan Eßer if (bootverbose) { 206287911bdSStefan Eßer printf ("pcibus_setup(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", oldval1); 207a3adc4f8SStefan Eßer } 208a3adc4f8SStefan Eßer 209ac19f918SStefan Eßer /*--------------------------------------- 21077b57314SStefan Eßer ** Assume configuration mechanism 1 for now ... 21177b57314SStefan Eßer **--------------------------------------- 21277b57314SStefan Eßer */ 21377b57314SStefan Eßer 2140e2f699bSStefan Eßer if ((oldval1 & CONF1_ENABLE_MSK) == 0) { 215287911bdSStefan Eßer 21677b57314SStefan Eßer pci_mechanism = 1; 21777b57314SStefan Eßer pci_maxdevice = 32; 21877b57314SStefan Eßer 21977b57314SStefan Eßer outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 22077b57314SStefan Eßer outb (CONF1_ADDR_PORT +3, 0); 22177b57314SStefan Eßer mode1res = inl (CONF1_ADDR_PORT); 222287911bdSStefan Eßer outl (CONF1_ADDR_PORT, oldval1); 22377b57314SStefan Eßer 22477b57314SStefan Eßer if (bootverbose) 225287911bdSStefan Eßer printf ("pcibus_setup(1a):\tmode1res=0x%08lx (0x%08lx)\n", 22677b57314SStefan Eßer mode1res, CONF1_ENABLE_CHK); 22777b57314SStefan Eßer 22877b57314SStefan Eßer if (mode1res) { 22977b57314SStefan Eßer if (pcibus_check()) 23077b57314SStefan Eßer return; 23177b57314SStefan Eßer }; 23277b57314SStefan Eßer 23377b57314SStefan Eßer outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 23477b57314SStefan Eßer mode1res = inl(CONF1_ADDR_PORT); 235287911bdSStefan Eßer outl (CONF1_ADDR_PORT, oldval1); 23677b57314SStefan Eßer 23777b57314SStefan Eßer if (bootverbose) 238287911bdSStefan Eßer printf ("pcibus_setup(1b):\tmode1res=0x%08lx (0x%08lx)\n", 23977b57314SStefan Eßer mode1res, CONF1_ENABLE_CHK1); 24077b57314SStefan Eßer 241c7483249SStefan Eßer if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 24277b57314SStefan Eßer if (pcibus_check()) 24377b57314SStefan Eßer return; 24477b57314SStefan Eßer }; 245287911bdSStefan Eßer } 24677b57314SStefan Eßer 24777b57314SStefan Eßer /*--------------------------------------- 24877b57314SStefan Eßer ** Try configuration mechanism 2 ... 24977b57314SStefan Eßer **--------------------------------------- 25077b57314SStefan Eßer */ 25177b57314SStefan Eßer 252287911bdSStefan Eßer oldval2 = inb (CONF2_ENABLE_PORT); 253287911bdSStefan Eßer 254287911bdSStefan Eßer if (bootverbose) { 255287911bdSStefan Eßer printf ("pcibus_setup(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", oldval2); 256287911bdSStefan Eßer } 257287911bdSStefan Eßer 258287911bdSStefan Eßer if ((oldval2 & 0xf0) == 0) { 259c7483249SStefan Eßer 26077b57314SStefan Eßer pci_mechanism = 2; 26177b57314SStefan Eßer pci_maxdevice = 16; 26277b57314SStefan Eßer 263287911bdSStefan Eßer outb (CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 264287911bdSStefan Eßer mode2res = inb(CONF2_ENABLE_PORT); 265287911bdSStefan Eßer outb (CONF2_ENABLE_PORT, oldval2); 266287911bdSStefan Eßer 267287911bdSStefan Eßer if (bootverbose) 268287911bdSStefan Eßer printf ("pcibus_setup(2a):\tmode2res=0x%02x (0x%02x)\n", 269287911bdSStefan Eßer mode2res, CONF2_ENABLE_CHK); 270287911bdSStefan Eßer 271287911bdSStefan Eßer if (mode2res == CONF2_ENABLE_RES) { 272287911bdSStefan Eßer if (bootverbose) 273287911bdSStefan Eßer printf ("pcibus_setup(2a):\tnow trying mechanism 2\n"); 274287911bdSStefan Eßer 27577b57314SStefan Eßer if (pcibus_check()) 27677b57314SStefan Eßer return; 277287911bdSStefan Eßer } 278287911bdSStefan Eßer } 27977b57314SStefan Eßer 28077b57314SStefan Eßer /*--------------------------------------- 281cda67911SStefan Eßer ** No PCI bus host bridge found 282ac19f918SStefan Eßer **--------------------------------------- 283ac19f918SStefan Eßer */ 284cda67911SStefan Eßer 285cda67911SStefan Eßer pci_mechanism = 0; 286cda67911SStefan Eßer pci_maxdevice = 0; 287ac19f918SStefan Eßer } 2885b3f532eSStefan Eßer 289ac19f918SStefan Eßer /*-------------------------------------------------------------------- 290ac19f918SStefan Eßer ** 291ac19f918SStefan Eßer ** Build a pcitag from bus, device and function number 292ac19f918SStefan Eßer ** 293ac19f918SStefan Eßer **-------------------------------------------------------------------- 294ac19f918SStefan Eßer */ 295ac19f918SStefan Eßer 296ac19f918SStefan Eßer static pcici_t 297ac19f918SStefan Eßer pcibus_tag (unsigned char bus, unsigned char device, unsigned char func) 298ac19f918SStefan Eßer { 299ac19f918SStefan Eßer pcici_t tag; 300ac19f918SStefan Eßer 301ac19f918SStefan Eßer tag.cfg1 = 0; 302ac19f918SStefan Eßer if (func >= 8) return tag; 303ac19f918SStefan Eßer 3045b3f532eSStefan Eßer switch (pci_mechanism) { 305ac19f918SStefan Eßer 306ac19f918SStefan Eßer case 1: 3072d144186SStefan Eßer if (device < 32) { 308ac19f918SStefan Eßer tag.cfg1 = CONF1_ENABLE 309ac19f918SStefan Eßer | (((u_long) bus ) << 16ul) 310ac19f918SStefan Eßer | (((u_long) device) << 11ul) 311ac19f918SStefan Eßer | (((u_long) func ) << 8ul); 3122d144186SStefan Eßer } 313ac19f918SStefan Eßer break; 314ac19f918SStefan Eßer case 2: 3152d144186SStefan Eßer if (device < 16) { 316ac19f918SStefan Eßer tag.cfg2.port = 0xc000 | (device << 8ul); 3172d144186SStefan Eßer tag.cfg2.enable = 0xf0 | (func << 1ul); 318ac19f918SStefan Eßer tag.cfg2.forward = bus; 3192d144186SStefan Eßer } 320ac19f918SStefan Eßer break; 321ac19f918SStefan Eßer }; 322ac19f918SStefan Eßer return tag; 323ac19f918SStefan Eßer } 3245b3f532eSStefan Eßer 3255b3f532eSStefan Eßer static pcici_t 3265b3f532eSStefan Eßer pcibus_ftag (pcici_t tag, u_char func) 3275b3f532eSStefan Eßer { 3285b3f532eSStefan Eßer switch (pci_mechanism) { 3295b3f532eSStefan Eßer 3305b3f532eSStefan Eßer case 1: 3315b3f532eSStefan Eßer tag.cfg1 &= ~0x700ul; 3325b3f532eSStefan Eßer tag.cfg1 |= (((u_long) func) << 8ul); 3335b3f532eSStefan Eßer break; 3345b3f532eSStefan Eßer case 2: 3352d144186SStefan Eßer tag.cfg2.enable = 0xf0 | (func << 1ul); 3365b3f532eSStefan Eßer break; 3375b3f532eSStefan Eßer }; 3385b3f532eSStefan Eßer return tag; 3395b3f532eSStefan Eßer } 3405b3f532eSStefan Eßer 341ac19f918SStefan Eßer /*-------------------------------------------------------------------- 342ac19f918SStefan Eßer ** 343ac19f918SStefan Eßer ** Read register from configuration space. 344ac19f918SStefan Eßer ** 345ac19f918SStefan Eßer **-------------------------------------------------------------------- 346ac19f918SStefan Eßer */ 347ac19f918SStefan Eßer 348ac19f918SStefan Eßer static u_long 349ac19f918SStefan Eßer pcibus_read (pcici_t tag, u_long reg) 350ac19f918SStefan Eßer { 351ac19f918SStefan Eßer u_long addr, data = 0; 352ac19f918SStefan Eßer 353ac19f918SStefan Eßer if (!tag.cfg1) return (0xfffffffful); 354ac19f918SStefan Eßer 3555b3f532eSStefan Eßer switch (pci_mechanism) { 356ac19f918SStefan Eßer 357ac19f918SStefan Eßer case 1: 358ac19f918SStefan Eßer addr = tag.cfg1 | (reg & 0xfc); 359ac19f918SStefan Eßer #ifdef PCI_DEBUG 360ac19f918SStefan Eßer printf ("pci_conf_read(1): addr=%x ", addr); 361ac19f918SStefan Eßer #endif 362ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, addr); 363ac19f918SStefan Eßer data = inl (CONF1_DATA_PORT); 364ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, 0 ); 365ac19f918SStefan Eßer break; 366ac19f918SStefan Eßer 367ac19f918SStefan Eßer case 2: 368ac19f918SStefan Eßer addr = tag.cfg2.port | (reg & 0xfc); 369ac19f918SStefan Eßer #ifdef PCI_DEBUG 370ac19f918SStefan Eßer printf ("pci_conf_read(2): addr=%x ", addr); 371ac19f918SStefan Eßer #endif 372ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT , tag.cfg2.enable ); 373ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 374ac19f918SStefan Eßer 375ac19f918SStefan Eßer data = inl ((u_short) addr); 376ac19f918SStefan Eßer 377ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, 0); 378ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 379ac19f918SStefan Eßer break; 380ac19f918SStefan Eßer }; 381ac19f918SStefan Eßer 382ac19f918SStefan Eßer #ifdef PCI_DEBUG 383ac19f918SStefan Eßer printf ("data=%x\n", data); 384ac19f918SStefan Eßer #endif 385ac19f918SStefan Eßer 386ac19f918SStefan Eßer return (data); 387ac19f918SStefan Eßer } 3885b3f532eSStefan Eßer 389ac19f918SStefan Eßer /*-------------------------------------------------------------------- 390ac19f918SStefan Eßer ** 391ac19f918SStefan Eßer ** Write register into configuration space. 392ac19f918SStefan Eßer ** 393ac19f918SStefan Eßer **-------------------------------------------------------------------- 394ac19f918SStefan Eßer */ 395ac19f918SStefan Eßer 396ac19f918SStefan Eßer static void 397ac19f918SStefan Eßer pcibus_write (pcici_t tag, u_long reg, u_long data) 398ac19f918SStefan Eßer { 399ac19f918SStefan Eßer u_long addr; 400ac19f918SStefan Eßer 401ac19f918SStefan Eßer if (!tag.cfg1) return; 402ac19f918SStefan Eßer 4035b3f532eSStefan Eßer switch (pci_mechanism) { 404ac19f918SStefan Eßer 405ac19f918SStefan Eßer case 1: 406ac19f918SStefan Eßer addr = tag.cfg1 | (reg & 0xfc); 407ac19f918SStefan Eßer #ifdef PCI_DEBUG 408ac19f918SStefan Eßer printf ("pci_conf_write(1): addr=%x data=%x\n", 409ac19f918SStefan Eßer addr, data); 410ac19f918SStefan Eßer #endif 411ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, addr); 412ac19f918SStefan Eßer outl (CONF1_DATA_PORT, data); 413ac19f918SStefan Eßer outl (CONF1_ADDR_PORT, 0 ); 414ac19f918SStefan Eßer break; 415ac19f918SStefan Eßer 416ac19f918SStefan Eßer case 2: 417ac19f918SStefan Eßer addr = tag.cfg2.port | (reg & 0xfc); 418ac19f918SStefan Eßer #ifdef PCI_DEBUG 419ac19f918SStefan Eßer printf ("pci_conf_write(2): addr=%x data=%x\n", 420ac19f918SStefan Eßer addr, data); 421ac19f918SStefan Eßer #endif 422ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, tag.cfg2.enable); 423ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 424ac19f918SStefan Eßer 425ac19f918SStefan Eßer outl ((u_short) addr, data); 426ac19f918SStefan Eßer 427ac19f918SStefan Eßer outb (CONF2_ENABLE_PORT, 0); 428ac19f918SStefan Eßer outb (CONF2_FORWARD_PORT, 0); 429ac19f918SStefan Eßer break; 430ac19f918SStefan Eßer }; 431ac19f918SStefan Eßer } 4325b3f532eSStefan Eßer 433ac19f918SStefan Eßer /*----------------------------------------------------------------------- 434ac19f918SStefan Eßer ** 435ac19f918SStefan Eßer ** Register an interupt handler for a pci device. 436ac19f918SStefan Eßer ** 437ac19f918SStefan Eßer **----------------------------------------------------------------------- 438ac19f918SStefan Eßer */ 439ac19f918SStefan Eßer 440ac19f918SStefan Eßer static int 4416ea3e9d8SBruce Evans pcibus_ihandler_attach (int irq, inthand2_t *func, int arg, unsigned * maskptr) 442ac19f918SStefan Eßer { 443a680ab75SBruce Evans char buf[16]; 444a680ab75SBruce Evans char *cp; 445a680ab75SBruce Evans int free_id, id, result; 446a680ab75SBruce Evans 447a680ab75SBruce Evans sprintf(buf, "pci irq%d", irq); 448a680ab75SBruce Evans for (cp = intrnames, free_id = 0, id = 0; id < NR_DEVICES; id++) { 449a680ab75SBruce Evans if (strcmp(cp, buf) == 0) 450a680ab75SBruce Evans break; 451a680ab75SBruce Evans if (free_id <= 0 && strcmp(cp, "pci irqnn") == 0) 452a680ab75SBruce Evans free_id = id; 453a680ab75SBruce Evans while (*cp++ != '\0') 454a680ab75SBruce Evans ; 455a680ab75SBruce Evans } 456a680ab75SBruce Evans if (id == NR_DEVICES) { 457a680ab75SBruce Evans id = free_id; 458a680ab75SBruce Evans if (id == 0) { 459a680ab75SBruce Evans /* 460a680ab75SBruce Evans * All pci irq counters are in use, perhaps because 461a680ab75SBruce Evans * config is old so there aren't any. Abuse the 462a680ab75SBruce Evans * clk0 counter. 463a680ab75SBruce Evans */ 464a680ab75SBruce Evans printf ( 465a680ab75SBruce Evans "pcibus_ihandler_attach: counting pci irq%d's as clk0 irqs\n", 466a680ab75SBruce Evans irq); 467a680ab75SBruce Evans } 468a680ab75SBruce Evans } 4695b3f532eSStefan Eßer result = register_intr( 470ac19f918SStefan Eßer irq, /* isa irq */ 471a680ab75SBruce Evans id, /* device id */ 472ac19f918SStefan Eßer 0, /* flags? */ 4736ea3e9d8SBruce Evans func, /* handler */ 474ac19f918SStefan Eßer maskptr, /* mask pointer */ 4755b3f532eSStefan Eßer arg); /* handler arg */ 476ac19f918SStefan Eßer 4775b3f532eSStefan Eßer if (result) { 4785b3f532eSStefan Eßer printf ("@@@ pcibus_ihandler_attach: result=%d\n", result); 4795b3f532eSStefan Eßer return (result); 480ac19f918SStefan Eßer }; 4815b3f532eSStefan Eßer update_intr_masks(); 482ac19f918SStefan Eßer 4835b3f532eSStefan Eßer INTREN ((1ul<<irq)); 4845b3f532eSStefan Eßer return (0); 4855b3f532eSStefan Eßer } 486ac19f918SStefan Eßer 4875b3f532eSStefan Eßer static int 4886ea3e9d8SBruce Evans pcibus_ihandler_detach (int irq, inthand2_t *func) 4895b3f532eSStefan Eßer { 4905b3f532eSStefan Eßer int result; 4915b3f532eSStefan Eßer 4925b3f532eSStefan Eßer INTRDIS ((1ul<<irq)); 4935b3f532eSStefan Eßer 4946ea3e9d8SBruce Evans result = unregister_intr (irq, func); 4955b3f532eSStefan Eßer 4965b3f532eSStefan Eßer if (result) 4975b3f532eSStefan Eßer printf ("@@@ pcibus_ihandler_detach: result=%d\n", result); 4985b3f532eSStefan Eßer 4995b3f532eSStefan Eßer update_intr_masks(); 5005b3f532eSStefan Eßer 5015b3f532eSStefan Eßer return (result); 5025b3f532eSStefan Eßer } 5035b3f532eSStefan Eßer 5045b3f532eSStefan Eßer static int 5055b3f532eSStefan Eßer pcibus_imask_include (int irq, unsigned* maskptr) 5065b3f532eSStefan Eßer { 5075b3f532eSStefan Eßer unsigned mask; 5085b3f532eSStefan Eßer 5095b3f532eSStefan Eßer if (!maskptr) return (0); 5105b3f532eSStefan Eßer 5115b3f532eSStefan Eßer mask = 1ul << irq; 5125b3f532eSStefan Eßer 5135b3f532eSStefan Eßer if (*maskptr & mask) 5145b3f532eSStefan Eßer return (-1); 5155b3f532eSStefan Eßer 5165b3f532eSStefan Eßer INTRMASK (*maskptr, mask); 5175b3f532eSStefan Eßer update_intr_masks(); 5185b3f532eSStefan Eßer 5195b3f532eSStefan Eßer return (0); 5205b3f532eSStefan Eßer } 5215b3f532eSStefan Eßer 5225b3f532eSStefan Eßer static int 5235b3f532eSStefan Eßer pcibus_imask_exclude (int irq, unsigned* maskptr) 5245b3f532eSStefan Eßer { 5255b3f532eSStefan Eßer unsigned mask; 5265b3f532eSStefan Eßer 5275b3f532eSStefan Eßer if (!maskptr) return (0); 5285b3f532eSStefan Eßer 5295b3f532eSStefan Eßer mask = 1ul << irq; 5305b3f532eSStefan Eßer 5315b3f532eSStefan Eßer if (! (*maskptr & mask)) 5325b3f532eSStefan Eßer return (-1); 5335b3f532eSStefan Eßer 53462ce633dSNate Williams INTRUNMASK (*maskptr, mask); 5355b3f532eSStefan Eßer update_intr_masks(); 5365b3f532eSStefan Eßer 5375b3f532eSStefan Eßer return (0); 538ac19f918SStefan Eßer } 539