idtpci.c revision 256281
1155192Srwatson/* $NetBSD: idtpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */ 2155192Srwatson 3155192Srwatson/*- 4155192Srwatson * Copyright (c) 2007 David Young. 5155192Srwatson * Copyright (c) 2007 Oleskandr Tymoshenko. All rights reserved. 6155192Srwatson * 7155192Srwatson * Redistribution and use in source and binary forms, with or 8155192Srwatson * without modification, are permitted provided that the following 9155192Srwatson * conditions are met: 10155192Srwatson * 1. Redistributions of source code must retain the above copyright 11155192Srwatson * notice, this list of conditions and the following disclaimer. 12155192Srwatson * 2. Redistributions in binary form must reproduce the above 13155192Srwatson * copyright notice, this list of conditions and the following 14155192Srwatson * disclaimer in the documentation and/or other materials provided 15155192Srwatson * with the distribution. 16155192Srwatson * 3. The name of the author may not be used to endorse or promote 17155192Srwatson * products derived from this software without specific prior 18155192Srwatson * written permission. 19155192Srwatson * 20155192Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 21155192Srwatson * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22155192Srwatson * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23155192Srwatson * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 24155192Srwatson * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 25155192Srwatson * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26155192Srwatson * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 27155192Srwatson * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28155192Srwatson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 29155192Srwatson * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30155192Srwatson * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31155192Srwatson * OF SUCH DAMAGE. 32155192Srwatson */ 33159259Srwatson/*- 34155192Srwatson * Copyright (c) 2006 Itronix Inc. 35155192Srwatson * All rights reserved. 36155192Srwatson * 37155192Srwatson * Written by Garrett D'Amore for Itronix Inc. 38155192Srwatson * 39159259Srwatson * Redistribution and use in source and binary forms, with or without 40155192Srwatson * modification, are permitted provided that the following conditions 41155192Srwatson * are met: 42155192Srwatson * 1. Redistributions of source code must retain the above copyright 43155192Srwatson * notice, this list of conditions and the following disclaimer. 44155192Srwatson * 2. Redistributions in binary form must reproduce the above copyright 45155192Srwatson * notice, this list of conditions and the following disclaimer in the 46155192Srwatson * documentation and/or other materials provided with the distribution. 47155192Srwatson * 3. The name of Itronix Inc. may not be used to endorse 48155192Srwatson * or promote products derived from this software without specific 49155192Srwatson * prior written permission. 50155192Srwatson * 51155192Srwatson * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 52155192Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 53155192Srwatson * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 54155192Srwatson * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 55155192Srwatson * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 56155192Srwatson * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57155192Srwatson * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 58155192Srwatson * ON ANY THEORY OF LIABILITY, WHETHER IN 59155192Srwatson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60155192Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 61155192Srwatson * POSSIBILITY OF SUCH DAMAGE. 62155192Srwatson */ 63155192Srwatson 64155192Srwatson#include <sys/cdefs.h> 65155192Srwatson__FBSDID("$FreeBSD: stable/10/sys/mips/idt/idtpci.c 227843 2011-11-22 21:28:20Z marius $"); 66155192Srwatson 67155192Srwatson#include <sys/param.h> 68155192Srwatson#include <sys/systm.h> 69155192Srwatson 70155192Srwatson#include <sys/bus.h> 71155192Srwatson#include <sys/interrupt.h> 72155192Srwatson#include <sys/malloc.h> 73155192Srwatson#include <sys/kernel.h> 74155192Srwatson#include <sys/module.h> 75155192Srwatson#include <sys/rman.h> 76155192Srwatson 77155192Srwatson#include <vm/vm.h> 78155192Srwatson#include <vm/pmap.h> 79155192Srwatson#include <vm/vm_extern.h> 80155192Srwatson 81155192Srwatson#include <machine/bus.h> 82155192Srwatson#include <machine/cpu.h> 83155192Srwatson#include <machine/pmap.h> 84155192Srwatson 85155192Srwatson#include <dev/pci/pcivar.h> 86155192Srwatson#include <dev/pci/pcireg.h> 87155192Srwatson 88155192Srwatson#include <dev/pci/pcib_private.h> 89155192Srwatson#include "pcib_if.h" 90155192Srwatson 91155192Srwatson#include <mips/idt/idtreg.h> 92155192Srwatson 93155192Srwatson#ifdef IDTPCI_DEBUG 94155192Srwatsonint idtpci_debug = 1; 95155192Srwatson#define IDTPCI_DPRINTF(__fmt, ...) \ 96155192Srwatsondo { \ 97155192Srwatson if (idtpci_debug) \ 98155192Srwatson printf((__fmt), __VA_ARGS__); \ 99155192Srwatson} while (/*CONSTCOND*/0) 100155192Srwatson#else /* !IDTPCI_DEBUG */ 101155192Srwatson#define IDTPCI_DPRINTF(__fmt, ...) do { } while (/*CONSTCOND*/0) 102155192Srwatson#endif /* IDTPCI_DEBUG */ 103155192Srwatson 104155192Srwatson#define IDTPCI_TAG_BUS_MASK 0x007f0000 105155192Srwatson#define IDTPCI_TAG_DEVICE_MASK 0x00007800 106155192Srwatson#define IDTPCI_TAG_FUNCTION_MASK 0x00000300 107155192Srwatson#define IDTPCI_TAG_REGISTER_MASK 0x0000007c 108155192Srwatson 109155192Srwatson#define IDTPCI_MAX_DEVICE 110155192Srwatson 111155192Srwatson#define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(IDT_BASE_PCI + (o))) 112155192Srwatson#define REG_WRITE(o,v) (REG_READ(o)) = (v) 113155192Srwatson 114155192Srwatsonunsigned int korina_fixup[24] = { 115155192Srwatson 0x00000157, 0x00000000, 0x00003c04, 0x00000008, 0x18800001, 0x18000001, 116155192Srwatson 0x48000008, 0x00000000, 0x00000000, 0x00000000, 0x011d0214, 0x00000000, 117155192Srwatson 0x00000000, 0x00000000, 0x38080101, 0x00008080, 0x00000d6e, 0x00000000, 118155192Srwatson 0x00000051, 0x00000000, 0x00000055, 0x18000000, 0x00000000, 0x00000000 119155192Srwatson}; 120155192Srwatson 121155192Srwatsonstruct idtpci_softc { 122155192Srwatson device_t sc_dev; 123155192Srwatson 124155192Srwatson int sc_busno; 125155192Srwatson struct rman sc_mem_rman[2]; 126155192Srwatson struct rman sc_io_rman[2]; 127155192Srwatson struct rman sc_irq_rman; 128155192Srwatson}; 129155192Srwatson 130155192Srwatsonstatic uint32_t 131155192Srwatsonidtpci_make_addr(int bus, int slot, int func, int reg) 132155192Srwatson{ 133155192Srwatson 134155192Srwatson return 0x80000000 | (bus << 16) | (slot << 11) | (func << 8) | reg; 135155192Srwatson} 136155192Srwatson 137155192Srwatsonstatic int 138155192Srwatsonidtpci_probe(device_t dev) 139155192Srwatson{ 140155192Srwatson 141155192Srwatson return (0); 142155192Srwatson} 143155192Srwatson 144155192Srwatsonstatic int 145155192Srwatsonidtpci_attach(device_t dev) 146155192Srwatson{ 147155192Srwatson int busno = 0; 148155192Srwatson struct idtpci_softc *sc = device_get_softc(dev); 149155192Srwatson unsigned int pci_data, force_endianess = 0; 150155192Srwatson int i; 151155192Srwatson bus_addr_t addr; 152155192Srwatson 153155192Srwatson sc->sc_dev = dev; 154155192Srwatson sc->sc_busno = busno; 155155192Srwatson 156155192Srwatson /* TODO: Check for host mode */ 157155192Srwatson 158155192Srwatson /* Enabled PCI, IG mode, EAP mode */ 159155192Srwatson REG_WRITE(IDT_PCI_CNTL, IDT_PCI_CNTL_IGM | IDT_PCI_CNTL_EAP | 160155192Srwatson IDT_PCI_CNTL_EN); 161155192Srwatson /* Wait while "Reset in progress bit" set */ 162155192Srwatson while(1) { 163155192Srwatson pci_data = REG_READ(IDT_PCI_STATUS); 164155192Srwatson if((pci_data & IDT_PCI_STATUS_RIP) == 0) 165155192Srwatson break; 166155192Srwatson } 167155192Srwatson 168155192Srwatson /* Reset status register */ 169155192Srwatson REG_WRITE(IDT_PCI_STATUS, 0); 170155192Srwatson /* Mask interrupts related to status register */ 171155192Srwatson REG_WRITE(IDT_PCI_STATUS_MASK, 0xffffffff); 172155192Srwatson 173155192Srwatson /* Disable PCI decoupled access */ 174155192Srwatson REG_WRITE(IDT_PCI_DAC, 0); 175155192Srwatson /* Zero status and mask DA interrupts */ 176155192Srwatson REG_WRITE(IDT_PCI_DAS, 0); 177155192Srwatson REG_WRITE(IDT_PCI_DASM, 0x7f); 178155192Srwatson 179155192Srwatson /* Init PCI messaging unit */ 180155192Srwatson /* Disable messaging interrupts */ 181155192Srwatson REG_WRITE(IDT_PCI_IIC, 0); 182155192Srwatson REG_WRITE(IDT_PCI_IIM, 0xffffffff); 183155192Srwatson REG_WRITE(IDT_PCI_OIC, 0); 184155192Srwatson REG_WRITE(IDT_PCI_OIM, 0); 185155192Srwatson 186155192Srwatson#ifdef __MIPSEB__ 187155192Srwatson force_endianess = IDT_PCI_LBA_FE; 188155192Srwatson#endif 189155192Srwatson 190155192Srwatson /* LBA0 -- memory window */ 191155192Srwatson REG_WRITE(IDT_PCI_LBA0, IDT_PCIMEM0_BASE); 192155192Srwatson REG_WRITE(IDT_PCI_LBA0_MAP, IDT_PCIMEM0_BASE); 193155192Srwatson REG_WRITE(IDT_PCI_LBA0_CNTL, IDT_PCI_LBA_SIZE_16MB | force_endianess); 194155192Srwatson pci_data = REG_READ(IDT_PCI_LBA0_CNTL); 195155192Srwatson 196155192Srwatson /* LBA1 -- memory window */ 197155192Srwatson REG_WRITE(IDT_PCI_LBA1, IDT_PCIMEM1_BASE); 198155192Srwatson REG_WRITE(IDT_PCI_LBA1_MAP, IDT_PCIMEM1_BASE); 199155192Srwatson REG_WRITE(IDT_PCI_LBA1_CNTL, IDT_PCI_LBA_SIZE_256MB | force_endianess); 200155192Srwatson pci_data = REG_READ(IDT_PCI_LBA1_CNTL); 201155192Srwatson 202155192Srwatson /* LBA2 -- IO window */ 203155192Srwatson REG_WRITE(IDT_PCI_LBA2, IDT_PCIMEM2_BASE); 204155192Srwatson REG_WRITE(IDT_PCI_LBA2_MAP, IDT_PCIMEM2_BASE); 205155192Srwatson REG_WRITE(IDT_PCI_LBA2_CNTL, IDT_PCI_LBA_SIZE_4MB | IDT_PCI_LBA_MSI | 206155192Srwatson force_endianess); 207155192Srwatson pci_data = REG_READ(IDT_PCI_LBA2_CNTL); 208155192Srwatson 209155192Srwatson /* LBA3 -- IO window */ 210155192Srwatson REG_WRITE(IDT_PCI_LBA3, IDT_PCIMEM3_BASE); 211155192Srwatson REG_WRITE(IDT_PCI_LBA3_MAP, IDT_PCIMEM3_BASE); 212159259Srwatson REG_WRITE(IDT_PCI_LBA3_CNTL, IDT_PCI_LBA_SIZE_1MB | IDT_PCI_LBA_MSI | 213155192Srwatson force_endianess); 214155192Srwatson pci_data = REG_READ(IDT_PCI_LBA3_CNTL); 215155192Srwatson 216155192Srwatson 217155192Srwatson pci_data = REG_READ(IDT_PCI_CNTL) & ~IDT_PCI_CNTL_TNR; 218155192Srwatson REG_WRITE(IDT_PCI_CNTL, pci_data); 219155192Srwatson pci_data = REG_READ(IDT_PCI_CNTL); 220159259Srwatson 221159259Srwatson /* Rewrite Target Control register with default values */ 222159259Srwatson REG_WRITE(IDT_PCI_TC, (IDT_PCI_TC_DTIMER << 8) | IDT_PCI_TC_RTIMER); 223155192Srwatson 224155192Srwatson /* Perform Korina fixup */ 225159259Srwatson addr = idtpci_make_addr(0, 0, 0, 4); 226159259Srwatson for (i = 0; i < 24; i++) { 227159259Srwatson 228159259Srwatson REG_WRITE(IDT_PCI_CFG_ADDR, addr); 229155192Srwatson REG_WRITE(IDT_PCI_CFG_DATA, korina_fixup[i]); 230155192Srwatson __asm__ volatile ("sync"); 231155192Srwatson 232155192Srwatson REG_WRITE(IDT_PCI_CFG_ADDR, 0); 233155192Srwatson REG_WRITE(IDT_PCI_CFG_DATA, 0); 234155192Srwatson addr += 4; 235159259Srwatson } 236155192Srwatson 237155192Srwatson /* Use KSEG1 to access IO ports for it is uncached */ 238155192Srwatson sc->sc_io_rman[0].rm_type = RMAN_ARRAY; 239155192Srwatson sc->sc_io_rman[0].rm_descr = "IDTPCI I/O Ports window 1"; 240155192Srwatson if (rman_init(&sc->sc_io_rman[0]) != 0 || 241155192Srwatson rman_manage_region(&sc->sc_io_rman[0], 242155192Srwatson IDT_PCIMEM2_BASE, IDT_PCIMEM2_BASE + IDT_PCIMEM2_SIZE - 1) != 0) { 243155192Srwatson panic("idtpci_attach: failed to set up I/O rman"); 244155192Srwatson } 245155192Srwatson 246155192Srwatson sc->sc_io_rman[1].rm_type = RMAN_ARRAY; 247155192Srwatson sc->sc_io_rman[1].rm_descr = "IDTPCI I/O Ports window 2"; 248155192Srwatson if (rman_init(&sc->sc_io_rman[1]) != 0 || 249155192Srwatson rman_manage_region(&sc->sc_io_rman[1], 250155192Srwatson IDT_PCIMEM3_BASE, IDT_PCIMEM3_BASE + IDT_PCIMEM3_SIZE - 1) != 0) { 251155192Srwatson panic("idtpci_attach: failed to set up I/O rman"); 252155192Srwatson } 253155192Srwatson 254155192Srwatson /* Use KSEG1 to access PCI memory for it is uncached */ 255155192Srwatson sc->sc_mem_rman[0].rm_type = RMAN_ARRAY; 256155192Srwatson sc->sc_mem_rman[0].rm_descr = "IDTPCI PCI Memory window 1"; 257155192Srwatson if (rman_init(&sc->sc_mem_rman[0]) != 0 || 258155192Srwatson rman_manage_region(&sc->sc_mem_rman[0], 259155192Srwatson IDT_PCIMEM0_BASE, IDT_PCIMEM0_BASE + IDT_PCIMEM0_SIZE) != 0) { 260155192Srwatson panic("idtpci_attach: failed to set up memory rman"); 261155192Srwatson } 262155192Srwatson 263155192Srwatson sc->sc_mem_rman[1].rm_type = RMAN_ARRAY; 264155192Srwatson sc->sc_mem_rman[1].rm_descr = "IDTPCI PCI Memory window 2"; 265155192Srwatson if (rman_init(&sc->sc_mem_rman[1]) != 0 || 266155192Srwatson rman_manage_region(&sc->sc_mem_rman[1], 267155192Srwatson IDT_PCIMEM1_BASE, IDT_PCIMEM1_BASE + IDT_PCIMEM1_SIZE) != 0) { 268155192Srwatson panic("idtpci_attach: failed to set up memory rman"); 269155192Srwatson } 270155192Srwatson 271155192Srwatson sc->sc_irq_rman.rm_type = RMAN_ARRAY; 272155192Srwatson sc->sc_irq_rman.rm_descr = "IDTPCI PCI IRQs"; 273155192Srwatson if (rman_init(&sc->sc_irq_rman) != 0 || 274155192Srwatson rman_manage_region(&sc->sc_irq_rman, PCI_IRQ_BASE, 275155192Srwatson PCI_IRQ_END) != 0) 276155192Srwatson panic("idtpci_attach: failed to set up IRQ rman"); 277155192Srwatson 278155192Srwatson device_add_child(dev, "pci", busno); 279155192Srwatson return (bus_generic_attach(dev)); 280155192Srwatson} 281155192Srwatson 282155192Srwatsonstatic int 283155192Srwatsonidtpci_maxslots(device_t dev) 284155192Srwatson{ 285155192Srwatson 286155192Srwatson return (PCI_SLOTMAX); 287155192Srwatson} 288155192Srwatson 289155192Srwatsonstatic uint32_t 290155192Srwatsonidtpci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, 291155192Srwatson int bytes) 292155192Srwatson{ 293155192Srwatson uint32_t data; 294155192Srwatson uint32_t shift, mask; 295155192Srwatson bus_addr_t addr; 296155192Srwatson 297155192Srwatson IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, 298155192Srwatson bus, slot, func, reg, bytes); 299155192Srwatson 300155192Srwatson addr = idtpci_make_addr(bus, slot, func, reg); 301155192Srwatson 302155192Srwatson REG_WRITE(IDT_PCI_CFG_ADDR, addr); 303155192Srwatson data = REG_READ(IDT_PCI_CFG_DATA); 304155192Srwatson 305155192Srwatson switch (reg % 4) { 306155192Srwatson case 3: 307155192Srwatson shift = 24; 308155192Srwatson break; 309159259Srwatson case 2: 310155192Srwatson shift = 16; 311155192Srwatson break; 312159259Srwatson case 1: 313155192Srwatson shift = 8; 314155192Srwatson break; 315155192Srwatson default: 316155192Srwatson shift = 0; 317155192Srwatson break; 318155192Srwatson } 319155192Srwatson 320155192Srwatson switch (bytes) { 321155192Srwatson case 1: 322155192Srwatson mask = 0xff; 323155192Srwatson data = (data >> shift) & mask; 324155192Srwatson break; 325155192Srwatson case 2: 326155192Srwatson mask = 0xffff; 327155192Srwatson if (reg % 4 == 0) 328155192Srwatson data = data & mask; 329159259Srwatson else 330155192Srwatson data = (data >> 16) & mask; 331155192Srwatson break; 332155192Srwatson case 4: 333159259Srwatson break; 334155192Srwatson default: 335155192Srwatson panic("%s: wrong bytes count", __func__); 336155192Srwatson break; 337155192Srwatson } 338155192Srwatson 339155192Srwatson __asm__ volatile ("sync"); 340155192Srwatson IDTPCI_DPRINTF("%s: read 0x%x\n", __func__, data); 341155192Srwatson 342155192Srwatson return (data); 343155192Srwatson} 344155192Srwatson 345155192Srwatsonstatic void 346155192Srwatsonidtpci_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, 347155192Srwatson uint32_t data, int bytes) 348155192Srwatson{ 349155192Srwatson bus_addr_t addr; 350155192Srwatson uint32_t reg_data; 351155192Srwatson uint32_t shift, mask; 352155192Srwatson 353155192Srwatson IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d) data %08x\n", __func__, 354155192Srwatson bus, slot, func, reg, bytes, data); 355155192Srwatson 356155192Srwatson if (bytes != 4) { 357155192Srwatson reg_data = idtpci_read_config(dev, bus, slot, func, reg, 4); 358155192Srwatson 359155192Srwatson switch (reg % 4) { 360155192Srwatson case 3: 361155192Srwatson shift = 24; 362155192Srwatson break; 363155192Srwatson case 2: 364155192Srwatson shift = 16; 365155192Srwatson break; 366155192Srwatson case 1: 367155192Srwatson shift = 8; 368155192Srwatson break; 369155192Srwatson default: 370155192Srwatson shift = 0; 371155192Srwatson break; 372155192Srwatson } 373155192Srwatson 374155192Srwatson switch (bytes) { 375155192Srwatson case 1: 376155192Srwatson mask = 0xff; 377155192Srwatson data = (reg_data & ~ (mask << shift)) | (data << shift); 378155192Srwatson break; 379155192Srwatson case 2: 380155192Srwatson mask = 0xffff; 381155192Srwatson if (reg % 4 == 0) 382155192Srwatson data = (reg_data & ~mask) | data; 383155192Srwatson else 384155192Srwatson data = (reg_data & ~ (mask << shift)) | 385155192Srwatson (data << shift); 386155192Srwatson break; 387155192Srwatson case 4: 388155192Srwatson break; 389155192Srwatson default: 390155192Srwatson panic("%s: wrong bytes count", __func__); 391155192Srwatson break; 392155192Srwatson } 393155192Srwatson } 394155192Srwatson 395155192Srwatson addr = idtpci_make_addr(bus, slot, func, reg); 396155192Srwatson 397155192Srwatson 398155192Srwatson REG_WRITE(IDT_PCI_CFG_ADDR, addr); 399155192Srwatson REG_WRITE(IDT_PCI_CFG_DATA, data); 400155192Srwatson __asm__ volatile ("sync"); 401155192Srwatson 402155192Srwatson REG_WRITE(IDT_PCI_CFG_ADDR, 0); 403155192Srwatson REG_WRITE(IDT_PCI_CFG_DATA, 0); 404155192Srwatson} 405155192Srwatson 406155192Srwatsonstatic int 407155192Srwatsonidtpci_route_interrupt(device_t pcib, device_t device, int pin) 408155192Srwatson{ 409155192Srwatson static int idt_pci_table[2][12] = 410155192Srwatson { 411155192Srwatson { 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 }, 412155192Srwatson { 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 } 413155192Srwatson }; 414155192Srwatson int dev, bus, irq; 415155192Srwatson 416155192Srwatson dev = pci_get_slot(device); 417155192Srwatson bus = pci_get_bus(device); 418155192Srwatson if (bootverbose) 419155192Srwatson device_printf(pcib, "routing pin %d for %s\n", pin, 420155192Srwatson device_get_nameunit(device)); 421155192Srwatson if (bus >= 0 && bus <= 1 && 422155192Srwatson dev >= 0 && dev <= 11) { 423155192Srwatson irq = IP_IRQ(6, idt_pci_table[bus][dev] + 4); 424155192Srwatson if (bootverbose) 425155192Srwatson printf("idtpci: %d/%d/%d -> IRQ%d\n", 426155192Srwatson pci_get_bus(device), dev, pci_get_function(device), 427155192Srwatson irq); 428155192Srwatson return (irq); 429155192Srwatson } else 430155192Srwatson printf("idtpci: no mapping for %d/%d/%d\n", 431155192Srwatson pci_get_bus(device), dev, pci_get_function(device)); 432155192Srwatson 433155192Srwatson return (-1); 434155192Srwatson} 435155192Srwatson 436155192Srwatsonstatic int 437155192Srwatsonidtpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 438155192Srwatson{ 439155192Srwatson struct idtpci_softc *sc = device_get_softc(dev); 440155192Srwatson 441155192Srwatson switch (which) { 442155192Srwatson case PCIB_IVAR_DOMAIN: 443155192Srwatson *result = 0; 444155192Srwatson return (0); 445155192Srwatson case PCIB_IVAR_BUS: 446155192Srwatson *result = sc->sc_busno; 447155192Srwatson return (0); 448155192Srwatson } 449155192Srwatson 450155192Srwatson return (ENOENT); 451155192Srwatson} 452155192Srwatson 453155192Srwatsonstatic int 454155192Srwatsonidtpci_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 455155192Srwatson{ 456155192Srwatson struct idtpci_softc * sc = device_get_softc(dev); 457155192Srwatson 458155192Srwatson switch (which) { 459155192Srwatson case PCIB_IVAR_BUS: 460155192Srwatson sc->sc_busno = result; 461155192Srwatson return (0); 462155192Srwatson } 463155192Srwatson return (ENOENT); 464155192Srwatson} 465155192Srwatson 466155192Srwatsonstatic struct resource * 467155192Srwatsonidtpci_alloc_resource(device_t bus, device_t child, int type, int *rid, 468155192Srwatson u_long start, u_long end, u_long count, u_int flags) 469155192Srwatson{ 470155192Srwatson 471155192Srwatson struct idtpci_softc *sc = device_get_softc(bus); 472155192Srwatson struct resource *rv = NULL; 473155192Srwatson struct rman *rm1, *rm2; 474155192Srwatson 475155192Srwatson switch (type) { 476155192Srwatson case SYS_RES_IRQ: 477155192Srwatson rm1 = &sc->sc_irq_rman; 478155192Srwatson rm2 = NULL; 479155192Srwatson break; 480155192Srwatson case SYS_RES_MEMORY: 481155192Srwatson rm1 = &sc->sc_mem_rman[0]; 482155192Srwatson rm2 = &sc->sc_mem_rman[1]; 483155192Srwatson break; 484155192Srwatson case SYS_RES_IOPORT: 485155192Srwatson rm1 = &sc->sc_io_rman[0]; 486155192Srwatson rm2 = &sc->sc_io_rman[1]; 487155192Srwatson break; 488155192Srwatson default: 489155192Srwatson return (NULL); 490155192Srwatson } 491155192Srwatson 492155192Srwatson rv = rman_reserve_resource(rm1, start, end, count, flags, child); 493155192Srwatson 494155192Srwatson /* Try second window if it exists */ 495155192Srwatson if ((rv == NULL) && (rm2 != NULL)) 496155192Srwatson rv = rman_reserve_resource(rm2, start, end, count, flags, 497155192Srwatson child); 498155192Srwatson 499155192Srwatson if (rv == NULL) 500155192Srwatson return (NULL); 501155192Srwatson 502155192Srwatson rman_set_rid(rv, *rid); 503155192Srwatson 504155192Srwatson if (flags & RF_ACTIVE) { 505155192Srwatson if (bus_activate_resource(child, type, *rid, rv)) { 506155192Srwatson rman_release_resource(rv); 507155192Srwatson return (NULL); 508155192Srwatson } 509155192Srwatson } 510155192Srwatson 511155192Srwatson return (rv); 512155192Srwatson} 513155192Srwatson 514155192Srwatsonstatic int 515155192Srwatsonidtpci_teardown_intr(device_t dev, device_t child, struct resource *res, 516155192Srwatson void *cookie) 517155192Srwatson{ 518155192Srwatson 519155192Srwatson return (intr_event_remove_handler(cookie)); 520155192Srwatson} 521155192Srwatson 522155192Srwatsonstatic device_method_t idtpci_methods[] = { 523155192Srwatson /* Device interface */ 524155192Srwatson DEVMETHOD(device_probe, idtpci_probe), 525155192Srwatson DEVMETHOD(device_attach, idtpci_attach), 526155192Srwatson DEVMETHOD(device_shutdown, bus_generic_shutdown), 527155192Srwatson DEVMETHOD(device_suspend, bus_generic_suspend), 528155192Srwatson DEVMETHOD(device_resume, bus_generic_resume), 529155192Srwatson 530155192Srwatson /* Bus interface */ 531155192Srwatson DEVMETHOD(bus_read_ivar, idtpci_read_ivar), 532155192Srwatson DEVMETHOD(bus_write_ivar, idtpci_write_ivar), 533155192Srwatson DEVMETHOD(bus_alloc_resource, idtpci_alloc_resource), 534155192Srwatson DEVMETHOD(bus_release_resource, bus_generic_release_resource), 535155192Srwatson DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 536155192Srwatson DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 537155192Srwatson DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 538155192Srwatson DEVMETHOD(bus_teardown_intr, idtpci_teardown_intr), 539155192Srwatson 540155192Srwatson /* pcib interface */ 541155192Srwatson DEVMETHOD(pcib_maxslots, idtpci_maxslots), 542155192Srwatson DEVMETHOD(pcib_read_config, idtpci_read_config), 543155192Srwatson DEVMETHOD(pcib_write_config, idtpci_write_config), 544155192Srwatson DEVMETHOD(pcib_route_interrupt, idtpci_route_interrupt), 545155192Srwatson 546155192Srwatson DEVMETHOD_END 547155192Srwatson}; 548155192Srwatson 549155192Srwatsonstatic driver_t idtpci_driver = { 550155192Srwatson "pcib", 551155192Srwatson idtpci_methods, 552155192Srwatson sizeof(struct idtpci_softc), 553155192Srwatson}; 554155192Srwatson 555155192Srwatsonstatic devclass_t idtpci_devclass; 556155192Srwatson 557155192SrwatsonDRIVER_MODULE(idtpci, obio, idtpci_driver, idtpci_devclass, 0, 0); 558155192Srwatson