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