pci.c revision 47339
190699Srobert/* 290699Srobert * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 390699Srobert * All rights reserved. 490699Srobert * 590699Srobert * Redistribution and use in source and binary forms, with or without 690699Srobert * modification, are permitted provided that the following conditions 790699Srobert * are met: 890699Srobert * 1. Redistributions of source code must retain the above copyright 990699Srobert * notice unmodified, this list of conditions, and the following 1090699Srobert * disclaimer. 1190699Srobert * 2. Redistributions in binary form must reproduce the above copyright 1290699Srobert * notice, this list of conditions and the following disclaimer in the 1390699Srobert * documentation and/or other materials provided with the distribution. 1490699Srobert * 1590699Srobert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1690699Srobert * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1790699Srobert * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1891295Srobert * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1991295Srobert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2091295Srobert * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2191295Srobert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2290699Srobert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2390699Srobert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2490699Srobert * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2590699Srobert * 2690699Srobert * $Id: pci.c,v 1.103 1999/05/10 17:56:22 dfr Exp $ 2790699Srobert * 2890699Srobert */ 2990699Srobert 3090699Srobert#include "opt_bus.h" 3190699Srobert 3290699Srobert#include "pci.h" 3395337Sjake#if NPCI > 0 3495337Sjake 3590699Srobert#include "opt_devfs.h" 3690699Srobert#include "opt_simos.h" 3790699Srobert 3890699Srobert#include <sys/param.h> 3990699Srobert#include <sys/systm.h> 4090699Srobert#include <sys/malloc.h> 4190699Srobert#include <sys/module.h> 4290699Srobert#include <sys/fcntl.h> 4390699Srobert#include <sys/conf.h> 4490699Srobert#include <sys/kernel.h> 4590699Srobert#include <sys/queue.h> 4690699Srobert#include <sys/types.h> 4790699Srobert#include <sys/buf.h> 4890699Srobert#ifdef DEVFS 4990699Srobert#include <sys/devfsext.h> 5090699Srobert#endif /* DEVFS */ 5190699Srobert 5290699Srobert#include <vm/vm.h> 5390699Srobert#include <vm/pmap.h> 5490699Srobert#include <vm/vm_extern.h> 5590699Srobert 5690699Srobert#include <sys/bus.h> 5790699Srobert#include <machine/bus.h> 5890699Srobert#include <sys/rman.h> 5990699Srobert#include <machine/resource.h> 6090699Srobert 6190699Srobert#include <pci/pcireg.h> 6290699Srobert#include <pci/pcivar.h> 6395340Sjake#include <pci/pci_ioctl.h> 6495340Sjake 6590699Srobert#ifdef APIC_IO 6690699Srobert#include <machine/smp.h> 6790699Srobert#endif /* APIC_IO */ 6890699Srobert 6990699Srobertstatic STAILQ_HEAD(devlist, pci_devinfo) pci_devq; 7090699Srobertu_int32_t pci_numdevs = 0; 7190699Srobertstatic u_int32_t pci_generation = 0; 7290699Srobert 7390699Srobert/* return base address of memory or port map */ 7490699Srobert 7590699Srobertstatic int 7690699Srobertpci_mapbase(unsigned mapreg) 7790699Srobert{ 7890699Srobert int mask = 0x03; 7990699Srobert if ((mapreg & 0x01) == 0) 8090699Srobert mask = 0x0f; 8190699Srobert return (mapreg & ~mask); 8290699Srobert} 8390699Srobert 8490699Srobert/* return map type of memory or port map */ 8590699Srobert 8690699Srobertstatic int 8790699Srobertpci_maptype(unsigned mapreg) 8890699Srobert{ 8990699Srobert static u_int8_t maptype[0x10] = { 9090699Srobert PCI_MAPMEM, PCI_MAPPORT, 9190699Srobert PCI_MAPMEM, 0, 9290699Srobert PCI_MAPMEM, PCI_MAPPORT, 9390699Srobert 0, 0, 9490699Srobert PCI_MAPMEM|PCI_MAPMEMP, PCI_MAPPORT, 9590699Srobert PCI_MAPMEM|PCI_MAPMEMP, 0, 9690699Srobert PCI_MAPMEM|PCI_MAPMEMP, PCI_MAPPORT, 9790699Srobert 0, 0, 9890699Srobert }; 9990699Srobert 10090699Srobert return maptype[mapreg & 0x0f]; 10190699Srobert} 10290699Srobert 10390699Srobert/* return log2 of map size decoded for memory or port map */ 10490699Srobert 10590699Srobertstatic int 10690699Srobertpci_mapsize(unsigned testval) 10790699Srobert{ 10890699Srobert int ln2size; 10990699Srobert 11090699Srobert testval = pci_mapbase(testval); 11190699Srobert ln2size = 0; 11290699Srobert if (testval != 0) { 11390699Srobert while ((testval & 1) == 0) 11490699Srobert { 11591295Srobert ln2size++; 11691295Srobert testval >>= 1; 11791295Srobert } 11891295Srobert } 11991295Srobert return (ln2size); 12091295Srobert} 12191295Srobert 12291295Srobert/* return log2 of address range supported by map register */ 12391295Srobert 12491295Srobertstatic int 12591295Srobertpci_maprange(unsigned mapreg) 12691295Srobert{ 12791295Srobert int ln2range = 0; 12890699Srobert switch (mapreg & 0x07) { 12990699Srobert case 0x00: 13090699Srobert case 0x01: 13190699Srobert case 0x05: 13290699Srobert ln2range = 32; 13391295Srobert break; 13491295Srobert case 0x02: 13591295Srobert ln2range = 20; 13691295Srobert break; 13791295Srobert case 0x04: 13891295Srobert ln2range = 64; 13991295Srobert break; 14091295Srobert } 14190699Srobert return (ln2range); 14291295Srobert} 14391295Srobert 14491295Srobert/* extract map parameters into newly allocated array of pcimap structures */ 14591295Srobert 14691295Srobertstatic pcimap * 14791295Srobertpci_readmaps(pcicfgregs *cfg, int maxmaps) 14891295Srobert{ 14991295Srobert int i, j = 0; 15090699Srobert pcimap *map; 15190699Srobert int map64 = 0; 15290699Srobert int reg = PCIR_MAPS; 15390699Srobert 15490699Srobert for (i = 0; i < maxmaps; i++) { 15591295Srobert int reg = PCIR_MAPS + i*4; 15691295Srobert u_int32_t base; 15791295Srobert u_int32_t ln2range; 15891295Srobert 15991295Srobert base = pci_cfgread(cfg, reg, 4); 16091295Srobert ln2range = pci_maprange(base); 16191295Srobert 16291295Srobert if (base == 0 || ln2range == 0 || base == 0xffffffff) 16391295Srobert continue; /* skip invalid entry */ 16491295Srobert else { 16591295Srobert j++; 16691295Srobert if (ln2range > 32) { 16791295Srobert i++; 16890699Srobert j++; 16990699Srobert } 17090699Srobert } 17190699Srobert } 17290699Srobert 17391295Srobert map = malloc(j * sizeof (pcimap), M_DEVBUF, M_WAITOK); 17491295Srobert if (map != NULL) { 17591295Srobert bzero(map, sizeof(pcimap) * j); 17691295Srobert cfg->nummaps = j; 17791295Srobert 17891295Srobert for (i = 0, j = 0; i < maxmaps; i++, reg += 4) { 17991295Srobert u_int32_t base; 18091295Srobert u_int32_t testval; 18191295Srobert 18291295Srobert base = pci_cfgread(cfg, reg, 4); 18391295Srobert 18491295Srobert if (map64 == 0) { 18590699Srobert if (base == 0 || base == 0xffffffff) 18690699Srobert continue; /* skip invalid entry */ 18790699Srobert pci_cfgwrite(cfg, reg, 0xffffffff, 4); 18890699Srobert testval = pci_cfgread(cfg, reg, 4); 18990699Srobert pci_cfgwrite(cfg, reg, base, 4); 19091295Srobert 19191295Srobert map[j].reg = reg; 19291295Srobert map[j].base = pci_mapbase(base); 19391295Srobert map[j].type = pci_maptype(base); 19491295Srobert map[j].ln2size = pci_mapsize(testval); 19591295Srobert map[j].ln2range = pci_maprange(testval); 19691295Srobert map64 = map[j].ln2range == 64; 19791295Srobert } else { 19891295Srobert /* only fill in base, other fields are 0 */ 19991295Srobert map[j].base = base; 20091295Srobert map64 = 0; 20191295Srobert } 20291295Srobert#ifdef __alpha__ 20391295Srobert /* 20491295Srobert * XXX: encode hose number in the base addr, 20590699Srobert * This will go away once the bus_space functions 20690699Srobert * can deal with multiple hoses 20790699Srobert */ 20890699Srobert 20990699Srobert if(cfg->hose){ 21091295Srobert if(map[j].base & 0x80000000){ 21191295Srobert printf("base addr = 0x%x\n", map[j].base); 21291295Srobert printf("hacked addr = 0x%x\n", 21391295Srobert map[j].base | (cfg->hose << 31)); 21491295Srobert 21591295Srobert panic("hose encoding hack would clobber base addr"); 21691295Srobert } 21791295Srobert if(cfg->hose > 1 ) 21891295Srobert panic("only one hose supported!"); 21991295Srobert map[j].base |= (cfg->hose << 31); 22091295Srobert } 22191295Srobert#endif 22291295Srobert j++; 22391295Srobert } 22491295Srobert } 22590699Srobert return (map); 22690699Srobert} 22790699Srobert 22890699Srobert/* adjust some values from PCI 1.0 devices to match 2.0 standards ... */ 22990699Srobert 23091295Srobertstatic void 23191295Srobertpci_fixancient(pcicfgregs *cfg) 23291295Srobert{ 23391295Srobert if (cfg->hdrtype != 0) 23491295Srobert return; 23591295Srobert 23691678Srobert /* PCI to PCI bridges use header type 1 */ 23791295Srobert if (cfg->baseclass == PCIC_BRIDGE && cfg->subclass == PCIS_BRIDGE_PCI) 23891295Srobert cfg->hdrtype = 1; 23991295Srobert} 24091295Srobert 24191295Srobert/* read config data specific to header type 1 device (PCI to PCI bridge) */ 24291295Srobert 24391295Srobertstatic void * 24491295Srobertpci_readppb(pcicfgregs *cfg) 24590699Srobert{ 24690699Srobert pcih1cfgregs *p; 24795340Sjake 24895340Sjake p = malloc(sizeof (pcih1cfgregs), M_DEVBUF, M_WAITOK); 24995340Sjake if (p == NULL) 25095340Sjake return (NULL); 25195340Sjake 25295340Sjake bzero(p, sizeof *p); 25395340Sjake 25495340Sjake p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_1, 2); 25595340Sjake p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_1, 2); 25695340Sjake 25795340Sjake p->seclat = pci_cfgread(cfg, PCIR_SECLAT_1, 1); 25895340Sjake 25995340Sjake p->iobase = PCI_PPBIOBASE (pci_cfgread(cfg, PCIR_IOBASEH_1, 2), 26095340Sjake pci_cfgread(cfg, PCIR_IOBASEL_1, 1)); 26195340Sjake p->iolimit = PCI_PPBIOLIMIT (pci_cfgread(cfg, PCIR_IOLIMITH_1, 2), 26295340Sjake pci_cfgread(cfg, PCIR_IOLIMITL_1, 1)); 26395340Sjake 26495340Sjake p->membase = PCI_PPBMEMBASE (0, 26595340Sjake pci_cfgread(cfg, PCIR_MEMBASE_1, 2)); 26690699Srobert p->memlimit = PCI_PPBMEMLIMIT (0, 26790699Srobert pci_cfgread(cfg, PCIR_MEMLIMIT_1, 2)); 26890699Srobert 26991295Srobert p->pmembase = PCI_PPBMEMBASE ( 27091295Srobert (pci_addr_t)pci_cfgread(cfg, PCIR_PMBASEH_1, 4), 27191295Srobert pci_cfgread(cfg, PCIR_PMBASEL_1, 2)); 27290699Srobert 27390699Srobert p->pmemlimit = PCI_PPBMEMLIMIT ( 27490699Srobert (pci_addr_t)pci_cfgread(cfg, PCIR_PMLIMITH_1, 4), 27590699Srobert pci_cfgread(cfg, PCIR_PMLIMITL_1, 2)); 27690699Srobert return (p); 27791295Srobert} 27891295Srobert 27991295Srobert/* read config data specific to header type 2 device (PCI to CardBus bridge) */ 28091295Srobert 28190699Srobertstatic void * 28291295Srobertpci_readpcb(pcicfgregs *cfg) 28391295Srobert{ 28491295Srobert pcih2cfgregs *p; 28591295Srobert 28695337Sjake p = malloc(sizeof (pcih2cfgregs), M_DEVBUF, M_WAITOK); 28791295Srobert if (p == NULL) 28891295Srobert return (NULL); 28991295Srobert 29091295Srobert bzero(p, sizeof *p); 29191295Srobert 29290699Srobert p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_2, 2); 29391295Srobert p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_2, 2); 29490699Srobert 29590699Srobert p->seclat = pci_cfgread(cfg, PCIR_SECLAT_2, 1); 29690699Srobert 29790699Srobert p->membase0 = pci_cfgread(cfg, PCIR_MEMBASE0_2, 4); 29890699Srobert p->memlimit0 = pci_cfgread(cfg, PCIR_MEMLIMIT0_2, 4); 29991295Srobert p->membase1 = pci_cfgread(cfg, PCIR_MEMBASE1_2, 4); 30091295Srobert p->memlimit1 = pci_cfgread(cfg, PCIR_MEMLIMIT1_2, 4); 30191295Srobert 30290699Srobert p->iobase0 = pci_cfgread(cfg, PCIR_IOBASE0_2, 4); 30390699Srobert p->iolimit0 = pci_cfgread(cfg, PCIR_IOLIMIT0_2, 4); 30490699Srobert p->iobase1 = pci_cfgread(cfg, PCIR_IOBASE1_2, 4); 30595337Sjake p->iolimit1 = pci_cfgread(cfg, PCIR_IOLIMIT1_2, 4); 30695337Sjake 30790699Srobert p->pccardif = pci_cfgread(cfg, PCIR_PCCARDIF_2, 4); 30891295Srobert return p; 30995340Sjake} 31090699Srobert 31191295Srobert/* extract header type specific config data */ 31290699Srobert 31395337Sjakestatic void 31491295Srobertpci_hdrtypedata(pcicfgregs *cfg) 31591295Srobert{ 31690699Srobert switch (cfg->hdrtype) { 31790699Srobert case 0: 31890699Srobert cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_0, 2); 31990699Srobert cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_0, 2); 32090699Srobert cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_0); 32191295Srobert break; 32295339Sjake case 1: 32391295Srobert cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_1, 2); 32491295Srobert cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_1, 2); 32595339Sjake cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_1, 1); 32690699Srobert cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_1, 1); 32791295Srobert cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_1); 32895337Sjake cfg->hdrspec = pci_readppb(cfg); 32990699Srobert break; 33090699Srobert case 2: 33195339Sjake cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_2, 2); 33295339Sjake cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_2, 2); 33391295Srobert cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_2, 1); 33495339Sjake cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_2, 1); 33591295Srobert cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_2); 33691295Srobert cfg->hdrspec = pci_readpcb(cfg); 33791295Srobert break; 33891295Srobert } 33995339Sjake} 34095339Sjake 34195339Sjake/* read configuration header into pcicfgrect structure */ 34295339Sjake 34391295Srobertstatic struct pci_devinfo * 34491295Srobertpci_readcfg(pcicfgregs *probe) 34595339Sjake{ 34695339Sjake pcicfgregs *cfg = NULL; 34795339Sjake struct pci_devinfo *devlist_entry; 34895339Sjake struct devlist *devlist_head; 34995339Sjake 35095339Sjake devlist_head = &pci_devq; 35191295Srobert 35291295Srobert devlist_entry = NULL; 35395339Sjake 35495340Sjake if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) { 35591295Srobert devlist_entry = malloc(sizeof(struct pci_devinfo), 35691295Srobert M_DEVBUF, M_WAITOK); 35795339Sjake if (devlist_entry == NULL) 35890699Srobert return (NULL); 35990699Srobert bzero(devlist_entry, sizeof *devlist_entry); 36090699Srobert 36190699Srobert cfg = &devlist_entry->cfg; 36290699Srobert 36391295Srobert cfg->hose = probe->hose; 36491295Srobert cfg->bus = probe->bus; 36591295Srobert cfg->slot = probe->slot; 36691295Srobert cfg->func = probe->func; 36791295Srobert cfg->vendor = pci_cfgread(cfg, PCIR_VENDOR, 2); 36890699Srobert cfg->device = pci_cfgread(cfg, PCIR_DEVICE, 2); 36991295Srobert cfg->cmdreg = pci_cfgread(cfg, PCIR_COMMAND, 2); 37091295Srobert cfg->statreg = pci_cfgread(cfg, PCIR_STATUS, 2); 37191678Srobert cfg->baseclass = pci_cfgread(cfg, PCIR_CLASS, 1); 37291678Srobert cfg->subclass = pci_cfgread(cfg, PCIR_SUBCLASS, 1); 37391295Srobert cfg->progif = pci_cfgread(cfg, PCIR_PROGIF, 1); 37491295Srobert cfg->revid = pci_cfgread(cfg, PCIR_REVID, 1); 37591295Srobert cfg->hdrtype = pci_cfgread(cfg, PCIR_HEADERTYPE, 1); 37691295Srobert cfg->cachelnsz = pci_cfgread(cfg, PCIR_CACHELNSZ, 1); 37791295Srobert cfg->lattimer = pci_cfgread(cfg, PCIR_LATTIMER, 1); 37891295Srobert cfg->intpin = pci_cfgread(cfg, PCIR_INTPIN, 1); 37991295Srobert cfg->intline = pci_cfgread(cfg, PCIR_INTLINE, 1); 38091295Srobert#ifdef __alpha__ 38191295Srobert alpha_platform_assign_pciintr(cfg); 38295340Sjake#endif 38391295Srobert 38491678Srobert#ifdef APIC_IO 38591678Srobert if (cfg->intpin != 0) { 38691678Srobert int airq; 38791678Srobert 38891295Srobert airq = pci_apic_irq(cfg->bus, cfg->slot, cfg->intpin); 38991295Srobert if (airq >= 0) { 39091295Srobert /* PCI specific entry found in MP table */ 39191295Srobert if (airq != cfg->intline) { 39291295Srobert undirect_pci_irq(cfg->intline); 39390699Srobert cfg->intline = airq; 39490699Srobert } 39590699Srobert } else { 39690699Srobert /* 39790699Srobert * PCI interrupts might be redirected to the 39891295Srobert * ISA bus according to some MP tables. Use the 39991295Srobert * same methods as used by the ISA devices 40095337Sjake * devices to find the proper IOAPIC int pin. 40195337Sjake */ 40291295Srobert airq = isa_apic_irq(cfg->intline); 40391295Srobert if ((airq >= 0) && (airq != cfg->intline)) { 40491295Srobert /* XXX: undirect_pci_irq() ? */ 40591295Srobert undirect_isa_irq(cfg->intline); 40691295Srobert cfg->intline = airq; 40791295Srobert } 40890699Srobert } 40991295Srobert } 41091295Srobert#endif /* APIC_IO */ 41191295Srobert 41291295Srobert cfg->mingnt = pci_cfgread(cfg, PCIR_MINGNT, 1); 41395340Sjake cfg->maxlat = pci_cfgread(cfg, PCIR_MAXLAT, 1); 41491295Srobert 41591295Srobert cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0; 41695337Sjake cfg->hdrtype &= ~PCIM_MFDEV; 41791295Srobert 41891295Srobert pci_fixancient(cfg); 41991295Srobert pci_hdrtypedata(cfg); 42090699Srobert 42191295Srobert STAILQ_INSERT_TAIL(devlist_head, devlist_entry, pci_links); 42291295Srobert 42391295Srobert devlist_entry->conf.pc_sel.pc_bus = cfg->bus; 42491295Srobert devlist_entry->conf.pc_sel.pc_dev = cfg->slot; 42590699Srobert devlist_entry->conf.pc_sel.pc_func = cfg->func; 42691295Srobert devlist_entry->conf.pc_hdr = cfg->hdrtype; 42795340Sjake 42895340Sjake devlist_entry->conf.pc_subvendor = cfg->subvendor; 42991295Srobert devlist_entry->conf.pc_subdevice = cfg->subdevice; 43091295Srobert devlist_entry->conf.pc_vendor = cfg->vendor; 43191295Srobert devlist_entry->conf.pc_device = cfg->device; 43290699Srobert 43391295Srobert devlist_entry->conf.pc_class = cfg->baseclass; 43491295Srobert devlist_entry->conf.pc_subclass = cfg->subclass; 43591295Srobert devlist_entry->conf.pc_progif = cfg->progif; 43691295Srobert devlist_entry->conf.pc_revid = cfg->revid; 43791295Srobert 43891295Srobert pci_numdevs++; 43991295Srobert pci_generation++; 44091295Srobert } 44191295Srobert return (devlist_entry); 44291295Srobert} 44391295Srobert 44491295Srobert#if 0 44591295Srobert/* free pcicfgregs structure and all depending data structures */ 44691295Srobert 44791295Srobertstatic int 44891295Srobertpci_freecfg(struct pci_devinfo *dinfo) 44991295Srobert{ 45091295Srobert struct devlist *devlist_head; 45191295Srobert 45291295Srobert devlist_head = &pci_devq; 45391295Srobert 45491295Srobert if (dinfo->cfg.hdrspec != NULL) 45591295Srobert free(dinfo->cfg.hdrspec, M_DEVBUF); 45691295Srobert if (dinfo->cfg.map != NULL) 45791295Srobert free(dinfo->cfg.map, M_DEVBUF); 45891295Srobert /* XXX this hasn't been tested */ 45991295Srobert STAILQ_REMOVE(devlist_head, dinfo, pci_devinfo, pci_links); 46091295Srobert free(dinfo, M_DEVBUF); 46191295Srobert 46295340Sjake /* increment the generation count */ 46391295Srobert pci_generation++; 46491295Srobert 46591295Srobert /* we're losing one device */ 46690699Srobert pci_numdevs--; 46791295Srobert return (0); 46890699Srobert} 46990699Srobert#endif 47090699Srobert 47190699Srobert 47290699Srobert/* 47391295Srobert * This is the user interface to PCI configuration space. 47491295Srobert */ 47591295Srobert 47691295Srobertstatic int 47791295Srobertpci_open(dev_t dev, int oflags, int devtype, struct proc *p) 47891295Srobert{ 47991295Srobert if ((oflags & FWRITE) && securelevel > 0) { 48091295Srobert return EPERM; 48190699Srobert } 48290699Srobert return 0; 48390699Srobert} 48490699Srobert 48590699Srobertstatic int 48691295Srobertpci_close(dev_t dev, int flag, int devtype, struct proc *p) 48791295Srobert{ 48891295Srobert return 0; 48991295Srobert} 49091295Srobert 49191678Srobert/* 49290699Srobert * Match a single pci_conf structure against an array of pci_match_conf 49391295Srobert * structures. The first argument, 'matches', is an array of num_matches 49491678Srobert * pci_match_conf structures. match_buf is a pointer to the pci_conf 49591295Srobert * structure that will be compared to every entry in the matches array. 49691678Srobert * This function returns 1 on failure, 0 on success. 49791678Srobert */ 49891678Srobertstatic int 49991295Srobertpci_conf_match(struct pci_match_conf *matches, int num_matches, 50091295Srobert struct pci_conf *match_buf) 50191678Srobert{ 50291678Srobert int i; 50391295Srobert 50491295Srobert if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0)) 50591295Srobert return(1); 50691678Srobert 50791678Srobert for (i = 0; i < num_matches; i++) { 50891295Srobert /* 50991295Srobert * I'm not sure why someone would do this...but... 51091295Srobert */ 51191295Srobert if (matches[i].flags == PCI_GETCONF_NO_MATCH) 51291678Srobert continue; 51391678Srobert 51491295Srobert /* 51591295Srobert * Look at each of the match flags. If it's set, do the 51691295Srobert * comparison. If the comparison fails, we don't have a 51791295Srobert * match, go on to the next item if there is one. 51891295Srobert */ 51991295Srobert if (((matches[i].flags & PCI_GETCONF_MATCH_BUS) != 0) 52091295Srobert && (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus)) 52191678Srobert continue; 52291678Srobert 52391295Srobert if (((matches[i].flags & PCI_GETCONF_MATCH_DEV) != 0) 52491295Srobert && (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev)) 52591295Srobert continue; 52691295Srobert 52791295Srobert if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC) != 0) 52891295Srobert && (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func)) 52991295Srobert continue; 53091678Srobert 53191295Srobert if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR) != 0) 53291678Srobert && (match_buf->pc_vendor != matches[i].pc_vendor)) 53391678Srobert continue; 53491678Srobert 53591678Srobert if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE) != 0) 53691678Srobert && (match_buf->pc_device != matches[i].pc_device)) 53791295Srobert continue; 53891678Srobert 53990699Srobert if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS) != 0) 54091295Srobert && (match_buf->pc_class != matches[i].pc_class)) 54190699Srobert continue; 54291295Srobert 54391295Srobert if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT) != 0) 54490699Srobert && (match_buf->pd_unit != matches[i].pd_unit)) 54590699Srobert continue; 54690699Srobert 54790699Srobert if (((matches[i].flags & PCI_GETCONF_MATCH_NAME) != 0) 54890699Srobert && (strncmp(matches[i].pd_name, match_buf->pd_name, 54991295Srobert sizeof(match_buf->pd_name)) != 0)) 55091295Srobert continue; 55191295Srobert 55291295Srobert return(0); 55390699Srobert } 554 555 return(1); 556} 557 558static int 559pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 560{ 561 struct pci_io *io; 562 const char *name; 563 int error; 564 565 if (!(flag & FWRITE)) 566 return EPERM; 567 568 569 switch(cmd) { 570 case PCIOCGETCONF: 571 { 572 struct pci_devinfo *dinfo; 573 struct pci_conf_io *cio; 574 struct devlist *devlist_head; 575 struct pci_match_conf *pattern_buf; 576 int num_patterns; 577 size_t iolen; 578 int ionum, i; 579 580 cio = (struct pci_conf_io *)data; 581 582 num_patterns = 0; 583 dinfo = NULL; 584 585 /* 586 * Hopefully the user won't pass in a null pointer, but it 587 * can't hurt to check. 588 */ 589 if (cio == NULL) { 590 error = EINVAL; 591 break; 592 } 593 594 /* 595 * If the user specified an offset into the device list, 596 * but the list has changed since they last called this 597 * ioctl, tell them that the list has changed. They will 598 * have to get the list from the beginning. 599 */ 600 if ((cio->offset != 0) 601 && (cio->generation != pci_generation)){ 602 cio->num_matches = 0; 603 cio->status = PCI_GETCONF_LIST_CHANGED; 604 error = 0; 605 break; 606 } 607 608 /* 609 * Check to see whether the user has asked for an offset 610 * past the end of our list. 611 */ 612 if (cio->offset >= pci_numdevs) { 613 cio->num_matches = 0; 614 cio->status = PCI_GETCONF_LAST_DEVICE; 615 error = 0; 616 break; 617 } 618 619 /* get the head of the device queue */ 620 devlist_head = &pci_devq; 621 622 /* 623 * Determine how much room we have for pci_conf structures. 624 * Round the user's buffer size down to the nearest 625 * multiple of sizeof(struct pci_conf) in case the user 626 * didn't specify a multiple of that size. 627 */ 628 iolen = min(cio->match_buf_len - 629 (cio->match_buf_len % sizeof(struct pci_conf)), 630 pci_numdevs * sizeof(struct pci_conf)); 631 632 /* 633 * Since we know that iolen is a multiple of the size of 634 * the pciconf union, it's okay to do this. 635 */ 636 ionum = iolen / sizeof(struct pci_conf); 637 638 /* 639 * If this test is true, the user wants the pci_conf 640 * structures returned to match the supplied entries. 641 */ 642 if ((cio->num_patterns > 0) 643 && (cio->pat_buf_len > 0)) { 644 /* 645 * pat_buf_len needs to be: 646 * num_patterns * sizeof(struct pci_match_conf) 647 * While it is certainly possible the user just 648 * allocated a large buffer, but set the number of 649 * matches correctly, it is far more likely that 650 * their kernel doesn't match the userland utility 651 * they're using. It's also possible that the user 652 * forgot to initialize some variables. Yes, this 653 * may be overly picky, but I hazard to guess that 654 * it's far more likely to just catch folks that 655 * updated their kernel but not their userland. 656 */ 657 if ((cio->num_patterns * 658 sizeof(struct pci_match_conf)) != cio->pat_buf_len){ 659 /* The user made a mistake, return an error*/ 660 cio->status = PCI_GETCONF_ERROR; 661 printf("pci_ioctl: pat_buf_len %d != " 662 "num_patterns (%d) * sizeof(struct " 663 "pci_match_conf) (%d)\npci_ioctl: " 664 "pat_buf_len should be = %d\n", 665 cio->pat_buf_len, cio->num_patterns, 666 (int)sizeof(struct pci_match_conf), 667 (int)sizeof(struct pci_match_conf) * 668 cio->num_patterns); 669 printf("pci_ioctl: do your headers match your " 670 "kernel?\n"); 671 cio->num_matches = 0; 672 error = EINVAL; 673 break; 674 } 675 676 /* 677 * Check the user's buffer to make sure it's readable. 678 */ 679 if ((error = useracc((caddr_t)cio->patterns, 680 cio->pat_buf_len, B_READ)) != 1){ 681 printf("pci_ioctl: pattern buffer %p, " 682 "length %u isn't user accessible for" 683 " READ\n", cio->patterns, 684 cio->pat_buf_len); 685 error = EACCES; 686 break; 687 } 688 /* 689 * Allocate a buffer to hold the patterns. 690 */ 691 pattern_buf = malloc(cio->pat_buf_len, M_TEMP, 692 M_WAITOK); 693 error = copyin(cio->patterns, pattern_buf, 694 cio->pat_buf_len); 695 if (error != 0) 696 break; 697 num_patterns = cio->num_patterns; 698 699 } else if ((cio->num_patterns > 0) 700 || (cio->pat_buf_len > 0)) { 701 /* 702 * The user made a mistake, spit out an error. 703 */ 704 cio->status = PCI_GETCONF_ERROR; 705 cio->num_matches = 0; 706 printf("pci_ioctl: invalid GETCONF arguments\n"); 707 error = EINVAL; 708 break; 709 } else 710 pattern_buf = NULL; 711 712 /* 713 * Make sure we can write to the match buffer. 714 */ 715 if ((error = useracc((caddr_t)cio->matches, cio->match_buf_len, 716 B_WRITE)) != 1) { 717 printf("pci_ioctl: match buffer %p, length %u " 718 "isn't user accessible for WRITE\n", 719 cio->matches, cio->match_buf_len); 720 error = EACCES; 721 break; 722 } 723 724 /* 725 * Go through the list of devices and copy out the devices 726 * that match the user's criteria. 727 */ 728 for (cio->num_matches = 0, error = 0, i = 0, 729 dinfo = STAILQ_FIRST(devlist_head); 730 (dinfo != NULL) && (cio->num_matches < ionum) 731 && (error == 0) && (i < pci_numdevs); 732 dinfo = STAILQ_NEXT(dinfo, pci_links), i++) { 733 734 if (i < cio->offset) 735 continue; 736 737 /* Populate pd_name and pd_unit */ 738 name = NULL; 739 if (dinfo->cfg.dev && dinfo->conf.pd_name[0] == '\0') 740 name = device_get_name(dinfo->cfg.dev); 741 if (name) { 742 strncpy(dinfo->conf.pd_name, name, 743 sizeof(dinfo->conf.pd_name)); 744 dinfo->conf.pd_name[PCI_MAXNAMELEN] = 0; 745 dinfo->conf.pd_unit = 746 device_get_unit(dinfo->cfg.dev); 747 } 748 749 if ((pattern_buf == NULL) || 750 (pci_conf_match(pattern_buf, num_patterns, 751 &dinfo->conf) == 0)) { 752 753 /* 754 * If we've filled up the user's buffer, 755 * break out at this point. Since we've 756 * got a match here, we'll pick right back 757 * up at the matching entry. We can also 758 * tell the user that there are more matches 759 * left. 760 */ 761 if (cio->num_matches >= ionum) 762 break; 763 764 error = copyout(&dinfo->conf, 765 &cio->matches[cio->num_matches], 766 sizeof(struct pci_conf)); 767 cio->num_matches++; 768 } 769 } 770 771 /* 772 * Set the pointer into the list, so if the user is getting 773 * n records at a time, where n < pci_numdevs, 774 */ 775 cio->offset = i; 776 777 /* 778 * Set the generation, the user will need this if they make 779 * another ioctl call with offset != 0. 780 */ 781 cio->generation = pci_generation; 782 783 /* 784 * If this is the last device, inform the user so he won't 785 * bother asking for more devices. If dinfo isn't NULL, we 786 * know that there are more matches in the list because of 787 * the way the traversal is done. 788 */ 789 if (dinfo == NULL) 790 cio->status = PCI_GETCONF_LAST_DEVICE; 791 else 792 cio->status = PCI_GETCONF_MORE_DEVS; 793 794 if (pattern_buf != NULL) 795 free(pattern_buf, M_TEMP); 796 797 break; 798 } 799 case PCIOCREAD: 800 io = (struct pci_io *)data; 801 switch(io->pi_width) { 802 pcicfgregs probe; 803 case 4: 804 case 2: 805 case 1: 806 probe.bus = io->pi_sel.pc_bus; 807 probe.slot = io->pi_sel.pc_dev; 808 probe.func = io->pi_sel.pc_func; 809 io->pi_data = pci_cfgread(&probe, 810 io->pi_reg, io->pi_width); 811 error = 0; 812 break; 813 default: 814 error = ENODEV; 815 break; 816 } 817 break; 818 819 case PCIOCWRITE: 820 io = (struct pci_io *)data; 821 switch(io->pi_width) { 822 pcicfgregs probe; 823 case 4: 824 case 2: 825 case 1: 826 probe.bus = io->pi_sel.pc_bus; 827 probe.slot = io->pi_sel.pc_dev; 828 probe.func = io->pi_sel.pc_func; 829 pci_cfgwrite(&probe, 830 io->pi_reg, io->pi_data, io->pi_width); 831 error = 0; 832 break; 833 default: 834 error = ENODEV; 835 break; 836 } 837 break; 838 839 default: 840 error = ENOTTY; 841 break; 842 } 843 844 return (error); 845} 846 847#define PCI_CDEV 78 848 849static struct cdevsw pcicdev = { 850 pci_open, pci_close, noread, nowrite, pci_ioctl, nostop, noreset, 851 nodevtotty, seltrue, nommap, nostrategy, "pci", 0, PCI_CDEV 852}; 853 854#ifdef DEVFS 855static void *pci_devfs_token; 856#endif 857 858static void 859pci_cdevinit(void *dummy) 860{ 861 dev_t dev; 862 863 dev = makedev(PCI_CDEV, 0); 864 cdevsw_add(&dev, &pcicdev, NULL); 865#ifdef DEVFS 866 pci_devfs_token = devfs_add_devswf(&pcicdev, 0, DV_CHR, 867 UID_ROOT, GID_WHEEL, 0644, "pci"); 868#endif 869} 870 871SYSINIT(pcidev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+PCI_CDEV, pci_cdevinit, NULL); 872 873#include "pci_if.h" 874 875/* 876 * A simple driver to wrap the old pci driver mechanism for back-compat. 877 */ 878 879static int 880pci_compat_probe(device_t dev) 881{ 882 struct pci_device *dvp; 883 struct pci_devinfo *dinfo; 884 pcicfgregs *cfg; 885 const char *name; 886 int error; 887 888 dinfo = device_get_ivars(dev); 889 cfg = &dinfo->cfg; 890 dvp = device_get_driver(dev)->priv; 891 892 /* 893 * Do the wrapped probe. 894 */ 895 error = ENXIO; 896 if (dvp && dvp->pd_probe) { 897 name = dvp->pd_probe(cfg, (cfg->device << 16) + cfg->vendor); 898 if (name) { 899 device_set_desc_copy(dev, name); 900 error = 0; 901 } 902 } 903 904 return error; 905} 906 907static int 908pci_compat_attach(device_t dev) 909{ 910 struct pci_device *dvp; 911 struct pci_devinfo *dinfo; 912 pcicfgregs *cfg; 913 int unit; 914 915 dinfo = device_get_ivars(dev); 916 cfg = &dinfo->cfg; 917 dvp = device_get_driver(dev)->priv; 918 919 unit = device_get_unit(dev); 920 if (unit > *dvp->pd_count) 921 *dvp->pd_count = unit; 922 if (dvp->pd_attach) 923 dvp->pd_attach(cfg, unit); 924 return 0; 925} 926 927static device_method_t pci_compat_methods[] = { 928 /* Device interface */ 929 DEVMETHOD(device_probe, pci_compat_probe), 930 DEVMETHOD(device_attach, pci_compat_attach), 931 932 { 0, 0 } 933}; 934 935static devclass_t pci_devclass; 936 937/* 938 * Create a new style driver around each old pci driver. 939 */ 940int 941compat_pci_handler(module_t mod, int type, void *data) 942{ 943 struct pci_device *dvp = (struct pci_device *)data; 944 driver_t *driver; 945 946 switch (type) { 947 case MOD_LOAD: 948 driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT); 949 if (!driver) 950 return ENOMEM; 951 bzero(driver, sizeof(driver_t)); 952 driver->name = dvp->pd_name; 953 driver->methods = pci_compat_methods; 954 driver->softc = sizeof(struct pci_devinfo *); 955 driver->priv = dvp; 956 devclass_add_driver(pci_devclass, driver); 957 break; 958 case MOD_UNLOAD: 959 printf("%s: module unload not supported!\n", dvp->pd_name); 960 return EOPNOTSUPP; 961 default: 962 break; 963 } 964 return 0; 965} 966 967/* 968 * New style pci driver. Parent device is either a pci-host-bridge or a 969 * pci-pci-bridge. Both kinds are represented by instances of pcib. 970 */ 971 972static void 973pci_print_verbose(struct pci_devinfo *dinfo) 974{ 975 if (bootverbose) { 976 int i; 977 pcicfgregs *cfg = &dinfo->cfg; 978 979 printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", 980 cfg->vendor, cfg->device, cfg->revid); 981 printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", 982 cfg->baseclass, cfg->subclass, cfg->progif, 983 cfg->hdrtype, cfg->mfdev); 984 printf("\tsubordinatebus=%x \tsecondarybus=%x\n", 985 cfg->subordinatebus, cfg->secondarybus); 986#ifdef PCI_DEBUG 987 printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n", 988 cfg->cmdreg, cfg->statreg, cfg->cachelnsz); 989 printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n", 990 cfg->lattimer, cfg->lattimer * 30, 991 cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250); 992#endif /* PCI_DEBUG */ 993 if (cfg->intpin > 0) 994 printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline); 995 996 for (i = 0; i < cfg->nummaps; i++) { 997 pcimap *m = &cfg->map[i]; 998 printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n", 999 i, m->type, m->ln2range, m->base, m->ln2size); 1000 } 1001 } 1002} 1003 1004static int 1005pci_add_children(device_t dev, int busno) 1006{ 1007 pcicfgregs probe; 1008 int bushigh = busno; 1009 1010#ifdef SIMOS 1011#undef PCI_SLOTMAX 1012#define PCI_SLOTMAX 0 1013#endif 1014 1015 bzero(&probe, sizeof probe); 1016#ifdef __alpha__ 1017 probe.hose = pcib_get_hose(dev); 1018#endif 1019#ifdef __i386__ 1020 probe.hose = 0; 1021#endif 1022 probe.bus = busno; 1023 1024 for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { 1025 int pcifunchigh = 0; 1026 for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) { 1027 struct pci_devinfo *dinfo = pci_readcfg(&probe); 1028 if (dinfo != NULL) { 1029 if (dinfo->cfg.mfdev) 1030 pcifunchigh = 7; 1031 1032 pci_print_verbose(dinfo); 1033 dinfo->cfg.dev = 1034 device_add_child(dev, NULL, -1, dinfo); 1035 1036 if (bushigh < dinfo->cfg.subordinatebus) 1037 bushigh = dinfo->cfg.subordinatebus; 1038 if (bushigh < dinfo->cfg.secondarybus) 1039 bushigh = dinfo->cfg.secondarybus; 1040 } 1041 } 1042 } 1043 1044 return bushigh; 1045} 1046 1047static int 1048pci_new_probe(device_t dev) 1049{ 1050 device_set_desc(dev, "PCI bus"); 1051 1052 pci_add_children(dev, device_get_unit(dev)); 1053 1054 return 0; 1055} 1056 1057static void 1058pci_print_child(device_t dev, device_t child) 1059{ 1060 struct pci_devinfo *dinfo; 1061 pcicfgregs *cfg; 1062 1063 dinfo = device_get_ivars(child); 1064 cfg = &dinfo->cfg; 1065 if (cfg->intpin > 0 && cfg->intline != 255) 1066 printf(" irq %d", cfg->intline); 1067 printf(" at device %d.%d", pci_get_slot(child), pci_get_function(child)); 1068 printf(" on %s%d", device_get_name(dev), device_get_unit(dev)); 1069} 1070 1071static int 1072pci_read_ivar(device_t dev, device_t child, int which, u_long *result) 1073{ 1074 struct pci_devinfo *dinfo; 1075 pcicfgregs *cfg; 1076 1077 dinfo = device_get_ivars(child); 1078 cfg = &dinfo->cfg; 1079 1080 switch (which) { 1081 case PCI_IVAR_SUBVENDOR: 1082 *result = cfg->subvendor; 1083 break; 1084 case PCI_IVAR_SUBDEVICE: 1085 *result = cfg->subdevice; 1086 break; 1087 case PCI_IVAR_VENDOR: 1088 *result = cfg->vendor; 1089 break; 1090 case PCI_IVAR_DEVICE: 1091 *result = cfg->device; 1092 break; 1093 case PCI_IVAR_DEVID: 1094 *result = (cfg->device << 16) | cfg->vendor; 1095 break; 1096 case PCI_IVAR_CLASS: 1097 *result = cfg->baseclass; 1098 break; 1099 case PCI_IVAR_SUBCLASS: 1100 *result = cfg->subclass; 1101 break; 1102 case PCI_IVAR_PROGIF: 1103 *result = cfg->progif; 1104 break; 1105 case PCI_IVAR_REVID: 1106 *result = cfg->revid; 1107 break; 1108 case PCI_IVAR_INTPIN: 1109 *result = cfg->intpin; 1110 break; 1111 case PCI_IVAR_IRQ: 1112 *result = cfg->intline; 1113 break; 1114 case PCI_IVAR_BUS: 1115 *result = cfg->bus; 1116 break; 1117 case PCI_IVAR_SLOT: 1118 *result = cfg->slot; 1119 break; 1120 case PCI_IVAR_FUNCTION: 1121 *result = cfg->func; 1122 break; 1123 case PCI_IVAR_SECONDARYBUS: 1124 *result = cfg->secondarybus; 1125 break; 1126 case PCI_IVAR_SUBORDINATEBUS: 1127 *result = cfg->subordinatebus; 1128 break; 1129 case PCI_IVAR_HOSE: 1130 /* 1131 * Pass up to parent bridge. 1132 */ 1133 *result = pcib_get_hose(dev); 1134 break; 1135 default: 1136 return ENOENT; 1137 } 1138 return 0; 1139} 1140 1141static int 1142pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 1143{ 1144 struct pci_devinfo *dinfo; 1145 pcicfgregs *cfg; 1146 1147 dinfo = device_get_ivars(child); 1148 cfg = &dinfo->cfg; 1149 1150 switch (which) { 1151 case PCI_IVAR_SUBVENDOR: 1152 case PCI_IVAR_SUBDEVICE: 1153 case PCI_IVAR_VENDOR: 1154 case PCI_IVAR_DEVICE: 1155 case PCI_IVAR_DEVID: 1156 case PCI_IVAR_CLASS: 1157 case PCI_IVAR_SUBCLASS: 1158 case PCI_IVAR_PROGIF: 1159 case PCI_IVAR_REVID: 1160 case PCI_IVAR_INTPIN: 1161 case PCI_IVAR_IRQ: 1162 case PCI_IVAR_BUS: 1163 case PCI_IVAR_SLOT: 1164 case PCI_IVAR_FUNCTION: 1165 return EINVAL; /* disallow for now */ 1166 1167 case PCI_IVAR_SECONDARYBUS: 1168 cfg->secondarybus = value; 1169 break; 1170 case PCI_IVAR_SUBORDINATEBUS: 1171 cfg->subordinatebus = value; 1172 break; 1173 default: 1174 return ENOENT; 1175 } 1176 return 0; 1177} 1178 1179static int 1180pci_mapno(pcicfgregs *cfg, int reg) 1181{ 1182 int i, nummaps; 1183 pcimap *map; 1184 1185 nummaps = cfg->nummaps; 1186 map = cfg->map; 1187 1188 for (i = 0; i < nummaps; i++) 1189 if (map[i].reg == reg) 1190 return (i); 1191 return (-1); 1192} 1193 1194static int 1195pci_porten(pcicfgregs *cfg) 1196{ 1197 return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); 1198} 1199 1200static int 1201pci_isportmap(pcicfgregs *cfg, int map) 1202 1203{ 1204 return ((unsigned)map < cfg->nummaps 1205 && (cfg->map[map].type & PCI_MAPPORT) != 0); 1206} 1207 1208static int 1209pci_memen(pcicfgregs *cfg) 1210{ 1211 return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); 1212} 1213 1214static int 1215pci_ismemmap(pcicfgregs *cfg, int map) 1216{ 1217 return ((unsigned)map < cfg->nummaps 1218 && (cfg->map[map].type & PCI_MAPMEM) != 0); 1219} 1220 1221static struct resource * 1222pci_alloc_resource(device_t dev, device_t child, int type, int *rid, 1223 u_long start, u_long end, u_long count, u_int flags) 1224{ 1225 int isdefault; 1226 struct pci_devinfo *dinfo = device_get_ivars(child); 1227 pcicfgregs *cfg = &dinfo->cfg; 1228 struct resource *rv, **rvp = 0; 1229 int map; 1230 1231 isdefault = (device_get_parent(child) == dev 1232 && start == 0UL && end == ~0UL && count == 1); 1233 1234 switch (type) { 1235 case SYS_RES_IRQ: 1236 if (*rid != 0) 1237 return 0; 1238 if (isdefault && cfg->intline != 255) { 1239 start = cfg->intline; 1240 end = cfg->intline; 1241 count = 1; 1242 } 1243 break; 1244 1245 case SYS_RES_DRQ: /* passthru for child isa */ 1246 break; 1247 1248 case SYS_RES_MEMORY: 1249 if (isdefault) { 1250 map = pci_mapno(cfg, *rid); 1251 if (pci_memen(cfg) && pci_ismemmap(cfg, map)) { 1252 start = cfg->map[map].base; 1253 count = 1 << cfg->map[map].ln2size; 1254 end = start + count; 1255 rvp = &cfg->map[map].res; 1256 } else 1257 return 0; 1258 } 1259 break; 1260 1261 case SYS_RES_IOPORT: 1262 if (isdefault) { 1263 map = pci_mapno(cfg, *rid); 1264 if (pci_porten(cfg) && pci_isportmap(cfg, map)) { 1265 start = cfg->map[map].base; 1266 count = 1 << cfg->map[map].ln2size; 1267 end = start + count; 1268 rvp = &cfg->map[map].res; 1269 } else 1270 return 0; 1271 } 1272 break; 1273 1274 default: 1275 return 0; 1276 } 1277 1278 rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 1279 type, rid, start, end, count, flags); 1280 if (rvp) 1281 *rvp = rv; 1282 1283 return rv; 1284} 1285 1286static int 1287pci_release_resource(device_t dev, device_t child, int type, int rid, 1288 struct resource *r) 1289{ 1290 int rv; 1291 struct pci_devinfo *dinfo = device_get_ivars(child); 1292 pcicfgregs *cfg = &dinfo->cfg; 1293 int map = 0; 1294 1295 switch (type) { 1296 case SYS_RES_IRQ: 1297 if (rid != 0) 1298 return EINVAL; 1299 break; 1300 1301 case SYS_RES_DRQ: /* passthru for child isa */ 1302 break; 1303 1304 case SYS_RES_MEMORY: 1305 case SYS_RES_IOPORT: 1306 /* 1307 * Only check the map registers if this is a direct 1308 * descendant. 1309 */ 1310 if (device_get_parent(child) == dev) 1311 map = pci_mapno(cfg, rid); 1312 else 1313 map = -1; 1314 break; 1315 1316 default: 1317 return (ENOENT); 1318 } 1319 1320 rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); 1321 1322 if (rv == 0) { 1323 switch (type) { 1324 case SYS_RES_IRQ: 1325 cfg->irqres = 0; 1326 break; 1327 1328 case SYS_RES_DRQ: /* passthru for child isa */ 1329 break; 1330 1331 case SYS_RES_MEMORY: 1332 case SYS_RES_IOPORT: 1333 if (map != -1) 1334 cfg->map[map].res = 0; 1335 break; 1336 1337 default: 1338 return ENOENT; 1339 } 1340 } 1341 1342 return rv; 1343} 1344 1345static u_int32_t 1346pci_read_config_method(device_t dev, device_t child, int reg, int width) 1347{ 1348 struct pci_devinfo *dinfo = device_get_ivars(child); 1349 pcicfgregs *cfg = &dinfo->cfg; 1350 return pci_cfgread(cfg, reg, width); 1351} 1352 1353static void 1354pci_write_config_method(device_t dev, device_t child, int reg, 1355 u_int32_t val, int width) 1356{ 1357 struct pci_devinfo *dinfo = device_get_ivars(child); 1358 pcicfgregs *cfg = &dinfo->cfg; 1359 pci_cfgwrite(cfg, reg, val, width); 1360} 1361 1362static int 1363pci_modevent(module_t mod, int what, void *arg) 1364{ 1365 switch (what) { 1366 case MOD_LOAD: 1367 STAILQ_INIT(&pci_devq); 1368 break; 1369 1370 case MOD_UNLOAD: 1371 break; 1372 } 1373 1374 return 0; 1375} 1376 1377static device_method_t pci_methods[] = { 1378 /* Device interface */ 1379 DEVMETHOD(device_probe, pci_new_probe), 1380 DEVMETHOD(device_attach, bus_generic_attach), 1381 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1382 DEVMETHOD(device_suspend, bus_generic_suspend), 1383 DEVMETHOD(device_resume, bus_generic_resume), 1384 1385 /* Bus interface */ 1386 DEVMETHOD(bus_print_child, pci_print_child), 1387 DEVMETHOD(bus_read_ivar, pci_read_ivar), 1388 DEVMETHOD(bus_write_ivar, pci_write_ivar), 1389 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 1390 DEVMETHOD(bus_alloc_resource, pci_alloc_resource), 1391 DEVMETHOD(bus_release_resource, pci_release_resource), 1392 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 1393 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1394 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 1395 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 1396 1397 /* PCI interface */ 1398 DEVMETHOD(pci_read_config, pci_read_config_method), 1399 DEVMETHOD(pci_write_config, pci_write_config_method), 1400 1401 { 0, 0 } 1402}; 1403 1404static driver_t pci_driver = { 1405 "pci", 1406 pci_methods, 1407 1, /* no softc */ 1408}; 1409 1410DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0); 1411 1412#endif /* NPCI > 0 */ 1413