code:
/*	$OpenBSD: pciide_machdep.c,v 1.8 2009/10/05 20:37:45 deraadt Exp $	*/
/*	$NetBSD: pciide_machdep.c,v 1.2 1999/02/19 18:01:27 mycroft Exp $	*/

/*-
 * Copyright (c) 2007 Juan Romero Pardines.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1998 Christopher G. Demetriou.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by Christopher G. Demetriou
 *	for the NetBSD Project.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * PCI IDE controller driver (i386 machine-dependent portion).
 *
 * Author: Christopher G. Demetriou, March 2, 1998 (derived from NetBSD
 * sys/dev/pci/ppb.c, revision 1.16).
 *
 * See "PCI IDE Controller Specification, Revision 1.0 3/4/94" from the
 * PCI SIG.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pciidereg.h>
#include <dev/pci/pciidevar.h>

#include <dev/isa/isavar.h>

#include <machine/cpufunc.h>
#include <i386/pci/pciide_gcsc_reg.h>

void gcsc_setup_channel(struct channel_softc *);

void *
pciide_machdep_compat_intr_establish(struct device *dev,
    struct pci_attach_args *pa, int chan, int (*func)(void *), void *arg)
{
	int irq;
	void *cookie;

	irq = PCIIDE_COMPAT_IRQ(chan);
	cookie = isa_intr_establish(NULL, irq, IST_EDGE, IPL_BIO, func, arg,
	    dev->dv_xname);

	return (cookie);
}

void
pciide_machdep_compat_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
{
	isa_intr_disestablish(NULL, cookie);
}

void
gcsc_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
{
	struct pciide_channel *cp;
	pcireg_t interface;
	bus_size_t cmdsize, ctlsize;

	printf(": DMA");
	pciide_mapreg_dma(sc, pa);

	sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
	    WDC_CAPABILITY_MODE;
	if (sc->sc_dma_ok) {
		sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;
		sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK;
		sc->sc_wdcdev.irqack = pciide_irqack;
	}

	sc->sc_wdcdev.PIO_cap = 4;
	sc->sc_wdcdev.DMA_cap = 2;
	sc->sc_wdcdev.UDMA_cap = 4;
	sc->sc_wdcdev.set_modes = gcsc_setup_channel;
	sc->sc_wdcdev.channels = sc->wdc_chanarray;
	sc->sc_wdcdev.nchannels = 1;

	interface = PCI_INTERFACE(pa->pa_class);

	pciide_print_channels(sc->sc_wdcdev.nchannels, interface);

	cp = &sc->pciide_channels[0];

	if (pciide_chansetup(sc, 0, interface) == 0)
		return;

	pciide_map_compat_intr(pa, cp, 0, interface);
	if (cp->hw_ok == 0)
		return;

	pciide_mapchan(pa, cp, interface,
	    &cmdsize, &ctlsize, pciide_pci_intr);
	if (cp->hw_ok == 0) {
		pciide_unmap_compat_intr(pa, cp, 0, interface);
		return;
	}

	gcsc_setup_channel(&cp->wdc_channel);
}

void
gcsc_setup_channel(struct channel_softc *chp)
{
	struct pciide_channel *cp = (struct pciide_channel *)chp;
	struct ata_drive_datas *drvp;
	uint64_t reg = 0;
	int drive, s;

	pciide_channel_dma_setup(cp);

	for (drive = 0; drive < 2; drive++) {
		drvp = &chp->ch_drive[drive];
		if ((drvp->drive_flags & DRIVE) == 0)
			continue;

		reg = rdmsr(drive ? GCSC_ATAC_CH0D1_DMA :
		    GCSC_ATAC_CH0D0_DMA);

		if (drvp->drive_flags & DRIVE_UDMA) {
			s = splbio();
			drvp->drive_flags &= ~DRIVE_DMA;
			splx(s);
			/* Enable the Ultra DMA mode bit */
			reg |= GCSC_ATAC_DMA_SEL;
			/* set the Ultra DMA mode */
			reg |= gcsc_udma_timings[drvp->UDMA_mode];

			wrmsr(drive ? GCSC_ATAC_CH0D1_DMA :
			    GCSC_ATAC_CH0D0_DMA, reg);

		} else if (drvp->drive_flags & DRIVE_DMA) {
			/* Enable the Multi-word DMA bit */
			reg &= ~GCSC_ATAC_DMA_SEL;
			/* set the Multi-word DMA mode */
			reg |= gcsc_mdma_timings[drvp->DMA_mode];

			wrmsr(drive ? GCSC_ATAC_CH0D1_DMA :
			    GCSC_ATAC_CH0D0_DMA, reg);
		}

		/* Always use PIO Format 1. */
		wrmsr(drive ? GCSC_ATAC_CH0D1_DMA :
		    GCSC_ATAC_CH0D0_DMA, reg | GCSC_ATAC_PIO_FORMAT);

		/* Set PIO mode */
		wrmsr(drive ? GCSC_ATAC_CH0D1_PIO : GCSC_ATAC_CH0D0_PIO,
		    gcsc_pio_timings[drvp->PIO_mode]);
	}

	pciide_print_modes(cp);
}


code:
/*	$OpenBSD: piix.c,v 1.10 2014/07/12 18:44:42 tedu Exp $	*/
/*	$NetBSD: piix.c,v 1.1 1999/11/17 01:21:20 thorpej Exp $	*/

/*-
 * Copyright (c) 1999 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Support for the Intel PIIX PCI-ISA bridge interrupt controller.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>

#include <machine/intr.h>
#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <i386/pci/pcibiosvar.h>
#include <i386/pci/piixreg.h>
#include <i386/pci/piixvar.h>

#ifdef PIIX_DEBUG
#define	DPRINTF(arg) printf arg
#else
#define	DPRINTF(arg)
#endif

int	piix_getclink(pciintr_icu_handle_t, int, int *);
int	piix_get_intr(pciintr_icu_handle_t, int, int *);
int	piix_set_intr(pciintr_icu_handle_t, int, int);
#ifdef PIIX_DEBUG
void	piix_pir_dump(struct piix_handle *);
#endif

const struct pciintr_icu piix_pci_icu = {
	piix_getclink,
	piix_get_intr,
	piix_set_intr,
	piix_get_trigger,
	piix_set_trigger,
};

int
piix_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
    pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
{
	struct piix_handle *ph;

	ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
	if (ph == NULL)
		return (1);

	ph->ph_iot = iot;
	ph->ph_pc = pc;
	ph->ph_tag = tag;

	if (bus_space_map(iot, PIIX_REG_ELCR, PIIX_REG_ELCR_SIZE, 0,
	    &ph->ph_elcr_ioh) != 0) {
		free(ph, M_DEVBUF, 0);
		return (1);
	}

#ifdef PIIX_DEBUG
	piix_pir_dump(ph);
#endif
	*ptagp = &piix_pci_icu;
	*phandp = ph;
	return (0);
}

int
piix_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
{
	DPRINTF(("PIIX link value 0x%x: ", link));

	/* Pattern 1: simple. */
	if (PIIX_LEGAL_LINK(link - 1)) {
		*clinkp = link - 1;
		DPRINTF(("PIRQ %d (simple)\n", *clinkp));
		return (0);
	}

	/* Pattern 2: configuration register offset */
	if (link >= 0x60 && link <= 0x63) {
		*clinkp = link - 0x60;
		DPRINTF(("PIRQ %d (register offset)\n", *clinkp));
		return (0);
	}

	/* Pattern 3: configuration register offset, PIRQE# - PIRQH# */
	if (link >= 0x68 && link <= 0x6b) {
		*clinkp = link - 0x64;
		DPRINTF(("PIRQ %d (high register offset)\n", *clinkp));
		return (0);
	}

	DPRINTF(("bogus IRQ selection source\n"));
	return (1);
}

int
piix_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
{
	struct piix_handle *ph = v;
	int shift, off;
	pcireg_t reg;

	if (PIIX_LEGAL_LINK(clink) == 0)
		return (1);

	off = PIIX_CFG_PIRQ;
	if (clink > 3) {
		off += 8;
		clink -= 4;
	}

	reg = pci_conf_read(ph->ph_pc, ph->ph_tag, off);
	shift = clink << 3;
	if ((reg >> shift) & PIIX_CFG_PIRQ_NONE)
		*irqp = I386_PCI_INTERRUPT_LINE_NO_CONNECTION;
	else
		*irqp = PIIX_PIRQ(reg, clink);

	return (0);
}

int
piix_set_intr(pciintr_icu_handle_t v, int clink, int irq)
{
	struct piix_handle *ph = v;
	int shift, off;
	pcireg_t reg;

	if (PIIX_LEGAL_LINK(clink) == 0 || PIIX_LEGAL_IRQ(irq) == 0)
		return (1);

	off = PIIX_CFG_PIRQ;
	if (clink > 3) {
		off += 8;
		clink -= 4;
	}

	reg = pci_conf_read(ph->ph_pc, ph->ph_tag, off);
	shift = clink << 3;
	reg &= ~((PIIX_CFG_PIRQ_NONE | PIIX_CFG_PIRQ_MASK) << shift);
	reg |= irq << shift;
	pci_conf_write(ph->ph_pc, ph->ph_tag, off, reg);

	return (0);
}

int
piix_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
{
	struct piix_handle *ph = v;
	int off, bit;
	u_int8_t elcr;

	if (PIIX_LEGAL_IRQ(irq) == 0)
		return (1);

	off = (irq > 7) ? 1 : 0;
	bit = irq & 7;

	elcr = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, off);
	if (elcr & (1 << bit))
		*triggerp = IST_LEVEL;
	else
		*triggerp = IST_EDGE;

	return (0);
}

int
piix_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
{
	struct piix_handle *ph = v;
	int off, bit;
	u_int8_t elcr;

	if (PIIX_LEGAL_IRQ(irq) == 0)
		return (1);

	off = (irq > 7) ? 1 : 0;
	bit = irq & 7;

	elcr = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, off);
	if (trigger == IST_LEVEL)
		elcr |= (1 << bit);
	else
		elcr &= ~(1 << bit);
	bus_space_write_1(ph->ph_iot, ph->ph_elcr_ioh, off, elcr);

	return (0);
}

#ifdef PIIX_DEBUG
void
piix_pir_dump(struct piix_handle *ph)
{
	int i, irq;
	pcireg_t irqs = pci_conf_read(ph->ph_pc, ph->ph_tag, PIIX_CFG_PIRQ);
	u_int8_t elcr[2];

	elcr[0] = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, 0);
	elcr[1] = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, 1);

	for (i = 0; i < 8; i++) {
		if (i == 4)
			irqs = pci_conf_read(ph->ph_pc, ph->ph_tag,
			    PIIX_CFG_PIRQH);

		irq = PIIX_PIRQ(irqs, i);
		if (irq & PIIX_CFG_PIRQ_NONE)
			printf("PIIX PIRQ %d: irq none (0x%x)\n", i, irq);
		else
			printf("PIIX PIRQ %d: irq %d\n", i, irq);
	}

	printf("PIIX irq:");
	for (i = 0; i < 16; i++)
		printf(" %2d", i);
	printf("\n");
	printf(" trigger:");
	for (i = 0; i < 16; i++)
		printf("  %c", (elcr[(i & 8) ? 1 : 0] & (1 << (i & 7))) ?
		       'L' : 'E');
	printf("\n");
}
#endif /* PIIX_DEBUG */

license: unknown


code:
/*	$OpenBSD: piixpcib.c,v 1.12 2015/04/12 18:37:54 mlarkin Exp $ */

/*
 * Copyright (c) 2007 Stefan Sperling <stsp@stsp.in-berlin.de>
 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 *-
 * Copyright (c) 2004, 2006 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Minoura Makoto, Matthew R. Green, and Jared D. McNeill.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Special driver for the Intel PIIX4 bridges that attaches
 * instead of pcib(4). In addition to the core pcib(4) functionality this
 * driver provides support for Intel SpeedStep technology present in
 * some Pentium III CPUs.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/sysctl.h>

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/kvm86.h>

/* 0x47534943 == "ISGE" ('Intel Speedstep Gate E') */
#define	PIIXPCIB_ISGE			0x47534943
#define	PIIXPCIB_IST_CALL		0x0000e980
#define	PIIXPCIB_GSIC_CMD		0x82
#define	PIIXPCIB_DEFAULT_COMMAND	\
	((PIIXPCIB_ISGE & 0xffffff00) | (PIIXPCIB_GSIC_CMD & 0xff))

#define	PIIXPCIB_DEFAULT_SMI_PORT	0xb2
#define	PIIXPCIB_DEFAULT_SMI_DATA	0xb3

#define	PIIXPCIB_GETSTATE		1
#define	PIIXPCIB_SETSTATE		2
#define	PIIXPCIB_SPEEDSTEP_HIGH		0
#define	PIIXPCIB_SPEEDSTEP_LOW		1

struct piixpcib_softc {
	struct device sc_dev;

	int		sc_sig;
	int		sc_smi_port;
	int		sc_smi_data;
	int		sc_command;
	int		sc_flags;

	int		state;
};

int	piixpcib_match(struct device *, void *, void *);
void	piixpcib_attach(struct device *, struct device *, void *);

void	piixpcib_setperf(int);
int	piixpcib_cpuspeed(int *);

int	piixpcib_set_ownership(struct piixpcib_softc *);
int	piixpcib_configure_speedstep(struct piixpcib_softc *);
int	piixpcib_getset_state(struct piixpcib_softc *, int *, int);
void	piixpcib_int15_gsic_call(struct piixpcib_softc *);

/* arch/i386/pci/pcib.c */
extern void	pcibattach(struct device *, struct device *, void *);

/* arch/i386/i386/machdep.c */
#if !defined(SMALL_KERNEL)
extern void	p3_update_cpuspeed(void);
#endif

extern int cpu_pae;

struct cfattach piixpcib_ca = {
	sizeof(struct piixpcib_softc),
	piixpcib_match,
	piixpcib_attach
};

struct cfdriver piixpcib_cd = {
	NULL, "piixpcib", DV_DULL
};

struct piixpcib_softc *piixpcib_sc;
extern int setperf_prio;

const struct pci_matchid piixpcib_devices[] = {
	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371AB_ISA}, /* PIIX4 */
	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_PM},  /* PIIX4 in MX440 */
};

void
piixpcib_int15_gsic_call(struct piixpcib_softc *sc)
{
	struct kvm86regs regs;
	int cmd;

	memset(&regs, 0, sizeof(struct kvm86regs));
	regs.eax = PIIXPCIB_IST_CALL;
	regs.edx = PIIXPCIB_ISGE;
	kvm86_simplecall(0x15, &regs);

	if (regs.eax == PIIXPCIB_ISGE) {
		sc->sc_sig = regs.eax;
		sc->sc_smi_port = regs.ebx & 0xff;

		cmd = (regs.ebx >> 16) & 0xff;
		/* GSIC may return cmd 0x80, should be PIIXPCIB_GSIC_CMD */
		if (cmd == 0x80)
			cmd = PIIXPCIB_GSIC_CMD;
		sc->sc_command = (sc->sc_sig & 0xffffff00) | (cmd & 0xff);

		sc->sc_smi_data = regs.ecx;
		sc->sc_flags = regs.edx;
	}
}

int
piixpcib_set_ownership(struct piixpcib_softc *sc)
{
	int rv;
	paddr_t pmagic;
	char magic[] = "Copyright (c) 1999 Intel Corporation";

	pmap_extract(pmap_kernel(), (vaddr_t)magic, &pmagic);

	__asm volatile(
		"movl $0, %%edi\n\t"
		"out %%al, (%%dx)\n"
		: "=D" (rv)
		: "a" (sc->sc_command),
		  "b" (0),
		  "c" (0),
		  "d" (sc->sc_smi_port),
		  "S" (pmagic)
	);

	return (rv ? ENXIO : 0);
}

int
piixpcib_configure_speedstep(struct piixpcib_softc *sc)
{
	int rv;

	sc->sc_sig = -1;

	/* setup some defaults */
	sc->sc_smi_port = PIIXPCIB_DEFAULT_SMI_PORT;
	sc->sc_smi_data = PIIXPCIB_DEFAULT_SMI_DATA;
	sc->sc_command = PIIXPCIB_DEFAULT_COMMAND;
	sc->sc_flags = 0;

	if (cpu_pae)
		return ENODEV;

	piixpcib_int15_gsic_call(sc);

	/* If signature doesn't match, bail out */
	if (sc->sc_sig != PIIXPCIB_ISGE)
		return ENODEV;

	if (piixpcib_set_ownership(sc) != 0) {
		printf(": unable to claim ownership from BIOS, "
		    "SpeedStep disabled");
		return ENXIO;
	}

	rv = piixpcib_getset_state(sc, &sc->state, PIIXPCIB_GETSTATE);
	if (rv != 0) {
		printf(": cannot determine CPU power state, "
		    "SpeedStep disabled");
		return ENXIO;
	}

	/* save the sc for IO tag/handle */
	piixpcib_sc = sc;

	return 0;
}

int
piixpcib_match(struct device *parent, void *match, void *aux)
{
	if (pci_matchbyid((struct pci_attach_args *)aux, piixpcib_devices,
	    sizeof(piixpcib_devices) / sizeof(piixpcib_devices[0])))
		return (2);	/* supersede pcib(4) */
	return (0);
}

void
piixpcib_attach(struct device *parent, struct device *self, void *aux)
{
	struct piixpcib_softc *sc = (struct piixpcib_softc *)self;

	if (setperf_prio < 2) {
		/* Set up SpeedStep. */
		if (piixpcib_configure_speedstep(sc) == 0) {
			printf(": SpeedStep");

			/* Hook into hw.setperf sysctl */
			cpu_setperf = piixpcib_setperf;
			setperf_prio = 2;
		}
	}

	/* Provide core pcib(4) functionality */
	pcibattach(parent, self, aux);
}

int
piixpcib_getset_state(struct piixpcib_softc *sc, int *state, int function)
{
	int new_state;
	int rv;
	int eax;

#ifdef DIAGNOSTIC
	if (function != PIIXPCIB_GETSTATE &&
	    function != PIIXPCIB_SETSTATE) {
		printf("%s: %s called with invalid function %d\n",
		    sc->sc_dev.dv_xname, __func__, function);
		return EINVAL;
	}
#endif

	__asm volatile(
		"movl $0, %%edi\n\t"
		"out %%al, (%%dx)\n"
		: "=a" (eax),
		  "=b" (new_state),
		  "=D" (rv)
		: "a" (sc->sc_command),
		  "b" (function),
		  "c" (*state),
		  "d" (sc->sc_smi_port),
		  "S" (0)
	);

	*state = new_state & 1;

	switch (function) {
	case PIIXPCIB_GETSTATE:
		if (eax)
			return ENXIO;
		break;
	case PIIXPCIB_SETSTATE:
		if (rv)
			return ENXIO;
		break;
	}

	return 0;
}

void
piixpcib_setperf(int level)
{
	struct piixpcib_softc *sc;
	int new_state;
	int tries, rv, s;

 	sc = piixpcib_sc;

#ifdef DIAGNOSTIC
	if (sc == NULL) {
		printf("%s: no cookie", __func__);
		return;
	}
#endif

	/* Only two states are available */
	if (level <= 50)
		new_state = PIIXPCIB_SPEEDSTEP_LOW;
	else
		new_state = PIIXPCIB_SPEEDSTEP_HIGH;

	if (sc->state == new_state)
		return;

	tries = 5;
	s = splhigh();

	do {
		rv = piixpcib_getset_state(sc, &new_state,
		    PIIXPCIB_SETSTATE);
		if (rv)
			delay(200);
	} while (rv && --tries);

	splx(s);

#ifdef DIAGNOSTIC
	if (rv)
		printf("%s: setting CPU power state failed",
		    sc->sc_dev.dv_xname);
#endif

	sc->state = new_state;

	/* Force update of hw.cpuspeed.
	 *
	 * XXX: First generation SpeedStep is only present in some
	 * Pentium III CPUs and we are lacking a reliable method to
	 * determine CPU freqs corresponding to low and high power state.
	 *
	 * And yes, I've tried it the way the Linux speedstep-smi
	 * driver does it, thank you very much. It doesn't work
	 * half the time (my machine has more than 4MHz ;-) and
	 * even crashes some machines without specific workarounds.
	 *
	 * So call p3_update_cpuspeed() from arch/i386/i386/machdep.c
	 * instead. Works fine on my Thinkpad X21.
	 *
	 * BUT: Apparently, if the bus is busy, the transition may be
	 * delayed and retried under control of evil SMIs we cannot
	 * control. So busy-wait a short while before updating hw.cpuspeed
	 * to decrease chances of picking up the old CPU speed.
	 * There seems to be no reliable fix for this.
	 */
	delay(200);
#if !defined(SMALL_KERNEL)
	p3_update_cpuspeed();
#endif
}


code:
/*	$OpenBSD: piixreg.h,v 1.4 2003/03/28 23:12:33 mickey Exp $	*/
/*	$NetBSD: piixreg.h,v 1.1 1999/11/17 01:21:21 thorpej Exp $	*/

/*
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Register definitions for the Intel PIIX PCI-ISA bridge interrupt controller.
 */

/*
 * PIRQ[3:0]# - PIRQ ROUTE CONTROL REGISTERS
 *
 * PCI Configuration registers 0x60-0x63, 0x68-0x6b
 */

#define	PIIX_LEGAL_LINK(link)	((link) >= 0 && (link) <= 7)

#define	PIIX_PIRQ_MASK		0xdef8
#define	PIIX_LEGAL_IRQ(irq)	((irq) >= 0 && (irq) <= 15 &&		\
				 ((1 << (irq)) & PIIX_PIRQ_MASK) != 0)

#define	PIIX_CFG_PIRQ		0x60	/* PCI configuration space */
#define	PIIX_CFG_PIRQH		0x68
#define	PIIX_CFG_PIRQ_NONE	0x80
#define	PIIX_CFG_PIRQ_MASK	0x0f
#define	PIIX_PIRQ(reg, x)	(((reg) >> ((x) << 3)) & 0xff)

/*
 * ELCR - EDGE/LEVEL CONTROL REGISTER
 *
 * PCI I/O registers 0x4d0, 0x4d1
 */
#define	PIIX_REG_ELCR		0x4d0
#define	PIIX_REG_ELCR_SIZE	2


code:
/*	$OpenBSD: piixvar.h,v 1.6 2008/06/26 05:42:11 ray Exp $	*/
/*	$NetBSD: piixvar.h,v 1.1 1999/11/17 01:21:21 thorpej Exp $	*/

/*-
 * Copyright (c) 1999 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Support for the Intel PIIX PCI-ISA bridge interrupt controller.
 */

int	piix_get_trigger(pciintr_icu_handle_t, int, int *);
int	piix_set_trigger(pciintr_icu_handle_t, int, int);

struct piix_handle {
	bus_space_tag_t ph_iot;
	bus_space_handle_t ph_elcr_ioh;
	pci_chipset_tag_t ph_pc;
	pcitag_t ph_tag;
};


code:
/*	$OpenBSD: rccosb4.c,v 1.5 2014/07/12 18:44:42 tedu Exp $	*/

/*
 * Copyright (c) 2004,2005 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Support for RCC South Bridge interrupt controller
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>

#include <machine/intr.h>
#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>

#include <i386/pci/pcibiosvar.h>
#include <i386/pci/piixvar.h>
#include <i386/pci/rccosb4reg.h>

struct osb4_handle {
	struct piix_handle piix;

#define	osb4_iot	piix.ph_iot
	bus_space_handle_t osb4_ioh;
};

int	osb4_getclink(pciintr_icu_handle_t, int, int *);
int	osb4_get_intr(pciintr_icu_handle_t, int, int *);
int	osb4_set_intr(pciintr_icu_handle_t, int, int);

const struct pciintr_icu osb4_pci_icu = {
	osb4_getclink,
	osb4_get_intr,
	osb4_set_intr,
	piix_get_trigger,
	piix_set_trigger,
};

int
osb4_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
    pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
{
	struct osb4_handle *ph;

	ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
	if (ph == NULL)
		return (1);

	ph->piix.ph_iot = iot;
	ph->piix.ph_pc = pc;
	ph->piix.ph_tag = tag;

	if (bus_space_map(iot, OSB4_PIAIR, 2, 0, &ph->osb4_ioh)) {
		free(ph, M_DEVBUF, 0);
		return (1);
	}

	if (bus_space_map(iot, OSB4_REG_ELCR, 2, 0, &ph->piix.ph_elcr_ioh)) {
		free(ph, M_DEVBUF, 0);
		return (1);
	}

	*ptagp = &osb4_pci_icu;
	*phandp = ph;
	return (0);
}

int
osb4_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
{
	if (OSB4_LEGAL_LINK(link - 1)) {
		*clinkp = link;
 		if (link <= OSB4_PISP)
			*clinkp |= PCI_INT_VIA_ISA;
		return (0);
	}

	return (1);
}

int
osb4_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
{
	struct osb4_handle *ph = v;
	int link = clink & 0xff;

	if (!OSB4_LEGAL_LINK(link))
		return (1);

	bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, link);
	*irqp = bus_space_read_1(ph->osb4_iot, ph->osb4_ioh, 1) & 0xf;
	if (*irqp == 0)
		*irqp = I386_PCI_INTERRUPT_LINE_NO_CONNECTION;

	return (0);
}

int
osb4_set_intr(pciintr_icu_handle_t v, int clink, int irq)
{
	struct osb4_handle *ph = v;
	int link = clink & 0xff;

	if (!OSB4_LEGAL_LINK(link) || !OSB4_LEGAL_IRQ(irq & 0xf))
		return (1);

	bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, link);
	bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 1, irq & 0xf);

	return (0);
}


code:
/*	$OpenBSD: rccosb4reg.h,v 1.3 2005/11/23 09:24:57 mickey Exp $	*/

/*
 * Copyright (c) 2004,2005 Michael Shalayeff
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Register definitions for the RCC South Bridge interrupt controller.
 */

#define	OSB4_LEGAL_LINK(link)	((link) >= 0 && (link) <= 0x1f)

#define	OSB4_PIRQ_MASK		0xdefa
#define	OSB4_LEGAL_IRQ(irq)	((irq) > 0 && (irq) <= 15 &&		\
				 ((1 << (irq)) & OSB4_PIRQ_MASK) != 0)

/*
 * PCI Interrupts Address Index Register
 */
#define	OSB4_PIAIR	0xc00
#define	OSB4_PIRR	0xc01
#define	OSB4_PISP	3	/* special lines assumed to route thru ISA */

/*
 * ELCR - EDGE/LEVEL CONTROL REGISTER
 *
 * PCI I/O registers 0x4d0, 0x4d1
 */
#define	OSB4_REG_ELCR		0x4d0
#define	OSB4_REG_ELCR_SIZE	2


code:
/*	$OpenBSD: sis85c503.c,v 1.8 2008/06/26 05:42:11 ray Exp $	*/
/*	$NetBSD: sis85c503.c,v 1.2 2000/07/18 11:24:09 soda Exp $	*/

/*-
 * Copyright (c) 1999 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Support for the SiS 85c503 PCI-ISA bridge interrupt controller.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <machine/intr.h>
#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <i386/pci/pcibiosvar.h>
#include <i386/pci/sis85c503reg.h>
#include <i386/pci/piixvar.h>

int	sis85c503_getclink(pciintr_icu_handle_t, int, int *);
int	sis85c503_get_intr(pciintr_icu_handle_t, int, int *);
int	sis85c503_set_intr(pciintr_icu_handle_t, int, int);

const struct pciintr_icu sis85c503_pci_icu = {
	sis85c503_getclink,
	sis85c503_get_intr,
	sis85c503_set_intr,
	piix_get_trigger,
	piix_set_trigger,
};

int
sis85c503_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
    pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
{

	if (piix_init(pc, iot, tag, ptagp, phandp) == 0) {
		*ptagp = &sis85c503_pci_icu;
		return (0);
	}

	return (1);
}

int
sis85c503_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
{

	/* Pattern 1: simple. */
	if (link >= 1 && link <= 4) {
		*clinkp = SIS85C503_CFG_PIRQ_REGSTART + link - 1;
		return (0);
	}

	/* Pattern 2: configuration register offset */
	if (link >= SIS85C503_CFG_PIRQ_REGSTART &&
	    link <= SIS85C503_CFG_PIRQ_REGEND) {
		*clinkp = link;
		return (0);
	}

	return (1);
}

int
sis85c503_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
{
	struct piix_handle *ph = v;
	pcireg_t reg;

	if (SIS85C503_LEGAL_LINK(clink) == 0)
		return (1);

	reg = pci_conf_read(ph->ph_pc, ph->ph_tag,
	    SIS85C503_CFG_PIRQ_REGOFS(clink));
	reg = SIS85C503_CFG_PIRQ_REG(reg, clink);

	if (reg & SIS85C503_CFG_PIRQ_ROUTE_DISABLE)
		*irqp = 0xff;
	else
		*irqp = reg & SIS85C503_CFG_PIRQ_INTR_MASK;

	return (0);
}

int
sis85c503_set_intr(pciintr_icu_handle_t v, int clink, int irq)
{
	struct piix_handle *ph = v;
	int shift;
	pcireg_t reg;

	if (SIS85C503_LEGAL_LINK(clink) == 0 || SIS85C503_LEGAL_IRQ(irq) == 0)
		return (1);

	reg = pci_conf_read(ph->ph_pc, ph->ph_tag,
	    SIS85C503_CFG_PIRQ_REGOFS(clink));
	shift = SIS85C503_CFG_PIRQ_SHIFT(clink);
	reg &= ~((SIS85C503_CFG_PIRQ_ROUTE_DISABLE |
	    SIS85C503_CFG_PIRQ_INTR_MASK) << shift);
	reg |= (irq << shift);
	pci_conf_write(ph->ph_pc, ph->ph_tag, SIS85C503_CFG_PIRQ_REGOFS(clink),
	    reg);

	return (0);
}


code:
/*	$OpenBSD: sis85c503reg.h,v 1.3 2000/03/28 03:38:00 mickey Exp $	*/
/*	$NetBSD: sis85c503reg.h,v 1.1 1999/11/17 01:21:21 thorpej Exp $	*/

/*
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Register definitions for the SiS 85c503 PCI-ISA bridge interrupt controller.
 */

#define	SIS85C503_CFG_PIRQ_REGSTART	0x41	/* PCI configuration space */
#define	SIS85C503_CFG_PIRQ_REGEND	0x44

#define	SIS85C503_LEGAL_LINK(link) ((link) >= SIS85C503_CFG_PIRQ_REGSTART && \
				    (link) <= SIS85C503_CFG_PIRQ_REGEND)

#define	SIS85C503_CFG_PIRQ_REGOFS(regofs) (((regofs) >> 2) << 2)
#define	SIS85C503_CFG_PIRQ_SHIFT(regofs)				\
	(((regofs) - SIS85C503_CFG_PIRQ_REGOFS(regofs)) << 3)

#define	SIS85C503_CFG_PIRQ_MASK		0xff
#define	SIS85C503_CFG_PIRQ_INTR_MASK	0x0f

#define	SIS85C503_CFG_PIRQ_REG(reg, regofs)				\
	(((reg) >> SIS85C503_CFG_PIRQ_SHIFT(regofs)) & SIS85C503_CFG_PIRQ_MASK)

#define	SIS85C503_CFG_PIRQ_ROUTE_DISABLE 0x80

#define	SIS85C503_PIRQ_MASK		0xdef8
#define	SIS85C503_LEGAL_IRQ(irq)	((irq) >= 0 && (irq) <= 15 &&	\
				 ((1 << (irq)) & SIS85C503_PIRQ_MASK) != 0)


code:
/* $OpenBSD: vga_post.c,v 1.8 2014/11/16 12:30:57 deraadt Exp $ */
/* $NetBSD: vga_post.c,v 1.12 2009/03/15 21:32:36 cegger Exp $ */

/*-
 * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/device.h>
#include <sys/malloc.h>

#include <uvm/uvm_extern.h>

#include <machine/pio.h>
#include <machine/vga_post.h>

#include <dev/x86emu/x86emu.h>
#include <dev/x86emu/x86emu_regs.h>

#define	BASE_MEMORY	65536	/* How much memory to allocate in Real Mode */

struct vga_post {
	struct x86emu emu;
	vaddr_t sys_image;
	uint32_t initial_eax;
	uint8_t bios_data[PAGE_SIZE];
	struct pglist ram_backing;
};

#ifdef DDB
struct vga_post *ddb_vgapostp;
void ddb_vgapost(void);
#endif

static uint8_t
vm86_emu_inb(struct x86emu *emu, uint16_t port)
{
	if (port == 0xb2) /* APM scratch register */
		return 0;

	if (port >= 0x80 && port < 0x88) /* POST status register */
		return 0;

	return inb(port);
}

static uint16_t
vm86_emu_inw(struct x86emu *emu, uint16_t port)
{
	if (port >= 0x80 && port < 0x88) /* POST status register */
		return 0;

	return inw(port);
}

static uint32_t
vm86_emu_inl(struct x86emu *emu, uint16_t port)
{
	if (port >= 0x80 && port < 0x88) /* POST status register */
		return 0;

	return inl(port);
}

static void
vm86_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val)
{
	if (port == 0xb2) /* APM scratch register */
		return;

	if (port >= 0x80 && port < 0x88) /* POST status register */
		return;

	outb(port, val);
}

static void
vm86_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val)
{
	if (port >= 0x80 && port < 0x88) /* POST status register */
		return;

	outw(port, val);
}

static void
vm86_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val)
{
	if (port >= 0x80 && port < 0x88) /* POST status register */
		return;

	outl(port, val);
}

struct vga_post *
vga_post_init(int bus, int device, int function)
{
	struct vga_post *sc;
	vaddr_t iter;
	struct vm_page *pg;
	vaddr_t sys_image, sys_bios_data;
	int err;

	sys_bios_data = uvm_km_valloc(kernel_map, PAGE_SIZE);
	if (sys_bios_data == 0)
		return NULL;

	sys_image = uvm_km_valloc(kernel_map, 1024 * 1024);
	if (sys_image == 0) {
		uvm_km_free(kernel_map, sys_bios_data, PAGE_SIZE);
		return NULL;
	}
	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);

	TAILQ_INIT(&sc->ram_backing);
	err = uvm_pglistalloc(BASE_MEMORY, 0, (paddr_t)-1, 0, 0,
	    &sc->ram_backing, BASE_MEMORY/PAGE_SIZE, UVM_PLA_WAITOK);
	if (err) {
		uvm_km_free(kernel_map, sc->sys_image, 1024 * 1024);
		free(sc, M_DEVBUF, 0);
		return NULL;
	}

	sc->sys_image = sys_image;
	sc->emu.sys_private = sc;

	pmap_kenter_pa(sys_bios_data, 0, PROT_READ);
	pmap_update(pmap_kernel());
	memcpy((void *)sc->bios_data, (void *)sys_bios_data, PAGE_SIZE);
	pmap_kremove(sys_bios_data, PAGE_SIZE);
	uvm_km_free(kernel_map, sys_bios_data, PAGE_SIZE);

	iter = 0;
	TAILQ_FOREACH(pg, &sc->ram_backing, pageq) {
		pmap_kenter_pa(sc->sys_image + iter, VM_PAGE_TO_PHYS(pg),
		    PROT_READ | PROT_WRITE);
		iter += PAGE_SIZE;
	}
	KASSERT(iter == BASE_MEMORY);

	for (iter = 640 * 1024; iter < 1024 * 1024; iter += PAGE_SIZE)
		pmap_kenter_pa(sc->sys_image + iter, iter,
		    PROT_READ | PROT_WRITE);
	pmap_update(pmap_kernel());

	memset(&sc->emu, 0, sizeof(sc->emu));
	x86emu_init_default(&sc->emu);
	sc->emu.emu_inb = vm86_emu_inb;
	sc->emu.emu_inw = vm86_emu_inw;
	sc->emu.emu_inl = vm86_emu_inl;
	sc->emu.emu_outb = vm86_emu_outb;
	sc->emu.emu_outw = vm86_emu_outw;
	sc->emu.emu_outl = vm86_emu_outl;

	sc->emu.mem_base = (char *)sc->sys_image;
	sc->emu.mem_size = 1024 * 1024;

	sc->initial_eax = bus * 256 + device * 8 + function;
#ifdef DDB
	ddb_vgapostp = sc;
#endif
	return sc;
}

void
vga_post_call(struct vga_post *sc)
{
	sc->emu.x86.R_EAX = sc->initial_eax;
	sc->emu.x86.R_EDX = 0x00000080;
	sc->emu.x86.R_DS = 0x0040;
	sc->emu.x86.register_flags = 0x3200;

	memcpy((void *)sc->sys_image, sc->bios_data, PAGE_SIZE);

	/* stack is at the end of the first 64KB */
	sc->emu.x86.R_SS = 0;
	sc->emu.x86.R_ESP = 0;

	/* Jump straight into the VGA BIOS POST code */
	x86emu_exec_call(&sc->emu, 0xc000, 0x0003);
}

void
vga_post_free(struct vga_post *sc)
{
	uvm_pglistfree(&sc->ram_backing);
	pmap_kremove(sc->sys_image, 1024 * 1024);

	uvm_km_free(kernel_map, sc->sys_image, 1024 * 1024);
	pmap_update(pmap_kernel());
	free(sc, M_DEVBUF, 0);
}

#ifdef DDB
void
ddb_vgapost(void)
{

	if (ddb_vgapostp)
		vga_post_call(ddb_vgapostp);
	else
		printf("ddb_vgapost: vga_post not initialized\n");
}
#endif


code:
/*	$OpenBSD: via8231.c,v 1.8 2008/06/26 05:42:11 ray Exp $	*/

/*-
 * Copyright (c) 1999 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * Copyright (c) 2005, by Michael Shalayeff
 * Copyright (c) 2003, by Matthew Gream
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Support for the VIA Technologies Inc. VIA8231 PCI to ISA Bridge
 * Based upon documentation:
 * 1. VIA VT8231 South Bridge, Revision 1.85 (March 11, 2002), pg 73
 * 2. VIA VT8237R South Bridge, Revision 2.06 (December 15, 2004), pg 100
 * Derived from amd756.c
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>

#include <machine/intr.h>
#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <i386/pci/pcibiosvar.h>
#include <i386/pci/via8231reg.h>

struct via8231_handle {
	bus_space_tag_t ph_iot;
	bus_space_handle_t ph_regs_ioh;
	pci_chipset_tag_t ph_pc;
	pcitag_t ph_tag;
	int flags;
#define	VT8237	0x0001
};

int via8231_getclink(pciintr_icu_handle_t, int, int *);
int via8231_get_intr(pciintr_icu_handle_t, int, int *);
int via8231_set_intr(pciintr_icu_handle_t, int, int);
int via8231_get_trigger(pciintr_icu_handle_t, int, int *);
int via8231_set_trigger(pciintr_icu_handle_t, int, int);
#ifdef VIA8231_DEBUG
static void via8231_pir_dump(const char*, struct via8231_handle *);
#endif

const struct pciintr_icu via8231_pci_icu = {
	via8231_getclink,
	via8231_get_intr,
	via8231_set_intr,
	via8231_get_trigger,
	via8231_set_trigger,
};

struct mask_shft_pair {
	int mask;
	int shft;
};

static const struct mask_shft_pair via8231_routing_cnfg[VIA8231_LINK_MAX+1] = {
	{ 0x0f,  0+4 }, /*PINTA#*/
	{ 0x0f,  8+0 }, /*PINTB#*/
	{ 0x0f,  8+4 }, /*PINTC#*/
	{ 0x0f, 16+4 }  /*PINTD#*/
};

#define VIA8231_GET_TRIGGER_CNFG(reg, pirq) \
	((reg) & (1 << (3 - (clink & 3))))
#define VIA8231_SET_TRIGGER_CNFG(reg, clink, cfg) \
	(((reg) & ~(1 << (3 - (clink & 3)))) | ((cfg) << (3 - (clink & 3))))

#define VIA8231_GET_ROUTING_CNFG(reg, pirq) \
	(((reg) >> via8231_routing_cnfg[(pirq)].shft) & \
	    via8231_routing_cnfg[(pirq)].mask)

#define VIA8231_SET_ROUTING_CNFG(reg, pirq, cfg) \
	(((reg) & ~(via8231_routing_cnfg[(pirq)].mask << \
	    via8231_routing_cnfg[(pirq)].shft)) | \
	    (((cfg) & via8231_routing_cnfg[(pirq)].mask) << \
	    via8231_routing_cnfg[(pirq)].shft))

int
via8231_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
    pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
{
	struct via8231_handle *ph;
	pcireg_t id;

	ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
	if (ph == NULL)
		return (1);

	ph->ph_iot = iot;
	ph->ph_pc = pc;
	ph->ph_tag = tag;
	id = pci_conf_read(pc, tag, PCI_ID_REG);
	ph->flags = PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
	     PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT8231_ISA? 0 : VT8237;

	*ptagp = &via8231_pci_icu;
	*phandp = ph;

#ifdef VIA8231_DEBUG
	via8231_pir_dump("via8231_init", ph);
#endif

	return 0;
}

int
via8231_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
{
	struct via8231_handle *ph = v;

	if ((ph->flags & VT8237) && !VIA8237_LINK_LEGAL(link - 1))
		return (1);

	if (!(ph->flags & VT8237) && !VIA8231_LINK_LEGAL(link - 1))
		return (1);

	*clinkp = link - 1;
	return (0);
}

int
via8231_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
{
	struct via8231_handle *ph = v;
	int reg, val;

	if (VIA8237_LINK_LEGAL(clink) == 0)
		return (1);

	if (VIA8231_LINK_LEGAL(clink)) {
		reg = VIA8231_GET_ROUTING(ph);
		val = VIA8231_GET_ROUTING_CNFG(reg, clink);
	} else {
		reg = VIA8237_GET_ROUTING(ph);
		val = (reg >> ((clink & 3) * 4)) & 0xf;
	}

	*irqp = (val == VIA8231_ROUTING_CNFG_DISABLED) ?
	    I386_PCI_INTERRUPT_LINE_NO_CONNECTION : val;

	return (0);
}

int
via8231_set_intr(pciintr_icu_handle_t v, int clink, int irq)
{
	struct via8231_handle *ph = v;
	int reg;

	if (VIA8237_LINK_LEGAL(clink) == 0 || VIA8231_PIRQ_LEGAL(irq) == 0)
		return (1);

#ifdef VIA8231_DEBUG
	printf("via8231_set_intr: link(%02x) --> irq(%02x)\n", clink, irq);
	via8231_pir_dump("via8231_set_intr: ", ph);
#endif

	if (VIA8231_LINK_LEGAL(clink)) {
		reg = VIA8231_GET_ROUTING(ph);
		VIA8231_SET_ROUTING(ph,
		    VIA8231_SET_ROUTING_CNFG(reg, clink, irq));
	} else {
		reg = VIA8237_GET_ROUTING(ph);
		VIA8237_SET_ROUTING(ph, (reg & ~(0xf << (clink & 3))) |
		    ((irq & 0xf) << (clink & 3)));
	}

	return (0);
}

int
via8231_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
{
	struct via8231_handle *ph = v;
	int reg, clink, max, pciirq;

	if (VIA8231_PIRQ_LEGAL(irq) == 0)
		return (1);

	max = ph->flags & VT8237? VIA8237_LINK_MAX : VIA8231_LINK_MAX;
	for (clink = 0; clink <= max; clink++) {
		via8231_get_intr(v, clink, &pciirq);
		if (pciirq == irq) {
			reg = VIA8231_LINK_LEGAL(clink)?
			    VIA8231_GET_TRIGGER(ph):
			    VIA8237_GET_TRIGGER(ph);
			*triggerp = VIA8231_GET_TRIGGER_CNFG(reg, clink)?
			    IST_EDGE : IST_LEVEL;
			return (0);
		}
	}

	return (1);
}

int
via8231_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
{
	struct via8231_handle *ph = v;
	int reg, clink, max, pciirq;

	if (VIA8231_PIRQ_LEGAL(irq) == 0 || VIA8231_TRIG_LEGAL(trigger) == 0)
		return (1);

#ifdef VIA8231_DEBUG
	printf("via8231_set_trig: irq(%02x) --> trig(%02x)\n", irq, trigger);
	via8231_pir_dump("via8231_set_trig: ", ph);
#endif

	max = ph->flags & VT8237? VIA8237_LINK_MAX : VIA8231_LINK_MAX;
	for (clink = 0; clink <= VIA8231_LINK_MAX; clink++) {
		via8231_get_intr(v, clink, &pciirq);
		if (pciirq == irq) {
			reg = VIA8231_LINK_LEGAL(clink)?
			    VIA8231_GET_TRIGGER(ph):
			    VIA8237_GET_TRIGGER(ph);
			switch (trigger) {
			case IST_LEVEL:
				reg = VIA8231_SET_TRIGGER_CNFG(reg, clink,
					VIA8231_TRIGGER_CNFG_LEVEL);
				break;
			case IST_EDGE:
				reg = VIA8231_SET_TRIGGER_CNFG(reg, clink,
					VIA8231_TRIGGER_CNFG_EDGE);
				break;
			default:
				return (1);
			}
			if (VIA8231_LINK_LEGAL(clink))
				VIA8231_SET_TRIGGER(ph, reg);
			else
				VIA8237_SET_TRIGGER(ph, reg);
			return (0);
		}
	}

	return (1);
}

#ifdef VIA8231_DEBUG
static void
via8231_pir_dump(const char *m, struct via8231_handle *ph)
{
	int a, b;

	a = VIA8231_GET_TRIGGER(ph);
	b = VIA8231_GET_ROUTING(ph);

	printf("%s STATE: trigger(%02x), routing(%08x)\n", m, a, b);
}
#endif


code:
/*	$OpenBSD: via8231reg.h,v 1.4 2005/10/26 21:38:28 mickey Exp $	*/

/*
 * Copyright (c) 2005, by Michael Shalayeff
 * Copyright (c) 2003, by Matthew Gream
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Register definitions for the VIA8231 PCI to ISA Bridge
 */

/*
 * Edge Triggered Interrupt Select register. (0x54)
 * bits 7-4: reserved
 * bit 3: Edge Triggered Interrupt Select for PCI Interrupt A
 * bit 2: Edge Triggered Interrupt Select for PCI Interrupt B
 * bit 1: Edge Triggered Interrupt Select for PCI Interrupt C
 * bit 0: Edge Triggered Interrupt Select for PCI Interrupt D
 *   0 = Non-invert (level)
 *   1 = Invert (edge)
 *
 * PIRQ Select register. (0x55 - 0x57)
 * (0x55)
 * bits 7-4:   PINTA# Routing
 * bits 3-0:   reserved
 * (0x56)
 * bits 7-4:   PINTC# Routing
 * bits 3-0:   PINTB# Routing
 * (0x57)
 * bits 7-4:   PINTD# Routing
 * bits 3-0:   reserved
 * PIRQ Select register. (0x44 - 0x47)
 * (0x44)
 * bits 7-4:   PINTF# Routing
 * bits 3-0:   PINTE# Routing
 * (0x45)
 * bits 7-4:   PINTH# Routing
 * bits 3-0:   PINTG# Routing
 * (0x46)
 * bit 4:	EFGH/ABCD share (1 -- use above mappings)
 * bit 3: Edge Triggered Interrupt Select for PCI Interrupt H
 * bit 2: Edge Triggered Interrupt Select for PCI Interrupt G
 * bit 1: Edge Triggered Interrupt Select for PCI Interrupt F
 * bit 0: Edge Triggered Interrupt Select for PCI Interrupt E
 *
 *   0000: Disabled  0100: IRQ4      1000: Reserved  1100: IRQ12
 *   0001: IRQ1      0101: IRQ5      1001: IRQ9      1101: Reserved
 *   0010: Reserved  0110: IRQ6      1010: IRQ10     1110: IRQ14
 *   0011: IRQ3      0111: IRQ7      1011: IRQ11     1111: IRQ15
 */
#define VIA8231_CFG_PIR		0x54
#define VIA8237_CFG_PIR		0x44

#define VIA8231_TRIGGER_CNFG_MASK		0x000000ff
#define VIA8231_TRIGGER_CNFG_SHFT		0
#define VIA8237_TRIGGER_CNFG_MASK		0x000f0000
#define VIA8237_TRIGGER_CNFG_SHFT		16
#define VIA8231_TRIGGER_CNFG_LEVEL		0
#define VIA8231_TRIGGER_CNFG_EDGE		1
#define VIA8237_TRIGGER_CNFG_ENA		0x00100000

#define VIA8231_GET_TRIGGER(ph)						\
	((pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR)	\
	    & VIA8231_TRIGGER_CNFG_MASK) >> VIA8231_TRIGGER_CNFG_SHFT)
#define VIA8237_GET_TRIGGER(ph)						\
	((pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR)	\
	    & VIA8237_TRIGGER_CNFG_MASK) >> VIA8237_TRIGGER_CNFG_SHFT)

#define VIA8231_SET_TRIGGER(ph, n)					\
	pci_conf_write((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR,	\
	(pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR)	\
	    & ~VIA8231_TRIGGER_CNFG_MASK) | ((n) << VIA8231_TRIGGER_CNFG_SHFT))
#define VIA8237_SET_TRIGGER(ph, n)					\
	pci_conf_write((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR,	\
	(pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR)	\
	    & ~VIA8237_TRIGGER_CNFG_MASK) | ((n) << VIA8237_TRIGGER_CNFG_SHFT))

#define VIA8231_ROUTING_CNFG_MASK		0xffffff00
#define VIA8231_ROUTING_CNFG_SHFT		8 /* skip 0x54 triggers */
#define VIA8231_ROUTING_CNFG_DISABLED		0
#define VIA8237_ROUTING_CNFG_MASK		0xffff
#define VIA8237_ROUTING_CNFG_SHFT		0

#define VIA8231_GET_ROUTING(ph)						\
	((pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR)	\
	    & VIA8231_ROUTING_CNFG_MASK) >> VIA8231_ROUTING_CNFG_SHFT)
#define VIA8237_GET_ROUTING(ph)						\
	((pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR)	\
	    & VIA8237_ROUTING_CNFG_MASK) >> VIA8237_ROUTING_CNFG_SHFT)

#define VIA8231_SET_ROUTING(ph, n)					\
	pci_conf_write((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR,	\
	(pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8231_CFG_PIR)	\
	    & ~VIA8231_ROUTING_CNFG_MASK) | ((n) << VIA8231_ROUTING_CNFG_SHFT))
#define VIA8237_SET_ROUTING(ph, n)					\
	pci_conf_write((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR,	\
	(pci_conf_read((ph)->ph_pc, (ph)->ph_tag, VIA8237_CFG_PIR)	\
	    & ~VIA8237_ROUTING_CNFG_MASK) | \
	    ((n) << VIA8237_ROUTING_CNFG_SHFT) | VIA8237_TRIGGER_CNFG_ENA)

#define VIA8231_PIRQ_MASK		0xdefa
#define VIA8231_PIRQ_LEGAL(irq)		\
	((irq) >= 0 && (irq) <= 15 && ((1 << (irq)) & VIA8231_PIRQ_MASK))
#define VIA8231_LINK_MAX		3
#define VIA8237_LINK_MAX		7
#define	VIA8231_LINK_LEGAL(link)	\
	((link) >= 0 && (link) <= VIA8231_LINK_MAX)
#define	VIA8237_LINK_LEGAL(link)	\
	((link) >= 0 && (link) <= VIA8237_LINK_MAX)
#define VIA8231_TRIG_LEGAL(trig)	\
	((trig) == IST_LEVEL || (trig) == IST_EDGE)


code:
/*	$OpenBSD: via82c586.c,v 1.11 2008/06/26 05:42:11 ray Exp $	*/
/*	$NetBSD: via82c586.c,v 1.2 2000/07/18 11:24:09 soda Exp $	*/

/*-
 * Copyright (c) 1999 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Support for the VIA 82c586 PCI-ISA bridge interrupt controller.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <machine/intr.h>
#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <i386/pci/pcibiosvar.h>
#include <i386/pci/via82c586reg.h>
#include <i386/pci/piixvar.h>

int	via82c586_getclink(pciintr_icu_handle_t, int, int *);
int	via82c586_get_intr(pciintr_icu_handle_t, int, int *);
int	via82c586_set_intr(pciintr_icu_handle_t, int, int);
int	via82c586_get_trigger(pciintr_icu_handle_t, int, int *);
int	via82c586_set_trigger(pciintr_icu_handle_t, int, int);

const struct pciintr_icu via82c586_pci_icu = {
	via82c586_getclink,
	via82c586_get_intr,
	via82c586_set_intr,
	via82c586_get_trigger,
	via82c586_set_trigger,
};

const int vp3_cfg_trigger_shift[] = {
	VP3_CFG_TRIGGER_SHIFT_PIRQA,
	VP3_CFG_TRIGGER_SHIFT_PIRQB,
	VP3_CFG_TRIGGER_SHIFT_PIRQC,
	VP3_CFG_TRIGGER_SHIFT_PIRQD,
};

#define	VP3_TRIGGER(reg, pirq)	(((reg) >> vp3_cfg_trigger_shift[(pirq)]) & \
				 VP3_CFG_TRIGGER_MASK)

const int vp3_cfg_intr_shift[] = {
	VP3_CFG_INTR_SHIFT_PIRQA,
	VP3_CFG_INTR_SHIFT_PIRQB,
	VP3_CFG_INTR_SHIFT_PIRQC,
	VP3_CFG_INTR_SHIFT_PIRQD,
	VP3_CFG_INTR_SHIFT_PIRQ0,
	VP3_CFG_INTR_SHIFT_PIRQ1,
	VP3_CFG_INTR_SHIFT_PIRQ2,
};

#define	VP3_PIRQ(reg, pirq)	(((reg) >> vp3_cfg_intr_shift[(pirq)]) & \
				 VP3_CFG_INTR_MASK)

int
via82c586_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
    pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
{
	pcireg_t reg;

	if (piix_init(pc, iot, tag, ptagp, phandp) == 0) {
		*ptagp = &via82c586_pci_icu;

		/*
		 * Enable EISA ELCR.
		 */
		reg = pci_conf_read(pc, tag, VP3_CFG_KBDMISCCTRL12_REG);
		reg |= VP3_CFG_MISCCTRL2_EISA4D04D1PORT_ENABLE <<
		    VP3_CFG_MISCCTRL2_SHIFT;
		pci_conf_write(pc, tag, VP3_CFG_KBDMISCCTRL12_REG, reg);

		return (0);
	}

	return (1);
}

int
via82c586_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
{

	if (VP3_LEGAL_LINK(link - 1)) {
		*clinkp = link - 1;
		return (0);
	}

	return (1);
}

int
via82c586_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
{
	struct piix_handle *ph = v;
	pcireg_t reg;
	int val;

	if (VP3_LEGAL_LINK(clink) == 0)
		return (1);

	reg = pci_conf_read(ph->ph_pc, ph->ph_tag, VP3_CFG_PIRQ_REG);
	val = VP3_PIRQ(reg, clink);
	*irqp = (val == VP3_PIRQ_NONE)?
	    I386_PCI_INTERRUPT_LINE_NO_CONNECTION : val;

	return (0);
}

int
via82c586_set_intr(pciintr_icu_handle_t v, int clink, int irq)
{
	struct piix_handle *ph = v;
	int shift, val;
	pcireg_t reg;

	if (VP3_LEGAL_LINK(clink) == 0 || VP3_LEGAL_IRQ(irq) == 0)
		return (1);

	reg = pci_conf_read(ph->ph_pc, ph->ph_tag, VP3_CFG_PIRQ_REG);
	via82c586_get_intr(v, clink, &val);
	shift = vp3_cfg_intr_shift[clink];
	reg &= ~(VP3_CFG_INTR_MASK << shift);
	reg |= (irq << shift);
	pci_conf_write(ph->ph_pc, ph->ph_tag, VP3_CFG_PIRQ_REG, reg);
	if (via82c586_get_intr(v, clink, &val) != 0 ||
	    val != irq)
		return (1);

	return (0);
}

int
via82c586_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
{
	struct piix_handle *ph = v;
	int i, error, check_consistency, pciirq, pcitrigger = IST_NONE;
	pcireg_t reg;

	if (VP3_LEGAL_IRQ(irq) == 0)
		return (1);

	check_consistency = 0;
	for (i = 0; i <= 3; i++) {
		via82c586_get_intr(v, i, &pciirq);
		if (pciirq == irq) {
			reg = pci_conf_read(ph->ph_pc, ph->ph_tag,
			    VP3_CFG_PIRQ_REG);
			if (VP3_TRIGGER(reg, i) == VP3_CFG_TRIGGER_EDGE)
				pcitrigger = IST_EDGE;
			else
				pcitrigger = IST_LEVEL;
			check_consistency = 1;
			break;
		}
	}

	error = piix_get_trigger(v, irq, triggerp);
	if (error == 0 && check_consistency && pcitrigger != *triggerp)
		return (1);
	return (error);
}

int
via82c586_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
{
	struct piix_handle *ph = v;
	int i, pciirq, shift, testtrig;
	pcireg_t reg;

	if (VP3_LEGAL_IRQ(irq) == 0)
		return (1);

	for (i = 0; i <= 3; i++) {
		via82c586_get_intr(v, i, &pciirq);
		if (pciirq == irq) {
			reg = pci_conf_read(ph->ph_pc, ph->ph_tag,
			    VP3_CFG_PIRQ_REG);
			shift = vp3_cfg_trigger_shift[i];
			/* XXX we only upgrade the trigger here */
			if (trigger == IST_LEVEL)
				reg &= ~(VP3_CFG_TRIGGER_MASK << shift);
			pci_conf_write(ph->ph_pc, ph->ph_tag,
			    VP3_CFG_PIRQ_REG, reg);
			break;
		}
	}

	if (piix_set_trigger(v, irq, trigger) != 0 ||
	    via82c586_get_trigger(v, irq, &testtrig) != 0 ||
	    testtrig != trigger)
		return (1);

	return (0);
}


code:
/*	$OpenBSD: via82c586reg.h,v 1.5 2001/06/08 03:18:04 mickey Exp $	*/
/*	$NetBSD: via82c586reg.h,v 1.2 2000/04/22 15:00:41 uch Exp $	*/

/*
 * Copyright (c) 1999, by UCHIYAMA Yasushi
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. The name of the developer may NOT be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Register definitions for the VIA 82c586 PCI-ISA bridge interrupt controller.
 */

#define	VP3_CFG_PIRQ_REG		0x54	/* PCI configuration space */
#define	VP3_CFG_KBDMISCCTRL12_REG	0x44
#define	VP3_CFG_IDEMISCCTRL3_REG	0x48

#define	VP3_CFG_MISCCTRL2_SHIFT		24
#define	VP3_CFG_MISCCTRL2_MASK		0x0f
#define	VP3_CFG_MISCCTRL2_EISA4D04D1PORT_ENABLE 0x20
#define	VP3_CFG_MISCCTRL2_REG(reg)					\
	(((reg) >> VP3_CFG_MISCCTRL2_SHIFT) & VP3_CFG_MISCCTRL2_MASK)

#define	VP3_CFG_TRIGGER_LEVEL		0
#define	VP3_CFG_TRIGGER_EDGE		1

#define	VP3_CFG_TRIGGER_MASK		0x01
#define	VP3_CFG_TRIGGER_SHIFT_PIRQA	3
#define	VP3_CFG_TRIGGER_SHIFT_PIRQB	2
#define	VP3_CFG_TRIGGER_SHIFT_PIRQC	1
#define	VP3_CFG_TRIGGER_SHIFT_PIRQD	0

#define	VP3_CFG_INTR_MASK		0x0f
#define	VP3_PIRQ_MASK			0xdefa

#define	VP3_CFG_INTR_SHIFT_PIRQA	0x14
#define	VP3_CFG_INTR_SHIFT_PIRQB	0x10
#define	VP3_CFG_INTR_SHIFT_PIRQC	0x1c
#define	VP3_CFG_INTR_SHIFT_PIRQD	0x0c
#define	VP3_CFG_INTR_SHIFT_PIRQ0	0x10
#define	VP3_CFG_INTR_SHIFT_PIRQ1	0x08
#define	VP3_CFG_INTR_SHIFT_PIRQ2	0x00

#define	VP3_PIRQ_NONE			0
#define	VP3_LEGAL_LINK(link)		((link) >= 0 && (link) <= 6)
#define	VP3_LEGAL_IRQ(irq)		((irq) >= 0 && (irq) <= 15 &&	\
					 ((1 << (irq)) & VP3_PIRQ_MASK) != 0)


code:
/Makefile/1.21/Mon Jan 20 08:49:58 2014//TOPENBSD_5_8_BASE
/Makefile.inc/1.45/Sat Dec 28 02:51:07 2013//TOPENBSD_5_8_BASE
D/biosboot////
D/boot////
D/cdboot////
D/cdbr////
D/etc////
D/fdboot////
D/libsa////
D/mbr////
D/pxeboot////


code:
#	$OpenBSD: Makefile,v 1.21 2014/01/20 08:49:58 deraadt Exp $

.if ${MACHINE} == "i386"
SUBDIR=	mbr cdbr
.endif
SUBDIR+=biosboot boot cdboot fdboot pxeboot

.include <bsd.subdir.mk>


code:
#	$OpenBSD: Makefile.inc,v 1.45 2013/12/28 02:51:07 deraadt Exp $

CFLAGS=${DEBUG} ${COPTS} -Os -Wall -Werror
CFLAGS+=	-fno-stack-protector -DMDRANDOM
CPPFLAGS+=-I${S} -I${SADIR}/libsa -I. -I${.CURDIR}
SACFLAGS=-D_STANDALONE
DEBUGLIBS=no
DEBUGFLAGS=
# DEBUGFLAGS+=-DDEBUG
# DEBUGFLAGS+=-DGIDT_DEBUG
# DEBUGFLAGS+=-DBIOS_DEBUG
# DEBUGFLAGS+=-DEXEC_DEBUG
# DEBUGFLAGS+=-DALLOC_TRACE
# DEBUGFLAGS+=-g -D_TEST
# DEBUGFLAGS+=-DUNIX_DEBUG
# DEBUGFLAGS+=-DBOOTP_DEBUG -DNETIF_DEBUG -DETHER_DEBUG
# DEBUGFLAGS+=-DNFS_DEBUG -DRPC_DEBUG -DRARP_DEBUG
LINKADDR=0x40120
LOADADDR=0x40000
HEAP_LIMIT=0x90000
BOOTREL=0x60000
BOOTMAGIC=0xc001d00d
#ROM_SIZE=32768
CLEANFILES+=	assym.h machine

.if empty(DEBUGFLAGS:M-D_TEST)
SACFLAGS+=-nostdinc -fno-builtin -fpack-struct
.endif

.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(obj)
.BEGIN:
	@([ X$(S) = X -o -h machine ] || ln -s $(S)/arch/i386/include machine)

assym.h: ${S}/kern/genassym.sh ${SADIR}/etc/genassym.cf
	sh ${S}/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} \
	    ${PARAM} < ${SADIR}/etc/genassym.cf > assym.h.tmp && \
	    mv -f assym.h.tmp assym.h
.endif

# NO_NET=no_net
BINDIR=	/usr/mdec

MANSUBDIR=i386


code:
#	$OpenBSD: Makefile,v 1.26 2013/01/18 21:09:04 espie Exp $

MAN=	biosboot.8

.if ${MACHINE} == "i386"
S=	${.CURDIR}/../../../..
SADIR=	${.CURDIR}/..

PROG=	biosboot
SRCS=	biosboot.S
LD=ld
LDFLAGS=-nostdlib -Ttext 0 -N -x -Bstatic -nopie
INSTALL_STRIP=

.depend biosboot.o: assym.h

${PROG}: $(OBJS)
	@rm -f $(PROG)
	$(LD) $(LDFLAGS) -o $(PROG) $(OBJS)
	@size $(PROG)

CPPFLAGS+=-DLOADADDR=$(LOADADDR) -DLINKADDR=$(LINKADDR) -DBOOTMAGIC=$(BOOTMAGIC)
CPPFLAGS+=${DEBUGFLAGS}
CFLAGS+=-fno-pie
#AFLAGS+=-Wa,-a
AFLAGS+=-fno-pie
.else
NOPROG=
.endif

.include <bsd.prog.mk>