code:
#	$OpenBSD: GENERIC,v 1.251 2015/06/02 13:53:43 mpi Exp $g
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
#
# For further information on hardware support for this architecture, see
# the intro(4) man page.  For further information about kernel options
# for this architecture, see the options(4) man page.  For an explanation
# of each device driver in this file see the section 4 man page for the
# device.

machine		macppc powerpc
include		"../../../conf/GENERIC"
maxusers	80			# estimated number of users

option		PCIVERBOSE
option		USBVERBOSE
#option		MACOBIOVERBOSE
option		ADBVERBOSE
option		ALTIVEC
option		APERTURE	# in-kernel aperture driver for XFree86

option	WSDISPLAY_COMPAT_USL		# VT handling
option	WSDISPLAY_COMPAT_RAWKBD		# provide raw scancodes; needed for X11
option	WSDISPLAY_DEFAULTSCREENS=6	# initial number of text consoles
option	WSDISPLAY_COMPAT_PCVT		# emulate some ioctls; needed for X11

option		USER_PCICONF	# user-space PCI configuration

config		bsd	swap generic

mainbus0	at root
cpu*		at mainbus0
mem*		at mainbus0

mpcpcibr*	at mainbus0	# MPC106 PCI Bridge.
memc*		at mainbus0
openpic*	at memc?	# openpic interrupt controller
kiic*           at memc?        # Keywest I2C
pchb*		at pci?
ht*		at mainbus0
smu*		at mainbus0

#### PCI Bus devices.

pci*		at mpcpcibr?
pci*		at ht?
ppb*		at pci?		# PCI-PCI bridges
hpb*		at pci?
pci*		at ppb?
pci*		at hpb?

siop*		at pci?
fxp*		at pci?
de*		at pci?
#vme*		at pci?
vgafb0		at pci?		# PCI VGA graphics
#ep*		at pci?		# 3Com 3c59x
#ne*		at pci?		# NE2000-compatible Ethernet
#adv*		at pci?		# AdvanSys 1200[A,B], 9xx[U,UA] SCSI
ahc*		at pci?		# Adaptec 294x, aic78x0 SCSI
#bha*		at pci?		# BusLogic 9xx SCSI
#ami*		at pci?
pcscp*		at pci?		# AMD Am53c974 PCscsi-PCI SCSI
qlw*		at pci?		# QLogic ISP SCSI
#qla*		at pci?		# QLogic ISP 2[123]xx FibreChannel
qle*		at pci?		# QLogic ISP 2[45]xx FibreChannel
mpi*		at pci?		# LSI Logic MPT-Fusion Message Passing Interface
arc*		at pci?		# Areca RAID Controllers
pciide*		at pci?
kauaiata*	at pci?		# Apple ATA 100
wdc*		at kauaiata?
macobio0	at pci?
gem*		at pci?		# GMAC ethernet
hme*		at pci?		# HME ethernet
vge*		at pci?		# VIA VT612x
dc*		at pci?		# DEC Tulip 21143 clones
xl*		at pci?		# 3C9xx ethernet
rl*		at pci?		# Realtek 81[23]9 ethernet
em*		at pci?		# Intel Pro/1000 ethernet
#ixgb*		at pci?		# Intel Pro/10Gb ethernet
epic*		at pci?		# SMC EPIC/100 ethernet
bge*		at pci?		# Broadcom BCM570x (aka Tigon3)
ti*		at pci?		# Alteon Tigon 1Gb ethernet
re*		at pci?		# Realtek 8169/8169S/8110S
stge*		at pci?		# Sundance TC9021 GigE
skc*		at pci?		# SysKonnect GEnesis 984x
sk*		at skc?		#  each port of above
mskc*		at pci?		# Marvell Yukon-2
msk*		at mskc?	#  each port of above
an*		at pci?		# Cisco/Aironet
ath*		at pci?		# Atheros AR5k (802.11a/b/g)
atw*		at pci?		# ADMtek ADM8211 (802.11)
bwi*		at pci?		# Broadcom AirForce (802.11b/g)
wi*		at pci?		# WaveLAN IEEE 802.11DS
ral*		at pci?		# Ralink RT2500/RT2501/RT2600
rtw*		at pci?		# Realtek 8180
vr*		at pci?		# VIA Rhine ethernet
pcn*		at pci?		# AMD PCnet-PCI Ethernet
xge*		at pci?		# Neterion Xframe-I/II 10Gb ethernet
mbg*		at pci?		# Meinberg Funkuhren radio clocks
malo*		at pci?		# Marvell Libertas
acx*		at pci?		# TI ACX100/ACX111 (802.11b/g)

amphy*		at mii?		# AMD 79C873 PHYs
dcphy*		at mii?		# Digital Clone PHYs
exphy*		at mii?		# 3Com internal PHYs
inphy*		at mii?		# Intel 82555 PHYs
iophy*		at mii?		# Intel 82553 PHYs
icsphy*		at mii?		# ICS1890 PHYs
lxtphy*		at mii?		# Level One LXT-970 PHYs
nsphy*		at mii?		# NS83840 PHYs
#nsphyter*	at mii?		# NS83843 PHYs
mtdphy*		at mii?		# Myson MTD972 PHYs
acphy*		at mii?		# Altima AC101 PHYs
qsphy*		at mii?		# Quality Semi QS6612 PHYs
luphy*		at mii?		# Lucent LU6612 PHY
sqphy*		at mii?		# Seeq 8022[013] PHYs
rlphy*		at mii?		# Realtek 8139 internal PHYs
#tlphy*		at mii?		# ThunderLAN PHYs
tqphy*		at mii?		# TDK Semiconductor PHYs
brgphy*		at mii?		# Broadcom 10/100/1000 PHYs
bmtphy*		at mii?		# Broadcom 10/100 PHYs
eephy*		at mii?		# Marvell 88E1000 Gigabit PHYs
xmphy*		at mii?		# XaQti XMAC-II PHYs
urlphy*		at mii?		# Realtek RTL8150L internal PHY
rgephy*		at mii?		# Realtek 8169S/8110S PHY
rlphy*		at mii?		# Realtek 8139 internal PHYs
ciphy*		at mii?		# Cicada CS8201 10/100/1000 copper PHY
ipgphy*		at mii?		# IC Plus IP1000A PHYs
ukphy*		at mii?		# generic unknown PHYs

# crypto
hifn*		at pci?		# Hifn7751/7811/7951
ubsec*		at pci?		# Broadcom 58xx
safe*		at pci?		# SafeNet SafeXcel 1141/1741
pwdog0		at pci?		# Quancom PWDOG1 watchdog timer

macintr0	at macobio?	# old interrupt controller
openpic*	at macobio?	# openpic interrupt controller
bm*		at macobio?	# BMAC ethernet
xlights*	at macobio?	# Xserve front panel LEDs
mc*		at macobio?	# MACE ethernet
#esp*		at macobio? flags 0x0000ffff # 53c9x SCSI
mesh*		at macobio? flags 0xffff # MESH SCSI
#nvram*		at macobio?	# nvram
adb*		at macobio?	# Apple Desktop Bus
apm0		at adb?		# APM emulation
piic0		at adb?		# PMU I2C
wi*		at macobio?	# airport
macgpio*	at macobio?	# GPIO, PMU interrupt router.
macgpio*	at macgpio?	# GPIO, PMU interrupt router.
sysbutton*	at macgpio?	# Xserve system id button.
pgs*		at macgpio?	# Programmer Switch.
dfs*		at macgpio?	# Dynamic Frequency Switching.
akbd*		at adb?		# ADB keyboard
wskbd*		at akbd? mux 1
ams*		at adb?		# ADB mouse
wsmouse*	at ams?	mux 0
abtn*		at adb?		# ADB button?
zsc*		at macobio?
zstty*		at zsc?

awacs*		at macobio?	# Apple audio device
kiic*		at macobio?	# Keywest I2C
snapper*	at macobio?	# Snapper audio device
tumbler*	at macobio?	# Tumbler audio device
onyx*		at macobio?	# Onyx audio device
aoa*		at macobio?	# Aoa audio device
daca*		at macobio?	# Daca audio device

bktr0		at pci?		# Bt8[47][89] tv/fmradio/video
radio*		at bktr?

# PCI audio devices
cmpci*		at pci?		# C-Media CMI8338/8738
eap*		at pci?		# Ensoniq AudioPCI S5016
emu*		at pci?		# SB Live!
eso*		at pci?		# ESS Solo-1 PCI AudioDrive

puc*		at pci?		# PCI "universal" comm device
#puc*		at cardbus?
com*		at puc?

mediabay*	at macobio?
wdc*		at mediabay?
wdc*		at macobio?
wd*		at wdc? flags 0x0000
wd*		at pciide? flags 0x0000
atapiscsi*	at wdc? flags 0x0000
atapiscsi*	at pciide? flags 0x0000

# USB Controllers
ohci*	at pci?			# Open Host Controller
ohci*	at cardbus?		# Open Host Controller
uhci*	at pci?			# Universal Host Controller
ehci*	at pci?			# Enhanced Host Controller
uhci*	at cardbus?		# Universal Host Controller
ehci*	at cardbus?		# Enhanced Host Controller

# USB bus support
usb*	at ohci?
usb*	at uhci?
usb*	at ehci?

# USB devices
uhub*	at usb?			# USB Hubs
uhub*	at uhub?		# USB Hubs
ualea*	at uhub?		# Araneus Alea II TRNG
umodem*	at uhub?		# USB Modems/Serial
ucom*	at umodem?
uvisor*	at uhub?		# Handspring Visor
ucom*	at uvisor?
uvscom*	at uhub?		# SUNTAC Slipper U VS-10U serial
ucom*	at uvscom?
ubsa*	at uhub?		# Belkin serial adapter
ucom*	at ubsa?
uftdi*	at uhub?		# FTDI FT8U100AX serial adapter
ucom*	at uftdi?
uplcom* at uhub?		# I/O DATA USB-RSAQ2 serial adapter
ucom*	at uplcom?
umct*	at uhub?		# MCT USB-RS232 serial adapter
ucom*	at umct?
uslcom*	at uhub?		# Silicon Laboratories CP210x serial
ucom*	at uslcom?
uark*	at uhub?		# Arkmicro ARK3116 serial
ucom*	at uark?
moscom*	at uhub?		# MosChip MCS7703 serial
ucom*	at moscom?
umcs*	at uhub?		# MosChip MCS78x0 serial
ucom*	at umcs?
uipaq*	at uhub?		# iPAQ serial adapter
ucom*	at uipaq?
umsm*	at uhub?		# Qualcomm MSM EVDO
ucom*	at umsm?
uchcom*	at uhub?		# WinChipHead CH341/340 serial
ucom*	at uchcom?
uaudio* at uhub?		# USB Audio
audio*	at uaudio?
umidi*	at uhub?		# USB MIDI
midi*	at umidi?
ulpt*	at uhub?		# USB Printers
umass*	at uhub?		# USB Mass Storage devices
uhidev*	at uhub?		# Human Interface Devices
utpms*	at uhidev?		# Apple touchpad mouse
wsmouse* at utpms? mux 0
ums*	at uhidev?		# USB mouse
wsmouse*	at ums? mux 0
uts*	at uhub?		# USB touchscreen
wsmouse*	at uts? mux 0
ukbd*	at uhidev?		# USB keyboard
wskbd*	at ukbd? mux 1
ucycom*	at uhidev?		# Cypress serial
ucom*	at ucycom?
uslhcom* at uhidev?		# Silicon Labs CP2110 USB HID UART
ucom*	at uslhcom?
uhid*	at uhidev?		# USB generic HID support
upd*	at uhidev?		# USB Power Devices sensors
aue*	at uhub?		# ADMtek AN986 Pegasus Ethernet
atu*	at uhub?		# Atmel AT76c50x based 802.11b
axe*	at uhub?		# ASIX Electronics AX88172 USB Ethernet
axen*	at uhub?		# ASIX Electronics AX88179 USB Ethernet
cue*	at uhub?		# CATC USB-EL1201A based Ethernet
kue*	at uhub?		# Kawasaki KL5KUSB101B based Ethernet
smsc*	at uhub?		# SMSC LAN95xx Ethernet
cdce*	at uhub?		# CDC Ethernet
urndis*	at uhub?		# Remote NDIS Ethernet
upl*	at uhub?		# Prolific PL2301/PL2302 host-to-host `network'
ugl*	at uhub?		# Genesys Logic GL620A-USB host-to-host `network'
udav*	at uhub?		# Davicom DM9601 based Ethernet
mos*	at uhub?		# MOSCHIP MCS7730/7830 10/100 Ethernet
url*	at uhub?		# Realtek RTL8150L based adapters
wi*	at uhub?		# WaveLAN IEEE 802.11DS
udsbr*	at uhub?		# D-Link DSB-R100 radio
radio*	at udsbr?		# USB radio
uberry*	at uhub?		# Research In Motion BlackBerry
ugen*	at uhub?		# USB Generic driver
uath*	at uhub?		# Atheros AR5005UG/AR5005UX
ural*	at uhub?		# Ralink RT2500USB
rum*	at uhub?		# Ralink RT2501USB/RT2601USB
run*	at uhub?		# Ralink RT2700U/RT2800U/RT3000U
rsu*	at uhub?		# Realtek RTL8188SU/RTL8191SU/RTL8192SU
urtwn*	at uhub?		# Realtek RTL8188CU/RTL8192CU
otus*	at uhub?		# Atheros AR9001U
athn*	at uhub?		# Atheros AR9002U
zyd*	at uhub?		# Zydas ZD1211
upgt*	at uhub?		# Conexant/Intersil PrismGT SoftMAC USB
urtw*	at uhub?		# Realtek 8187
udcf*	at uhub?		# Gude Expert mouseCLOCK
umbg*	at uhub?		# Meinberg Funkuhren USB5131
uthum*	at uhidev?		# TEMPerHUM sensor
ugold*	at uhidev?		# gold TEMPer sensor
utrh*	at uhidev?		# USBRH sensor
utwitch* at uhidev?		# YUREX BBU sensor
uow*	at uhub?		# Maxim/Dallas DS2490 1-Wire adapter
onewire* at uow?

# USB Video
uvideo* at uhub?
video*  at uvideo?

udl*		at uhub?
wsdisplay*	at udl?

# I2C bus support
iic*		at kiic?
iic*		at piic?
iic*		at smu?

# I2C devices
lmtemp*		at iic?
lmenv*		at iic?
maxtmp*		at iic?
adc*		at iic?
tsl*		at iic?
admtmp*		at iic?
#pcagpio*	at iic?
#gpio*		at pcagpio?
maxds*		at iic?
fcu*		at iic?
adt*		at iic?
asms*		at iic?
spdmem*		at mem?

# CardBus bus support
cardbus*	at cardslot?
pcmcia*		at cardslot?
cbb*		at pci?
cardslot*	at cbb?
ep*		at pcmcia?	# PCMCIA based 3C5xx ethernet
an*		at pcmcia?	# Cisco/Aironet
ath*		at cardbus?	# Atheros AR5k (802.11a/b/g)
wi*		at pcmcia?	# WaveLAN IEEE 802.11DS
malo*		at pcmcia?	# Marvell 88W8385
dc*		at cardbus?	# 21143, "tulip" clone ethernet
fxp*		at cardbus?	# Intel PRO/100 ethernet
xl*		at cardbus?	# 3C575/3C656 ethernet
rl*		at cardbus?	# Realtek 81[23]9 ethernet
re*		at cardbus?	# Realtek 8169/8169S/8110S
rtw*		at cardbus?	# Realtek 8180
wdc*		at pcmcia?
com*		at pcmcia?
com*		at cardbus?
malo*		at cardbus?	# Marvell Libertas
acx*		at cardbus?	# TI ACX100/ACX111 (802.11b/g)
bwi*		at cardbus?	# Broadcom AirForce (802.11b/g)
ral*		at cardbus?	# Ralink RT2500/RT2501/RT2600

wsdisplay*	at vgafb?

#appleagp*	at pchb?
#agp*		at appleagp?	# AGP bridges

radeondrm*	at pci? 	# ATI Radeon DRM driver
drm*		at radeondrm?
wsdisplay*	at radeondrm?

# Audio support
audio*		at awacs?
audio*		at snapper?
audio*		at tumbler?
audio*		at onyx?
audio*		at cmpci?
audio*		at eap?
audio*		at emu?
audio*		at eso?
audio*		at uaudio?
audio*		at aoa?
audio*		at daca?

# MIDI support
midi*		at eap?

scsibus*	at scsi?
sd*		at scsibus?
st*		at scsibus?
cd*		at scsibus?
ch*		at scsibus?
safte*		at scsibus?
ses*		at scsibus?
uk*		at scsibus?

mpath0	at root
emc*	at scsibus?
hds*	at scsibus?
rdac*	at scsibus?
sym*	at scsibus?

# 1-Wire devices
option ONEWIREVERBOSE
owid*	at onewire?		# ID
owsbm*	at onewire?		# Smart Battery Monitor
owtemp* at onewire?		# Temperature
owctr*	at onewire?			# Counter device

pseudo-device	hotplug	1	# devices hot plugging
pseudo-device	wsmux	2	# mouse & keyboard multiplexor

path: sys/arch/macppc/conf/GENERIC


code:
#	$OpenBSD: GENERIC.MP,v 1.1 2007/05/03 21:21:33 kettenis Exp $

include "arch/macppc/conf/GENERIC"

option	MULTIPROCESSOR
#option	MP_LOCKDEBUG

cpu*	at mainbus?

license: unknown


code:
#	$OpenBSD: Makefile.macppc,v 1.71 2015/01/13 01:12:49 deraadt Exp $

# For instructions on building kernels consult the config(8) and options(4)
# manual pages.
#
# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE
#	IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
# DEBUG is set to -g by config if debugging is requested (config -g).
# PROF is set to -pg by config if profiling is requested (config -p).

.include <bsd.own.mk>

SIZE?=	size
STRIP?=	strip

# source tree is located via $S relative to the compilation directory
.ifndef S
S!=	cd ../../../..; pwd
.endif

_machdir?=	$S/arch/${_mach}
_archdir?=	$S/arch/${_arch}

INCLUDES=	-nostdinc -I$S -I. -I$S/arch
CPPFLAGS=	${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -D__${_mach}__ -MD -MP
CWARNFLAGS=	-Werror -Wall -Wimplicit-function-declaration \
		-Wno-main -Wno-uninitialized \
		-Wframe-larger-than=2047

CMACHFLAGS=	-msoft-float -Wa,-many
CMACHFLAGS+=	-fno-builtin-printf -fno-builtin-snprintf \
		-fno-builtin-vsnprintf -fno-builtin-log \
		-fno-builtin-log2 -fno-builtin-malloc ${NOPIE_FLAGS}
.if ${IDENT:M-DNO_PROPOLICE}
CMACHFLAGS+=	-fno-stack-protector
.endif

COPTS?=		-O2
CFLAGS=		${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
AFLAGS=		-D_LOCORE ${CMACHFLAGS}
LINKFLAGS=	-N -Ttext 100114 -e start --warn-common -nopie

.if ${IDENT:M-DDDB_STRUCT}
DB_STRUCTINFO=	db_structinfo.h
.else
DB_STRUCTINFO=
.endif

HOSTCC?=	${CC}
HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//}
HOSTED_CFLAGS=	${CFLAGS}
HOSTED_C=	${HOSTCC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $<

NORMAL_C_NOP=	${CC} ${CFLAGS} ${CPPFLAGS} -c $<
NORMAL_C=	${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
NORMAL_S=	${CC} ${AFLAGS} ${CPPFLAGS} -c $<

%OBJS

%CFILES

%SFILES

# load lines for config "xxx" will be emitted as:
# xxx: ${SYSTEM_DEP} swapxxx.o
#	${SYSTEM_LD_HEAD}
#	${SYSTEM_LD} swapxxx.o
#	${SYSTEM_LD_TAIL}
SYSTEM_HEAD=	locore.o param.o ioconf.o
SYSTEM_OBJ=	${SYSTEM_HEAD} ${OBJS}
SYSTEM_DEP=	Makefile ${SYSTEM_OBJ}
SYSTEM_LD_HEAD=	@rm -f $@
SYSTEM_LD=	@echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_HEAD} vers.o $${OBJS}'; \
		${LD} ${LINKFLAGS} -o $@ ${SYSTEM_HEAD} vers.o ${OBJS}
SYSTEM_LD_TAIL=	@${SIZE} $@; chmod 755 $@

DEBUG?=
.if ${DEBUG} == "-g"
LINKFLAGS+=	-X
STRIPFLAGS=	-g -x
SYSTEM_LD_TAIL+=; \
		echo mv $@ $@.gdb; rm -f $@.gdb; mv $@ $@.gdb; \
		echo ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb; \
		${STRIP} ${STRIPFLAGS} -o $@ $@.gdb
.else
LINKFLAGS+=	-S -x
.endif

%LOAD

# cc's -MD puts the source and output paths in the dependency file;
# since those are temp files here we need to fix it up.  It also
# puts the file in /tmp, so we use -MF to put it in the current
# directory as assym.P and then generate assym.d from it with a
# good target name
assym.h: $S/kern/genassym.sh Makefile \
	 ${_archdir}/${_arch}/genassym.cf ${_machdir}/${_mach}/genassym.cf
	cat ${_archdir}/${_arch}/genassym.cf ${_machdir}/${_mach}/genassym.cf | \
	    sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} -MF assym.P > assym.h.tmp
	sed '1s/.*/assym.h: \\/' assym.P > assym.d
	sort -u assym.h.tmp > assym.h

param.c: $S/conf/param.c
	rm -f param.c
	cp $S/conf/param.c .

param.o: param.c Makefile
	${NORMAL_C}

mcount.o: $S/lib/libkern/mcount.c Makefile
	${NORMAL_C_NOP}

ioconf.o: ioconf.c
	${NORMAL_C}

vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
	sh $S/conf/newvers.sh
	${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c

clean::
	rm -f eddep *bsd *bsd.gdb tags *.[dio] [a-z]*.s \
	    [Ee]rrs linterrs assym.h ${DB_STRUCTINFO}

lint:
	@lint -hbxncez -Dvolatile= ${CPPFLAGS} -UKGDB \
	    ${CFILES} ioconf.c param.c | \
	    grep -v 'static function .* unused'

depend:
	@touch $@

tags:
	@echo "see $S/kern/Makefile for tags"

db_structinfo.h: $S/ddb/db_structinfo.c $S/ddb/parse_structinfo.pl
	${CC} ${CFLAGS} ${CPPFLAGS} -MT $@ -gstabs -c $S/ddb/db_structinfo.c
	objdump -g db_structinfo.o | perl $S/ddb/parse_structinfo.pl > $@
	rm -f db_structinfo.o

locore.o: ${_machdir}/${_mach}/locore.S assym.h
mutex.o: assym.h

# The install target can be redefined by putting a
# install-kernel-${MACHINE_NAME} target into /etc/mk.conf
MACHINE_NAME!=  uname -n
install: install-kernel-${MACHINE_NAME}
.if !target(install-kernel-${MACHINE_NAME}})
install-kernel-${MACHINE_NAME}:
	cmp -s bsd /bsd || ln -f /bsd /obsd
	cp bsd /nbsd
	mv /nbsd /bsd
.endif

# pull in the dependency information
.if !empty(DB_STRUCTINFO) && !exists(${DB_STRUCTINFO})
 ${SYSTEM_OBJ}: ${DB_STRUCTINFO}
.endif
.ifnmake clean
. for o in ${SYSTEM_OBJ} assym.h ${DB_STRUCTINFO}
.  if exists(${o:R}.d)
.   include "${o:R}.d"
.  elif exists($o)
    .PHONY: $o
.  endif
. endfor
.endif

%RULES


code:
#	$OpenBSD: RAMDISK,v 1.112 2015/07/17 22:52:28 tedu Exp $

machine		macppc powerpc
maxusers	4

option		TIMEZONE=0
option		DST=0
option		SMALL_KERNEL
option		NO_PROPOLICE
option		BOOT_CONFIG

option		MINIROOTSIZE=8192
option		RAMDISK_HOOKS

option		PCIVERBOSE

option		FFS
option		FFS2
option		NFSCLIENT
option		CD9660
option		UDF
option		MSDOSFS
option		INET6
option		CRYPTO

config		bsd root on rd0a swap on rd0b

mainbus0	at root
softraid0	at root
cpu0		at mainbus0

mpcpcibr*	at mainbus0		# MPC106 PCI Bridge.
memc*		at mainbus0
openpic*	at memc?		# openpic interrupt controller
kiic*		at memc?		# Keywest I2C
pchb*		at pci?			# host bridge identifiers
ht*		at mainbus0
smu*		at mainbus0

pci*		at mpcpcibr?
pci*		at ht?
ppb*		at pci?			# PCI-PCI bridges
hpb*		at pci?
pci*		at ppb?
pci*		at hpb?

macobio0	at pci?
macintr0	at macobio?		# old interrupt controller
openpic*	at macobio?		# openpic interrupt controller

siop*		at pci?
fxp*		at pci?
de*		at pci?
vgafb0		at pci?			# PCI VGA graphics
ahc*		at pci?			# Adaptec 294x, aic78x0 SCSI
pcscp*		at pci?			# AMD Am53c974 PCscsi-PCI SCSI
qlw*		at pci?			# QLogic ISP SCSI
qla*		at pci?			# QLogic ISP 2[123]xx FibreChannel
qle*		at pci?			# QLogic ISP 2[45]xx FibreChannel
mpi*		at pci?			# LSI Logic MPT-Fusion Message Passing Interface
arc*		at pci?			# Areca RAID Controllers
pciide*		at pci?
kauaiata*	at pci?			# Apple ATA 100
wdc*		at kauaiata?

iic*		at kiic?
fcu*		at iic?

gem*		at pci?			# GMAC ethernet
hme*		at pci?			# HME ethernet
vge*		at pci?			# VIA VT612x
dc*		at pci?			# DEC Tulip 21143 clones
xl*		at pci?			# 3C9xx ethernet
em*		at pci?			# Intel Pro/1000 ethernet
epic*		at pci?			# SMC EPIC/100 ethernet
bge*		at pci?			# Broadcom BCM570x (aka Tigon3)
ti*		at pci?			# Alteon Tigon 1Gb ethernet
re*		at pci?			# Realtek 8169/8169S/8110S
rl*		at pci?			# Realtek 81[23]9 ethernet
stge*		at pci?			# Sundance TC9021 GigE
skc*		at pci?			# SysKonnect GEnesis 984x
sk*		at skc?			#  each port of above
mskc*		at pci?			# Marvell Yukon-2
msk*		at mskc?		#  each port of above
an*		at pci?			# Cisco/Aironet 802.11DS
ath*		at pci?			# Atheros AR5k (802.11a/b/g)
wi*		at pci?			# WaveLAN IEEE 802.11DS
vr*		at pci?			# VIA Rhine ethernet
pcn*		at pci?			# AMD PCnet-PCI Ethernet
xge*		at pci?			# Neterion Xframe-I/II 10Gb ethernet
ral*		at pci?			# Ralink RT2500/RT2501/RT2600

amphy*		at mii?			# AMD 79C873 PHYs
dcphy*		at mii?			# Digital Clone PHYs
acphy*		at mii?			# Altima AC101 PHYs
exphy*		at mii?			# 3Com internal PHYs
inphy*		at mii?			# Intel 82555 PHYs
iophy*		at mii?			# Intel 82553 PHYs
icsphy*		at mii?			# Integrated Circuit Systems ICS1890
lxtphy*		at mii?			# Level One LXT-970 PHYs
nsphy*		at mii?			# NS83840 PHYs
mtdphy*		at mii?			# Myson MTD972 PHYs
qsphy*		at mii?			# Quality Semiconductor QS6612 PHYs
luphy*		at mii?			# Lucent LU6612 PHY
sqphy*		at mii?			# Seeq 80220/80221/80223 PHYs
rlphy*		at mii?			# Realtek 8139 internal PHYs
tqphy*		at mii?			# TDK Semiconductor PHYs
brgphy*		at mii?			# Broadcom 10/100/1000 PHYs
bmtphy*		at mii?			# Broadcom 10/100 PHYs
eephy*		at mii?			# Marvell 88E1000 Gigabit PHYs
xmphy*		at mii?			# XaQti XMAC-II PHYs
urlphy*		at mii?			# Realtek RTL8150L internal PHY
rgephy*		at mii?			# Realtek 8169S/8110S PHY
rlphy*		at mii?			# Realtek 8139 internal PHYs
ciphy*		at mii?			# Cicada CS8201 10/100/1000 copper PHY
ipgphy*		at mii?			# IC Plus IP1000A PHYs
ukphy*		at mii?			# generic unknown PHYs

bm*		at macobio?		# bmac ethernet
mc*		at macobio?		# MACE ethernet
mesh*		at macobio? flags 0xffff# MESH SCSI
adb*		at macobio?		# Apple Desktop Bus
wi*		at macobio?		# Apple Airport 802.11DS
macgpio*	at macobio?		# GPIO, PMU interrupt router.
macgpio*	at macgpio?		# GPIO, PMU interrupt router.
akbd*		at adb?			# ADB keyboard
wskbd*		at akbd? mux 1
zsc*		at macobio?
zstty*		at zsc?

mediabay*	at macobio?
wdc*		at mediabay?
wdc*		at macobio?
wd*		at wdc? flags 0x0000
wd*		at pciide?
atapiscsi*	at wdc? flags 0x0000
atapiscsi*	at pciide? flags 0x0000

ohci*		at pci?
ohci*		at cardbus?
uhci*		at pci?
ehci*		at pci?
ehci*		at cardbus?

usb*		at ohci?
usb*		at uhci?
usb*		at ehci?
uhub*		at usb?
uhub*		at uhub?

uhidev*		at uhub?
uhid*		at uhidev?		# USB Generic HID devices
ukbd*		at uhidev?		# USB HID Keyboard devices
aue*		at uhub?		# ADMtek AN986 Pegasus Ethernet
axe*		at uhub?		# ASIX Electronics AX88172 USB Ethernet
axen*		at uhub?		# ASIX Electronics AX88179 USB Ethernet
cue*		at uhub?		# CATC USB-EL1201A based Ethernet
kue*		at uhub?		# Kawasaki KL5KUSB101B based Ethernet
smsc*		at uhub?		# SMSC LAN95xx Ethernet
cdce*		at uhub?		# CDC Ethernet
upl*		at uhub?		# Prolific PL2301/PL2302 host-to-host
ugl*		at uhub?		# Genesys Logic GL620USB-A host-to-host
udav*		at uhub?		# Davicom DM9601 based Ethernet
mos*		at uhub?		# MOSCHIP MCS7730/7830 10/100 Ethernet
ural*		at uhub?		# Ralink RT2500
rum*		at uhub?		# Ralink RT2501USB/RT2601USB
urtwn*		at uhub?		# Realtek RTL8188CU/RTL8192CU
zyd*		at uhub?		# Zydas ZD1211
url*		at uhub?		# Realtek RTL8150L based adapters
wi*		at uhub?		# WaveLAN IEEE 802.11DS
umass*		at uhub?

cardbus*	at cardslot?
pcmcia*		at cardslot?
cbb*		at pci?
cardslot*	at cbb?
ath*		at cardbus?		# Atheros AR5k (802.11a/b/g)
wi*		at pcmcia?		# WaveLAN IEEE 802.11DS
dc*		at cardbus?		# 21143, "tulip" clone ethernet
fxp*		at cardbus?		# Intel PRO/100 ethernet
xl*		at cardbus?		# 3C575/3C656 ethernet
rl*		at cardbus?		# Realtek 81[23]9 ethernet
re*		at cardbus?		# Realtek 8169/8169S/8110S
wdc*		at pcmcia?
ral*		at cardbus?		# Ralink RT2500/RT2501/RT2600

wsdisplay*	at vgafb?
wskbd*		at ukbd? mux 1

scsibus*	at scsi?
sd*		at scsibus?
st*		at scsibus?
cd*		at scsibus?

pseudo-device	loop 1
pseudo-device	bpfilter 1
pseudo-device	vlan
pseudo-device	rd 1
pseudo-device	wsmux 2
pseudo-device	bio 1

path: sys/arch/macppc/conf/RAMDISK


code:
#	$OpenBSD: files.macppc,v 1.83 2015/06/26 11:15:32 dlg Exp $

#
# macppc-specific configuration info
#
maxpartitions 16

maxusers 2 8 128

file	arch/macppc/macppc/autoconf.c
file	arch/macppc/macppc/clock.c
file	arch/macppc/macppc/conf.c
file	arch/macppc/macppc/disksubr.c			disk
file	arch/macppc/macppc/machdep.c
file	arch/macppc/macppc/wscons_machdep.c
file	arch/macppc/macppc/mem.c
file	arch/macppc/macppc/ofw_machdep.c
file	arch/macppc/macppc/openfirm.c
file	arch/macppc/macppc/openprom.c
file	dev/cninit.c
file	arch/macppc/macppc/ofwreal.S
file	arch/macppc/macppc/db_interface.c		ddb

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

#
# MAC generic
#
file	arch/macppc/dev/dbdma.c

#
# Openfirmware support
#

define	mainbus {}
device	mainbus
attach	mainbus at root
file	arch/macppc/macppc/mainbus.c			mainbus

device	cpu
attach	cpu at mainbus
file	arch/macppc/macppc/cpu.c
file	arch/macppc/macppc/opendev.c

device	memc {}
attach	memc at mainbus
file	arch/macppc/dev/uni_n.c				memc

major	{rd = 17}
major	{wd = 0}
major	{sd = 2}
major	{cd = 3}

include "scsi/files.scsi"

include "dev/pci/files.pci"
file	arch/macppc/pci/pciide_machdep.c		pciide

device	mpcpcibr {} : pcibus
attach	mpcpcibr at mainbus
file	arch/macppc/pci/mpcpcibus.c			mpcpcibr

device  ht {} : pcibus
attach	ht at mainbus
file	arch/macppc/pci/ht.c				ht

file	arch/macppc/pci/pci_machdep.c			mpcpcibr | ht

device	smu: i2cbus
attach	smu at mainbus
file	arch/macppc/dev/smu.c				smu

#
# "workstation console" routines
#

include "dev/wscons/files.wscons"

#
# mac peripheral pieces.
#

#file	arch/macppc/pci/bandit.c			pci

# HT bridge
device  hpb {} : pcibus
attach	hpb at pci
file	arch/macppc/pci/hpb.c				hpb needs-flag

# PCI-Host bridge chipsets
device  pchb: agpbus
attach	pchb at pci
file	arch/macppc/pci/pchb.c				pchb

# AGP bridge support. attach at pchb
file	arch/macppc/pci/agp_machdep.c			agp

#
# Machine-independent ATAPI drivers
#

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

# MAC periph

device	macobio {}
attach	macobio at pci
file	arch/macppc/pci/macobio.c			macobio

# kauai ATA glue
device	kauaiata {}
attach	kauaiata at pci
file	arch/macppc/pci/kauaiata.c			kauaiata

#device	esp: scsi, ncr53c9x
#attach	esp at macobio
#file	arch/macppc/dev/esp.c				esp

device	mesh: scsi
attach	mesh at macobio
file	arch/macppc/dev/mesh.c				mesh

device	mc: ifnet, ether
attach	mc at macobio
file	arch/macppc/dev/if_mc.c				mc

device	bm: ether, ifnet, ifmedia, mii, mii_bitbang
attach	bm at macobio
file	arch/macppc/dev/if_bm.c				bm

device	macintr {}
attach	macintr at macobio
file	arch/macppc/dev/macintr.c			macintr

device	openpic {}
attach	openpic at macobio, memc
file	arch/macppc/dev/openpic.c			openpic

device	zsc {[channel = -1]}
attach	zsc at macobio
file	arch/macppc/dev/zs.c				zsc needs-flag
file	dev/ic/z8530sc.c				zsc

device	zstty: tty
attach	zstty at zsc
file	dev/ic/z8530tty.c				zstty needs-flag

device	adb {}
attach	adb at macobio
file	arch/macppc/dev/adb.c				adb needs-flag
file	arch/macppc/dev/pm_direct.c			adb

include	"dev/adb/files.adb"
file	arch/macppc/dev/akbd_machdep.c			akbd

device	apm
attach	apm at adb
file	arch/macppc/dev/apm.c				apm needs-count

device	abtn
attach	abtn at adb
file	arch/macppc/dev/abtn.c				abtn

device	awacs: audio
attach	awacs at macobio
file	arch/macppc/dev/awacs.c				awacs

# Mediabay
device	mediabay {}
attach	mediabay at macobio
file	arch/macppc/dev/mediabay.c			mediabay

# Keywest I2C
device	kiic: i2cbus
attach	kiic at macobio
attach	kiic at memc	with kiic_memc
file	arch/macppc/dev/kiic.c				kiic

# PMU I2C
device	piic: i2cbus
attach	piic at adb
file	arch/macppc/dev/piic.c				piic

# I2S
define	i2s
file	arch/macppc/dev/i2s.c				i2s

# blinkenlights
device	xlights
attach	xlights at macobio
file	arch/macppc/dev/xlights.c			xlights

# snapper audio
device	snapper: audio, i2s
attach	snapper at macobio
file	arch/macppc/dev/snapper.c			snapper

# tumbler audio
device	tumbler: audio, i2s
attach	tumbler at macobio
file	arch/macppc/dev/tumbler.c			tumbler

# onyx audio
device	onyx: audio, i2s
attach	onyx at macobio
file	arch/macppc/dev/onyx.c				onyx

# aoa audio
device	aoa: audio, i2s
attach	aoa at macobio
file	arch/macppc/dev/aoa.c				aoa

# daca audio
device	daca: audio, i2s
attach	daca at macobio
file	arch/macppc/dev/daca.c				daca

#device	nvram
#attach	nvram at macobio
#file	arch/macppc/dev/nvram.c				nvram needs-flag

device	macgpio {}
attach	macgpio at macobio with macgpio
attach	macgpio at macgpio with macgpio_gpio
file	arch/macppc/dev/macgpio.c			macgpio

device	sysbutton {}
attach	sysbutton at macgpio
file	arch/macppc/dev/sysbutton.c

device	pgs {}
attach	pgs at macgpio
file	arch/macppc/dev/pgs.c

device	dfs {}
attach	dfs at macgpio
file	arch/macppc/dev/dfs.c

attach	wdc at mediabay, macobio, kauaiata with wdc_obio
file	arch/macppc/dev/wdc_obio.c			wdc_obio

attach	wi at macobio with wi_obio
file	arch/macppc/dev/if_wi_obio.c			wi_obio

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

# VGA framebuffer
device	vgafb: wsemuldisplaydev, rasops8, rasops16, rasops32
attach	vgafb at pci
file	arch/macppc/pci/vgafb.c				vgafb needs-flag

#
# CARDBUS
#
include	"dev/cardbus/files.cardbus"
file	arch/macppc/macppc/rbus_machdep.c		cardbus

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

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

#
# Machine-independent I2C drivers
#
include "dev/i2c/files.i2c"
file	arch/macppc/dev/maci2c.c			i2cbus

device	mem: i2c
attach	mem at mainbus

#
# Machine-independent GPIO drivers
#
include "dev/gpio/files.gpio"

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

# Sun HME Ethernet controllers
device	hme: ether, ifnet, mii, ifmedia
file	dev/ic/hme.c

attach	hme at pci with hme_pci
file	dev/pci/if_hme_pci.c				hme_pci

# Apple Sudden Motion Sensor
device	asms
attach	asms at i2c
file	arch/macppc/dev/asms.c			asms


code: src/sys/arch/macppc/dev

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


code:
/*	$OpenBSD: abtn.c,v 1.17 2015/01/27 09:45:51 dlg Exp $	*/
/*	$NetBSD: abtn.c,v 1.1 1999/07/12 17:48:26 tsubai Exp $	*/

/*-
 * Copyright (c) 2002, Miodrag Vallat.
 * Copyright (C) 1999 Tsubai Masanari.  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. 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.
 */

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

#include <machine/bus.h>

#include <dev/ofw/openfirm.h>
#include <macppc/macppc/ofw_machdep.h>

#include <dev/adb/adb.h>

#include "audio.h"
#include "cd.h"
#include "wskbd.h"

#define ABTN_HANDLER_ID 31

struct abtn_softc {
	struct device sc_dev;

	int origaddr;		/* ADB device type */
	int adbaddr;		/* current ADB address */
	int handler_id;
};

int abtn_match(struct device *, void *, void *);
void abtn_attach(struct device *, struct device *, void *);
void abtn_adbcomplete(caddr_t, caddr_t, int);

#if NWSKBD > 0
extern int cd_eject(void);
#if NAUDIO > 0
extern int wskbd_set_mixervolume(long, long);
#endif
#endif

struct cfattach abtn_ca = {
	sizeof(struct abtn_softc), abtn_match, abtn_attach
};
struct cfdriver abtn_cd = {
	NULL, "abtn", DV_DULL
};

struct task eject_task =
    TASK_INITIALIZER((void (*)(void *))cd_eject, NULL);

int
abtn_match(struct device *parent, void *cf, void *aux)
{
	struct adb_attach_args *aa = aux;

	if (strcmp(aa->name, adb_device_name) != 0)
		return (0);

	if (aa->origaddr == ADBADDR_MISC &&
	    aa->handler_id == ABTN_HANDLER_ID)
		return 1;

	return 0;
}

void
abtn_attach(struct device *parent, struct device *self, void *aux)
{
	struct abtn_softc *sc = (struct abtn_softc *)self;
	struct adb_attach_args *aa = aux;
	ADBSetInfoBlock adbinfo;

	printf(": brightness/volume/eject buttons\n");

	sc->origaddr = aa->origaddr;
	sc->adbaddr = aa->adbaddr;
	sc->handler_id = aa->handler_id;

	adbinfo.siServiceRtPtr = (Ptr)abtn_adbcomplete;
	adbinfo.siDataAreaAddr = (caddr_t)sc;

	set_adb_info(&adbinfo, sc->adbaddr);
}

void
abtn_adbcomplete(caddr_t buffer, caddr_t data, int adb_command)
{
	u_int cmd, brightness;

	cmd = buffer[1];

	switch (cmd) {
	case 0x0a:	/* decrease brightness */
		brightness = cons_brightness;
		if (brightness == MAX_BRIGHTNESS)
			brightness++;		/* get round values */
		brightness -= STEP_BRIGHTNESS;
		of_setbrightness(brightness);
		break;

	case 0x09:	/* increase brightness */
		brightness = cons_brightness + STEP_BRIGHTNESS;
		of_setbrightness(brightness);
		break;

#if NAUDIO > 0 && NWSKBD > 0
	case 0x08:	/* mute */
	case 0x01:	/* mute, AV hardware */
		wskbd_set_mixervolume(0, 1);
		break;
	case 0x07:	/* decrease volume */
	case 0x02:	/* decrease volume, AV hardware */
		wskbd_set_mixervolume(-1, 1);
		break;
	case 0x06:	/* increase volume */
	case 0x03:	/* increase volume, AV hardware */
		wskbd_set_mixervolume(1, 1);
		break;
#endif
	case 0x0c:	/* mirror display key */
		/* Need callback to do something with this */
		break;
#if NWSKBD > 0 && NCD > 0
	case 0x0b:	/* eject tray */
		task_add(systq, &eject_task);
		break;
#endif
	case 0x7f:	/* numlock */
		/* Need callback to do something with this */
		break;

	default:
#ifdef DEBUG
		if ((cmd & ~0x7f) == 0)
			printf("unknown ADB button 0x%x\n", cmd);
#endif
		break;
	}
}


code:
/*	$OpenBSD: adb.c,v 1.40 2015/06/24 11:58:06 mpi Exp $	*/
/*	$NetBSD: adb.c,v 1.6 1999/08/16 06:28:09 tsubai Exp $	*/
/*	$NetBSD: adb_direct.c,v 1.14 2000/06/08 22:10:45 tsubai Exp $	*/

/*
 * Copyright (C) 1996, 1997 John P. Wittkoski
 * 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 John P. Wittkoski.
 * 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.
 */

/*-
 * Copyright (C) 1994	Bradley A. Grantham
 * 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.
 */

/*
 * This code is rather messy, but I don't have time right now
 * to clean it up as much as I would like.
 * But it works, so I'm happy. :-) jpw
 */

/*
 * TO DO:
 *  - We could reduce the time spent in the adb_intr_* routines
 *    by having them save the incoming and outgoing data directly
 *    in the adbInbound and adbOutbound queues, as it would reduce
 *    the number of times we need to copy the data around. It
 *    would also make the code more readable and easier to follow.
 *  - (Related to above) Use the header part of adbCommand to
 *    reduce the number of copies we have to do of the data.
 *  - (Related to above) Actually implement the adbOutbound queue.
 *    This is fairly easy once you switch all the intr routines
 *    over to using adbCommand structs directly.
 *  - There is a bug in the state machine of adb_intr_cuda
 *    code that causes hangs, especially on 030 machines, probably
 *    because of some timing issues. Because I have been unable to
 *    determine the exact cause of this bug, I used the timeout function
 *    to check for and recover from this condition. If anyone finds
 *    the actual cause of this bug, the calls to timeout and the
 *    adb_cuda_tickle routine can be removed.
 */

#include <sys/param.h>
#include <sys/device.h>
#include <sys/fcntl.h>
#include <sys/poll.h>
#include <sys/selinfo.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
#include <sys/timeout.h>
#include <sys/systm.h>

#include <machine/autoconf.h>
#include <machine/cpu.h>
#include <dev/ofw/openfirm.h>

#include <dev/adb/adb.h>
#include <macppc/dev/adbvar.h>
#include <macppc/dev/pm_direct.h>
#include <macppc/dev/viareg.h>

#include "apm.h"

#define printf_intr printf

#ifdef DEBUG
#ifndef ADB_DEBUG
#define ADB_DEBUG
#endif
#endif

int	adb_polling;		/* Are we polling?  (Debugger mode) */
#ifdef ADB_DEBUG
int	adb_debug;		/* Output debugging messages */
#endif /* ADB_DEBUG */

/* some misc. leftovers */
#define vPB		0x0000
#define vPB3		0x08
#define vPB4		0x10
#define vPB5		0x20
#define vSR_INT		0x04
#define vSR_OUT		0x10

/* the type of ADB action that we are currently performing */
#define ADB_ACTION_NOTREADY	0x1	/* has not been initialized yet */
#define ADB_ACTION_IDLE		0x2	/* the bus is currently idle */
#define ADB_ACTION_OUT		0x3	/* sending out a command */
#define ADB_ACTION_IN		0x4	/* receiving data */

/*
 * Shortcuts for setting or testing the VIA bit states.
 * Not all shortcuts are used for every type of ADB hardware.
 */
#define ADB_SET_STATE_IDLE_CUDA()   via_reg_or(VIA1, vBufB, (vPB4 | vPB5))
#define ADB_SET_STATE_TIP()	    via_reg_and(VIA1, vBufB, ~vPB5)
#define ADB_CLR_STATE_TIP() 	    via_reg_or(VIA1, vBufB, vPB5)
#define ADB_TOGGLE_STATE_ACK_CUDA() via_reg_xor(VIA1, vBufB, vPB4)
#define ADB_SET_STATE_ACKOFF_CUDA() via_reg_or(VIA1, vBufB, vPB4)
#define ADB_SET_SR_INPUT()	    via_reg_and(VIA1, vACR, ~vSR_OUT)
#define ADB_SET_SR_OUTPUT()	    via_reg_or(VIA1, vACR, vSR_OUT)
#define ADB_SR()		    read_via_reg(VIA1, vSR)
#define ADB_VIA_INTR_ENABLE()	    write_via_reg(VIA1, vIER, 0x84)
#define ADB_VIA_INTR_DISABLE()	    write_via_reg(VIA1, vIER, 0x04)
#define ADB_VIA_CLR_INTR()	    write_via_reg(VIA1, vIFR, 0x04)
#define ADB_INTR_IS_OFF		   (vPB3 == (read_via_reg(VIA1, vBufB) & vPB3))
#define ADB_INTR_IS_ON		   (0 == (read_via_reg(VIA1, vBufB) & vPB3))
#define ADB_SR_INTR_IS_ON	   (vSR_INT == (read_via_reg(VIA1, \
						vIFR) & vSR_INT))

/*
 * This is the delay that is required (in uS) between certain
 * ADB transactions. The actual timing delay for for each uS is
 * calculated at boot time to account for differences in machine speed.
 */
#define ADB_DELAY	150

/*
 * Maximum ADB message length; includes space for data, result, and
 * device code - plus a little for safety.
 */
#define ADB_MAX_MSG_LENGTH	16
#define ADB_MAX_HDR_LENGTH	8

#define ADB_QUEUE		32
#define ADB_TICKLE_TICKS	4

/*
 * Eventually used for two separate queues, the queue between
 * the upper and lower halves, and the outgoing packet queue.
 */
struct adbCommand {
	u_char	header[ADB_MAX_HDR_LENGTH];	/* not used yet */
	u_char	data[ADB_MAX_MSG_LENGTH];	/* packet data only */
	u_char	*saveBuf;	/* where to save result */
	u_char	*compRout;	/* completion routine pointer */
	u_char	*compData;	/* completion routine data pointer */
	u_int	cmd;		/* the original command for this data */
	u_int	unsol;		/* 1 if packet was unsolicited */
	u_int	ack_only;	/* 1 for no special processing */
};

/*
 * A few variables that we need and their initial values.
 */
int	adbHardware = ADB_HW_UNKNOWN;
int	adbActionState = ADB_ACTION_NOTREADY;
int	adbWaiting;		/* waiting for return data from the device */
int	adbWriteDelay;		/* working on (or waiting to do) a write */

int	adbWaitingCmd;		/* ADB command we are waiting for */
u_char	*adbBuffer;		/* pointer to user data area */
void	*adbCompRout;		/* pointer to the completion routine */
void	*adbCompData;		/* pointer to the completion routine data */
int	adbStarting = 1;	/* doing adb_reinit so do polling differently */

u_char	adbInputBuffer[ADB_MAX_MSG_LENGTH];	/* data input buffer */
u_char	adbOutputBuffer[ADB_MAX_MSG_LENGTH];	/* data output buffer */

int	adbSentChars;		/* how many characters we have sent */

struct	adbCommand adbInbound[ADB_QUEUE];	/* incoming queue */
int	adbInCount;			/* how many packets in in queue */
int	adbInHead;			/* head of in queue */
int	adbInTail;			/* tail of in queue */

int	tickle_count;			/* how many tickles seen for this packet? */
int	tickle_serial;			/* the last packet tickled */
int	adb_cuda_serial;		/* the current packet */
struct	timeout adb_cuda_timeout;
struct	timeout adb_softintr_timeout;
int	adbempty;			/* nonzero if no adb devices */

extern struct cfdriver adb_cd;

volatile u_char *Via1Base;

/*
 * The following are private routines.
 */
#ifdef ADB_DEBUG
void	print_single(u_char *);
#endif
void	adb_intr_cuda(void);
void	adb_soft_intr(void);
int	send_adb_cuda(u_char *, u_char *, void *, void *, int);
void	adb_cuda_tickle(void);
void	adb_pass_up(struct adbCommand *);
void	adb_op_comprout(caddr_t, caddr_t, int);
void	adb_reinit(struct adb_softc *);
int	count_adbs(struct adb_softc *);
int	get_ind_adb_info(struct adb_softc *, ADBDataBlock *, int);
int	get_adb_info(ADBDataBlock *, int);
int	adb_op(Ptr, Ptr, Ptr, short);
void	adb_hw_setup(void);
int	adb_cmd_result(u_char *);
void	setsoftadb(void);

int	adb_intr(void *arg);
void	adb_cuda_autopoll(void);
void 	adb_cuda_fileserver_mode(void);

#ifdef ADB_DEBUG
/*
 * print_single
 * Diagnostic display routine. Displays the hex values of the
 * specified elements of the u_char. The length of the "string"
 * is in [0].
 */
void
print_single(str)
	u_char *str;
{
	int x;

	if (str == NULL) {
		printf_intr("no data - null pointer\n");
		return;
	}
	if (*str == '\0') {
		printf_intr("nothing returned\n");
		return;
	}
	if (*str > 20) {
		printf_intr("ADB: ACK > 20 no way!\n");
		*str = 20;
	}
	printf_intr("(length=0x%x):", *str);
	for (x = 1; x <= *str; x++)
		printf_intr("  0x%02x", str[x]);
	printf_intr("\n");
}
#endif

void
adb_cuda_tickle(void)
{
	volatile int s;

	if (adbActionState == ADB_ACTION_IN) {
		if (tickle_serial == adb_cuda_serial) {
			if (++tickle_count > 0) {
				s = splhigh();
				adbActionState = ADB_ACTION_IDLE;
				adbInputBuffer[0] = 0;
				ADB_SET_STATE_IDLE_CUDA();
				splx(s);
			}
		} else {
			tickle_serial = adb_cuda_serial;
			tickle_count = 0;
		}
	} else {
		tickle_serial = adb_cuda_serial;
		tickle_count = 0;
	}

	timeout_add(&adb_cuda_timeout, ADB_TICKLE_TICKS);
}

/*
 * called when when an adb interrupt happens
 *
 * Cuda version of adb_intr
 * TO DO: do we want to add some calls to intr_dispatch() here to
 * grab serial interrupts?
 */
void
adb_intr_cuda(void)
{
	volatile int i, ending;
	volatile unsigned int s;
	struct adbCommand packet;

	s = splhigh();		/* can't be too careful - might be called */
				/* from a routine, NOT an interrupt */

	ADB_VIA_CLR_INTR();	/* clear interrupt */
	ADB_VIA_INTR_DISABLE();	/* disable ADB interrupt on IIs. */

switch_start:
	switch (adbActionState) {
	case ADB_ACTION_IDLE:
		/*
		 * This is an unexpected packet, so grab the first (dummy)
		 * byte, set up the proper vars, and tell the chip we are
		 * starting to receive the packet by setting the TIP bit.
		 */
		adbInputBuffer[1] = ADB_SR();
		adb_cuda_serial++;
		if (ADB_INTR_IS_OFF)	/* must have been a fake start */
			break;

		ADB_SET_SR_INPUT();
		ADB_SET_STATE_TIP();

		adbInputBuffer[0] = 1;
		adbActionState = ADB_ACTION_IN;
#ifdef ADB_DEBUG
		if (adb_debug)
			printf_intr("idle 0x%02x ", adbInputBuffer[1]);
#endif
		break;

	case ADB_ACTION_IN:
		adbInputBuffer[++adbInputBuffer[0]] = ADB_SR();
		/* intr off means this is the last byte (end of frame) */
		if (ADB_INTR_IS_OFF)
			ending = 1;
		else
			ending = 0;

		if (1 == ending) {	/* end of message? */
#ifdef ADB_DEBUG
			if (adb_debug) {
				printf_intr("in end 0x%02x ",
				    adbInputBuffer[adbInputBuffer[0]]);
				print_single(adbInputBuffer);
			}
#endif

			/*
			 * Are we waiting AND does this packet match what we
			 * are waiting for AND is it coming from either the
			 * ADB or RTC/PRAM sub-device? This section _should_
			 * recognize all ADB and RTC/PRAM type commands, but
			 * there may be more... NOTE: commands are always at
			 * [4], even for RTC/PRAM commands.
			 */
			/* set up data for adb_pass_up */
			memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1);

			if ((adbWaiting == 1) &&
			    (adbInputBuffer[4] == adbWaitingCmd) &&
			    ((adbInputBuffer[2] == 0x00) ||
			    (adbInputBuffer[2] == 0x01))) {
				packet.saveBuf = adbBuffer;
				packet.compRout = adbCompRout;
				packet.compData = adbCompData;
				packet.unsol = 0;
				packet.ack_only = 0;
				adb_pass_up(&packet);

				adbWaitingCmd = 0;	/* reset "waiting" vars */
				adbWaiting = 0;
				adbBuffer = NULL;
				adbCompRout = NULL;
				adbCompData = NULL;
			} else {
				packet.unsol = 1;
				packet.ack_only = 0;
				adb_pass_up(&packet);
			}

			/* reset vars and signal the end of this frame */
			adbActionState = ADB_ACTION_IDLE;
			adbInputBuffer[0] = 0;
			ADB_SET_STATE_IDLE_CUDA();
			/*ADB_SET_SR_INPUT();*/

			/*
			 * If there is something waiting to be sent out,
			 * the set everything up and send the first byte.
			 */
			if (adbWriteDelay == 1) {
				delay(ADB_DELAY);	/* required */
				adbSentChars = 0;
				adbActionState = ADB_ACTION_OUT;
				/*
				 * If the interrupt is on, we were too slow
				 * and the chip has already started to send
				 * something to us, so back out of the write
				 * and start a read cycle.
				 */
				if (ADB_INTR_IS_ON) {
					ADB_SET_SR_INPUT();
					ADB_SET_STATE_IDLE_CUDA();
					adbSentChars = 0;
					adbActionState = ADB_ACTION_IDLE;
					adbInputBuffer[0] = 0;
					break;
				}
				/*
				 * If we got here, it's ok to start sending
				 * so load the first byte and tell the chip
				 * we want to send.
				 */
				ADB_SET_STATE_TIP();
				ADB_SET_SR_OUTPUT();
				write_via_reg(VIA1, vSR, adbOutputBuffer[adbSentChars + 1]);
			}
		} else {
			ADB_TOGGLE_STATE_ACK_CUDA();
#ifdef ADB_DEBUG
			if (adb_debug)
				printf_intr("in 0x%02x ",
				    adbInputBuffer[adbInputBuffer[0]]);
#endif
		}
		break;

	case ADB_ACTION_OUT:
		i = ADB_SR();	/* reset SR-intr in IFR */
#ifdef ADB_DEBUG
		if (adb_debug)
			printf_intr("intr out 0x%02x ", i);
#endif

		adbSentChars++;
		if (ADB_INTR_IS_ON) {	/* ADB intr low during write */
#ifdef ADB_DEBUG
			if (adb_debug)
				printf_intr("intr was on ");
#endif
			ADB_SET_SR_INPUT();	/* make sure SR is set to IN */
			ADB_SET_STATE_IDLE_CUDA();
			adbSentChars = 0;	/* must start all over */
			adbActionState = ADB_ACTION_IDLE;	/* new state */
			adbInputBuffer[0] = 0;
			adbWriteDelay = 1;	/* must retry when done with
						 * read */
			delay(ADB_DELAY);
			goto switch_start;	/* process next state right
						 * now */
			break;
		}
		if (adbOutputBuffer[0] == adbSentChars) {	/* check for done */
			if (0 == adb_cmd_result(adbOutputBuffer)) {	/* do we expect data
									 * back? */
				adbWaiting = 1;	/* signal waiting for return */
				adbWaitingCmd = adbOutputBuffer[2];	/* save waiting command */
			} else {	/* no talk, so done */
				/* set up stuff for adb_pass_up */
				memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1);
				packet.saveBuf = adbBuffer;
				packet.compRout = adbCompRout;
				packet.compData = adbCompData;
				packet.cmd = adbWaitingCmd;
				packet.unsol = 0;
				packet.ack_only = 1;
				adb_pass_up(&packet);

				/* reset "waiting" vars, just in case */
				adbWaitingCmd = 0;
				adbBuffer = NULL;
				adbCompRout = NULL;
				adbCompData = NULL;
			}

			adbWriteDelay = 0;	/* done writing */
			adbActionState = ADB_ACTION_IDLE;	/* signal bus is idle */
			ADB_SET_SR_INPUT();
			ADB_SET_STATE_IDLE_CUDA();
#ifdef ADB_DEBUG
			if (adb_debug)
				printf_intr("write done ");
#endif
		} else {
			write_via_reg(VIA1, vSR, adbOutputBuffer[adbSentChars + 1]);	/* send next byte */
			ADB_TOGGLE_STATE_ACK_CUDA();	/* signal byte ready to
							 * shift */
#ifdef ADB_DEBUG
			if (adb_debug)
				printf_intr("toggle ");
#endif
		}
		break;

	case ADB_ACTION_NOTREADY:
#ifdef ADB_DEBUG
		if (adb_debug)
			printf_intr("adb: not yet initialized\n");
#endif
		break;

	default:
		;
#ifdef ADB_DEBUG
		if (adb_debug)
			printf_intr("intr: unknown ADB state\n");
#endif
	}

	ADB_VIA_INTR_ENABLE();	/* enable ADB interrupt on IIs. */

	splx(s);		/* restore */
}

int
send_adb_cuda(u_char * in, u_char * buffer, void *compRout, void *data, int
	command)
{
	int s, len;

#ifdef ADB_DEBUG
	if (adb_debug)
		printf_intr("SEND\n");
#endif

	if (adbActionState == ADB_ACTION_NOTREADY)
		return 1;

	/* Don't interrupt while we are messing with the ADB */
	s = splhigh();

	if ((adbActionState == ADB_ACTION_IDLE) &&	/* ADB available? */
	    (ADB_INTR_IS_OFF)) {	/* and no incoming interrupt? */
	} else
		if (adbWriteDelay == 0)	/* it's busy, but is anything waiting? */
			adbWriteDelay = 1;	/* if no, then we'll "queue"
						 * it up */
		else {
			splx(s);
			return 1;	/* really busy! */
		}

#ifdef ADB_DEBUG
	if (adb_debug)
		printf_intr("QUEUE\n");
#endif
	if ((long)in == (long)0) {	/* need to convert? */
		if ((command & 0x0c) == 0x08)	/* copy addl data ONLY if
						 * doing a listen! */
			len = buffer[0];	/* length of additional data */
		else
			len = 0;/* no additional data */

		adbOutputBuffer[0] = 2 + len;	/* dev. type + command + addl.
						 * data */
		adbOutputBuffer[1] = 0x00;	/* mark as an ADB command */
		adbOutputBuffer[2] = (u_char)command;	/* load command */

		/* copy additional output data, if any */
		memcpy(adbOutputBuffer + 3, buffer + 1, len);
	} else
		/* if data ready, just copy over */
		memcpy(adbOutputBuffer, in, in[0] + 2);

	adbSentChars = 0;	/* nothing sent yet */
	adbBuffer = buffer;	/* save buffer to know where to save result */
	adbCompRout = compRout;	/* save completion routine pointer */
	adbCompData = data;	/* save completion routine data pointer */
	adbWaitingCmd = adbOutputBuffer[2];	/* save wait command */

	if (adbWriteDelay != 1) {	/* start command now? */
#ifdef ADB_DEBUG
		if (adb_debug)
			printf_intr("out start NOW");
#endif
		delay(ADB_DELAY);
		adbActionState = ADB_ACTION_OUT;	/* set next state */
		ADB_SET_SR_OUTPUT();	/* set shift register for OUT */
		write_via_reg(VIA1, vSR, adbOutputBuffer[adbSentChars + 1]);	/* load byte for output */
		ADB_SET_STATE_ACKOFF_CUDA();
		ADB_SET_STATE_TIP();	/* tell ADB that we want to send */
	}
	adbWriteDelay = 1;	/* something in the write "queue" */

	splx(s);

	if ((s & (1 << 18)) || adb_polling) /* XXX were VIA1 interrupts blocked ? */
		/* poll until byte done */
		while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON)
		    || (adbWaiting == 1))
			if (ADB_SR_INTR_IS_ON) {	/* wait for "interrupt" */
				adb_intr_cuda();	/* process it */
				if (cold)
					delay(ADB_DELAY);
				adb_soft_intr();
			}

	return 0;
}

/*
 * Called when when an adb interrupt happens.
 * This routine simply transfers control over to the appropriate
 * code for the machine we are running on.
 */
int
adb_intr(void *arg)
{
	switch (adbHardware) {
	case ADB_HW_PMU:
		pm_intr();
		break;

	case ADB_HW_CUDA:
		adb_intr_cuda();
		break;
	}
	return 1;
}

/*
 * adb_pass_up is called by the interrupt-time routines.
 * It takes the raw packet data that was received from the
 * device and puts it into the queue that the upper half
 * processes. It then signals for a soft ADB interrupt which
 * will eventually call the upper half routine (adb_soft_intr).
 *
 * If in->unsol is 0, then this is either the notification
 * that the packet was sent (on a LISTEN, for example), or the
 * response from the device (on a TALK). The completion routine
 * is called only if the user specified one.
 *
 * If in->unsol is 1, then this packet was unsolicited and
 * so we look up the device in the ADB device table to determine
 * what its default service routine is.
 *
 * If in->ack_only is 1, then we really only need to call
 * the completion routine, so don't do any other stuff.
 *
 * Note that in->data contains the packet header AND data,
 * while adbInbound[]->data contains ONLY data.
 *
 * Note: Called only at interrupt time. Assumes this.
 */
void
adb_pass_up(struct adbCommand *in)
{
	int start = 0, len = 0, cmd = 0;
	ADBDataBlock block;

	if (adbInCount >= ADB_QUEUE) {
#ifdef ADB_DEBUG
		if (adb_debug)
			printf_intr("adb: ring buffer overflow\n");
#endif
		return;
	}

	if (in->ack_only) {
		len = in->data[0];
		cmd = in->cmd;
		start = 0;
	} else {
		switch (adbHardware) {
		case ADB_HW_CUDA:
			/* If it's unsolicited, accept only ADB data for now */
			if (in->unsol)
				if (0 != in->data[2])
					return;
			cmd = in->data[4];
			if (in->data[0] < 5)
				len = 0;
			else
				len = in->data[0]-4;
			start = 4;
			break;

		case ADB_HW_PMU:
			cmd = in->data[1];
			if (in->data[0] < 2)
				len = 0;
			else
				len = in->data[0]-1;
			start = 1;
			break;

		case ADB_HW_UNKNOWN:
			return;
		}

		/* Make sure there is a valid device entry for this device */
		if (in->unsol) {
			/* ignore unsolicited data during adbreinit */
			if (adbStarting)
				return;
			/* get device's comp. routine and data area */
			if (-1 == get_adb_info(&block, ADB_CMDADDR(cmd)))
				return;
		}
	}

	/*
 	 * If this is an unsolicited packet, we need to fill in
 	 * some info so adb_soft_intr can process this packet
 	 * properly. If it's not unsolicited, then use what
 	 * the caller sent us.
 	 */
	if (in->unsol) {
		adbInbound[adbInTail].compRout = (void *)block.dbServiceRtPtr;
		adbInbound[adbInTail].compData = (void *)block.dbDataAreaAddr;
		adbInbound[adbInTail].saveBuf = (void *)adbInbound[adbInTail].data;
	} else {
		adbInbound[adbInTail].compRout = (void *)in->compRout;
		adbInbound[adbInTail].compData = (void *)in->compData;
		adbInbound[adbInTail].saveBuf = (void *)in->saveBuf;
	}

#ifdef ADB_DEBUG
	if (adb_debug && in->data[1] == 2)
		printf_intr("adb: caught error\n");
#endif

	/* copy the packet data over */
	/*
	 * TO DO: If the *_intr routines fed their incoming data
	 * directly into an adbCommand struct, which is passed to
	 * this routine, then we could eliminate this copy.
	 */
	memcpy(adbInbound[adbInTail].data + 1, in->data + start + 1, len);
	adbInbound[adbInTail].data[0] = len;
	adbInbound[adbInTail].cmd = cmd;

	adbInCount++;
	if (++adbInTail >= ADB_QUEUE)
		adbInTail = 0;

	/*
	 * If the debugger is running, call upper half manually.
	 * Otherwise, trigger a soft interrupt to handle the rest later.
	 */
	if (adb_polling)
		adb_soft_intr();
	else
		setsoftadb();
}

/*
 * Called to process the packets after they have been
 * placed in the incoming queue.
 *
 */
void
adb_soft_intr(void)
{
	int s;
	int cmd = 0;
	u_char *buffer;
	u_char *comprout;
	u_char *compdata;

/*delay(2*ADB_DELAY);*/

	while (adbInCount) {
#ifdef ADB_DEBUG
		if (adb_debug & 0x80)
			printf_intr("%x %x %x ",
			    adbInCount, adbInHead, adbInTail);
#endif
		/* get the data we need from the queue */
		buffer = adbInbound[adbInHead].saveBuf;
		comprout = adbInbound[adbInHead].compRout;
		compdata = adbInbound[adbInHead].compData;
		cmd = adbInbound[adbInHead].cmd;

		/* copy over data to data area if it's valid */
		/*
		 * Note that for unsol packets we don't want to copy the
		 * data anywhere, so buffer was already set to 0.
		 * For ack_only buffer was set to 0, so don't copy.
		 */
		if (buffer)
			memcpy(buffer, adbInbound[adbInHead].data,
			    adbInbound[adbInHead].data[0] + 1);

#ifdef ADB_DEBUG
			if (adb_debug & 0x80) {
				printf_intr("%p %p %p %x ",
				    buffer, comprout, compdata, (short)cmd);
				printf_intr("buf: ");
				print_single(adbInbound[adbInHead].data);
			}
#endif
		/*
		 * Remove the packet from the queue before calling
                 * the completion routine, so that the completion
                 * routine can reentrantly process the queue.  For
                 * example, this happens when polling is turned on
                 * by entering the debuger by keystroke.
                 */
		s = splhigh();
		adbInCount--;
		if (++adbInHead >= ADB_QUEUE)
			adbInHead = 0;
		splx(s);

		/* call default completion routine if it's valid */
		if (comprout) {
			((int (*)(u_char *, u_char *, int)) comprout)
			    (buffer, compdata, cmd);
		}

	}
}

/*
 * This is my version of the ADBOp routine. It mainly just calls the
 * hardware-specific routine.
 *
 *   data 	: pointer to data area to be used by compRout
 *   compRout	: completion routine
 *   buffer	: for LISTEN: points to data to send - MAX 8 data bytes,
 *		  byte 0 = # of bytes
 *		: for TALK: points to place to save return data
 *   command	: the adb command to send
 *   result	: 0 = success
 *		: -1 = could not complete
 */
int
adb_op(Ptr buffer, Ptr compRout, Ptr data, short command)
{
	int result;

	switch (adbHardware) {
	case ADB_HW_PMU:
		result = pm_adb_op((u_char *)buffer, (void *)compRout,
		    (void *)data, (int)command);

		if (result == 0)
			return 0;
		else
			return -1;
		break;

	case ADB_HW_CUDA:
		result = send_adb_cuda((u_char *)0, (u_char *)buffer,
		    (void *)compRout, (void *)data, (int)command);
		if (result == 0)
			return 0;
		else
			return -1;
		break;

	default:
		return -1;
	}
}

/*
 * adb_hw_setup
 * This routine sets up the possible machine specific hardware
 * config (mainly VIA settings) for the various models.
 */
void
adb_hw_setup(void)
{
	volatile int i;

	switch (adbHardware) {

	case ADB_HW_PMU:
		/*
		 * XXX - really PM_VIA_CLR_INTR - should we put it in
		 * pm_direct.h?
		 */
		write_via_reg(VIA1, vIFR, 0x90);	/* clear interrupt */
		break;

	case ADB_HW_CUDA:
		via_reg_or(VIA1, vDirB, 0x30);	/* register B bits 4 and 5:
						 * outputs */
		via_reg_and(VIA1, vDirB, 0xf7);	/* register B bit 3: input */
		via_reg_and(VIA1, vACR, ~vSR_OUT);	/* make sure SR is set
							 * to IN */
		write_via_reg(VIA1, vACR, (read_via_reg(VIA1, vACR) | 0x0c) & ~0x10);
		adbActionState = ADB_ACTION_IDLE;	/* used by all types of
							 * hardware */
		write_via_reg(VIA1, vIER, 0x84);/* make sure VIA interrupts
						 * are on */
		ADB_SET_STATE_IDLE_CUDA();	/* set ADB bus state to idle */

		/* sort of a device reset */
		i = ADB_SR();	/* clear interrupt */
		ADB_VIA_INTR_DISABLE();	/* no interrupts while clearing */
		ADB_SET_STATE_IDLE_CUDA();	/* reset state to idle */
		delay(ADB_DELAY);
		ADB_SET_STATE_TIP();	/* signal start of frame */
		delay(ADB_DELAY);
		ADB_TOGGLE_STATE_ACK_CUDA();
		delay(ADB_DELAY);
		ADB_CLR_STATE_TIP();
		delay(ADB_DELAY);
		ADB_SET_STATE_IDLE_CUDA();	/* back to idle state */
		i = ADB_SR();	/* clear interrupt */
		ADB_VIA_INTR_ENABLE();	/* ints ok now */
		break;

	case ADB_HW_UNKNOWN:
	default:
		write_via_reg(VIA1, vIER, 0x04);/* turn interrupts off - TO
						 * DO: turn PB ints off? */
		break;
	}
}

/*
 * adb_reinit sets up the adb stuff
 *
 */
void
adb_reinit(struct adb_softc *sc)
{
	u_char send_string[ADB_MAX_MSG_LENGTH];
	ADBDataBlock data;	/* temp. holder for getting device info */
	volatile int i, x;
	int s;
	int command;
	int result;
	int saveptr;		/* point to next free relocation address */
	int device;
	int nonewtimes;		/* times thru loop w/o any new devices */
	int ADBNumDevices = 0;

	/* Make sure we are not interrupted while building the table. */
	if (adbHardware != ADB_HW_PMU)	/* ints must be on for PB? */
		s = splhigh();

	/* Let intr routines know we are running reinit */
	adbStarting = 1;

	/*
	 * Initialize the ADB table.  For now, we'll always use the same table
	 * that is defined at the beginning of this file - no mallocs.
	 */
	for (i = 0; i < 16; i++)
		sc->sc_devtable[i].handler_id = 0;

	adb_hw_setup();		/* init the VIA bits and hard reset ADB */

	delay(1000);

	/* send an ADB reset first */
	adb_op_sync((Ptr)0, (short)0x00);
	delay(200000);

	/*
	 * Probe for ADB devices. Probe devices 1-15 quickly to determine
	 * which device addresses are in use and which are free. For each
	 * address that is in use, move the device at that address to a higher
	 * free address. Continue doing this at that address until no device
	 * responds at that address. Then move the last device that was moved
	 * back to the original address. Do this for the remaining addresses
	 * that we determined were in use.
	 *
	 * When finished, do this entire process over again with the updated
	 * list of in use addresses. Do this until no new devices have been
	 * found in 20 passes though the in use address list. (This probably
	 * seems long and complicated, but it's the best way to detect multiple
	 * devices at the same address - sometimes it takes a couple of tries
	 * before the collision is detected.)
	 */

	/* initial scan through the devices */
	for (i = 1; i < 16; i++) {
		send_string[0] = 0;
		command = ADBTALK(i, 3);
		result = adb_op_sync((Ptr)send_string, (short)command);

		if (send_string[0] != 0) {
			/* check for valid device handler */
			switch (send_string[2]) {
			case 0:
			case 0xfd:
			case 0xfe:
			case 0xff:
				continue;	/* invalid, skip */
			}

			/* found a device */
			++ADBNumDevices;
			KASSERT(ADBNumDevices < 16);
			sc->sc_devtable[ADBNumDevices].handler_id =
				(int)send_string[2];
			sc->sc_devtable[ADBNumDevices].orig_addr = i;
			sc->sc_devtable[ADBNumDevices].curr_addr = i;
			sc->sc_devtable[ADBNumDevices].data = NULL;
			sc->sc_devtable[ADBNumDevices].handler = NULL;
		}
	}

	/* find highest unused address */
	for (saveptr = 15; saveptr > 0; saveptr--)
		if (-1 == get_adb_info(&data, saveptr))
			break;

#ifdef ADB_DEBUG
	if (adb_debug & 0x80) {
		printf_intr("first free is: 0x%02x\n", saveptr);
		printf_intr("devices: %i\n", ADBNumDevices);
	}
#endif

	nonewtimes = 0;		/* no loops w/o new devices */
	while (saveptr > 0 && nonewtimes++ < 11) {
		for (i = 1; i <= ADBNumDevices; i++) {
			device = sc->sc_devtable[i].curr_addr;
#ifdef ADB_DEBUG
			if (adb_debug & 0x80)
				printf_intr("moving device 0x%02x to 0x%02x "
				    "(index 0x%02x)  ", device, saveptr, i);
#endif

			/* send TALK R3 to address */
			command = ADBTALK(device, 3);
			adb_op_sync((Ptr)send_string, (short)command);

			/* move device to higher address */
			command = ADBLISTEN(device, 3);
			send_string[0] = 2;
			send_string[1] = (u_char)(saveptr | 0x60);
			send_string[2] = 0xfe;
			adb_op_sync((Ptr)send_string, (short)command);
			delay(500);

			/* send TALK R3 - anything at new address? */
			command = ADBTALK(saveptr, 3);
			adb_op_sync((Ptr)send_string, (short)command);
			delay(500);

			if (send_string[0] == 0) {
#ifdef ADB_DEBUG
				if (adb_debug & 0x80)
					printf_intr("failed, continuing\n");
#endif
				continue;
			}

			/* send TALK R3 - anything at old address? */
			command = ADBTALK(device, 3);
			result = adb_op_sync((Ptr)send_string, (short)command);
			if (send_string[0] != 0) {
				/* check for valid device handler */
				switch (send_string[2]) {
				case 0:
				case 0xfd:
				case 0xfe:
				case 0xff:
					continue;	/* invalid, skip */
				}

				/* new device found */
				/* update data for previously moved device */
				sc->sc_devtable[i].curr_addr = saveptr;
#ifdef ADB_DEBUG
				if (adb_debug & 0x80)
					printf_intr("old device at index %i\n",i);
#endif
				/* add new device in table */
#ifdef ADB_DEBUG
				if (adb_debug & 0x80)
					printf_intr("new device found\n");
#endif
				if (saveptr > ADBNumDevices) {
					++ADBNumDevices;
					KASSERT(ADBNumDevices < 16);
				}
				sc->sc_devtable[ADBNumDevices].handler_id =
					(int)send_string[2];
				sc->sc_devtable[ADBNumDevices].orig_addr = device;
				sc->sc_devtable[ADBNumDevices].curr_addr = device;
				/* These will be set correctly in adbsys.c */
				/* Until then, unsol. data will be ignored. */
				sc->sc_devtable[ADBNumDevices].data = NULL;
				sc->sc_devtable[ADBNumDevices].handler = NULL;
				/* find next unused address */
				for (x = saveptr; x > 0; x--) {
					if (-1 == get_adb_info(&data, x)) {
						saveptr = x;
						break;
					}
				}
				if (x == 0)
					saveptr = 0;
#ifdef ADB_DEBUG
				if (adb_debug & 0x80)
					printf_intr("new free is 0x%02x\n",
					    saveptr);
#endif
				nonewtimes = 0;
			} else {
#ifdef ADB_DEBUG
				if (adb_debug & 0x80)
					printf_intr("moving back...\n");
#endif
				/* move old device back */
				command = ADBLISTEN(saveptr, 3);
				send_string[0] = 2;
				send_string[1] = (u_char)(device | 0x60);
				send_string[2] = 0xfe;
				adb_op_sync((Ptr)send_string, (short)command);
				delay(1000);
			}
		}
	}

#ifdef ADB_DEBUG
	if (adb_debug) {
		for (i = 1; i <= ADBNumDevices; i++) {
			x = get_ind_adb_info(sc, &data, i);
			if (x != -1)
				printf_intr("index 0x%x, addr 0x%x, type 0x%x\n",
				    i, x, data.devType);
		}
	}
#endif

#ifdef ADB_DEBUG
	if (adb_debug) {
		if (0 == ADBNumDevices)	/* tell user if no devices found */
			printf_intr("adb: no devices found\n");
	}
#endif

	adbStarting = 0;	/* not starting anymore */
#ifdef ADB_DEBUG
	if (adb_debug)
		printf_intr("adb: adb_reinit complete\n");
#endif

	if (adbHardware == ADB_HW_CUDA) {
		timeout_set(&adb_cuda_timeout, (void *)adb_cuda_tickle, NULL);
		timeout_add(&adb_cuda_timeout, ADB_TICKLE_TICKS);
	}

	if (adbHardware != ADB_HW_PMU)	/* ints must be on for PB? */
		splx(s);
}

/*
 * adb_cmd_result
 *
 * This routine lets the caller know whether the specified adb command string
 * should expect a returned result, such as a TALK command.
 *
 * returns: 0 if a result should be expected
 *          1 if a result should NOT be expected
 */
int
adb_cmd_result(u_char *in)
{
	switch (adbHardware) {
	case ADB_HW_CUDA:
		/* was it an ADB talk command? */
		if ((in[1] == 0x00) && ((in[2] & 0x0c) == 0x0c))
			return 0;
		/* was it an RTC/PRAM read date/time? */
		if ((in[1] == 0x01) && (in[2] == 0x03))
			return 0;
		return 1;

	case ADB_HW_PMU:
		return 1;

	default:
		return 1;
	}
}

/*
 * adb_op_sync
 *
 * This routine does exactly what the adb_op routine does, except that after
 * the adb_op is called, it waits until the return value is present before
 * returning.
 */
int
adb_op_sync(Ptr buffer, short command)
{
	int tmout;
	int result;
	volatile int flag = 0;

	result = adb_op(buffer, (void *)adb_op_comprout,
	    (void *)&flag, command);	/* send command */
	if (result == 0) {		/* send ok? */
		/*
		 * Total time to wait is calculated as follows:
		 *  - Tlt (stop to start time): 260 usec
		 *  - start bit: 100 usec
		 *  - up to 8 data bytes: 64 * 100 usec = 6400 usec
		 *  - stop bit (with SRQ): 140 usec
		 * Total: 6900 usec
		 *
		 * This is the total time allowed by the specification.  Any
		 * device that doesn't conform to this will fail to operate
		 * properly on some Apple systems.  In spite of this we
		 * double the time to wait; some Cuda-based apparently
		 * queues some commands and allows the main CPU to continue
		 * processing (radical concept, eh?).  To be safe, allow
		 * time for two complete ADB transactions to occur.
		 */
		for (tmout = 13800; !flag && tmout >= 10; tmout -= 10)
			delay(10);
		if (!flag && tmout > 0)
			delay(tmout);

		if (!flag)
			result = -2;
	}

	return result;
}

/*
 * adb_op_comprout
 *
 * This function is used by the adb_op_sync routine so it knows when the
 * function is done.
 */
void
adb_op_comprout(caddr_t buffer, caddr_t compdata, int cmd)
{
	*(int *)compdata = 0x01;		/* update flag value */
}

int
count_adbs(struct adb_softc *sc)
{
	int i;
	int found;

	found = 0;

	for (i = 1; i < 16; i++)
		if (0 != sc->sc_devtable[i].handler_id)
			found++;

	return found;
}

int
get_ind_adb_info(struct adb_softc *sc, ADBDataBlock * info, int index)
{
	if ((index < 1) || (index > 15))	/* check range 1-15 */
		return (-1);

#ifdef ADB_DEBUG
	if (adb_debug & 0x80)
		printf_intr("index 0x%x handler id 0x%x\n", index,
		    sc->sc_devtable[index].handler_id);
#endif
	if (0 == sc->sc_devtable[index].handler_id)	/* make sure it's a valid entry */
		return (-1);

	info->devType = sc->sc_devtable[index].handler_id;
	info->origADBAddr = sc->sc_devtable[index].orig_addr;
	info->dbServiceRtPtr = (Ptr)sc->sc_devtable[index].handler;
	info->dbDataAreaAddr = (Ptr)sc->sc_devtable[index].data;

	return (sc->sc_devtable[index].curr_addr);
}

int
get_adb_info(ADBDataBlock * info, int adbAddr)
{
	struct adb_softc *sc = adb_cd.cd_devs[0];
	int i;

	if (sc == NULL)
		return (-1);

	if ((adbAddr < 1) || (adbAddr > 15))	/* check range 1-15 */
		return (-1);

	for (i = 1; i < 15; i++)
		if (sc->sc_devtable[i].curr_addr == adbAddr) {
			info->devType = sc->sc_devtable[i].handler_id;
			info->origADBAddr = sc->sc_devtable[i].orig_addr;
			info->dbServiceRtPtr = (Ptr)sc->sc_devtable[i].handler;
			info->dbDataAreaAddr = sc->sc_devtable[i].data;
			return 0;	/* found */
		}

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

int
set_adb_info(ADBSetInfoBlock * info, int adbAddr)
{
	struct adb_softc *sc = adb_cd.cd_devs[0];
	int i;

	if (sc == NULL)
		return (-1);

	if ((adbAddr < 1) || (adbAddr > 15))	/* check range 1-15 */
		return (-1);

	for (i = 1; i < 15; i++)
		if (sc->sc_devtable[i].curr_addr == adbAddr) {
			sc->sc_devtable[i].handler =
			    (void *)(info->siServiceRtPtr);
			sc->sc_devtable[i].data = info->siDataAreaAddr;
			return 0;	/* found */
		}

	return (-1);		/* not found */

}

/* caller should really use machine-independent version: getPramTime */
/* this version does pseudo-adb access only */
int
adb_read_date_time(time_t *time)
{
	u_char output[ADB_MAX_MSG_LENGTH];
	int result;
	int retcode;
	volatile int flag = 0;
	u_int32_t t;

	switch (adbHardware) {
	case ADB_HW_PMU:
		pm_read_date_time(time);
		retcode = 0;
		break;

	case ADB_HW_CUDA:
		output[0] = 0x02;	/* 2 byte message */
		output[1] = 0x01;	/* to pram/rtc device */
		output[2] = 0x03;	/* read date/time */
		result = send_adb_cuda((u_char *)output, (u_char *)output,
		    (void *)adb_op_comprout, (void *)&flag, (int)0);
		if (result != 0) {	/* exit if not sent */
			retcode = -1;
			break;
		}

		while (0 == flag)	/* wait for result */
			;

		delay(20); /* completion occurs too soon? */
		memcpy(&t, output + 1, sizeof(t));
		*time = (time_t)t;
		retcode = 0;
		break;

	case ADB_HW_UNKNOWN:
	default:
		retcode = -1;
		break;
	}
	if (retcode == 0) {
#define DIFF19041970 2082844800
		*time -= DIFF19041970;

	} else {
		*time = 0;
	}
	return retcode;
}

/* caller should really use machine-independent version: setPramTime */
/* this version does pseudo-adb access only */
int
adb_set_date_time(time_t time)
{
	u_char output[ADB_MAX_MSG_LENGTH];
	int result;
	volatile int flag = 0;
	u_int32_t t;

	time += DIFF19041970;
	switch (adbHardware) {

	case ADB_HW_CUDA:
		t = time;		/* XXX eventually truncates */

		output[0] = 0x06;	/* 6 byte message */
		output[1] = 0x01;	/* to pram/rtc device */
		output[2] = 0x09;	/* set date/time */
		output[3] = (u_char)(t >> 24);
		output[4] = (u_char)(t >> 16);
		output[5] = (u_char)(t >> 8);
		output[6] = (u_char)(t);
		result = send_adb_cuda((u_char *)output, (u_char *)0,
		    (void *)adb_op_comprout, (void *)&flag, (int)0);
		if (result != 0)	/* exit if not sent */
			return -1;

		while (0 == flag)	/* wait for send to finish */
			;

		return 0;

	case ADB_HW_PMU:
		pm_set_date_time(time);
		return 0;

	default:
		return -1;
	}
}

int
adb_poweroff(void)
{
	u_char output[ADB_MAX_MSG_LENGTH];
	int result;

	adb_polling = 1;

	switch (adbHardware) {
	case ADB_HW_PMU:
		/* Clear the wake on AC loss event */
		pmu_fileserver_mode(0);
		pm_adb_poweroff();

		for (;;);		/* wait for power off */

		return 0;

	case ADB_HW_CUDA:
		output[0] = 0x02;	/* 2 byte message */
		output[1] = 0x01;	/* to pram/rtc/soft-power device */
		output[2] = 0x0a;	/* set poweroff */
		result = send_adb_cuda((u_char *)output, (u_char *)0,
		    (void *)0, (void *)0, (int)0);
		if (result != 0)	/* exit if not sent */
			return -1;

		for (;;);		/* wait for power off */

		return 0;

	default:
		return -1;
	}
}

void
setsoftadb()
{
	if (!timeout_initialized(&adb_softintr_timeout))
		timeout_set(&adb_softintr_timeout, (void *)adb_soft_intr, NULL);
	timeout_add(&adb_softintr_timeout, 1);
}

void
adb_cuda_autopoll()
{
	volatile int flag = 0;
	int result;
	u_char output[16];

	output[0] = 0x03;	/* 3-byte message */
	output[1] = 0x01;	/* to pram/rtc/soft-power device */
	output[2] = 0x01;	/* cuda autopoll */
	output[3] = 0x01;
	result = send_adb_cuda(output, output, adb_op_comprout,
	    (void *)&flag, 0);
	if (result != 0)	/* exit if not sent */
		return;

	while (flag == 0);	/* wait for result */
}

void
adb_cuda_fileserver_mode()
{
	volatile int flag = 0;
	int result;
	u_char output[16];

	output[0] = 0x03;	/* 3-byte message */
	output[1] = 0x01; 	/* to pram/rtc device/soft-power device */
	output[2] = 0x13;	/* cuda file server mode */
	output[3] = 0x01;	/* True - Turn on after AC loss */

	result = send_adb_cuda(output, output, adb_op_comprout,
	    (void *)&flag, 0);
	if (result != 0)
		return;

	while (flag == 0);
}

void
adb_restart()
{
	int result;
	u_char output[16];

	adb_polling = 1;

	switch (adbHardware) {
	case ADB_HW_CUDA:
		output[0] = 0x02;	/* 2 byte message */
		output[1] = 0x01;	/* to pram/rtc/soft-power device */
		output[2] = 0x11;	/* restart */
		result = send_adb_cuda((u_char *)output, (u_char *)0,
				       (void *)0, (void *)0, (int)0);
		if (result != 0)	/* exit if not sent */
			return;
		while (1);		/* not return */

	case ADB_HW_PMU:
		pm_adb_restart();
		while (1);		/* not return */
	}
}

/*
 * Driver definition.
 */

int	adbmatch(struct device *, void *, void *);
void	adbattach(struct device *, struct device *, void *);

struct cfattach adb_ca = {
	sizeof(struct adb_softc), adbmatch, adbattach
};

int
adbmatch(struct device *parent, void *cf, void *aux)
{
	struct confargs *ca = aux;

	if (ca->ca_nreg < 8)
		return 0;

	if (ca->ca_nintr < 4)
		return 0;

	if (strcmp(ca->ca_name, "via-cuda") == 0)
		return 1;

	if (strcmp(ca->ca_name, "via-pmu") == 0)
		return 1;

	return 0;
}

void
adbattach(struct device *parent, struct device *self, void *aux)
{
	struct adb_softc *sc = (struct adb_softc *)self;
	struct confargs *ca = aux;
	struct confargs nca;
	char name[32];
	int node;
	ADBDataBlock adbdata;
	struct adb_attach_args aa_args;
	int totaladbs;
	int adbindex, adbaddr;

	ca->ca_reg[0] += ca->ca_baseaddr;

	sc->sc_regbase = mapiodev(ca->ca_reg[0], ca->ca_reg[1]);
	Via1Base = sc->sc_regbase;

	if (strcmp(ca->ca_name, "via-cuda") == 0)
		adbHardware = ADB_HW_CUDA;
	else if (strcmp(ca->ca_name, "via-pmu") == 0) {
		adbHardware = ADB_HW_PMU;

		/*
		 * Bus reset can take a long time if no adb devices are
		 * connected, e.g. on a Mac Mini; so check for an adb
		 * child in the OF tree to speed up pm_adb_op().
		 */
		adbempty = 1;
		for (node = OF_child(ca->ca_node); node; node = OF_peer(node)) {
			if (OF_getprop(node, "name", name, sizeof name) <= 0)
				continue;
			if (strcmp(name, "adb") == 0) {
				adbempty = 0;
				break;
			}
		}
	}

	adb_polling = 1;
	if (!adbempty) {
		adb_reinit(sc);
		totaladbs = count_adbs(sc);
		printf(": irq %d, %s, %d target%s", ca->ca_intr[0], ca->ca_name,
		    totaladbs, (totaladbs == 1) ? "" : "s");
	}
	printf("\n");

	mac_intr_establish(parent, ca->ca_intr[0], IST_LEVEL, IPL_TTY,
	    adb_intr, sc, sc->sc_dev.dv_xname);

	/* init powerpc globals which control RTC functionality */
	time_read = adb_read_date_time;
	time_write = adb_set_date_time;

#if NAPM > 0
	if (adbHardware == ADB_HW_PMU) {
		/* Magic for signalling the apm driver to match. */
		nca.ca_name = "apm";
		nca.ca_node = node;
		config_found(self, &nca, NULL);
	}
#endif

	/* Attach I2C controller. */
	for (node = OF_child(ca->ca_node); node; node = OF_peer(node)) {
		if (OF_getprop(node, "name", name, sizeof name) <= 0)
			continue;
		if (strcmp(name, "pmu-i2c") == 0) {
			nca.ca_name = "piic";
			nca.ca_node = node;
			config_found(self, &nca, NULL);
		}
	}

	if (adbHardware == ADB_HW_CUDA)
		adb_cuda_fileserver_mode();
	if (adbHardware == ADB_HW_PMU)
		pmu_fileserver_mode(1);

	/*
	 * XXX If the machine doesn't have an ADB bus (PowerBook5,6+)
	 * yes it sounds stupid to attach adb(4), but don't try to send
	 * ADB commands otherwise the PMU may shutdown the machine...
	 */
	if (adbempty)
		return;

	/* for each ADB device */
	for (adbindex = 1; adbindex <= totaladbs; adbindex++) {
		/* Get the ADB information */
		adbaddr = get_ind_adb_info(sc, &adbdata, adbindex);

		aa_args.name = adb_device_name;
		aa_args.origaddr = adbdata.origADBAddr;
		aa_args.adbaddr = adbaddr;
		aa_args.handler_id = adbdata.devType;

		(void)config_found(self, &aa_args, adbprint);
	}

	if (adbHardware == ADB_HW_CUDA)
		adb_cuda_autopoll();
	adb_polling = 0;
}


code:
/*	$OpenBSD: adbvar.h,v 1.10 2013/08/10 08:13:32 mpi Exp $	*/
/*	$NetBSD: adbvar.h,v 1.3 2000/06/08 22:10:46 tsubai Exp $	*/

/*-
 * Copyright (C) 1994	Bradley A. Grantham
 * 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.
 */

struct adb_device {
	int	handler_id;
	int	orig_addr;
	int	curr_addr;

	void	(*handler)(void);
	void	*data;
};

struct adb_softc {
	struct device sc_dev;
	char *sc_regbase;

	struct adb_device	sc_devtable[16];
};

extern int adbHardware;

/* types of adb hardware that we support */
#define ADB_HW_UNKNOWN		0x01	/* don't know */
#define ADB_HW_PMU		0x04	/* PowerBook series */
#define ADB_HW_CUDA		0x05	/* Machines with a Cuda chip */

int	adb_poweroff(void);
void	adb_restart(void);
int	adb_read_date_time(time_t *t);
int	adb_set_date_time(time_t t);


code:
/*	$OpenBSD: akbd_machdep.c,v 1.1 2006/01/18 23:21:17 miod Exp $	*/
/*	$NetBSD: akbd.c,v 1.13 2001/01/25 14:08:55 tsubai Exp $	*/

/*
 * Copyright (C) 1998	Colin Wood
 * 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 Colin Wood.
 * 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.
 */

#include <sys/param.h>
#include <sys/timeout.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/fcntl.h>
#include <sys/poll.h>
#include <sys/selinfo.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
#include <sys/systm.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wskbdvar.h>

#include <dev/adb/adb.h>
#include <dev/adb/akbdvar.h>
#include <dev/adb/keyboard.h>

void	akbd_cngetc(void *, u_int *, int *);
void	akbd_cnpollc(void *, int);

struct wskbd_consops akbd_consops = {
	akbd_cngetc,
	akbd_cnpollc,
};

static int _akbd_is_console;

int
akbd_is_console()
{
	return (_akbd_is_console);
}

int
akbd_cnattach()
{
	_akbd_is_console = 1;
	wskbd_cnattach(&akbd_consops, NULL, &akbd_keymapdata);
	return 0;
}

void
akbd_cngetc(void *v, u_int *type, int *data)
{
	int key, press, val;
	int s;
	extern int adb_intr(void *);

	s = splhigh();

	adb_polledkey = -1;
	adb_polling = 1;

	while (adb_polledkey == -1) {
		adb_intr(NULL); /* adb does not use the argument */
		DELAY(10000);				/* XXX */
	}

	adb_polling = 0;
	splx(s);

	key = adb_polledkey;
	press = ADBK_PRESS(key);
	val = ADBK_KEYVAL(key);

	*data = val;
	*type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
}

void
akbd_cnpollc(void *v, int on)
{
}


code:
/*	$OpenBSD: aoa.c,v 1.6 2010/02/26 21:52:14 jasper Exp $	*/

/*-
 * Copyright (c) 2005 Tsubai Masanari.  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. 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.
 */

/*
 * WORK-IN-PROGRESS AOAKeylargo audio driver.
 */

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

#include <dev/audio_if.h>
#include <dev/ofw/openfirm.h>
#include <macppc/dev/dbdma.h>

#include <machine/autoconf.h>

#include <macppc/dev/i2svar.h>

#ifdef AOA_DEBUG
# define DPRINTF printf
#else
# define DPRINTF while (0) printf
#endif

/* XXX */
#define aoa_softc i2s_softc

int aoa_getdev(void *, struct audio_device *);
int aoa_match(struct device *, void *, void *);
void aoa_attach(struct device *, struct device *, void *);
void aoa_set_volume(struct aoa_softc *, int, int);
void aoa_get_default_params(void *, int, struct audio_params *);

struct cfattach aoa_ca = {
	sizeof(struct aoa_softc), aoa_match, aoa_attach
};

struct cfdriver aoa_cd = {
	NULL, "aoa", DV_DULL
};

struct audio_hw_if aoa_hw_if = {
	i2s_open,
	i2s_close,
	NULL,
	i2s_query_encoding,
	i2s_set_params,
	i2s_round_blocksize,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	i2s_halt_output,
	i2s_halt_input,
	NULL,
	aoa_getdev,
	NULL,
	i2s_set_port,
	i2s_get_port,
	i2s_query_devinfo,
	i2s_allocm,
	NULL,
	i2s_round_buffersize,
	i2s_mappage,
	i2s_get_props,
	i2s_trigger_output,
	i2s_trigger_input,
	aoa_get_default_params
};

struct audio_device aoa_device = {
	"AOA",
	"",
	"aoa"
};

int
aoa_match(struct device *parent, void *match, void *aux)
{
	struct confargs *ca = aux;
	int soundbus, soundchip;
	char compat[32];

	if (strcmp(ca->ca_name, "i2s") != 0)
		return (0);

	if ((soundbus = OF_child(ca->ca_node)) == 0 ||
	    (soundchip = OF_child(soundbus)) == 0)
		return (0);

	bzero(compat, sizeof compat);
	OF_getprop(soundchip, "compatible", compat, sizeof compat);

	if (strcmp(compat, "AOAKeylargo") == 0)
		return (1);
	if (strcmp(compat, "AOAK2") == 0)
		return (1);

	return (0);
}

void
aoa_attach(struct device *parent, struct device *self, void *aux)
{
	struct aoa_softc *sc = (struct aoa_softc *)self;

	sc->sc_setvolume = aoa_set_volume;

	i2s_attach(parent, sc, aux);
	audio_attach_mi(&aoa_hw_if, sc, &sc->sc_dev);
}

int
aoa_getdev(void *h, struct audio_device *retp)
{
	*retp = aoa_device;
	return (0);
}

void
aoa_set_volume(struct aoa_softc *sc, int left, int right)
{
	/* This device doesn't provide volume control. */
}

void
aoa_get_default_params(void *addr, int mode, struct audio_params *params)
{
	i2s_get_default_params(params);
}


code:
/*	$OpenBSD: apm.c,v 1.17 2011/07/02 22:20:07 nicm Exp $	*/

/*-
 * Copyright (c) 2001 Alexander Guy.  All rights reserved.
 * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved.
 * Copyright (c) 1995 John T. Kohl.  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 names of the authors nor the names of contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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 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.
 *
 */

#include "apm.h"

#if NAPM > 1
#error only one APM emulation device may be configured
#endif

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/device.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/event.h>

#include <machine/conf.h>
#include <machine/cpu.h>
#include <machine/apmvar.h>
#include <machine/autoconf.h>

#include <macppc/dev/pm_direct.h>

#if defined(APMDEBUG)
#define DPRINTF(x)	printf x
#else
#define	DPRINTF(x)	/**/
#endif

struct apm_softc {
	struct device sc_dev;
	struct klist sc_note;
	int    sc_flags;
};

int apmmatch(struct device *, void *, void *);
void apmattach(struct device *, struct device *, void *);

struct cfattach apm_ca = {
	sizeof(struct apm_softc), apmmatch, apmattach
};

struct cfdriver apm_cd = {
	NULL, "apm", DV_DULL
};

#define	APMUNIT(dev)	(minor(dev)&0xf0)
#define	APMDEV(dev)	(minor(dev)&0x0f)
#define APMDEV_NORMAL	0
#define APMDEV_CTL	8

void filt_apmrdetach(struct knote *kn);
int filt_apmread(struct knote *kn, long hint);
int apmkqfilter(dev_t dev, struct knote *kn);

struct filterops apmread_filtops =
	{ 1, NULL, filt_apmrdetach, filt_apmread};

/*
 * Flags to control kernel display
 *	SCFLAG_NOPRINT:		do not output APM power messages due to
 *				a power change event.
 *
 *	SCFLAG_PCTPRINT:	do not output APM power messages due to
 *				to a power change event unless the battery
 *				percentage changes.
 */

#define SCFLAG_NOPRINT	0x0008000
#define SCFLAG_PCTPRINT	0x0004000
#define SCFLAG_PRINT	(SCFLAG_NOPRINT|SCFLAG_PCTPRINT)

#define	SCFLAG_OREAD 	(1 << 0)
#define	SCFLAG_OWRITE	(1 << 1)
#define	SCFLAG_OPEN	(SCFLAG_OREAD|SCFLAG_OWRITE)

int
apmmatch(struct device *parent, void *match, void *aux)
{
	struct confargs *ca = aux;

	if (strcmp(ca->ca_name, "apm") != 0)
		return (0);

	return (1);
}

void
apmattach(struct device *parent, struct device *self, void *aux)
{
	struct pmu_battery_info info;

	pm_battery_info(0, &info);

	printf(": battery flags 0x%X, ", info.flags);
	printf("%d%% charged\n", ((info.cur_charge * 100) / info.max_charge));
}

int
apmopen(dev_t dev, int flag, int mode, struct proc *p)
{
	struct apm_softc *sc;
	int error = 0;

	/* apm0 only */
	if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
	    !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
		return ENXIO;

	DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n",
	    APMDEV(dev), p->p_pid, flag, mode));

	switch (APMDEV(dev)) {
	case APMDEV_CTL:
		if (!(flag & FWRITE)) {
			error = EINVAL;
			break;
		}
		if (sc->sc_flags & SCFLAG_OWRITE) {
			error = EBUSY;
			break;
		}
		sc->sc_flags |= SCFLAG_OWRITE;
		break;
	case APMDEV_NORMAL:
		if (!(flag & FREAD) || (flag & FWRITE)) {
			error = EINVAL;
			break;
		}
		sc->sc_flags |= SCFLAG_OREAD;
		break;
	default:
		error = ENXIO;
		break;
	}
	return error;
}

int
apmclose(dev_t dev, int flag, int mode, struct proc *p)
{
	struct apm_softc *sc;

	/* apm0 only */
	if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
	    !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
		return ENXIO;

	DPRINTF(("apmclose: pid %d flag %x mode %x\n", p->p_pid, flag, mode));

	switch (APMDEV(dev)) {
	case APMDEV_CTL:
		sc->sc_flags &= ~SCFLAG_OWRITE;
		break;
	case APMDEV_NORMAL:
		sc->sc_flags &= ~SCFLAG_OREAD;
		break;
	}
	return 0;
}

int
apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
	struct apm_softc *sc;
	struct pmu_battery_info batt;
	struct apm_power_info *power;
	int error = 0;

	/* apm0 only */
	if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
	    !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
		return ENXIO;

	switch (cmd) {
		/* some ioctl names from linux */
	case APM_IOC_STANDBY:
		if ((flag & FWRITE) == 0)
			error = EBADF;
		break;
	case APM_IOC_SUSPEND:
		if ((flag & FWRITE) == 0)
			error = EBADF;
		break;
	case APM_IOC_PRN_CTL:
		if ((flag & FWRITE) == 0)
			error = EBADF;
		else {
			int flag = *(int *)data;
			DPRINTF(( "APM_IOC_PRN_CTL: %d\n", flag ));
			switch (flag) {
			case APM_PRINT_ON:	/* enable printing */
				sc->sc_flags &= ~SCFLAG_PRINT;
				break;
			case APM_PRINT_OFF: /* disable printing */
				sc->sc_flags &= ~SCFLAG_PRINT;
				sc->sc_flags |= SCFLAG_NOPRINT;
				break;
			case APM_PRINT_PCT: /* disable some printing */
				sc->sc_flags &= ~SCFLAG_PRINT;
				sc->sc_flags |= SCFLAG_PCTPRINT;
				break;
			default:
				error = EINVAL;
				break;
			}
		}
		break;
	case APM_IOC_DEV_CTL:
		if ((flag & FWRITE) == 0)
			error = EBADF;
		break;
	case APM_IOC_GETPOWER:
	        power = (struct apm_power_info *)data;

		pm_battery_info(0, &batt);

		power->ac_state = ((batt.flags & PMU_PWR_AC_PRESENT) ?
		    APM_AC_ON : APM_AC_OFF);
		power->battery_life =
		    ((batt.cur_charge * 100) / batt.max_charge);

		/*
		 * If the battery is charging, return the minutes left until
		 * charging is complete. apmd knows this.
		 */

		if (!(batt.flags & PMU_PWR_BATT_PRESENT)) {
			power->battery_state = APM_BATT_UNKNOWN;
			power->minutes_left = 0;
			power->battery_life = 0;
		} else if ((power->ac_state == APM_AC_ON) &&
			   (batt.draw > 0)) {
			power->minutes_left =
			    (((batt.max_charge - batt.cur_charge) * 3600) /
			    batt.draw) / 60;
			power->battery_state = APM_BATT_CHARGING;
		} else {
			power->minutes_left =
			    ((batt.cur_charge * 3600) / (-batt.draw)) / 60;

			/* XXX - Arbitrary */
			if (power->battery_life > 60)
				power->battery_state = APM_BATT_HIGH;
			else if (power->battery_life < 10)
				power->battery_state = APM_BATT_CRITICAL;
			else
				power->battery_state = APM_BATT_LOW;
		}
		break;
	case APM_IOC_STANDBY_REQ:
		if ((flag & FWRITE) == 0)
			error = EBADF;
		break;
	case APM_IOC_SUSPEND_REQ:
		if ((flag & FWRITE) == 0)
			error = EBADF;
		break;
	default:
		error = ENOTTY;
	}

	return error;
}

void
filt_apmrdetach(struct knote *kn)
{
	struct apm_softc *sc = (struct apm_softc *)kn->kn_hook;

	SLIST_REMOVE(&sc->sc_note, kn, knote, kn_selnext);
}

int
filt_apmread(struct knote *kn, long hint)
{
	/* XXX weird kqueue_scan() semantics */
	if (hint && !kn->kn_data)
		kn->kn_data = (int)hint;

	return (1);
}

int
apmkqfilter(dev_t dev, struct knote *kn)
{
	struct apm_softc *sc;

	/* apm0 only */
	if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
	    !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
		return ENXIO;

	switch (kn->kn_filter) {
	case EVFILT_READ:
		kn->kn_fop = &apmread_filtops;
		break;
	default:
		return (EINVAL);
	}

	kn->kn_hook = (caddr_t)sc;
	SLIST_INSERT_HEAD(&sc->sc_note, kn, kn_selnext);

	return (0);
}