code:
#	$OpenBSD: files.alpha,v 1.102 2015/07/17 22:52:28 tedu Exp $
#	$NetBSD: files.alpha,v 1.32 1996/11/25 04:03:21 cgd Exp $
#
# alpha-specific configuration info

# maxpartitions must be first item in files.${ARCH}
maxpartitions 16

maxusers 2 8 128

# this loses, but there's no way to define attributes which have attributes
define	alpha_shared_intr
file	arch/alpha/dev/shared_intr.c	alpha_shared_intr | dec_eb164 |
					dec_kn20aa | dec_6600 | dec_550 |
					dec_1000 | dec_1000a | dec_eb64plus |
					dec_kn300

define	alpha_sgmap
file	arch/alpha/dev/sgmap_common.c		alpha_sgmap | dec_3000_500

#
# Bus-independent devices
#

device	mainbus {}			# no locators (yet?)
attach	mainbus at root

device	cpu {}				# not really optional
attach	cpu at mainbus
file	arch/alpha/alpha/cpu.c			cpu

major	{vnd = 9}

#
# Media Independent Interface (mii)
#
include	"dev/mii/files.mii"

#
# Machine-independent SCSI drivers
#

include	"scsi/files.scsi"
major	{st = 2}
major	{cd = 3}
major	{sd = 8}
major	{rd = 6}

# Raster operations
include	"dev/rasops/files.rasops"
include	"dev/wsfont/files.wsfont"

#
# "workstation console" routines
#

include	"dev/wscons/files.wscons"

#
# Bus-independent support for DEC devices
#
include	"dev/dec/files.dec"

#
# TURBOchannel Devices
#
include	"dev/tc/files.tc"

#
# MCBUS bus Devices
#
device	mcbus { mid = -1 }
attach	mcbus at mainbus
file	arch/alpha/mcbus/mcbus.c		mcbus & dec_kn300

device	mcmem: mcbus
attach	mcmem at mcbus
file	arch/alpha/mcbus/mcmem.c		mcmem

# TC attachment is MD
attach	tc at tcbus

device	tcasic: tcbus
attach	tcasic at mainbus
file	arch/alpha/tc/tcasic.c			tcasic	needs-flag
file	arch/alpha/tc/tc_bus_mem.c		tcasic
file	arch/alpha/tc/tc_dma.c			tcasic
file	arch/alpha/tc/tc_dma_3000_300.c		tcasic & dec_3000_300
file	arch/alpha/tc/tc_dma_3000_500.c		tcasic & dec_3000_500
file	arch/alpha/tc/tc_sgmap.c		tcasic & dec_3000_500
file	arch/alpha/tc/tc_3000_500.c		tcasic & dec_3000_500
file	arch/alpha/tc/tc_3000_300.c		tcasic & dec_3000_300

# the TURBOchannel IOCTL ASIC
# IOASIC device and attachment defined in sys/dev/tc/files.tc
file	arch/alpha/tc/ioasic.c			ioasic needs-flag

# PMAG-B CX
device	cfb: wsemuldisplaydev
attach	cfb at tc
file	arch/alpha/tc/cfb.c			cfb		needs-flag

# PMAGB-B HX or CXT
device	sfb: wsemuldisplaydev
attach	sfb at tc
file	arch/alpha/tc/sfb.c			sfb		needs-flag

# 8530 UARTs
device	scc
attach	scc at ioasic
file	arch/alpha/tc/scc.c			scc		needs-count

# TC and baseboard ioasic Lance ethernet are in files.tc

#
# ISA Bus support
#

#
# Machine-independent ATAPI drivers
#

include	"dev/atapiscsi/files.atapiscsi"
include	"dev/ata/files.ata"

include	"dev/pci/files.pci"	# XXX some ISA devs are 'at pci' too.
include	"dev/isa/files.isa"
major	{wd = 0}
major	{fd = 4}

device	pcic: pcmciabus
file	dev/ic/i82365.c			pcic

# PCIC pcmcia controller on ISA bus.
attach	pcic at isa with pcic_isa
file	dev/isa/i82365_isa.c		pcic_isa

# Code common to ISA and ISAPnP attachments
file	dev/isa/i82365_isasubr.c	pcic_isa | pcic_isapnp | pcic_pci

#
# Machine-independent PCMCIA drivers
#
include "dev/pcmcia/files.pcmcia"

#
# ISA Bus devices
#

file	arch/alpha/isa/isa_machdep.c		isa

define	isadma_bounce
file	arch/alpha/isa/isadma_bounce.c		isadma_bounce & isa_dma

include	"dev/pckbc/files.pckbc"

#
# EISA Bus support
#

include	"dev/eisa/files.eisa"

file	arch/alpha/eisa/eisa_machdep.c		eisa

#
# PCI Bus support
#

# include "dev/pci/files.pci" XXX SEE ABOVE

file	arch/alpha/pci/pciide_machdep.c		pciide

define	alpha_pci_sgmap_pte64
file	arch/alpha/pci/pci_sgmap_pte64.c	alpha_pci_sgmap_pte64

device	apecs: pcibus, alpha_sgmap, alpha_pci_sgmap_pte64
attach	apecs at mainbus
file	arch/alpha/pci/apecs.c			apecs	needs-flag
file	arch/alpha/pci/apecs_bus_io.c		apecs
file	arch/alpha/pci/apecs_bus_mem.c		apecs
file	arch/alpha/pci/apecs_pci.c		apecs
file	arch/alpha/pci/apecs_dma.c		apecs

device	lca: pcibus, alpha_sgmap, alpha_pci_sgmap_pte64
attach	lca at mainbus
file	arch/alpha/pci/lca.c			lca	needs-flag
file	arch/alpha/pci/lca_bus_io.c		lca
file	arch/alpha/pci/lca_bus_mem.c		lca
file	arch/alpha/pci/lca_pci.c		lca
file	arch/alpha/pci/lca_dma.c		lca

device	cia: pcibus, alpha_sgmap, alpha_pci_sgmap_pte64
attach	cia at mainbus
file	arch/alpha/pci/cia.c			cia	needs-flag
file	arch/alpha/pci/cia_dma.c		cia
file	arch/alpha/pci/cia_pci.c		cia
file	arch/alpha/pci/cia_bus_io.c		cia
file	arch/alpha/pci/cia_bus_mem.c		cia
file	arch/alpha/pci/cia_bwx_bus_io.c		cia
file	arch/alpha/pci/cia_bwx_bus_mem.c	cia

device	irongate: pcibus, isadma_bounce
attach	irongate at mainbus
file	arch/alpha/pci/irongate.c		irongate
file	arch/alpha/pci/irongate_bus_io.c	irongate
file	arch/alpha/pci/irongate_bus_mem.c	irongate
file	arch/alpha/pci/irongate_dma.c		irongate
file	arch/alpha/pci/irongate_pci.c		irongate

device	tsc {}
attach	tsc at mainbus
file	arch/alpha/pci/tsc.c			tsc

device	tsciic: i2cbus, i2c_bitbang
attach	tsciic at tsc
file	arch/alpha/pci/tsciic.c			tsciic

device	tsp: pcibus, alpha_sgmap, alpha_pci_sgmap_pte64
attach	tsp at tsc
file	arch/alpha/pci/tsp_dma.c		tsp
file	arch/alpha/pci/tsp_pci.c		tsp
file	arch/alpha/pci/tsp_bus_io.c		tsp
file	arch/alpha/pci/tsp_bus_mem.c		tsp

device	mcpcia: pcibus, alpha_sgmap, alpha_pci_sgmap_pte64
attach	mcpcia at mcbus
file	arch/alpha/pci/mcpcia.c		mcpcia
file	arch/alpha/pci/mcpcia_bus_io.c	mcpcia
file	arch/alpha/pci/mcpcia_bus_mem.c	mcpcia
file	arch/alpha/pci/mcpcia_dma.c	mcpcia
file	arch/alpha/pci/mcpcia_pci.c	mcpcia

file	arch/alpha/pci/pci_2100_a50.c		dec_2100_a50
file	arch/alpha/pci/pci_axppci_33.c		dec_axppci_33
file	arch/alpha/pci/pci_eb164.c		dec_eb164
file	arch/alpha/pci/pci_eb164_intr.s		dec_eb164
file	arch/alpha/pci/pci_eb64plus.c		dec_eb64plus
file	arch/alpha/pci/pci_eb64plus_intr.s	dec_eb64plus
file	arch/alpha/pci/pci_kn20aa.c		dec_kn20aa
file	arch/alpha/pci/pci_kn300.c		dec_kn300
file	arch/alpha/pci/pci_550.c		dec_550
file	arch/alpha/pci/pci_1000a.c		dec_1000a
file	arch/alpha/pci/pci_1000.c		dec_1000
file	arch/alpha/pci/pci_6600.c		dec_6600
file	arch/alpha/pci/pci_alphabook1.c		dec_alphabook1
file	arch/alpha/pci/pci_up1000.c		api_up1000

#
# PCI Bus devices
#

file	arch/alpha/pci/pci_machdep.c		pci

device	sio: isabus, alpha_shared_intr, cy82c693
attach	sio at pci
device	pceb: isabus, eisabus, cy82c693
attach	pceb at pci
file	arch/alpha/pci/sio.c			sio | pceb	needs-flag
file	arch/alpha/pci/sio_pic.c		sio | pceb

device	hme: ether, ifnet, mii, ifmedia
file	dev/ic/hme.c			hme
attach	hme at pci with hme_pci
file	dev/pci/if_hme_pci.c		hme_pci

#
# ISA PnP
#

include	"dev/isa/files.isapnp"
file	arch/alpha/isa/isapnp_machdep.c		isapnp

#
# Devices that can live on multiple busses
#

device	mcclock
attach	mcclock at ioasic with mcclock_ioasic
attach	mcclock at isa with mcclock_isa
file	arch/alpha/alpha/mcclock.c		mcclock
file	arch/alpha/tc/mcclock_ioasic.c		mcclock_ioasic
file	arch/alpha/isa/mcclock_isa.c		mcclock_isa

#
# Standard files
#

file	arch/alpha/alpha/autoconf.c
file	arch/alpha/alpha/clock.c
file	arch/alpha/alpha/conf.c
file	arch/alpha/alpha/db_disasm.c		ddb
file	arch/alpha/alpha/db_interface.c		ddb
file	arch/alpha/alpha/db_trace.c		ddb
file	arch/alpha/alpha/interrupt.c
file	arch/alpha/alpha/ipifuncs.c		multiprocessor
file	arch/alpha/alpha/lock_machdep.c		multiprocessor
file	arch/alpha/alpha/machdep.c
file	arch/alpha/alpha/mainbus.c
file	arch/alpha/alpha/mem.c
file	arch/alpha/alpha/pmap.c
file	arch/alpha/alpha/process_machdep.c
file	arch/alpha/alpha/prom.c
file	arch/alpha/alpha/sys_machdep.c
file	arch/alpha/alpha/trap.c
file	arch/alpha/alpha/fp_complete.c		!no_ieee
file	arch/alpha/alpha/vm_machdep.c
file	arch/alpha/alpha/disksubr.c
file	arch/alpha/dev/bus_dma.c
file	arch/alpha/alpha/mutex.c

#
# Network protocol checksum routines
#

file	arch/alpha/alpha/in_cksum.c

# XXX
file	arch/alpha/alpha/promcons.c

# XXX
file	arch/alpha/alpha/cpuconf.c
file	arch/alpha/alpha/dec_2100_a50.c		dec_2100_a50
file	arch/alpha/alpha/dec_21000.c		dec_21000
file	arch/alpha/alpha/dec_3000_300.c		dec_3000_300
file	arch/alpha/alpha/dec_3000_500.c		dec_3000_500
file	arch/alpha/alpha/dec_axppci_33.c	dec_axppci_33
file	arch/alpha/alpha/dec_eb164.c		dec_eb164
file	arch/alpha/alpha/dec_eb64plus.c		dec_eb64plus
file	arch/alpha/alpha/dec_kn20aa.c		dec_kn20aa
file	arch/alpha/alpha/dec_kn300.c		dec_kn300
file	arch/alpha/alpha/dec_550.c		dec_550
file	arch/alpha/alpha/dec_alphabook1.c	dec_alphabook1
file	arch/alpha/alpha/dec_1000a.c		dec_1000 | dec_1000a
file	arch/alpha/alpha/dec_6600.c		dec_6600
file	arch/alpha/alpha/api_up1000.c		api_up1000

#
# Machine-independent I2C drivers
#
include "dev/i2c/files.i2c"

#
# Machine-independent USB drivers
#
include	"dev/usb/files.usb"

#
# Machine-independent 1-Wire drivers
#
include "dev/onewire/files.onewire"

# Machine-dependent libkern components
file	lib/libkern/softfloat.c			!no_ieee
file	lib/libkern/arch/alpha/__divl.S
file	lib/libkern/arch/alpha/__divlu.S
file	lib/libkern/arch/alpha/__divq.S
file	lib/libkern/arch/alpha/__divqu.S
file	lib/libkern/arch/alpha/__reml.S
file	lib/libkern/arch/alpha/__remlu.S
file	lib/libkern/arch/alpha/__remq.S
file	lib/libkern/arch/alpha/__remqu.S


code:
/*	$OpenBSD: ld.script,v 1.3 2012/12/17 20:31:26 miod Exp $	*/

/*
 * Copyright (c) 2009 Miodrag Vallat.
 *
 * 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.
 */

/*
 * Linker script for an alpha static ELF binary, without any C++ code
 * (ctor/dtor/eh_frame).
 */

OUTPUT_FORMAT("elf64-alpha")
OUTPUT_ARCH(alpha)
ENTRY(__start)
SECTIONS
{
	/*
	 * The start address needs to be a physical address allowing for
	 * enough room for the console firmware, and the boot loader.
	 * On most alpha machines, the console fits in no more than
	 * 2MB, to which we need to add 256KB of boot blocks and the
	 * initial kernel stack.
	 * However, some of the last alpha models (*5 D and E series,
	 * *7, and G series) have much larger console sizes.
	 *
	 * For reference, here is a list of systems and their console
	 * sizes:
	 *
	 *	AXPpci33		10e000, 110000
	 *	EB164			11c000
	 *	AS400 (Avanti)		11e000
	 *	2100/A50 (Avanti)	11e500
	 *	AS1000			12e000
	 *	AS200, AS255		13a000, 1f2000
	 *	AS250			148000
	 *	AS500			14a000
	 *	AS500/600		14c000
	 *	Multia			154000, 158000, 166000
	 *	DS20			156000
	 *	PC164			180000
	 *	PWS			1d6000, 1d8000, 1f2000
	 *	3305 (AS1000A)		1da000
	 *	164SX			1de000
	 *	AS1200			1f0000
	 *	XP1000, AS2100, AS4100	200000
	 *	ES40, CS20, DS10	200000
	 *	AS8400			200000
	 *	ES45			32c000
	 *	DS25			51c000
	 *	GS160			5f2000
	 *
	 * If you change this value, make sure to update KERNBASE in
	 * <machine/param.h> as well.
	 *
	 * Note that the current setting will not work on a GS160.  If you
	 * are the lucky owner of such a system and want to run OpenBSD on
	 * it, please contact <alpha@openbsd.org>
	 */
	. = 0xfffffc0000580000;

	.text :		{ *(.text .text.* .gnu.linkonce.t.*) }
	PROVIDE(etext = .);
	.rodata :	{ *(.rodata .rodata.* .gnu.linkonce.r.*) }
	.data :		{ *(.data .data.* .gnu.linkonce.d.*) }
	.got :		{ *(.got) }
	.sdata :	{ *(.sdata .sdata.* .gnu.linkonce.s.*) }
	.lit8 :		{ *(.lit8) }
	.lita :		{ *(.lita) }
	.sdata :	{ *(.sdata .sdata*) }
	PROVIDE(edata = .);
	.sbss :		{ *(.sbss .sbss.* .gnu.linkonce.sb.* .scommon) }
	.bss :		{ *(.bss .bss.* .gnu.linkonce.b.* COMMON) }
	PROVIDE(_end = .);
	PROVIDE(end = .);
	/DISCARD/ :
	{
		*(.comment)
		*(.eh_frame)
	}
}

license: unknown


code: src/sys/arch/alpha/dev

path: sys/arch/alpha/dev/CVS/Repository


code:
/* $OpenBSD: bus_dma.c,v 1.35 2014/11/16 12:30:56 deraadt Exp $ */
/* $NetBSD: bus_dma.c,v 1.40 2000/07/17 04:47:56 thorpej Exp $ */

/*-
 * Copyright (c) 1997, 1998 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.
 */

#define _ALPHA_BUS_DMA_PRIVATE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/mbuf.h>

#include <uvm/uvm_extern.h>

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

int	_bus_dmamap_load_buffer_direct(bus_dma_tag_t,
	    bus_dmamap_t, void *, bus_size_t, struct proc *, int,
	    paddr_t *, int *, int);

/*
 * Common function for DMA map creation.  May be called by bus-specific
 * DMA map creation functions.
 */
int
_bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
	bus_dma_tag_t t;
	bus_size_t size;
	int nsegments;
	bus_size_t maxsegsz;
	bus_size_t boundary;
	int flags;
	bus_dmamap_t *dmamp;
{
	struct alpha_bus_dmamap *map;
	void *mapstore;
	size_t mapsize;

	/*
	 * Allocate and initialize the DMA map.  The end of the map
	 * is a variable-sized array of segments, so we allocate enough
	 * room for them in one shot.
	 *
	 * Note we don't preserve the WAITOK or NOWAIT flags.  Preservation
	 * of ALLOCNOW notifies others that we've reserved these resources,
	 * and they are not to be freed.
	 *
	 * The bus_dmamap_t includes one bus_dma_segment_t, hence
	 * the (nsegments - 1).
	 */
	mapsize = sizeof(struct alpha_bus_dmamap) +
	    (sizeof(bus_dma_segment_t) * (nsegments - 1));
	if ((mapstore = malloc(mapsize, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ?
	    (M_NOWAIT | M_ZERO) : (M_WAITOK | M_ZERO))) == NULL)
		return (ENOMEM);

	map = (struct alpha_bus_dmamap *)mapstore;
	map->_dm_size = size;
	map->_dm_segcnt = nsegments;
	map->_dm_maxsegsz = maxsegsz;
	if (t->_boundary != 0 && t->_boundary < boundary)
		map->_dm_boundary = t->_boundary;
	else
		map->_dm_boundary = boundary;
	map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
	map->dm_mapsize = 0;		/* no valid mappings */
	map->dm_nsegs = 0;
	map->_dm_window = NULL;

	*dmamp = map;
	return (0);
}

/*
 * Common function for DMA map destruction.  May be called by bus-specific
 * DMA map destruction functions.
 */
void
_bus_dmamap_destroy(t, map)
	bus_dma_tag_t t;
	bus_dmamap_t map;
{

	free(map, M_DEVBUF, 0);
}

/*
 * Utility function to load a linear buffer.  lastaddrp holds state
 * between invocations (for multiple-buffer loads).  segp contains
 * the starting segment on entrance, and the ending segment on exit.
 * first indicates if this is the first invocation of this function.
 */
int
_bus_dmamap_load_buffer_direct(t, map, buf, buflen, p, flags,
    lastaddrp, segp, first)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	void *buf;
	bus_size_t buflen;
	struct proc *p;
	int flags;
	paddr_t *lastaddrp;
	int *segp;
	int first;
{
	bus_size_t sgsize;
	pmap_t pmap;
	bus_addr_t curaddr, lastaddr, baddr, bmask;
	vaddr_t vaddr = (vaddr_t)buf;
	int seg;

	if (p != NULL)
		pmap = p->p_vmspace->vm_map.pmap;
	else
		pmap = pmap_kernel();

	lastaddr = *lastaddrp;
	bmask = ~(map->_dm_boundary - 1);

	for (seg = *segp; buflen > 0 ; ) {
		/*
		 * Get the physical address for this segment.
		 */
		pmap_extract(pmap, vaddr, &curaddr);

		/*
		 * If we're beyond the current DMA window, indicate
		 * that and try to fall back into SGMAPs.
		 */
		if (t->_wsize != 0 && curaddr >= t->_wsize)
			return (EINVAL);

		curaddr |= t->_wbase;

		/*
		 * Compute the segment size, and adjust counts.
		 */
		sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET);
		if (buflen < sgsize)
			sgsize = buflen;
		if (map->_dm_maxsegsz < sgsize)
			sgsize = map->_dm_maxsegsz;

		/*
		 * Make sure we don't cross any boundaries.
		 */
		if (map->_dm_boundary > 0) {
			baddr = (curaddr + map->_dm_boundary) & bmask;
			if (sgsize > (baddr - curaddr))
				sgsize = (baddr - curaddr);
		}

		/*
		 * Insert chunk into a segment, coalescing with
		 * the previous segment if possible.
		 */
		if (first) {
			map->dm_segs[seg].ds_addr = curaddr;
			map->dm_segs[seg].ds_len = sgsize;
			first = 0;
		} else {
			if ((map->_dm_flags & DMAMAP_NO_COALESCE) == 0 &&
			    curaddr == lastaddr &&
			    (map->dm_segs[seg].ds_len + sgsize) <=
			     map->_dm_maxsegsz &&
			    (map->_dm_boundary == 0 ||
			     (map->dm_segs[seg].ds_addr & bmask) ==
			     (curaddr & bmask)))
				map->dm_segs[seg].ds_len += sgsize;
			else {
				if (++seg >= map->_dm_segcnt)
					break;
				map->dm_segs[seg].ds_addr = curaddr;
				map->dm_segs[seg].ds_len = sgsize;
			}
		}

		lastaddr = curaddr + sgsize;
		vaddr += sgsize;
		buflen -= sgsize;
	}

	*segp = seg;
	*lastaddrp = lastaddr;

	/*
	 * Did we fit?
	 */
	if (buflen != 0) {
		/*
		 * If there is a chained window, we will automatically
		 * fall back to it.
		 */
		return (EFBIG);		/* XXX better return value here? */
	}

	return (0);
}

/*
 * Common function for loading a direct-mapped DMA map with a linear
 * buffer.  Called by bus-specific DMA map load functions with the
 * OR value appropriate for indicating "direct-mapped" for that
 * chipset.
 */
int
_bus_dmamap_load_direct(t, map, buf, buflen, p, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	void *buf;
	bus_size_t buflen;
	struct proc *p;
	int flags;
{
	paddr_t lastaddr;
	int seg, error;

	/*
	 * Make sure that on error condition we return "no valid mappings".
	 */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;
	KASSERT((map->_dm_flags & (BUS_DMA_READ|BUS_DMA_WRITE)) == 0);

	if (buflen > map->_dm_size)
		return (EINVAL);

	seg = 0;
	error = _bus_dmamap_load_buffer_direct(t, map, buf, buflen,
	    p, flags, &lastaddr, &seg, 1);
	if (error == 0) {
		map->dm_mapsize = buflen;
		map->dm_nsegs = seg + 1;
		map->_dm_window = t;
	} else if (t->_next_window != NULL) {
		/*
		 * Give the next window a chance.
		 */
		error = bus_dmamap_load(t->_next_window, map, buf, buflen,
		    p, flags);
	}
	return (error);
}

/*
 * Like _bus_dmamap_load_direct(), but for mbufs.
 */
int
_bus_dmamap_load_mbuf_direct(t, map, m0, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	struct mbuf *m0;
	int flags;
{
	paddr_t lastaddr;
	int seg, error, first;
	struct mbuf *m;

	/*
	 * Make sure that on error condition we return "no valid mappings."
	 */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;
	KASSERT((map->_dm_flags & (BUS_DMA_READ|BUS_DMA_WRITE)) == 0);

#ifdef DIAGNOSTIC
	if ((m0->m_flags & M_PKTHDR) == 0)
		panic("_bus_dmamap_load_mbuf_direct: no packet header");
#endif

	if (m0->m_pkthdr.len > map->_dm_size)
		return (EINVAL);

	first = 1;
	seg = 0;
	error = 0;
	for (m = m0; m != NULL && error == 0; m = m->m_next) {
		if (m->m_len == 0)
			continue;
		error = _bus_dmamap_load_buffer_direct(t, map,
		    m->m_data, m->m_len, NULL, flags, &lastaddr, &seg, first);
		first = 0;
	}
	if (error == 0) {
		map->dm_mapsize = m0->m_pkthdr.len;
		map->dm_nsegs = seg + 1;
		map->_dm_window = t;
	} else if (t->_next_window != NULL) {
		/*
		 * Give the next window a chance.
		 */
		error = bus_dmamap_load_mbuf(t->_next_window, map, m0, flags);
	}
	return (error);
}

/*
 * Like _bus_dmamap_load_direct(), but for uios.
 */
int
_bus_dmamap_load_uio_direct(t, map, uio, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	struct uio *uio;
	int flags;
{
	paddr_t lastaddr;
	int seg, i, error, first;
	bus_size_t minlen, resid;
	struct proc *p = NULL;
	struct iovec *iov;
	caddr_t addr;

	/*
	 * Make sure that on error condition we return "no valid mappings."
	 */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;
	KASSERT((map->_dm_flags & (BUS_DMA_READ|BUS_DMA_WRITE)) == 0);

	resid = uio->uio_resid;
	iov = uio->uio_iov;

	if (uio->uio_segflg == UIO_USERSPACE) {
		p = uio->uio_procp;
#ifdef DIAGNOSTIC
		if (p == NULL)
			panic("_bus_dmamap_load_uio_direct: "
			    "USERSPACE but no proc");
#endif
	}

	first = 1;
	seg = 0;
	error = 0;
	for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
		/*
		 * Now at the first iovec to load.  Load each iovec
		 * until we have exhausted the residual count.
		 */
		minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
		addr = (caddr_t)iov[i].iov_base;

		error = _bus_dmamap_load_buffer_direct(t, map,
		    addr, minlen, p, flags, &lastaddr, &seg, first);
		first = 0;

		resid -= minlen;
	}
	if (error == 0) {
		map->dm_mapsize = uio->uio_resid;
		map->dm_nsegs = seg + 1;
		map->_dm_window = t;
	} else if (t->_next_window != NULL) {
		/*
		 * Give the next window a chance.
		 */
		error = bus_dmamap_load_uio(t->_next_window, map, uio, flags);
	}
	return (error);
}

/*
 * Like _bus_dmamap_load_direct(), but for raw memory.
 */
int
_bus_dmamap_load_raw_direct(t, map, segs, nsegs, size, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	bus_dma_segment_t *segs;
	int nsegs;
	bus_size_t size;
	int flags;
{

	panic("_bus_dmamap_load_raw_direct: not implemented");
}

/*
 * Common function for unloading a DMA map.  May be called by
 * chipset-specific DMA map unload functions.
 */
void
_bus_dmamap_unload(t, map)
	bus_dma_tag_t t;
	bus_dmamap_t map;
{

	/*
	 * No resources to free; just mark the mappings as
	 * invalid.
	 */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;
	map->_dm_window = NULL;
	map->_dm_flags &= ~(BUS_DMA_READ|BUS_DMA_WRITE);
}

/*
 * Common function for DMA map synchronization.  May be called
 * by chipset-specific DMA map synchronization functions.
 */
void
_bus_dmamap_sync(t, map, offset, len, op)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	bus_addr_t offset;
	bus_size_t len;
	int op;
{

	/*
	 * Flush the store buffer.
	 */
	alpha_mb();
}

/*
 * Common function for DMA-safe memory allocation.  May be called
 * by bus-specific DMA memory allocation functions.
 */
int
_bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
	bus_dma_tag_t t;
	bus_size_t size, alignment, boundary;
	bus_dma_segment_t *segs;
	int nsegs;
	int *rsegs;
	int flags;
{

	return (_bus_dmamem_alloc_range(t, size, alignment, boundary,
	    segs, nsegs, rsegs, flags, (paddr_t)0, (paddr_t)-1));
}

/*
 * Allocate physical memory from the given physical address range.
 * Called by DMA-safe memory allocation methods.
 */
int
_bus_dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs,
    flags, low, high)
	bus_dma_tag_t t;
	bus_size_t size, alignment, boundary;
	bus_dma_segment_t *segs;
	int nsegs;
	int *rsegs;
	int flags;
	paddr_t low;
	paddr_t high;
{
	paddr_t curaddr, lastaddr;
	struct vm_page *m;
	struct pglist mlist;
	int curseg, error, plaflag;

	/* Always round the size. */
	size = round_page(size);

	/*
	 * Allocate pages from the VM system.
	 */
	plaflag = flags & BUS_DMA_NOWAIT ? UVM_PLA_NOWAIT : UVM_PLA_WAITOK;
	if (flags & BUS_DMA_ZERO)
		plaflag |= UVM_PLA_ZERO;

	TAILQ_INIT(&mlist);
	error = uvm_pglistalloc(size, low, high, alignment, boundary,
	    &mlist, nsegs, plaflag);
	if (error)
		return (error);

	/*
	 * Compute the location, size, and number of segments actually
	 * returned by the VM code.
	 */
	m = TAILQ_FIRST(&mlist);
	curseg = 0;
	lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m);
	segs[curseg].ds_len = PAGE_SIZE;
	m = TAILQ_NEXT(m, pageq);

	for (; m != NULL; m = TAILQ_NEXT(m, pageq)) {
		curaddr = VM_PAGE_TO_PHYS(m);
#ifdef DIAGNOSTIC
		if (curaddr < low || curaddr >= high) {
			printf("uvm_pglistalloc returned non-sensical"
			    " address 0x%lx\n", curaddr);
			panic("_bus_dmamem_alloc");
		}
#endif
		if (curaddr == (lastaddr + PAGE_SIZE))
			segs[curseg].ds_len += PAGE_SIZE;
		else {
			curseg++;
			segs[curseg].ds_addr = curaddr;
			segs[curseg].ds_len = PAGE_SIZE;
		}
		lastaddr = curaddr;
	}

	*rsegs = curseg + 1;

	return (0);
}

/*
 * Common function for freeing DMA-safe memory.  May be called by
 * bus-specific DMA memory free functions.
 */
void
_bus_dmamem_free(t, segs, nsegs)
	bus_dma_tag_t t;
	bus_dma_segment_t *segs;
	int nsegs;
{
	struct vm_page *m;
	bus_addr_t addr;
	struct pglist mlist;
	int curseg;

	/*
	 * Build a list of pages to free back to the VM system.
	 */
	TAILQ_INIT(&mlist);
	for (curseg = 0; curseg < nsegs; curseg++) {
		for (addr = segs[curseg].ds_addr;
		    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
		    addr += PAGE_SIZE) {
			m = PHYS_TO_VM_PAGE(addr);
			TAILQ_INSERT_TAIL(&mlist, m, pageq);
		}
	}

	uvm_pglistfree(&mlist);
}

/*
 * Common function for mapping DMA-safe memory.  May be called by
 * bus-specific DMA memory map functions.
 */
int
_bus_dmamem_map(t, segs, nsegs, size, kvap, flags)
	bus_dma_tag_t t;
	bus_dma_segment_t *segs;
	int nsegs;
	size_t size;
	caddr_t *kvap;
	int flags;
{
	vaddr_t va, sva;
	size_t ssize;
	bus_addr_t addr;
	int curseg, error;
	const struct kmem_dyn_mode *kd;

	/*
	 * If we're only mapping 1 segment, use K0SEG, to avoid
	 * TLB thrashing.
	 */
	if (nsegs == 1) {
		*kvap = (caddr_t)ALPHA_PHYS_TO_K0SEG(segs[0].ds_addr);
		return (0);
	}

	size = round_page(size);
	kd = flags & BUS_DMA_NOWAIT ? &kd_trylock : &kd_waitok;
	va = (vaddr_t)km_alloc(size, &kv_any, &kp_none, kd);
	if (va == 0)
		return (ENOMEM);

	*kvap = (caddr_t)va;

	sva = va;
	ssize = size;
	for (curseg = 0; curseg < nsegs; curseg++) {
		for (addr = segs[curseg].ds_addr;
		    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
		    addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) {
			if (size == 0)
				panic("_bus_dmamem_map: size botch");
			error = pmap_enter(pmap_kernel(), va, addr,
			    PROT_READ | PROT_WRITE,
			    PROT_READ | PROT_WRITE | PMAP_WIRED | PMAP_CANFAIL);
			if (error) {
				pmap_update(pmap_kernel());
				km_free((void *)sva, ssize, &kv_any, &kp_none);
				return (error);
			}
		}
	}
	pmap_update(pmap_kernel());

	return (0);
}

/*
 * Common function for unmapping DMA-safe memory.  May be called by
 * bus-specific DMA memory unmapping functions.
 */
void
_bus_dmamem_unmap(t, kva, size)
	bus_dma_tag_t t;
	caddr_t kva;
	size_t size;
{

#ifdef DIAGNOSTIC
	if ((u_long)kva & PGOFSET)
		panic("_bus_dmamem_unmap");
#endif

	/*
	 * Nothing to do if we mapped it with K0SEG.
	 */
	if (kva >= (caddr_t)ALPHA_K0SEG_BASE &&
	    kva <= (caddr_t)ALPHA_K0SEG_END)
		return;

	km_free(kva, round_page(size), &kv_any, &kp_none);
}

/*
 * Common function for mmap(2)'ing DMA-safe memory.  May be called by
 * bus-specific DMA mmap(2)'ing functions.
 */
paddr_t
_bus_dmamem_mmap(t, segs, nsegs, off, prot, flags)
	bus_dma_tag_t t;
	bus_dma_segment_t *segs;
	int nsegs;
	off_t off;
	int prot, flags;
{
	int i;

	for (i = 0; i < nsegs; i++) {
#ifdef DIAGNOSTIC
		if (off & PGOFSET)
			panic("_bus_dmamem_mmap: offset unaligned");
		if (segs[i].ds_addr & PGOFSET)
			panic("_bus_dmamem_mmap: segment unaligned");
		if (segs[i].ds_len & PGOFSET)
			panic("_bus_dmamem_mmap: segment size not multiple"
			    " of page size");
#endif
		if (off >= segs[i].ds_len) {
			off -= segs[i].ds_len;
			continue;
		}

		return (segs[i].ds_addr + off);
	}

	/* Page not found. */
	return (-1);
}


code:
/* $OpenBSD: sgmap_common.c,v 1.14 2014/12/09 06:58:28 doug Exp $ */
/* $NetBSD: sgmap_common.c,v 1.13 2000/06/29 09:02:57 mrg Exp $ */

/*-
 * Copyright (c) 1997, 1998 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.
 */

#define _ALPHA_BUS_DMA_PRIVATE

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/proc.h>

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

#include <alpha/dev/sgmapvar.h>

/*
 * Some systems will prefetch the next page during a memory -> device DMA.
 * This can cause machine checks if there is not a spill page after the
 * last page of the DMA (thus avoiding hitting an invalid SGMAP PTE).
 */
vaddr_t		alpha_sgmap_prefetch_spill_page_va;
bus_addr_t	alpha_sgmap_prefetch_spill_page_pa;

void
alpha_sgmap_init(t, sgmap, name, wbase, sgvabase, sgvasize, ptesize, ptva,
    minptalign)
	bus_dma_tag_t t;
	struct alpha_sgmap *sgmap;
	const char *name;
	bus_addr_t wbase;
	bus_addr_t sgvabase;
	bus_size_t sgvasize;
	size_t ptesize;
	void *ptva;
	bus_size_t minptalign;
{
	bus_dma_segment_t seg;
	size_t ptsize;
	int rseg;

	if (sgvasize & PGOFSET) {
		printf("size botch for sgmap `%s'\n", name);
		goto die;
	}

	sgmap->aps_wbase = wbase;
	sgmap->aps_sgvabase = sgvabase;
	sgmap->aps_sgvasize = sgvasize;

	if (ptva != NULL) {
		/*
		 * We already have a page table; this may be a system
		 * where the page table resides in bridge-resident SRAM.
		 */
		sgmap->aps_pt = ptva;
		sgmap->aps_ptpa = 0;
	} else {
		/*
		 * Compute the page table size and allocate it.  At minimum,
		 * this must be aligned to the page table size.  However,
		 * some platforms have more strict alignment requirements.
		 */
		ptsize = (sgvasize / PAGE_SIZE) * ptesize;
		if (minptalign != 0) {
			if (minptalign < ptsize)
				minptalign = ptsize;
		} else
			minptalign = ptsize;
		if (bus_dmamem_alloc(t, ptsize, minptalign, 0, &seg, 1, &rseg,
		    BUS_DMA_NOWAIT)) {
			panic("unable to allocate page table for sgmap `%s'",
			    name);
			goto die;
		}
		sgmap->aps_ptpa = seg.ds_addr;
		sgmap->aps_pt = (caddr_t)ALPHA_PHYS_TO_K0SEG(sgmap->aps_ptpa);
	}

	/*
	 * Create the extent map used to manage the virtual address
	 * space.
	 */
	sgmap->aps_ex = extent_create((char *)name, sgvabase, sgvasize - 1,
	    M_DEVBUF, NULL, 0, EX_NOWAIT|EX_NOCOALESCE);
	if (sgmap->aps_ex == NULL) {
		printf("unable to create extent map for sgmap `%s'\n",
		    name);
		goto die;
	}
	mtx_init(&sgmap->aps_mtx, IPL_HIGH);

	/*
	 * Allocate a spill page if that hasn't already been done.
	 */
	if (alpha_sgmap_prefetch_spill_page_va == 0) {
		if (bus_dmamem_alloc(t, PAGE_SIZE, 0, 0, &seg, 1, &rseg,
		    BUS_DMA_NOWAIT)) {
			printf("unable to allocate spill page for sgmap `%s'\n",
			    name);
			goto die;
		}
		alpha_sgmap_prefetch_spill_page_pa = seg.ds_addr;
		alpha_sgmap_prefetch_spill_page_va =
		    ALPHA_PHYS_TO_K0SEG(alpha_sgmap_prefetch_spill_page_pa);
		bzero((caddr_t)alpha_sgmap_prefetch_spill_page_va, PAGE_SIZE);
	}

	return;
 die:
	panic("alpha_sgmap_init");
}

int
alpha_sgmap_dmamap_setup(map, nsegments, flags)
	bus_dmamap_t map;
	int nsegments;
	int flags;
{
	map->_dm_cookie = mallocarray(nsegments, sizeof(struct extent_region),
	    M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK);
	return (map->_dm_cookie == NULL);
}

int
alpha_sgmap_dmamap_create(t, size, nsegments, maxsegsz, boundary,
    flags, dmamp)
	bus_dma_tag_t t;
	bus_size_t size;
	int nsegments;
	bus_size_t maxsegsz;
	bus_size_t boundary;
	int flags;
	bus_dmamap_t *dmamp;
{
	bus_dmamap_t map;
	int error;

	error = _bus_dmamap_create(t, size, nsegments, maxsegsz,
	    boundary, flags, dmamp);
	if (error)
		return (error);

	map = *dmamp;
	if (alpha_sgmap_dmamap_setup(map, nsegments, flags)) {
		_bus_dmamap_destroy(t, map);
		return (ENOMEM);
	}

	/* XXX BUS_DMA_ALLOCNOW */

	return (0);
}

void
alpha_sgmap_dmamap_teardown(map)
	bus_dmamap_t map;
{
	free(map->_dm_cookie, M_DEVBUF, 0);
}

void
alpha_sgmap_dmamap_destroy(t, map)
	bus_dma_tag_t t;
	bus_dmamap_t map;
{
	KASSERT(map->dm_mapsize == 0);

	alpha_sgmap_dmamap_teardown(map);
	_bus_dmamap_destroy(t, map);
}


code:
/* $OpenBSD: sgmap_typedep.c,v 1.14 2014/07/11 12:55:32 dlg Exp $ */
/* $NetBSD: sgmap_typedep.c,v 1.17 2001/07/19 04:27:37 thorpej Exp $ */

/*-
 * Copyright (c) 1997, 1998 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.
 */

#ifdef SGMAP_DEBUG
int			__C(SGMAP_TYPE,_debug) = 0;
#endif

SGMAP_PTE_TYPE		__C(SGMAP_TYPE,_prefetch_spill_page_pte);

int			__C(SGMAP_TYPE,_load_buffer)(bus_dma_tag_t,
			    bus_dmamap_t, void *buf, size_t buflen,
			    struct proc *, int, int, struct alpha_sgmap *);

void
__C(SGMAP_TYPE,_init_spill_page_pte)(void)
{

	__C(SGMAP_TYPE,_prefetch_spill_page_pte) =
	    (alpha_sgmap_prefetch_spill_page_pa >>
	     SGPTE_PGADDR_SHIFT) | SGPTE_VALID;
}

int
__C(SGMAP_TYPE,_load_buffer)(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
    size_t buflen, struct proc *p, int flags, int seg,
    struct alpha_sgmap *sgmap)
{
	vaddr_t endva, va = (vaddr_t)buf;
	paddr_t pa;
	pmap_t pmap;
	bus_addr_t dmaoffset, sgva;
	bus_size_t sgvalen, boundary, alignment;
	struct extent_region *regions = map->_dm_cookie;
	SGMAP_PTE_TYPE *pte, *page_table = sgmap->aps_pt;
	int pteidx, error, spill;

	if (seg >= map->_dm_segcnt)
		return (EFBIG);

	/* Initialize the spill page PTE if it hasn't been already. */
	if (__C(SGMAP_TYPE,_prefetch_spill_page_pte) == 0)
		__C(SGMAP_TYPE,_init_spill_page_pte)();

	/*
	 * Remember the offset into the first page and the total
	 * transfer length.
	 */
	dmaoffset = ((u_long)buf) & PGOFSET;

#ifdef SGMAP_DEBUG
	if (__C(SGMAP_TYPE,_debug)) {
		printf("sgmap_load: ----- buf = %p -----\n", buf);
		printf("sgmap_load: dmaoffset = 0x%lx, buflen = 0x%lx\n",
		    dmaoffset, buflen);
	}
#endif
	if (p != NULL)
		pmap = p->p_vmspace->vm_map.pmap;
	else
		pmap = pmap_kernel();

	/*
	 * Allocate the necessary virtual address space for the
	 * mapping.  Round the size, since we deal with whole pages.
	 */

	/*
	 * XXX Always allocate a spill page for now.  Note
	 * the spill page is not needed for an in-bound-only
	 * transfer.
	 */
	if ((flags & BUS_DMA_READ) == 0)
		spill = 1;
	else
		spill = 0;

	endva = round_page(va + buflen);
	va = trunc_page(va);

	boundary = map->_dm_boundary;
	alignment = PAGE_SIZE;

	sgvalen = (endva - va);
	if (spill) {
		sgvalen += PAGE_SIZE;

		/*
		 * ARGH!  If the addition of the spill page bumped us
		 * over our boundary, we have to 2x the boundary limit.
		 */
		if (boundary && boundary < sgvalen) {
			alignment = boundary;
			do {
				boundary <<= 1;
			} while (boundary < sgvalen);
		}
	}

#if 0
	printf("len 0x%lx -> 0x%lx, boundary 0x%lx -> 0x%lx -> ",
	    (endva - va), sgvalen, map->_dm_boundary, boundary);
#endif

	mtx_enter(&sgmap->aps_mtx);
	error = extent_alloc_with_descr(sgmap->aps_ex, sgvalen, alignment,
	    0, boundary, EX_NOWAIT, &regions[seg], &sgva);
	mtx_leave(&sgmap->aps_mtx);
	if (error)
		return (error);

#if 0
	printf("error %d sgva 0x%lx\n", error, sgva);
#endif

	pteidx = sgva >> SGMAP_ADDR_PTEIDX_SHIFT;
	pte = &page_table[pteidx * SGMAP_PTE_SPACING];

#ifdef SGMAP_DEBUG
	if (__C(SGMAP_TYPE,_debug))
		printf("sgmap_load: sgva = 0x%lx, pteidx = %d, "
		    "pte = %p (pt = %p)\n", sgva, pteidx, pte,
		    page_table);
#endif

	/* Generate the DMA address. */
	map->dm_segs[seg].ds_addr = sgmap->aps_wbase | sgva | dmaoffset;
	map->dm_segs[seg].ds_len = buflen;

#ifdef SGMAP_DEBUG
	if (__C(SGMAP_TYPE,_debug))
		printf("sgmap_load: wbase = 0x%lx, vpage = 0x%x, "
		    "dma addr = 0x%lx\n", sgmap->aps_wbase, sgva,
		    map->dm_segs[seg].ds_addr);
#endif

	for (; va < endva; va += PAGE_SIZE, pteidx++,
	     pte = &page_table[pteidx * SGMAP_PTE_SPACING]) {
		/* Get the physical address for this segment. */
		(void)pmap_extract(pmap, va, &pa);

		/* Load the current PTE with this page. */
		*pte = (pa >> SGPTE_PGADDR_SHIFT) | SGPTE_VALID;
#ifdef SGMAP_DEBUG
		if (__C(SGMAP_TYPE,_debug))
			printf("sgmap_load:     pa = 0x%lx, pte = %p, "
			    "*pte = 0x%lx\n", pa, pte, (u_long)(*pte));
#endif
	}

	if (spill) {
		/* ...and the prefetch-spill page. */
		*pte = __C(SGMAP_TYPE,_prefetch_spill_page_pte);
#ifdef SGMAP_DEBUG
		if (__C(SGMAP_TYPE,_debug)) {
			printf("sgmap_load:     spill page, pte = %p, "
			    "*pte = 0x%lx\n", pte, *pte);
			printf("sgmap_load:     pte count = %d\n",
			    map->_dm_ptecnt);
		}
#endif
	}

	return (0);
}

int
__C(SGMAP_TYPE,_load)(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
    bus_size_t buflen, struct proc *p, int flags, struct alpha_sgmap *sgmap)
{
	int seg, error;

	/*
	 * Make sure that on error condition we return "no valid mappings".
	 */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;

	if (buflen > map->_dm_size)
		return (EINVAL);

	KASSERT((map->_dm_flags & (BUS_DMA_READ|BUS_DMA_WRITE)) == 0);
	KASSERT((flags & (BUS_DMA_READ|BUS_DMA_WRITE)) !=
	    (BUS_DMA_READ|BUS_DMA_WRITE));

	map->_dm_flags |= flags & (BUS_DMA_READ|BUS_DMA_WRITE);

	seg = 0;
	error = __C(SGMAP_TYPE,_load_buffer)(t, map, buf, buflen, p,
	    flags, seg, sgmap);

	alpha_mb();

#if defined(SGMAP_DEBUG) && defined(DDB)
	if (__C(SGMAP_TYPE,_debug) > 1)
		Debugger();
#endif

	if (error == 0) {
		map->dm_mapsize = buflen;
		map->dm_nsegs = 1;
		map->_dm_window = t;
	} else {
		map->_dm_flags &= ~(BUS_DMA_READ|BUS_DMA_WRITE);
		if (t->_next_window != NULL) {
			/* Give the next window a chance. */
			error = bus_dmamap_load(t->_next_window, map, buf,
			    buflen, p, flags);
		}
	}
	return (error);
}

int
__C(SGMAP_TYPE,_load_mbuf)(bus_dma_tag_t t, bus_dmamap_t map,
    struct mbuf *m0, int flags, struct alpha_sgmap *sgmap)
{
	struct mbuf *m;
	int seg, error;

	/*
	 * Make sure that on error condition we return "no valid mappings".
	 */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;

#ifdef DIAGNOSTIC
	if ((m0->m_flags & M_PKTHDR) == 0)
		panic(__S(__C(SGMAP_TYPE,_load_mbuf)) ": no packet header");
#endif

	if (m0->m_pkthdr.len > map->_dm_size)
		return (EINVAL);

	KASSERT((map->_dm_flags & (BUS_DMA_READ|BUS_DMA_WRITE)) == 0);
	KASSERT((flags & (BUS_DMA_READ|BUS_DMA_WRITE)) !=
	    (BUS_DMA_READ|BUS_DMA_WRITE));

	map->_dm_flags |= flags & (BUS_DMA_READ|BUS_DMA_WRITE);

	seg = 0;
	error = 0;
	for (m = m0; m != NULL && error == 0; m = m->m_next) {
		if (m->m_len == 0)
			continue;
		error = __C(SGMAP_TYPE,_load_buffer)(t, map,
		    m->m_data, m->m_len, NULL, flags, seg, sgmap);
		seg++;
	}

	alpha_mb();

#if defined(SGMAP_DEBUG) && defined(DDB)
	if (__C(SGMAP_TYPE,_debug) > 1)
		Debugger();
#endif

	if (error == 0) {
		map->dm_mapsize = m0->m_pkthdr.len;
		map->dm_nsegs = seg;
		map->_dm_window = t;
	} else {
		/* Need to back out what we've done so far. */
		map->dm_nsegs = seg - 1;
		__C(SGMAP_TYPE,_unload)(t, map, sgmap);
		map->_dm_flags &= ~(BUS_DMA_READ|BUS_DMA_WRITE);
		if (t->_next_window != NULL) {
			/* Give the next window a chance. */
			error = bus_dmamap_load_mbuf(t->_next_window, map,
			    m0, flags);
		}
	}

	return (error);
}

int
__C(SGMAP_TYPE,_load_uio)(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio,
    int flags, struct alpha_sgmap *sgmap)
{
	bus_size_t minlen, resid;
	struct proc *p = NULL;
	struct iovec *iov;
	caddr_t addr;
	int i, seg, error;

	/*
	 * Make sure that on error condition we return "no valid mappings".
	 */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;

	KASSERT((map->_dm_flags & (BUS_DMA_READ|BUS_DMA_WRITE)) == 0);
	KASSERT((flags & (BUS_DMA_READ|BUS_DMA_WRITE)) !=
 	    (BUS_DMA_READ|BUS_DMA_WRITE));

	map->_dm_flags |= flags & (BUS_DMA_READ|BUS_DMA_WRITE);

	resid = uio->uio_resid;
	iov = uio->uio_iov;

	if (uio->uio_segflg == UIO_USERSPACE) {
		p = uio->uio_procp;
#ifdef DIAGNOSTIC
		if (p == NULL)
			panic(__S(__C(SGMAP_TYPE,_load_uio))
			    ": USERSPACE but no proc");
#endif
	}

	seg = 0;
	error = 0;
	for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0;
	     i++, seg++) {
		/*
		 * Now at the first iovec to load.  Load each iovec
		 * until we have exhausted the residual count.
		 */
		minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
		addr = (caddr_t)iov[i].iov_base;

		error = __C(SGMAP_TYPE,_load_buffer)(t, map,
		    addr, minlen, p, flags, seg, sgmap);

		resid -= minlen;
	}

	alpha_mb();

#if defined(SGMAP_DEBUG) && defined(DDB)
	if (__C(SGMAP_TYPE,_debug) > 1)
		Debugger();
#endif

	if (error == 0) {
		map->dm_mapsize = uio->uio_resid;
		map->dm_nsegs = seg;
	} else {
		/* Need to back out what we've done so far. */
		map->dm_nsegs = seg - 1;
		__C(SGMAP_TYPE,_unload)(t, map, sgmap);
		map->_dm_flags &= ~(BUS_DMA_READ|BUS_DMA_WRITE);
		if (t->_next_window != NULL) {
			/* Give the next window a chance. */
			error = bus_dmamap_load_uio(t->_next_window, map,
			    uio, flags);
		}
	}

	return (error);
}

int
__C(SGMAP_TYPE,_load_raw)(bus_dma_tag_t t, bus_dmamap_t map,
    bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags,
    struct alpha_sgmap *sgmap)
{
	KASSERT((map->_dm_flags & (BUS_DMA_READ|BUS_DMA_WRITE)) == 0);
	KASSERT((flags & (BUS_DMA_READ|BUS_DMA_WRITE)) !=
	    (BUS_DMA_READ|BUS_DMA_WRITE));

	panic(__S(__C(SGMAP_TYPE,_load_raw)) ": not implemented");
}

void
__C(SGMAP_TYPE,_unload)(bus_dma_tag_t t, bus_dmamap_t map,
    struct alpha_sgmap *sgmap)
{
	SGMAP_PTE_TYPE *pte, *page_table = sgmap->aps_pt;
	bus_addr_t osgva, sgva, esgva;
	int error, spill, seg, pteidx;

	for (seg = 0; seg < map->dm_nsegs; seg++) {
		/*
		 * XXX Always allocate a spill page for now.  Note
		 * the spill page is not needed for an in-bound-only
		 * transfer.
		 */
		if ((map->_dm_flags & BUS_DMA_READ) == 0)
			spill = 1;
		else
			spill = 0;

		sgva = map->dm_segs[seg].ds_addr & ~sgmap->aps_wbase;

		esgva = round_page(sgva + map->dm_segs[seg].ds_len);
		osgva = sgva = trunc_page(sgva);

		if (spill)
			esgva += PAGE_SIZE;

		/* Invalidate the PTEs for the mapping. */
		for (pteidx = sgva >> SGMAP_ADDR_PTEIDX_SHIFT;
		     sgva < esgva; sgva += PAGE_SIZE, pteidx++) {
			pte = &page_table[pteidx * SGMAP_PTE_SPACING];
#ifdef SGMAP_DEBUG
			if (__C(SGMAP_TYPE,_debug))
				printf("sgmap_unload:     pte = %p, "
				    "*pte = 0x%lx\n", pte, (u_long)(*pte));
#endif
			*pte = 0;
		}

		alpha_mb();

		/* Free the virtual address space used by the mapping. */
		mtx_enter(&sgmap->aps_mtx);
		error = extent_free(sgmap->aps_ex, osgva, (esgva - osgva),
		    EX_NOWAIT);
		mtx_leave(&sgmap->aps_mtx);
		if (error != 0)
			panic(__S(__C(SGMAP_TYPE,_unload)));
	}

	map->_dm_flags &= ~(BUS_DMA_READ|BUS_DMA_WRITE);

	/* Mark the mapping invalid. */
	map->dm_mapsize = 0;
	map->dm_nsegs = 0;
	map->_dm_window = NULL;
}


code:
/* $OpenBSD: sgmap_typedep.h,v 1.3 2008/06/26 05:42:08 ray Exp $ */
/* $NetBSD: sgmap_typedep.h,v 1.4 1998/06/04 01:22:52 thorpej Exp $ */

/*-
 * Copyright (c) 1997, 1998 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.
 */

#undef __C
#undef __S

#define	__C(A,B)	__CONCAT(A,B)
#define	__S(S)		__STRING(S)

extern	SGMAP_PTE_TYPE	__C(SGMAP_TYPE,_prefetch_spill_page_pte);

void	__C(SGMAP_TYPE,_init_spill_page_pte)(void);
int	__C(SGMAP_TYPE,_load)(bus_dma_tag_t, bus_dmamap_t,
	    void *, bus_size_t, struct proc *, int, struct alpha_sgmap *);
int	__C(SGMAP_TYPE,_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
	    struct mbuf *, int, struct alpha_sgmap *);
int	__C(SGMAP_TYPE,_load_uio)(bus_dma_tag_t, bus_dmamap_t,
	    struct uio *, int, struct alpha_sgmap *);
int	__C(SGMAP_TYPE,_load_raw)(bus_dma_tag_t, bus_dmamap_t,
	    bus_dma_segment_t *, int, bus_size_t, int, struct alpha_sgmap *);
void	__C(SGMAP_TYPE,_unload)(bus_dma_tag_t, bus_dmamap_t,
	    struct alpha_sgmap *);


code:
/* $OpenBSD: sgmapvar.h,v 1.7 2014/06/14 23:11:20 jmatthew Exp $ */
/* $NetBSD: sgmapvar.h,v 1.10 1998/08/14 16:50:02 thorpej Exp $ */

/*-
 * Copyright (c) 1997, 1998 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.
 */

#ifndef	_ALPHA_COMMON_SGMAPVAR_H
#define	_ALPHA_COMMON_SGMAPVAR_H

#include <sys/extent.h>
#include <sys/mutex.h>
#include <machine/bus.h>

/*
 * Bits n:13 of the DMA address are the index of the PTE into
 * the SGMAP page table.
 */
#define	SGMAP_ADDR_PTEIDX_SHIFT	13

/*
 * An Alpha SGMAP's state information.  Nothing in the sgmap requires
 * locking[*], with the exception of the extent map.  Locking of the
 * extent map is handled within the extent manager itself.
 *
 * [*] While the page table is a `global' resource, access to it is
 * controlled by the extent map; once a region has been allocated from
 * the map, that region is effectively `locked'.
 */
struct alpha_sgmap {
	struct extent *aps_ex;		/* extent map to manage sgva space */
	struct mutex aps_mtx;
	void	*aps_pt;		/* page table */
	bus_addr_t aps_ptpa;		/* page table physical address */
	bus_addr_t aps_sgvabase;	/* base of the sgva space */
	bus_size_t aps_sgvasize;	/* size of the sgva space */
	bus_addr_t aps_wbase;		/* base of the dma window */
};

extern	vaddr_t alpha_sgmap_prefetch_spill_page_va;
extern	bus_addr_t alpha_sgmap_prefetch_spill_page_pa;

void	alpha_sgmap_init(bus_dma_tag_t, struct alpha_sgmap *,
	    const char *, bus_addr_t, bus_addr_t, bus_size_t, size_t, void *,
	    bus_size_t);

int	alpha_sgmap_dmamap_setup(bus_dmamap_t, int, int);
void	alpha_sgmap_dmamap_teardown(bus_dmamap_t);
int	alpha_sgmap_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
	    bus_size_t, int, bus_dmamap_t *);
void	alpha_sgmap_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);

#endif	/* _ALPHA_COMMON_SGMAPVAR_H */


code:
/* $OpenBSD: shared_intr.c,v 1.21 2015/05/19 20:28:14 miod Exp $ */
/* $NetBSD: shared_intr.c,v 1.13 2000/03/19 01:46:18 thorpej Exp $ */

/*
 * Copyright (c) 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Authors: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

/*
 * Common shared-interrupt-line functionality.
 */

#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
#include <sys/queue.h>

#include <machine/intr.h>

static const char *intr_typename(int);

static const char *
intr_typename(type)
	int type;
{

	switch (type) {
	case IST_UNUSABLE:
		return ("disabled");
	case IST_NONE:
		return ("none");
	case IST_PULSE:
		return ("pulsed");
	case IST_EDGE:
		return ("edge-triggered");
	case IST_LEVEL:
		return ("level-triggered");
	}
	panic("intr_typename: unknown type %d", type);
}

struct alpha_shared_intr *
alpha_shared_intr_alloc(n)
	unsigned int n;
{
	struct alpha_shared_intr *intr;
	unsigned int i;

	intr = mallocarray(n, sizeof(struct alpha_shared_intr), M_DEVBUF,
	    cold ? M_NOWAIT : M_WAITOK);
	if (intr == NULL)
		panic("alpha_shared_intr_alloc: couldn't malloc intr");

	for (i = 0; i < n; i++) {
		TAILQ_INIT(&intr[i].intr_q);
		intr[i].intr_sharetype = IST_NONE;
		intr[i].intr_dfltsharetype = IST_NONE;
		intr[i].intr_nstrays = 0;
		intr[i].intr_maxstrays = 5;
		intr[i].intr_private = NULL;
	}

	return (intr);
}

int
alpha_shared_intr_dispatch(intr, num)
	struct alpha_shared_intr *intr;
	unsigned int num;
{
	struct alpha_shared_intrhand *ih;
	int rv, handled;

	handled = 0;
	TAILQ_FOREACH(ih, &intr[num].intr_q, ih_q) {
#if defined(MULTIPROCESSOR)
		/* XXX Need to support IPL_MPSAFE eventually. */
		if (ih->ih_level < IPL_CLOCK)
			__mp_lock(&kernel_lock);
#endif
		/*
		 * The handler returns one of three values:
		 *   0:	This interrupt wasn't for me.
		 *   1: This interrupt was for me.
		 *  -1: This interrupt might have been for me, but I can't say
		 *      for sure.
		 */
		rv = (*ih->ih_fn)(ih->ih_arg);
		if (rv)
			ih->ih_count.ec_count++;
#if defined(MULTIPROCESSOR)
		if (ih->ih_level < IPL_CLOCK)
			__mp_unlock(&kernel_lock);
#endif
		handled = handled || (rv != 0);
		if (intr_shared_edge == 0 && rv == 1)
			break;
	}

	return (handled);
}

void *
alpha_shared_intr_establish(intr, num, type, level, fn, arg, basename)
	struct alpha_shared_intr *intr;
	unsigned int num;
	int type, level;
	int (*fn)(void *);
	void *arg;
	const char *basename;
{
	struct alpha_shared_intrhand *ih;

	if (intr[num].intr_sharetype == IST_UNUSABLE) {
		printf("alpha_shared_intr_establish: %s %d: unusable\n",
		    basename, num);
		return NULL;
	}

	/* no point in sleeping unless someone can free memory. */
	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
	if (ih == NULL)
		panic("alpha_shared_intr_establish: can't malloc intrhand");

#ifdef DIAGNOSTIC
	if (type == IST_NONE)
		panic("alpha_shared_intr_establish: bogus type");
#endif

	switch (intr[num].intr_sharetype) {
	case IST_EDGE:
		intr_shared_edge = 1;
		/* FALLTHROUGH */
	case IST_LEVEL:
		if (type == intr[num].intr_sharetype)
			break;
	case IST_PULSE:
		if (type != IST_NONE) {
			if (TAILQ_EMPTY(&intr[num].intr_q)) {
				printf("alpha_shared_intr_establish: %s %d: warning: using %s on %s\n",
				    basename, num, intr_typename(type),
				    intr_typename(intr[num].intr_sharetype));
				type = intr[num].intr_sharetype;
			} else {
				panic("alpha_shared_intr_establish: %s %d: can't share %s with %s",
				    basename, num, intr_typename(type),
				    intr_typename(intr[num].intr_sharetype));
			}
		}
		break;

	case IST_NONE:
		/* not currently used; safe */
		break;
	}

	ih->ih_intrhead = intr;
	ih->ih_fn = fn;
	ih->ih_arg = arg;
	ih->ih_level = level;
	ih->ih_num = num;
	evcount_attach(&ih->ih_count, basename, &ih->ih_num);

	intr[num].intr_sharetype = type;
	TAILQ_INSERT_TAIL(&intr[num].intr_q, ih, ih_q);

	return (ih);
}

void
alpha_shared_intr_disestablish(intr, cookie)
	struct alpha_shared_intr *intr;
	void *cookie;
{
	struct alpha_shared_intrhand *ih = cookie;
	unsigned int num = ih->ih_num;

	/*
	 * Just remove it from the list and free the entry.  We let
	 * the caller deal with resetting the share type, if appropriate.
	 */
	evcount_detach(&ih->ih_count);
	TAILQ_REMOVE(&intr[num].intr_q, ih, ih_q);
	free(ih, M_DEVBUF, 0);
}

int
alpha_shared_intr_get_sharetype(intr, num)
	struct alpha_shared_intr *intr;
	unsigned int num;
{

	return (intr[num].intr_sharetype);
}

int
alpha_shared_intr_isactive(intr, num)
	struct alpha_shared_intr *intr;
	unsigned int num;
{

	return (!TAILQ_EMPTY(&intr[num].intr_q));
}

int
alpha_shared_intr_firstactive(struct alpha_shared_intr *intr, unsigned int num)
{

	return (!TAILQ_EMPTY(&intr[num].intr_q) &&
		TAILQ_NEXT(intr[num].intr_q.tqh_first, ih_q) == NULL);
}

void
alpha_shared_intr_set_dfltsharetype(intr, num, newdfltsharetype)
	struct alpha_shared_intr *intr;
	unsigned int num;
	int newdfltsharetype;
{

#ifdef DIAGNOSTIC
	if (alpha_shared_intr_isactive(intr, num))
		panic("alpha_shared_intr_set_dfltsharetype on active intr");
#endif

	intr[num].intr_dfltsharetype = newdfltsharetype;
	intr[num].intr_sharetype = intr[num].intr_dfltsharetype;
}

void
alpha_shared_intr_set_maxstrays(intr, num, newmaxstrays)
	struct alpha_shared_intr *intr;
	unsigned int num;
	int newmaxstrays;
{
	int s = splhigh();
	intr[num].intr_maxstrays = newmaxstrays;
	intr[num].intr_nstrays = 0;
	splx(s);
}

void
alpha_shared_intr_reset_strays(intr, num)
	struct alpha_shared_intr *intr;
	unsigned int num;
{

	/*
	 * Don't bother blocking interrupts; this doesn't have to be
	 * precise, but it does need to be fast.
	 */
	intr[num].intr_nstrays = 0;
}

void
alpha_shared_intr_stray(intr, num, basename)
	struct alpha_shared_intr *intr;
	unsigned int num;
	const char *basename;
{

	intr[num].intr_nstrays++;

	if (intr[num].intr_maxstrays == 0)
		return;

	if (intr[num].intr_nstrays <= intr[num].intr_maxstrays)
		log(LOG_ERR, "stray %s %d%s\n", basename, num,
		    intr[num].intr_nstrays >= intr[num].intr_maxstrays ?
		      "; stopped logging" : "");
}

void
alpha_shared_intr_set_private(intr, num, v)
	struct alpha_shared_intr *intr;
	unsigned int num;
	void *v;
{

	intr[num].intr_private = v;
}

void *
alpha_shared_intr_get_private(intr, num)
	struct alpha_shared_intr *intr;
	unsigned int num;
{

	return (intr[num].intr_private);
}


code:
/eisa_machdep.c/1.5/Sat Jul 12 18:44:40 2014//TOPENBSD_5_8_BASE
/eisa_machdep.h/1.8/Sat Aug 22 02:54:50 2009//TOPENBSD_5_8_BASE
D

path: sys/arch/alpha/eisa/CVS/Entries


code: src/sys/arch/alpha/eisa

path: sys/arch/alpha/eisa/CVS/Repository


code:
/* $OpenBSD: eisa_machdep.c,v 1.5 2014/07/12 18:44:40 tedu Exp $ */
/* $NetBSD: eisa_machdep.c,v 1.1 2000/07/29 23:18:47 thorpej Exp $ */

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe.
 *
 * 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.
 */

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

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

#include <dev/eisa/eisareg.h>
#include <dev/eisa/eisavar.h>

int	eisa_compute_maxslots(const char *);

#define	EISA_SLOT_HEADER_SIZE	31
#define	EISA_SLOT_INFO_OFFSET	20

#define	EISA_FUNC_INFO_OFFSET	34
#define	EISA_CONFIG_BLOCK_SIZE	320

#define	ECUF_TYPE_STRING	0x01
#define	ECUF_MEM_ENTRY		0x02
#define	ECUF_IRQ_ENTRY		0x04
#define	ECUF_DMA_ENTRY		0x08
#define	ECUF_IO_ENTRY		0x10
#define	ECUF_INIT_ENTRY		0x20
#define	ECUF_DISABLED		0x80

#define	ECUF_SELECTIONS_SIZE	26
#define	ECUF_TYPE_STRING_SIZE	80
#define	ECUF_MEM_ENTRY_SIZE	7
#define	ECUF_IRQ_ENTRY_SIZE	2
#define	ECUF_DMA_ENTRY_SIZE	2
#define	ECUF_IO_ENTRY_SIZE	3
#define	ECUF_INIT_ENTRY_SIZE	60

#define	ECUF_MEM_ENTRY_CNT	9
#define	ECUF_IRQ_ENTRY_CNT	7
#define	ECUF_DMA_ENTRY_CNT	4
#define	ECUF_IO_ENTRY_CNT	20

#define	CBUFSIZE		512

/*
 * EISA configuration space, as set up by the ECU, may be sparse.
 */
bus_size_t eisa_config_stride;
paddr_t eisa_config_addr;		/* defaults to 0 */
paddr_t eisa_config_header_addr;

struct ecu_mem {
	SIMPLEQ_ENTRY(ecu_mem) ecum_list;
	bus_addr_t ecum_addr;
	bus_size_t ecum_size;
	int	ecum_isram;
	int	ecum_decode;
	int	ecum_unitsize;
};

struct ecu_irq {
	SIMPLEQ_ENTRY(ecu_irq) ecui_list;
	int	ecui_irq;
	int	ecui_ist;
	int	ecui_shared;
};

struct ecu_dma {
	SIMPLEQ_ENTRY(ecu_dma) ecud_list;
	int	ecud_drq;
	int	ecud_shared;
	int	ecud_size;
#define	ECUD_SIZE_8BIT		0
#define	ECUD_SIZE_16BIT		1
#define	ECUD_SIZE_32BIT		2
#define	ECUD_SIZE_RESERVED	3
	int	ecud_timing;
#define	ECUD_TIMING_ISA		0
#define	ECUD_TIMING_TYPEA	1
#define	ECUD_TIMING_TYPEB	2
#define	ECUD_TIMING_TYPEC	3
};

struct ecu_io {
	SIMPLEQ_ENTRY(ecu_io) ecuio_list;
	bus_addr_t ecuio_addr;
	bus_size_t ecuio_size;
	int	ecuio_shared;
};

struct ecu_func {
	SIMPLEQ_ENTRY(ecu_func) ecuf_list;
	int ecuf_funcno;
	u_int32_t ecuf_id;
	u_int16_t ecuf_slot_info;
	u_int16_t ecuf_cfg_ext;
	u_int8_t ecuf_selections[ECUF_SELECTIONS_SIZE];
	u_int8_t ecuf_func_info;
	u_int8_t ecuf_type_string[ECUF_TYPE_STRING_SIZE];
	u_int8_t ecuf_init[ECUF_INIT_ENTRY_SIZE];
	SIMPLEQ_HEAD(, ecu_mem) ecuf_mem;
	SIMPLEQ_HEAD(, ecu_irq) ecuf_irq;
	SIMPLEQ_HEAD(, ecu_dma) ecuf_dma;
	SIMPLEQ_HEAD(, ecu_io) ecuf_io;
};

struct ecu_data {
	SIMPLEQ_ENTRY(ecu_data) ecud_list;
	int ecud_slot;
	u_int8_t ecud_eisaid[EISA_IDSTRINGLEN];
	u_int32_t ecud_offset;

	/* General slot info. */
	u_int8_t ecud_slot_info;
	u_int16_t ecud_ecu_major_rev;
	u_int16_t ecud_ecu_minor_rev;
	u_int16_t ecud_cksum;
	u_int16_t ecud_ndevfuncs;
	u_int8_t ecud_funcinfo;
	u_int32_t ecud_comp_id;

	/* The functions */
	SIMPLEQ_HEAD(, ecu_func) ecud_funcs;
};

SIMPLEQ_HEAD(, ecu_data) ecu_data_list =
    SIMPLEQ_HEAD_INITIALIZER(ecu_data_list);

static void
ecuf_init(struct ecu_func *ecuf)
{

	memset(ecuf, 0, sizeof(*ecuf));
	SIMPLEQ_INIT(&ecuf->ecuf_mem);
	SIMPLEQ_INIT(&ecuf->ecuf_irq);
	SIMPLEQ_INIT(&ecuf->ecuf_dma);
	SIMPLEQ_INIT(&ecuf->ecuf_io);
}

static void
eisa_parse_mem(struct ecu_func *ecuf, u_int8_t *dp)
{
	struct ecu_mem *ecum;
	int i;

	for (i = 0; i < ECUF_MEM_ENTRY_CNT; i++) {
		ecum = malloc(sizeof(*ecum), M_DEVBUF, M_ZERO|M_WAITOK);

		ecum->ecum_isram = dp[0] & 0x1;
		ecum->ecum_unitsize = dp[1] & 0x3;
		ecum->ecum_decode = (dp[1] >> 2) & 0x3;
		ecum->ecum_addr = (dp[2] | (dp[3] << 8) | (dp[4] << 16)) << 8;
		ecum->ecum_size = (dp[5] | (dp[6] << 8)) << 10;
		if (ecum->ecum_size == 0)
			ecum->ecum_size = (1 << 26);
		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_mem, ecum, ecum_list);

#ifdef EISA_DEBUG
		printf("MEM 0x%lx 0x%lx %d %d %d\n",
		    ecum->ecum_addr, ecum->ecum_size,
		    ecum->ecum_isram, ecum->ecum_unitsize,
		    ecum->ecum_decode);
#endif

		if ((dp[0] & 0x80) == 0)
			break;
		dp += ECUF_MEM_ENTRY_SIZE;
	}
}

static void
eisa_parse_irq(struct ecu_func *ecuf, u_int8_t *dp)
{
	struct ecu_irq *ecui;
	int i;

	for (i = 0; i < ECUF_IRQ_ENTRY_CNT; i++) {
		ecui = malloc(sizeof(*ecui), M_DEVBUF, M_ZERO|M_WAITOK);

		ecui->ecui_irq = dp[0] & 0xf;
		ecui->ecui_ist = (dp[0] & 0x20) ? IST_LEVEL : IST_EDGE;
		ecui->ecui_shared = (dp[0] & 0x40) ? 1 : 0;
		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_irq, ecui, ecui_list);

#ifdef EISA_DEBUG
		printf("IRQ %d %s%s\n", ecui->ecui_irq,
		    ecui->ecui_ist == IST_LEVEL ? "level" : "edge",
		    ecui->ecui_shared ? " shared" : "");
#endif

		if ((dp[0] & 0x80) == 0)
			break;
		dp += ECUF_IRQ_ENTRY_SIZE;
	}
}

static void
eisa_parse_dma(struct ecu_func *ecuf, u_int8_t *dp)
{
	struct ecu_dma *ecud;
	int i;

	for (i = 0; i < ECUF_DMA_ENTRY_CNT; i++) {
		ecud = malloc(sizeof(*ecud), M_DEVBUF, M_ZERO|M_WAITOK);

		ecud->ecud_drq = dp[0] & 0x7;
		ecud->ecud_shared = dp[0] & 0x40;
		ecud->ecud_size = (dp[1] >> 2) & 0x3;
		ecud->ecud_timing = (dp[1] >> 4) & 0x3;
		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_dma, ecud, ecud_list);

#ifdef EISA_DEBUG
		printf("DRQ %d%s %d %d\n", ecud->ecud_drq,
		    ecud->ecud_shared ? " shared" : "",
		    ecud->ecud_size, ecud->ecud_timing);
#endif

		if ((dp[0] & 0x80) == 0)
			break;
		dp += ECUF_DMA_ENTRY_SIZE;
	}
}

static void
eisa_parse_io(struct ecu_func *ecuf, u_int8_t *dp)
{
	struct ecu_io *ecuio;
	int i;

	for (i = 0; i < ECUF_IO_ENTRY_CNT; i++) {
		ecuio = malloc(sizeof(*ecuio), M_DEVBUF, M_ZERO|M_WAITOK);

		ecuio->ecuio_addr = dp[1] | (dp[2] << 8);
		ecuio->ecuio_size = (dp[0] & 0x1f) + 1;
		ecuio->ecuio_shared = (dp[0] & 0x40) ? 1 : 0;
		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_io, ecuio, ecuio_list);

#ifdef EISA_DEBUG
		printf("IO 0x%lx 0x%lx%s\n", ecuio->ecuio_addr,
		    ecuio->ecuio_size,
		    ecuio->ecuio_shared ? " shared" : "");
#endif

		if ((dp[0] & 0x80) == 0)
			break;
		dp += ECUF_IO_ENTRY_SIZE;
	}
}

static void
eisa_read_config_bytes(paddr_t addr, void *buf, size_t count)
{
	const u_int8_t *src = (const u_int8_t *)ALPHA_PHYS_TO_K0SEG(addr);
	u_int8_t *dst = buf;

	for (; count != 0; count--) {
		*dst++ = *src;
		src += eisa_config_stride;
	}
}

static void
eisa_read_config_word(paddr_t addr, u_int32_t *valp)
{
	const u_int8_t *src = (const u_int8_t *)ALPHA_PHYS_TO_K0SEG(addr);
	u_int32_t val = 0;
	int i;

	for (i = 0; i < sizeof(val); i++) {
		val |= (u_int32_t)*src << (i * 8);
		src += eisa_config_stride;
	}

	*valp = val;
}

static size_t
eisa_uncompress(void *cbufp, void *ucbufp, size_t count)
{
	const u_int8_t *cbuf = cbufp;
	u_int8_t *ucbuf = ucbufp;
	u_int zeros = 0;

	while (count--) {
		if (zeros) {
			zeros--;
			*ucbuf++ = '\0';
		} else if (*cbuf == '\0') {
			*ucbuf++ = *cbuf++;
			zeros = *cbuf++ - 1;
		} else
			*ucbuf++ = *cbuf++;
	}

	return ((size_t)cbuf - (size_t)cbufp);
}

void
eisa_init(eisa_chipset_tag_t ec)
{
	struct ecu_data *ecud;
	paddr_t cfgaddr;
	u_int32_t offset;
	u_int8_t eisaid[EISA_IDSTRINGLEN];
	u_int8_t *cdata, *data;
	u_int8_t *cdp, *dp;
	struct ecu_func *ecuf;
	int i, func;

	/*
	 * Locate EISA configuration space.
	 */
	if (hwrpb->rpb_condat_off == 0UL ||
	    (hwrpb->rpb_condat_off >> 63) != 0) {
		printf(": WARNING: no EISA configuration space");
		return;
	}

	if (eisa_config_header_addr) {
		printf("\n");
		panic("eisa_init: EISA config space already initialized");
	}

	eisa_config_header_addr = hwrpb->rpb_condat_off;
	if (eisa_config_stride == 0)
		eisa_config_stride = 1;

#ifdef EISA_DEBUG
	printf("\nEISA config header at 0x%lx\n", eisa_config_header_addr);
	printf("EISA config at %p\n", eisa_config_addr);
	printf("EISA config stride: %ld\n", eisa_config_stride);
#endif

	/*
	 * Read SLOT 0 (motherboard) id, and decide how many (logical)
	 * slots there are.
	 */
	eisa_read_config_bytes(eisa_config_header_addr, eisaid, sizeof(eisaid));
	eisaid[EISA_IDSTRINGLEN - 1] = '\0';	/* sanity */
	ec->ec_maxslots = eisa_compute_maxslots((const char *)eisaid);
	printf(": %s, %d slots", (const char *)eisaid, ec->ec_maxslots - 1);

	/*
	 * Read the slot headers, and allocate config structures for
	 * valid slots.
	 */
	for (cfgaddr = eisa_config_header_addr, i = 0;
	    i < eisa_maxslots(ec); i++) {
		eisa_read_config_bytes(cfgaddr, eisaid, sizeof(eisaid));
		eisaid[EISA_IDSTRINGLEN - 1] = '\0';	/* sanity */
		cfgaddr += sizeof(eisaid) * eisa_config_stride;
		eisa_read_config_word(cfgaddr, &offset);
		cfgaddr += sizeof(offset) * eisa_config_stride;

		if (offset != 0 && offset != 0xffffffff) {
#ifdef EISA_DEBUG
			printf("SLOT %d: offset 0x%08x eisaid %s\n",
			    i, offset, eisaid);
#endif
			ecud = malloc(sizeof(*ecud), M_DEVBUF, M_ZERO|M_WAITOK);

			SIMPLEQ_INIT(&ecud->ecud_funcs);

			ecud->ecud_slot = i;
			memcpy(ecud->ecud_eisaid, eisaid, sizeof(eisaid));
			ecud->ecud_offset = offset;
			SIMPLEQ_INSERT_TAIL(&ecu_data_list, ecud, ecud_list);
		}
	}

	/*
	 * Now traverse the valid slots and read the info.
	 */

	cdata = malloc(CBUFSIZE, M_TEMP, M_ZERO|M_WAITOK);

	data = malloc(CBUFSIZE, M_TEMP, M_ZERO|M_WAITOK);

	SIMPLEQ_FOREACH(ecud, &ecu_data_list, ecud_list) {
		cfgaddr = eisa_config_addr + ecud->ecud_offset;
#ifdef EISA_DEBUG
		printf("Checking SLOT %d\n", ecud->ecud_slot);
		printf("Reading config bytes at %p to cdata[0]\n", cfgaddr);
#endif
		eisa_read_config_bytes(cfgaddr, &cdata[0], 1);
		cfgaddr += eisa_config_stride;

		for (i = 1; i < CBUFSIZE; cfgaddr += eisa_config_stride, i++) {
#ifdef EISA_DEBUG
			printf("Reading config bytes at %p to cdata[%d]\n",
			    cfgaddr, i);
#endif
			eisa_read_config_bytes(cfgaddr, &cdata[i], 1);
			if (cdata[i - 1] == 0 && cdata[i] == 0)
				break;
		}
		if (i == CBUFSIZE) {
			/* assume this compressed data invalid */
#ifdef EISA_DEBUG
			printf("SLOT %d has invalid config\n", ecud->ecud_slot);
#endif
			continue;
		}

		i++;	/* index -> length */

#ifdef EISA_DEBUG
		printf("SLOT %d compressed data length %d:",
		    ecud->ecud_slot, i);
		{
			int j;

			for (j = 0; j < i; j++) {
				if ((j % 16) == 0)
					printf("\n");
				printf("0x%02x ", cdata[j]);
			}
			printf("\n");
		}
#endif

		cdp = cdata;
		dp = data;

		/* Uncompress the slot header. */
		cdp += eisa_uncompress(cdp, dp, EISA_SLOT_HEADER_SIZE);
#ifdef EISA_DEBUG
		printf("SLOT %d uncompressed header data:",
		    ecud->ecud_slot);
		{
			int j;

			for (j = 0; j < EISA_SLOT_HEADER_SIZE; j++) {
				if ((j % 16) == 0)
					printf("\n");
				printf("0x%02x ", dp[j]);
			}
			printf("\n");
		}
#endif

		dp = &data[EISA_SLOT_INFO_OFFSET];
		ecud->ecud_slot_info = *dp++;
		ecud->ecud_ecu_major_rev = *dp++;
		ecud->ecud_ecu_minor_rev = *dp++;
		memcpy(&ecud->ecud_cksum, dp, sizeof(ecud->ecud_cksum));
		dp += sizeof(ecud->ecud_cksum);
		ecud->ecud_ndevfuncs = *dp++;
		ecud->ecud_funcinfo = *dp++;
		memcpy(&ecud->ecud_comp_id, dp, sizeof(ecud->ecud_comp_id));
		dp += sizeof(ecud->ecud_comp_id);

#ifdef EISA_DEBUG
		printf("SLOT %d: ndevfuncs %d\n", ecud->ecud_slot,
		    ecud->ecud_ndevfuncs);
#endif

		for (func = 0; func < ecud->ecud_ndevfuncs; func++) {
			dp = data;
			cdp += eisa_uncompress(cdp, dp, EISA_CONFIG_BLOCK_SIZE);
#ifdef EISA_DEBUG
			printf("SLOT %d:%d uncompressed data:",
			    ecud->ecud_slot, func);
			{
				int j;

				for (j = 0; i < EISA_CONFIG_BLOCK_SIZE; j++) {
					if ((j % 16) == 0)
						printf("\n");
					printf("0x%02x ", dp[j]);
				}
				printf("\n");
			}
#endif

			/* Skip disabled functions. */
			if (dp[EISA_FUNC_INFO_OFFSET] & ECUF_DISABLED) {
#ifdef EISA_DEBUG
				printf("SLOT %d:%d disabled\n",
				    ecud->ecud_slot, func);
#endif
				continue;
			}
#ifdef EISA_DEBUG
			else
				printf("SLOT %d:%d settings\n",
				    ecud->ecud_slot, func);
#endif

			ecuf = malloc(sizeof(*ecuf), M_DEVBUF, M_WAITOK);

			ecuf_init(ecuf);
			ecuf->ecuf_funcno = func;
			SIMPLEQ_INSERT_TAIL(&ecud->ecud_funcs, ecuf,
			    ecuf_list);

			memcpy(&ecuf->ecuf_id, dp, sizeof(ecuf->ecuf_id));
			dp += sizeof(ecuf->ecuf_id);

			memcpy(&ecuf->ecuf_slot_info, dp,
			    sizeof(ecuf->ecuf_slot_info));
			dp += sizeof(ecuf->ecuf_slot_info);

			memcpy(&ecuf->ecuf_cfg_ext, dp,
			    sizeof(ecuf->ecuf_cfg_ext));
			dp += sizeof(ecuf->ecuf_cfg_ext);

			memcpy(&ecuf->ecuf_selections, dp,
			    sizeof(ecuf->ecuf_selections));
			dp += sizeof(ecuf->ecuf_selections);

			memcpy(&ecuf->ecuf_func_info, dp,
			    sizeof(ecuf->ecuf_func_info));
			dp += sizeof(ecuf->ecuf_func_info);

			if (ecuf->ecuf_func_info & ECUF_TYPE_STRING)
				memcpy(ecuf->ecuf_type_string, dp,
				    sizeof(ecuf->ecuf_type_string));
			dp += sizeof(ecuf->ecuf_type_string);

			if (ecuf->ecuf_func_info & ECUF_MEM_ENTRY)
				eisa_parse_mem(ecuf, dp);
			dp += ECUF_MEM_ENTRY_SIZE * ECUF_MEM_ENTRY_CNT;

			if (ecuf->ecuf_func_info & ECUF_IRQ_ENTRY)
				eisa_parse_irq(ecuf, dp);
			dp += ECUF_IRQ_ENTRY_SIZE * ECUF_IRQ_ENTRY_CNT;

			if (ecuf->ecuf_func_info & ECUF_DMA_ENTRY)
				eisa_parse_dma(ecuf, dp);
			dp += ECUF_DMA_ENTRY_SIZE * ECUF_DMA_ENTRY_CNT;

			if (ecuf->ecuf_func_info & ECUF_IO_ENTRY)
				eisa_parse_io(ecuf, dp);
			dp += ECUF_IO_ENTRY_SIZE * ECUF_IO_ENTRY_CNT;

			if (ecuf->ecuf_func_info & ECUF_INIT_ENTRY)
				memcpy(ecuf->ecuf_init, dp,
				    sizeof(ecuf->ecuf_init));
			dp += sizeof(ecuf->ecuf_init);
		}
	}

	free(cdata, M_TEMP, 0);
	free(data, M_TEMP, 0);
}

/*
 * Return the number of logical slots a motherboard supports,
 * from its signature.
 */
int
eisa_compute_maxslots(const char *idstring)
{
	int nslots;

	if (strcmp(idstring, "DEC2400") == 0)		/* Jensen */
		nslots = 1 + 6;
	else if (strcmp(idstring, "DEC2A01") == 0)	/* AS 2000/2100 */
		nslots = 1 + 8;
	else if (strcmp(idstring, "DEC5000") == 0)	/* AS 1000/600A */
		nslots = 1 + 8;
	else if (strcmp(idstring, "DEC5100") == 0)	/* AS 600 */
		nslots = 1 + 4;
	else if (strcmp(idstring, "DEC5301") == 0)	/* AS 800 */
		nslots = 1 + 3;
	else if (strcmp(idstring, "DEC6000") == 0)	/* AS 8200/8400 */
		nslots = 1 + 8;
	else if (strcmp(idstring, "DEC6400") == 0)	/* AS 4x00/1200 */
		nslots = 1 + 3;
	else {
		/*
		 * Unrecognized design. Not likely to happen, since
		 * Digital ECU will not recognize it either.
		 * But just in case the EISA configuration data badly
		 * fooled us, return the largest possible value.
		 */
		nslots = 1 + 8;
	}

	return nslots;
}


code:
/*	$OpenBSD: eisa_machdep.h,v 1.8 2009/08/22 02:54:50 mk Exp $	*/
/*	$NetBSD: eisa_machdep.h,v 1.1 1996/04/12 05:39:51 cgd Exp $	*/

/*
 * Copyright (c) 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

/*
 * Types provided to machine-independent EISA code.
 */
typedef struct alpha_eisa_chipset *eisa_chipset_tag_t;
typedef int eisa_intr_handle_t;

struct alpha_eisa_chipset {
	void	*ec_v;
	int	ec_maxslots;

	void	(*ec_attach_hook)(struct device *, struct device *,
		    struct eisabus_attach_args *);
	int	(*ec_intr_map)(void *, u_int,
		    eisa_intr_handle_t *);
	const char *(*ec_intr_string)(void *, eisa_intr_handle_t);
	void	*(*ec_intr_establish)(void *, eisa_intr_handle_t,
		    int, int, int (*)(void *), void *, const char *);
	void	(*ec_intr_disestablish)(void *, void *);
};

/*
 * Functions provided to machine-independent EISA code.
 */
#define	eisa_attach_hook(p, s, a)					\
    (*(a)->eba_ec->ec_attach_hook)((p), (s), (a))
#define	eisa_maxslots(c)						\
    ((c)->ec_maxslots)
#define	eisa_intr_map(c, i, hp)						\
    (*(c)->ec_intr_map)((c)->ec_v, (i), (hp))
#define	eisa_intr_string(c, h)						\
    (*(c)->ec_intr_string)((c)->ec_v, (h))
#define	eisa_intr_establish(c, h, t, l, f, a, nm)			\
    (*(c)->ec_intr_establish)((c)->ec_v, (h), (t), (l), (f), (a), (nm))
#define	eisa_intr_disestablish(c, h)					\
    (*(c)->ec_intr_disestablish)((c)->ec_v, (h))

/*
 * Internal functions, NOT TO BE USED BY MACHINE-INDEPENDENT CODE!
 */

void	eisa_init(eisa_chipset_tag_t);


path: sys/arch/alpha/include/CVS/Entries


code: src/sys/arch/alpha/include

path: sys/arch/alpha/include/CVS/Repository


code:
/*	$OpenBSD: _float.h,v 1.1 2012/06/26 16:12:43 deraadt Exp $	*/

/*
 * Copyright (c) 1989, 1993
 *	The Regents of the University of California.  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. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
 */

#ifndef _MACHINE__FLOAT_H_
#define _MACHINE__FLOAT_H_

#define __FLT_RADIX		2		/* b */
#define __FLT_ROUNDS		__flt_rounds()
#define __FLT_EVAL_METHOD	0		/* no promotions */

#define __FLT_MANT_DIG		24		/* p */
#define __FLT_EPSILON		1.19209290E-07F	/* b**(1-p) */
#define __FLT_DIG		6		/* floor((p-1)*log10(b))+(b == 10) */
#define __FLT_MIN_EXP		-125		/* emin */
#define __FLT_MIN		1.17549435E-38F	/* b**(emin-1) */
#define __FLT_MIN_10_EXP	-37		/* ceil(log10(b**(emin-1))) */
#define __FLT_MAX_EXP		128		/* emax */
#define __FLT_MAX		3.40282347E+38F	/* (1-b**(-p))*b**emax */
#define __FLT_MAX_10_EXP	38		/* floor(log10((1-b**(-p))*b**emax)) */

#define __DBL_MANT_DIG		53
#define __DBL_EPSILON		2.2204460492503131E-16
#define __DBL_DIG		15
#define __DBL_MIN_EXP		-1021
#define __DBL_MIN		2.2250738585072014E-308
#define __DBL_MIN_10_EXP	-307
#define __DBL_MAX_EXP		1024
#define __DBL_MAX		1.7976931348623157E+308
#define __DBL_MAX_10_EXP	308

#define __LDBL_MANT_DIG		DBL_MANT_DIG
#define __LDBL_EPSILON		DBL_EPSILON
#define __LDBL_DIG		DBL_DIG
#define __LDBL_MIN_EXP		DBL_MIN_EXP
#define __LDBL_MIN		DBL_MIN
#define __LDBL_MIN_10_EXP	DBL_MIN_10_EXP
#define __LDBL_MAX_EXP		DBL_MAX_EXP
#define __LDBL_MAX		DBL_MAX
#define __LDBL_MAX_10_EXP	DBL_MAX_10_EXP

#define __DECIMAL_DIG		17

#endif /* _MACHINE__FLOAT_H_ */


code:
/*	$OpenBSD: _types.h,v 1.22 2014/03/19 05:14:12 guenther Exp $	*/

/*-
 * Copyright (c) 1990, 1993
 *	The Regents of the University of California.  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. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
 *
 *	@(#)types.h	8.3 (Berkeley) 1/5/94
 *	@(#)ansi.h	8.2 (Berkeley) 1/4/94
 */

#ifndef _MACHINE__TYPES_H_
#define _MACHINE__TYPES_H_

#if defined(_KERNEL)
typedef struct label_t {
	long val[10];
} label_t;
#endif

/*
 * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned
 * value for all data types (int, long, ...).   The result is an
 * unsigned long and must be cast to any desired pointer type.
 *
 * _ALIGNED_POINTER is a boolean macro that checks whether an address
 * is valid to fetch data elements of type t from on this architecture.
 * This does not reflect the optimal alignment, just the possibility
 * (within reasonable limits).
 */
#define	_ALIGNBYTES		7
#define	_STACKALIGNBYTES	_ALIGNBYTES
#define	_ALIGN(p)		(((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES)
#define	_ALIGNED_POINTER(p,t)	((((unsigned long)(p)) & (sizeof(t) - 1)) == 0)

/* 7.18.1.1 Exact-width integer types */
typedef	signed char		__int8_t;
typedef	unsigned char		__uint8_t;
typedef	short			__int16_t;
typedef	unsigned short		__uint16_t;
typedef	int			__int32_t;
typedef	unsigned int		__uint32_t;
/* LONGLONG */
typedef	long long		__int64_t;
/* LONGLONG */
typedef	unsigned long long	__uint64_t;

/* 7.18.1.2 Minimum-width integer types */
typedef	__int8_t		__int_least8_t;
typedef	__uint8_t		__uint_least8_t;
typedef	__int16_t		__int_least16_t;
typedef	__uint16_t		__uint_least16_t;
typedef	__int32_t		__int_least32_t;
typedef	__uint32_t		__uint_least32_t;
typedef	__int64_t		__int_least64_t;
typedef	__uint64_t		__uint_least64_t;

/* 7.18.1.3 Fastest minimum-width integer types */
typedef	__int32_t		__int_fast8_t;
typedef	__uint32_t		__uint_fast8_t;
typedef	__int32_t		__int_fast16_t;
typedef	__uint32_t		__uint_fast16_t;
typedef	__int32_t		__int_fast32_t;
typedef	__uint32_t		__uint_fast32_t;
typedef	__int64_t		__int_fast64_t;
typedef	__uint64_t		__uint_fast64_t;
#define	__INT_FAST8_MIN		INT32_MIN
#define	__INT_FAST16_MIN	INT32_MIN
#define	__INT_FAST32_MIN	INT32_MIN
#define	__INT_FAST64_MIN	INT64_MIN
#define	__INT_FAST8_MAX		INT32_MAX
#define	__INT_FAST16_MAX	INT32_MAX
#define	__INT_FAST32_MAX	INT32_MAX
#define	__INT_FAST64_MAX	INT64_MAX
#define	__UINT_FAST8_MAX	UINT32_MAX
#define	__UINT_FAST16_MAX	UINT32_MAX
#define	__UINT_FAST32_MAX	UINT32_MAX
#define	__UINT_FAST64_MAX	UINT64_MAX

/* 7.18.1.4 Integer types capable of holding object pointers */
typedef	long			__intptr_t;
typedef	unsigned long		__uintptr_t;

/* 7.18.1.5 Greatest-width integer types */
typedef	__int64_t		__intmax_t;
typedef	__uint64_t		__uintmax_t;

/* Register size */
typedef long			__register_t;

/* VM system types */
typedef unsigned long		__vaddr_t;
typedef unsigned long		__paddr_t;
typedef unsigned long		__vsize_t;
typedef unsigned long		__psize_t;

/* Standard system types */
typedef double			__double_t;
typedef float			__float_t;
typedef long			__ptrdiff_t;
typedef	unsigned long		__size_t;
typedef	long			__ssize_t;
#if defined(__GNUC__) && __GNUC__ >= 3
typedef	__builtin_va_list	__va_list;
#else
typedef struct {
	char *__base;
	int __offset;
	int __pad;
} __va_list;
#endif

/* Wide character support types */
#ifndef __cplusplus
typedef	int			__wchar_t;
#endif
typedef int			__wint_t;
typedef	int			__rune_t;
typedef	void *			__wctrans_t;
typedef	void *			__wctype_t;

#endif	/* _MACHINE__TYPES_H_ */